DirectShow技術描述與應用(3) (轉)
DirectShow中的事件通知:namespace prefix = o ns = "urn:schemas--com::office" />
這一部分將描述在Microsoft® DirectShow®過濾器表中,事件是如何實現的;一個應用如何才能接受到事件通知並且響應它們。
事件通知概述
過濾器透過投遞事件通知來向過濾器表管理器通報一個事件。事件可以是包含任何資訊,如流的結束,也可以是一個錯誤,如還原流的失敗。過濾器表管理器本身處理一些過濾器事件,其它事件則留給應用程式來進行處理。如果過濾器表管理器遇到一個不能處理的事件,它就將事件放入到一個佇列中去。同樣的,過濾器表管理器也會將它自己的事件通知放入佇列中去,以期應用程式來進行處理。
應用程式可以從佇列中接收到事件並對它們做出響應。因此DirectShow的事件通知與Microsoft® ®訊息佇列非常相似。應用程式可以取消過濾器表管理器本身可以處理事件的這種行為,過濾器表管理則直接地將這些事件放入佇列中去,由應用程式來進行處理。這種機制允許:
- 過濾器表管理器與應用程式進行通訊。
- 過濾器可以與應用程式和過濾器表管理進行通訊。
- 由應用程式確定它自己都處理哪些事件。
接收事件
過濾器表管理器向外部暴露三個介面,來支援事件通知.
- IMediaEventSink包含過濾器投遞事件的方法
- IMediaEvent包含應用程式接收事件的方法
- _cpp/htm/imediaeventexinterface.htm">IMediaEventEx inherits from and extends the IMediaEvent interface.
- IMediaEventEx繼承於並擴充套件了IMdeiaEvent介面
過濾器透過過濾器表管理器的IMediaEventSink::Notify方法來投遞事件通知。一個事件通知由一個事件程式碼和兩個D型引數組成。根據不同的事件程式碼,引數值可能會是指標、返回碼、參考時間或者其它資訊。
為能從佇列中接收事件,應用程式應呼叫IMediaEvent::GetEvent方法來接收資料。這個方法會被阻斷直到從一個佇列中得到一個事件或者超過時限。當呼叫完GetEvent後,應用程式應該總是呼叫IMediaEvent::FreeEventParams方法來釋放在事件引數中的資源。例如引數有可能是由過濾器表提供的BSTR字串。
下面的程式碼提供一個如何從佇列中接受事件的。
long evCode, param1, param2;
HRESULT hr;
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
switch(evCode)
{
// Call application-defined functions for each
// type of event that you want to handle.
}
hr = pEvent->FreeEventParams(evCode, param1, param2);
}
為了停止某個事件的過濾器表管理器的預設處理,可以呼叫IMediaEvent::CancelDefaultHandling方法。你可以透過呼叫IMediaEvent::RestoreDefaultHandling方法來恢復事件的預設處理。對於那些沒有過濾器表管理器預設處理的事件,呼叫這些方法將不會產生任何影響。
為了DirectShow事件,應用程式需要一種在佇列中有事件在等待時,能夠被得知的方法。過濾表管理器提供兩種途徑來實現:
- 視窗通知:過濾器表管理器在產生一個新事件時,嚮應用程式視窗傳送一個自定義的訊息。
- 事件訊號:如果在佇列有DirectShow事件時,則過濾器表管理器傳送一個視窗事件。並在佇列為空時重置事件。
- An application can use either technique. Window notification is usually simpler.
- 應用程式可以使用其它手法來實現。但視窗訊息通常會更為簡單。
視窗通知
可以呼叫IMediaEventEx::SetNotifyWindow方法來指定一個私有訊息,來建立起視窗通知。這個私有訊息可以使用從WM_APP到WM_APP+0xBfff之間的數。只要當過濾器表管理向佇列裡放入新的事件,它就會向指定的應用程式視窗傳送資訊。應用程式對來自Windows訊息迴圈的訊息作出響應。
下面程式碼說明了如何設定通知視窗。
#define WM_GRAPHNOTIFY WM_APP + 1 // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
下面程式碼說明了如何對視窗訊息做出響應
LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
switch (msg)
{
case WM_GRAPHNOTIFY:
HandleEvent(); //應用程式定義的.
break;
//也可以在這裡編寫訊息處理。
}
return (DefWindowProc(hwnd, msg, wParam, lParam));
}
因為事件通知和訊息迴圈都是非同步的,所以在你的應用程式對訊息作出響應時,佇列中有可能包含多個事件訊息。也可能有時候事件會變得無效,那麼它就會被清除出佇列。因此,在你的事件處理程式碼中,應不停地的呼叫GetEvent方法,直至返回失敗碼,即訊息佇列已為空。
注意,在你釋放IMediaEventEx指標時,先要透過向SetNotifyWindow傳入一個空指標來取消事件通知。在你的事件處理程式碼中,一個定要在呼叫GetEvent方法前檢查IMeiaEventEx指標的有效性。這樣可以預防在釋放了IMediaEventEx指標後,應用程式再次事件處理程式碼所可能出現的錯誤。
事件的發出(signal)
過濾器表管理器維護一個手動重置(manual-reset)的事件,用來反應事件佇列的狀態。如果事件佇列包含有未解決的事件通知,那麼過濾器表管理會發出一個手動重置事件。如果事件為空,呼叫IMediaEvent::GetEvent方法會重置事件。應用程式可以使用此事件來確定佇列的狀態。
注意:這個語術可能會被誤解。手動重置事件是一個透過Windows CreateEvent函式建立的事件型別,它在DirectShow中並不做任何事情。
呼叫IMediaEvent::GetEventHandle方法可以得到手動重置事件的控制程式碼。可以透過WaitForMultiple函式來等待這個事件的發生。一旦此事件發生,呼叫IMediaEvent::GetEvent方法就可以得到DirectShow事件。
下面的程式碼示例了這樣的功能。它取得事件的控制程式碼,每100毫秒的間隔等待事件的發生。當事件發生後,透過呼叫GetEvent方法來取得事件,並將事件程式碼和事件引數顯示出來。當EC_COMPLETE事件(其表示回放已經完成)出現則迴圈結束。
HANDLE hEvent;
long evCode, param1, param2;
BOOLEAN bDone = FALSE;
HRESULT hr = S_OK;
hr = pEvent->GetEventHandle((OAEVENT*)&hEv);
while(!bDone)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100))
{
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
printf("Event code: %#04xn Params: %d, %dn", evCode, param1, param2);
hr = pEvent->FreeEventParams(evCode, param1, param2);
bDone = (EC_COMPLETE == evCode);
}
}
}
因為過濾器表會適當地自動設定或重置事件,你的應用程式可以免於對這些事情的處理。同樣的,當你釋放了過濾器表後,過濾器表就會釋放掉事件控制程式碼。因此在你釋放過濾器表後,就不要再去使用事件控制程式碼。
(待續...)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-977251/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Embedding技術與應用(3):Embeddings技術的實踐應用
- 進階 Redis 技術與應用Redis
- 大資料技術原理與應用大資料
- Embedding技術與應用(4): Embedding應用工程探析
- 百度文件智慧技術與應用
- Delphi 技術的優缺點與應用
- 【主流技術】Mybatis Plus的理解與應用MyBatis
- IPv6技術與應用創新
- vivo直播應用技術實踐與探索
- 區塊鏈技術與應用:未來的一場技術革命區塊鏈
- 10-入侵檢測技術原理與應用
- 知識圖譜——技術與行業應用行業
- 多程序程式設計:原理、技術與應用程式設計
- 產品資料管理(PDM)技術與應用
- PDM技術的基本功能與應用
- MACD技術的高階應用--MACD與波浪Mac
- iOS應用效能監控與分析技術深度解析iOS
- 虛擬機器遷移技術原理與應用虛擬機
- 深度強化學習技術開發與應用強化學習
- 情感分析技術在美團的探索與應用
- 乾貨 | 知識圖譜的技術與應用
- 行動網路安全技術與應用培訓
- AIoT技術的廣泛應用與巨大優勢AI
- 後臺開發 -- 核心技術與應用實踐
- 【轉】阿里技術專家詳解DDD-應用架構阿里應用架構
- 玩轉iOS開發:裝逼技術RunTime的應用(一)iOS
- 深度學習核心技術實踐與圖神經網路新技術應用深度學習神經網路
- 機器學習的技術原理、應用與挑戰機器學習
- 釘釘協同引擎與應用場景技術探索
- 得物技術時間切片的實踐與應用
- 人臉識別:技術應用與商業實踐
- 區塊鏈特徵與區塊鏈技術應用落地區塊鏈特徵
- GPU在AI業務中的核心技術與應用GPUAI
- 阿里NLP總監分享-NLP技術的應用與思考阿里
- 大資料技術原理與應用——大資料概述大資料
- Java Chassis 3技術解密,流式響應如何簡化AI應用開發Java解密AI
- 企業應用的轉折點:記憶體計算技術記憶體
- GPRS與4G網路:技術差異與應用選擇
- 【應用技術】AM335x串列埠技術分析串列埠