Visual LabINTERACTIVE LEARNING
阶段 3 · 码流容器基础22 分钟

裸码流:NALU、参数集与访问单元

Elementary Stream、Annex B、Length Prefix、SPS/PPS

进入编码器输出层,理解 H.264 NAL Unit、Start Code 与长度前缀、SPS/PPS 和一帧数据的边界。

LEARNING GOALS

先明确本课目标

1

区分裸码流与容器

2

识别 Annex B Start Code 与 Length Prefix

3

理解 SPS/PPS 的作用

MENTAL MODEL · 再建立心智模型

裸码流是一串带类型的小包:参数集先告诉解码器如何理解后面的图像数据,容器或协议再负责给这些包补充轨道和时间信息。

MINIMAL EXAMPLE

怎样从连续字节中找到一个个 NALU?

Annex B 在 NAL Unit 前插入三或四字节 Start Code。扫描器找到相邻 Start Code 后,两者之间就是一个 NALU 的字节范围。

最小例子javascript
function isStartCode(bytes, i) {
  return bytes[i] === 0 && bytes[i + 1] === 0 &&
    (bytes[i + 2] === 1 ||
      (bytes[i + 2] === 0 && bytes[i + 3] === 1));
}
const nalType = bytes[nalOffset] & 0x1f;
  1. 扫描零字节前缀 识别 00 00 01 或 00 00 00 01。
  2. 确定 NALU 范围 当前起始码末尾到下一起始码之前属于一个单元。
  3. 读取类型低五位 H.264 NAL header 的低 5 bit 表示 nal_unit_type。

可把裸 H.264 字节流拆成 SPS、PPS、IDR Slice 与普通 Slice 等单元。

本课概念
OPTIONAL · 按需查阅完整术语表与概念边界

遇到陌生术语时再展开,不打断主线实验。

展开⌄
LIVE EXPERIMENT · 先获得反馈

边改边运行

浏览器加载后会激活代码编辑器、独立运行环境与实时输出。

本课挑战

写一个最小 Annex B NALU 扫描器,输出 offset、size、nal_unit_type。

DEEP DIVE · 实验之后

回到原理,解释刚才发生了什么

先用结果建立反馈,再按运行流程、核心原理和知识关系逐层深入。

CORE IDEA

核心讲解

01

NALU 是 H.264 的传输单元

每个 NAL Unit 有类型字段,可承载参数集、Slice 或补充信息。多个相关 NALU 组成一个访问单元,通常对应一张编码图像。

02

边界表达有不同方式

Annex B 用 00 00 01/00 00 00 01 起始码分隔 NALU;MP4 样本中常用固定宽度长度前缀,并把参数集放在配置记录。

OPTIONAL · 迁移时查阅Web 与原生实现对照

主线实验完成后,再用完整映射处理跨平台或跨 API 迁移。

展开⌄
API COMPARISON

Web 和原生都可能接触同一 Codec 配置,只是浏览器通常要求结构化 Chunk 和 description。

WebGL

FFmpeg AVPacket 保存压缩数据,extradata 保存容器解析出的参数配置,Bitstream Filter 可转换格式。

WebGPU

WebCodecs EncodedVideoChunk 携带时间戳,decoderConfig.description 可包含 avcC 等 Codec 配置。

把“码流格式”和“Codec 类型”分开描述,H.264 数据在不同容器中可能拥有不同边界格式。