D3D11 presenta un'API video che è fondamentalmente DXVA2 con un'interfaccia leggermente alterata sopra. Hai bisogno di una buona comprensione di H.264 Bitstreams per procedere (davvero!). cioè assicurati di avere un parser H.264 a portata di mano per estrarre campi delle strutture SPS e PPS e tutte le fette di un frame codificato.
1) Ottieni l'istanza ID3D11VIDEODEVICE dal tuo ID3D11DEVICE e ID3D11VIDEOContext dal tuo immediato contesto del dispositivo D3D11 Nota: su Win7, devi creare il tuo dispositivo con il livello di funzionalità 9_3 per ottenere supporto video! (In Win8 funziona solo)
2) Crea un'istanza ID3D11VIDEODECODER per H.264 Usa ID3D11VIDEODEVICE :: GETVIDEODECODERPROFILECOUNT, GETVIDEODECODERPROFILE, CHECKVIDEODECODERFORFORMAT ... per iterare tutti i profili supportati e trovarne uno con GUID D3D11_DECODER_PROFILE_H264_VLOFGT per H264 Come outputFormat la migliore scommessa è dxgi_format_nv12.
3) Decodifica dei singoli cornici vede Supportare la decodifica video Direct3d 11 in Media Foundation:
- ID3D11VIDEOContext :: DecoderBeginFrame (decodificatore, outputView -> Texture frame decodificata)
- RIMBIFICA IL BUFFER:
- D3d11_video_decoder_buffer_picture_parameters
- D3D11_VIDEO_DECODER_BUFFER_INVERS_QUANTIZZAZIONE_MATRIX
- D3d11_video_decoder_buffer_bitstream
- D3d11_video_decoder_buffer_slice_control
I buffer sono riempiti con le corrispondenti strutture DXVA2 (vedi DXVA2.H) Le specifiche DXVA2 complete è qui, avrai bisogno di mappare i campi H.264 SPS/PPS di conseguenza.
Vedere:
Quindi:
- Id3d11Videocontext :: Inviabuffers per commettere tutti i buffer compilati
- Id3d11videocontext :: decoderEndframe per finire il frame corrente
3) d3d11_video_decoder_buffer_picture_parameters buffer contiene anche informazioni su tutti i frame/superficie dei riferimenti - devi gestirli da solo, cioè assicurarsi che le superfici/trame siano disponibili per la GPU!
È abbastanza complicato, controlla FFMPEG e Media Player Classic, hanno entrambi DXVA2 (anche se non tramite DX11).
4) Converti da NV12 in RGB (A), alcuni GPU (livelli di funzionalità D3D11) consentono di utilizzare NV12 come input shader, alcuni no. Nel caso in cui non sia possibile utilizzare direttamente NV12, dai un'occhiata alle interfacce D3D11Videoprocessore che dispongono di conversione NV12/YUV420-> RGB per tutte le GPU con supporto D3D11.
La conversione potrebbe essere eseguita in codice come questo:
// 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);