D3D11은 기본적으로 위의 약간 변경된 인터페이스를 갖는 DXVA2 인 비디오 API를 특징으로합니다. H.264 비트 스트림을 잘 이해해야합니다 (실제로!). 즉, SPS 및 PPS 구조의 필드와 인코딩 된 프레임의 모든 슬라이스를 추출하기 위해 H.264 파서가 손에 든다.
1) ID3D11Device에서 ID3D11VideoDevice 인스턴스와 id3d11videocontext에서 id3d11videodevice 인스턴스를 얻으십시오. (Win8에서는 단지 작동합니다)
2) H.264에 대한 Id3d11videodecoder 인스턴스를 만듭니다. id3d11videodevice :: getVideodecoderProfilecount, getVideodeCoderProfile, CheckVideoDecoDerformat ... 모든 지원되는 프로파일을 통해 반복하고 D3D11_DECODER_PROFILE_H264_VLD _NOFTORATION을 사용하여 찾아 내고 있습니다. outputformat로서 가장 좋은 방법은 dxgi_format_nv12입니다.
3) 개별 프레임의 디코딩 참조 Media Foundation에서 Direct3d 11 비디오 디코딩 지원:
- id3d11videocontext :: decoderbeginframe (decoder, outputview-> 디코딩 프레임 텍스처)
- 충전 버퍼 :
- d3d11_video_decoder_buffer_picture_parameters
- d3d11_video_decoder_buffer_inverse_quantization_matrix
- d3d11_video_decoder_buffer_bitstream
- d3d11_video_decoder_buffer_slice_control
버퍼는 해당 DXVA2 구조로 채워져 있습니다 (DXVA2.H 참조) 전체 DXVA2 사양이 여기에 있으며, 이에 따라 H.264 SPS/PPS 필드를 매핑해야합니다.
보다:
그 다음에:
- Id3d11videocontext :: 제출 버퍼를 모두 채워진 버퍼를 커밋합니다
- id3d11videocontext :: decoderendframe 현재 프레임을 완료합니다
3) d3d11_video_decoder_buffer_picture_parameters 버퍼도 모든 참조 프레임/표면에 대한 정보도 포함되어 있습니다 - 직접 관리해야합니다. 즉, GPU에 표면/텍스처를 사용할 수 있는지 확인하십시오!
FFMPEG 및 미디어 플레이어 클래식을 확인하고 DXVA2 (DX11을 통한 것은 아니지만) 지원이 매우 복잡합니다.
4) NV12에서 RGB (A)로 변환하면 일부 GPU (D3D11 기능 레벨)는 NV12를 셰이더 입력으로 사용할 수있게되며 일부는 그렇지 않습니다. NV12를 직접 사용할 수없는 경우 D3D11 지원이있는 모든 GPU에 대한 NV12/YUV420-> RGB 변환을 특징으로하는 D3D11Videoprocessor 인터페이스를 살펴보십시오.
변환은 다음과 같은 코드로 수행 될 수 있습니다.
// 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);