Coletores de Mídia

Coletores de mídia são os objetos de pipeline que recebem dados de mídia. Um coletor de mídia é o destino de um ou mais fluxos de mídia. Os coletores de mídia se enquadram em duas categorias gerais:

  • Um renderizador é um coletor de mídia que apresenta dados para reprodução. O EVR (renderizador de vídeo avançado) exibe quadros de vídeo e o renderizador de áudio reproduz fluxos de áudio por meio do som cartão ou outro dispositivo de áudio.

  • Um coletor de arquivos é um coletor de mídia que grava dados em um arquivo ou em outro armazenamento.

A main diferença entre eles é que um coletor de arquivos não consome os dados a uma taxa de reprodução fixa. Em vez disso, ele grava os dados que recebe o mais rápido possível.

Coletores de mídia expõem a interface IMFMediaSink . Cada coletor de mídia contém um ou mais coletores de fluxo. Cada coletor de fluxo recebe os dados de um fluxo. Coletores de fluxo expõem a interface IMFStreamSink . Normalmente, um aplicativo não cria coletores de mídia diretamente. Em vez disso, o aplicativo cria um ou mais objetos de ativação, que a Sessão de Mídia usa para criar o coletor. Todas as outras operações no coletor são tratadas pela Sessão de Mídia e o aplicativo não chama nenhum método no coletor de mídia ou em nenhum dos coletores de fluxo. Para obter mais informações sobre objetos de ativação, consulte Objetos de ativação.

Você deve ler o restante deste tópico se estiver escrevendo um coletor de mídia personalizado ou se quiser usar um coletor de mídia diretamente sem a Sessão de Mídia.

Coletores de fluxo

Um coletor de mídia pode ter um número fixo de coletores de fluxo ou pode dar suporte à adição e remoção de coletores de fluxo. Se ele tiver um número fixo de coletores de fluxo, o método IMFMediaSink::GetCharacteristics retornará o sinalizador MEDIASINK_FIXED_STREAMS. Caso contrário, você pode adicionar e remover coletores de fluxo. Para adicionar um novo coletor de fluxo, chame IMFMediaSink::AddStreamSink. Para remover um coletor de fluxo, chame IMFMediaSink::RemoveStreamSink. O sinalizador MEDIASINK_FIXED_STREAMS indica que o coletor de mídia não dá suporte a esses dois métodos. (Ele pode dar suporte a alguma outra maneira de configurar o número de fluxos, por exemplo, definindo parâmetros de inicialização quando o coletor é criado.) A lista de coletores de fluxo é ordenada. Para enumerá-los por valor de índice, chame o método IMFMediaSink::GetStreamSinkByIndex .

Os coletores de fluxo também têm identificadores. Os identificadores de fluxo são exclusivos no coletor de mídia, mas não precisam ser consecutivos. Dependendo do coletor de mídia, os identificadores de fluxo podem ter algum significado relacionado ao conteúdo. Por exemplo, um coletor de arquivos pode gravar os identificadores de fluxo no cabeçalho do arquivo. Caso contrário, eles são arbitrários. Para obter um coletor de fluxo por seu identificador, chame IMFMediaSink::GetStreamSinkById.

Relógio de Apresentação

A taxa na qual um coletor de mídia consome amostras é controlada pelo Relógio de Apresentação. A Sessão de Mídia seleciona o relógio da apresentação e o define no coletor de mídia chamando o método IMFMediaSink::SetPresentationClock do coletor de mídia. O relógio de apresentação deve ser definido no coletor de mídia antes que o streaming possa começar. Cada coletor de mídia requer um relógio de apresentação para ser executado. O coletor de mídia usa o relógio de apresentação para duas finalidades:

  • Para receber notificações quando o streaming é iniciado ou interrompido. O coletor de mídia recebe essas notificações por meio da interface IMFClockStateSink , que todos os coletores de mídia devem implementar.

  • Para determinar quando ele deve renderizar amostras. Quando o coletor de mídia recebe um novo exemplo, ele obtém o carimbo de data/hora da amostra e tenta renderizar o exemplo nesse momento da apresentação.

O relógio de apresentação deriva seus horários de relógio de outro objeto chamado de origem de hora da apresentação. As fontes de tempo de apresentação expõem a interface IMFPresentationTimeSource . Alguns coletores de mídia têm acesso a um relógio preciso, portanto, expõem essa interface. Isso significa que um coletor de mídia pode agendar amostras em relação a um tempo fornecido pelo próprio relógio. No entanto, o coletor de mídia não pode assumir que esse seja o caso. Ele sempre deve usar o tempo do relógio de apresentação, independentemente de o relógio de apresentação ser controlado pelo próprio coletor de mídia ou por algum outro relógio.

Se um coletor de mídia não puder corresponder a taxas com um relógio diferente do seu, o método GetCharacteristics retornará o sinalizador MEDIASINK_CANNOT_MATCH_CLOCK. Se esse sinalizador estiver presente e o relógio de apresentação usar uma fonte de tempo de apresentação diferente, o coletor de mídia provavelmente terá um desempenho ruim. Por exemplo, ele pode ocorrer uma falha durante a reprodução.

Um coletor sem taxa é um coletor de mídia que ignora os carimbos de data/hora em exemplos e consome dados assim que cada amostra chega. Um coletor de mídia sem taxa retorna o sinalizador MEDIASINK_RATELESS do método GetCharacteristics . Normalmente, esse sinalizador se aplica a coletores de arquivos. Se cada coletor de mídia no pipeline for sem taxa, a Sessão de Mídia usará um relógio de apresentação sem taxa especial. Esse relógio é executado tão rapidamente quanto os coletores consomem amostras.

Formatos de fluxo

Antes que o coletor de mídia possa receber amostras, o cliente deve definir o tipo de mídia nos coletores de fluxo. Para definir o tipo de mídia, chame o método IMFStreamSink::GetMediaTypeHandler do coletor de fluxo. Esse método retorna um ponteiro para a interface IMFMediaTypeHandler . Use essa interface para obter a lista de tipos de mídia preferenciais, obter o tipo de mídia atual e definir o tipo de mídia.

Para obter a lista de tipos de mídia preferenciais, chame IMFMediaTypeHandler::GetMediaTypeByIndex. Os tipos preferenciais devem ser usados como uma dica para o cliente. A lista pode estar incompleta ou incluir tipos de mídia parciais. Um tipo de mídia parcial é aquele que não tem todos os atributos necessários para descrever um formato válido. Por exemplo, um tipo de vídeo parcial pode especificar o espaço de cor e a profundidade do bit, mas não a largura ou altura da imagem. Um tipo de áudio parcial pode especificar o formato de compactação e a taxa de exemplo, mas não o número de canais de áudio.

Para obter o tipo de mídia atual do coletor de fluxo, chame IMFMediaTypeHandler::GetCurrentMediaType. Quando um coletor de fluxo é criado pela primeira vez, ele pode ter um tipo de mídia padrão já definido ou pode não ter nenhum tipo de mídia até que o cliente defina um.

Para definir o tipo de mídia, chame IMFMediaTypeHandler::SetCurrentMediaType. Alguns coletores de fluxo podem não dar suporte à alteração do tipo depois que for definido. Portanto, é útil testar tipos de mídia antes de defini-los. Para testar se o coletor de mídia aceitará um tipo de mídia, (sem definir o tipo), chame IMFMediaTypeHandler::IsMediaTypeSupported.

Fluxo de Dados

Os coletores de mídia usam um modelo de pull, o que significa que os coletores de fluxo solicitam dados conforme precisam. O cliente deve responder em tempo hábil para evitar falhas.

Alguns coletores de mídia dão suporte ao pré-registro. Pré-registro é o processo de fornecer dados ao coletor de mídia antes do início do relógio de apresentação. Se um coletor de mídia der suporte ao pré-registro, o coletor de mídia exporá a interface IMFMediaSinkPreroll e o método GetCharacteristics retornará o sinalizador MEDIASINK_CAN_PREROLL. O pré-registro garante que o coletor de mídia esteja pronto para apresentar o primeiro exemplo quando o relógio de apresentação for iniciado. É recomendável que o cliente sempre faça o pré-registro se o coletor de mídia der suporte a ele, pois ele pode evitar falhas ou lacunas durante a reprodução.

O fluxo de dados para um coletor de mídia funciona da seguinte maneira:

  1. O cliente define os tipos de mídia e o relógio de apresentação. O coletor de mídia registra-se com o relógio de apresentação para receber notificações sobre alterações de estado do relógio.
  2. Opcionalmente, as consultas de cliente para IMFMediaSinkPreroll. Se o coletor de mídia expor essa interface, o cliente chamará IMFMediaSinkPreroll::NotifyPreroll. Caso contrário, o cliente pulará para a etapa 5.
  3. Cada coletor de fluxo envia um ou mais eventos MEStreamSinkRequestSample . Em resposta a cada um desses eventos, o cliente obtém a próxima amostra de dados desse fluxo e chama IMFStreamSink::P rocessSample.
  4. Quando cada coletor de fluxo recebe dados de pré-registro suficientes, ele envia um evento MEStreamSinkPrerolled .
  5. O cliente chama IMFPresentationClock::Start para iniciar o relógio de apresentação.
  6. O relógio de apresentação notifica o coletor de mídia de que o relógio está começando chamando IMFClockStateSink::OnClockStart.
  7. Para obter mais dados, cada coletor de fluxo envia eventos MEStreamSinkRequestSample . Em resposta a cada um desses eventos, o cliente obtém o próximo exemplo e chama ProcessSample. Esta etapa é repetida até que a apresentação termine.

A maioria dos coletores de mídia processa amostras de forma assíncrona, para que os coletores de fluxo possam enviar mais de uma solicitação de exemplo por vez.

Durante o streaming, o cliente pode chamar IMFStreamSink::P laceMarker e IMFStreamSink::Flush a qualquer momento. Os marcadores são descritos na próxima seção. A liberação faz com que o coletor de fluxo solte todos os exemplos que ele enfileiraram, mas ainda não foram renderizados.

Marcadores

Os marcadores fornecem uma maneira de o cliente indicar pontos específicos no fluxo. Um marcador consiste nas seguintes informações:

  • O tipo de marcador, definido como um membro da enumeração MFSTREAMSINK_MARKER_TYPE .
  • Dados associados ao marcador. O significado dos dados depende do tipo de marcador. Alguns tipos de marcadores não têm dados.
  • Dados opcionais para uso próprio do cliente.

Para colocar um marcador, o cliente chama IMFStreamSink::P laceMarker. O coletor de fluxo conclui o processamento de todos os exemplos recebidos antes da chamada do PlaceMarker e envia um evento MEStreamSinkMarker .

A maioria dos coletores de mídia mantém uma fila de exemplos pendentes, que processam de forma assíncrona. Os eventos de marcador devem ser serializados com processamento de exemplo, portanto, o coletor de mídia deve colocar os marcadores na mesma fila. Por exemplo, suponha que o cliente faça as seguintes chamadas de método:

  1. ProcessSample (exemplo nº 1)
  2. ProcessSample (exemplo nº 2)
  3. PlaceMarker (Marcador nº 1)
  4. ProcessSample (exemplo nº 3)
  5. PlaceMarker (Marcador nº 2)

Neste exemplo, o coletor de fluxo deve enviar o evento MEStreamSinkMarker para o marcador nº 1 depois de processar o exemplo nº 2 e o evento para o marcador nº 2 depois de processar o exemplo nº 3.

Se o cliente liberar um coletor de fluxo, o coletor de fluxo processará imediatamente os marcadores que estavam na fila. Ele define o código status para E_ABORT nesses eventos.

Alguns marcadores contêm informações relevantes para o coletor de mídia:

  • MFSTREAMSINK_MARKER_TICK: indica que há uma lacuna no fluxo. O próximo exemplo será uma descontinuidade.
  • MFSTREAMSINK_MARKER_ENDOFSEGMENT: indica o final de um segmento ou o final de um fluxo. O próximo exemplo (se houver) pode ser uma descontinuidade.
  • MFSTREAMSINK_MARKER_EVENT: contém um evento. Dependendo do tipo de evento e da implementação do coletor de mídia, o coletor de mídia pode manipular o evento ou ignorá-lo.

Alterações de estado

Um coletor de mídia é notificado sobre as alterações de estado no relógio de apresentação por meio da interface IMFClockStateSink do coletor de mídia. Quando o cliente define o relógio de apresentação, o coletor de mídia chama IMFPresentationClock::AddClockStateSink para se registrar para notificações do relógio. A tabela a seguir resume como um coletor de mídia se comporta em resposta às alterações de estado do relógio.

Alteração de estado do relógio Processamento de exemplo Processamento de marcador
OnClockStart Processe exemplos cujo carimbo de data/hora seja igual ou posterior à hora de início do relógio. Envie o evento MEStreamSinkMarker quando todos os exemplos recebidos antes do marcador serem processados.
OnClockPause O coletor de mídia pode falhar em ProcessSample enquanto está em pausa.
Se o coletor de mídia aceitar amostras enquanto estiver em pausa, ele deverá enfileirar até que o relógio seja reiniciado. Não processe nenhum exemplo na fila enquanto estiver em pausa.
Se houver exemplos enfileirados, coloque marcadores na mesma fila. Envie o evento de marcador quando o relógio for reiniciado.
Caso contrário, envie o evento de marcador imediatamente.
OnClockRestart Processe todos os exemplos que foram enfileirados durante a pausa e, em seguida, trate o mesmo que OnClockStart. Envie eventos MEStreamSinkMarker para marcadores enfileirados (serializados com processamento de exemplo) e, em seguida, trate o mesmo que OnClockStart.
OnClockStop Remova todos os exemplos na fila. Outras chamadas para ProcessSample podem falhar. Enviar eventos de marcador na fila. Em chamadas subsequentes para PlaceMarker, envie o evento de marcador imediatamente.

 

Além disso, os coletores de fluxo devem enviar os seguintes eventos quando tiverem concluído as transições de estado:

Finalização

Alguns coletores de mídia exigem uma etapa de processamento extra após a entrega da última amostra. Normalmente, esse requisito se aplica a coletores de arquivos, que devem gravar cabeçalhos ou índices no arquivo. Se um coletor de mídia exigir qualquer processamento final, ele exporá a interface IMFFinalizableMediaSink .

Depois que o cliente entrega o último exemplo, o cliente consulta essa interface. Se o coletor de mídia der suporte à interface, o cliente chamará IMFFinalizableMediaSink::BeginFinalize para executar o processamento final de forma assíncrona. Esse método segue o modelo assíncrono padrão do Media Foundation, descrito em Métodos de Retorno de Chamada Assíncronos. O coletor de mídia pode assumir que o cliente chamará BeginFinalize. A falha ao chamar BeginFinalize pode resultar em um arquivo criado incorretamente.

Desligar

Quando o cliente terminar de usar o coletor de mídia, o cliente chamará IMFMediaSink::Shutdown. Dentro desse método, o coletor de mídia deve interromper qualquer contagem de referência circular. Normalmente, haverá referências circulares entre o coletor de mídia e os coletores de fluxo.

Se você estiver usando o objeto auxiliar da fila de eventos para implementar IMFMediaEventGenerator, chame IMFMediaEventQueue::Shutdown na fila de eventos. Esse método desliga a fila de eventos e sinaliza qualquer chamador que esteja aguardando um evento no momento.

Após o desligamento, todos os métodos no coletor de mídia retornam MF_E_SHUTDOWN, com exceção dos métodos IUnknown .

Interfaces do Coletor de Mídia

A tabela a seguir lista as interfaces padrão que os coletores de mídia podem expor por meio de QueryInterface. Coletores de mídia também podem expor interfaces personalizadas.

Interface Descrição
IMFMediaSink A interface primária para coletores de mídia. (Obrigatório.)
IMFClockStateSink Usado para notificar o coletor de mídia quando o relógio de apresentação altera o estado. (Obrigatório.)
IMFFinalizableMediaSink Implemente se o coletor de mídia precisar executar uma etapa de processamento final. (Opcional).
IMFGetService Implemente se o coletor de mídia expor qualquer interface de serviço. (Opcional).
IMFMediaEventGenerator Implemente se o coletor de mídia enviar eventos. (Opcional).
IMFMediaSinkPreroll Implemente se o coletor de mídia der suporte ao pré-registro. (Opcional).
IMFPresentationTimeSource Implemente se o coletor de mídia puder fornecer uma fonte de tempo para o relógio de apresentação. (Opcional).
IMFQualityAdvise Implemente se o coletor de mídia puder ajustar a qualidade da reprodução. (Opcional).

 

Opcionalmente, um coletor de mídia pode implementar a interface como serviço a seguir.

Interface de serviço Descrição
IMFRateSupport Relata o intervalo de taxas de reprodução com suporte.

 

Para obter mais informações sobre interfaces de serviço e IMFGetService, consulte Interfaces de serviço.

Interfaces do coletor de fluxo

Os coletores de fluxo devem expor as interfaces a seguir por meio de QueryInterface.

Interface Descrição
IMFStreamSink A interface primária para coletores de fluxo. (Obrigatório.)
IMFMediaEventGenerator Enfileira eventos. A interface IMFStreamSink herda essa interface. (Obrigatório.)

 

Atualmente, nenhuma interface de serviço é definida para coletores de fluxo.

Eventos do coletor de fluxo

A tabela a seguir lista os eventos definidos para coletores de fluxo genéricos. Os coletores de fluxo também podem enviar eventos personalizados não listados aqui.

Evento Descrição
MEStreamSinkFormatChanged O tipo de mídia do coletor de fluxo não é mais válido. (Opcional).
MEStreamSinkMarker Um marcador foi processado. (Obrigatório.)
MEStreamSinkPaused O coletor de fluxo foi pausado. (Obrigatório.)
MEStreamSinkPrerolled O pré-registro foi concluído. (Opcional).
MEStreamSinkRateChanged O coletor de fluxo alterou a taxa de reprodução. (Opcional).
MEStreamSinkRequestSample Uma nova amostra é solicitada. (Obrigatório.)
MEStreamSinkScrubSampleComplete Uma solicitação de limpeza foi concluída. (Opcional).
MEStreamSinkStarted O coletor de fluxo foi iniciado. (Obrigatório.)
MEStreamSinkStopped O coletor de fluxo parou. (Obrigatório.)

 

Atualmente, nenhum evento de uso geral é definido para coletores de mídia. Alguns coletores de mídia podem enviar eventos personalizados.

Media Foundation Pipeline

Arquitetura Media Foundation