D3D11 dispose d'une API vidéo qui est essentiellement DXVA2 avec une interface légèrement modifiée ci-dessus. Vous avez besoin d'une bonne compréhension de H.264 Bitstreams pour continuer (vraiment!). IE Assurez-vous que vous avez un analyseur H.264 à portée de main pour extraire les champs des structures SPS et PPS et toutes les tranches d'un cadre codé.
1) Obtenez l'instance ID3D11VideODevice à partir de votre ID3D11Device et ID3D11VideOContext à partir de votre contexte de périphérique D3D11 immédiat Remarque: Sur Win7, vous devez créer votre appareil avec le niveau de fonctionnalité 9_3 pour obtenir une prise en charge vidéo! (Dans win8 ça marche juste)
2) Créez une instance ID3D11VideODECODER pour H.264 Utilisez ID3D11VideoDevice :: GetVideOcoderProfileCount, GetVideOdeCodederProfile, CheckVideOcoderFormat ... Pour iterater tous les profils pris en charge, et en trouver un avec GUID D3D11_DECODER_PROFILE_H264_VLD_NOFGT POUR FILMGRAIN. Comme OutputFormat, votre meilleur pari est dxgi_format_nv12.
3) Décodage des cadres individuels voir Prise en charge du décodage vidéo Direct3d 11 dans Media Foundation:
- Id3d11videocontext :: DecoderBeginFrame (Decoder, OutputView -> Texture de trame décodée)
- Remplissez les tampons:
- D3d11_video_decoder_buffer_picture_parameters
- D3d11_video_decoder_buffer_inverse_quantization_matrix
- D3d11_video_decoder_buffer_bitsstream
- D3d11_video_decoder_buffer_slice_control
Les tampons sont remplis des structures DXVA2 correspondantes (voir DXVA2.H) La spécification complète DXVA2 est ici, vous en aurez besoin pour cartographier les champs H.264 SPS / PPS en conséquence.
Voir:
Alors:
- Id3d11videocontext :: soumises pour commettre tous les tampons remplis
- Id3d11videoconText :: DecoderendFrame pour terminer le cadre actuel
3) D3D11_video_decoder_buffer_picture_parameters tampon contient également des informations sur toutes les références / surface - vous devez les gérer vous-même, c'est-à-dire que les surfaces / textures sont disponibles pour le GPU!
C'est assez compliqué, vérifiez FFMPEG et Media Player Classic, ils ont tous deux le support DXVA2 (mais pas via DX11).
4) Convertir de NV12 en RVB (A), certains GPU (niveaux de fonctionnalité D3D11) permettent d'utiliser NV12 comme entrée de shader, d'autres non. Dans le cas où il n'est pas possible d'utiliser directement NV12, jetez un œil aux interfaces D3D11Videoprocesseur qui comportent la conversion NV12 / YUV420-> RVB pour tous les GPU avec le support D3D11.
La conversion pourrait être effectuée en code comme ceci:
// 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);