- 由 zhongluqiang创建, 最后修改于2月 14, 2023
关于视频
图像连续播放形成视频,单个的图像称为一帧(Frame),帧的播放速度称为帧率(Frame Rate),一般用FPS描述帧率,指每秒播放多少帧图像(Frame per Second)。
一般来说,人眼能感觉到视频卡顿的帧率为15帧,低于15帧时,人眼能察觉出画面的不连贯,高于15帧时,人眼的主观感受差别不大。由于视觉滞留效应(指人眼看到的图像消失后,图像仍会在大脑中停留一段时间,约为1/24秒),当视频帧率高于24帧每秒时,人眼就已经无法感知了。为了实现立体视觉,两只眼睛的看到的画面要不一样,这样双眼的立体视觉帧率就至少需要达到48FPS。游戏显卡输出的FPS可以高达几百帧,但这与显卡、显示器帧率不同步导致的撕裂效应有关,参考:画面撕裂、卡顿、垂直同步。
PAL制彩色电视每秒25帧,NTSC制每秒30帧。
关于视频通信延时,当延时小于200ms时质量为优秀,此时类似于面对面聊天,基本无法察觉。延时200ms~500ms,类似于打电话,可以察觉,但基本不影响通信。延时500ms~800ms则可以明显察觉。当延时大于800ms时,就已经不适合实时通信了。
关于视频压缩
解决音视频数字化后数据量大与存储媒体和通信网带宽小的矛盾,以分辨率640x480,帧率15,采样格式YUV420,量化深度8bit的视频为例,其码率为:
640*x480*3/2*15*8bit = 55.296Mbps
参考设置视频编码属性 - 视频通话 - 文档中心 - 声网Agora,该视频属性下推荐的码率约为500Kbps,压缩率需要达到1:100才适合在网络传输。
通常H264的压缩率可以达到1:100,而H265的压缩率可以达到1:200或以上,参考:H.264与H.265视频压缩编码参考码率 - 光何 - 博客园。
视频压缩原理
视频数据中的冗余信息
- 时间冗余:视频中的相邻两帧之间内容相似,存在运动关系。
- 空间冗余:视频中的某一帧内部的相邻像素存在相似性。
- 编码冗余:视频中不同的数据出现的概率不同。(参考熵编码,比如游程编程、哈夫曼编码)
- 视觉冗余:观众的视觉系统对视频中的不同部分敏感程度不同。(参考JPEG压缩)
视频压缩办法
预测编码
主要包括两种方法:
- 帧内预测:根据当前帧已编码的数据进行预测,利用图像内相邻像素之间的相关性去除视频中的空间冗余,比如可以根据像素点左边和上边的像素来预测当前像素点的值。
- 帧间预测:将部分已编码的图像作为参考帧,利用前后帧之间的时间相关性去除视频中的时间冗余,比如视频编码中常见的I/P/B帧。
在H.261和MPEG-2等早期标准中便已经引入了基于运动补偿预测的帧间编码算法,在H.264及以后的标准中加入了帧内预测,通过将视频帧划分成宏块和子宏块进行分割,并对子宏块用帧内预测方法压缩空间冗余。
无论是帧内预测还是帧间预测都需要将图像划分成不同的宏块,以在一个更小尺寸的子像素块内进行。如果是帧内预测,那么一个子像素块会先从已编码的相邻子像素块中获取参考值,再从预设的预测模式中选择最佳模式进行编码,并将预测模式写入输出码流。在解码时通过解出的预测模式和已解码的相邻像素重建像素块。
在帧间预测中,宏块分割生成的子像素块在参考帧中搜索最匹配的参考像素块,其中,匹配度最高的像素块相对于当前块在空间域的偏移称为运动矢量。将参考帧的索引号和运动矢量输出到码流中,解码时根据参考帧索引获取指定参考帧,再根据运动矢量就可以预测出像素块。
运动矢量不会直接被编码,而是会分成运动矢量预测(Motion Vector Prediction, MVP)和运动矢量残差(Motion Vector Difference, MVD)两部分。其中MVP是通过已编码完成的信息预测的,MVD是通过熵编码写入输出码流的。已完成编码的相邻像素块,其运动信息大概率具有相关性,甚至运动轨迹完全一致,因此通过预测的方式编码运动矢量在多数情况下可以有效减少码流的数据量。
在未发生场景切换时,视频前后帧之间的相关性通常比视频帧内部相邻像素之间的相关性要大得多,因此帧间编码可以取得比帧内编码更高的压缩比。但帧间编码依赖参考帧,如果参考帧丢失,则会无法对当前帧进行解码,并且会导致后续所有依赖该参考帧的码流帧解码失败。
变换编码
与JPEG图像压缩标准一致,使用离散余弦变换和有损量化实现视频压缩。
常用的视频编码标准都会将预测编码和变换编码一起使用,称为混合编码,比如先对图像使用预测编码,然后将预测编码得到的图像与原图像相减,得到残差值,然后对残差值进行变换编码,这种方式可以最大程度地发挥两种编码的优势,达到最佳压缩效率。因为经过预测编码后得到的图像往往与原图像已经比较接近,这样残差值就会比较平坦,很适合使用类似DCT+量化这样的变换编码进行压缩。
熵编码
熵编码对应无损压缩,应用在视频压缩的最后一步,用于对数据进行进一步压缩。在JPEG图像压缩中,图像经过离散余弦变换和量化后,使用游程编码和哈夫曼编码进行熵编码。在视频压缩中,常用的熵编码算法如下:
- 指数哥伦步编码(UVLC)算法:常用于帧与Slice头信息的解析过程。
- 上下文自适应的变长编码(CAVLC)算法:主要用于H.264的Baseline Profile等格式的宏块类型、变换系数等信息的编码。
- 上下文自适应的二进制算术编码(CABAC)算法:主要用于H.264的Main/High Profile和H.265等格式的宏块类型、变换系数等信息的编码。
视频编码标准
本节内容参考以下链接:
- 《新一代视频压缩编码标准:H264/AVC》(毕厚杰) 第4章“视频编码标准简介”
- 即时通讯音视频开发(十九):零基础,史上最通俗视频编码技术入门-实时音视频/专项技术区 - 即时通讯开发者社区!
- 【x264视频编码器应用与实现】一. 视频编码与x264基本介绍 | 音视频技术大讲堂
增加一些个人理解和补充:
- 早期无论是音频还是视频,传输的都是模拟信号。以调频广播为例,将音频波形通过高频载波进行调制,输入的音频是模拟的,输出的调制信号也是模拟的,但这并不影响从调制信号中还原出音频波形。
对视频信号的调制也是类似,在黑白电视阶段,可以把视频亮度的变化看成一个连续的波形,这个波形也可以使用与音频类似的方式进行调制与传输。发展到彩色电视后,为了兼容原来的黑白电视,使用YUV颜色空间转换,这样原来的亮度信号调制不受影响,只需要多增加色度信号调制就可以了。 - 在数字计算机还远未普及的年代,基于模拟信号的电视广播就已经很流行了,所以很多视频编码的标准都是从模拟电视广播继承过来的,比如P制和N制,逐行和隔行,甚至早期的视频编码标准,连分辨率都只有那么几个,因为能显示视频的电视的分辨率也就那么一些,根本没必要考虑所有的分辨率。(早期电视的分辨率对应CRT显示器的显象管扫描线密集程度,从标准的角度来看,肯定不会每家都生产不一样的分辨率。)
主流视频编码标准发展历程
H.261标准
ITU-T发布的视频编码标准,是第一个实用的视频编码标准,奠定了视频压缩“块+混合编码”的主要框架,支持图像分块、帧间预测(运动补偿预测,运动矢量+残差值)、DCT编码量化、zigzag扫描等技术。H.261不支持帧内预测。以下是H261的编码过程,注意这里的图像输入其实是宏块,而不是一整幅图像:
输入图像(宏块)首先和上一帧进行相关性判断,如果相关性大则采用帧间编码,否则使用帧内编码。帧内编码直接走DCT变换和量化,这点和JPEG压缩一样。帧间编码则首先是找到与上一帧匹配的宏块,求出运动矢量,然后将当前块与上一帧的匹配宏块相减,求出残差值,再对残差值进行DCT变换和量化,将量化结果和运动矢量输出到复合编码器,形成最终的码流。
H261只针对CIF和QCIF格式两种图像进行处理,因为H261用于视频通信,但不同国家采用不同的电视制式,不能直接互通,所以H261采用了一种公共中间格式(Common Intermmediate Formt, CIF),不论何种彩色格式,发送方先把自己国家的彩电制式转成CIF,经H261编码后再由CIF格式转换到接收方彩电制式。
MPEG-1 标准
ISO/IEC组织发布的视频编码标准,和H.261同时代的产物,和H.261一样支持宏块划分、运动补偿、DCT变换和量化等技术,不同的是,MPEG-1定义了三种图像类型:I、P、B图像。I 图像即帧内( Intra)图像,采用帧内编码,不参考其它图像,但可作为其它类型图像的参考帧。 P 图像即预测( Predicted)图像,采用帧间编码,参考前一幅 I 或 P 图像,用作运动补偿。 B 图像即双向预测( Bi- predicted)图像,参考前后两个方向图像。
除此外,MPEG-1还在编码结构上引入了切片(Slice),切片小于帧但大于宏块,编码时一个切片内的宏块不会依赖其他切片的宏块。切片用于防止误码在一帧图像内传播,也可用于实现并行编码。
MPEG-1对比H.261:
- 支持I、P、B帧。
- 支持切片。
- 编码器基本一致,但要考虑双向预测编码和解码。
当年的VCD使用的就是MPEG-1编码,码率1.5Mbps。
MPEG-2/H.262
ITU-T和ISO/IEC联合发布的视频编码标准,编解码器与H.261区别不大,但其编码复用系统(如何打包码流,决定码流结构)比较重要,其定义的码流结构(MPEG-PS、MPEG-TS)在现在仍有广泛应用,以下是MPEG-2的编解码器结构:
- MPEG-2的宏块大小是固定的,对于亮度分量,其大小为16x16,对于色度分量,其大小为8x8。MPEG-2宏块匹配最小只能到8x8,16x16的亮度分量会被分成4个8x8的宏块进行匹配。
- MPEG-2也没有使用帧内预测。
以下是MPEG-2的编码复用系统结构:
MPEG-2码流分为三层:
- 基本流(ES,elementary bit stream),包括原始的视频基本流(Video ES)和原始的音频基本流(Audio ES)。
- 打包基本流(PES,packet elementary stream),对ES进行打包,长度可变,最大为65536字节。
- 传输流(TS,transport stream)& 节目流(PS,program stream),把若干个不同节目的PES打包到一起,输出传输流或节目流。传输流是定长的,自带校验,抗传输误码,适合实时传输,节目流不是定长的,抗误码能力弱,适合介质存储。
除此之外,MPEG-2还定义了不同的档次和级别,以适用于不同的设备。MPEG-2按不同的压缩比分成5个档次,按视频清晰度分为4个级别,一共有20种组合,最常用的有11种,分别用于标准数字电视、高清晰度电视,码流从4Mbps到100Mbps。
- DVD使用了MPEG-2技术,播放DVD时可以切换字幕和配音就和节目流中包含不同的节目有关。
- 有线电视和卫星锅使用了MPEG-2技术,当年电视的换台、加密授权和MPEG-2有关。
H.264/AVC
ITU-T和ISO/IEC联合开发的标准,旨在提供一个在更低的比特率的情况下依然能够提供良好视频质量的标准(一半或者更少于MPEG-2),同时不会太大的增加设计的复杂性。H.264的另外一个目标是提供足够的灵活性,以允许该标准能够应用于各种各样的网络和系统的各应用上,包括低和高比特率,低和高分辨率视频,广播,DVD存储,RTP / IP分组网络和ITU-T多媒体电话系统。
从目前来看H264的这两个目标都达到了,从压缩比来看,H264可以很容易实现1:100的压缩比,比MPEG-2平均1:50的压缩比要少一半,而H264标准定义的NAL单元,也为H264码流的传输和存储提供了非常大的灵活性,H264码流可以很容易地实现传输、存储、分片以及打包成其他封装格式的功能。
注意MPEG-4和H264的区别,两者都用于视频压缩,但是这两个标准的思路相差十万八千里。MPEG-4标准的编码基于对象,关注的是物体的运动、形状和纹理,H264是基于运动补偿的视频编码标准,关注的是宏块和宏块的运动。在MPEG-4标准的编码中,一段影像的编码方式可能是记录这段影像中有哪些感兴趣的物体,这些物体是怎么变化的,这样就算影像变化很快,码率也不会出现很大变化,或者也可以说只需要很小的码率,就可以解出很高的视频帧率,这就很适合用于超低比特率编码的场景,比如视频会议和可视电话。
真正和H264有关的是MPEG Part10,因为H264/AVC是ITU-T和ISO/IEC两个组织一起开发的,因此在ITU-T这边叫H264,在ISO/IEC这边叫MPEG-4 Part 10,然后H264本身还被叫做高级视频编码(AVC,Advanced Video Coding),总之H264/AVC/MPEG-4 Part10都是代表一个意思,不用在意这些细节。
H264没有明确规定一个编解码器如何实现,而是规定了H264码流结构和解码方法,各个厂商可在这个框架下自己设计编解码器。以下是H264的编码器和解码器功能组成:
H264支持帧内预测。
相关名词解释:
- ME:Motion Estimation,运动评估
- MC:Motion Compensation,运动补偿
- P:Predition, PRED,指预测值
编码过程:
仍然采用预测和变换的混合编码方式,输入帧以宏块为单位参与编码。
如果是帧内预测编码,则根据当前块的像素特点选择一种预测模式,使得根据该预测模式得到的预测值P与当前块的差异值最小,然后将预测值P与当前块相减,得到残差值Dn,对Dn进行变换、量化后,得到变换系数X,将X进行熵编码,再与预测模式一起组成压缩后的码流,打包进NAL单元。
如果是帧间编码,则根据参考帧F'n-1进行运动评估,找到当前宏块在参考帧中对应的宏块,然后计算运动矢量和运动补偿,运动矢量表示参考帧中的宏块相对当前块的坐标位置,运动补偿表示参考帧对应的宏块和当前块的残差值,将残差值进行变换、量化,得到变换系数X,将X进行熵编码,再与参考帧的宏块编号、运动矢量组成压缩后的码流。
帧间编码的重点是在参考帧中为当前正在编码的宏块找到一个匹配块。使用的办法是在参考帧的当前宏块位置附近进行搜索。搜索区域越大,计算成本越高,但也越不容易错过匹配块。如果找不到匹配的块,那这个宏块就会使用帧内预测,这也是为什么在H264的P slice和B slice中都有可能存在采用帧内预测的I宏块。
编码器内部必须有重建图像的功能,也就是生成上面的F'n,用于提供预测用的参考图像。因为H264在执行帧间编码时,后面的帧会依赖前面的帧,而前面的帧已经编码过了,如果要计算残差值,就必须先把前面的帧再解码出来作为参考。
实际上编码器肯定也会缓存一些前面的帧,但如果依赖的帧跨度过大(H264的多帧预测(包括单向和双向预测)参考帧可达5~15帧),那就不得不从已编码的数据中解码参考帧了。
H.265/HEVC
//TODO
MPEG-2对比H.264
参考:https://www.bilibili.com/video/BV1yy4y1J7TE/
H.265对比H.264
// TODO
- 无标签