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

Perface

本主题介绍用于视频渲染的8位YUV颜色格式

本文介绍了在YUV和RGB格式之间转换的技术,还提供了对YUV格式进行上采样的技术。

本文使用YUV视频解码或渲染的任何人。

Introduction

视频行业定义了许多YUV格式。本文确定了建议在Windows中进行视频渲染的8位YUV格式。

鼓励解码器供应商和显示器供应商支持本文中描述的格式。本文不涉及YUV颜色的其他用途,例如静态摄影。

本文中描述的格式都使用每个像素位置8位来编码Y通道(也称为亮度通道),并使用每个样本8位来对每个U或V色度样本进行编码。

然而,大多数YUV格式平均每像素使用的比特数少于24,因为它们包含的U和V样本比Y样本少本文不涵盖具有10比特或更高Y通道的YUV格式。

Note: 就本文而言,术语U等同于Cb,术语V等同于Cr。

本文涵盖以下主题:

  • YUV采样。介绍最常见的YUV采样技术。
  • 曲面定义。介绍推荐的YUV格式。
  • 颜色空间和色度采样率转换。提供一些在YUV和RGB格式之间转换以及在不同YUV格式之间转换的指导原则。
  • 在Media Foundation中识别YUV格式。解释如何在Media Foundation中描述YUV格式类型。

YUV采样-YUV Sampling

色度通道可以具有比亮度通道更低的采样率,而不会显著损失感知质量。一种称为“A:B:C”的符号用于描述U和V相对于Y的采样频率:

  • 4:4:4意味着色度通道没有下采样。
  • 4:2:2表示2:1的水平下采样,没有垂直下采样。对于每两个U或V样本,每条扫描线包含四个Y样本。
  • 4:2:0表示2:1的水平下采样,2:1的垂直下采样。
  • 4:1:1表示4:1水平下采样,没有垂直下采样。对于每个U和V样本,每条扫描线包含四个Y样本。4:1:1采样比其他格式不太常见,本文中也没有详细讨论。

下图显示了如何对每个下采样率的色度进行采样

  • 亮度样本用十字表示,
  • 色度样本用圆圈表示。


在ITU-R建议BT.601中定义了4:2:2采样的主要形式。

4:2:0采样有两种常见的变体。

  • 其中一个用于MPEG-2视频,
  • 另一个用于MPEG-4和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格式。这些可分为以下几类:

  • 4:4:4 Formats, 32 Bits per Pixel
  • 4:2:2 Formats, 16 Bits per Pixel
  • 4:2:0 Formats, 16 Bits per Pixel
  • 4:2:0 Formats, 12 Bits per Pixel

首先,为了理解以下内容,您应该了解以下概念:

  • Surface 原点。对于本文中描述的YUV格式,Surface (0,0)始终是Surface 的左上角。

  • Stride是Surface 的宽度(以字节为单位),有时称为pitch。给定左上角的Surface 原点,步长始终为正。

  • 对齐Surface 的对齐由图形显示驱动程序自行决定。Surface 必须始终DWORD对齐;也就是说,保证Surface 内的各条线源自32位(DWORD)边界。然而,根据硬件的需要,对准可以大于32位。

  • 压缩格式与平面格式。YUV格式分为压缩格式和平面格式。在压缩格式中,Y、U和V分量存储在单个阵列中。像素被组织成宏像素组,其布局取决于格式。在平面格式中,Y、U和V元素存储为三个独立的平面。

本文中描述的每种YUV格式都有一个指定的FOURCC代码。FOURCC代码是一个32位无符号整数,通过连接四个ASCII字符创建。

4:4:4 Formats, 32 Bits per Pixel

AYUV

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


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

4:2:2 Formats, 16 Bits per Pixel

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

  • YUY2
  • UYVY

两者都是压缩格式,其中每个宏像素是编码为四个连续字节的两个像素。这导致色度的水平下采样因子为2。

YUY2

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


如果图像被寻址为小端WORD值的阵列,

则第一个WORD包含最低有效位(LSB)中的第一个Y样本和最高有效位(MSB)中的第一个U(Cb)样本。

第二个WORD包含LSB中的第二个Y样本和MSB中的第一个V(Cr)样本。

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

UYVY

这种格式与YUY2格式相同,只是字节顺序相反——也就是说,色度和亮度字节被翻转(图4)。

如果图像被寻址为两个小端WORD值的数组,

则第一个WORD在LSB中包含U,在MSB中包含Y0,

第二个WORD的LSB中包括V,在MSBs中包含Y1。

4:2:0 Formats, 16 Bits per Pixel

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

  • IMC1
  • IMC3

这两种YUV格式都是平面格式。

色度通道在水平维度和垂直维度上都以因子2进行二次采样。

IMC1

所有Y个样本首先在内存中显示为无符号字符值的数组。接着是所有的V(Cr)样本,然后是所有的U(Cb)样本。

V和U平面与Y平面具有相同的步长,从而产生未使用的内存区域,如图5所示。

U和V平面必须从16行的倍数的内存边界开始。图5显示了352 x 240视频帧的U和V的原点。U和V平面的起始地址计算如下:

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

其中,pY是指向内存阵列起始位置的字节指针,如下图所示。

IMC3

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

4:2:0 Formats, 12 Bits per Pixel

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

  • IMC2
  • IMC4
  • YV12
  • NV12

在所有这些格式中,色度通道在水平维度和垂直维度上都以因子2进行二次采样。

IMC2

此格式与IMC1相同,只是以下不同:V(Cr)和U(Cb)线在半步边界处交错。

换句话说,色度区域中的每条全步幅线都以一行V样本开始,然后是一行U样本,从下一个半步幅边界开始(图7)。

这种布局比IMC1更有效地利用了地址空间。它将色度地址空间减半,从而将总地址空间减少25%。

在4:2:0格式中,IMC2是仅次于NV12的第二大首选格式。下图说明了这个过程。

IMC4

此格式与IMC2相同,只是U(Cb)和V(Cr)线被交换,如下图所示。

YV12

所有Y个样本首先在内存中显示为无符号字符值的数组。该阵列之后紧接着是所有的V(Cr)样本。

V平面的步幅是Y平面步幅的一半;并且V平面包含的线是Y平面的一半。

V平面后面紧跟着所有U(Cb)采样,其步长和线数与V平面相同,如下图所示。

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平面和包含压缩U和V采样的阵列。

颜色空间与色度采样率的转换

本节提供了在YUV和RGB之间进行转换以及在某些不同YUV格式之间进行转换的指南。

在本节中,我们考虑了两种RGB编码方案:8位计算机RGB,也称为sRGB或“full-scale”RGB,

以及演播室视频RGB,或“具有head-room and toe-room的RGB”。它们的定义如下:

  • 计算机RGB对红色、绿色和蓝色的每个样本使用8位。黑色由R=G=B=0表示,白色由R=G=B=255表示。

  • Studio视频RGB对红色、绿色和蓝色的每个采样使用一定数量的位N,其中N为8或更多。
    Studio视频RGB使用与计算机RGB不同的缩放因子,并且有偏移。黑色用R=G=B=16*2(N-8)表示,白色用R=G=C=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:4YUV之间的转换。要将4:2:0或4:2:2 YUV转换为RGB,我们建议将YUV数据转换为4:4:4 YUV,然后从4:4:4转换为RGB。

AYUV格式为4:4:4格式,Y、U和V采样各使用8位。对于一些应用,YUV也可以使用每个样本超过8位来定义。

已经为数字视频定义了来自RGB的两种主要YUV转换。两者都基于被称为ITU-R建议BT.709的规范。第一个转换是BT.709中定义的用于50Hz的较旧YUV形式。

它与ITU-R建议BT.601中规定的关系相同,也被称为其旧名称CCIR601。

它应该被认为是标准清晰度电视分辨率(720x576)和较低分辨率视频的首选YUV格式。其特征在于两个常数Kr和Kb的值:

Kr = 0.299
Kb = 0.114

第二种转换是BT.709中为60Hz定义的较新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))

where

  • M是每个YUV采样的比特数(M>=8)。
  • Z是 black-level变量。对于计算机RGB,Z等于0。对于工作室视频RGB,Z等于16*2^(N-8),其中N是每个RGB采样的位数(N>=8)。
  • S是缩放变量。对于计算机RGB,S等于255。对于演播室视频RGB,S等于219*2^(N-8)。

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

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

Note:clip3应该被实现为一个函数,而不是一个预处理器宏;否则将对参数进行多次求值。

Y采样表示亮度,U采样和V采样分别表示蓝色和红色的颜色偏差。Y的标称范围为16*2(M-8)至235*2(M-8)。

黑色表示为16*2(M-8),白色表示为235*2(M-8)。

U和V的标称范围为162(M-8)到240*2(M-8),值1282^(M-8)表示中性色度。

但是,实际值可能会超出这些范围。

对于工作室视频RGB形式的输入数据,剪辑操作是必要的,以将U和V值保持在0到(2^M)-1的范围内。

如果输入是计算机RGB,则不需要进行剪裁操作,因为转换公式无法生成超出此范围的值。

这些是没有近似的精确公式。本文档中的所有内容都源自这些公式。本节介绍以下转换:

  • Converting RGB888 to YUV 4:4:4
  • Converting 8-bit YUV to RGB888
  • Converting 4:2:0 YUV to 4:2:2 YUV
  • Converting 4:2:2 YUV to 4:4:4 YUV
  • Converting 4:2:0 YUV to 4:4:4 YUV

将 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 需要两倍的垂直上转换。本节描述执行上转换的示例方法。该方法假设视频图像是逐行扫描的。

NOTE:4:2:0到4:2:2隔行扫描转换过程存在非典型问题并且难以实现。本文不讨论将隔行扫描从 4:2:0 转换为 4:2:2 的问题。

令输入色度样本的每条垂直线都是一个Cin[]范围从 0 到 N - 1 的数组。输出图像上相应的垂直线将是一个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);

其中clip()表示裁剪到[0…255]的范围。

NOTE:处理边缘的方程可以在数学上得到简化。它们以这种形式显示是为了说明图片边缘的夹紧效果。

实际上,此方法通过在四个相邻像素上插值曲线来计算每个缺失值,并根据两个最近像素的值进行加权(图 11)。本示例中使用的特定插值方法使用称为 Catmull-Rom 插值(也称为三次卷积插值)的众所周知的方法在半整数位置生成缺失样本。

图 11. 显示 4:2:0 至 4:2:2 上采样的图表

在信号处理方面,垂直上转换理想情况下应包括相移补偿,以解决 4:2:0 采样线位置和 4:2:0 采样线位置之间的半像素垂直偏移(相对于输出 4:2:2 采样网格)。每隔 4:2:2 采样线的位置。然而,引入此偏移会增加生成样本所需的处理量,并且无法从上采样的 4:2:2 图像重建原始 4:2:0 样本。它还无法将视频直接解码为 4:2:2 表面,然后使用这些表面作为参考图片来解码流中的后续图片。因此,这里提供的方法没有考虑样本的精确垂直对齐。

如果您从使用 H.261、H.263 或 MPEG-1 视频中定义的采样网格的 4:2:0 视频开始,则输出 4:2:2 色度样本的相位也将移动一半- 相对于亮度采样网格间距的像素水平偏移(相对于 4:2:2 色度采样网格间距的四分之一像素偏移)。然而,4:2:0 视频的 MPEG-2 形式可能更常用于 PC,并且不会遇到此问题。此外,在相当高的图像分辨率下,这种区别可能不会对视觉造成损害。尝试纠正这个问题会产生与垂直相位偏移所讨论的相同类型的问题。

将 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。您还可以切换两个上转换过程的顺序,因为操作顺序对于结果的视觉质量并不重要。

其他 YUV 格式

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

  • AI44 是一种调色版 YUV 格式,每个样本 8 位。每个样本在 4 个最高有效位 (MSB) 中包含一个索引,在 4 个最低有效位 (LSB) 中包含一个 alpha 值。索引指的是 YUV 调色板条目的数组,必须在格式的媒体类型中定义它。该格式主要用于子图片图像。
  • NV11 是一种 4:1:1 平面格式,每像素 12 位。Y 样本首先出现在内存中。Y 平面后面是压缩的 U (Cb) 和 V (Cr) 样本阵列。当组合的 UV 数组被寻址为小尾数WORD值的数组时,U 样本包含在每个WORD的 LSB 中,V 样本包含在 MSB 中。(此内存布局与 NV12 类似,尽管色度采样不同。)
  • Y41P 是一种 4:1:1 压缩格式,水平方向上每四个像素采样一次 U 和 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 等效,只是 U 和 V 样本交换了。

识别 Media Foundation 中的 YUV 格式

本文中描述的每种 YUV 格式都有一个指定的 FOURCC 代码。FOURCC 代码是通过连接四个 ASCII 字符创建的 32 位无符号整数。

有多种 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

XXXXXXXXFOURCC 代码在哪里。因此,YUY2 的子类型 GUID 为:

32595559-0000-0010-8000-00AA00389B71 

最常见的 YUV 格式 GUID 的常量在头文件 mfapi.h 中定义。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TrustZone_Hcoco

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值