Per Android 11 o versioni successive, puoi utilizzare il framework Android Tuner per fornire contenuti A/V. Il framework utilizza la pipeline hardware dei fornitori, rendendolo adatto sia per SoC di fascia bassa che di fascia alta. Il framework fornisce un modo sicuro per fornire contenuto A/V protetto da un ambiente di esecuzione attendibile (TEE) e un percorso multimediale sicuro (SMP), consentendone l'uso in un ambiente di protezione dei contenuti altamente limitato.
L'interfaccia standardizzata tra Tuner e Android CAS si traduce in un'integrazione più rapida tra i fornitori di Tuner e i fornitori di CAS. L'interfaccia del sintonizzatore funziona con MediaCodec
e AudioTrack
per creare una soluzione unica per Android TV. L'interfaccia Tuner supporta sia la TV digitale che la TV analogica in base ai principali standard di trasmissione.
Componenti
Per Android 11, tre componenti sono progettati specificamente per la piattaforma TV.
- Tuner HAL: un'interfaccia tra il framework e i fornitori
- API Tuner SDK: un'interfaccia tra il framework e le app
- Tuner Resource Manager (TRM): coordina le risorse HW del sintonizzatore
Per Android 11, i seguenti componenti sono stati migliorati.
- CAS V2
-
TvInputService
o TV Input Service (TIS) -
TvInputManagerService
o TV Input Manager Service (TIMS) -
MediaCodec
o media codec -
AudioTrack
o traccia audio -
MediaResourceManager
o gestore delle risorse multimediali (MRM)
Figura 1. Interazioni tra i componenti di Android TV
Caratteristiche
Frontend supporta gli standard DTV di seguito.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analogico
Il frontend in Android 12 con Tuner HAL 1.1 o versioni successive supporta lo standard DTV di seguito.
- DTMB
Demux supporta i protocolli di flusso riportati di seguito.
- Flusso di trasporto (TS)
- Protocollo di trasporto multimediale MPEG (MMTP)
- Protocollo Internet (IP)
- Digitare il valore della lunghezza (TLV)
- Protocollo a livello di collegamento ATSC (ALP)
Descrambler supporta le protezioni dei contenuti di seguito.
- Percorso multimediale sicuro
- Cancella percorso multimediale
- Registro locale sicuro
- Riproduzione locale sicura
Le API del sintonizzatore supportano i casi d'uso riportati di seguito.
- Scansione
- Abitare
- Riproduzione
- Disco
Tuner, MediaCodec
e AudioTrack
supportano le modalità di flusso di dati seguenti.
- Carico utile ES con buffer di memoria libero
- Carico utile ES con handle di memoria sicuro
- Passaggio
Design generale
Il Tuner HAL è definito tra il framework Android e l'hardware del fornitore.
- Descrive cosa si aspetta il framework dal fornitore e come il fornitore potrebbe farlo.
- Esporta le funzionalità di frontend, demux e descrambler nel framework tramite
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
eILnb
. - Include le funzioni per integrare il Tuner HAL con altri componenti del framework, come
MediaCodec
eAudioTrack
.
Vengono create una classe Tuner Java e una classe nativa.
- L'API Tuner Java consente alle app di accedere a Tuner HAL tramite API pubbliche.
- La classe nativa consente il controllo delle autorizzazioni e la gestione di grandi quantità di dati di registrazione o riproduzione con il sintonizzatore HAL.
- Il modulo Native Tuner è un ponte tra la classe Tuner Java e Tuner HAL.
Viene creata una classe TRM.
- Gestisce risorse sintonizzatore limitate, come sessioni Frontend, LNB, CAS e un dispositivo di ingresso TV dall'ingresso TV HAL.
- Applica le regole per recuperare risorse insufficienti dalle app. La regola predefinita è la vittoria in primo piano.
Media CAS e CAS HAL sono migliorati con le funzionalità seguenti.
- Apre sessioni CAS per diversi usi e algoritmi.
- Supporta sistemi CAS dinamici, come la rimozione e l'inserimento di CICAM.
- Si integra con il sintonizzatore HAL fornendo token chiave.
MediaCodec
e AudioTrack
sono migliorati con le funzionalità seguenti.
- Prende la memoria A/V sicura come input di contenuto.
- Configurato per eseguire la sincronizzazione A/V hardware nella riproduzione con tunnel.
- Supporto configurato per
ES_payload
e modalità passthrough.
Figura 2. Schema dei componenti all'interno del Tuner HAL
Flusso di lavoro generale
I diagrammi seguenti illustrano le sequenze di chiamata per la riproduzione della trasmissione in diretta.
Impostare
Figura 3. Sequenza di configurazione per la riproduzione della trasmissione in diretta
Gestire A/V
Figura 4. Gestione di A/V per la riproduzione di trasmissioni in diretta
Gestione dei contenuti criptati
Figura 5. Gestione del contenuto criptato per la riproduzione della trasmissione in diretta
Elaborazione di dati A/V
Figura 6. Elaborazione A/V per la riproduzione di trasmissioni in diretta
API dell'SDK del sintonizzatore
L'API Tuner SDK gestisce le interazioni con Tuner JNI, Tuner HAL e TunerResourceManager
. L'app TIS utilizza l'API Tuner SDK per accedere alle risorse e ai sottocomponenti del sintonizzatore, come il filtro e il decodificatore. Frontend e demux sono componenti interni.
Figura 7. Interazioni con l'API Tuner SDK
Versioni
Da Android 12, l'API Tuner SDK supporta la nuova funzionalità in Tuner HAL 1.1, che è un aggiornamento della versione compatibile con le versioni precedenti di Tuner 1.0.
Utilizzare la seguente API per verificare la versione HAL in esecuzione.
-
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
La versione HAL minima richiesta può essere trovata nella documentazione delle nuove API di Android 12.
Pacchi
L'API Tuner SDK fornisce i quattro pacchetti seguenti.
-
android.media.tv.tuner
-
android.media.tv.tuner.frontend
-
android.media.tv.tuner.filter
-
android.media.tv.tuner.dvr
Figura 8. Pacchetti API Tuner SDK
Sintonizzatore.media.tv Android
Il pacchetto Tuner è un punto di ingresso per utilizzare il framework Tuner. L'app TIS usa il pacchetto per inizializzare e acquisire istanze di risorse specificando l'impostazione iniziale e il callback.
-
tuner()
: inizializza un'istanza di Tuner specificando i parametriuseCase
esessionId
. -
tune()
: acquisisce una risorsa frontend e ottimizza specificando il parametroFrontendSetting
. -
openFilter()
: acquisisce un'istanza di filtro specificando il tipo di filtro. -
openDvrRecorder()
: acquisisce un'istanza di registrazione specificando la dimensione del buffer. -
openDvrPlayback()
: acquisisce un'istanza di riproduzione specificando la dimensione del buffer. -
openDescrambler()
: acquisisce un'istanza di descrambler. -
openLnb()
: acquisisce un'istanza LNB interna. -
openLnbByName()
: acquisisce un'istanza LNB esterna. -
openTimeFilter()
: acquisisce un'istanza di filtro temporale.
Il pacchetto Tuner fornisce funzionalità che non sono coperte dai pacchetti filtro, DVR e frontend. Le funzionalità sono elencate di seguito.
-
cancelTuning
-
scan
/cancelScanning
-
getAvSyncHwId
-
getAvSyncTime
-
connectCiCam1
/disconnectCiCam
-
shareFrontendFromTuner
-
updateResourcePriority
-
setOnTuneEventListener
-
setResourceLostListener
Android.media.tv.tuner.frontend
Il pacchetto frontend include raccolte di impostazioni, informazioni, stati, eventi e funzionalità relativi al frontend.
Classi
FrontendSettings
è derivato per diversi standard DTV dalle classi seguenti.
-
AnalogFrontendSettings
-
Atsc3FrontendSettings
-
AtscFrontendSettings
-
DvbcFrontendSettings
-
DvbsFrontendSettings
-
DvbtFrontendSettings
-
Isdbs3FrontendSettings
-
IsdbsFrontendSettings
-
IsdbtFrontendSettings
Da Android 12 con Tuner HAL 1.1 o successivo, è supportato il seguente standard DTV.
-
DtmbFrontendSettings
FrontendCapabilities
è derivato per diversi standard DTV dalle classi seguenti.
-
AnalogFrontendCapabilities
-
Atsc3FrontendCapabilities
-
AtscFrontendCapabilities
-
DvbcFrontendCapabilities
-
DvbsFrontendCapabilities
-
DvbtFrontendCapabilities
-
Isdbs3FrontendCapabilities
-
IsdbsFrontendCapabilities
-
IsdbtFrontendCapabilities
Da Android 12 con Tuner HAL 1.1 o successivo, è supportato il seguente standard DTV.
-
DtmbFrontendCapabilities
FrontendInfo
recupera le informazioni del frontend. FrontendStatus
recupera lo stato corrente del frontend. OnTuneEventListener
ascolta gli eventi sul frontend. L'app TIS utilizza ScanCallback
per elaborare i messaggi di scansione dal frontend.
Scansione dei canali
Per configurare una TV, l'app scansiona le possibili frequenze e crea una scaletta di canali a cui gli utenti possono accedere. TIS potrebbe utilizzare Tuner.tune
, Tuner.scan(BLIND_SCAN)
o Tuner.scan(AUTO_SCAN)
per completare la scansione dei canali.
Se TIS dispone di informazioni di consegna accurate per il segnale, come frequenza, standard (ad esempio, T/T2, S/S2) e informazioni aggiuntive necessarie (ad esempio, PLD ID), Tuner.tune
è l'opzione più veloce consigliata .
Quando l'utente chiama Tuner.tune
, si verificano le seguenti azioni:
- TIS popola
FrontendSettings
con le informazioni richieste utilizzandoTuner.tune
. - L'HAL segnala i messaggi di sintonizzazione
LOCKED
se il segnale è bloccato. - TIS utilizza
Frontend.getStatus
per raccogliere le informazioni necessarie. - TIS passa alla successiva frequenza disponibile nell'elenco delle frequenze.
TIS chiama nuovamente Tuner.tune
finché tutte le frequenze non sono esaurite.
Durante l'ottimizzazione, puoi chiamare stopTune()
o close()
per mettere in pausa o terminare la chiamata Tuner.tune
.
Tuner.scan(AUTO_SCAN)
Se TIS non dispone di informazioni sufficienti per utilizzare Tuner.tune
, ma ha un elenco di frequenze e un tipo standard (ad esempio, DVB T/C/S), si Tuner.scan(AUTO_SCAN)
.
Quando l'utente chiama Tuner.scan(AUTO_SCAN)
, si verificano le seguenti azioni:
TIS utilizza
Tuner.scan(AUTO_SCAN)
conFrontendSettings
pieno di frequenza.I rapporti HAL scansionano i messaggi
LOCKED
se il segnale è bloccato. L'HAL potrebbe anche segnalare altri messaggi di scansione per fornire informazioni aggiuntive sul segnale.TIS utilizza
Frontend.getStatus
per raccogliere le informazioni necessarie.TIS chiama
Tuner.scan
affinché l'HAL continui all'impostazione successiva sulla stessa frequenza. Se la strutturaFrontendSettings
è vuota, l'HAL utilizza la successiva impostazione disponibile. In caso contrario, HAL utilizzaFrontendSettings
per una scansione una tantum e inviaEND
per indicare che l'operazione di scansione è terminata.TIS ripete le azioni precedenti fino a quando tutte le impostazioni sulla frequenza non sono esaurite.
L'HAL invia
END
per indicare che l'operazione di scansione è terminata.TIS passa alla successiva frequenza disponibile nell'elenco delle frequenze.
TIS chiama Tuner.scan(AUTO_SCAN)
finché tutte le frequenze non sono esaurite.
Durante la scansione, puoi chiamare stopScan()
o close()
per mettere in pausa o terminare la scansione.
Tuner.scan(BLIND_SCAN)
Se TIS non dispone di un elenco di frequenze e il fornitore HAL può cercare la frequenza del frontend specificato dall'utente per ottenere la risorsa frontend, si Tuner.scan(BLIND_SCAN)
.
- TIS utilizza
Tuner.scan(BLIND_SCAN)
. È possibile specificare una frequenza inFrontendSettings
per la frequenza iniziale, ma TIS ignora le altre impostazioni inFrontendSettings
. - L'HAL segnala un messaggio di scansione
LOCKED
se il segnale è bloccato. - TIS utilizza
Frontend.getStatus
per raccogliere le informazioni necessarie. - TIS chiama nuovamente
Tuner.scan
per continuare la scansione. (FrontendSettings
viene ignorato.) - TIS ripete le azioni precedenti fino a quando tutte le impostazioni sulla frequenza non sono esaurite. L'HAL incrementa la frequenza senza che sia necessaria alcuna azione da parte di TIS. L'HAL riporta
PROGRESS
.
TIS chiama Tuner.scan(AUTO_SCAN)
finché tutte le frequenze non sono esaurite. L'HAL riporta END
per indicare che l'operazione di scansione è terminata.
Durante la scansione, puoi chiamare stopScan()
o close()
per mettere in pausa o terminare la scansione.
Figura 9. Diagramma di flusso di una scansione TIS
Android.media.tv.tuner.filter
Il pacchetto di filtri è una raccolta di operazioni di filtro insieme a configurazione, impostazioni, callback ed eventi. Il pacchetto include le operazioni seguenti. Fare riferimento al codice sorgente di Android per l'elenco completo delle operazioni.
-
configure()
-
start()
-
stop()
-
flush()
-
read()
Fare riferimento al codice sorgente di Android per l'elenco completo.
FilterConfiguration
è derivato dalle classi seguenti. Le configurazioni sono per il tipo di filtro principale e specificano quale protocollo utilizza il filtro per estrarre i dati.
-
AlpFilterConfiguration
-
IpFilterConfiguration
-
MmtpFilterConfiguration
-
TlvFilterConfiguration
-
TsFilterConfiguration
Le impostazioni sono derivate dalle classi seguenti. Le impostazioni riguardano il sottotipo di filtro e specificano i tipi di dati che il filtro può escludere.
-
SectionSettings
-
AvSettings
-
PesSettings
-
RecordSettings
-
DownloadSettings
FilterEvent
è derivato dalle classi seguenti per segnalare eventi per diversi tipi di dati.
-
SectionEvent
-
MediaEvent
-
PesEvent
-
TsRecordEvent
-
MmtpRecordEvent
-
TemiEvent
-
DownloadEvent
-
IpPayloadEvent
Da Android 12 con Tuner HAL 1.1 o versioni successive, sono supportati i seguenti eventi.
-
IpCidChangeEvent
-
RestartEvent
-
ScramblingStatusEvent
Eventi e formato dati da filtro
Tipo di filtro | Bandiere | Eventi | Operazione dati | Formato dei dati |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION | isRaw: | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | In base all'evento e al programma interno, corriFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ di HAL nel buffer del client. | Un pacchetto di sessioni assemblato viene compilato in FMQ da un altro pacchetto di sessioni. |
isRaw: | Obbligatorio:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opzionale: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ I dati vengono copiati dall'MQ di HAL nel buffer del client. | ||
TS.PES | isRaw: | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | In base all'evento e al programma interno, corriFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ dell'HAL nel buffer del client. | Un pacchetto PES assemblato viene riempito in FMQ da un altro pacchetto PES. |
isRaw: | Obbligatorio:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opzionale: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ I dati vengono copiati dall'MQ di HAL nel buffer del client. | ||
MMTP.PES | isRaw: | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | In base all'evento e al programma interno, corriFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ dell'HAL nel buffer del client. | Un pacchetto MFU assemblato viene riempito in FMQ da un altro pacchetto MFU. |
isRaw: | Obbligatorio:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opzionale: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ I dati vengono copiati dall'MQ dell'HAL nel buffer del client. | ||
TS.TS | N / A | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | In base all'evento e al programma interno, corriFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ dell'HAL nel buffer del client. | ts filtrato con ts headerè compilato in FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video | isPassthrough: | Opzionale:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Il client può avviare MediaCodec dopo aver ricevuto DemuxFilterStatus::DATA_READY .Il client può chiamare Filter.flush dopo aver ricevuto DemuxFilterStatus::DATA_OVERFLOW . | N / A |
isPassthrough: | Obbligatorio:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opzionale: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Per utilizzare MediaCodec :for i=0; i<n; i++ Per utilizzare l'audio diretto di AudioTrack :for i=0; i<n; i++ | Dati ES o ES parziali nella memoria ION. | |
TS.PCR IP.NTP ALP.PTP | N / A | Obbligatorio: N/A Facoltativo: N/A | N / A | N / A |
TS.RECORD | N / A | Obbligatorio:DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opzionale: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Per i dati dell'indice:for i=0; i<n; i++ Per i contenuti registrati , in base a RecordStatus::* e alla pianificazione interna, effettuare una delle seguenti operazioni:
| Per i dati dell'indice: trasportato nel carico utile dell'evento. Per il contenuto registrato: flusso TS con mux compilato in FMQ. |
TS.TEMI | N / A | Obbligatorio:DemuxFilterEvent::DemuxFilterTemiEvent[n] Opzionale: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ | N / A |
MMTP.MMTP | N / A | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | In base all'evento e al programma interno, corriFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ dell'HAL nel buffer del client. | mmtp filtrato con intestazione mmtp è compilato in FMQ. |
MMTP.RECORD | N / A | Obbligatorio:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opzionale: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Per i dati dell'indice: for i=0; i<n; i++ Per i contenuti registrati , in base a RecordStatus::* e alla pianificazione interna, effettuare una delle seguenti operazioni:
| Per i dati dell'indice: trasportato nel carico utile dell'evento. Per il contenuto registrato: flusso registrato con mux compilato in FMQ. Se la sorgente del filtro per la registrazione è da TLV.TLV a IP.IP con passthrough, il flusso registrato ha un'intestazione TLV e IP. |
MMTP.DOWNLOAD | N / A | Obbligatorio:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opzionale: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size) I dati vengono copiati dall'MQ di HAL nel buffer del client. | Il pacchetto di download viene compilato in FMQ da un altro pacchetto di download IP. |
IP.IP_PAYLOAD | N / A | Obbligatorio:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opzionale: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size) I dati vengono copiati dall'MQ di HAL nel buffer del client. | Il pacchetto di carico utile IP viene compilato in FMQ da un altro pacchetto di carico utile IP. |
IP.IP TLV.TLV ALP.ALP | isPassthrough: | Opzionale:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Il flusso secondario del protocollo filtrato alimenta il filtro successivo nella catena di filtri. | N / A |
isPassthrough: | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | In base all'evento e al programma interno, corriFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ dell'HAL nel buffer del client. | Il flusso secondario del protocollo filtrato con l'intestazione del protocollo viene compilato in FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH | N / A | Opzionale:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Il payload del protocollo filtrato alimenta il filtro successivo nella catena di filtri. | N / A |
Esempio di flusso per utilizzare il filtro per creare PSI/SI
Figura 10. Flusso per costruire PSI/SI
Apri un filtro.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
Configura e avvia il 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();
Processo
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); } } } };
Flusso di esempio per usare MediaEvent dal filtro
Figura 11. Flusso per utilizzare MediaEvent dal filtro
- Apri, configura e avvia i filtri A/V.
- Processo
MediaEvent
. - Ricevi
MediaEvent
. - Accodare il blocco lineare al
codec
. - Rilasciare l'handle A/V quando i dati sono stati consumati.
Android.media.tv.tuner.dvr
DvrRecorder
fornisce questi metodi per la registrazione.
-
configure
-
attachFilter
-
detachFilter
-
start
-
flush
-
stop
-
setFileDescriptor
-
write
DvrPlayback
fornisce questi metodi per la riproduzione.
-
configure
-
start
-
flush
-
stop
-
setFileDescriptor
-
read
DvrSettings
viene utilizzato per configurare DvrRecorder
e DvrPlayback
. OnPlaybackStatusChangedListener
e OnRecordStatusChangedListener
vengono utilizzati per segnalare lo stato di un'istanza DVR.
Esempio di flusso per avviare un record
Figura 12. Flusso per avviare un record
Apri, configura e avvia
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();
Ricevi
RecordEvent
e recupera le informazioni sull'indice.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. } } } };
Inizializza
OnRecordStatusChangedListener
e archivia i dati del record.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); } } };
Sintonizzatore HAL
Il Tuner HAL segue HIDL e definisce l'interfaccia tra il framework e l'hardware del fornitore. I fornitori utilizzano l'interfaccia per implementare Tuner HAL e il framework la usa per comunicare con l'implementazione Tuner HAL.
Moduli
Sintonizzatore HAL 1.0
Moduli | Controlli di base | Controlli specifici del modulo | File 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 (derivato da Tuner HAL 1.0)
Moduli | Controlli di base | Controlli specifici del modulo | File 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. Diagramma delle interazioni tra i moduli Tuner HAL
Collegamento del filtro
Il Tuner HAL supporta il collegamento dei filtri in modo tale che i filtri possano essere collegati ad altri filtri per più livelli. I filtri seguono le regole seguenti.
- I filtri sono collegati come un albero, non è consentito chiudere il percorso.
- Il nodo principale è demux.
- I filtri funzionano in modo indipendente.
- Tutti i filtri iniziano a ricevere dati.
- Il collegamento del filtro scorre sull'ultimo filtro.
Il blocco di codice seguente e la Figura 14 illustrano un esempio di filtraggio di più livelli.
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. Diagramma di flusso di un collegamento di filtro per più livelli
Responsabile delle risorse del sintonizzatore
Prima di Tuner Resource Manager (TRM), il passaggio tra due app richiedeva lo stesso hardware Tuner. TV Input Framework (TIF) utilizzava un meccanismo di "vincita prima ad acquisire", il che significa che l'app che ottiene la risorsa per prima mantiene la risorsa. Tuttavia, questo meccanismo potrebbe non essere l'ideale per alcuni casi d'uso complicati.
TRM viene eseguito come servizio di sistema per gestire le risorse hardware Tuner, TVInput
e CAS per le app. TRM utilizza un meccanismo di "vincita in primo piano", che calcola la priorità dell'app in base allo stato in primo piano o in background dell'app e al tipo di caso d'uso. TRM concede o revoca la risorsa in base alla priorità. TRM centralizza la gestione delle risorse ATV per broadcast, OTT e DVR.
Interfaccia TRM
TRM espone le interfacce AIDL in ITunerResourceManager.aidl
per il framework Tuner, MediaCas
e TvInputHardwareManager
per la registrazione, la richiesta o il rilascio di risorse.
Di seguito sono elencate le interfacce per la gestione dei client.
-
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
-
unregisterClientProfile(in int clientId)
Le interfacce per richiedere e rilasciare risorse sono elencate di seguito.
-
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
Le classi cliente e richiesta sono elencate di seguito.
-
ResourceClientProfile
-
ResourcesReclaimListener
-
TunerFrontendRequest
-
TunerDemuxRequest
-
TunerDescramblerRequest
-
CasSessionRequest
-
TunerLnbRequest
Priorità del cliente
TRM calcola la priorità del cliente utilizzando i parametri del profilo del cliente e il valore di priorità dal file di configurazione. La priorità potrebbe anche essere aggiornata da un valore di priorità arbitrario dal client.
Parametri nel profilo del cliente
TRM recupera l'ID del processo da mTvInputSessionId
per decidere se un'app è un'app in primo piano o in background. Per creare mTvInputSessionId
, TvInputService.onCreateSession
o TvInputService.onCreateRecordingSession
inizializza una sessione TIS.
mUseCase
indica il caso d'uso della sessione. I casi d'uso predefiniti sono elencati di seguito.
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
}
File di configurazione
File di configurazione predefinito
Il file di configurazione predefinito riportato di seguito fornisce valori di priorità per casi d'uso predefiniti. Gli utenti possono modificare i valori utilizzando un file di configurazione personalizzato .
Caso d'uso | Primo piano | Sfondo |
---|---|---|
LIVE | 490 | 400 |
PLAYBACK | 480 | 300 |
RECORD | 600 | 500 |
SCAN | 450 | 200 |
BACKGROUND | 180 | 100 |
File di configurazione personalizzato
I fornitori possono personalizzare il file di configurazione /vendor/etc/tunerResourceManagerUseCaseConfig.xml
. Questo file viene utilizzato per aggiungere, rimuovere o aggiornare i tipi di casi d'uso e i valori di priorità dei casi d'uso. Il file personalizzato può utilizzare platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
come modello.
Ad esempio, un nuovo caso d'uso del fornitore è VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
. Il formato dovrebbe seguire platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
.
Valore di priorità arbitrario e buon valore
TRM fornisce updateClientPriority
affinché il client aggiorni il valore di priorità arbitrario e il valore piacevole. Il valore di priorità arbitrario sovrascrive il valore di priorità calcolato dal tipo di caso d'uso e dall'ID sessione.
Il valore piacevole indica quanto è indulgente il comportamento del client quando è in conflitto con un altro client. Il valore piacevole diminuisce il valore di priorità del cliente prima che il suo valore di priorità venga confrontato con il cliente impegnativo.
Meccanismo di recupero
Il diagramma seguente mostra come le risorse vengono recuperate e assegnate quando si verifica un conflitto di risorse.
Figura 15. Diagramma del meccanismo di recupero per un conflitto tra le risorse del sintonizzatore