深入浅出H.264码流分析

深入浅出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帧(关键帧)

  • 特点:完整图像,解码不依赖其他帧

  • 结构

    css 复制代码
    SPS + 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码流分析,你就能像"视频医生"一样精准诊断问题! 🩺📹

相关推荐
Kapaseker1 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴1 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭11 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab12 小时前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe18 小时前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农1 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos
鹏程十八少1 天前
4.Android 30分钟手写一个简单版shadow, 从零理解shadow插件化零反射插件化原理
android·前端·面试
Kapaseker1 天前
一杯美式搞定 Kotlin 空安全
android·kotlin
三少爷的鞋1 天前
Android 协程时代,Handler 应该退休了吗?
android
火柴就是我2 天前
让我们实现一个更好看的内部阴影按钮
android·flutter