深入浅出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码流分析,你就能像"视频医生"一样精准诊断问题! 🩺📹

相关推荐
_李小白5 小时前
【Android FrameWork】延伸阅读:SurfaceFlinger线程
android
csdn12259873366 小时前
JetPack Compose 入门先搞清楚
android·compose·jetpack
liang_jy6 小时前
Android LaunchMode
android·面试
阿里云云原生7 小时前
Android App 崩溃排查实战:如何利用 RUM 完整数据与符号化技术定位问题?
android·阿里云·云原生·rum
过期动态8 小时前
JDBC高级篇:优化、封装与事务全流程指南
android·java·开发语言·数据库·python·mysql
没有了遇见10 小时前
Android 音乐播放器之MotionLayout实现View流畅变换
android
TheNextByte111 小时前
在 PC 和Android之间同步音乐的 4 种方法
android
君莫啸ོ11 小时前
Android基础-Activity属性 android:configChanges
android
TimeFine11 小时前
Android AI解放生产力(七):更丰富的AI运用前瞻
android
保持低旋律节奏11 小时前
linux——进程状态
android·linux·php