Partilhar via


Usando o modelo de classe DMO

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

O DirectShow inclui um modelo de classe, IMediaObjectImpl, para implementar DMOs. O modelo lida com muitas das tarefas de "contabilidade", como a validação de parâmetros de entrada. Usando o modelo, você pode se concentrar na funcionalidade que é específica para o seu DMO. Além disso, o modelo ajuda a garantir que você crie uma implementação robusta. O modelo é definido no arquivo de cabeçalho Dmoimpl.h, localizado no diretório Include do SDK.

O modelo de IMediaObjectImpl herda a interface IMediaObject. Para criar um DMO usando o modelo, defina uma nova classe que deriva de IMediaObjectImpl. O modelo implementa todos os IMediaObject métodos. Na maioria dos casos, o modelo chama um método privado correspondente na classe derivada. O modelo fornece os seguintes recursos:

  • Verificação de parâmetros fundamentais. Os métodos do modelo verificam se os parâmetros necessários não estão NULL, se os índices de fluxo estão dentro dos limites e se os sinalizadores são válidos.
  • Bloqueio. Os métodos de modelo chamam dois métodos internos, Lock e Unlock, para serializar operações no DMO. Esse recurso garante que o DMO seja thread-safe.
  • Tipos de mídia. O modelo armazena os tipos de mídia definidos pelo cliente e fornece métodos de acesso para os tipos de mídia.
  • Streaming. O modelo impede o streaming até que o cliente tenha definido tipos de mídia para todos os fluxos não opcionais. Ele também garante que o método IMediaObject::AllocateStreamingResources seja chamado antes do início do streaming, o que garante que os recursos sejam alocados.

A classe derivada deve implementar o IUnknown interface; o modelo não fornece essa interface. Você pode usar a ATL (Ative Template Library) para implementar IUnknownou pode fornecer alguma outra implementação. O modelo também não implementa o mecanismo de bloqueio. A classe derivada deve implementar os métodos Lock e Unlock. Se você criar sua classe usando ATL, poderá usar as implementações ATL padrão.

Declarando a classe derivada

O modelo de classe IMediaObjectImpl é declarado da seguinte forma:

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

Os três parâmetros do modelo são _DERIVED_, NUMBEROFINPUTS e NUMBEROFOUTPUTS. Defina _DERIVED_ igual ao nome da sua classe. Os outros dois parâmetros definem o número de fluxos de entrada e fluxos de saída no DMO. Por exemplo, para criar uma classe DMO chamada CMyDmo que suporta um fluxo de entrada e dois fluxos de saída, use a seguinte declaração:

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

O restante desta seção descreve como o modelo implementa os vários métodos em IMediaObject.

métodos para definir tipos de mídia

Os seguintes métodos definem ou recuperam tipos de mídia no DMO:

  • GetInputType, GetOutputType. Esses métodos retornam tipos de mídia preferenciais, por número de fluxo e índice de tipo. O modelo chama InternalGetInputType ou InternalGetOutputType na classe derivada.
  • DefinirTipoDeEntrada, DefinirTipoDeSaída. Esses métodos definem o tipo de mídia em um fluxo, testam um tipo de mídia ou limpam um tipo de mídia. Para validar o tipo de media, o modelo chama InternalCheckInputType ou InternalCheckOutputType na classe derivada. A classe derivada retorna S_OK para aceitar o tipo ou DMO_E_INVALIDTYPE para rejeitar o tipo. O template lida com a configuração ou limpeza do tipo de mídia.
  • ObterTipoDeCorrenteDeEntrada, ObterTipoDeCorrenteDeSaída. Esses métodos retornam o tipo de mídia atual para um fluxo ou DMO_E_TYPE_NOT_SET se nenhum tipo estiver definido. O modelo implementa completamente esses métodos.

Métodos Informativos

Os métodos a seguir fornecem informações sobre o DMO.

  • GetInputMaxLatency, SetInputMaxLatency. Esses métodos recuperam ou definem a latência máxima. O template chama InternalGetInputMaxLatency ou InternalSetInputMaxLatency na classe derivada.
  • GetInputSizeInfo, GetOutputSizeInfo. Esses métodos retornam os requisitos de buffer do DMO para um fluxo especificado. Se nenhum tipo de mídia tiver sido definido nesse fluxo, o modelo retornará DMO_E_TYPE_NOT_SET. Caso contrário, chama InternalGetInputSizeInfo ou InternalGetOutputSizeInfo na classe derivada.
  • GetInputStreamInfoGetOutputStreamInfo. Esses métodos retornam vários sinalizadores que indicam como o cliente deve formatar os dados. O modelo chama InternalGetInputStreamInfo ou InternalGetOutputStreamInfo na classe derivada.
  • GetStreamCount. Esse método retorna o número de fluxos de entrada e saída. O modelo implementa esse método, usando os parâmetros do modelo.

Métodos para alocação de recursos

  • O método AllocateStreamingResources aloca todos os recursos de que o DMO precisa antes do início do streaming. O método FreeStreamingResources libera os mesmos recursos. O modelo chama InternalAllocateStreamingResources e InternalFreeStreamingResources, respectivamente.

O cliente do DMO não é obrigado a chamar esses métodos, mas o modelo chama automaticamente AllocateStreamingResources antes do início do streaming. Portanto, o DMO pode assumir que os recursos foram corretamente alocados até ao momento em que ProcessInput é chamado. O DMO deve chamar FreeStreamingResources no seu destrutor.

Além disso, quando o modelo chama InternalAllocateStreamingResources, ele define um sinalizador interno, para que ele não chame esse método novamente até chamar InternalFreeStreamingResources. Isso garante que os recursos não sejam realocados acidentalmente, o que pode causar vazamentos de memória.

Métodos para streaming

Os seguintes métodos são usados para transmitir dados:

  • GetInputStatus. Esse método indica se o DMO pode aceitar entrada neste momento. O template chama InternalAcceptingInput na classe derivada. Se o DMO puder aceitar entrada, a classe derivada retornará S_OK e o modelo configurará o bit de DMO_INPUT_STATUSF_ACCEPT_DATA no parâmetro dwFlags. Caso contrário, a classe derivada retorna S_FALSE e o modelo define dwFlags a zero.
  • ProcessInput. Este método processa um buffer de entrada. O modelo chama AllocateStreamingResources, descrito anteriormente. Em seguida, ele chama InternalAcceptingInput na classe derivada. Se o DMO puder aceitar novas entradas, o modelo chamará InternalProcessInput.
  • ProcessOutput. Este método processa um conjunto de buffers de saída, um buffer para cada fluxo de saída. O modelo chama AllocateStreamingResources e, em seguida, InternalProcessOutput.
  • Descontinuidade. Este método sinaliza uma descontinuidade em um fluxo de entrada. O modelo chama InternalAcceptingInput na classe derivada. Se esse método retornar S_OK, o modelo chamará InternalDiscontinuity na classe derivada.
  • Flush. Este método limpa o DMO. O modelo chama InternalFlush na classe derivada. O DMO deve descartar todos os buffers de entrada que ainda mantém para serem processados.

O modelo não fornece nenhum suporte direto para o IMediaObjectInPlace interface.

Métodos para bloquear

O bloqueio é usado para proteger o estado do DMO em um ambiente multithreaded. Em um projeto ATL, o método IMediaObject::Lock causa um conflito de nome com o método ATL Lock. Para resolver o conflito, o modelo renomeia o IMediaObject método para DMOLock. Ao compilar a classe derivada, defina FIX_LOCK_NAME antes de incluir o arquivo de cabeçalho Dmo.h:

#define FIX_LOCK_NAME
#include <dmo.h>

Essa diretiva faz com que o pré-processador substitua DMOLock por Lock na declaração da interface IMediaObject. Os aplicativos ainda podem invocar o método usando o nome Lock, porque a ordem vtable não é alterada. O método DMOLock chama Lock ou Unlock na classe derivada. Se você estiver usando ATL para implementar a classe derivada, esses métodos já estão definidos pela ATL, portanto, nenhum código adicional é necessário. Se não estiver a usar ATL, deve fornecer os métodos Lock e Unlock na sua classe derivada.

O modelo bloqueia automaticamente o DMO em cada um dos métodos IMediaObject . A classe derivada pode precisar bloquear o DMO dentro de outros métodos públicos que implementa (por exemplo, se ele suporta IMediaObjectInPlace). O modelo de classe também fornece uma classe auxiliar interna, IMediaObjectImpl::LockIt, que é útil para bloquear e desbloquear o DMO.

Resumo

Para os métodos seguintes de IMediaObject, o modelo chama um método correspondente com a mesma assinatura da classe derivada. A classe derivada deve implementar cada um dos métodos mostrados na segunda coluna.

Método IMediaObject Método de classe derivada
AlocarRecursosDeStreaming InternalAllocateStreamingResources
Descontinuidade Descontinuidade Interna
Flush InternalFlush
FreeStreamingResources InternalFreeStreamingResources
GetInputMaxLatency InternalGetInputMaxLatency
ObterInformaçãoTamanhoEntrada InternalGetInputSizeInfo
GetInputStreamInfo InternalGetInputStreamInfo
GetInputType InternalGetInputType
GetOutputSizeInfo ObterInformaçõesDeTamanhoDeSaídaInterno
GetOutputStreamInfo InternalGetOutputStreamInfo
GetOutputType InternalGetOutputType
ProcessInput EntradaProcessoInterno
SaídaDoProcesso SaídaDoProcessoInterno
SetInputMaxLatency InternalSetInputMaxLatency

 

Para os métodos de IMediaObject restantes, não há uma correspondência direta entre métodos de template e métodos de classe derivada. A tabela a seguir resume quais métodos são totalmente implementados pelo modelo e quais métodos chamam outros métodos na classe derivada.

Método IMediaObject Método de classe derivada
ObterTipoCorrenteDeEntrada Totalmente implementado
GetOutputCurrentType Totalmente implementado
GetStreamCount Totalmente implementado
GetInputStatus InternalAcceptingInput
Lock (implementado como DMOLock) Bloquear, desbloquear
SetInputType InternalCheckInputType
SetOutputType InternalCheckOutputType

 

Modelo de classe IMediaObjectImpl

Escrevendo um DMO