Pipes e circuitos AVStream
Um pipe é um conjunto de filtros AVStream que compartilham um alocador comum.
A ilustração a seguir mostra um pipe composto por três filtros AVStream: um filtro de origem, um filtro de transformação inplace e um filtro de renderizador.
Neste exemplo, KSProxy (não mostrado) escolheu um alocador, representado pelo bloco Alloc no diagrama.
O AVStream cria um objeto solicitante interno associado ao filtro de origem. No diagrama, o solicitante aparece como Req. O minidriver especifica no membro AllocatorFraming de KSPIN_DESCRIPTOR_EX o tipo de memória e a quantidade de memória contínua a serem atribuídas a um quadro. Assim, o solicitante obtém quadros do alocador e os passa para o próximo componente no circuito.
Os dados do filtro de origem fluem para um filtro de transformação implementado por outro driver AVStream.
Por fim, os dados fluem para o filtro do renderizador implementado por um terceiro filtro AVStream.
Como todos os pinos neste grafo são pinos AVStream, o AVStream usa suas próprias interfaces de transporte internas em vez de enviar IRPs por meio de IoCallDriver, reduzindo a latência e melhorando o desempenho.
Especificamente, quando o aplicativo faz com que o grafo faça a transição para KSSTATE_ACQUIRE (por exemplo, quando o usuário clica em Reproduzir no GraphEdit), o AVStream conecta diretamente as filas de filtro, conforme mostrado acima.
Portanto, os quadros enviados downstream retornam ao solicitante, onde podem ser reciclados quando a renderização é concluída. Esse caminho de dados AVStream é um circuito.
Considere um segundo exemplo, mostrado na ilustração abaixo, no qual o filtro de transformação não é um filtro AVStream, mas ainda é um filtro de modo kernel.
Como no primeiro exemplo, este exemplo inclui três filtros: uma origem AVStream, uma transformação KS (pode ser um driver que usa KS diretamente ou um minidriver na classe de fluxo) e um renderizador AVStream.
Como na primeira ilustração, os pinos são interconectados pela primeira vez. No entanto, quando o grafo de filtro faz a transição para KSSTATE_ACQUIRE, o filtro Kernel Streaming 1.0 não dá suporte à interface de transporte AVStream. Como resultado, o AVStream não ignora os pinos; Em vez disso, ele deve usar E/S para mover dados entre filtros.
Especificamente, quando um quadro sai da fila do filtro de origem, o AVStream chama IoCallDriver. Nessa chamada, o parâmetro Irp contém o quadro a ser passado do pino de saída da origem para o filtro de transformação.
Quando o pino de entrada do renderizador recebe o IRP, o pino coloca o IRP na fila. Quando o driver do renderizador conclui um quadro, ele retorna o quadro para o pino de entrada do renderizador, conforme mostrado no segundo exemplo.
O AVStream agora chama IoCompleteRequest para retornar o quadro upstream. O pino de saída do filtro de origem recebe uma notificação de conclusão. A rotina de retorno de chamada do processo de fixação do minidriver pode chamar KsStreamPointerUnlock e mover os quadros de volta para o solicitante para serem reciclados no circuito.
Considere um exemplo final no qual a origem do quadro está no modo de usuário. (Como alternativa, o destino do quadro final pode estar no modo de usuário.)
Na ilustração abaixo, um filtro de transformação não inserção no modo kernel recebe quadros de um filtro DirectShow no modo de usuário e envia o quadro transformado para um renderizador AVStream no modo kernel:
Quando os quadros chegam do modo de usuário, o objeto de pino AVStream os coloca na fila da seção de pipe de entrada.
O filtro de transformação não insubstituível aloca os quadros transformados no modo kernel e, em seguida, usa o segundo pipe como um circuito para esses quadros. Como o renderizador é um filtro AVStream, o AVStream ignora os pinos e usa a interface de transporte AVStream para colocar os quadros diretamente na fila do filtro de renderização.
O minidriver pode injetar quadros no circuito chamando KsPinSubmitFrame ou KsPinSubmitFrameMdl. Se o minidriver usar esse método, o solicitante AVStream receberá quadros como resultado dessas chamadas, em vez de um alocador de modo kernel.