可以在 FFmpeg 上将 VP8 或 VP9 编码与 Intel Quick Sync 一起使用吗?

可以在 FFmpeg 上将 VP8 或 VP9 编码与 Intel Quick Sync 一起使用吗?

根据维基百科上的图表,后来的Intel CPU通过Quick Sync支持VP8编码,Kaby Lake甚至支持VP9编码。

是否有任何 FFmpeg 构建能够利用这一点?

当我运行ffmpeg -codecs最新的 Zeranoe 版本时,我看到:

DEV.L. vp8    On2 VP8 (decoders: vp8 libvpx vp8_cuvid vp8_qsv ) (encoders: libvpx )

运行 FFmpeg-vcodec vp8_qsv输出失败,因为显然没有编码器。

这是我的构建的问题吗,还是目前 FFmpeg 不支持?

答案1

现在可以实现,但是要在 Linux 上通过 VAAPI 实现。

这里是一个要点,向您展示如何在 Ubuntu 16.04LTS 上生成可运行的版本。

对于基于 QSV 的编码器,经测试开源英特尔媒体 SDK(在 Apollolake 测试平台上),只有 H.264/AVC 和 HEVC 编码器可用。较新的一代通常会提供更多的编码功能。

请注意,QuickSync 硬件加速需要媒体驱动程序系统上的软件包。某些 Linux 发行版,例如 Ubuntu 19.04LTS(及以上版本)将其打包到他们的存储库中

更新: VP9 编码现已为 IceLake (ICL+) 启用通过 QuickSync 同步硬件,以及FFmpeg 可以利用它

演示如何使用 FFmpegvp9_vaapivp9_qsv编码器包装器的示例:

您需要直接使用 FFmpeg,您可以选择添加vp9_超帧vp9_raw_reorder 比特流过滤器如果在编码器中启用 B 帧,则在同一命令行中vp9_vaapi

例子:

ffmpeg -vaapi_device /dev/dri/renderD128 -hwaccel vaapi \
-i http://server:port -vf 'format=nv12|vaapi,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 帧,因为这些比特流过滤器有其他不良影响,例如摆弄编码器的速率控制触发类似这样的错误。这在生产环境中是不可取的。这就是为什么下面的脚本没有启用该选项,而是直接在编码器选项中定义一组速率控制模式。

如果您需要利用 VAAPI 的 1:N 编码,请使用以下代码片段:

  1. 如果需要去隔行,请调用deinterlace_vaapi过滤器:
    ffmpeg -loglevel debug -threads 1 \
    -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]scale_vaapi=1152:648[v0]; \
    [n1]scale_vaapi=848:480[v1];
    [n2]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"
  1. 不使用去隔行:
    ffmpeg -loglevel debug -threads 1 \
    -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,split=3[n0][n1][n2]; \
    [n0]scale_vaapi=1152:648[v0]; \
    [n1]scale_vaapi=848:480[v1];
    [n2]scale_vaapi=640:360[v2]" \
    -b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 2250k -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 1750k -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 1000k -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"
  1. 使用英特尔的 QuickSync(在支持的平台上):

在 Intel Icelake 及更高版本上,您可以使用vp9_qsv编码器包装器,但目前已知有以下限制:

(a). 您必须启用,因为目前驱动程序low_power mode仅公开了 VDENC 解码路径。iHD

(b).MSDK不支持编码选项1和extra_data。

(c). MSDK 中会默认插入 IVF 头,但 FFmpeg 不需要该头,因此默认为禁用状态。

请参阅以下示例:

  1. 如果需要去隔行,请调用vpp_qsv过滤器:
    ffmpeg -nostdin -y -fflags +genpts -init_hw_device qsv=hw \
    -hwaccel qsv -hwaccel_output_format qsv \
    -filter_hw_device hw \
    -threads 1 -vsync 1 -async 1 -reinit_filter 1 \
    -i 'http://server:port' \
    -filter_complex "[0:v]format=nv12|qsv,hwupload=extra_hw_frames=64,vpp_qsv=deinterlace=2:async_depth=4,split[n0][n1][n2]; \
    [n0]vpp_qsv=w=1152:h=648:async_depth=4[v0]; \
    [n1]vpp_qsv=w=848:h=480:async_depth=4[v1];
    [n2]vpp_qsv=w=640:h=360:async_depth=4[v2]" \
    -b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 360k -c:v:0 vp9_qsv -g:v:0 50 -r:v:0 25 -low_power:v:0 2 \
    -b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 280k -c:v:1 vp9_qsv -g:v:1 50 -r:v:1 25 -low_power:v:1 2 \
    -b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 160k -c:v:2 vp9_qsv -g:v:2 50 -r:v:2 25 -low_power: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"
  1. 不使用去隔行:
    ffmpeg -nostdin -y -fflags +genpts -init_hw_device qsv=hw \
    -hwaccel qsv -hwaccel_output_format qsv \
    -filter_hw_device hw \
    -threads 1 -vsync 1 -async 1 -reinit_filter 1 \
    -i 'http://server:port' \
    -filter_complex "[0:v]format=nv12|qsv,hwupload=extra_hw_frames=64,split=3[n0][n1][n2]; \
    [n0]vpp_qsv=w=1152:h=648:async_depth=4[v0]; \
    [n1]vpp_qsv=w=848:h=480:async_depth=4[v1];
    [n2]vpp_qsv=w=640:h=360:async_depth=4[v2]" \
    -b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 2250k -c:v:0 vp9_qsv -g:v:0 50 -r:v:0 25 -low_power:v:0 2  \
    -b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 1750k -c:v:1 vp9_qsv -g:v:1 50 -r:v:1 25 -low_power:v:1 2  \
    -b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 1000k -c:v:2 vp9_qsv -g:v:2 50 -r:v:2 25 -low_power: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"

请注意,我们使用了vpp_qsv filter选项设置为 4 的。与使用和async_depth相比,这大大提高了转码性能。请参阅scale_qsvdeinterlace_qsv这次提交在 FFmpeg 的 git 上。

笔记:如果您使用 QuickSync 路径,请注意,如果系统上的 Media SDK 库支持 MFE(多帧编码模式),则将默认启用它。

参考:

  1. 查看编码器选项,包括支持的速率控制方法:
ffmpeg -h encoder=vp9_vaapi
  1. 查看deinterlace_vaapi过滤器使用选项:
ffmpeg -h filter=deinterlace_vaapi
  1. 关于vpp_qsv过滤器的使用,请参见:
ffmpeg -h filter=vpp_qsv

例如,如果您想要从去隔行器获得场速率输出而不是帧速率输出,则可以将选项传递rate=field给它:

-vf=vaapi_deinterlace=rate=field

例如,此功能与支持以下功能的编码器相关:巴马福. 其他的,比如 FFmpeg 中基于 NVENC 的,没有实现这个(截至撰写本文时)。

使用 FFmpeg 中基于硬件的编码器最大限度提高性能的技巧:

尽可能参考内置文档,如上例所示。它们可以发现潜在的陷阱,您可以通过了解过滤器链和编码器初始化的工作原理、不支持的功能等以及对性能的影响来避免这些陷阱。

其次,在可能的情况下,利用需要多个输出的 1:N 转码。这样,输入和过滤器链产品就可以重复使用。

例如,您将在上面的代码片段中看到,我们只调用一次去隔行器,然后通过split过滤器将其输出拆分为单独的缩放器。这样做是为了降低如果我们多次调用去隔行器时产生的开销,否则会造成浪费。

相关内容