H264 协议解析 -- 速通版

前排提示:之所以叫 “速通版”,前提是对有一定音视频基础知识的人群,可参考本文快速了解一些重点信息和内容。


H264 编码协议

编码原理 —— 使用帧内压缩帧间压缩的⽅式提⾼编码压缩率:

  • ① 每帧的像素块之间存在相似性,通过存储差异数据来压缩图像数据,即帧内压缩
     
  • ② 帧与帧之间也存在相似性,同样也可以存储差异数据来再次压缩数据,即帧间压缩

 

重点需要关注的是 帧内压缩。 H264 采⽤了 I 帧、P 帧和 B 帧策略来实现连续帧之间的压缩。( 注意这里的 I、P、B帧是 H264 编码协议里面的的定义概念,并不是真正的物理的存在的事物。

  • I 帧 Intra picture 帧内编码帧

    I 帧通常是每个 GOP(group of pictures) 的第一个帧;

    一个 I 帧可以看成是⼀张图片经过压缩后的产物;

    I 帧本身可以通过视频解压算法解压成⼀张单独的完整的图片。

  • P 帧 Predicative-frame 向前预测编码帧

    P 帧需要参考其前⾯的⼀个 I 帧或者 P 帧来生成⼀张完整的图片。

  • B 帧 Bi-directional interpolated prediction frame 双向预测帧

    B 帧需要参考其前⼀个 I 或者 P 帧及其后⾯的⼀个 P 帧来⽣成⼀张完整的图片。

 

很显然,不同的帧所占字节数大小: I 帧 > P 帧 > B 帧

不同帧的编码复杂程度:B 帧 > P 帧 > I 帧


一、H264 整体结构

众所周知,网络协议的设计都是分层的。相似的原理,为了方便 H264 文件进行网络传输,H264 定义了一套封装分层结构。 H264 将文件先分为连续的视频帧序,帧内的图像数据再一层层的分为片、宏块和子块进行传输,具体分层如下:

  • 序列 (GOP)
  • 图片 (pictrue)
  • 片 (Slice)
  • 宏块 (Macroblock)
  • 子块 (subblock)

示意图如下:


二、H264 关键概念

1. 视频序列  (Coded Video Sequence)

就是⼀段内容差别不是很⼤的图像编码后生成的⼀串数据流。

当图像内容(运动)变化比较少时,⼀个序列可以很长(此时可以编⼀个 I 帧,然后⼀直 P 帧、B帧);

当运动变化多时,⼀个序列就比较短(此时可以只包含⼀个 I 帧和大概3、4个 P 帧)。

在视频编码序列中, Reference(参考周期)指两个 P 帧之间的距离。

所以,在码率不变的前提下 ——

  • ① GOP 值越⼤,P、B 帧的数量会越多,平均每个 I、P、B 帧所占⽤的 字节数就越多,也就更容易获取较好的图像质量;
  • ② Reference 越⼤,B 帧的数量越多,同理也 更容易获得较好的图像质量。

2. GOP (group of pictures,图像组)

主要⽤作形容⼀个 IDR 帧 到下⼀个 IDR 帧之间的间隔了多少个帧 (当然,也可以指两个 I 帧之间的距离)。 注意,GOP 值不宜设置过大。

在视频内容里的场景切换(图像内容变化大)时,H.264编码器会自动强制插入⼀个 I 帧,此时,实际的 GOP 值被缩短了。另一方面,当 I 帧的图像质量比较差时,会影响到当前 GOP 内后续 P、B 帧的图像质量,直到下⼀个 GOP 开始才有可能得以恢复。同时,由于 P、B 帧比 I 帧复杂,所以过多的 P、B 帧会影响编码效率,使编码效率降低。

另外,GOP 会影响 Seek 操作的响应速度。当Seek 操作需要直接定位、解码某⼀个 P 或 B 帧时,就需要先解码得到对应 GOP 内的 I 帧及前 N 个预测帧。所以,GOP 值越大,需要解码的预测帧就越多,Seek 响应的时间也越长。

3. IDR (Instantaneous Decoding Refresh,即时解码刷新)

⼀个序列的第⼀个图像叫做 IDR 图像(立即刷新图像),所有的IDR 图像都是 I 帧图像。

I 帧是帧组 GOP 的基础帧 (如果为 IDR, 则为第⼀帧), 在⼀组中只有⼀个 IDR 帧,可以有⼀个或多个 I 帧;

I 帧不用参考任何帧,但是之后的 P 帧和 B 帧是有可能参考这个 I 帧之前的帧的。但是,IDR 不允许这样。

IDR帧的核心作用 —— 为了解码的重同步。

当解码器解码到 IDR 图像时,⽴即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始⼀个新的序列。 这样,如果前⼀个序列出现重⼤错误,在这里可以获得重新同步的机会。IDR 图像之后的图像永远不会使用 IDR 之前的图像的数据来解码。

4. NALU (Network Abstract Layer Unit) 结构

H.264 原始码流(裸流)是由⼀个接⼀个 NALU 组成,NALU 的功能分为 2 层:

  • VCL (视频编码层): 包括核心压缩引擎和块,宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码;
  • NAL (网络提取层): 负责将 VCL 产⽣的比特字符串适配到各种各样的⽹络和多元环境中,覆盖了所有片级以上的语法级别。

原始 NALU 单元 = [ StartCode ] + [ NALU Header ] + [ NALU Payload ]

其中, Start Code 标示 NALU 单元的开始,必须是"00 00 00 01" 或"00 00 01";

除此之外,基本相当于⼀个 NAL Header + RBSP (Raw Byte Sequence Playload 原始字节序列负荷);

5. SPS(Sequence Paramter Set,序列参数集)

SPS 中保存了⼀组编码视频序列的全局参数。

6. PPS(Picture Paramter Set,图像参数集)

对应的是⼀个序列中某⼀幅图像或者某几幅图像的参数。

注意,传输 H264 原始码流(裸流)过程中,在发送 I 帧之前,至少要 先发⼀次 SPS 和 PPS


二、H264 封装模式

H264 编码后数据,有 2 种封装模式:

  • annexb 模式:

    传统模式,有 startcode,SPS 和 PPS 是在 ES 中;

  • mp4 模式:

    ⼀般的 mp4、mkv 文件都是 mp4 模式,没有 startcode。

    SPS 和 PPS 以及其它信息都被封装在 container 中,每⼀个 frame 前⾯ 4 个字节是这个 frame的长度。


三、 MP4 转 H264

FFmpeg 的代码层面,提供了名称为 h264_mp4toannexbbsf-Bit Stream Filter 来实现这个功能。

FFmpeg 命令行,也可以实现将 MP4 转换成 H264 (注意 -bsf: 后面需要空格)

ffmpeg -i test.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 test.h264

补充,使用命令行查看 FFmpeg 支持的所有 Bit Stream Filter 类型

ffmpeg -bsfs

运行结果:


PS:分享

一个 系统深入学习音视频 知识的课程 —— https://xxetb.xetslk.com/s/45jaSl


(学无止境,文章如有纰漏不足,欢迎您不吝指正!谢谢 ^_^)

  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值