修改現(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)考慮下圖中的圖。
動(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 管理器嘗試停止filter
,filter
應(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
鏈犀填。
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)參考下圖。
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)用接口室奏。