Como criar uma playlist

Este tópico descreve como usar a Origem da Sequência para reproduzir uma sequência de arquivos.

Visão geral

Para reproduzir arquivos de mídia em uma sequência, o aplicativo deve adicionar topologias em uma sequência para criar uma playlist e enfileirar essas topologias na Sessão de Mídia para reprodução.

A origem do sequenciador garante a reprodução perfeita inicializando e carregando a próxima topologia antes que a Sessão de Mídia comece a reproduzir a topologia atual. Isso permite que o aplicativo inicie a próxima topologia rapidamente sempre que for necessário.

A Sessão de Mídia é responsável por alimentar dados para os coletores e reproduzir as topologias na origem da sequência. Além disso, a Sessão de Mídia gerencia o tempo de apresentação para os segmentos.

Para obter mais informações sobre como a origem do sequenciador gerencia topologias, consulte Sobre a origem do sequencer.

Este passo a passo contém as seguintes etapas:

  1. Pré-requisitos
  2. Inicializando o Media Foundation
  3. Criando objetos do Media Foundation
  4. Criando a fonte de mídia
  5. Criando topologias parciais
  6. Adicionando topologias à origem do sequencer
  7. Definindo a primeira topologia na sessão de mídia
  8. Enfileirando a próxima topologia na sessão de mídia
  9. Liberando a origem do sequenciador

Os exemplos de código mostrados neste tópico são trechos do tópico Sequencer Source Example Code, que contém o código de exemplo completo.

Pré-requisitos

Antes de iniciar este passo a passo, familiarize-se com os seguintes conceitos do Media Foundation:

Leia também Como reproduzir arquivos de mídia com o Media Foundation, pois o código de exemplo aqui se expande sobre o código nesse tópico.

Inicializando o Media Foundation

Antes de usar qualquer interface ou método do Media Foundation, inicialize o Media Foundation chamando a função MFStartup . Para obter mais informações, consulte Inicializando o Media Foundation.

    hr = MFStartup(MF_VERSION);

Criando objetos do Media Foundation

Em seguida, crie os seguintes objetos do Media Foundation:

  • Sessão de mídia. Esse objeto expõe a interface IMFMediaSession , que fornece métodos para reproduzir, pausar e parar a topologia atual.
  • Origem do sequenciador. Esse objeto expõe a interface IMFSequencerSource , que fornece métodos para adicionar, atualizar e excluir topologias em uma sequência.
  1. Chame a função MFCreateMediaSession para criar a Sessão de Mídia.
  2. Chame IMFMediaEventQueue::BeginGetEvent para solicitar o primeiro evento da Sessão de Mídia.
  3. Chame a função MFCreateSequencerSource para criar a origem do sequenciador.

O código a seguir cria a Sessão de Mídia e solicita o primeiro evento:

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

Criando a fonte de mídia

Em seguida, crie uma fonte de mídia para o primeiro segmento de playlist. Use o Resolvedor de Origem para criar uma fonte de mídia a partir de uma URL. Para fazer isso, chame a função MFCreateSourceResolver para criar um resolvedor de origem e, em seguida, chame o método IMFSourceResolver::CreateObjectFromURL para criar a fonte de mídia.

Para obter informações sobre fontes de mídia, consulte Fontes de mídia.

Criando topologias parciais

Cada segmento na origem do sequenciador tem sua própria topologia parcial. Em seguida, crie topologias parciais para fontes de mídia. Para uma topologia parcial, os nós de origem da topologia são conectados diretamente aos nós de saída, sem especificar transformações intermediárias. A Sessão de Mídia usa o objeto carregador de topologia para resolve a topologia. Depois que uma topologia é resolvida, os decodificadores necessários e outros nós de transformação são adicionados. A origem do sequenciador também pode conter topologias completas.

Para criar o objeto de topologia, use a função MFCreateTopology e use a interface IMFTopologyNode para criar nós de fluxo.

Para obter instruções completas sobre como usar esses elementos de programação para criar topologias, consulte Criando topologias de reprodução.

Um aplicativo pode reproduzir uma parte selecionada da origem nativa configurando o nó de origem. Para fazer isso, defina o atributo MF_TOPONODE_MEDIASTART e o atributo MF_TOPONODE_MEDIASTOP em nós de topologia MF_TOPOLOGY_SOURCESTREAM_NODE. Especifique a hora de início da mídia e o tempo de parada de mídia em relação ao início da origem nativa como tipos UINT64 .

Adicionando topologias à origem do sequencer

Em seguida, adicione à fonte do sequenciador as topologias parciais que você criou. Cada elemento de sequência, chamado de segmento, recebe um identificador MFSequencerElementId . Para obter mais informações sobre como a origem do sequenciador gerencia topologias, consulte Sobre a origem do sequencer.

Depois que todas as topologias são adicionadas à origem do sequenciador, o aplicativo deve sinalizar o último segmento na sequência para encerrar a reprodução no pipeline. Sem esse sinalizador, a origem do sequenciador espera que mais topologias sejam adicionadas.

  1. Chame o método IMFSequencerSource::AppendTopology para adicionar uma topologia específica à origem do sequenciador.

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

    AppendTopology adiciona a topologia especificada à sequência. Esse método retorna o identificador de segmento no parâmetro pdwId .

    Se a topologia for a última na origem do sequenciador, passe SequencerTopologyFlags_Last no parâmetro dwFlags . Esse valor é definido na enumeração MFSequencerTopologyFlags .

  2. Chame IMFSequencerSource::UpdateTopologyFlags para atualizar os sinalizadores para a topologia associada ao identificador de segmento na lista de entrada. Nesse caso, a chamada indica que o segmento especificado é o último segmento no sequenciador. (Essa chamada será opcional se a última topologia for especificada na chamada 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;
            }
        }
    

O aplicativo pode substituir a topologia de um segmento por outra topologia chamando IMFSequencerSource::UpdateTopology e passando a nova topologia em pTopology. Se houver novas fontes nativas na nova topologia, as fontes serão adicionadas ao cache de origem. A lista de pré-registro também é atualizada.

Definindo a primeira topologia na sessão de mídia

Em seguida, enfileira a primeira topologia na origem da sequência na Sessão de Mídia. Para obter a primeira topologia da origem do sequenciador, o aplicativo deve chamar o método IMFMediaSourceTopologyProvider::GetMediaSourceTopology . Esse método retorna a topologia parcial, que é resolvida pela Sessão de Mídia.

Para obter informações sobre topologias parciais, consulte Sobre topologias.

  1. Recupere a fonte de mídia nativa para a primeira topologia da origem da sequência.

  2. Crie um descritor de apresentação para a fonte de mídia chamando o método IMFMediaSource::CreatePresentationDescriptor .

  3. Recupere a topologia associada para a apresentação chamando o método IMFMediaSourceTopologyProvider::GetMediaSourceTopology .

  4. Defina a primeira topologia na Sessão de Mídia chamando IMFMediaSession::SetTopology.

    Chame SetTopology com o parâmetro dwSetTopologyFlags definido como NULL. Isso instrui a Sessão de Mídia a iniciar a topologia especificada quando a topologia atual for concluída. Como nesse caso, a topologia especificada é a primeira topologia e não há nenhuma apresentação atual, a Sessão de Mídia inicia a nova apresentação imediatamente.

    O valor NULL também indica que a Sessão de Mídia deve resolve a topologia porque a topologia retornada pelo provedor de topologia é sempre uma topologia parcial.

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

Enfileirando a próxima topologia na sessão de mídia

Em seguida, o aplicativo precisa lidar com o evento MENewPresentation .

A origem do sequencer gera MENewPresentation quando a Sessão de Mídia começa a reproduzir um segmento que tem outro segmento seguindo-o. Esse evento informa o aplicativo sobre a próxima topologia na origem da sequência fornecendo o descritor de apresentação para o próximo segmento na lista de pré-registro. O aplicativo deve recuperar a topologia associada usando o provedor de topologia e enfileira-la na Sessão de Mídia. Em seguida, a origem do sequenciador pré-registrou essa topologia, o que garante uma transição perfeita entre as apresentações.

Quando o aplicativo busca entre segmentos, o aplicativo recebe vários eventos MENewPresentation à medida que a origem do sequenciador atualiza a lista de pré-registro e configura a topologia correta. O aplicativo deve manipular cada evento e enfileirar a topologia retornada nos dados do evento, na Sessão de Mídia. Para obter informações sobre como ignorar segmentos, consulte Usando a origem do sequencer.

Para obter informações sobre como obter notificações de origem do sequenciador, consulte Eventos de origem do sequencer.

  1. No manipulador de eventos MENewPresentation , recupere o descritor de apresentação para o próximo segmento dos dados do evento.

  2. Obtenha a topologia associada para a apresentação chamando o método IMFMediaSourceTopologyProvider::GetMediaSourceTopology .

  3. Defina a topologia na Sessão de Mídia chamando o método IMFMediaSession::SetTopology .

    A Sessão de Mídia inicia a nova apresentação quando a apresentação atual é concluída.

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

Liberando a origem do sequenciador

Por fim, desligue a origem do sequenciador. Para fazer isso, chame o método IMFMediaSource::Shutdown na origem do sequenciador. Essa chamada desliga todas as fontes de mídia nativas subjacentes na origem do sequenciador.

Depois de liberar a origem do sequenciador, o aplicativo deve fechar e desligar a Sessão de Mídia chamando IMFMediaSession::Close e IMFMediaSession::Shutdown, nessa ordem.

Para evitar vazamentos de memória, o aplicativo deve liberar ponteiros para interfaces do Media Foundation quando elas não forem mais necessárias.

Próximas etapas

Este passo a passo ilustra como criar uma playlist básica usando a origem do sequenciador. Depois de criar a playlist, talvez você queira adicionar recursos avançados, como ignorar segmentos, alterar o estado de reprodução e buscar dentro de um segmento. A lista a seguir fornece links para os tópicos relacionados:

Origem do sequenciador