【Android音视频开发】视频编码原理
文章版本号 | 变更内容 | 变更日期 | 备注 |
---|---|---|---|
0.0.1 | 创建 | 2022/9/30 | 初版 |
0.0.2 | 补充视频编码原理内容 | 2022/10/10 | 完成初版编写 |
1. 前言
在【Android音视频开发】 这一系列文章的开头,介绍一下音视频编码的原理是很有必要的,有利于对后续出现的概念的理解。我的上一篇文章已经对音频的编码原理进行了介绍,还没看过的小伙伴可以点这里阅读,在这篇文章中我将按照同样的思路介绍一下视频的编码原理。
2. 正文
2.1 图像的本质
物体对可见光的反射,经由人眼接收后在视网膜上成像,就形成了我们所看到的“图像”。人眼可以看作一台高达5.76亿像素的“超级相机”,而对于这个“超级相机”而言,图像其实就是大量像素点(带有颜色的点)的组合-这也就是图像的本质。
2.1.1 图像的相关概念
- 像素(点):图像由多个“带有颜色的点”组成,这里提到的“带有颜色的点”被称为像素点,像素点是构成图像的基本单位,一幅图像由多个像素点组成。例如1080p的图像就由1920x1080=2073600个像素点组成,也可以说这个图像是200万像素的,1920x1080也被称为分辨率。
- 分辨率:图像横竖两个方向上容纳像素点的数量,分辨率越大图像越清晰、越细腻。
2.1.2 像素点的颜色表示
- 三原色:每种颜色都能由红(Red)、绿(Green)、蓝(Blue)三种颜色调制出来,因此红绿蓝称为三原色,计算机中用RGB表示。
- 基色分量:R\G\B也被称为“基色分量”,在计算机中每个基色分量占用的空间为8bit(1byte),因此每个基色分量的取值范围为0(0b0000 0000)~255(0b1111 1111),即256个取值。
三个基色分量组合起来能表示的颜色有256x256x256=1677 7216种,也可简称为1600万色和24位色,这个颜色范围已经超过了人眼可见的所有颜色,所以又叫真彩色。再高的话对于人眼来说已经没有意义了,因为识别不出来。
除了使用RGB颜色模型来表示色彩外,常用的颜色模型还有YUV颜色模型,后面会提到。
2.2 视频的本质
视频,其实就是一张张图像的连续播放。 当图像的切换速度达到或超过一定数值时,对人眼来说,看到的就是我们认知中的视频效果了,这里提到的“切换速度”就是我们常说的帧率。人眼舒适放松时的可视帧数是每秒24帧(即帧率为24),集中精神时不超过30帧,眨眼时睁开眼瞬间可以捕捉到的帧数是30帧以上。
2.2.1 视频中的基本概念
(视频)帧:是视频的一个基本概念,表示一张图像,如翻页动画书中的一页,就是一帧。一个视频就是由许许多多帧组成的。
帧率:单位时间(1秒)内显示的视频帧数量,单位为:帧/秒 或 fps(frames per second),帧率越大,画面越顺滑,过渡越自然。
帧率的几个典型值:
- 24/25 fps:1 秒 24/25 帧,一般的电影帧率;
- 30/60 fps:1 秒 30/60 帧,游戏的帧率,30 帧可以接受,60 帧会感觉更加流畅逼真。
- 85 fps 以上人眼基本无法察觉出来了,所以更高的帧率在视频里没有太大意义。
色彩空间:像素点颜色值的取值空间。常用的有两种,RGB 和 YUV,也可以称为颜色模型。
RGB在上面有介绍了,下面主要介绍一下YUV颜色模型(该颜色模型在后续讲视频编解码时会多次用到)。
2.2.1.1 YUV颜色模型
早期的电视都是黑白的 ,即只有亮度值 Y。有了彩色电视以后,加入了 UV 两种色度,两者组合形成了现在的 YUV,也叫 YCbCr:
- Y:亮度,就是灰度值 。除了表示亮度信号外,还含有较多的绿色通道量;
- U:蓝色通道与亮度的差值;
- V:红色通道与亮度的差值。
YUV颜色模型的优势:
人眼对亮度敏感,对色度不敏感,因此减少部分 UV 的数据量,人眼无法感知出来,这样可以通过压缩 UV 的分辨率,在不影响观感的前提下,减小视频的体积。
YUV与RGB的换算公式:
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R- 0.515G - 0.100B
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
常用的YUV编码格式:
- YU12 (I420/YUV420P)
- YV12
- I422(YUV422P)
- NV12(YUV420SP)
- NV21(Android 相机(Camera)默认的输出格式)
对于YUV格式的详细介绍可以去看这篇文章,在这里我就不赘述了。
2.3 视频编码原理
编码:就是按指定的方法,将信息从一种形式(格式),转换成另一种形式(格式)。
视频编码:就是将一种视频格式,转换成另一种视频格式。
视频的编码原理与音频编码类似,也是通过减少冗余量进行压缩编码,不过与音频编码不同的是,视频编码利用的是人眼在视频观测上的冗余。
2.3.1 未编码的视频有多大
以一个分辨率1920×1280,帧率30的视频为例,每帧图像为1920×1280=2,073,600(Pixels 像素),每个像素点是24bit(RGB颜色模型,每个颜色分量为1byte=8bit),也就是每幅图片为2073600×24=49766400 bit,即49766400bit=6220800byte≈6.22MB,这是一幅1920×1280图片的原始大小,还要乘以帧率30。
也就是说:每秒视频的大小是186.6MB,每分钟大约是11GB,一部90分钟的电影,约是1000GB。
这样庞大的数据量对传输和存储的技术、成本要求都是巨大的,因此对视频进行编码压缩是很有必要的。
2.3.2 视频图像存在的冗余
视频图像中存在的冗余主要有上方表格所示的几类,视频编码的目的就在于在尽可能去除上面的这些冗余量的同时保留最好的图像效果。
而在这几类冗余中,视频编码技术优先消除的目标是空间冗余和时间冗余。接下来,就和大家介绍一下,究竟需要采用什么样的办法,才能干掉它们。
2.3.3 编码技术实现
视频是由不同的帧画面连续播放形成的。
这些帧,主要分为三类,分别是:
- I帧;
- B帧;
- P帧。
I帧:是自带全部信息的独立帧,是最完整的画面(占用的空间最大),无需参考其它图像便可独立进行解码。视频序列中的第一个帧,始终都是I帧。
B帧:“双向预测编码帧”,以前帧后帧作为参考帧。不仅参考前面,还参考后面的帧,所以,它的压缩率最高,可以达到200:1。不过,因为依赖后面的帧,所以不适合实时传输(例如视频会议)。
P帧:“帧间预测编码帧”,需要参考前面的I帧和/或P帧的不同部分,才能进行编码。P帧对前面的P和I参考帧有依赖性。但是,P帧压缩率比较高,占用的空间较小(相对于I帧)。
通过对帧的分类处理,可以大幅压缩视频的大小。毕竟,要处理的对象,大幅减少了(从整个图像,变成图像中的一个区域)。
帧分类压缩示意图.png我们来通过一个例子看一下。
这有两个帧:
好像是一样的?
不对,将这两个图做成GIF动图,就能看出来,是不一样的:
人在动,背景是没有在动的,两张图之间的差值如下:
也就是说,图一到图二,只有部分像素进行了移动。移动轨迹如下:
在已知图一信息的情况下,只需要知道这些移动轨迹,就能参考得出图二,这个,就是运动估计和补偿。
当然了,如果总是按照像素来算,数据量会比较大,所以,一般都是把图像切割为不同的“块(Block)”或“宏块(MacroBlock)”,对它们进行计算。一个宏块一般为16像素×16像素。
好了,我来梳理一下。对I帧的处理,是采用帧内编码方式,只利用本帧图像内的空间相关性。对P帧的处理,采用帧间编码(前向运动估计),同时利用空间和时间上的相关性。简单来说,采用运动补偿(motion compensation)算法来去掉冗余信息。
需要特别注意,I帧(帧内编码),虽然只有空间相关性,但整个编码过程也不简单。
如上图所示,整个帧内编码,还要经过DCT(离散余弦变换)、量化、编码等多个过程。限于篇幅,加之较为复杂,这里就不过多解释了。
那么,视频经过编码解码之后,如何衡量和评价编解码的效果呢?
一般来说,分为客观评价和主观评价。客观评价,就是拿数字来说话。例如计算信噪比/峰值信噪比。
信噪比的计算,我就不介绍了,丢个公式,有空可以自己慢慢研究。
除了客观评价,就是主观评价了。主观评价,就是用人的主观感知直接测量,说人话就是——“好不好看我说了算”。比如用两种编码方式编码出来的两个视频,在你的观感上哪个更清晰、流畅,在你看来更清晰流畅的,就是在主观评价上来说编码效果更好的。
2.4 视频编码格式
发展历史:
发展史示意图中最后提到的HEVC,就是我们如今常说的H.265格式。
H.265作为一种新编码标准,相比H.264有极大的性能提升,目前已经成为最新视频编码系统的标配。
2.5 (音)视频封装格式
对于任何一部视频来说,只有图像,没有声音,肯定是不行的。所以,视频编码后,要加上音频编码,一起进行封装。
封装:就是封装格式,简单来说,就是将已经编码压缩好的视频轨和音频轨按照一定的格式放到一个文件中。再通俗点,视频轨相当于饭,而音频轨相当于菜,封装格式就是一个饭盒,用来盛放饭菜的容器。
目前主要的视频封装格式有如下几种:MPG、VOB、MP4、3GP、ASF、RMVB、WMV、MOV、Divx、MKV、FLV、TS/PS等。
封装之后的视频,就可以传输了,也可以通过视频播放器进行解码观看。