Сравнение преобразований MFT и объектов DMO

Преобразования Media Foundation (MFT) — это эволюция модели преобразования, впервые появилась с объектами мультимедиа (DMOS) DirectX. В этом разделе перечислены main отличия MFT от МДО. Прочтите этот раздел, если вы уже знакомы с интерфейсами DMO или хотите преобразовать существующий объект DMO в MFT.

Этот раздел состоит из следующих подразделов.

Число потоков

DMO имеет фиксированное число потоков, а MFT может поддерживать динамическое число потоков. Клиент может добавлять входные потоки, а MFT — новые потоки вывода во время обработки. Однако MFT не требуются для поддержки динамических потоков. MFT может иметь фиксированное количество потоков, как и DMO.

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

Кроме того, метод IMFTransform::P rocessOutput определяет поведение при добавлении или удалении потоков вывода.

Так как У МДО имеются фиксированные потоки, потоки в DMO определяются с помощью значений индекса, отсчитываемых от нуля. С другой стороны, MFT используют идентификаторы потоков, которые не обязательно соответствуют значениям индекса. Это связано с тем, что количество потоков на MFT может измениться. Например, поток 0 можно удалить, оставив поток 1 в качестве первого потока. Однако MFT с фиксированным числом потоков должен соблюдать то же соглашение, что и МД, и использовать значения индекса для идентификаторов потоков.

Согласование формата

MFT используют интерфейс IMFMediaType для описания типов мультимедиа. В противном случае согласование формата с помощью MFT работает на те же основные принципы, что и в случае с МДО. В следующей таблице перечислены методы согласования формата для dmos и соответствующие методы для MFT.

Метод DMO Метод MFT
IMediaObject::GetInputCurrentType IMFTransform::GetInputCurrentType
IMediaObject::GetInputMaxLatency IMFTransform::GetInputStreamInfo
IMediaObject::GetInputSizeInfo IMFTransform::GetInputStreamInfo
IMediaObject::GetInputType IMFTransform::GetInputAvailableType
IMediaObject::GetOutputCurrentType IMFTransform::GetOutputCurrentType
IMediaObject::GetOutputSizeInfo IMFTransform::GetOutputStreamInfo
IMediaObject::GetOutputType IMFTransform::GetOutputAvailableType

 

Потоковые операторы

Как и объекты управления административными данными, MFT обрабатывают данные с помощью вызовов методов ProcessInput и ProcessOutput . Ниже приведены основные различия между процессами DMO и MFT при потоковой передаче данных.

Выделение ресурсов

В MFT нет методов IMediaObject::AllocateStreamingResources и IMediaObject::FreeStreamingResources, используемых с объектами административного управления. Для эффективной обработки распределения и освобождения ресурсов MFT может реагировать на следующие сообщения в методе IMFTransform::P rocessMessage :

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

Эти два сообщения не имеют точного эквивалента DMO.

Обработка данных

MFT используют примеры мультимедиа для хранения входных и выходных данных. Примеры мультимедиа предоставляют интерфейс IMFSample и содержат следующие данные:

  • Метка времени и длительность.
  • Атрибуты, содержащие сведения для каждого примера. Список атрибутов см. в разделе Пример атрибутов.
  • Ноль или более буферов мультимедиа. Каждый буфер мультимедиа предоставляет интерфейс IMFMediaBuffer .

Интерфейс IMFMediaBuffer аналогичен интерфейсу IMediaBuffer DMO. Чтобы получить доступ к базовому буферу памяти, вызовите IMFMediaBuffer::Lock. Этот метод примерно эквивалентен IMediaBuffer::GetBufferAndLength для объектов dmos.

Для несжатых видеоданных буфер мультимедиа также может поддерживать интерфейс IMF2DBuffer . MFT, обрабатывающий несжатое видео (в качестве входных или выходных данных), должен быть подготовлен к использованию интерфейса IMF2DBuffer , если буфер предоставляет его. Дополнительные сведения см. в разделе Несжатые буферы видео.

Media Foundation предоставляет некоторые стандартные реализации IMFMediaBuffer, поэтому обычно не требуется писать собственную реализацию. Чтобы создать буфер DMO из буфера Media Foundation, вызовите MFCreateLegacyMediaBufferOnMFMediaBuffer.

Промывки

В MFT нет метода Flush . Чтобы очистить MFT, вызовите IMFTransform::P rocessMessage с сообщением MFT_MESSAGE_COMMAND_FLUSH .

Прерывания потоков

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

Прочие различия

Ниже приведены некоторые дополнительные незначительные различия между MFT и dmos.

Флаги

В следующих таблицах перечислены различные флаги DMO и их эквиваленты MFT. Всякий раз, когда флаг DMO сопоставляется непосредственно с флагом MFT, оба флага имеют одинаковое числовое значение. Однако некоторые флаги DMO не имеют точных эквивалентов MFT и наоборот.

Флаги ProcessInput

МДО: перечисление _DMO_INPUT_DATA_BUFFER_FLAGS .

MFT: нет эквивалентного перечисления.

Флаг DMO Флаг MFT
DMO_INPUT_DATA_BUFFERF_SYNCPOINT Нет эквивалентного флага. Вместо этого задайте атрибут MFSampleExtension_CleanPoint в примере.
DMO_INPUT_DATA_BUFFERF_TIME Нет эквивалентного флага. Вместо этого вызовите IMFSample::SetSampleTime в образце.
DMO_INPUT_DATA_BUFFERF_TIMELENGTH Нет эквивалентного флага. Вместо этого вызовите IMFSample::SetSampleDuration в образце.

 

Флаги ProcessOutput

МДО: перечисление _DMO_PROCESS_OUTPUT_FLAGS .

MFT: перечисление _MFT_PROCESS_OUTPUT_FLAGS .

Флаг DMO Флаг MFT
DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER

 

МДО: перечисление _DMO_OUTPUT_DATA_BUFFER_FLAGS .

MFT: перечисление _MFT_OUTPUT_DATA_BUFFER_FLAGS .

Флаг DMO Флаг MFT
DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT Нет эквивалентного флага. Вместо этого проверка для атрибута MFSampleExtension_CleanPoint в примере.
DMO_OUTPUT_DATA_BUFFERF_TIME Нет эквивалентного флага. Вместо этого вызовите imfSample::GetSampleTime в образце.
DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH Нет эквивалентного флага. Вместо этого вызовите IMFSample::GetSampleDuration в образце.
DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE MFT_OUTPUT_DATA_BUFFER_INCOMPLETE
Нет эквивалентного флага. MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
Нет эквивалентного флага. MFT_OUTPUT_DATA_BUFFER_STREAM_END
Нет эквивалентного флага. MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE

 

Флаги GetInputStatus

МДО: перечисление _DMO_INPUT_STATUS_FLAGS .

MFT: перечисление _MFT_INPUT_STATUS_FLAGS .

Флаг DMO Флаг MFT
DMO_INPUT_STATUSF_ACCEPT_DATA MFT_INPUT_STATUS_ACCEPT_DATA

 

Флаги GetOutputStatus

МДО: нет эквивалентного перечисления.

MFT: перечисление _MFT_OUTPUT_STATUS_FLAGS .

Флаг DMO Флаг MFT
Нет эквивалентного флага. MFT_OUTPUT_STATUS_SAMPLE_READY

 

Флаги GetInputStreamInfo

МДО: перечисление _DMO_INPUT_STREAM_INFO_FLAGS .

MFT: перечисление _MFT_INPUT_STREAM_INFO_FLAGS .

Флаг DMO Флаг MFT
DMO_INPUT_STREAMF_WHOLE_SAMPLES MFT_INPUT_STREAM_WHOLE_SAMPLES
DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE
DMO_INPUT_STREAMF_HOLDS_BUFFERS MFT_INPUT_STREAM_HOLDS_BUFFERS
Нет эквивалентного флага. MFT_INPUT_STREAM_DOES_NOT_ADDREF
Нет эквивалентного флага. MFT_INPUT_STREAM_REMOVABLE
Нет эквивалентного флага. MFT_INPUT_STREAM_OPTIONAL

 

Флаги GetOutputStreamInfo

МДО: перечисление _DMO_OUTPUT_STREAM_INFO_FLAGS .

MFT: перечисление _MFT_OUTPUT_STREAM_INFO_FLAGS .

Флаг DMO Флаг MFT
DMO_OUTPUT_STREAMF_WHOLE_SAMPLES MFT_OUTPUT_STREAM_WHOLE_SAMPLES
DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE
DMO_OUTPUT_STREAMF_DISCARDABLE MFT_OUTPUT_STREAM_DISCARDABLE
DMO_OUTPUT_STREAMF_OPTIONAL MFT_OUTPUT_STREAM_OPTIONAL
Нет эквивалентного флага. MFT_OUTPUT_STREAM_PROVIDES_SAMPLES
Нет эквивалентного флага. MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
Нет эквивалентного флага. MFT_OUTPUT_STREAM_LAZY_READ
Нет эквивалентного флага. MFT_OUTPUT_STREAM_REMOVABLE

 

Флаги SetInputType/SetOutputType

DmOs: перечисление _DMO_SET_TYPE_FLAGS .

MFT: перечисление _MFT_SET_TYPE_FLAGS .

Флаг DMO Флаг MFT
DMO_SET_TYPEF_TEST_ONLY MFT_SET_TYPE_TEST_ONLY
DMO_SET_TYPEF_CLEAR Нет эквивалентного флага. Вместо этого присвойте типу носителя значение NULL , чтобы очистить тип мультимедиа.

 

Коды ошибок

В следующей таблице показано, как сопоставить коды ошибок DMO с кодами ошибок MFT. Гибридный объект MFT/DMO должен возвращать коды ошибок DMO из методов IMediaObject и коды ошибок MFT из методов IMFTransform . Коды ошибок DMO определяются в файле заголовка MediaErr.h. Коды ошибок MFT определяются в файле заголовка mferror.h.

Код ошибки DMO Код ошибки MFT
DMO_E_INVALIDTYPE MF_E_INVALIDTYPE
DMO_E_INVALIDSTREAMINDEX MF_E_INVALIDSTREAMNUMBER
DMO_E_NOTACCEPTING MF_E_NOTACCEPTING
DMO_E_NO_MORE_ITEMS MF_E_NO_MORE_TYPES
DMO_E_TYPE_NOT_ACCEPTED MF_E_INVALIDMEDIATYPE
DMO_E_TYPE_NOT_SET MF_E_TRANSFORM_TYPE_NOT_SET

 

Создание гибридных объектов DMO/MFT

Интерфейс IMFTransform слабо основан на IMediaObject, который является основным интерфейсом для объектов мультимедиа DirectX (DMOS). Можно создать объекты, которые предоставляют оба интерфейса. Однако это может привести к конфликтам имен, так как интерфейсы имеют некоторые методы с одинаковыми именами. Эту проблему можно решить одним из двух способов:

Решение 1. Добавьте следующую строку в начало любого CPP-файла, содержащего функции MFT:

#define MFT_UNIQUE_METHOD_NAMES

При этом объявление интерфейса IMFTransform изменяется таким образом, что большинство имен методов имеют префикс "MFT". Таким образом, IMFTransform::P rocessInput становится IMFTransform::MFTProcessInput, а IMediaObject::P rocessInput сохраняет свое первоначальное имя. Этот метод наиболее полезен при преобразовании существующего объекта DMO в гибридное DMO/MFT. Вы можете добавить новые методы MFT, не изменяя методы DMO.

Решение 2. Используйте синтаксис C++ для устранения неоднозначности имен, унаследованных от нескольких интерфейсов. Например, объявите MFT-версию ProcessInput следующим образом:

CMyHybridObject::IMFTransform::ProcessInput(...)

Объявите версию DMO ProcessInput следующим образом:

CMyHybridObject::IMediaObject::ProcessInput(...)

При внутреннем вызове метода в объекте можно использовать этот синтаксис, но это переопределит виртуальное состояние метода. Лучший способ выполнения вызовов из объекта :

hr = ((IMediaObject*)this)->ProcessInput(...)

Таким образом, если вы наследуете другой класс от CMyHybridObject и переопределите метод CMyHybridObject::IMediaObject::P rocessInput, вызывается правильный виртуальный метод. Интерфейсы DMO описаны в документации по пакету SDK DirectShow.

Преобразования Media Foundation