Обмен текстурами между Intel Media SDK и OpenGL

Code Sample

Краткий обзор

Обычно в ОС Windows* для обработки видео используется Direct3D. Однако во многих приложениях неизменность графического интерфейса и внешнего вида при работе на разных платформах обеспечивается за счет возможностей OpenGL*. В последних версиях графических драйверов Intel поддерживается расширение NV_DX_interop, что обеспечи-вает возможность обмена поверхностями между D3D и OpenGL для их последующего использования в Intel® Media SDK. В Intel® Media SDK можно настроить использование Direct3D, а благодаря поддержке NV_DX_interop кадровый буфер Intel Media SDK может использоваться в OpenGL. При этом устраняется необходимость в ресурсоемком копировании текстур из графического процессора в ЦП и обратно для обработки. В данном примере кода и техническом документе приведена процедура настройки использования D3D в Intel® Media SDK для кодирования и декодирования видео, преобразования цветов из цветовой схемы NV12 (стандартный цветовой формат Media SDK) в схему RGBA (стандартный цветовой формат OpenGL) и сопоставления наложения поверхности D3D с на текстурой текстуру OpenGL. В данной процедуре отсутствует этап копирования текстур из графического процессора в ЦП для обработки, что всегда представляло большую сложность при использовании OpenGL с Intel® Media SDK.

Требования к системе

Пример кода написан с помощью Visual Studio* 2013. Он предназначен (1) для демонст-рации работы Miracast и (2) обмена текстурами между Intel® Media SDK и OpenGL. В процессе обмена декодированные поверхности Intel® Media SDK сопоставляются с текстурами OpenGL без необходимости в выполнении копирования, что значительно повышает эффективность работы. При использовании процессоров Haswell и более поздних версий выполняется аппаратное ускорение декодера MJPEG. При использовании процессоров более ранних версий в Media SDK автоматически применяется программный декодер. Необходимо использовать камеру с поддержкой MJPEG (это может быть как встроенная камера, так и камера с подключением через USB).
Большая часть процедур, используемых в примере кода и техническом документе, применимы и для Visual Studio 2012 (за исключением идентификации типа подключения Miracast). Пример кода основан на Intel® Media SDK 2014 для клиентских систем. Загрузить пример можно по следующей ссылке: (https://software.intel.com/sites/default/files/MediaSDK2014Clients.zip.) После установки SDK создается набор переменных среды для поиска правильных путей к файлам заголовков и библиотекам в Visual Studio.

Обзор приложения

Приложение распознает камеру как устройство ввода MJPEG, выполняет декодирование этого видео, затем кодирование потока в формат H264 и, наконец, его декодирование и завершение обработки. Поток видео формата MJPEG с камеры (после декодирования) и полностью обработанные потоки отображаются в графическом интерфейсе на базе MFC. В системах Haswell для обеспечения удобочитаемости выполняется последовательный запуск двух декодеров и одного кодировщика (с разрешением 1080p). Благодаря аппаратному ускорению эта процедура не занимает много времени. Единственным ограничением количества передаваемых кадров в секунду является скорость работы камеры. В реальных условиях кодировщики и декодеры запускаются в отдельных потоках, поэтому проблем с производительностью возникать не должно.

При использовании одного монитора в графическом интерфейсе на базе OpenGL потоковое видео с камеры отображается в режиме «картинка в картинке» поверх обработанного видео (рис. 1). При использовании технологии Miracast программа автоматически определяет монитор с поддержкой Miracast , и на нем во весь экран отображается окно с обработанным видео, при этом в основном графическом интерфейсе отображается необработанное видео с камеры. Такой режим позволяет с легкостью сравнить исходное и кодированное видео. Кроме того, в меню View -> Monitor Topology можно отслеживать текущую топологию мониторов, а также изменять ее. К сожалению, запустить подключение Miracast в этом меню невозможно. Это можно сделать только в меню чудо-кнопок ОС (меню чудо-кнопок справа -> «Устройства» -> «Проект»). На настоящий момент API для запуска подключения Miracast не существует. При этом отключить Miracast-монитор можно, изменив топологию мониторов на «только внутренние». При наличии нескольких мониторов, подключенных с помощью проводов, их топологию можно в любой момент изменить в этом меню.

Рисунок 1. Топология с использованием одного монитора. Видео с камеры MJPEG отображается в правом нижнем углу. Обработанное видео отображается во весь экран. При включении режима использования нескольких мониторов (например, в режиме Miracast) программа обнаруживает данное изменение, в результате чего видео с камеры MJPEG и обработанное видео автоматически выводятся на разные мониторы.

Главная точка входа для настройки процесса обработки

Пример кода выполнен на базе MFC. Главная точка входа для настройки процесса обработки — CChildView::OnCreate (). Здесь выполняется инициализация камеры с последующим транскодированием видео из формата MJPEG в H264, декодированием формата H264 и связыванием текстур из транскодера и декодера в модуле визуализации OpenGL. Транскодер представляет собой подкласс декодера с добавлением кодировщика поверх базового декодера. Событие OnCreate запускает поток, в рамках которого осуществляется и упорядочивается потоковое вещание с камеры. При считывании потокового вещания рабочий поток отправляет сообщение функции OnCamRead, которая выполняет декодирование видео в формате MJPEG, кодирование в формат H264, его декодирование и обновление текстур в модуле визуализации OpenGL. На верхнем уровне весь процесс очень прозрачен и прост.

Инициализация декодера/транскодера

Для использования D3D9Ex необходимо выполнить инициализацию декодера и транс-кодера. Intel® Media SDK может быть настроен на использование программного метода, D3D9 или D3D11. В этом примере для упрощения преобразования цветов используется D3D9. Стандартным цветовым форматом Intel® Media SDK является NV12. Для преобразования цветовой схемы в формат RGBA можно использовать функцию IDirect3DDevice9::StretchRect или функцию IDirectXVideoProcessor::VideoProcessBlt. В целях упрощения в этом техническом документе используется функция StretchRect, однако на практике рекомендуется использовать функцию VideoProcessBlt, так как в нее включена дополнительная возможность последующей обработки. К сожалению, D3D11 не поддерживает StretchRect, что может усложнить процесс преобразования цветов. Кроме того, в этом документе для выполнения различных опытов (таких как сочетание различных типов программного и аппаратного обеспечения) в декодере и транскодере используются отдельные устройства D3D. Однако для экономии ресурсов памяти в декодере и транскодере может использоваться одно устройство D3D. В результате такой настройки процесса обработки результатам, получаемым на выходе после декодирования, задается тип (mfxFrameSurface1 *). Это оболочка для D3D9. Тип mfxFrameSurface1 -> Data. MemId можно преобразовать в тип (IDirect3DSurface9 *). После декодирования этот тип можно использовать в StretchRect или VideoProcessBlt функции CDecodeD3d9::ColorConvert. Полученные поверхности Media SDK нельзя сделать общими, однако преобразование цветов все равно является обязательным в OpenGL. Для хранения результатов преобразования создаются общие поверхности.

Инициализация транскодера

Декодированные транскодером данные направляются непосредственно в кодировщик. Убедитесь, что при выделении поверхностей используется MFX_MEMTYPE_FROM_DECODE.

Связывание текстур в D3D и OpenGL

Код для связывания текстуры можно найти в функции CRenderOpenGL::BindTexture. Убедитесь, что расширение WGLEW_NV_DX_interop определено, затем последовательно используйте функции wglDxOpenDeviceNV, wglDXSetResourceShareHandleNV и wglDXRegisterObjectNV. Поверхность D3D связывается с текстурой OpenGL. Текстуры не обновляются автоматически. Их можно обновить, вызвав функции wglDXLockObjectsNV/wglDXUnlockObjectsNV (CRenderOpenGL::UpdateCamTexture и CRenderOpenGL::UpdateDecoderTexture). После обновления текстуру можно использовать, как любую другую текстуру в OpenGL.

Важные моменты при изменении топологии для нескольких мониторов

Может показаться, что вывести еще одно окно на внешний монитор и управлять им посредством обнаружения изменений в топологии довольно просто. Однако на деле ОС может потребоваться некоторое время для инициализации переключения между режимами, завершения настройки монитора и отображения содержимого. Учитывая использование кодировщика/декодера/D3D/OpenGL и всех сопутствующих компонентов, отладка этого процесса может быть довольно сложным делом. В примере кода при переключении между режимами повторно используется большая часть процедуры, однако более простым вариантом может быть завершение процесса и его повторная инициализация, так как если процесс добавления монитора занимает более 10 секунд, могут возникнуть различные проблемы — даже при подключении с помощью кабелей HDMI или VGA.

Задачи на будущее

Пример кода для этого технического документа написан для D3D9 и не включает поддержку D3D11. Пока трудно с точностью сказать, какой способ преобразования цветовой схемы NV12 в схему RGBA при отсутствии StretchRect или VideoProcessBlt является наиболее эффективным. Документ и пример кода будут обновлены после разрешения вопроса с использованием D3D11.

Благодарности

Выражаем благодарность Петеру Ларссону (Petter Larsson), Михелю Джеронимо (Michel Jeronimo), Томасу Итону (Thomas Eaton) и Петру Биалеки (Piotr Bialecki) за их помощь в создании этого документа.



 

Intel, эмблема Intel и Xeon являются товарными знаками корпорации Intel в США и в других странах.
*Прочие наименования и товарные знаки могут быть собственностью третьих лиц.
© Корпорация Intel, 2013. Все права защищены.

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