共用方式為


動態重新連線

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、imfMediaEngine 取代,並在媒體基金會 音訊/視訊擷取。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayerIMFMediaEngine 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]

在大部分的 DirectShow 篩選中,當圖形主動串流數據時,無法重新連接釘選。 應用程式必須先停止圖形,才能重新連接針腳。 不過,某些篩選條件確實支援在圖形執行時針腳重新連線,這是稱為動態重新連線的程式。 這可由應用程式或圖形中的篩選來完成。

例如,請考慮下圖中的圖表。

動態圖表建置圖表

動態重新連線的其中一個案例可能是從圖形中移除 Filter 2,而圖形正在執行,並將它取代為另一個篩選。 若要讓此案例運作,下列情況必須成立:

  • Filter 3 (pin D) 上的輸入針腳必須支援 IPinConnection 介面。 此介面可讓針腳重新連線,而不需要停止篩選。
  • 篩選 1 (pin A) 上的輸出針腳必須能夠在重新連接發生時封鎖媒體數據的流程。 在重新連線期間,針腳 A 與針腳 D 之間無法移動任何數據。 一般而言,這表示輸出釘選必須支援 IPinFlowControl 介面。 不過,如果 Filter 1 是起始重新連線的篩選條件,它可能會有一些內部機制來封鎖自己的數據流。

動態重新連線將涉及下列步驟:

  1. 封鎖數據流從釘選 A。
  2. 重新連接釘選 A 以釘選 D,可能透過新的中繼篩選。
  3. 解除封鎖釘選 A,讓數據再次開始流動。

步驟 1. 封鎖數據流

若要封鎖數據流,請在釘選 A 上呼叫 IPinFlowControl::Block。這個方法可以異步或同步呼叫。 若要以異步方式呼叫 方法 ,請建立 Win32 事件物件,並將事件句柄傳遞至 Block 方法。 方法會立即傳回。 使用 waitForSingleObject等函式,等候事件發出訊號。 釘選會在事件封鎖數據流時發出訊號。 例如:

// 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);
    }
}

若要同步 呼叫 方法,只需將值傳遞 NULL,而不是事件句柄即可。 現在方法會封鎖,直到作業完成為止。 在針腳準備好提供新的範例之前,可能不會發生這種情況。 如果篩選暫停,這可能需要任意的時間長度。 因此,請勿從主要應用程式線程進行同步呼叫。 使用背景工作線程,或以異步方式呼叫 方法。

步驟 2. 重新連線 Pin

若要重新連線釘選,請查詢篩選圖形管理員中的 IGraphConfig 介面,並呼叫 IGraphConfig::ReconnectIGraphConfig::Reconfigure重新連線 方法較容易使用;它會執行下列動作:

  • 停止中繼篩選條件(範例中的篩選 2),並從圖形中移除它們。
  • 視需要新增中繼篩選。
  • 連接所有針腳。
  • 暫停或執行任何新的篩選,以符合圖形的狀態。

重新連線 方法有數個選擇性參數,可用來指定針腳連線的媒體類型和要使用的中繼篩選。 例如:

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);     

如需詳細資訊,請參閱參考頁面。 如果 重新連線 方法不夠彈性,您可以使用 Reconfigure 方法,此方法會呼叫應用程式定義的回呼方法來重新連接針腳。 若要使用此方法,請在應用程式中實作 IGraphConfigCallback 介面。

呼叫 Reconfigure之前,請依照先前所述封鎖輸出釘選的數據流。 然後,推送仍在您重新連線之圖形區段中擱置的任何數據,如下所示:

  1. IPinConnection::NotifyEndOfStream 在重新連線鏈結中最遠下游的輸入針腳上呼叫 (範例中的 pin D)。 傳入 Win32 事件的句柄。
  2. 在輸入釘選上呼叫 IPin::EndOfStream,該輸入針腳會緊接在封鎖數據流的輸出針腳下游。 (在此範例中,數據流在釘選 A 上遭到封鎖,因此您會在 pin B 上呼叫 EndOfStream
  3. 等候事件發出訊號。 輸入針腳 (pin D) 會在收到串流結束通知時發出事件訊號。 這表示沒有數據在針腳之間移動,而且呼叫端可以安全地重新連接針腳。

請注意,IGraphConfig::Reconnect 方法會自動處理先前的步驟。 如果您使用 Reconfigure 方法,則只需要執行這些步驟。

將數據推送至圖形之後,請呼叫 Reconfigure,並將指標傳遞至 IGraphConfigCallback 回呼介面。 Filter Graph 管理員會呼叫您提供的 IGraphConfigCallback::Reconfigure 方法。

步驟 3. 解除封鎖數據流

重新連線針腳之後,請呼叫 IPinFlowControl::Block,並將第一個參數的值設為零,以解除封鎖數據流。

注意

如果動態重新連線是由篩選執行,您必須注意一些線程問題。 如果 Filter Graph 管理員嘗試停止篩選,它可能會死結,因為圖表會等候篩選停止,而同時篩選可能會等待數據推送至圖形。 為了防止可能的死結,本節所述的一些方法會處理 Win32 事件。 如果 Filter Graph Manager 嘗試停止篩選,篩選條件應該會發出事件訊號。 如需詳細資訊,請參閱 IGraphConfigIPinConnection

 

動態圖形建置