En Android 11 o versiones posteriores, puedes usar el framework de Tuner de Android para entregar contenido A/V. El framework usa la canalización de hardware de los proveedores, lo que lo hace adecuado para los 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 de medios segura (SMP), lo que permite que se use en un entorno de protección de contenido muy restringido.
La interfaz estandarizada entre Tuner y Android CAS permite una integración más rápida entre los proveedores de Tuner y los proveedores de CAS. La interfaz de Tuner funciona con MediaCodec
y AudioTrack
para crear una solución global para Android TV.
La interfaz del sintonizador admite tanto la TV digital como la analógica según los principales estándares de transmisión.
Componentes
En Android 11, se diseñaron tres componentes 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.
- Tuner Resource Manager (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 Servicio de administrador de entrada de TV (TIMS)MediaCodec
o códec de mediosAudioTrack
o pista de audioMediaResourceManager
o administrador de recursos multimedia (MRM)
Figura 1: Interacciones entre los 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 en Android 12 con Tuner HAL 1.1 o versiones posteriores admite el estándar de DTV que se indica a continuación.
- DTMB
Demux admite los siguientes protocolos de transmisión:
- Flujo de transporte (TS)
- Protocolo de transporte de medios MPEG (MMTP)
- Protocolo de Internet (IP)
- Valor de longitud del tipo (TLV)
- Protocolo de capa de vínculo de ATSC (ALP)
El decodificador admite las siguientes protecciones de contenido.
- Ruta de medios segura
- Ruta de medios clara
- Registro local seguro
- Reproducción local segura
Las APIs del sintonizador admiten los casos de uso que se indican a continuación.
- Escanear
- En vivo
- Reproducción
- Grabar
Los elementos Tuner, MediaCodec
y AudioTrack
admiten los siguientes modos de flujo de datos.
- Carga útil de ES con búfer de memoria claro
- Carga útil de ES con identificador de memoria seguro
- Modo de cámara externa
Diseño general
El HAL del sintonizador se define entre el framework de Android y el hardware del proveedor.
- Describe lo que el marco espera del proveedor y cómo este podría hacerlo.
- Exporta las funcionalidades de frontend, demux y descrambler al framework a través de las interfaces
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
yILnb
. - Incluye las funciones para integrar el HAL de Tuner con otros componentes del framework, como
MediaCodec
yAudioTrack
.
Se crean una clase Tuner de Java y una clase nativa.
- La API de Tuner para Java permite que las apps accedan a Tuner HAL a través de APIs públicas.
- La clase nativa permite el control de permisos y el procesamiento de grandes cantidades de datos de grabación o reproducción con el HAL de Tuner.
- El módulo Native Tuner es un puente entre la clase Tuner de Java y el HAL de Tuner.
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 medios y el HAL de CAS se mejoraron con las siguientes funciones.
- Abre sesiones de CAS para diferentes usos y algoritmos.
- Admite sistemas CAS dinámicos, como la inserción y extracción de CICAM.
- Se integra con el HAL del sintonizador proporcionando tokens clave.
MediaCodec
y AudioTrack
se mejoraron con las siguientes funciones.
- Toma la memoria A/V segura como entrada de contenido.
- Se configura 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.
Figura 2: Diagrama de los componentes dentro del 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
Figura 3: Secuencia de configuración para la reproducción de transmisiones en vivo
Manipulación de equipos audiovisuales
Figura 4: Cómo controlar el A/V para la reproducción de transmisiones en vivo
Cómo controlar el contenido codificado
Figura 5: Cómo controlar el contenido codificado para la reproducción de transmisiones en vivo
Procesamiento de datos de A/V
Figura 6: Procesamiento de A/V para la reproducción de transmisiones en vivo
API del SDK del sintonizador
La API del SDK de Tuner controla las interacciones con Tuner JNI, Tuner HAL 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. Los componentes internos son el frontend y el demux.
Figura 7: Interacciones con la API del SDK de Tuner
Versiones
A partir de Android 12, la API del SDK de Tuner admite nuevas funciones 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 del HAL en ejecución.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
La versión mínima requerida del HAL se puede encontrar 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
Figura 8: Paquetes de la API del SDK de Tuner
Android.media.tv.tuner
El paquete 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()
: Inicializa una instancia de Tuner especificando los parámetrosuseCase
ysessionId
.tune()
: Adquiere un recurso de frontend y lo ajusta especificando el parámetroFrontendSetting
.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 de LNB interna.openLnbByName()
: Adquiere una instancia de LNB externa.openTimeFilter()
: Adquiere una instancia de filtro de tiempo.
El paquete Tuner proporciona funcionalidades que no se incluyen en los paquetes de filtro, DVR y frontend. Las funcionalidades 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 siguientes clases.
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 del frontend.
Búsqueda de canales
Para configurar una TV, la app analiza las frecuencias posibles y crea una lista de canales a la que los usuarios pueden acceder. El TIS puede usar Tuner.tune
, Tuner.scan(BLIND_SCAN)
o Tuner.scan(AUTO_SCAN)
para completar el análisis del canal.
Si el TIS tiene información de entrega precisa para el canal, como la frecuencia, el estándar (por ejemplo, T/T2, S/S2) y la información adicional necesaria (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
, suceden las siguientes acciones:
- El TIS completa
FrontendSettings
con la información requerida usandoTuner.tune
. - El HAL informa mensajes de ajuste
LOCKED
si el indicador está bloqueado. - El TIS usa
Frontend.getStatus
para recopilar la información necesaria. - El TIS se mueve a la siguiente frecuencia disponible en su lista de frecuencias.
El TIS vuelve a llamar a Tuner.tune
hasta que se agotan todas las frecuencias.
Durante el ajuste, puedes llamar a stopTune()
o close()
para pausar o finalizar la llamada de 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)
, suceden las siguientes acciones:
El TIS usa
Tuner.scan(AUTO_SCAN)
conFrontendSettings
completado con la frecuencia.El HAL informa mensajes de
LOCKED
si el indicador está bloqueado. El HAL también puede informar otros mensajes de análisis para proporcionar información adicional sobre la señal.El TIS usa
Frontend.getStatus
para recopilar la información necesaria.La 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 estructuraFrontendSettings
está vacía, el HAL usa el siguiente parámetro de configuración disponible. De lo contrario, el HAL usaFrontendSettings
para un análisis único y envíaEND
para indicar que finalizó la operación de análisis.El TIS repite las acciones anteriores hasta que se agota toda la configuración de la frecuencia.
El HAL envía
END
para indicar que finalizó la operación de análisis.El TIS se mueve a la siguiente frecuencia disponible en su lista de frecuencias.
El TIS vuelve a llamar a Tuner.scan(AUTO_SCAN)
hasta que se agotan todas las frecuencias.
Durante el análisis, puedes llamar a stopScan()
o close()
para pausar o finalizar el análisis.
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)
.
- El TIS usa
Tuner.scan(BLIND_SCAN)
. Se puede especificar una frecuencia enFrontendSettings
para la frecuencia de inicio, pero el TIS ignora otros parámetros de configuración enFrontendSettings
. - El HAL informa un mensaje de
LOCKED
de búsqueda si se bloquea la señal. - El TIS usa
Frontend.getStatus
para recopilar la información necesaria. - El TIS vuelve a llamar a
Tuner.scan
para continuar con el análisis. (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 el TIS deba realizar ninguna acción.
El HAL informa
PROGRESS
.
El TIS vuelve a llamar a Tuner.scan(AUTO_SCAN)
hasta que se agotan todas las frecuencias.
El HAL informa END
para indicar que finalizó la operación de análisis.
Durante el análisis, puedes llamar a stopScan()
o close()
para pausar o finalizar el análisis.
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 filtrado junto con la configuración, los parámetros, 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. Los parámetros de configuración son para el tipo de filtro principal y especifican qué protocolo usa el filtro para extraer datos.
AlpFilterConfiguration
IpFilterConfiguration
MmtpFilterConfiguration
TlvFilterConfiguration
TsFilterConfiguration
Los parámetros de configuración se derivan 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 siguientes clases 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
Eventos y formato de 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: |
Obligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Según el evento y el programa interno, ejecutaFilter.read(buffer, offset, adjustedSize) una o más
veces.Los datos se copian del MQ del HAL al búfer del cliente. |
Un paquete de sesión ensamblado se completa en FMQ con otro paquete de sesión. |
isRaw: |
Obligatorio:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Los datos se copian del MQ del HAL al búfer del cliente. |
||
TS.PES |
isRaw: |
Obligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Según el evento y el programa interno, ejecutaFilter.read(buffer, offset, adjustedSize) una o más
veces.Los datos se copian de la MQ del HAL al búfer del cliente. |
Un paquete PES ensamblado se completa en FMQ con otro paquete PES. |
isRaw: |
Obligatorio:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Los datos se copian del MQ del HAL al búfer del cliente. |
||
MMTP.PES |
isRaw: |
Obligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Según el evento y el programa interno, ejecutaFilter.read(buffer, offset, adjustedSize) una o más
veces.Los datos se copian del MQ del HAL al búfer del cliente. |
Un paquete MFU ensamblado se completa en FMQ con otro paquete MFU. |
isRaw: |
Obligatorio:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Los datos se copian del MQ del 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, ejecutaFilter.read(buffer, offset, adjustedSize) una o más
veces.Los datos se copian del MQ del HAL al búfer del cliente. |
Se filtró ts con el encabezado ts se completa en FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
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: |
Obligatorio:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Para usar MediaCodec , haz lo siguiente:for i=0; i<n; i++ Para usar el audio directo de AudioTrack , haz lo siguiente:for i=0; i<n; i++ |
Datos de ES o datos parciales de ES 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 de índice:for i=0; i<n; i++ Para el contenido grabado, según el RecordStatus::* y el programa interno, haz una de las siguientes acciones:
|
Para los datos del índice: Se incluyen en la carga útil del evento. Para el contenido grabado: Se completó el flujo de TS multiplexado 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++ |
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, ejecutaFilter.read(buffer, offset, adjustedSize) una o más
veces.Los datos se copian del MQ del HAL al búfer del cliente. |
Se filtró 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 de índice: for i=0; i<n; i++ Para el contenido grabado, según el cronograma interno y RecordStatus::* , haz una de las siguientes acciones:
|
Para los datos del í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 TLV.TLV a
IP.IP con transferencia, el flujo grabado tiene un
encabezado de TLV y de 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 del HAL al búfer del cliente. |
El paquete de descarga se completa en FMQ con otro paquete de descarga de IP. |
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 del HAL al búfer del cliente. |
Otro paquete de carga útil de IP llena el paquete de carga útil de IP en FMQ. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Opcional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
El sub flujo de protocolo filtrado alimenta el siguiente filtro en la cadena de filtros. | N/A |
isPassthrough: |
Obligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Según el evento y el programa interno, ejecutaFilter.read(buffer, offset, adjustedSize) una o más
veces.Los datos se copian del MQ del HAL al búfer del cliente. |
Se filtró el subflujo de protocolo con el encabezado de protocolo completado. FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
N/A | Opcional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
La carga útil del protocolo filtrado alimenta el siguiente filtro en la cadena de filtros. | N/A |
Ejemplo de flujo para usar el filtro y compilar PSI/SI
Figura 10: Flujo para compilar PSI/SI
Abre un filtro.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
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();
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
Figura 11: Flujo para usar MediaEvent desde el filtro
- Abre, configura y, luego, inicia los filtros de A/V.
- Procesa
MediaEvent
. - Recibe
MediaEvent
. - Pon en cola el bloque lineal en
codec
. - Libera el identificador 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 una grabación
Figura 12: Flujo para iniciar un registro
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();
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. } } } };
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 la HAL del sintonizador, y el framework la usa para comunicarse con la implementación de la HAL del sintonizador.
Módulos
HAL del 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 |
Figura 13: Diagrama de las interacciones entre los módulos HAL del sintonizador
Vinculación de filtros
El HAL del sintonizador admite la vinculación de filtros, de modo que los filtros se pueden vincular a otros filtros para varias capas. Los filtros siguen las reglas que se indican a continuación.
- Los filtros se vinculan 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 recibir datos.
- La vinculación del filtro se vacía en el último filtro.
En el siguiente bloque de código y en la Figura 14, se ilustra un ejemplo de filtrado de 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>)
}
Figura 14: Diagrama de flujo de una vinculación de filtros para varias capas
Administrador de recursos del sintonizador
Antes de Tuner Resource Manager (TRM), cambiar entre dos apps requería el mismo hardware del sintonizador. El TV Input Framework (TIF) usaba un mecanismo de "el primero en adquirir gana", lo que significa que la app que obtiene el recurso primero se lo queda. 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. TRM usa un mecanismo de "ganancia 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. El TRM otorga o revoca el recurso según la prioridad. El TRM centraliza la administración de recursos de ATV para transmisiones, OTT y DVR.
Interfaz de TRM
El TRM expone interfaces de AIDL en ITunerResourceManager.aidl
para el framework de Tuner, MediaCas
y TvInputHardwareManager
para registrar, solicitar o liberar 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 de solicitud.
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
Prioridad del cliente
El TRM calcula la prioridad del cliente con parámetros del perfil del cliente y el valor de prioridad del archivo de configuración. El cliente también puede actualizar la prioridad con un valor arbitrario.
Parámetros en el perfil del cliente
TRM recupera el ID del proceso de mTvInputSessionId
para decidir si una app es de primer o segundo plano. Para crear mTvInputSessionId
, TvInputService.onCreateSession
o TvInputService.onCreateRecordingSession
inicializa una sesión de TIS.
mUseCase
indica el caso de uso de la sesión. A continuación, se indican los casos de uso predefinidos.
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 un 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
TRM proporciona updateClientPriority
para que el cliente actualice el valor de prioridad arbitrario y el valor de cortesía.
El valor de prioridad arbitrario anula el valor de prioridad calculado a partir del tipo de caso de uso y el ID de sesión.
El valor de cortesía indica qué tan tolerante es el comportamiento del cliente cuando entra en conflicto con otro cliente. El valor de nice disminuye el valor de prioridad del cliente antes de que se compare con el del 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.
Figura 15: Diagrama del mecanismo de recuperación para un conflicto entre recursos de Tuner