Estados de filtro

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

Los filtros tienen tres estados posibles: detenidos, en pausa y en ejecución. El propósito del estado en pausa es indicar los datos en el grafo, de modo que un comando de ejecución responda inmediatamente. Filter Graph Manager controla todas las transiciones de estado. Cuando una aplicación llama a IMediaControl::Run, IMediaControl::P ause o IMediaControl::Stop, el Administrador de gráficos de filtros llama al método IMediaFilter correspondiente en todos los filtros. Las transiciones entre detenidas y en ejecución siempre pasan por el estado en pausa, por lo que si la aplicación llama a Ejecutar en un gráfico detenido, el Administrador de gráficos de filtros pausa el gráfico antes de ejecutarlo.

Para la mayoría de los filtros, los estados en ejecución y en pausa son idénticos. Tenga en cuenta el siguiente gráfico de filtros:

Representador de transformación de >> origen

Supongamos por ahora que el filtro de origen no es un origen de captura activa. Cuando el filtro de origen se pausa, crea un subproceso que genera nuevos datos y lo escribe en muestras multimedia lo antes posible. El subproceso "inserta" los ejemplos de bajada llamando a IMemInputPin::Receive en el pin de entrada del filtro de transformación. El filtro de transformación recibe los ejemplos en el subproceso del filtro de origen. Puede usar un subproceso de trabajo para entregar los ejemplos al representador, pero normalmente los entrega en el mismo subproceso. Mientras el representador está en pausa, espera a recibir un ejemplo. Después de recibir uno, bloquea y mantiene esa muestra indefinidamente. Si es un representador de vídeo, muestra el ejemplo como una imagen de póster y vuelve a dibujar la imagen según sea necesario.

En este momento, la secuencia está totalmente cued y lista para su representación. Si el gráfico permanece en pausa, los ejemplos se "acumulan" en el gráfico detrás del primer ejemplo, hasta que se bloquee cada filtro en Receive o IMemAllocator::GetBuffer. Sin embargo, no se pierde ningún dato. Una vez desbloqueado el subproceso de origen, simplemente se reanuda desde el punto donde se bloqueó.

El filtro de origen y el filtro de transformación omiten la transición de pausa a en ejecución; simplemente continúan procesando los datos lo más rápido posible. Pero cuando se ejecuta el representador, comienza a representar ejemplos. En primer lugar, representa la muestra que tenía mientras estaba en pausa. A continuación, cada vez que recibe un nuevo ejemplo, calcula el tiempo de presentación del ejemplo. (Para obtener más información, consulte Hora y relojes en DirectShow). El representador contiene cada ejemplo hasta el momento de la presentación, en cuyo momento representa el ejemplo. Mientras espera el tiempo de presentación, se bloquea en el método Receive o recibe nuevos ejemplos en un subproceso de trabajo con una cola. Los filtros ascendentes del representador no intervienen en la programación.

Los orígenes activos, como los dispositivos de captura, son una excepción a esta arquitectura general. Con un origen activo, no es adecuado indicar los datos de antemano. La aplicación puede pausar el gráfico y esperar mucho tiempo antes de ejecutarlo. El gráfico no debe representar ejemplos "obsoletos". Por lo tanto, un origen activo no genera ninguna muestra mientras está en pausa, solo mientras se ejecuta. Para indicar este hecho al Administrador de gráficos de filtros, el método IMediaFilter::GetState del filtro de origen devuelve VFW_S_CANT_CUE. Este código de retorno indica que el filtro ha cambiado al estado en pausa, aunque el representador no haya recibido ningún dato.

Cuando se detiene un filtro, rechaza más muestras que se le entregan. Los filtros de origen apagan sus subprocesos de streaming y otros filtros apagan los subprocesos de trabajo que puedan haber creado. Pins descommiten sus asignadores.

Transiciones de estado

El Administrador de gráficos de filtros lleva a cabo todas las transiciones de estado en orden ascendente, empezando desde el representador y trabajando hacia atrás hasta el filtro de origen. Esta ordenación es necesaria para evitar que se quiten muestras y para evitar que el grafo se interbloquee. Las transiciones de estado más cruciales están entre pausadas y detenidas:

  • Detenido en pausa: a medida que cada filtro se detiene, está listo para recibir muestras del siguiente filtro. El filtro de origen es el último que se va a pausar. Crea el subproceso de streaming y comienza a entregar ejemplos. Dado que todos los filtros de bajada están en pausa, ningún filtro rechaza ninguna muestra. El Administrador de gráficos de filtros no completa la transición hasta que cada representador del grafo haya recibido una muestra (con la excepción de los orígenes activos, como se ha descrito anteriormente).
  • Pausado para detenido: cuando se detiene un filtro, libera los ejemplos que contiene, lo que desbloquea los filtros ascendentes que esperan en GetBuffer. Si el filtro está esperando un recurso dentro del método Receive , deja de esperar y vuelve de Receive, que desbloquea el filtro de llamada. Por lo tanto, cuando el Administrador de gráficos de filtros detiene el siguiente filtro ascendente, ese filtro no está bloqueado en GetBuffer o Receive, y puede responder al comando stop. El filtro ascendente puede entregar algunas muestras adicionales antes de obtener el comando stop, pero el filtro de bajada simplemente los rechaza, ya que ya se ha detenido.

Data Flow en el gráfico de filtros