Framework de Tuner

En el caso de Android 11 o versiones posteriores, puedes usar el framework de Android Tuner para entregar contenido A/V. El framework usa la canalización de hardware de los proveedores, lo que lo hace adecuado para SoC de gama baja y alta. El framework proporciona una forma segura de entregar contenido de A/V protegido por un entorno de ejecución confiable (TEE) y una ruta de acceso multimedia segura (SMP), lo que le permite usarse en un entorno de protección de contenido muy restringido.

La interfaz estandarizada entre el sintonizador y el CAS de Android permite una integración más rápida entre los proveedores de sintonizadores y los proveedores de CAS. La interfaz del sintonizador funciona con MediaCodec y AudioTrack para crear una solución global para Android TV. La interfaz del sintonizador admite TV digital y analógica según los principales estándares de transmisión.

Componentes

En Android 11, tres componentes están diseñados específicamente para la plataforma de TV.

  • HAL del sintonizador: Es una interfaz entre el framework y los proveedores.
  • API del SDK de Tuner: Es una interfaz entre el framework y las apps.
  • Administrador de recursos de sintonizador (TRM): Coordina los recursos de HW del sintonizador.

En Android 11, se mejoraron los siguientes componentes:

  • CAS V2
  • TvInputService o servicio de entrada de TV (TIS)
  • TvInputManagerService o el servicio de TV Input Manager (TIMS)
  • MediaCodec o códec multimedia
  • AudioTrack o pista de audio
  • MediaResourceManager o el administrador de recursos multimedia (MRM)

Diagrama de flujo de los componentes del framework de Tuner.

Figura 1: Interacciones entre componentes de Android TV

Funciones

El frontend admite los siguientes estándares de DTV.

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Analógico

El frontend de Android 12 con Tuner HAL 1.1 o versiones posteriores es compatible con el siguiente estándar de DTV.

  • DTMB

El demux admite los siguientes protocolos de transmisión.

  • Flujo de transporte (TS)
  • Protocolo de transporte multimedia MPEG (MMTP)
  • Protocolo de Internet (IP)
  • Valor de longitud del tipo (TLV)
  • Protocolo de capa de vínculo (ALP) de ATSC

El decodificador admite las siguientes protecciones de contenido.

  • Ruta de medios segura
  • Borra la ruta de contenido multimedia
  • Registro local seguro
  • Cómo proteger la reproducción local

Las APIs de Tuner admiten los siguientes casos de uso.

  • Escanear
  • En vivo
  • Reproducción
  • Grabar

El sintonizador, MediaCodec y AudioTrack admiten los siguientes modos de flujo de datos.

  • Carga útil de ES con búfer de memoria clara
  • Carga útil de ES con control de memoria seguro
  • Modo de cámara externa

Diseño general

El HAL de Tuner se define entre el framework de Android y el hardware del proveedor.

  • Describe lo que el framework espera del proveedor y cómo podría hacerlo.
  • Exporta las funciones del frontend, el demux y el decodificador al framework a través de las interfaces IFrontend, IDemux, IDescrambler, IFilter, IDvr y ILnb.
  • Incluye las funciones para integrar el HAL de Tuner con otros componentes del framework, como MediaCodec y AudioTrack.

Se crean una clase Java y una clase nativa de Tuner.

  • La API de Java de Tuner permite que las apps accedan al HAL de Tuner a través de APIs públicas.
  • La clase nativa permite el control de permisos y el manejo de grandes cantidades de datos de grabación o reproducción con el HAL del sintonizador.
  • El módulo de sintonizador nativo es un puente entre la clase de Java del sintonizador y el HAL del sintonizador.

Se crea una clase de TRM.

  • Administra recursos limitados del sintonizador, como el frontend, el LNB, las sesiones de CAS y un dispositivo de entrada de TV desde el HAL de entrada de TV.
  • Aplica reglas para recuperar recursos insuficientes de las apps. La regla predeterminada es la victoria en primer plano.

El CAS de contenido multimedia y el HAL de CAS se mejoran con las siguientes funciones.

  • Abre sesiones de CAS para diferentes usos y algoritmos.
  • Admite sistemas de CAS dinámicos, como la inserción y eliminación de CICAM.
  • Se integra con el HAL de sintonizador proporcionando tokens de clave.

MediaCodec y AudioTrack se mejoran con las siguientes funciones.

  • Toma memoria de A/V segura como entrada de contenido.
  • Se configuró para realizar la sincronización de A/V de hardware en la reproducción en túnel.
  • Se configuró la compatibilidad con ES_payload y el modo de transferencia.

Diseño general del HAL del sintonizador

Figura 2: Diagrama de los componentes dentro del sistema HAL del sintonizador

Flujo de trabajo general

En los siguientes diagramas, se ilustran las secuencias de llamadas para la reproducción de transmisiones en vivo.

Configuración

Secuencia de configuración del diagrama de reproducción de la transmisión en vivo.

Figura 3: Secuencia de configuración para la reproducción de transmisiones en vivo

Cómo controlar el contenido multimedia

Diagrama de control de audio y video para la reproducción de transmisiones en vivo.

Figura 4: Controla el audio y video para la reproducción de transmisiones en vivo

Cómo controlar el contenido codificado

Manejo de contenido codificado para el diagrama de reproducción de transmisiones en vivo.

Figura 5: Cómo controlar el contenido codificado para la reproducción de transmisiones en vivo

Procesamiento de datos de audio y video

Procesa los datos de A/V para el diagrama de reproducción de transmisiones en vivo.

Figura 6: Procesamiento de audio y video para la reproducción de transmisiones en vivo

API del SDK de Tuner

La API del SDK de Tuner controla las interacciones con el JNI de Tuner, el HAL de Tuner y TunerResourceManager. La app de TIS usa la API del SDK de Tuner para acceder a los recursos y subcomponentes de Tuner, como el filtro y el decodificador. El frontend y el demux son componentes internos.

Diagrama de flujo de la API del SDK de Tuner.

Figura 7: Interacciones con la API del SDK de Tuner

Versiones

A partir de Android 12, la API del SDK de Tuner admite la nueva función en Tuner HAL 1.1, que es una actualización retrocompatible de la versión 1.0 de Tuner.

Usa la siguiente API para verificar la versión de HAL en ejecución.

  • android.media.tv.tuner.TunerVersionChecker.getTunerVersion()

Puedes encontrar la versión mínima de HAL requerida en la documentación de las nuevas APIs de Android 12.

Paquetes

La API del SDK de Tuner proporciona los cuatro paquetes que se indican a continuación.

  • android.media.tv.tuner
  • android.media.tv.tuner.frontend
  • android.media.tv.tuner.filter
  • android.media.tv.tuner.dvr

Diagrama de flujo de los paquetes de la API del SDK de Tuner.

Figura 8: Paquetes de la API del SDK de Tuner

Android.media.tv.tuner

El paquete de Tuner es un punto de entrada para usar el framework de Tuner. La app de TIS usa el paquete para inicializar y adquirir instancias de recursos especificando el parámetro de configuración inicial y la devolución de llamada.

  • tuner(): Especifica los parámetros useCase y sessionId para inicializar una instancia de Tuner.
  • tune(): Adquiere un recurso de frontend y lo ajusta especificando el parámetro FrontendSetting.
  • openFilter(): Adquiere una instancia de filtro especificando el tipo de filtro.
  • openDvrRecorder(): Adquiere una instancia de grabación especificando el tamaño del búfer.
  • openDvrPlayback(): Adquiere una instancia de reproducción especificando el tamaño del búfer.
  • openDescrambler(): Adquiere una instancia de decodificador.
  • openLnb(): Adquiere una instancia interna de LNB.
  • openLnbByName(): Adquiere una instancia de LNB externa.
  • openTimeFilter(): Adquiere una instancia de filtro de tiempo.

El paquete Tuner proporciona funciones que no se incluyen en los paquetes de filtro, DVR y frontend. Las funciones se enumeran a continuación.

  • cancelTuning
  • scan/cancelScanning
  • getAvSyncHwId
  • getAvSyncTime
  • connectCiCam1/disconnectCiCam
  • shareFrontendFromTuner
  • updateResourcePriority
  • setOnTuneEventListener
  • setResourceLostListener

Android.media.tv.tuner.frontend

El paquete de frontend incluye colecciones de parámetros de configuración, información, estados, eventos y capacidades relacionados con el frontend.

Clases

FrontendSettings se deriva para diferentes estándares de DTV según las clases que se indican a continuación.

  • AnalogFrontendSettings
  • Atsc3FrontendSettings
  • AtscFrontendSettings
  • DvbcFrontendSettings
  • DvbsFrontendSettings
  • DvbtFrontendSettings
  • Isdbs3FrontendSettings
  • IsdbsFrontendSettings
  • IsdbtFrontendSettings

A partir de Android 12 con Tuner HAL 1.1 o versiones posteriores, se admite el siguiente estándar de DTV.

  • DtmbFrontendSettings

FrontendCapabilities se deriva para diferentes estándares de DTV según las clases que se indican a continuación.

  • AnalogFrontendCapabilities
  • Atsc3FrontendCapabilities
  • AtscFrontendCapabilities
  • DvbcFrontendCapabilities
  • DvbsFrontendCapabilities
  • DvbtFrontendCapabilities
  • Isdbs3FrontendCapabilities
  • IsdbsFrontendCapabilities
  • IsdbtFrontendCapabilities

A partir de Android 12 con Tuner HAL 1.1 o versiones posteriores, se admite el siguiente estándar de DTV.

  • DtmbFrontendCapabilities

FrontendInfo recupera la información del frontend. FrontendStatus recupera el estado actual del frontend. OnTuneEventListener escucha los eventos en el frontend. La app de TIS usa ScanCallback para procesar los mensajes de análisis desde el frontend.

Búsqueda de canales

Para configurar una TV, la app escanea las posibles frecuencias y crea una alineación de canales para que los usuarios accedan a ellos. Es posible que TIS use Tuner.tune, Tuner.scan(BLIND_SCAN) o Tuner.scan(AUTO_SCAN) para completar el análisis de canales.

Si el TIS tiene información de entrega precisa para la señal, como la frecuencia, el estándar (por ejemplo, T/T2, S/S2) y la información necesaria adicional (por ejemplo, el ID de PLD), se recomienda Tuner.tune como la opción más rápida.

Cuando el usuario llama a Tuner.tune, se producen las siguientes acciones:

  • TIS propaga FrontendSettings con la información requerida mediante Tuner.tune.
  • El informe de HAL sintoniza los mensajes LOCKED si la señal está bloqueada.
  • TIS usa Frontend.getStatus para recopilar la información necesaria.
  • El TIS pasa a la siguiente frecuencia disponible en su lista de frecuencias.

TIS vuelve a llamar a Tuner.tune hasta que se agoten todas las frecuencias.

Durante la sintonización, puedes llamar a stopTune() o close() para pausar o finalizar la llamada a Tuner.tune.

Tuner.scan(AUTO_SCAN)

Si el TIS no tiene suficiente información para usar Tuner.tune, pero tiene una lista de frecuencias y un tipo estándar (por ejemplo, DVB T/C/S), se recomienda Tuner.scan(AUTO_SCAN).

Cuando el usuario llama a Tuner.scan(AUTO_SCAN), se producen las siguientes acciones:

  • TIS usa Tuner.scan(AUTO_SCAN) con FrontendSettings lleno de frecuencia.

  • El informe de HAL analiza los mensajes LOCKED si el indicador está bloqueado. Es posible que el HAL también informe otros mensajes de escaneo para proporcionar información adicional sobre la señal.

  • TIS usa Frontend.getStatus para recopilar la información necesaria.

  • TIS llama a Tuner.scan para que el HAL continúe con el siguiente parámetro de configuración en la misma frecuencia. Si la estructura FrontendSettings está vacía, el HAL usa el siguiente parámetro de configuración disponible. De lo contrario, HAL usa FrontendSettings para una búsqueda única y envía END para indicar que la operación de búsqueda finalizó.

  • El TIS repite las acciones anteriores hasta que se agota toda la configuración de la frecuencia.

  • El sistema HAL envía END para indicar que finalizó la operación de análisis.

  • El TIS pasa a la siguiente frecuencia disponible en su lista de frecuencias.

TIS vuelve a llamar a Tuner.scan(AUTO_SCAN) hasta que se agoten todas las frecuencias.

Durante el análisis, puedes llamar a stopScan() o close() para pausarlo o finalizarlo.

Tuner.scan(BLIND_SCAN)

Si el TIS no tiene una lista de frecuencias y el HAL del proveedor puede buscar la frecuencia del frontend especificado por el usuario para obtener el recurso del frontend, se recomienda Tuner.scan(BLIND_SCAN).

  • TIS usa Tuner.scan(BLIND_SCAN). Se puede especificar una frecuencia en FrontendSettings para la frecuencia de inicio, pero TIS ignora otros parámetros de configuración en FrontendSettings.
  • El HAL informa un mensaje de escaneo LOCKED si la señal está bloqueada.
  • TIS usa Frontend.getStatus para recopilar la información necesaria.
  • TIS vuelve a llamar a Tuner.scan para continuar con el escaneo. (FrontendSettings se ignora).
  • El TIS repite las acciones anteriores hasta que se agota toda la configuración de la frecuencia. El HAL incrementa la frecuencia sin que sea necesario que el TIS realice ninguna acción. El HAL informa PROGRESS.

TIS vuelve a llamar a Tuner.scan(AUTO_SCAN) hasta que se agoten todas las frecuencias. El sistema HAL informa END para indicar que finalizó la operación de análisis.

Durante el análisis, puedes llamar a stopScan() o close() para pausarlo o finalizarlo.

Diagrama de flujo del proceso de análisis de TIS.

Figura 9: Diagrama de flujo de un análisis de TIS

Android.media.tv.tuner.filter

El paquete de filtros es una colección de operaciones de filtro junto con la configuración, los parámetros de configuración, las devoluciones de llamada y los eventos. El paquete incluye las siguientes operaciones. Consulta el código fuente de Android para obtener la lista completa de operaciones.

  • configure()
  • start()
  • stop()
  • flush()
  • read()

Consulta el código fuente de Android para obtener la lista completa.

FilterConfiguration se deriva de las siguientes clases. Las configuraciones son para el tipo de filtro principal y especifican qué protocolo usa el filtro para extraer datos.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

La configuración se deriva de las siguientes clases. La configuración es para el subtipo de filtro y especifica qué tipos de datos puede excluir el filtro.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent se deriva de las clases que se indican a continuación para informar eventos de diferentes tipos de datos.

  • SectionEvent
  • MediaEvent
  • PesEvent
  • TsRecordEvent
  • MmtpRecordEvent
  • TemiEvent
  • DownloadEvent
  • IpPayloadEvent

A partir de Android 12 con Tuner HAL 1.1 o versiones posteriores, se admiten los siguientes eventos.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Formato de eventos y datos del filtro
Tipo de filtro Marcas Eventos Operación de datos Formato de datos
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Obligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Según el evento y el programa interno, ejecuta
Filter.read(buffer, offset, adjustedSize) una o más veces.

Los datos se copian del MQ de HAL al búfer del cliente.
Otro paquete de sesión completa un paquete de sesión ensamblado en la FMQ.
isRaw:
false
Obligatorio:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcional:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


Los datos se copian del MQ de HAL al búfer del cliente.
TS.PES isRaw:
true
Obligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Según el evento y el programa interno, ejecuta
Filter.read(buffer, offset, adjustedSize) una o más veces.

Los datos se copian del MQ de HAL al búfer del cliente.
Otro paquete de PES completa un paquete de PES ensamblado en FMQ.
isRaw:
false
Obligatorio:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcional:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Los datos se copian del MQ de HAL al búfer del cliente.
MMTP.PES isRaw:
true
Obligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Según el evento y el programa interno, ejecuta
Filter.read(buffer, offset, adjustedSize) una o más veces.

Los datos se copian del MQ de HAL al búfer del cliente.
Otro paquete de MFU completa un paquete de MFU ensamblado en la FMQ.
isRaw:
false
Obligatorio:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcional:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Los datos se copian del MQ de HAL al búfer del cliente.
TS.TS
N/A Obligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Según el evento y el programa interno, ejecuta
Filter.read(buffer, offset, adjustedSize) una o más veces.

Los datos se copian del MQ de HAL al búfer del cliente.
Se filtra ts con el encabezado ts
se completa en FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
El cliente puede iniciar MediaCodec después de recibir DemuxFilterStatus::DATA_READY.
El cliente puede llamar a Filter.flush después de recibir DemuxFilterStatus::DATA_OVERFLOW.
N/A
isPassthrough:
false
Obligatorio:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcional:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Para usar MediaCodec:
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Para usar Direct Audio de AudioTrack:
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Datos de ES o ES parciales en la memoria de ION
TS.PCR
IP.NTP
ALP.PTP
N/A Obligatorio: N/A
Opcional: N/A
N/A N/A
TS.RECORD N/A Obligatorio:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Para los datos del índice:
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


Para el contenido grabado, según RecordStatus::* y el programa interno, haz una de las siguientes acciones:
  • Ejecuta DvrRecord.write(adustedSize) una o más veces en el almacenamiento.
    Los datos se transfieren del MQ de HAL al almacenamiento.
  • Ejecuta DvrRecord.write(buffer, adustedSize) una o más veces para almacenar en búfer.
    Los datos se copian del MQ de HAL al búfer del cliente.
Para datos de índice: Se incluyen en la carga útil del evento.

Para contenido grabado: Se completó la transmisión de TS multiplexada en la FMQ.
TS.TEMI N/A Obligatorio:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
N/A
MMTP.MMTP N/A Obligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Según el evento y el programa interno, ejecuta
Filter.read(buffer, offset, adjustedSize) una o más veces.

Los datos se copian del MQ de HAL al búfer del cliente.
Se filtra mmtp con el encabezado mmtp
se completa en FMQ.
MMTP.RECORD N/A Obligatorio:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Para los datos del índice: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Para el contenido grabado, según RecordStatus::* y el programa interno, haz una de las siguientes acciones:
  • Ejecuta DvrRecord.write(adjustedSize) una o más veces en el almacenamiento.
    Los datos se transfieren del MQ de HAL al almacenamiento.
  • Ejecuta DvrRecord.write(buffer, adjustedSize) una o más veces para almacenar en búfer.
    Los datos se copian del MQ de HAL al búfer del cliente.
Para datos de índice: Se incluyen en la carga útil del evento.

Para el contenido grabado: Se completó la transmisión grabada multiplexada en la FMQ.

Si la fuente del filtro para la grabación es de TLV.TLV a IP.IP con transferencia directa, la transmisión grabada tiene un encabezado TLV y IP.
MMTP.DOWNLOAD N/A Obligatorio:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcional:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

Los datos se copian del MQ de HAL al búfer del cliente.
Otro paquete de descarga de IP completa el paquete de descarga en FMQ.
IP.IP_PAYLOAD N/A Obligatorio:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcional:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

Los datos se copian del MQ de HAL al búfer del cliente.
Otro paquete de carga útil de IP completa el paquete de carga útil de IP en FMQ.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
El subflujo de protocolo filtrado alimenta al siguiente filtro en la cadena de filtros. N/A
isPassthrough:
false
Obligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Según el evento y el programa interno, ejecuta
Filter.read(buffer, offset, adjustedSize) una o más veces.

Los datos se copian del MQ de HAL al búfer del cliente.
El subflujo de protocolo filtrado con el encabezado del protocolo se completa en FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
N/A Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
La carga útil del protocolo filtrada alimenta al siguiente filtro en la cadena de filtros. N/A
Ejemplo de flujo para usar el filtro para compilar PSI/SI

Flujo de ejemplo para usar el filtro para compilar PSI/SI.

Figura 10: Flujo para compilar PSI/SI

  1. Abre un filtro.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Configura y, luego, inicia el filtro.

    Settings settings = SectionSettingsWithTableInfo
        .builder(Filter.TYPE_TS)
        .setTableId(2)
        .setVersion(1)
        .setCrcEnabled(true)
        .setRaw(false)
        .setRepeat(false)
        .build();
      FilterConfiguration config = TsFilterConfiguration
        .builder()
        .setTpid(10)
        .setSettings(settings)
        .build();
      filter.configure(config);
      filter.start();
    
  3. Procesa SectionEvent.

    FilterCallback filterCallback = new FilterCallback() {
      @Override
      public void onFilterEvent(Filter filter, FilterEvent[] events) {
        for (FilterEvent event : events) {
          if (event instanceof SectionEvent) {
            SectionEvent sectionEvent = (SectionEvent) event;
            int tableId = sectionEvent.getTableId();
            int version = sectionEvent.getVersion();
            int dataLength = sectionEvent.getDataLength();
            int sectionNumber = sectionEvent.getSectionNumber();
            filter.read(buffer, 0, dataLength); }
          }
        }
    };
    
Ejemplo de flujo para usar MediaEvent desde el filtro

Ejemplo de flujo para usar MediaEvent desde el filtro.

Figura 11: Flujo para usar MediaEvent desde el filtro

  1. Abre, configura y, luego, inicia los filtros de A/V.
  2. Procesa MediaEvent.
  3. Recibe MediaEvent.
  4. Coloca en cola el bloque lineal en codec.
  5. Libera el control de A/V cuando se hayan consumido los datos.

Android.media.tv.tuner.dvr

DvrRecorder proporciona estos métodos para la grabación.

  • configure
  • attachFilter
  • detachFilter
  • start
  • flush
  • stop
  • setFileDescriptor
  • write

DvrPlayback proporciona estos métodos para la reproducción.

  • configure
  • start
  • flush
  • stop
  • setFileDescriptor
  • read

DvrSettings se usa para configurar DvrRecorder y DvrPlayback. OnPlaybackStatusChangedListener y OnRecordStatusChangedListener se usan para informar el estado de una instancia de DVR.

Ejemplo de flujo para iniciar un registro

Ejemplo de flujo para iniciar un registro.

Figura 12: Flujo para iniciar un registro

  1. Abre, configura y, luego, inicia DvrRecorder.

    DvrRecorder recorder = openDvrRecorder(/* bufferSize */ 1000, executor, listener);
    DvrSettings dvrSettings = DvrSettings
    .builder()
    .setDataFormat(DvrSettings.DATA_FORMAT_TS)
    .setLowThreshold(100)
    .setHighThreshold(900)
    .setPacketSize(188)
    .build();
    recorder.configure(dvrSettings);
    recorder.attachFilter(filter);
    recorder.setFileDescriptor(fd);
    recorder.start();
    
  2. Recibe RecordEvent y recupera la información del índice.

    FilterCallback filterCallback = new FilterCallback() {
      @Override
      public void onFilterEvent(Filter filter, FilterEvent[] events) {
        for (FilterEvent event : events) {
          if (event instanceof TsRecordEvent) {
            TsRecordEvent recordEvent = (TsRecordEvent) event;
            int tsMask = recordEvent.getTsIndexMask();
            int scMask = recordEvent.getScIndexMask();
            int packetId = recordEvent.getPacketId();
            long dataLength = recordEvent.getDataLength();
            // handle the masks etc. }
          }
        }
    };
    
  3. Inicializa OnRecordStatusChangedListener y almacena los datos del registro.

      OnRecordStatusChangedListener listener = new OnRecordStatusChangedListener() {
        @Override
        public void onRecordStatusChanged(int status) {
          // a customized way to consume data efficiently by using status as a hint.
          if (status == Filter.STATUS_DATA_READY) {
            recorder.write(size);
          }
        }
      };
    

HAL del sintonizador

La HAL del sintonizador sigue HIDL y define la interfaz entre el framework y el hardware del proveedor. Los proveedores usan la interfaz para implementar el HAL de sintonizador, y el framework la usa para comunicarse con la implementación del HAL de sintonizador.

Módulos

HAL de sintonizador 1.0

Módulos Controles básicos Controles específicos del módulo Archivos HAL
ITuner N/A frontend(open, getIds, getInfo), openDemux, openDescrambler, openLnb, getDemuxCaps ITuner.hal
IFrontend setCallback, getStatus, close tune, stopTune, scan, stopScan, setLnb IFrontend.hal
IFrontendCallback.hal
IDemux close setFrontendDataSource, openFilter, openDvr, getAvSyncHwId, getAvSyncTime, connect / disconnectCiCam IDemux.hal
IDvr close, start, stop, configure attach/detachFilters, flush, getQueueDesc IDvr.hal
IDvrCallback.hal
IFilter close, start, stop, configure, getId flush, getQueueDesc, releaseAvHandle, setDataSource IFilter.hal
IFilterCallback.hal
ILnb close, setCallback setVoltage, setTone, setSatellitePosition, sendDiseqcMessage ILnb.hal
ILnbCallback.hal
IDescrambler close setDemuxSource, setKeyToken, addPid, removePid IDescrambler.hal

Tuner HAL 1.1 (derivado de Tuner HAL 1.0)

Módulos Controles básicos Controles específicos del módulo Archivos HAL
ITuner N/A getFrontendDtmbCapabilities @1.1::ITuner.hal
IFrontend tune_1_1, scan_1_1, getStatusExt1_1 link/unlinkCiCam @1.1::IFrontend.hal
@1.1::IFrontendCallback.hal
IFilter getStatusExt1_1 configureIpCid, configureAvStreamType, getAvSharedHandle, configureMonitorEvent @1.1::IFilter.hal
@1.1::IFilterCallback.hal

Diagrama de flujo de las interacciones entre los módulos del sistema HAL del sintonizador.

Figura 13: Diagrama de las interacciones entre los módulos HAL del sintonizador

Vinculación de filtros

El HAL de Tuner admite la vinculación de filtros, de modo que los filtros se pueden vincular a otros para varias capas. Los filtros siguen las reglas que se indican a continuación.

  • Los filtros están vinculados como un árbol, no se permite la ruta de cierre.
  • El nodo raíz es demux.
  • Los filtros funcionan de forma independiente.
  • Todos los filtros comienzan a obtener datos.
  • El vínculo del filtro se borra en el último filtro.

En el siguiente bloque de código y en la Figura 14, se muestra un ejemplo de cómo filtrar varias capas.

demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
        ipFilter = ITuner.openFilter(<IP, ..>)
        mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter1.setDataSource(<ipFilter>)
        mmtpFilter2.setDataSource(<ipFilter>)
}

Ejemplo de diagrama de vinculación de filtros.

Figura 14: Diagrama de flujo de un vínculo de filtro para varias capas

Administrador de recursos del sintonizador

Antes del Administrador de recursos de sintonizador (TRM), cambiar entre dos apps requería el mismo hardware de sintonizador. El framework de entrada de TV (TIF) usaba un mecanismo de "ganancia del primero en adquirir", lo que significa que la app que obtenga el recurso primero lo conservará. Sin embargo, este mecanismo podría no ser ideal para algunos casos de uso complicados.

El TRM se ejecuta como un servicio del sistema para administrar los recursos de hardware del sintonizador, TVInput y CAS para las apps. La TRM usa un mecanismo de "victoria en primer plano", que calcula la prioridad de la app según su estado en primer o segundo plano, y el tipo de caso de uso. La TRM otorga o revoca el recurso según la prioridad. La TRM centraliza la administración de recursos de ATV para la transmisión, OTT y DVR.

Interfaz de TRM

TRM expone interfaces de AIDL en ITunerResourceManager.aidl para que el framework de Tuner, MediaCas y TvInputHardwareManager registren, soliciten o liberen recursos.

A continuación, se enumeran las interfaces para la administración de clientes.

  • registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
  • unregisterClientProfile(in int clientId)

A continuación, se indican las interfaces para solicitar y liberar recursos.

  • requestFrontend(TunerFrontendRequest request, int[] frontendHandle) / releaseFrontend
  • requestDemux(TunerDemuxRequest request, int[] demuxHandle) / releaseDemux
  • requestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle) / releaseDescrambler
  • requestCasSession(CasSessionRequest request, int[] casSessionHandle) / releaseCasSession
  • requestLnb(TunerLnbRequest request, int[] lnbHandle)/releaseLnb

A continuación, se enumeran las clases de cliente y solicitud.

  • ResourceClientProfile
  • ResourcesReclaimListener
  • TunerFrontendRequest
  • TunerDemuxRequest
  • TunerDescramblerRequest
  • CasSessionRequest
  • TunerLnbRequest

Prioridad del cliente

La TRM calcula la prioridad del cliente con los parámetros de su perfil y el valor de prioridad del archivo de configuración. La prioridad también se puede actualizar con un valor de prioridad arbitrario del cliente.

Parámetros en el perfil del cliente

TRM recupera el ID de proceso de mTvInputSessionId para decidir si una app es en primer o segundo plano. Para crear mTvInputSessionId, TvInputService.onCreateSession o TvInputService.onCreateRecordingSession, se inicializa una sesión de TIS.

mUseCase indica el caso de uso de la sesión. Los casos de uso predefinidos se enumeran a continuación.

TvInputService.PriorityHintUseCaseType  {
  PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
  PRIORITY_HINT_USE_CASE_TYPE_LIVE
  PRIORITY_HINT_USE_CASE_TYPE_RECORD,
  PRIORITY_HINT_USE_CASE_TYPE_SCAN,
  PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
}

Archivo de configuración

Archivo de configuración predeterminado

El siguiente archivo de configuración predeterminado proporciona valores de prioridad para casos de uso predefinidos. Los usuarios pueden cambiar los valores con un archivo de configuración personalizado.

Caso de uso Primer plano Información general
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Archivo de configuración personalizado

Los proveedores pueden personalizar el archivo de configuración /vendor/etc/tunerResourceManagerUseCaseConfig.xml. Este archivo se usa para agregar, quitar o actualizar los tipos de casos de uso y los valores de prioridad de los casos de uso. El archivo personalizado puede usar platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml como plantilla.

Por ejemplo, un caso de uso de proveedor nuevo es VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]. El formato debe seguir platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd.

Valor de prioridad arbitrario y valor agradable

La TRM proporciona updateClientPriority para que el cliente actualice el valor de prioridad y el valor de prioridad agradable. El valor de prioridad arbitrario reemplaza el valor de prioridad calculado a partir del tipo de caso de uso y el ID de sesión.

El valor de nice indica qué tan indulgente es el comportamiento del cliente cuando está en conflicto con otro cliente. El valor agradable disminuye el valor de prioridad del cliente antes de que se compare con el cliente desafiante.

Mecanismo de recuperación

En el siguiente diagrama, se muestra cómo se recuperan y asignan los recursos cuando se produce un conflicto de recursos.

Diagrama del proceso del mecanismo de recuperación.

Figura 15: Diagrama del mecanismo de recuperación para un conflicto entre los recursos de Tuner