フィルタまたはピンのインターフェイスの検索
DirectShow の多くの処理で、アプリケーションはフィルタ グラフ マネージャに対してメソッドを呼び出す。しかし、状況によっては、アプリケーションはフィルタかピンに直接メソッドを呼び出す必要がある。たとえば、多くのフィルタはフィルタの構成に使われる特別なインターフェイスを公開する。
フィルタ インターフェイスの場合、フィルタの IBaseFilter インターフェイスへのポインタを既に持っていることがある。その場合、QueryInterface を使えば他方のインターフェイスを取得できる。しかし、フィルタ グラフ マネージャがグラフにフィルタを追加することがある。(詳細については、「インテリジェント接続」を参照すること。)その場合、IEnumFilters インターフェイスを使ってグラフのすべてのフィルタをループし、それぞれのフィルタを順に問い合わせる。次の関数はこの処理を示している。
HRESULT FindFilterInterface(
IGraphBuilder *pGraph, // フィルタ グラフ マネージャへのポインタ。
REFGUID iid, // 取得するインターフェイスの IID。
void **ppUnk) // インターフェイス ポインタを取得する。
{
if (!pGraph || !ppUnk) return E_POINTER;
HRESULT hr = E_FAIL;
IEnumFilters *pEnum = NULL;
IBaseFilter *pF = NULL;
if (FAILED(pGraph->EnumFilters(&pEnum)))
{
return E_FAIL;
}
// すべてのフィルタにインターフェイスを問い合わせる。
while (S_OK == pEnum->Next(1, &pF, 0))
{
hr = pF->QueryInterface(iid, ppUnk);
pF->Release();
if (SUCCEEDED(hr))
{
break;
}
}
pEnum->Release();
return hr;
}
次の例は上の関数を使う。
hr = pGraph->RenderFile(L"C:\\Example.avi", 0);
if (SUCCEEDED(hr))
{
IIPDVDec *pDvDec;
hr = FindFilterInterface(pGraph, IID_IIPDVDec, (void**)&pDvDec);
if (SUCCEEDED(hr))
{
pDvDec->put_IPDisplay(DVRESOLUTION_QUARTER);
pDvDec->Release();
}
else if (hr == E_NOINTERFACE)
{
// このファイルには DV ビデオがない。
}
else
{
// 他のエラーが発生した。
}
}
まず、この例では再生用に AVI ファイルをレンダリングする。次に、ファイルに DV エンコードされたビデオがある場合、出力解像度を 4 分の 1 のサイズに設定する。出力解像度を設定するインターフェイスは IIPDVDec インターフェイスである。このインターフェイスは DV ビデオ デコーダ フィルタにより公開される。AVI ファイルに DV エンコードされたビデオがある場合、RenderFile メソッドはフィルタ グラフに DV ビデオ デコーダを自動的に入れる。その場合、FindFilterInterface 関数は成功し、IIPDVDec インターフェイスへのポインタを返す。それ以外の場合、関数は E_NOINTERFACE を返す。この値は、AVI ファイルに DV ビデオがないことを表す。
ピンのインターフェイスを見つけるには、IEnumPins インターフェイスを使い、フィルタのピンをループする。次の関数は、その方法を示している。
HRESULT FindPinInterface(
IBaseFilter *pFilter, // 検索するフィルタへのポインタ。
REFGUID iid, // インターフェイスの IID。
void **ppUnk) // インターフェイス ポインタを取得する。
{
if (!pFilter || !ppUnk) return E_POINTER;
HRESULT hr = E_FAIL;
IEnumPins *pEnum = 0;
if (FAILED(pFilter->EnumPins(&pEnum)))
{
return E_FAIL;
}
// すべてのピンにインターフェイスを問い合わせる。
IPin *pPin = 0;
while (S_OK == pEnum->Next(1, &pPin, 0))
{
hr = pPin->QueryInterface(iid, ppUnk);
pPin->Release();
if (SUCCEEDED(hr))
{
break;
}
}
pEnum->Release();
return hr;
}
次の関数はフィルタ "または" ピンのインターフェイスを検索する。
HRESULT FindInterfaceAnywhere(
IGraphBuilder *pGraph,
REFGUID iid,
void **ppUnk)
{
if (!pGraph || !ppUnk) return E_POINTER;
HRESULT hr = E_FAIL;
IEnumFilters *pEnum = 0;
if (FAILED(pGraph->EnumFilters(&pEnum)))
{
return E_FAIL;
}
// グラフのすべてのフィルタ内をループする。
IBaseFilter *pF = 0;
while (S_OK == pEnum->Next(1, &pF, 0))
{
hr = pF->QueryInterface(iid, ppUnk);
if (FAILED(hr))
{
// フィルタはインターフェイスを公開しないが、
// そのピンの 1 つは公開している可能性がある。
hr = FindPinInterface(pF, iid, ppUnk);
}
pF->Release();
if (SUCCEEDED(hr))
{
break;
}
}
pEnum->Release();
return hr;
}
ここに示したすべての関数は QueryInterface が最初に成功した時点で停止する点に注意すること。
参照