FFMPEG硬件加速出现hwupload错误

4

我目前正在尝试在FFMPEG上使用vaapi硬件加速。

在我的命令中,我使用了hwaccelvaapihwaccel_output_formatvaapi-hwaccel_device/dev/dri/renderD128,以及-vf作为format=nv12,hwupload,视频编解码器-c:vh264_vaapi

现在当我尝试启动它时,我得到错误信息:

grep stderr: [hwupload @ 0x30bb660]需要硬件设备引用才能上传帧。 [Parsed_hwupload_1 @ 0x30bb560]查询格式“Parsed_hwupload_1”失败:无效参数

我能否在某个地方定义硬件设备引用?我以为这就是我使用hwaccel_device的方式,但似乎不是。那么我该怎么做才能让它正常工作呢?

1个回答

15

您需要按照下面的文档正确初始化您的硬件加速器(也许我们应该及时为此创建一个维基条目?):

假设以下代码片段:

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'

说明:

(a). VAAPI 可用,并且我们将绑定DRM节点/dev/dri/renderD128到编码会话中。

(b). 我们正在接受UDP输入,其中$ingest_ip:$port_ip对应于已知的UDP输入流,分别匹配IP和端口配对,具有定义的FIFO大小(由'?fifo_size=n'参数指示)。

(c). 编码为一个打包成MPEG传输流的输出UDP流(请参见使用的复用器mepgts),其中必要的参数分别匹配输出IP和端口配对。

(d). 定义了视频比特率($video_bitrate$unit,其中$unit可以是K或M,视情况而定)和音频比特率($audio_bitrate$unit,其中$unit应为K,用于AAC LC-based编码),如上所示,通过适当的编码器设置传递给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,应遵循以下注意事项:

  1. VAAPI基于编码器仅能接受VAAPI表面作为输入,因此通常需要先使用hwupload实例将正常帧转换为vaapi格式帧。请注意,表面的内部格式将从hwupload输入的格式派生,因此可能需要额外的格式过滤器使一切正常工作,如上面的代码片段所示:

i. -init_hw_device vaapi=intel:/dev/dri/renderD128 初始化了一个名为vaapi的硬件设备(可以通过-hwaccel_device-filter_hw_device进行调用,如上所示),并绑定到DRM渲染节点/dev/dri/renderD128。可以省略前缀intel:,但在具有多个支持VAAPI的设备的环境中,例如具有Intel 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定义),按需要传递参数。你可以修改我上面代码段中提供的示例,但如果需要进一步优化,请参考之前解释过的编码器文档。

额外福利:处理基于Intel的QSV编码器:

我包括了这个部分作为未来的参考,针对那些使用Intel开源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编码器的原因之一是它们的映射容易出错,并且常常带有一些与编码器故障无关的最不实用的错误信息。在可能的情况下,请使用VAAPI。 QSV的用途(如果适用)是用于低功耗编码,例如英特尔的Apollolake和不足的Cannonlake初始提供

希望这份文档能对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接