首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >给 FFmpeg 的 MOV muxer 加上 Common Encryption(cbcs)支持(三):NAL 视频的 subsample 加密

给 FFmpeg 的 MOV muxer 加上 Common Encryption(cbcs)支持(三):NAL 视频的 subsample 加密

原创
作者头像
TVP 悟空
发布于 2026-11-15 11:08:11
发布于 2026-11-15 11:08:11
50
举报

音频可以整段 AES-CBC 加密,视频不行——尤其 H.264/HEVC 这类 NAL 结构化视频。

ISO/IEC 23001-7 明确要求视频走 subsample 加密,把一部分字节保持明文。

为什么不能整段加密视频

原因在于播放器/转封装器需要在不解密的情况下做很多事:

  • 把 ISO-BMFF 的 length-prefixed 格式转成 Annex B;
  • 读取 SEI、参数集、slice header 里的信息;
  • 做轨道级别的编辑、切分、DRM 前置处理。

如果 NAL 长度、NAL 头、slice header 都被加密,这些操作就做不了。所以

标准规定:

  • NAL 长度字段必须明文;
  • NAL 头必须明文(H.264 1 字节,HEVC 2 字节);
  • 非 slice NAL(VPS/SPS/PPS/SEI/AUD 等)必须明文;
  • slice header 明文;
  • 只有 slice data 加密。

对 avc1 来说,slice header 明文是 SHOULD;对 avc3/hvc1/hev1 是

必须。

我们怎么组织 subsample

在 MOV 里,subsample 信息写在 senc/traf 里,每个条目是

(BytesOfClearData, BytesOfProtectedData) 的组合,总长度刚好覆盖整个

样本。

对 H.264/HEVC 的写码器,我们按 NAL 逐个处理:

  • 非 slice NAL:整个写进 clear,(nal_size, 0)。
  • slice NAL:写 length + NAL 头 + slice header 为 clear,其余写进 protected。

模式加密(cbcs 的 1:9 等)只作用于 protected 范围,且每个 subsample

从样本 IV 重新开始 CBC 链。

两个容易忽略的实现细节

  1. 长 clear run 不能塞进一个条目。BytesOfClearData 是 16 位,超过 65535 就得拆成多个条目,前面用 (65535, 0),最后一个带 protected。 我们第一版直接传 16 位,一个 7 万字节的 filler NAL 就被截断了。
  2. saiz 每个条目只有 1 字节。一个样本的辅助信息如果超过 255 字节 (比如 43 个 AV1 tile 的 subsample),得在写之前报错,而不是静默截断。

顺带处理的兼容路径

  • AC-3/E-AC-3 走整样本加密;
  • 音频(AAC 等)无 subsample、constant IV、不写 senc;
  • VVC/LCEVC/APV/字幕目前没有对应加密路径,直接拒绝,而不是写出带 加密信号却实际明文/无法解密的文件;
  • rtphint 与加密互斥,直接拒绝。

下一篇是这一篇的核心依赖:slice header 到底在哪里结束?我们要自己算出

这个边界。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 为什么不能整段加密视频
  • 我们怎么组织 subsample
  • 两个容易忽略的实现细节
  • 顺带处理的兼容路径
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档