再圧縮グラフの構築
[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、および Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayer、IMFMediaEngine、Audio/Video Capture を使用することを強くお勧めします。 Microsoft は、従来の API を使用する既存のコードを、可能であれば新しい API を使用するように書き直すよう提案しています。]
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 を使用してフィルター グラフを作成します。
- AVI Mux フィルターと ファイル ライターを含むグラフのレンダリング セクションを作成します。
- ソース フィルターと圧縮フィルターをグラフに追加します。
- ソース フィルターを 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 つのインターフェイスを公開します。
- IConfigInterleaving インターフェイス: インターリーブ モードを設定します。
- IConfigAviMux インターフェイス: マスター ストリームと AVI 互換性インデックスを設定します。
ソース フィルターと圧縮フィルターを追加する
次の手順では、ソース フィルターと圧縮フィルターをフィルター グラフに追加します。 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 ファイルなどの他のファイルの種類でも機能します。 結果として得られるフィルター グラフは多少異なります。
関連トピック