使用视频编解码器专用数据 (Microsoft Media Foundation)

如果没有编码器提供的某些数据,则无法正确解压缩 Windows Media Video 9 编解码器生成的压缩输出。 此数据(称为编解码器专用数据)必须追加到输出媒体类型。 可以通过调用 IWMCodecPrivateData 接口的方法获取编解码器私有数据。 将其他完整的 DMO_MEDIA_TYPE 结构传递给 IWMCodecPrivateData::SetPartialOutputType。 然后调用 IWMCodecPrivateData::GetPrivateData 两次,一次获取数据的大小,然后再次将数据复制到该大小的缓冲区。 创建一个新缓冲区来保存追加私有数据的 VIDEOINFOHEADER 结构,并将结构和数据复制到该缓冲区。 最后,将 DMO_MEDIA_TYPE 结构的 pbFormat 成员设置为新创建的缓冲区的地址,并将 cbFormat 成员设置为 VIDEOINFOHEADER 和私有数据的组合大小(以字节为单位)。

如果使用 MediaFoundation,可以通过调用 MFCreateAMMediaTypeFromMFMediaTypeIMFMediaType 接口构造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;
}

注意

视频编码器提供的编解码器专用数据不保证与同一配置的不同编解码器实现提供的专用数据相同。 必须始终使用本主题中的步骤生成此值;切勿从其他文件复制私有数据。

 

配置视频编码

使用视频