Compatibilidad con la descodificación de vídeo de Direct3D 11 en Media Foundation
En este tema se describe cómo admitir Microsoft Direct3D 11 en un descodificador de Microsoft Media Foundation. En especial, describe la comunicación entre el descodificador y el representador de vídeo. Este tema no describe cómo implementar las operaciones de descodificación.
- Información general
- Abrir un controlador de dispositivo
- Buscar una configuración de descodificador
- Reserva a la descodificación de software
- Asignación de búferes sin comprimir
- Descodificar
- Temas relacionados
Información general
En el resto de este tema, se usan los siguientes términos:
- Descodificador de software. El descodificador de software es la transformación de Media Foundation (MFT) que recibe muestras de vídeo comprimidas y genera fotogramas de vídeo sin comprimir.
- Dispositivo descodificador. El dispositivo decodificador es el acelerador de vídeo, y está implementado por el controlador de gráficos. El dispositivo descodificador realiza operaciones de descodificación aceleradas.
- Canalización. La canalización hospeda el descodificador de software y entrega búferes hacia y desde el descodificador de software. Dependiendo de la aplicación, la canalización puede ser la Sesión multimedia, el Lector de origen o el código de aplicación que llama directamente a la MFT.
Para realizar la descodificación mediante Direct3D 11, el descodificador de software debe tener un puntero a un dispositivo Direct3D 11. El dispositivo Direct3D 11 se crea externamente al descodificador de software. En un escenario de Sesión multimedia, el representador de vídeo crea el dispositivo Direct3D 11. En un escenario de Lector de origen, normalmente la aplicación crea el dispositivo Direct3D 11.
El Administrador de dispositivos DXGI se usa para compartir Direct3D 11 entre componentes. El Administrador de dispositivos DXGI expone la interfaz IMFDXGIDeviceManager. La canalización establece el puntero IMFDXGIDeviceManager en el descodificador de software enviando el mensaje MFT_MESSAGE_SET_D3D_MANAGER.
En el siguiente diagrama se muestra la relación entre el descodificador de software, Direct3D 11 y la canalización.
Estos son los pasos básicos que debe realizar un descodificador de software para admitir Direct3D 11 en Media Foundation:
- Abra un controlador para el dispositivo Direct3D 11.
- Busque una configuración de descodificador.
- Asigne búferes sin comprimir.
- Descodificar fotogramas.
Estos pasos se describen con más detalle en el resto de este tema.
Abrir un controlador de dispositivo
El descodificador MFT usa el administrador de dispositivos DXGI para obtener un controlador para el dispositivo Direct3D 11. Para abrir el controlador del dispositivo, realice los siguientes pasos:
- El descodificador MFT debe exponer al atributo MF_SA_D3D11_AWARE con el valor TRUE.
- El cargador de topología consulta este atributo llamando a IMFTransform::GetAttributes. El valor TRUE indica que MFT admite Direct3D 11.
- El cargador de topología llama a IMFTransform::ProcessMessage con el mensaje MFT_MESSAGE_SET_D3D_MANAGER. El parámetro ulParam es un puntero IUnknown al administrador de dispositivos DXGI. Consulte este puntero para la interfaz IMFDXGIDeviceManager.
- Llame a IMFDXGIDeviceManager::OpenDeviceHandle para obtener un controlador para el dispositivo Direct3D 11.
- Para obtener un puntero al dispositivo Direct3D 11, llame a IMFDXGIDeviceManager::GetVideoService. Pase el controlador del dispositivo y el valor IID_ID3D11Device. El método devuelve un puntero a la interfaz ID3D11Device.
- Para obtener un puntero al acelerador de vídeo, llame a IMFDXGIDeviceManager::GetVideoService de nuevo. Esta vez, pase el controlador del dispositivo y el valor IID_ID3D11VideoDevice. El método devuelve un puntero a la interfaz ID3D11VideoDevice.
- Llame a ID3D11Device::GetImmediateContext para obtener un puntero ID3D11DeviceContext.
- Llame a QueryInterface en ID3D11DeviceContext para obtener un puntero ID3D11VideoContext.
- Se recomienda usar la protección de varios subprocesos en el contexto del dispositivo para evitar problemas de interbloqueo que a veces pueden producirse al llamar a ID3D11VideoContext::GetDecoderBuffer o ID3D11VideoContext::ReleaseDecoderBuffer. Para establecer la protección de varios subprocesos, llame primero a QueryInterface en ID3D11Device para obtener un puntero ID3D10Multithread. A continuación, llame a ID3D10Multithread::SetMultithreadProtected y pase true para bMTProtect.
Buscar una configuración de descodificador
Para realizar la descodificación, el descodificador de software debe encontrar una configuración compatible compatible con el dispositivo de descodificador, incluido un formato de destino de representación. Este paso se produce dentro del método IMFTransform::SetInputType, como se indica a continuación.
- Valide el tipo de medio de entrada. Si se rechaza el tipo, omita los pasos restantes y devuelva un código de error.
- Llame a ID3D11VideoDevice::GetVideoDecoderProfileCount para obtener el número de perfiles admitidos.
- Llame a ID3D11VideoDevice::GetVideoDecoderProfile para enumerar los perfiles y obtener los GUID de perfil.
- Busque un GUID de perfil que coincida con el formato de vídeo y las funcionalidades del descodificador de software. Por ejemplo, un descodificador MPEG-2 buscaría D3D11_DECODER_PROFILE_MPEG2_MOCOMP,D3D11_DECODER_PROFILE_MPEG2_IDCT y D3D11_DECODER_PROFILE_MPEG2_VLD.
- Si se encuentra un GUID de descodificador adecuado, compruebe el formato de salida llamando al método ID3D11VideoDevice::CheckVideoDecoderFormat. Pase el GUID del descodificador y un valor de DXGI_FORMAT que especifique el formato de destino de representación.
- A continuación, busque una configuración adecuada para el descodificador.
- Llame a ID3D11VideoDevice::GetVideoDecoderConfigCount para obtener el número de configuraciones de descodificador. Pase el mismo GUID de dispositivo de descodificador, junto con una estructura de D3D11_VIDEO_DECODER_DESC que describe el formato de destino de representación propuesto.
- Llame a ID3D11VideoDevice::GetVideoDecoderConfig para enumerar las configuraciones del descodificador.
En el método IMFTransform::GetOutputAvailableType, devuelva un formato de vídeo sin comprimir basado en el formato de destino de representación propuesto.
En el método IMFTransform::SetOutputType, compruebe el tipo de medio con el formato de destino de representación.
Reserva a la descodificación de software
Es posible que MFT no pueda encontrar una configuración. Por ejemplo, es posible que el controlador de gráficos no admita las funcionalidades adecuadas. En ese caso, el MFT debe revertir a la descodificación de software, como se indica a continuación.
- Los métodos SetInputType ySetOutputType deben devolver MF_E_UNSUPPORTED_D3D_TYPE.
- En respuesta, el cargador de topología enviará el mensaje de MFT_MESSAGE_SET_D3D_MANAGER con el valor NULL para el parámetro ulParam.
- El MFT libera su puntero a la interfaz IMFDXGIDeviceManager.
- El cargador de topología renegocia el tipo de medio.
En este momento, el MFT puede usar la descodificación de software.
Asignación de búferes sin comprimir
El descodificador es responsable de asignar texturas de Direct3D 11 para usarlas como búferes de vídeo sin comprimir. El atributo MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT de los atributos de flujo de salida (vea IMFTransform::GetOutputStreamAttributes) se utiliza para determinar cuántas superficies debe asignar el descodificador para que el renderizador de vídeo las utilice para el desentrelazado. Un descodificador debería utilizar este valor delimitándolo por unos límites superior e inferior razonables, por ejemplo 3-32. Para obtener contenido progresivo, consulte MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE.
En el método IMFTransform::GetOutputStreamInfo, establezca la marca MFT_OUTPUT_STREAM_PROVIDES_SAMPLES en la estructura MFT_OUTPUT_STREAM_INFO. Esta marca notifica a la sesión multimedia que el MFT asigna sus propios ejemplos de salida. Para asignar los ejemplos de salida, MFT realiza los siguientes pasos:
Cree una matriz de texturas 2D llamando a ID3D11Device::CreateTexture2D. En la D3D11_TEXTURE2D_DESC, establezca ArraySize igual al número de superficies que necesita el descodificador. Esta característica incluye:
- Superficies para fotogramas de referencia.
- Superficies para el desentrelazado (tres superficies).
- Superficies que el descodificador necesita para el almacenamiento en búfer.
Las marcas de enlace (BindFlags) deben incluir la marca de D3D11_BIND_DECODER y las marcas de enlace establecidas a través del atributo MF_SA_D3D11_BINDFLAGS en los atributos de flujo de salida.
Para cada superficie de la matriz de texturas, llame a ID3D11VideoDevice::CreateVideoDecoderOutputView para crear una vista de salida del descodificador de vídeo. Durante la descodificación, estas vistas de salida se pasarán al método ID3D11VideoContext::DecoderBeginFrame.
Para cada superficie de la matriz de texturas, cree un ejemplo multimedia como se indica a continuación:
- Cree un búfer multimedia DXGI llamando a la función MFCreateDXGISurfaceBuffer. Pase el puntero ID3D11Texture2D y el desplazamiento de cada elemento de la matriz de texturas. La función devuelve un puntero IMFMediaBuffer.
- Cree un ejemplo de medio vacío llamando a la función MFCreateVideoSampleFromSurface. Establezca el parámetro pUnkSurface igual a NULL. La función devuelve un puntero IMFSample.
- Llame a IMFSample::AddBuffer para agregar el búfer multimedia al ejemplo.
Debe destruir todas las texturas que cree al mismo tiempo, en lugar de destruir solo algunas y seguir usando el recordatorio.
Descodificación
Para crear el dispositivo de descodificador, llame a ID3D11VideoDevice::CreateVideoDecoder. El método devuelve un puntero a la interfaz ID3D11VideoDecoder. La descodificación debe producirse dentro del método IMFTransform::ProcessOutput. En cada fotograma, llame a IMFDXGIDeviceManager::TestDevice para probar la disponibilidad de DXGI. Si el dispositivo ha cambiado, el descodificador de software debe volver a crear el dispositivo descodificador, como se indica a continuación:
- Cierre el identificador del dispositivo llamando a IMFDXGIDeviceManager::CloseDeviceHandle.
- Libera todos los recursos asociados al dispositivo Direct3D 11 anterior, incluidas las interfaces ID3D11VideoDecoder, ID3D11VideoContext, ID3D11Texture2D y ID3D11VideoDecoderOutputView.
- Abra un nuevo identificador de dispositivo.
- Negocia una nueva configuración de descodificador, como se ha descrito anteriormente en Buscar una configuración de descodificador. Este paso es necesario porque es posible que las funcionalidades del dispositivo hayan cambiado.
- Cree un nuevo dispositivo de descodificador.
Suponiendo que el controlador del dispositivo sea válido, el proceso de descodificación funciona de la siguiente manera:
- Obtenga una superficie disponible que no esté actualmente en uso. Inicialmente, todas las superficies están disponibles.
- Consulte el ejemplo multimedia de la interfaz IMFTrackedSample.
- Llame a IMFTrackedSample::SetAllocator y proporcione un puntero a la interfaz IMFAsyncCallback. (El descodificador de software debe implementar esta interfaz). Cuando el representador de vídeo libera el ejemplo, se invocará la devolución de llamada. Use esta devolución de llamada para realizar un seguimiento de qué ejemplos están disponibles actualmente y cuáles están en uso.
- Call ID3D11VideoContext::DecoderBeginFrame. Pase los punteros a la interfaz ID3D11VideoDecoder para el dispositivo descodificador y la interfaz ID3D11VideoDecoderOutputView para la vista de salida.
- Realice lo siguiente una o varias veces:
- Llame a ID3D11VideoContext::GetDecoderBuffer para obtener un búfer.
- Rellene el búfer.
- Call ID3D11VideoContext::ReleaseDecoderBuffer.
- Llame a ID3D11VideoContext::SubmitDecoderBuffer. Este método indica al dispositivo de descodificador que realice las operaciones de descodificación en el marco.
- Llame a ID3D11VideoContext::DecoderEndFrame para indicar el final de la descodificación del marco actual.
Direct3D 11 usa las mismas estructuras de datos que DXVA 2.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 DecoderBeginFrame y SubmitDecoderBuffer, puede llamar a GetDecoderBuffer varias veces, pero solo una vez para cada tipo de búfer. Si usa el mismo tipo de búfer dos veces sin llamar a SubmitDecoderBuffer, sobrescribirá los datos en el búfer.
Temas relacionados