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

相关推荐
maki0774 小时前
虚幻版Pico大空间VR入门教程 05 —— 原点坐标和项目优化技巧整理
android·游戏引擎·vr·虚幻·pico·htc vive·大空间
千里马学框架4 小时前
音频焦点学习之AudioFocusRequest.Builder类剖析
android·面试·智能手机·车载系统·音视频·安卓framework开发·audio
fundroid8 小时前
掌握 Compose 性能优化三步法
android·android jetpack
TeleostNaCl9 小时前
如何在 IDEA 中使用 Proguard 自动混淆 Gradle 编译的Java 项目
android·java·经验分享·kotlin·gradle·intellij-idea
旷野说10 小时前
Android Studio Narwhal 3 特性
android·ide·android studio
maki07716 小时前
VR大空间资料 01 —— 常用VR框架对比
android·ue5·游戏引擎·vr·虚幻·pico
xhBruce20 小时前
InputReader与InputDispatcher关系 - android-15.0.0_r23
android·ims
领创工作室20 小时前
安卓设备分区作用详解-测试机红米K40
android·java·linux
hello_ludy20 小时前
Android 中的 mk 和 bp 文件编译说明
android·编译
maki0771 天前
VR大空间资料 03 —— VRGK使用体验和源码分析
android·vr·虚幻·源码分析·oculus·htc vive·vrgk