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
TvInputServicelub Usługa wprowadzania danych w TV (TIS)TvInputManagerServicelub Usługa zarządzania wejściami telewizora (TIMS).MediaCodeclub kodek multimedialny.AudioTracklub ścieżkę audio.MediaResourceManagerlub 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,IDvriILnb. - Zawiera funkcje integrujące Tuner HAL z innymi komponentami platformy, takimi jak
MediaCodeciAudioTrack.
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_payloadi 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.tunerandroid.media.tv.tuner.frontendandroid.media.tv.tuner.filterandroid.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 parametryuseCaseisessionId.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.
cancelTuningscan/cancelScanninggetAvSyncHwIdgetAvSyncTimeconnectCiCam1/disconnectCiCamshareFrontendFromTunerupdateResourcePrioritysetOnTuneEventListenersetResourceLostListener
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.
AnalogFrontendSettingsAtsc3FrontendSettingsAtscFrontendSettingsDvbcFrontendSettingsDvbsFrontendSettingsDvbtFrontendSettingsIsdbs3FrontendSettingsIsdbsFrontendSettingsIsdbtFrontendSettings
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.
AnalogFrontendCapabilitiesAtsc3FrontendCapabilitiesAtscFrontendCapabilitiesDvbcFrontendCapabilitiesDvbsFrontendCapabilitiesDvbtFrontendCapabilitiesIsdbs3FrontendCapabilitiesIsdbsFrontendCapabilitiesIsdbtFrontendCapabilities
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
FrontendSettingswymaganymi informacjami za pomocąTuner.tune. - Jeśli sygnał jest zablokowany, HAL zgłasza komunikaty
LOCKED. - TIS używa
Frontend.getStatusdo 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
LOCKEDwiadomoś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.getStatusdo 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 strukturaFrontendSettingsjest pusta, HAL używa następnego dostępnego ustawienia. W przeciwnym razie HAL używaFrontendSettingsdo 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ć wFrontendSettingsdla 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.getStatusdo zbierania niezbędnych informacji. - TIS ponownie dzwoni
Tuner.scan, aby kontynuować skanowanie. (FrontendSettingsjest 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.
AlpFilterConfigurationIpFilterConfigurationMmtpFilterConfigurationTlvFilterConfigurationTsFilterConfiguration
Ustawienia pochodzą z tych klas: Ustawienia dotyczą podtypu filtra i określają, jakie rodzaje danych może on wykluczać.
SectionSettingsAvSettingsPesSettingsRecordSettingsDownloadSettings
FilterEvent pochodzi z klas poniżej i służy do raportowania zdarzeń dotyczących różnych rodzajów danych.
SectionEventMediaEventPesEventTsRecordEventMmtpRecordEventTemiEventDownloadEventIpPayloadEvent
W przypadku Androida 12 z Tuner HAL w wersji 1.1 lub nowszej obsługiwane są te zdarzenia:
IpCidChangeEventRestartEventScramblingStatusEvent
Zdarzenia i format danych z filtra
| Typ filtra | Flagi | Wydarzenia | Operacja na danych | Format danych |
|---|---|---|---|---|
TS.SECTIONMMTP.SECTIONIP.SECTIONTLV.SECTIONALP.SECTION |
isRaw: |
Obowiązkowe:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWZalecane: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWOpcjonalne: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++Dane są kopiowane z MQ HAL do bufora klienta. |
||
TS.PES |
isRaw: |
Obowiązkowe:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWZalecane: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWOpcjonalne: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++Dane są kopiowane z MQ HAL do bufora klienta. |
||
MMTP.PES |
isRaw: |
Obowiązkowe:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWZalecane: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWOpcjonalne: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWZalecane: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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.AudioTS.VideoMMTP.AudioMMTP.Video |
isPassthrough: |
Opcjonalnie:DemuxFilterStatus::DATA_READYDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWOpcjonalne: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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.PCRIP.NTPALP.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_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATEROpcjonalne: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
Nie dotyczy |
MMTP.MMTP |
Nie dotyczy | Obowiązkowe:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWZalecane: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATEROpcjonalne: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWOpcjonalne: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWOpcjonalne: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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.IPTLV.TLVALP.ALP |
isPassthrough: |
Opcjonalnie:DemuxFilterStatus::DATA_READYDemuxFilterStatus::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_READYDemuxFilterStatus::DATA_OVERFLOWZalecane: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::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_THROUGHTLV.PAYLOAD_THROUGHALP.PAYLOAD_THROUGH |
Nie dotyczy | Opcjonalnie:DemuxFilterStatus::DATA_READYDemuxFilterStatus::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.
configureattachFilterdetachFilterstartflushstopsetFileDescriptorwrite
DvrPlayback udostępnia te metody odtwarzania.
configurestartflushstopsetFileDescriptorread
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
RecordEventi 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
OnRecordStatusChangedListeneri 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.halIFrontendCallback.hal |
IDemux |
close |
setFrontendDataSource, openFilter, openDvr, getAvSyncHwId,
getAvSyncTime, connect / disconnectCiCam |
IDemux.hal |
IDvr |
close, start, stop, configure |
attach/detachFilters, flush, getQueueDesc |
IDvr.halIDvrCallback.hal |
IFilter |
close, start, stop, configure, getId |
flush, getQueueDesc, releaseAvHandle, setDataSource |
IFilter.halIFilterCallback.hal |
ILnb |
close, setCallback |
setVoltage, setTone, setSatellitePosition, sendDiseqcMessage |
ILnb.halILnbCallback.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)/releaseFrontendrequestDemux(TunerDemuxRequest request, int[] demuxHandle)/releaseDemuxrequestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle)/releaseDescramblerrequestCasSession(CasSessionRequest request, int[] casSessionHandle)/releaseCasSessionrequestLnb(TunerLnbRequest request, int[] lnbHandle)/releaseLnb
Poniżej znajdziesz klasy klienta i żądania.
ResourceClientProfileResourcesReclaimListenerTunerFrontendRequestTunerDemuxRequestTunerDescramblerRequestCasSessionRequestTunerLnbRequest
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