6. DirectShow-事件和事件響應(yīng)

事件的消息隊(duì)列機(jī)制

filter通過(guò)發(fā)布事件通知來(lái)通知 Filter Graph 管理器有關(guān)事件。 該事件可能是預(yù)期事件(例如流的末尾)卧斟,也可能表示錯(cuò)誤囚聚,例如無(wú)法呈現(xiàn)流跨晴。 Filter Graph 管理器自行處理某些filter事件,而其他filter事件則留給應(yīng)用程序處理根吁。 如果 Filter Graph 管理器不處理filter事件员淫,則會(huì)將事件通知放入隊(duì)列中。 filter圖還可以為應(yīng)用程序?qū)⒆约旱氖录ㄖ抨?duì)击敌。

應(yīng)用程序從隊(duì)列中檢索事件介返,并根據(jù)事件類型對(duì)其進(jìn)行響應(yīng)。 因此愚争,DirectShow 中的事件通知類似于 Microsoft Windows 消息隊(duì)列方案映皆。 應(yīng)用程序還可以取消filter關(guān)系圖管理器對(duì)給定事件類型的默認(rèn)行為挤聘。 然后轰枝,F(xiàn)ilter Graph 管理器將這些事件直接放入隊(duì)列中供應(yīng)用程序處理。

  • 用于與應(yīng)用程序通信的 Filter Graph 管理器组去。
  • 用于與應(yīng)用程序和filter關(guān)系圖管理器通信的filter鞍陨。
  • 應(yīng)用程序,以確定其在處理事件中的參與程度从隆。

Filter Graph 管理器公開(kāi)三個(gè)支持事件通知的接口诚撵。

  • IMediaEventSink 包含用于發(fā)布事件的filter的方法。
  • IMediaEvent 包含應(yīng)用程序用于檢索事件的方法键闺。
  • IMediaEventEx 繼承自 并擴(kuò)展 IMediaEvent 接口寿烟。
    通過(guò)在 Filter Graph 管理器上調(diào)用 IMediaEventSink::Notify 方法篩選事件通知。 事件通知由一個(gè)定義事件類型的事件代碼和兩個(gè)提供其他信息的參數(shù)組成辛燥。 根據(jù)事件代碼筛武,參數(shù)可能包含指針、返回代碼挎塌、引用時(shí)間或其他信息徘六。 有關(guān)事件代碼和參數(shù)的完整列表,請(qǐng)參閱 事件通知代碼榴都。

若要從隊(duì)列中檢索事件待锈,應(yīng)用程序在 Filter Graph Manager 上調(diào)用 IMediaEvent::GetEvent 方法。 此方法將阻塞嘴高,直到有要返回的事件竿音,或直到指定的時(shí)間過(guò)去。 假設(shè)存在排隊(duì)事件拴驮,該方法返回事件代碼和兩個(gè)事件參數(shù)春瞬。 調(diào)用 GetEvent 后,應(yīng)用程序應(yīng)始終調(diào)用 IMediaEvent::FreeEventParams 方法莹汤,以釋放與事件參數(shù)關(guān)聯(lián)的任何資源快鱼。 例如,參數(shù)可能是由filter圖分配的 BSTR 值。

下面的代碼示例概述了如何從隊(duì)列中檢索事件抹竹。

long evCode;
LONG_PTR param1, param2;
HRESULT hr;
while (hr = pEvent->GetEvent(&evCode, &param1, &param2, 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);
}

若要替代 Filter Graph 管理器對(duì)事件的默認(rèn)處理线罕,請(qǐng)使用事件代碼作為參數(shù)調(diào)用 IMediaEvent::CancelDefaultHandling 方法。 可以通過(guò)調(diào)用 IMediaEvent::RestoreDefaultHandling 方法來(lái)恢復(fù)默認(rèn)處理窃判。 如果filter圖未對(duì)指定的事件代碼執(zhí)行默認(rèn)處理钞楼,則調(diào)用這些方法不起作用。

事件的兩種響應(yīng)機(jī)制

若要處理 DirectShow 事件袄琳,應(yīng)用程序需要一種方法來(lái)查明事件何時(shí)在隊(duì)列中等待询件。 Filter Graph 管理器提供了兩種執(zhí)行此操作的方法:

  • 窗口通知: 每當(dāng)有新事件時(shí),F(xiàn)ilter Graph 管理器會(huì)將用戶定義的 Windows 消息發(fā)送到應(yīng)用程序窗口唆樊。
  • 事件信號(hào): 如果隊(duì)列中有 DirectShow 事件宛琅,F(xiàn)ilter Graph 管理器會(huì)發(fā)出 Windows 事件信號(hào),如果隊(duì)列為空逗旁,則重置事件嘿辟。

應(yīng)用程序可以使用任一技術(shù)。 窗口通知通常更簡(jiǎn)單片效。

窗口通知

若要設(shè)置窗口通知红伦,請(qǐng)調(diào)用 IMediaEventEx::SetNotifyWindow 方法并指定私人消息。 應(yīng)用程序可以使用從WM_APP到0xBFFF范圍內(nèi)的消息號(hào)作為私人消息淀衣。 每當(dāng) Filter Graph 管理器在隊(duì)列中放置新事件通知時(shí)昙读,它會(huì)將此消息發(fā)布到指定的窗口。 應(yīng)用程序從窗口的消息循環(huán)中響應(yīng)消息膨桥。

下面的代碼示例演示如何設(shè)置通知窗口蛮浑。

#define WM_GRAPHNOTIFY WM_APP + 1   // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

該消息是普通的 Windows 消息,獨(dú)立于 DirectShow 事件通知隊(duì)列發(fā)布国撵。 此方法的優(yōu)點(diǎn)是大多數(shù)應(yīng)用程序已實(shí)現(xiàn)消息循環(huán)陵吸。 因此,無(wú)需執(zhí)行大量額外工作即可合并 DirectShow 事件處理介牙。

下面的代碼示例演示了如何響應(yīng)通知消息的概述壮虫。 有關(guān)完整示例,請(qǐng)參閱 響應(yīng)事件环础。

LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
    switch (msg)
    {
        case WM_GRAPHNOTIFY:
            HandleEvent();  // Application-defined function.
            break;
        // Handle other Windows messages here too.
    }
    return (DefWindowProc(hwnd, msg, wParam, lParam));
}

由于事件通知和消息循環(huán)都是異步的囚似,因此在應(yīng)用程序響應(yīng)消息時(shí),隊(duì)列可能包含多個(gè)事件线得。 此外饶唤,如果事件變得無(wú)效,有時(shí)可以從隊(duì)列中清除這些事件贯钩。 因此募狂,在事件處理代碼中办素,調(diào)用 IAMMediaEvent::GetEvent ,直到返回失敗代碼祸穷,指示隊(duì)列為空性穿。

在釋放 IMediaEventEx 指針之前,請(qǐng)使用 NULL 指針調(diào)用 SetNotifyWindow 來(lái)取消事件通知雷滚。 在事件處理代碼中需曾,檢查 IMediaEventEx 指針在調(diào)用 GetEvent 之前是否有效。 這些步驟可防止可能出現(xiàn)的錯(cuò)誤祈远,即應(yīng)用程序在釋放 IMediaEventEx 指針后接收事件通知呆万。

事件信號(hào)

Filter Graph 管理器保留一個(gè)反映事件隊(duì)列狀態(tài)的手動(dòng)重置事件。 如果隊(duì)列包含掛起的事件通知车份,F(xiàn)ilter Graph 管理器會(huì)發(fā)出手動(dòng)重置事件的信號(hào)谋减。 如果隊(duì)列為空,則對(duì) IMediaEvent::GetEvent 方法的調(diào)用將重置事件躬充。 應(yīng)用程序可以使用此事件來(lái)確定隊(duì)列的狀態(tài)逃顶。

備注

此處的術(shù)語(yǔ)可能會(huì)令人困惑。 手動(dòng)重置事件是由 Windows CreateEvent 函數(shù)創(chuàng)建的事件類型, 它與 DirectShow 定義的事件無(wú)關(guān)充甚。

調(diào)用 IMediaEvent::GetEventHandle 方法以獲取手動(dòng)重置事件的句柄。 等待通過(guò)調(diào)用 WaitForMultipleObjects 等函數(shù)發(fā)出事件信號(hào)霸褒。 發(fā)出事件信號(hào)后伴找,調(diào)用 IMediaEvent::GetEvent 以獲取 DirectShow 事件。

以下代碼示例演示了此方法废菱。 它獲取事件句柄技矮,然后以 100 毫秒的間隔等待事件發(fā)出信號(hào)。 如果事件收到信號(hào)殊轴,它將調(diào)用 GetEvent 并將事件代碼和事件參數(shù)輸出到控制臺(tái)窗口衰倦。 循環(huán)在 發(fā)生EC_COMPLETE 事件時(shí)終止,指示播放已完成旁理。

HANDLE  hEvent; 
long    evCode, param1, param2;
BOOLEAN bDone = FALSE;
HRESULT hr = S_OK;
hr = pEvent->GetEventHandle((OAEVENT*)&hEvent);
if (FAILED(hr))
{
    /* Insert failure-handling code here. */
}

while(!bDone) 
{
    if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100))
    { 
        while (S_OK == pEvent->GetEvent(&evCode, &param1, &param2, 0)) 
        {
            printf("Event code: %#04x\n Params: %d, %d\n", evCode, param1, param2);
            pEvent->FreeEventParams(evCode, param1, param2);
            bDone = (EC_COMPLETE == evCode);
        }
    }
} 

由于filter圖會(huì)在適當(dāng)時(shí)自動(dòng)設(shè)置或重置事件樊零,因此應(yīng)用程序不應(yīng)這樣做。 此外孽文,釋放filter圖時(shí)驻襟,filter圖將關(guān)閉事件句柄,因此不要在該點(diǎn)之后使用事件句柄芋哭。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沉衣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子减牺,更是在濱河造成了極大的恐慌豌习,老刑警劉巖存谎,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異肥隆,居然都是意外死亡愕贡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門巷屿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)固以,“玉大人,你說(shuō)我怎么就攤上這事嘱巾『┝眨” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵旬昭,是天一觀的道長(zhǎng)篙螟。 經(jīng)常有香客問(wèn)我,道長(zhǎng)问拘,這世上最難降的妖魔是什么遍略? 我笑而不...
    開(kāi)封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮骤坐,結(jié)果婚禮上绪杏,老公的妹妹穿的比我還像新娘。我一直安慰自己纽绍,他們只是感情好蕾久,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著拌夏,像睡著了一般僧著。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上障簿,一...
    開(kāi)封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天盹愚,我揣著相機(jī)與錄音,去河邊找鬼站故。 笑死皆怕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的世蔗。 我是一名探鬼主播端逼,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼污淋!你這毒婦竟也來(lái)了顶滩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤寸爆,失蹤者是張志新(化名)和其女友劉穎礁鲁,沒(méi)想到半個(gè)月后盐欺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仅醇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年冗美,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片析二。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粉洼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叶摄,到底是詐尸還是另有隱情属韧,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布蛤吓,位于F島的核電站宵喂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏会傲。R本人自食惡果不足惜锅棕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淌山。 院中可真熱鬧裸燎,春花似錦、人聲如沸艾岂。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)王浴。三九已至,卻和暖如春梅猿,著一層夾襖步出監(jiān)牢的瞬間氓辣,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工袱蚓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钞啸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓喇潘,卻偏偏與公主長(zhǎng)得像体斩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子颖低,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容