视频渲染推荐的 8 位 YUV 格式

加里·沙利文和斯蒂芬·埃斯特罗普

Microsoft Corporation

2002 年 4 月,2008 年 11 月更新

本主题介绍建议在 Windows 操作系统中呈现视频的 8 位 YUV 颜色格式。 本文介绍在 YUV 和 RGB 格式之间进行转换的技术,并提供用于向上采样 YUV 格式的技术。 本文适用于在 Windows 中使用 YUV 视频解码或渲染的任何人。

简介

在整个视频行业定义许多 YUV 格式。 本文标识建议在Windows中呈现视频的 8 位 YUV 格式。 建议解码器供应商和显示供应商支持本文中所述的格式。 本文不解决 YUV 颜色的其他用途,如仍然摄影。

本文中所述的格式均使用每个像素位置 8 位来编码 Y 通道 (也称为 luma 通道) ,并使用每个样本 8 位对每个 U 或 V 色度样本进行编码。 但是,大多数 YUV 格式平均每像素使用 24 位,因为它们包含的样本比 Y 少。本文不介绍 10 位或更高 Y 通道的 YUV 格式。

注意

在本文中,术语 U 等效于 Cb,术语 V 等效于 Cr。

 

本文涵盖以下主题:

YUV 采样

色度通道的采样率可能低于 luma 通道,而不会显著丧失感知质量。 称为“A:B:C”表示法的表示法用于描述相对于 Y 的采样频率和 V:

  • 4:4:4 表示没有色度通道的下采样。
  • 4:2:2 表示 2:1 水平向下采样,无垂直向下采样。 每个扫描行包含每两个 U 或 V 样本的四个 Y 样本。
  • 4:2:0 表示 2:1 水平向下采样,2:1 垂直向下采样。
  • 4:1:1 表示 4:1 水平向下采样,无垂直向下采样。 每个扫描行均包含四个 Y 样本,每个样本均包含 V 样本。 4:1:1 采样比其他格式不太常见,本文未详细讨论。

下图显示了如何针对每个下采样率对色度进行采样。 Luma 样本由十字表示,色度样本由圆表示。

figure 1. chroma sampling

4:2:2 采样的主要形式是在ITU-R 建议 BT.601 中定义的。 有两个常见变体为 4:2:0 采样。 其中一个用于 MPEG-2 视频,另一个用于 MPEG-1 和ITU-T 推荐 H.261 和 H.263。

与 MPEG-1 方案相比,在 MPEG-2 方案与为 4:2:2 和 4:4:4 格式定义的采样网格之间转换更简单。 因此,MPEG-2 方案优先于Windows,应被视为 4:2:0 格式的默认解释。

Surface 定义

本部分介绍建议用于视频渲染的 8 位 YUV 格式。 这些类别分为几个类别:

首先,应了解以下概念,以便了解以下内容:

  • 图面原点。 对于本文中所述的 YUV 格式,原点 (0,0) 始终是表面左上角。
  • 步幅。 表面的步幅(有时称为音调)是图面宽度(以字节为单位)。 鉴于左上角的表面原点,步幅始终是积极的。
  • 对齐方式。 图面的对齐方式由图形显示驱动程序决定。 图面必须始终为 DWORD 对齐;也就是说,保证图面中的单个线条源自 32 位 (DWORD) 边界。 但是,对齐方式可能大于 32 位,具体取决于硬件的需求。
  • 打包格式与平面格式。 YUV 格式分为 打包 格式和 平面 格式。 以打包格式,Y、U 和 V 组件存储在单个数组中。 像素组织成一组宏像素,其布局取决于格式。 采用平面格式,Y、U 和 V 组件存储为三个单独的平面。

本文所述的每个 YUV 格式都有一个分配的 FOURCC 代码。 FOURCC 代码是一个 32 位无符号整数,通过串联四个 ASCII 字符来创建。

4:4:4 格式,每个像素 32 位

AYUV

建议使用 4:4:4 格式,使用 FOURCC 代码 AYUV。 这是一种打包格式,其中每个像素编码为四个连续字节,按下图所示的序列排列。

figure 2. ayuv memory layout

标记为 A 的字节包含 alpha 的值。

4:2:2 格式,每像素 16 位

建议使用以下 FOURCC 代码使用两种 4:2:2 格式:

  • YUY2
  • UYVY

这两种格式都是打包格式,其中每个宏像素都是编码为四个连续字节的两个像素。 这会导致色度水平向下采样,其系数为 2。

YUY2

在 YUY2 格式中,可以将数据视为无符号 字符 值的数组,其中第一个字节包含第一个 Y 样本,第二个字节包含第一个 U (Cb) 样本,第三个字节包含第二个 Y 样本,第四个字节包含第一个 V (Cr) 示例,如下图所示。

figure 3. yuy2 memory layout

如果图像作为小端 WORD 值的数组进行寻址,则第一个 WORD 包含最小有效位中的第一个 Y 样本, (LSB) ,以及第一个 U (Cb) 样本, (MSB) 。 第二 个 WORD 包含 LSB 中的第二个 Y 示例和 MSB 中的第一个 V (Cr) 示例。

YUY2 是 Microsoft DirectX 视频加速 (DirectX VA) 的首选 4:2:2 像素格式。 它预计将是 DirectX VA 加速器支持 4:2:2 视频的中期要求。

UYVY

此格式与 YUY2 格式相同,但字节顺序相反,即色度和 luma 字节 (图 4) 翻转。 如果图像作为两个小端 WORD 值的数组进行寻址,则第一个 WORD 包含 MSB 中的 LSB 和 Y0 中的 U,第二个 WORD 包含 MSB 中的 LSB 和 Y1 中的 V。

figure 4. uyvy memory layout

4:2:0 格式,每个像素 16 位

建议每像素使用两个 4:2:0 16 位 (bpp) 格式,并使用以下 FOURCC 代码:

  • IMC1
  • IMC3

这两种 YUV 格式都是平面格式。 色度通道由水平维度和垂直尺寸中的两个因素进行子采样。

IMC1

所有 Y 样本首先以无符号 字符 值数组的形式出现在内存中。 随后是 V (Cr) 示例,然后是所有 U (Cb) 示例。 V 和 U 平面的步幅与 Y 平面相同,导致内存区域未使用,如图 5 所示。 你和 V 平面必须以 16 行的倍数的内存边界开始。 图 5 显示了 352 x 240 视频帧的源和 V。 你和 V 平面的起始地址按如下方式计算:

BYTE* pV = pY + (((Height + 15) & ~15) * Stride);
BYTE* pU = pY + (((((Height * 3) / 2) + 15) & ~15) * Stride);

其中 pY 是指向内存数组开头的字节指针,如下图所示。

figure 5. imc1 memory layout (example)

IMC3

此格式与 IMC1 相同,只是交换了你和 V 平面,如下图所示。

figure 6. imc3 memory layout

4:2:0 格式,每像素 12 位

建议使用四个 4:2:0 12-bpp 格式,并使用以下 FOURCC 代码:

  • IMC2
  • IMC4
  • YV12
  • NV12

在所有这些格式中,色度通道被水平和垂直维度中的两个因素子采样。

IMC2

此格式与 IMC1 相同,但以下差异除外:V (Cr) 和 U (Cb) 线交错在半步边界处。 换句话说,色度区域中的每个全步线都以 V 样本线开头,然后是一行 U 样本,从下一个半步边界开始 (,图 7) 。 此布局比 IMC1 更有效地使用地址空间。 它将色度地址空间削减一半,因此总地址空间减少了 25%。 在 4:2:0 格式中,IMC2 是 NV12 之后的第二个首选格式。 下图演示了此过程。

figure 7. imc2 memory layout

IMC4

此格式与 IMC2 相同,除非交换了 U (Cb) 和 V (Cr) 行,如下图所示。

figure 8. imc4 memory layout

YV12

所有 Y 样本首先以无符号 字符 值数组的形式出现在内存中。 此数组紧跟所有 V (Cr) 示例。 V 平面的步幅是 Y 平面的一半:和 V 平面包含 Y 平面的一半行。 V 平面紧随所有 U (Cb) 样本,其步幅和行数与 V 平面相同,如下图所示。

figure 9. yv12 memory layout

NV12

所有 Y 样本首先以内存形式显示为具有偶数行的无符号 字符 值的数组。 Y 平面紧接着是包含打包的 U (Cb) 和 V (Cr) 样本的无符号 字符 值的数组。 当组合的 U-V 数组作为小端 WORD 值的数组进行寻址时,LSB 包含 U 值,而 MSB 包含 V 值。 NV12 是 DirectX VA 的首选 4:2:0 像素格式。 它应该是支持 4:2:0 视频的 DirectX VA 加速器的中间术语要求。 下图显示了包含打包的 Y 平面和包含 V 示例的数组。

figure 10. nv12 memory layout

颜色空间和色度采样率转换

本部分提供在 YUV 和 RGB 之间转换的准则,以及用于在一些不同的 YUV 格式之间进行转换。 我们在本部分中考虑了两种 RGB 编码方案: 8 位计算机 RGB,也称为 sRGB 或“完全缩放”RGB,以及 工作室视频 RGB,或“带头室和托室的 RGB”。这些定义如下:

  • 计算机 RGB 为每个红色、绿色和蓝色样本使用 8 位。 黑色由 R = G = B = 0 表示,白色由 R = G = B = 255 表示。
  • 工作室视频 RGB 对每个红色、绿色和蓝色样本使用一些位 N,其中 N 为 8 或更多。 工作室视频 RGB 使用与计算机 RGB 不同的缩放系数,并且具有偏移量。 黑色由 R = G = B = 16*2^ (N-8) 表示,白色由 R = G = B = B = 235*2^ (N-8) 表示。 但是,实际值可能超出此范围。

工作室视频 RGB 是Windows中视频的首选 RGB 定义,而计算机 RGB 是非视频应用程序的首选 RGB 定义。 在 RGB 的任一形式中,色度坐标在ITU-R BT.709中指定,用于定义 RGB 颜色初选。 R、G 和 B 的 (x,y) 坐标分别 (0.64、0.33) 、 (0.30、0.60) 和 (0.15、0.06) 。 引用白色是 D65,坐标 (0.3127,0.3290) 。 名义伽马是 1/0.45 (大约 2.2) ,精确伽马在ITU-R BT.709 中详细定义。

RGB 与 4:4:4 YUV 之间的转换

我们首先介绍 RGB 与 4:4:4 YUV 之间的转换。 若要将 4:2:0 或 4:2:2 YUV 转换为 RGB,建议将 YUV 数据转换为 4:4:4 YUV,然后将 4:4:4 YUV 转换为 RGB。 AYUV 格式(4:4:4 格式)对 Y、U 和 V 样本使用 8 位。 对于某些应用程序,还可以使用每个示例 8 位以上的 YUV 进行定义。

已为数字视频定义了两个来自 RGB 的主导 YUV 转换。 这两者都基于称为ITU-R 建议 BT.709 的规范。 第一个转换是在 BT.709 中为 50-Hz 使用的旧 YUV 形式定义的。 它与ITU-R 建议 BT.601 中指定的关系相同,也称为其旧名称 CCIR 601。 它应该被视为标准定义电视分辨率的首选 YUV 格式, (720 x 576) 和分辨率较低的视频。 它的特点是两个常量 KrKb 的值:

Kr = 0.299
Kb = 0.114

第二次转换是在 BT.709 中为 60-Hz 使用的较新的 YUV 形式,应被视为高于 SDTV 的视频分辨率的首选格式。 它的特点是这两个常量的不同值:

Kr = 0.2126
Kb = 0.0722

从 RGB 到 YUV 的转换从以下内容开始定义:

L = Kr * R + Kb * B + (1 - Kr - Kb) * G

然后,获取 YUV 值,如下所示:

Y =                   floor(2^(M-8) * (219*(L-Z)/S + 16) + 0.5)
U = clip3(0, (2^M)-1, floor(2^(M-8) * (112*(B-L) / ((1-Kb)*S) + 128) + 0.5))
V = clip3(0, (2^M)-1, floor(2^(M-8) * (112*(R-L) / ((1-Kr)*S) + 128) + 0.5))

其中

  • M 是每个 YUV 样本的位数, (M >= 8) 。
  • Z 是黑色级别变量。 对于计算机 RGB,Z 等于 0。 对于工作室视频 RGB,Z 等于 16*2^ (N-8) ,其中 N 是每个 RGB 样本的位数, (N >= 8) 。
  • S 是缩放变量。 对于计算机 RGB,S 等于 255。 对于工作室视频 RGB,S 等于 219*2^ (N-8) 。

函数平面 (x) 返回小于或等于 x 的最大整数。 函数 clip3 (x、y、z) 的定义如下:

clip3(x, y, z) = ((z < x) ? x : ((z > y) ? y : z))

注意

clip3 应实现为函数而不是预处理器宏;否则,将多次计算参数。

 

Y 样本表示亮度,你和 V 样本分别表示与蓝色和红色的颜色偏差。 Y 的名义范围为 16*2^ (M-8) 到 235*2^ (M-8) 。 黑色表示为 16*2^ (M-8) ,白色表示为 235*2^ (M-8) 。 的名义范围是 16*2^ (M-8) 到 240*2^ (M-8) ,值为 128*2^ (M-8) 表示中性色。 但是,实际值可能超出这些范围。

对于工作室视频 RGB 形式的输入数据,需要剪辑操作才能将你和 V 值保持在 0 范围内,以 (2^M) -1。 如果输入是计算机 RGB,则不需要剪辑操作,因为转换公式无法在此范围之外生成值。

这些公式是没有近似的确切公式。 本文档后面的所有内容都派生自这些公式。 本节介绍下列转换:

将 RGB888 转换为 YUV 4:4:4

对于计算机 RGB 输入和 8 位 BT.601 YUV 输出,我们认为上一部分中给出的公式可以合理地按以下方式进行近似:

Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16
U = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128
V = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128

这些公式使用系数生成 8 位结果,该系数不需要超过 8 位的 (无符号) 精度。 中间结果最多需要 16 位精度。

将 8 位 YUV 转换为 RGB888

从原始 RGB 到 YUV 公式中,可以派生 BT.601 的以下关系。

Y = round( 0.256788 * R + 0.504129 * G + 0.097906 * B) +  16 
U = round(-0.148223 * R - 0.290993 * G + 0.439216 * B) + 128
V = round( 0.439216 * R - 0.367788 * G - 0.071427 * B) + 128

因此,给定:

C = Y - 16
D = U - 128
E = V - 128

可以将 YUV 转换为 RGB 的公式派生如下:

R = clip( round( 1.164383 * C                   + 1.596027 * E  ) )
G = clip( round( 1.164383 * C - (0.391762 * D) - (0.812968 * E) ) )
B = clip( round( 1.164383 * C +  2.017232 * D                   ) )

其中 clip() 表示剪辑到 [0..255] 的范围。 我们认为这些公式可以合理地按以下公式进行近似:

R = clip(( 298 * C           + 409 * E + 128) >> 8)
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
B = clip(( 298 * C + 516 * D           + 128) >> 8)

这些公式使用一些系数,这些系数需要超过 8 位精度才能生成每个 8 位结果,中间结果需要 16 位以上的精度。

若要将 4:2:0 或 4:2:2 YUV 转换为 RGB,建议将 YUV 数据转换为 4:4:4 YUV,然后将 4:4:4 YUV 转换为 RGB。 后面的部分提供了一些方法,用于将 4:2:0 和 4:2:2 格式转换为 4:4:4。

将 4:2:0 YUV 转换为 4:2:2 YUV

将 4:2:0 YUV 转换为 4:2:2 YUV 需要按两个因素进行垂直向上转换。 本部分介绍用于执行 upconversion 的示例方法。 该方法假定视频图片是渐进式扫描。

注意

4:2:0 到 4:2:2:2 交错扫描转换过程存在非典型问题,难以实现。 本文未解决将交错扫描从 4:2:0 转换为 4:2:2:2 的问题。

 

让每个输入色度样本的垂直线都是介于 0 到 N - 1 之间的数组 Cin[] 。 输出图像上的相应垂直线将是一个 Cout[] 数组,范围为 0 到 2N - 1。 若要转换每个垂直线,请执行以下步骤:

Cout[0]     = Cin[0];
Cout[1]     = clip((9 * (Cin[0] + Cin[1]) - (Cin[0] + Cin[2]) + 8) >> 4);
Cout[2]     = Cin[1];
Cout[3]     = clip((9 * (Cin[1] + Cin[2]) - (Cin[0] + Cin[3]) + 8) >> 4);
Cout[4]     = Cin[2]
Cout[5]     = clip((9 * (Cin[2] + Cin[3]) - (Cin[1] + Cin[4]) + 8) >> 4);
...
Cout[2*i]   = Cin[i]
Cout[2*i+1] = clip((9 * (Cin[i] + Cin[i+1]) - (Cin[i-1] + Cin[i+2]) + 8) >> 4);
...
Cout[2*N-3] = clip((9 * (Cin[N-2] + Cin[N-1]) - (Cin[N-3] + Cin[N-1]) + 8) >> 4);
Cout[2*N-2] = Cin[N-1];
Cout[2*N-1] = clip((9 * (Cin[N-1] + Cin[N-1]) - (Cin[N-2] + Cin[N-1]) + 8) >> 4);

其中剪辑 () 表示剪辑范围为 [0..255]。

注意

处理边缘的公式可以数学简化。 它们以这种形式显示,以说明图片边缘的夹紧效果。

 

实际上,此方法通过将曲线内插在四个相邻像素上来计算每个缺失值,其权重为两个最接近像素的值, (图 11) 。 此示例中使用的特定内插方法使用称为Catmull-Rom内插(也称为立方卷积内插)在半整数位置生成缺失样本。

figure 11. diagram showing 4:2:0 to 4:2:2 upsampling

在信号处理术语中,垂直向上转换应包括一个相移补偿,以考虑相对于输出 4:2:2:2 采样网格之间的半像素垂直偏移量 (,) 4:2:0 样本线的位置,以及每个其他 4:2:2 采样线的位置。 但是,引入此偏移量会增加生成样本所需的处理量,并使无法从向上采样的 4:2:2:2 图像重新构造原始的 4:2:0 样本。 它还使无法将视频直接解码为 4:2:2 图面,然后使用这些图面作为参考图片来解码流中的后续图片。 因此,此处提供的方法不考虑样本的精确垂直对齐方式。 这样做在相当高的图片分辨率上可能不是视觉有害的。

如果从使用 H.261 中定义的采样网格的 4:2:0 视频开始, H.263 或 MPEG-1 视频,输出 4:2:2 色度样本的阶段也将相对于 luma 采样网格上的间距进行半像素水平偏移, (相对于 4:2:2:2 色度采样网格的间距) 。 但是,MPEG-2 形式的 4:2:0 视频可能更常用在电脑上,并且不会遇到此问题。 此外,这种区别在相当高的图片分辨率上可能不是视觉有害的。 如果尝试更正此问题,将创建针对垂直相差讨论的相同问题。

将 4:2:2 YUV 转换为 4:4:4 YUV

将 4:2:2 YUV 转换为 4:4:4 YUV 需要按两个因素进行水平向上转换。 前面为垂直向上转换描述的方法也可以应用于水平向上转换。 对于 MPEG-2 和ITU-R BT.601 视频,此方法将生成具有正确相对齐的示例。

将 4:2:0 YUV 转换为 4:4:4 YUV

若要将 4:2:0 YUV 转换为 4:4:4 YUV,只需遵循前面所述的两种方法即可。 将 4:2:0 图像转换为 4:2:2,然后将 4:2:2 图像转换为 4:4:4: 4。 还可以切换两个上转过程的顺序,因为操作顺序对结果的视觉质量并不重要。

其他 YUV 格式

其他一些不太常见的 YUV 格式包括:

  • AI44 是一种淡化 YUV 格式,每个样本有 8 位。 每个示例包含 4 个最有效位 (MSB) 的索引,以及 4 个最小有效位中的 alpha 值, (LSB) 。 索引引用了一组 YUV 调色板条目,该条目必须在媒体类型中为格式定义。 此格式主要用于子图片图像。
  • NV11 是一种 4:1:1 平面格式,每像素 12 位。 Y 示例首先显示在内存中。 Y 平面后接一组打包的 U (Cb) 和 V (Cr) 样本。 当合并的 U-V 数组作为小端 WORD 值的数组进行寻址时,U 样本包含在每个 WORD 的 LSB 中,V 样本包含在 MSB 中。 (此内存布局类似于 NV12,尽管色度采样不同。)
  • Y41P 是一种 4:1:1 打包格式,你和 V 水平采样每四个像素一次。 每个宏像素包含 8 个字节(以三个字节为单位),具有以下字节布局: U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y7
  • Y41T 与 Y41P 相同,但每个 Y 样本的最小有效位指定色度键 (0 = 透明,1 = 不透明) 。
  • Y42T 与 UYVY 相同,但每个 Y 样本的最小有效位指定色度键 (0 = 透明,1 = 不透明) 。
  • YVYU 等效于 YUYV,但交换了你和 V 示例。

在媒体基础中识别 YUV 格式

本文所述的每个 YUV 格式都有一个分配的 FOURCC 代码。 FOURCC 代码是一个 32 位无符号整数,通过串联四个 ASCII 字符来创建。

可以通过各种 C/C++ 宏在源代码中更轻松地声明 FOURCC 值。 例如, MAKEFOURCC 宏在 Mmsystem.h 中声明, FCC 宏在 Aviriff.h 中声明。 按如下所示使用它们:

DWORD fccYUY2 = MAKEFOURCC('Y','U','Y','2');
DWORD fccYUY2 = FCC('YUY2');

还可以直接将 FOURCC 代码声明为字符串文本,只需反转字符的顺序即可。 例如:

DWORD fccYUY2 = '2YUY';  // Declares the FOURCC 'YUY2'

由于Windows操作系统使用小端体系结构,因此需要扭转顺序。 “Y”= 0x59,“U”= 0x55,“2”= 0x32,因此“2YUY”0x32595559。

在 Media Foundation 中,格式由主要类型 GUID 和子类型 GUID 标识。 计算机视频格式的主要类型始终MFMediaType_Video。 可以通过将 FOURCC 代码映射到 GUID 来构造子类型,如下所示:

XXXXXXXX-0000-0010-8000-00AA00389B71 

其中 XXXXXXXX 是 FOURCC 代码。 因此,YUY2 的子类型 GUID 为:

32595559-0000-0010-8000-00AA00389B71 

最常见的 YUV 格式 GUID 的常量在头文件 mfapi.h 中定义。 有关这些常量的列表,请参阅 视频子类型 GUID

关于 YUV 视频

视频媒体类型