首页 关于 微信公众号
欢迎关注我的微信公众号

音视频基础知识

视频编解码方式

视频编解码的过程是指对数字视频进行压缩或解压缩的一个过程。

在做视频编解码时,需要考虑以下这些因素的平衡:视频的质量、用来表示视频所需要的数据量(通常称之为码率)、编码算法和解码算法的复杂度、针对数据丢失和错误的鲁棒性(Robustness)、编辑的方便性、随机访问、编码算法设计的完美性、端到端的延时以及其它一些因素。

常见的视频编码方式有:

介绍了上面这些「视频编解码方式」后,我们来说说它和上一节讲的「视频封装格式」的关系。可以把「视频封装格式」看做是一个装着视频、音频、「视频编解码方式」等信息的容器。一种「视频封装格式」可以支持多种「视频编解码方式」,比如:QuickTime File Format(.MOV) 支持几乎所有的「视频编解码方式」,MPEG(.MP4) 也支持相当广的「视频编解码方式」。当我们看到一个视频文件名为 test.mov 时,我们可以知道它的「视频文件格式」是 .mov,也可以知道它的视频封装格式是 QuickTime File Format,但是无法知道它的「视频编解码方式」。那比较专业的说法可能是以 A/B 这种方式,A 是「视频编解码方式」,B 是「视频封装格式」。比如:一个 H.264/MOV 的视频文件,它的封装方式就是 QuickTime File Format,编码方式是 H.264。

音频编解码方式

视频中除了画面通常还有声音,所以这就涉及到音频编解码。在视频中经常使用的音频编码方式有:

关于 H.264

概念

H.264 是现在广泛采用的一种编码方式。关于 H.264 相关的概念,从大到小排序依次是:序列、图像、片组、片、NALU、宏块、亚宏块、块、像素。

我们先来解释几个概念:

image

image

image

颜色模型

我们听过最多的颜色模型应该就是经典的 RGB 模型了。

image

在 RGB 模型中每种颜色需要 3 个数字,分别表示 R、G、B,比如 (255, 0, 0) 表示红色,通常一个数字占用 1 字节,那么表示一种颜色需要 24 bits。那么有没有更高效的颜色模型能够用更少的 bit 来表示颜色呢?

现在我们假设我们定义一个「亮度(Luminance)」的概念来表示颜色的亮度,那它就可以用含 R、G、B 的表达式表示为:

Y = kr*R + kg*G + kb*B

Y 即「亮度」,kr、kg、kb 即 R、G、B 的权重值。

这时,我们可以定义一个「色度(Chrominance)」的概念来表示颜色的差异:

Cr = R – Y
Cg = G – Y
Cb = B – Y

Cr、Cg、Cb 分别表示在 R、G、B 上的色度分量。上述模型就是 YCbCr 颜色模型基本原理。

YCbCr 是属于 YUV 家族的一员,是在计算机系统中应用最为广泛的颜色模型,就比如在本文所讲的视频领域。在 YUV 中 Y 表示的是「亮度」,也就是灰阶值,U 和 V 则是表示「色度」。YUV 的关键是在于它的亮度信号 Y 和色度信号 U、V 是分离的。那就是说即使只有 Y 信号分量而没有 U、V 分量,我们仍然可以表示出图像,只不过图像是黑白灰度图像。在YCbCr 中 Y 是指亮度分量,Cb 指蓝色色度分量,而 Cr 指红色色度分量。

现在我们从 ITU-R BT.601-7 标准中拿到推荐的相关系数,就可以得到 YCbCr 与 RGB 相互转换的公式:

Y = 0.299R + 0.587G + 0.114B
Cb = 0.564(B - Y)
Cr = 0.713(R - Y)
R = Y + 1.402Cr
G = Y - 0.344Cb - 0.714Cr
B = Y + 1.772Cb

这样对于 YCbCr 这个颜色模型我们就有个初步认识了,但是我们会发现,这里 YCbCr 也仍然用了 3 个数字来表示颜色啊,有节省 bit 吗?为了回答这个问题,我们来结合视频中的图像和图像中的像素表示来说明。

图片是由类似下面的像素组成:

image

一副图片就是一个像素阵列:

image

上图中,每个像素的 3 个分量的信息是完整的,YCbCr 4:4:4。

image

上图中,对于每个像素点都保留「亮度」值,但是省略每行中偶素位像素点的「色度」值,从而节省了 bit。

image

上图中,做了更多的省略,但是对图片质量的影响却不会太大。

对于更细节的内容,可以查询与 YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1 和 YCbCr 4:4:4 相关的知识。

码流格式

在上节中,我们简单的介绍了和 H.264 编码相关的图片、像素以及颜色模型相关的概念,那这一节就接着简要介绍一下 H.264 码流的结构,以及如何从 H.264 的码流中找到那些像素。

对于一个解码器来说,它的工作对象就是从一个特定结构的数据流中去获取有效的 bit 流,而这个数据流则是结构化后分为数据包传输的,其大致结构如下:

image

我们可以看到,在 NAL 包之间存在着一些间隔标记。

NAL 包的第一个字节是定义包类型的头文件,NAL 包有这样一些类型:

类型 定义
0 Undefined
1 Slice layer without partitioning non IDR
2 Slice data partition A layer
3 Slice data partition B layer
4 Slice data partition C layer
5 Slice layer without partitioning IDR
6 Additional information (SEI)
7 Sequence parameter set
8 Picture parameter set
9 Access unit delimiter
10 End of sequence
11 End of stream
12 Filler data
13..23 Reserved
24..31 Undefined

NAL 的类型说明了当前这个 NAL 包的数据结构和数据含义,它可能是片(Slice),参数集或者填充数据等等。

image

如上图所示,NAL 包将其负载数据存储在 RBSP(Raw Byte Sequence Payload) 中,RBSP 是一系列的 SODB(String Of Data Bits)。

image

下面,我们来具体看看 H.264 的码流结构:

image

一张图片可以包含一个或多个分片(Slice),而每一个分片(Slice)又会被分为了若干宏块(Macroblock)。对于分片(Slice)来说,有如下这些类型:

类型 定义
0 P-slice. Consists of P-macroblocks (each macro block is predicted using one reference frame) and / or I-macroblocks.
1 B-slice. Consists of B-macroblocks (each macroblock is predicted using one or two reference frames) and / or I-macroblocks.
2 I-slice. Contains only I-macroblocks. Each macroblock is predicted from previously coded blocks of the same slice.
3 SP-slice. Consists of P and / or I-macroblocks and lets you switch between encoded streams.
4 SI-slice. It consists of a special type of SI-macroblocks and lets you switch between encoded streams.
5 P-slice.
6 B-slice.
7 I-slice.
8 SP-slice.
9 SI-slice.

如我们所见,每个分片也包含着头和数据两部分,分片头中包含着分片类型、分片中的宏块类型、分片帧的数量以及对应的帧的设置和参数等信息,而分片数据中则是宏块,这里就是我们要找的存储像素数据的地方。

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

image

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

至此,我们对 H.264 的码流数据结构应该有了一个大致的了解。

帧内预测和帧间预测

在上一节的末尾,我们介绍了宏块的数据结构,其中提到了「预测类型」这个字段,这里就接着说说「帧内预测」和「帧间预测」这两种在视频编码中常用到的压缩方法,也可以称为「帧内压缩」和「帧间压缩」。

帧内压缩类似于图片压缩,跟这一帧的前面(或后面)一帧(或几帧)无关,由当前帧中,已编码的部分来推测当前待编码的这一部分数据是什么。帧间压缩是由这一帧的前(或后)一帧(或几帧)来推测当前待压缩的这一部分数据是什么。

上节中,我们说过图片可以划分为宏块。一般来说,运动多细节多的部分,划分成小块来编码,无变化的大片的部分,划分成大块来编码。其大致效果如下:

image

帧内预测

对于帧内压缩,我们可以看下图示例:

image

我们可以通过第 1、2、3、4、5 块的编码来推测和计算第 6 块的编码,因此就不需要对第 6 块进行编码了,从而压缩了第 6 块,节省了空间。

帧内预测在 H.264 编码标准里有以下几种预测方法:

image

帧间预测

对于帧间压缩,可以看下面连续的两帧:

image

image

可以看到前后两帧的差异其实是很小的,这时候用帧间压缩就很有意义。

做帧间压缩常用的方式就是块匹配(Block Matching),就是找找看前面已经编码的几帧里面,和我当前这个块最类似的一个块,这样我就不用编码当前块的内容了,只需要编码当前块和我找到的那个块的差异(称为残差)即可。找最像的块的过程叫运动搜索(Motion Search),又叫运动估计(Motion Estimation)。用残差和原来的块就能推算出当前块的过程叫运动补偿(Motion Compensation)。

image

视频业务

我们平常最常接触到的视频相关的业务方式通常有:本地视频文件播放网络视频点播网络视频直播等等几种。对于网络视频点播、网络视频直播,整个过程大致如下图所示:

image

而本地视频文件播放就更简单了,是在上面的过程中省略掉解协议的过程。

流媒体协议

随着互联网基础设施越来越完善,网络视频点播和直播业务也越来越多,这其中少不了流媒体协议的支持。常见的流媒体协议有:

业务方案

在国内主流的一些视频业务相关的公司中,主要采用的视频业务方案有:

网络视频点播

公司 协议 封装 视频编码 音频编码 播放器
CNTV HTTP MP4 H.264 AAC Flash
CNTV(部分) RTMP FLV H.264 AAC Flash
华数 TV HTTP MP4 H.264 AAC Flash
优酷网 HTTP FLV H.264 AAC Flash
土豆网 HTTP F4V H.264 AAC Flash
56网 HTTP FLV H.264 AAC Flash
音悦台 HTTP MP4 H.264 AAC Flash
乐视网 HTTP FLV H.264 AAC Flash
新浪视频 HTTP FLV H.264 AAC Flash

网络视频点播业务采用 HTTP 有两方面优势:

网络视频点播服务采用的封装格式有多种:MP4,FLV,F4V 等,它们之间的区别不是很大。

视频编码标准和音频编码标准是 H.264 和 AAC,这两种标准分别是当今实际应用中编码效率最高的视频标准和音频标准。

视频播放器方面则都使用了 Flash 播放器。

网络视频直播

公司 协议 封装 视频编码 音频编码 播放器
华数 TV RTMP FLV H.264 AAC Flash
六间房 RTMP FLV H.264 AAC Flash
中国教育电视台 RTMP FLV H.264 AAC Flash
北广传媒移动电视 RTMP FLV H.264 AAC Flash
上海IPTV RTSP+RTP TS H.264 MP2 机顶盒

网络视频直播服务采用 RTMP 作为直播协议的好处是可以直接被 Flash 播放器支持,而 Flash 播放器在 PC 时代有着极高的普及率,并且与浏览器结合的很好。因此这种流媒体直播平台基本上可以实现了「无插件直播」,极大降低了用户使用成本。

封装格式、视频编码、音频编码、播放器方面几乎全部采用了 FLV、H.264、AAC、Flash。FLV、RTMP、Flash 都是 Adobe 公司的产品,天生有着良好的结合性。

在现在看来,以上的数据已经有些过时了,比如现在随着移动互联网时代的爆发,H5 以及客户端应用的普及,行业中对视频业务技术方案的选择也逐渐在发生着变化,而我们则需要结合眼下的实际情况和技术发展的趋势去做出合适的技术选型。

Blog

Opinion

Project