Partilhar via


Suporte ao DXVA 2.0 no Media Foundation

Este tópico descreve como dar suporte à Aceleração de Vídeo DirectX (DXVA) 2.0 em uma MFT (transformação do Media Foundation) usando o Microsoft Direct3D 9 Especificamente, ele descreve a comunicação entre o decodificador e o renderizador de vídeo, que é mediado pelo carregador de topologia. Este tópico não descreve como implementar a decodificação DXVA.

No restante deste tópico, o termo decodificador refere-se ao decodificador MFT, que recebe vídeo compactado e gera vídeo descompactado. O termo dispositivo de decodificador refere-se a um acelerador de vídeo de hardware implementado pelo driver gráfico.

Dica

Para obter informações sobre a decodificação de vídeo do Microsoft Direct3D 11, consulte Suporte à decodificação de vídeo direct3D 11 no Media Foundation.

 

Observação

Os aplicativos da Windows Store devem usar o Direct3D 11.

 

Estas são as etapas básicas que um decodificador deve executar para dar suporte ao DXVA 2.0 no Media Foundation:

  1. Abra um identificador para o dispositivo Direct3D 9.
  2. Localize uma configuração de decodificador DXVA.
  3. Alocar buffers descompactados.
  4. Decodificar quadros.

Essas etapas são descritas mais detalhadamente no restante deste tópico.

Abrindo um identificador de dispositivo Direct3D

O MFT usa o gerenciador de dispositivos Do Microsoft Direct3D para obter um identificador para o dispositivo Direct3D 9. Para abrir o identificador do dispositivo, execute as seguintes etapas:

  1. Exponha o atributo MF_SA_D3D_AWARE com o valor TRUE. O carregador de topologia consulta esse atributo chamando IMFTransform::GetAttributes. Definir o atributo como TRUE notifica o carregador de topologia de que o MFT dá suporte a DXVA.
  2. Quando a negociação de formato começa, o carregador de topologia chama IMFTransform::P rocessMessage com a mensagem MFT_MESSAGE_SET_D3D_MANAGER . O parâmetro ulParam é um ponteiro IUnknown para o gerenciador de dispositivos Direct3D do renderizador de vídeo. Consulte esse ponteiro para a interface IDirect3DDeviceManager9 .
  3. Chame IDirect3DDeviceManager9::OpenDeviceHandle para obter um identificador para o dispositivo Direct3D do renderizador.
  4. Chame IDirect3DDeviceManager9::GetVideoService e passe o identificador do dispositivo. Esse método retorna um ponteiro para a interface IDirectXVideoDecoderService .
  5. Armazene em cache os ponteiros e o identificador do dispositivo.

Localizando uma configuração do decodificador

O MFT deve encontrar uma configuração compatível para o dispositivo decodificador DXVA. Execute as seguintes etapas dentro do método IMFTransform::SetInputType depois de validar o tipo de entrada:

  1. Chame IDirectXVideoDecoderService::GetDecoderDeviceGuids. Esse método retorna uma matriz de GUIDs de dispositivo de decodificador.

  2. Execute um loop pela matriz de GUIDs do decodificador para localizar os que o decodificador dá suporte. Por exemplo, para um decodificador MPEG-2, você procuraria DXVA2_ModeMPEG2_MOCOMP, DXVA2_ModeMPEG2_IDCT ou DXVA2_ModeMPEG2_VLD.

  3. Quando encontrar um GUID de dispositivo de decodificador candidato, passe o GUID para o método IDirectXVideoDecoderService::GetDecoderRenderTargets . Esse método retorna uma matriz de formatos de destino de renderização, especificados como valores D3DFORMAT .

  4. Execute um loop pelos formatos de destino de renderização e procure um formato compatível com o decodificador.

  5. Chame IDirectXVideoDecoderService::GetDecoderConfigurations. Passe o mesmo GUID do dispositivo de decodificador, juntamente com uma estrutura de DXVA2_VideoDesc que descreve o formato de saída proposto. O método retorna uma matriz de estruturas DXVA2_ConfigPictureDecode . Cada estrutura descreve uma configuração possível para o dispositivo decodificador. Procure uma configuração compatível com o decodificador.

  6. Armazene o formato e a configuração de destino de renderização.

No método IMFTransform::GetOutputAvailableType , retorne um formato de vídeo descompactado, com base no formato de destino de renderização proposto.

No método IMFTransform::SetOutputType, marcar o tipo de mídia em relação ao formato de destino de renderização.

Fallback para Decodificação de Software

Se o MFT não conseguir encontrar uma configuração DXVA (por exemplo, se o driver gráfico não tiver os recursos corretos), ele deverá retornar o código de erro MF_E_UNSUPPORTED_D3D_TYPE dos métodos SetInputType e SetOutputType . O carregador de topologia responderá enviando a mensagem MFT_MESSAGE_SET_D3D_MANAGER com o valor NULL para o parâmetro ulParam . O MFT deve liberar seu ponteiro para a interface IDirect3DDeviceManager9 . O carregador de topologia renegociará o tipo de mídia e o MFT poderá usar a decodificação de software.

Alocando buffers descompactados

No DXVA 2.0, o decodificador é responsável por alocar superfícies Direct3D a serem usadas como buffers de vídeo descompactados. O decodificador deve alocar três superfícies para o EVR usar para desinterlacização. Esse número foi corrigido, pois o Media Foundation não fornece uma maneira de o EVR especificar quantas superfícies o driver gráfico requer para desinterlacização. Três superfícies devem ser suficientes para qualquer driver.

No método IMFTransform::GetOutputStreamInfo , defina o sinalizador MFT_OUTPUT_STREAM_PROVIDES_SAMPLES na estrutura MFT_OUTPUT_STREAM_INFO . Esse sinalizador notifica a Sessão de Mídia de que o MFT aloca seus próprios exemplos de saída.

Para criar as superfícies, chame IDirectXVideoAccelerationService::CreateSurface. (A interface IDirectXVideoDecoderService herda esse método de IDirectXVideoAccelerationService.) Você pode fazer isso em SetInputType, depois de localizar o formato de destino de renderização.

Para cada superfície, chame MFCreateVideoSampleFromSurface para criar um exemplo de mídia para manter a superfície. O método retorna um ponteiro para a interface IMFSample .

Decodificação

Para criar o dispositivo decodificador, chame IDirectXVideoDecoderService::CreateVideoDecoder. O método retorna um ponteiro para a interface IDirectXVideoDecoder do dispositivo decodificador.

A decodificação deve ocorrer dentro do método IMFTransform::P rocessOutput . Em cada quadro, chame IDirect3DDeviceManager9::TestDevice para testar o identificador do dispositivo. Se o dispositivo tiver sido alterado, o método retornará DXVA2_E_NEW_VIDEO_DEVICE. Se isso ocorrer, faça o seguinte:

  1. Feche o identificador do dispositivo chamando IDirect3DDeviceManager9::CloseDeviceHandle.
  2. Libere os ponteiros IDirectXVideoDecoderService e IDirectXVideoDecoder .
  3. Abra um novo identificador de dispositivo.
  4. Negocie uma nova configuração de decodificador, conforme descrito em "Localizando uma configuração de decodificador" anteriormente nesta página.
  5. Crie um novo dispositivo de decodificador.

Supondo que o identificador do dispositivo seja válido, o processo de decodificação funciona da seguinte maneira:

  1. Obtenha uma superfície disponível que não está em uso no momento. (Inicialmente, todas as superfícies estão disponíveis.)
  2. Consulte o exemplo de mídia para a interface IMFTrackedSample .
  3. Chame IMFTrackedSample::SetAllocator e forneça um ponteiro para a interface IMFAsyncCallback , implementada pelo decodificador. Quando o renderizador de vídeo liberar o exemplo, o retorno de chamada do decodificador será invocado.
  4. Chame IDirectXVideoDecoder::BeginFrame.
  5. Faça o seguinte uma ou mais vezes:
    1. Chame IDirectXVideoDecoder::GetBuffer para obter um buffer de decodificador DXVA.
    2. Preencha o buffer.
    3. Chame IDirectXVideoDecoder::ReleaseBuffer.
    4. Chame IDirectXVideoDecoder::Execute para executar as operações de decodificação no quadro.

A DXVA 2.0 usa as mesmas estruturas de dados que a DXVA 1.0 para operações de decodificação. Para o conjunto original de perfis DXVA (para H.261, H.263 e MPEG-2), essas estruturas de dados são descritas na especificação DXVA 1.0.

Dentro de cada par de chamadas BeginFrame/Execute , você pode chamar GetBuffer várias vezes, mas apenas uma vez para cada tipo de buffer DXVA. Se você chamá-lo duas vezes com o mesmo tipo de buffer, substituirá os dados.

Use o retorno de chamada do método SetAllocator (etapa 3) para acompanhar quais amostras estão disponíveis no momento e quais estão em uso.

Aceleração de vídeo do DirectX 2.0

Transformações do Media Foundation