Per Android 11 o versioni successive, puoi usare il framework di Android Tuner per pubblicare contenuti A/V. Il framework utilizza la pipeline hardware dei fornitori, il che lo rende adatto sia per SoC di fascia bassa che di fascia alta. Il framework fornisce un modo sicuro per fornire contenuti A/V protetti da un ambiente di esecuzione attendibile (TEE) e da un percorso multimediale sicuro (SMP), il che consente di utilizzarlo in un ambiente di protezione dei contenuti altamente limitato.
L'interfaccia standardizzata tra Tuner e Android CAS garantisce un'integrazione più rapida tra i fornitori di sintonizzatori e i fornitori CAS. L'interfaccia di Tuner è compatibile
con MediaCodec
e AudioTrack
per creare una soluzione unica per Android TV.
L'interfaccia del sintonizzatore 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.
- HAL del sintonizzatore: un'interfaccia tra il framework e i fornitori
- API Tuner SDK:un'interfaccia tra il framework e le app
- Tuner Resource Manager (TRM): risorse HW di Coordinates Tuner
Per Android 11, i componenti seguenti sono stati ottimizzati.
- CAS V2
TvInputService
o TV Input Service (TIS)TvInputManagerService
o TV Input Manager Service (TIMS)MediaCodec
o codec multimedialeAudioTrack
o traccia audioMediaResourceManager
o Media Resource Manager (MRM)
Figura 1. Interazioni tra i componenti di Android TV
Funzionalità
Il frontend supporta gli standard DTV riportati di seguito.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analogici
Il frontend in Android 12 con Tuner HAL 1.1 o versioni successive supporta lo standard DTV riportato di seguito.
- DTMB
Il demux supporta i protocolli di streaming riportati di seguito.
- Transport Stream (TS)
- MPEG Media Transport Protocol (MMTP)
- Protocollo internet (IP)
- Valore della lunghezza del tipo (TLV)
- Protocollo ATSC link-layer (ALP)
Descrambler supporta le seguenti protezioni dei contenuti.
- Percorso multimediale sicuro
- Cancellare il percorso dei contenuti multimediali
- Record locale sicuro
- Riproduzione locale sicura
Le API di ottimizzazione supportano i casi d'uso riportati di seguito.
- Scansione
- In diretta
- Riproduzione
- Registra
Tuner, MediaCodec
e AudioTrack
supportano le seguenti modalità di flusso di dati.
- Payload ES con buffer di memoria libera
- Payload ES con handle di memoria sicuro
- Passthrough
Design complessivo
L'HAL per il sintonizzatore è definito tra il framework Android e l'hardware del fornitore.
- Descrive cosa il framework si aspetta dal fornitore e come il fornitore potrebbe farlo.
- Esporta le funzionalità di frontend, demux e decodificatore nel framework
tramite le interfacce
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
eILnb
. - Include le funzioni per integrare l'HAL di Tuner con altri componenti del framework, come
MediaCodec
eAudioTrack
.
Vengono create una classe Java e una classe nativa Tuner.
- L'API Tuner Java consente alle app di accedere a Tuner HAL tramite API pubbliche.
- La classe Native consente il controllo delle autorizzazioni e la gestione di grandi quantità di dati di registrazione o riproduzione con il sintonizzatore HAL.
- Il modulo Tuner nativo è un ponte tra la classe Java Tuner e l'HAL Tuner.
Viene creata una classe TRM.
- Gestisce risorse limitate del sintonizzatore, come le sessioni frontend, LNB e CAS e un dispositivo di ingresso TV dall'HAL di ingresso TV.
- Applica regole per recuperare risorse insufficienti dalle app. La regola predefinita è la finestra in primo piano.
Media CAS e CAS HAL sono migliorati con le funzionalità riportate di seguito.
- Apre sessioni CAS per utilizzi e algoritmi diversi.
- Supporta sistemi CAS dinamici, come la rimozione e l'inserimento di CICAM.
- Si integra con Tuner HAL fornendo token chiave.
MediaCodec
e AudioTrack
sono stati migliorati con le funzionalità riportate di seguito.
- Accetta memoria A/V sicura come input di contenuti.
- Configurato per eseguire la sincronizzazione A/V hardware nella riproduzione in tunnel.
- Supporto configurato per
ES_payload
e la modalità passthrough.
Figura 2. Diagramma dei componenti all'interno dell'HAL Tuner
Flusso di lavoro complessivo
I seguenti diagrammi illustrano le sequenze di chiamate per la riproduzione di trasmissioni dal vivo.
Configura
Figura 3. Sequenza di configurazione per la riproduzione di una trasmissione in diretta
Gestione dell'audio/video
Figura 4. Gestione audio/video per la riproduzione di trasmissioni live
Gestione dei contenuti illeggibili
Figura 5. Gestione dei contenuti criptati per la riproduzione di trasmissioni dal vivo
Elaborazione dei dati A/V
Figura 6. Elaborazione audio/video per la riproduzione di trasmissioni live
API Tuner SDK
L'API Tuner SDK gestisce le interazioni con il codice JNI di Tuner, l'HAL di Tuner
e TunerResourceManager
. L'app TIS utilizza l'API Tuner SDK per accedere alle risorse e ai sottocomponenti di Tuner, come il filtro e il decodificatore. Frontend e demux sono componenti interni.
Figura 7. Interazioni con l'API dell'SDK Tuner
Versioni
A partire da Android 12, l'API Tuner SDK supporta la nuova funzionalità di Tuner HAL 1.1, un upgrade della versione compatibile con le versioni precedenti di Tuner 1.0.
Utilizza la seguente API per controllare la versione HAL in esecuzione.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
La versione HAL minima richiesta è disponibile nella documentazione delle nuove API di Android 12.
Pacchetti
L'API Tuner SDK fornisce i quattro pacchetti riportati di seguito.
android.media.tv.tuner
android.media.tv.tuner.frontend
android.media.tv.tuner.filter
android.media.tv.tuner.dvr
Figura 8. Pacchetti dell'API SDK Tuner
Android.media.tv.tuner
Il pacchetto Tuner è un punto di ingresso per utilizzare il framework Tuner. L'app TIS utilizza 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 ed esegui l'ottimizzazione 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 decodificatore.openLnb()
: acquisisce un'istanza LNB interna.openLnbByName()
: acquisisce un'istanza LNB esterna.openTimeFilter()
: acquisisce un'istanza di filtro temporale.
Il pacchetto Tuner offre funzionalità che non sono incluse nei pacchetti di filtri, 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
viene dedotto per diversi standard DTV dalle classi riportate di seguito.
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
A partire da Android 12 con Tuner HAL 1.1 o versioni successive, è supportato il seguente standard DTV.
DtmbFrontendSettings
FrontendCapabilities
viene dedotto per diversi standard DTV dalle classi riportate di seguito.
AnalogFrontendCapabilities
Atsc3FrontendCapabilities
AtscFrontendCapabilities
DvbcFrontendCapabilities
DvbsFrontendCapabilities
DvbtFrontendCapabilities
Isdbs3FrontendCapabilities
IsdbsFrontendCapabilities
IsdbtFrontendCapabilities
A partire da Android 12 con Tuner HAL 1.1 o versioni successive, è supportato il seguente standard DTV.
DtmbFrontendCapabilities
FrontendInfo
recupera le informazioni del frontend.
FrontendStatus
recupera lo stato attuale del frontend.
OnTuneEventListener
ascolta gli eventi sul frontend.
L'app TIS utilizza ScanCallback
per elaborare i messaggi di scansione dal frontend.
Ricerca canali
Per configurare una TV, l'app analizza le possibili frequenze e crea una selezione
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 del canale.
Se il TIS dispone di informazioni accurate sulla trasmissione del segnale, ad esempio frequenza, standard (ad es. T/T2, S/S2) e informazioni aggiuntive necessarie (ad es. ID PLD), alloraTuner.tune
è consigliato come opzione più rapida.
Quando l'utente chiama Tuner.tune
, vengono eseguite le seguenti azioni:
- Il TIS compila
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. - Il TIS passa alla frequenza disponibile successiva nell'elenco delle frequenze.
TIS chiama di nuovo Tuner.tune
fino a esaurimento di tutte le frequenze.
Durante la sintonizzazione, puoi chiamare stopTune()
o close()
per mettere in pausa o terminare la chiamataTuner.tune
.
Tuner.scan(AUTO_SCAN)
Se il TIS non dispone di informazioni sufficienti per utilizzare Tuner.tune
, ma ha un elenco di frequenze e un tipo di standard (ad esempio DVB T/C/S), consigliamo di utilizzare Tuner.scan(AUTO_SCAN)
.
Quando l'utente chiama Tuner.scan(AUTO_SCAN)
, si verificano le seguenti azioni:
TIS utilizza
Tuner.scan(AUTO_SCAN)
conFrontendSettings
compilato con frequenza.I report dell'HAL analizzano i messaggi
LOCKED
se il segnale è bloccato. L'HAL potrebbe anche segnalare altri messaggi di scansione per fornire ulteriori informazioni sull'indicatore.TIS utilizza
Frontend.getStatus
per raccogliere le informazioni necessarie.TIS chiama
Tuner.scan
per l'HAL per passare all'impostazione successiva sulla stessa frequenza. Se la strutturaFrontendSettings
è vuota, l'HAL utilizza la successiva impostazione disponibile. In caso contrario, l'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 non sono esaurite tutte le impostazioni della frequenza.
L'HAL invia
END
per indicare che l'operazione di scansione è terminata.Il TIS passa alla successiva frequenza disponibile nel proprio elenco di frequenze.
TIS chiama di nuovo Tuner.scan(AUTO_SCAN)
fino a esaurimento di tutte le frequenze.
Durante la scansione, puoi chiamare stopScan()
o close()
per metterla in pausa o terminarla.
Tuner.scan(BLIND_SCAN)
Se TIS non dispone di un elenco di frequenze e l'HAL del fornitore può cercare la frequenza del frontend specificato dall'utente per ottenere la risorsa frontend, è consigliabile Tuner.scan(BLIND_SCAN)
.
- TIS utilizza
Tuner.scan(BLIND_SCAN)
. InFrontendSettings
è possibile specificare una frequenza per la frequenza di inizio, ma TIS ignora le altre impostazioni inFrontendSettings
. - L'HAL segnala un messaggio di scansione
LOCKED
se l'indicatore è bloccato. - TIS utilizza
Frontend.getStatus
per raccogliere le informazioni necessarie. - TIS chiama di nuovo
Tuner.scan
per continuare la scansione. (FrontendSettings
viene ignorato). - Il TIS ripete le azioni riportate sopra finché tutte le impostazioni della frequenza non sono esaurite. L'HAL incrementa la frequenza senza che sia necessario alcun intervento da parte del TIS.
L'HAL segnala
PROGRESS
.
TIS chiama di nuovo Tuner.scan(AUTO_SCAN)
fino a esaurimento di tutte le frequenze.
L'HAL segnala END
per indicare che l'operazione di scansione è stata completata.
Durante la scansione, puoi chiamare stopScan()
o close()
per mettere in pausa o terminare la scansione.
Figura 9. Diagramma di flusso di un'analisi 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 riportate di seguito. Per l'elenco completo delle operazioni, fai riferimento al codice sorgente di Android.
configure()
start()
stop()
flush()
read()
Per l'elenco completo, consulta il codice sorgente di Android.
FilterConfiguration
è ottenuto dalle classi riportate di seguito. Le configurazioni sono per il tipo di filtro principale e specificano il protocollo utilizzato dal filtro per estrarre i dati.
AlpFilterConfiguration
IpFilterConfiguration
MmtpFilterConfiguration
TlvFilterConfiguration
TsFilterConfiguration
Le impostazioni derivano dalle classi riportate di seguito. Le impostazioni si riferiscono al sottotipo di filtro e specificano i tipi di dati che il filtro può escludere.
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
FilterEvent
deriva dalle classi seguenti per generare report sugli 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 dei dati dal filtro
Tipo di filtro | Bandiere | Eventi | Operazione sui 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 alla pianificazione interna, eseguiFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ di HAL al buffer del client. |
Un pacchetto di sessione assemblato viene compilato in FMQ da un altro pacchetto di sessione. |
isRaw: |
Obbligatorio:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Facoltativo: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ I dati vengono copiati dall'MQ di HAL al 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 alla pianificazione interna, eseguiFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dal MQ dell'HAL al buffer del client. |
Un pacchetto PES assemblato viene compilato in FMQ da un altro pacchetto PES. |
isRaw: |
Obbligatorio:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Facoltativo: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ I dati vengono copiati dal MQ di HAL al 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 alla pianificazione interna, eseguiFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dal MQ dell'HAL al buffer del client. |
Un pacchetto MFU assemblato viene compilato in FMQ da un altro pacchetto MFU. |
isRaw: |
Obbligatorio:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Facoltativo: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ I dati vengono copiati dall'MQ dell'HAL al buffer del client. |
||
TS.TS |
N/D | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
In base all'evento e alla pianificazione interna, eseguiFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dal MQ dell'HAL al buffer del client. |
Il filtro ts con intestazione ts è compilato in FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
Facoltativo: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/D |
isPassthrough: |
Obbligatorio:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Facoltativo: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Per usare MediaCodec :for i=0; i<n; i++ Per usare l'audio diretto di AudioTrack :for i=0; i<n; i++ |
Dati ES o dati ES parziali nella memoria ION. | |
TS.PCR IP.NTP ALP.PTP |
N/D | Obbligatorio:N/A
Facoltativo: N/A |
N/D | N/D |
TS.RECORD |
N/D | Obbligatorio: DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Facoltativo: 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 programmazione interna, svolgi
una delle seguenti operazioni:
|
Per i dati dell'indice: trasportati nel payload dell'evento. Per i contenuti registrati: stream TS multiplexato compilato in FMQ. |
TS.TEMI |
N/D | Obbligatorio:DemuxFilterEvent::DemuxFilterTemiEvent[n] Facoltativo: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
N/D |
MMTP.MMTP |
N/D | Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
In base all'evento e alla programmazione interna, eseguiFilter.read(buffer, offset, adjustedSize) una o più
volte.I dati vengono copiati dall'MQ dell'HAL al buffer del client. |
Il filtro mmtp con intestazione mmtp è compilato in FMQ. |
MMTP.RECORD |
N/D | Obbligatorio:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Facoltativo: 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 programmazione interna, svolgi una delle seguenti operazioni:
|
Per i dati di indice: viene trasferito il payload dell'evento. Per i contenuti registrati: stream registrati con Mux compilato FMQ. Se l'origine del filtro per la registrazione è TLV.TLV -IP.IP con il passthrough, lo stream registrato ha un'intestazione TLV e IP. |
MMTP.DOWNLOAD |
N/D | Obbligatorio:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Facoltativo: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size) I dati vengono copiati dal MQ di HAL al buffer del client. |
Il pacchetto di download viene compilato in FMQ da un altro pacchetto di download IP. |
IP.IP_PAYLOAD |
N/D | Obbligatorio:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Facoltativo: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size) I dati vengono copiati dal MQ di HAL al buffer del client. |
Il pacchetto di payload IP viene compilato in FMQ da un altro pacchetto di payload IP. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Facoltativo:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Il sottostream del protocollo filtrato viene inviato al filtro successivo nella catena di filtri. | N/D |
isPassthrough: |
Obbligatorio:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Consigliato: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
In base all'evento e alla pianificazione interna, eseguiFilter.read(buffer, offset, adjustedSize) una o più volte.I dati vengono copiati dall'MQ dell'HAL al buffer del client. |
Il flusso secondario del protocollo filtrato con intestazione del protocollo è compilato in FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
N/D | Facoltativo:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Il payload del protocollo filtrato alimenta il filtro successivo nella catena di filtri. | N/D |
Flusso di esempio per utilizzare il filtro per creare PSI/SI
Figura 10. Flusso per la creazione di 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();
Elabora
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 utilizzare MediaEvent dal filtro
Figura 11. Flusso per utilizzare MediaEvent dal filtro
- Apri, configura e avvia i filtri A/V.
- Elaborazione
MediaEvent
. - Ricevi
MediaEvent
. - Inserisci in coda il blocco lineare in
codec
. - Rilascia 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
offre questi metodi per la riproduzione.
configure
start
flush
stop
setFileDescriptor
read
DvrSettings
viene utilizzato per configurare DvrRecorder
e DvrPlayback
.
I criteri OnPlaybackStatusChangedListener
e OnRecordStatusChangedListener
vengono utilizzati
per segnalare lo stato di un'istanza DVR.
Esempio di flusso per avviare una registrazione
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); } } };
HAL del sintonizzatore
L'HAL per l'accordatore è conforme allo standard HIDL e definisce l'interfaccia tra il framework e l'hardware del fornitore. I fornitori utilizzano l'interfaccia per implementare l'HAL del sintonizzatore e il framework la utilizza per comunicare con l'implementazione dell'HAL del sintonizzatore.
Moduli
Tuner HAL 1.0
Moduli | Comandi di base | Controlli specifici per i moduli | File HAL |
---|---|---|---|
ITuner |
N/D | frontend(open, getIds, getInfo) , openDemux , openDescrambler , openLnb e getDemuxCaps |
ITuner.hal |
IFrontend |
setCallback , getStatus e 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 e getQueueDesc |
IDvr.hal IDvrCallback.hal |
IFilter |
close , start , stop , configure e 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 e removePid |
IDescrambler.hal |
Sintonizzatore HAL 1.1 (derivato da Sintonizzatore HAL 1.0)
Moduli | Comandi di base | Controlli specifici per i moduli | File HAL |
---|---|---|---|
ITuner |
N/D | getFrontendDtmbCapabilities |
@1.1::ITuner.hal |
IFrontend |
tune_1_1 , scan_1_1 e 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 dell'HAL per il sintonizzatore
Filtra collegamento
L'HAL per l'ottimizzazione supporta il collegamento dei filtri in modo che i filtri possano essere collegati ad altri filtri per più livelli. I filtri seguono le regole riportate di seguito.
- I filtri sono collegati come un albero, il percorso di chiusura non è consentito.
- Il nodo radice è demux.
- I filtri funzionano in modo indipendente.
- Tutti i filtri iniziano a ricevere dati.
- Il collegamento viene eseguito il flush dell'ultimo filtro.
Il blocco di codice di seguito e la Figura 14 mostrano un esempio di applicazione di filtri a 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 filtri per più strati
Tuner Resource Manager
Prima di Tuner Resource Manager (TRM), il passaggio tra due app richiedeva lo stesso hardware per Tuner. TV Input Framework (TIF) utilizzava un meccanismo "chi arriva prima vince", il che significa che l'app che ottiene per prima la risorsa la mantiene. Tuttavia, questo meccanismo potrebbe non essere ideale per alcuni casi d'uso complessi.
TRM viene eseguito come servizio di sistema per gestire le risorse hardware di Tuner, TVInput
e CAS per le app. Il TRM utilizza un meccanismo di "vittoria in primo piano", che calcola la priorità dell'app in base allo stato in primo piano o in background e al tipo di caso d'uso. Il TRM concede o revoca la risorsa in base alla priorità. TRM centralizza la gestione delle risorse ATV per la trasmissione, OTT e DVR.
Interfaccia TRM
TRM espone interfacce AIDL in ITunerResourceManager.aidl
per il framework Tuner, MediaCas
e TvInputHardwareManager
per registrare, richiedere o rilasciare risorse.
Le interfacce per la gestione dei clienti sono elencate di seguito.
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 client e request sono elencate di seguito.
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
Priorità del cliente
TRM calcola la priorità del client utilizzando i parametri del profilo del client e il valore di priorità del file di configurazione. La priorità potrebbe anche essere aggiornata con un valore di priorità arbitrario dal client.
Parametri nel profilo del cliente
TRM recupera l'ID processo da mTvInputSessionId
per stabilire se 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 i valori di priorità per scenari di utilizzo predefiniti. Gli utenti possono modificare i valori utilizzando un file di configurazione personalizzato.
Caso d'uso | Primo piano | Background |
---|---|---|
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 deve essere
platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
.
Valore di priorità arbitrario e valore accettabile
TRM fornisce updateClientPriority
al client per aggiornare il valore di priorità arbitrario e il valore accettabile.
Il valore di priorità arbitrario sovrascrive il valore di priorità calcolato
dal tipo di caso d'uso e dall'ID sessione.
Il valore nice indica quanto è permissivo il comportamento del client quando è in conflitto con un altro client. Il valore nice diminuisce il valore della priorità del client prima che questo venga confrontato con il client problematico.
Meccanismo di recupero
Il diagramma seguente mostra in che modo le risorse vengono recuperate e assegnate quando si verifica un conflitto tra le risorse.
Figura 15. Diagramma del meccanismo di recupero per un conflitto tra le risorse del sintonizzatore