FFmpeg 中 YUV

来源:互联网 发布:成都医院招聘网络总监 编辑:程序博客网 时间:2024/04/29 22:27

转自:http://hi.baidu.com/absolutely1st/item/463dc75965079dc7d2e10cfa

正文:

FFmpeg 源码分析 Part Three: YUV

先给出YUV格式的定义:

YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间。


YUV名词解释和原理:

YUV的原理是,将亮度和色度分离,根据人眼的特性,相对于色度,人对亮度更敏感一些。

利用这个特性我们可以适当的减少色度的信息。


在YUV的三个字母中,“Y”表示亮度,“U”和“V”表示色度。

在一些技术文档里,YUV还有其他的一些名字,主要的有这2个:YCbCr和YPbPr。 


YCbCr:Y与YUV中的解释一致,表示亮度。

Cb/Cr中,C代表分量,Cb表示的就是蓝色分量信号,Cr表示的是红色分量信号。

Y除了亮度信号外,还叠加了绿色分量信号。数字信号是YCbCr,JPEG和MPEG2都采用的是此格式。

YCbCr表示隔行扫描色差输出,是属于YUV经过缩放和偏移的翻版。


YPbPr:YCbCr在模拟分量视频也称为YPbPr。

YPbPr是将模拟的Y,Pb,Pr信号分开,使用三条线缆来独立输出,

保障了色彩还原的准确性,YPbPr表示逐行扫描色差输出。


YUV的存储格式:

先简要说明一下bpp比特每像素:表示一个像素点所能取到的不同颜色数取决于bpp。Max_bpp = 2^颜色深度。

常见的取值有8bpp =2^8 = 256色,16bpp高彩色,24bpp真彩色,48bpp用于专业扫描仪,TIFF文件。

对于超过8位的深度,这些数位就是三个分量(红绿蓝)的各自的数位的总和。

一个16位的深度通常分为5位红色和5位蓝色,6位绿色(眼睛对于绿色更为敏感)。

24位的深度一般是每个分量8位。

在有些系统中,32位深度也是可选的:这意味着24位的像素有8位额外的数位来描述透明度。


在RGB格式中,一个24bpp像素要占用4个字节空间。

在YUV中可以对于uv色度分量进行压缩,但对图像质量影响不大,所以YUV所占空间要比RGB要小。


YUV存储与RGB格式最大的不同在于,RGB格式每个点的数据是连续保存在一起的,即 RGBRGBRGBRGB.... 

而在YUV中,每个Y分量独立存储,但是连续几个点的U,V保存在一起,这几点个合起来称为marco-pixel,

这种存储格式称为packed格式(打包格式)


另外一种存储格式是把一幅图像中Y,U,V分别用三个独立的数组表示。

这种模式称为planar模式(平面格式)。


YUV的采样格式:

先介绍一个好东西:FourCC码。


FourCC全称Four-Character Codes,代表四字符代码 (four character code), 

它是一个32位的标示符,其实就是typedef unsigned int FOURCC;是一种独立标示视频数据流格式的四字符代码。


视频播放软件通过查询 FourCC 代码并且寻找与 FourCC 代码相关联的视频解码器来播放特定的视频流。


传统的FourCC码的生成方式为:

#define MAKE_FOURCC(a,b,c,d) \  

( ((uint32_t)d) | ( ((uint32_t)c) << 8 ) | ( ((uint32_t)b) << 16 ) | ( ((uint32_t)a) << 24 ) )


下面所用的采样格式也可以通过FourCC码来表示。


我们一般用YUV三者的比率来表示不同的格式,主要有YUV444,YUV422,YUV420,YUV411

YUV444:

FourCC 码为 AYUV,表示色度UV分量没有减少采样。

即Y,U,V各占一个字节,透明分量Alpha再占一个字节。共占4个字节,这就和RGB 24bpp是一样的。

每个像素都被组织为4个连续字节,组织顺序如下所示:

                


YUV422:

表示UV分量减半采样。比如第一个点采样YU,第二个点采样YV,这样每个点占2个字节,16位。

2个像素组成了一个宏像素。

支持2个4:2:2格式,FourCC码为:

第一种,YUY2,

第一个字节包含第一个 Y 样例,

第二个字节包含第一个 U (Cb) 样例,

第三个字节包含第二个 Y 样例,

第四个字节包含第一个 V (Cr) 样例,如图所示 :

在小端模式下,(即低地址存放低位,高地址存放高位),看作由两个WORD 值组成的数组,

则第一个 WORD 在最低有效位 (LSB) 中包含 Y0,在最高有效位 (MSB) 中包含 U。

第二个 WORD 在 LSB 中包含 Y1,在 MSB 中包含 V。


第二种,UYVY,只是将YUY2中的亮度和色度的字节序反一下。如图所示:


YUV420:

表示每4个点隔点只取U,隔行后每4个点隔点只取V

这种采样并不是说有Y和Cb,而没有Cr。而是说Cb和Cr分量隔行才采样一次。

比如第一行采样4:2:0,第二行采样4:0:2....以此类推。

举个实例:

原本的8个像素点:

【Y0,U0,V0】【Y1,U1,V1】【Y2,U2,V2】【Y3,U3,V3】

【Y4,U4,V4】【Y5,U5,V5】【Y6,U6,V6】【Y7,U7,V7】

经过YUV420采样,得到:

【Y0,U0】【Y1】【Y2,U2】【Y3】

【Y4,V4】【Y5】【Y6,V6】【Y7】

支持6种4:2:2格式,FourCC码为:

第一种,IMC1,所有 Y 样例都会作为不带正负号的char值组成的数组首先显示在内存中。

后面跟着所有 V (Cr) 样例,然后是所有 U (Cb) 样例。

V 和 U 平面与 Y 平面具有相同的跨距,从而生成如图 8 所示的内存的未使用区域。

如图所示:

第二种,IMC3,和IMC1类似,只是V和U平面进行了交换而已。

第三种,IMC2,此格式与 IMC1 相同,只是 V (Cr) 和 U (Cb) 行在半跨距边界处进行了交错。

换句话说,就是色度区域中的每个完整跨距行都以一行 V 样例开始,

然后是一行在下一个半跨距边界处开始的 U 样例(图 10)。

此布局与 IMC1 相比,能够更加高效地利用地址空间。它的色度地址空间缩小了一半,

因此整体地址空间缩小了 25%。在各个 4:2:0 格式中,IMC2 是第二首选格式,排在 NV12 之后。

如图所示:

第四种,IMC4,和IMC2类似,只是V和U平面进行了交换而已。

第五种,YV12,所有 Y 样例都会作为不带正负号的char值组成的数组首先显示在内存中。

此数组后面紧接着所有 V (Cr) 样例。

V 平面的跨距为 Y 平面跨距的一半,V 平面包含的行为 Y 平面包含行的一半。

V 平面后面紧接着所有 U (Cb) 样例,它的跨距和行数与 V 平面相同。

如图所示:

第六种,NV12,所有 Y 样例都会作为由不带正负号的char值组成的数组首先显示在内存中,并且行数为偶数。

Y 平面后面紧接着一个由不带正负号的char值组成的数组,其中包含了打包的 U (Cb) 和 V (Cr) 样例,

如图 13 所示。

当组合的 U-V 数组被视为一个由小端WORD值组成的数组时,

LSB 包含 U 值,MSB 包含 V 值。NV12 是用于 DirectX VA 的首选 4:2:0 像素格式。如图所示: