Framework dell'ottimizzazione

Per Android 11 o versioni successive, puoi utilizzare il framework 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 il sintonizzatore e il CAS Android consente un'integrazione più rapida tra i fornitori di sintonizzatori 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 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): coordina le risorse HW del sintonizzatore

Per Android 11, sono stati migliorati i seguenti componenti.

  • CAS V2
  • TvInputService o servizio di input TV (TIS)
  • TvInputManagerService o TV Input Manager Service (TIMS)
  • MediaCodec o codec multimediale
  • AudioTrack o traccia audio
  • MediaResourceManager o Media Resource Manager (MRM)

Diagramma di flusso dei componenti del framework di Tuner.

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.

  • Stream di trasporto (TS)
  • MPEG Media Transport Protocol (MMTP)
  • IP (Internet Protocol)
  • Valore della lunghezza del tipo (TLV)
  • Protocollo ATSC link-layer (ALP)

Il decodificatore supporta le protezioni dei contenuti riportate di seguito.

  • Percorso dei contenuti multimediali sicuri
  • Cancella percorso contenuti multimediali
  • Record locale sicuro
  • Riproduzione locale sicura

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

  • Scansione
  • In diretta
  • Riproduzione
  • Registra

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

  • Payload ES con buffer di memoria vuoto
  • Payload ES con handle di memoria sicuro
  • Passthrough

Design generale

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 quest'ultimo potrebbe farlo.
  • Esporta le funzionalità di frontend, demux e decodificatore nel framework tramite le interfacce IFrontend, IDemux, IDescrambler, IFilter, IDvr e ILnb.
  • Include le funzioni per integrare l'HAL di Tuner con altri componenti del framework, come MediaCodec e AudioTrack.

Vengono create una classe Java e una classe nativa di Tuner.

  • 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 l'HAL Tuner.
  • 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 Frontend, LNB, sessioni 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 diversi utilizzi e algoritmi.
  • Supporta sistemi CAS dinamici, come la rimozione e l'inserimento di CICAM.
  • Si integra con l'HAL del sintonizzatore fornendo token chiave.

MediaCodec e AudioTrack sono 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.

Design complessivo del Tuner HAL.

Figura 2. Diagramma dei componenti all'interno dell'HAL per il sintonizzatore

Flusso di lavoro complessivo

I diagrammi riportati di seguito illustrano le sequenze di chiamate per la riproduzione della trasmissione dal vivo.

Configura

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

Figura 3. Configura la sequenza per la riproduzione della trasmissione live

Gestione dell'audio/video

Diagramma di gestione dell'audio/video per la riproduzione di trasmissioni dal vivo.

Figura 4. Gestione dell'audio/video per la riproduzione di trasmissioni dal vivo

Gestione dei contenuti criptati

Diagramma di gestione dei contenuti criptati per la riproduzione di trasmissioni in diretta.

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

Elaborazione dei dati A/V

Elabora i dati audio/video per il diagramma della riproduzione di trasmissioni live.

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

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 componenti secondari del sintonizzatore, come il filtro e lo scodificatore. 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à in Tuner HAL 1.1, che è un upgrade della versione di Tuner 1.0 compatibile con le versioni precedenti.

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

Diagramma di flusso dei pacchetti dell'API SDK Tuner.

Figura 8. Pacchetti API dell'SDK del 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 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 di decodificatore.
  • openLnb(): acquisisce un'istanza LNB interna.
  • openLnbByName(): acquisisce un'istanza LNB esterna.
  • openTimeFilter(): acquisisce un'istanza di filtro temporale.

Il pacchetto Tuner fornisce funzionalità non coperte dai 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 esegue la scansione delle 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:

  • TIS compila FrontendSettings con le informazioni richieste utilizzando Tuner.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 finché non sono state esaurite 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), vengono eseguite le seguenti azioni:

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

  • L'HAL segnala la scansione dei messaggi LOCKED se l'indicatore è 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 consentire all'HAL di passare all'impostazione successiva sulla stessa frequenza. Se la struttura FrontendSettings è vuota, l'HAL utilizza la successiva impostazione disponibile. In caso contrario, l'HAL utilizza FrontendSettings per una scansione una tantum e invia END 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 frequenza disponibile successiva nell'elenco delle frequenze.

TIS chiama di nuovo Tuner.scan(AUTO_SCAN) finché non sono state esaurite tutte le frequenze.

Durante la ricerca, puoi chiamare stopScan() o close() per mettere in pausa o terminare la ricerca.

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). È 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 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) finché non sono state esaurite tutte le frequenze. 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 di scansione TIS.

Figura 9. Diagramma di flusso di una scansione TIS

Android.media.tv.tuner.filter

Il pacchetto di filtri è una raccolta di operazioni di filtro, nonché di configurazione, impostazioni, callback ed eventi. Il pacchetto include le operazioni riportate di seguito. Per l'elenco completo delle operazioni, consulta il codice sorgente di Android.

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

Per l'elenco completo, consulta il codice sorgente di Android.

FilterConfiguration deriva dalle classi seguenti. 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 è derivato dalle classi riportate di seguito 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 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:
true
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
In base all'evento e alla programmazione interna, esegui
Filter.read(buffer, offset, adjustedSize) una o più volte.

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

Facoltativo:
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 di HAL al buffer del client.
TS.PES isRaw:
true
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
In base all'evento e alla pianificazione interna, esegui
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 in FMQ da un altro pacchetto PES.
isRaw:
false
Obbligatorio:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facoltativo:
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 di HAL al buffer del client.
MMTP.PES isRaw:
true
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
In base all'evento e alla pianificazione interna, esegui
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 compilato in FMQ da un altro pacchetto MFU.
isRaw:
false
Obbligatorio:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facoltativo:
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/D Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
In base all'evento e alla pianificazione interna, esegui
Filter.read(buffer, offset, adjustedSize) una o più volte.

I dati vengono copiati dall'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:
true
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:
false
Obbligatorio:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facoltativo:
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/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++
DemuxFilterTsRecordEvent[i];


Per i contenuti registrati, in base a RecordStatus::* e alla programmazione interna, svolgi una delle seguenti operazioni:
  • Esegui DvrRecord.write(adustedSize) una o più volte nello spazio di archiviazione.
    I dati vengono trasferiti dall'MQ dell'HAL allo spazio di archiviazione.
  • Esegui DvrRecord.write(buffer, adustedSize) una o più volte per mettere in buffer.
    I dati vengono copiati dal MQ dell'HAL al buffer client.
Per i dati di indice: viene trasferito il payload dell'evento.

Per i contenuti registrati: stream TS con Muxed 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++
DemuxFilterTemiEvent[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 pianificazione interna, esegui
Filter.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++
DemuxFilterMmtpRecordEvent[i];


Per i contenuti registrati, in base a RecordStatus::* e alla programmazione interna, esegui una delle seguenti operazioni:
  • Esegui DvrRecord.write(adjustedSize) una o più volte nello spazio di archiviazione.
    I dati vengono trasferiti dall'MQ dell'HAL allo spazio di archiviazione.
  • Esegui DvrRecord.write(buffer, adjustedSize)una o più volte per eseguire il buffer.
    I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Per i dati di indice: viene trasferito il payload dell'evento.

Per i contenuti registrati: stream registrato con codifica multiplex riempito in FMQ.

Se l'origine del filtro per la registrazione è compresa tra TLV.TLV e IP.IP con passthrough, lo stream registrato avrà 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 dall'MQ di HAL al buffer del client.
Il pacchetto del payload IP viene compilato in FMQ da un altro pacchetto del payload IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Facoltativo:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Il sottostream del protocollo filtrato viene inviato al filtro successivo nella catena di filtri. N/D
isPassthrough:
false
Obbligatorio:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Consigliato:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
In base all'evento e alla pianificazione interna, esegui
Filter.read(buffer, offset, adjustedSize) una o più volte.

I dati vengono copiati dall'MQ dell'HAL al buffer del client.
Il sottostream del protocollo filtrato con l'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 viene inviato al filtro successivo nella catena di filtri. N/D
Flusso di esempio per utilizzare il filtro per creare PSI/SI

Flusso di esempio per l&#39;utilizzo del filtro per creare PSI/SI.

Figura 10. Flusso per la creazione di 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. Elaborazione 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

Flusso di esempio per l&#39;utilizzo di MediaEvent dal filtro.

Figura 11. Procedura per utilizzare MediaEvent dal filtro

  1. Apri, configura e avvia i filtri A/V.
  2. Elaborazione MediaEvent.
  3. Ricevi MediaEvent.
  4. Inserisci in coda il blocco lineare in codec.
  5. Rilascia l'handle 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.

Esempio di flusso per avviare una registrazione

Flusso di esempio per avviare una registrazione.

Figura 12. Flusso per avviare una registrazione

  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 dei 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 Tuner segue 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 del modulo File HAL
ITuner N/D frontend(open, getIds, getInfo), openDemux, openDescrambler, openLnb, 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, removePid IDescrambler.hal

Tuner HAL 1.1 (derivato da Tuner HAL 1.0)

Moduli Comandi di base Controlli specifici del modulo 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

Diagramma di flusso delle interazioni tra i moduli dell&#39;HAL per sintonizzatori.

Figura 13. Diagramma delle interazioni tra i moduli HAL del sintonizzatore

Collegamento dei filtri

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 struttura ad albero. Il percorso di chiusura non è consentito.
  • Il nodo principale è demux.
  • I filtri funzionano in modo indipendente.
  • Tutti i filtri iniziano a ricevere dati.
  • Il collegamento dei filtri viene eseguito nell'ultimo filtro.

Il blocco di codice riportato di seguito e la Figura 14 illustrano un esempio di filtro 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 dei filtri.

Figura 14. Diagramma di flusso di un collegamento di filtri per più livelli

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. 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. 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 client 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

Il TRM calcola la priorità del client utilizzando i parametri del suo profilo e il valore della priorità del file di configurazione. La priorità potrebbe essere aggiornata anche da un valore di priorità arbitrario del client.

Parametri nel profilo del cliente

Il TRM recupera l'ID processo da mTvInputSessionId per decidere se un'app è in primo piano o in background. Per creare mTvInputSessionId, TvInputService.onCreateSession o TvInputService.onCreateRecordingSession, viene inizializzata 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 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 conforme a platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd.

Valore di priorità arbitrario e valore accettabile

TRM fornisce updateClientPriority per consentire al client di aggiornare il valore della priorità e il valore di nice arbitrari. 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 "utile" diminuisce il valore di priorità del cliente prima che questo venga confrontato con quello del client 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 rivendicazione.

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