Question

J'ai fait des recherches sur toute la journée et je n'ai pas été très loin. Je suis sous Windows 7, en utilisant DirectX 11. (Ma sortie finale est d'être un cadre de vidéo sur une texture DX11) Je veux décoder de très grands fichiers vidéo H.264, et le processeur (à l'aide de libav) ne Coupez-le.

J'ai examiné les capacités HWACCEL de Libav à l'aide de DXVA2, mais appuyez sur un bloc de route lorsque je dois créer un idirectxvideOdecoder, qui ne peut être créé qu'avec une interface D3D9. (que je n'ai pas en utilisant dx11)

Chaque fois que j'ai recherché la documentation DXVA, il ne fait pas référence à DX11, a-t-il été supprimé dans DX10 ou 11? (Je ne trouve aucune confirmation de cela, ni nulle part qui dit que DXVA2 est redondant, peut-être qu'il a été superdé par DXVA-HD?)

Ensuite, j'ai examiné le SDK Media Foundation car cela ressemble à ce que je suis censé utiliser pour DX11 ... mais aucun des types n'existe dans mes en-têtes (les documents disent simplement inclureu003Cd3d11.h> , mais cela ne donne rien). Ils spécifient également un minimum de Windows 8 pour l'utiliser.

Je crois que pour utiliser MF, j'ai besoin du SDK Windows 8, qui comprend désormais tous les Libs / Headers DirectX.

Donc, cela laisse un écart avec Windows 7 ... Est-il possible d'obtenir un décodage vidéo accéléré du matériel? Et si oui, quelle API suis-je censé utiliser?

Edit: Comme un autre suivi, mon implémentation Mediafoundation (et AVF, Android, Magic Leap, etc etc etc) est dans mon projet open sourcehttps://github.com/newchromantics/poph264Edit2: Mais je ne sais pas si cela prend en charge Win7 :)

Était-ce utile?

La solution

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);

Autres conseils

En tant que suivi, j'utilise actuellement Mediafoundation avec Windows 7,8 et 10, avec DirectX (ou simplement Windows SDK dans le cas de 8+)

Il prend en charge beaucoup moins de formats (ou plutôt, résolutions / niveaux de profil), et actuellement je ne sais pas exactement s'il utilise une accélération matérielle ou non ...

Mais cette API est compatible, qui était la requête d'origine

Comment utiliser le décodage vidéo / H.264 accéléré matériel avec DirectX 11 et Windows 7?

Vous ne pouvez pas.

ID3D11VideODevice n'est disponible que pour Windows 8 Id3d11videodevice.

ID3D11VideODECODER n'est avalaïble que pour Windows 8 Id3d11videodecoder.

Sur Windows 7, vous pouvez simplement utiliser DirectX 9 pour la vidéo accélérée en matériel / H.264. Merci Microsoft. Le bon nouveau, iDirect3D9EX fonctionne ... ouais ... l'autre bonne nouvelle, les performances de décodage du GPU sont très bonnes en utilisant DirectX9 sur Windows 7.

Voici un code source pour Windows 7 et DirectX 9: MOFO7777, dans le cadre du projet H264DXVA2DECODER.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top