次の方法で共有


再圧縮グラフの構築

[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayerIMFMediaEngine、および Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayerIMFMediaEngineAudio/Video Capture を使用することを強くお勧めします。 Microsoft は、従来の API を使用する既存のコードを、可能であれば新しい API を使用するように書き直すよう提案しています。]

AVI ファイルの再圧縮の一般的なフィルター グラフは、次のようになります。

avi 再圧縮グラフ

AVI スプリッター フィルターは、ファイル ソース (非同期) フィルターからデータをプルし、ビデオ ストリームとオーディオ ストリームに解析します。 ビデオ圧縮解除器は、圧縮されたビデオをデコードします。圧縮されたビデオは、ビデオ コンプレッサーによって再圧縮されます。 解凍器の選択は、ソース ファイルによって異なります。 これは Intelligent Connect によって自動的に処理されます。 アプリケーションは、通常、ユーザーにリストを提示することによって、コンプレッサーを選択する必要があります。 ( 「圧縮フィルターの選択」を参照してください)。

圧縮されたビデオは、 AVI 多重化フィルターに移動します。 この例のオーディオ ストリームは圧縮されないため、AVI スプリッターから AVI Mux に直接移動します。 AVI Mux は 2 つのストリームをインターリーブし、 ファイル ライター フィルター によって出力がディスクに書き込まれます。 元のファイルにオーディオ ストリームがない場合でも、AVI Mux が必要であることに注意してください。

このフィルター グラフを作成する最も簡単な方法は、 キャプチャ グラフ ビルダーを使用することです。これは、キャプチャ グラフやその他のカスタム フィルター グラフを構築するための DirectShow コンポーネントです。

まず、CoCreateInstance を呼び出してキャプチャ グラフ ビルダーを作成します。

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

次に、Capture Graph Builder を使用してフィルター グラフを作成します。

  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 形式を制御するための 2 つのインターフェイスを公開します。

ソース フィルターと圧縮フィルターを追加する

次の手順では、ソース フィルターと圧縮フィルターをフィルター グラフに追加します。 SetOutputFileName を呼び出すと、Capture Graph Builder によって Filter Graph Manager のインスタンスが自動的に作成されます。 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");

この時点で、次の図に示すように、ソース フィルターと圧縮フィルターはグラフ内の他の何にも接続されません。

ソース フィルターと圧縮フィルターを使用してグラフをフィルター処理する

ソースを多重化に接続する

最後のステップは、ビデオコンプレッサーを介して、ソースフィルタをAVIマルチプレクサフィルタに接続することです。 ICaptureGraphBuilder2::RenderStream メソッドを使用します。このメソッドは、ソース フィルターの出力ピンを、必要に応じて圧縮フィルターを介して指定されたシンク フィルターに接続します。

最初の 2 つのパラメーターでは、接続するソース フィルターのピンを指定します。ピン カテゴリとメディアの種類を指定します。 非同期ファイル ソース フィルターには出力ピンが 1 つしかないため、これらのパラメーターは NULL にする必要があります。 次の 3 つのパラメーターは、ソース フィルター、圧縮フィルター (存在する場合)、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 の 2 回目の呼び出しは失敗します。 これは正しい動作です。 グラフは RenderStream の最初の呼び出しの後に完了するため、2 番目の呼び出しの失敗は無害です。

この例では、2 つの RenderStream 呼び出しの順序が重要です。 2 回目の呼び出しではコンプレッサーが指定されていないため、AVI スプリッターから接続されていないピンが接続されます。 この呼び出しを他の呼び出しの前に行うと、ビデオ コンプレッサーなしでビデオ ストリームが AVI Mux に接続される可能性があります。 したがって、(圧縮フィルターを使用して) より具体的な呼び出しが最初に行われる必要があります。

前の説明では、ソース ファイルが AVI ファイルであることを前提としています。 ただし、この手法は、MPEG ファイルなどの他のファイルの種類でも機能します。 結果として得られるフィルター グラフは多少異なります。

AVI ファイルの再圧縮