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 チャネルとも呼ばれます) をエンコードし、各 U または V の彩度サンプルをエンコードするためにサンプルごとに 8 ビットを使用します。 ただし、ほとんどのYUV形式では、Yのサンプル数よりもUとVのサンプル数が少ないため、1ピクセルあたりのビット数は平均で24ビット未満になります。この記事では、Yチャンネルが10ビット以上のYUV形式については扱いません。
注
この記事の目的上、U という用語は Cb に相当し、V という用語は Cr に相当します。
この記事では、次のトピックについて説明します。
- YUV のサンプリング。 最も一般的な YUV サンプリング手法について説明します。
- サーフェス定義。 推奨される YUV 形式について説明します。
- 色空間と彩度サンプリング レートの変換。 YUV 形式と RGB 形式間の変換と、異なる YUV 形式間の変換に関するいくつかのガイドラインを提供します。
- Media Foundation での YUV 形式の識別。 Media Foundation で YUV 形式の種類を記述する方法について説明します。
YUV サンプリング
クロマチャンネルは、知覚品質を劇的に失うことなく、ルマチャンネルよりも低いサンプリングレートを持つことができます。 "A:B:C" 表記と呼ばれる表記は、UおよびVがYに対してどのくらいの頻度でサンプリングされるかを表すために使用されます。
- 4:4:4は、クロムチャンネルのダウンサンプリングがないことを意味します。
- 4:2:2 は 2:1 水平ダウンサンプリングを意味し、垂直ダウンサンプリングは行われません。 すべてのスキャン ラインには、2 つの U または V サンプルごとに 4 つの Y サンプルが含まれています。
- 4:2:0 は 2:1 水平ダウンサンプリングを意味し、垂直ダウンサンプリングは 2:1 です。
- 4:1:1 は 4:1 水平ダウンサンプリングを意味し、垂直ダウンサンプリングは行われません。 各 U および V サンプルに対して、すべてのスキャンラインには 4 つの Y サンプルが含まれています。 4:1:1 サンプリングは他の形式ほど一般的ではなく、この記事では詳しく説明しません。
次の図は、ダウンサンプリングレートごとに彩度がどのようにサンプリングされるかを示しています。 Lumaサンプルは十字で表され、彩度サンプルは円で表されます。
4:2:2 サンプリングの主要な形式は、ITU-R Recommendation BT.601 で定義されています。 4:2:0 サンプリングには 2 つの一般的なバリエーションがあります。 そのうちの 1 つは MPEG-2 ビデオで使用され、もう 1 つは MPEG-1 と ITU-T Recommendations H.261 および H.263 で使用されます。
MPEG-1 スキームと比較すると、MPEG-2 スキームと、4:2:2 および 4:4:4 形式に定義されているサンプリング グリッドの間で変換する方が簡単です。 このため、WINDOWS では MPEG-2 スキームが推奨され、4:2:0 形式の既定の解釈と見なす必要があります。
Surface の定義
このセクションでは、ビデオ レンダリングに推奨される 8 ビット YUV 形式について説明します。 これらはいくつかのカテゴリに分類されます。
- 4:4:4 フォーマット、ピクセルあたり 32 ビット
- 4:4:4 フォーマット、ピクセルあたり 24 ビット
- 4:2:2 フォーマット、ピクセルあたり 16 ビット
- 4:2:0 フォーマット、ピクセルあたり 16 ビット
- 4:2:0 フォーマット、ピクセルあたり 12 ビット
まず、次の点を理解するために、次の概念に注意する必要があります。
- Surface の原点。 この記事で説明する YUV 形式の場合、原点 (0,0) は常にサーフェスの左上隅です。
- ストライド。 サーフェスのストライド (ピッチとも呼ばれます) は、サーフェスの幅 (バイト単位) です。 左上隅に Surface の原点がある場合、Stride は常にポジティブです。
- 配置。 サーフェスの配置は、グラフィックス ディスプレイ ドライバーの判断で行われます。 サーフェスは常に DWORD で整列する必要があります。つまり、サーフェス内の個々の行は、32 ビット (DWORD) 境界に由来することが保証されます。 ただし、ハードウェアのニーズに応じて、アラインメントは 32 ビットを超える場合があります。
- パック形式と平面形式。 YUV 形式は、 パック形式 と 平面 形式に分割されます。 パック形式では、Y、U、V の各コンポーネントが 1 つの配列に格納されます。 ピクセルはマクロピクセルのグループに編成され、レイアウトは形式によって異なります。 平面形式では、Y、U、および V コンポーネントは 3 つの別々の平面として格納されます。
この記事で説明する各 YUV 形式には、FOURCC コードが割り当てられます。 FOURCC コードは、4 つの ASCII 文字を連結して作成される 32 ビット符号なし整数です。
- 4:4:4 (32 bpp)
- 4:4:4 (24 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 形式を使用することをお勧めします。 これはパック形式であり、各ピクセルは 4 つの連続したバイトとしてエンコードされ、次の図に示すシーケンスに配置されます。
A とマークされたバイトには、アルファの値が含まれています。
4:4:4 フォーマット、ピクセルあたり 24 ビット
I444
I444 形式では、すべての Y サンプルが、符号なし文字値の配列としてメモリ内で最初に表示されます。 この配列の直後に、すべての U (Cb) サンプルが続きます。 U平面のストライドはY平面の同じストライドです。U 平面には、Y 平面と同じ数の線が含まれています。 U 平面の直後に、すべての V (Cr) サンプルが続き、U 平面と同じストライドとライン数が表示されます。 Y/U/V プレーンのパディングはありません。
4:2:2 フォーマット、ピクセルあたり 16 ビット
次の FOURCC コードを使用して、2 つの 4:2:2 形式をお勧めします。
- YUY2
- UYVY
どちらもパック形式であり、各マクロピクセルは 4 つの連続したバイトとしてエンコードされた 2 ピクセルです。 これにより、彩度が 2 倍の水平ダウンサンプリングが行われます。
YUY2
YUY2 形式では、データは符号なし 文字 値の配列として扱うことができます。最初のバイトには最初の Y サンプルが含まれ、2 番目のバイトには最初の U (Cb) サンプルが含まれ、3 番目のバイトには 2 番目の Y サンプルが含まれ、4 番目のバイトには最初の V (Cr) サンプルが含まれます。次の図に示すようにします。
イメージがリトル エンディアン WORD 値の配列としてアドレス指定されている場合、最初の WORD には下位ビット (LSB) の最初の Y サンプルと、最上位ビット (MSB) の最初の U (Cb) サンプルが含まれます。 2 番目の WORD には、LSB の 2 番目の Y サンプルと、MSB の最初の V (Cr) サンプルが含まれています。
YUY2 は、Microsoft DirectX ビデオ アクセラレーション (DirectX VA) に推奨される 4:2:2 ピクセル形式です。 これは、4:2:2 ビデオをサポートする DirectX VA アクセラレータの中間的な要件になると予想されます。
UYVY
この形式は YUY2 形式と同じですが、バイト順が逆の場合、つまり、クロマバイトとルマバイトが反転されます (図 4)。 イメージが 2 つのリトル エンディアン WORD 値の配列としてアドレス指定されている場合、最初の WORD には LSB に U が、MSB には Y0 が、2 番目の WORD には LSB に V、MSB に Y1 が含まれます。
I422
I422 形式では、すべての Y サンプルが、符号なし文字値の配列としてメモリ内で最初に表示されます。 この配列の直後に、すべての U (Cb) サンプルが続きます。 U平面のストライドはY平面の半分のストライドです。U 平面には、Y 平面と同じ数の線が含まれています。 次の図に示すように、U 平面の直後に、U 平面と同じストライドとライン数を持つすべての V (Cr) サンプルが続きます。 Y/U/V プレーンのパディングはありません。
4:2:0 フォーマット、ピクセルあたり 16 ビット
2 つの 4:2:0 16 ビット/ピクセル (bpp) 形式をお勧めします。FOURCC コードは次のとおりです。
- IMC1
- IMC3
これらの YUV 形式はどちらも平面形式です。 彩度チャネルは、水平寸法と垂直寸法の両方で2の係数でサブサンプリングされます。
IMC1
すべての Y サンプルは、符号なし char 値の配列としてメモリ内で最初に表示されます。 その後、すべての V (Cr) サンプルと、すべての U (Cb) サンプルが続きます。 図 5 に示すように、V 平面と U 平面は Y 平面と同じストライドを持ち、メモリの未使用領域になります。 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 フォーマット、ピクセルあたり 12 ビット
次の FOURCC コードを使用して、4:2:0 12-bpp 形式を 4 つ使用することをお勧めします。
- IMC2
- IMC4
- YV12
- NV12
これらのすべてのフォーマットにおいて、彩度チャンネルは水平寸法と垂直寸法の両方で2の係数でサブサンプリングされます。
IMC2
この形式は、次の違いを除いて IMC1 と同じです。V (Cr) と U (Cb) の行は、ハーフストライド境界でインターリーブされます。 つまり、彩度領域の各フルストライドラインはVサンプルのラインから始まり、次のハーフストライド境界から始まるUサンプルのラインが続きます(図7)。 このレイアウトでは、IMC1 よりもアドレス空間を効率的に使用できます。 これは、彩度のアドレス空間を半分に削減し、合計アドレス空間を 25% 削減します。 4:2:0 形式の中で、IMC2 は NV12 より後の 2 番目に優先される形式です。 次の図は、このプロセスを示しています。
IMC4
この形式は IMC2 と同じですが、次の図に示すように、U (Cb) 行と V (Cr) 行がスワップされる点が異なります。
YV12
すべての Y サンプルは、符号なし char 値の配列としてメモリ内で最初に表示されます。 この配列の直後に、すべての V (Cr) サンプルが続きます。 V平面のストライドはY平面の半分のストライドです。V 平面には、Y 平面の半分の線が含まれています。 次の図に示すように、V 平面の直後に、V 平面と同じストライドとライン数を持つすべての U (Cb) サンプルが続きます。
NV12
すべての Y サンプルは、偶数行の符号なし char 値の配列としてメモリ内で最初に表示されます。 Y 平面の直後に、パックされた U (Cb) サンプルと V (Cr) サンプルを含む符号なし char 値の配列が続きます。 結合された U-V 配列がリトル エンディアン WORD 値の配列としてアドレス指定されている場合、LSB には U 値が含まれており、MSB には V 値が含まれます。 NV12 は、DirectX VA に推奨される 4:2:0 ピクセル形式です。 これは、4:2:0 ビデオをサポートする DirectX VA アクセラレータの中間的な要件になると予想されます。 次の図は、Y 平面と、パックされた you サンプルと V サンプルを含む配列を示しています。
色空間と彩度サンプリング レートの変換
このセクションでは、YUV と RGB の間の変換と、いくつかの異なる YUV 形式間の変換に関するガイドラインを示します。 このセクションでは、 8 ビット コンピューター RGB (sRGB または "フルスケール" RGB とも呼ばれます) と スタジオ ビデオ RGB、または "ヘッドルームとトゥルームを含む RGB" という 2 つの 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 カラーの原色の定義 ITU-R BT.709 で指定されています。 R、G、B の (x,y) 座標はそれぞれ (0.64、0.33)、(0.30、0.60)、および (0.15,0.06) です。 白色点は、座標 (0.3127、0.3290) の D65 です。 名目ガンマは 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 に変換することをお勧めします。 4:4:4 形式の AYUV 形式では、Y、U、V の各サンプルにそれぞれ 8 ビットが使用されます。 YUV は、一部のアプリケーションでサンプルあたり 8 ビットを超えるビットを使用して定義することもできます。
RGB からの 2 つの主要な YUV 変換がデジタル ビデオ用に定義されています。 どちらも、ITU-R Recommendation BT.709 と呼ばれる仕様に基づいています。 最初の変換は、BT.709 で 50 Hz で使用するために定義された古い YUV 形式です。 これは、ITU-R Recommendation BT.601 で指定された関係と同じです。これは、以前の名前である CCIR 601 でも知られています。 これは、標準定義テレビ解像度 (720 x 576) と低解像度ビデオの推奨 YUV 形式と見なす必要があります。 これは、2 つの定数 Kr と Kb の値によって特徴付 けます。
Kr = 0.299
Kb = 0.114
2 番目の変換は、BT.709 で 60 Hz を使用するために定義された新しい YUV フォームであり、SDTV 上のビデオ解像度の推奨形式と見なす必要があります。 これは、次の 2 つの定数に対して異なる値が特徴です。
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 になります。 スタジオ ビデオ 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 サンプルは明るさを表し、You サンプルと 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 に変換するには、2 倍の垂直アップコンバージョンが必要です。 このセクションでは、アップコンバージョンを実行するためのメソッドの例について説明します。 このメソッドは、ビデオ画像がプログレッシブ スキャンであることを前提としています。
注
4:2:0 から 4:2:2 のインターレース スキャン変換プロセスでは、非現実的な問題が発生し、実装が困難です。 この記事では、インターレース スキャンを 4:2:0 から 4: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] の範囲へのクリッピングを表します。
注
エッジを処理するための数式は、数学的に簡略化できます。 図の端のクランプ効果を示すために、この形式で示します。
実際には、このメソッドは、隣接する 4 つのピクセル上の曲線を補間し、2 つの最も近いピクセルの値に重み付けすることで、各欠損値を計算します (図 11)。 この例で使用する特定の補間方法では、3 次畳み込み補間とも呼ばれる、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 の彩度サンプリング グリッドの間隔に対する 4 分の 1 ピクセルオフセット) に対する 1/5 ピクセルの水平オフセットでシフトされます。 ただし、MPEG-2 形式の 4:2:0 ビデオは、おそらく PC でより一般的に使用され、この問題の影響を受けません。 さらに、この区別は、合理的に高い画像解像度では視覚的に害を受けないでしょう。 この問題を修正しようとすると、垂直位相オフセットについて説明したのと同じ種類の問題が作成されます。
4:2:2 YUV から 4:4:4 YUV への変換
4:2:2 YUV から 4:4:4 YUV に変換するには、2 倍の水平方向のアップコンバージョンが必要です。 前に垂直アップコンバージョンについて説明した方法は、水平のアップコンバージョンにも適用できます。 MPEG-2 および ITU-R BT.601 ビデオの場合、このメソッドは正しい位相アラインメントを持つサンプルを生成します。
4:2:0 YUV から 4:4:4 YUV への変換
4:2:0 YUV を 4:4:4 YUV に変換するには、前に説明した 2 つの方法に従うだけです。 4:2:0 イメージを 4:2:2 に変換し、4:2:2 イメージを 4:4:4 に変換します。 また、2 つのアップコンバージョン プロセスの順序を切り替えることもできます。これは、操作の順序が結果の視覚的品質にとって重要ではないためです。
YUY2 から I422 への変換
4:2:2 カラー形式の場合、一部のデコーダーは既定でMFVideoFormat_YUY2出力できます。これはパック形式です。 ただし、多くのエンコーダーでは、MFVideoFormat_I422平面形式での入力が必要です。 このような場合、トランスコード ビデオ プロセッサ Media Foundation Transform (一般に "XVP" と呼ばれます) をパイプラインに挿入して、MFVideoFormat_YUY2をMFVideoFormat_I422に変換できます。 詳細については、「 ビデオ プロセッサ Media Foundation Transform のコード変換」を参照してください。 この例では、XVP を使用して、エンコード ワークフローに対してこの変換を実行する方法を示します。
#include <mfapi.h>
#include <wmcodecdsp.h> // CLSID_VideoProcessorMFT
using Microsoft::WRL;
HRESULT ConvertYUY2toI422WithXVP(
_In_ IMFSample* inputSample,
_In_ MFT_OUTPUT_DATA_BUFFER* outputBuffer,
UINT32 width,
UINT32 height)
{
RETURN_HR_IF_NULL(E_INVALIDARG, inputSample);
RETURN_HR_IF_NULL(E_INVALIDARG, outputBuffer);
ComPtr<IMFTransform> xvp;
RETURN_IF_FAILED(CoCreateInstance(
CLSID_VideoProcessorMFT,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&xvp)));
// Set input type: MFVideoFormat_YUY2
ComPtr<IMFMediaType> inputType;
RETURN_IF_FAILED(MFCreateMediaType(&inputType));
RETURN_IF_FAILED(inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
RETURN_IF_FAILED(inputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2));
RETURN_IF_FAILED(MFSetAttributeSize(inputType.Get(), MF_MT_FRAME_SIZE, width, height));
RETURN_IF_FAILED(spXVP->SetInputType(0, inputType.Get(), 0));
// Set output type: MFVideoFormat_I422
ComPtr<IMFMediaType> outputType;
RETURN_IF_FAILED(MFCreateMediaType(&outputType));
RETURN_IF_FAILED(outputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
RETURN_IF_FAILED(outputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_I422));
RETURN_IF_FAILED(MFSetAttributeSize(outputType.Get(), MF_MT_FRAME_SIZE, width, height));
RETURN_IF_FAILED(xvp->SetOutputType(0, outputType.Get(), 0));
// Submit input sample
RETURN_IF_FAILED(xvp->ProcessInput(0, inputSample, 0));
// Request the converted output sample
DWORD status = 0;
return xvp->ProcessOutput(0, 1, outputBuffer, &status);
}
AYUV から I444 への変換
4:4:4 カラー形式の場合、一部のデコーダーは既定でMFVideoFormat_AYUV出力できます。これはパック形式です。 ただし、多くのエンコーダーでは、MFVideoFormat_I444平面形式での入力が必要です。 このような場合、トランスコーディング ビデオ プロセッサ Media Foundation Transform (XVP) をパイプラインに挿入して、MFVideoFormat_AYUVをMFVideoFormat_I444に変換できます。 この例では、XVP を使用して、エンコード ワークフローに対してこの変換を実行する方法を示します。
#include <mfapi.h>
#include <wmcodecdsp.h> // CLSID_VideoProcessorMFT
using Microsoft::WRL;
HRESULT ConvertAYUVtoI444WithXVP(
_In_ IMFSample* inputSample,
_In_ MFT_OUTPUT_DATA_BUFFER* outputBuffer,
UINT32 width,
UINT32 height)
{
RETURN_HR_IF_NULL(E_INVALIDARG, inputSample);
RETURN_HR_IF_NULL(E_INVALIDARG, outputBuffer);
ComPtr<IMFTransform> xvp;
RETURN_IF_FAILED(CoCreateInstance(
CLSID_VideoProcessorMFT,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&xvp)));
// Set input type: MFVideoFormat_AYUV
ComPtr<IMFMediaType> inputType;
RETURN_IF_FAILED(MFCreateMediaType(&inputType));
RETURN_IF_FAILED(inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
RETURN_IF_FAILED(inputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV));
RETURN_IF_FAILED(MFSetAttributeSize(inputType.Get(), MF_MT_FRAME_SIZE, width, height));
RETURN_IF_FAILED(xvp->SetInputType(0, inputType.Get(), 0));
// Set output type: MFVideoFormat_I444
ComPtr<IMFMediaType> outputType;
RETURN_IF_FAILED(MFCreateMediaType(&outputType));
RETURN_IF_FAILED(outputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
RETURN_IF_FAILED(outputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_I444));
RETURN_IF_FAILED(MFSetAttributeSize(outputType.Get(), MF_MT_FRAME_SIZE, width, height));
RETURN_IF_FAILED(xvp->SetOutputType(0, outputType.Get(), 0));
// Submit input sample
RETURN_IF_FAILED(xvp->ProcessInput(0, inputSample, 0));
// Request the converted output sample
DWORD status = 0;
return xvp->ProcessOutput(0, 1, outputBuffer, &status);
}
その他 YUV 形式
その他の一般的でない YUV 形式には、次のようなものがあります。
- AI44 は、サンプルあたり 8 ビットのパレット化された YUV 形式です。 各サンプルには、4 つの最上位ビット (MSB) のインデックスと、4 つの最下位ビット (LSB) のアルファ値が含まれています。 インデックスは、形式のメディアの種類で定義する必要がある YUV パレット エントリの配列を参照します。 この形式は、主にサブ画像に使用されます。
- NV11 は、ピクセルあたり 12 ビットの 4:1:1 平面形式です。 Y サンプルはメモリ内で最初に表示されます。 Y 平面の後に、パックされた U (Cb) サンプルと V (Cr) サンプルの配列が続きます。 結合された U-V 配列がリトル エンディアン WORD 値の配列としてアドレス指定されている場合、U サンプルは各 WORD の LSB に含まれており、V サンプルは MSB に含まれます。 (このメモリ レイアウトは NV12 に似ていますが、彩度サンプリングは異なります)。
- Y41P は 4:1:1 パック形式で、U と V は水平方向に4ピクセルごとにサンプリングされます。 各マクロピクセルには 3 バイトで 8 ピクセルが含まれています。バイト レイアウトは次のとおりです。
U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y7
- Y41T は Y41P と同じですが、各 Y サンプルの最下位ビットがクロム キー (0 = 透明、1 = 不透明) を指定する点が異なります。
- Y42T は UYVY と同じですが、各 Y サンプルの最下位ビットが彩度キー (0 = 透明、1 = 不透明) を指定する点が異なります。
- YVYU は、YOU サンプルと V サンプルがスワップされる点を除き、YUYV と同等です。
Media Foundation での YUV 形式の識別
この記事で説明する各 YUV 形式には、FOURCC コードが割り当てられます。 FOURCC コードは、4 つの ASCII 文字を連結して作成される 32 ビット符号なし整数です。
ソース コードで FOURCC 値を簡単に宣言できるようにするさまざまな C/C++ マクロがあります。 たとえば、 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」を参照してください。
関連トピック