次の方法で共有


フィルタまたはピンのインターフェイスの検索

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 が最初に成功した時点で停止する点に注意すること。

参照