Является ли DX11VideoRenderer потокобезопасным?

Я использую образец Microsoft DX11VideoRenderer для рендеринга видео в реальном времени в Windows 10. Когда я запускаю только один поток, видео выглядит великолепно. Однако, когда я запускаю более 4 или 5 потоков, некоторые видео в соответствующих окнах начинают периодически гаснуть. Эффект может распространяться только на часть или на все видеоокно.

Также я получаю несколько периодических ошибок от этого вызова функции в моем файле журнала:

hr = pVideoContext->VideoProcessorBlt(m_pVideoProcessor, pOutputView, 0, 1, &StreamData );

Возвращенная ошибка: E_INVALIDARG Один или несколько аргументов недействительны 0x80070057

Я использую в своем коде только модули Presenter.cpp и display.cpp из DX11VideoRenderer. Исходный код находится по адресу: пример рендеринга видео DirectX

Мое первоначальное подозрение на данном этапе заключается в том, что DXVideoRenderer может быть не потокобезопасным. Я нашел эту информацию о многопоточности: Введение в многопоточность в Direct3D 11, в котором говорится:

Хотя использование контекста устройства (ID3D11DeviceContext) не является потокобезопасным, использование устройства Direct3D 11 (ID3D11Device) является потокобезопасным.

Но кажется, что, поскольку я использую отдельные экземпляры класса CPresenter для каждого окна, не должно быть проблем с тем, что ID3D11DeviceContext не является потокобезопасным, поскольку каждое окно должно иметь это собственный экземпляр ID3D11DeviceContext.

Есть ли у кого-нибудь опыт или идеи об этом образце программного обеспечения DX11VideoRenderer и о том, что может быть причиной этой проблемы?

Спасибо!

-ОБНОВЛЕНИЕ-

Мне удалось воспроизвести проблему только с одним окном, поэтому она больше не связана с многопоточностью. Если я вручную изменяю размер окна много раз, иногда видео в окне может мерцать. Когда это происходит, я вижу в своем журнале, что тот же вызов функции VideoProcessorBlt() завершился ошибкой с тем же кодом возврата, E_INVALIDARG.


person Gary G.    schedule 10.05.2018    source источник
comment
Вы создаете новое устройство для каждого окна или просто отложенный контекст? Если вы используете разные контексты с одним устройством, один или несколько из них являются отложенным контекстом, и, скорее всего, средство визуализации видео не сможет использовать отложенный контекст. Чтобы получить несколько непосредственных контекстов, вам нужно несколько экземпляров устройства.   -  person Chuck Walbourn    schedule 10.05.2018
comment
Может быть, один или несколько аргументов действительно недействительны? Может быть, какая-то другая часть вашей программы страдает от проблем, связанных с безопасностью потоков?   -  person user7860670    schedule 10.05.2018
comment
Я не думаю, что DX11VideoRenderer имеет проблемы с многопоточностью, но это не обязательно означает, что используемые вами части этого кода также являются потокобезопасными. В целом, я думаю, что вопрос поставлен здесь неправильно. Если вы используете рендерер как законченный примитив, то мы обсуждаем его потокобезопасность, в противном случае вопрос касается вашего кода, и в этом смысле недостаточно подробностей.   -  person Roman R.    schedule 10.05.2018
comment
@ChuckWalbourn Я вызываю CPresenter::SetVideoWindow() для каждого нового окна. Это вызывает CPresenter::CreateDXGIManagerAndDevice(), который затем вызывает D3D11CreateDevice(), который создает новое устройство для каждого окна.   -  person Gary G.    schedule 10.05.2018
comment
@VTT Я быстро проверил значения указателя в параметрах вызова VideoProcessorBlt(), и все они такие же, как при успешном вызове функции. Мне нужно будет более подробно изучить структуры, на которые ссылаются указатели, чтобы увидеть, есть ли там разница.   -  person Gary G.    schedule 10.05.2018
comment
@РоманР. Это больше не похоже на проблему с потоками. Пожалуйста, смотрите мое обновление в моем OP. Я постараюсь изолировать соответствующие части моего кода и дать более подробную информацию.   -  person Gary G.    schedule 10.05.2018


Ответы (1)


Если я вручную изменяю размер окна много раз, иногда видео в окне может мерцать. Когда это происходит, я вижу в своем журнале, что тот же вызов функции VideoProcessorBlt() имел сбой с тем же кодом возврата, E_INVALIDARG.

Это поведение не задокументировано корпорацией Майкрософт.

Проблема та же, что и с DirectX9, но ошибка возникает с IDirect3DDevice9::Present сразу после VideoProcessBltHD. Код HRESULT — 0x88760872, а 0x88760872 не задокументирован.

Поэтому при изменении размера окна может возникнуть ошибка.

См. H264Dxva2Decoder:

В Dxva2Renderer.cpp проверьте HANDLE_DIRECTX_ERROR_UNDOCUMENTED.

Стратегия, которую я выбрал, состоит в том, чтобы приостановить воспроизведение видео (см. WindowsFormProc и WM_ENTERSIZEMOVE/WM_SYSCOMMAND), а также избежать мерцания.

При этом ошибка исчезает.

PS: обычно эту ошибку можно смело игнорировать.

Я думаю, что эта ошибка просто для того, чтобы сообщить вам, что при изменении размера окна базовый API пытается синхронизировать представление DirectX с вашим HWND, который быстро меняет размер.

person mofo77    schedule 27.01.2020