Receptores de medios

Los receptores de medios son los objetos de canalización que reciben datos multimedia. Un receptor de medios es el destino de una o varias secuencias multimedia. Los receptores multimedia se dividen en dos categorías generales:

  • Un representador es un receptor multimedia que presenta datos para la reproducción. El representador de vídeo mejorado (EVR) muestra fotogramas de vídeo y el representador de audio reproduce secuencias de audio a través de la tarjeta de sonido u otro dispositivo de audio.

  • Un receptor de archivo es un receptor multimedia que escribe datos en un archivo u otro almacenamiento.

La principal diferencia entre ellos es que un receptor de archivo no consume los datos a una velocidad de reproducción fija. En su lugar, escribe los datos que recibe lo antes posible.

Los receptores multimedia exponen la interfaz IMFMediaSink . Cada receptor multimedia contiene uno o varios receptores de secuencias. Cada receptor de flujo recibe los datos de una secuencia. Los receptores de flujo exponen la interfaz IMFStreamSink . Normalmente, una aplicación no crea receptores de medios directamente. En su lugar, la aplicación crea uno o varios objetos de activación, que usa la sesión multimedia para crear el receptor. Todas las demás operaciones del receptor se controlan mediante la sesión multimedia y la aplicación no llama a ningún método en el receptor multimedia ni en ninguno de los receptores de secuencia. Para obtener más información sobre los objetos de activación, vea Objetos de activación.

Debe leer el resto de este tema si está escribiendo un receptor de medios personalizado o si desea usar un receptor de medios directamente sin la sesión multimedia.

Receptores de flujos

Un receptor multimedia puede tener un número fijo de receptores de secuencias, o puede admitir la adición y eliminación de receptores de secuencias. Si tiene un número fijo de receptores de flujo, el método IMFMediaSink::GetCharacteristics devuelve la marca MEDIASINK_FIXED_STREAMS. De lo contrario, puede agregar y quitar receptores de flujos. Para agregar un nuevo receptor de secuencias, llame a IMFMediaSink::AddStreamSink. Para quitar un receptor de flujo, llame a IMFMediaSink::RemoveStreamSink. La marca MEDIASINK_FIXED_STREAMS indica que el receptor de medios no admite estos dos métodos. (Es posible que admita alguna otra manera de configurar el número de secuencias, por ejemplo, estableciendo parámetros de inicialización cuando se crea el receptor). Se ordena la lista de receptores de flujo. Para enumerarlos por valor de índice, llame al método IMFMediaSink::GetStreamSinkByIndex .

Los receptores de flujo también tienen identificadores. Los identificadores de flujo son únicos dentro del receptor de medios, pero no tienen que ser consecutivos. Dependiendo del receptor multimedia, los identificadores de flujo pueden tener algún significado relacionado con el contenido. Por ejemplo, un receptor de archivo podría escribir los identificadores de secuencia en el encabezado de archivo. De lo contrario, son arbitrarios. Para obtener un receptor de flujo por su identificador, llame a IMFMediaSink::GetStreamSinkById.

Reloj de presentación

La velocidad a la que un receptor multimedia consume muestras se controla mediante el reloj de presentación. La sesión multimedia selecciona el reloj de presentación y lo establece en el receptor multimedia llamando al método IMFMediaSink::SetPresentationClock del receptor de medios. El reloj de presentación debe establecerse en el receptor multimedia antes de que pueda comenzar el streaming. Cada receptor de medios requiere que se ejecute un reloj de presentación. El receptor de medios usa el reloj de presentación para dos propósitos:

  • Para recibir notificaciones cuando se inicia o detiene el streaming. El receptor de medios recibe estas notificaciones a través de la interfaz IMFClockStateSink , que todos los receptores multimedia deben implementar.

  • Para determinar cuándo debe representar ejemplos. Cuando el receptor de medios recibe un nuevo ejemplo, obtiene la marca de tiempo del ejemplo e intenta representar la muestra en ese momento de presentación.

El reloj de presentación deriva sus horas de reloj de otro objeto denominado origen de hora de presentación. Los orígenes de tiempo de presentación exponen la interfaz IMFPresentationTimeSource . Algunos receptores multimedia tienen acceso a un reloj preciso, por lo que exponen esta interfaz. Esto significa que un receptor de medios puede programar muestras con una hora proporcionada por su propio reloj. Sin embargo, el receptor de medios no puede suponer que esto es el caso. Siempre debe usar la hora del reloj de presentación, independientemente de si el reloj de presentación está controlado por el propio receptor multimedia o por algún otro reloj.

Si un receptor multimedia no puede coincidir con las tasas con un reloj distinto del suyo propio, el método GetCharacteristics devuelve la marca MEDIASINK_CANNOT_MATCH_CLOCK. Si esta marca está presente y el reloj de presentación usa un origen de tiempo de presentación diferente, es probable que el receptor de medios funcione mal. Por ejemplo, podría producirse un error durante la reproducción.

Un receptor sin frecuencia es un receptor multimedia que omite las marcas de tiempo en muestras y consume datos en cuanto llega cada muestra. Un receptor de medios sin velocidad devuelve la marca MEDIASINK_RATELESS del método GetCharacteristics . Normalmente, esta marca se aplica a los receptores de archivo. Si cada receptor de medios de la canalización no tiene velocidad, la sesión multimedia usa un reloj de presentación sin frecuencia especial. Este reloj se ejecuta tan rápidamente como los receptores consumen muestras.

Formatos de secuencia

Para que el receptor de medios pueda recibir muestras, el cliente debe establecer el tipo de medio en los receptores de la secuencia. Para establecer el tipo de medio, llame al método IMFStreamSink::GetMediaTypeHandler del receptor de la secuencia. Este método devuelve un puntero a la interfaz IMFMediaTypeHandler . Use esta interfaz para obtener la lista de tipos multimedia preferidos, obtener el tipo de medio actual y establecer el tipo de medio.

Para obtener la lista de tipos de medios preferidos, llame a IMFMediaTypeHandler::GetMediaTypeByIndex. Los tipos preferidos se deben tomar como sugerencia al cliente. La lista puede estar incompleta o incluir tipos de medios parciales. Un tipo de medio parcial es uno que no tiene todos los atributos necesarios para describir un formato válido. Por ejemplo, un tipo de vídeo parcial podría especificar el espacio de color y la profundidad de bits, pero no el ancho o alto de la imagen. Un tipo de audio parcial puede especificar el formato de compresión y la frecuencia de muestreo, pero no el número de canales de audio.

Para obtener el tipo de medio actual del receptor de la secuencia, llame a IMFMediaTypeHandler::GetCurrentMediaType. Cuando se crea por primera vez un receptor de secuencia, es posible que tenga un tipo de medio predeterminado ya establecido o que no tenga ningún tipo de medio hasta que el cliente establezca uno.

Para establecer el tipo de medio, llame a IMFMediaTypeHandler::SetCurrentMediaType. Es posible que algunos receptores de secuencias no admitan cambiar el tipo después de que se haya establecido. Por lo tanto, resulta útil probar los tipos de medios antes de establecerlos. Para comprobar si el receptor de medios aceptará un tipo de medio(sin establecer el tipo), llame a IMFMediaTypeHandler::IsMediaTypeSupported.

Data Flow

Los receptores multimedia usan un modelo de extracción, lo que significa que los receptores de flujos solicitan datos según lo necesiten. El cliente debe responder de forma oportuna para evitar cualquier brillo.

Algunos receptores multimedia admiten la inscripción previa. La inscripción previa es el proceso de proporcionar datos al receptor multimedia antes de que se inicie el reloj de presentación. Si un receptor de medios admite la inscripción previa, el receptor de medios expone la interfaz IMFMediaSinkPreroll y el método GetCharacteristics devuelve la marca MEDIASINK_CAN_PREROLL. La inscripción previa garantiza que el receptor de medios esté listo para presentar la primera muestra cuando se inicia el reloj de presentación. Se recomienda que el cliente siempre realice la inscripción previa si el receptor de medios lo admite, ya que puede evitar interrupciones o huecos durante la reproducción.

El flujo de datos a un receptor multimedia funciona de la siguiente manera:

  1. El cliente establece los tipos de medios y el reloj de presentación. El receptor de medios se registra con el reloj de presentación para recibir notificaciones sobre los cambios de estado del reloj.
  2. Opcionalmente, el cliente consulta para IMFMediaSinkPreroll. Si el receptor de medios expone esta interfaz, el cliente llama a IMFMediaSinkPreroll::NotifyPreroll. De lo contrario, el cliente pasa al paso 5.
  3. Cada receptor de secuencias envía uno o varios eventos MEStreamSinkRequestSample . En respuesta a cada uno de estos eventos, el cliente obtiene el siguiente ejemplo de datos para esa secuencia y llama a IMFStreamSink::P rocessSample.
  4. Cuando cada receptor de secuencia recibe suficientes datos de inscripción previa, envía un evento MEStreamSinkPrerolled .
  5. El cliente llama a IMFPresentationClock::Start para iniciar el reloj de presentación.
  6. El reloj de presentación notifica al receptor multimedia que el reloj se está iniciando llamando a IMFClockStateSink::OnClockStart.
  7. Para obtener más datos, cada receptor de flujos envía eventos MEStreamSinkRequestSample . En respuesta a cada uno de estos eventos, el cliente obtiene el ejemplo siguiente y llama a ProcessSample. Este paso se repite hasta que finaliza la presentación.

La mayoría de los receptores multimedia procesan muestras de forma asincrónica, por lo que los receptores de flujos pueden enviar más de una solicitud de ejemplo a la vez.

Durante el streaming, el cliente puede llamar a IMFStreamSink::P laceMarker y IMFStreamSink::Flush en cualquier momento. Los marcadores se describen en la sección siguiente. El vaciado hace que el receptor de la secuencia quite los ejemplos que ha puesto en cola, pero aún no se ha representado.

Marcadores

Los marcadores proporcionan una manera para que el cliente indique puntos específicos en la secuencia. Un marcador consta de la siguiente información:

  • Tipo de marcador, definido como miembro de la enumeración MFSTREAMSINK_MARKER_TYPE .
  • Datos asociados al marcador. El significado de los datos depende del tipo de marcador. Algunos tipos de marcador no tienen datos.
  • Datos opcionales para el propio uso del cliente.

Para colocar un marcador, el cliente llama a IMFStreamSink::P laceMarker. El receptor de secuencia termina de procesar los ejemplos que recibió antes de la llamada a PlaceMarker y, a continuación, envía un evento MEStreamSinkMarker .

La mayoría de los receptores multimedia mantienen una cola de muestras pendientes, que procesan de forma asincrónica. Los eventos de marcador deben serializarse con el procesamiento de muestras, por lo que el receptor de medios debe colocar los marcadores en la misma cola. Por ejemplo, supongamos que el cliente realiza las siguientes llamadas de método:

  1. ProcessSample (ejemplo 1)
  2. ProcessSample (ejemplo 2)
  3. PlaceMarker (Marcador n.º 1)
  4. ProcessSample (ejemplo 3)
  5. PlaceMarker (Marcador n.º 2)

En este ejemplo, el receptor de la secuencia debe enviar el evento MEStreamSinkMarker para el marcador n.º 1 después de procesar la muestra n.º 2 y el evento para el marcador n.º 2 después de procesar la muestra 3.

Si el cliente vacía un receptor de flujo, el receptor de la secuencia procesa inmediatamente los marcadores que estaban en la cola. Establece el código de estado en E_ABORT en estos eventos.

Algunos marcadores contienen información relevante para el receptor de medios:

  • MFSTREAMSINK_MARKER_TICK: indica que hay un hueco en la secuencia. El ejemplo siguiente será una discontinuidad.
  • MFSTREAMSINK_MARKER_ENDOFSEGMENT: indica el final de un segmento o el final de una secuencia. El ejemplo siguiente (si existe) podría ser una discontinuidad.
  • MFSTREAMSINK_MARKER_EVENT: contiene un evento. Según el tipo de evento y la implementación del receptor de medios, el receptor de medios puede controlar el evento o ignorarlo.

Cambios de estado

Se notifica a un receptor de medios los cambios de estado en el reloj de presentación a través de la interfaz IMFClockStateSink del receptor de medios. Cuando el cliente establece el reloj de presentación, el receptor de medios llama a IMFPresentationClock::AddClockStateSink para registrarse para recibir notificaciones desde el reloj. En la tabla siguiente se resume cómo se comporta un receptor multimedia en respuesta a los cambios de estado del reloj.

Cambio de estado del reloj Procesamiento de ejemplo Procesamiento de marcadores
OnClockStart Procese muestras cuya marca de tiempo sea igual o posterior a la hora de inicio del reloj. Envíe el evento MEStreamSinkMarker cuando se hayan procesado todas las muestras recibidas antes de procesar el marcador.
OnClockPause El receptor de medios puede producir un error en ProcessSample mientras está en pausa.
Si el receptor de medios acepta muestras mientras está en pausa, debe ponerlas en cola hasta que se reinicie el reloj. No procese ningún ejemplo en cola mientras está en pausa.
Si hay ejemplos en cola, coloque marcadores en la misma cola. Envíe el evento de marcador cuando se reinicie el reloj.
De lo contrario, envíe el evento de marcador inmediatamente.
OnClockRestart Procese los ejemplos que se han puesto en cola mientras están en pausa y, a continuación, trate lo mismo que OnClockStart. Envíe eventos MEStreamSinkMarker para marcadores en cola (serializados con procesamiento de muestras) y, a continuación, trate lo mismo que OnClockStart.
OnClockStop Quite todos los ejemplos en cola. Se pueden producir errores en otras llamadas a ProcessSample . Enviar eventos de marcador en cola. En las llamadas posteriores a PlaceMarker, envíe el evento de marcador inmediatamente.

 

Además, los receptores de secuencia deben enviar los siguientes eventos cuando hayan completado las transiciones de estado:

Finalizando

Algunos receptores multimedia requieren un paso de procesamiento adicional después de que se entregue el último ejemplo. Normalmente, este requisito se aplica a los receptores de archivo, que deben escribir encabezados o índices en el archivo. Si un receptor multimedia requiere un procesamiento final, expone la interfaz IMFFinalizableMediaSink .

Una vez que el cliente entrega el último ejemplo, el cliente consulta esta interfaz. Si el receptor de medios admite la interfaz, el cliente llama a IMFFinalizableMediaSink::BeginFinalize para realizar el procesamiento final de forma asincrónica. Este método sigue el modelo asincrónico estándar de Media Foundation, descrito en Métodos de devolución de llamada asincrónica. El receptor de medios puede suponer que el cliente llamará a BeginFinalize. Si no se llama a BeginFinalize , se puede producir un archivo creado incorrectamente.

Cerrando

Cuando el cliente haya terminado de usar el receptor de medios, el cliente llama a IMFMediaSink::Shutdown. Dentro de este método, el receptor de medios debe interrumpir los recuentos de referencia circulares. Normalmente, habrá referencias circulares entre el receptor multimedia y los receptores de secuencia.

Si usa el objeto auxiliar de cola de eventos para implementar IMFMediaEventGenerator, llame a IMFMediaEventQueue::Shutdown en la cola de eventos. Este método apaga la cola de eventos y señala a cualquier llamador que esté esperando un evento.

Después del apagado, todos los métodos del receptor multimedia devuelven MF_E_SHUTDOWN, a excepción de los métodos IUnknown .

Interfaces de receptor multimedia

En la tabla siguiente se enumeran las interfaces estándar que los receptores multimedia pueden exponer a través de QueryInterface. Los receptores multimedia también pueden exponer interfaces personalizadas.

Interfaz Descripción
IMFMediaSink Interfaz principal para receptores multimedia. (Requerido)
IMFClockStateSink Se usa para notificar al receptor multimedia cuando cambia el estado del reloj de presentación. (Requerido)
IMFFinalizableMediaSink Implemente si el receptor de medios debe realizar un paso de procesamiento final. (Opcional).
IMFGetService Implemente si el receptor de medios expone cualquier interfaz de servicio. (Opcional).
IMFMediaEventGenerator Implemente si el receptor de medios envía eventos. (Opcional).
IMFMediaSinkPreroll Implemente si el receptor de medios admite la inscripción previa. (Opcional).
IMFPresentationTimeSource Implemente si el receptor de medios puede proporcionar un origen de hora para el reloj de presentación. (Opcional).
IMFQualityAdvise Implemente si el receptor multimedia puede ajustar la calidad de reproducción. (Opcional).

 

Opcionalmente, un receptor de medios puede implementar la siguiente interfaz como servicio.

Interfaz de servicio Descripción
IMFRateSupport Informa del intervalo de velocidades de reproducción admitidas.

 

Para obtener más información sobre las interfaces de servicio y IMFGetService, consulte Interfaces de servicio.

Interfaces receptores de flujos

Los receptores de flujo deben exponer las siguientes interfaces a través de QueryInterface.

Interfaz Descripción
IMFStreamSink Interfaz principal para receptores de flujos. (Requerido)
IMFMediaEventGenerator Eventos de colas. La interfaz IMFStreamSink hereda esta interfaz. (Requerido)

 

Actualmente no se definen interfaces de servicio para receptores de flujos.

Eventos de receptor de flujos

En la tabla siguiente se enumeran los eventos definidos para receptores de flujos genéricos. Los receptores de flujos también pueden enviar eventos personalizados que no aparecen aquí.

Evento Descripción
MEStreamSinkFormatChanged El tipo de medio del receptor de secuencia ya no es válido. (Opcional).
MEStreamSinkMarker Se procesó un marcador. (Requerido)
MEStreamSinkPaused El receptor de la secuencia se ha pausado. (Requerido)
MEStreamSinkPrerolled La inscripción previa está completa. (Opcional).
MEStreamSinkRateChanged El receptor de secuencias ha cambiado la velocidad de reproducción. (Opcional).
MEStreamSinkRequestSample Se solicita un nuevo ejemplo. (Requerido)
MEStreamSinkScrubSampleComplete Se completó una solicitud de limpieza. (Opcional).
MEStreamSinkStarted Se ha iniciado el receptor de la secuencia. (Requerido)
MEStreamSinkStopped El receptor de la secuencia se ha detenido. (Requerido)

 

Actualmente no se definen eventos de uso general para receptores multimedia. Algunos receptores multimedia pueden enviar eventos personalizados.

Canalización de Media Foundation

Arquitectura de Media Foundation