Struttura del sintonizzatore

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 distribuire contenuti A/V protetti da un ambiente di esecuzione affidabile (TEE) e da un percorso multimediale sicuro (SMP), consentendone l'utilizzo 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 del sintonizzatore supporta sia la TV digitale che la TV analogica basate sui 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.

  • CASV2
  • TvInputService o servizio di ingresso TV (TIS)
  • TvInputManagerService o servizio di gestione dell'ingresso TV (TIMS)
  • MediaCodec o codec multimediale
  • AudioTrack o traccia audio
  • MediaResourceManager o gestore delle risorse multimediali (MRM)

Diagramma di flusso dei componenti del framework Tuner.

Figura 1. Interazioni tra i componenti Android TV

Caratteristiche

Il frontend supporta gli standard DTV riportati di seguito.

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Analogico

Il frontend in Android 12 con Tuner HAL 1.1 o versione successiva supporta lo standard DTV riportato 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)
  • Valore della lunghezza del tipo (TLV)
  • Protocollo di livello collegamento ATSC (ALP)

Descrambler supporta le protezioni dei contenuti riportate di seguito.

  • Percorso multimediale sicuro
  • Percorso multimediale chiaro
  • Archiviazione locale protetta
  • Riproduzione locale protetta

Le API del sintonizzatore supportano i casi d'uso riportati di seguito.

  • Scansione
  • Vivere
  • Riproduzione
  • Documentazione

Tuner, MediaCodec e AudioTrack supportano le modalità di flusso dei dati riportate di seguito.

  • Payload ES con buffer di memoria cancellato
  • Payload ES con handle di memoria sicuro
  • Passante

Progettazione complessiva

L'HAL del sintonizzatore è 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 le interfacce IFrontend , IDemux , IDescrambler , IFilter , IDvr e ILnb .
  • Include le funzioni per integrare il Tuner HAL con altri componenti del framework, come MediaCodec e AudioTrack .

Vengono create una classe Java Tuner e una classe nativa.

  • L'API Java Tuner consente alle app di accedere all'HAL Tuner 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 Java Tuner e l'HAL Tuner.

Viene creata una classe TRM.

  • Gestisce risorse limitate del sintonizzatore, come Frontend, LNB, sessioni CAS e un dispositivo di ingresso TV dall'HAL di ingresso TV.
  • 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 CICAM.
  • Si integra con l'HAL Tuner fornendo token chiave.

MediaCodec e AudioTrack sono migliorati con le funzionalità seguenti.

  • Utilizza la memoria A/V protetta come input del contenuto.
  • Configurato per eseguire la sincronizzazione A/V hardware nella riproduzione con tunnel.
  • Supporto configurato per ES_payload e modalità passthrough.

Progettazione generale del sintonizzatore HAL.

Figura 2. Diagramma dei componenti all'interno del Tuner HAL

Flusso di lavoro complessivo

I diagrammi seguenti illustrano le sequenze di chiamata per la riproduzione di trasmissioni dal vivo.

Impostare

Sequenza di installazione del diagramma di riproduzione della trasmissione in diretta.

Figura 3. Sequenza di configurazione per la riproduzione della trasmissione dal vivo

Gestione audio/video

Gestione del diagramma di riproduzione A/V per la trasmissione dal vivo.

Figura 4. Gestione di A/V per la riproduzione di trasmissioni dal vivo

Gestire contenuti criptati

Gestione del contenuto criptato per il diagramma di riproduzione della trasmissione in diretta.

Figura 5. Gestione dei contenuti criptati per la riproduzione di trasmissioni dal vivo

Elaborazione dati A/V

Elabora i dati A/V per il diagramma di riproduzione della trasmissione dal vivo.

Figura 6. Elaborazione A/V per la riproduzione di trasmissioni dal vivo

API SDK 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 descrambler. Frontend e demux sono componenti interni.

Diagramma di flusso dell'API Tuner SDK.

Figura 7. Interazioni con l'API Tuner SDK

Versioni

A partire da Android 12, l'API Tuner SDK supporta la nuova funzionalità di 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 è reperibile nella documentazione delle nuove API di Android 12.

Pacchetti

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

Diagramma di flusso dei pacchetti API Tuner SDK.

Figura 8. Pacchetti API Tuner SDK

Android.media.tv.tuner

Il pacchetto Tuner è un punto di accesso 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 Tuner specificando i parametri useCase e sessionId .
  • tune() : acquisisce una risorsa frontend e la ottimizza specificando il parametro FrontendSetting .
  • 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 descrambler.
  • openLnb() : acquisisce un'istanza LNB interna.
  • openLnbByName() : acquisisce un'istanza LNB esterna.
  • openTimeFilter() : acquisisce un'istanza del 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 viene derivato per diversi standard DTV dalle classi seguenti.

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

A partire da Android 12 con Tuner HAL 1.1 o versione successiva, è supportato il seguente standard DTV.

  • DtmbFrontendSettings

FrontendCapabilities viene derivato per diversi standard DTV dalle classi seguenti.

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

A partire da Android 12 con Tuner HAL 1.1 o versione successiva, è 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 esegue la scansione delle possibili frequenze e crea una lista 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, ID PLD), allora Tuner.tune è consigliato come opzione più veloce .

Quando l'utente chiama Tuner.tune , si verificano le seguenti azioni:

  • TIS popola FrontendSettings con le informazioni richieste utilizzando Tuner.tune .
  • L'HAL riporta i messaggi tune LOCKED se il segnale è bloccato.
  • TIS utilizza Frontend.getStatus per raccogliere le informazioni necessarie.
  • TIS si sposta sulla successiva frequenza disponibile nel suo elenco di 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 .

Sintonizzatore.scan(AUTO_SCAN)

Se TIS non dispone di informazioni sufficienti per utilizzare Tuner.tune , ma dispone di un elenco di frequenze e di un tipo standard (ad esempio, DVB T/C/S), si consiglia Tuner.scan(AUTO_SCAN) .

Quando l'utente chiama Tuner.scan(AUTO_SCAN) , si verificano le seguenti azioni:

  • TIS utilizza Tuner.scan(AUTO_SCAN) con FrontendSettings riempito con frequenza.

  • I report HAL scansionano i messaggi LOCKED se il segnale è bloccato. L'HAL potrebbe anche segnalare altri messaggi di scansione per fornire ulteriori informazioni sul segnale.

  • TIS utilizza Frontend.getStatus per raccogliere le informazioni necessarie.

  • TIS chiama Tuner.scan affinché l'HAL continui con l'impostazione successiva sulla stessa frequenza. Se la struttura FrontendSettings è vuota, l'HAL utilizza la successiva impostazione disponibile. In caso contrario, HAL utilizza FrontendSettings per un'analisi una tantum e invia END per indicare che l'operazione di analisi è terminata.

  • TIS ripete le azioni precedenti finché tutte le impostazioni sulla frequenza non vengono esaurite.

  • L'HAL invia END per indicare che l'operazione di scansione è terminata.

  • TIS si sposta sulla successiva frequenza disponibile nel suo elenco di frequenze.

TIS richiama nuovamente 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.

Sintonizzatore.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, si consiglia Tuner.scan(BLIND_SCAN) .

  • TIS utilizza Tuner.scan(BLIND_SCAN) . È possibile specificare una frequenza in FrontendSettings per la frequenza iniziale, ma TIS ignora altre impostazioni in FrontendSettings .
  • L'HAL segnala un messaggio di scansione LOCKED se il segnale è bloccato.
  • TIS utilizza Frontend.getStatus per raccogliere le informazioni necessarie.
  • TIS richiama nuovamente Tuner.scan per continuare la scansione. ( FrontendSettings viene ignorato.)
  • TIS ripete le azioni precedenti finché tutte le impostazioni sulla frequenza non vengono esaurite. L'HAL incrementa la frequenza senza che sia necessaria alcuna azione da parte di TIS. L'HAL riporta PROGRESS .

TIS richiama nuovamente Tuner.scan(AUTO_SCAN) finché tutte le frequenze non sono esaurite. L'HAL segnala 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.

Diagramma di flusso del processo TIS Scan.

Figura 9. Diagramma di flusso di una scansione TIS

Android.media.tv.tuner.filter

Il pacchetto filter è una raccolta di operazioni di filtro insieme a configurazione, impostazioni, callback ed eventi. Il pacchetto comprende le operazioni riportate di seguito. Fare riferimento al codice sorgente Android per l'elenco completo delle operazioni.

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

Fare riferimento al codice sorgente Android per l'elenco completo.

FilterConfiguration è derivato dalle classi seguenti. Le configurazioni riguardano il tipo di filtro principale e specificano quale protocollo utilizza il filtro per estrarre i dati.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Le impostazioni derivano dalle classi seguenti. Le impostazioni riguardano il sottotipo di filtro e specificano quali tipi di dati 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 versione successiva, sono supportati i seguenti eventi.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Eventi e formato 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:
true
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Secondo l'evento e il programma interno, corri
Filter.read(buffer, offset, adjustedSize) una o più volte.

I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Un pacchetto di sessioni assemblato viene compilato in FMQ da un altro pacchetto di sessioni.
isRaw:
false
Obbligatorio:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


I dati vengono copiati dall'MQ dell'HAL al buffer del client.
TS.PES isRaw:
true
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Secondo l'evento e il programma interno, corri
Filter.read(buffer, offset, adjustedSize) una o più volte.

I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Un pacchetto PES assemblato viene compilato nella FMQ da un altro pacchetto PES.
isRaw:
false
Obbligatorio:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


I dati vengono copiati dall'MQ dell'HAL al buffer del client.
MMTP.PES isRaw:
true
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Secondo l'evento e il programma interno, corri
Filter.read(buffer, offset, adjustedSize) una o più volte.

I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Un pacchetto MFU assemblato viene riempito nella FMQ da un altro pacchetto MFU.
isRaw:
false
Obbligatorio:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


I dati vengono copiati dall'MQ dell'HAL al buffer del client.
TS.TS
N / A Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Secondo l'evento e il programma interno, corri
Filter.read(buffer, offset, adjustedSize) una o più volte.

I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Filtrato ts con l'intestazione ts
è compilato FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
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:
false
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++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Per utilizzare l'audio diretto di AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Dati ES o ES parziali nella memoria ION.
TS.PCR
IP.NTP
ALP.PTP
N / A Obbligatorio: N/D
Facoltativo: N/D
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++
DemuxFilterTsRecordEvent[i];


Per i contenuti registrati , in base a RecordStatus::* e alla pianificazione interna, effettuare una delle seguenti operazioni:
  • Eseguire DvrRecord.write(adustedSize) una o più volte nell'archivio.
    I dati vengono trasferiti dall'MQ dell'HAL all'archiviazione.
  • Eseguire DvrRecord.write(buffer, adustedSize) una o più volte nel buffer.
    I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Per i dati dell'indice: trasportato nel payload dell'evento.

Per i contenuti registrati: flusso TS 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++
DemuxFilterTemiEvent[i];
N / A
MMTP.MMTP N / A Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Secondo l'evento e il programma interno, corri
Filter.read(buffer, offset, adjustedSize) una o più volte.

I dati vengono copiati dall'MQ dell'HAL al buffer del client.
mmtp filtrato con intestazione mmtp
è compilato 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 indice: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Per i contenuti registrati , in base a RecordStatus::* e alla pianificazione interna, effettuare una delle seguenti operazioni:
  • Eseguire DvrRecord.write(adjustedSize) una o più volte nell'archivio.
    I dati vengono trasferiti dall'MQ dell'HAL all'archiviazione.
  • Eseguire DvrRecord.write(buffer, adjustedSize) una o più volte nel buffer.
    I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Per i dati dell'indice: trasportato nel payload dell'evento.

Per i contenuti registrati: flusso registrato con multiplex compilato in FMQ.

Se l'origine del filtro per la registrazione è TLV.TLV a IP.IP con passthrough, il flusso registrato avrà un TLV e un'intestazione 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 dell'HAL al buffer del client.
Il pacchetto di download viene compilato 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 dell'HAL al buffer del client.
Il pacchetto di payload IP viene compilato nella FMQ da un altro pacchetto di payload IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Opzionale:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Il flusso secondario del protocollo filtrato alimenta il filtro successivo nella catena di filtri. N / A
isPassthrough:
false
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Secondo l'evento e il programma interno, corri
Filter.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 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
Flusso di esempio per utilizzare il filtro per creare PSI/SI

Flusso di esempio per l'utilizzo del filtro per creare PSI/SI.

Figura 10. Flusso per costruire PSI/SI

  1. Apri un filtro.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. 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();
    
  3. SectionEvent processoEvento .

    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

Flusso di esempio per utilizzare MediaEvent dal filtro.

Figura 11. Flusso per utilizzare MediaEvent dal filtro

  1. Apri, configura e avvia i filtri A/V.
  2. Elabora MediaEvent .
  3. Ricevi MediaEvent .
  4. Accoda il blocco lineare al codec .
  5. Rilasciare la maniglia A/V una volta consumati i dati.

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.

Flusso di esempio per avviare un record

Flusso di esempio per avviare un record.

Figura 12. Flusso per avviare un record

  1. 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();
    
  2. 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. }
          }
        }
    };
    
  3. Inizializza OnRecordStatusChangedListener e memorizza 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

L'HAL del sintonizzatore 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 utilizza 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

Sintonizzatore HAL 1.1 (derivato dal sintonizzatore 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

Diagramma di flusso delle interazioni tra i moduli del Tuner HAL.

Figura 13. Schema delle interazioni tra i moduli HAL Tuner

Collegamento del filtro

L'HAL del sintonizzatore 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 radice è 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 riportato di seguito 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>)
}

Diagramma di esempio di collegamento del filtro.

Figura 14. Diagramma di flusso di un collegamento di filtro per più strati

Gestore delle risorse del sintonizzatore

Prima di Tuner Resource Manager (TRM), il passaggio tra due app richiedeva lo stesso hardware del sintonizzatore. TV Input Framework (TIF) utilizzava un meccanismo di "vincita del primo ad acquisire", il che significa che qualunque app 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 Sintonizzatore, TVInput e CAS per le app. 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. 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 registrare, richiedere o rilasciare risorse.

Le interfacce per la gestione del cliente sono elencate di seguito.

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

Di seguito sono elencate le interfacce per richiedere e rilasciare risorse.

  • 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 richiesta 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 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 è 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 caso d'uso di un nuovo 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 valore gradevole

TRM fornisce updateClientPriority affinché il client aggiorni il valore di priorità arbitrario e il valore nice. Il valore di priorità arbitrario sovrascrive il valore di priorità calcolato dal tipo di caso d'uso e dall'ID di sessione.

Il valore nice indica quanto è indulgente il comportamento del client quando è in conflitto con un altro client. Il valore gradevole 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.

Diagramma del processo del meccanismo di recupero.

Figura 15. Diagramma del meccanismo di recupero per un conflitto tra le risorse del Tuner