FFMPEG Hwaccel error with hwupload



我目前正在尝试在FFMPEG上使用vaapi hwaccelleration。

在我的指挥下,我有hwaccelvaapihwaccel_output_fomratvaapi-hwaccel_device/dev/dri/renderD128,以及-vfformat=nv12, hwupload和视频编解码器-c:vh264_vaapi

当我现在尝试启动它时,我收到错误

grep stderr: [hwupload @ 0x30bb660] A hardware deveice reference is required to upload frames to. [Parsed_hwupload_1 @ 0x30bb560] Query format failed for 'Parsed_hwupload_1': Invalid argument

我可以在某处定义硬件设备引用吗?我以为这就是我对hwaccel_device所做的,但似乎不是。那么我能做些什么来让它工作呢?

您需要正确初始化硬件加速器,如下面的文档所示(也许我们应该及时为此创建一个 wiki 条目?

假设以下代码片段:

ffmpeg -re -threads 4 -loglevel debug 
-init_hw_device vaapi=intel:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device intel -filter_hw_device intel 
-i 'udp://$ingest_ip:$ingest_port?fifo_size=9000000' 
-vf 'format=nv12|vaapi,hwupload' 
-c:v h264_vaapi -b:v $video_bitrate$unit -maxrate:v $video_bitrate$unit -qp:v 21 -sei +identifier+timing+recovery_point -profile:v main -level 4 
-c:a aac -b:a $audio_bitrate$unit -ar 48000 -ac 2 
-flags -global_header -fflags +genpts -f mpegts 'udp://$feed_ip:$feed_port'

哪里:

VAAPI 可用,我们将 DRM 节点/dev/dri/renderD128绑定到编码会话,并且

我们采用 udp 输入,其中$ingest_ip:$port_ip对应于已知的 UDP 输入流,分别匹配 IP 和端口配对,具有定义的 fifo 大小(如'?fifo_size=n'参数所示(。

(c(. 编码为打包为 MPEG 传输流的输出 udp 流(请参阅正在使用的复用器,mpegts(,必要的参数分别与输出 IP 和端口配对匹配。

定义视频比特率($video_bitrate$unit,其中$unit可以是K或M,如你所愿(和音频比特率($audio_bitrate$unit,其中$unit应为K,对于基于AAC LC的编码(,如上所示,并将适当的编码器设置传递给vaapi编码器。供您参考,截至撰写本文时,FFmpeg 中有四个可用的视频编码器,即:

i. h264_vaapi
ii. hevc_vaapi
iii. vp8_vaapi
iii. vp9_vaapi

省略了 mjpeg 编码器(因为它在此上下文中不感兴趣(,并且这些编码器的文档中的每一个都可以通过以下方式访问:

ffmpeg -hide_banner -h encoder=$encoder_name

其中$encoder_name与上面列表中的编码器匹配。

对于 VAAPI,以下注意事项适用:

基于 VAAPI
  1. 的编码器只能将输入作为 VAAPI 图面,因此通常需要在 hwupload 实例之前将普通帧转换为 VAAPI 格式帧。请注意,图面的内部格式将派生自 hwupload 输入的格式,因此可能需要其他格式筛选器才能使一切正常工作,如上面的代码片段所示:

我。-init_hw_device vaapi=intel:/dev/dri/renderD128初始化绑定到 DRM 渲染节点/dev/dri/renderD128的名为 vaapi 的硬件设备(稍后可以通过-hwaccel_device-filter_hw_device调用,如上所述(。可以删除intel:前缀,但在存在多个支持 VAAPI 的设备的环境中,识别供应商名称使用的渲染节点通常很有用,例如具有英特尔 IGP 和 AMD GPU 的装备。

ii. 注意-hwaccel_output_format vaapi定义的格式约束。这是满足 1 中的条件所必需的。

iii. 然后,我们选取命名的硬件加速实现 vaapi,并为硬件加速器设备 (-hwaccel_device( 和我们将通过 hwupload 过滤器将硬件帧上传到的设备 (-filter_hw_device( 调用它。如您所观察到的,省略后者将导致编码器初始化失败。

iv. 现在,仔细检查视频过滤器语法:

-vf 'format=nv12|vaapi,hwupload'

此视频筛选器链将任何不受支持的视频帧转换为 VAAPI 硬件格式,在通过 hwupload 将帧上传到设备之前应用已知约束。这样做是出于安全原因;不能假定编码器将接受解码格式。此模式下的性能会因源、解码器设备和使用的 VAAPI 驱动程序而异。

五.现在,对于视频编码器(由-c:v $encoder_name定义(,根据需要传递参数。您可以修改我在上面的代码片段中提供的示例,但如果您需要进一步调整,最好参考前面所述的编码器文档。

奖励:处理基于英特尔的 QSV 编码器:

我将本节包括在内以供将来参考,供那些使用英特尔开源 MSDK 实现 FFmpeg 的 QSV 和相关编码器的用户使用。请参阅下面的代码片段:

ffmpeg -re -threads 4 -loglevel debug 
-init_hw_device qsv=qsv:MFX_IMPL_hw_any -hwaccel qsv -filter_hw_device qsv 
-i 'udp://$ingest_ip:$ingest_port?fifo_size=9000000' 
-vf 'hwupload=extra_hw_frames=10,vpp_qsv:deinterlace=2,format=nv12' 
-c:v h264_qsv -b:v $video_bitrate$unit -rdo 1 -pic_timing_sei 1 -recovery_point_sei 1 -profile high -aud 1 
-c:a aac -b:a $audio_bitrate$unit -ar 48000 -ac 2 
-flags -global_header -fflags +genpts -f mpegts 'udp://$feed_ip:$feed_port'

您可以看到相似之处。

QSV 编码器使用 VAAPI 样式映射(如上所述(,但为 hwupload 筛选器放置了一个额外的约束:必须使用hwupload=extra_hw_frames=10参数,否则编码器的初始化将失败。

尽管QSV的输出质量据说更好,但我不能推荐QSV编码器的原因之一是它们的映射很脆弱,通常以一些最无用的错误退出,这些错误通常与编码器的故障方式无关。 在可能的情况下,坚持使用VAAPI。QSV 的实用性(如果适用(适用于低功耗编码,就像英特尔的 Apollolake 和贫血的 Cannonlake 初始产品一样。

希望本文档对您有用。

最新更新