Media Foundation でYUV→RGB変換

· · Media Foundation, C++, Windows開発, 動画処理, YUV

結論

Media Foundationのdecoderから出てくるフレームは NV12YUY2 などのYUV形式です。RGB画像として扱うには変換が必要です。

2つのパターン

  1. 自動変換MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING を有効にして RGB32 を要求(静止画抽出やサムネイル向け)
  2. 自前変換NV12/YUY2 を受け取って自分でRGBに変換(大量処理や色の制御が必要な場合向け)

処理の流れ

MP4ファイル → decoder → NV12/YUY2のフレーム
                         ↓
           パターンA: Source Readerの自動変換 → RGB32
           パターンB: 自前変換コード → BGRA

YUVの基本

サブサンプリング(色の間引き方)

形式 意味 代表例
4:4:4 各画素がY/U/Vをそれぞれ持つ AYUV
4:2:2 横2画素でU/Vを共有 YUY2
4:2:0 2x2画素でU/Vを共有 NV12

NV12(4:2:0)

2x2ブロックの4画素が1組のU/Vを共有します。Yは各画素ごと、UVプレーンは別にあります。

YUY2(4:2:2)

横2画素が1組のU/Vを共有。バイト列は Y0 U Y1 V Y2 U Y3 V ... と並びます。

変換で見るべき情報

  • MF_MT_YUV_MATRIX:色変換行列(BT.601かBT.709か)
  • MF_MT_VIDEO_NOMINAL_RANGE:輝度範囲(通常は16〜235のlimited range)

これらを見ずに変換すると色ずれが起きます。対応していない値はエラーにするのが安全です。

パターンA:自動変換(おすすめの第一歩)

やり方

  1. Source Reader作成時に MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING = TRUE
  2. 出力メディアタイプを MFVideoFormat_RGB32 に設定
  3. ReadSample でRGB32フレームを取得

注意点

  • この変換はソフトウェア処理で、リアルタイム再生向けではない
  • RGB32 の4バイト目はアルファとは限らない(PNG保存前に 0xFF で埋める)
  • 数フレームの処理なら十分実用的

パターンB:自前変換

向いているケース

  • 大量フレーム処理で最適化したい
  • BT.601/BT.709/rangeを明示的に制御したい
  • RGB32 以外の出力形式が必要
  • GPUやSIMDと組み合わせたい

変換の手順

  1. Source Readerの出力を NV12YUY2 にする
  2. メディアタイプからサイズ、stride、matrix、rangeを取得
  3. バッファをロックして画素データを読む
  4. 各画素のY/U/Vを求め、変換行列をかけてBGRAに変換

変換式(BT.601 limited range)

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

R = clip(1.164 * C + 1.596 * E)
G = clip(1.164 * C - 0.392 * D - 0.813 * E)
B = clip(1.164 * C + 2.017 * D)

BT.709では係数が変わります。

strideの注意

行ごとのバイト数は width * bytesPerPixel とは限りません。実際のstrideは IMF2DBuffer::Lock2D が返す値を使います。またbottom-up画像ではstrideが負になることがあります。

実務で踏みやすい落とし穴

  1. RGB32 をアルファ付きRGBAだと思い込む — 4バイト目は不透明に固定する
  2. width * bytesPerPixel でstrideを決め打ちする — 実際のstrideを使う
  3. color metadataを見ずにBT.601/BT.709を推測する — 色ずれはクラッシュしないので気付きにくい
  4. NV12 のUVプレーンオフセットを width * height で計算する — 実際のstrideとheightで計算する
  5. インターレース動画をプログレッシブ前提で処理する — 櫛状ノイズの原因になる

選び方の目安

観点 自動変換 自前変換
実装の速さ
数枚の静止画抽出
大量フレーム/リアルタイム
matrix/rangeの明示制御
RGB32以外の出力

まず自動変換で正しい絵を確認し、必要なら自前変換に置き換えるのが実務で有効な順番です。

関連する記事

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

Media Foundation でMP4から静止画を切り出す

Media Foundation の Source Reader で MP4 から指定時刻に最も近いフレームを取り出し、PNG として保存する手順を解説します。シーク誤差や stride、RGB32 のアルファ未定義などの落とし穴と、安定動作させるための実装ポイントが分かります。

記事を読む

共有メモリの安全な使い方

共有メモリを実務で扱うときの典型的な落とし穴を整理し、同期、可視性、寿命、ABI、権限、クラッシュ復旧まで踏まえた事故率の低い設計の出発点を、Windows と POSIX の両方の API を交えながら具体的に示します。

記事を読む

関連トピック

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

このテーマがつながるサービス

この記事は次のサービスページにつながります。近い入口からご覧ください。

ブログ一覧に戻る