Поделиться через


Использование шаблона класса DMO

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует, чтобы новый код использовал MediaPlayer, IMFMediaEngine и аудио- и видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, использующий устаревшие API, чтобы по возможности использовать новые API.]

DirectShow включает шаблон класса IMediaObjectImpl для реализации dmos. Шаблон обрабатывает многие задачи "бухгалтерского учета", такие как проверка входных параметров. С помощью шаблона можно сосредоточиться на функциональных возможностях, относящихся к DMO. Кроме того, шаблон помогает обеспечить надежную реализацию. Шаблон определяется в файле заголовка Dmoimpl.h, расположенном в каталоге Include пакета SDK.

Шаблон IMediaObjectImpl наследует интерфейс IMediaObject . Чтобы создать DMO с помощью шаблона, определите новый класс, производный от IMediaObjectImpl. Шаблон реализует все методы IMediaObject . В большинстве случаев шаблон вызывает соответствующий частный метод в производном классе. Шаблон предоставляет следующие функции:

  • Базовая проверка параметров. Методы шаблона проверяют, что обязательные параметры не имеют значения NULL, индексы потоков находятся в пределах диапазона и что флаги допустимы.
  • Блокировки. Методы шаблона вызывают два внутренних метода, Lock и Unlock, для сериализации операций в DMO. Эта функция гарантирует потокобезопасность DMO.
  • Типы мультимедиа. Шаблон хранит типы мультимедиа, заданные клиентом, и предоставляет методы доступа для типов мультимедиа.
  • Потокового. Шаблон запрещает потоковую передачу, пока клиент не настроит типы мультимедиа для всех необязательных потоков. Он также гарантирует, что метод IMediaObject::AllocateStreamingResources вызывается перед началом потоковой передачи, что гарантирует выделение ресурсов.

Производный класс должен реализовывать интерфейс IUnknown ; шаблон не предоставляет этот интерфейс. Для реализации IUnknown можно использовать библиотеку активных шаблонов (ATL) или предоставить другую реализацию. Шаблон также не реализует механизм блокировки. Производный класс должен реализовывать методы Lock и Unlock . Если вы создаете класс с помощью ATL, можно использовать реализации ATL по умолчанию.

Объявление производного класса

Шаблон класса IMediaObjectImpl объявляется следующим образом:

template <class _DERIVED_, int NUMBEROFINPUTS, int NUMBEROFOUTPUTS>
class IMediaObjectImpl : public ImediaObject

Три параметра шаблона: _DERIVED_, NUMBEROFINPUTS и NUMBEROFOUTPUTS. Задайте значение _DERIVED_ равным имени класса. Два других параметра определяют количество входных и выходных потоков в DMO. Например, чтобы создать класс DMO CMyDmo, поддерживающий один входной и два выходных потоков, используйте следующее объявление:

class CMyDmo : public IMediaObjectImpl<CMyDmo, 1, 2>

В оставшейся части этого раздела описывается, как шаблон реализует различные методы в IMediaObject.

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

Следующие методы задают или извлекают типы носителей в DMO:

  • GetInputType, GetOutputType. Эти методы возвращают предпочтительные типы мультимедиа по номеру потока и индексу типа. Шаблон вызывает InternalGetInputType или InternalGetOutputType в производном классе.
  • SetInputType, SetOutputType. Эти методы задают тип мультимедиа в потоке, проверяют тип носителя или очищают тип мультимедиа. Чтобы проверить тип носителя, шаблон вызывает InternalCheckInputType или InternalCheckOutputType в производном классе. Производный класс возвращает S_OK для принятия типа или DMO_E_INVALIDTYPE, чтобы отклонить тип. Шаблон обрабатывает настройку или очистку типа носителя.
  • GetInputCurrentType, GetOutputCurrentType. Эти методы возвращают текущий тип мультимедиа для потока или DMO_E_TYPE_NOT_SET, если тип не задан. Шаблон полностью реализует эти методы.

Информационные методы

Следующие методы предоставляют сведения о DMO.

  • GetInputMaxLatency, SetInputMaxLatency. Эти методы извлекают или задают максимальную задержку. Шаблон вызывает InternalGetInputMaxLatency или InternalSetInputMaxLatency для производного класса.
  • GetInputSizeInfo, GetOutputSizeInfo. Эти методы возвращают требования к буферу DMO для указанного потока. Если в этом потоке не задан тип мультимедиа, шаблон возвращает DMO_E_TYPE_NOT_SET. В противном случае он вызывает InternalGetInputSizeInfo или InternalGetOutputSizeInfo в производном классе.
  • GetInputStreamInfo, GetOutputStreamInfo. Эти методы возвращают различные флаги, указывающие, как клиент должен форматировать данные. Шаблон вызывает InternalGetInputStreamInfo или InternalGetOutputStreamInfo в производном классе.
  • GetStreamCount. Этот метод возвращает количество входных и выходных потоков. Шаблон реализует этот метод с использованием параметров шаблона.

Методы выделения ресурсов

  • Метод AllocateStreamingResources выделяет все ресурсы, необходимые DMO перед началом потоковой передачи. Метод FreeStreamingResources освобождает те же ресурсы. Шаблон вызывает InternalAllocateStreamingResources и InternalFreeStreamingResources соответственно.

Клиент DMO не требуется вызывать эти методы, но шаблон автоматически вызывает AllocateStreamingResources перед запуском потоковой передачи. Таким образом, DMO может предположить, что ресурсы были правильно выделены к моменту вызова ProcessInput . DMO должен вызывать FreeStreamingResources в своем деструкторе.

Кроме того, когда шаблон вызывает InternalAllocateStreamingResources, он устанавливает внутренний флаг, чтобы он не вызывал этот метод снова до вызова InternalFreeStreamingResources. Это гарантирует, что ресурсы не будут выделены случайно, что может привести к утечке памяти.

Методы потоковой передачи

Для потоковой передачи данных используются следующие методы:

  • GetInputStatus. Этот метод указывает, может ли DMO принимать входные данные в настоящее время. Шаблон вызывает InternalAcceptingInput в производном классе. Если DMO может принимать входные данные, производный класс возвращает S_OK, а шаблон задает бит DMO_INPUT_STATUSF_ACCEPT_DATA в параметре dwFlags . В противном случае производный класс возвращает S_FALSE, а шаблон задает dwFlags равным нулю.
  • ProcessInput. Этот метод обрабатывает входной буфер. Шаблон вызывает Метод AllocateStreamingResources, описанный выше. Затем он вызывает InternalAcceptingInput для производного класса. Если DMO может принимать новые входные данные, шаблон вызывает InternalProcessInput.
  • ProcessOutput. Этот метод обрабатывает набор выходных буферов, по одному буферу для каждого выходного потока. Шаблон вызывает AllocateStreamingResources , а затем InternalProcessOutput.
  • Разрыв. Этот метод сигнализирует о разрыве во входном потоке. Шаблон вызывает InternalAcceptingInput в производном классе. Если этот метод возвращает S_OK, шаблон вызывает InternalDiscontinuity для производного класса.
  • Очистка. Этот метод очищает DMO. Шаблон вызывает InternalFlush для производного класса. DMO должен отменить все входные буферы, которые по-прежнему хранятся для обработки.

Шаблон не обеспечивает прямую поддержку интерфейса IMediaObjectInPlace .

Методы блокировки

Блокировка используется для защиты состояния DMO в многопоточной среде. В проекте ATL метод IMediaObject::Lock вызывает конфликт имен с методом ATL Lock . Чтобы устранить конфликт, шаблон переименовывает метод IMediaObject в DMOLock. При компиляции производного класса определите FIX_LOCK_NAME перед включением файла заголовка Dmo.h:

#define FIX_LOCK_NAME
#include <dmo.h>

Эта директива заставляет препроцессор заменить DMOLock на Lock в объявлении интерфейса IMediaObject . Приложения по-прежнему могут вызывать метод с именем Lock, так как порядок vtable не изменяется. Метод DMOLock вызывает Lock или Unlock для производного класса. Если вы используете ATL для реализации производного класса, эти методы уже определены ATL, поэтому дополнительный код не требуется. Если вы не используете ATL, необходимо указать методы Lock и Unlock в производном классе.

Шаблон автоматически блокирует DMO в каждом из методов IMediaObject . Производный класс может потребоваться заблокировать DMO внутри других открытых методов, которые он реализует (например, если он поддерживает IMediaObjectInPlace). Шаблон класса также предоставляет внутренний вспомогательный класс IMediaObjectImpl::LockIt, который полезен для блокировки и разблокировки DMO.

Сводка

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

Метод IMediaObject Метод производного класса
AllocateStreamingResources InternalAllocateStreamingResources
Разрыв InternalDiscontinuity
Очистка InternalFlush
FreeStreamingResources InternalFreeStreamingResources
GetInputMaxLatency InternalGetInputMaxLatency
GetInputSizeInfo InternalGetInputSizeInfo
GetInputStreamInfo InternalGetInputStreamInfo
GetInputType InternalGetInputType
GetOutputSizeInfo InternalGetOutputSizeInfo
GetOutputStreamInfo InternalGetOutputStreamInfo
GetOutputType InternalGetOutputType
ProcessInput InternalProcessInput
ProcessOutput InternalProcessOutput
SetInputMaxLatency InternalSetInputMaxLatency

 

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

Метод IMediaObject Метод производного класса
GetInputCurrentType Полностью реализовано
GetOutputCurrentType Полностью реализовано
GetStreamCount Полностью реализовано
GetInputStatus InternalAcceptingInput
Блокировка (реализована как DMOLock) Блокировка, разблокировка
SetInputType InternalCheckInputType
SetOutputType InternalCheckOutputType

 

Шаблон класса IMediaObjectImpl

Создание DMO