Media Foundation でYUV→RGB変換
結論
Media Foundationのdecoderから出てくるフレームは NV12 や YUY2 などのYUV形式です。RGB画像として扱うには変換が必要です。
2つのパターン:
- 自動変換:
MF_SOURCE_READER_ENABLE_VIDEO_PROCESSINGを有効にしてRGB32を要求(静止画抽出やサムネイル向け) - 自前変換:
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:自動変換(おすすめの第一歩)
やり方
- Source Reader作成時に
MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING = TRUE - 出力メディアタイプを
MFVideoFormat_RGB32に設定 ReadSampleでRGB32フレームを取得
注意点
- この変換はソフトウェア処理で、リアルタイム再生向けではない
RGB32の4バイト目はアルファとは限らない(PNG保存前に0xFFで埋める)- 数フレームの処理なら十分実用的
パターンB:自前変換
向いているケース
- 大量フレーム処理で最適化したい
BT.601/BT.709/rangeを明示的に制御したいRGB32以外の出力形式が必要- GPUやSIMDと組み合わせたい
変換の手順
- Source Readerの出力を
NV12かYUY2にする - メディアタイプからサイズ、stride、matrix、rangeを取得
- バッファをロックして画素データを読む
- 各画素の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が負になることがあります。
実務で踏みやすい落とし穴
RGB32をアルファ付きRGBAだと思い込む — 4バイト目は不透明に固定するwidth * bytesPerPixelでstrideを決め打ちする — 実際のstrideを使う- color metadataを見ずにBT.601/BT.709を推測する — 色ずれはクラッシュしないので気付きにくい
NV12のUVプレーンオフセットをwidth * heightで計算する — 実際のstrideとheightで計算する- インターレース動画をプログレッシブ前提で処理する — 櫛状ノイズの原因になる
選び方の目安
| 観点 | 自動変換 | 自前変換 |
|---|---|---|
| 実装の速さ | ◎ | △ |
| 数枚の静止画抽出 | ◎ | ○ |
| 大量フレーム/リアルタイム | △ | ◎ |
| matrix/rangeの明示制御 | △ | ◎ |
| RGB32以外の出力 | △ | ◎ |
まず自動変換で正しい絵を確認し、必要なら自前変換に置き換えるのが実務で有効な順番です。
関連する記事
同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。
Media Foundation で動画に画像・文字を合成する
Media Foundation で MP4 の各フレームに画像と文字を焼き込み、新しい MP4 として書き出す流れを Source Reader、描画、色変換、Sink Writer の四段階で整理し、そのまま貼れる C++ サンプルで動かしながら学べます。
Media Foundation でMP4から静止画を切り出す
Media Foundation の Source Reader で MP4 から指定時刻に最も近いフレームを取り出し、PNG として保存する手順を解説します。シーク誤差や stride、RGB32 のアルファ未定義などの落とし穴と、安定動作させるための実装ポイントが分かります。
Media Foundation 入門【COMベースのWindowsメディアAPI】
Media Foundation の全体像を、Source Reader / Sink Writer / MFT / Media Session といった部品の役割と、COM 由来の HRESULT・GUID・apartment がどこに顔を出すかから整理します。最初に押さ...
共有メモリの安全な使い方
共有メモリを実務で扱うときの典型的な落とし穴を整理し、同期、可視性、寿命、ABI、権限、クラッシュ復旧まで踏まえた事故率の低い設計の出発点を、Windows と POSIX の両方の API を交えながら具体的に示します。
C#をNative AOTでDLL化しC/C++から呼び出す方法
C# のクラスライブラリを Native AOT でネイティブ DLL として発行し、UnmanagedCallersOnly で C/C++ から呼び出す構成を、設計指針・最小実装・はまりどころまでまとめて整理した実務向け解説記事です。
関連トピック
このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。
Windows技術トピック
Windows 開発、不具合調査、既存資産活用の技術トピックをまとめた入口です。
このテーマがつながるサービス
この記事は次のサービスページにつながります。近い入口からご覧ください。
Windowsアプリ開発
業務アプリ、装置連携、通信ツールなどの Windows ソフト開発を支援します。