H264 编解码协议详解

1.、什么是 H264?
H264 是 MPEG-4 标准所定义的最新编码格式,同时也是技术含量最高、代表最新技术水平的视频编码格式之一,标准写法应该是H.264

H264 视频格式是经过有损压缩的,但在技术上尽可能做的降低存储体积下获得较好图像质量和低带宽图像快速传输。

2、一些相关名词解释
下图为 H264 码流分层图


2.1、VCL & NAL
H264 原始码流是由一个接一个 NALU(NAL Unit) 组成,它的功能分为两层,VCL(Video Coding Layer)视频编码层和 NAL(Network Abstraction Layer)网络提取层。

VCL:包括核心压缩引擎和块、宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码;
NAL:负责将 VCL 产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别;
NAL是 H.264 为适应网络传输应用而制定的一层数据打包操作。传统的视频编码算法编完的视频码流在任何应用领域下(无论用于存储、传输等)都是统一的码流模式,视频码流仅有视频编码层 VCL(Video Coding Layer)。而 H.264 可根据不同应用增加不同的 NAL 片头,以适应不同的网络应用环境,减少码流的传输差错。

在 VCL 进行数据传输或存储之前,这些编码的 VCL 数据,被映射或封装进NAL单元(NALU)。

一个 NALU = 一组对应于视频编码的 NALU 头部信息 + 一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)
1


一个原始的 H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是 “00 00 00 01”

实际原始视频图像数据保存在 VCL 分层的 NAL Units 中

2.2、片(slice)
一个片 = Slice Header + Slice Data
1
片是 H.264 提出的新概念,实际原始视频图像数据保存在 VCL 层级的 NAL Unit 中,这部分数据在码流中被称作是片(slice)。一个 slice 包含一帧图像的部分或全部数据,换言之,一帧视频图像可以编码为一个或若干个 slice。一个 slice 最少包含一个宏块,最多包含整帧图像的数据。在不同的编码实现中,同一帧图像中所构成的 slice 数目不一定相同。

一个 slice 编码之后被打包进一个 NALU,所以 slice = NALU

那么为什么要设置片呢?
设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。

在上图中,可以看到每个图像中,若干宏块(Macroblock)被排列成片。一个视频图像可编成一个或更多个片,每片包含整数个宏块 (MB),每片至少包含一个宏块。

slice 类型
slice    意义
I slice    只包含 I 宏块
P slice    包含 P 和 I 宏块
B slice    包含 B 和 I 宏块
SP slice    包含 P 或 I 宏块,用于不同码流之间的切换
SI slice    一种特殊类型的编码宏块
slice 组成
每一个 slice 总体来看都由两部分组成,一部分作为 slice header,用于保存 slice 的总体信息(如当前 slice 的类型等),另一部分为 slice body,通常是一组连续的宏块结构(或者宏块跳过信息)

2.3、宏块(Macroblock)
刚才在片中提到了宏块,那么什么是宏块呢?

宏块是视频信息的主要承载者。一个编码图像通常划分为多个宏块组成.包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中像素阵列。

一个宏块由一个 16×16 亮度像素和附加的一个 8×8 Cb 和一个 8×8 Cr 彩色像素块组成。

宏块分类    意义
I 宏块    利用从当前片中已解码的像素作为参考进行帧内预测
P 宏块    利用前面已编码图像作为参考进行帧内预测
B 宏块    利用双向的参考图像(当前和未来的已编码图像帧)进行帧内预测
2.4、帧(frame)和场(filed)
视频的一场和一帧用来产生一个编码图像,一帧通常是一个完整的图像,当采集视频信号时,如果采用隔行扫描(奇、偶数行),则扫描下来的一帧图像就被分成了两个部分,这每一部分都被称为 [场],根据次序,分为 [顶场] 和 [底场]。

扩展阅读:为什么会产生场的概念?
人眼可察觉到的电视视频图像刷新中的闪烁为 0.02 秒,即当电视系统的帧率低于 50 帧/秒,人眼可感觉得出画面的闪烁。常规如 PAL 制式电视系统帧率为 25 帧/秒、NTSC 制式的则为 30 帧/秒,如果采用逐行扫描将不可避免地在视频刷新时产生闪烁现象。而另一方面如果单纯的提高帧率达到避免闪烁刷新效果,则会增加系统的频带宽度。

这便引出了隔行扫描技术及 [场] 的概念

在隔行扫描中,每一帧包含两个场(top field)和(bottom field),其中每个 field 包含一帧中一半数量的水平线,top field 包含所有奇数线,bottom field 则包含所有偶数线。则在电视显示过程中,电子枪每发射一行隔一行—先发射奇数行13579…(top field)回头再发射2468…(bottom field)利用两次扫描来完成一幅图像,因为视觉的滞留性,我们看到的效果是差不多的。如在 NTSC 视频中 frame 的频率为30次/秒-àfield的频率则为 60 次/秒,大于了人眼可察觉闪烁的频率。

适用类型
方式    作用域
帧编码方式    活动量较小或者静止的图像宜采用
场编码方式    活动量较大的运动图像


2.5、I 帧、P 帧、B 帧与 pts/dts
帧的分类    中文    意义
I 帧    帧内编码帧,又称 intra picture    I 帧通常是每个 GOP(MPEG 所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象。I帧可以看成是一个图像经过压缩后的产物
P 帧    前向预测编码帧,又称 predictive-frame    通过充分将低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧
B 帧    双向预测帧,又称 bi-directional interpolated prediction frame    既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧
I frame: 自身可以通过视频解压算法解压成一张单独的完整的图片;
P frame:需要参考其前面的一个 I frame 或者 B frame 来生成一张完整的图片;
B frame: 则要参考其前一个 I 或者 P帧 及其后面的一个 P 帧来生成一张完整的图片;
pts/dts
名称    意义
PTS(Presentation Time Stamp)    PTS 主要用于度量解码后的视频帧什么时候被显示出来
DTS(Decode Time Stamp)    DTS 主要是标识内存中的 bit 流什么时候开始送入解码器中进行解码


DTS 与 PTS 的不同:
DTS 主要用户视频的解码,在解码阶段使用。PTS主要用于视频的同步和输出,在 display 的时候使用。再没有 B frame 的时候输出顺序是一样的。

2.6、GOP
GOP 是画面组,一个 GOP 是一组连续的画面。
GOP 一般有两个数字,如 M = 3,N = 12,M 制定 I 帧与 P 帧之间的距离,N 指定两个 I 帧之间的距离。那么现在的 GOP 结构是

I BBP BBP BBP BB I
1
增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量,至于怎么取舍,得看需求了。

2.7、IDR
一个序列的第一帧叫做 IDR帧(Instantaneous Decoding Refresh,立即解码刷新)。

I 帧和 IDR 帧都是使用帧内预测,本质上是同一个东西,在解码和编码中为了方便,将视频序列中第一个 I 帧和其他 I 帧区分开,所以把第一个 I 帧称作 IDR,这样就方便控制编码和解码流程。

IDR 帧的作用是立刻刷新,使错误不致传播,从 IDR 帧开始,重新算一个新的序列开始编码。

核心作用
H.264 引入 IDR 帧是为了解码的重同步,当解码器解码到 IDR 帧时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会,IDR 帧之后的帧永远不会使用 IDR 之前的图像的数据来解码。

3、H264 码流分层结构


如上图,在 H264 中,句法元素共被组织成:序列、图像(帧)、片、宏块、子宏块五个层次。

句法元素的分层结构有助于更有效地节省码流。例如,在一个图像中,经常会在各个片之间有相同的数据,如果每个片都同时携带这些数据,势必会造成码流的浪费。更为有效的做法是将该图像的公共信息抽取出来,形成图像一级的句法元素,而在片级只携带该片自身独有的句法元素。

4、NALU Header & RBSP 结构


如上图:NALU = NAL Header + RBSP

4.1、NALU Header
前面已经说到,每个 NALU 由一个字节的 Header 和 RBSP(Raw Byte Sequence Payload) 组成。

NALU Header 由三部分组成,forbidden_bit(1bit),nal_ref_idc(2bits)代表优先级,nal_unit_type(5bits)代表该 NALU 的类型。

forbidden_zero_bit
1 bit,H264 规定此位必须为 0

nal_ref_idc
用于表示当前 NALU 的重要性,值越大,越重要

解码器在解码处理不过来的时候,可以丢掉重要性为 0 的 NALU

nal_ref_idc 不等于 0 时, NAL unit 的内容可能是 SPS/PPS/参考帧 的片
nal_ref_idc 等于 0 时,NAL unit 的内容可能是非参考图像的片
当某个图像的片的 nal_ref_id 等于 0 时,该图像的所有片均应等于 0
nal_unit_type
nal_unit_type 是否包含 VCL 层编码数据分为 VCL NAL units 和 non-VCL NAL units;

VCL NAL units 中包含 VCL 层编码输出的数据, 而 non-VCL NAL units 则不包含。

nal_unit_type    the content of NAL unit
1 ~ 5    VCL NAL units
others(SPS/PPS .etc)    non-VCL NAL units
所有的值对于类型如下:

4.2、RBSP


上图是 RBSP 序列举例

上图是 RBSP 的描述

SODB 与 RBSP
SODB 数据比特串 -> 是编码后的原始数据.
RBSP 原始字节序列载荷 -> 在原始编码数据的后面添加了 结尾比特。一个 bit “1” 若干比特 “0”,以便字节对齐。


--------------------- 
作者:岁月斑驳7 
来源:CSDN 
原文:https://blog.csdn.net/qq_19923217/article/details/83348095 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
h.264视频编解码源代码.rar 详细说明:h.264标准代码,用于视频编码!可以实现各种视频的编码和解码,可以在这个代码的基础上进行各种开发,比如算法的优化,转码技术,实现各种分辨了的转码-h.264 standard code, uses in the video frequency code! May realize each kind of video frequency code and the decoding, may carry on each kind of development in this code foundation, for instance the algorithm optimization, transfers the code technology, realizes each kind has distinguished extension code 文件列表: jm73 ....\JM ....\..\bin ....\..\...\decoder.cfg ....\..\...\encoder.cfg ....\..\...\lencod.exe ....\..\...\lencod.map ....\..\...\lencod.pdb ....\..\CHANGES.TXT ....\..\Changes_detail.txt ....\..\copyright.txt ....\..\disclaimer.txt ....\..\doc ....\..\...\coding_style.doc ....\..\...\doxygen.txt ....\..\...\h26l.css ....\..\...\ldecod.dox ....\..\...\lencod.dox ....\..\encoder.cfg ....\..\foreman_part_qcif.yuv ....\..\ldecod ....\..\......\inc ....\..\......\...\annexb.h ....\..\......\...\biaridecod.h ....\..\......\...\block.h ....\..\......\...\cabac.h ....\..\......\...\context_ini.h ....\..\......\...\contributors.h ....\..\......\...\ctx_tables.h ....\..\......\...\defines.h ....\..\......\...\elements.h ....\..\......\...\erc_api.h ....\..\......\...\erc_do.h ....\..\......\...\erc_globals.h ....\..\......\...\errorconcealment.h ....\..\......\...\fmo.h ....\..\......\...\global.h ....\..\......\...\header.h ....\..\......\...\image.h ....\..\......\...\leaky_bucket.h ....\..\......\...\macroblock.h ....\..\......\...\mbuffer.h ....\..\......\...\mb_access.h ....\..\......\...\memalloc.h ....\..\......\...\nalu.h ....\..\......\...\nalucommon.h ....\..\......\...\output.h ....\..\......\...\parset.h ....\..\......\...\parsetcommon.h ....\..\......\...\rtp.h ....\..\......\...\sei.h ....\..\......\...\vlc.h ....\..\......\Makefile ....\..\......\src ....\..\......\...\annexb.c ....\..\......\...\biaridecod.c ....\..\......\...\block.c ....\..\......\...\cabac.c ....\..\......\...\context_ini.c ....\..\......\...\erc_api.c ....\..\......\...\erc_do_i.c ....\..\......\...\erc_do_p.c ....\..\......\...\errorconcealment.c ....\..\......\...\filehandle.c ....\..\......\...\fmo.c ....\..\......\...\header.c ....\..\......\...\image.c ....\..\......\...\ldecod.c ....\..\......\...\leaky_bucket.c ....\..\......\...\loopFilter.c ....\..\......\...\macroblock.c ....\..\......\...\mbuffer.c ....\..\......\...\mb_access.c ....\..\......\...\memalloc.c ....\..\......\...\nal.c ....\..\......\...\nalu.c ....\..\......\...\nalucommon.c ....\..\......\...\nal_part.c ....\..\......\...\output.c ....\..\......\...\parset.c ....\..\......\...\parsetcommon.c ....\..\......\...\rtp.c ....\..\......\...\sei.c ....\..\......\...\vlc.c ....\..\ldecod.dsp ....\..\ldecod.dsw ... ...
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值