一、编码基础概念

1、为什么要进行视频编码?

视频是由一帧帧图像组成,就如常见的gif图片,如果打开一张gif图片,可以发现里面是由很多张图片组成。一般视频为了不让观众感觉到卡顿,一秒钟至少需要16帧画面(一般是30帧),假如该视频是一个1280x720分辨率的视频,那么不经过编码一秒钟的大小:

结果:1280x720x60≈843.75M

所以不经过编码的视频根本没法保存,更不用说传输了。

2、视频压缩编码标准

视频中存在很多冗余信息,比如图像相邻像素之间有较强的相关性,视频序列的相邻图像之间内容相似,人的视觉系统对某些细节不敏感等,对这部分冗余信息进行处理的过程就是视频编码。

H.26X系列(由ITU[国际电传视讯联盟]主导)H.261:主要在老的视频会议和视频电话产品中使用H.263:主要用在视频会议、视频电话和网络视频上H.264:H.264/MPEG-4第十部分,或称AVC(Advanced Video Coding,高级视频编码),是一种视频压缩标准,一种被广泛使用的高精度视频的录制、压缩和发布格式。H.265:高效率视频编码(High Efficiency Video Coding,简称HEVC)是一种视频压缩标准,H.264/MPEG-4 AVC的继任者。可支持4K分辨率甚至到超高画质电视,最高分辨率可达到8192×4320(8K分辨率),这是目前发展的趋势,尚未有大众化编码软件出现MPEG系列(由ISO[国际标准组织机构]下属的MPEG[运动图象专家组]开发)MPEG-1第二部分:MPEG-1第二部分主要使用在VCD上,有些在线视频也使用这种格式MPEG-2第二部分(MPEG-2第二部分等同于H.262,使用在DVD、SVCD和大多数数字视频广播系统中MPEG-4第二部分(MPEG-4第二部分标准可以使用在网络传输、广播和媒体存储上

3、编码流程
在进行当前信号编码时,编码器首先会产生对当前信号做预测的信号,称作预测信号(predicted signal)

预测的方式:

    时间上的预测(interprediction),亦即使用先前帧的信号做预测空间上的预测 (intra prediction),亦即使用同一张帧之中相邻像素的信号做预测

得到预测信号后,编码器会将当前信号与预测信号相减得到残余信号(residual signal),并只对残余信号进行编码,如此一来,可以去除一部份时间上或是空间上的冗余信息。

编码器并不会直接对残余信号进行编码,而是先将残余信号经过变换(通常为离散余弦变换)然后量化以进一步去除空间上和感知上的冗余信息。量化后得到的量化系数会再透过熵编码,去除统计上的冗余信息。

二、H.264编码详解(AVC)

1、H.264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称

相关理解:在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像帧A,随后的B帧就不编码全部图像,只写入与A帧的差别,这样B帧的大小就只有完整帧的1/10或更小!B帧之后的C帧如果变化不大,我们可以继续以参考B的方式编码C帧,这样循环下去。这段图像我们称为一个序列:序列就是有相同特点的一段数据当某个图像与之前的图像变化很大,无法参考前面的帧来生成,那我们就结束上一个序列,开始下一段序列也就是对这个图像生成一个完整帧A1,随后的图像就参考A1生成,只写入与A1的差别内容

2、H.264三种帧

在H.264中定义了三种帧:
    I帧:完整编码的帧叫I帧
    P帧:参考之前的I帧生成的只包含差异部分编码的帧叫P帧
    B帧:参考前后的帧编码的帧叫B帧

H264采用的核心算法是帧内压缩和帧间压缩:
    帧内压缩是生成I帧的算法
    帧间压缩是生成B帧和P帧的算法

压缩方法:
    分组:把几帧图像分为一组(GOP,也就是一个序列),为防止运动变化,帧数不宜取多
    定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;
    预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;
    数据传输:最后将I帧数据与预测的差值信息进行存储和传输。

GOP序列:
    在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流。
    一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像:

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

    一个序列就是一段内容差异不太大的图像编码后生成的一串数据流:

a、当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个I帧,然后一直P帧、B帧了。
b、当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。

在视频编码序列中,GOP即Group of picture(图像组),指两个I帧之间的距离。

帧、P帧、B帧实际顺序&&编码顺序:

CSDN站内私信我,领取最新最全C++音视频学习提升资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)

三、H.264分层设计

H264算法在概念上分为两层:
    VCL:(Video Coding Layer)视频编码层,负责高效的内容表示。
    NAL:(Network Abstraction Layer)网络提取层,负责以网络所要求的恰当的方式对数据进行打包和传送。
    上面所学习的知识都是VCL层。

NAL设计的目的,是根据不同的网络把数据打包成相应的格式,将VCL产生的比特字符串适配到各种各样的网络和多元环境中。

NAL的封装方式:
    NAL是将每一帧数据写入到一个NAL单元中,进行传输或存储的
    NALU分为NAL头和NAL体
    NALU头通常为00 00 00 01,作为一个新的NALU的起始标识
    NALU体封装着VCL编码后的信息或者其他信息

NAL的封装过程:
    I帧、P帧、B帧都是被封装成一个或者多个NALU进行传输或者存储的
    每一个I帧开始之前也有非VCL的NAL单元,用于保存其他信息,它们是PPS、SPS
    PPS(Picture Parameter Sets):图像参数集
    SPS(Sequence Parameter Set):序列参数集
    在实际的H264数据帧中,往往帧前面带有00 00 00 01 或 00 00 01分隔符,一般来说编码器编出的首帧数据为PPS与SPS,接着为I帧,后续是B帧、P帧等数据

首先来一段大家都熟悉的官方话来介绍一下 H.264

H.264: H.264/AVC项目的目的是为了创建一个比以前的视频压缩标准,在更低的比特率的情况下依然能够提供良好视频质量的标准(如,一半或者更少于MPEG-2,H.263,或者MPEG-4 Part2 )。同时,还要不会太大的增加设计的复杂性。
优势:
1)网络亲和性,即可适用于各种传输网络
2)高的视频压缩比,当初提出的指标是比 H.263,MPEG-4,约为它们的 2 倍,现在都已基 实现;

那么很明显,什么时候需要到压缩呢?

当然是文件体积太大的时候啦,我们想想,所谓的视频,就是像小时候的连环画一样,在一秒内翻过 24 张以上的图片,就感觉图像是连续的了,这就是视频的原理。

但是大家有没有想过,一张图片有多大呢?

我们的屏幕分辨率按 1280 * 720 算的话,一秒钟的视频大概就 2.64 MB 了,大家想想,我们大部分的小伙伴为了下载个小嗨片省吃俭用才开了个 1M 的网线,然后连个直播都看不了是什么感觉。那肯定不能这样了,所以我们要进行压缩,而 H.264 不仅压缩比比较高,对网络的兼容性也非常好,所以大多数人做直播也就选择了 H.264 作为编码格式了。

编码流程:

那么 H.264 其编解码流程是怎么样的呢?其实可以主要分为 5 部分: 帧间和帧内预测(Estimation)、变换(Transform)和反变换、量化(Quantization)和反量化、环路滤波(Loop Filter)、熵编码(Entropy Coding)。

看起来很高深的样子,实际上也是很高深的样子,因为这里面包含着许许多多的算法和专业知识,这里我们就不做过多的讲解,有兴趣的同学可以自己研究研究。

原理简介

H.264 原始码流(又称为裸流),是有一个接一个的 NALU 组成的,而它的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL, Network Abstraction Layer)。
VCL 数据即编码处理的输出,它表示被压缩编码后的视频数据 序列。在 VCL 数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元(以下简称 NALU,Nal Unit) 中。每个 NALU 包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组 对应于视频编码的 NALU 头部信息。RBSP 的基本结构是:在原始编码数据的后面填加了结尾 比特。一个 bit“1”若干比特“0”,以便字节对齐。

NAL 单元排列

上图中的 NALU头 + RBSP 就相当与一个 NALU (Nal Unit), 每个单元都按独立的 NALU 传送。 其实说白了,H.264 中的结构全部都是以 NALU 为主的,理解了 NALU,就理解 H.264 的结构了。

一帧图片跟 NALU 的关联 :

究竟 NALU 是怎么由一帧图片变化而来的呀,H.264究竟为什么这么神奇?

一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了,我们可以来看看 NALU 跟片的关系(slice)。

图片编码后

NALU 结构

小伙伴们要明白,片(slice)的概念不同与帧(frame),帧(frame)是用作描述一张图片的,一帧(frame)对应一张图片,而片(slice),是 H.264 中提出的新概念,是通过编码图片后切分通过高效的方式整合出来的概念,一张图片至少有一个或多个片(slice)。

上图中可以看出,片(slice)都是又 NALU 装载并进行网络传输的,但是这并不代表 NALU 内就一定是切片,这是充分不必要条件,因为 NALU 还有可能装载着其他用作描述视频的信息。

什么是切片(slice)?

片的主要作用是用作宏块(Macroblock)的载体(ps:下面会介绍到宏块的概念)。片之所以被创造出来,主要目的是为限制误码的扩散和传输。

如何限制误码的扩散和传输?

每个片(slice)都应该是互相独立被传输的,某片的预测(片(slice)内预测和片(slice)间预测)不能以其它片中的宏块(Macroblock)为参考图像。

我们可以理解为一 张/帧 图片可以包含一个或多个分片(Slice),而每一个分片(Slice)包含整数个宏块(Macroblock),即每片(slice)至少一个 宏块(Macroblock),最多时每片包 整个图像的宏块。

上图结构中,我们不难看出,每个分片也包含着头和数据两部分:

  1. 分片头中包含着分片类型、分片中的宏块类型、分片帧的数量、分片属于那个图像以及对应的帧的设置和参数等信息。
  2. 分片数据中则是宏块,这里就是我们要找的存储像素数据的地方。

什么是宏块?

宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列
组成部分:

  • 一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个 8×8 Cr 彩色像素块组成。
  • 每个图象中,若干宏块被排列成片的形式。

从上图中,可以看到,宏块中包含了宏块类型、预测类型、Coded Block Pattern 编码的块模式、Quantization Parameter 量化参数、像素的亮度和色度数据集等等信息。

切片(slice)类型跟宏块类型的关系

I片:只包 I宏块,I 宏块利用从当前片中已解码的像素作为参考进行帧内预测(不能取其它片中的已解码像素作为参考进行帧内预测)。

P片:可包 P和I宏块,P 宏块利用前面已编码图象作为参考图象进行帧内预测,一个帧内编码的宏块可进一步作宏块的分割:即 16×16、16×8、8×16 或 8×8 亮度像素块(以及附带的彩色像素);如果选了 8×8 的子宏块,则可再分成各种子宏块的分割,其尺寸为 8×8、8×4、4×8 或 4×4 亮度像素块(以及附带的彩色像素)。

B片:可包 B和I宏块,B 宏块则利用双向的参考图象(当前和 来的已编码图象帧)进行帧内预测。

SP片(切换P):用于不同编码流之间的切换,包含 P 和/或 I 宏块

SI片:扩展档次中必须具有的切换,它包 了一种特殊类型的编码宏块,叫做 SI 宏块,SI 也是扩展档次中的必备功能。

H264的格式

H.264的两种打包/封装方法:字节流AnnexB格式 和 AVCC格式 (只有这两种)

在H264用于网络发送时,要封装成RTP格式!!!

(一)AnnexB格式---用于实时播放

1.AnnexB流结构:使用start code分隔NAL(start code为三字节或四字节,0x000001或0x00000001,一般是四字节);SPS和PPS按流的方式写在头部。

开始前缀(00000001或000001)+ NALU数据  绝大部分编码器的默认输出格式

NALU 就是 h264的实际数据部分。NALU = NALUHeader+EBSP 组成; EBSP = 防止竞争码+RBSP; RBSP = SODB + RBSP尾部 。

EBSP为扩展字节序列载荷(Encapsulated Byte Sequence Payload) EBSP = RBSP插入防竞争字节(0x03

RBSP为原始字节序列载荷(Raw Byte Sequence Payload)-------- RBSP = SODB + RBSP Trailing Bits(RBSP尾部补齐字节);引入RBSP Trailing Bits做8位字节补齐。
SODB为原始数据比特流 (String Of Data Bits)   -------   就是最原始的编码/压缩得到的数据。

H264码流结构:(下面两种表示都不错)

一共有两种起始码start_code:

  1. 3字节0x000001  单帧多slice(即单帧多个NALU)之间间隔
  2. 4字节0x00000001 帧之间,或者SPS、PPS等之前

4字节类型的起始码在连续的数据传输中非常有用,因为用字节来对齐、分割流数据,比如:用连续的31个bit 0 后接一个bit 1 来分割流数据,是很容易的。

如果接下来的bit是0(因为每个NALU都以bit0开始),那么这就是一个NALU包数据的起始位置了。4字节类型的开始码通常只用于标识流中的随机访问点,如SPS PPS AUD和IDR,然后其他地方都用3字节类型的开始码以减少数据量

防止竞争字节(0x03):前面讲到用StartCode的字节串来分割NALU,于是问题来了,如果RBSP中也包括了StartCode(0x000001或0x00000001)怎么办呢?所以,就有了防止竞争字节(0x03):

编码时,扫描RBSP,如果遇到连续两个0x00字节,就在后面添加防止竞争字节(0x03);
解码时,同样扫描EBSP,进行逆向操作即可。

编码如下:

解码操作:

在解码的时候如果在内部遇到0x000003序列时,就可以将其抛弃即可以恢复原始数据。EBSP 去除防止竞争码后就可以得到 RBSP。

NALU Header

上面是截取的 NAL 层的语法头部部分。如果先不考虑语法,可以先如下理解,将第一个字节(1+2+5 正好是一个字节)按 bits 展开。

  • 第一位为 forbidden_zero_bit forbidden_zero_bit禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。
  • 后两位为 nal_ref_idc nal_ref_idc 代表 NALU 的重要性。值越大说明约重要。取值范围0~3,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。当前的 NAL 是参考帧,序列集参数集或图像集重要数据时必须大于0。
  • 最后五位为 nal_unit_type 指的是当前 NAL 的类型。

1-4:I/P/B帧,合起来介绍的原因是,他们是依据VLC的slice区分的,这块因为本文不涉及,一方面是这个太过于细节,真要展开篇幅太长;另一个原因是就算不了解slice、macroblock也不影响对H264格式的理解。

5:IDR帧。I帧的一种,告诉解码器,之前依赖的解码参数集合(接下来要出现的SPS\PPS等)可以被刷新了。

6:SEI,英文全称Supplemental Enhancement Information,翻译为“补充增强信息”,提供了向视频码流中加入额外信息的方法。

7:SPS,全称Sequence Paramater Set,翻译为“序列参数集”。SPS中保存了一组编码视频序列(Coded Video Sequence)的全局参数。因此该类型保存的是和编码序列相关的参数。

8: PPS,全称Picture Paramater Set,翻译为“图像参数集”。该类型保存了整体图像相关的参数。

9:AU分隔符,AU全称Access Unit,它是一个或者多个NALU的集合,代表了一个完整的帧。

根据以上字段:判断类型

例如上面00000001后有67,68以及65:

其中0x67的二进制码为:0110 0111

4-8为00111,转为十进制7,参考第二幅图:7对应序列参数集SPS

其中0x68的二进制码为:0110 1000

4-8为01000,转为十进制8,参考第二幅图:8对应图像参数集PPS

其中0x65的二进制码为:0110 0101

4-8为00101,转为十进制5,参考第二幅图:5对应IDR图像中的片(I帧)

其中0x41的二进制码为:0100 0001

4-8为00001,转为十进制1,参考第二幅图:1对应非IDR图像中的片(这里指的是P帧)

其中0x61的二进制码为:0110 0001

4-8为00001,转为十进制1,参考第二幅图:1对应非IDR图像中的片(同上,为P帧,仅仅是重要性不同)

其中0x06的二进制码为:0000 0100

4-8为00100,转为十进制6,参考第二幅图:6对应SEI

特殊的NALU类型:SPS和PPS

SPS和PPS存储了编解码需要一些图像参数。

AnnexB格式每个NALU都包含起始码,且通常会周期性的在关键帧之前重复SPS和PPS (在I帧之前)

所以解码器可以从视频流随机点开始进行解码,实时的流格式

I/P/B帧:

I帧(帧内编码帧)是一种自带全部信息的独立帧无需参考其它图像便可独立进行解码。可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)

视频序列中的第一个帧始终都是I帧。
如果所传输的比特流遭到破坏,则需要将I帧用作新查看器的起始点或重新同步点
I帧可以用来实现快进、快退以及其它随机访问功能。
1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
2.解码时仅用I帧的数据就可重构完整图像;
3.I帧描述了图像背景和运动主体的详情;
4.I帧不需要参考其他画面而生成;
5.I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
6.I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
7.I帧不需要考虑运动矢量;
8.I帧所占数据的信息量比较大。

P帧(帧间预测编码帧)需要参考前面的I帧和/或P帧的不同部分才能进行编码。

与I帧相比,P帧通常占用更少的数据位,但其缺点是,由于P帧对前面的P和I参考帧有着复杂的依赖性,因此对传输错误非常敏感
P帧属于前向预测的帧间编码,它只参考 前面最靠近它 的I帧或者P帧
P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。
在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。

1.P帧是I帧后面相隔1~2帧的编码帧;
2.P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
3.解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
4.P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
5.P帧可以是其后面P帧的参考帧,也可以是其 前后 的B帧的参考帧;
6.由于P帧是参考帧,它可能造成解码错误的扩散;
7.由于是差值传送,P帧的压缩比较高

B帧:双向预测内插编码帧。

B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),
换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累
1.B帧是由 前面的I或P帧 和 后面的P帧 来进行预测的;
2.B帧传送的是它与前面的I或P帧和后面的P帧之间预测误差及运动矢量;
3.B帧是双向预测编码帧;
4.B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;
5.B帧不是参考帧,不会造成解码错误的扩散。

I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。

AU分隔:

一个单独的NALU包、或者甚至一个VCL NALU包都不意味着是一个独立的帧,一帧数据可以被分割成几个NALU,一个或多个NALU组成了一个Access Units(AU),AU包含了一个完整的帧。把帧分割成几个独立的NALU需要耗费许多CPU资源,所以分割帧数据并不经常使用。实际上AU分隔不常用。

NALU Body 由NALU = NALUHeader+EBSP可以知道Body=EBSP;

EBSP = 防止竞争码+RBSP;
RBSP = SODB + RBSP尾部 。

去掉防竞争码后,我们得到了 RBSP。下一步就是如何从 RBSP 中获取原始的编码数据SODP(String Of Data Bits)。

对于 RBSP 尾部分成两种类型:

(1)RBSP尾部:其中大多数类型(非1-5)的NALU,使用这种尾部。

rbsp_stop_one_bit 停止位 占1个比特位,值为1
rbsp_alignment_zero_bit 值为0,目的是为了进行字节对齐,占据若干比特位,用若干个0bits对齐,用来补齐这个字节

所以RBSP就等于,SODB在它的最后一个字节的最后一个比特后,紧跟值为1的1个比特,然后增加若干比特的0,以补齐这个字节。

(2)条带RBSP尾部 :另一种尾部,就是当NALU类型为条带时,也即nal_unit_type等于1~5时,这时RBSP使用下面这种尾部

可以看到,rbsp_slice_trailing_bits()默认情况下,就是上面介绍的第一种尾部
只是当entropy_coding_mode_flag值为1,也即当前采用的熵编码为CABAC,而且more_rbsp_trailing_data()返回为true,也即RBSP中有更多数据时,添加一个或多个0x0000。

所以我们拿到RBSP,只需要按照上述语法,去掉RBSP的尾部,就可以得到SODB。然后就可以对照对应类型的NALU的句法,解析出语法元素的值。

AVCC---用于存储

另一个存储H.264流的方式是AVCC格式,在这种格式中,每一个NALU包都加上了一个指定其长度(NALU包大小)的前缀(in big endian format大端格式),这种格式的包非常容易解析,但是这种格式去掉了Annex B格式中的字节对齐特性,而且前缀可以是1、2或4字节,这让AVCC格式变得更复杂了,指定前缀字节数(1、2或4字节)的值保存在一个头部对象中(流开始的部分),这个头通常称为’extradata’或者’sequence header’(重点)

1.AVCC格式了解:使用NALU长度(固定字节,通常为4字节,取决于头部的NALULengthSizeMinusOne字段)分隔NAL;在头部包含extradata(或sequence header)的结构体。(extradata包含分隔的字节数、SPS和PPS)

解码器配置参数在一开始就配置好了(所以我们不能像视频网站中的实时播放一样可以在中间修改参数,比如:帧率,画面),系统可以很容易的识别NALU的边界,不需要额外的起始码,减少了资源的浪费,同时可以在播放时调到视频的中间位置。
这种格式通常被用于可以被随机访问的多媒体数据。如存储在硬盘的文件:MP4、MKV通常用AVCC格式来存储

AVCC格式不使用起始码(start code)作为NALU的分界,这种格式在每个NALU前都加上一个大端格式的前缀(1、2、4字节,代表NALU长度)

所以在解析AVCC格式的时候需要将指定的前缀字节数的值保存在一个头部对象中,这个都通常称为extradata或者sequence header。同时,SPS和PPS数据也需要保存在extradata或者叫’sequence header’中。

  • 视频开始有extradata,包含SPS,PPS
  • 每个NALU前有存储NALU的长度,

2.先分析头部extradata,获取SPS、PPS以及NALULengthSizeMinusOne字段信息

1.其中 extradata 前4字节无用,跳过即可。

2.第5个字节:前6位保留,全部置为1,即('111111'b);后两位NALULengthSizeMinusOne字段用于告诉我们NALU前缀大小

值=0 对应前缀1字节 对应每个NALU包最大长度255字节
  值=1 对应前缀2字节 对应每个NALU包最大长度64K
  值=3 对应前缀4字节 使用最多

3.第6个字节:前3位保留,全部置为1,即('111'b);后5位用于存放SPS NALU的个数(通常为1个)

4.取决于第6个字节中指定的SPS NALU个数,开始进行循环获取SPS数据:

接下来获取两个字节采用两个字节,作为前缀指示接下来的一个SPS NALU的大小"N"(字节数)。每次获取一个SPS NALU单元数据,都需要先获取其前缀信息

接下来获取N个字节获取SPS的数据

5.获取全部SPS数据后,开始获取PPS数据,获取1个字节,内部存放了PPS NALU单元的个数(通常为1个)

6.取决于前1个字节中指定的PPS NALU个数,开始进行循环获取PPS数据:

接下来获取两个字节采用两个字节,作为前缀指示接下来的一个PPS NALU的大小"N"(字节数)。每次获取一个PPS NALU单元数据,都需要先获取其前缀信息

接下来获取N个字节获取PPS的数据

SPS和PPS被存储在了非NALU包中(out of band带外),即独立于基本流数据。 这些数据的存储和传输是文件容器的任务,超出了本文的范畴。

3.AVCC流结构

AVCC中的NALU格式,与AnnexB格式一致。当我们将AVCC转AnnexB时,如果检测到NALU Type = 5关键帧,那么在关键帧前面加上SPS NALU和PPS NALU即可。

虽然AVCC格式不使用起始码,防竞争字节还是有的。所以我们在转换AVCC与AnnexB格式的时候,不用考虑防竞争字节。因为NALU内部是一致的。

H264编码基础概念+格式分析相关推荐

  1. 【音视频】H264编码基础

    H264编码基础 0x1 基本介绍 视频是由一帧帧图像组成,视频为了不卡顿,一秒钟至少要16帧画面,但是图片内容太大,传输不现实.因此需要对他们编码. 官方文档:http://www.itu.int/ ...

  2. Android音视频【一】H264编码基础

    人间观察 岁月催人,时间过的太快了 音视频编码解码就是指通过特定的压缩/解压技术,将某个音视频格式的数据转换为另一种音视频格式数据.目前在Android中的音视频用的最多的就是H264+aac的方式进 ...

  3. 【开源项目】使用FFMPEG解析H264编码为YUV格式

    头文件 #pragma once#ifndef _VIDEO_DECODING_HEADER_ #define _VIDEO_DECODING_HEADER_#define INBUF_SIZE 40 ...

  4. 看完就懂的《H264编码原理及框图》

    H264编码原理及框图 ------------ 分析H264原理: H264是新一代的编码标准,以高压缩高质量和支持多重网络的流媒体著称,在编码上,主要是以下理解:参照一段时间内图像的统计结果表明, ...

  5. H.264编码基础知识详解

    一.编码基础概念 1.为什么要进行视频编码? 视频是由一帧帧图像组成,就如常见的gif图片,如果打开一张gif图片,可以发现里面是由很多张图片组成.一般视频为了不让观众感觉到卡顿,一秒钟至少需要16帧 ...

  6. 直播一:H.264编码基础知识详解

    一.编码基础概念 1.为什么要进行视频编码? 视频是由一帧帧图像组成,就如常见的gif图片,如果打开一张gif图片,可以发现里面是由很多张图片组成.一般视频为了不让观众感觉到卡顿,一秒钟至少需要16帧 ...

  7. H264编码器5( x264源代码简单分析:x264_slice_write() 与H264 编码简介)

    x264源代码简单分析:x264_slice_write() 来自:https://blog.csdn.net/leixiaohua1020/article/details/45536607 H264 ...

  8. H264编码 封装成MP4格式 视频流 RTP封包

    From:http://www.cnblogs.com/ghw-NO1/archive/2012/08/28/2660848.html 一.概述 本文讲述的是对H264编码且封装成MP4格式的视频流进 ...

  9. Exynos4412 IIC总线驱动开发(一)—— IIC 基础概念及驱动架构分析

    关于Exynos4412 IIC 裸机开发请看 :Exynos4412 裸机开发 -- IIC总线 ,下面回顾下 IIC 基础概念 一.IIC 基础概念 IIC(Inter-Integrated Ci ...

  10. Exynos4412 IIC总线驱动开发(一)—— IIC 基础概念及驱动架构分析 (iic驱动框架,i2c驱动框架)...

    转载于 : http://blog.csdn.net/zqixiao_09/article/details/50917655 关于Exynos4412 IIC 裸机开发请看 :Exynos4412 裸 ...

最新文章

  1. matlab单元数组与结构体的区别,MATLAB中的结构体和单元数组
  2. 桌面程序explorer_备份Internet Explorer 7搜索提供程序列表
  3. redis-配置主从-实际操作-over
  4. 计算与推断思维 十七、更新预测
  5. matches php,PHP 正则表达式 推荐
  6. 一个令你颤抖的flutter动画:Basic Animations
  7. Excel填充日期和星期
  8. 凯撒密码的超详细讲解
  9. 联想微型计算机怎么进入bios,联想笔记本怎么进入bios 电脑屏幕上出现Lenovo并
  10. 加密狗复制,破解,备份,模拟,OEM ,写狗工具开发
  11. 苹果手机一直显示搜索服务器,苹果手机safari浏览器搜索页面没有了
  12. MM 移动类型-入门篇
  13. debug——程序停止正常工作
  14. OpenERP 7.0入门(一):安装及开发环境部署
  15. 网站实用性是这样建出来的
  16. java获取jira上的任务
  17. win系统cpu温度获取
  18. 更换服务器IP有哪些步骤?如何操作?
  19. IBM PC机是一台什么计算机,PC机是什么类型的计算机
  20. 兆芯服务器芯片,兆芯 ZX-200 IO扩展芯片

热门文章

  1. Cipher文件加密
  2. 拯救我们的健康:戒烟应用大盘点
  3. 2021京东商城APP手机模板 HTML+CSS+JavaScript
  4. 深入浅出dev、test、pre、pro四大环境
  5. 【信息系统项目管理师】第一章 信息系统综合知识(考点汇总篇)
  6. java sync 实现原理_JAVA 同步实现原理
  7. 活动报名场地预约自定义表单小程序开发
  8. taskctl控制容器之定时器个人理解
  9. 取消android所有动画,android – 动画取消动画
  10. ArcGIS教程 - 8 空间数据拓扑处理