Entrega de ejemplos

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

En este artículo se describe cómo un filtro entrega un ejemplo. Describe el modelo de inserción, mediante métodos IMemInputPin y el modelo de extracción, mediante IAsyncReader.

Modelo de inserción: entrega de un ejemplo

El pin de salida entrega un ejemplo llamando al método IMemInputPin::Receive o al método IMemInputPin::ReceiveMultiple , que es equivalente pero entrega una matriz de ejemplos. El pin de entrada puede bloquearse dentro de Receive (o ReceiveMultiple). Si el pin puede bloquearse, su método IMemInputPin::ReceiveCanBlock debe devolver S_OK. Si el pin garantiza que nunca se bloquee, ReceiveCanBlock debe devolver S_FALSE. El valor devuelto S_OK no significa que Receive siempre se bloquee, solo que podría.

Aunque Receive puede bloquear para esperar a que un recurso esté disponible, no debe bloquearse para esperar a que se produzcan más datos del filtro ascendente. Si lo hace, puede provocar un interbloqueo en el que el filtro ascendente espera a que el filtro de nivel inferior libere la muestra, lo que nunca sucede porque el filtro de nivel inferior está esperando en el filtro ascendente. Sin embargo, si un filtro tiene varios pines de entrada, un pin puede esperar a que otro pin reciba datos. Por ejemplo, el filtro Avi Mux lo hace para que pueda intercalar datos de audio y vídeo.

Un pin puede rechazar una muestra por varias razones:

  • El pin está vaciado (consulte Vaciado).
  • El pin no está conectado.
  • El filtro se detiene.
  • Se produjo otro error.

El método Receive debe devolver S_FALSE en el primer caso y un código de error en los demás casos. El filtro ascendente debe dejar de enviar muestras cuando el código de retorno no sea S_OK.

Puede considerar que los tres primeros casos son errores "esperados", en el sentido de que el filtro estaba en estado incorrecto para recibir muestras. Un error inesperado sería uno que hace que el pin rechace una muestra aunque el pin esté en estado de recepción. Si se produce un error de este tipo, el pin debe enviar una notificación de fin de secuencia de bajada y enviar un evento de EC_ERRORABORT al Administrador de gráficos de filtros.

En las clases base de DirectShow, el método CBaseInputPin::CheckStreaming comprueba si hay casos de error generales: vaciado, detenido, etc. La clase derivada deberá comprobar si hay errores específicos del filtro. En caso de error, el método CBaseInputPin::Receive envía la notificación de fin de secuencia y el evento EC_ERRORABORT.

Modelo de extracción: solicitud de un ejemplo

En la interfaz IAsyncReader , el pin de entrada solicita ejemplos del pin de salida llamando a uno de los métodos siguientes:

El método Request es asincrónico; El pin de entrada llama a IAsyncReader::WaitForNext para esperar a que se complete la solicitud. Los otros dos métodos son sincrónicos.

Cuándo entregar datos

Un filtro siempre entrega muestras mientras se encuentra en estado de ejecución. En la mayoría de los casos, un filtro también entrega muestras mientras está en pausa. Esto permite que el gráfico indique los datos para que la reproducción se inicie inmediatamente cuando se llame a Run (consulte Estados de filtro). Si el filtro no entrega datos mientras está en pausa, el método IMediaFilter::GetState del filtro debe devolver VFW_S_CANT_CUE en estado en pausa. Este código de retorno indica que el gráfico de filtros no espere a que los datos del filtro finalicen la transición de pausa. De lo contrario, el método Pause se bloqueará indefinidamente. Para obtener código de ejemplo, vea CBaseFilter::GetState.

Estos son algunos ejemplos de cuándo es posible que un filtro necesite devolver VFW_S_CANT_CUE:

  • Los orígenes activos, como los filtros de captura, no deben enviar datos mientras están en pausa. Consulte Generar datos en un filtro de captura.
  • Un filtro divisor podría o no enviar datos mientras estaba en pausa, en función de la implementación. Si el filtro usa subprocesos independientes para poner en cola datos en cada patilla de salida, puede enviar datos mientras están en pausa. Pero si el filtro usa un único subproceso para cada patilla de salida, el primer pin podría bloquear el subproceso cuando llama a Receive, lo que impedirá que los otros patillas envíen datos. En ese caso, debe devolver VFW_S_CANT_CUE.
  • Un filtro puede entregar datos esporádicamente. Por ejemplo, podría analizar un flujo de datos personalizado y filtrar algunos paquetes al entregar otros. En ese caso, es posible que no se garantice que el filtro entregue datos mientras está en pausa.

Un filtro de origen (mediante el modelo de inserción) o un filtro de analizador (mediante el modelo de inserción y extracción) crea uno o varios subprocesos de streaming, que entregan muestras lo antes posible. Los filtros de bajada, como los descodificadores y las transformaciones, normalmente envían datos solo cuando se llama a Receive en sus patillas de entrada.

Recepción y entrega de ejemplos