在編碼器中處理資料
在您交涉編碼器 MFT 的輸入類型和輸出類型之後,如 編碼器上的媒體類型交涉中所述,您可以開始處理媒體資料範例。 資料會以媒體範例的形式傳遞, (IMFSample 介面) ,也會從輸出收到作為媒體樣本。
將資料傳送至編碼器進行處理之前,您必須配置媒體範例,並新增一個包含需要編碼之媒體資料的多個媒體緩衝區。 呼叫 IMFTransform::P rocessInput ,並將指標傳遞至配置的媒體範例。 除了媒體範例之外, ProcessInput 也需要輸入資料流程識別碼。 若要取得資料流程識別碼,請呼叫 IMFTransform::GetStreamIDs。 因為編碼器的設計只有一個和一個輸出,所以這些資料流程識別碼一律具有 0 的值。
若要從編碼器取得資料,請呼叫 IMFTransform::P rocessOutput。 在呼叫 ProcessOutput之前,您必須瞭解編碼器是否配置輸出媒體範例,或者您必須明確執行此動作。 若要這樣做,請呼叫 IMFTransform::GetOutputStreamInfo。 這會傳回 MFT_OUTPUT_STREAM_INFO 結構中的輸出媒體範例資訊。 如果編碼器配置媒體樣本,它會傳回 dwFlags 成員中的MFT_OUTPUT_STREAM_PROVIDES_SAMPLES旗標, 而 cbSize 成員包含零。 如果編碼器需要您配置輸出緩衝區,請根據 cbSize中傳回的大小建立輸出媒體範例和相關聯的媒體緩衝區。 當您呼叫 ProcessSample時,請將指標傳遞至新建立的媒體範例。 在編碼會話期間,編碼器會以編碼的資料填入輸出媒體範例所指向的媒體緩衝區。
若要啟動編碼會話,請呼叫 ProcessInput,將輸入媒體範例傳遞至編碼器。 編碼器會開始處理和資料,並產生一或多個輸出媒體範例,只要其傳回MF_E_TRANSFORM_NEED_MORE_INPUT, ProcessOutput 就必須擷取這些輸出媒體範例。 如果您呼叫 ProcessInput 以傳遞更多輸入,只要有要擷取的輸出資料, ProcessInput 就會失敗並產生MF_E_NOTACCEPTING。 除非用戶端至少呼叫 ProcessOutput 一次,否則編碼器不會再接受任何輸入。
您應該為所有傳遞的輸入樣本設定精確的時間戳記和持續時間。 時間戳記並非絕對必要,但有助於維護音訊/視訊同步處理。 如果您沒有範例的時間戳記,最好不要使用不確定的值。
編碼器處理範例
下列範例程式碼示範如何呼叫 IMFTransform::P rocessOutput 以取得編碼的範例。 如需此範例的完整內容,請參閱 編碼器範例程式碼。
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;
};
相關主題