在systemd-nspawn容器中使用硬件加速视频编解码

nspawn容器中使用VA-API硬件加速

Posted by wszqkzqk on December 13, 2024
本文字数:2494

前言

某些情况下,我们存在在容器中使用硬件加速编解码视频的需求。本文将介绍如何在systemd-nspawn容器中使用硬件加速视频编解码。

原理

systemd-nspawn容器是一个轻量级的容器,它可以在不使用虚拟机的情况下提供隔离的环境。在容器中使用硬件加速视频编解码,需要将硬件加速设备映射到容器中。

方法

一般来说,硬件加速设备的设备节点位于/dev/dri目录下,例如/dev/dri/renderD128。我们可以/dev/dri目录使用--bind选项映射到容器中,使容器可以访问硬件加速设备。

然而,如果单纯只是映射而没有其他操作,容器中的应用仍不能使用硬件加速设备,例如打开容器:

sudo systemd-nspawn --bind /dev/dri -bD /path/to/container/root

这时如果在容器中运行vainfo,会发现无法打开硬件加速设备:

Trying display: wayland
VA error: wayland: failed to open /dev/dri/renderD128
VA error: wayland: failed to open /dev/dri/renderD128: Operation not permitted (errno 1)
VA error: wayland: did not get DRM device

这是systemd-nspawn的默认权限设置导致的。我们还需要额外传递--property=DeviceAllow='char-drm rw'选项,使容器中的应用可以访问硬件加速设备:

sudo systemd-nspawn --bind /dev/dri --property=DeviceAllow='char-drm rw' -bD /path/to/container/root

这时在容器中运行vainfo,就可以看到硬件加速设备的信息了:

Trying display: wayland
vainfo: VA-API version: 1.22 (libva 2.22.0)
vainfo: Driver version: Mesa Gallium driver 24.3.1-arch1.4 for AMD Radeon Graphics (radeonsi, renoir, LLVM 18.1.8, DRM 3.59, 6.12.4-zen1-1-zen)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileHEVCMain10             : VAEntrypointEncSlice
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileVP9Profile0            : VAEntrypointVLD
      VAProfileVP9Profile2            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc

此时,可以尝试使用FFmpeg等工具进行硬件加速视频编解码:

ffmpeg -hwaccel auto -i /path/to/your-video.mp4 -c:v hevc_vaapi -vf hwupload -c:a copy output.mp4

其中-hwaccel auto表示自动选择硬件加速器,如果选中了VA-API硬件加速器,在日志中会有这样的输出:

AVHWDeviceContext @ 0x5a1a52ebfc40] Cannot load libcuda.so.1
[AVHWDeviceContext @ 0x5a1a52ebfc40] Could not dynamically load CUDA
Device creation failed: -1.
[vist#0:0/hevc @ 0x5a1a52eac580] [dec:hevc @ 0x5a1a52eadd40] Using auto hwaccel type vaapi with new default device.

日志中的Using auto hwaccel type vaapi with new default device.表示FFmpeg选择使用VA-API硬件加速。当然,VA-API硬件加速器并不是-hwaccel auto的最优先选择,如果有cuda可用,FFmpeg会优先选择cuda硬件加速器。这在日志中也将会有体现。(也可以不使用auto,明确将-hwaccel选项设置为vaapi等)

-c:v hevc_vaapi表示使用VA-API硬件加速器进行HEVC编码,-vf hwupload表示使用硬件上传(如果颜色空间不支持一般可以使用-vf 'hwupload,scale_vaapi=format=nv12'转化,有关FFmpeg硬件加速的使用方法,可以参见笔者的另一篇博客)。如果硬件本身支持示例中的HEVC编码,且容器的硬件加速配置成功,这一命令应当能够正常运行。