视频编解码在音视频开发中的根底,咱们在了解了编解码后,才能够对视频进行编码、传输、播映、存储、视频的封装宽和封装也是要依赖编解码的,今日让咱们一起学习视频的编码。

视频的发展到今日,视频的编解码还是首要以H264为主,在一些超高清的视频可能运用H265.下面就以H264进行讲解。

根底知识

为什么要编码?

  • 由于视频数据太大,不进行编码传输和存储所在空间都会很大。
  • 视频数据中,有许多冗余数据,把它们去掉人眼也不会发现。

在编码中怎么紧缩数据呢?

  • 帧内猜测紧缩,处理的是空域数据冗余问题。
  • 帧间猜测紧缩(运动估计与补偿),处理的是时域数据冗余问题。
  • 整数离散余弦改换(DCT),将空间上的相关性变为频域上无关的数据然后进行量化。
  • CABAC紧缩。

经过紧缩后的帧:

  • I帧:关键帧,选用帧内紧缩技能。
  • P帧:向前参阅帧,在紧缩时,只参阅前面现已处理的帧。选用帧间紧缩技能。
  • B帧:双向参阅帧,在紧缩时,它即参阅前而的帧,又参阅它后面的帧。选用帧间紧缩技能。

GOP 两个I帧之间是一个图画序列,在一个图画序列中只要一个I帧。如下图所示:

02-视频编码H264基础知识

H264紧缩技能

帧内猜测紧缩

一帧便是对应一个图画,把这个图画区分为许多宏块,再把宏块区分为多个子块,最终对子块进行猜测得到更少的数据。

H264的基本原理其实十分简略,下咱们就简略的描述一下H264紧缩数据的进程。经过摄像头采集到的视频帧(按每秒 30 帧算),被送到 H264 编码器的缓冲区中。编码器先要为每一幅图片区分宏块。 以下面这张图为例:

02-视频编码H264基础知识
区分宏块:H264默许是运用 16X16 巨细的区域作为一个宏块,也能够区分成 8X8 巨细。

02-视频编码H264基础知识
区分好宏块后,核算宏块的像素值。

02-视频编码H264基础知识
以此类推,核算一幅图画中每个宏块的像素值,一切宏块都处理完后如下面的样子。

02-视频编码H264基础知识
继续区分子块:H264对比较平整的图画运用 16X16 巨细的宏块。但为了更高的紧缩率,还能够在 16X16 的宏块上更区分出更小的子块。子块的巨细能够是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4十分的灵活。

02-视频编码H264基础知识
上幅图中,红框内的 16X16 宏块中大部分是蓝色背景,而三只鹰的部分图画被划在了该宏块内,为了更好的处理三只鹰的部分图画,H264就在 16X16 的宏块内又区分出了多个子块。

02-视频编码H264基础知识
这样再经过帧内紧缩,能够得到更高效的数据。下图是分别运用mpeg-2和H264对上面宏块进行紧缩后的成果。其间左半部分为MPEG-2子块区分后紧缩的成果,右半部分为H264的子块划紧缩后的成果,能够看出H264的区分办法更具优势。

02-视频编码H264基础知识

关于这些数据,还能够经过帧内猜测,数据更小。 在帧内猜测形式中,猜测块P是根据已编码重建块和当前块构成的。对亮度像素而言,P块用于44子块或许1616宏块的相关操作。44亮度子块有9种可选猜测形式,独立猜测每一个44亮度子块,适用于带有许多细节的图画编码;1616亮度块有4种猜测形式,猜测整个1616亮度块,适用于平整区域图画编码;色度块也有4种猜测形式,类似于1616亮度块猜测形式。编码器通常挑选使P块和编码块之间差异最小的猜测形式。

下面举个比如,4*4亮度猜测形式 44亮度块的上方和左方像素A~M为已编码和重构像素,用作编解码器中的猜测参阅像素。a~p为待猜测像素,运用A~M值和9种形式实现。其间形式2(DC猜测)根据A~M中已编码像素猜测,而其余形式只要在所需猜测像素悉数提供才能运用。图6.15箭头表明了每种形式猜测方向。对形式3~8,猜测像素由A~M加权平均而得。例如,形式4中,d=round(B/4+C/2+D/4)。

02-视频编码H264基础知识

02-视频编码H264基础知识

02-视频编码H264基础知识

其他的 88 1616 的也差不多,就不在这儿细讲了,感兴趣的小伙伴能够去网上搜素一下,有许多的文章。

帧间猜测紧缩

帧内猜测紧缩处理了空间上数据冗余的问题,帧间紧缩便是处理时刻上数据冗余的问题。其间时刻上的数据冗余是最大的。

为什么说时刻上的冗余是最大的呢?假设摄像头每秒抓取30帧,这30帧的数据大部分状况下都是相相关的。也有可能不止30帧的的数据,可能几十帧,上百帧的数据都是相关特别亲近的。

关于这些相关特别亲近的帧,其实咱们只需要保存一帧的数据,其它帧都能够经过这一帧再按某种规矩猜测出来,所以说视频数据在时刻上的冗余是最多的。

为了到达相关帧经过猜测的办法来紧缩数据,就需要将视频帧进行分组。那么怎么判定某些帧联系亲近,能够划为一组呢?咱们来看一下比如,下面是捕获的一组运动的台球的视频帧,台球从右上角滚到了左下角。

02-视频编码H264基础知识
H264编码器会按顺序,每次取出两幅相邻的帧进行宏块比较,核算两帧的类似度。

02-视频编码H264基础知识
经过宏块扫描与宏块查找能够发现这两个帧的相关度是十分高的。进而发现这一组帧的相关度都是十分高的。因此,上面这几帧就能够区分为一组。其算法是:在相邻几幅图画画面中,一般有差别的像素只要10%以内的点,亮度差值改变不超过2%,而色度差值的改变只要1%以内,咱们以为这样的图能够分到一组。

在这样一组帧中,经过编码后,咱们只保存第一帖的完好数据,其它帧都经过参阅上一帧核算出来。咱们称第一帧为IDR/I帧,其它帧咱们称为P/B帧,这样编码后的数据帧组咱们称为GOP

在H264编码器中将帧分组后,就要核算帧组内物体的运动矢量了。还以上面运动的台球视频帧为例,咱们来看一下它是怎么核算运动矢量的。

H264编码器首要按顺序从缓冲区头部取出两帧视频数据,然后进行宏块扫描。当发现其间一幅图片中有物体时,就在另一幅图的邻近方位(查找窗口中)进行查找。假设此刻在另一幅图中找到该物体,那么就能够核算出物体的运动矢量了。下面这幅图便是查找后的台球移动的方位。

02-视频编码H264基础知识

经过上图中台球方位相差,就能够核算出台图运转的方向和间隔。H264依次把每一帧中球移动的间隔和方向都记载下来就成了下面的样子。

02-视频编码H264基础知识
运动矢量核算出来后,将相同部分(也便是绿色部分)减去,就得到了补偿数据。咱们终究只需要将补偿数据进行紧缩保存,今后在解码时就能够康复原图了。紧缩补偿后的数据只需要记载很少的一点数据。如下所示:

02-视频编码H264基础知识

咱们把运动矢量与补偿称为帧间紧缩技能,它处理的是视频帧在时刻上的数据冗余。除了帧间紧缩,帧内也要进行数据紧缩,帧内数据紧缩处理的是空间上的数据冗余。下面咱们就来介绍一下帧内紧缩技能。

上面啰啰嗦嗦把帧内猜测紧缩和帧间猜测紧缩讲完了。接下来就进入到了用代码完成案例了。

一些名词

帧率: 帧率(Frame Rate)是用于丈量显现帧数的丈量。所谓的丈量单位为每秒显现帧数(frames per second,简称fps)或“赫兹”(Hz)。 每秒显现帧数(fps)或许帧率表明图形处理器处理场时每秒能够更新的次数。高帧率能够得到更流通、更传神的动画。一般来说,30fps便是能够接受的,但是将功能提高至60fps则能够明显提高交互感和传神感,但是超过75fps就不简单发觉有明显的流通度提高了。假设帧率超过屏幕改写率,则只会浪费图画处理能力,由于监视器不能以这么快的速度更新,这样超过改写率的帧率就浪费掉了。

分辨率: 视频分辨率是指视频成像产品所构成的图画巨细或尺度。

改写率 改写率是指屏幕每秒画面被改写的次数,改写率分为笔直改写率和水平改写率,一般说到的改写率通常指笔直改写率。笔直改写率表明屏幕上图画每秒重绘多少次,也便是每秒屏幕改写的次数,以Hz(赫兹)为单位。改写率越高,图画就越稳定,图画显现就越自然清晰,对眼睛的影响也越小。改写率越低,图画闪耀和抖动得就越凶猛,眼睛疲惫得就越快。一般来说,如能到达80Hz以上的改写率,就能够完全消除图画闪耀和抖动感,眼睛也不太简单疲惫。

编码格局 编码的意图是紧缩数据量,选用编码算法紧缩冗余数据。常用的编码格局有如下这两种。

  • MPEG(MPEG-2、MPEG-4)
  • H.26X(H.263、H.264/AVC、H.265/HEVC)

封装格局 把编码后的音视频数据以一定格局封装到一个容器,封装格局有MP4、MKV、AVI、TS等。

码率 码率也便是比特率,比特率是单位时刻播映连续的媒体(如紧缩后的音频或视频)的比特数量。比特率越高,带宽消耗得越多。比特(bit)便是二进制里边最小的单位,要么是0,要么是1。 文件巨细(b)=码率(b/s)时长(s)

此处提出一个问题,是码率越大,画质越好,视频越流通吗?这是错误的说法,实际上视频质量和码率、编码算法都有联系。

DTS: 即Decode Time Stamp,首要用于标示读入内存中的比特流在什么时分开始送入解码器中进行解码。

PTS: 即Presentation Time Stamp,首要用于衡量解码后的视频帧什么时分被显现出来。

YUV: 也被称作YCrCb,是被欧洲电视系统所选用的一种色彩编码办法(归于PAL),是PAL和SECAM模拟彩色电视制式选用的色彩空间模型。其间的Y、U、V几个字母不是英文单词的首字母,其间Y代表亮度,UV代表色差,U和V是构成色彩的两个重量。在Android 里边一般是运用YUV420.

RGB: 是一种色彩空间模型,经过对红(R)、绿(G)、蓝(B)3个色彩通道的改变以及它们相互之间的叠加来得到各式各样的色彩,RGB即代表红、绿、蓝3个通道的色彩。

为什么视频的数据运用YUV 而不是 RGB?

  • 由于YUV 数据更小,拿YUV420举比如

02-视频编码H264基础知识
能够看到运用YUV 数据量少了一半。

H264数据结构

H264编码分层
  • NAL层:(Network Abstraction Layer,视频数据网络笼统层) : 它的作用是H264只要在网络上传输,在传输的进程每个包以太网是1500字节,而H264的帧往往会大于1500字节,所以要进行拆包,将一个帧拆成多个包进行传输,一切的拆包或许组包都是经过NAL层去处理的。
  • VCL层:(Video Coding Layer,视频数据编码层) : 对视频原始数据进行紧缩

H264是一种码流 类似于一种不见头,也不见尾的一条河流。怎么从和流中取到自己想要的数据呢,在H264的标砖中有这样的一个封装格局叫做”Annex-B”的字节省格局。 它是H264编码的首要字节省格局。几乎市面上的编码器是以这种格局进行输出的。起始码0x 00 00 00 01 或许 0x 00 00 01 作为分隔符

两个 0x 00 00 00 01之间的字节数据 是表明一个NAL Unit

02-视频编码H264基础知识

原始的NALU单元组成:[start code] + [NALU header] + [NALU payload];

02-视频编码H264基础知识
NAL Header 的组成为: forbidden_zero_bit(1bit) + nal_ref_idc(2bit) + nal_unit_type(5bit)

  • forbidden_zero_bit:制止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。
  • nal_ref_idc:nal重要性指示,标志该NAL单元的重要性,值越大,越重要,解码器在解码处理不过来的时分,能够丢掉重要性为0的NALU。
  • nal_unit_type:NALU类型取值如下表所示:

02-视频编码H264基础知识

02-视频编码H264基础知识

02-视频编码H264基础知识
看看一个比如:

00 00 00 01 为起始符,67 即 nal_unit_type。
0x67的二进制是 0110 0111forbidden_zero_bit(1bit) = 0nal_ref_idc(2bit) = 3nal_unit_type(5bit) = 7;即 SPS 类型。

通常状况咱们看到的NLAU类型便是SPS、PPS、SEI、IDR的slice、非IDR这几种。

SODB 和 RBSP 联系: SODB(String Of Data Bits):最原始的编码数据RBSP, 长度不一定是8的倍数,此刻需要对齐.  RBSP: 在SODB的后面添加了结束比特(RBSP trailing bits 一个bit“1”)若干比特“0”,以便字节对齐。

02-视频编码H264基础知识

咱们知道码流是由一个个的NAL Unit组成的,NALU是由NALU头和RBSP数据组成,而RBSP可能是SPS,PPS,Slice或SEI,现在咱们这儿SEI不会出现,并且SPS坐落第一个NALU,PPS坐落第二个NALU,其他便是Slice(严谨点区分的话能够把IDR等等再分出来)了。

这其间NALU的RBSP除了能承载实在的视频紧缩数据,还能传输编码器的装备信息,其间能传输视频紧缩数据的为slice。

咱们就能够这样了解:

  • 一个h264 数据由多个NALU组成
  • 一个NALU 有 起始码0x 00 00 01 或0x 00 00 00 01 和 slice 组成
  • 一个slice 便是实在的紧缩数据了,里边有许多宏块的数据
  • 一个宏块数据里边又有 宏块类型、宏块猜测数据和残差数据组成 slice 也有类型:

02-视频编码H264基础知识

H264编码

运用的是哥伦布指数编码。

为什么运用哥伦布编码?

  • 由于音视频的数据许多,但是每个数据量比较小,运用哥伦布编码能够用更少的位数就能表达完好的意思,所以h264选用哥伦布编码的方式。

指数哥伦布码(Exponential-Golomb code, 即Exp-Golomb code)是熵编码的一种编码方式,正常来说,能够拓展位k阶,但是在H264中运用的是0阶指数哥伦布编码,在H.264中运用ue(v)表明0阶无符号指数哥伦布编码的解码进程,用se(v)表明0阶有符号指数哥伦布编码进程。

0阶无符号指数哥伦布编码进程

0阶无符号指数哥伦布编码最终生成的比特串格局为”前缀1后缀”,前缀和后缀的长度是相同的。

假设咱们待编码的数字codeNum = 4,0阶无符号指数哥伦布编码的进程如下:

(1)将数字以二进制写出,4的二进制为100,由于0阶指数哥伦布编码一切不必去掉低位

(2)将上面的二进制+1,100加1为101,留下的比特数为3,3-1=2,一切需要添加前导0的个数为2

(3)由于第一步没有去掉,一切这一步不进行任何操作,终究生成的比特串为00101

0阶指数哥伦布编码能够简化为如下进程

(1)将codeNum+1,4+1=5

(2)将加1后的数字用二进制表明,5的二进制位101,1后缀=101,后缀位01,长度2

(3)前缀与后缀长度相同,在前面加上2个0

下面对不同codeNum进行编码成果

codeNum codeNum+1 codeNum+1的二进制 需补前缀0的个数 编码后的比特串(红色表明补的前缀0)
0 1 1 0 1
1 2 10 1(0) 010
2 3 11 1(0) 011
3 4 100 2(00) 00100
4 5 101 2(00) 00101
5 6 110 2(00) 00110
6 7 111 2(00) 00111

0阶无符号指数哥伦布编码的解析进程如下

(1)找到第一个不为0的bit,并记载总共找到了0的个数(num),这个时分读到的这个bit肯定是1

(2)然后读num个后缀

(3)1后缀转变成十进制便是本来的codeNum,codeNum = (1 <<i) + 后缀(十进制) – 1;

比如比特串的二进制为:00111,首要找到第一个不为0的比特,前面0的个数为2,然后再读2个后缀11,11十进制为3,这个时分codeNum = (1 << 2) + 3 – 1 = 4 + 3 – 1 = 6

总结

  • H264 的紧缩原理
  • 一些名词的解释
  • H264 的数据结构
  • H264 运用 0阶无符号指数哥伦布编码