Ответ 1
D3D11 имеет видео api, которое в основном DXVA2 со слегка измененным интерфейсом выше. Вам нужно хорошо понимать потоки бит h.264, чтобы продолжить (действительно!). т.е. убедитесь, что у вас есть парсер h.264 под рукой, чтобы извлекать поля структур SPS и PPS и все фрагменты закодированного фрейма.
1) Получите экземпляр ID3D11VideoDevice из вашего ID3D11Device и ID3D11VideoContext из вашего непосредственного контекста устройства D3D11 ПРИМЕЧАНИЕ. В Win7 вам необходимо создать свое устройство с уровнем 9_3 для получения поддержки видео! (В Win8 он просто работает)
2) Создайте экземпляр ID3D11VideoDecoder для h.264 Используйте ID3D11VideoDevice:: GetVideoDecoderProfileCount, GetVideoDecoderProfile, CheckVideoDecodeRFormat... для итерации всех поддерживаемых профилей и поиска одного с GUID D3D11_DECODER_PROFILE_H264_VLD_NOFGT для h264 без filmgrain. В качестве OutputFormat ваш лучший выбор - DXGI_FORMAT_NV12.
3) Декодирование отдельных кадров см. Поддержка Direct3D 11 Декодирование видео в Media Foundation:
- ID3D11VideoContext:: DecoderBeginFrame (декодер, 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:: SubmitBuffers для фиксации всех заполненных буферов
- ID3D11VideoContext:: DecoderEndFrame для завершения текущего кадра
3) Буфер D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS также содержит информацию обо всех ссылках на фреймы/поверхность - вам нужно управлять ими самостоятельно, то есть убедиться, что поверхности/текстуры доступны для GPU!
Это довольно сложно, проверьте ffmpeg и Media Player Classic, они имеют поддержку DXVA2 (хотя и не через DX11).
4) Преобразование из NV12 в RGB (A), некоторые графические процессоры (уровни функций D3D11) позволяют использовать NV12 в качестве шейдерного ввода, а некоторые нет. В случае, если невозможно напрямую использовать NV12, посмотрите интерфейсы D3D11VideoProcessor, которые поддерживают преобразование NV12/YUV420- > RGB для всех графических процессоров с поддержкой D3D11.
Преобразование может быть выполнено в коде следующим образом:
// 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);