(この記事は私の blog の http://umezawa.dyndns.info/wordpress/?p=7392 の転載です)
要約
Media Foundation で RGB を扱うときはメディアタイプに必ず MF_MT_DEFAULT_STRIDE を付けよう。
内容
Windows Vista 以降には Media Foundation という新しいマルチメディアフレームワークがあります。新しいと言っても10年以上経ってますけど。
Media Foundation 映像のメディアタイプには optional な attribute として MF_MT_DEFAULT_STRIDE というものがあります。これは非圧縮フォーマットにおいてライン間のオフセットを指定するものですが、結果としてフォーマットの「方向」がトップダウンかボトムアップかを指定することができます。 Image Stride に書いてある通り、正の値だとトップダウンで、負の値だとボトムアップです。最初に optional と書いた通り、この attribute は無くてもよくて、その場合フォーマットのサブタイプ(RGB24とかYUY2とかそういうの)に応じたデフォルト値を使うことになります。
YUY2 とかなら方向はトップダウンに決まっているので話は簡単です。一方、RGB の場合はトップダウンもボトムアップも両方あるため、話が面倒になります。マイクロソフト製のコードですらこの辺りは混乱しており、MFT コーデックの出力フォーマットが MF_MT_DEFAULT_STRIDE を省略した RGB に設定されている場合、エクスプローラーのサムネイル生成ではボトムアップとして表示されますが、Windows Media Player や TopoEdit ではトップダウンとして表示されます。以前、Windows 10 だとエクスプローラーのサムネイル生成が上下反転するという問題があると書きましたが、それはこの辺の問題を踏んだせいで起きた現象というわけです。
どっちが正しいのか、ということもどうも判然としません。 Uncompressed Video Buffers という記事には「MF_MT_DEFAULT_STRIDE が省略されている場合は MFGetStrideForBitmapInfoHeader を読んで計算しろ」と書いてあります。この API は RGB フォーマットに対しては負の値を返すのですが、一般的に省略されている場合にボトムアップを仮定すべきなのかに関する直接的な記述は見つけられません。まあ、ボトムアップにしておくのが妥当な気はするのですが…
一応、コーデックがサポートしている出力フォーマットを返す際に RGB の場合は必ず MF_MT_DEFAULT_STRIDE を付けることで方向を固定することはできるようで、そうするとエクスプローラーのサムネイル生成でも Windows Media Player でも TopoEdit でも MF_MT_DEFAULT_STRIDE の付いたフォーマットが設定され、正しい方向で描画されます。というわけで、 optional といいつつ RGB の場合においてはほぼ必須 attribute という認識でいるべきです。もっとも、省略されたメディアタイプを設定された場合にどういう挙動をすべきか(設定を拒否するとかボトムアップを仮定するとか)は難しいところですし、サポートしている入力フォーマットを返す時は縦横ピクセル数が確定していないのでそもそも stride を計算できません。