Швидке кодування відео в Linux c Nvidia NVENC з SDK 7.5 і ffmpeg 3.0.2 на Nvidia GTX 960/970/980

image

Дана стаття була написана за мотивами статті Ефективне кодування відео в Linux c Nvidia NVENC: частина 1, загальна, проте має свої особливості і, на відміну від оригінальної статті, де чомусь упустили цей момент, я застосував перероблений патч Nvidia Acceleration до FFmpeg 3.0.2, отримавши крім енкодера nvenc ще й швидкий фільтр ресайза — nvresize.

Разом я отримав можливість апаратно кодувати відео в H. 264 і HEVC за допомогою відеокарти Nvidia GTX 960 на досить слабкому комп'ютері (Xeon L5420) зі швидкістю (для H. 264), що перевищує можливості даного процесора до 10 разів та у 3 рази щодо Core i7)! Причому на моєму улюбленому Debian 8 Jessie.

Отже, почнемо!

Технологія

Nvidia NVENC це технологія, що забезпечує кодування відео в H. 264 і HEVC на обчислювальних потужностях GPU. Важливе зауваження: скільки-небудь якісне і швидке кодування на момент написання статті (травень 2016) можуть забезпечити тільки карти другого покоління Maxwell, і для десктопних це: GTX 960, GTX 970 і GTX 980 (для довідки: є ще дорога проф. лінійка Nvidia Quadro). Причому NVENC модуль працює з однаковою швидкістю на всіх трьох картах (неперевірена інформація, будь ласка, поправте мене якщо це не так!), тому брати старші версії має сенс тільки якщо платформа використовується (крім кодування) для ігор.

Реалізація (FFmpeg)

Все різноманіття реалізацій Nvidia CUDA можна подивитися за адресою. Від себе хочу сказати, що для відео найбільш поширеним є популярний інструмент — FFmpeg. Його ми і будемо використовувати.

Програмне забезпечення

Хоч це і банально, але перерахую мінімально необхідний набір апаратних вимог (заснований на реальному досвіді):
  1. Материнська плата: з підтримкою PCI-E. Рекомендую платформу Intel з-за тісного зв'язку Intel, Nvidia і особистої приязні. Хай вибачать мене шанувальники AMD!
  2. Процесор: двох-ядерний, рівня не нижче Core2 Duo. Рекомендую Core i3 і деякі дешеві Xeon (так-так!).
  3. Пам'ять: DDR2/3/4, мінімум 2 Гб. Цікавий факт, при двох потоках кодування сумарне споживання пам'яті у мене ~0.7 Гб.
  4. Відеокарта: будь-яка відеокарта Nvidia GTX 960, GTX 970 або GTX 980. 2 Гб або 4 Гб, геймерська чи ні — не важливо! Головне, стежте за габаритами і врахуйте, що у всіх моделей GTX 960 що я бачив, додаткове живлення підключається зверху.
  5. БЖ ATX з дод. коннектором живлення (6 пін для нашої задачі вистачить). Рекомендую потужність не менше 400 Вт.

Програмне забезпечення

Подальше оповідання спирається на певний базис з систем, програм і їх конкретних версій. Особливо відзначу що я використав Debian, а не Ubuntu, для якої є навіть офф. пакети SDK, т. к. хотів спробувати налаштувати все в улюбленому дистрибутиві.
  1. Операційна система: Debian 8 Jessie з додатковим репозиторієм Deb Multimedia
  2. Nvidia CUDA 7.5.18
  3. Nvidia SDK 6.0.1
  4. FFmpeg 3.0.2
  5. Патч Nvidia Acceleration, змінено мною для сумісності з FFmpeg 3.0.2

Збірка

Найважливіший з файлів — це перший, з драйвером. Тільки він і потрібен якщо ви хочете встановити пакет після його складання.
Завантажуємо файли, які нам знадобляться для подальшої роботи. Розмір ~1.3 Гб.
cd /usr/src
wget 'http://developer.download.nvidia.com/compute/cuda/7.5/Prod/local_installers/cuda_7.5.18_linux.run'
wget 'https://developer.nvidia.com/video-sdk-601' -O 'video-sdk-601.zip'
wget 'http://developer.download.nvidia.com/compute/redist/ffmpeg/1511-patch/cudautils.zip'
wget 'http://ffmpeg.org/releases/ffmpeg-3.0.2.tar.bz2'
wget 'http://kuzko.com/dl/ffmpeg_NVIDIA_gpu_acceleration.3.0.2.patch'
MD5 файлів
4b3bcecf0dfc35928a0898793cf3e4c6 cuda_7.5.18_linux.run
24af45272ed2881f88ed534d3211b584 video-sdk-601.zip
f3f890bd314a568c47191810453cad2c cudautils.zip
7db5efb1070872823143e1365fdfcd53 ffmpeg-3.0.2.tar.bz2
a4f59f92675e02a0fa5c6cd124eda64e ffmpeg_NVIDIA_gpu_acceleration.3.0.2.patch

SHA1 файлів
0f366a88968b9eee01044de197e27764bc1567d6 cuda_7.5.18_linux.run
e57c7b4cfb298d4c725a0bb4477928e228dabb1c video-sdk-601.zip
edc818bef432d708466c5454974b9851523a86ba cudautils.zip
c40731a221fbfaa50671d69fe894bedd664f91e2 ffmpeg-3.0.2.tar.bz2
f305832ed42beeff7d7c26a00f79668b63b322ec ffmpeg_NVIDIA_gpu_acceleration.3.0.2.patch


Додаємо репозиторій Deb Multimedia (він потрібен якщо ви хочете отримати/використати FFmpeg, який максимально наближений до того, який викладає Deb Multimedia). Цей репозиторій обов'язковий для моєї збірки!
Для ледачихСтворюємо файл з одним рядком:
echo 'deb http://www.deb-multimedia.org jessie main non-free' > /etc/apt/sources.list.d/deb-multimedia.list
Далі виконуємо
apt-get update
І встановлюємо keyring:
apt-get install deb-multimedia-keyring

Тепер оновлюємо систему і ставимо необхідні для складання драйвера пакети. Цей крок також необхідний!
Необхідні дії
apt-get update
apt-get -y dist-upgrade
apt-get -y install build-essential dkms ccache pkg-config libglu1-mesa-dev libx11-dev libxi-dev libxmu-dev

Встановлюємо Nvidia Driver, приймаємо угода (accept), всі решта відповіді за замовчуванням. Якщо попередять що система не є підходящою, не переживайте, це нормально! Можна передати ключ -silent для швидкої установки, але краще пройдіться самі.
Необхідні дії
cd /usr/src
chmod +x cuda_7.5.18_linux.run
./cuda_7.5.18_linux.run

Вибір подальшого дії залежить від вас. Ви можете довіритися мені й скачати готовий deb файл (створений через checkinstall) і пропустити наступні кроки, або здійснити збірку вручну, встановивши необхідні бібліотеки і зібравши пакет самостійно через checkinstall.
Я джедай, чого мені боятися?
cd /usr/src
wget 'http://kuzko.com/dl/ffmpeg_3.0.2-nvenc-7.5.18-nvresize-cudautils-20160523-1_amd64.deb'
dpkg -i ffmpeg_3.0.2-nvenc-7.5.18-nvresize-cudautils-20160523-1_amd64.deb
apt-get -f install

Якщо ви вибрали світлу сторону сили, то давайте продовжимо, встановимо бібліотеки, необхідні для складання (для цього, крім усього іншого, і був потрібен Deb Multimedia), підготуємо відмінності файли, cudautils і застосований патч:
Необхідні дії
apt-get install -y --force-yes libfdk-aac-dev libopencv-dev libiec61883-dev libavc1394-dev libass-dev libbluray-dev libbs2b-dev libkvazaar-dev libilbc2 libilbc-dev libopenh264-dev libsnappy-dev libsoxr-dev libxv1 libxcb-shape0
cd /usr/src
unzip video-sdk-601.zip;
/bin/cp -prf nvidia_video_sdk_6.0.1/Samples/common/inc/nvCPUOPSys.h /usr/include
/bin/cp -prf nvidia_video_sdk_6.0.1/Samples/common/inc/nvEncodeAPI.h /usr/include
/bin/cp -prf nvidia_video_sdk_6.0.1/Samples/common/inc/nvFileIO.h /usr/include
/bin/cp -prf nvidia_video_sdk_6.0.1/Samples/common/inc/NvHWEncoder.h /usr/include
/bin/cp -prf nvidia_video_sdk_6.0.1/Samples/common/inc/nvUtils.h /usr/include
unzip cudautils.zip
cd cudautils
make
tar zxf ffmpeg-3.0.2.tar.bz2
cd ffmpeg-3.0.2
patch -Np1 -i ../ffmpeg_NVIDIA_gpu_acceleration.3.0.2.patch

Тепер ми готові виконати три основні команди по збірці пакету (configure / make / checkinstall).
Відзначу кілька моментів, які ви можете змінити під себе:
  1. додано --enable-nvenc і --enable-nvresize (куди ж без них!)
  2. Модифіковані --extra-і --cflags extra-ldflags, щоб включити в себе cudautils
  3. Прибрані --enable-opencl (не зміг знайти бібліотеку для нього) і --enable-libtesseract (зайвий модуль на мій погляд)
  4. FFmpeg збирається без --enable-shared, хоча ніщо не заважає вам його повернути назад
  5. make -j10 можете змінювати на специфічне для вашої системи (я використовував build-машину, де threads+2=10)
  6. в Залежності checkinstall я вставив для того, щоб при установці з нуля, було достатньо виконати apt-get -f install і встановити необхідні пакети, а не вишукувати через ldd що ж ще потрібно встановити
  7. Також із-за недосконалості checkinstall довелося виконати кілька необов'язкових дій (видалення конфліктуючих dev пакетів і створення теки /usr/share/ffmpeg)
Отже, йдемо за кавою, але тільки після відпрацювання configure
cd /usr/src
cd ffmpeg-3.0.2
./configure --prefix=/usr --extra-cflags='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -I../cudautils ' --extra-ldflags='-Wl,-z,relro -L../cudautils ' --cc='ccache cc' --enable-libmp3lame --enable-gpl --enable-nonfree --enable-libvorbis --enable-pthreads --enable-libfaac --enable-libxvid --enable-postproc --enable-x11grab --enable-libgsm --enable-libtheora --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libx264 --enable-libspeex --enable-nonfree --enable-libvpx --enable-libschroedinger --disable-encoder=libschroedinger --enable-version3 --enable-libopenjpeg --enable-librtmp --enable-avfilter --enable-libfreetype --disable-decoder=amrnb --enable-libvo-amrwbenc --libdir=/usr/lib/x86_64-linux-gnu --disable-vda --enable-libbluray --enable-libcdio --enable-gnutls --enable-frei0r --enable-openssl --enable-libass --enable-libopus --enable-fontconfig --enable-libpulse --disable-mipsdsp --disable-mips32r2 --disable-msa --disable-mipsfpu --disable-mipsdspr2 --enable-libvidstab --enable-libzvbi --enable-avresample --enable-libutvideo --enable-libfdk-aac --enable-libx265 --enable-libbs2b --enable-libilbc --enable-libopenh264 --enable-libkvazaar --enable-libsnappy --enable-libsoxr --enable-libiec61883 --enable-vaapi --enable-libdc1394 --disable-altivec --shlibdir=/usr/lib/x86_64-linux-gnu --enable-nvenc --enable-nvresize
make -j10
apt-get -y remove libswscale-dev libavcodec-dev libswresample-dev libavutil-dev
mkdir -p /usr/share/ffmpeg
checkinstall --pkgname=ffmpeg --pkgversion "10:3.0.2-nvenc-7.5.18-nvresize-cudautils-`date +%Y - %m - %d`" --backup=no --requires='libcdio-paranoia1,libjack0,libasound2,libsdl1.2debian,libdc1394-22,libavc1394-0,libiec61883-0,libvidstab1.0,libbs2b0,libva1,libzvbi0,libx265-79,libx264-148,libvpx1,libvo-amrwbenc0,libutvideo15,libtheora0,libspeex1,libsoxr0,libsnappy1,libschroedinger-1.0-0,libopus0,libopenjpeg5,libopenh264-1,libopencore-amrwb0,libopencore-amrnb0,libmp3lame0,libkvazaar3,libilbc2,libgsm1,libfdk-aac1,libfaac0,libbluray1,libass5,libxcb-xfixes0,libcrystalhd3,libxvidcore4,libxv1,libxcb-shape0'--default

Якщо в результаті ви отримали deb файл, то приймайте мої вітання!
До речі, checkinstall може і лайнутися при установці пакету. Не страшно. Установіть (якщо не встановився) пакет вручну через dpkg -i ffmpeg_3.0.2-nvenc-7.5.18-nvresize-cudautils-20160523-1_amd64.deb, потім apt-get -f install для встановлення залежностей.

Параметри nvenc і nvresize

Чомусь, не всі знають які параметри приймає nvenc і nvresize, а для цього потрібно всього лише запустити ffmpeg з ключем -h:
ffmpeg -h encoder=nvenc_h264
Encoder nvenc_h264 [NVIDIA NVENC h264 encoder]:
General capabilities: delay 
Threading capabilities: none
Supported pixel formats: yuv420p nv12
nvenc_h264 AVOptions:
-preset <string> E..V.... Set the encoding preset (one of slow = hq 2pass, medium = hq, fast = hp, hq, hp, bd, ll, llhq, llhp, default) (default "hq")
-profile <string> E..V.... Set the encoding profile (high, main, baseline)
-level <string> E..V.... Set the encoding level restriction (auto, 1.0, 1.0 b, 1.1, 1.2, ..., 4.2, 5.0, 5.1)
-tier <string> E..V.... Set the encoding tier (main or high)
-cbr <boolean> E..V.... Use cbr encoding mode (default false)
-2pass <boolean> E..V.... Use 2pass encoding mode (default auto)
-gpu <int> E..V.... Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on. (from 0 to INT_MAX) (default 0)
-delay <int> E..V.... Delays frame output by the given amount of frames. (from 0 to INT_MAX) (default INT_MAX)
-enableaq <boolean> E..V.... set to 1 to enable AQ (default false

ffmpeg -h encoder=nvenc_hevc
Encoder nvenc_hevc [NVIDIA NVENC hevc encoder]:
General capabilities: delay 
Threading capabilities: none
Supported pixel formats: yuv420p nv12
nvenc_hevc AVOptions:
-preset <string> E..V.... Set the encoding preset (one of slow = hq 2pass, medium = hq, fast = hp, hq, hp, bd, ll, llhq, llhp, default) (default "hq")
-profile <string> E..V.... Set the encoding profile (high, main, baseline)
-level <string> E..V.... Set the encoding level restriction (auto, 1.0, 1.0 b, 1.1, 1.2, ..., 4.2, 5.0, 5.1)
-tier <string> E..V.... Set the encoding tier (main or high)
-cbr <boolean> E..V.... Use cbr encoding mode (default false)
-2pass <boolean> E..V.... Use 2pass encoding mode (default auto)
-gpu <int> E..V.... Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on. (from 0 to INT_MAX) (default 0)
-delay <int> E..V.... Delays frame output by the given amount of frames. (from 0 to INT_MAX) (default INT_MAX)
-enableaq <boolean> E..V.... set to 1 to enable AQ (default false

ffmpeg -h filter=nvresize
Filter nvresize
GPU accelerated video resizer.
Inputs:
#0: default (video)
Outputs:
dynamic (depending on the options)
nvresize AVOptions:
outputs <int> FV ...... set number of outputs (from 1 to 16) (default 1)
readback <int> FV ...... read result back to FB (from 0 to 1) (default 0)
gpu <int> FV ...... Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on. (from 0 to INT_MAX) (default 0)
force_original_aspect_ratio <int> FV ...... decrease increase or w/h if necessary to keep the original AR (from 0 to 2) (default 0)

Доцільність. Заради чого все це?

Я не буду тут наводити докладні бенчмарки (якщо тільки співтовариство не попросить мене провести певні тести), їх вистачає в інтернеті, та й швидкість кодування безпосередньо картою приблизно однакова і більше залежить від вихідного відео, дозволу/бітрейт кодованого і додаткової обробки (кодування звуку, накладення фільтрів).
Ось деякі цифри для тестової (дешевою і стародавньої!) системи на Xeon L5420 (4 ядра по 2.5 ГГц)576p исходник, x264, бітрейт виставлений в 3000k:
frame= 7500 fps= 58 q=-1.0 Lsize= 107951kB time=00:05:00.00 bitrate=2947.8 kbits/s speed=2.32 x
576p исходник, nvenc_h264, бітрейт виставлений в 3000k:
frame= 7500 fps=804 q=-0.0 Lsize= 116997kB time=00:05:00.00 bitrate=3194.8 kbits/s speed=32.2 x
На 1080p исходнике (37 мегабіт вихідних в 10-15 мегабіт) швидкість 0.42 x та 4.2 x — Nvidia знову швидше приблизно в 10 разів.
При кодуванні 1080p в HEVC на процесор боляче дивитися, там цифри 0.08 x і нижче, карта близько 3x видає.

Для системи на Core i7 різниця не така велика, але все одно карта в 3-4 рази швидше, ніж x265 на HEVC 1080p (15000k) і в 13 разів на HEVC 576p (3000к). І це при тому, що сам процесор i7 зазвичай стоїть GTX 960 і дорожче.

Що стосується якості. Я перфекціоніст, але вважаю що є безліч застосувань для апаратного кодування, т. к. зниження якості насправді помітно слабко (дивився як на проф. монітор Dell 24", так і на телевізорі 60" — всі з близької відстані) і тільки при т. зв. pixel хантинге. Зате швидкість робить можливим вирішення завдань, які зазвичай не здатні виконуватися в реальному часі на процесорі.

Я свідомо опустив подробиці по швидкості nvresize, крім його параметрів, т. к. хоч це і дуже цікавий і швидкий фільтр, але його використання виходить за рамки даної статті.

Сподіваюся, що моя праця не пропаде даром і допоможе ще більшій кількості людей долучитися до технології апаратного кодування, обійшовши деякі підводні камені, на рішення яких я витратив досить багато часу. Але це коштувало того!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.