H.264(也称为AVC)是一种广泛使用的视频压缩标准。要从16进制数据中理解H.264文件,我们需要了解其基本结构和编码原理。

H.264基本结构

H.264流由一系列称为NAL单元(Network Abstraction Layer Units)的数据包组成。每个NAL单元包含一个头部和有效载荷。

NAL单元头部结构(1字节):

| forbidden_zero_bit(1) | nal_ref_idc(2) | nal_unit_type(5) |
  • forbidden_zero_bit: 必须为0
  • nal_ref_idc: 表示NAL单元的重要性(00-11)
  • nal_unit_type: 表示NAL单元类型

常见NAL单元类型

类型值(16进制) 类型名称 描述
0x01 非IDR图像的片 普通视频帧数据
0x05 IDR图像的片 关键帧数据
0x06 补充增强信息(SEI) 额外信息如时间戳等
0x07 序列参数集(SPS) 重要编码参数
0x08 图像参数集(PPS) 解码所需参数
0x09 访问单元分隔符 帧边界标记

如何分析16进制H.264数据

  1. 查找起始码:H.264通常以00 00 00 0100 00 01作为NAL单元起始码

  2. 解析NAL头部:起始码后的第一个字节是NAL头部

例如,看到以下16进制数据:

00 00 00 01 67 64 00 1E AC ...
  • 00 00 00 01是起始码
  • 67是NAL头部:
    • 二进制01100111
    • forbidden_zero_bit = 0
    • nal_ref_idc = 3 (高重要性)
    • nal_unit_type = 7 (SPS)
  1. 参数集解析

    • SPS(0x67)和PPS(0x68)包含关键编码信息
    • 需要特殊解析才能提取分辨率、帧率等
  2. 帧数据解析

    • IDR帧(0x65)是关键帧
    • 普通帧(0x61, 0x41等)

实际分析示例

假设有以下16进制片段:

00 00 00 01 67 64 00 1E AC D9 40 A0 2F F9 70 11 
00 00 00 01 68 E9 7B 2C 8B 00 00 00 01 65 B8 40 
F0 8C 03 C2 21 1A 80 00 00 00 01 41 E2 01 10 5F 

解析:

  1. 第一个NAL单元:
    • 起始码:00 00 00 01
    • NAL头部:67 → SPS
  2. 第二个NAL单元:
    • 起始码:00 00 00 01
    • NAL头部:68 → PPS
  3. 第三个NAL单元:
    • 起始码:00 00 00 01
    • NAL头部:65 → IDR帧(关键帧)
  4. 第四个NAL单元:
    • 起始码:00 00 00 01
    • NAL头部:41 → 普通帧

工具推荐

要更深入分析H.264流,可以使用:

  1. H.264比特流分析器:如Elecard StreamEye, CodecVisa
  2. 16进制编辑器:010 Editor, HxD
  3. FFmpegffmpeg -i input.h264 -c copy -bsf:v trace_headers -f null - 2>log.txt

SPS和PPS的长度是固定的吗

在H.264标准中,SPS(序列参数集)和PPS(图像参数集)的字节长度不是固定的,它们的长度会根据编码配置的不同而变化。以下是详细说明:

1. SPS和PPS的长度是可变的

SPS和PPS的内容是**可变长编码(VLC)**的,具体长度取决于:

  • 编码配置参数(如分辨率、帧率、档次/级别等)
  • 使用的H.264功能(如熵编码方式、参考帧数量等)
示例对比
  • 简单配置的SPS(如低分辨率、Baseline档次)可能只有 10~20字节
  • 复杂配置的SPS(如高分辨率、High档次支持多参考帧)可能达到 50字节以上

2. 影响SPS/PPS长度的关键参数

SPS和PPS中存储的以下参数会影响其大小:

  • SPS

    • profile_idclevel_idc(编码档次和级别)
    • pic_width_in_mbs_minus_1pic_height_in_map_units_minus_1(分辨率)
    • log2_max_frame_num_minus_4(帧编号长度)
    • num_ref_frames(参考帧数量)
    • entropy_coding_mode_flag(CABAC/CAVLC选择)
    • 其他高级选项(如帧间预测、色度格式等)。
  • PPS

    • entropy_coding_mode_flag
    • num_slice_groups_minus_1
    • weighted_pred_flag(加权预测)
    • deblocking_filter_control_present_flag(去块滤波控制)。

3. 如何从16进制数据中识别SPS/PPS的边界

虽然长度不固定,但可以通过以下方式定位:

  1. 起始码:SPS/PPS以 00 00 0100 00 00 01 开头。
  2. NAL单元类型
    • SPS的NAL头部通常是 0x67nal_unit_type=7)。
    • PPS的NAL头部通常是 0x68nal_unit_type=8)。
  3. 结束位置:下一个起始码出现时,表示当前SPS/PPS结束。
示例

以下16进制片段中:

00 00 00 01 67 64 00 0A AC 72 84 44 26 84 00 00 00 01 68 E9 7B 2C 8B
  • 第一个NAL单元(SPS):
    • 起始码:00 00 00 01
    • NAL头部:67(SPS)
    • 内容:64 00 0A AC 72 84 44 26 84(共9字节)。
  • 第二个NAL单元(PPS):
    • 起始码:00 00 00 01
    • NAL头部:68(PPS)
    • 内容:E9 7B 2C 8B(共4字节)。

4. 为什么长度可变?

H.264的设计目标是灵活性

  • 支持从移动设备(低分辨率、低码率)到广播级(高分辨率、高复杂度)的各种场景。
  • 参数集需要适配不同编码配置,因此采用指数哥伦布编码(Exp-Golomb),进一步压缩数据,但导致长度不固定。

5. 实际应用中的注意事项

  1. 封装格式的影响
    • 在MP4或FLV等容器中,SPS/PPS可能被提取到文件头部(如avcC盒子),此时可能不带起始码。
    • 在裸流(.h264文件)中,通常以起始码分隔。
  2. 解析工具
    • 使用 ffmpeg -i input.h264 -c:v copy -bsf:v trace_headers -f null - 可打印SPS/PPS内容。
    • 专业的H.264分析工具(如Elecard StreamEye)能可视化参数。

总结

  • SPS和PPS的长度不固定,取决于编码配置。
  • 通过起始码和NAL头部类型可定位它们。
  • 需要解析具体内容才能获取分辨率、帧率等关键信息。

关于SPS的字段解析

在H.264的SPS(序列参数集)中,profile_idclevel_idc固定位置的字段,但后续参数需要通过**指数哥伦布编码(Exp-Golomb)**解析。以下是具体定位和解析方法:

1. SPS的16进制结构概览

一个典型的SPS NAL单元(NAL类型=0x67)的16进制格式如下:

00 00 01 | 67 | 64 00 0A AC 72 84 44 26 84 ...
  • 00 00 01:起始码(或00 00 00 01
  • 67:NAL头部(forbidden_zero_bit=0 + nal_ref_idc=3 + nal_unit_type=7
  • 后续字节:SPS的实际内容(从profile_idc开始)。

2. 固定位置的字段

SPS的前几个字段是按顺序固定的(无需哥伦布编码):

字段名 字节偏移(从SPS内容开始) 长度 示例(67 64 00 0A AC...
profile_idc 第1字节 1 64
constraint_setX_flags 第2字节(低4位) 4bit 00的低4位是0000
level_idc 第3字节 1 0A
示例解析

对于SPS内容部分 64 00 0A AC...

  • profile_idc = 0x64(100)→ High Profile
  • constraint_set0_flags = 0x00 & 0x0F0000(无约束)
  • level_idc = 0x0A(10)→ Level 1.0

3. 后续可变字段的解析

从第4字节开始(如AC),需要通过指数哥伦布编码解析,顺序固定但长度可变。关键字段包括:

  1. seq_parameter_set_id
  2. log2_max_frame_num_minus_4
  3. pic_order_cnt_type
  4. max_num_ref_frames
  5. pic_width_in_mbs_minus_1(分辨率相关)
  6. pic_height_in_map_units_minus_1
解析工具
  • 手动解析复杂,推荐使用工具:
    ffmpeg -i input.h264 -c:v copy -bsf:v trace_headers -f null - 2>&1 | grep "SPS"
    
    输出示例:
    SPS: profile=100, level=10, width=176, height=144
    

4. 关键字段的16进制定位表

以SPS内容 64 00 0A AC 72 84 44 26 84 为例:

字段名 字节位置 值(16进制) 解析结果
profile_idc 1 64 High Profile (100)
constraint_setX_flags 2 00 无特殊约束
level_idc 3 0A Level 1.0
seq_parameter_set_id 4 AC Exp-Golomb解码后通常为0
log2_max_frame_num_minus_4 后续 72... 需按哥伦布编码逐bit解析

5. 常见profile_idclevel_idc对照表

Profile IDC
值(16进制) 名称 用途
42 Baseline Profile 低复杂度(移动设备)
4D Main Profile 通用视频
64 High Profile 高质量(广播、存储)
Level IDC
值(16进制) 级别 最大分辨率/帧率
0A 1.0 176x144@15fps
1E 3.0 720x480@30fps
28 4.0 1920x1080@30fps

6. 手动解析示例

假设SPS内容为 64 00 1E AC 72 84 44 26 84

  1. profile_idc = 0x64 → High Profile
  2. level_idc = 0x1E → Level 3.0
  3. 后续字段需按哥伦布编码解析:
    • AC10101100 → 解析为seq_parameter_set_id=0
    • 7201110010log2_max_frame_num_minus_4=4

总结

  • **profile_idclevel_idc**是SPS的第1和第3字节(跳过起始码和NAL头部后)。
  • 后续字段需按哥伦布编码解析,建议使用工具(如FFmpeg)自动化提取。
  • 分辨率等参数需要解析更深的字段,通常需借助专业分析工具。

关于PPS(图像参数集)的解析逻辑

PPS(图像参数集)的解析逻辑与SPS类似,但结构不同,关键区别在于字段顺序和内容。以下是详细对比和PPS的解析方法:

1. PPS与SPS的解析逻辑对比

特性 SPS(序列参数集) PPS(图像参数集)
NAL单元类型 0x67(NAL头部低5位=7) 0x68(NAL头部低5位=8)
核心字段顺序 固定顺序:profile_idclevel_idc→… 固定顺序:pic_parameter_set_idseq_parameter_set_id→…
字段编码 前3字节固定,后续用哥伦布编码 全部字段用哥伦布编码(无固定长度头部)
关键信息 分辨率、帧率、档次级别 熵编码模式、参考帧权重、去块滤波控制

2. PPS的16进制结构解析

典型PPS的16进制示例
00 00 01 | 68 | E9 7B 2C 8B
  • 00 00 01:起始码
  • 68:NAL头部(nal_unit_type=8表示PPS)
  • E9 7B 2C 8B:PPS的实际内容(全部需哥伦布编码解析)
PPS字段解析顺序
  1. pic_parameter_set_id
    • 第一个Exp-Golomb编码值(示例中E911101001→解码后通常为0
  2. seq_parameter_set_id
    • 第二个Exp-Golomb编码值(关联对应的SPS)
  3. entropy_coding_mode_flag
    • 0=CAVLC,1=CABAC(影响后续语法元素解析)
  4. num_ref_idx_lX_active_minus1(参考帧列表控制)
  5. weighted_pred_flag(加权预测)
  6. deblocking_filter_control_present_flag(去块滤波)

3. 关键字段的16进制定位示例

以PPS内容 E9 7B 2C 8B 为例(需按比特流解析):

字段名 原始16进制 Exp-Golomb解码结果 含义
pic_parameter_set_id E9 0 PPS ID=0
seq_parameter_set_id 7B 0 关联的SPS ID=0
entropy_coding_mode_flag 2C 1 使用CABAC熵编码
num_ref_idx_l0_active_minus1 8B 0 前向参考帧数量=1

🔍 :实际解析需将16进制转换为二进制后,按哥伦布编码规则逐bit读取。


4. 为什么PPS比SPS更简单?

  • 字段更少:PPS通常仅需10~20字节,而SPS可能需要50+字节。
  • 无分辨率/帧率:这些关键参数在SPS中定义,PPS仅补充解码控制参数。
  • 依赖SPS:PPS通过seq_parameter_set_id绑定到特定SPS。

5. 自动化解析工具推荐

  1. FFmpeg

    ffmpeg -i input.h264 -c:v copy -bsf:v trace_headers -f null - 2>&1 | grep "PPS"
    

    输出示例:

    PPS: entropy_coding_mode_flag=1, weighted_pred_flag=0
    
  2. H.264分析工具

    • Elecard StreamEye:可视化PPS/SPS结构。
    • CodecVisa:逐比特解析哥伦布编码字段。

6. 手动解析PPS的步骤

假设PPS内容为 68 E9 7B 2C 8B

  1. 定位起始:跳过00 00 01 68,从E9开始解析。
  2. 解析pic_parameter_set_id
    • E911101001 → 哥伦布解码为0
  3. 解析seq_parameter_set_id
    • 7B01111011 → 解码为0(关联SPS ID=0)。
  4. 解析entropy_coding_mode_flag
    • 下一个比特1→ 使用CABAC。

总结

  • PPS的解析逻辑与SPS不同:全部字段需哥伦布编码,无固定头部。
  • 关键字段pic_parameter_set_idseq_parameter_set_id、熵编码模式。
  • 工具优先:手动解析复杂,推荐用FFmpeg或专业工具提取参数。

关于H.264中的指数哥伦布编码(Exp-Golomb)解析详解

在H.264标准中,SPS(序列参数集)和PPS(图像参数集)的大部分参数都采用**指数哥伦布编码(Exp-Golomb)**进行压缩存储。这是一种变长编码(VLC)方式,用于高效表示小数值(如0、1、2)和较大的数值(如1000)。

1. 指数哥伦布编码的基本规则

指数哥伦布编码的二进制结构分为三部分:

[M个前导0] [1] [M个信息位]
  • M:由前导0的数量决定(即 M = 前导0的个数)。
  • 1:分隔符,标志前导0结束。
  • 信息位:共M位,表示具体数值。

解码公式
[
\text{Value} = 2^M - 1 + \text{信息位(二进制转十进制)}
]


2. 解码步骤(手动解析示例)

假设有一个二进制比特流片段:
00010110(16进制 16),需要解析连续的Exp-Golomb编码值。

示例1:解析第一个值

  1. 查找前导0
    • 比特流:00010110
    • 前导0有 3个M=3
  2. 读取分隔符1
    • 消耗掉0001
  3. 读取M=3位信息位
    • 剩余0110 → 取前3位 011
  4. 计算数值
    [
    \text{Value} = 2^3 - 1 + \text{011(3)} = 8 - 1 + 3 = 10
    ]
    解析结果10
  5. 剩余比特流
    • 已消耗0001011,剩余0(可能属于下一个Exp-Golomb编码)。

示例2:解析SPS/PPS中的常见字段

假设SPS内容部分的一个字节 AC(二进制 10101100),解析步骤如下:

  1. 比特流10101100
  2. 解析pic_parameter_set_id
    • 前导0:1(无前导0,M=0
    • 分隔符:1
    • 信息位:无(M=0
    • 计算:
      [
      \text{Value} = 2^0 - 1 + 0 = 0
      ]
      解析结果0
  3. 剩余比特流0101100(继续解析下一个值)。

3. H.264中常见的Exp-Golomb编码字段

字段名 所在位置 示例(二进制→值)
seq_parameter_set_id SPS的第4字节 AC101011000
pic_parameter_set_id PPS的第1字节 E9111010010
log2_max_frame_num_minus_4 SPS的后续字段 72011100104
num_ref_frames SPS的后续字段 84100001004

4. 特殊情况:ue(v)se(v)me(v)

H.264定义了三种Exp-Golomb变体:

  1. ue(v):无符号指数哥伦布编码(最常用,如seq_parameter_set_id)。
    • 直接按上述规则解析。
  2. se(v):有符号指数哥伦布编码(用于表示负数)。
    • 先按ue(v)解码,再转换:
      [
      \text{Value} = (-1)^{k+1} \times \lceil k/2 \rceil, \quad k = \text{ue(v)}
      ]
  3. me(v):映射指数哥伦布编码(用于宏块类型)。
    • 需查表转换。

5. 自动化解析工具

手动解析复杂,推荐:

  1. FFmpeg
    ffmpeg -i input.h264 -c:v copy -bsf:v trace_headers -f null - 2>&1 | grep "exp_golomb"
    
  2. H.264分析软件
    • Elecard StreamEye:可视化比特流和哥伦布编码。
    • CodecVisa:逐比特解析。

6. 总结

  • Exp-Golomb编码 = [前导0] [1] [信息位],数值计算为 (2^M - 1 + \text{信息位})。
  • SPS/PPS的关键字段(如seq_parameter_set_id)必须用此方法解析。
  • 手动解析时:先转二进制,找前导0,计算数值。
  • 实际应用:优先使用工具(FFmpeg)自动提取参数。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐