Microsoft DirectX 8.0

プロジェクトのロードとプレビュー

ここでは、Microsoft® DirectShow® 編集サービス (DES) でプロジェクトをロードしてプレビューする方法を説明している。ここでは、空のタイムラインに XML プロジェクト ファイルをロードし、タイムラインをプレビュー用にレンダリングするサンプル アプリケーションを紹介している。このサンプル アプリケーションを変更して、この SDK に付属するサンプル XML プロジェクトを扱うことができる。

ここには、以下のトピックが含まれる。

プロジェクト ファイルのロード

プロジェクト ファイルをロードするには 2 つのコンポーネントが必要である。XML パーサーと空のタイムラインの 2 つである。XML パーサーは、XML プロジェクト ファイルを読み込み、ファイルに定義されている各オブジェクトを作成する。そして、作成したオブジェクトをタイムラインに挿入し、デフォルトのフレーム レートなどのタイムラインの属性を設定する。次のサンプル コードは、ファイルをロードする。

HRESULT         hr;
IAMTimeline     *pTL = NULL;
IXml2Dex        *pXML = NULL; 

hr = CoCreateInstance(CLSID_AMTimeline, 
            NULL, CLSCTX_INPROC_SERVER, 
            IID_IAMTimeline, (void**)&pTL);

hr = CoCreateInstance(CLSID_Xml2Dex, 
            NULL, CLSCTX_INPROC_SERVER, 
            IID_IXml2Dex, (void**)&pXML);

hr = pXML->ReadXMLFile(pTL, L"C:\\example.xtl"); 
pXML->Release();

パーサーは、プロジェクト ファイルのロードと保存のためのメソッドを持つ IXml2Dex インターフェイスを公開する。タイムラインは、タイムラインの操作と新しいタイムライン オブジェクトの作成のためのメソッドを持つ IAMTimeline インターフェイスを公開する。コードに示したように、CoCreateInstance 関数を呼び出して各コンポーネントを作成する。新しいインスタンスの作成によって、そのインターフェイスの参照カウントがインクリメントされることを忘れないこと。メモリ リークを回避するには、インターフェイスの使用が終わったら必ず解放する必要がある。この例では、IXml2Dex を指すポインタは必要なくなるので、このインターフェイスを解放できる。IAMTimeline を指すポインタは、タイムラインのプレビューのためにまだ必要である。

IXml2Dex::ReadXMLFile メソッドは、指定されたファイルを読み込み、そのファイルで定義されているオブジェクトをタイムラインに挿入する。ファイル名は、BSTR 値を使って指定される。例のコードを短くするために、ここではファイル名をリテラル文字列として指定している。通常は、[ファイルを開く] ダイアログ ボックスなどを使ってファイル名を取得する。

ReadXML メソッドは、動作が成功した場合は成功コードを返す。そうでない場合は、VFW_E_INVALID_FILE_FORMAT などのエラー コードを返す。エラー条件を正しく処理するためには、常に戻り値をチェックする必要がある。例のコードを短くするために、ここではエラーをチェックしていない。

プロジェクトのプレビュー

プロジェクトをプレビューするためには、タイムラインから DirectShow フィルタ グラフを構築するレンダリング エンジンと呼ばれるコンポーネントが必要である。フィルタ グラフが、プロジェクトを実際にレンダリングする。レンダリング エンジンを使って、プロジェクトのプレビューおよび最終出力ファイルの書き込みを行うことができる。

ここでは、レンダリング エンジンの詳細については説明しない。プレビューの場合は、いくつかのメソッド呼び出ししか必要としない。出力ファイルを書き込む方法などの詳細については、「プロジェクトのレンダリング」を参照すること。次のサンプル コードは、プレビュー グラフを構築する方法を示している。

IRenderEngine *pRender = NULL; 
hr = CoCreateInstance(CLSID_RenderEngine,
            NULL, CLSCTX_INPROC_SERVER,
            IID_IRenderEngine, (void**) &pRender);

hr = pRender->SetTimelineObject(pTL);
hr = pRender->ConnectFrontEnd( );
hr = pRender->RenderOutputPins( );

CoCreateInstance 関数を使ってレンダリング エンジンを作成する。次に、レンダリング エンジンの IRenderEngine インターフェイスの以下のメソッドを呼び出す。

グラフが構築されれば、DirectShow フィルタ グラフの場合と同じように、そのグラフを実行することによりプロジェクトをプレビューできる。最初に、IRenderEngine::GetFilterGraph メソッドを呼び出して、フィルタ グラフへのポインタを取得する。

IGraphBuilder   *pGraph = NULL;
hr = pRender->GetFilterGraph(&pGraph);

そのフィルタ グラフに、IMediaControl および IMediaEvent インターフェイスについて照会する。この 2 つのインターフェイスを使って、グラフを実行し、再生が完了するまで待機する。これらのインターフェイスの使い方の詳細については、「ファイルの再生法」および「イベントへの応答」を参照すること。次のコードは、これらのインターフェイスを使う方法の 1 つを示している。

IMediaControl   *pControl = NULL;
IMediaEvent     *pEvent = NULL;
long evCode;

pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
hr = pControl->Run();
hr = pEvent->WaitForCompletion(INFINITE, &evCode);
pControl->Stop();

この例のコードは、IMediaEvent::WaitForCompletion メソッド呼び出しの INFINITE パラメータによって、再生が完了するまでプログラムの実行を停止させる。ただし、再生中に問題が発生した場合には、プログラムが応答できなくなる可能性がある。実際のアプリケーションでは、メッセージ ループを使って再生が完了するまで待機する。また、ユーザーに再生を中断させる方法を提供することが推奨される。

クリーン アップ

レンダリング エンジンの使用が終わったら、必ず IRenderEngine::ScrapIt メソッドを呼び出す。このメソッドは、フィルタ グラフを削除し、レンダリング エンジンが保持していたすべてのリソースを解放する。

pRender->ScrapIt();

サンプル コード

以下は、ここで説明したサンプル アプリケーション全体のコードである。

#include <dshow.h>
#include <qedit.h>

// タイムラインをプレビューする。
void PreviewTL(IAMTimeline *pTL, IRenderEngine *pRender) 
{
    HRESULT hr;
    IGraphBuilder   *pGraph = NULL;
    IMediaControl   *pControl = NULL;
    IMediaEvent     *pEvent = NULL;

    // グラフを構築する。
    hr = pRender->SetTimelineObject(pTL);
    hr = pRender->ConnectFrontEnd( );
    hr = pRender->RenderOutputPins( );

    // グラフを実行する。
    hr = pRender->GetFilterGraph(&pGraph);
    pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
    hr = pControl->Run();

    long evCode;
    hr = pEvent->WaitForCompletion(INFINITE, &evCode);
    pControl->Stop();

    // クリーン アップする。
    pEvent->Release();
    pControl->Release();
    pGraph->Release();
}

void main( void )
{
    HRESULT         hr;
    IAMTimeline     *pTL = NULL;
    IRenderEngine   *pRender = NULL; 
    IXml2Dex        *pXML = NULL; 

    CoInitialize(NULL);
    hr = CoCreateInstance(CLSID_AMTimeline, 
                NULL, CLSCTX_INPROC_SERVER, 
                IID_IAMTimeline, (void**)&pTL);
    hr = CoCreateInstance(CLSID_Xml2Dex, 
                NULL, CLSCTX_INPROC_SERVER, 
                IID_IXml2Dex, (void**)&pXML);
    hr = CoCreateInstance(CLSID_RenderEngine,
                NULL, CLSCTX_INPROC_SERVER,
                IID_IRenderEngine, (void**)&pRender);

    // プロジェクト ファイルをロードする。
    hr = pXML->ReadXMLFile(pTL, L"C:\\example.xtl"); 
    pXML->Release();

    PreviewTL(pTL, pRender);

    // クリーン アップする。   
    pRender->ScrapIt();
    pTL->Release();
    pRender->Release();
    CoUninitialize();
}