[DirectShow] DirectShowからアプリケーションへのメッセージ
DirectShowからアプリケーションへのメッセージ
複数のフィルタから構成されるグラフで,すべてのフレームのレンダリングが終わったとき,エラーが起きたときなど,DirectShow側からそのイベントが起きたタイミングを知ることができれば,便利である.コールバックで実装することも可能であるが,DirectShowでは,これをWindows のメッセージを機能を利用し,アプリケーション側にメッセージを送信することができる.そのプログラミングについて説明する.
メッセージ送信の設定
まず,IMediaEventExのインタフェースのポインタをグラフビルダから取得する.
hResult = m_pGraph->QueryInterface(IID_IMediaEventEx, (void **) &m_pMediaEvent); if (hResult != S_OK)return FALSE;
このインタフェースを利用し,イベントを処理する.IMediaEventExのメソッド,SetNotifyWindowを使い,ビルダがメッセージを送信するウィンドウを指定する.指定にはウィンドウハンドルを利用する.具体的には以下のように設定する.
hResult = m_pMediaEvent->SetNotifyWindow((OAHWND)this->m_hWnd, WM_DSHOW,0); if (hResult != S_OK)return FALSE;
第1引数がメッセージの送信先のウィンドウハンドル,第2引数がメッセージの識別子となる.第3引数がメッセージを受け取るときのパラメータWPARAMとなる.第2引数は,他のメッセージと重複することはあってはならないため,ユーザ用の未定義値を利用する.これには,WM_APPを利用する.
#define WM_DSHOW WM_APP+1
このウィンドウメッセージを処理する.
受信側のコーディング
SDKのAPIを利用する場合は,WM_PAINTなどと並んで,WM_DSHOWを処理する.MFCの場合には,以下のようにオリジナルのメッセージハンドラを実装する.
BEGIN_MESSAGE_MAP(CDirectShowSkeltonMFCExView, CView) //\{\{AFX_MSG_MAP(CDirectShowSkeltonMFCExView) ON_WM_SIZE() ON_MESSAGE(WM_DSHOW,CDirectShowSkeltonMFCExView::OnWMDSHOW ) // 追加 //\}\}AFX_MSG_MAP END_MESSAGE_MAP()
これで,MFCを利用する場合,メッセージ受信時にOnWMDSHOWが呼び出されることとなる.しかし,受信しても,グラフビルダで何が行ったかはこのままではわからない.DirectShowで発生するイベントは,すべてがそのまま送信されるのではない.DirectShow側の細かいイベントは,IMediaEventExインタフェースを通して,取り出すことになる.WM_DSHOWメッセージ受信時にIMediaEventExからDirectShowイベントを取得する.
このイベント処理は,EventHandleで実装する.
void HandleEvent(void){ long evCode, param1, param2; HRESULT hResult; // イベントキューからイベントを取り出す while (hResult = m_pMediaEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hResult)){ // 上で取り出したイベントを消去する hResult = m_pMediaEvent->FreeEventParams(evCode, param1, param2); if ((EC_USER == evCode)){ if( param1 == PARAM_MESSAGE_FROM_FILTER && param2==PARAM_MESSAGE_FROM_FILTER){ this->MessageBox("フィルタからメッセージを受け取りました.","DirectShowSkeltonMFCEx",MB_OK); break; 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 }
まず,IMediaEventExのGetEventメソッドでメッセージを取得する.取得したメッセージは,FreeEventParamsで消去する.DirectShowのメッセージは処理されるまで,バッファに残るため,このように処理したメッセージは明示的に消去する必要がある.取得した情報は,ここで自由に処理することができる.
送信側のコーディング
DirectShowのメッセージは,フィルタからも送信することができる.これは,NotifyEventメソッドで送信することができる.
NotifyEvent( EC_USER, wParam, lParam );
ここでの第1引数が,DirectShowメッセージの識別子であり,第2,3引数がDirectShowメッセージのパラメータとなる.
DirectShowのビルダグラフもメッセージを送信する.たとえば,EC_COMPLETEは,すべてのストリームが再生が終わった場合に送信される.他にもデバイスを失ったときなどメッセージが送信されるタイミングがある.これは,ヘルプに記載されている.MSDNを参考にされたい.
http://code.google.com/p/sonson-code/source/browse/#svn/trunk/win/DirectShow/ThroughEx