Эффективное кодирование видео в 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 ввела ограничение: на обычных десктопных видеокартах нельзя кодировать больше двух потоков видео одновременно. Снятию этого ограничения будет посвящена моя следующая статья, которая, вероятно, будет интересна немного другому кругу читателей.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 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 юнита тогда.

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