Fornecendo exemplos
[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in 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.]
Este artigo descreve como um filtro fornece um exemplo. Ele descreve o modelo de push, usando métodos IMemInputPin e o modelo de pull, usando IAsyncReader.
Modelo de push: fornecendo um exemplo
O pin de saída fornece um exemplo chamando o método IMemInputPin::Receive ou o método IMemInputPin::ReceiveMultiple , que é equivalente, mas fornece uma matriz de exemplos. O pino de entrada pode ser bloqueado dentro de Receive (ou ReceiveMultiple). Se o pino puder ser bloqueado, seu método IMemInputPin::ReceiveCanBlock deverá retornar S_OK. Se o pin garantir que nunca será bloqueado, ReceiveCanBlock deverá retornar S_FALSE. O valor retornado S_OK não significa que Receive sempre bloqueia, apenas que ele pode.
Embora Receive possa bloquear para aguardar a disponibilização de um recurso, ele não deve bloquear a espera por mais dados do filtro upstream. Isso pode causar um deadlock em que o filtro de upstream aguarda o filtro downstream liberar o exemplo, o que nunca acontece porque o filtro downstream está aguardando o filtro upstream. No entanto, se um filtro tiver vários pinos de entrada, um pino poderá aguardar até que outro pino receba dados. Por exemplo, o filtro AVI Mux faz isso para que possa intercalar dados de áudio e vídeo.
Um pin pode rejeitar um exemplo por vários motivos:
- O pino está sendo liberado (consulte Liberação).
- O pino não está conectado.
- O filtro é interrompido.
- Ocorreu algum outro erro.
O método Receive deve retornar S_FALSE no primeiro caso e um código de falha nos outros casos. O filtro de upstream deve parar de enviar amostras quando o código de retorno não for S_OK.
Você pode considerar os três primeiros casos como falhas "esperadas", no sentido de que o filtro estava no estado errado para receber amostras. Uma falha inesperada seria aquela que faz com que o pino rejeite uma amostra, mesmo que o pino esteja em um estado de recebimento. Se ocorrer um erro desse tipo, o pino deverá enviar uma notificação de fim de fluxo downstream e enviar um evento EC_ERRORABORT para o Gerenciador de Gráficos de Filtro.
Nas classes base do DirectShow, o método CBaseInputPin::CheckStreaming verifica se há casos de falha gerais– liberação, parada e assim por diante. A classe derivada precisará marcar para falhas específicas do filtro. Em caso de erro, o método CBaseInputPin::Receive envia a notificação de fim de fluxo e o evento EC_ERRORABORT.
Modelo de pull: solicitando um exemplo
Na interface IAsyncReader , o pin de entrada solicita exemplos do pino de saída chamando um dos seguintes métodos:
O método Request é assíncrono; o pin de entrada chama IAsyncReader::WaitForNext para aguardar a conclusão da solicitação. Os outros dois métodos são síncronos.
Quando entregar dados
Um filtro sempre fornece exemplos enquanto está no estado em execução. Na maioria dos casos, um filtro também fornece amostras enquanto está em pausa. Isso permite que o grafo indira os dados para que a reprodução seja iniciada imediatamente quando a execução for chamada (consulte Estados de filtro). Se o filtro não fornecer dados enquanto estiver em pausa, o método IMediaFilter::GetState do filtro deverá retornar VFW_S_CANT_CUE no estado pausado. Esse código de retorno sinaliza que o grafo de filtro não deve aguardar os dados do filtro antes de concluir a transição de pausa. Caso contrário, o método Pause será bloqueado indefinidamente. Para obter um código de exemplo, consulte CBaseFilter::GetState.
Aqui estão alguns exemplos de quando um filtro pode precisar retornar VFW_S_CANT_CUE:
- Fontes dinâmicas, como filtros de captura, não devem enviar dados enquanto estiverem em pausa. Consulte Produzindo dados em um filtro de captura.
- Um filtro de divisor pode ou não enviar dados enquanto está em pausa, dependendo da implementação. Se o filtro usar threads separados para enfileirar dados em cada pino de saída, ele poderá enviar dados enquanto estiver em pausa. Mas se o filtro usar um único thread para cada pino de saída, o primeiro pino poderá bloquear o thread quando ele chamar Receive, o que impedirá que os outros pinos enviem dados. Nesse caso, você deve retornar VFW_S_CANT_CUE.
- Um filtro pode fornecer dados esporadicamente. Por exemplo, ele pode analisar um fluxo de dados personalizado e filtrar alguns pacotes enquanto entrega outros. Nesse caso, talvez não haja garantia de que o filtro forneça dados enquanto estiver em pausa.
Um filtro de origem (usando o modelo de push) ou um filtro de analisador (usando o modelo de push/pull) cria um ou mais threads de streaming, que fornecem amostras o mais rápido possível. Filtros downstream, como decodificadores e transformações, normalmente enviam dados somente quando Receive é chamado em seus pinos de entrada.
Tópicos relacionados