Системный архитектор
0,1
рейтинг
14 июля 2015 в 12:43

Разработка → Эффективное кодирование видео в Linux c Nvidia NVENC: часть 1, общая


Эта статья содержит практические сведения, полезные для организации эффективного кодирования видео на Linux с использованием последних видеопроцессоров Nvidia.
Чем не является эта статья:
  • Не является пособием по выбору технологии аппаратного кодирования или агитацией в пользу описываемой. Кроме Nvidia NVENC есть Intel QuickSync, есть AMD VCE, наверняка есть и ещё что-то. Все эти технологии имеют разные характеристики, которые трудно даже уложить на одну шкалу для сравнения. Тем не менее, я сделал свой выбор.
  • Не является претензией на самый быстрый/качественный способ кодирования. По причинам, указанным выше.

Об NVENC


Nvidia NVENC это технология, позволяющая кодировать видео в H.264 (и H.265 для последних процессоров Maxwell) силами GPU со скоростями несколько сот кадров в секунду (в зависимости от профиля и разрешения). Вендор предоставляет возможность использования этой технологии в виде набора разработчика NVENC SDK.

Реализация


Имеется множество утилит для различных платформ, которые в каком-то виде дают доступ к функционалу SDK. В марте 2015 года вышел релиз ffmpeg, который включил в себя поддержку NVENC. ffmpeg занимает центральное положение среди всего множества свободного и не очень ПО для работы с видео, поэтому с практической точки зрения он наиболее интересен. Этим инструментом можно и обрабатывать видеофайлы (1, 2), и вести потоковое вещание (1, 2). С момента мартовского релиза вышел ещё один, который включил в себя ещё больше опций для кодека nvenc и поддержку H.265 (HEVC).

Сборкой FFmpeg с поддержкой NVENC мы и займёмся.

Развёртывание

Для создания рабочей конфигурации нам потребуется:
  • Одна видеокарта Nvidia на ядре Kepler или Maxwell. На мой взгляд самый интересный выбор это GTX 970 — процессор Maxwell второго поколения (GM204) за 300$.
  • Один линукс типовой (ubuntu 14.04) на компьютере с видеокартой.


Драйверы и рантайм CUDA

Драйверы и библиотеки установить за раз одним пакетом. Из репозитория лучше ничего не использовать.
sudo apt-get update
sudo apt-get -y install axel build-essential dkms
axel 'http://developer.download.nvidia.com/compute/cuda/7_0/Prod/local_installers/cuda_7.0.28_linux.run'
chmod +x cuda_7.0.28_linux.run
sudo ./cuda_7.0.28_linux.run

На все вопросы уважаемого компьютера следует ответить утвердительно. После установки — перезагрузить.

Заголовочные файлы nvenc

Для сборки приложений с nvenc sdk неободимы некоторые заголовочные файлы. Раньше их необходимо было стягивать из виндовой версии SDK. Но прогресс идёт семимильными шагами и теперь этот файл можно стянуть из примеров в линуксовом SDK. Найдите в примерах (были установлены вместе с рантаймом и драйверами на предыдущем шаге) файлы
nvCPUOPSys.h
nvEncodeAPI.h
nvFileIO.h
NvHWEncoder.h
nvUtils.h

и положите их в /usr/include. Они потребуются только один раз, при сборке ffmpeg. На всех машинах они не нужны.

FFMPEG

Начать его сборку лучше с установки всех сборочных зависимостей.
sudo apt-get build-dep libav
sudo apt-get install -y libfdk-aac-dev libopencv-dev

Я мог что-то забыть, что-то может измениться. Чтобы найти недостающий для сборки файл, не стесняйтесь пользоваться apt-file:
$ sudo apt-get install apt-file -y
$ sudo apt-file update
$ apt-file search libxcb-shm.so.0
libxcb-shm0: /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0
libxcb-shm0: /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0


Скачиваем с сайта последнюю версию ffmpeg, распаковываем, конфигурируем, собираем и устанавливаем:
axel 'http://ffmpeg.org/releases/ffmpeg-2.7.1.tar.bz2'
tar xf ffmpeg-2.7.1.tar.bz2
cd ffmpeg-2.7.1
./configure --cpu=native --enable-pthreads --extra-version=habrahabr.ru --enable-bzlib --enable-libdc1394 --enable-libfreetype --enable-frei0r --enable-gnutls --enable-libgsm --enable-libmp3lame --enable-librtmp --enable-libopencv --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-vaapi --enable-vdpau --enable-libvorbis --enable-libvpx --enable-zlib --enable-libfdk-aac --enable-nonfree --enable-gpl --enable-swscale --enable-libcdio --enable-x11grab --enable-libx264 --enable-libxvid --enable-libopencore-amrnb --enable-version3 --enable-libopencore-amrwb --enable-version3 --enable-libvo-aacenc --enable-version3 --enable-libvo-amrwbenc --enable-version3 --enable-nvenc
make -j5
sudo make install

Собираем с libfdk-aac, он точно предпочтительнее имеющегося кодека aac. Кроме прочего, можно заметить опцию --enable-nvenc. В остальном параметры выбраны по мотивам билдспеки пакета libav в самом дистрибутиве ubuntu. После всех манипуляций должен появиться рабочий ffmpeg в /usr/local/bin/ffmpeg.

Применение

Запуск

Опции запуска все точно такие же, как при софтверном кодировании, но только вместо libx264 видеокодек будет называться nvenc (он же nvenc_h264) для h.264 и nvenc_hevc для h.265.
/usr/local/bin/ffmpeg -i input.mov -vcodec nvenc -b:v 5000k -r 30 ... output.mp4


Производительность и качество

Чтобы произвести 1 час видео в 4х качествах с хорошей точностью транскодинга, нужно или потратить примерно 1 час машинного времени двух шестиядерных ксеонов, или чуть более получаса времени десктопа с такой видеокартой. Качество результатов получается неотличимое от программного кодека x264 с аналогичными установками.

Ограничения

Увы и ах, Nvidia ввела ограничение: на обычных десктопных видеокартах нельзя кодировать больше двух потоков видео одновременно. Снятию этого ограничения будет посвящена моя следующая статья, которая, вероятно, будет интересна немного другому кругу читателей.
@YourChief
карма
46,5
рейтинг 0,1
Системный архитектор
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (21)

  • +3
    Автор, давай вторую часть уже. Это у тебя рассчитана на немного другой круг читателей.
    • +2
      Пишу как раз, там скриншотов GDB много.
  • 0
    Но прогресс идёт семимильными шагами

    Кстати о прогрессе.
    Плач Ярославны
    У НВидии на линуксе есть один застарелый и неприятный баг: когда система загружена (например, компиляция идет), экран частично или полностью перестает перерисовываться. Ну то есть вплоть до того, что вводишь в консоли ls, а результата не видишь. Но если сдвинуть окно — все моментально отрисовывается. Необновленное окно может висеть часами, т.е. это не задержка.
    Багу уже много лет, его фиксили все — и нвидия, и разработчики гнома. Есть множество рецептов по его обходу, разной степени эзотеричности (от отключения power saving на видеокарте до каких-то непонятных ключиков в иксовых конфигах). Ни один не работает гарантированно. Обновление дров с сайта нвидии проблему не решает. Видеокарты, на которых баг вылазит — самые разные (от древней quadro до более-менее современных бюджетных). Линуксы, на которых баг вылазит, тоже разные: дебиан, ред хат энтерпрайзный, етц.

    Так вот, интересно: починили уже или по-прежнему все очень печально?
    • +1
      Я примерно такой эффект видел на старом макбуке, на который установлен линукс, и по-моему там встроенная видеокарта intel. При работе в gnome-terminal не после каждого нажатия перерисовывается окно и иногда введённого текста не видно. Может это другая проблема, а может проблема в какой-нибудь прослойке: в иксах, в DRI. Насчёт nvidia не знаю ничего — на этих машинах иксы никогда не запускались.
      • 0
        Может это другая проблема, а может проблема в какой-нибудь прослойке: в иксах, в DRI.

        Грузишь линукс с драйвером nvidia — грабли. Причем грабли возникают даже в текстовом режиме(!) при использовании frame buffer.
        Грузишь тот же линукс с драйвером… эээ… как его бишь? nouveaux? — все прекрасно работает, но ни CUDA, ни OpenCL не доступны (что естественно).

        Насчёт nvidia не знаю ничего — на этих машинах иксы никогда не запускались.

        Погодите-ка. Как это не запускались? Разве для того, чтобы заработала CUDA, не нужны запущенные иксы?
        Для работы OpenCL, например, иксы должны быть запущены обязательно.

        • +3
          Для CUDA не нужны иксы совсем, это точно. У Радеонов для OpenCL, вроде, нужны.
  • 0
    Весной пробовал nvenc (ffmpeg тогда его еще не умел) на Tesla K40 в сравнении с текущим на тот момент ffmpeg на 8 ядрах (-threads 8) Xeon E5-2600V2.
    Если в один ролик за раз все было еще неплохо, то на двух оба варианта выдавали схожие числа. А на 3+ в параллель вариант на gpu сливал подчистую.
    Так что или один-два потока на не самой дешевой gpu (~200к), или минимум 3-4-5 потоков на сильно более дешевых cpu (около 10к, если не ошибаюсь). При той же скорости каждого отдельного качества.

    nvenc конвертился с пресетами NV_ENC_PRESET_LOW_LATENCY_DEFAULT, NV_ENC_PRESET_HQ и NV_ENC_PRESET_HP.
    ffmpeg выдавал уже готовый готовый mp4 файл, в то время как nvenc выдавал только x264 поток, который еще нужно сохранить в mp4 контейнер.

    Новый ffmpeg обязательно попробую, как руки дойдут.
    • 0
      Tesla K40 это Kepler. Для NVENC нецелесообразно пользоваться чем-то кроме новых Maxwell (GM20*). Я тестировал на Quadro K2000 с Kepler — скорость в разы меньше по сравнению даже с GTX 970.
      • 0
        А какая скорость выходит на Maxwell?
        K40 выдавала около 600-700 кадров в секунду на целевом 240/360, но сваливалась до несерьезных 50-60 кадров для 720.
        • +1
          Нашел вот. Стоит попробовать :)
          image

      • 0
        Попробовал, кстати, Grid K1: получилось достойно по скорости, но весьма печально по качеству. Но уже не сравнить с K40 — гораздо лучше.
        На очереди еще Quadro M6000…
        • 0
          Отпишитесь, пожалуйста, как попробуете — очень интересно как оно.
          • +1
            Quadro M6000 вышла почти в 2 раза производительней, чем Grid K1. По показаниям nvidia-smi обе карточки были полностью загружены в энкодере. Grid K1, в свою очередь, примерно в 1.5-2 раза быстрее, чем на cpu уровня E5-2620v3.
            • 0
              Ну вот как раз и получается, что GTX 970 где-то рядом с M6000, притом что M6000 стоит больше в разы
              • 0
                А GTX 970 может обрабатывать сразу 40+ конвертаций?
                • 0
                  Есть ограничение 2 сессии конвертации на систему, которое я снял во второй части своей статьи.

                  По производительности тут уже зависит от качества кодируемых потоков. Например, в моём юзкейсе процессор не успевает декодировать так много потоков (а диски читать и писать). В любом случае производительность/цена у GTX 970 получается самая высокая.
                  • 0
                    В моем случае очень важна высокая производительность во много потоков. Тесты гонял в ~45 параллельных потоков конвертации (качества 240p-1080p, из них 720-1080 примерно 20-30% общего числа). А так, вообще, еще в планах тесты на чем-то из семейства этой M6000, но попроще и подешевле).
  • 0
    можно брать любую GTX 970 карту или есть разница?
    • 0
      У меня все разные:
      • 4Gb <PCI-E> DDR-5 ZOTAC <GeForce GTX 970> (RTL) DualDVI+HDMI+DP+SLI
      • ASUS TURBO-GTX970-OC-4GD5 /GTX970,DVI*2,HDMI,DP,4G,D5


      производители выставляют им немного разную частоту, в соответствии с этим есть несущественная разница. В остальном разницы нет. Количество видеопамяти некритично — на практике её расходуется в районе полугигабайта.
      • 0
        они однослотовые есть, или вы их в сервера не засовываете?
        • 0
          В microATX. Глубина стойки позволяет уложить два корпуса на одном уровне лёжа, 2 машины занимают где-то 3 юнита тогда.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.