D3D11 presenta una API de video que es básicamente DXVA2 con una interfaz ligeramente alterada arriba. Necesita una buena comprensión de H.264 BitStreams para proceder (¡realmente!). es decir, asegúrese de tener un analizador H.264 a mano para extraer campos de las estructuras SPS y PPS y todas las rebanadas de un marco codificado.
1) Obtenga la instancia ID3D11VIDEDEVICE de su ID3D11Device e ID3D11VideOcontext de su contexto de dispositivo D3D11 inmediato Nota: ¡En Win7, debe crear su dispositivo con el nivel de funciones 9_3 para obtener soporte de video! (En Win8 simplemente funciona)
2) Cree una instancia de ID3D11VideOdEcoder para H.264 Use ID3D11VIDEDEDVICE :: GetVideodeCoderProfileCount, getVideodeCoderProfile, checkVideOdEcoderFormat ... para iterar a través de todos los perfiles compatibles y encontrar uno con GUID D3D11_Decoder_Profile_H264_Vld_NOfgT For H264 sin Guid. Como salida, su mejor apuesta es DXGI_FORMAT_NV12.
3) Decodificación de los marcos individuales ver Soporte de decodificación de video Direct3D 11 en Media Foundation:
- ID3D11VideOcontext :: decoderBeginFrame (decoder, outputView -> textura de cuadro decodificado)
- Llenar buffers:
- D3d11_video_decoder_buffer_picture_parameters
- D3d11_video_decoder_buffer_inverse_quantization_matrix
- D3d11_video_decoder_buffer_bitstream
- D3d11_video_decoder_buffer_slice_control
Los buffers se llenan con las estructuras DXVA2 correspondientes (ver DXVA2.H) La especificación completa de DXVA2 está aquí, lo necesitará para asignar los campos H.264 SPS/PPS en consecuencia.
Ver:
Después:
- ID3D11VideOcontext :: SubmitBuffers para confirmar todos los buffers llenos
- ID3D11VideOcontext :: DecoderEndframe para finalizar el marco actual
3) D3D11_Video_Decoder_Buffer_Picture_Parameters Buffer también contiene información sobre todas las referencias de marcos/superficie: ¡debe administrarlos usted mismo, es decir, asegúrese de que las superficies/texturas estén disponibles para la GPU!
Es bastante complicado, verifique FFMPEG y Media Player Classic, ambos tienen soporte DXVA2 (aunque no a través de DX11).
4) Convierte de NV12 a RGB (a), algunas GPU (niveles de características D3D11) permiten usar NV12 como entrada de sombreador, otras no. En caso de que no sea posible usar NV12 directamente, eche un vistazo a las interfaces D3D11VideOprocessor que cuentan con la conversión NV12/YUV420-> RGB para todas las GPU con soporte D3D11.
La conversión podría realizarse en un código como este:
// Setup ID3D11Video*
ID3D11VideoProcessor * d3dVideoProc = ...;
ID3D11VideoDevice * d3dVideoDevice = ...;
ID3D11VideoProcessorEnumerator * d3dVideoProcEnum = ...;
ID3D11Texture2D * srcTextureNV12Fmt = ...;
ID3D11Texture2D * dstTextureRGBFmt = ...;
// Use Video Processor
// Create views for VideoProc In/Output
ID3D11VideoProcessorInputView * videoProcInputView;
ID3D11VideoProcessorOutputView * videoProcOutputView;
{
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inputViewDesc = { 0 };
inputViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
inputViewDesc.Texture2D.ArraySlice = arraySliceIdx;
inputViewDesc.Texture2D.MipSlice = 0;
hr = d3dVideoDevice->CreateVideoProcessorInputView(srcTextureNV12Fmt, d3dVideoProcEnum, &inputViewDesc, &videoProcInputView);
}
{
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outputViewDesc = { D3D11_VPOV_DIMENSION_TEXTURE2D };
outputViewDesc.Texture2D.MipSlice = 0;
hr = d3dVideoDevice->CreateVideoProcessorOutputView(dstTextureRGBFmt, d3dVideoProcEnum, &outputViewDesc, &videoProcOutputView);
}
// Setup streams
D3D11_VIDEO_PROCESSOR_STREAM streams = { 0 };
streams.Enable = TRUE;
streams.pInputSurface = videoProcInputView.get();
RECT srcRect = { /* source rectangle in pixels*/ };
RECT dstRect = { /* destination rectangle in pixels*/ };
// Perform VideoProc Blit Operation (with color conversion)
hr = videoCtx_->VideoProcessorBlt(d3dVideoProc, videoProcOutputView.get(), 0, 1, &streams);