本文主要说明自托管媒体库(以 Octans 播放子系统为例)在服务端 HLS 转码时,如何在软件、tonemap_vaapitonemap_opencl 之间做 tone mapping 选型:能力门禁、按动态范围分流的 Planner 逻辑、验证分层含义,以及「厂商 codec 矩阵 ≠ 本机已接线」的边界。设备节点以 /dev/dri/renderD128 一类占位符给出。

浏览器 Web 播放往往不要求客户端原生吃下全部 HDR / Dolby Vision 组合,而是在服务端把内容压到可播的 SDR / BT.709 基线。真正执行编解码的不是 Web 框架本身,而是托管的 FFmpeg 子进程;服务端负责的是:识别媒体事实 → 探测运行时能力 → 选链路 → 失败可观察地回退

先分清术语

术语含义常见误区
VAAPILinux 通用视频加速 API;能力来自底层驱动(如 Intel iHD「装了 VAAPI 包」≠ 硬解/硬编/tonemap 都可用
OpenCL interop把 VAAPI 表面映射到 OpenCL,做 tonemap_opencl 后再 map 回 VAAPI不等于独立 OpenCL 解码器;仍依赖 VAAPI 硬解/硬编
QSV / NVENC / AMF厂商专有编解码路径与当前「VAAPI + OpenCL」主线是不同 provider 候选
Tone mapping动态范围 / 色彩转换(HDR/HLG/DOVI → SDR)不等于降分辨率、降码率(那是输出质量处理)
Capability gate启动或运行时探测到的真实 codec / filter / hw 能力不能用「二进制能 -version」替代

工程上的一句话:

ffmpeg 编译进了某个 encoder
  ≠ 这台机器运行时可用
  ≠ Planner 已经把这条路接入业务 HLS

真正可用需要三件事同时成立:硬件存在、驱动与 ICD 可用、当前 FFmpeg 构建支持对应后端;业务上还要第四件:能力图已探测、命令模板已接线、样片验证通过

后端硬转码基线:为什么是 VAAPI + OpenCL

家用 / 轻量多用户 Linux 媒体服务器上,Intel 核显走 VAAPI 通常比先上 QSV 更适合做统一基线:

  • Linux 侧更通用,和 libvaintel-media-driver、FFmpeg 滤镜栈更容易收敛。
  • 后续 scale、色彩处理、硬件滤镜路径更直接。
  • 同一套思路后续也能部分复用到 AMD 的 VAAPI 路线。

NVIDIA 更适合高吞吐、多路并发的 NVENC/NVDEC 专机;AMD 可走 VAAPI 或后续专项 AMF当前主线先把 Linux / Intel VAAPI 与 OpenCL interop 跑稳,其它厂商 provider 按真实硬件再补。

概念上的全硬件视频链路:

VAAPI decode / upload
  → VAAPI scale 或 OpenCL tone mapping
  → VAAPI encode
  → fMP4 HLS 输出

设备与工具链占位:

render device:  /dev/dri/renderD128    # 以本机 ls /dev/dri 为准
ffmpeg root:    <ffmpeg-root>          # 例:/opt/octans-ffmpeg
ffmpeg:         <ffmpeg-root>/bin/ffmpeg
OpenCL ICD:     发行版 intel-opencl-icd 一类包(厂商与版本因环境而异)

动态范围如何分流

Tone mapping 只在「需要把 HDR 类内容变成 Web SDR」时介入。SDR 源不需要动态范围转换,只走普通 VAAPI 或软件的 decode / scale / encode。

分流表(EnginePolicy=Auto 口径)

输入色彩范围优先硬件路线软件基线说明
SDRVAAPI decode → scale_vaapih264_vaapi / hevc_vaapi软件 decode/encode无 tone mapping
HDR10 / PQ优先 tonemap_vaapi;能力缺失时可试 OpenCLtonemapx → BT.709HDR10+ 不保留 dynamic metadata,按 PQ 基线
HDR10+同 HDR10同 HDR10动态元数据不保留进输出
HLGtonemap_vaapi 不适用;OpenCL:VAAPI decode → tonemap_opencl → scale_vaapi → encodetonemapxHLG 是 OpenCL 硬件链的典型动机
DV 有可用 fallback按 fallback 类型(SDR / HDR10 / HDR10+ / HLG)复用上表按 fallback转码时不应用 DV RPU/EL,不保留 DV metadata
pure DOVI / 无 fallback(如 P5)OpenCL:tonemap_opencl:apply_dovi=true 串 VAAPI 解/编tonemapx:apply_dovi=trueDOVI reshaping 必须显式 apply_dovi

链路 ID 便于日志与排障对齐(名称可因实现略有差异):

链路 ID(概念)适用
vaapi-tonemap-hdr-bt709-nv12HDR10 / HDR10+ 等 PQ 系,VAAPI tonemap
opencl-tonemap-hdr-bt709-nv12HLG / 部分 HDR 的 OpenCL tonemap
opencl-tonemap-dovi-bt709-nv12pure DOVI,apply_dovi=true
tonemapx-*-bt709-yuv420p软件 fallback 或显式软件 engine

不要把 OpenCL 链路混进 tonemap_vaapi 的 capability 标记。 二者依赖不同:OpenCL 需要 ICD 初始化与 VAAPI/OpenCL interop 扩展;失败模式、探测项、回退策略都不相同。

OpenCL 全硬件链示意

VAAPI decode
  → hwmap 到 OpenCL
  → tonemap_opencl(目标 t/m/p=bt709,format=nv12)
  → hwmap 回 VAAPI
  → scale_vaapi
  → h264_vaapi / hevc_vaapi

代表性命令结构(路径已通用化;业务 HLS 还有 playlist / segment / pause 等参数,此处仅示意 filter 串联):

<ffmpeg-root>/bin/ffmpeg \
  -init_hw_device vaapi=va:/dev/dri/renderD128 \
  -init_hw_device opencl=ocl@va \
  -filter_hw_device ocl \
  -hwaccel vaapi \
  -hwaccel_device va \
  -hwaccel_output_format vaapi \
  -i "$input" \
  -vf 'hwmap=derive_device=opencl,tonemap_opencl=tonemap=bt2390:t=bt709:m=bt709:p=bt709:format=nv12:apply_dovi=true,hwmap=derive_device=vaapi:reverse=1,scale_vaapi=w=1920:h=1080:format=nv12,setsar=1' \
  -c:v hevc_vaapi \
  -tag:v hvc1 \
  "$output"

要点:

  • HLG 不要误开 apply_dovi=true;pure DOVI 必须显式写出。
  • 非 16:9 源注意 setsar=1 或等价处理,避免播放器按异常 SAR 展示。
  • 输出色彩标记应落到 bt709/bt709/bt709,不要只依赖 encoder 默认 metadata。
  • 日志里若出现 clCreateFromVA_APIMediaSurfaceINTEL 一类 interop 符号,说明走了 Intel VAAPI/OpenCL 互通路径(厂商扩展,不可默认跨卡通用)。

能力门禁:Planner 真正在看什么

选型顺序可以粗画成:

媒体事实(codec / profile / bit depth / transfer / DOVI fallback)
  + 客户端能力(能否播某种 HLS 输出 codec 等)
  + 运行时 capability graph
  + 策略(EnginePolicy=Auto | 显式 VAAPI | 显式 OpenCL | 显式软件)
  → 选定 transform chain + encoder
  → 启动失败则按策略 fallback 或 fail fast

应单独探测的门

含义
render 设备/dev/dri/renderD* 存在且进程有权限
VAAPI 基础vainfo / FFmpeg hwaccelsvaapi;目标 encoder(h264_vaapi / hevc_vaapi 等)可用
tonemap_vaapi滤镜存在且对目标 transfer(如 PQ)可初始化
OpenCL platformICD 已安装;初始化平台数 > 0(未装 ICD 常见 -1001
tonemap_opencl滤镜、算法、目标色彩、apply_dovi 能力
VAAPI↔OpenCL interop能否 hwmap 往返,而不是只软解再 hwupload
输出侧目标分辨率 / profile constraints、客户端是否接受 HEVC HLS 等

能力开启以探测结果为准,不以「装了某某 deb 包名」为准。配置侧常见原则:

  • EnginePolicy=Auto:按上表优先硬件,能力缺失或启动失败可回退软件 tonemapx
  • 显式 OpenCL / 显式 VAAPI:能力不足时宜 fail fast,避免静默跑成另一条链却写着「硬转码」。
  • 软件 tonemapx 与 OpenCL tonemap_opencl 的算法配置应分开,避免把 CPU 曲线误读成硬件通用配置。
  • 历史上的 zscale + tonemap 不宜再当第二套软件 fallback 与 tonemapx 并存:pure DOVI 需要 apply_dovi 级别的 reshaping;双软件链只会放大归因成本。缺 tonemapx 时应 fail fast。

硬件失败时的推荐策略是:按配置回退软件,而不是直接让用户「播不了」;但 fallback 必须可观察——日志应写明实际路径是 vaapiopenclsoftware 还是 vaapi-fallback-software,并带上 device、engine、filter chain 与原因。

「验证」到底验证了什么

ffmpeg -version 成功不等于播放可用。建议分层,前一层失败不进入后一层:

1. 二进制与动态库完整
2. 关键 codec / filter / muxer 与项目补丁行为存在
3. capability helper / 后端能力图识别正确
4. 最小 VAAPI 编码冒烟(testsrc + h264_vaapi 等)
5. 真实样片:SDR 硬解硬编 HLS
6. 真实样片:HDR10 VAAPI tonemap HLS;HLG / pure DOVI OpenCL 链
7. 业务会话:playlist、segment、浏览器播放、runtime pause / seek、fallback 归因

OpenCL tone mapping 的研究验证通常分三层:

  1. 软件解码后 hwupload 到 OpenCL,确认 tonemap_opencl 本身可用。
  2. VAAPI decode → OpenCL tonemap → VAAPI encode 串通。
  3. 接上 scale_vaapi,输出 H.264 / H.265 样片并做观感检查。

MP4 短样片通过 ≠ 业务 HLS 已接入。 连续 seek、event playlist、stdin runtime pause、多会话并发,都要单独验收。Docker 与 Host 还要分别确认:/dev/dri 映射、用户组 video/render、OpenCL ICD 是否进镜像。

本机冒烟示例

ls -l /dev/dri
vainfo --display drm --device /dev/dri/renderD128

<ffmpeg-root>/bin/ffmpeg -hide_banner -hwaccels
<ffmpeg-root>/bin/ffmpeg -hide_banner -encoders | rg 'vaapi|libx26'

# 最小 VAAPI 编码
<ffmpeg-root>/bin/ffmpeg -hide_banner -y \
  -vaapi_device /dev/dri/renderD128 \
  -f lavfi -i testsrc2=size=1280x720:rate=30 \
  -t 2 \
  -vf 'format=nv12,hwupload' \
  -c:v h264_vaapi \
  /tmp/vaapi-smoke.mp4

OpenCL 未就绪时的典型失败:

Failed to get number of OpenCL platforms: -1001

处理方向是安装匹配 GPU 的 OpenCL ICD,并确认容器/服务进程能读到 ICD 配置,而不是只换 FFmpeg 二进制。

性能观察:只当结论,不当普适 SLA

在单机 Intel iHD + UHD 类核显、约 60s 样片对照上,有过这些方向性结论(数值因驱动、分辨率、码率、low-power entrypoint 而变,不可当全球 SLA):

  • HDR10 场景:tonemap_vaapi 通常比 tonemap_opencl 更快;能走 VAAPI 就优先 VAAPI。
  • HLG / pure DOVI:硬件 tonemap 依赖 OpenCL 路线;软件 tonemapx 是 Auto 的安全网。
  • 输出 codec:同场景 H.264 VAAPI 往往比未调优的 H.265 VAAPI 更容易拿到实时余量;若硬件暴露 HEVC low-power encode entrypoint,H.265 速度可显著改善。
  • 服务端分片生产长期 speed < 1x 时,前端会表现为缓冲难涨、seek 后长时间 preparing——根因可能在 encoder 参数,而不只是客户端网络。

这些结论只服务「本机默认策略怎么设」;换 GPU 代际、关 low-power、换分辨率,必须重测。

边界:GPU 矩阵不是万能答案

厂商公开的固定功能编解码矩阵(H.264 / HEVC / AV1 / VP9 等按代际的 D/E)回答的是:

「这块硅理论上有没有固定功能单元」

回答:

  • 当前 FFmpeg 是否编译并探测到该路径;
  • Docker 是否映射了 render 节点与 ICD;
  • tonemap_vaapi 是否覆盖 HLG;
  • pure DOVI 是否有 apply_dovi 的硬/软链路;
  • Planner 是否已把该 codec 接进 HLS 输入/输出白名单。

再补几条工程红线:

  1. SKU 例外:无核显 Core F、无 NVENC 的低端 NVIDIA、RX 6500/W6400 一类「几乎无硬编」SKU,不能只按品牌粗判。
  2. Profile / bit depth:「支持 HEVC」≠ Main 10 / 4:2:2 / 4:4:4 都能硬转。
  3. AV1 解编分离:多数平台先有 decode、后有 encode;不能写「有 AV1 就能硬编 HLS」。
  4. 长尾 codec(ProRes、DNxHR、FFV1、老屏幕录制等):默认软件,不进固定功能硬解承诺。
  5. 跨厂商 OpenCL interop:Intel 上验证的 VAAPI↔OpenCL 扩展,不自动等于 AMD/NVIDIA 同构可用。
  6. Vulkan / libplacebo:即便 FFmpeg 编进了相关能力,未接入业务链路前不能写成「当前支持」。

更稳妥的数据模型是两步:

1) 媒体流识别:codec / profile / pix_fmt / transfer / hdr_metadata / dovi_fallback
2) 设备能力匹配:GPU + 驱动 + API + 本项目 capability graph + 输出策略

运维检查清单

现象优先查
总是软件转码能力图是否缺 VAAPI/OpenCL;render 权限;容器 /dev/dri
HDR10 正常、HLG 极慢或失败是否误走 tonemap_vaapi;OpenCL ICD 与 interop
pure DOVI 发灰 / 错色是否缺少 apply_dovi=true;是否落到无 DOVI 的滤镜链
有 OpenCL 滤镜仍初始化失败ICD 包、容器环境变量、多 GPU 下 device 选择
画面 SAR 异常非 16:9 是否补了 setsar=1
日志写 hard 实际是 softfallback 是否可观察;显式策略是否应 fail fast
换机后全挂驱动 / 内核 / SR-IOV VF / render 节点编号变化

Unraid 等场景下把核显 VF 直通进 Ubuntu 再跑 VAAPI,属于设备如何出现在 /dev/dri 的问题;本文不展开,见同系列 Unraid / UHD 770 文。

注意事项

  1. 本文是选型与验证口径,不是完整 codec 支持矩阵,也不是 API 契约。
  2. 命令中的 /dev/dri/renderD128<ffmpeg-root> 均为占位;以本机 ls、配置文件与 capability 日志为准。
  3. 内网样片路径、对象存储 artifact、精确 deb digest、私有 registry 不要写进公开文。
  4. 硬件加速失败应可回退、可观测;不要用「神秘卡顿」代替明确的 engine 字段。
  5. 验证过的是特定驱动 + FFmpeg runtime + 样片集合;升级驱动或 runtime 后应重跑分层验证。

相关阅读

同系列还可对照:

来源

本文综合改写自 Octans 项目文档中的硬件转码基线说明、OpenCL + VAAPI tone mapping 验证研究、视频编解码硬件支持复核,以及播放转码支持矩阵中的正式分流口径;性能段落仅吸收公开 benchmark 中的方向性结论。路径与版本已通用化,不绑定特定内网环境或对象存储位置。