Comparação de MFTs e DMOs

As MFTs (transformações do Media Foundation) são uma evolução do modelo de transformação introduzido pela primeira vez com DMOs (Objetos de Mídia) do DirectX. Este tópico resume as main maneiras pelas quais os MFTs diferem dos DMOs. Leia este tópico se você já estiver familiarizado com as interfaces DMO ou se quiser converter um DMO existente em um MFT.

Este tópico contém as seguintes seções:

Número de fluxos

Um DMO tem um número fixo de fluxos, enquanto um MFT pode dar suporte a um número dinâmico de fluxos. O cliente pode adicionar fluxos de entrada e o MFT pode adicionar novos fluxos de saída durante o processamento. No entanto, os MFTs não são necessários para dar suporte a fluxos dinâmicos. Um MFT pode ter um número fixo de fluxos, assim como um DMO.

Os métodos a seguir são usados para dar suporte a fluxos dinâmicos em um MFT:

Além disso, o método IMFTransform::P rocessOutput define o comportamento para adicionar ou remover fluxos de saída.

Como os DMOs têm fluxos fixos, os fluxos em um DMO são identificados usando valores de índice baseados em zero. Os MFTs, por outro lado, usam identificadores de fluxo que não correspondem necessariamente aos valores de índice. Isso ocorre porque o número de fluxos em um MFT pode mudar. Por exemplo, o fluxo 0 pode ser removido, deixando o fluxo 1 como o primeiro fluxo. No entanto, um MFT com um número fixo de fluxos deve observar a mesma convenção que DMOs e usar valores de índice para identificadores de fluxo.

Formatar Negociação

Os MFTs usam a interface IMFMediaType para descrever tipos de mídia. Caso contrário, a negociação de formato com MFTs funciona nos mesmos princípios básicos que com DMOs. A tabela a seguir lista os métodos de negociação de formato para DMOs e os métodos correspondentes para MFTs.

Método DMO Método 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

 

Streaming

Assim como os DMOs, os MFTs processam dados por meio de chamadas para os métodos ProcessInput e ProcessOutput . Aqui estão as principais diferenças entre os processos de DMO e MFT ao transmitir dados.

Alocando recursos

Os MFTs não têm os métodos IMediaObject::AllocateStreamingResources e IMediaObject::FreeStreamingResources usados com DMOs. Para lidar com alocação e desalocação de recursos com eficiência, um MFT pode responder às seguintes mensagens no método IMFTransform::P rocessMessage :

Além disso, o cliente pode sinalizar o início e o fim de um fluxo chamando ProcessMessage com as seguintes mensagens:

Essas duas mensagens não têm equivalente DMO exato.

Processando dados

Os MFTs usam exemplos de mídia para armazenar dados de entrada e saída. Exemplos de mídia expõem a interface IMFSample e contêm os seguintes dados:

  • Carimbo de data/hora e duração.
  • Atributos que contêm informações por exemplo. Para obter uma lista de atributos, consulte Atributos de exemplo.
  • Zero ou mais buffers de mídia. Cada buffer de mídia expõe a interface IMFMediaBuffer .

A interface IMFMediaBuffer é semelhante à interface IMediaBuffer do DMO. Para acessar o buffer de memória subjacente, chame IMFMediaBuffer::Lock. Esse método é aproximadamente equivalente a IMediaBuffer::GetBufferAndLength para DMOs.

Para dados de vídeo descompactados, um buffer de mídia também pode dar suporte à interface IMF2DBuffer . Um MFT que processa vídeo descompactado (como entrada ou saída) deve estar preparado para usar a interface IMF2DBuffer se o buffer o expor. Para obter mais informações, consulte Buffers de vídeo descompactados.

A Media Foundation fornece algumas implementações padrão do IMFMediaBuffer, portanto, geralmente não é necessário escrever sua própria implementação. Para criar um buffer DMO de um buffer do Media Foundation, chame MFCreateLegacyMediaBufferOnMFMediaBuffer.

Liberando

Os MFTs não têm um método Flush . Para liberar um MFT, chame IMFTransform::P rocessMessage com a mensagem MFT_MESSAGE_COMMAND_FLUSH .

Descontinuidades de fluxo

Os MFTs não têm um método Descontinuidade . Para sinalizar uma descontinuidade em um fluxo, defina o atributo MFSampleExtension_Discontinuity no exemplo de entrada.

Diferenças diversas

Aqui estão algumas diferenças secundárias adicionais entre MFTs e DMOs.

Flags

As tabelas a seguir listam os vários sinalizadores DMO e seus equivalentes de MFT. Sempre que um sinalizador DMO é mapeado diretamente para um sinalizador MFT, ambos os sinalizadores têm o mesmo valor numérico. No entanto, alguns sinalizadores DMO não têm equivalentes MFT exatos e vice-versa.

Sinalizadores ProcessInput

DMOs: _DMO_INPUT_DATA_BUFFER_FLAGS enumeração.

MFTs: nenhuma enumeração equivalente.

Sinalizador DMO Sinalizador MFT
DMO_INPUT_DATA_BUFFERF_SYNCPOINT Nenhum sinalizador equivalente. Em vez disso, defina o atributo MFSampleExtension_CleanPoint no exemplo.
DMO_INPUT_DATA_BUFFERF_TIME Nenhum sinalizador equivalente. Em vez disso, chame IMFSample::SetSampleTime no exemplo.
DMO_INPUT_DATA_BUFFERF_TIMELENGTH Nenhum sinalizador equivalente. Em vez disso, chame IMFSample::SetSampleDuration no exemplo.

 

Sinalizadores ProcessOutput

DMOs: _DMO_PROCESS_OUTPUT_FLAGS enumeração.

MFTs: _MFT_PROCESS_OUTPUT_FLAGS enumeração.

Sinalizador DMO Sinalizador MFT
DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER

 

DMOs: _DMO_OUTPUT_DATA_BUFFER_FLAGS enumeração.

MFTs: _MFT_OUTPUT_DATA_BUFFER_FLAGS enumeração.

Sinalizador DMO Sinalizador MFT
DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT Nenhum sinalizador equivalente. Em vez disso, marcar para o atributo MFSampleExtension_CleanPoint no exemplo.
DMO_OUTPUT_DATA_BUFFERF_TIME Nenhum sinalizador equivalente. Em vez disso, chame IMFSample::GetSampleTime no exemplo.
DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH Nenhum sinalizador equivalente. Em vez disso, chame IMFSample::GetSampleDuration no exemplo.
DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE MFT_OUTPUT_DATA_BUFFER_INCOMPLETE
Nenhum sinalizador equivalente. MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
Nenhum sinalizador equivalente. MFT_OUTPUT_DATA_BUFFER_STREAM_END
Nenhum sinalizador equivalente. MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE

 

Sinalizadores GetInputStatus

DMOs: _DMO_INPUT_STATUS_FLAGS enumeração.

MFTs: _MFT_INPUT_STATUS_FLAGS enumeração.

Sinalizador DMO Sinalizador MFT
DMO_INPUT_STATUSF_ACCEPT_DATA MFT_INPUT_STATUS_ACCEPT_DATA

 

Sinalizadores GetOutputStatus

DMOs: nenhuma enumeração equivalente.

MFTs: _MFT_OUTPUT_STATUS_FLAGS enumeração.

Sinalizador DMO Sinalizador MFT
Nenhum sinalizador equivalente. MFT_OUTPUT_STATUS_SAMPLE_READY

 

Sinalizadores GetInputStreamInfo

DMOs: _DMO_INPUT_STREAM_INFO_FLAGS enumeração.

MFTs: _MFT_INPUT_STREAM_INFO_FLAGS enumeração.

Sinalizador DMO Sinalizador 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
Nenhum sinalizador equivalente. MFT_INPUT_STREAM_DOES_NOT_ADDREF
Nenhum sinalizador equivalente. MFT_INPUT_STREAM_REMOVABLE
Nenhum sinalizador equivalente. MFT_INPUT_STREAM_OPTIONAL

 

Sinalizadores GetOutputStreamInfo

DMOs: _DMO_OUTPUT_STREAM_INFO_FLAGS enumeração.

MFTs: _MFT_OUTPUT_STREAM_INFO_FLAGS enumeração.

Sinalizador DMO Sinalizador 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
Nenhum sinalizador equivalente. MFT_OUTPUT_STREAM_PROVIDES_SAMPLES
Nenhum sinalizador equivalente. MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
Nenhum sinalizador equivalente. MFT_OUTPUT_STREAM_LAZY_READ
Nenhum sinalizador equivalente. MFT_OUTPUT_STREAM_REMOVABLE

 

Sinalizadores SetInputType/SetOutputType

DMOs: _DMO_SET_TYPE_FLAGS enumeração.

MFTs: _MFT_SET_TYPE_FLAGS enumeração.

Sinalizador DMO Sinalizador MFT
DMO_SET_TYPEF_TEST_ONLY MFT_SET_TYPE_TEST_ONLY
DMO_SET_TYPEF_CLEAR Nenhum sinalizador equivalente. Em vez disso, defina o tipo de mídia como NULL para limpar o tipo de mídia.

 

Códigos de erro

A tabela a seguir mostra como mapear códigos de erro DMO para códigos de erro MFT. Um objeto MFT/DMO híbrido deve retornar os códigos de erro DMO dos métodos IMediaObject e os códigos de erro MFT dos métodos IMFTransform . Os códigos de erro DMO são definidos no arquivo de cabeçalho MediaErr.h. Os códigos de erro MFT são definidos no arquivo de cabeçalho mferror.h.

Código de erro DMO Código de erro 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

 

Criando objetos DMO/MFT híbridos

A interface IMFTransform é vagamente baseada em IMediaObject, que é a interface principal para DMOs (Objetos de Mídia) DirectX. É possível criar objetos que expõem ambas as interfaces. No entanto, isso pode levar a colisões de nomenclatura, pois as interfaces têm alguns métodos que compartilham o mesmo nome. Você pode resolver esse problema de duas maneiras:

Solução 1: inclua a seguinte linha na parte superior de qualquer arquivo .cpp que contenha funções MFT:

#define MFT_UNIQUE_METHOD_NAMES

Isso altera a declaração da interface IMFTransform para que a maioria dos nomes de método seja prefixada com "MFT". Assim, IMFTransform::P rocessInput torna-se IMFTransform::MFTProcessInput, enquanto IMediaObject::P rocessInput mantém seu nome original. Essa técnica será mais útil se você estiver convertendo um DMO existente em um DMO/MFT híbrido. Você pode adicionar os novos métodos MFT sem alterar os métodos DMO.

Solução 2: use a sintaxe C++ para desambiguar nomes herdados de mais de uma interface. Por exemplo, declare a versão MFT de ProcessInput da seguinte maneira:

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

Declare a versão DMO de ProcessInput da seguinte maneira:

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

Se você fizer uma chamada interna para um método dentro do objeto , poderá usar essa sintaxe, mas isso substituirá a status virtual do método . Uma maneira melhor de fazer chamadas de dentro do objeto é a seguinte:

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

Dessa forma, se você derivar outra classe do método CMyHybridObject e substituir o método CMyHybridObject::IMediaObject::P rocessInput, o método virtual correto será chamado. As interfaces DMO estão documentadas na documentação do SDK do DirectShow.

Transformações do Media Foundation