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 без пленки. В качестве OutputFormat ваш лучший выбор - DXGI_FORMAT_NV12.
3) Декодирование отдельных кадров см Supporting Direct3D 11 Video Decoding in Media Foundation:
- ID3D11VideoContext :: DecoderBeginFrame (декодер, outputView -> декодированный кадр текстуры)
- Fill буфера:
- D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS
- D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX
- D3D11_VIDE O_DECODER_BUFFER_BITSTREAM
- D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL
буферы заполняются соответствующими DXVA2 структурами (см dxva2.h) Полный DXVA2 спецификации здесь, вам нужно, чтобы отобразить h.264 СФС/соответственно.
См:
Тогда:
- 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);
Спасибо, комментарий на странице в 3) предполагает, что это только win8 (что я и считаю). Теперь, по крайней мере, я знаю, что я должен/мог использовать, я попробую и посмотрю, работает ли он на win7. Я уже написал [man readable] h264 parser, когда я пытался создать OpenCL-декодер, так что это первый бит, сделанный :) Как упоминалось в OP ffmpeg, это не вариант, поскольку он не поддерживает DX11. –
Я также могу отказаться от этого и просто попробовать NVidia и варианты декодирования видео в формате AMD, я просто надеялся на решение generic (directx) изначально. –
Мы активно используем его на Win7, единственное требование - установить обновление платформы Windows 7. FFMPEG был больше предназначен как источник того, как заполнить структуры DXVA2 :) – youaresoomean