フィルター同士を接続するルーチン
DirectShowのフィルターを自力で接続させるためのルーチン。
参考サイト
function GetUnconnectedPin(pFilter: IBaseFilter; PinDir: PIN_DIRECTION; var ppPin:
IPin): HResult;
function ConnectFilters(pGraph: IGraphBuilder; pOut: IPin; pDest: IBaseFilter):
HResult; overload;
function ConnectFilters(pGraph: IGraphBuilder; pSrc: IBaseFilter; pDest: IBaseFilter):
HResult; overload;
一番下のConnectFilters関数をメインに使います。
その上の二つの関数は一番下のConnectFilters関数から呼ばれるルーチンです。
function GetUnconnectedPin(pFilter: IBaseFilter; PinDir: PIN_DIRECTION;
var ppPin: IPin): HResult;
// http://msdn.microsoft.com/ja-jp/library/cc973418.aspx
var
li_Ret : HResult;
pEnum : IEnumPins;
pPin : IPin;
pTmp : IPin;
ThisPinDir : TPinDirection ;
begin
ppPin :=
nil;
if (pFilter =
nil)
then
begin
Result := E_POINTER;
Exit;
end;
pEnum :=
nil;
pPin :=
nil;
li_Ret := pFilter.EnumPins(pEnum);
if (FAILED(li_Ret))
then
begin
Result := li_Ret;
Exit;
end;
while (pEnum.Next(1, pPin,
nil) = S_OK)
do
begin
pPin.QueryDirection(ThisPinDir);
if (ThisPinDir = PinDir)
then
begin
pTmp :=
nil;
li_Ret := pPin.ConnectedTo(pTmp);
if (Succeeded(li_Ret))
then
begin
// 既に接続済み。必要なピンではない。
pTmp :=
nil;
end
else
begin
// 未接続。これが必要なピン。
pEnum :=
nil;
ppPin := pPin;
Result := S_OK;
Exit;
end;
end;
pPin :=
nil;
end;
pEnum :=
nil;
// 一致するピンが見つからなかった。
Result := E_FAIL;
end;
function ConnectFilters(
pGraph : IGraphBuilder;
// フィルタ グラフ マネージャ。
pOut : IPin;
// アップストリーム フィルタの出力ピン。
pDest : IBaseFilter
// ダウンストリーム フィルタ。
): HResult;
overload;
// http://msdn.microsoft.com/ja-jp/library/cc973418.aspx
var
PinDir : TPinDirection;
pIn : IPin;
begin
if (pGraph =
nil)
or (pOut =
nil)
or (pDest =
nil)
then begin
Result := E_POINTER;
Exit;
end;
pOut.QueryDirection(PinDir);
if (PinDir <> PINDIR_OUTPUT)
then
begin
Result := E_FAIL;
Exit;
end;
// ダウンストリーム フィルタの入力ピンを検索する。
pIn :=
nil;
Result :=
GetUnconnectedPin(pDest, PINDIR_INPUT, pIn);
if (FAILED(Result))
then
begin
Exit;
end;
// 接続を試す。
Result :=
pGraph.Connect(pOut, pIn);
pIn :=
nil;
end;
function ConnectFilters(
pGraph : IGraphBuilder;
pSrc : IBaseFilter;
pDest : IBaseFilter
): HResult;
overload;
// http://msdn.microsoft.com/ja-jp/library/cc973418.aspx
var
pOut : IPin;
begin
if (pGraph =
nil)
or (pSrc =
nil)
or (pDest =
nil)
then begin
Result := E_POINTER;
Exit;
end;
// 最初のフィルタの出力ピンを検索する。
pOut :=
nil;
Result :=
GetUnconnectedPin(pSrc, PINDIR_OUTPUT, pOut);
if (FAILED(Result))
then
begin
Exit;
end;
Result := ConnectFilters(pGraph, pOut, pDest);
pOut :=
nil;
end;
フィルターには出力用(out)と入力用(in)のピンというものがあります。
フィルターによっては出力ピンだけのものや入力ピンだけのもの、あるいは複数の入出力ピンを持つものあります。
例えばファイルを読み込むソースフィルターは出力ピンだけを持つフィルターですしビデオ映像を画面に出力するビデオレンダラーは入力ピンだけを持つフィルターです。
更にビデオレンダラーのうちでもVMR7やVMR9などは複数の入力ピンを持っています。
これらの色々あるフィルターを繋ぐにはソースフィルターに近い上流側のフィルターの出力ピンと下流側のフィルターの入力ピンを取得して繋ぐということになります。
この出力ピンと入力ピンを繋ぐということを行っているのが1番目のConnectFilters関数中の
pGraph.Connect(pOut, pIn) の部分です。
ではその繋ぐためのピンをどうやって取得するのかというと、フィルター中にあるピンを列挙していき、まだどのフィルターのピンとも接続されていないピンを探し当てるということをします。
それを行っているのがGetUnconnectedPin関数です。
こうして繋ぎたいフィルター中の未接続のピンをGetUnconnectedPin関数で取得して、それをフィルターグラフのConnectメソッドで接続します。
それが pGraph.Connect(pOut, pIn); の部分なわけです。
このConnectFilters関数は引数を三つ取ります。
第一引数にはフィルタグラフを指定します。
第二引数には繋ぎたいフィルターのうち、入力(ソースフィルターなど)に近い上流側のフィルターを指定します。
第三引数には繋ぎたいフィルターのうち、出力(ビデオレンダラーなど)に近い下流側のフィルターを指定します。
function ConnectFilters(
pGraph : IGraphBuilder; // フィルターグラフ
pSrc : IBaseFilter; // 上流側フィルター
pDest : IBaseFilter // 下流側フィルター
): HResult;