首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >给 FFmpeg 的 MOV muxer 加上 Common Encryption(cbcs)支持(四):自己实现 H.264/HEVC slice heade

给 FFmpeg 的 MOV muxer 加上 Common Encryption(cbcs)支持(四):自己实现 H.264/HEVC slice heade

原创
作者头像
TVP 悟空
发布于 2026-11-15 11:09:07
发布于 2026-11-15 11:09:07
80
举报

第三篇说清楚了边界:slice header 要明文,slice data 才加密。但 slice

header 是变长的,必须解析 bitstream 才知道它到哪里结束。

为什么不能直接用 libavcodec

最自然的想法是复用 libavcodec 里的 H.264/HEVC slice header 解析。比如

Olivier 给的参考 patch 就是把 h264_slice.c 里的

ff_h264_slice_header_parse 导出来,让 MOV muxer 直接调。

问题在于库的依赖方向:libavformat 和 libavcodec 是互相独立的库,

libavformat 不能去链接 libavcodec 的内部符号。静态构建能过,shared

构建会引入循环依赖,这是 FFmpeg 上游不会接受的写法。

FFmpeg 里已有的折中做法是源码复制:libavformat/h2645_parse.c 就是

直接 #include "libavcodec/h2645_parse.c",让两边各自编译一份。我们沿用了

这个思路,在 libavformat 里写了自包含的精简解析器:

  • cenc_h264.c:H.264 的 SPS/PPS + slice header;
  • cenc_hevc.c:HEVC 的 VPS/SPS/PPS/RPS + slice header。

只保留“算 slice header 长度”需要的字段,不做解码。

关键复用:ff_h2645_packet_split

算 slice header 边界,第一步是拿到去转义后的 RBSP 和 NAL 头。我们复用

ff_h2645_packet_split:

  • 帮我们切 NAL、去 emulation prevention bytes;
  • 给出 GetBitContext(已经越过 NAL 头);
  • 给出每个 EPB 的位置,用于把 RBSP 偏移映射回原始字节。

slice header 的解析就从这个 gb 开始,走一遍语法:

  • H.264:first_mb_in_slice、slice_type、pps_id、frame_num、 POC、ref_pic_list_reordering、pred_weight_table、 dec_ref_pic_marking、slice_qp_delta、deblocking 参数……
  • HEVC:first_slice_segment_in_pic_flag、slice_pic_parameter_set_id、 slice_segment_address、slice_type、POC、RPS、long-term RPS、SAO、 ref list 修改、weighted pred、entry point offsets……

EPB 映射

RBSP 是去转义后的,写进文件的是原始 escaped NAL。所以算出的 RBSP 字节数

还要加上这段 slice header 里被去掉的 EPB 数量,才等于原始 NAL 里的明文

字节数。ff_h2645_packet_split 提供的 skipped_bytes_pos 正好干这个。

边界怎么验证

round-trip 测试只能证明“加密和解密用同一套 subsample 信息”,不能证明

边界算对了。我们用 FFmpeg 解码器临时插桩,对比我们自己算出的 clear

长度和解码器里的 slice data offset:

  • H.264 的 CAMACI3 IDR:双方都是 6 字节 slice header;
  • HEVC 的 ipcm IDR / TRAIL:双方一致。

这是整个实现里最需要独立校验的部分。

为什么同时做 H.264 和 HEVC

HEVC 的 hev1/hvc1 对 slice header 明文是硬要求,所以 HEVC 解析器必须

做;H.264 的 avc3 同样是硬要求,avc1 是 SHOULD。为了让实现一致,我们

两个都做了,而不是只做 HEVC。

下一篇聊踩坑:这些解析器里、以及写码器分派里,有哪些容易翻车的边界。

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

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

目录
  • 为什么不能直接用 libavcodec
  • 关键复用:ff_h2645_packet_split
  • EPB 映射
  • 边界怎么验证
  • 为什么同时做 H.264 和 HEVC
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档