シーケンサー ソースを使用する
このトピックでは、シーケンサー ソースの使用方法について説明します。 このチュートリアルは、次のセクションで構成されています。
シーケンサー ソースの一般的な概要については、「シーケンサー ソースについて」を参照してください。
概要
シーケンサー ソースでは、次のインターフェイスが公開されます。
Interface | 説明 |
---|---|
IMFMediaSource | 汎用メディア ソース機能を公開します。 |
IMFSequencerSource | アプリケーションでトポロジを追加または削除できるようにします。 |
IMFMediaSourceTopologyProvider | メディア セッションでキューに登録する次のトポロジを取得します。 |
IMFMediaSourcePresentationProvider | セグメントを終了するためにメディア セッションによって使用されます。 このインターフェイスは、アプリケーションでは使用されません。 |
IMFGetService | サービス インターフェイスのシーケンサー ソースに対してクエリを実行します。 |
メディア ソースのシーケンスを再生するには、次の手順を実行します。
- シーケンサー ソースを作成するには、MFCreateSequencerSource 関数を呼び出します。
- 「再生トポロジの作成」の説明に従って、セグメントごとに再生トポロジを作成します。 プレゼンテーションにトポロジを追加するには、IMFSequencerSource::AppendTopology を呼び出します。
- 再生を開始する前に、シーケンサー ソースで IMFMediaSource::CreatePresentationDescriptor を呼び出します。 このメソッドは、最初のセグメントのプレゼンテーション記述子へのポインターを返します。 このセグメントに関連付けられているトポロジを取得するには、IMFMediaSourceTopologyProvider インターフェイスのシーケンサー ソースで QueryInterface を呼び出します。 プレゼンテーション記述子を IMFMediaSourceTopologyProvider::GetMediaSourceTopology メソッドに渡します。 このメソッドはトポロジへのポインターを返します。
- メディア セッションの IMFMediaSession::SetTopology メソッドを呼び出して、最初のセグメントのトポロジをメディア セッションに渡します。
- IMFMediaSession::Start を呼び出して再生を開始します。
- シーケンサー ソースは、次のセグメントをプリロールする準備ができたら、イベント データが IMFPresentationDescriptor インターフェイス ポインターである MENewPresentation イベントを送信します。 ここでも、シーケンサー ソースで GetMediaSourceTopology を呼び出してセグメントのトポロジを取得し、SetTopology を呼び出してメディア セッションでトポロジを設定します。 メディア ソースを再開する必要はありません。次のセグメントまで自動的に再生されます。
- アプリケーションが終了する前に、IMFMediaSource::Shutdown を呼び出してシーケンサー ソースをシャットダウンします。
次のコードは、トポロジを取得し、メディア セッションで設定する方法を示しています。
// Queues the next topology on the session.
HRESULT CPlaylist::QueueNextSegment(IMFPresentationDescriptor *pPD)
{
IMFMediaSourceTopologyProvider *pTopoProvider = NULL;
IMFTopology *pTopology = NULL;
//Get the topology for the presentation descriptor
HRESULT hr = m_pSequencerSource->QueryInterface(IID_PPV_ARGS(&pTopoProvider));
if (FAILED(hr))
{
goto done;
}
hr = pTopoProvider->GetMediaSourceTopology(pPD, &pTopology);
if (FAILED(hr))
{
goto done;
}
//Set the topology on the media session
m_pSession->SetTopology(NULL, pTopology);
done:
SafeRelease(&pTopoProvider);
SafeRelease(&pTopology);
return hr;
}
完全なコード例については、「シーケンサー ソースのサンプル コード」を参照してください。
トポロジを追加する
シーケンサー ソースには、2 つのトポロジ リスト、"入力リスト" と "プリロール リスト" が含まれています。
入力リストは、再生リスト セグメントに対応するトポロジのコレクションであり、IMFSequencerSource::AppendTopology を呼び出してアプリケーションによって追加された順番になっています。 このメソッドにより、各トポロジに MFSequencerElementId 型の一意の "セグメント識別子" が割り当てられます。 セグメント識別子は、すべてのソース トポロジ ノードの属性として設定されます。 アプリケーションでは、MF_TOPONODE_SEQUENCE_ELEMENTID 属性を使用してソース ノードからセグメント識別子を取得できます。 同じトポロジに対して AppendTopology が複数回アプリケーションによって呼び出されると、入力リストにトポロジが重複して存在する可能性がありますが、それは一意のセグメント識別子によって識別されます。
プリロール リストは、再生の準備のために初期化された入力リスト トポロジのコレクションです。 これにより、アクティブなトポロジが終了したときにメディア セッションが次のトポロジにシームレスに移行できます。 アプリケーションがトポロジの追加または削除をプリロール リストから直接行うことはできません。これがシーケンサー ソースによって生成されるのは、トポロジが再生のために入力リストから選択されたときです。 これにより次のトポロジが、シーケンサー ソースによって、入力リストからプリロール リストに追加されます。 その後、シーケンサー ソースにより MENewPresentation イベントが非同期的に発生し、プリロール トポロジのプレゼンテーション記述子がイベント データとして渡されます。 アプリケーションは、メディア セッションの IMFMediaEventGenerator インターフェイスを使用してこのイベントをリッスンし、IMFMediaSession::SetTopology を呼び出して、メディア セッション上のプリロール トポロジをキューに登録する必要があります。 これは、メディア セッションがアクティブ トポロジの再生を完了する前に行われなければなりません。 アクティブなトポロジの再生終了後に再生しなければならない次のトポロジについては、SetTopology によってメディア セッションに通知されます。 シームレスな移行を確実に行うには、メディア セッションが前のトポロジの再生を完了する前に、アプリケーションで SetTopology を呼び出す必要があります。 それ以外の場合、セグメント間にギャップが生まれます。
MENewPresentation イベントは、アクティブなトポロジの後にトポロジがある場合に発生します。 そのため、入力リストに含まれるトポロジが 1 つだけの場合、またはアクティブなトポロジが入力リストの最後のトポロジである場合、このイベントは発生しません。
プリロール リストは入力リストと同期され、トポロジが入力リストに追加または入力リストから削除されるたびに更新されます。
トポロジを削除する
シーケンサー ソースからトポロジを削除するには、アプリケーションで IMFSequencerSource::DeleteTopology メソッドを呼び出し、セグメント識別子を指定する必要があります。
DeleteTopology を呼び出す前に、削除するトポロジがメディア セッションで使用されていないことを、アプリケーションで確認する必要があります。 これを行うには、DeleteTopology がアプリケーションで呼び出される前に、次の両方が発生しなければなりません。
メディア セッションで再生が確実に完了していることをトポロジが確認できるように、MF_TOPOSTATUS_ENDED を含む MESessionTopologyStatus イベントが受信される。
メディア セッションで次のトポロジの再生が開始したことを次のトポロジが確認できるように、MF_TOPOSTATUS_STARTED_SOURCEを含む MESessionTopologyStatus が受信される。メディア セッションでシーケンサー ソースの最後のトポロジが完了したことを確認できるように MESessionEnded イベントが受信される。
削除されるセグメントがアクティブなトポロジの場合は、再生が停止され、シーケンサー ソースによって MEEndOfPresentationSegment イベントが発生します。 アクティブなトポロジも最後のトポロジである場合は、MEEndOfPresentation イベントが発生します。
セグメントにスキップする
アプリケーションでシーケンス内の特定のセグメントにスキップするには、次のようにセグメント オフセットを使用してメディア セッションを開始します。
MFCreateSequencerSegmentOffset 関数を呼び出して、セグメント オフセットを作成します。 dwId パラメーターでセグメントの識別子を指定します (識別子は、最初にトポロジをシーケンサー ソースに追加したときに、IMFSequencerSource::AppendTopology メソッドによって返されました)。hnsOffset パラメーターでは、セグメントの開始位置を基準とした時間オフセットが指定されます。 この時点で再生が開始します。 pvarSegmentOffset パラメーターについては、空の PROPVARIANT のアドレスを渡します。 関数から制御が戻ったとき、この PROPVARIANT にはセグメント オフセットが含まれています。
メディア セッションで IMFMediaSession::Start メソッドを呼び出します。 pguidTimeFormat パラメーターについては、GUID 値 MF_TIME_FORMAT_SEGMENT_OFFSET を使用します。 この値は、セグメント オフセットによってシークを示します。 pvarStartPosition パラメーターについては、前の手順で作成した PROPVARIANT のアドレスを渡します。
次のコード例は、シーケンス内の指定したセグメントの先頭にスキップする方法を示しています。
// Skips to the specified segment in the sequencer source
HRESULT CPlaylist::SkipTo(DWORD index)
{
if (index >= m_count)
{
return E_INVALIDARG;
}
MFSequencerElementId ID = m_segments[index].SegmentID;
PROPVARIANT var;
HRESULT hr = MFCreateSequencerSegmentOffset(ID, NULL, &var);
if (SUCCEEDED(hr))
{
hr = m_pSession->Start(&MF_TIME_FORMAT_SEGMENT_OFFSET, &var);
PropVariantClear(&var);
}
return hr;
}
アプリケーションによるシークが複数のセグメントにわたる場合、シーケンサー ソースによって現在のセグメントが終了し、新しいセグメントの再生準備が行われ、そのアプリケーションは複数のイベントを受け取ります。 これらのイベントは非同期的に受信されるため、イベントの正確なシーケンスを予測することは困難です。 これらのイベントは次のとおりです。
メディア セッションの新しいスキップ先セグメントに対する MENewPresentation イベントが、シーケンサー ソースによって送信されます。
アクティブなセグメントを終了したシーケンサー ソースにより、MEEndOfPresentationSegment イベントが送信されます。
その後、プリロール トポロジがシーケンサー ソースによって取り消されます。 これにより、取り消されたトポロジに対して次のイベントが発生します。
- MF_TOPOSTATUS_READY フラグを持つ MESessionTopologyStatus イベント。
- MF_TOPOSTATUS_STARTED_SOURCE フラグを持つ MESessionTopologyStatus イベント。
- MF_EVENT_SOURCE_TOPOLOGY_CANCELED 属性を持つ MEEndOfPresentationSegment イベント。これはトポロジがシーケンサー ソースによって取り消されたことを示します。
次に、シーケンサー ソースは新しいセグメントのイベントを送信します。これには、さまざまな MESessionTopologyStatus イベントが含まれます。
新しいセグメントがリストの最後でない場合、プリロール リストがシーケンサー ソースによって更新され、新しいプリロール トポロジに対して別の MENewPresentation が生成されます。 プリロール リストのトポロジの詳細については、「シーケンサー ソースについて」を参照してください。
シーケンサー ソースによって送信されるイベントの詳細については、シーケンサー ソース イベントに関するトピックを参照してください。
関連トピック