Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Tunelización multimedia

Puede implementar tunelización multimedia en el marco de Android 5.0 y superior. Aunque la tunelización multimedia no es necesaria para Android TV, proporciona la mejor experiencia para contenido de ultra alta definición (4K).

Para Android 11 o superior, puede implementar tunelización multimedia con contenido de audio y video alimentado directamente desde Tuner. Codec2 y AudioTrack pueden utilizar el ID de sincronización HW desde el sintonizador, lo que podría corresponder a la referencia de reloj de programa (PCR) o el canal de reloj de tiempo del sistema (STC).

Fondo

El marco de medios de Android maneja el contenido de audio / video de cuatro maneras:

  • Software Pure (decodificación local): El procesador de aplicaciones (AP) descodifica localmente audio de modulación por código de pulso (PCM) sin aceleración especial. Se usa siempre para Ogg Vorbis y se usa para MP3 y AAC cuando no hay soporte de descarga comprimida.
  • Descarga de audio comprimido envía comprime datos de audio directamente al procesador de señal digital (DSP) y mantiene el AP fuera tanto como sea posible. Úselo para reproducir archivos de música con la pantalla apagada.
  • Pasarela de audio comprimido envía audio comprimido (específicamente AC3 y E-AC3) directamente a través de HDMI a un televisor o receptor externo de audio, sin decodificar en el dispositivo Android TV. La parte de video se maneja por separado.
  • Multimedia túnel envía comprime datos de audio y video juntos. Cuando los decodificadores de video y audio reciben la transmisión codificada, no regresa al marco. Idealmente, la transmisión no interrumpe el AP.
  • Multimedia pasarela envía comprime datos de audio y video juntos desde el sintonizador a los decodificadores de vídeo y audio sin la participación del marco.
Diagrama de flujo de tunelización multimedia
Flujo túnel Figura 1. Multimedia

Comparación de enfoques

Software puro Descarga de audio comprimido Passthrough de audio comprimido Túneles multimedia Passthrough multimedia
Decodificar ubicación AP DSP Receptor de TV o audio / video (AVR) TV o AVR TV o AVR
Maneja audio no
Maneja video no no no

Para desarrolladores de aplicaciones

Crear un SurfaceView ejemplo, obtener un identificador de sesión de audio, a continuación, crear los AudioTrack y MediaCodec casos para proporcionar la sincronización y configuraciones necesarias para la reproducción y el marco de decodificación de video.

Para Android 11 o superior, como una alternativa para el ID de sesión de audio, la aplicación puede obtener el HW de sincronización ID desde el sintonizador y proporcionarla a AudioTrack y MediaCodec instancias para A / V de sincronización.

Sincronización A / V

En el modo de túnel multimedia, el audio y el video se sincronizan en un reloj maestro.

  • Para Android 11 o superior, PCR o STC de Tuner puede ser el reloj maestro para la sincronización A / V.
  • Para Android 10 o versiones anteriores, el reloj de audio es el reloj maestro que se usa para la reproducción de A / V.

Si el vídeo tunelizado MediaCodec de instancia y AudioTrack casos están vinculados a la HW_AV_SYNC ejemplo, en AudioTrack , el reloj implícito derivado de HW_AV_SYNC restringe cuando se presenta cada fotograma de vídeo y audio de la muestra, basado en el audio real o sello de tiempo de presentación de trama de vídeo (PTS).

Flujo de llamadas a la API

Para Android 11 o superior, el cliente puede usar el ID de sincronización de HW de Tuner.

  1. Crear un SurfaceView ejemplo.
    SurfaceView sv = new SurfaceView(mContext);
  2. Obtenga una identificación de sesión de audio. Este único ID se utiliza en la creación de la pista de audio ( AudioTrack ). Se pasa al codec de los medios de comunicación ( MediaCodec ) y utilizado por el marco de los medios de comunicación para enlazar las rutas de audio y vídeo.
    AudioManager am = mContext.getSystemService(AUDIO_SERVICE);
    int audioSessionId = am.generateAudioSessionId()
    // or, for Android 11 or higher
    int avSyncId = tuner.getAvSyncHwId();
  3. Crear AudioTrack con HW A / V SYNC AudioAttributes .

    El gestor de políticas de audio pide a la capa de abstracción de hardware (HAL) para una salida de dispositivo que soporta FLAG_HW_AV_SYNC , y crea una pista de audio directamente conectado a esta salida sin mezclador intermedio.

    AudioAttributes.Builder aab = new AudioAttributes.Builder();
    aab.setUsage(AudioAttributes.USAGE_MEDIA);
    aab.setContentType(AudioAttributes.CONTENT_TYPE_MOVIE);
    aab.setFlag(AudioAttributes.FLAG_HW_AV_SYNC);
    
    // or, for Android 11 or higher
    new tunerConfig = TunerConfiguration(0, avSyncId);
    aab.setTunerConfiguration(tunerConfig);
    
    AudioAttributes aa = aab.build();
    AudioTrack at = new AudioTrack(aa);
    
  4. Crear un video MediaCodec instancia y configurarlo para la reproducción de videos en túnel.
    // retrieve codec with tunneled video playback feature
    MediaFormat mf = MediaFormat.createVideoFormat(“video/hevc”, 3840, 2160);
    mf.setFeatureEnabled(CodecCapabilities.FEATURE_TunneledPlayback, true);
    MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
    String codecName = mcl.findDecoderForFormat(mf);
    if (codecName == null) {
      return FAILURE;
    }
    // create codec and configure it
    mf.setInteger(MediaFormat.KEY_AUDIO_SESSION_ID, audioSessionId);
    
    // or, for Android 11 or higher
    mf.setInteger(MediaFormat.KEY_HARDWARE_AV_SYNC_ID, avSyncId);
    
    MediaCodec mc = MediaCodec.createCodecByName(codecName);
    mc.configure(mf, sv.getSurfaceHolder().getSurface(), null, 0);
    
  5. Decodifica los fotogramas de video.
    mc.start();
     for (;;) {
       int ibi = mc.dequeueInputBuffer(timeoutUs);
       if (ibi >= 0) {
         ByteBuffer ib = mc.getInputBuffer(ibi);
         // fill input buffer (ib) with valid data
         ...
         mc.queueInputBuffer(ibi, ...);
       }
       // no need to dequeue explicitly output buffers. The codec
       // does this directly to the sideband layer.
     }
     mc.stop();
     mc.release();
     mc = null;

Nota: Puede cambiar el orden de los pasos 3 y 4 en este proceso, como se ve en las dos figuras siguientes.

Diagrama de la pista de audio creada antes de configurar el códec
Figura 2. Pista de audio creado antes de configurar el codec
Diagrama de la pista de audio creada después de la configuración del códec
Figura 3. Pista de audio creada después de configurar el codec

Para fabricantes de dispositivos

OEMs debe crear un video separada decodificador OpenMAX IL (OMX) componente para la reproducción de vídeo de apoyo tunelizado. Este componente OMX debe anunciar que es capaz de reproducir un túnel (en media_codecs.xml ).

<Feature name=”tunneled-playback” required=”true” />

El componente también debe ser compatible con un OMX extendió parámetro OMX.google.android.index.configureVideoTunnelMode que utiliza un ConfigureVideoTunnelModeParams estructura.

struct ConfigureVideoTunnelModeParams {
    OMX_U32 nSize;              // IN
    OMX_VERSIONTYPE nVersion;   // IN
    OMX_U32 nPortIndex;         // IN
    OMX_BOOL bTunneled;         // IN/OUT
    OMX_U32 nAudioHwSync;       // IN
    OMX_PTR pSidebandWindow;    // OUT
};

Cuando un túnel MediaCodec se hace solicitud de creación, el marco configura el componente OMX en el modo de túnel (estableciendo bTunneled a OMX_TRUE ) y pasa el dispositivo de salida de audio asociado creado con una AUDIO_HW_AV_SYNC bandera para el componente OMX (en nAudioHwSync ).

Si los soportes de componentes de esta configuración, se debe asignar un asa de banda lateral a este codec y pasar de nuevo a través de la pSidebandWindow miembro. Un asa de banda lateral es una etiqueta de identificación para la capa de túnel que permite que el hardware Compositor (HW Compositor) identificarla. Si el componente no admite esta configuración, se debe establecer bTunneled a OMX_FALSE .

El marco recupera la capa tunelizada (el identificador de banda lateral) asignada por el componente OMX y la pasa al HW Composer. Esta capa de compositionType se establece en HWC_SIDEBAND . (Ver hardware/libhardware/include/hardware/hwcomposer.h ).

HW Composer es responsable de recibir nuevos búferes de imágenes de la transmisión en el momento adecuado (por ejemplo, sincronizados con el dispositivo de salida de audio asociado), componerlos con el contenido actual de otras capas y mostrar la imagen resultante. Esto ocurre independientemente del ciclo normal de preparación / ajuste. Las llamadas de preparación / configuración ocurren solo cuando cambian otras capas o cuando cambian las propiedades de la capa de banda lateral (como la posición o el tamaño).

Configuración

frameworks / av / services / audioflinger / AudioFlinger.cpp

El HAL devuelve el HW_AV_SYNC ID como una representación decimal cadena de caracteres de un número entero de 64 bits. (Ver frameworks/av/services/audioflinger/AudioFlinger.cpp ).

audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
char *reply = dev->get_parameters(dev, AUDIO_PARAMETER_HW_AV_SYNC);
AudioParameter param = AudioParameter(String8(reply));
int hwAVSyncId;
param.getInt(String8(AUDIO_PARAMETER_HW_AV_SYNC), hwAVSyncId);

frameworks / av / services / audioflinger / Threads.cpp

El marco de audio debe encontrar el flujo de salida HAL a la que corresponde esta sesión de identificación y consulta de la HAL para los hwAVSyncId utilizando set_parameters .

mOutput->stream->common.set_parameters(&mOutput->stream->common,
AUDIO_PARAMETER_STREAM_HW_AV_SYNC=hwAVSyncId);

Configuración del decodificador OMX

MediaCodec.java

El marco audio encuentra el flujo de salida HAL correspondiente para esta ID de sesión y recupera el audio-hw-sync ID mediante la consulta de la HAL para la AUDIO_PARAMETER_STREAM_HW_AV_SYNC bandera usando get_parameters .

// Retrieve HW AV sync audio output device from Audio Service
// in MediaCodec.configure()
if (entry.getKey().equals(MediaFormat.KEY_AUDIO_SESSION_ID)) {
    int sessionId = 0;
    try {
        sessionId = (Integer)entry.getValue();
    }
    catch (Exception e) {
        throw new IllegalArgumentException("Wrong Session ID Parameter!");
    }
    keys[i] = "audio-hw-sync";
    values[i] = AudioSystem.getAudioHwSyncForSession(sessionId);
}

// ...

Este HW de sincronización ID se pasa a la OMX tunelizado decodificador de vídeo usando la costumbre parámetro OMX.google.android.index.configureVideoTunnelMode .

ACodec.cpp

Después de obtener el ID de sincronización del hardware de audio, ACodec lo usa para configurar el decodificador de video tunelizado para que el decodificador de video tunelizado sepa qué pista de audio sincronizar.

// Assume you're going to use tunneled video rendering.
// Configure OMX component in tunneled mode and grab sideband handle (sidebandHandle) from OMX
// component.

native_handle_t* sidebandHandle;

// Configure OMX component in tunneled mode
status_t err = mOMX->configureVideoTunnelMode(mNode, kPortIndexOutput,
        OMX_TRUE, audioHwSync, &sidebandHandle);

OMXNodeInstance.cpp

El componente OMX está configurado por el configureVideoTunnelMode método anterior.

// paraphrased

OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
        "OMX.google.android.index.configureVideoTunnelMode");

OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);

ConfigureVideoTunnelModeParams tunnelParams;
InitOMXParams(&tunnelParams);
tunnelParams.nPortIndex = portIndex;
tunnelParams.bTunneled = tunneled;
tunnelParams.nAudioHwSync = audioHwSync;
err = OMX_SetParameter(mHandle, index, &tunnelParams);

err = OMX_GetParameter(mHandle, index, &tunnelParams);

sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;

ACodec.cpp

Una vez que el componente OMX está configurado en modo tunelizado, la manija de la banda lateral se asocia con la superficie de renderizado.

  err = native_window_set_sideband_stream(nativeWindow.get(),
  sidebandHandle); if (err != OK) { ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
  sidebandHandle, err); return err; }

Luego, la sugerencia de resolución máxima, si está presente, se envía al componente.

// Configure max adaptive playback resolution - as for any other video decoder
int32_t maxWidth = 0, maxHeight = 0;
if (msg->findInt32("max-width", &maxWidth) &&
    msg->findInt32("max-height", &maxHeight)) {
    err = mOMX->prepareForAdaptivePlayback(
              mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
}

Pausar soporte

Android 5.0 y versiones anteriores no incluyen soporte de pausa. Puede pausar la reproducción en túnel solo por falta de A / V, pero si el búfer interno para el video es grande (por ejemplo, hay 1 segundo de datos en el componente OMX), hace que la pausa parezca no responder.

En Android 5.1 y superior, AudioFlinger admite pausa y reanudación para salidas de audio directas (tunelizadas). Si HAL implementa pausa / reanudación, la pausa / reanudación de la pista se reenvía a HAL.

La secuencia de llamada de pausa, descarga y reanudación se respeta ejecutando las llamadas HAL en el hilo de reproducción (igual que la descarga).

Soporte Codec2

Para Android 11 o superior, Codec2 admite la reproducción en túnel.

CCodec.cpp

Para admitir la reproducción en túnel, Codec2 funciona de manera similar a OMX. Para admitir el ID de sincronización de HW desde Tuner, Codec2 busca el ID de sincronización en las fuentes siguientes.

sp<ANativeWindow> nativeWindow = static_cast<ANativeWindow *>(surface.get());
int32_t audioHwSync = 0;
if (!msg->findInt32("hw-av-sync-id", &audioHwSync)) {
       if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
       }
}
err = configureTunneledVideoPlayback(comp, audioHwSync, nativeWindow);

Sugerencias de implementación

Audio HAL

Para Android 11, el ID de sincronización de HW de PCR o STC se puede usar para la sincronización A / V, por lo que solo se admite la transmisión de video.

Para Android 10 o inferior, dispositivos que admiten la reproducción de vídeo de túnel deben tener al menos un perfil de flujo de salida de audio con las banderas FLAG_HW_AV_SYNC y AUDIO_OUTPUT_FLAG_DIRECT en su audio_policy.conf archivo. Estos indicadores se utilizan para configurar el reloj del sistema desde el reloj de audio.

OMX

Los fabricantes de dispositivos deben tener un componente OMX separado para la reproducción de video en túnel. Los fabricantes pueden tener componentes OMX adicionales para otros tipos de reproducción de audio y video, como la reproducción segura.

Este componente debe especificar 0 tampones ( nBufferCountMin , nBufferCountActual ) en su puerto de salida.

El componente de túnel también debe implementar la OMX.google.android.index.prepareForAdaptivePlayback setParameter extensión.

El componente de túnel debe especificar sus capacidades en el media_codecs.xml archivo y declarar la función de reproducción de un túnel. También debería aclarar cualquier limitación en el tamaño de la trama, la alineación o la tasa de bits.


    <MediaCodec name="OMX.OEM_NAME.VIDEO.DECODER.AVC.tunneled"
    type="video/avc" >
        <Feature name="adaptive-playback" />
        <Feature name="tunneled-playback" required=”true” />
        <Limit name="size" min="32x32" max="3840x2160" />
        <Limit name="alignment" value="2x2" />
        <Limit name="bitrate" range="1-20000000" />
            ...
    </MediaCodec>

Si se utiliza el mismo componente OMX para admitir decodificación tunelizada y no tunelizada, entonces debería dejar la función de reproducción tunelizada como no requerida. Tanto los decodificadores tunelizados como los no tunelizados tienen las mismas limitaciones de capacidad.

    <MediaCodec name="OMX.OEM_NAME.VIDEO.DECODER.AVC" type="video/avc" >
        <Feature name="adaptive-playback" />
        <Feature name="tunneled-playback" />
        <Limit name="size" min="32x32" max="3840x2160" />
        <Limit name="alignment" value="2x2" />
        <Limit name="bitrate" range="1-20000000" />
            ...
    </MediaCodec>

Compositor de HW

Cuando hay una capa de un túnel (una capa con HWC_SIDEBAND compositionType ) en una pantalla, de la capa sidebandStream es el mango de banda lateral asignado por el componente de vídeo OMX.

El HW Compositor sincroniza decodificado fotogramas de vídeo (desde el componente de OMX tunelizado) a la pista de audio asociado (con el audio-hw-sync ID). Cuando un nuevo fotograma de video se convierte en actual, HW Composer lo combina con el contenido actual de todas las capas recibidas durante la última llamada de preparación / configuración, y muestra la imagen resultante. Las llamadas de preparación / configuración ocurren solo cuando cambian otras capas o cuando cambian las propiedades de la capa de banda lateral (como la posición o el tamaño).

La Figura 4 representa el HW Composer trabajando con el sincronizador de HW (o kernel / controlador), para combinar cuadros de video (7b) con la última composición (7a) para mostrarlos en el momento correcto, basado en audio (7c).

Diagrama del compositor de hardware que combina fotogramas de video basados ​​en el audio
Figura 4. HW Compositor trabajar con el HW (o kernel / conductor) sincronizador