H.264编码基础

643 阅读11分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 >>

前言

本文介绍了曾经自学H.26编码格式的所学所得,分享给大家。

图像的概念

  • 视频是由图像组成,为了传输被压缩
  • 图像由像素组成,像素由RGB组成
  • 分辨率:横向的像素点,纵向的像素点 常见宽高比:16:9/4:3
  • 帧率:每秒采集/播放的图像个数
  • 码率:单位时间内所有帧数据的大小之和

未编码视频的RGB码流

RGB码流 = 分辨率(宽×高)×3(byte)×帧率

ex:1280×720×3×25=69120000约等于69M

由于我们常说的流是按位为单位 所以乘8

69×8=552M

YUV

  • YUV:Y代表明亮度,UV的作用是描述影像色彩及饱和度(仅有Y就能播放,播放的为黑白)
  • 主要的采样格式:YUV4:2:0(最基础 所有播放器基本都支持)/YUV4:2:2/YUV4:4:4
  • 展示YUV

  • RGB与YUV的关系
    • RGB用于屏幕图像的显示
  • Yuv用于采集与编码
  • 对于图像显示器来说,它是通过RGB模型来显示图像的,⽽在传输图像数据时⼜是使⽤YUV模型,这是因为YUV模型可以节省带宽。因此就需要采集图像时将RGB模型转换到YUV模型,显示时再将YUV模型转成RGB
  • RGB转YUV
    • Y=0.299×R+0.587×G+0.114×B
  • U=-0.147×R-0.289×G+0.436×B
  • V=0.615×R-0.515×G-0.100×B
  • YUV转RGB
    • R = Y+1.140×V
  • G= Y-0.394×U - 0.581×V
  • B = Y+2.031×U
  • YUV常见格式

  • YUV存储格式(4:2:0)

H.264

GOP

什么是GOP?

在视频编码序列中,GOP即Group of picture(图像组),一个图像组内摄像机或者镜头它都没有发生大的变化,GOP也指两个I帧之间的距离,Reference(参考周期)指两个P帧之间的距离

  • 相同组强相关 不同组是不相关的

H.264中的I帧P帧B帧

  • I帧:关键帧,采用帧内压缩技术。IDR帧属于I帧,I帧不一定是IDR帧
  • P帧:向前参考帧,压缩时只参考前面已经处理的帧,采用帧间压缩技术,它占I帧一半大小(差别帧)

  • B帧:双向参考帧率压缩时即参考前面已处理的帧也参考后面的帧,使用帧间压缩技术占I的1/4大小(占用cpu耗时多,实时通讯不使用因为容易造成卡顿)

注:一个I帧所占用的字节数大于一个P帧,一个P帧所占用的字节数大于一个B帧,在码率不变的前提下,GOP值越大,P、B帧的数量会越多,平均每个I、P、B帧所占用的字节数就越多,也就更容易获取较好的图像质量;Reference越大,B帧的数量越多,同理也更容易获得较好的图像质量。但是,通过提高GOP值来提高图像质量是有限度的,在遇到场景切换的情况时,H.264编码器会自动强制插入一个I帧,此时实际的GOP值被缩短了。另一方面,在一个GOP中,P、B帧是由I帧预测得到的,当I帧的图像质量比较差时,会影响到一个GOP中后续P、B帧的图像质量,直到下一个GOP开始才有可能得以恢复,所以GOP值也不宜设置过大。

IDR帧与I帧的区别和联系

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

帧与分组的关系

image-20211227154140878

在解码过程中需要先解码I帧后解码P帧再根据IP进行解码B帧

在解码完成播放过程中按照IBP顺序播放

SPS与PPS

SPS/PPS实际上就是存储GOP的参数

  • SPS 序列参数集
  • PPS 图像参数集
  • 他们在IDR帧前成对出现
  • 一组帧之前我们首先收到的是SPS/PPS数据.如果没有这组参数的话,我们无法解码.

视频花屏卡顿原因

花屏是因为你丢了P帧或者I帧,导致解码错误. 而卡顿是为了防止花屏,将整组错误的GOP数据扔掉了.直达下一组正确的GOP再重新刷屏.而这中间的时间差,就是我们所感受的卡顿.

宏块

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

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

划分好宏块后,计算宏块的像素值。

以此类推,计算一幅图像中每个宏块的像素值,所有宏块都处理完后如下面的样子。

H264对比较平坦的图像使用 16X16 大小的宏块。但为了更高的压缩率,还可以在 16X16 的宏块上更划分出更小的子块。子块的大小可以是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4非常的灵活。

H264压缩技术

有损压缩技术

  • 帧内压缩率解决空域数据冗余问题(将不必要的数据全部去掉)
    • 相邻像素差别不大,所以根据宏块预测
  • 人对亮度的敏感度超过色度
  • YUV很容易将亮度和色度分开
  • H264以宏块为基础,进行帧内预测,有九种帧内预测方式,H.264会自动选择哪种预测方式更接近真实结果。标注预测的模式类别,后续再根据类别进行处理还原数据。

帧内预测后的图像与原始图像的对比如下:

将原始图像与帧内预测后的图像相减得残差值。

  • 帧间压缩技术解决的是时域数据冗余问题(根据前一帧进行压缩也是有损压缩)
    • 参考帧:后面的帧参考前面的帧进行编码

  • 如上图相邻的三帧,第一张是I帧的话,图像编码时只要将望远镜部分分割成很小的宏块,根据宏块匹配方法找到第二张图像对应的宏块(宏块匹配),求出运动矢量。
  • 运动估计(宏块匹配+运动矢量)通过宏块匹配的方法找到运动矢量,宏块匹配是方法手段,目的是找到运动矢量。

  • 如图将一张图划分成很多的小宏快,抽出相邻的两帧,记录前一帧小球的宏块(坐标位置),逐行扫描查找相邻帧的宏块,找相似度最高的宏块认为是同一个宏块记录下它的坐标,与原始坐标对比记录距离和方向,就这样记录了台球宏块的运动矢量。
  • 每一个帧进行宏块匹配,求出运动矢量,所有帧的矢量和就还原了小球的运动轨迹,这就是运动估计。如下图;

  • 我们只要存储台球的运动矢量和一小部分背景数据,之外,宏块的匹配中还是有些误差的,上一张图片与下一张图片对应的宏块还是有些误差和损耗的,因此要存一些残差值(运动补偿),如下;
  • 运动补偿(解码找到残差值)

  • 因此真正传的压缩数据是运动矢量与宏块的残差值,后边到了解码时根据运动矢量复原,然后根据残差值补全。

无损压缩技术

在经过有损压缩后,H.264认为还不够小,所以会使用无损压缩技术再次进行压缩。

  • 整数离散余弦变换(DCT)将空间上的相关性变为频域上无关的数据然后进行量化(无损压缩)
    • 傅里叶里面说任何信号都可以有多个不同振幅和频率的正弦波或者余弦波信号叠加而成,

如果采用的是余弦的话那就叫CT变换( Cosine Transform),如果输入信号是离散(Discrete )的,那么就叫DCT变换。

  • H264将残差值进行DCT变换进行进一步压缩
  • 将残差宏块数字化后如图所示

  • 将残差数据宏块进行 DCT 转换

  • 由此我们可以看见有关联的数据集中在一角,其余位置填0补充
  • CABAC压缩(无损压缩)

H264码流

压缩处理后 输出的就是码流文件,可以保存为一个多媒体文件也可以进行网络传输

H.264原始码流(裸流)是由⼀个接⼀个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(⽹络提取层)

  • NAL层:视频数据网络抽象层,防止了丢包乱序重复,接收端能检查出来是否丢包乱序等(用于网络传输)
  • VCL层:视频数据编码层

NALU结构单元的主体结构如下所示;⼀个原始的H.264 NALU单元通常由[StartCode] [NALU Header] [NALU Body]三部分组成,其中 Start Code ⽤于标示这是⼀个NALU 单元的开 始,必须是"00 00 00 01" 或"00 00 01",除此之外基本相当于⼀个NAL header + RBSP:

码流基本概念

  • SODB 原始数据比特流,长度不一定是8的倍数,需要补齐,它是由VCL层产生的
  • RBSP SODB+trailing bits 算法是如果SODB最后一个字节不对齐,则补1和0
  • NALU NAL Header(1B)+RBSP

ta

整个码流格式

SPS重要参数

  • H264profile
    • 对视频压缩特性的描述 profile越高说明采用了越高级的压缩特性
  • H264Level
    • Level是对视频的描述,leve越高视频码率 分辨率 fps越高

H264profile

在mianProfile之上还有更新的压缩特性,使得图像的压缩率能更高,比如High层支持了对颜色的变化,88的帧内预测,88的转化。High10位数更多了 图像会更清晰

  • Baseline

(最低Profile)级别支持I/P 帧,只支持无交错(Progressive)和CAVLC,一般用于低阶或需要额外容错的应用,比如视频通话、手机视频等;

profile_idc = 66

  • Extended

EP-Extended profile:进阶画质,是后来才加入的。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC

profile_idc = 88

  • Main

(主要Profile)级别提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced),同样提供对于CAVLC 和CABAC 的支持,用于主流消费类电子产品规格如低解码(相对而言)的mp4、便携的视频播放器、PSP和Ipod等;

profile_idc = 77

  • High

(高端Profile,也叫FRExt)级别在Main的基础上增加了8x8 内部预测、自定义量化、无损视频编码和更多的YUV 格式(如4:4:4),用于广播及视频碟片存储(蓝光影片),高清电视的应用。

profile_idc = 100

  • H.264 Baseline profile、Extended profile和Main profile都是针对8位样本数据、4:2:0格式的视频序列
  • High profile将其扩展到8~12位样本数据,视频格式可以为4:2:0、4:2:2、4:4:4

设立了High profile(HP)、High 10 profile(Hi10P)、High 4:2:2 profile (Hi422P)、High 4:4:4 profile(Hi444P) 4个profile,这4个profile都以Main profile为基础。

在相同配置情况下,High profile(HP)可以比Main profile(MP)节省10%的码流量,比MPEG-2MP(基于数字存储媒体运动图像和语音的压缩标准)节省60%的码流量,具有更好的编码性能。

H264Level

Level是对视频本身特性的描述(码率、分辨率、fps),Level越高,视频的码率、分辨率、fps越高,而level主要是对码流的关键参数的取值范围作了限定,与解码器的处理能力和存储能力相关联。

其他参数

PPS与SliceHeader

PPS

SliceHeader

Slice header中主要保存了当前slice的一些全局的信息,slice body中的宏块在进行解码时需依赖这些信息

  • 帧类型
  • GOP中解码帧序号
  • 预测权重
  • 滤波

参考文献:

SEI补充增强信息

zhuanlan.zhihu.com/p/71928833

www.jianshu.com/p/0c296b05e…

cloud.tencent.com/developer/a…

bbs.huaweicloud.com/forum/threa…

IPB帧

帧编码场编码

www.pianshen.com/article/198…