影片渲染的建議 8 位元 YUV 格式
加里·沙利文和斯蒂芬·埃斯特羅普
Microsoft公司
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 位,因為它們的 U 和 V 的樣本比 Y 的少。本文未涵蓋 10 位以上 Y 通道的 YUV 格式。
注意
為了本文的目的,U 一詞相當於 Cb,而 V 一詞相當於 Cr。
本文涵蓋下列主題:
- YUV 取樣。 描述最常見的 YUV 取樣技術。
- 表面定義。 描述建議的 YUV 格式。
- 色彩空間和色度取樣率轉換。 提供在 YUV 和 RGB 格式之間轉換,以及在不同 YUV 格式之間進行轉換的一些指導方針。
- 在 Media Foundation 架構中識別 YUV 格式。 說明如何描述 Media Foundation 中的 YUV 格式類型。
YUV 取樣
色度通道的取樣率可能低於 luma 通道,而不會大幅喪失感知品質。 稱為 “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 水準向下取樣,沒有垂直向下取樣。 每個掃描行都包含四個 Y 樣本對應於每個 U 和 V 樣本。 4:1:1 取樣比其他格式不太常見,本文不會詳細討論。
下列圖表顯示了每種下取樣速率的色度取樣方式。 Luma 樣本是以十字表示,色度樣本則以圓形表示。
4:2:2 取樣的主要形式定義於建議 BT.601 ITU-R。 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 格式的默認解譯。
表面定義
本節說明建議用於視訊轉譯的 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 bpp)
- 4:2:2 (16 bpp)
- 4:2:0 (16 bpp)
- 4:2:0 (12 bpp)
4:4:4 格式,每個像素 32 位元
AYUV
建議使用 FOURCC 代碼 AYUV 的單一 4:4:4 格式。 這是包裝格式,其中每個像素都會編碼為四個連續位元組,並依下圖所示的順序排列。
標示為 A 的位元組包含 Alpha 的值。
4:2:2 格式,每個像素 16 位元
建議使用兩種 4:2:2 格式,使用下列 FOURCC 代碼:
- YUY2
- UYVY
兩者都是封裝格式,其中每個巨像素是將兩個像素編碼為四個連續位元組。 這會導致色度水準降低兩倍。
YUY2
在 YUY2 格式中,數據可以視為不帶正負號 char 值的陣列,其中第一個字節包含第一個 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 格式相同,但位元節順序反轉,也就是說,色度和 luma 位元組會翻轉(圖 4)。 如果影像是以兩個字節 WORD 值的數位來尋址,則第一個 WORD 在 MSB 的 LSB 和 Y0 中包含 U,而第二個 WORD 在 MSB 的 LSB 和 Y1 中包含 V。
4:2:0 格式,每像素 16 位元
建議使用以下 FOURCC 代碼的兩種 4:2:0 16 位元(bpp)格式:
- IMC1
- IMC3
這兩種 YUV 格式都是平面格式。 色度通道會由水平和垂直維度中的兩個因數進行子取樣。
IMC1
所有 Y 範例都會先以無符號 char 值陣列的形式出現在記憶體中。 接著是所有 V (Cr) 樣本,然後是所有 U (Cb) 樣本。 V 和 U 平面的步幅與 Y 平面相同,導致記憶體區域未使用,如圖 5 所示。 U 和 V 平面必須從 16 行倍數的記憶體邊界開始。 圖 5 顯示 352 x 240 視訊畫面的 U 和 V 的來源。 U和平面的起始地址計算如下:
BYTE* pV = pY + (((Height + 15) & ~15) * Stride);
BYTE* pU = pY + (((((Height * 3) / 2) + 15) & ~15) * Stride);
其中 pY 是指向記憶體陣列開頭的位址指標,如下圖所示。
IMC3
此格式與 IMC1 相同,但 U 和 V 分量已互換,如下圖所示。
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 之後的第二個慣用格式。 下方圖片說明此過程。
IMC4
此格式與 IMC2 相同,但 U(Cb)和 V(Cr)行已互換,如下圖所示。
YV12
所有 Y 範例都會先以無符號 char 值陣列的形式出現在記憶體中。 此陣列緊接著所有 V (Cr) 範例。 V 平面的步幅是 Y 平面的步幅的一半,且 V 平面中包含的線條數量是 Y 平面的二分之一。 V 平面緊接著所有 U (Cb) 樣本,其步幅和行數與 V 平面相同,如下圖所示。
NV12
所有 Y 範例都會先以不帶正負號 字元陣列的形式出現在記憶體中, 具有偶數行的值。 Y 平面緊接著一個不帶正負號的 char 陣列,其 值中包含打包的 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 或「完整縮放」RGB,以及 工作室視訊 RGB,或「具有前端室和 Toe-room 的 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 = 235*2^(N-8) 表示。 不過,實際值可能超出此範圍。
在 Windows 中,Studio 視訊 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 Recommendation BT.709 的規格為基礎。 第一個轉換是為 50 Hz 使用而在 BT.709 中定義的較舊 YUV 格式。 它與 ITU-R 建議 BT.601 中指定的關聯相同,也稱為其舊名稱 CCIR 601。 它應該被視為標準解析度電視(720 x 576)和較低解析度視訊的首選 YUV 格式。 其特徵是兩個常數的值,Kr 和 Kb:
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)。
函式 floor(x) 會傳回小於或等於 x 的最大整數。 函式 clip3(x, y, z) 的定義如下:
clip3(x, y, z) = ((z < x) ? x : ((z > y) ? y : z))
注意
clip3 應該實作為函式,而不是預處理器巨集;否則會導致對參數的多次評估。
Y 樣本代表亮度,而 U 和 V 樣本分別代表藍色和紅色的色彩偏差。 Y 的名義範圍是 16*2^(M-8) 到 235*2^(M-8)。 黑色以 16*2^(M-8)表示,白色則以 235*2^(M-8) 表示。 U 和 V 的名義範圍是 16*2^(M-8) 到 240*2^(M-8),值 128*2^(M-8) 代表中性色度。 不過,實際值可能超出這些範圍。
針對以工作室視頻 RGB 格式的輸入數據,必須執行裁剪操作,以保持 U 值和 V 值在 0 到 (2^M)-1 的範圍內。 如果輸入是計算機 RGB,則不需要剪輯作業,因為轉換公式無法產生超出此範圍的值。
這些是沒有近似的確切公式。 本文件後面的所有內容都是基於這些公式。 本節說明下列轉換:
- 將 RGB888 轉換為 YUV 4:4:4
- 將 8 位 YUV 轉換為 RGB888
- 將 4:2:0 YUV 轉換為 4:2:2 YUV
- 將 4:2:2 YUV 轉換為 4:4:4 YUV
- 將 4:2:0 YUV 轉換為 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 需要由兩個因素進行垂直向上轉換。 本節說明執行 upconversion 的範例方法。 方法假設影片圖片是漸進式掃描。
注意
4:2:0 到 4: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);
其中 clip() 表示裁剪至範圍 [0..255]。
注意
處理邊緣的方程式可以數學簡化。 它們以這種形式顯示,以說明圖片邊緣的夾緊效果。
實際上,這個方法會藉由將曲線插補到四個相鄰圖元上來計算每個遺漏值,其加權會指向兩個最接近圖元的值(圖 11)。 此範例中使用的特定插值方法是利用一種眾所周知的方法,稱為「Catmull-Rom 插值」,在半整數位置生成遺漏樣點,這亦稱為立方卷積插值。
在信號處理術語中,垂直向上轉換應該理想地包含相位偏移補償,以考慮到 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 色度樣本的相位也會相對於 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 需要將水平方向升頻至兩倍。 先前所述的垂直向上轉換方法也可以套用至水平向上轉換。 針對 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 是一種具有每個樣本 8 位的調色盤 YUV 格式。 每個樣本都包含 4 個最大有效位 (MSB) 中的索引,以及 4 個最小有效位 (LSB) 中的 Alpha 值。 索引指的是一個包含 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 打包格式,其中 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
其中 XXXXXXXX
是FOURCC程式碼。 因此,YUY2 的子類型 GUID 為:
32595559-0000-0010-8000-00AA00389B71
最常見的 YUV 格式 GUID 常數定義於頭檔 mfapi.h 中。 如需這些常數的清單,請參閱 Video Subtype GUID。
相關主題