Использование источника Sequencer

В этом разделе описывается использование источника Sequencer. Он содержит следующие разделы:

Общие сведения об источнике последовательности см. в разделе "О источнике последовательности".

Обзор

Источник последовательности предоставляет следующие интерфейсы.

Интерфейс Description
IMFMediaSource Предоставляет функциональные возможности источника универсальных носителей.
МВФSequencerSource Позволяет приложению добавлять или удалять топологии.
МВФMediaSourceTopologyProvider Извлекает следующую топологию в очередь в сеансе мультимедиа.
МВФMediaSourcePresentationProvider Используется сеансом мультимедиа для завершения сегментов. Приложения не используют этот интерфейс.
МВФGetService Запрашивает источник последовательности для интерфейсов служб.

 

Чтобы воспроизвести последовательность источников мультимедиа, выполните следующие действия.

  1. Чтобы создать источник последовательности, вызовите функцию MFCreateSequencerSource .
  2. Для каждого сегмента создайте топологию воспроизведения, как описано в разделе "Создание топологий воспроизведения". Чтобы добавить топологию в презентацию, вызовите МВФSequencerSource::AddTopology.
  3. Перед началом воспроизведения вызовите МВФMediaSource::CreatePresentationDescriptor в источнике последовательности. Этот метод возвращает указатель на дескриптор презентации для первого сегмента. Чтобы получить топологию, связанную с этим сегментом, вызовите QueryInterface в источнике последовательности для интерфейса IMFMediaSourceTopologyProvider. Передайте дескриптор презентации методу IMFMediaSourceTopologyProvider::GetMediaSourceTopology . Этот метод возвращает указатель на топологию.
  4. Передайте топологию для первого сегмента в сеанс мультимедиа, вызвав метод МВФMediaSession::SetTopology.
  5. Начните воспроизведение, вызвав МВФMediaSession::Start.
  6. Когда источник последовательности готов к подготовке к следующему сегменту, он отправляет событие MENewPresentation, данные о событии которого являются указателем интерфейса МВФPresentationDescriptor. Опять же, получите топологию для сегмента, вызвав GetMediaSourceTopology в источнике последовательности и задайте топологию в сеансе мультимедиа путем вызова SetTopology. Не обязательно повторно запустить источник мультимедиа; он автоматически будет воспроизводиться в следующем сегменте.
  7. Прежде чем приложение завершит работу, закройте источник последовательности, вызвав МВФMediaSource::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;
}

Полный пример кода см. в разделе "Исходный код Sequencer".

Добавление топологий

Источник последовательности поддерживает два списка топологий: входной список и список предварительной подготовки.

Входной список — это коллекция топологий, соответствующих сегментам списка воспроизведения, в том порядке, в который они были добавлены приложением путем вызова IMFSequencerSource::AddTopology. Этот метод назначает каждую топологию уникальным идентификатором сегмента типа MFSequencerElementId. Идентификатор сегмента задается как атрибут для всех узлов исходной топологии. Приложение может получить идентификатор сегмента из исходного узла с помощью атрибута MF_TOPONODE_SEQUENCE_ELEMENTID . Список входных данных может иметь повторяющиеся топологии, если приложение с именем AppendTopology в одной топологии несколько раз; однако они определяются своими уникальными идентификаторами сегментов.

Список предварительной подготовки — это коллекция топологий входных списков, которые были инициализированы при подготовке к воспроизведению. Это позволяет сеансу мультимедиа легко переходить к следующей топологии, когда активная топология заканчивается. Приложение не может напрямую добавлять или удалять топологии из списка предварительной подготовки; Он создается источником последовательности при выборе топологии из входного списка для воспроизведения. Это приводит к добавлению следующей топологии из входного списка в список предварительной регистрации. После этого источник последовательности асинхронно вызывает событие MENewPresentation и передает дескриптор презентации для топологии доролла в виде данных события. Приложение должно прослушивать это событие с помощью интерфейса МВФMediaEventGenerator сеанса мультимедиа и очереди топологии предварительной подготовки на сеансе мультимедиа путем вызова МВФMediaSession::SetTopology. Это необходимо сделать, прежде чем сеанс мультимедиа завершит воспроизведение активной топологии. SetTopology сообщает сеансу мультимедиа о следующей топологии, которую он должен воспроизводить после завершения воспроизведения активной топологии. Чтобы обеспечить простой переход, приложение должно вызвать SetTopology , прежде чем сеанс мультимедиа завершит воспроизведение предыдущей топологии. В противном случае между сегментами будет разрыв.

Событие MENewPresentation вызывается до тех пор, пока существует топология после активной топологии. Следовательно, если входной список содержит только одну топологию или если активная топология является последней в входном списке, это событие не вызывается.

Список предварительной подготовки синхронизируется со списком входных данных и обновляется при каждом добавлении топологии в или удалении из входного списка.

Удаление топологий

Чтобы удалить топологию из источника последовательности, приложение должно вызвать метод IMFSequencerSource::D eleteTopology и указать идентификатор сегмента.

Перед вызовом DeleteTopology приложение должно убедиться, что сеанс мультимедиа не использует топологию, которую приложение хочет удалить. Для этого необходимо выполнить оба следующих действия перед вызовом DeleteTopology приложения:

  • Событие MESessionTopologyStatus с MF_TOPOSTATUS_ENDED получено для топологии, чтобы убедиться, что сеанс мультимедиа завершил воспроизведение.

  • MESessionTopologyStatus с MF_TOPOSTATUS_STARTED_SOURCE получается для следующей топологии, чтобы убедиться, что сеанс мультимедиа начал воспроизводить следующую топологию, событие MESessionEnded получено, чтобы убедиться, что сеанс мультимедиа выполняется с последней топологией в источнике последовательности.

Если удаленный сегмент является активной топологией, воспроизведение останавливается, а источник последовательности вызывает событие MEEndOfPresentationSegment . Если активная топология также является последней топологией, вызывается событие MEEndOfPresentation .

Пропуск в сегмент

Приложение может перейти к определенному сегменту в последовательности, запуская сеанс мультимедиа со смещением сегмента следующим образом:

  1. Вызовите функцию MFCreateSequencerSegmentOffset , чтобы создать смещение сегмента. Укажите идентификатор сегмента в параметре dwId . (Идентификатор был возвращен идентификатором Метод IMFSequencerSource::AddTopology при первом добавлении топологии в источник последовательности.) Параметр hnsOffset указывает смещение времени относительно начала сегмента. Воспроизведение начнется в это время. Для параметра pvarSegmentOffset передайте адрес пустого PROPVARIANT. При возврате функции этот PROPVARIANT содержит смещение сегмента.

  2. Вызовите метод 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;
}

Когда приложение ищет по сегментам, приложение получает несколько событий, так как источник последовательности заканчивает текущий сегмент и готовится к воспроизведению нового сегмента. Так как эти события получаются асинхронно, трудно предсказать точную последовательность событий. Эти события приведены следующим образом:

Дополнительные сведения о событиях, отправленных источником последовательности, можно найти в разделе "События источника последовательности".

Создание списка воспроизведения

Источник Sequencer