Share via


Compatibilidad con DXVA 2.0 en DirectShow

En este tema se describe cómo admitir DirectX Video Acceleration (DXVA) 2.0 en un filtro de descodificador DirectShow. En concreto, describe la comunicación entre el descodificador y el representador de vídeo. En este tema no se describe cómo implementar la descodificación de DXVA.

Requisitos previos

En este tema se supone que está familiarizado con la escritura de filtros directShow. Para obtener más información, consulte el tema Escribir filtros directShow en la documentación del SDK de DirectShow. En los ejemplos de código de este tema se supone que el filtro de descodificador se deriva de la clase CTransformFilter , con la siguiente definición de clase:

class CDecoder : public CTransformFilter
{
public:
    static CUnknown* WINAPI CreateInstance(IUnknown *pUnk, HRESULT *pHr);

    HRESULT CompleteConnect(PIN_DIRECTION direction, IPin *pPin);

    HRESULT InitAllocator(IMemAllocator **ppAlloc);
    HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp);

    // TODO: The implementations of these methods depend on the specific decoder.
    HRESULT CheckInputType(const CMediaType *mtIn);
    HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);
    HRESULT CTransformFilter::GetMediaType(int,CMediaType *);

private:
    CDecoder(HRESULT *pHr);
    ~CDecoder();

    CBasePin * GetPin(int n);

    HRESULT ConfigureDXVA2(IPin *pPin);
    HRESULT SetEVRForDXVA2(IPin *pPin);

    HRESULT FindDecoderConfiguration(
        /* [in] */  IDirectXVideoDecoderService *pDecoderService,
        /* [in] */  const GUID& guidDecoder, 
        /* [out] */ DXVA2_ConfigPictureDecode *pSelectedConfig,
        /* [out] */ BOOL *pbFoundDXVA2Configuration
        );

private:
    IDirectXVideoDecoderService *m_pDecoderService;

    DXVA2_ConfigPictureDecode m_DecoderConfig;
    GUID                      m_DecoderGuid;
    HANDLE                    m_hDevice;

    FOURCC                    m_fccOutputFormat;
};

En el resto de este tema, el término descodificador hace referencia al filtro de descodificador, que recibe vídeo comprimido y genera vídeo sin comprimir. El término dispositivo descodificador hace referencia a un acelerador de vídeo de hardware implementado por el controlador de gráficos.

Estos son los pasos básicos que debe realizar un filtro de descodificador para admitir DXVA 2.0:

  1. Negociar un tipo de medio.
  2. Busque una configuración de descodificador DXVA.
  3. Notifique al representador de vídeo que el descodificador usa la descodificación DXVA.
  4. Proporcione un asignador personalizado que asigne superficies de Direct3D.

Estos pasos se describen con más detalle en el resto de este tema.

Notas de migración

Si va a migrar desde DXVA 1.0, debe tener en cuenta algunas diferencias significativas entre las dos versiones:

  • DXVA 2.0 no usa las interfaces IAMVideoAccelerator e IAMVideoAcceleratorNotify , ya que el descodificador puede acceder a las API de DXVA 2.0 directamente a través de la interfaz IDirectXVideoDecoder .
  • Durante la negociación de tipos multimedia, el descodificador no usa un GUID de aceleración de vídeo como subtipo. En su lugar, el subtipo es solo el formato de vídeo sin comprimir (como NV12), como con la descodificación de software.
  • El procedimiento para configurar el acelerador ha cambiado. En DXVA 1.0, el descodificador llama a Execute con una estructura de DXVA_ConfigPictureDecode para configurar el accerlator. En DXVA 2.0, el descodificador usa la interfaz IDirectXVideoDecoderService , como se describe en la sección siguiente.
  • El descodificador asigna los búferes sin comprimir. El representador de vídeo ya no los asigna.
  • En lugar de llamar a IAMVideoAccelerator::D isplayFrame para mostrar el marco descodificado, el descodificador entrega el fotograma al representador llamando a IMemInputPin::Receive, como con la descodificación de software.
  • El descodificador ya no es responsable de comprobar cuándo los búferes de datos son seguros para las actualizaciones. Por lo tanto, DXVA 2.0 no tiene ningún método equivalente a IAMVideoAccelerator::QueryRenderStatus.
  • La combinación de subpictura se realiza mediante el representador de vídeo, mediante las API del procesador de vídeo DXVA2.0. Los descodificadores que proporcionan subpicturas (por ejemplo, descodificadores de DVD) deben enviar datos de subpicturas en un pin de salida independiente.

Para las operaciones de descodificación, DXVA 2.0 usa las mismas estructuras de datos que DXVA 1.0.

El filtro de representador de vídeo mejorado (EVR) admite DXVA 2.0. Los filtros del representador de mezcla de vídeos (VMR-7 y VMR-9) solo admiten DXVA 1.0.

Búsqueda de una configuración de descodificador

Una vez que el descodificador negocia el tipo de medio de salida, debe encontrar una configuración compatible para el dispositivo de descodificador DXVA. Puede realizar este paso dentro del método CBaseOutputPin::CompleteConnect del pin de salida. Este paso garantiza que el controlador de gráficos admita las funcionalidades necesarias para el descodificador, antes de que el descodificador se confirme en el uso de DXVA.

Para buscar una configuración para el dispositivo descodificador, haga lo siguiente:

  1. Consulte el pin de entrada del representador para la interfaz IMFGetService .

  2. Llame a IMFGetService::GetService para obtener un puntero a la interfaz IDirect3DDeviceManager9 . El GUID del servicio se MR_VIDEO_ACCELERATION_SERVICE.

  3. Llama a IDirect3DDeviceManager9::OpenDeviceHandle para obtener un identificador para el dispositivo Direct3D del representador.

  4. Llame a IDirect3DDeviceManager9::GetVideoService y pase el identificador del dispositivo. Este método devuelve un puntero a la interfaz IDirectXVideoDecoderService .

  5. Llame a IDirectXVideoDecoderService::GetDecoderDeviceGuids. Este método devuelve una matriz de GUID de dispositivo de descodificador.

  6. Recorra en bucle la matriz de GUID de descodificador para buscar las que admite el filtro de descodificador. Por ejemplo, para un descodificador MPEG-2, buscaría DXVA2_ModeMPEG2_MOCOMP, DXVA2_ModeMPEG2_IDCT o DXVA2_ModeMPEG2_VLD.

  7. Cuando encuentre un GUID de dispositivo de descodificador candidato, pase el GUID al método IDirectXVideoDecoderService::GetDecoderRenderTargets . Este método devuelve una matriz de formatos de destino de representación, especificados como valores D3DFORMAT .

  8. Recorra en bucle los formatos de destino de representación y busque uno que coincida con el formato de salida. Normalmente, un dispositivo descodificador admite un único formato de destino de representación. El filtro de descodificador debe conectarse al representador mediante este subtipo. En la primera llamada a CompleteConnect, el descodificador puede anular el formato de destino de representación y, a continuación, devolver este formato como un tipo de salida preferido.

  9. Llame a IDirectXVideoDecoderService::GetDecoderConfigurations. Pase el mismo GUID del dispositivo de descodificador, junto con una estructura de DXVA2_VideoDesc que describe el formato propuesto. El método devuelve una matriz de estructuras de DXVA2_ConfigPictureDecode . Cada estructura describe una posible configuración para el dispositivo descodificador.

  10. Suponiendo que los pasos anteriores se realicen correctamente, almacene el identificador del dispositivo Direct3D, el GUID del dispositivo descodificador y la estructura de configuración. El filtro usará esta información para crear el dispositivo descodificador.

En el código siguiente se muestra cómo buscar una configuración de descodificador.

HRESULT CDecoder::ConfigureDXVA2(IPin *pPin)
{
    UINT    cDecoderGuids = 0;
    BOOL    bFoundDXVA2Configuration = FALSE;
    GUID    guidDecoder = GUID_NULL;

    DXVA2_ConfigPictureDecode config;
    ZeroMemory(&config, sizeof(config));

    // Variables that follow must be cleaned up at the end.

    IMFGetService               *pGetService = NULL;
    IDirect3DDeviceManager9     *pDeviceManager = NULL;
    IDirectXVideoDecoderService *pDecoderService = NULL;

    GUID   *pDecoderGuids = NULL; // size = cDecoderGuids
    HANDLE hDevice = INVALID_HANDLE_VALUE;

    // Query the pin for IMFGetService.
    HRESULT hr = pPin->QueryInterface(IID_PPV_ARGS(&pGetService));

    // Get the Direct3D device manager.
    if (SUCCEEDED(hr))
    {
        hr = pGetService->GetService(

            MR_VIDEO_ACCELERATION_SERVICE,
            IID_PPV_ARGS(&pDeviceManager)
            );
    }

    // Open a new device handle.
    if (SUCCEEDED(hr))
    {
        hr = pDeviceManager->OpenDeviceHandle(&hDevice);
    } 

    // Get the video decoder service.
    if (SUCCEEDED(hr))
    {
        hr = pDeviceManager->GetVideoService(
            hDevice, IID_PPV_ARGS(&pDecoderService));
    }

    // Get the decoder GUIDs.
    if (SUCCEEDED(hr))
    {
        hr = pDecoderService->GetDecoderDeviceGuids(
            &cDecoderGuids, &pDecoderGuids);
    }

    if (SUCCEEDED(hr))
    {
        // Look for the decoder GUIDs we want.
        for (UINT iGuid = 0; iGuid < cDecoderGuids; iGuid++)
        {
            // Do we support this mode?
            if (!IsSupportedDecoderMode(pDecoderGuids[iGuid]))
            {
                continue;
            }

            // Find a configuration that we support. 
            hr = FindDecoderConfiguration(pDecoderService, pDecoderGuids[iGuid],
                &config, &bFoundDXVA2Configuration);
            if (FAILED(hr))
            {
                break;
            }

            if (bFoundDXVA2Configuration)
            {
                // Found a good configuration. Save the GUID and exit the loop.
                guidDecoder = pDecoderGuids[iGuid];
                break;
            }
        }
    }

    if (!bFoundDXVA2Configuration)
    {
        hr = E_FAIL; // Unable to find a configuration.
    }

    if (SUCCEEDED(hr))
    {
        // Store the things we will need later.

        SafeRelease(&m_pDecoderService);
        m_pDecoderService = pDecoderService;
        m_pDecoderService->AddRef();

        m_DecoderConfig = config;
        m_DecoderGuid = guidDecoder;
        m_hDevice = hDevice;
    }

    if (FAILED(hr))
    {
        if (hDevice != INVALID_HANDLE_VALUE)
        {
            pDeviceManager->CloseDeviceHandle(hDevice);
        }
    }

    SafeRelease(&pGetService);
    SafeRelease(&pDeviceManager);
    SafeRelease(&pDecoderService);
    return hr;
}
HRESULT CDecoder::FindDecoderConfiguration(
    /* [in] */  IDirectXVideoDecoderService *pDecoderService,
    /* [in] */  const GUID& guidDecoder, 
    /* [out] */ DXVA2_ConfigPictureDecode *pSelectedConfig,
    /* [out] */ BOOL *pbFoundDXVA2Configuration
    )
{
    HRESULT hr = S_OK;
    UINT cFormats = 0;
    UINT cConfigurations = 0;

    D3DFORMAT                   *pFormats = NULL;     // size = cFormats
    DXVA2_ConfigPictureDecode   *pConfig = NULL;      // size = cConfigurations

    // Find the valid render target formats for this decoder GUID.
    hr = pDecoderService->GetDecoderRenderTargets(
        guidDecoder,
        &cFormats,
        &pFormats
        );

    if (SUCCEEDED(hr))
    {
        // Look for a format that matches our output format.
        for (UINT iFormat = 0; iFormat < cFormats;  iFormat++)
        {
            if (pFormats[iFormat] != (D3DFORMAT)m_fccOutputFormat)
            {
                continue;
            }

            // Fill in the video description. Set the width, height, format, 
            // and frame rate.
            DXVA2_VideoDesc videoDesc = {0};

            FillInVideoDescription(&videoDesc); // Private helper function.
            videoDesc.Format = pFormats[iFormat];

            // Get the available configurations.
            hr = pDecoderService->GetDecoderConfigurations(
                guidDecoder,
                &videoDesc,
                NULL, // Reserved.
                &cConfigurations,
                &pConfig
                );

            if (FAILED(hr))
            {
                break;
            }

            // Find a supported configuration.
            for (UINT iConfig = 0; iConfig < cConfigurations; iConfig++)
            {
                if (IsSupportedDecoderConfig(pConfig[iConfig]))
                {
                    // This configuration is good.
                    *pbFoundDXVA2Configuration = TRUE;
                    *pSelectedConfig = pConfig[iConfig];
                    break;
                }
            }

            CoTaskMemFree(pConfig);
            break;

        } // End of formats loop.
    }

    CoTaskMemFree(pFormats);

    // Note: It is possible to return S_OK without finding a configuration.
    return hr;
}

Dado que este ejemplo es genérico, parte de la lógica se ha colocado en funciones auxiliares que el descodificador tendría que implementar. En el código siguiente se muestran las declaraciones de estas funciones:

// Returns TRUE if the decoder supports a given decoding mode.
BOOL IsSupportedDecoderMode(const GUID& mode);

// Returns TRUE if the decoder supports a given decoding configuration.
BOOL IsSupportedDecoderConfig(const DXVA2_ConfigPictureDecode& config);

// Fills in a DXVA2_VideoDesc structure based on the input format.
void FillInVideoDescription(DXVA2_VideoDesc *pDesc);

Notificación al representador de vídeo

Si el descodificador encuentra una configuración de descodificador, el siguiente paso es notificar al representador de vídeo que el descodificador usará la aceleración de hardware. Puede realizar este paso dentro del método CompleteConnect . Este paso debe producirse antes de seleccionar el asignador, ya que afecta a cómo se selecciona el asignador.

  1. Consulte el pin de entrada del representador para la interfaz IMFGetService .
  2. Llame a IMFGetService::GetService para obtener un puntero a la interfaz IDirectXVideoMemoryConfiguration . El GUID de servicio se MR_VIDEO_ACCELERATION_SERVICE.
  3. Llame a IDirectXVideoMemoryConfiguration::GetAvailableSurfaceTypeByIndex en un bucle, incrementando la variable dwTypeIndex desde cero. Detenga cuando el método devuelva el valor DXVA2_SurfaceType_DecoderRenderTarget en el parámetro pdwType . Este paso garantiza que el representador de vídeo admita la descodificación acelerada por hardware. Este paso siempre se realizará correctamente para el filtro EVR.
  4. Si el paso anterior se realizó correctamente, llame a IDirectXVideoMemoryConfiguration::SetSurfaceType con el valor DXVA2_SurfaceType_DecoderRenderTarget. Al llamar a SetSurfaceType con este valor, el representador de vídeo se coloca en modo DXVA. Cuando el representador de vídeo está en este modo, el descodificador debe proporcionar su propio asignador.

En el código siguiente se muestra cómo notificar al representador de vídeo.

HRESULT CDecoder::SetEVRForDXVA2(IPin *pPin)
{
    HRESULT hr = S_OK;

    IMFGetService                       *pGetService = NULL;
    IDirectXVideoMemoryConfiguration    *pVideoConfig = NULL;

    // Query the pin for IMFGetService.
    hr = pPin->QueryInterface(__uuidof(IMFGetService), (void**)&pGetService);

    // Get the IDirectXVideoMemoryConfiguration interface.
    if (SUCCEEDED(hr))
    {
        hr = pGetService->GetService(
            MR_VIDEO_ACCELERATION_SERVICE, IID_PPV_ARGS(&pVideoConfig));
    }

    // Notify the EVR. 
    if (SUCCEEDED(hr))
    {
        DXVA2_SurfaceType surfaceType;

        for (DWORD iTypeIndex = 0; ; iTypeIndex++)
        {
            hr = pVideoConfig->GetAvailableSurfaceTypeByIndex(iTypeIndex, &surfaceType);
            
            if (FAILED(hr))
            {
                break;
            }

            if (surfaceType == DXVA2_SurfaceType_DecoderRenderTarget)
            {
                hr = pVideoConfig->SetSurfaceType(DXVA2_SurfaceType_DecoderRenderTarget);
                break;
            }
        }
    }

    SafeRelease(&pGetService);
    SafeRelease(&pVideoConfig);

    return hr;
}

Si el descodificador encuentra una configuración válida y notifica correctamente al representador de vídeo, el descodificador puede usar DXVA para la descodificación. El descodificador debe implementar un asignador personalizado para su pin de salida, como se describe en la sección siguiente.

Asignar búferes sin comprimir

En DXVA 2.0, el descodificador es responsable de asignar superficies de Direct3D para usarlas como búferes de vídeo sin comprimir. Por lo tanto, el descodificador debe implementar un asignador personalizado que creará las superficies. Los ejemplos multimedia proporcionados por este asignador contendrán punteros a las superficies de Direct3D. El EVR recupera un puntero a la superficie llamando a IMFGetService::GetService en el ejemplo multimedia. El identificador de servicio se MR_BUFFER_SERVICE.

Para proporcionar el asignador personalizado, realice los pasos siguientes:

  1. Defina una clase para los ejemplos multimedia. Esta clase puede derivar de la clase CMediaSample . Dentro de esta clase, haga lo siguiente:
    • Almacene un puntero a la superficie de Direct3D.
    • Implemente la interfaz IMFGetService . En el método GetService , si el GUID del servicio es MR_BUFFER_SERVICE, consulte la superficie de Direct3D para la interfaz solicitada. De lo contrario, GetService puede devolver MF_E_UNSUPPORTED_SERVICE.
    • Invalide el método CMediaSample::GetPointer para devolver E_NOTIMPL.
  2. Defina una clase para el asignador. El asignador puede derivar de la clase CBaseAllocator . Dentro de esta clase, haga lo siguiente.
  3. En el pin de salida del filtro, invalide el método CBaseOutputPin::InitAllocator . Dentro de este método, cree una instancia del asignador personalizado.
  4. En el filtro, implemente el método CTransformFilter::D ecideBufferSize . El parámetro pProperties indica el número de superficies que requiere el EVR. Agregue a este valor el número de superficies que necesita el descodificador y llame a IMemAllocator::SetProperties en el asignador.

En el código siguiente se muestra cómo implementar la clase de ejemplo multimedia:

class CDecoderSample : public CMediaSample, public IMFGetService
{
    friend class CDecoderAllocator;

public:

    CDecoderSample(CDecoderAllocator *pAlloc, HRESULT *phr)
        : CMediaSample(NAME("DecoderSample"), (CBaseAllocator*)pAlloc, phr, NULL, 0),
          m_pSurface(NULL),
          m_dwSurfaceId(0)
    { 
    }

    // Note: CMediaSample does not derive from CUnknown, so we cannot use the
    //       DECLARE_IUNKNOWN macro that is used by most of the filter classes.

    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
    {
        CheckPointer(ppv, E_POINTER);

        if (riid == IID_IMFGetService)
        {
            *ppv = static_cast<IMFGetService*>(this);
            AddRef();
            return S_OK;
        }
        else
        {
            return CMediaSample::QueryInterface(riid, ppv);
        }
    }
    STDMETHODIMP_(ULONG) AddRef()
    {
        return CMediaSample::AddRef();
    }

    STDMETHODIMP_(ULONG) Release()
    {
        // Return a temporary variable for thread safety.
        ULONG cRef = CMediaSample::Release();
        return cRef;
    }

    // IMFGetService::GetService
    STDMETHODIMP GetService(REFGUID guidService, REFIID riid, LPVOID *ppv)
    {
        if (guidService != MR_BUFFER_SERVICE)
        {
            return MF_E_UNSUPPORTED_SERVICE;
        }
        else if (m_pSurface == NULL)
        {
            return E_NOINTERFACE;
        }
        else
        {
            return m_pSurface->QueryInterface(riid, ppv);
        }
    }

    // Override GetPointer because this class does not manage a system memory buffer.
    // The EVR uses the MR_BUFFER_SERVICE service to get the Direct3D surface.
    STDMETHODIMP GetPointer(BYTE ** ppBuffer)
    {
        return E_NOTIMPL;
    }

private:

    // Sets the pointer to the Direct3D surface. 
    void SetSurface(DWORD surfaceId, IDirect3DSurface9 *pSurf)
    {
        SafeRelease(&m_pSurface);

        m_pSurface = pSurf;
        if (m_pSurface)
        {
            m_pSurface->AddRef();
        }

        m_dwSurfaceId = surfaceId;
    }

    IDirect3DSurface9   *m_pSurface;
    DWORD               m_dwSurfaceId;
};

En el código siguiente se muestra cómo implementar el método Alloc en el asignador.

HRESULT CDecoderAllocator::Alloc()
{
    CAutoLock lock(this);

    HRESULT hr = S_OK;

    if (m_pDXVA2Service == NULL)
    {
        return E_UNEXPECTED;
    }

    hr = CBaseAllocator::Alloc();

    // If the requirements have not changed, do not reallocate.
    if (hr == S_FALSE)
    {
        return S_OK;
    }

    if (SUCCEEDED(hr))
    {
        // Free the old resources.
        Free();

        // Allocate a new array of pointers.
        m_ppRTSurfaceArray = new (std::nothrow) IDirect3DSurface9*[m_lCount];
        if (m_ppRTSurfaceArray == NULL)
        {
            hr = E_OUTOFMEMORY;
        }
        else
        {
            ZeroMemory(m_ppRTSurfaceArray, sizeof(IDirect3DSurface9*) * m_lCount);
        }
    }

    // Allocate the surfaces.
    if (SUCCEEDED(hr))
    {
        hr = m_pDXVA2Service->CreateSurface(
            m_dwWidth,
            m_dwHeight,
            m_lCount - 1,
            (D3DFORMAT)m_dwFormat,
            D3DPOOL_DEFAULT,
            0,
            DXVA2_VideoDecoderRenderTarget,
            m_ppRTSurfaceArray,
            NULL
            );
    }

    if (SUCCEEDED(hr))
    {
        for (m_lAllocated = 0; m_lAllocated < m_lCount; m_lAllocated++)
        {
            CDecoderSample *pSample = new (std::nothrow) CDecoderSample(this, &hr);

            if (pSample == NULL)
            {
                hr = E_OUTOFMEMORY;
                break;
            }
            if (FAILED(hr))
            {
                break;
            }
            // Assign the Direct3D surface pointer and the index.
            pSample->SetSurface(m_lAllocated, m_ppRTSurfaceArray[m_lAllocated]);

            // Add to the sample list.
            m_lFree.Add(pSample);
        }
    }

    if (SUCCEEDED(hr))
    {
        m_bChanged = FALSE;
    }
    return hr;
}

Este es el código del método Free :

void CDecoderAllocator::Free()
{
    CMediaSample *pSample = NULL;

    do
    {
        pSample = m_lFree.RemoveHead();
        if (pSample)
        {
            delete pSample;
        }
    } while (pSample);

    if (m_ppRTSurfaceArray)
    {
        for (long i = 0; i < m_lAllocated; i++)
        {
            SafeRelease(&m_ppRTSurfaceArray[i]);
        }

        delete [] m_ppRTSurfaceArray;
    }
    m_lAllocated = 0;
}

Para obtener más información sobre cómo implementar asignadores personalizados, consulte el tema Proporcionar un asignador personalizado en la documentación del SDK de DirectShow.

Descodificación

Para crear el dispositivo descodificador, llame a IDirectXVideoDecoderService::CreateVideoDecoder. El método devuelve un puntero a la interfaz IDirectXVideoDecoder del dispositivo descodificador.

En cada fotograma, llame a IDirect3DDeviceManager9::TestDevice para probar el identificador del dispositivo. Si el dispositivo ha cambiado, el método devuelve DXVA2_E_NEW_VIDEO_DEVICE. Si esto ocurre, haga lo siguiente:

  1. Cierre el identificador del dispositivo llamando a IDirect3DDeviceManager9::CloseDeviceHandle.
  2. Libere los punteros IDirectXVideoDecoderService e IDirectXVideoDecoder .
  3. Abra un nuevo identificador de dispositivo.
  4. Negocia una nueva configuración de descodificador, como se describe en la sección Búsqueda de una configuración de descodificador.
  5. Cree un nuevo dispositivo de descodificador.

Suponiendo que el identificador del dispositivo es válido, el proceso de descodificación funciona de la siguiente manera:

  1. Llame a IDirectXVideoDecoder::BeginFrame.
  2. Haga lo siguiente una o varias veces:
    1. Llame a IDirectXVideoDecoder::GetBuffer para obtener un búfer de descodificador DXVA.
    2. Rellene el búfer.
    3. Llame a IDirectXVideoDecoder::ReleaseBuffer.
  3. Llame a IDirectXVideoDecoder::Execute para realizar las operaciones de descodificación en el marco.

DXVA 2.0 usa las mismas estructuras de datos que DXVA 1.0 para las operaciones de descodificación. Para el conjunto original de perfiles DXVA (para H.261, H.263 y MPEG-2), estas estructuras de datos se describen en la especificación DXVA 1.0.

Dentro de cada par de llamadas BeginFrame/Execute , puede llamar a GetBuffer varias veces, pero solo una vez para cada tipo de búfer DXVA. Si lo llama dos veces con el mismo tipo de búfer, sobrescribirá los datos.

Después de llamar a Execute, llame a IMemInputPin::Receive para entregar el fotograma al representador de vídeo, como con la descodificación de software. El método Receive es asincrónico; después de que se devuelva, el descodificador puede continuar descodificar el siguiente fotograma. El controlador de pantalla impide que los comandos de descodificación sobrescriban el búfer mientras el búfer está en uso. El descodificador no debe reutilizar una superficie para descodificar otro fotograma hasta que el representador haya liberado el ejemplo. Cuando el representador libera el ejemplo, el asignador vuelve a poner el ejemplo en su grupo de ejemplos disponibles. Para obtener el siguiente ejemplo disponible, llame a CBaseOutputPin::GetDeliveryBuffer, que a su vez llama a IMemAllocator::GetBuffer. Para obtener más información, vea el tema Información general de Data Flow en DirectShow en la documentación de DirectShow.

Aceleración de vídeo de DirectX 2.0