(FFmpeg) VP9 Кодирование Vaapi в контейнер .mp4 или .webm из данного официального примера ffmpeg - PullRequest
1 голос
/ 05 марта 2019

Я пытаюсь реализовать процесс кодирования аппаратного ускорения vp9. Я последовал примеру официального gfub ffmpeg ( Здесь -> vaapi_encode.c ).

Но в данном примере сохраните только файл .yuv в файл .h264, я хотел бы сохранить кадры в контейнере .mp4 или .webm. И имея возможность контролировать качество и т. Д.

Я не читаю кадры из файла, я собираю кадры из прямой трансляции. При наличии полных 5 секунд кадров из прямой трансляции закодируйте эти кадры с помощью vp9_vaapi в файл 5 секунд .mp4.

Я могу сохранить все 5-секундные кадры из моей прямой трансляции в файл .mp4 или .webm, но они не могут быть воспроизведены правильно (точнее: продолжайте загрузку, и я открываюсь).

Результат из примера официального сайта:

enter image description here

Результат файла vp9 .mp4 в кодировке процессора:

enter image description here

Edit: Результат enter image description here

1 Ответ

2 голосов
/ 07 марта 2019

Вам нужно будет использовать FFmpeg напрямую, где вы можете дополнительно добавить vp9_superframe и vp9_raw_reorder фильтры потока битов в той же командной строке, если вы включите B-кадры в кодировщике vp9_vaapi.

Пример:

ffmpeg -vaapi_device /dev/dri/renderD128 -re -i http://server:port -vf 'format=nv12,hwupload' -c:v vp9_vaapi -global_quality 50 -bf 1 -bsf:v vp9_raw_reorder,vp9_superframe -f segment -segment_time 5 -segment_format_options movflags=+faststart output%03d.mp4

При необходимости настройте входные и выходные пути / URL-адреса.

Что делает эта команда:

Она создаст 5-секундные сегменты mp4 длиной через сегментный мультиплексор .Посмотрите, как используется movflags=+faststart, и как он был передан в качестве опции формата нижележащему мультиплексору mp4 с помощью флага -segment_format_options выше.

Длина сегмента может быть не ровно 5 секунд, так как каждыйсегмент начинается (обрезается) (с) ключевого кадра.

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

Если вам нужно использовать кодирование 1: N с VAAPI, используйтеэти фрагменты:

  1. Если вам нужно деинтерлейсировать, вызовите фильтр deinterlace_vaapi:
    ffmpeg -re -threads 4 -loglevel debug -filter_complex_threads 4 \
    -init_hw_device vaapi=va:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_device va -filter_hw_device va -hwaccel_output_format vaapi \
    -i 'http://server:port' \
    -filter_complex "[0:v]format=nv12|vaapi,hwupload,deinterlace_vaapi,split=3[n0][n1][n2]; \
    [n0]format=nv12|vaapi,hwupload,scale_vaapi=1152:648[v0]; \
    [n1]format=nv12|vaapi,hwupload,scale_vaapi=848:480[v1];
    [n2]format=nv12|vaapi,hwupload,scale_vaapi=640:360[v2]" \
    -b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 360k -c:v:0 vp9_vaapi -g:v:0 50 -r:v:0 25 -rc_mode:v:0 2 \
    -b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 280k -c:v:1 vp9_vaapi -g:v:1 50 -r:v:1 25 -rc_mode:v:1 2 \
    -b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 160k -c:v:2 vp9_vaapi -g:v:2 50 -r:v:2 25 -rc_mode:v:2 2 \
    -c:a aac -b:a 128k -ar 48000 -ac 2 \
    -flags -global_header -f tee -use_fifo 1 \
    -map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
    "[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
     [select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
     [select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
Без деинтерлейсинга:
    ffmpeg -re -threads 4 -loglevel debug -filter_complex_threads 4 \
    -init_hw_device vaapi=va:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_device va -filter_hw_device va -hwaccel_output_format vaapi \
    -i 'http://server:port' \
    -filter_complex "[0:v]split=3[n0][n1][n2]; \
    [n0]format=nv12|vaapi,hwupload,scale_vaapi=1152:648[v0]; \
    [n1]format=nv12|vaapi,hwupload,scale_vaapi=848:480[v1];
    [n2]format=nv12|vaapi,hwupload,scale_vaapi=640:360[v2]" \
    -b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 360k -c:v:0 vp9_vaapi -g:v:0 50 -r:v:0 25 -rc_mode:v:0 2  \
    -b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 280k -c:v:1 vp9_vaapi -g:v:1 50 -r:v:1 25 -rc_mode:v:1 2  \
    -b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 160k -c:v:2 vp9_vaapi -g:v:2 50 -r:v:2 25 -rc_mode:v:2 2  \
    -c:a aac -b:a 128k -ar 48000 -ac 2 \
    -flags -global_header -f tee -use_fifo 1 \
    -map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
    "[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
     [select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
     [select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"

Примечание: Если вы используете путь QuickSync, обратите внимание, что MFE (режим многокадрового кодирования) будет включен по умолчанию, еслиБиблиотека Media SDK в вашей системе поддерживает ее.

Формулы, использованные для получения приведенного выше фрагмента:

Оптимальный размер буфера: v = 4 (b: v / fps)

Заданная частота кадров (в соответствии с изображением OP): 25

Установить размер GOP как: 2 * кадр / с (интервал GOP установлен на 2 секунды).

Мы ограничиваем потокподсчитывает для видеокодера (ов) через -threads:v, чтобы предотвратить переполнение VBV.

Используется лестница разрешения: 640p, 480p и 360p в 16: 9, см. эту ссылку.Отрегулируйте это при необходимости.

Замените указанные выше переменные ($output_path{0-2}, вход и т. Д.) На необходимые.

Проверка и отчет.

Текущие наблюдения:

В моей системе я могу кодировать до 5 потоков в режиме реального времени с VP9, ​​используя рекомендованные Apple разрешения и битрейт для кодирования HEVC для HLS в качестве эталона,См. Рисунок ниже о загрузке системы и т. Д.

system load and stats with 5 simultaneous VAAPI encodes in progress

Сведения о платформе:

Я в сетисистема Coffee-lake, использующая драйвер i965 для этого рабочего процесса:

libva info: VA-API version 1.5.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'i965'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_1_5
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.5 (libva 2.4.0.pre1)
vainfo: Driver version: Intel i965 driver for Intel(R) Coffee Lake - 2.4.0.pre1 (2.3.0-11-g881e67a)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Simple            : VAEntrypointEncSlice
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointEncSliceLP
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointEncSliceLP
      VAProfileH264MultiviewHigh      : VAEntrypointVLD
      VAProfileH264MultiviewHigh      : VAEntrypointEncSlice
      VAProfileH264StereoHigh         : VAEntrypointVLD
      VAProfileH264StereoHigh         : VAEntrypointEncSlice
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointEncPicture
      VAProfileVP8Version0_3          : VAEntrypointVLD
      VAProfileVP8Version0_3          : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileHEVCMain10             : VAEntrypointEncSlice
      VAProfileVP9Profile0            : VAEntrypointVLD
      VAProfileVP9Profile0            : VAEntrypointEncSlice
      VAProfileVP9Profile2            : VAEntrypointVLD

Моя информация о сборке ffmpeg:

ffmpeg -buildconf
ffmpeg version N-93308-g1144d5c96d Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.3.0-27ubuntu1~18.04)
  configuration: --pkg-config-flags=--static --prefix=/home/brainiarc7/bin --bindir=/home/brainiarc7/bin --extra-cflags=-I/home/brainiarc7/bin/include --extra-ldflags=-L/home/brainiarc7/bin/lib --enable-cuda-nvcc --enable-cuvid --enable-libnpp --extra-cflags=-I/usr/local/cuda/include/ --extra-ldflags=-L/usr/local/cuda/lib64/ --enable-nvenc --extra-cflags=-I/opt/intel/mediasdk/include --extra-ldflags=-L/opt/intel/mediasdk/lib --extra-ldflags=-L/opt/intel/mediasdk/plugins --enable-libmfx --enable-libass --enable-vaapi --disable-debug --enable-libvorbis --enable-libvpx --enable-libdrm --enable-opencl --enable-gpl --cpu=native --enable-opengl --enable-libfdk-aac --enable-libx265 --enable-openssl --extra-libs='-lpthread -lm' --enable-nonfree
  libavutil      56. 26.100 / 56. 26.100
  libavcodec     58. 47.103 / 58. 47.103
  libavformat    58. 26.101 / 58. 26.101
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 48.100 /  7. 48.100
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100

  configuration:
    --pkg-config-flags=--static
    --prefix=/home/brainiarc7/bin
    --bindir=/home/brainiarc7/bin
    --extra-cflags=-I/home/brainiarc7/bin/include
    --extra-ldflags=-L/home/brainiarc7/bin/lib
    --enable-cuda-nvcc
    --enable-cuvid
    --enable-libnpp
    --extra-cflags=-I/usr/local/cuda/include/
    --extra-ldflags=-L/usr/local/cuda/lib64/
    --enable-nvenc
    --extra-cflags=-I/opt/intel/mediasdk/include
    --extra-ldflags=-L/opt/intel/mediasdk/lib
    --extra-ldflags=-L/opt/intel/mediasdk/plugins
    --enable-libmfx
    --enable-libass
    --enable-vaapi
    --disable-debug
    --enable-libvorbis
    --enable-libvpx
    --enable-libdrm
    --enable-opencl
    --enable-gpl
    --cpu=native
    --enable-opengl
    --enable-libfdk-aac
    --enable-libx265
    --enable-openssl
    --extra-libs='-lpthread -lm'
    --enable-nonfree

И вывод из inxi:

inxi -F
System:    Host: cavaliere Kernel: 5.0.0 x86_64 bits: 64 Desktop: Gnome 3.28.3 Distro: Ubuntu 18.04.2 LTS
Machine:   Device: laptop System: ASUSTeK product: Zephyrus M GM501GS v: 1.0 serial: N/A
           Mobo: ASUSTeK model: GM501GS v: 1.0 serial: N/A
           UEFI: American Megatrends v: GM501GS.308 date: 10/01/2018
Battery    BAT0: charge: 49.3 Wh 100.0% condition: 49.3/55.0 Wh (90%)
CPU:       6 core Intel Core i7-8750H (-MT-MCP-) cache: 9216 KB
           clock speeds: max: 4100 MHz 1: 2594 MHz 2: 3197 MHz 3: 3633 MHz 4: 3514 MHz 5: 3582 MHz 6: 3338 MHz
           7: 3655 MHz 8: 3684 MHz 9: 1793 MHz 10: 3651 MHz 11: 3710 MHz 12: 3662 MHz
Graphics:  Card-1: Intel Device 3e9b
           Card-2: NVIDIA GP104M [GeForce GTX 1070 Mobile]
           Display Server: x11 (X.Org 1.19.6 ) drivers: modesetting,nvidia (unloaded: fbdev,vesa,nouveau)
           Resolution: 1920x1080@144.03hz
           OpenGL: renderer: GeForce GTX 1070/PCIe/SSE2 version: 4.6.0 NVIDIA 418.43
Audio:     Card-1 Intel Cannon Lake PCH cAVS driver: snd_hda_intel Sound: ALSA v: k5.0.0
           Card-2 NVIDIA GP104 High Definition Audio Controller driver: snd_hda_intel
           Card-3 Kingston driver: USB Audio
Network:   Card: Intel Wireless-AC 9560 [Jefferson Peak] driver: iwlwifi
           IF: wlo1 state: up mac: (redacted)
Drives:    HDD Total Size: 3050.6GB (94.5% used)
           ID-1: /dev/nvme0n1 model: Samsung_SSD_960_EVO_1TB size: 1000.2GB
           ID-2: /dev/sda model: Crucial_CT2050MX size: 2050.4GB
Partition: ID-1: / size: 246G used: 217G (94%) fs: ext4 dev: /dev/nvme0n1p5
           ID-2: swap-1 size: 8.59GB used: 0.00GB (0%) fs: swap dev: /dev/nvme0n1p6
RAID:      No RAID devices: /proc/mdstat, md_mod kernel module present
Sensors:   System Temperatures: cpu: 64.0C mobo: N/A gpu: 61C
           Fan Speeds (in rpm): cpu: N/A
Info:      Processes: 412 Uptime: 3:32 Memory: 4411.3/32015.5MB Client: Shell (bash) inxi: 2.3.56 

Почему этот последний бит включен:

Я использую последнее ядро ​​Linux на сегодняшний день, версия 5.0.То же самое относится и к стеку графических драйверов в Ubuntu 18.04LTS.FFmpeg был построен, как показано здесь , так как на этом ноутбуке оба графических процессора NVIDIA + Intel включены через Optimus.Таким образом, я могу подключаться к часам VAAPI, QuickSync и NVENC по мере необходимости. Ваш пробег может варьироваться , даже если наше оборудование идентично.

Ссылки:

  1. См. Параметры кодера, включая поддерживаемые методы управления скоростью:
ffmpeg -h encoder=vp9_vaapi
См. Параметры использования фильтра deinterlace_vaapi:
ffmpeg -h filter=deinterlace_vaapi

Например, если вы хотите получить вывод с частотой поля, а не вывод с частотой кадров из деинтерлейсера, вы можете передать параметр rate=fieldвместо этого:

-vf=vaapi_deinterlace=rate=field

Эта функция, например, связана с кодировщиками, которые поддерживают MBAFF .Другие, такие как основанные на NVENC в FFmpeg, не имеют этого реализованного (на момент написания).

Советы по продвижению с FFmpeg:

Где возможно, делайте выводы из встроенных документов, как в приведенных выше примерах.Они могут выявить потенциальные подводные камни, которых вы можете избежать, поняв, как работает цепочка фильтров и инициализация кодировщика, неподдерживаемые функции и т. Д., А также влияние на производительность.

Например, вы увидите, что в приведенных выше фрагментах мы вызываем деинтерлейсер только один раз, а затем разделяем его 'выход через фильтр split на отдельные скейлеры. Это делается для снижения накладных расходов, если бы мы вызывали деинтерлейсер более одного раза, и это было бы расточительно.

...