Приемники мультимедиа

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

  • Отрисовщик — это приемник мультимедиа, который предоставляет данные для воспроизведения. Расширенный отрисовщик видео (EVR) отображает видеокадры, а звуковой отрисовщик воспроизводит звуковые потоки через звуковой карта или другое звуковое устройство.

  • Приемник архива — это приемник мультимедиа, который записывает данные в файл или другое хранилище.

Разница между main заключается в том, что приемник архива не использует данные с фиксированной скоростью воспроизведения. Вместо этого он записывает полученные данные как можно быстрее.

Приемники мультимедиа предоставляют интерфейс IMFMediaSink . Каждый приемник мультимедиа содержит один или несколько приемников потоков. Каждый приемник потока получает данные из одного потока. Приемники потоков предоставляют интерфейс IMFStreamSink . Обычно приложение не создает приемники мультимедиа напрямую. Вместо этого приложение создает один или несколько объектов активации, которые сеанс мультимедиа использует для создания приемника. Все остальные операции в приемнике обрабатываются сеансом мультимедиа, и приложение не вызывает методы в приемнике мультимедиа или приемниках потоков. Дополнительные сведения об объектах активации см. в разделе Объекты активации.

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

Приемники потоков

Приемник мультимедиа может иметь фиксированное число приемников потоков или поддерживать добавление и удаление приемников потоков. Если имеется фиксированное число приемников потока, метод IMFMediaSink::GetCharacteristics возвращает флаг MEDIASINK_FIXED_STREAMS. В противном случае можно добавить и удалить приемники потоков. Чтобы добавить новый приемник потока, позвоните по телефону IMFMediaSink::AddStreamSink. Чтобы удалить приемник потока, вызовите IMFMediaSink::RemoveStreamSink. Флаг MEDIASINK_FIXED_STREAMS указывает, что приемник мультимедиа не поддерживает эти два метода. (Он может поддерживать другой способ настройки количества потоков, например путем задания параметров инициализации при создании приемника.) Список приемников потоков упорядочен. Чтобы перечислить их по значению индекса, вызовите метод IMFMediaSink::GetStreamSinkByIndex .

Приемники потоков также имеют идентификаторы. Идентификаторы потоков являются уникальными в приемнике мультимедиа, но не должны быть последовательными. В зависимости от приемника мультимедиа идентификаторы потоков могут иметь некоторое значение, связанное с содержимым. Например, приемник архива может записать идентификаторы потока в заголовок файла. В противном случае они являются произвольными. Чтобы получить приемник потока по идентификатору, вызовите IMFMediaSink::GetStreamSinkById.

Часы презентации

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

  • Получение уведомлений при запуске или остановке потоковой передачи. Приемник мультимедиа получает эти уведомления через интерфейс IMFClockStateSink , который должны реализовать все приемники мультимедиа.

  • Определение времени отрисовки примеров. Когда приемник мультимедиа получает новый образец, он получает метку времени из примера и пытается отобразить пример во время презентации.

Часы представления наследуют время от другого объекта, называемого источником времени презентации. Источники времени презентации предоставляют интерфейс IMFPresentationTimeSource . Некоторые приемники мультимедиа имеют доступ к точным часам, поэтому они предоставляют этот интерфейс. Это означает, что приемник мультимедиа может запланировать выборку по времени, предоставленному собственными часами. Однако приемник мультимедиа не может предположить, что это так. Он всегда должен использовать время из часов презентации, независимо от того, управляются ли часы презентации самим приемником мультимедиа или другими часами.

Если приемник мультимедиа не может сопоставить частоту с часами, отличной от его собственных, метод GetCharacteristics возвращает флаг MEDIASINK_CANNOT_MATCH_CLOCK. Если этот флаг присутствует и часы презентации используют другой источник времени презентации, приемник мультимедиа, скорее всего, будет работать плохо. Например, во время воспроизведения может возникнуть сбой.

Приемник без скорости — это приемник мультимедиа, который игнорирует метки времени в примерах и использует данные сразу после поступления каждой выборки. Приемник мультимедиа без скорости возвращает флаг MEDIASINK_RATELESS из метода GetCharacteristics . Обычно этот флаг применяется к архивным приемникам. Если все приемники мультимедиа в конвейере не являются скоростными, сеанс мультимедиа использует специальные часы презентации без скорости. Эти часы запускаются так же быстро, как приемники используют образцы.

Форматы потоков

Прежде чем приемник мультимедиа сможет получать образцы, клиент должен задать тип носителя в приемниках потоков. Чтобы задать тип носителя, вызовите метод IMFStreamSink::GetMediaTypeHandler приемника потока. Этот метод возвращает указатель на интерфейс IMFMediaTypeHandler . Используйте этот интерфейс для получения списка предпочтительных типов мультимедиа, получения текущего типа мультимедиа и задания типа носителя.

Чтобы получить список предпочтительных типов мультимедиа, вызовите IMFMediaTypeHandler::GetMediaTypeByIndex. Предпочтительные типы следует рассматривать как подсказку клиенту. Список может быть неполным или включать частичные типы носителей. Частичный тип мультимедиа — это тип, который не имеет всех атрибутов, необходимых для описания допустимого формата. Например, частичный тип видео может указывать цветовое пространство и битовую глубину, но не ширину или высоту изображения. Частичный тип звука может указывать формат сжатия и частоту выборки, но не количество звуковых каналов.

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

Чтобы задать тип носителя, вызовите IMFMediaTypeHandler::SetCurrentMediaType. Некоторые приемники потоков могут не поддерживать изменение типа после установки параметра . Поэтому перед их настройкой полезно протестировать типы носителей. Чтобы проверить, принимает ли приемник мультимедиа тип носителя (без задания типа), вызовите IMFMediaTypeHandler::IsMediaTypeSupported.

Поток данных

Приемники мультимедиа используют модель извлечения, что означает, что приемники потока запрашивают данные по мере необходимости. Клиент должен своевременно реагировать, чтобы избежать сбоев.

Некоторые приемники мультимедиа поддерживают предварительную настройку. Предварительная подготовка — это процесс предоставления данных в приемник мультимедиа до запуска часов презентации. Если приемник мультимедиа поддерживает предварительную настройку, приемник мультимедиа предоставляет интерфейс IMFMediaSinkPreroll , а метод GetCharacteristics возвращает флаг MEDIASINK_CAN_PREROLL. Предварительная подготовка гарантирует, что приемник мультимедиа готов к представлению первого образца при запуске часов презентации. Рекомендуется всегда выполнять предварительную настройку клиента, если приемник мультимедиа поддерживает его, так как это может предотвратить сбои или пробелы во время воспроизведения.

Поток данных в приемник мультимедиа работает следующим образом:

  1. Клиент задает типы мультимедиа и часы презентации. Приемник мультимедиа регистрирует себя в часах презентации для получения уведомлений об изменениях состояния часов.
  2. При необходимости клиент запрашивает IMFMediaSinkPreroll. Если приемник мультимедиа предоставляет этот интерфейс, клиент вызывает IMFMediaSinkPreroll::NotifyPreroll. В противном случае клиент переходит к шагу 5.
  3. Каждый приемник потока отправляет одно или несколько событий MEStreamSinkRequestSample . В ответ на каждое из этих событий клиент получает следующую выборку данных для этого потока и вызывает IMFStreamSink::P rocessSample.
  4. Когда каждый приемник потока получает достаточно данных, он отправляет событие MEStreamSinkPrerolled .
  5. Клиент вызывает IMFPresentationClock::Start , чтобы запустить часы презентации.
  6. Часы презентации уведомляют приемник мультимедиа о запуске часов, вызывая IMFClockStateSink::OnClockStart.
  7. Чтобы получить больше данных, каждый приемник потока отправляет события MEStreamSinkRequestSample . В ответ на каждое из этих событий клиент получает следующий пример и вызывает ProcessSample. Этот шаг повторяется до завершения презентации.

Большинство приемников мультимедиа обрабатывают образцы асинхронно, поэтому приемники потоков могут отправлять несколько примеров запросов за раз.

Во время потоковой передачи клиент может вызвать IMFStreamSink::P laceMarker и IMFStreamSink::Flush в любое время. Маркеры описаны в следующем разделе. Очистка приводит к тому, что приемник потока удаляет все образцы, которые он поставил в очередь, но еще не отрисованы.

Маркеры

Маркеры предоставляют клиенту способ указания определенных точек в потоке. Маркер состоит из следующих сведений:

  • Тип маркера, определенный как член перечисления MFSTREAMSINK_MARKER_TYPE .
  • Данные, связанные с маркером. Значение данных зависит от типа маркера. Некоторые типы маркеров не имеют данных.
  • Необязательные данные для собственного использования клиента.

Чтобы разместить маркер, клиент вызывает IMFStreamSink::P laceMarker. Приемник потока завершает обработку всех примеров, полученных до вызова PlaceMarker , а затем отправляет событие MEStreamSinkMarker .

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

  1. ProcessSample (пример 1)
  2. ProcessSample (пример 2)
  3. PlaceMarker (Маркер 1)
  4. ProcessSample (пример 3)
  5. PlaceMarker (Маркер 2)

В этом примере приемник потока должен отправить событие MEStreamSinkMarker для маркера 1 после обработки образца 2 и событие для маркера 2 после обработки образца 3.

Если клиент сбрасывает приемник потока, приемник потока немедленно обрабатывает все маркеры, которые находились в очереди. Он задает код состояния, E_ABORT по этим событиям.

Некоторые маркеры содержат сведения, относящиеся к приемнику мультимедиа:

  • MFSTREAMSINK_MARKER_TICK: указывает на разрыв в потоке. Следующий пример будет разрывом.
  • MFSTREAMSINK_MARKER_ENDOFSEGMENT: указывает конец сегмента или конец потока. Следующий пример (если таковой имеется) может быть разрывом.
  • MFSTREAMSINK_MARKER_EVENT: содержит событие. В зависимости от типа события и реализации приемника мультимедиа приемник может обрабатывать событие или игнорировать его.

"Изменения состояния".

Приемник мультимедиа получает уведомление об изменениях состояния в часах представления через интерфейс IMFClockStateSink приемника мультимедиа. Когда клиент устанавливает часы презентации, приемник мультимедиа вызывает IMFPresentationClock::AddClockStateSink , чтобы зарегистрировать себя для получения уведомлений от часов. В следующей таблице представлена сводка поведения приемника мультимедиа в ответ на изменения состояния часов.

Изменение состояния часов Обработка примеров Обработка маркеров
OnClockStart Примеры обработки, метка времени которых равна времени начала часов или позже. Отправьте событие MEStreamSinkMarker , когда все образцы, полученные до обработки маркера.
OnClockPause Приемник мультимедиа может завершиться ошибкой ProcessSample во время приостановки.
Если приемник мультимедиа принимает примеры во время приостановки, он должен ставить их в очередь до перезапуска часов. Не обрабатывайте образцы, помещенные в очередь, пока они приостановлены.
Если есть образцы, помещенные в очередь, поместите маркеры в ту же очередь. Отправка события маркера при перезапуске часов.
В противном случае немедленно отправьте событие маркера.
OnClockRestart Обработайте все примеры, которые были поставлены в очередь во время приостановки, а затем обработайте так же, как OnClockStart. Отправлять события MEStreamSinkMarker для маркеров в очереди (сериализованных с обработкой образца), а затем обрабатывать те же события, что и OnClockStart.
OnClockStop Удалите все образцы, помещенные в очередь. Дальнейшие вызовы ProcessSample могут завершиться ошибкой. Отправка событий маркера в очереди. При последующих вызовах PlaceMarker немедленно отправьте событие маркера.

 

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

Завершение

Некоторые приемники мультимедиа требуют дополнительного этапа обработки после доставки последнего образца. Обычно это требование применяется к приемникам архивов, которые должны записывать заголовки или индексы в файл. Если приемник мультимедиа требует какой-либо окончательной обработки, он предоставляет интерфейс IMFFinalizableMediaSink .

После того как клиент доставляет последний пример, клиент запрашивает этот интерфейс. Если приемник мультимедиа поддерживает интерфейс, клиент вызывает IMFFinalizableMediaSink::BeginFinalize для асинхронного выполнения окончательной обработки. Этот метод следует стандартной асинхронной модели Media Foundation, описанной в разделе Асинхронные методы обратного вызова. Приемник мультимедиа может предполагать, что клиент вызовет BeginFinalize. Сбой вызова BeginFinalize может привести к неправильному созданию файла.

Завершает работу

Когда клиент завершает работу с приемником мультимедиа, клиент вызывает IMFMediaSink::Shutdown. Внутри этого метода приемник мультимедиа должен нарушить любое число циклических ссылок. Как правило, между приемником мультимедиа и приемником потока будут циклические ссылки.

Если вы используете вспомогательный объект очереди событий для реализации IMFMediaEventGenerator, вызовите IMFMediaEventQueue::Shutdown в очереди событий. Этот метод завершает работу очереди событий и передает сигнал любому вызывающему объекту, который в настоящее время ожидает события.

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

Интерфейсы приемников мультимедиа

В следующей таблице перечислены стандартные интерфейсы, которые приемники мультимедиа могут предоставлять через QueryInterface. Приемники мультимедиа также могут предоставлять пользовательские интерфейсы.

Интерфейс Описание
IMFMediaSink Основной интерфейс для приемников мультимедиа. (Обязательно).
IMFClockStateSink Используется для уведомления приемника мультимедиа об изменении состояния часов презентации. (Обязательно).
IMFFinalizableMediaSink Реализуйте , если приемник мультимедиа должен выполнить последний шаг обработки. (Необязательно.)
IMFGetService Реализуйте, если приемник мультимедиа предоставляет любые интерфейсы служб. (Необязательно.)
IMFMediaEventGenerator Реализуйте, если приемник мультимедиа отправляет какие-либо события. (Необязательно.)
IMFMediaSinkPreroll Реализуйте, если приемник мультимедиа поддерживает предварительную настройку. (Необязательно.)
IMFPresentationTimeSource Реализуйте, если приемник мультимедиа может предоставить источник времени для часов презентации. (Необязательно.)
IMFQualityAdvise Реализуйте, может ли приемник мультимедиа изменять качество воспроизведения. (Необязательно.)

 

При необходимости приемник мультимедиа может реализовать следующий интерфейс в качестве службы.

Интерфейс службы Описание
IMFRateSupport Сообщает диапазон поддерживаемых скоростей воспроизведения.

 

Дополнительные сведения об интерфейсах служб и IMFGetService см. в разделе Service Interfaces.

Интерфейсы приемника потоков

Приемники потоков должны предоставлять следующие интерфейсы через QueryInterface.

Интерфейс Описание
IMFStreamSink Основной интерфейс для приемников потоков. (Обязательно).
IMFMediaEventGenerator События очереди. Интерфейс IMFStreamSink наследует этот интерфейс. (Обязательно).

 

В настоящее время для приемников потоков не определены интерфейсы служб.

События приемника потоковой передачи

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

Событие Описание
MEStreamSinkFormatChanged Недопустимый тип носителя приемника потока. (Необязательно.)
MEStreamSinkMarker Маркер обработан. (Обязательно).
MEStreamSinkPaused Приемник потока приостановлен. (Обязательно).
MEStreamSinkPrerolled Предварительная подготовка завершена. (Необязательно.)
MEStreamSinkRateChanged Приемник потока изменил частоту воспроизведения. (Необязательно.)
MEStreamSinkRequestSample Запрашивается новый пример. (Обязательно).
MEStreamSinkScrubSampleComplete Запрос на скраб выполнен. (Необязательно.)
MEStreamSinkStarted Запущен приемник потока. (Обязательно).
MEStreamSinkStopped Приемник потока остановлен. (Обязательно).

 

В настоящее время для приемников мультимедиа не определены события общего назначения. Некоторые приемники мультимедиа могут отправлять пользовательские события.

Конвейер Media Foundation

Архитектура Media Foundation