DirectShow 使用手引き

再生コントロール

再生を開始するには、IMediaControl::Run() メソッドを使用します。

  1. ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
  2. if (ctrl != 0) {
  3. ctrl->Run();
  4. }

再生の一時停止、停止を行うには、IMediaControl::Pause(), Stop() メソッドを使用します。

  1. ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
  2. if (ctrl != 0) {
  3. ctrl->Pause();
  4. }
  5. ...
  6. ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
  7. if (ctrl != 0) {
  8. ctrl->Stop();
  9. }

フィルターグラフイベントの取得

再生終了などのイベントを取得するには、以下のようにします。

  1. HWND hwnd;
  2. ...
  3. ATL::CComQIPtr<IMediaEventEx> me(m_FilterGraph);
  4. if (me != 0) {
  5. hRslt = me->SetNotifyWindow(
  6. (OAHWND)hwnd,
  7. WM_EVENT_NOTIFY,
  8. 0);
  9. if (FAILED(hRslt)) {
  10. return;
  11. }
  12. }

イベント発生時に、ウィンドウメッセージが送信されるように設定します。

  1. MESSAGE_HANDLER(WM_EVENT_NOTIFY, OnEventNotify)
  2. ...
  3. LRESULT OnEventNotify(
  4. UINT uMsg,
  5. WPARAM wParam,
  6. LPARAM lParam,
  7. BOOL& bHandled)
  8. {
  9. if (m_FilterGraph == 0) {
  10. return 0;
  11. }
  12. ATL::CComQIPtr<IMediaEvent> me(m_FilterGraph);
  13. if (me != 0) {
  14. LONG lEventCode = 0;
  15. LONG_PTR lParam1 = 0;
  16. LONG_PTR lParam2 = 0;
  17. HRESULT hRslt = me->GetEvent(
  18. &lEventCode,
  19. &lParam1,
  20. &lParam2,
  21. 0);
  22. if (SUCCEEDED(hRslt)) {
  23. if (lEventCode == EC_COMPLETE) {
  24. ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
  25. if (ctrl != 0) {
  26. ctrl->Stop();
  27. }
  28. }
  29. me->FreeEventParams(
  30. lEventCode,
  31. lParam1,
  32. lParam2);
  33. }
  34. }
  35. return 0;
  36. }

メッセージ処理の例は、以上のようになります。

IMediaEvent::GetEvent(), IMediaEvent::FreeEventParams() メソッドを使用して、イベント の情報を取得します。

ここでは、EC_COMPLETE (再生終了イベント) のとき、フィルターグラフを停止させています。

再生位置の取得

現在再生中の位置を取得するには、以下のように記述します。

  1. ATL::CComQIPtr<IMediaSeeking> seek(m_FilterGraph);
  2. if (seek != 0) {
  3. INT64 pos= 0;
  4. seek->GetCurrentPosition(&pos);
  5. ...
  6. }

特別な設定を行わない限り、取得される時間の単位は、100 ns 単位の値となります。(REFERENCE_TIME)

再生時間の取得

コンテンツの再生時間を取得するには、以下のように記述します。

  1. ATL::CComQIPtr<IMediaSeeking> seek(m_FilterGraph);
  2. if (seek != 0) {
  3. INT64 duration = 0;
  4. seek->GetDuration(&duration);
  5. ...
  6. }

特に設定しない場合、取得される時間の単位は、100 ns 単位の値となります。(REFERENCE_TIME)

シーク処理

任意の再生位置へ移動処理を行うには、以下のように記述します。

  1. INT64 pos;
  2. ...
  3. if (m_FilterGraph != 0) {
  4. ATL::CComQIPtr<IMediaSeeking> seek(m_FilterGraph);
  5. if (seek != 0) {
  6. seek->SetPositions(
  7. &pos,
  8. AM_SEEKING_AbsolutePositioning,
  9. 0,
  10. AM_SEEKING_NoPositioning);
  11. }
  12. }

通常、移動先の時間単位は、100 ns 単位となります。(REFERENCE_TIME)

フォーマット情報取得

フィルターの出力ピンのフォーマット情報を取得するには、以下のようにできます。

  1. ATL::CComPtr<IPin> pin;
  2. hRslt = filter->FindPin(L"Audio", &pin);
  3. if (FAILED(hRslt)) {
  4. return;
  5. }
  6. ATL::CComPtr<IEnumMediaTypes> em;
  7. hRslt = pin->EnumMediaTypes(&em);
  8. if (FAILED(hRslt)) {
  9. return;
  10. }
  11. for (; ; )
  12. AM_MEDIA_TYPE* mt = 0;
  13. ULONG c = 0;
  14. hRslt = em->Next(1, &mt, &c);
  15. if (FAILED(hRslt)) {
  16. return;
  17. }
  18. if (mt == 0) {
  19. break;
  20. }
  21. if (mt->formattype == FORMAT_WaveFormatEx &&
  22. mt->pbFormat != 0 &&
  23. mt->cbFormat >= sizeof(WAVEFORMATEX)) {
  24. WAVEFORMATEX* w = (WAVEFORMATEX*)(mt->pbFormat);
  25. ...
  26. }
  27. QDSA_FreeMediaType(mt);
  28. }

IPin::EnumMediaTypes() メソッドで IEnumMediaTypes インターフェイスを取得し、 IEnumMediaTypes::Next() メソッドで、メディアタイプを列挙します。

取得したメディアタイプ構造体のメモリーを解放するには、QDSA_FreeMediaType() 関数 を使用できます。