Microsoft DirectX 8.0

DMO サンプル

説明

DMO サンプルは、Microsoft® DirectX® メディア オブジェクト (DMO) のサンプルである。MPEG-1 ビデオ パケットを入力とし、出力ストリームを 2 つ生成する。最初の出力ストリームには、RGB 565 フォーマットのビデオ フレームが含まれている。各フレームは MPEG-1 ビデオから取得したタイム コードを表示し、それがない場合は何も表示しない。2 つめの出力ストリームは、タイム コードの付いた、オプションのテキスト ストリームである。

DMO サンプルは、IMediaObjectImpl 基底クラス テンプレートを使用して、IMediaObject インターフェイスを実装する。このテンプレートの使用法の詳細については、「DMO 基底クラスの使い方」を参照すること。Active Template Library (ATL) は、登録、集合、IUnknown、DLL エントリ ポイントなど、さまざまな COM の詳細を処理する。

パス

ソース :(SDK ルート)\samples\Multimedia\DirectShow\DMO\DMOSample

ユーザー ガイド

このプロジェクト ワークスペースでは、Dmosample.dll という名前の DLL を作成する。Regsvr32 ユーティリティを使って DLL を作成する。この DMO の動作を見るには、 Microsoft® DirectShow® GraphEdit ユーティリティを使用する。ただし、MPEG-1 ビデオ ファイルが必要である。次の手順に従って実行する。

  1. GraphEdit を実行する。
  2. MPEG-1 ファイルをレンダリングする。
  3. フィルタ グラフから MPEG-1 ビデオ デコーダ フィルタを選択して、Del キーを押す。
  4. グラフに DMO サンプルを挿入する。
  5. MPEG-1 ストリーム スプリッタ上の [Video] というラベルの付いた小さなボックスから、DMO サンプル上の [in0] というボックスまでマウスをドラッグして、MPEG-1 ストリーム スプリッタを DMO サンプルに接続する。(図を参照すること)
  6. DMO サンプルをビデオ レンダラに接続する。
    • DMO サンプル上の [out0] というラベルの付いたボックスから、ビデオ レンダラ上の [Input] というラベルの付いたボックスまでマウスをドラッグする。
    • GraphEdit により、RGB タイプ間の変換を行うカラー スペース変換 フィルタが自動的に挿入される。
  7. [GraphEdit] ツール バーの [Play] ボタンを押すか、または [Graph] メニューで [Play] をクリックする。

グラフを実行すると、タイム コードを表示する [Video] ウィンドウが現れる。

DMO サンプル フィルタの接続

プログラミング上の注意

DMO サンプルには、以下のソースおよびヘッダー ファイルが含まれている。

DMO サンプルは、以下のリソース ファイルも使用する。

次の注意は、実装について詳細に説明している。

Dmosample.cpp

このファイルには、ATL が DMO オブジェクトを作成して登録するのに使用するオブジェクト マップが含まれる。また、エクスポートされる DLL 関数も含まれる。このような関数には、エントリ ポイント関数 (DllMain)、および COM に必要な関数 (DllCanUnloadNowDllGetClassObjectDllRegisterServer、および DllUnregisterServer) がある。

ATL COM AppWizard は、このファイルに含まれるコードの大部分を自動生成する。次の 2 つが追加される。

Resource.h

このヘッダー ファイルで宣言される 1 つの定数 IDR_SAMPLE は、ATL の自動登録メカニズムで使用される。定数 IDR_SAMPLE は、テキスト リソースを識別する。これはリソース ファイル Sample.rgs で定義され、リソース ファイル Dmosample.rc によりインポートされる。ヘッダー ファイル Sample.h には、次の行がある。

DECLARE_REGISTRY_RESOURCEID(IDR_SAMPLE)  

これにより、ATL は IDR_SAMPLE リソースに宣言された登録情報を使用できる。

Sample.h

DEFINE_GUID マクロは、DMO のクラス識別子 (CLSID) を宣言する。

CSample クラスは次のクラスから派生する。

CSample は、 カスタム マーシャリングを実行するフリー スレッド マーシャラ オブジェクトを集める。COM ライブラリが、サンプル プロセス内の複数のスレッドにまたがって CSample ポインタをマーシャリングする場合、まったく同じポインタが返される。COM ライブラリが複数のプロセスまたは複数のマシンにまたがってオブジェクトをマーシャリングしようとすると、エラーが発生する。ATL は、フリー スレッド マーシャラを集成するために必要なすべてのコードを追加する。このコードは、FinalConstruct メソッドと FinalRelease メソッドに現れる。COM マップ内の COM_INTERFACE_ENTRY_AGGREGATE エントリは、フリー スレッド マーシャラに IMarshal インターフェイスを委任する。

CSample クラスは、次のメンバ変数を宣言する。

m_pUnkMarshalerフリー スレッド マーシャラ オブジェクトへのポインタ。
m_pBuffer入力バッファへのポインタ。DMO はすべての入力を処理するまで、バッファの参照カウントを保持する。
m_pbData入力バッファ内の次のバイトへのポインタ。
m_cbData未処理のバイト数。
m_rtFrame最後の出力フレームのタイム スタンプ。
m_StreamStateMPEG データを解析する、CStreamState ヘルパ クラスのインスタンス。
m_bPictureDMO が出力するピクチャ情報を持っているかどうかを示す、ブール型フラグ。

Sample.cpp

このファイルは、CSample クラスにメソッドを実装する。

InternalGetInputStreamInfo

DMO は、任意のバウンダリに整列された任意のバイト数を処理できるので、このメソッドはゼロ フラグを返す。

InternalGetOutputStreamInfo

最初の出力ストリームは、固定サイズのサンプル全体を一度に作成する。これは、ビデオ デコーダでよく行われる。2 番目の出力ストリームはオプションである。返されるフラグは、これらの属性を示す。

InternalCheckInputType

入力タイプは、FORMAT_MPEGVide フォーマット タイプの MPEG-1 ビデオ ペイロードでなければならない。入力タイプの設定後、メソッドはフォーマットの変更を受け付けない。

InternalCheckOutputType

このメソッドは、出力フォーマットを検証する。出力ストリームは次の 2 つである。

  • ストリーム 0。このストリームでサポートされる唯一のメディア タイプは RGB-565 である。実際のビデオ デコーダは通常、複数のフォーマットをサポートする。また、出力のフレーム サイズは、入力のフレーム サイズと一致しなければならない。これは、実際のビデオ デコーダの多くに当てはまる。このストリームは、入力タイプが設定されてからでないと設定できない。
  • ストリーム 1。メディア タイプは MEDIATYPE_Text でなければならない。

タイプの設定後、新しいタイプが現在のタイプに一致しない場合、メソッドは失敗する。DMO がストリーミング中にフォーマット変更を処理できない場合は、同様のコードを含める必要がある。実際、サンプル DMO は、1 度に 1 つの出力フレームを生成するので、フォーマット変更を容易に受け入れることができる。

InternalGetInputType

このメソッドは、タイプを返さない。このため、あらゆるインデックス値が範囲外となり、戻り値は DMO_E_NO_MORE_ITEMS である。詳細については、「IMediaObject::GetInputType」を参照すること。

InternalGetOutputType

入力タイプが設定されていない場合、このメソッドはタイプを返さない。設定されている場合、各ストリームに 1 つのタイプが返される。ストリーム 0 の場合、入力サイズに等しいフレーム サイズの RGB-565 が返される。ストリーム 1 の場合、MEDIATYPE_Text が返される。

InternalGetInputSizeInfo

入力ストリームの最小バッファ サイズは 1 バイトであり、整列要件はない。ストリームはルックアヘッドを実行しない。

InternalGetOutputSizeInfo

ストリーム 0 の場合、バッファは出力サンプルを保持できるサイズが必要である。ストリーム 1 の場合、バッファはタイム スタンプ付きのテキスト文字列を保持できるサイズが必要である。

InternalFlush

このメソッドは、m_pBuffer (ATL スマート ポインタ) を NULL に設定することで、入力バッファを解放する。また、CStreamState オブジェクトをリセットする InternalDiscontinuity メソッドも呼び出す。

InternalProcessInput

このメソッドは、可能な限り多くの入力データを処理する。処理は次の手順で実行される。

  • Calls IMediaBuffer::GetBufferAndLength メソッドを呼び出して、入力データへのポインタと入力データのサイズを取得する。
  • 入力バッファへの参照カウントを保持する。m_pBuffer 変数は、ATL スマート ポインタなので、この変数に値を設定すると、IUnknown::AddRef メソッドを呼び出す効果を持つ。
  • タイム スタンプを CStreamState オブジェクトに渡す。サンプルにタイム スタンプがない場合は、値 INVALID_TIME を使用する。
  • プロセス ヘルパ メソッドを呼び出して、データを処理する。

InternalProcessOutput

出力するデータがない場合、このメソッドは S_FALSE を返す。データがある場合、出力データを生成する。ストリーム 0 の場合、次の手順で実行される。

  • 出力バッファが出力データを保持するのに十分なサイズであることを確認する。ない場合、メソッドはエラーを返す。
  • OurFillRect メソッドを呼び出して、背景を描画し、DrawOurText メソッドを呼び出して、テキストを描画する。
  • タイム スタンプを設定する。このフレームに有効なタイム スタンプがある場合は、それを使用する。ない場合は、前のタイム スタンプを平均フレーム レートでインクリメントする。
  • Process メソッドを再び呼び出して、入力バッファに残っていればすべてのデータを処理する。これにより出力データが増えた場合、DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE フラグを設定する。

ストリーム 1 はオプションであるので、呼び出し側はストリーム 1 用のバッファを割り当てていないことがある。ストリーム 1 に出力バッファがないとしても、DMO はタイム コードをテキスト文字列として書き込む。タイム スタンプと処理フラグはストリーム 0 のものを参照する。

InternalAcceptingInput

DMO に前の入力バッファの参照カウントがまだある場合、DMO はそれ以上の入力を受け付けない。

Process

このプライベート メソッドは、CStreamState オブジェクトを更新しながら、入力データを 1 度に 1 バイトずつ順に処理する。入力データを処理し終えるまでに CStreamState オブジェクトがピクチャ バウンダリを見つけると、Process メソッドは S_OK を返す。ピクチャ バウンダリがない場合は、S_FALSE を返す。