視訊轉譯的建議 8 位 YUV 格式

Gary Sullivan 和 Stephen Estrop

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 的取樣頻率:

  • 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 取樣與其他格式較不常見,本文不會詳細討論。

下圖顯示如何針對每個降級取樣率取樣 chroma。 Luma 樣本是以交叉表示,而色度樣本則以圓形表示。

圖 1.chroma 取樣

以 4:2:2 取樣的主要形式定義于 BT-R 建議 BT.601 中。 4:2:0 取樣有兩個常見的變體。 其中一個用於 MPEG-2 視訊,另一個則用於 MPEG-1 和在 HTTP-T Recommendations H.261 和 H.263 中。

相較于 MPEG-1 配置,在 MPEG-2 配置與針對 4:2:2 和 4:4:4:4 格式定義的取樣方格之間轉換比較簡單。 基於這個理由,Windows 中偏好使用 MPEG-2 配置,而且應該視為預設解譯 4:2:0 格式。

Surface 定義

本節說明建議用於視訊轉譯的 8 位 YUV 格式。 這些分為數個類別:

首先,您應該注意下列概念,以瞭解下列內容:

  • 表面原點。 針對本文所述的 YUV 格式,原點 (0,0) 一律是表面左上角。
  • Stride。 表面的步幅有時稱為音調,是以位元組為單位的表面寬度。 假設左上角的表面原點,步幅一律為正數。
  • 對齊方式。 表面的對齊方式是圖形顯示驅動程式的任意方式。 表面必須一律對齊 DWORD;也就是說,介面內的個別線條保證源自 32 位 (DWORD) 界限。 不過,根據硬體的需求,對齊方式可以大於 32 位。
  • 封裝格式與平面格式。 YUV 格式分為 封裝 格式和 平面 格式。 以封裝格式,Y、U 和 V 元件會儲存在單一陣列中。 圖元會組織成宏圖元群組,其版面配置取決於格式。 在平面格式中,Y、U 和 V 元件會儲存為三個不同的平面。

本文所述的每個 YUV 格式都有指派的 FOURCC 程式碼。 FOURCC 程式碼是串連四個 ASCII 字元所建立的 32 位不帶正負號的整數。

4:4:4 格式,每個圖元 32 位

AYUV

建議使用單一 4:4:4 格式,並搭配 FOURCC 程式碼 AYUV。 這是封裝格式,其中每個圖元會編碼為四個連續位元組,並依下圖所示的序列排列。

圖 2.ayuv 記憶體配置

標示為 A 的位元組包含 Alpha 的值。

4:2:2 格式,每個圖元 16 位

建議使用下列 FOURCC 代碼的兩種 4:2:2 格式:

  • YUY2
  • UYVY

這兩者都是封裝格式,其中每個宏圖元都是編碼為四個連續位元組的兩個圖元。 這會導致水準向下取樣的 chroma 乘以兩個因素。

YUY2

在 YUY2 格式中,資料可以視為不帶正負號 字元 值的陣列,其中第一個位元組包含第一個 Y 樣本、第二個位元組包含第一個 U (Cb) 範例、第三個位元組包含第二個 Y 範例,而第四個位元組包含第一個 V (Cr) 範例,如下圖所示。

圖 3.yuy2 記憶體配置

如果影像是以小到尾 WORD 值的陣列來定址,則第一個 WORD 會包含最小有效位中的第一個 Y 樣本, (LSB) ,而第一個 U (Cb) 樣本則 (MSB) 。 第二 個 WORD 包含 LSB 中的第二個 Y 範例,以及 MSB 中的第一個 V (Cr) 範例。

YUY2 是 Microsoft DirectX 影片加速的慣用 4:2:2 像素格式, (DirectX VA) 。 DirectX VA 加速器預期是支援 4:2:2 視訊的中繼詞彙需求。

UYVY

此格式與 YUY2 格式相同,但位元組順序反轉除外,亦即, (圖 4) 翻轉 chroma 和 luma 位元組。 如果影像是以兩個位元組尾 WORD 值的陣列來定址,則第一個 WORD 會在 MSB 中的 LSB 和 Y0 中包含 U,而第二個 WORD 則包含 MSB 中的 V 和 Y1。

圖 4.uyvy 記憶體配置

4:2:0 格式,每個圖元 16 位

建議使用下列 FOURCC 程式碼,每個圖元有兩個 4:2:0 16 位, (bpp) 格式:

  • 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 是記憶體陣列開頭的位元組指標,如下圖所示。

圖 5.imc1 記憶體配置 (範例)

IMC3

此格式與 IMC1 相同,但您和 V 平面會交換,如下圖所示。

圖 6.imc3 記憶體配置

4:2:0 格式,每圖元 12 位

建議使用四個 4:2:0 12-bpp 格式,使用下列 FOURCC 代碼:

  • IMC2
  • IMC4
  • YV12
  • NV12

在這些格式中,色板通道會以水準和垂直維度中的兩個因素進行子取樣。

IMC2

除了下列差異之外,此格式與 IMC1 相同:V (Cr) 和 U (Cb) 線條交錯在半步界限。 換句話說,chroma 區域中的每個完整跨步線都是以一行 V 樣本開頭,後面接著一行 U 樣本,從下一個半步界限開始 (圖 7) 。 此配置會比 IMC1 更有效率地使用位址空間。 它會將色度位址空間縮減為一半,因此總位址空間會減少 25%。 在 4:2:0 格式中,IMC2 是 NV12 之後最慣用的格式。 下圖說明此程式。

圖 7.imc2 記憶體配置

IMC4

此格式與 IMC2 相同,但 U (Cb) 和 V (Cr) 行會交換,如下圖所示。

圖 8.imc4 記憶體配置

YV12

所有 Y 範例都會先出現在記憶體中,做為不帶正負號 字元 值的陣列。 此陣列會緊接著所有 V (Cr) 範例。 V 平面的步進是 Y 平面的一半;和 V 平面包含 Y 平面的一半行。 V 平面會緊接著所有 U (Cb) 範例,其與 V 平面具有相同的步幅和行數,如下圖所示。

圖 9.yv12 記憶體配置

NV12

所有 Y 範例都會先出現在記憶體中,做為不帶正負號 字元 值的陣列,其中包含偶數行。 Y 平面會緊接著未帶正負號 字元 值的陣列,其中包含封裝的 U (Cb) 和 V (Cr) 範例。 當合併的 U-V 陣列定址為位元組尾 WORD 值的陣列時,LSB 會包含 U 值,而 MSB 則包含 V 值。 NV12 是 DirectX VA 慣用的 4:2:0 像素格式。 DirectX VA 加速器預期是支援 4:2:0 視訊的中繼詞彙需求。 下圖顯示 Y 平面和包含封裝您和 V 範例的陣列。

圖 10.nv12 記憶體配置

色彩空間和色彩取樣率轉換

本節提供在 YUV 與 RGB 之間轉換的指導方針,以及用於在一些不同的 YUV 格式之間進行轉換。 我們會在本節中考慮兩個 RGB 編碼配置: 8 位電腦 RGB,也稱為 sRGB 或「完整縮放」RGB,以及 工作室視訊 RGB,或「具有頭室和 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 = B = 235*2^ (N-8) 表示。 不過,實際值可能落在這個範圍之外。

Studio 視訊 RGB 是 Windows 中視訊的慣用 RGB 定義,而電腦 RGB 是非視訊應用程式慣用的 RGB 定義。 在 RGB 的任一種形式中,色度座標會如在「RGB-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) 。 標稱 gamma 是大約 1/0.45 (大約 2.2) ,在) 中詳細說明精確 gamma。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 轉換。 這兩者都是以稱為「啟用」-R 建議 BT.709 的規格為基礎。 第一個轉換是針對 BT.709 中使用 50-Hz 所定義的較舊 YUV 表單。 它與在[][使用者建議][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))

where

  • M 是每個 YUV 範例的位數, (M > = 8) 。
  • Z 是黑色層級變數。 若為電腦 RGB,Z 等於 0。 針對 Studio 視訊 RGB,Z 等於 16*2^ (N-8) ,其中 N 是每個 RGB 範例的位數 (N > = 8) 。
  • S 是調整變數。 若為電腦 RGB,S 等於 255。 針對 Studio 視訊 RGB,S 等於 219*2^ (N-8) 。

函式 floor (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) 。 您和 V 的名義範圍是 16*2^ (M-8) 到 240*2^ (M-8) ,值為 128*2^ (M-8) 代表中性色度。 不過,實際值可能落在這些範圍之外。

對於 Studio 視訊 RGB 形式的輸入資料,剪輯作業必須保留介於 0 到 (2^M) -1 範圍內的您和 V 值。 如果輸入是電腦 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 交錯掃描轉換程式呈現非典型問題,難以實作。 本文無法解決將交錯掃描從 4:2:0 轉換為 4:2:2:2 的問題。

 

讓輸入色色樣本的每個垂直線都是範圍從 0 到 N - 1 的陣列 Cin[] 。 輸出影像上的對應垂直線將是範圍從 0 到 2N - 1 的陣列 Cout[] 。 若要轉換每個垂直線,請執行下列程式:

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]。

注意

處理邊緣的方程式可以以數學方式簡化。 它們會以此形式顯示,以說明圖片邊緣的固定效果。

 

實際上,這個方法會藉由將曲線插補到四個相鄰圖元上,以計算每個遺漏值,其加權為兩個最接近圖元的值 (圖 11) 。 此範例中使用的特定插補方法會使用稱為Catmull-Rom插補點的已知方法,在半整數位置產生遺漏的樣本,也稱為三次方卷積插補點。

圖 11.顯示 4:2:0 到 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 色度取樣方格間距的四圖元位移) 。 不過,MPEG-2 格式的 4:2:0 視訊可能較常用於電腦,而且不會遭受此問題的影響。 此外,區別在合理的高圖片解析度上可能不是視覺有害的。 嘗試更正此問題時,會建立與垂直階段位移所討論的相同問題。

將 4:2:2 YUV 轉換為 4:4:4 YUV

將 4:2:2 YUV 轉換為 4:4:4 YUV 需要以兩個因素水準向上轉換。 先前針對垂直 upconversion 所描述的方法也可以套用至水準 upconversion。 若為 MPEG-2 和一個使用之一式的 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。 您也可以切換兩個 upconversion 程式的順序,因為作業順序對結果的視覺品質並不重要。

其他 YUV 格式

其他較不常見的 YUV 格式包括下列各項:

  • AI44 是一種以每個樣本 8 位表示的 Palettized YUV 格式。 每個範例都包含 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 中。 (雖然 chroma 取樣不同,但此記憶體配置與 NV12 類似。)
  • Y41P 是 4:1:1 封裝格式,且您和 V 會水準取樣每四個圖元一次。 每個 macropixel 包含三個位元組的 8 圖元,並具有下列位元組配置: U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y7
  • Y41T 與 Y41P 相同,但每個 Y 樣本的最小有效位會指定 chroma 索引鍵 (0 = 透明,1 = 不透明) 。
  • Y42T 與 UYVY 相同,但每個 Y 樣本的最小有效位會指定 chroma 索引鍵 (0 = 透明,1 = 不透明) 。
  • YV YU 相當於 YUYV,但您和 V 範例會交換。

識別媒體基礎中的 YUV 格式

本文所述的每個 YUV 格式都有指派的 FOURCC 程式碼。 FOURCC 程式碼是串連四個 ASCII 字元所建立的 32 位不帶正負號的整數。

有各種 C/C++ 宏可讓您更輕鬆地在原始程式碼中宣告 FOURCC 值。 例如, MAKEFOURCC 宏是在 Mmsystem.h 中宣告的,而在 Aviriff.h 中宣告 了則表示了一個 SMS 宏。 請使用它們,如下所示:

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。

在媒體基礎中,格式是由主要類型 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 影片

視訊媒體類型