共用方式為


使用擷取圖形產生器建置圖形

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

儘管其名稱如此,擷取圖形產生器仍可用於建置許多種類的自定義篩選圖形,而不只是擷取圖形。 本文提供如何使用這個對象的簡短概觀。

擷取圖形產生器會公開 ICaptureGraphBuilder2 介面。 首先,呼叫 CoCreateInstance 來建立擷取圖形產生器和篩選圖形管理員。 然後,使用 Filter Graph 管理員的指標呼叫 ICaptureGraphBuilder2::SetFiltergraph,以初始化擷取圖形產生器,如下所示:

IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;

// Create the Filter Graph Manager.
HRESULT hr =  CoCreateInstance(CLSID_FilterGraph, NULL,
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

if (SUCCEEDED(hr))
{
    // Create the Capture Graph Builder.
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, 
        (void **)&pBuilder);
    if (SUCCEEDED(hr))
    {
        pBuilder->SetFiltergraph(pGraph);
    }
};

連接篩選

ICaptureGraphBuilder2::RenderStream 方法會將鏈結中的兩或三個篩選連接在一起。 一般而言,當每個濾鏡沒有超過一個相同類型的輸入針腳或輸出針腳時,此方法效果最佳。 此討論一開始會忽略 renderStream 的前兩個參數,並將焦點放在最後三個參數。 第三個參數是 IUnknown 指標,可以指定篩選器(作為 IBaseFilter 介面指標)或輸出接點(作為 IPin 介面指標)。 第四個和第五個參數指定 IBaseFilter 指標。 RenderStream 方法會連接鏈結中的所有三個篩選。 例如,假設 ABC 是篩選條件。 假設每個過濾器都有一個輸入接腳和一個輸出接腳。 下列呼叫會將 A 連接到 B,然後將 B 連接到 C:

'RenderStream(NULL、NULL、A、B、C)'

所有連線都是「智慧型」,這表示會視需要將其他篩選新增至圖表。 如需詳細資訊,請參閱 Intelligent Connect。 若要只連線兩個篩選,請將中間值設定為 NULL。 例如,此呼叫會將 A 連接到 C:

'RenderStream(NULL、NULL、A、NULL、C)'

您可以呼叫 方法兩次來建立較長的鏈結:

'RenderStream(NULL, NULL, A, B, C)' 'RenderStream(NULL, NULL, C, D, E)'

如果最後一個參數 NULL,此方法會自動找到預設轉譯器。 它會針對視訊使用 視訊轉譯器,以及音訊 DirectSound 轉譯器。 因此:

RenderStream(NULL、NULL、A、NULL、NULL)

相當於

'RenderStream(NULL、NULL、A、NULL、R)'

其中 R 是適當的轉譯器。 若要連接視訊混合轉譯器篩選,而不是影片轉譯器,不過,您必須明確指定它。

如果您在第三個參數中指定過濾器,而不是針腳,您可能需要指定應該用於連接的輸出針腳。 這是方法前兩個參數的目的。 第一個參數只適用於擷取篩選。 它會指定表示針腳類別的 GUID。 如需類別的完整清單,請參閱 Pin 屬性集。 這兩個類別適用於所有擷取篩選條件:

  • PIN_CATEGORY_CAPTURE
  • PIN_CATEGORY_PREVIEW

如果擷取濾鏡沒有提供擷取和預覽的個別接腳,RenderStream 方法會插入 Smart Tee 濾鏡,這會將串流分割成擷取流和預覽流。 從應用程式的觀點來看,您可以直接將所有擷取過濾器視為具有個別的接腳,並忽略圖的基礎拓撲。

針對檔案擷取,請將擷取接腳連接到多工濾波器。 要進行即時預覽,將預覽端口連接到渲染器。 如果您切換這兩個類別,圖表可能會在檔案擷取期間卸除過多的畫面格;但如果圖表已正確連接,則會視需要卸除預覽畫面,以維持擷取數據流的輸送量。

下列範例示範如何連接這兩個數據流:

// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, NULL, pCapFilter, NULL, pMux);
// Preview:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, pCapFilter, NULL, NULL);

某些擷取篩選器也支援隱藏式字幕,由 PIN_CATEGORY_VBI表示。 若要擷取檔案的隱藏式輔助字幕,請將此類別轉譯為多任務篩選器。 若要在預覽視窗中檢視隱藏式輔助字幕,請連線到轉譯器:

// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, pMux);
// Preview on screen:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, NULL);

RenderStream 的第二個參數 用於識別媒體類型,通常是以下其中一項:

  • 媒體類型_音頻
  • 影片類型
  • MEDIATYPE_Interleaved (DV)

每當篩選的輸出針腳支援慣用媒體類型的列舉時,您就可以使用此參數。 針對檔案來源,擷取圖形產生器會視需要自動新增剖析器篩選,然後在剖析器上查詢媒體類型。 (如需範例,請參閱 重新壓縮 AVI 檔案。)此外,如果鏈結中的最後一個濾鏡有數個輸入接腳,此方法會嘗試列舉它們的媒體類型。 不過,並非所有篩選都支援這項功能。

尋找篩選和 Pins 上的介面

建置圖表之後,您通常需要找出圖表中篩選器和接針所公開的各種介面。 例如,擷取篩選可能會公開 IAMDroppedFrames 介面,而篩選的輸出針腳可能會公開 IAMStreamConfig 介面。

尋找介面最簡單的方式是使用 ICaptureGraphBuilder2::FindInterface 方法。 此方法會遍歷圖(篩選和釘選),直到找到所需的介面為止。 您可以指定搜尋的起點,而且您可以將搜尋限制為從起點篩選上游或下游。

下列範例會在影片預覽針腳上搜尋 IAMStreamConfig 介面:

IAMStreamConfig *pConfig = NULL;
HRESULT hr = pBuild->FindInterface(
    &PIN_CATEGORY_PREVIEW, 
    &MEDIATYPE_Video,
    pVCap, 
    IID_IAMStreamConfig, 
    (void**)&pConfig
);
if (SUCCESSFUL(hr))
{
    /* ... */
    pConfig->Release();
}

注意

本主題 "在篩選器或釘上尋找介面" 展示使用 IGraphBuilder 介面的替代方法,而非使用 ICaptureGraphBuilder2。 使用的方法取決於您的應用程式。 如果您的應用程式已經使用 ICaptureGraphBuilder2 來建置圖形,則 ICaptureGraphBuilder2::FindInterface 是很好的方法。 否則,請考慮使用 IGraphBuilder 方法。

 

尋找釘子

在較不常見的情況下,您可能需要在濾鏡上定位個別的釘選,不過在大部分情況下,RenderStreamFindInterface 方法會省去您的麻煩。 如果您需要在篩選器上尋找特定釘選,ICaptureGraphBuilder2::FindPin 輔助方法很有用。 指定類別、媒體類型(影片或音訊)、方向,以及針腳是否需要保持未連接。

例如,下列程式代碼會在捕捉濾鏡中搜尋未連接的影片預覽引腳:

IPin *pPin = NULL;
hr = pBuild->FindPin(
    pCap,                   // Pointer to the filter to search.
    PINDIR_OUTPUT,          // Search for an output pin.
    &PIN_CATEGORY_PREVIEW,  // Search for a preview pin.
    &MEDIATYPE_Video,       // Search for a video pin.
    TRUE,                   // The pin must be unconnected. 
    0,                      // Return the first matching pin (index 0).
    &pPin);                 // This variable receives the IPin pointer.
if (SUCCESSFUL(hr))
{
    /* ... */
    pPin->Release();
}

視訊擷取