O D3D11 apresenta uma API de vídeo que é basicamente DXVA2 com uma interface ligeiramente alterada acima. Você precisa de um bom entendimento dos transportes H.264 para prosseguir (realmente!). ou seja, certifique -se de ter um analisador H.264 à mão para extrair campos das estruturas SPS e PPS e todas as fatias de um quadro codificado.
1) Obtenha a instância ID3D11VideODEVICE do seu ID3D11Device e ID3D11Videocontext do seu dispositivo D3D11 imediato Nota: No Win7, você deve criar seu dispositivo com o recurso Nível 9_3 para obter suporte ao vídeo! (No Win8, ele apenas funciona)
2) Crie uma instância ID3D11VideODecoder para H.264 Use ID3D11VideODevice :: getVideOdecoderProfileCount, GetVideOdecoderProfile, checkVideodecoder_PROFIDA 4 FIMPIDANTENTENTENTENTENTENTENTENTENTENTENTENTENTENTENTEM4 DO FILDATH4 DO FILDA40 Encontre -se com Diretores D3D1D1_DED4 Como outputFormat, sua melhor aposta é dxgi_format_nv12.
3) Decodificação dos quadros individuais veja Suportando Direct3D 11 Decoding de vídeo na Media Foundation:
- Id3d11videocontext :: decoderbeginframe (decodificador, outputView -> textura do quadro decodificado)
- Preencha os buffers:
- D3d11_video_decoder_buffer_picture_parameters
- D3d11_video_decoder_buffer_inverse_quantization_matrix
- D3d11_video_decoder_buffer_bittream
- D3d11_video_decoder_buffer_slice_control
Os buffers são preenchidos com as estruturas DXVA2 correspondentes (consulte DXVA2.H) A especificação DXVA2 completa está aqui, você precisará para mapear os campos H.264 SPS/PPS de acordo.
Ver:
Então:
- ID3D11VideoContext :: submmitbuffers para cometer todos os buffers preenchidos
- ID3D11VideoContext :: decoderendframe para terminar o quadro atual
3) D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS Buffer também contém informações sobre todas as referências quadros/superfície - você precisa gerenciá -las você mesmo, ou seja, verifique se as superfícies/texturas estão disponíveis para a GPU!
É bastante complicado, verifique o FFMPEG e o Media Player Classic, ambos têm suporte ao DXVA2 (embora não via DX11).
4) Converter de NV12 para RGB (A), algumas GPUs (níveis de características D3D11) permitem usar o NV12 como entrada do shader, outros não. Caso não seja possível usar o NV12 diretamente, dê uma olhada nas interfaces D3D11VideOprocessor que apresentam conversão NV12/YUV420-> RGB para todas as GPUs com suporte D3D11.
A conversão pode ser realizada em 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);