Elaborazione dei dati nel codificatore
Dopo aver negoziato il tipo di input e il tipo di output per il codificatore MFT, come descritto in Negoziazione tipo di supporto nel codificatore, è possibile avviare l'elaborazione di esempi di dati multimediali. I dati vengono passati sotto forma di campioni multimediali (interfaccia FMSample ) e ricevuti anche dall'output come campioni multimediali.
Prima di inviare dati al codificatore per l'elaborazione, è necessario allocare un esempio multimediale e aggiungere uno di più buffer multimediali contenenti dati multimediali che devono essere codificati. Chiamare FMTransform::P rocessInput e passare un puntatore all'esempio di supporto allocato. Oltre all'esempio multimediale, ProcessInput richiede anche l'identificatore del flusso di input. Per ottenere l'identificatore di flusso, chiamare FMTransform::GetStreamIDs. Poiché un codificatore è progettato per avere solo uno e un output, questi identificatori di flusso hanno sempre il valore 0.
Per ottenere dati dal codificatore, chiamare FMTransform::P rocessOutput. Prima di chiamare ProcessOutput, è necessario scoprire se il codificatore alloca gli esempi di supporti di output o è necessario farlo in modo esplicito. A tale scopo, chiamare FMTransform::GetOutputStreamInfo. In questo modo vengono restituite informazioni di esempio di supporto di output nella struttura MFT_OUTPUT_STREAM_INFO . Se il codificatore alloca esempi multimediali, restituisce il flag MFT_OUTPUT_STREAM_PROVIDES_SAMPLES nel membro dwFlags e il membro cbSize contiene zero. Se il codificatore prevede di allocare il buffer di output, creare l'esempio di supporto di output e il buffer multimediale associato in base alle dimensioni restituite in cbSize. Quando si chiama ProcessSample, passare un puntatore all'esempio di supporto appena creato. Durante la sessione di codifica, il codificatore riempie i buffer multimediali, puntati dall'esempio di supporto di output, con i dati codificati.
Per avviare la sessione di codifica, passare l'esempio di supporto di input al codificatore chiamando ProcessInput. Il codificatore avvia l'elaborazione e i dati e genera uno o più esempi di supporti di output che devono essere recuperati da ProcessOutput , purché restituisca MF_E_TRANSFORM_NEED_MORE_INPUT. Se si chiama ProcessInput per passare più input, purché siano presenti dati di output da recuperare, ProcessInput ha esito negativo con MF_E_NOTACCEPTING. Il codificatore non accetta più input finché il client chiama ProcessOutput almeno una volta.
È necessario impostare timestamp e durate accurati per tutti gli esempi di input passati. I timestamp non sono strettamente necessari, ma consentono di mantenere la sincronizzazione audio/video. Se non si hanno i timestamp per gli esempi, è preferibile lasciarli fuori che usare valori incerti.
Esempio di elaborazione del codificatore
Il codice di esempio seguente illustra come chiamare FMTransform::P rocessOutput per ottenere un esempio codificato. Per il contesto completo di questo esempio, vedere Codice di esempio del codificatore.
HRESULT CWmaEncoder::ProcessOutput(IMFSample **ppSample)
{
if (m_pMFT == NULL)
{
return MF_E_NOT_INITIALIZED;
}
*ppSample = NULL;
IMFMediaBuffer* pBufferOut = NULL;
IMFSample* pSampleOut = NULL;
DWORD dwStatus;
MFT_OUTPUT_STREAM_INFO mftStreamInfo = { 0 };
MFT_OUTPUT_DATA_BUFFER mftOutputData = { 0 };
HRESULT hr = m_pMFT->GetOutputStreamInfo(m_dwOutputID, &mftStreamInfo);
if (FAILED(hr))
{
goto done;
}
//create a buffer for the output sample
hr = MFCreateMemoryBuffer(mftStreamInfo.cbSize, &pBufferOut);
if (FAILED(hr))
{
goto done;
}
//Create the output sample
hr = MFCreateSample(&pSampleOut);
if (FAILED(hr))
{
goto done;
}
//Add the output buffer
hr = pSampleOut->AddBuffer(pBufferOut);
if (FAILED(hr))
{
goto done;
}
//Set the output sample
mftOutputData.pSample = pSampleOut;
//Set the output id
mftOutputData.dwStreamID = m_dwOutputID;
//Generate the output sample
hr = m_pMFT->ProcessOutput(0, 1, &mftOutputData, &dwStatus);
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
{
hr = S_OK;
goto done;
}
// TODO: Handle MF_E_TRANSFORM_STREAM_CHANGE
if (FAILED(hr))
{
goto done;
}
*ppSample = pSampleOut;
(*ppSample)->AddRef();
done:
SafeRelease(&pBufferOut);
SafeRelease(&pSampleOut);
return hr;
};
Argomenti correlati