エンコーダーでのデータの処理
エンコーダーの MFT の入力の種類と出力の種類をネゴシエートした後、「エンコーダーの メディアの種類ネゴシエーション」で説明されているように、メディア データ サンプルの処理を開始できます。 データは、メディア サンプル (IMFSample インターフェイス) の形式で渡され、出力からメディア サンプルとして受け取られます。
処理のためにエンコーダーにデータを送信する前に、メディア サンプルを割り当て、エンコードする必要があるメディア データを含むメディア バッファーの 1 つを追加する必要があります。 IMFTransform::P rocessInput を呼び出し、割り当てられたメディア サンプルへのポインターを渡します。 ProcessInput には、メディア サンプルに加えて、入力ストリーム識別子も必要です。 ストリーム識別子を取得するには、 IMFTransform::GetStreamIDs を呼び出します。 エンコーダーは 1 つの出力のみを持つよう設計されているため、これらのストリーム識別子の値は常に 0 です。
エンコーダーからデータを取得するには、 IMFTransform::P rocessOutput を呼び出します。 ProcessOutput を呼び出す前に、エンコーダーが出力メディア サンプルを割り当てるか、明示的に割り当てる必要があるかを確認する必要があります。 これを行うには、 IMFTransform::GetOutputStreamInfo を呼び出します。 これにより、 MFT_OUTPUT_STREAM_INFO 構造体の出力メディア サンプル情報が返されます。 エンコーダーがメディア サンプルを割り当てると、 dwFlags メンバーのMFT_OUTPUT_STREAM_PROVIDES_SAMPLES フラグが返され、 cbSize メンバーに 0 が含まれます。 エンコーダーで出力バッファーを割り当てることが予想される場合は、 cbSize で返されるサイズに基づいて、出力メディア サンプルと関連付けられているメディア バッファーを作成します。 ProcessSample を呼び出すときに、新しく作成されたメディア サンプルへのポインターを渡します。 エンコード セッション中に、エンコーダーは、出力メディア サンプルが指すメディア バッファーにエンコードされたデータを入力します。
エンコード セッションを開始するには、 ProcessInput を呼び出して入力メディア サンプルをエンコーダーに渡します。 エンコーダーは、処理とデータを開始し、MF_E_TRANSFORM_NEED_MORE_INPUTを返す限り ProcessOutput によって取得する必要がある 1 つ以上の出力メディア サンプルを生成します。 取得する出力データがある限り、 ProcessInput を呼び出してより多くの入力を渡すと、 ProcessInput はMF_E_NOTACCEPTINGで失敗します。 エンコーダーは、クライアントが ProcessOutput を少なくとも 1 回呼び出すまで、それ以上の入力を受け入れません。
渡されるすべての入力サンプルに正確なタイムスタンプと期間を設定する必要があります。 タイムスタンプは厳密には必要ありませんが、オーディオ/ビデオの同期を維持するのに役立ちます。 サンプルのタイムスタンプがない場合は、不確実な値を使用するよりも、それらを除外することをお勧めします。
エンコーダー処理の例
次のコード例は 、IMFTransform::P rocessOutput を呼び出してエンコードされたサンプルを取得する方法を示しています。 この例の完全なコンテキストについては、「 Encoder Example Code」を参照してください。
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;
};
関連トピック