共用方式為


建置 Recompression Graph

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

AVI 檔案重新壓縮的典型篩選圖形如下所示:

avi recompression 圖形

AVI 分割器篩選器會從檔案來源 (非同步) 篩選提取資料,並將其剖析為視訊和音訊串流。 視訊解壓縮器會將壓縮的視訊解碼,影片壓縮器會將其重新壓縮。 解壓縮程式的選擇取決於來源檔案; 智慧型連線會自動處理。 應用程式必須選擇冰箱,通常是藉由向使用者呈現清單。 (請參閱 選擇壓縮篩選器。)

壓縮的視訊接著會移至 AVI Mux 篩選器。 此範例中的音訊資料流程不會壓縮,因此它會直接從 AVI 分割器移至 AVI Mux。 AVI Mux 會交錯這兩個數據流,而 檔案寫入器篩選器 會將輸出寫入磁片。 請注意,即使原始檔案沒有音訊資料流程,也需要 AVI Mux。

建置此篩選圖形最簡單的方式是使用 Capture Graph Builder,這是用來建置擷取圖形和其他自訂篩選圖形的 DirectShow 元件。

首先,呼叫 CoCreateInstance 以建立擷取圖形產生器:

ICaptureGraphBuilder2 *pBuild = NULL;
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, 
                        NULL, CLSCTX_INPROC_SERVER,
    IID_ICaptureGraphBuilder2, (void **)&pBuild);

然後使用擷取圖形產生器來建置篩選圖形:

  1. 建置圖形的轉譯區段,其中包含 AVI Mux 篩選器和 檔案寫入器
  2. 將來源篩選和壓縮篩選新增至圖形。
  3. 將來源篩選準則連線到 MUX 篩選器。 擷取圖表產生器會插入剖析來源檔案所需的任何分割器和解碼器篩選。 它也可以透過壓縮篩選器來路由傳送視訊和音訊串流。

下列各節說明每個步驟。

建置轉譯區段

若要建置圖形的轉譯區段,請呼叫 ICaptureGraphBuilder2::SetOutputFileName 方法。 這個方法會採用輸入參數,以指定輸出的媒體子類型,以及輸出檔的名稱。 它會傳回 MUX 篩選和檔案寫入器的指標。 圖形建置的下一個階段需要 MUX 篩選準則。 此範例不需要檔案寫入器的指標,因此參數可以是 Null

IBaseFilter *pMux = NULL;
hr = pBuild->SetOutputFileName(
        &MEDIASUBTYPE_Avi, // File type. 
        wszOutputFile,     // File name, as a wide-character string.
        &pMux,             // Receives a pointer to the multiplexer.
        NULL);             // Receives a pointer to the file writer. 

當方法傳回時,MUX 篩選準則具有未處理的參考計數,因此請務必稍後釋放指標。

下圖顯示此時的篩選圖表。

篩選圖形的轉譯區段

MUX 篩選器會公開兩個介面來控制 AVI 格式:

新增來源和壓縮篩選

下一個步驟是將來源和壓縮篩選新增至篩選圖形。 當您呼叫 SetOutputFileName 時,擷取圖形產生器會自動建立 Filter Graph 管理員的實例。 呼叫 ICaptureGraphBuilder2::GetFiltergraph 方法,以取得它的指標:

IGraphBuilder *pGraph = NULL;
hr = pBuild->GetFiltergraph(&pGraph);

現在,呼叫 IGraphBuilder::AddSourceFilter 方法來新增非同步檔案來源篩選,以及 IFilterGraph::AddFilter 方法來新增視訊設備:

IBaseFilter *pSrc = NULL;
hr = pGraph->AddSourceFilter(wszInputFile, L"Source Filter", &pSrc);
hr = pGraph->AddFilter(pVComp, L"Compressor");

此時,來源篩選和壓縮篩選器不會連接到圖形中的其他任何專案,如下圖所示:

具有來源和壓縮篩選的篩選圖表

將來源連線到 Mux

最後一個步驟是透過視訊設備將來源篩選準則連線到 AVI Mux 篩選器。 使用 ICaptureGraphBuilder2::RenderStream 方法,此方法可將來源篩選上的輸出釘選連接到指定的接收篩選器,選擇性地透過壓縮篩選器。

前兩個參數會藉由指定釘選類別和媒體類型,指定要連接的來源篩選釘選。 非同步檔案來源篩選器只有一個輸出針腳,因此這些參數應該是 Null。 接下來的三個參數會指定來源篩選準則、如果有任何) ,則壓縮篩選 (,以及 Mux 篩選準則。

下列程式碼範例會透過影片壓縮來轉譯視訊串流:

hr = pBuild->RenderStream(
        NULL,       // Output pin category
        NULL,       // Media type
        pSrc,       // Source filter
        pVComp,     // Compression filter
        pMux);      // Sink filter (the AVI Mux)

下圖顯示目前為止的篩選圖表。

轉譯的視訊資料流程

假設來源檔案有音訊資料流程, AVI 分隔器 篩選器已建立音訊的輸出釘選。 若要連線此釘選,請再次呼叫 RenderStream:

hr = pBuild->RenderStream(NULL, NULL, pSrc, NULL, pMux);

此處未指定壓縮篩選器。 來源篩選的輸出釘選已經連接,因此 RenderStream 方法會在分割器篩選上搜尋未連接的輸出針腳。 它會尋找音訊釘選,並將它直接連接到 MUX 篩選器。 如果來源檔案沒有音訊資料流程,則第二次呼叫 RenderStream 將會失敗。 這是正常的現象。 圖形會在第一次呼叫 RenderStream 之後完成,因此第二次呼叫中的失敗是無損害的。

在此範例中,兩個 RenderStream 呼叫的順序很重要。 因為第二個呼叫未指定冰箱,所以它會從 AVI 分割器連接任何未連接的針腳。 如果您在另一個通話之前進行此呼叫,它可能會將視訊串流連線到 AVI Mux,而不需要您的視訊設備。 因此,壓縮篩選) 必須先進行更明確的呼叫 (。

上一個討論假設原始程式檔是 AVI 檔案。 不過,這項技術也適用于其他檔案類型,例如 MPEG 檔案。 產生的篩選圖表會稍有不同。

重新壓縮 AVI 檔案