Partilhar via


Estados do filtro

[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.]

Os filtros têm três estados possíveis: parado, pausado e em execução. O objetivo do estado pausado é sinalizar dados no gráfico, para que um comando run responda imediatamente. O Gerenciador de gráficos de filtro controla todas as transições de estado. Quando um aplicativo chama IMediaControl::Run, IMediaControl::P auseou IMediaControl::Stop, o Filter Graph Manager chama o métodoIMediaFilter correspondenteem todos os filtros. As transições entre interrompido e em execução sempre passam pelo estado pausado, portanto, se o aplicativo chamar Executar em um gráfico interrompido, o Gerenciador de Gráficos de Filtro pausará o gráfico antes de executá-lo.

Para a maioria dos filtros, os estados em execução e pausados são idênticos. Considere o seguinte gráfico de filtro:

Fonte > transformar > renderizador

Suponha, por enquanto, que o filtro de origem não é uma fonte de captura em tempo real. Quando o filtro de origem pausa, ele cria um thread que gera novos dados e os grava em amostras de mídia o mais rápido possível. O thread "empurra" as amostras para jusante chamando IMemInputPin::Receive no pino de entrada do filtro de transformação. O filtro de transformação recebe as amostras no thread do filtro de origem. Ele pode usar um thread de trabalho para entregar as amostras ao renderizador, mas normalmente as entrega no mesmo thread. Enquanto o renderizador está pausado, ele aguarda para receber uma amostra. Depois de receber uma, bloqueia e retém essa amostra indefinidamente. Se for um renderizador de vídeo, ele exibe a amostra como uma imagem de pôster, repintando a imagem conforme necessário.

Neste ponto, o fluxo está totalmente sinalizado e pronto para renderização. Se o gráfico permanecer pausado, as amostras "se acumularão" no gráfico atrás da primeira amostra, até que cada filtro seja bloqueado em de recebimento ou IMemAllocator::GetBuffer. No entanto, nenhum dado é perdido. Uma vez que o thread de origem é desbloqueado, ele simplesmente retoma a partir do ponto onde bloqueou.

O filtro de origem e o filtro de transformação ignoram a transição de pausado para execução — eles simplesmente continuam a processar dados o mais rápido possível. Mas quando o renderizador é executado, ele começa a renderizar amostras. Primeiro, ele renderiza a amostra que continha enquanto estava pausada. Em seguida, cada vez que recebe uma nova amostra, calcula o tempo de apresentação da amostra. (Para obter detalhes, consulte Hora e Relógios no DirectShow.) O renderizador mantém cada amostra até o momento da apresentação, momento em que renderiza a amostra. Enquanto aguarda o tempo de apresentação, ele bloqueia no método Receive ou recebe novas amostras em um thread de trabalho com uma fila. Os filtros a montante do renderizador não estão envolvidos no agendamento.

Fontes em tempo real, como dispositivos de captura, são uma exceção a essa arquitetura geral. Com uma fonte ao vivo, não é apropriado indicar quaisquer dados com antecedência. O aplicativo pode pausar o gráfico e, em seguida, esperar por um longo tempo antes de executá-lo. O gráfico não deve renderizar amostras "obsoletas". Portanto, uma fonte ativa não produz amostras enquanto pausada, apenas durante a execução. Para sinalizar esse fato para o Filter Graph Manager, o método IMediaFilter::GetState do filtro de origem retorna VFW_S_CANT_CUE. Esse código de retorno indica que o filtro mudou para o estado pausado, mesmo que o renderizador não tenha recebido nenhum dado.

Quando um filtro para, rejeita mais amostras que lhe sejam entregues. Os filtros de origem desligam seus threads de streaming e outros filtros desligam todos os threads de trabalho que eles possam ter criado. Pins descomprometem seus alocadores.

Transições de Estado

O Filter Graph Manager realiza todas as transições de estado em ordem upstream, começando a partir do renderizador e trabalhando para trás até o filtro de origem. Essa ordenação é necessária para evitar que as amostras sejam descartadas e para evitar que o gráfico fique bloqueado. As transições de estado mais cruciais são entre pausado e interrompido:

  • Interrompido para pausar: À medida que cada filtro pausa, ele fica pronto para receber amostras do próximo filtro. O filtro de origem é o último a pausar. Ele cria o thread de streaming e começa a entregar amostras. Como todos os filtros a jusante estão pausados, nenhum filtro rejeita nenhuma amostra. O Gerenciador de gráficos de filtro não conclui a transição até que cada renderizador no gráfico tenha recebido uma amostra (com exceção de fontes ativas, conforme descrito anteriormente).
  • Pausado para parar: quando um filtro para, ele libera todas as amostras que ele retém, o que desbloqueia todos os filtros upstream aguardando em GetBuffer. Se o filtro estiver aguardando um recurso dentro do métodode recebimento, ele interromperá a espera e retornará de de recebimento , que desbloqueia o filtro de chamada. Portanto, quando o Gerenciador de Gráfico de Filtros para o próximo filtro upstream, esse filtro não é bloqueado no GetBuffer ou Receivee pode responder ao comando stop. O filtro upstream pode fornecer algumas amostras extras antes de receber o comando stop, mas o filtro downstream simplesmente as rejeita, porque já parou.

fluxo de dados no gráfico de filtro