MFT asincrónicos

En este tema se describe el procesamiento asincrónico de datos para las transformaciones (MFT) de Media Foundation.

Nota

Este tema se aplica a Windows 7 o posterior.

 

Acerca de las MFT asincrónicas

Cuando las MFT se introdujeron en Windows Vista, la API se diseñó para el procesamiento de datos sincrónico . En ese modelo, el MFT siempre está esperando a obtener la entrada o esperando a generar la salida.

Considere un descodificador de vídeo típico. Para obtener un marco descodificado, el cliente llama a IMFTransform::P rocessOutput. Si el descodificador tiene suficientes datos para descodificar un marco, ProcessOutput se bloquea mientras MFT descodifica el marco. De lo contrario, ProcessOutput devuelve MF_E_TRANSFORM_NEED_MORE_INPUT, lo que indica que el cliente debe llamar a IMFTransform::P rocessInput.

Este modelo funciona bien si el descodificador realiza todas sus operaciones de descodificación en un subproceso. Pero supongamos que el descodificador usa varios subprocesos para descodificar fotogramas en paralelo. Para obtener el mejor rendimiento, el descodificador debe recibir una entrada nueva cada vez que un subproceso de descodificación se vuelve inactivo. Pero la velocidad a la que los subprocesos completan las operaciones de descodificación no se alinearán exactamente con las llamadas del cliente a ProcessInput y ProcessOutput, lo que da lugar a subprocesos que esperan trabajo.

Windows 7 presenta el procesamiento asincrónico controlado por eventos para las MFT. En este modelo, cada vez que MFT necesita entrada o tiene salida, envía un evento al cliente.

Requisitos generales

En este tema se describe cómo difieren las MFT asincrónicas de MFT sincrónica. Excepto cuando se indique en este tema, los dos modelos de procesamiento son los mismos. (En concreto, la negociación de formato es la misma).

Una MFT asincrónica debe implementar las siguientes interfaces:

Eventos

Un MFT asincrónico usa los siguientes eventos para indicar su estado de procesamiento de datos:

Evento Descripción
METransformNeedInput Se envía cuando el MFT puede aceptar más entradas.
METransformHaveOutput Se envía cuando el MFT tiene salida.
METransformDrainComplete Se envía cuando se completa una operación de purga. Vea Purgar.
METransformMarker Se envía cuando se procesa un marcador. Consulte Marcadores.

 

Estos eventos se envían fuera de banda. Es importante comprender la diferencia entre los eventos dentro de banda y fuera de banda en el contexto de un MFT.

El diseño MFT original admite eventos en banda . Un evento en banda contiene información sobre el flujo de datos, como información sobre un cambio de formato. El cliente envía eventos en banda al MFT llamando a IMFTransform::P rocessEvent. MFT puede enviar eventos en banda de vuelta al cliente en el método ProcessOutput . (En concreto, los eventos se transmiten en el miembro pEvents de la estructura MFT_OUTPUT_DATA_BUFFER ).

Un MFT envía eventos fuera de banda a través de la interfaz IMFMediaEventGenerator de la siguiente manera:

  1. El MFT implementa la interfaz IMFMediaEventGenerator , como se describe en Generadores de eventos multimedia.
  2. El cliente llama a IUnknown::QueryInterface en el MFT para la interfaz IMFMediaEventGenerator . Una MFT asincrónica debe exponer esta interfaz. Las MFT sincrónicas no deben exponer esta interfaz.
  3. El cliente llama a IMFMediaEventGenerator::BeginGetEvent y IMFMediaEventGenerator::EndGetEvent para recibir eventos fuera de banda de MFT.

ProcessInput

El método IMFTransform::P rocessInput se modifica de la siguiente manera:

  1. Cuando se inicia el streaming, el cliente envía el mensaje MFT_MESSAGE_NOTIFY_START_OF_STREAM .
  2. Durante el streaming, MFT solicita datos mediante el envío de un evento METransformNeedInput . Los datos del evento son el identificador de flujo.
  3. Para cada evento METransformNeedInput , el cliente llama a ProcessInput para la secuencia especificada.
  4. Al final del streaming, el cliente puede llamar a ProcessMessage con el mensaje MFT_MESSAGE_NOTIFY_END_OF_STREAM .

Notas de implementación:

ProcessOutput

El método IMFTransform::P rocessOutput se modifica de la siguiente manera:

  1. Cada vez que el MFT tiene salida, envía un evento METransformHaveOutput .
  2. Para cada evento METransformHaveOutput , el cliente llama a ProcessOutput.

Notas de implementación:

  • Si el cliente llama a ProcessOutput en cualquier otro momento, el método devuelve E_UNEXPECTED.
  • Un MFT asincrónico nunca debe devolver MF_E_TRANSFORM_NEED_MORE_INPUT desde el método ProcessOutput . Si el MFT requiere más entrada, envía un evento METransformNeedInput .

Purgando

La purga de un MFT hace que el MFT genere tanto salida como pueda de cualquier dato de entrada que ya se haya enviado. La purga de un MFT asincrónico funciona de la siguiente manera:

  1. El cliente envía el mensaje MFT_MESSAGE_COMMAND_DRAIN .
  2. El MFT sigue enviando eventos METransformHaveOutput hasta que no tenga más datos para procesar. No envía eventos METransformNeedInput durante este tiempo.
  3. Una vez que el MFT envía el último evento METransformHaveOutput , envía un evento METransformDrainComplete .

Una vez completada la purga, el MFT no envía otro evento METransformNeedInput hasta que recibe un mensaje de MFT_MESSAGE_NOTIFY_START_OF_STREAM del cliente.

Lavado

El cliente puede vaciar el MFT enviando el mensaje MFT_MESSAGE_COMMAND_FLUSH . El MFT quita todas las muestras de entrada y salida que contiene.

El MFT no envía otro evento METransformNeedInput hasta que recibe un mensaje de MFT_MESSAGE_NOTIFY_START_OF_STREAM del cliente.

Marcadores

El cliente puede marcar un punto en la secuencia enviando el mensaje MFT_MESSAGE_COMMAND_MARKER . El MFT responde de la siguiente manera:

  1. MFT genera tantas muestras de salida como pueda a partir de los datos de entrada existentes, enviando un evento METransformHaveOutput para cada ejemplo de salida.
  2. Una vez generada toda la salida, MFT envía un evento METransformMarker . Este evento debe enviarse después de todos los eventos METransformHaveOutput .

Por ejemplo, supongamos que un descodificador tiene suficientes datos de entrada para generar cuatro ejemplos de salida. Si el cliente envía el mensaje de MFT_MESSAGE_COMMAND_MARKER , MFT pondrá en cola cuatro eventos METransformHaveOutput (uno por ejemplo de salida), seguido de un evento METransformMarker .

El mensaje de marcador es similar al mensaje de purga. Sin embargo, una purga se considera una interrupción en la secuencia, mientras que un marcador no lo es. El drenaje y los marcadores tienen las siguientes diferencias.

Drenaje:

  • Durante la purga, el MFT no envía eventos METransformNeedInput .
  • MFT descarta los datos de entrada que no se pueden usar para crear un ejemplo de salida.
  • Algunos TMF producen una "cola" al final de los datos. Por ejemplo, los efectos de audio, como reverberación o eco, producen datos adicionales después de que los datos de entrada se hayan detenido. Un MFT que genera una cola debe hacerlo al final de una operación de purga.
  • Una vez que el MFT haya terminado de purgarse, marca la siguiente muestra de salida con el atributo MFSampleExtension_Discontinuity , para indicar una discontinuidad en la secuencia.

Marcador:

  • El MFT sigue enviando eventos METransformNeedInput antes de enviar el evento de marcador.
  • MFT no descarta ningún dato de entrada. Si hay datos parciales, se debe procesar después del punto de marcador.
  • El MFT no produce una cola en el punto del marcador.
  • El MFT no establece la marca de discontinuidad después del punto de marcador.

Cambios de formato

Un MFT asincrónico debe admitir cambios de formato dinámico, como se describe en Control de cambios de flujo.

Atributos

Un MFT asincrónico debe implementar el método IMFTransform::GetAttributes para devolver un almacén de atributos válido. Los siguientes atributos se aplican a las MFP asincrónicas:

Atributo Descripción
MF_TRANSFORM_ASYNC El MFT debe establecer este atributo en TRUE (1). El cliente puede consultar este atributo para detectar si MFT es asincrónico.
MF_TRANSFORM_ASYNC_UNLOCK
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE El MFT debe establecer este atributo en TRUE (1). El cliente puede suponer que este atributo está establecido.

 

Desbloqueo de MFP asincrónicas

Las MFP asincrónicas no son compatibles con el modelo de procesamiento de datos MFT original. Para evitar que las MFP asincrónicas interrumpan las aplicaciones existentes, se define el siguiente mecanismo:

El cliente llama a IMFTransform::GetAttributes en el MFT. El cliente consulta para este atributo MF_TRANSFORM_ASYNC . Para un MFT asincrónico, el valor de este atributo es **TRUE**. Para desbloquear el MFT, el cliente debe establecer el atributo MF_TRANSFORM_ASYNC_UNLOCK en **TRUE**.

Hasta que el cliente desbloquee el MFT, todos los métodos IMFTransform deben devolver MF_E_TRANSFORM_ASYNC_LOCKED, con las siguientes excepciones:

En el código siguiente se muestra cómo desbloquear un MFT asincrónico:

HRESULT UnlockAsyncMFT(IMFTransform *pMFT)
{
    IMFAttributes *pAttributes = NULL;

    HRESULT hr = hr = pMFT->GetAttributes(&pAttributes);

    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
        pAttributes->Release();
    }
    
    return hr;
}

Apagar el MFT

Las MFT asincrónicas deben implementar la interfaz IMFShutdown .

  • Apagado: MFT debe apagar su cola de eventos. Si usa la cola de eventos estándar, llame a IMFMediaEventQueue::Shutdown. Opcionalmente, MFT puede liberar otros recursos. El cliente no debe usar MFT después de llamar a Shutdown.
  • GetShutdownStatus: después de llamar a Shutdown , MFT debe devolver el valor MFSHUTDOWN_COMPLETED en el parámetro pStatus . No debe devolver el valor MFSHUTDOWN_INITIATED.

Registro y enumeración

Para registrar un MFT asincrónico, llame a la función MFTRegister y establezca la marca MFT_ENUM_FLAG_ASYNCMFT en el parámetro Flags . (Anteriormente, esta marca estaba reservada).

Para enumerar las MFP asincrónicas, llame a la función MFTEnumEx y establezca la marca MFT_ENUM_FLAG_ASYNCMFT en el parámetro Flags . Por motivos de compatibilidad con versiones anteriores, la función MFTEnum no enumera las MFP asincrónicas. De lo contrario, la instalación de un MFT asincrónico en el equipo del usuario podría interrumpir las aplicaciones existentes.

Transformaciones de Media Foundation