LINUX.ORG.RU

Рескалинг в ffmpeg через vaapi.

 , ,


0

2

Есть проблемка. Суть ее в следующем:
Через конкат куча картинок с разным разрешением скармливаются фильтрам и енкодеру vp9-vaapi. Если они одного разрешения, то скалинг и через scale=, и через scale_vaapi= до нужного разрешения работает. Если же, разрешение у картинок разное, то вываливат следующую ошибку:

ffmpeg version 3.4.1 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-16)
  configuration: --prefix=/usr --enable-vaapi --enable-nonfree --extra-libs=-lpthread --enable-libx264 --enable-libvpx --enable-gpl --enable-libfreetype --enable-filter=movie
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
[AVHWDeviceContext @ 0x2cf26e0] Opened VA display via DRM device /dev/dri/renderD128.
[AVHWDeviceContext @ 0x2cf26e0] libva: VA-API version 1.0.0
[AVHWDeviceContext @ 0x2cf26e0] libva: va_getDriverName() returns 0
[AVHWDeviceContext @ 0x2cf26e0] libva: User requested driver 'iHD'
[AVHWDeviceContext @ 0x2cf26e0] libva: Trying to open /opt/intel/mediasdk/lib64/iHD_drv_video.so
[AVHWDeviceContext @ 0x2cf26e0] libva: Found init function __vaDriverInit_1_0
[AVHWDeviceContext @ 0x2cf26e0] libva: va_openDriver() returns 0
[AVHWDeviceContext @ 0x2cf26e0] Initialised VAAPI connection: version 1.0
[AVHWDeviceContext @ 0x2cf26e0] Matched «Intel i965 driver for Intel(R) Kaby Lake - 2.0.1.pre1 (2.0.0-22-gb56eed0)» as known driver «Intel i965 (Quick Sync)».
Input #0, concat, from '/root/temp/test.list':
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: mjpeg, 1 reference frame, yuvj420p(pc, bt470bg/unknown/unknown, center), 1280x720, 25 tbr, 25 tbn, 25 tbc
[Parsed_scale_0 @ 0x2d17ca0] w:1280 h:720 flags:'bilinear' interl:0
Stream mapping:
  Stream #0:0 (mjpeg) -> scale
  hwupload -> Stream #0:0 (vp9_vaapi)
Press [q] to stop, [?] for help
[Parsed_scale_0 @ 0x2d20de0] w:1280 h:720 flags:'bilinear' interl:0
[graph 0 input from stream 0:0 @ 0x2d228e0] w:1280 h:720 pixfmt:yuvj420p tb:1/25 fr:25/1 sar:0/1 sws_param:flags=2
[swscaler @ 0x2d590e0] deprecated pixel format used, make sure you did set range correctly
[Parsed_scale_0 @ 0x2d20de0] w:1280 h:720 fmt:yuvj420p sar:0/1 -> w:1280 h:720 fmt:nv12 sar:0/1 flags:0x2
Output #0, matroska, to '/root/temp/out2.mkv':
  Metadata:
    encoder         : Lavf57.83.100
    Stream #0:0: Video: vp9 (vp9_vaapi) (Profile 0), 1 reference frame (VP90 / 0x30395056), vaapi_vld(center), 1280x720, q=2-31, 25 fps, 1k tbn, 25 tbc
    Metadata:
      encoder         : Lavc57.107.100 vp9_vaapi
Automatically inserted bitstream filter 'vp9_superframe'; args="
[Parsed_scale_0 @ 0x2d23260] w:1280 h:720 flags:'bilinear' interl:0
[graph 0 input from stream 0:0 @ 0x2d141c0] w:1920 h:1080 pixfmt:yuvj420p tb:1/25 fr:25/1 sar:0/1 sws_param:flags=2
[scaler_out_0_0 @ 0x2d22f00] w:1280 h:720 flags:'bicubic' interl:0
[auto_scaler_0 @ 0x2d6ff00] w:iw h:ih flags:'bilinear' interl:0
[scaler_out_0_0 @ 0x2d22f00] auto-inserting filter 'auto_scaler_0' between the filter 'Parsed_hwupload_2' and the filter 'scaler_out_0_0'
Impossible to convert between the formats supported by the filter 'Parsed_hwupload_2' and the filter 'auto_scaler_0'
Error reinitializing filters!
Failed to inject frame into filter network: Function not implemented
Error while processing the decoded data for stream #0:0
Conversion failed!

Подскажите куда копать)

P.S.: Или такую вываливает:

Impossible to convert between the formats supported by the filter 'Parsed_hwupload_2' and the filter 'auto_scaler_0'
Error reinitializing filters!
Failed to inject frame into filter network: Function not implemented

Ответ на: комментарий от anonymous

в том то и дело, что файлов много чтобы создавать отскаленые копии, и их нельзя модифицировать. Раньше делали через програмный кодек и конструкция вида scale=w=X:h=Y прекрасно работала для разношерстных картинок, а на аппаратном ни в какую =(

lasthappy ()

Может кто подскажет, как будет работать вся эта конструкция чезе pipe? Если я буду одним потоком создавать их картинок mjpeg c изменением размера и все это перенаправлять во второй ffmpeg где уже будет этот поток браться и транскодироваться в нужный формат.
Много ли озу понадобится?
Как будет работать, если отдача в пайп будет гораздо быстрее, чем прием, или наоборот?

lasthappy ()

естественно, скалер инициализируется один раз и на входе ожидает один и тот же размер

хотя может и сработает, если автоматическое добавление фильтров отключить

Harald ★★★★★ ()
Ответ на: комментарий от lasthappy

лучше каждую картинку отдельно масштабировать и сохранять в raw-формат, чтобы потом передать на вход енкодеру в следующем экземпляре процесса ffmpeg

Harald ★★★★★ ()
Ответ на: комментарий от Harald

так я и использую программный скалер (scaler). Только в купе с программным кодеком все отлично, а с аппаратным - какая-то дичь)
Есть еще аппаратный (scaler_vaapi), с ним та же история, только он вообще не работает с программными кодеками, а с аппаратным в случае если на входе картинки с одним разрешением.

И да кстати, картинки формируются через concat и на входе определяются как mjpeg поток

lasthappy ()
Ответ на: комментарий от lasthappy

так вот, если тут все картинки, скажем, 1920 на 1080, то в этом случае все ок - на выходе будет видео с разрешением 1280x720. А если там, половина файлов - 1920x1080, а следующая за ними половина - 1280x720, то на выходе мы получим ошибку, которая возникает на смене разрешения во входящем потоке. Ffmpeg упадет, а выходной файл будет содержать видео из первой половины картинок, приведенных к разрешению 1280x720. И даже если для воторой половины картинок родное изображение 1280x720, все равно вылетит на них.
Работает до первой смены разрешения на входе, сцук =(

lasthappy ()

но вообще это всё в принципе разруливается программно, если дёргать API libavfilter, а не из командной строки ffmpeg. Можно для каждого входного размера свой экземпляр scale_vaapi держать

Harald ★★★★★ ()
Ответ на: комментарий от Harald

Это все сложно))
ffmpeg -f concat -safe 0 -i «/root/temp/test.list» -c:v mjpeg -s 1920x1080 -q 0 -f mjpeg - 2>/dev/null | ffmpeg -y -vaapi_device /dev/dri/renderD128 -i - -vf 'format=nv12,hwupload' -c:v vp9_vaapi -r 25 output.mp4

Вот так все работает. Картинки конкатом рулятся в mjpeg без сжатия и с рескалингом и выдаются в pipe, который слушается во второй команде и кодируются аппаратным кодеком в vp9. Мне только вот интересно, когда картинок гигов так на много будет, не сожрет ли мне всю озу....

lasthappy ()
Ответ на: комментарий от lasthappy

не будет ли накапливаться поток в буфере?

Будет, пока в буфере будет место, потом пишущий процесс встанет на паузу, пока данные не будут прочитаны. Это управляется непосредственно ядром. Размер буфера можно посмотреть в /proc/sys/fs/pipe-max-size.

cdslow ()