Show page source of DirectShowUseage #45990

= !DirectShow 使用手引き =

== 再生コントロール

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

{{{ code c
ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
if (ctrl != 0) {
	ctrl->Run();
}
}}}

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

{{{ code c
ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
if (ctrl != 0) {
	ctrl->Pause();
}

...

ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
if (ctrl != 0) {
	ctrl->Stop();
}
}}}

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

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

{{{ code c
HWND hwnd;

...

ATL::CComQIPtr<IMediaEventEx> me(m_FilterGraph);
if (me != 0) {
	hRslt = me->SetNotifyWindow(
		(OAHWND)hwnd,
		WM_EVENT_NOTIFY,
		0);
	if (FAILED(hRslt)) {
		return;
	}
}
}}}

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

{{{ code c
MESSAGE_HANDLER(WM_EVENT_NOTIFY, OnEventNotify)

...

LRESULT OnEventNotify(
	UINT   uMsg,
	WPARAM wParam,
	LPARAM lParam,
	BOOL&  bHandled)
{
	if (m_FilterGraph == 0) {
		return 0;
	}

	ATL::CComQIPtr<IMediaEvent> me(m_FilterGraph);
	if (me != 0) {
		LONG lEventCode = 0;

		LONG_PTR lParam1 = 0;
		LONG_PTR lParam2 = 0;

		HRESULT hRslt = me->GetEvent(
			&lEventCode,
			&lParam1,
			&lParam2,
			0);
		if (SUCCEEDED(hRslt)) {
			if (lEventCode == EC_COMPLETE) {
				ATL::CComQIPtr<IMediaControl> ctrl(m_FilterGraph);
				if (ctrl != 0) {
					ctrl->Stop();
				}
			}

			me->FreeEventParams(
				lEventCode,
				lParam1,
				lParam2);
		}
	}

	return 0;
}
}}}

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

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

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

== 再生位置の取得

{{{ code c
ATL::CComQIPtr<IMediaSeeking> seek(m_FilterGraph);
if (seek != 0) {
	INT64 pos= 0;
	seek->GetCurrentPosition(&pos);

	...
}
}}}

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

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

== 再生時間の取得

{{{ code c
ATL::CComQIPtr<IMediaSeeking> seek(m_FilterGraph);
if (seek != 0) {
	INT64 duration = 0;
	seek->GetDuration(&duration);

	...
}
}}}

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

== シーク処理

{{{ code c
INT64 pos;

...

if (m_FilterGraph != 0) {
	ATL::CComQIPtr<IMediaSeeking> seek(m_FilterGraph);
	if (seek != 0) {
		seek->SetPositions(
			&pos,
			AM_SEEKING_AbsolutePositioning,
			0,
			AM_SEEKING_NoPositioning);
	}
}
}}}

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

== フォーマット情報取得

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

{{{ code c
ATL::CComPtr<IPin> pin;
hRslt = filter->FindPin(L"Audio", &pin);
if (FAILED(hRslt)) {
	return;
}

ATL::CComPtr<IEnumMediaTypes> em;
hRslt = pin->EnumMediaTypes(&em);
if (FAILED(hRslt)) {
	return;
}

for (; ; )
	AM_MEDIA_TYPE* mt = 0;
	ULONG c = 0;
	hRslt = em->Next(1, &mt, &c);
	if (FAILED(hRslt)) {
		return;
	}
	if (mt == 0) {
		break;
	}

	if (mt->formattype == FORMAT_WaveFormatEx &&
		mt->pbFormat != 0 &&
		mt->cbFormat >= sizeof(WAVEFORMATEX)) {

		WAVEFORMATEX* w = (WAVEFORMATEX*)(mt->pbFormat);

		...
	}

	QDSA_FreeMediaType(mt);
}
}}}

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

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