次の方法で共有


再生リストを作成する方法

このトピックでは、シーケンス ソースを使用して一連のファイルを再生する方法について説明します。

概要

メディア ファイルをシーケンスで再生するには、再生リストを作成するトポロジをシーケンスに追加し、再生のためにメディア セッションでこれらのトポロジをキューに入れなければなりません。

シーケンサー ソースは、メディア セッションが現在のトポロジの再生を開始する前に、次のトポロジを初期化して読み込むことで、シームレスな再生を保証します。 これにより、アプリケーションは必要なときにいつでも次のトポロジをすばやく開始できます。

メディア セッションは、シンクにデータを供給し、シーケンス ソースでトポロジを再生する役割を担います。 さらに、メディア セッションはセグメントのプレゼンテーション時間を管理します。

シーケンサー ソースがトポロジを管理する方法の詳細については、「 Sequencer ソースについて」を参照してください。

このチュートリアルには、次の手順が含まれています。

  1. 前提条件
  2. Media Foundation の初期化
  3. Media Foundation オブジェクトの作成
  4. メディア ソースの作成
  5. 部分トポロジの作成
  6. Sequencer ソースへのトポロジの追加
  7. メディア セッションでの最初のトポロジの設定
  8. メディアセッションで次のトポロジをキューに入れる
  9. Sequencer ソースの解放

このトピックに示すコード例は、完全なサンプル コードを含む Sequencer Source Example Code というトピックからの抜粋です。

[前提条件]

このチュートリアルを開始する前に、次の Media Foundation の概念を理解しておいてください。

また、Media Foundation を使用してメディア ファイルを再生する方法についても説明します。ここで示すコード例は、そのトピックのコードを展開しているためです。

メディア ファンデーションの初期化

Media Foundation のインターフェイスまたはメソッドを使用する前に、 MFStartup 関数を呼び出して Media Foundation を初期化します。 詳細については、「 Media Foundation の初期化」を参照してください。

    hr = MFStartup(MF_VERSION);

Media Foundation オブジェクトの作成

次に、次の Media Foundation オブジェクトを作成します。

  • メディア セッション。 このオブジェクトは、現在のトポロジを再生、一時停止、および停止するメソッドを提供する IMFMediaSession インターフェイスを公開します。
  • シーケンサーのソース。 このオブジェクトは、シーケンス内のトポロジを追加、更新、および削除するメソッドを提供する IMFSequencerSource インターフェイスを公開します。
  1. MFCreateMediaSession 関数を呼び出して、メディア セッションを作成します。
  2. IMFMediaEventQueue::BeginGetEvent を呼び出して、メディア セッションから最初のイベントを要求します。
  3. MFCreateSequencerSource 関数を呼び出して、シーケンサー ソースを作成します。

次のコードは、メディア セッションを作成し、最初のイベントを要求します。

//  Create a new instance of the media session.
HRESULT CPlayer::CreateSession()
{
    // Close the old session, if any.
    HRESULT hr = CloseSession();
    if (FAILED(hr))
    {
        goto done;
    }

    assert(m_state == Closed);

    // Create the media session.
    hr = MFCreateMediaSession(NULL, &m_pSession);
    if (FAILED(hr))
    {
        goto done;
    }

    // Start pulling events from the media session
    hr = m_pSession->BeginGetEvent((IMFAsyncCallback*)this, NULL);
    if (FAILED(hr))
    {
        goto done;
    }

    m_state = Ready;

done:
    return hr;
}

メディア ソースの作成

次に、最初のプレイリスト セグメントのメディア ソースを作成します。 ソース リゾルバーを使用して、URL からメディア ソースを作成します。 そのためには、 MFCreateSourceResolver 関数を呼び出してソース リゾルバーを作成し 、IMFSourceResolver::CreateObjectFromURL メソッドを呼び出してメディア ソースを作成します。

メディア ソースの詳細については、「 メディア ソース」を参照してください。

部分トポロジの作成

シーケンサー ソース内の各セグメントには、独自の部分トポロジがあります。 次に、メディア ソースの部分トポロジを作成します。 部分トポロジの場合、トポロジ ソース ノードは、中間変換を指定せずに出力ノードに直接接続されます。 メディア セッションでは、トポロジ ローダー オブジェクトを使用してトポロジを解決します。 トポロジが解決されると、必要なデコーダーとその他の変換ノードが追加されます。 シーケンサー ソースには、完全なトポロジを含めることもできます。

トポロジ オブジェクトを作成するには、 MFCreateTopology 関数を使用し、 IMFTopologyNode インターフェイスを使用してストリーム ノードを作成します。

これらのプログラミング要素を使用してトポロジを作成する方法の詳細については、「 再生トポロジの作成」を参照してください。

アプリケーションは、ソース ノードを構成することで、ネイティブ ソースの選択された部分を再生できます。 これを行うには、トポロジ ノードで MF_TOPONODE_MEDIASTART 属性と MF_TOPONODE_MEDIASTOP 属性 MF_TOPOLOGY_SOURCESTREAM_NODE 設定します。 UINT64 の種類として、ネイティブ ソースの開始を基準としたメディアの開始時刻とメディアの停止時間を指定します。

Sequencer ソースへのトポロジの追加

次に、作成した部分トポロジをシーケンサー ソースに追加します。 セグメントと呼ばれる各シーケンス要素には、MFSequencerElementId 識別子が割り当てられます。 シーケンサー ソースがトポロジを管理する方法の詳細については、「 Sequencer ソースについて」を参照してください。

すべてのトポロジがシーケンサー ソースに追加された後、アプリケーションは、パイプラインでの再生を終了するために、シーケンス内の最後のセグメントにフラグを設定する必要があります。 このフラグがない場合、シーケンサー ソースはさらに多くのトポロジが追加されることを期待します。

  1. IMFSequencerSource::AppendTopology メソッドを呼び出して、特定のトポロジをシーケンサー ソースに追加します。

        hr = m_pSequencerSource->AppendTopology(
            pTopology, 
            SequencerTopologyFlags_Last, 
            &SegmentId
            );
    

    AppendTopology は、指定されたトポロジをシーケンスに追加します。 このメソッドは 、pdwId パラメーターのセグメント識別子を返します。

    トポロジがシーケンサー ソースの最後のトポロジである場合は、 dwFlags パラメーターにSequencerTopologyFlags_Lastを渡します。 この値は 、MFSequencerTopologyFlags 列挙型で定義されます。

  2. IMFSequencerSource::UpdateTopologyFlags を呼び出して、入力リストのセグメント識別子に関連付けられているトポロジのフラグを更新します。 この場合、呼び出しは、指定されたセグメントがシーケンサーの最後のセグメントであることを示します。 (この呼び出しは、 AppendTopology 呼び出しで最後のトポロジが指定されている場合は省略可能です)。

        BOOL bFirstSegment = (NumSegments() == 0);
    
        if (!bFirstSegment)
        {
            // Remove the "last segment" flag from the last segment.
            hr = m_pSequencerSource->UpdateTopologyFlags(LastSegment(), 0);
            if (FAILED(hr))
            {
                goto done;
            }
        }
    

アプリケーションは、 IMFSequencerSource::UpdateTopology を呼び出し、 pTopology で新しいトポロジを渡すことで、セグメントのトポロジを別のトポロジに置き換えることができます。 新しいトポロジに新しいネイティブ ソースがある場合、ソースはソース キャッシュに追加されます。 プリロール リストも更新されます。

メディア セッションでの最初のトポロジの設定

次に、メディア セッションのシーケンス ソースの最初のトポロジをキューに入れます。 シーケンサー ソースから最初のトポロジを取得するには、アプリケーションで IMFMediaSourceTopologyProvider::GetMediaSourceTopology メソッドを呼び出す必要があります。 このメソッドは、メディア セッションによって解決される部分トポロジを返します。

部分トポロジの詳細については、「トポロジ について」を参照してください。

  1. シーケンス ソースの最初のトポロジのネイティブ メディア ソースを取得します。

  2. IMFMediaSource::CreatePresentationDescriptor メソッドを呼び出して、メディア ソースのプレゼンテーション記述子を作成します。

  3. IMFMediaSourceTopologyProvider::GetMediaSourceTopology メソッドを呼び出して、プレゼンテーションに関連付けられているトポロジを取得します。

  4. IMFMediaSession::SetTopology を呼び出して、メディア セッションの最初のトポロジを設定します。

    dwSetTopologyFlags パラメーターを NULL に設定して SetTopology を呼び出します。 これにより、現在のトポロジが完了したときに、指定したトポロジを開始するようにメディア セッションに指示します。 この場合、指定したトポロジが最初のトポロジであり、現在のプレゼンテーションがないため、メディア セッションは新しいプレゼンテーションをすぐに開始します。

    NULL 値は、トポロジ プロバイダーによって返されるトポロジは常に部分トポロジであるため、メディア セッションがトポロジを解決する必要があることを示します。

// 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;
}

メディアセッションで次のトポロジをキューに入れる

次に、アプリケーションで MENewPresentation イベントを処理する必要があります。

Sequencer ソースは、メディア セッションがその後に別のセグメントを持つセグメントの再生を開始すると 、MENewPresentation を発生させます。 このイベントは、プリロール リスト内の次のセグメントのプレゼンテーション記述子を指定することによって、シーケンス ソース内の次のトポロジについてアプリケーションに通知します。 アプリケーションは、関連付けられているトポロジをトポロジ プロバイダーを使用して取得し、メディア セッションでキューに登録する必要があります。 その後、シーケンサー ソースによってこのトポロジが事前登録され、プレゼンテーション間のシームレスな切り替えが保証されます。

アプリケーションが複数のセグメントをシークすると、シーケンサー ソースがプリロール リストを更新し、正しいトポロジを設定するときに、アプリケーションはいくつかの MENewPresentation イベントを受け取ります。 アプリケーションは、各イベントを処理し、メディア セッションのイベント データで返されたトポロジをキューに入れなければなりません。 セグメントのスキップの詳細については、「 Sequencer ソースの使用」を参照してください。

シーケンサー ソース通知の取得については、「 Sequencer ソース イベント」を参照してください。

  1. MENewPresentation イベント ハンドラーで、イベント データから次のセグメントのプレゼンテーション記述子を取得します。

  2. IMFMediaSourceTopologyProvider::GetMediaSourceTopology メソッドを呼び出して、プレゼンテーションに関連付けられているトポロジを取得します。

  3. IMFMediaSession::SetTopology メソッドを呼び出して、メディア セッションでトポロジを設定します。

    メディア セッションは、現在のプレゼンテーションが完了すると、新しいプレゼンテーションを開始します。

HRESULT CPlaylist::OnNewPresentation(IMFMediaEvent *pEvent)
{
    IMFPresentationDescriptor *pPD = NULL;

    HRESULT hr = GetEventObject(pEvent, &pPD);

    if (SUCCEEDED(hr))
    {
        // Queue the next segment on the media session
        hr = QueueNextSegment(pPD);
    }

    SafeRelease(&pPD);
    return hr;
}

Sequencer ソースの解放

最後に、シーケンサー ソースをシャットダウンします。 これを行うには、シーケンサー ソースで IMFMediaSource::Shutdown メソッドを呼び出します。 この呼び出しにより、シーケンサー ソース内のすべての基になるネイティブ メディア ソースがシャットダウンされます。

シーケンサー ソースを解放した後、アプリケーションは、IMFMediaSession::Close と IMFMediaSession::Shutdown を呼び出して、メディア セッションを閉じてシャットダウンする必要があります。

メモリ リークを回避するには、不要になったら、アプリケーションで Media Foundation インターフェイスへのポインターを解放する必要があります。

次のステップ

このチュートリアルでは、シーケンサー ソースを使用して基本的なプレイリストを作成する方法を示しました。 プレイリストを作成したら、セグメントのスキップ、再生状態の変更、セグメント内のシークなどの高度な機能を追加できます。 次の一覧に、関連トピックへのリンクを示します。

sequencer ソース