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

相关推荐
音视频牛哥2 小时前
把Android设备变成“国标摄像头”:GB28181移动终端实战接入指南
android·音视频·大牛直播sdk·gb28181安卓端·gb28181对接·gb28181平台对接·gb28181监控
tangweiguo030519872 小时前
Jetpack Compose 响应式布局实战:BoxWithConstraints 完全指南
android
難釋懷2 小时前
Android开发-视图基础
android
Anthony_sun5 小时前
UniAppx 跳转Android 系统通讯录
android·uniapp
温柔的小猪竹9 小时前
android中的背压问题及解决方案
android
小妖6669 小时前
uni-app 引入vconsole web端正常,安卓端报错 Cannot read property ‘sendBeacon‘ of undefined
android·前端·uni-app
努力学习的小廉10 小时前
深入了解linux系统—— 进程控制
android·linux·服务器
帅次13 小时前
Flutter TabBar / TabBarView 详解
android·flutter·ios·小程序·iphone·taro·reactnative
每次的天空17 小时前
Android第六次面试总结之Java设计模式(二)
android·java·面试
北执南念1 天前
IDEA回滚代码操作
android·java·intellij-idea