ビデオ コーデックのプライベート データの使用 (Microsoft Media Foundation)
Windows Media Video 9 コーデックによって生成された圧縮出力は、エンコーダーによって提供されるデータがないと、適切に圧縮解除できません。 コーデック プライベート データと呼ばれるこのデータは、出力メディアの種類に追加する必要があります。 IWMCodecPrivateData インターフェイスのメソッドを呼び出すことで、コーデックのプライベート データを取得できます。 それ以外の場合は 、完全なDMO_MEDIA_TYPE 構造体を IWMCodecPrivateData::SetPartialOutputType に渡します。 次に 、IWMCodecPrivateData::GetPrivateData を 2 回呼び出し、1 回呼び出してデータのサイズを取得し、もう一度データをそのサイズのバッファーにコピーします。 プライベート データが追加された VIDEOINFOHEADER 構造体を保持する新しいバッファーを作成し、その構造体とデータをそのバッファーにコピーします。 最後に、DMO_MEDIA_TYPE構造体の pbFormat メンバーを新しく作成されたバッファーのアドレスに設定し、cbFormat メンバーを VIDEOINFOHEADER とプライベート データの合計サイズ (バイト単位) に設定します。
MediaFoundation を使用している場合は、MFCreateAMMediaTypeFromMFMediaType を呼び出すことによって、IMFMediaType インターフェイスからDMO_MEDIA_TYPE構造体を構築できます。
エンコーダーのプロパティを最初に設定した後に取得したコーデック プライベート データを使用する必要があります。 プロパティが変更された場合は、新しいプライベート データを取得する必要があります。 エンコード セッションに対してすべてのプロパティが設定された後に取得したプライベート データを使用しない場合、デコーダーはデータを圧縮解除できない可能性があります。
次のコード例は、ビデオの種類のプライベート データを取得する方法を示しています。
HRESULT GetFinalOutputType(DMO_MEDIA_TYPE* pMedia, IMediaObject* pDMO)
{
// WARNING //
// This function does not deallocate the memory pointed to by
// pMedia->pbFormat. If the VIDEOINFOHEADER referenced by pbFormat
// was dynamically allocated, a reference to it must be kept before
// calling this function so that it can be freed.
// Perform simple parameter checks.
if(pMedia == NULL || pDMO == NULL)
return E_POINTER;
if(pMedia->formattype != MEDIATYPE_VideoInfo)
return E_INVALIDARG;
HRESULT hr = S_OK;
IWMCodecPrivateData* pPrivData = NULL;
BYTE* pbData = NULL;
DWORD cbData = 0;
BYTE* pbNewVidInf = NULL;
DWORD cbNewVidInf = 0;
BYTE* pbNewPriv = NULL;
// Get the private data interface.
hr = pDMO->QueryInterface(IID_IWMCodecPrivateData,
(void**)&pPrivData);
GOTO_EXIT_IF_FAILED(hr);
// Set the partial media type.
hr = pPrivData->SetPartialOutputType(pMedia);
GOTO_EXIT_IF_FAILED(hr);
// Get the size of the private data.
hr = pPrivData->GetPrivateData(NULL, &cbData);
GOTO_EXIT_IF_FAILED(hr);
// Allocate memory for the private data.
pbData = new BYTE[cbData];
if(pbData == NULL)
{
hr = E_OUTOFMEMORY;
goto Exit:
}
// Get the private data.
hr = pPrivData->GetPrivateData(pbData, &cbData);
// Allocate memory for the new VIDEOINFOHEADER.
cbNewVidInf = pMedia->cbFormat + cbData;
pbNewVidInf = new BYTE[cbNewVidInf];
// Copy the VIDEOINFOHEADER to the new buffer.
memcpy((void*)pbNewVidInf, (void*)pMedia->pbFormat, pMedia->cbFormat);
// Get the address of the first byte following the VIDEOINFOHEADER.
pbNewPriv = pbNewVidInf + pMedia->cbFormat;
// Copy the private data to the new buffer.
memcpy((void*)pbNewPriv, (void*)pbData, cbData);
// Set the new VIDEOINFOHEADER in the DMO_MEDIA_TYPE.
pMedia->pbFormat = pbNewVidInf;
pMedia->cbFormat = cbNewVidInf;
Exit:
SAFE_RELEASE(pPrivData);
SAFE_ARRAY_DELETE(pbData);
pbNewPriv = NULL;
return hr;
}
注意
ビデオ エンコーダーによって配信されるコーデックのプライベート データは、同じ構成に対して同じコーデックの別の実装によって配信されるプライベート データと同じであるとは限りません。 この値は、このトピックの手順を使用して常に生成する必要があります。プライベート データを別のファイルからコピーしないでください。
関連トピック