Media Foundation Transform (MFT) はMedia Data処理の一般的なモデルを提供し、デコーダー、エンコーダーやDSP (Digital Signal Processor) で用いられます。
MFTを作成するには、いくつかの方法があります。
MFTEnumEx()で、指定基準に適合するMFTのリストを得られます。
HRESULT MFTEnumEx( [in] GUID guidCategory, // MFTのカテゴリを表すGUID。その値はMFT_CATEGORYで定義されている [in] UINT32 Flags, // 処理方法を示す_MFT_ENUM_FLAGの値 [in] const MFT_REGISTER_TYPE_INFO *pInputType, // 入力するMedia Typeに適合する、MFT_REGISTER_TYPE_INFOへのポインタ [in] const MFT_REGISTER_TYPE_INFO *pOutputType, // 出力するMedia Typeに適合する、MFT_REGISTER_TYPE_INFOへのポインタ [out] IMFActivate ***pppMFTActivate, // 検索基準に適合したMFTオブジェクトの配列へのポインタ [out] UINT32 *pnumMFTActivate // MFTオブジェクトの配列の要素の数 );MFTEnumEx function (mfapi.h) - Win32 apps | Microsoft Learn
Flagsにゼロを指定すると、MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER
と同等となります。MFT_ENUM_FLAG_ALLを指定すると、MFT_ENUM_FLAG_SORTANDFILTER以外のすべてのフラグが指定されます。Flagsに適合するMFTがなくてもS_OKが返されるため、pnumMFTActivateの数を確認するようにします。
列挙子 | 値 | 内容 |
---|---|---|
MFT_ENUM_FLAG_SYNCMFT | 0x00000001 | Enumerates V1 MFTs. This is default. |
MFT_ENUM_FLAG_ASYNCMFT | 0x00000002 | Enumerates only software async MFTs also known as V2 MFTs |
MFT_ENUM_FLAG_HARDWARE | 0x00000004 | Enumerates V2 hardware async MFTs |
MFT_ENUM_FLAG_FIELDOFUSE | 0x00000008 | Enumerates MFTs that require unlocking |
MFT_ENUM_FLAG_LOCALMFT | 0x00000010 | Enumerates Locally (in-process) registered MFTs |
MFT_ENUM_FLAG_TRANSCODE_ONLY | 0x00000020 | Enumerates decoder MFTs used by transcode only |
MFT_ENUM_FLAG_SORTANDFILTER | 0x00000040 | Apply system local, do not use and preferred sorting and filtering |
MFT_ENUM_FLAG_SORTANDFILTER_APPROVED_ONLY | 0x000000C0 | Similar to MFT_ENUM_FLAG_SORTANDFILTER, but apply a local policy of: MF_PLUGIN_CONTROL_POLICY_USE_APPROVED_PLUGINS |
MFT_ENUM_FLAG_SORTANDFILTER_WEB_ONLY | 0x00000140 | Similar to MFT_ENUM_FLAG_SORTANDFILTER, but apply a local policy of: MF_PLUGIN_CONTROL_POLICY_USE_WEB_PLUGINS |
MFT_ENUM_FLAG_SORTANDFILTER_WEB_ONLY_EDGEMODE | 0x00000240 | Similar to MFT_ENUM_FLAG_SORTANDFILTER, but apply a local policy of: MF_PLUGIN_CONTROL_POLICY_USE_WEB_PLUGINS_EDGEMODE |
pInputTypeやpOutputTypeにNULLを指定すると、すべてのMedia Typeに適合します。
MFT_REGISTER_TYPE_INFO pOutputType[] = { { MFMediaType_Video, MFVideoFormat_RGB32 } };
IMFActivate** ppMFTActivate;
UINT32 numMFTActivate;
HRESULT hr = MFTEnumEx(
MFT_CATEGORY_VIDEO_PROCESSOR,
MFT_ENUM_FLAG_ALL,
NULL,
pOutputType,
&ppMFTActivate,
&numMFTActivate);
IMFTransform* pTransform;
if (0< numMFTActivate)
{
// IMFTransformのオブジェクトを生成する
hr = ppMFTActivate[0]->ActivateObject(__uuidof(IMFTransform), (void **)&pTransform);
}
CoTaskMemFree(ppMFTActivate);
CoCreateInstance()では、次のようにMFTのインスタンスを得られます。
IMFTransform* pTransform; HRESULT hr = CoCreateInstance( CLSID_VideoProcessorMFT, NULL, CLSCTX_INPROC_SERVER, __uuidof(IMFTransform), (void**)&pTransform);
対象とするストリームをMFTに指示するための、識別子を取得します。
IMFTransform* pTransform = ... // 入出力のストリームの数を取得する DWORD dwInputIDArraySize; DWORD dwOutputIDArraySize; hr = pTransform->GetStreamCount(&dwInputIDArraySize, &dwOutputIDArraySize); // ストリーム識別子の配列を取得する DWORD* pdwInputIDs = new DWORD[dwInputIDArraySize]; DWORD* pdwOutputIDs = new DWORD[dwOutputIDArraySize]; hr = pTransform->GetStreamIDs(dwInputIDArraySize, pdwInputIDs, dwOutputIDArraySize, pdwOutputIDs); DWORD dwInputStreamID = 0; DWORD dwOutputStreamID = 0; if (hr != E_NOTIMPL) { dwInputStreamID = pdwInputIDs[0]; dwOutputStreamID = pdwOutputIDs[0]; } delete[] pdwInputIDs; delete[] pdwOutputIDs;
MFTの入力と出力のストリームの数を得られます。
HRESULT GetStreamCount( [out] DWORD *pcInputStreams, [out] DWORD *pcOutputStreams );IMFTransform::GetStreamCount (mftransform.h) - Win32 apps | Microsoft Learn
返されるストリームには、Media TypeがないかNULLのMedia Typeのストリームの数も含まれます。
MFTの入力と出力のストリーム識別子を得られます。
HRESULT GetStreamIDs( [in] DWORD dwInputIDArraySize, [out] DWORD *pdwInputIDs, [in] DWORD dwOutputIDArraySize, [out] DWORD *pdwOutputIDs );IMFTransform::GetStreamIDs (mftransform.h) - Win32 apps | Microsoft Learn
E_NOTIMPLが返されるときは、MFTにゼロから始まる連続する識別子を持つ固定数のストリームがあることを意味します。
MFTがデータを処理できるように、入力と出力のストリームごとにMedia Typeを設定しなければなりません。
DWORD dwFlags = 0; hr = pTransform->SetInputType(dwInputStreamID, pInputMediaType, dwFlags); hr = pTransform->SetOutputType(dwOutputStreamID, pOutputMediaType, dwFlags);
MFTによっては入力と出力を設定する順番が要求されることがあり、SetInputType()がMF_E_TRANSFORM_TYPE_NOT_SETを返すならば、先に出力を設定します。
MFTの入力ストリームのMedia Typeを、設定または 検査できます。
HRESULT SetInputType(
[in] DWORD dwInputStreamID,
[in] IMFMediaType *pType,
[in] DWORD dwFlags // MFT_SET_TYPE_TEST_ONLYならば、pTypeを検査して設定しない
);
IMFTransform::SetInputType (mftransform.h) - Win32 apps | Microsoft Learn
Media Typeを設定したら、ストリームごとにバッファ要件を取得します。
MFT_OUTPUT_STREAM_INFO mftStreamInfo;
ZeroMemory(&mftStreamInfo, sizeof(MFT_OUTPUT_STREAM_INFO));
// デコーダで処理される出力バッファの大きさを取得する
hr = pTransform->GetOutputStreamInfo(dwOutputStreamID, &mftStreamInfo);
HRESULT GetOutputStreamInfo( [in] DWORD dwOutputStreamID, [out] MFT_OUTPUT_STREAM_INFO *pStreamInfo );IMFTransform::GetOutputStreamInfo (mftransform.h) - Win32 apps | Microsoft Learn
IMFSample* pSample = ... // デコーダへ入力を送る DWORD dwReserved = 0; hr = pTransform->ProcessInput(dwInputStreamID, pSample, dwReserved); // 変換出力用のバッファを作成する MFT_OUTPUT_STREAM_INFO mftStreamInfo; ZeroMemory(&mftStreamInfo, sizeof(MFT_OUTPUT_STREAM_INFO)); // デコーダで処理される出力バッファの大きさを取得する hr = pTransform->GetOutputStreamInfo(dwOutputStreamID, &mftStreamInfo); // 出力サンプルを作成する IMFSample* pSampleOut = NULL; IMFMediaBuffer* pBufferOut = NULL; // 出力サンプル用のバッファを作成する hr = MFCreateMemoryBuffer(mftStreamInfo.cbSize, &pBufferOut); hr = MFCreateSample(&pSampleOut); hr = pSampleOut->AddBuffer(pBufferOut); MFT_OUTPUT_DATA_BUFFER mftOutputData; ZeroMemory(&mftOutputData, sizeof(mftOutputData)); mftOutputData.dwStreamID = dwOutputStreamID; mftOutputData.pSample = pSampleOut; // デコーダで出力サンプルを生成する DWORD dwProcessOutput = 0; DWORD dwStatus = 0; hr = pTransform->ProcessOutput(dwProcessOutput, dwOutputIDArraySize, &mftOutputData, &dwStatus);
MFTへメッセージを送れます。
HRESULT ProcessMessage( [in] MFT_MESSAGE_TYPE eMessage, // 送信するメッセージ [in] ULONG_PTR ulParam // メッセージ パラメータ。その意味はメッセージに依存する );IMFTransform::ProcessMessage (mftransform.h) - Win32 apps | Microsoft Learn
eMessageには、MFT_MESSAGE_TYPEの値を指定します。
列挙子 | 内容 |
---|---|
MFT_MESSAGE_NOTIFY_BEGIN_STREAMING | ストリーミングが開始することを、MFTに通知する |
MFT_MESSAGE_NOTIFY_END_OF_STREAM | 入力ストリームが終了したことを、MFTに通知する |
MFT_MESSAGE_COMMAND_DRAIN | 蓄えたデータの排出を、MFTに要求する |
MFTは利用できる入力から完全な出力を生成できないとき、入力データを失います。クライアントは一般的に、ソースストリームの最後に達するか、ソースストリームのフォーマットが変更される直前に、MFTに排出を要求します。Draining an MFT - Basic MFT Processing Model - Win32 apps | Microsoft Learn
ProcessMessage()でMFT_MESSAGE_COMMAND_DRAINを送信する以外にも、MF_E_TRANSFORM_NEED_MORE_INPUTが返されるまでProcessOutput()を呼ぶことでも、MFTからデータを排出できます。
MFTの入力ストリームへ、データを配送できます。
HRESULT ProcessInput( [in] DWORD dwInputStreamID, // 入力ストリームの識別子 [in] IMFSample *pSample, // 入力サンプルへのポインタ [in] DWORD dwFlags // 予約。必ず0 );IMFTransform::ProcessInput (mftransform.h) - Win32 apps | Microsoft Learn
現在の入力データから、出力を生成できます。
HRESULT ProcessOutput(
[in] DWORD dwFlags,
[in] DWORD cOutputBufferCount, // pOutputSamples配列の要素の数
[in, out] MFT_OUTPUT_DATA_BUFFER *pOutputSamples,
[out] DWORD *pdwStatus
);
IMFTransform::ProcessOutput (mftransform.h) - Win32 apps | Microsoft Learn
戻り値によっては、追加の処理が必要となります。