다음을 통해 공유


비디오 코덱 프라이빗 데이터 사용(Microsoft Media Foundation)

Windows Media Video 9 코덱에서 생성된 압축된 출력은 인코더에서 제공하는 일부 데이터 없이는 제대로 압축 해제할 수 없습니다. 코덱 프라이빗 데이터라고 하는 이 데이터는 출력 미디어 형식에 추가되어야 합니다. IWMCodecPrivateData 인터페이스의 메서드를 호출하여 코덱 프라이빗 데이터를 가져올 수 있습니다. 그렇지 않으면 완전한 DMO_MEDIA_TYPE 구조를 IWMCodecPrivateData::SetPartialOutputType에 전달합니다. 그런 다음 IWMCodecPrivateData::GetPrivateData 를 두 번 호출하여 데이터의 크기를 가져옵니다. 그런 다음 다시 해당 크기의 버퍼에 데이터를 복사합니다. 프라이빗 데이터가 추가된 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;
}

참고

비디오 인코더에서 제공하는 코덱 프라이빗 데이터는 동일한 구성에 대해 동일한 코덱의 다른 구현에서 제공하는 프라이빗 데이터와 동일하지 않습니다. 이 항목의 단계를 사용하여 항상 이 값을 생성해야 합니다. 다른 파일에서 프라이빗 데이터를 복사하지 않습니다.

 

비디오 인코딩 구성

비디오 작업