C++でMicrosoft Media Session

 メジャーなコーデックとコンテナがMicrosoftのライブラリ自体に組み込まれたため、非常に強力になっているのだが、メディアファイルの扱いがDirectShowに比べてちょっと面倒になっている。DirectShowの様に、フィルターがないとどうしようもないというケースは少なくなったが、再生制御がMedia SessionでInvokeされるイベントありきになったため、再生と停止だけならともかく、シークやリウィンド、スローモーションなどはMedia Sessionイベント機構について知らないとなにをやっているかわからない。 が、一応そのあたりのサンプルはすでに用意されており、それを流用することでなんとか自分のものには出来る。

 上記サンプルはそれ単体では使えず、自分のプログラムで構築したMedia Sessionトポロジー等を渡して初期化すると、PlayerSeekingクラスから一応の制御は出来るようになる。トポロジーとは、DirectShowでいうところのフィルターグラフである。「ピン」の概念を使わなくなったのか、そういった類の抽象化はトポロジー構築には出てこない(詳しく調べていないので類似の抽象化はあるかもしれないが)。しかし、PlayerSeekingクラスはお世辞にもちゃんと作られたクラスとは言い難いので、修正しないと所望の動作にならない部分もいくつか出てくるだろう。そのあたりはMedia Sessionのお勉強だと思って読み、いじってみるのがいいだろう。さらに凝った機構がどうしても必要という時は、それらをPlayerSeekingと併用、若しくは包括するのも良いだろう。

  • 実際にはメディアソースの準備が整っただとかなんだとか、いろいろなことで細かくイベントがInvokeされる仕様になっているので、イベントに合わせてなにかしたいときはそれらについての理解と実装が必要になる。シーク処理も、イベント処理なしで実装だけならできるが、シークによってInvokeされるイベントを処理できないと、あまり上手な機構には出来ない。シークだけではなく、スクリブル処理などを実装するときは、プライバックレートを細かく変更させなければならず、スクリブル処理に伴うイベントも用意されており、これを処理しないとまともには実装できない。MSDNにあるPlayerSeekingはこれらの実装を例として一応示してくれているため、少しの修正で使える。

 Media Sessionのイベント機構はそれはそれでエレガントで、細かい制御ができて良いのかもしれないが、DirectShowのプレイバック制御の簡単さを思い出すとうんざりしてしまったことは否めない。まぁ実装できてしまったから今となってはどうでもいいが、MFPlayの出来がもう少ししっかりしていれば良かったという印象がある。MFPlayはDirectShow並にプレイバック制御が簡単で、EVR(Enhanced Video Renderer)機構との連携によりウィンドウへのレンダリングも容易なため、プレイヤーソフトなどには適しているが、プレイバック中のサンプルデータの取得機構がそれ自体に無く、MicrosoftSDKにあるVideoThumnailサンプルにあるように、Source Readerインターフェイスから取得する方法ぐらいしか見つけられていない。この方法は一応、再生中のある時点での画像等をサンプリングできるのだが、再生タイミングからは相当な時間遅れるため、プレイバックとほぼ同時刻にサンプリングして表示する、などといった処理には使えなかった。問題なく行える方法もあるのかもしれないが、どうがんばっても見つけられなかったため、MFPlay周りのインターフェイスでは無理があると判断。ウィンドウに描画されるならそのウィンドウの画像自体をゲットしてくれば軽いのだが、可視状態のウィンドウが必要になってしまうためスマートではない。実際にはMedia Sessionで実装でき、そもそもMFPlayインターフェイスは「Deprecated」扱いなためこれから期待できるものではないので、文句をいっても修正はないだろう。

 同様にプレイバックとその制御ができるインターフェイス複数あることにまず違和感はあり、とりあえずMFPlayインターフェイスを用意はしたが、プロジェクトを引き継いだMicrosoftの中の人が、「システムオタとしてこんなものは看過できん」と言いながらMedia Sessionを用意したような気がしないでもない。