В этом посте речь пойдет о вопросах кодирования видео «в промышленных масштабах» с применением видеокодека h264 на GPU, интегрированном в современные процессоры Intel и о том опыте, который приобрела наша компания Inventos в процессе создания и оптимизации медиа сервера для обработки потокового видео.

Введение

Итак, была поставлена задача разработать медиа сервер, представляющий собой эдакий «комбайн» на все случаи жизни и умеющий следующее:
  • Кодирование/рессемплинг аудио/видео почти во все известные форматы, среди которых HLS, HDS, RTMP, mp4, etc;
  • Поддержка съема сигнала с SDI, DVB;
  • Балансировка и масштабирование серверов раздачи и кодирования;
  • Описание конфигурации кодировщика на встроенном языке;
  • Различные модули для нормализации звука, усиления, деинтерлейсинга видео и т.д.


Этот продукт под кодовым названием «streambuilder» является бэкендом медиа платформы Webcaster.pro. Решение написано на C++ с использованием библиотек libavcodec, в которые имплементированы многие известные кодеки, такие как h264, mpeg4 и т.д. Такое решение позволяет достаточно быстро разворачивать инфраструктуру доставки контента любой сложности и является гибким в плане конфигурирования.

Наш медиасервер, а, точнее, язык конфигурации, позволяет представить все этапы обработки аудио/видео в виде направленного ациклического графа. В корневой вершине находится источник сигнала, а остальные представляют собой различные блоки, проводящие операции над данными. При помощи конфигурационных файлов мы можем описывать графы, удовлетворяющие почти любым потребностям. В сильно упрощенном виде этот граф будет выглядеть следующим образом:



Несмотря на то, что код библиотек libavcodec хорошо оптимизирован, о�� рассчитан на работу на CPU, содержащим конечное число исполнительных устройств, таком, как x86 based. Увеличение количества ядер только отчасти решает проблему, так как обходится это недешево, да и ядра всегда есть чем загрузить, помимо кодирования видео. И логичным шагом была попытка использовать возможности графических ускорителей для решения данной задачи.

Теперь немного о самом кодировании видео. Как известно, в основе сжатия видео лежат множество алгоритмов из разных разделов математики. Это фурье — анализ, вейвлеты, операции с матрицами, векторами, вероятностные алгоритмы и т. д. Объединяет их одно — все они так или иначе работают с видео данными, которые представляют собой не что иное, как векторы и матрицы. Мы не будет углубляться в особенности сжатия конкретными видеокодеками, но следует понимать, что такие задачи крайне затратны по ресурсам в плане памяти и особенно процессорного времени. Тем более, если речь идет о промышленных масштабах кодирования. До недавнего времени процесс кодирования осуществлялся на центральных процессорах. CPU характеризуются прежде всего ограниченным числом исполнительных блоков. И даже, несмотря на то, что в современных процессорах появилось много ядер, число исполнительных блоков остается конечным. Конечно, производители процессоров добавляют элементы суперскалярной архитектуры в свои чипы (например, наборы инструкций SSExxx/AVX от Intel). Они позволяют одной инструкцией обработать несколько однотипных чисел, но всегда существуют такие задачи, как сжатие видео, когда ресурсов все равно не бывает много, особенно в свете появления новых стандартов вещания (HD, 4k, и т. д.). GPU, в свою очередь, обладают большим количеством исполнительных блоков, которые, впрочем, умеют исполнять ограниченное число инструкций. Соответственно, GPU идеально подходят для обработки однотипных данных, с использованием параллельных алгоритмов. Кроме этого, многие производители GPU добавляют в свои видео ускорители дополнительные команды для ускорения обработки мультимедиа данных.

Решение от Intel

В качестве эксперимента мы решили попробовать ускорить кодирование видео при помощи графических сопроцессоров Intel HD Graphics, встроенных в современные процессоры Intel. Intel любезно предоставляет свой Media SDK для кодирования, декодирования, ресемплинга и других алгоритмов видео обработки. Данный SDK, к нашей большой радости, теперь доступен и для Linux, что крайне важно для промышленного использования. Именно благодаря появлению поддержки Linux мы заинтересовались этим решением. Коллег из Intel тоже заинтересовали результаты практического использования данного SDK в условиях промышленного использования. При этом, должен отметить, на протяжении всего периода разработки сотрудники Intel нам очень сильно помогали, отвечали на вопросы (которых было много поначалу) и давали действительно ценные советы.

В комплекте вместе с Media SDK идет хорошая документация и примеры почти на все случаи жизни. Процесс интеграции Intel Media SDK сильно упростило наличие примеров, без них он, надо сказать, покажется не самым тривиальным. Суть интеграции заключалась в замены наиболее требовательных к аппаратной части софтверных модулей кодирования/декодирования/ресемплинга на соответствующие модули, использующие аппаратные возможности Intel HD Graphics.

Тесты

Конфигурация нашего тестового стенда: Процессор i7-3770 3.4 GHz, память 3 Гб. Версия Intel Media SDK for Linux Servers — 16.1.0.10043. В качестве источника брались разные медиафайлы и результат усреднялся.

Кодирование RAW видео в h264
ffmpeg intel media sdk
720x608, h264 RAW, 30 сек, 3000 кб/с 1.2 сек 0.24 сек

Пример транскодирования с демуксером/муксером ffmpeg (аудио пакеты писались без транскодирования)
ffmpeg intel media sdk
720x608, aac+h264, 30 сек, 3000 кб/с 1.6 сек 0.32 сек

streambuilder
simple streambuilder with intel media sdk
1920x800 + resize 1280x720, 3000 кб/с h264, aac, 12 минут 5.4 мин 2.3 мин

А теперь посмотрим на результаты. Для начала мы собрали примеры, которые шли в комплекте. В кодировании RAW видео в h264 тестовая программа обогнала ffmpeg h264 encoder при схожих параметрах в 4-5 раз, при этом надо сделать поправку на время, затраченное на операции дисковых записи/чтения (то есть реальный результат немного выше). Fmpeg при этом на 100% нагружал все ядра CPU. Video decoder и аппаратное изменение размеров изображения показали сходные результаты. Мы также собрали пример транскодирования с демуксером/муксером ffmpeg. Этот пример использует особый тип памяти для работы с фреймами и в нем фреймы передаются от декодера на энкодер минуя стадию копирования данных из памяти SDK в YUV формат в системной памяти. Соответственно, здесь Intel Media SDK показал производительность в среднем в 5 раза выше, чем аналогичное транскодирование при помощи ffmpeg.

Наш медиаконвеер совместно с аппаратными модулями кодирования показал увеличение производительности в 2-3 раза. И это ожидаемый результат, так как большая часть производительности терялась на операциях копирования памяти. Gprof показал, что 80% процессорного времени уходило на работу с памятью, что вызывало задержки при подачи фреймов на аппаратный энкодер/декодер. Однако, эту проблемы мы планируем закрыть в ближайшее время, используя напрямую структуры памяти Intel SDK при обмене пакетами между разными модулями. Мы ожидаем здесь значительного увеличения производительности.

Итак, в качестве плюсов решения от Intel можно выделить следующее.
  • Аппаратный энкодер (для h264) более адекватно воспринял параметры кодирования, нежели софтварный (libavcodec). Например, более точно выдерживался битрейт при кодировании. Для ffmpeg API его необходимо долго и мучительно подбирать;
  • При кодировании почти не используется процессор. В наших тестах CPU использовался для транскодирования аудио потока и операций с памятью внутри конвейера. Общая загрузка была на уровне 25% (загружено было примерно одно ядро из 4-х).

Из минусов этого решения можно отметить разве что чуть больший порог вхождения и привязка SDK к конкретному ядру Linux, но это не показалось нам критичным.

Что дальше

В качестве итога могу отметить, что всю инфраструктуру продукта можно перевести на новый API примерно за 1 человеко-месяц (без учета тестирования). Кроме этого, мы использовали старый API. В новой версии SDK появилось много новых плюшек, таких как аналог двухпроходного кодирования на 100 фреймах, расчет dts кодированного пакета, увеличение качества видео и т. д. Для тестов мы использовали обычный настольный компьютер с достаточно производительным CPU. В ближайшее время мы планируем попробовать новую версию API, а также провести тесты на серверных решениях. Кроме этого, мы планируем провести расширенные тесты на различных наборах параметров для получения более полной картины, результатами которых мы поделимся в самое ближайшее время.

UPD
Вот два ролика: первый получен кодированием при помощи ffmpeg, второй при помощи Intel Media SDK И там и там почти все параметры по умолчанию, битрейт 8000 Кб/сек
webcaster.pro/video1.mp4
webcaster.pro/video2.mp4