深入浅出H.264码流分析
一、H.264是啥?
H.264就像视频的快递打包术:
- 作用:把原始视频压缩成小包裹(节省空间/带宽)
- 地位:最常用的视频编码标准(监控/直播/视频网站都在用)
- 压缩原理:只存储画面变化的部分(关键帧+差异帧)
二、H.264码流结构
1. 三层结构
graph TD
A[H.264码流] --> B[NALU单元]
B --> C[Slice切片]
C --> D[宏块MB]
2. 关键概念
术语 | 作用 | 类比 |
---|---|---|
NALU | 数据基本单元 | 快递包裹 |
SPS/PPS | 解码参数说明书 | 快递面单 |
I帧 | 完整画面 | 完整商品 |
P帧 | 与前一帧的差异 | 商品补发件 |
B帧 | 前后帧的差异 | 需要前后包裹才能组装 |
三、NALU单元解析
1. NALU头部格式
diff
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
- F(1bit):错误标志(0=正常)
- NRI(2bit):重要性(11=最重要)
- Type(5bit):类型代码
2. 常见NALU类型
类型值 | 名称 | 作用 |
---|---|---|
1 | 非IDR Slice | 普通帧数据 |
5 | IDR Slice | 关键帧(I帧) |
6 | SEI | 补充信息(如时间戳) |
7 | SPS | 解码参数集 |
8 | PPS | 图像参数集 |
四、手工分析H.264文件
1. 用xxd查看二进制
bash
xxd -g 1 test.h264 | less
输出示例:
makefile
00000000: 00 00 00 01 67 64 00 1e ac d9 40 50 05 bb 01 10 ....gd....@P....
00000010: 00 00 00 01 68 eb e3 cb 22 c0 00 00 00 01 65 b8 ....h...".....e.
00 00 00 01
:NALU起始码67
:SPS(type=7)68
:PPS(type=8)65
:IDR帧(type=5)
2. 使用工具分析
bash
# 使用ffprobe查看
ffprobe -v error -show_frames test.h264
# 输出示例:
[FRAME]
media_type=video
key_frame=1 # 关键帧
pkt_pts=0
pkt_size=28543
[/FRAME]
五、安卓代码解析H.264
1. 提取SPS/PPS
java
// 从MediaCodec获取参数
ByteBuffer sps = format.getByteBuffer("csd-0"); // SPS
ByteBuffer pps = format.getByteBuffer("csd-1"); // PPS
// 转16进制打印
Log.d("H264", "SPS: " + bytesToHex(sps));
Log.d("H264", "PPS: " + bytesToHex(pps));
2. 实时解析帧类型
java
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outputIndex = decoder.dequeueOutputBuffer(info, timeout);
if (outputIndex >= 0) {
ByteBuffer buffer = outputBuffers[outputIndex];
byte[] data = new byte[info.size];
buffer.get(data);
// 检查NALU类型
int nalType = data[4] & 0x1F; // 取第5字节的低5位
String frameType;
switch (nalType) {
case 5: frameType = "I帧"; break;
case 1: frameType = "P帧"; break;
default: frameType = "其他帧";
}
Log.d("H264", "帧类型: " + frameType);
}
六、H.264关键帧结构
1. I帧(关键帧)
-
特点:完整图像,解码不依赖其他帧
-
结构 :
cssSPS + PPS + SEI + I Slice
2. GOP(图像组)
graph LR
I --> P --> B --> B --> P --> B --> I
- GOP长度:两个I帧之间的间隔(直播通常2秒)
七、码流分析工具推荐
工具 | 用途 | 平台 |
---|---|---|
Elecard StreamEye | 可视化分析 | Windows |
H264Visa | 逐帧查看 | Windows |
FFmpeg/FFprobe | 命令行分析 | 全平台 |
CodecVisa | 安卓端分析 | Android |
八、避坑指南
1. 常见问题
- 花屏:丢失I帧或SPS/PPS
- 无法解码 :NALU缺少起始码
00 00 00 01
- 同步问题:时间戳(PTS/DTS)错乱
2. 优化建议
- 关键帧间隔:直播设2秒(GOP=帧率×2)
- SPS/PPS:每个I帧前重复发送
- 码率控制:根据分辨率调整
九、终极分析口诀
"H.264码流分三层,NALU里藏乾坤
SPS/PPS是配置,I帧完整P帧差
起始码头要认准,0x000001是标准
分析工具辅助看,编解码问题无处藏"
掌握H.264码流分析,你就能像"视频医生"一样精准诊断问题! 🩺📹