8. DirectShow-filter change

修改現(xiàn)有filter

如果需要修改現(xiàn)有filter羞芍,可以停止該圖哗戈,進(jìn)行更改,然后重新啟動(dòng)該圖涩金。 這通常是最佳方法谱醇。 但是,在某些情況下步做,你可能希望在圖形仍在運(yùn)行時(shí)對(duì)其進(jìn)行更改副渴。 例如:

  • 應(yīng)用程序在播放期間插入視頻效果filter
  • filter將媒體類(lèi)型切換為中流全度,可能需要新的解壓縮filter煮剧。
  • 應(yīng)用程序?qū)⑿碌囊曨l流添加到圖形。
    這些都是 動(dòng)態(tài)圖形生成的示例将鸵,該術(shù)語(yǔ)涵蓋在圖形繼續(xù)運(yùn)行時(shí)對(duì)filter Graph所做的任何類(lèi)型的更改勉盅。 動(dòng)態(tài)圖形生成可以由應(yīng)用程序或圖形中的filter啟動(dòng)。 可以采用三種不同的方案:
  • 動(dòng)態(tài)格式更改:filter可以在中游更改格式顶掉,而無(wú)需刪除或替換任何filter草娜。
  • 動(dòng)態(tài)重新連接:通過(guò)添加或刪除filter來(lái)更改圖形。
  • filter鏈:添加痒筒、刪除和控制filter鏈宰闰。

動(dòng)態(tài)重新連接

在大多數(shù) DirectShow filter中,當(dāng)圖形主動(dòng)流式傳輸數(shù)據(jù)時(shí)簿透,無(wú)法重新連接pin移袍。 應(yīng)用程序必須在重新連接pin之前停止圖形。 但是老充,某些filter在圖形運(yùn)行時(shí)支持pin重新連接葡盗,此過(guò)程稱(chēng)為動(dòng)態(tài)重新連接。 這可以通過(guò)應(yīng)用程序或圖形中的filter來(lái)完成啡浊。

例如觅够,請(qǐng)考慮下圖中的圖。


image.png

動(dòng)態(tài)重新連接的一種方案可能是在圖形正在運(yùn)行時(shí)從圖形中刪除filter 2巷嚣,并將其替換為另一個(gè)filter喘先。 若要使此方案正常工作,必須滿(mǎn)足以下條件:

  • filter 3 (pin D) 上的輸入pin必須支持 IPinConnection 接口涂籽。 此接口允許在不停止filter的情況下重新連接pin
  • filter 1 上的輸出pin (pin A) 必須能夠在重新連接發(fā)生時(shí)阻止媒體數(shù)據(jù)流砸抛。 在重新連接期間评雌,任何數(shù)據(jù)都不能在pin A 和pin D 之間傳輸树枫。 通常,這意味著輸出pin必須支持 IPinFlowControl 接口景东。 但是砂轻,如果filter 1 是啟動(dòng)重新連接的filter,則它可能有一些內(nèi)部機(jī)制來(lái)阻止其自己的數(shù)據(jù)流斤吐。

動(dòng)態(tài)重新連接將涉及以下步驟:

  • 阻止來(lái)自pin A 的數(shù)據(jù)流搔涝。
  • 重新連接pin A 到pin D,可能通過(guò)新的中間filter和措。
  • 取消阻止固定 A庄呈,以便數(shù)據(jù)再次開(kāi)始流動(dòng)。

阻止數(shù)據(jù)流

若要阻止數(shù)據(jù)流派阱,請(qǐng)?jiān)?code>pin A 上調(diào)用 IPinFlowControl::Block 诬留。可以異步或同步調(diào)用此方法贫母。 若要 異步調(diào)用 方法文兑,請(qǐng)創(chuàng)建 Win32 事件對(duì)象并將事件句柄傳遞給 Block 方法。 方法將立即返回腺劣。 使用 WaitForSingleObject 等函數(shù)等待事件發(fā)出信號(hào)绿贞。 pin在事件阻止數(shù)據(jù)流時(shí)發(fā)出信號(hào)。 例如:

// Create an event
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hEvent != NULL)
{
    // Block the data flow.
    hr = pFlowControl->Block(AM_PIN_FLOW_CONTROL_BLOCK, hEvent); 
    if (SUCCEEDED(hr))
    {
        // Wait for the pin to finish.
        DWORD dwRes = WaitForSingleObject(hEvent, dwMilliseconds);
    }
}

若要 同步調(diào)用 方法橘原,只需傳遞值 NULL 而不是事件句柄籍铁。 現(xiàn)在, 方法將阻止靠柑,直到操作完成寨辩。 在pin準(zhǔn)備好提供新示例之前,可能不會(huì)發(fā)生這種情況歼冰。 如果filter已暫停靡狞,則可能需要任意時(shí)間長(zhǎng)度。 因此隔嫡,不要從main應(yīng)用程序線(xiàn)程進(jìn)行同步調(diào)用甸怕。 使用工作線(xiàn)程,或者異步調(diào)用 方法腮恩。

重新連接pin

若要重新連接pin梢杭,請(qǐng)查詢(xún) IGraphConfig 接口的 Filter Graph 管理器,并調(diào)用 IGraphConfig::Reconnect 或 IGraphConfig::Reconfigure秸滴。 重新連接方法更易于使用;它執(zhí)行以下操作:

停止示例) 中 (filter 2 的中間filter武契,并將其從圖中刪除。
根據(jù)需要添加新的中間filter
連接所有pin咒唆。
暫徒斓妫或運(yùn)行任何新filter,以匹配圖形的狀態(tài)全释。
重新連接方法有多個(gè)可選參數(shù)装处,可用于指定pin連接的媒體類(lèi)型和要使用的中間filter。 例如:

pGraph->AddFilter(pNewFilter, L"New Filter for the Graph");
pConfig->Reconnect(
   pPinA,      // Reconnect this output pin...
   pPinD,      // ... to this input pin.
   pMediaType, // Use this media type.
   pNewFilter, // Connect them through this filter.
   NULL, 
   0);     

有關(guān)詳細(xì)信息浸船,請(qǐng)參閱參考頁(yè)妄迁。 如果 重新連接 方法不夠靈活,可以使用 Reconfigure 方法李命,該方法調(diào)用應(yīng)用程序定義的回調(diào)方法來(lái)重新連接pin登淘。 若要使用此方法,請(qǐng)?jiān)趹?yīng)用程序中實(shí)現(xiàn) IGraphConfigCallback 接口项戴。

在調(diào)用 重新配置之前形帮,請(qǐng)阻止來(lái)自輸出pin的數(shù)據(jù)流,如前所述周叮。 然后推送正在重新連接的關(guān)系圖部分仍處于掛起狀態(tài)的任何數(shù)據(jù)辩撑,如下所示:
在示例) 中,在重新連接鏈中最遠(yuǎn)下游的輸入pin上調(diào)用 IPinConnection::NotifyEndOfStream (pin D仿耽。 將句柄傳遞到 Win32 事件合冀。
在從阻止數(shù)據(jù)流的輸出pin直接下游的輸入pin上調(diào)用 IPin::EndOfStream 。 (在此示例中项贺,數(shù)據(jù)流在pin A 處被阻止君躺,因此可以在pin B.)
等待事件發(fā)出信號(hào)。 輸入pin (pin D) 接收流結(jié)束通知時(shí)向事件發(fā)出信號(hào)开缎。 這表示沒(méi)有數(shù)據(jù)在pin之間傳輸棕叫,并且調(diào)用方可以安全地重新連接pin
請(qǐng)注意奕删, IGraphConfig::重新連接 方法會(huì)自動(dòng)處理前面的步驟俺泣。 僅當(dāng)使用 Reconfigure 方法時(shí),才需要執(zhí)行這些步驟完残。

通過(guò)圖形推送數(shù)據(jù)后伏钠,調(diào)用 重新配置 并將指針傳遞到 IGraphConfigCallback 回調(diào)接口。 Filter Graph 管理器將調(diào)用你提供的 IGraphConfigCallback::Reconfigure 方法谨设。

取消阻止數(shù)據(jù)流

重新連接pin后熟掂,請(qǐng)為第一個(gè)參數(shù)調(diào)用值為零的 IPinFlowControl::Block 來(lái)取消阻止數(shù)據(jù)流。

備注
如果動(dòng)態(tài)重新連接由filter執(zhí)行扎拣,則必須注意一些線(xiàn)程問(wèn)題赴肚。 如果 Filter Graph 管理器嘗試停止filter素跺,它可能會(huì)死鎖,因?yàn)閳D形等待filter停止誉券,同時(shí)filter可能正在等待數(shù)據(jù)通過(guò)圖形推送亡笑。 為了防止可能出現(xiàn)的死鎖,本部分所述的某些方法會(huì)處理 Win32 事件横朋。 如果 Filter Graph 管理器嘗試停止filterfilter應(yīng)發(fā)出事件信號(hào)百拓。 有關(guān)詳細(xì)信息琴锭,請(qǐng)參閱 IGraphConfig 和 IPinConnection。

filter

filter鏈?zhǔn)菨M(mǎn)足以下條件的filter序列:

  • 鏈中的每個(gè)filter最多有一個(gè)連接的輸入pin和一個(gè)連接的輸出pin衙传。
  • 無(wú)需遍歷鏈外部的filter即可遍歷鏈中的每個(gè)filter决帖。

例如,在下圖中蓖捶,filter A–B地回、C-D 和 F–G-H 是filter鏈。 F-G-H (F-G 和 G-H) 中的每個(gè)子鏈也是一個(gè)filter鏈俊鱼。 filter鏈可以包含單個(gè)filter刻像,因此filter A、B并闲、C细睡、D、F帝火、G 和 H 也是不同的filter鏈溜徙。 filter E 具有兩個(gè)輸入連接,因此包含filter E 的任何filter序列都不是filter鏈犀填。

image.png

filter鏈 (示例 1)

IFilterChain 接口提供用于控制filter鏈的以下方法:

Label 值
IFilterChain::StartChain 啟動(dòng)鏈蠢壹。
IFilterChain::StopChain 停止鏈。
IFilterChain::P auseChain 暫停鏈九巡。
IFilterChain::RemoveChain 從圖中刪除鏈图贸。

沒(méi)有用于添加鏈的特定方法。 若要添加鏈比庄,請(qǐng)使用 IFilterGraph::AddFilter 方法插入新filter求妹。 然后,通過(guò)調(diào)用 IGraphBuilder::Connect佳窑、 IGraphBuilder::Render 或類(lèi)似方法連接filter制恍。

當(dāng)圖形運(yùn)行時(shí),filter鏈可以在運(yùn)行和停止之間切換神凑。 當(dāng)圖形暫停時(shí)净神,它可以在暫停和停止之間切換何吝。 這些是filter鏈唯一可能的狀態(tài)轉(zhuǎn)換。

filter鏈準(zhǔn)則

使用 IFilterChain 方法時(shí)鹃唯,請(qǐng)務(wù)必確保圖中的filter可以支持filter鏈接操作爱榕。 否則,可能會(huì)導(dǎo)致死鎖或圖形錯(cuò)誤坡慌。 在鏈更改狀態(tài)后黔酥,連接到鏈的filter必須正常運(yùn)行。

使用 IFilterChain 的最佳方式是使用一組專(zhuān)為鏈接設(shè)計(jì)的filter洪橘。 使用以下準(zhǔn)則來(lái)確保filter對(duì)filter鏈操作是安全的跪者。 這些要點(diǎn)參考下圖。

image.png

filter鏈 (示例 2)

filter鏈的狀態(tài)更改之前熄求,必須完成filter鏈邊界上的所有數(shù)據(jù)處理調(diào)用渣玲。 此規(guī)則適用于 IMemInputPin::Receive、 IPin::NewSegment 和 IPin::EndOfStream 的方法弟晚。 鏈中的filter必須從對(duì)鏈外filter進(jìn)行的這些方法的調(diào)用返回;和 鏈外部的filter必須從鏈中的filter進(jìn)行的調(diào)用返回忘衍。
例如,在上圖中卿城,filter B 必須完成來(lái)自filter A 的任何數(shù)據(jù)處理調(diào)用枚钓,而filter E 必須完成來(lái)自filter D 的任何調(diào)用。如果pin公開(kāi) IPinFlowControl 和 IPinConnection 接口瑟押,可以通過(guò)調(diào)用 IPinFlowControl::Block 和 IGraphConfig::P ushThroughData 方法通過(guò)圖形推送數(shù)據(jù)秘噪,如 動(dòng)態(tài)重新連接中所述。 filter可能還支持用于推送數(shù)據(jù)的專(zhuān)用方法勉耀。

上游filter必須預(yù)期鏈的狀態(tài)會(huì)發(fā)生更改指煎。 例如,在上圖中便斥,假設(shè)鏈已停止至壤,但filter A 調(diào)用 IMemInputPin::Receive。 調(diào)用失敗枢纠,filter A 的響應(yīng)是停止流式處理像街。 當(dāng)應(yīng)用程序重啟鏈時(shí),它不起作用晋渺,因?yàn)?code>filter A 不再流式處理數(shù)據(jù)镰绎。
下游filter還必須預(yù)期鏈的狀態(tài)會(huì)發(fā)生更改。 否則木西,下游filter可能會(huì)在等待從未到達(dá)的樣本時(shí)阻止畴栖。 例如,多路復(fù)用器 (MUX) filter通常需要來(lái)自其所有輸入pin的數(shù)據(jù)八千。 從一個(gè)輸入pin停止數(shù)據(jù)流可能會(huì)阻止其他流進(jìn)行處理吗讶。 這可能會(huì)導(dǎo)致圖形死鎖燎猛。
從鏈外filter到鏈內(nèi)filter的每個(gè)pin連接都應(yīng)具有其自己的分配器,而其他連接不共享該分配器照皆。 當(dāng)鏈更改狀態(tài)或從圖中刪除時(shí)重绷,分配器可能已取消提交。 如果其他連接使用相同的分配器膜毁,則它們無(wú)法再處理示例昭卓。
除非連接到鏈的filter支持動(dòng)態(tài)斷開(kāi)連接,否則請(qǐng)勿刪除鏈瘟滨。 通常葬凳,連接的filter將支持 IPinConnection 或 IPinFlowControl 接口,但可能改為支持專(zhuā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)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)念恍,“玉大人六剥,你說(shuō)我怎么就攤上這事》寤铮” “怎么了疗疟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)瞳氓。 經(jīng)常有香客問(wèn)我策彤,道長(zhǎng),這世上最難降的妖魔是什么匣摘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任店诗,我火速辦了婚禮,結(jié)果婚禮上音榜,老公的妹妹穿的比我還像新娘抛虫。我一直安慰自己选脊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布灰追。 她就那樣靜靜地躺著,像睡著了一般惕味。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 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)封第一講書(shū)人閱讀 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)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)察郁。三九已至衍慎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間皮钠,已是汗流浹背稳捆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 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)容