如何将 ffmpeg 与 mjpeg_vaapi 编码器(带硬件加速)一起使用?

how to use ffmpeg with mjpeg_vaapi encoder (with hardware acceleration)?

当我在没有硬件加速的情况下将 ffmpeg 与 mjpeg 编码器一起使用时,一切正常。我使用以下命令:

ffmpeg -nostdin -rtsp_transport udp_multicast -allowed_media_types 'video' -i 'rtsp://MYIP' -ss 00:00:0.00 -f image2pipe -q:v 24 -vf scale=-2:480,format=yuv420p -c:v mjpeg -vframes 1 pipe:1

但是,当我尝试使用带有硬件加速的 mjpeg 时,我总是得到错误:

ffmpeg -nostdin -rtsp_transport udp_multicast -allowed_media_types 'video' -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i 'rtsp://MYIP' -ss 00:00:0.00 -f image2pipe -q:v 24 -vf scale=-2:480,format=yuv420p -c:v mjpeg_vaapi -vframes 1 pipe:1
ffmpeg version N-91514-gc51e0cd Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 20160609
  configuration: --pkg-config-flags=--static
  libavutil      56. 18.102 / 56. 18.102
  libavcodec     58. 21.106 / 58. 21.106
  libavformat    58. 17.101 / 58. 17.101
  libavdevice    58.  4.101 / 58.  4.101
  libavfilter     7. 26.100 /  7. 26.100
  libswscale      5.  2.100 /  5.  2.100
  libswresample   3.  2.100 /  3.  2.100
libva info: VA-API version 0.39.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_0_39
libva info: va_openDriver() returns 0
Input #0, rtsp, from 'rtsp://MYIP':
  Metadata:
    title           : Session streamed with GStreamer
    comment         : rtsp-server
  Duration: N/A, start: 0.180600, bitrate: N/A
    Stream #0:0: Video: h264 (Main), yuvj420p(pc, progressive), 800x600, 50 fps, 50 tbr, 90k tbn, 100 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (mjpeg_vaapi))
Impossible to convert between the formats supported by the filter 'graph 0 input from stream 0:0' 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!

我尝试了一些额外的选项,但仍然失败:

ffmpeg -nostdin -rtsp_transport udp_multicast -allowed_media_types 'video' -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i 'rtsp://MYIP' -ss 00:00:0.00 -f image2pipe -q:v 24 -vf "scale_vaapi=w=800:h=600" -b:v 700k -r 25 -vcodec mjpeg_vaapi -vframes 1 pipe:1                
ffmpeg version N-91514-gc51e0cd Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 20160609
  configuration: --pkg-config-flags=--static
  libavutil      56. 18.102 / 56. 18.102
  libavcodec     58. 21.106 / 58. 21.106
  libavformat    58. 17.101 / 58. 17.101
  libavdevice    58.  4.101 / 58.  4.101
  libavfilter     7. 26.100 /  7. 26.100
  libswscale      5.  2.100 /  5.  2.100
  libswresample   3.  2.100 /  3.  2.100
libva info: VA-API version 0.39.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_0_39
libva info: va_openDriver() returns 0
Input #0, rtsp, from 'rtsp://MYIP':
  Metadata:
    title           : Session streamed with GStreamer
    comment         : rtsp-server
  Duration: N/A, start: 0.179933, bitrate: N/A
    Stream #0:0: Video: h264 (Main), yuvj420p(pc, progressive), 800x600, 50 fps, 50 tbr, 90k tbn, 100 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (mjpeg_vaapi))
[mjpeg_vaapi @ 0x374cd80] Encoding entrypoint not found (12 / 7).
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!

任何人都可以提出正确的选择以使其发挥作用吗?

所以问题是我的 Intel CPU 平台很旧 (Broadwell) 并且 JPEG encoding 支持启动 Braswell。请在 page

上按平台查看所有支持的编解码器

在安装了 Skylake CPU 的机器上执行 运行 相同的命令后,它从第一次尝试开始就成功了:)

当您尝试利用 Intel 的硬件编码时,您需要检查两件事

  1. 而是你的特定英特尔支持你想要的编码器
  2. 而是您的 ffmpeg 二进制文件是否从使用硬件加速库编译的某个地方获取。

要了解您的英特尔支持哪种编码器,您只需键入:

vainfo|grep -i enc

它将列出您的处理器支持的编码器。例如,在我的例子中,它产生以下结果:

libva info: VA-API version 1.13.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_13
libva info: va_openDriver() returns 0
      VAProfileMPEG2Simple            : VAEntrypointEncSlice
      VAProfileMPEG2Main              : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointEncSliceLP
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointEncSliceLP
      VAProfileJPEGBaseline           : VAEntrypointEncPicture
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
      VAProfileHEVCMain               : VAEntrypointEncSlice

就我而言,我的英特尔 cpu 确实支持 mjpeg 编码。

如果你找不到任何类似于 mjpeg 的东西,那么,你几乎可以放弃使用英特尔的硬件加速来完成你想要在那台机器上做的事情的想法。

接下来您需要做的是首先找出您的 ffmpeg 二进制文件是否支持 Intel 的 vaapi。首先是输入:

ffmpeg -hide_banner -hwaccels

如果其中一行有“vaapi”,则表示使用 Intel 硬件加速库编译的 ffmpeg。如果你的 vainfo 命令有你想要的但上面的命令没有显示 vaapi,那么,你需要获取另一个 ffmpeg 二进制副本。来自不同的来源,或者自己编译。

接下来是罗列所有实际使用vaapi的ffmpeg编码器,希望有一个类似mjpeg的:

ffmpeg -hide_banner -encoders|grep -i vaapi

就我而言,我确实有:

 V....D h264_vaapi           H.264/AVC (VAAPI) (codec h264)
 V....D hevc_vaapi           H.265/HEVC (VAAPI) (codec hevc)
 V....D mjpeg_vaapi          MJPEG (VAAPI) (codec mjpeg)
 V....D mpeg2_vaapi          MPEG-2 (VAAPI) (codec mpeg2video)
 V....D vp8_vaapi            VP8 (VAAPI) (codec vp8)
 V....D vp9_vaapi            VP9 (VAAPI) (codec vp9)

因此,就我而言,编码器就在那里。

如果 vainfoffmpeg -hwaccels 都产生了你需要的东西,但最后一步没有,那么,你需要得到来自某处的另一个 ffmpeg 二进制文件。

祝你好运。