Unter Android 11 oder höher können Sie das Android Tuner-Framework verwenden, um A/V-Inhalte bereitzustellen. Das Framework nutzt die Hardwarepipeline der Anbieter und eignet sich daher sowohl für Low-End- als auch für High-End-SoCs. Es bietet eine sichere Möglichkeit, A/V-Inhalte bereitzustellen, die durch eine vertrauenswürdige Ausführungsumgebung (Trusted Execution Environment, TEE) und einen sicheren Medienpfad (Secure Media Path, SMP) geschützt sind. So kann es in einer stark eingeschränkten Umgebung für den Schutz von Inhalten verwendet werden.
Die standardisierte Schnittstelle zwischen Tuner und Android CAS führt zu einer schnelleren Integration zwischen Tuner- und CAS-Anbietern. Die Tuner-Oberfläche funktioniert mit MediaCodec
und AudioTrack
, um eine globale Lösung für Android TV zu schaffen.
Die Tuner-Oberfläche unterstützt sowohl digitales als auch analoges Fernsehen auf Grundlage der wichtigsten Übertragungsstandards.
Komponenten
Für Android 11 wurden drei Komponenten speziell für die TV-Plattform entwickelt.
- Tuner HAL: Eine Schnittstelle zwischen dem Framework und den Anbietern
- Tuner SDK API:Eine Schnittstelle zwischen dem Framework und Apps
- Tuner Resource Manager (TRM): Koordiniert die Hardwareressourcen des Tuners
Für Android 11 wurden die folgenden Komponenten optimiert.
- CAS V2
TvInputService
oder TV-Eingabedienst (TIS)TvInputManagerService
oder TV Input Manager Service (TIMS)MediaCodec
oder Medien-CodecAudioTrack
oder AudiotrackMediaResourceManager
oder Media Resource Manager (MRM)
Abbildung 1: Interaktionen zwischen Android TV-Komponenten
Funktionen
Das Frontend unterstützt die folgenden DTV-Standards.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analog
Das Frontend in Android 12 mit Tuner HAL 1.1 oder höher unterstützt den unten aufgeführten DTV-Standard.
- DTMB
Demux unterstützt die folgenden Streamprotokolle.
- Transport Stream (TS)
- MPEG Media Transport Protocol (MMTP)
- Internet Protocol (IP)
- Type Length Value (TLV)
- ATSC-Link-Ebenen-Protokoll (ALP)
Der Descrambler unterstützt die folgenden Inhaltsschutzmaßnahmen.
- Sicherer Medienpfad
- Medienpfad löschen
- Lokalen Eintrag sichern
- Lokale Wiedergabe schützen
Tuner APIs unterstützen die folgenden Anwendungsfälle.
- Scannen
- Live
- Wiedergabe
- Aufnehmen
Tuner, MediaCodec
und AudioTrack
unterstützen die folgenden Datenflussmodi.
- ES-Nutzlast mit leeren Arbeitsspeicher-Puffer
- ES-Nutzlast mit sicherem Speicher-Handle
- Passthrough
Design allgemein
Die Tuner HAL wird zwischen dem Android-Framework und der Hardware des Anbieters definiert.
- Beschreibt, was das Framework vom Anbieter erwartet und wie er dies umsetzen kann.
- Exportiert die Funktionen von frontend, Demux und Descrambler über die Schnittstellen
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
undILnb
in das Framework. - Enthält die Funktionen zur Einbindung der Tuner-HAL in andere Framework-Komponenten wie
MediaCodec
undAudioTrack
.
Eine Java-Klasse und eine native Klasse für den Tuner werden erstellt.
- Mit der Tuner Java API können Apps über öffentliche APIs auf die Tuner HAL zugreifen.
- Die native Klasse ermöglicht die Berechtigungssteuerung und Verarbeitung großer Mengen von Aufnahme- oder Wiedergabedaten mit der Tuner HAL.
- Das native Tuner-Modul ist eine Brücke zwischen der Tuner-Java-Klasse und der Tuner-HAL.
Eine TRM-Klasse wird erstellt.
- Verwaltet begrenzte Tunerressourcen wie Frontend, LNB, CAS-Sitzungen und ein TV-Eingabegerät über die HAL für TV-Eingaben.
- Es werden Regeln angewendet, um nicht ausreichende Ressourcen aus Apps zurückzugewinnen. Die Standardregel ist „Im Vordergrund“.
Media CAS und die CAS HAL wurden um die folgenden Funktionen erweitert.
- Öffnet CAS-Sitzungen für verschiedene Verwendungen und Algorithmen.
- Unterstützt dynamische CAS-Systeme wie das Entfernen und Einfügen von CICAM.
- Integriert sich über Schlüssel-Tokens in die Tuner-HAL.
MediaCodec
und AudioTrack
wurden um die folgenden Funktionen erweitert.
- Nimmt sicheren A/V-Speicher als Inhaltseingabe an.
- Konfiguriert für die hardwaregestützte Synchronisierung von Audio und Video bei der getunnelten Wiedergabe.
- Unterstützung für
ES_payload
und Passthrough-Modus konfiguriert
Abbildung 2: Diagramm der Tuner-HAL-Komponenten
Gesamter Workflow
Die folgenden Diagramme zeigen Aufrufssequenzen für die Wiedergabe von Liveübertragungen.
Einrichten
Abbildung 3: Einrichtungsabfolge für die Wiedergabe von Livestreams
Umgang mit A/V
Abbildung 4: Umgang mit Audio-/Videoinhalten für die Wiedergabe von Liveübertragungen
Umgang mit verschlüsselten Inhalten
Abbildung 5: Umgang mit verschlüsselten Inhalten für die Wiedergabe von Liveübertragungen
Verarbeitung von A/V-Daten
Abbildung 6 A/V-Dateien für die Wiedergabe von Livestreams verarbeiten
Tuner SDK API
Die Tuner SDK API verarbeitet die Interaktionen mit der Tuner JNI, der Tuner HAL und TunerResourceManager
. Die TIS-App verwendet die Tuner SDK API, um auf Tuner-Ressourcen und Unterkomponenten wie den Filter und den Dekoder zuzugreifen. Frontend und Demux sind interne Komponenten.
Abbildung 7. Interaktionen mit der Tuner SDK API
Versionen
Ab Android 12 unterstützt die Tuner SDK API eine neue Funktion in Tuner HAL 1.1, einem abwärtskompatiblen Versionsupgrade von Tuner 1.0.
Verwenden Sie die folgende API, um die ausgeführte HAL-Version zu prüfen.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
Die Mindestversion der HAL finden Sie in der Dokumentation der neuen Android 12 APIs.
Pakete
Die Tuner SDK API bietet die vier folgenden Pakete.
android.media.tv.tuner
android.media.tv.tuner.frontend
android.media.tv.tuner.filter
android.media.tv.tuner.dvr
Abbildung 8. Tuner SDK API-Pakete
Android.media.tv.tuner
Das Tuner-Paket ist ein Einstiegspunkt für die Verwendung des Tuner-Frameworks. Die TIS-App verwendet das Paket, um Ressourceninstanzen zu initialisieren und zu erwerben, indem die anfängliche Einstellung und der Rückruf angegeben werden.
tuner()
: Initialisiert eine Tunerinstanz durch Angabe der ParameteruseCase
undsessionId
.tune()
: Hiermit wird eine Frontend-Ressource abgerufen und durch Angabe des ParametersFrontendSetting
optimiert.openFilter()
: Hiermit wird eine Filterinstanz durch Angabe des Filtertyps abgerufen.openDvrRecorder()
: Erwirbt eine Aufnahmeinstanz, indem die Puffergröße angegeben wird.openDvrPlayback()
: Erwirbt eine Wiedergabeinstanz, indem die Puffergröße angegeben wird.openDescrambler()
: Erwirbt eine Dekoderinstanz.openLnb()
: Erwirbt eine interne LNB-Instanz.openLnbByName()
: Erwirbt eine externe LNB-Instanz.openTimeFilter()
: Ruft eine Zeitfilterinstanz ab.
Das Tuner-Paket bietet Funktionen, die nicht durch die Filter-, DVR- und Frontend-Pakete abgedeckt sind. Die Funktionen sind unten aufgeführt.
cancelTuning
scan
/cancelScanning
getAvSyncHwId
getAvSyncTime
connectCiCam1
/disconnectCiCam
shareFrontendFromTuner
updateResourcePriority
setOnTuneEventListener
setResourceLostListener
Android.media.tv.tuner.frontend
Das Frontend-Paket enthält Sammlungen von Frontend-bezogenen Einstellungen, Informationen, Status, Ereignissen und Funktionen.
Klassen
FrontendSettings
wird für verschiedene DTV-Standards von den folgenden Klassen abgeleitet.
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
Ab Android 12 mit Tuner HAL 1.1 oder höher wird der folgende DTV-Standard unterstützt.
DtmbFrontendSettings
FrontendCapabilities
wird für verschiedene DTV-Standards durch die folgenden Klassen abgeleitet.
AnalogFrontendCapabilities
Atsc3FrontendCapabilities
AtscFrontendCapabilities
DvbcFrontendCapabilities
DvbsFrontendCapabilities
DvbtFrontendCapabilities
Isdbs3FrontendCapabilities
IsdbsFrontendCapabilities
IsdbtFrontendCapabilities
Ab Android 12 mit Tuner HAL 1.1 oder höher wird der folgende DTV-Standard unterstützt.
DtmbFrontendCapabilities
FrontendInfo
ruft die Informationen des Front-Ends ab.
FrontendStatus
ruft den aktuellen Status des Front-Ends ab.
OnTuneEventListener
überwacht die Ereignisse im Frontend.
Die TIS-App verwendet ScanCallback
, um Scannachrichten vom Frontend zu verarbeiten.
Kanalsuche
Um einen Fernseher einzurichten, scannt die App mögliche Frequenzen und erstellt ein Kanalangebot, auf das Nutzer zugreifen können. TIS verwendet möglicherweise Tuner.tune
, Tuner.scan(BLIND_SCAN)
oder Tuner.scan(AUTO_SCAN)
, um das Kanalscannen abzuschließen.
Wenn TIS korrekte Übermittlungsinformationen für das Signal hat, z. B. Frequenz, Standard (z. B. T/T2, S/S2) und weitere erforderliche Informationen (z. B. PLD-ID), wird Tuner.tune
als schnellere Option empfohlen.
Wenn der Nutzer Tuner.tune
anruft, geschieht Folgendes:
- TIS füllt
FrontendSettings
mithilfe vonTuner.tune
mit den erforderlichen Informationen aus. - Die HAL meldet
LOCKED
-Nachrichten, wenn das Signal gesperrt ist. - TIS verwendet
Frontend.getStatus
, um die erforderlichen Informationen zu erfassen. - TIS wechselt zur nächsten verfügbaren Frequenz in der Frequenzliste.
TIS ruft Tuner.tune
so lange wieder auf, bis alle Frequenzen erschöpft sind.
Während der Abstimmung können Sie stopTune()
oder close()
drücken, um den Tuner.tune
-Anruf zu pausieren oder zu beenden.
Tuner.scan(AUTO_SCAN)
Wenn TIS nicht genügend Informationen für die Verwendung von Tuner.tune
hat, aber eine Frequenzliste und einen Standardtyp (z. B. DVB-T/C/S) hat, wird Tuner.scan(AUTO_SCAN)
empfohlen.
Wenn der Nutzer Tuner.scan(AUTO_SCAN)
anruft, geschieht Folgendes:
Bei TIS wird
Tuner.scan(AUTO_SCAN)
mitFrontendSettings
ausgefüllt, wobeiFrontendSettings
für die Häufigkeit steht.Die HAL-Berichte scannen
LOCKED
Nachrichten, wenn das Signal gesperrt ist. Der HAL kann auch andere Scannachrichten senden, um zusätzliche Informationen zum Signal bereitzustellen.TIS verwendet
Frontend.getStatus
, um die erforderlichen Informationen zu erfassen.TIS ruft
Tuner.scan
auf, damit die HAL mit der nächsten Einstellung mit derselben Frequenz fortfährt. Wenn dieFrontendSettings
-Struktur leer ist, verwendet die HAL die nächste verfügbare Einstellung. Andernfalls verwendet HALFrontendSettings
für einen einmaligen Scan und sendetEND
, um anzugeben, dass der Scanvorgang abgeschlossen ist.TIS wiederholt die oben genannten Aktionen, bis alle Einstellungen für die Frequenz ausgeschöpft sind.
Der HAL sendet
END
, um anzugeben, dass der Scanvorgang abgeschlossen ist.TIS wechselt zur nächsten verfügbaren Frequenz in der Frequenzliste.
TIS ruft Tuner.scan(AUTO_SCAN)
so lange wieder auf, bis alle Frequenzen erschöpft sind.
Während des Scannens können Sie stopScan()
oder close()
drücken, um den Vorgang zu pausieren oder zu beenden.
Tuner.scan(BLIND_SCAN)
Wenn TIS keine Häufigkeitsliste hat und die HAL des Anbieters nach der Häufigkeit des vom Nutzer angegebenen Front-Ends suchen kann, um die Front-End-Ressource abzurufen, wird Tuner.scan(BLIND_SCAN)
empfohlen.
- TIS verwendet
Tuner.scan(BLIND_SCAN)
. InFrontendSettings
kann eine Häufigkeit für den Start angegeben werden. Andere Einstellungen inFrontendSettings
werden von TIS jedoch ignoriert. - Die HAL meldet eine Scan-
LOCKED
-Nachricht, wenn das Signal gesperrt ist. - TIS verwendet
Frontend.getStatus
, um die erforderlichen Informationen zu erfassen. - TIS ruft
Tuner.scan
noch einmal auf, um mit dem Scannen fortzufahren. (FrontendSettings
wird ignoriert.) - TIS wiederholt die oben genannten Aktionen, bis alle Einstellungen für die Frequenz ausgeschöpft sind. Die HAL erhöht die Häufigkeit, ohne dass TIS etwas tun muss.
Der HAL meldet
PROGRESS
.
TIS ruft Tuner.scan(AUTO_SCAN)
so lange wieder auf, bis alle Frequenzen erschöpft sind.
Der HAL meldet END
, um anzugeben, dass der Scanvorgang abgeschlossen ist.
Während des Scans können Sie stopScan()
oder close()
drücken, um den Scan zu pausieren oder zu beenden.
Abbildung 9. Flussdiagramm eines TIS-Scans
Android.media.tv.tuner.filter
Das Filterpaket enthält Filtervorgänge sowie Konfiguration, Einstellungen, Rückrufe und Ereignisse. Das Paket enthält die folgenden Vorgänge. Eine vollständige Liste der Vorgänge finden Sie im Android-Quellcode.
configure()
start()
stop()
flush()
read()
Eine vollständige Liste finden Sie im Android-Quellcode.
FilterConfiguration
wird aus den folgenden Klassen abgeleitet. Die Konfigurationen gelten für den Hauptfiltertyp und geben an, welches Protokoll der Filter zum Extrahieren von Daten verwendet.
AlpFilterConfiguration
IpFilterConfiguration
MmtpFilterConfiguration
TlvFilterConfiguration
TsFilterConfiguration
Die Einstellungen werden aus den folgenden Klassen abgeleitet. Die Einstellungen gelten für den Filteruntertyp und geben an, welche Daten vom Filter ausgeschlossen werden können.
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
FilterEvent
wird aus den unten aufgeführten Klassen abgeleitet, um Ereignisse für verschiedene Datentypen zu erfassen.
SectionEvent
MediaEvent
PesEvent
TsRecordEvent
MmtpRecordEvent
TemiEvent
DownloadEvent
IpPayloadEvent
Ab Android 12 mit Tuner HAL 1.1 oder höher werden die folgenden Ereignisse unterstützt.
IpCidChangeEvent
RestartEvent
ScramblingStatusEvent
Ereignisse und Datenformat aus dem Filter
Filtertyp | Flaggen | Ereignisse | Datenvorgang | Datenformat |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION |
isRaw: |
Erforderlich:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Empfohlen: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Führen Sie Filter.read(buffer, offset, adjustedSize) gemäß dem Ereignis und dem internen Zeitplan ein- oder mehrmals aus.Die Daten werden aus dem MQ von HAL in den Client-Puffer kopiert. |
Ein zusammengesetztes Sitzungspaket wird in der FMQ durch ein anderes Sitzungspaket gefüllt. |
isRaw: |
Erforderlich:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Optional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Die Daten werden aus dem MQ von HAL in den Client-Puffer kopiert. |
||
TS.PES |
isRaw: |
Erforderlich:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Empfohlen: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Führen Sie Filter.read(buffer, offset, adjustedSize) gemäß dem Ereignis und dem internen Zeitplan ein- oder mehrmals aus.Daten werden aus dem MQ der HAL in den Client-Puffer kopiert. |
Ein zusammengesetztes PES-Paket wird in FMQ von einem anderen PES-Paket ausgefüllt. |
isRaw: |
Erforderlich:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Optional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Die Daten werden aus dem MQ von HAL in den Client-Puffer kopiert. |
||
MMTP.PES |
isRaw: |
Erforderlich:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Empfohlen: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Führen Sie Filter.read(buffer, offset, adjustedSize) gemäß dem Ereignis und dem internen Zeitplan ein- oder mehrmals aus.Die Daten werden aus dem MQ der HAL in den Client-Puffer kopiert. |
Ein zusammengesetztes MFU-Paket wird in FMQ durch ein anderes MFU-Paket gefüllt. |
isRaw: |
Erforderlich:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Optional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Die Daten werden aus dem MQ der HAL in den Client-Puffer kopiert. |
||
TS.TS |
– | Erforderlich:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Empfohlen: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Führen Sie Filter.read(buffer, offset, adjustedSize) gemäß dem Ereignis und dem internen Zeitplan ein- oder mehrmals aus.Daten werden aus dem MQ der HAL in den Client-Puffer kopiert. |
Ausgefilterte ts mit ts -Headerwird in FMQ ausgefüllt. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
Optional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Der Kunde kann MediaCodec starten, nachdem er DemuxFilterStatus::DATA_READY erhalten hat.Der Client kann Filter.flush aufrufen, nachdem er DemuxFilterStatus::DATA_OVERFLOW empfangen hat. |
– |
isPassthrough: |
Erforderlich:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Optional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
So verwenden Sie MediaCodec :for i=0; i<n; i++ So verwenden Sie Direct Audio von AudioTrack :for i=0; i<n; i++ |
ES- oder teilweise ES-Daten im ION-Speicher. | |
TS.PCR IP.NTP ALP.PTP |
– | Erforderlich: –
Optional: – |
– | – |
TS.RECORD |
– | Erforderlich: DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Optional: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Für Indexdaten:for i=0; i<n; i++ Für aufgezeichnete Inhalte: Gehe gemäß RecordStatus::* und dem internen Zeitplan so vor:
|
Indexdaten:Werden in der Ereignisnutzlast übertragen. Für aufgezeichnete Inhalte:Gemischter TS-Stream, der in FMQ gefüllt ist. |
TS.TEMI |
– | Erforderlich:DemuxFilterEvent::DemuxFilterTemiEvent[n] Optional: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
– |
MMTP.MMTP |
– | Erforderlich:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Empfohlen: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Führen Sie Filter.read(buffer, offset, adjustedSize) gemäß dem Ereignis und dem internen Zeitplan ein- oder mehrmals aus.Daten werden aus dem MQ der HAL in den Client-Puffer kopiert. |
Ausgefilterte mmtp mit mmtp -Headerwird in FMQ ausgefüllt. |
MMTP.RECORD |
– | Erforderlich:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Optional: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Indexdaten: for i=0; i<n; i++ Aufgezeichnete Inhalte: Führe gemäß RecordStatus::* und dem internen Zeitplan eine der folgenden Aktionen aus:
|
Indexdaten:Werden in der Ereignisnutzlast übertragen. Für aufgezeichnete Inhalte:Gemischter aufgezeichneter Stream, der in FMQ ausgefüllt ist. Wenn die Filterquelle für die Aufzeichnung TLV.TLV bis IP.IP mit Passthrough ist, hat der aufgezeichnete Stream einen TLV- und einen IP-Header. |
MMTP.DOWNLOAD |
– | Erforderlich:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Optional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size) Die Daten werden aus dem MQ von HAL in den Client-Puffer kopiert. |
Das Downloadpaket wird in FMQ von einem anderen IP-Downloadpaket ausgefüllt. |
IP.IP_PAYLOAD |
– | Erforderlich:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Optional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size) Die Daten werden aus dem MQ von HAL in den Client-Puffer kopiert. |
Das IP-Nutzlastpaket wird in der FMQ durch ein anderes IP-Nutzlastpaket gefüllt. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Optional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Der herausgefilterte Protokoll-Unterstream wird an den nächsten Filter in der Filterkette weitergeleitet. | – |
isPassthrough: |
Erforderlich:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Empfohlen: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Führen Sie Filter.read(buffer, offset, adjustedSize) gemäß dem Ereignis und dem internen Zeitplan ein- oder mehrmals aus.Daten werden aus dem MQ der HAL in den Client-Puffer kopiert. |
Der herausgefilterte Protokoll-Substream mit Protokoll-Header wird in FMQ ausgefüllt. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
– | Optional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Die herausgefilterte Protokollnutzlast wird an den nächsten Filter in der Filterkette weitergeleitet. | – |
Beispiel für die Verwendung eines Filters zum Erstellen von PSI/SI
Abbildung 10. Ablauf zum Erstellen von PSI/SI
Öffnen Sie einen Filter.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
Konfigurieren und starten Sie den Filter.
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();
SectionEvent
verarbeitenFilterCallback 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); } } } };
Beispiel für die Verwendung von „MediaEvent“ aus einem Filter
Abbildung 11 Ablauf zum Verwenden von „MediaEvent“ aus dem Filter
- Öffnen, konfigurieren und starten Sie die Audio-/Videofilter.
MediaEvent
verarbeitenMediaEvent
erhalten- Stellen Sie den linearen Block in die Warteschlange für
codec
. - Gib den A/V-Handle frei, wenn die Daten verbraucht wurden.
Android.media.tv.tuner.dvr
DvrRecorder
bietet folgende Methoden zur Aufzeichnung.
configure
attachFilter
detachFilter
start
flush
stop
setFileDescriptor
write
DvrPlayback
bietet folgende Wiedergabemethoden.
configure
start
flush
stop
setFileDescriptor
read
Mit DvrSettings
werden DvrRecorder
und DvrPlayback
konfiguriert.
OnPlaybackStatusChangedListener
und OnRecordStatusChangedListener
werden verwendet, um den Status einer DVR-Instanz zu melden.
Beispiel für einen Ablauf zum Starten eines Datensatzes
Abbildung 12 Ablauf zum Starten eines Datensatzes
Öffnen, konfigurieren und starten Sie
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();
RecordEvent
empfangen und die Indexinformationen abrufenFilterCallback 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. } } } };
Initialisieren Sie
OnRecordStatusChangedListener
und speichern Sie die Datensatzdaten.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); } } };
Tuner-HAL
Die Tuner-HAL folgt HIDL und definiert die Schnittstelle zwischen dem Framework und der Hardware des Anbieters. Anbieter verwenden die Schnittstelle, um die Tuner HAL zu implementieren, und das Framework verwendet sie, um mit der Tuner HAL-Implementierung zu kommunizieren.
Module
Tuner HAL 1.0
Module | Grundlegende Bedienelemente | Modulspezifische Steuerelemente | HAL-Dateien |
---|---|---|---|
ITuner |
– | frontend(open, getIds, getInfo) , openDemux ,
openDescrambler , openLnb ,
getDemuxCaps |
ITuner.hal |
IFrontend |
setCallback , getStatus , close
| tune , stopTune , scan ,
stopScan , setLnb |
IFrontend.hal IFrontendCallback.hal |
IDemux |
close |
setFrontendDataSource , openFilter , openDvr , getAvSyncHwId ,
getAvSyncTime , connect / disconnectCiCam |
IDemux.hal |
IDvr |
close , start , stop , configure |
attach/detachFilters , flush , getQueueDesc |
IDvr.hal IDvrCallback.hal |
IFilter |
close , start , stop , configure , getId |
flush , getQueueDesc , releaseAvHandle , setDataSource |
IFilter.hal IFilterCallback.hal |
ILnb |
close , setCallback |
setVoltage , setTone , setSatellitePosition , sendDiseqcMessage |
ILnb.hal ILnbCallback.hal |
IDescrambler |
close |
setDemuxSource , setKeyToken ,
addPid , removePid |
IDescrambler.hal |
Tuner HAL 1.1 (abgeleitet von Tuner HAL 1.0)
Module | Grundlegende Bedienelemente | Modulspezifische Steuerelemente | HAL-Dateien |
---|---|---|---|
ITuner |
– | 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 |
Abbildung 13 Diagramm der Interaktionen zwischen den Tuner HAL-Modulen
Filterverknüpfung
Die Tuner-HAL unterstützt die Filterverknüpfung, sodass Filter für mehrere Ebenen mit anderen Filtern verknüpft werden können. Die Filter folgen den folgenden Regeln.
- Filter sind als Baum verknüpft, ein geschlossener Pfad ist nicht zulässig.
- Der Stammknoten ist „demux“.
- Filter arbeiten unabhängig voneinander.
- Für alle Filter werden Daten abgerufen.
- Die Filterverknüpfung wird beim letzten Filter geleert.
Der Codeblock unten und Abbildung 14 zeigen ein Beispiel für das Filtern mehrerer Ebenen.
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>)
}
Abbildung 14. Flussdiagramm einer Filterverknüpfung für mehrere Ebenen
Tuner Resource Manager
Vor Tuner Resource Manager (TRM) war für den Wechsel zwischen zwei Apps dieselbe Tuner-Hardware erforderlich. Das TV Input Framework (TIF) verwendete einen Mechanismus, bei dem die App, die die Ressource zuerst erhält, sie auch behält. Dieser Mechanismus ist jedoch möglicherweise nicht ideal für einige komplexe Anwendungsfälle.
TRM wird als Systemdienst ausgeführt, um die Tuner-, TVInput
- und CAS-Hardwareressourcen für Apps zu verwalten. Bei der TRM-Funktion wird ein „Vorrang im Vordergrund“-Mechanismus verwendet, der die Priorität der App basierend auf dem Status im Vordergrund oder Hintergrund und dem Anwendungsfall berechnet. TRM gewährt oder entzieht die Ressource basierend auf der Priorität. TRM zentralisiert die Verwaltung von ATV-Ressourcen für Broadcast, OTT und DVR.
TRM-Schnittstelle
TRM stellt AIDL-Schnittstellen in ITunerResourceManager.aidl
für das Tuner-Framework, MediaCas
und TvInputHardwareManager
bereit, um Ressourcen zu registrieren, anzufordern oder freizugeben.
Die Oberflächen für die Kundenverwaltung sind unten aufgeführt.
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
unregisterClientProfile(in int clientId)
Die Schnittstellen zum Anfordern und Freigeben von Ressourcen sind unten aufgeführt.
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
Client- und Anfrageklassen sind unten aufgeführt.
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
Kundenpriorität
TRM berechnet die Priorität des Clients anhand von Parametern aus dem Profil des Clients und dem Prioritätswert aus der Konfigurationsdatei. Die Priorität kann auch durch einen beliebigen Prioritätswert vom Client aktualisiert werden.
Parameter im Profil des Kunden
TRM ruft die Prozess-ID von mTvInputSessionId
ab, um zu entscheiden, ob es sich bei einer App um eine App im Vordergrund oder im Hintergrund handelt. Um mTvInputSessionId
, TvInputService.onCreateSession
oder TvInputService.onCreateRecordingSession
zu erstellen, wird eine TIS-Sitzung initialisiert.
mUseCase
gibt den Anwendungsfall der Sitzung an. Die vordefinierten Anwendungsfälle sind unten aufgeführt.
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
}
Konfigurationsdatei
Standardkonfigurationsdatei
Die folgende Standardkonfigurationsdatei enthält Prioritätswerte für vordefinierte Anwendungsfälle. Nutzer können die Werte mit einer benutzerdefinierten Konfigurationsdatei ändern.
Anwendungsfall | Vordergrund | Hintergrund |
---|---|---|
LIVE |
490 | 400 |
PLAYBACK |
480 | 300 |
RECORD |
600 | 500 |
SCAN |
450 | 200 |
BACKGROUND |
180 | 100 |
Benutzerdefinierte Konfigurationsdatei
Anbieter können die Konfigurationsdatei anpassen./vendor/etc/tunerResourceManagerUseCaseConfig.xml
Mit dieser Datei können Sie die Anwendungsfalltypen und die Prioritätswerte für Anwendungsfälle hinzufügen, entfernen oder aktualisieren.
Die benutzerdefinierte Datei kann platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
als Vorlage verwenden.
Ein Beispiel für einen neuen Anwendungsfall für einen Anbieter ist VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
.
Das Format sollte platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
sein.
Willkürlicher Prioritätswert und Nice-Wert
TRM stellt updateClientPriority
für den Client bereit, um den beliebigen Prioritätswert und den Nice-Wert zu aktualisieren.
Der beliebige Prioritätswert überschreibt den Prioritätswert, der aus dem Anwendungsfalltyp und der Sitzungs-ID berechnet wird.
Der Wert „nice“ gibt an, wie tolerant das Verhalten des Clients ist, wenn er mit einem anderen Client in Konflikt steht. Der Wert „nett“ verringert den Prioritätswert des Kunden, bevor sein Prioritätswert mit dem des schwierigen Kunden verglichen wird.
Reaktivierungsmechanismus
Das folgende Diagramm zeigt, wie Ressourcen bei einem Ressourcenkonflikt zurückgefordert und neu zugewiesen werden.
Abbildung 15. Diagramm des Rückforderungsmechanismus bei einem Konflikt zwischen Tunerressourcen