Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
[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.]
Quando um pino entrega dados de mídia para outro pino, ele não passa um ponteiro direto para o buffer de memória. Em vez disso, ele fornece um ponteiro para um objeto COM que gerencia a memória. Este objeto, chamado exemplo de mídia, expõe a interface IMediaSample. O pino recetor acessa o buffer de memória chamando métodos IMediaSample, como IMediaSample::GetPointer, IMediaSample::GetSizee IMediaSample::GetActualDataLength.
As amostras viajam sempre a jusante, desde o pino de saída até ao pino de entrada. No modelo push, o pino de saída entrega uma amostra chamando IMemInputPin::Receive no pino de entrada. O pino de entrada processará os dados de forma síncrona (ou seja, completamente dentro do método Receive) ou os processará de forma assíncrona em um thread de trabalho. É permitido que o pino de entrada bloqueie dentro do método Receive, caso precise aguardar por recursos.
Outro objeto COM, chamado alocador , é responsável pela criação e gestão de amostras de mídia. Os alocadores expõem a interface IMemAllocator. Sempre que um filtro precisa de uma amostra de mídia com um buffer vazio, ele chama o método IMemAllocator::GetBuffer, que retorna um ponteiro para a amostra. Cada conexão de pino compartilha um alocador. Quando dois pinos se conectam, eles decidem qual filtro irá fornecer o alocador. Os pinos definem também propriedades no alocador, tal como o número de buffers e o tamanho de cada buffer. (Para obter detalhes, consulte Como os filtros se conectam e negociando alocadores.)
A ilustração a seguir mostra as relações entre o alocador, as amostras de mídia e o filtro.
Contagem de referência de amostra de mídia
Um alocador cria um pool finito de amostras. A qualquer momento, algumas amostras podem estar em uso, enquanto outras estão disponíveis para chamadas GetBuffer. O alocador usa a contagem de referência para acompanhar as amostras. O método GetBuffer retorna um exemplo com uma contagem de referência de 1. Se a contagem de referência for zero, a amostra voltará para o pool do alocador, onde poderá ser usada na próxima chamada GetBuffer. Enquanto a contagem de referência permanecer acima de zero, a amostra não estará disponível para GetBuffer. Se cada amostra pertencente ao alocador estiver em uso, o método GetBuffer bloqueará até que uma amostra fique disponível.
Por exemplo, suponha que um pino de entrada receba uma amostra. Se ele processar a amostra de forma síncrona, dentro do método Receive, ele não incrementará a contagem de referência. Depois que Receber retorna, o pino de saída libera a amostra, a contagem de referência vai para zero e a amostra retorna ao pool do alocador. Por outro lado, se o pino de entrada processar a amostra em um thread de trabalho, ele incrementará a contagem de referência antes de sair do método Receive. A contagem de referência é agora 2. Quando o pino de saída libera a amostra, a contagem vai para 1; a amostra ainda não regressa à piscina. Depois de o thread de trabalhador concluir o processamento do exemplo, invoca Release para libertar o exemplo. Agora, a amostra retorna ao pool.
Quando um pino recebe uma amostra, ele pode copiar os dados para outra amostra ou pode modificar a amostra original e entregá-la ao próximo filtro. Potencialmente, uma amostra pode percorrer todo o comprimento do gráfico, com cada filtro chamando AddRef e Release sucessivamente. Portanto, o pino de saída nunca deve reutilizar uma amostra depois de chamar Receber, porque um filtro a seguir pode estar a utilizar a amostra. O pino de saída deve sempre chamar GetBuffer para obter uma nova amostra.
Esse mecanismo reduz a quantidade de alocação de memória, porque os filtros reutilizam os mesmos buffers. Também impede que os filtros gravem acidentalmente sobre dados que não foram processados, porque o alocador mantém uma lista de amostras disponíveis.
Um filtro pode usar alocadores separados para entrada e saída. Ele pode fazer isso se expandir os dados de entrada (por exemplo, descompactando-os). Se a saída não for maior do que a entrada, um filtro poderá processar os dados no local, sem copiá-los para uma nova amostra. Nesse caso, duas ou mais conexões de pinos podem compartilhar um alocador.
Cometer e desautorizar alocadores
Quando um filtro cria um alocador pela primeira vez, o alocador não reservou nenhum buffer de memória. Neste ponto, todas as chamadas para o GetBuffer método falharão. Quando o streaming é iniciado, o pino de saída chama IMemAllocator::Commit, que confirma o alocador, fazendo com que ele aloque memória. Os Pins agora podem chamar GetBuffer.
Quando o streaming é interrompido, o pino chama IMemAllocator::Decommit, que descomita o alocador. Todas as chamadas subsequentes para GetBuffer falham até que o alocador esteja comprometido novamente. Além disso, se alguma chamada para GetBuffer estiver bloqueada no momento aguardando um exemplo, ela retornará imediatamente um código de falha. O método Decommit pode ou não liberar a memória, dependendo da implementação. Por exemplo, a classe CMemAllocator aguarda até o seu método destrutor para liberar memória.
Tópicos relacionados