次の方法で共有


ファイルの再生法

ここでは、DirectShow プログラミングの一例を示す。オーディオまたはビデオ ファイルを再生する簡単なコンソール アプリケーションが示されている。このプログラムはほんの数行であるが、DirectShow プログラミングの可能性の一端を顕著に示している。

DirectShow アプリケーション プログラミングの概要」で説明しているように、DirectShow アプリケーションが実行する基本的な手順は常に同じである。

  1. フィルタ グラフ マネージャのインスタンスを作成する。
  2. フィルタ グラフ マネージャを使ってフィルタ グラフを作成する。
  3. グラフを実行し、データをフィルタで処理する。

まず最初に、CoInitialize を呼び出して COM ライブラリを初期化する。

HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
    // ここにエラー処理コードを追加する。 この例ではわかりやすくするために省略している。
}

説明を簡単にするために、この例では戻り値を無視しているが、通常はメソッドの呼び出しからの HRESULT 値をチェックする必要がある。

次に、CoCreateInstance を呼び出してフィルタ グラフ マネージャを作成する。

IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

ここに示されているように、クラス識別子 (CLSID) は CLSID_FilterGraph である。フィルタ グラフ マネージャはインプロセス DLL として提供されるので、実行コンテキストは CLSCTX_INPROC_SERVER である。DirectShow ではフリースレッド モデルをサポートしているので、COINIT_MULTITHREADED フラグを指定して CoInitializeEx を呼び出すこともできる。

CoCreateInstance を呼び出すと IGraphBuilder インターフェイスが返される。このインターフェイスにフィルタ グラフを作成するためのほとんどのメソッドが含まれている。この例では、これ以外に 2 つのインターフェイスが必要である。

  • IMediaControl はストリーミングを制御する。このインターフェイスには、グラフを停止および開始するメソッドが含まれている。
  • IMediaEvent には、フィルタ グラフ マネージャからイベントを取得するためのメソッドがある。この例では、このインターフェイスを使って、再生が完了するまで待機する。

これらのインターフェイスはいずれもフィルタ グラフ マネージャによって公開される。これらのインターフェイスを照会するには、返された IGraphBuilder ポインタを使う。

IMediaControl *pControl;
IMediaEvent   *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

これで、フィルタ グラフを作成できる。ファイルの再生については、単一のメソッドの呼び出しで行われる。

hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);

IGraphBuilder::RenderFile メソッドは、指定されたファイルを再生できるフィルタ グラフを作成する。最初のパラメータは、ワイド文字 (2 バイト) の文字列で表されたファイル名である。2 つ目のパラメータは予約済みで、NULL でなければならない。

このメソッドは、指定されたファイルが存在しない場合、またはファイル フォーマットが認識されない場合、失敗することがある。ここでは、メソッドが成功したと仮定して、フィルタ グラフで再生の準備ができたとする。グラフを実行するには、IMediaControl::Run メソッドを呼び出す。

hr = pControl->Run();

フィルタ グラフを実行すると、データはフィルタ内で処理され、ビデオおよびオーディオとしてレンダリングされる。再生は別のスレッドで続けられる。IMediaEvent::WaitForCompletion メソッドを呼び出して、再生が完了するまで待機できる。

long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);

このメソッドは、ファイルの再生が終了するまで、または指定されたタイムアウト間隔が経過するまで、ブロック状態となる。値 INFINITE は、ファイルの再生が完了するまで、アプリケーションが無期限にブロック状態となることを意味する。より現実的なイベント処理の例については、「イベントへの応答」を参照すること。

アプリケーションが終了したら、インターフェイスのポインタを解放し、COM ライブラリを閉じる。

pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();

サンプル コード

以下は、ここで説明した例のコード全体である。

#include <dshow.h>
void main(void)
{
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent   *pEvent = NULL;

    // COM ライブラリを初期化する。
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }

    // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }

    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

    // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
    hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
    if (SUCCEEDED(hr))
    {
        // グラフを実行する。
        hr = pControl->Run();
        if (SUCCEEDED(hr))
        {
            // 完了するまで待機する。
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);

            // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
            // 無期限にブロックする場合がある。
        }
    }
    pControl->Release();
    pEvent->Release();
    pGraph->Release();
    CoUninitialize();
}

参照