ALVR 硬件视频编码加速测试指南:用 FFmpeg 验证 NVENC 与 VA-API 编码管线
ALVR 硬件视频编码加速测试指南:用 FFmpeg 验证 NVENC 与 VA-API 编码管线
ALVR 通过 Wi-Fi 将 PC 上的 VR 画面流式传输到头显,其流畅度高度依赖 GPU 硬件视频编码。本文以 ALVR 仓库中的 FFmpeg-Hardware-Encoding-Testing.md 为主线,讲解如何在 Nvidia、Intel、AMD 三种 GPU 平台上用 FFmpeg 的测试命令验证硬件编码(Offloading)是否真正生效,并对照 ALVR 在 Linux 下实际的 FFmpeg VA-API 编码实现与补丁,帮助你在配置 ALVR 之前先确认自己的编码硬件可用。
读完本文,你将掌握:三大编码器(AVC/H.264、HEVC/H.265、AV1)与四大图形编码 API 的核心区别、testsrc2 测试源的正确用法、三大 GPU 平台各自的硬件编码验证命令与监控手段,以及 ALVR 源码中 VA-API 编码管线的真实工作方式。
为什么需要先验证硬件编码
ALVR 服务端在每一帧都要把渲染出的 VR 画面压缩成视频流再经 Wi-Fi 发送。编码是最耗 CPU 的环节之一,只有把它卸载(offload)到 GPU 的专用编码单元,才能在高分辨率、高刷新率(如 90 FPS 甚至 120 FPS)下保持低延迟。从 ALVR 的 Linux 编码管线源码可以看到,VA-API 编码器对应三个 FFmpeg 编码器名称(见 EncodePipelineVAAPI.cpp):
const char* encoder(ALVR_CODEC codec) {
switch (codec) {
case ALVR_CODEC_H264:
return "h264_vaapi";
case ALVR_CODEC_HEVC:
return "hevc_vaapi";
case ALVR_CODEC_AV1:
return "av1_vaapi";
}
...
}
也就是说,ALVR 的 Linux 端在运行时就依赖 FFmpeg 的 *_vaapi 编码器。如果硬件不支持对应编码,编码会失败或退回软件编码(软编),延迟和画质都会明显劣化。因此,在正式部署 ALVR 之前用本文的测试命令确认“硬件编码确实生效”,是排查卡顿、高延迟问题的第一步。
三大视频编码器:ALVR 支持的编码格式
测试之前先明确要验证的目标格式。ALVR 编码器选择对应三种主流视频编码标准:
- AVC(H.264 / MPEG-4 Part 10):基于块的运动补偿视频压缩标准,是目前应用最广的视频格式,最高支持 8K UHD 分辨率,硬件编码支持最普及。ALVR 中的
ALVR_CODEC_H264即映射为h264_vaapi/h264_nvenc。 - HEVC(H.265 / MPEG-H Part 2):作为 AVC 的继任者,在同画质下数据压缩率可提升 25%~50%,最高支持 8192×4320(含 8K UHD);其 10 位 Main 10 profile 已被几乎所有新硬件编码器支持。ALVR 中的
ALVR_CODEC_HEVC映射为hevc_vaapi/hevc_nvenc。 - AV1(AOMedia Video 1):开放、免版税的视频编码格式,由开放媒体联盟(AOMedia)作为 VP9 的继任者推出,起初面向互联网视频传输,其码流规范包含参考编解码器。硬件编码支持仅限最新一代硬件(如 Nvidia Ada Lovelace、Intel Arc、AMD RDNA3/VCN 4.0+)。
从 ALVR 的 Linux 编码实现还可以看到 10 位编码的具体做法:EncodePipelineVAAPI.cpp 中,当编码器为 HEVC 或 AV1 且开启 10 位编码时,硬件帧的软件格式(sw_format)使用 AV_PIX_FMT_P010,否则使用 AV_PIX_FMT_NV12。这对应 ALVR 会话设置中的 use_10bit_encoder 选项(见 lib.rs)。
四大图形编码 API
- VA-API(Video Acceleration API):开源 API,让 VLC、GStreamer 等应用使用 GPU 硬件视频加速能力,由自由开源库 libva 加硬件专用驱动实现。Intel 用 intel-media-driver,AMD 用 mesa-va-drivers。可用
vainfo命令查看当前 VA-API 状态(列出支持的编码/解码入口点与格式)。 - Vulkan Video:Vulkan 面向 3D 图形与计算的低开销跨平台 API 的扩展,用于视频编解码。AV1 解码扩展已发布,H.264/H.265 编码扩展亦已纳入 Vulkan SDK,ALVR 仓库中即有 Vulkan 视频层(见 vulkan_layer)作为支撑;就编码而言其支持仍属“即将到来(upcoming)”状态,本文测试命令不涉及。
- NVENC:Nvidia 显卡中的专用视频编码单元,把计算密集的编码从 CPU 卸载到 GPU 上的专用硬件模块。
- AMF(Advanced Media Framework):AMD 提供的 SDK,用于在多媒体处理中充分使用 AMD GPU,是 AMD 侧的专有编码 API(在 Linux 上 ALVR 主要走 VA-API)。
生成测试视频源:testsrc2
用真实的游戏画面测试会受场景复杂度干扰,难以判断编码是否走硬件。testsrc2 测试源则能提供稳定、可重复的输入。原文给出的生成命令为:
ffmpeg -hide_banner -f lavfi -i testsrc2=duration=30:size=1280x720:rate=90
各要素说明:
-f lavfi:Libavfilter 输入虚拟设备。它从一个 libavfilter 滤镜图的开放输出 pad 读取数据,并为每个开放输出建立对应流;滤镜图通过graph选项指定,这里的-i testsrc2=...即为该滤镜图。testsrc2:生成测试视频图案的源滤镜,显示彩色图案、滚动渐变和时戳,主要用于测试。与testsrc相似,但支持更多像素格式(不只是rgb24),可直接作为其他测试输入而无需格式转换。- 三个参数的含义:
duration为视频时长(秒)、size为画面尺寸(宽×高)、rate为帧率(FPS)。
原文采用的完整测试套路是 duration=300:size=1280x720:rate=90,即 5 分钟、720p、90 FPS——90 FPS 正好对齐常见 VR 头显刷新率。请注意:使用测试源做输入仍会产生 CPU 负载(FFmpeg 本身要生成画面),监控 GPU 是否卸载编码时,预期到 FFmpeg 进程仍有 CPU 占用是正常的。
渲染回放验证
编码产出的文件是否正确,用你最顺手的播放器验证即可:
- MPV:基于 MPlayer、mplayer2 和 FFmpeg 的自由开源播放器,支持 Linux、BSD、macOS、Windows,并有 Android 移植版(mpv-android),跨 ARM、PowerPC、x86/IA-32、x86-64、MIPS 等架构。
- VLC:VideoLAN 项目开发的自由开源、跨平台媒体播放器与流媒体服务器,支持桌面系统与 Android、iOS、iPadOS 等移动平台。
Nvidia GPU 验证(NVENC 管线)
Nvidia 平台只支持 NVENC:目前 Nvidia 的 VA-API 驱动(nvidia-vaapi-driver)只实现了 NVDEC(解码),编码必须走 NVENC。开始前请对照 Nvidia 官方的 GPU 编码/解码支持矩阵确认你的显卡支持 NVENC 及对应编码格式。
监控工具:
- nvtop:Neat Videocard TOP,类似 htop 的任务监视器,支持 AMD、Intel 和 Nvidia GPU,可多 GPU 显示。
- nvidia-smi pmon:基于 NVIDIA 管理库(NVML)的命令行工具,
pmon子命令列出每个设备上运行的计算与图形进程统计。
三种编码的测试命令(NVENC):
# H.264
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-c:v h264_nvenc -qp 18 \
nvidia-h264_nvec-90fps-300s.mp4
# H.265
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-c:v hevc_nvenc -qp 18 \
nvidia-hevc_nvec-90fps-300s.mp4
# AV1(仅 Ada Lovelace 及更新架构)
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-c:v av1_nvenc -qp 18 \
nvidia-av1_nvec-90fps-300s.mp4
参数说明:-c:v 选择视频编码器(h264_nvenc / hevc_nvenc / av1_nvenc);-qp 18 以固定量化参数(Constant QP)方式控制质量,值越小质量越高、码率越大。运行期间用 nvtop 或 nvidia-smi pmon 观察编码器引擎利用率,确认编码发生在 GPU 而非 CPU。
Intel GPU 验证(VA-API 管线)
Intel 平台只支持 VA-API,GEN 架构图形硬件配合 intel-media-driver。编码前请对照 Intel oneVPL 的硬件支持文档确认你的 CPU/GPU 支持的编码格式。
监控工具:同样推荐 nvtop(它同时支持 AMD、Intel、Nvidia GPU)。
三种编码的测试命令(VA-API,设备节点 /dev/dri/renderD128):
# H.264
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \
-c:v h264_vaapi -qp 18 \
intel-h264_vaapi-90fps-300s.mp4
# H.265
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \
-c:v hevc_vaapi -qp 18 \
intel-hevc_vaapi-90fps-300s.mp4
# AV1(仅 Arc A 系列)
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \
-c:v av1_vaapi -qp 18 \
intel-av1_vaapi-90fps-300s.mp4
VA-API 命令与 NVENC 的关键差异:-vaapi_device /dev/dri/renderD128 指定 VA-API 渲染节点(通常即集成显卡的 render 节点),-vf 'format=nv12,hwupload' 先把帧转成 NV12 再上传(upload)到 GPU 显存,随后交给 h264_vaapi / hevc_vaapi / av1_vaapi 编码器。ALVR 的 Linux 编码实现与这里的 hwupload 思路一致——见 EncodePipelineVAAPI.cpp,它通过 map_frame 把 Vulkan 帧映射为 DRM-PRIME 帧再转为 VA-API 帧,避免显存拷贝。
AMD GPU 验证(VA-API 管线)
AMD 平台只支持 VA-API,配合 mesa-va-drivers。编码需要 Video Core Next(VCN)硬件;AV1 编码需要 VCN 4.0+(RDNA3/Navi 3x 系列)硬件。请对照硬件特性确认编码支持。
监控工具:nvtop 同样适用于 AMD GPU。
三种编码的测试命令(VA-API):
# H.264
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \
-c:v h264_vaapi -qp 18 \
amd-h264_vaapi-90fps-300s.mp4
# H.265
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \
-c:v hevc_vaapi -qp 18 \
amd-hevc_vaapi-90fps-300s.mp4
# AV1(仅 VCN 4.0+,Navi 3x)
ffmpeg -hide_banner \
-f lavfi -i testsrc2=duration=300:size=1280x720:rate=90 \
-vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' \
-c:v av1_vaapi -qp 18 \
amd-av1_vaapi-90fps-300s.mp4
AMD 在 HEVC 编码上有特殊性:仓库补丁 0006-Add-AV_VAAPI_DRIVER_QUIRK_HEVC_ENCODER_ALIGN_64_16-f.patch 为 AMD Radeon 驱动增加了 64×16 的表面对齐要求——AMD 的 VA-API HEVC 编码器要求 surface 宽度按 64、高度按 16 对齐,而不像其他硬件那样依赖 min_cb_size。这意味着在 AMD 上测试 HEVC 时,若画面尺寸不符合对齐要求,编码参数会被 FFmpeg 内部调整对齐,属正常现象。
仓库佐证:ALVR 在 Linux 上如何依赖 FFmpeg VA-API
上述测试命令并非孤立存在,ALVR 的 Linux 编码管线与它们共享同一套 FFmpeg VA-API 机制,仓库中有直接证据:
- 编码器选型:EncodePipelineVAAPI.cpp 的
encoder()函数按ALVR_CODEC枚举选择h264_vaapi/hevc_vaapi/av1_vaapi,与测试命令的-c:v完全对应。 - 硬件帧上下文:同文件
set_hwframe_ctx()创建AV_PIX_FMT_VAAPI硬件帧上下文,并按 10 位编码开关选择P010(10 bit,HEVC/AV1)或NV12作为软件格式,帧池初始大小 3。 - 帧映射零拷贝:
map_frame()把 Vulkan 渲染帧以 DRM-PRIME 描述符形式交给 VA-API 硬件帧上下文,实现 Vulkan→VA-API 的映射,避免 CPU 拷贝。 - FFmpeg 专项补丁:ALVR 仓库在 xtask/patches 维护了一组针对 FFmpeg 的补丁,其中多个直接影响 VA-API 编码行为:
- 0002-vaapi_encode-Force-enable-global-header.patch:强制启用 global header,便于流式传输(ALVR 走 UDP/RTSP 流需要参数集在流头部);
- 0003-vaapi_encode_h265-Set-vui_parameters_present_flag.patch:为 H.265 打开
vui_parameters_present_flag,保证 VUI 参数(色彩信息、帧率等)正确写入 SPS,对解码端正确渲染至关重要; - 0004-vaapi_encode-Allow-to-dynamically-change-bitrate-and.patch:允许在编码过程中动态更新码率与帧率——这正是 ALVR 动态码率调整(见 bitrate.rs)在 VA-API 上的底层支撑;
- 0005-vaapi_encode-Add-filler_data-option.patch:新增
filler_data选项控制填充数据,用于稳定码率输出; - 0006-Add-AV_VAAPI_DRIVER_QUIRK_HEVC_ENCODER_ALIGN_64_16-f.patch:针对 AMD Radeon HEVC 编码器的 64×16 对齐处理。
这些补丁说明,ALVR 对 VA-API 编码不只是“能用就行”,而是做了面向实时流媒体的深度适配。如果你的自编译 FFmpeg 缺少这些补丁,ALVR 的 Linux VA-API 编码可能遇到参数集、动态码率或 AMD 对齐方面的问题。
测试结果的判定要点
- 编码器是否正确启用:命令输出中应能看到所选编码器的初始化信息(如
h264_vaapi、hevc_vaapi、av1_vaapi、h264_nvenc等);若 FFmpeg 报告编码器不可用、初始化失败或参数不支持,说明硬件或驱动不满足条件。 - GPU 是否真正参与:运行期间用
nvtop(三平台通用)或nvidia-smi pmon(Nvidia)观察编码引擎(Encoder Engine / Video Engine)占用率。若编码引擎占用明显上升而 CPU 占用没有成倍增长,即说明编码已卸载到 GPU。 - 输出是否可正常播放:用 MPV 或 VLC 回放生成的 mp4,确认画面(彩色图案 + 滚动渐变 + 时戳)与时间轴正确。
- 与 ALVR 设置的对应:确认硬件支持后,在 ALVR 会话设置中选择对应的编码器(H.264/HEVC/AV1)与 10 位编码开关,即可让 ALVR 复用你刚验证过的硬件编码管线。