しかしまあ、ここまで日本語の資料がないとMediaFoundationを使ってもいいかどうか怪しいと思いたくなるのは私だけではないでしょうね・・・。
というわけでMediaFoundationです。MicrosoftがDirectShowに代わってWindowsVista以降で使用できるようにしたマルチメディアAPI群です。
(たしかMicrosoftのページかどこかで書いてあったような気がしますが)DirectShowの場合、メモリ管理に難があります。
特に各フィルタ間を移動するメモリはすべてIMemAllocatorといったインターフェイスで「隣のフィルタまでしかメモリを移動できない」という問題点があります。
同じ内容のメモリを引き渡したり、一部分だけをそのままコピーして渡す、というときにメモリコピーが無駄に発生するというものです。
まあ、いろいろと改良を加えて登場したMediaFoundationですが、果たしてゲーム(特にADVゲーム)の動画再生としてDirectShowを置き換えられるのでしょうか?
という視点を重視しながら実装していきたいと思います。
MediaFoundationで再生できるメディア種類は?
MicrosoftのSupported Media Formats in Media Foundationにもありますが、動画フォーマットなら
- Advanced Streaming Format (.asf,.wma,.wmv)
だけです。
え?と驚きたくなるのもわかりますが、WindowsVistaを含めるとこれだけになってしまいます。
AVIやWAV、MPEG-4のサポートが追加されたのはWindows7のタイミングですのでサポートが非常に狭いです。
そのため、ゲームで使うならAdvanced Streaming Format一択となってしまいます。
ちなみにMPEG-1はどのOSでもサポート対象外です。もしMediaFoundationで再生させたいならサンプルコードにDLLの実装がありますのでそれを使うことになります。
Windows98時代からADVゲームの動画フォーマットだったMPEG-1もそろそろ引退の時か・・・という感じもします。
当たり前だが、WindowsXPはサポート対象外
WinXP上では使用できません。DirectX11なんかと同じですね。
サポート期間切れになりますので余り気にする必要はないとは思いますが・・・。
そのため、もしWinXPをADVシステムの対象OSとして残したいなら判別して動作させる必要があります。
Windows7などであっても使えないことあり
前にWindowsMediaPlayer12でハードウェアデコードを使わないようにするには?などで紹介したことがあるとおり、特殊なツールを使うと使用しないようにすることがができます。
DirectShowでも同様なことはできるのですが、Windows7以降を目安にmp4再生を実装するとこれで止められる、ということが起こりえないこともないので注意が必要です。
実際、私のPCでサンプルを32bit版でテストするとmp4が再生できず、64bit版でテストするとmp4が再生できる、ということが起こりました。
使用するにはコードにも注意
一応使用するヘッダファイルおよびライブラリをC言語形式で書いておくと
#include <windows.h> //#include <objbase.h> //#include <process.h> //#include <tchar.h> #include <mfapi.h> #include <mfidl.h> #include <mferror.h> #include <evr.h> #include "unknownbase.h" #pragma comment(lib,"mf.lib") #pragma comment(lib,"mfplat.lib") #pragma comment(lib,"mfuuid.lib") #pragma comment(lib,"strmiids.lib")
となります。(unknownbase.hについては番外編の[IUnknownの実装]を参照)
よく見るとなぜかstrmiids.lib(DirectShowで使うライブラリ定義)が入っています。つまり完全に独立してるのかと思いきや、プログラム作成時にはDirectShowのライブラリが必要というわけです。
コード上でも依存しているような項目はほとんど見られませんが、たま~にDirectShowのフィルタを使う、とか言う変な項目が出てきたりします。
あと、MediaFoundationにはスタートアップとシャットダウン時にコードが必要です。
int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nShowCmd) { MFStartup(MF_VERSION); ・・・ MFShutdown(); return 0; }
というように、MediaFoundationを使う前にMFStartup、MediaFoundationに関するすべてのインターフェイスを解放してプログラムが終了する前にMFShutdownが必要になります。
この辺はWindowsのSocket通信で使用するWSAStartupとWSACleanupと同じですね。
ちなみにCoInitialize~CoUninitializeはあった方がいいですが必須ではありません。
基本はIMFMediaSessionを使う形で行う
登場した初期にはIMFPMediaPlayerという管理がとてもやりやすいインターフェイスが登場していたのですが、これがdeprecated(将来廃止される)となっているので対象にしません。
まあ、使いやすくても廃止されてはたまったものではないですからね。またMediaFoundationでいろいろと操作をするならどうしてもIMFMediaSession経由で行う必要があるのでこうなります。
次回は全体を管理するクラスの宣言を見てみる
MediaFoundationを使うにはどうしても管理クラスが必要になります。DirectShowとは違うところですね。
その管理クラスの宣言を見ていきます。この時点でどんなインターフェイスが必要かを見ていきます。