D3D11 verfügt über eine Video -API, die im Grunde genommen DXVA2 mit einer leicht veränderten Schnittstelle oben ist. Sie brauchen einen guten Verständnis von H.264 Bitstreams, um fortzufahren (wirklich!). IE stellen Sie sicher, dass Sie einen H.264 -Parser zur Verfügung haben, um Felder der SPS- und PPS -Strukturen und aller Scheiben eines codierten Rahmens zu extrahieren.
1) Erhalten Sie ID3D11VideoDevice -Instanz von Ihrem ID3D11Device und ID3D11Videocontext aus Ihrem unmittelbaren D3D11 -Gerätskontext Hinweis: Auf Win7 müssen Sie Ihr Gerät mit Funktionsstufe 9_3 erstellen, um Videounterstützung zu erhalten! (In Win8 funktioniert es einfach)
2) Erstellen Sie eine ID3D11VideodeCoder -Instanz für H.264. Verwenden Sie ID3D11VideodeVice :: GetVideodeCoderProfileCount, GetVideodeCoderProfile, checkvideodeCoderformat ... um durch alle unterstützten Profile zu iterieren, und findet einen mit Guid D3d11_Decoder_Profile_H26_VLD_NOFGTOCHOCER. Als OutputFormat ist Ihre beste Wahl dxgi_format_nv12.
3) Decodierung der einzelnen Rahmen siehe Unterstützung von Direct3D 11 Video Decoding in Media Foundation:
- ID3D11Videocontext :: DecoderBeginframe (Decoder, Ausgabeview -> Decodierte Frame -Textur)
- Puffer füllen:
- D3d11_video_decoder_buffer_picture_parameters
- D3d11_video_decoder_buffer_inverse_quantization_matrix
- D3d11_video_decoder_buffer_bitstream
- D3d11_video_decoder_buffer_slice_control
Die Puffer sind mit den entsprechenden DXVA2 -Strukturen gefüllt (siehe DXVA2.H). Die vollständige DXVA2 -Spezifikation ist hier. Sie benötigen sie, um die H.264 -SPS/PPS -Felder entsprechend abzubilden.
Sehen:
Dann:
- ID3D11Videocontext :: Subjektbuffer, um alle gefüllten Puffer zu begehen
- ID3D11Videocontext :: Decoderendframe, um den aktuellen Frame zu beenden
3) D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS -Puffer enthält außerdem Informationen zu allen Referenzen Frames/Surface - Sie müssen sie selbst verwalten.
Es ist ziemlich kompliziert, überprüft FFMPEG und Media Player Classic, beide haben DXVA2 -Support (wenn auch nicht über DX11).
4) Konvertieren Sie von NV12 in RGB (A), einige GPUs (D3D11 -Feature -Ebenen) können NV12 als Shadereingang verwenden, einige nicht. Wenn es nicht möglich ist, NV12 direkt zu verwenden, sehen Sie sich die D3D11Videoprocessor-Schnittstellen an, die mit NV12/YUV420-> RGB-Konvertierung für alle GPUs mit D3D11-Unterstützung verfügen.
Die Konvertierung könnte in einem solchen Code durchgeführt werden:
// 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);