在您交涉編碼器 MFT 的輸入類型和輸出類型之後,如編碼器 上的媒體類型交涉中所述,您可以開始處理媒體數據範例。 數據會以媒體樣本的形式傳遞(IMFSample 介面),並作為媒體樣本從輸出接收。
將數據傳送至編碼器進行處理之前,您必須先配置媒體範例,並新增一個包含需要編碼之媒體數據的媒體緩衝區。 呼叫 IMFTransform::ProcessInput,並將指標傳遞至已配置的媒體樣本。 除了媒體範例之外,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;
};
相關主題