YV12とは?4:2:0平面フォーマットの基礎とI420/NV12比較ガイド

YV12 とは — 概要

YV12(しばしば「Y'V12」や「YV12 planar」とも呼ばれる)は、ビデオや画像処理で広く使われるピクセルフォーマット(サブサンプリングされたYUV形式)の一つです。4:2:0 のチャンネル構成を持つ平面(planar)形式で、輝度(Y)と色差成分(クロマ)のデータを別々の平面に格納します。Y(輝度)→V(赤差)→U(青差)の順序で平面が並ぶ点が特徴で、同様の 4:2:0 平面形式である I420(IYUV、Y,U,V の順)との違いはクロマ平面の順序だけです。

基本的な性質と用語

  • サンプリング: 4:2:0(水平・垂直ともにクロマを半分にサンプリング)。1フレームあたりピクセル数の平均で 12 ビット(1.5 バイト/ピクセル)に相当。
  • 平面配置(planar): Y 平面、続いて V 平面、続いて U 平面の順で格納される(Y,V,U)。
  • 用途: ビデオ圧縮、キャプチャ、ストレージ、ビデオ処理ライブラリや古い Windows / DirectShow API などで見られる。
  • 色表現: 「YV12」自体はピクセル形式(サンプル配置)を定義するものであって、色空間(BT.601 / BT.709 等)やレンジ(フルレンジ/テレビレンジ)を必ずしも規定しない。実際の意味はコンテナやシステムの慣例に依存する。

メモリレイアウト(バイト配置の詳細)

幅 W、高さ H のフレームを仮定すると、YV12 の標準的なバイト配置は以下のようになります(ストライド(行バイト幅)にパディングがない理想的な場合)。

Y plane: W * H bytes           (1 byte per luma sample)
V plane: (W/2) * (H/2) bytes   (1 byte per subsampled V sample)
U plane: (W/2) * (H/2) bytes   (1 byte per subsampled U sample)
Total: W*H + 2*(W/2 * H/2) = W*H*1.5 bytes

重要点:

  • 幅 W、または高さ H は偶数である必要がある場合がほとんど。クロマが半分の解像度になるため、奇数だと配置がずれる/扱えない実装がある。
  • 多くの実装では各平面のストライド(行ごとのバイト数)にパディングを加えるため、実際のバイト数は W*H*1.5 よりも多くなることがある。特にハードウェアやDMAに合わせて 16 / 32 バイト境界でアラインされることがある。
  • I420 と比べると差はクロマ平面の順序(I420: Y, U, V / YV12: Y, V, U)だけだが、API に渡す時にポインタの割当て順序を間違えると色が反転する。

サイズ計算の実例

ストライド無し(ピッチ = 幅)で、幅 1280、高さ 720 の場合:

  • Y: 1280 * 720 = 921,600 bytes
  • V: (1280/2) * (720/2) = 640 * 360 = 230,400 bytes
  • U: 同上 = 230,400 bytes
  • 合計 = 1,382,400 bytes(= 1280 * 720 * 1.5)

色変換(YUV → RGB)の基礎

YV12 は Y とクロマ(U,V)を分離しているため、画面表示や処理のために RGB に変換する必要があります。色空間(BT.601 / BT.709)やレンジ(フル/限界)が異なると変換行列やオフセットが異なる点に注意してください。ここでは一般的な BT.601(限界レンジ: Y=16..235, Cb/Cr=16..240)に基づく整数ベースの標準式を示します。

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

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

ここで clamp() は 0..255 に収める関数です。浮動小数点版では、係数は BT.601 / BT.709 に対応して変わります。YV12 自体は色マトリクスを規定しないため、映像ソース(放送、映画、デバイス)やメタデータで指定された色空間に従って変換するのが正しい運用です。

I420 / YV12 / NV12 など、他フォーマットとの違い

  • I420 (別名 IYUV, YUV420p): Y, U, V の順で格納される 4:2:0 プラナル形式。YV12 はこれとほぼ同じだがクロマ順が V→U。
  • NV12: Y 平面の後にインタリーブされた UV 平面(UとVが交互に並ぶ)を持つセミプラナル(semi-planar)形式。多くの GPU / ハードウェアアクセラレーションが NV12 を優先サポートする。
  • YV16, YUY2 など: クロマサンプリングが 4:2:2 や 4:2:0 以外のフォーマットもある。用途や互換性で選択が変わる。

実装上の注意点と落とし穴

  • 必ず幅・高さが偶数かチェックする。奇数の場合はパディング行を足す等の処理が必要になる。
  • ストライド(pitch)と各平面の行アライメントに注意。多くの API やハードウェアは行バイトを 2/4/16/32 の境界に揃えることを要求する。ストライドがある場合、Y, V, U 各平面のポインタ計算はストライドに従って行う。
  • クロマ位置(サンプリング位置)の扱いは標準やライブラリにより異なる(center vs cosited)。ズレがあるとエッジ周りで色ズレが発生する。
  • 色空間(BT.601 / BT.709 / BT.2020)やレンジ(フル/リミテッド)がソースと変換側で一致しているかを確認する。誤ったマトリクスを使うと色かぶりやコントラストの違いが生じる。
  • API やライブラリによっては YV12 を I420 と同義に扱わず、クロマポインタだけ入れ替える必要がある。ポインタ順序に注意。

パフォーマンス面の考慮

YV12 はメモリ効率が高く、圧縮効率の面でも有利(クロマサブサンプリングでデータ量を削減)ですが、平面アクセスのためにキャッシュ効率が低下する場面があります。特にループで横方向に走査する処理や GPU テクスチャ転送時には、NV12 のようなセミプラナル(インタリーブ)フォーマットがパフォーマンス上有利なことが多いです。

  • CPU 上で高速変換する場合は、SIMD(SSE/NEON)を使って Y 平面とクロマ平面を同時に処理する最適化が有効。
  • GPU 転送やハードウェアデコーダを使う場合、サポートされるピクセルフォーマット(多くは NV12)に合わせる必要がある。場合によっては YV12 ↔ NV12 の変換コストが発生する。
  • メモリの連続性(各平面を連続バッファに格納)やアライメントを整えることで DMA 転送やキャッシュ挙動が改善される。

実際の使用例・互換性

  • 古い DirectShow/Windows の API やいくつかの VFW(Video for Windows)環境で YV12 の FourCC が使われてきた歴史がある。
  • ビデオキャプチャデバイスやソフトウェアエンコーダ/デコーダ間での中間フォーマットとして利用されることがある。
  • 現代のハードウェアやブラウザのビデオパイプラインでは NV12 の方が広く最適化されているため、YV12 はソフトウェア処理系で見る機会が比較的多い。

トラブルシューティングのヒント

  • 色が赤/青反転して見える → U と V の平面が入れ違っている(I420 と YV12 の順序違いを疑う)。
  • 縞やぎざぎざが出る → 奇数幅/奇数高さによるクロマサンプリングのズレ、またはストライドの取り扱いミス。
  • 色が薄い/コントラストが変 → 色空間(BT.601 と BT.709)のミスマッチ、あるいはフルレンジ/リミテッドレンジの違い。
  • パフォーマンスが悪い → 平面レイアウトゆえにキャッシュミスが発生している可能性。NV12 等との比較を検討。

まとめ

YV12 は汎用性の高い 4:2:0 平面ピクセルフォーマットで、Y, V, U の順序で格納されることが最大の特徴です。I420 とほぼ同等であるもののクロマ平面の並びが異なるため、APIやライブラリ間のデータ受け渡しでは順序に細心の注意が必要です。色変換に際しては色空間とレンジの扱いが正確であることが重要で、パフォーマンス要件に応じて NV12 等の他フォーマットへの変換を検討するとよいでしょう。

参考文献