Para Android 11 o superior, puede usar el marco de Android Tuner para entregar contenido A/V. El marco utiliza la canalización de hardware de los proveedores, lo que lo hace adecuado tanto para SoC de gama baja como de gama alta. El marco proporciona una forma segura de entregar contenido A/V protegido por un entorno de ejecución confiable (TEE) y una ruta segura de medios (SMP), lo que permite su uso en un entorno de protección de contenido altamente restringido.
La interfaz estandarizada entre Tuner y Android CAS da como resultado una integración más rápida entre los proveedores de Tuner y los proveedores de CAS. La interfaz Tuner funciona con MediaCodec
y AudioTrack
para crear una solución mundial para Android TV. La interfaz del sintonizador es compatible tanto con la televisión digital como con la televisión analógica según los principales estándares de transmisión.
Componentes
Para Android 11, tres componentes están diseñados específicamente para la plataforma de TV.
- Tuner HAL: una interfaz entre el marco y los proveedores
- Tuner SDK API: una interfaz entre el marco y las aplicaciones
- Tuner Resource Manager (TRM): coordina los recursos de hardware del sintonizador
Para Android 11, se han mejorado 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 multimedia -
AudioTrack
o pista de audio -
MediaResourceManager
o administrador de recursos de medios (MRM)
Figura 1. Interacciones entre los componentes de Android TV
Características
Frontend es compatible con los estándares DTV a continuación.
- ATSC
- ATSC3
- TDT C/S/T
- ISDB S/S3/T
- Cosa análoga
La interfaz de Android 12 con Tuner HAL 1.1 o superior es compatible con el estándar DTV a continuación.
- DTMB
Demux es compatible con los protocolos de transmisión a continuación.
- Flujo de transporte (TS)
- Protocolo de transporte de medios MPEG (MMTP)
- Protocolo de Internet (IP)
- Valor de longitud de tipo (TLV)
- Protocolo de capa de enlace ATSC (ALP)
Descrambler admite las siguientes protecciones de contenido.
- Ruta segura de medios
- Borrar ruta de medios
- Registro local seguro
- Reproducción local segura
Las API de Tuner son compatibles con los siguientes casos de uso.
- Escanear
- Vivir
- Reproducción
- Registro
Tuner, MediaCodec
y AudioTrack
admiten los siguientes modos de flujo de datos.
- Carga útil ES con búfer de memoria transparente
- Carga útil ES con identificador de memoria seguro
- Pasar por
Diseño general
Tuner HAL se define entre el marco de trabajo de Android y el hardware del proveedor.
- Describe lo que el marco espera del proveedor y cómo podría hacerlo.
- Exporta las funcionalidades de frontend, demux y descrambler al marco a través de
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
eILnb
. - Incluye las funciones para integrar el Tuner HAL con otros componentes del marco, como
MediaCodec
yAudioTrack
.
Se crean una clase Tuner Java y una clase nativa.
- Tuner Java API permite que las aplicaciones accedan a Tuner HAL a través de API 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 Tuner HAL.
- El módulo Native Tuner es un puente entre la clase Tuner Java y Tuner HAL.
Se crea una clase TRM.
- Administra recursos limitados de Tuner, como Frontend, LNB, sesiones CAS y un dispositivo de entrada de TV desde la HAL de entrada de TV.
- Aplica reglas para recuperar recursos insuficientes de las aplicaciones. La regla predeterminada es la victoria en primer plano.
Media CAS y CAS HAL se han mejorado con las siguientes funciones.
- Abre sesiones de CAS para diferentes usos y algoritmos.
- Admite sistemas CAS dinámicos, como la extracción e inserción de CICAM.
- Se integra con Tuner HAL al proporcionar tokens clave.
MediaCodec
y AudioTrack
se han mejorado con las siguientes funciones.
- Toma memoria A/V segura como entrada de contenido.
- Configurado para sincronizar hardware A/V en reproducción en túnel.
- Soporte configurado para
ES_payload
y modo passthrough.
Figura 2. Diagrama de los componentes dentro del Tuner HAL
Flujo de trabajo general
Los siguientes diagramas 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
Manejo de A/V
Figura 4. Manejo de A/V para la reproducción de transmisiones en vivo
Manejo de contenido codificado
Figura 5. Manejo de contenido codificado para la reproducción de transmisiones en vivo
Procesamiento de datos A/V
Figura 6. Procesamiento de A/V para reproducción de transmisiones en vivo
API del sintonizador SDK
La API de Tuner SDK maneja las interacciones con Tuner JNI, Tuner HAL y TunerResourceManager
. La aplicación TIS utiliza la API del SDK de Tuner para acceder a los recursos y subcomponentes de Tuner, como el filtro y el decodificador. Frontend y demux son componentes internos.
Figura 7. Interacciones con la API de Tuner SDK
Versiones
A partir de Android 12, Tuner SDK API admite una nueva función en Tuner HAL 1.1, que es una actualización de versión compatible con versiones anteriores de Tuner 1.0.
Utilice la siguiente API para verificar la versión HAL en ejecución.
-
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
La versión HAL mínima requerida se puede encontrar en la documentación de las nuevas API de Android 12.
Paquetes
La API Tuner SDK proporciona los cuatro paquetes 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 API de Tuner SDK
Android.media.tv.sintonizador
El paquete Tuner es un punto de entrada para usar el marco Tuner. La aplicación TIS usa el paquete para inicializar y adquirir instancias de recursos especificando la configuración inicial y la devolución de llamada.
-
tuner()
: Inicializa una instancia de Tuner especificando los parámetrosuseCase
ysessionId
. -
tune()
: Adquiere un recurso frontend y lo sintoniza 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 descodificador. -
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 funcionalidades que no están cubiertas por los paquetes de filtro, DVR y interfaz. 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 interfaz incluye colecciones de configuraciones, información, estados, eventos y capacidades relacionadas con la interfaz.
Clases
FrontendSettings
se deriva para diferentes estándares de DTV por las clases a continuación.
-
AnalogFrontendSettings
-
Atsc3FrontendSettings
-
AtscFrontendSettings
-
DvbcFrontendSettings
-
DvbsFrontendSettings
-
DvbtFrontendSettings
-
Isdbs3FrontendSettings
-
IsdbsFrontendSettings
-
IsdbtFrontendSettings
A partir de Android 12 con Tuner HAL 1.1 o superior, se admite el siguiente estándar DTV.
-
DtmbFrontendSettings
FrontendCapabilities
se deriva para diferentes estándares de DTV por las clases a continuación.
-
AnalogFrontendCapabilities
-
Atsc3FrontendCapabilities
-
AtscFrontendCapabilities
-
DvbcFrontendCapabilities
-
DvbsFrontendCapabilities
-
DvbtFrontendCapabilities
-
Isdbs3FrontendCapabilities
-
IsdbsFrontendCapabilities
-
IsdbtFrontendCapabilities
A partir de Android 12 con Tuner HAL 1.1 o superior, se admite el siguiente estándar DTV.
-
DtmbFrontendCapabilities
FrontendInfo
recupera la información de la interfaz. FrontendStatus
recupera el estado actual de la interfaz. OnTuneEventListener
escucha los eventos en la interfaz. La aplicación TIS usa ScanCallback
para procesar mensajes de escaneo desde la interfaz.
Escaneo de canales
Para configurar un televisor, la aplicación escanea las posibles frecuencias y crea una lista de canales para que los usuarios accedan. TIS puede usar Tuner.tune
, Tuner.scan(BLIND_SCAN)
o Tuner.scan(AUTO_SCAN)
para completar el escaneo de canales.
Si TIS tiene información de entrega precisa para la señal, como frecuencia, estándar (por ejemplo, T/T2, S/S2) e información adicional necesaria (por ejemplo, PLD ID), entonces se recomienda Tuner.tune
como la opción más rápida .
Cuando el usuario llama a Tuner.tune
, suceden las siguientes acciones:
- TIS llena
FrontendSettings
con la información requerida usandoTuner.tune
. - El HAL informa mensajes de sintonización
LOCKED
si la señal está bloqueada. - TIS utiliza
Frontend.getStatus
para recopilar la información necesaria. - 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, puede llamar a stopTune()
o close()
para pausar o finalizar la llamada Tuner.tune
.
Sintonizador.escaneo(AUTO_SCAN)
Si 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), entonces se recomienda Tuner.scan(AUTO_SCAN)
.
Cuando el usuario llama a Tuner.scan(AUTO_SCAN)
, suceden las siguientes acciones:
TIS usa
Tuner.scan(AUTO_SCAN)
conFrontendSettings
lleno de frecuencia.Los informes HAL escanean mensajes
LOCKED
si la señal está bloqueada. El HAL también podría informar otros mensajes de exploración para proporcionar información adicional sobre la señal.TIS utiliza
Frontend.getStatus
para recopilar la información necesaria.TIS llama a
Tuner.scan
para que HAL continúe con la siguiente configuración en la misma frecuencia. Si la estructuraFrontendSettings
está vacía, HAL usa la siguiente configuración disponible. De lo contrario, HAL usaFrontendSettings
para un escaneo único y envíaEND
para indicar que la operación de escaneo finalizó.TIS repite las acciones anteriores hasta que se agoten todas las configuraciones en la frecuencia.
El HAL envía
END
para indicar que la operación de exploración ha finalizado.TIS pasa a la siguiente frecuencia disponible en su lista de frecuencias.
TIS vuelve a llamar a Tuner.scan(AUTO_SCAN)
hasta agotar todas las frecuencias.
Durante el escaneo, puede llamar a stopScan()
o close()
para pausar o finalizar el escaneo.
Sintonizador.escaneo(BLIND_SCAN)
Si TIS no tiene una lista de frecuencias y el proveedor HAL puede buscar la frecuencia de la interfaz especificada por el usuario para obtener el recurso de la interfaz, entonces se recomienda Tuner.scan(BLIND_SCAN)
.
- TIS usa
Tuner.scan(BLIND_SCAN)
. Se puede especificar una frecuencia enFrontendSettings
para la frecuencia de inicio, pero TIS ignora otras configuraciones enFrontendSettings
. - El HAL informa un mensaje de escaneo
LOCKED
si la señal está bloqueada. - TIS utiliza
Frontend.getStatus
para recopilar la información necesaria. - TIS vuelve a llamar a
Tuner.scan
para continuar escaneando. (FrontendSettings
se ignora). - TIS repite las acciones anteriores hasta que se agoten todas las configuraciones en la frecuencia. El HAL incrementa la frecuencia sin necesidad de ninguna acción por parte de TIS. El HAL informa
PROGRESS
.
TIS vuelve a llamar a Tuner.scan(AUTO_SCAN)
hasta agotar todas las frecuencias. El HAL informa END
para indicar que la operación de exploración ha finalizado.
Durante el escaneo, puede llamar a stopScan()
o close()
para pausar o finalizar el escaneo.
Figura 9. Diagrama de flujo de un escaneo TIS
Android.media.tv.tuner.filtro
El paquete de filtro es una colección de operaciones de filtro junto con configuración, ajustes, devoluciones de llamada y eventos. El paquete incluye las siguientes operaciones. Consulte el código fuente de Android para ver la lista completa de operaciones.
-
configure()
-
start()
-
stop()
-
flush()
-
read()
Consulte el código fuente de Android para ver la lista completa.
FilterConfiguration
se deriva de las clases siguientes. Las configuraciones son para el tipo de filtro principal y especifican qué protocolo usa el filtro para extraer datos.
-
AlpFilterConfiguration
-
IpFilterConfiguration
-
MmtpFilterConfiguration
-
TlvFilterConfiguration
-
TsFilterConfiguration
Los ajustes se derivan de las clases siguientes. 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 para diferentes tipos de datos.
-
SectionEvent
-
MediaEvent
-
PesEvent
-
TsRecordEvent
-
MmtpRecordEvent
-
TemiEvent
-
DownloadEvent
-
IpPayloadEvent
A partir de Android 12 con Tuner HAL 1.1 o superior, se admiten los siguientes eventos.
-
IpCidChangeEvent
-
RestartEvent
-
ScramblingStatusEvent
Eventos y formato de datos del filtro
Tipo de filtro | banderas | 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 | De acuerdo al evento y cronograma interno, correrFilter.read(buffer, offset, adjustedSize) una o más veces.Los datos se copian del MQ de HAL al búfer del cliente. | Un paquete de sesión ensamblado se llena 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 de HAL al búfer del cliente. | ||
TS.PES | isRaw: | Obligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | De acuerdo al evento y cronograma interno, correrFilter.read(buffer, offset, adjustedSize) una o más veces.Los datos se copian desde el MQ de HAL al búfer del cliente. | Un paquete PES ensamblado se llena 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 de HAL al búfer del cliente. | ||
MMTP.PES | isRaw: | Obligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | De acuerdo al evento y cronograma interno, correrFilter.read(buffer, offset, adjustedSize) una o más veces.Los datos se copian desde el MQ de HAL al búfer del cliente. | Un paquete MFU ensamblado se llena 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 desde el 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 | De acuerdo al evento y cronograma interno, correrFilter.read(buffer, offset, adjustedSize) una o más veces.Los datos se copian desde el MQ de HAL al búfer del cliente. | Filtrado ts con encabezado ts se rellena 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 :for i=0; i<n; i++ Para usar Direct Audio de AudioTrack :for i=0; i<n; i++ | ES o datos ES parciales en la memoria 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 datos de índice:for i=0; i<n; i++ Para el contenido grabado , según RecordStatus::* y la programación interna, realice una de las siguientes acciones:
| Para datos de índice: transportados en la carga útil del evento. Para contenido grabado: flujo de TS multiplexado rellenado en 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 | De acuerdo al evento y cronograma interno, correrFilter.read(buffer, offset, adjustedSize) una o más veces.Los datos se copian desde el MQ de HAL al búfer del cliente. | Filtrado mmtp con encabezado mmtp se rellena 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 datos de índice: for i=0; i<n; i++ Para el contenido grabado , según RecordStatus::* y la programación interna, realice una de las siguientes acciones:
| Para datos de índice: transportados en la carga útil del evento. Para contenido grabado: transmisión grabada multiplexada completada en FMQ. Si el origen del filtro para la grabación es TLV.TLV a IP.IP con transferencia, el flujo grabado tiene un encabezado IP y TLV. |
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. | 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 de HAL al búfer del cliente. | El paquete de carga útil de IP se completa en FMQ con otro paquete de carga útil de IP. |
IP.IP TLV.TLV ALP.ALP | isPassthrough: | Opcional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | El subflujo 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 | De acuerdo al evento y cronograma interno, correrFilter.read(buffer, offset, adjustedSize) una o más veces.Los datos se copian desde el MQ de HAL al búfer del cliente. | El flujo secundario de protocolo filtrado con encabezado de 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 filtrado alimenta el siguiente filtro en la cadena de filtros. | N / A |
Flujo de ejemplo para usar el filtro para construir PSI/SI
Figura 10. Flujo para construir PSI/SI
Abre un filtro.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
Configure e inicie 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();
Proceso
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); } } } };
Flujo de ejemplo para usar MediaEvent desde el filtro
Figura 11. Flujo para usar MediaEvent desde el filtro
- Abra, configure e inicie los filtros A/V.
- Procesar
MediaEvent
. - Recibir
MediaEvent
. - Ponga en cola el bloque lineal al
codec
. - Suelte el controlador A/V cuando se hayan consumido los datos.
Android.media.tv.tuner.dvr
DvrRecorder
proporciona estos métodos para grabar.
-
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 utiliza para configurar DvrRecorder
y DvrPlayback
. OnPlaybackStatusChangedListener
y OnRecordStatusChangedListener
se utilizan para informar el estado de una instancia de DVR.
Flujo de ejemplo para iniciar un registro
Figura 12. Flujo para iniciar un registro
Abra, configure e inicie
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();
Reciba
RecordEvent
y recupere 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. } } } };
Inicialice
OnRecordStatusChangedListener
y almacene 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); } } };
Sintonizador HAL
Tuner HAL sigue HIDL y define la interfaz entre el marco y el hardware del proveedor. Los proveedores usan la interfaz para implementar Tuner HAL y el marco la usa para comunicarse con la implementación de Tuner HAL.
Módulos
Sintonizador HAL 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 CiCam | IDemux.hal |
IDvr | close , start , stop , configure | attach/detachFilters , getQueueDesc , flush | IDvr.hal IDvrCallback.hal |
IFilter | close , start , stop , configure , getId | setDataSource , flush , getQueueDesc , releaseAvHandle | IFilter.hal IFilterCallback.hal |
ILnb | close , setCallback de llamada | 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 Tuner HAL
Enlace de filtro
Tuner HAL admite la vinculación de filtros de modo que los filtros se pueden vincular a otros filtros para múltiples capas. Los filtros siguen las reglas a continuación.
- Los filtros están vinculados como un árbol, no se permite cerrar la ruta.
- El nodo raíz es demux.
- Los filtros funcionan de forma independiente.
- Todos los filtros comienzan a obtener datos.
- El enlace del filtro descarga el último filtro.
El bloque de código a continuación y la Figura 14 ilustran 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 un enlace de filtro para múltiples capas
Administrador de recursos del sintonizador
Antes de Tuner Resource Manager (TRM), cambiar entre dos aplicaciones requería el mismo hardware Tuner. TV Input Framework (TIF) usó un mecanismo de "ganador primero en adquirir", lo que significa que la aplicación que obtiene el recurso primero se queda con el recurso. Sin embargo, este mecanismo podría no ser ideal para algunos casos de uso complicados.
TRM se ejecuta como un servicio del sistema para administrar los recursos de hardware Tuner, TVInput
y CAS para las aplicaciones. TRM utiliza un mecanismo de "ganancia en primer plano", que calcula la prioridad de la aplicación según el estado de primer plano o segundo plano de la aplicación y el tipo de caso de uso. TRM otorga o revoca el recurso en función de la prioridad. TRM centraliza la gestión de recursos de ATV para transmisión, OTT y DVR.
interfaz TRM
TRM expone las interfaces AIDL en ITunerResourceManager.aidl
para el marco Tuner, MediaCas
y TvInputHardwareManager
para registrar, solicitar o liberar recursos.
Las interfaces para la gestión de clientes se enumeran a continuación.
-
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
-
unregisterClientProfile(in int clientId)
Las interfaces para solicitar y liberar recursos se enumeran a continuación.
-
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
Las clases de clientes y solicitudes se enumeran a continuación.
-
ResourceClientProfile
-
ResourcesReclaimListener
-
TunerFrontendRequest
-
TunerDemuxRequest
-
TunerDescramblerRequest
-
CasSessionRequest
-
TunerLnbRequest
prioridad del cliente
TRM calcula la prioridad del cliente mediante el uso de parámetros del perfil del cliente y el valor de prioridad del archivo de configuración. La prioridad también puede actualizarse mediante un valor de prioridad arbitrario del cliente.
Parámetros en el perfil del cliente
TRM recupera el ID del proceso de mTvInputSessionId
para decidir si una aplicación es una aplicación en primer plano o en segundo plano. Para crear mTvInputSessionId
, TvInputService.onCreateSession
o TvInputService.onCreateRecordingSession
inicializa una sesión 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 archivo de configuración predeterminado a continuación proporciona valores de prioridad para casos de uso predefinidos. Los usuarios pueden cambiar los valores mediante un archivo de configuración personalizado .
caso de uso | Primer plano | Fondo |
---|---|---|
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 utiliza para agregar, eliminar 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 nuevo caso de uso de proveedor es VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
. El formato debe seguir el siguiente platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
.
Valor de prioridad arbitrario y buen valor
TRM proporciona updateClientPriority
para que el cliente actualice el valor de prioridad arbitrario y el valor agradable. El valor de prioridad arbitrario sobrescribe el valor de prioridad calculado a partir del tipo de caso de uso y el ID de sesión.
El valor agradable indica cuán 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 su valor de prioridad se compare con el del cliente desafiante.
mecanismo de recuperación
El siguiente diagrama muestra cómo se reclaman y asignan los recursos cuando ocurre un conflicto de recursos.
Figura 15. Diagrama del mecanismo de reclamación para un conflicto entre recursos Tuner