W przypadku Androida 11 lub nowszego możesz używać platformy Android Tuner do przesyłania treści audio-wideo. Platforma korzysta z potoku sprzętowego dostawców, dzięki czemu nadaje się zarówno do układów SoC z niższej, jak i z wyższej półki. Zapewnia bezpieczny sposób dostarczania treści audio-wideo chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę multimediów (SMP), co umożliwia jej używanie w wysoce ograniczonym środowisku ochrony treści.
Standardowy interfejs między tunerem a systemem CAS na Androidzie przyspiesza integrację między dostawcami tunerów i dostawcami systemów CAS. Interfejs Tuner współpracuje z MediaCodec
i AudioTrack
, aby stworzyć jedno rozwiązanie dla Androida TV.
Interfejs tunera obsługuje zarówno telewizję cyfrową, jak i analogową w oparciu o główne standardy transmisji.
Komponenty
W przypadku Androida 11 3 komponenty zostały zaprojektowane specjalnie z myślą o platformie TV.
- Tuner HAL: interfejs między platformą a dostawcami.
- Interfejs API pakietu SDK tunera: interfejs między platformą a aplikacjami.
- Menedżer zasobów tunera (TRM): koordynuje zasoby sprzętowe tunera.
W Androidzie 11 ulepszyliśmy te komponenty:
- CAS V2
TvInputService
lub Usługa wprowadzania danych w TV (TIS)TvInputManagerService
lub Usługa zarządzania wejściami telewizora (TIMS).MediaCodec
lub kodek multimedialny.AudioTrack
lub ścieżkę audio.MediaResourceManager
lub menedżer zasobów multimedialnych (MRM).
Rysunek 1. Interakcje między komponentami Androida TV
Funkcje
Frontend obsługuje te standardy DTV:
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analogowe
Interfejs w Androidzie 12 z Tuner HAL w wersji 1.1 lub nowszej obsługuje poniższy standard DTV.
- DTMB
Demux obsługuje te protokoły strumieniowe:
- Strumień transportowy (TS)
- Protokół transportu multimediów MPEG (MMTP)
- Protokół internetowy (IP)
- Wartość długości typu (TLV)
- Protokół warstwy łącza ATSC (ALP)
Dekoder obsługuje poniższe zabezpieczenia treści.
- Bezpieczna ścieżka multimediów
- Wyczyść ścieżkę multimediów
- Zabezpieczanie lokalnego rekordu
- Bezpieczne odtwarzanie lokalne
Interfejsy API tunera obsługują te przypadki użycia:
- Skanowanie
- Na żywo
- Odtwarzanie
- Nagrywaj
Tuner, MediaCodec
i AudioTrack
obsługują te tryby przepływu danych:
- Ładunek ES z wyczyszczonym buforem pamięci
- Ładunek ES z bezpiecznym uchwytem pamięci
- Widok otoczenia
Ogólny projekt
Warstwa HAL tunera jest zdefiniowana między platformą Androida a sprzętem dostawcy.
- Opisuje, czego oczekuje od dostawcy platforma i jak dostawca może to osiągnąć.
- Eksportuje funkcje frontendu, demultipleksera i dekodera do platformy za pomocą interfejsów
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
iILnb
. - Zawiera funkcje integrujące Tuner HAL z innymi komponentami platformy, takimi jak
MediaCodec
iAudioTrack
.
Tworzone są klasa Java Tuner i klasa natywna.
- Interfejs Tuner Java API umożliwia aplikacjom dostęp do Tuner HAL za pomocą publicznych interfejsów API.
- Klasa natywna umożliwia sterowanie uprawnieniami i obsługę dużych ilości danych nagrywania lub odtwarzania za pomocą interfejsu HAL tunera.
- Moduł Native Tuner to pomost między klasą Tuner Java a warstwą HAL tunera.
Tworzona jest klasa TRM.
- Zarządza ograniczonymi zasobami tunera, takimi jak interfejs, LNB, sesje CAS i urządzenie wejściowe TV z poziomu HAL wejścia TV.
- Stosuje reguły, aby odzyskać niewystarczające zasoby z aplikacji. Regułą domyślną jest wygrana pierwszego planu.
Media CAS i CAS HAL zostały wzbogacone o te funkcje:
- Otwiera sesje CAS dla różnych zastosowań i algorytmów.
- Obsługuje dynamiczne systemy CAS, takie jak wyjmowanie i wkładanie modułów CICAM.
- Integruje się z Tuner HAL, udostępniając tokeny kluczy.
MediaCodec
i AudioTrack
zostały ulepszone o funkcje wymienione poniżej.
- Przyjmuje bezpieczną pamięć A/V jako dane wejściowe treści.
- Skonfigurowane do synchronizacji sprzętowej audio-wideo w odtwarzaniu tunelowanym.
- Skonfigurowana obsługa
ES_payload
i trybu przekazywania.
Rysunek 2. Diagram komponentów w warstwie HAL tunera
Ogólny przepływ pracy
Poniższe diagramy przedstawiają sekwencje wywołań w przypadku odtwarzania transmisji na żywo.
Konfiguracja
Rysunek 3. Konfigurowanie sekwencji odtwarzania transmisji na żywo
Obsługa sprzętu audio-wideo
Rysunek 4. Obsługa dźwięku i obrazu podczas odtwarzania transmisji na żywo
Postępowanie w przypadku zaszyfrowanych treści
Rysunek 5. Postępowanie z zaszyfrowanymi treściami podczas odtwarzania transmisji na żywo
Przetwarzanie danych audio-wideo
Rysunek 6. Przetwarzanie audio i wideo do odtwarzania transmisji na żywo
Interfejs Tuner SDK API
Interfejs API pakietu Tuner SDK obsługuje interakcje z Tuner JNI, Tuner HAL i TunerResourceManager
. Aplikacja TIS korzysta z interfejsu Tuner SDK API, aby uzyskiwać dostęp do zasobów i podzespołów Tunera, takich jak filtr i dekoder. Frontend i demux to komponenty wewnętrzne.
Rysunek 7. Interakcje z interfejsem Tuner SDK API
Wersje
Od Androida 12 interfejs API pakietu SDK Tuner obsługuje nową funkcję w Tuner HAL 1.1, która jest wstecznie zgodną aktualizacją wersji Tuner 1.0.
Aby sprawdzić działającą wersję HAL, użyj tego interfejsu API.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
Minimalną wymaganą wersję HAL znajdziesz w dokumentacji nowych interfejsów API Androida 12.
Pakiety
Interfejs API pakietu SDK Tuner udostępnia 4 pakiety wymienione poniżej.
android.media.tv.tuner
android.media.tv.tuner.frontend
android.media.tv.tuner.filter
android.media.tv.tuner.dvr
Rysunek 8. Pakiety interfejsu API pakietu SDK Tuner
Android.media.tv.tuner
Pakiet Tuner to punkt wejścia do korzystania z platformy Tuner. Aplikacja TIS używa pakietu do inicjowania i pozyskiwania instancji zasobów przez określenie ustawienia początkowego i wywołania zwrotnego.
tuner()
: inicjuje instancję Tunera, określając parametryuseCase
isessionId
.tune()
: pobiera zasób interfejsu i dostraja go, określając parametrFrontendSetting
.openFilter()
: pobiera instancję filtra, określając jego typ.openDvrRecorder()
: Pobiera instancję nagrywania, określając rozmiar bufora.openDvrPlayback()
: Pobiera instancję odtwarzania, określając rozmiar bufora.openDescrambler()
: pobiera instancję dekodera.openLnb()
: pobiera wewnętrzną instancję LNB.openLnbByName()
: uzyskuje instancję zewnętrznego konwertera LNB.openTimeFilter()
: Pobiera instancję filtra czasu.
Pakiet Tuner udostępnia funkcje, które nie są objęte pakietami filtrów, DVR i frontend. Funkcje te są wymienione poniżej.
cancelTuning
scan
/cancelScanning
getAvSyncHwId
getAvSyncTime
connectCiCam1
/disconnectCiCam
shareFrontendFromTuner
updateResourcePriority
setOnTuneEventListener
setResourceLostListener
Android.media.tv.tuner.frontend
Pakiet interfejsu zawiera zbiory ustawień, informacji, stanów, zdarzeń i funkcji związanych z interfejsem.
Zajęcia
FrontendSettings
jest obliczany dla różnych standardów DTV na podstawie poniższych klas.
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
W przypadku Androida 12 z Tuner HAL w wersji 1.1 lub nowszej obsługiwany jest ten standard DTV:
DtmbFrontendSettings
FrontendCapabilities
jest obliczany dla różnych standardów DTV na podstawie klas poniżej.
AnalogFrontendCapabilities
Atsc3FrontendCapabilities
AtscFrontendCapabilities
DvbcFrontendCapabilities
DvbsFrontendCapabilities
DvbtFrontendCapabilities
Isdbs3FrontendCapabilities
IsdbsFrontendCapabilities
IsdbtFrontendCapabilities
W przypadku Androida 12 z Tuner HAL w wersji 1.1 lub nowszej obsługiwany jest ten standard DTV:
DtmbFrontendCapabilities
FrontendInfo
pobiera informacje z interfejsu.
FrontendStatus
pobiera bieżący stan interfejsu.
OnTuneEventListener
nasłuchuje zdarzeń w interfejsie.
Aplikacja TIS używa ScanCallback
do przetwarzania wiadomości ze skanowania z frontendu.
Skanowanie kanałów
Aby skonfigurować telewizor, aplikacja skanuje możliwe częstotliwości i tworzy listę kanałów, do których użytkownicy mają dostęp. TIS może używać Tuner.tune
, Tuner.scan(BLIND_SCAN)
lub Tuner.scan(AUTO_SCAN)
do skanowania kanałów.
Jeśli TIS ma dokładne informacje o dostawie sygnału, takie jak częstotliwość, standard (np. T/T2, S/S2) i dodatkowe niezbędne informacje (np. identyfikator PLD), zalecamy użycie opcji Tuner.tune
, ponieważ jest szybsza.
Gdy użytkownik zadzwoni pod numer Tuner.tune
, nastąpią te działania:
- TIS wypełnia pole
FrontendSettings
wymaganymi informacjami za pomocąTuner.tune
. - Jeśli sygnał jest zablokowany, HAL zgłasza komunikaty
LOCKED
. - TIS używa
Frontend.getStatus
do zbierania niezbędnych informacji. - TIS przełącza się na następną dostępną częstotliwość na liście częstotliwości.
TIS ponownie wywołuje Tuner.tune
, aż wszystkie częstotliwości zostaną wyczerpane.
Podczas dostrajania możesz zadzwonić pod numer stopTune()
lub close()
, aby wstrzymać lub zakończyć połączenie Tuner.tune
.
Tuner.scan(AUTO_SCAN)
Jeśli usługa TIS nie ma wystarczających informacji, aby użyć Tuner.tune
, ale ma listę częstotliwości i standardowy typ (np. DVB T/C/S), zalecane jest Tuner.scan(AUTO_SCAN)
.
Gdy użytkownik zadzwoni pod numer Tuner.scan(AUTO_SCAN)
, nastąpią te działania:
TIS używa
Tuner.scan(AUTO_SCAN)
z wypełnionym polemFrontendSettings
, które zawiera częstotliwość.Skanowanie raportów HAL
LOCKED
wiadomości, jeśli sygnał jest zablokowany. Warstwa HAL może też zgłaszać inne komunikaty skanowania, aby dostarczać dodatkowych informacji o sygnałach.TIS używa
Frontend.getStatus
do zbierania niezbędnych informacji.TIS wywołuje
Tuner.scan
, aby HAL mógł przejść do następnego ustawienia na tej samej częstotliwości. Jeśli strukturaFrontendSettings
jest pusta, HAL używa następnego dostępnego ustawienia. W przeciwnym razie HAL używaFrontendSettings
do jednorazowego skanowania i wysyłaEND
, aby wskazać, że operacja skanowania została zakończona.TIS powtarza powyższe działania, dopóki nie wyczerpią się wszystkie ustawienia częstotliwości.
HAL wysyła
END
, aby wskazać, że skanowanie zostało zakończone.TIS przełącza się na następną dostępną częstotliwość na liście częstotliwości.
TIS ponownie wywołuje Tuner.scan(AUTO_SCAN)
, aż wszystkie częstotliwości zostaną wyczerpane.
Podczas skanowania możesz zadzwonić pod numer stopScan()
lub close()
, aby wstrzymać lub zakończyć skanowanie.
Tuner.scan(BLIND_SCAN)
Jeśli TIS nie ma listy częstotliwości, a HAL dostawcy może wyszukiwać częstotliwość określonego przez użytkownika interfejsu, aby uzyskać zasób interfejsu, zalecana jest opcja Tuner.scan(BLIND_SCAN)
.
- TIS używa
Tuner.scan(BLIND_SCAN)
. Częstotliwość można określić wFrontendSettings
dla częstotliwości początkowej, ale TIS ignoruje inne ustawienia wFrontendSettings
. - Jeśli sygnał jest zablokowany, HAL zgłasza skanowanie
LOCKED
. - TIS używa
Frontend.getStatus
do zbierania niezbędnych informacji. - TIS ponownie dzwoni
Tuner.scan
, aby kontynuować skanowanie. (FrontendSettings
jest ignorowany). - TIS powtarza powyższe działania, dopóki nie wyczerpią się wszystkie ustawienia częstotliwości. HAL zwiększa częstotliwość bez konieczności podejmowania działań przez TIS.
Raporty HAL
PROGRESS
.
TIS ponownie wywołuje Tuner.scan(AUTO_SCAN)
, aż wszystkie częstotliwości zostaną wyczerpane.
HAL zgłasza END
, aby wskazać, że skanowanie zostało zakończone.
Podczas skanowania możesz zadzwonić pod numer stopScan()
lub close()
, aby wstrzymać lub zakończyć skanowanie.
Rysunek 9. Schemat blokowy skanowania TIS
Android.media.tv.tuner.filter
Pakiet filtrów to zbiór operacji filtrowania wraz z konfiguracją, ustawieniami, wywołaniami zwrotnymi i zdarzeniami. Pakiet obejmuje te działania: Pełną listę operacji znajdziesz w kodzie źródłowym Androida.
configure()
start()
stop()
flush()
read()
Pełną listę znajdziesz w kodzie źródłowym Androida.
FilterConfiguration
pochodzi z tych klas: Konfiguracje dotyczą głównego typu filtra i określają, jakiego protokołu używa filtr do wyodrębniania danych.
AlpFilterConfiguration
IpFilterConfiguration
MmtpFilterConfiguration
TlvFilterConfiguration
TsFilterConfiguration
Ustawienia pochodzą z tych klas: Ustawienia dotyczą podtypu filtra i określają, jakie rodzaje danych może on wykluczać.
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
FilterEvent
pochodzi z klas poniżej i służy do raportowania zdarzeń dotyczących różnych rodzajów danych.
SectionEvent
MediaEvent
PesEvent
TsRecordEvent
MmtpRecordEvent
TemiEvent
DownloadEvent
IpPayloadEvent
W przypadku Androida 12 z Tuner HAL w wersji 1.1 lub nowszej obsługiwane są te zdarzenia:
IpCidChangeEvent
RestartEvent
ScramblingStatusEvent
Zdarzenia i format danych z filtra
Typ filtra | Flagi | Wydarzenia | Operacja na danych | Format danych |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION |
isRaw: |
Obowiązkowe:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiajFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z kolejki MQ HAL do bufora klienta. |
Jeden zmontowany pakiet sesji jest wypełniany w FMQ przez inny pakiet sesji. |
isRaw: |
Obowiązkowe:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalne: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Dane są kopiowane z MQ HAL do bufora klienta. |
||
TS.PES |
isRaw: |
Obowiązkowe:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiajFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z kolejki MQ HAL do bufora klienta. |
Jeden zmontowany pakiet PES jest wypełniany w FMQ przez inny pakiet PES. |
isRaw: |
Obowiązkowe:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalne: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Dane są kopiowane z MQ HAL do bufora klienta. |
||
MMTP.PES |
isRaw: |
Obowiązkowe:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiajFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z kolejki MQ HAL do bufora klienta. |
Jeden zmontowany pakiet MFU jest wypełniany w FMQ przez inny pakiet MFU. |
isRaw: |
Obowiązkowe:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalne: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Dane są kopiowane z kolejki MQ HAL do bufora klienta. |
||
TS.TS |
Nie dotyczy | Obowiązkowe:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiajFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z kolejki MQ HAL do bufora klienta. |
Odfiltrowane ts z ts nagłówkiemjest wypełnione w FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
Opcjonalnie:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Klient może rozpocząć MediaCodec po otrzymaniu DemuxFilterStatus::DATA_READY .Klient może zadzwonić Filter.flush po otrzymaniu DemuxFilterStatus::DATA_OVERFLOW . |
Nie dotyczy |
isPassthrough: |
Obowiązkowe:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalne: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Aby użyć MediaCodec :for i=0; i<n; i++ Aby użyć bezpośredniego dźwięku z AudioTrack :for i=0; i<n; i++ |
Dane ES lub częściowe dane ES w pamięci ION. | |
TS.PCR IP.NTP ALP.PTP |
Nie dotyczy | Obowiązkowy: nie dotyczy
Opcjonalny: nie dotyczy |
Nie dotyczy | Nie dotyczy |
TS.RECORD |
Nie dotyczy | Obowiązkowe: DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opcjonalne: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W przypadku danych indeksu:for i=0; i<n; i++ W przypadku nagranych treści, zgodnie z RecordStatus::* i harmonogramem wewnętrznym, wykonaj jedną z tych czynności:
|
W przypadku danych indeksu: są one przesyłane w ładunku zdarzenia. W przypadku nagranych treści: strumień Muxed TS wypełniony w FMQ. |
TS.TEMI |
Nie dotyczy | Obowiązkowe:DemuxFilterEvent::DemuxFilterTemiEvent[n] Opcjonalne: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
Nie dotyczy |
MMTP.MMTP |
Nie dotyczy | Obowiązkowe:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiajFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z kolejki MQ HAL do bufora klienta. |
Pole „Filtered out mmtp with mmtp header” jest wypełnione w FMQ. |
MMTP.RECORD |
Nie dotyczy | Obowiązkowe:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opcjonalne: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W przypadku danych indeksu: for i=0; i<n; i++ W przypadku nagranych treści, zgodnie z RecordStatus::* i wewnętrznym harmonogramem, wykonaj jedną z tych czynności:
|
W przypadku danych indeksu: są one przesyłane w ładunku zdarzenia. W przypadku nagranych treści: wypełniony multipleksowany nagrany strumień FMQ. Jeśli źródłem filtra do nagrywania jest TLV.TLV do IP.IP z przekazywaniem, nagrywany strumień ma nagłówek TLV i IP. |
MMTP.DOWNLOAD |
Nie dotyczy | Obowiązkowe:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalne: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size) Dane są kopiowane z kolejki komunikatów HAL do bufora klienta. |
Pakiet pobierania jest wypełniany w FMQ przez inny pakiet pobierania IP. |
IP.IP_PAYLOAD |
Nie dotyczy | Obowiązkowe:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalne: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size) Dane są kopiowane z kolejki komunikatów HAL do bufora klienta. |
Pakiet danych IP jest zastępowany w FMQ przez inny pakiet danych IP. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Opcjonalnie:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Podstrumień protokołu po zastosowaniu filtra przekazuje dane do następnego filtra w łańcuchu filtrów. | Nie dotyczy |
isPassthrough: |
Obowiązkowe:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiajFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z kolejki MQ HAL do bufora klienta. |
Odfiltrowany podstrumień protokołu z wypełnionym nagłówkiem protokołu FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
Nie dotyczy | Opcjonalnie:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Odfiltrowane dane protokołu są przekazywane do następnego filtra w łańcuchu filtrów. | Nie dotyczy |
Przykładowy proces używania filtra do tworzenia PSI/SI
Rysunek 10. Proces tworzenia PSI/SI
Otwórz filtr.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
Skonfiguruj i uruchom filtr.
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();
Przetwarzanie
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); } } } };
Przykładowy przepływ użycia MediaEvent z filtra
Rysunek 11. Flow to use MediaEvent from filter
- Otwórz, skonfiguruj i uruchom filtry A/V.
- Przetwarzanie
MediaEvent
. - Otrzymaj
MediaEvent
. - Umieść blok liniowy w kolejce na pozycji
codec
. - Zwolnij uchwyt A/V, gdy dane zostaną wykorzystane.
Android.media.tv.tuner.dvr
DvrRecorder
udostępnia te metody nagrywania.
configure
attachFilter
detachFilter
start
flush
stop
setFileDescriptor
write
DvrPlayback
udostępnia te metody odtwarzania.
configure
start
flush
stop
setFileDescriptor
read
DvrSettings
służy do konfigurowania DvrRecorder
i DvrPlayback
.
OnPlaybackStatusChangedListener
i OnRecordStatusChangedListener
służą do raportowania stanu instancji DVR.
Przykładowy przepływ rozpoczynania nagrywania
Rysunek 12. Flow do rozpoczęcia nagrywania
Otwórz, skonfiguruj i uruchom
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();
Otrzymaj
RecordEvent
i pobierz informacje o indeksie.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. } } } };
Zainicjuj
OnRecordStatusChangedListener
i zapisz dane rekordu.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
Warstwa HAL tunera jest zgodna z HIDL i określa interfejs między platformą a sprzętem dostawcy. Dostawcy używają tego interfejsu do implementowania HAL tunera, a platforma używa go do komunikacji z implementacją HAL tunera.
Moduły
Tuner HAL 1.0
Moduły | Podstawowe funkcje sterowania | Ustawienia dotyczące modułu | Pliki HAL |
---|---|---|---|
ITuner |
Nie dotyczy | 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 (pochodny od Tuner HAL 1.0)
Moduły | Podstawowe funkcje sterowania | Ustawienia dotyczące modułu | Pliki HAL |
---|---|---|---|
ITuner |
Nie dotyczy | 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 |
Rysunek 13. Diagram interakcji między modułami Tuner HAL
Połączenie filtra
Warstwa HAL tunera obsługuje łączenie filtrów, dzięki czemu można je łączyć z innymi filtrami na wielu warstwach. Filtry działają zgodnie z tymi regułami:
- Filtry są połączone w drzewo, a zamknięta ścieżka jest niedozwolona.
- Węzłem głównym jest demux.
- Filtry działają niezależnie.
- Wszystkie filtry zaczynają otrzymywać dane.
- Połączenie filtra jest czyszczone na ostatnim filtrze.
Blok kodu poniżej i rysunek 14 przedstawiają przykład filtrowania wielu warstw.
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>)
}
Rysunek 14. Schemat połączenia filtrów dla wielu warstw
Menedżer zasobów tunera
Przed wprowadzeniem Menedżera zasobów tunera (TRM) przełączanie między dwiema aplikacjami wymagało tego samego sprzętu tunera. TV Input Framework (TIF) używa mechanizmu „pierwszy, który pozyska, wygrywa”, co oznacza, że aplikacja, która jako pierwsza uzyska dostęp do zasobu, zachowuje go. Ten mechanizm może jednak nie być idealny w przypadku niektórych skomplikowanych zastosowań.
TRM działa jako usługa systemowa, która zarządza tunerem, TVInput
i zasobami sprzętowymi CAS na potrzeby aplikacji. TRM korzysta z mechanizmu „zwycięstwa na pierwszym planie”, który oblicza priorytet aplikacji na podstawie jej stanu (na pierwszym planie lub w tle) i typu przypadku użycia. TRM przyznaje lub odbiera zasób na podstawie priorytetu. TRM centralizuje zarządzanie zasobami ATV w przypadku transmisji, OTT i DVR.
Interfejs TRM
TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl
dla platformy Tuner, MediaCas
i TvInputHardwareManager
, aby rejestrować, żądać lub zwalniać zasoby.
Poniżej znajdziesz listę interfejsów do zarządzania klientami.
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
unregisterClientProfile(in int clientId)
Interfejsy do wysyłania próśb o zasoby i ich zwalniania są wymienione poniżej.
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
Poniżej znajdziesz klasy klienta i żądania.
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
Priorytet klienta
TRM oblicza priorytet klienta na podstawie parametrów z jego profilu i wartości priorytetu z pliku konfiguracyjnego. Priorytet może też zostać zaktualizowany przez klienta za pomocą dowolnej wartości priorytetu.
Parametry w profilu klienta
TRM pobiera identyfikator procesu z mTvInputSessionId
, aby określić, czy aplikacja jest aplikacją na pierwszym planie czy w tle. Aby utworzyć mTvInputSessionId
, TvInputService.onCreateSession
lub TvInputService.onCreateRecordingSession
, usługa TIS inicjuje sesję.
mUseCase
– wskazuje przypadek użycia sesji. Predefiniowane przypadki użycia są wymienione poniżej.
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
}
Plik konfiguracji
Domyślny plik konfiguracji
Poniższy domyślny plik konfiguracyjny zawiera wartości priorytetów dla wstępnie zdefiniowanych przypadków użycia. Użytkownicy mogą zmieniać wartości za pomocą dostosowanego pliku konfiguracyjnego.
Przypadek użycia | Pierwszy plan | Tło |
---|---|---|
LIVE |
490 | 400 |
PLAYBACK |
480 | 300 |
RECORD |
600 | 500 |
SCAN |
450 | 200 |
BACKGROUND |
180 | 100 |
Dostosowany plik konfiguracji
Dostawcy mogą dostosowywać plik konfiguracji/vendor/etc/tunerResourceManagerUseCaseConfig.xml
. Ten plik służy do dodawania, usuwania i aktualizowania typów przypadków użycia oraz wartości priorytetu przypadków użycia.
Dostosowany plik może używać
platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
jako szablonu.
Na przykład nowy przypadek użycia dostawcy to VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
.
Format powinien być zgodny z tym wzorcem: platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
.
Dowolna wartość priorytetu i wartość nice
TRM udostępnia updateClientPriority
, aby klient mógł zaktualizować dowolną wartość priorytetu i wartość nice.
Dowolna wartość priorytetu zastępuje wartość priorytetu obliczoną na podstawie typu przypadku użycia i identyfikatora sesji.
Wartość nice określa, jak pobłażliwe jest zachowanie klienta, gdy jest ono sprzeczne z zachowaniem innego klienta. Wartość nice zmniejsza priorytet klienta, zanim zostanie on porównany z priorytetem klienta wymagającego.
Mechanizm odzyskiwania
Diagram poniżej pokazuje, jak zasoby są odzyskiwane i przypisywane w przypadku konfliktu zasobów.
Rysunek 15. Diagram mechanizmu odzyskiwania w przypadku konfliktu między zasobami Tuner