次の方法で共有


DirectShow 編集サービスにおけるデコーダの選択

DirectShow 編集サービス (DES) がビデオ編集プロジェクトをレンダリングするとき、レンダリング エンジンは必要なデコーダを自動的に選択する。この処理は IRenderEngine::ConnectFrontEnd メソッド内で行われるか、レンダリング中に動的に行われる。

ユーザーは、特定のファイルをデコードできる複数のデコーダをインストールしていることがある。MPEG-2 コンテンツの場合、これは特に当てはまる。DirectShow が MPEG-2 デコーダを提供していないため、ユーザーはサード パーティのデコーダをインストールすることが多いためである。複数のデコーダが利用できる場合、DES はインテリジェント接続アルゴリズムを使ってデコーダを選択する。

アプリケーションが使うデコーダを直接指定する方法はない。しかし、IAMGraphBuilderCallback コールバック インターフェイスを使い、間接的にデコーダを選択できる。アプリケーションにこのインターフェイスを実装すると、グラフ作成プロセス中に通知を受け、グラフから特定のフィルタを拒否できる。

最初に、IAMGraphBuilderCallback インターフェイスを公開するクラスを実装する。

class GraphBuilderCB : public IAMGraphBuilderCallback
{
public:
     // メソッド宣言 (省略)。
};

次に、フィルタ グラフ マネージャのインスタンスを作成し、コールバック通知を受け取るようにクラスを登録する。

// コールバック オブジェクトのインスタンスを宣言する。
GraphBuilderCB GraphCB; 

// フィルタ グラフ マネージャを作成する。
CComPtr<IGraphBuilder> pGraph;
hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if (FAILED(hr))
{
    // エラー処理 (省略)。
}
// コールバックを受け取るように登録する。
CComQIPtr<IObjectWithSite> pSite(pGraph);
if (pSite)
{
    hr = pSite->SetSite((IUnknown*)&GraphCB);
}

次に、レンダリング エンジンを作成し、フィルタ グラフ マネージャへのポインタを使って IRenderEngine::SetFilterGraph メソッドを呼び出す。この処理により、レンダリング エンジンは独自のフィルタ グラフ マネージャを作成せずに、コールバック用に構成されたインスタンスを代わりに使うことになる。

CComPtr<IRenderEngine> pRender;
hr = pRender.CoCreateInstance(CLSID_RenderEngine);
if (FAILED(hr))
{
    // エラー処理 (省略)。
}

hr = pRender->SetFilterGraph(pGraph);

プロジェクトがレンダリングされると、フィルタ グラフ マネージャが新しいフィルタを作成する直前に、アプリケーションの IAMGraphBuilderCallback::SelectedFilter メソッドが呼び出される。SelectedFilter メソッドは、フィルタ用のモニカを表す IMoniker インターフェイスへのポインタを受け取る。モニカを調べ、フィルタを拒否することを決めたら、SelectedFilter メソッドからエラー コードを返す。

ここで難しいのは、デコーダを表すモニカ、特に拒否したいデコーダを表すモニカを識別することである。以下のような解決方法がある。

  • プロジェクトをレンダリングする前に、IFilterMapper2::EnumMatchingFilters メソッドを使い、必要な入力タイプを受け付けるように登録されているフィルタのリストを作成する。ビデオまたはオーディオの圧縮タイプの場合、このリストはデコーダの集合にマップされる。

  • EnumMatchingFilters メソッドはモニカのコレクションを返す。「フィルタ マッパーの使い方」に説明されているように、コレクションのモニカごとに DisplayName プロパティを取得する。

  • 表示名のリストを格納するが、デコードに使うフィルタに一致する表示名は省く。ソフトウェア フィルタの表示名は次の形式を取る。

    OLESTR("@device:sw:{CategoryGUID}\{FilterCLSID}");
    

    ここで、CategoryGUID はフィルタ カテゴリの GUID であり、FilterCLSID はフィルタの CLSID である。DMO の場合、フォーマットは同じだが、 sw を dmo に変更する。

    リストには、必要なメディア タイプを出力するが、優先フィルタではないすべてのフィルタの表示名が含まれる。

  • SelectedFilter メソッドで、提示されたモニカの DisplayName プロパティを取得し、保存されたリストと突き合わせて調べる。表示名がリストのエントリに一致する場合、そのフィルタは拒否する。それ以外の場合、S_OK を返してそのフィルタを受け付ける。