W przypadku Androida 11 lub nowszego możesz używać platformy Android Tuner do dostarczania treści audio-wideo. Platforma korzysta z potoku sprzętowego dostarczanego przez producentó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ę multimedialną (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 przypadku Androida 11 ulepszyliśmy te komponenty:
- CAS V2
TvInputServicelub usługa wejścia TV (TIS)TvInputManagerServicelub Usługa zarządzania wejściami TV (TIMS)MediaCodeclub kodek multimediówAudioTracklub ścieżkę audio.MediaResourceManagerlub menedżer zasobów multimedialnych (MRM).
Rysunek 1. Interakcje między komponentami Androida TV
Funkcje
Interfejs obsługuje te standardy DTV:
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analogowy
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 nośnika
- Oczyść ścieżkę nośnika
- Zabezpieczanie lokalnego rekordu
- Bezpieczne odtwarzanie lokalne
Interfejsy API tunera obsługują te przypadki użycia:
- Skanuj
- Na żywo
- Odtwarzanie
- Nagraj
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 się od dostawcy w ramach tych wytycznych i jak dostawca może to osiągnąć.
- Eksportuje funkcje frontendu, demultipleksera i deszyfratora do platformy za pomocą interfejsów
IFrontend,IDemux,IDescrambler,IFilter,IDvriILnb. - Zawiera funkcje integrujące HAL tunera 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 kontrolę uprawnień 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 odzyskiwać niewystarczające zasoby z aplikacji. Regułą domyślną jest wygrana pierwszego planu.
Media CAS i CAS HAL zostały wzbogacone o funkcje wymienione poniżej.
- 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 warstwą HAL tunera, udostępniając kluczowe tokeny.
MediaCodec i AudioTrack zostały wzbogacone o funkcje wymienione poniżej.
- Przyjmuje bezpieczną pamięć A/V jako dane wejściowe treści.
- Skonfigurowano synchronizację sprzętową 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ń podczas odtwarzania transmisji na żywo.
Konfiguracja
Rysunek 3. Konfigurowanie sekwencji odtwarzania transmisji na żywo
Obsługa plików audio-wideo
Rysunek 4. Obsługa dźwięku i obrazu podczas odtwarzania transmisji na żywo
Postępowanie z zaszyfrowanymi treściami
Rysunek 5. Postępowanie z zaszyfrowanymi treściami podczas odtwarzania transmisji na żywo
Przetwarzanie danych audio i 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 Tuner SDK API 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()
Minimalna wymagana wersja HAL znajduje się w dokumentacji nowych interfejsów API Androida 12.
Pakiety
Interfejs Tuner SDK API 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 uzyskiwania 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(): uzyskuje instancję odtwarzania, określając rozmiar bufora.openDescrambler(): pobiera instancję dekodera.openLnb(): uzyskuje 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 poniższych klas.
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 ona szybsza.
Gdy użytkownik zadzwoni pod numer Tuner.tune, nastąpią te działania:
- Usługa 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 przechodzi do następnej dostępnej częstotliwości 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ść.Raporty HAL skanują wiadomości
LOCKED, jeśli sygnał jest zablokowany. HAL może też zgłaszać inne komunikaty skanowania, aby dostarczać dodatkowe informacje 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 przechodzi do następnej dostępnej częstotliwości 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 pod numer
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 zajęć: 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 poniższych klas i służy do raportowania zdarzeń dotyczących różnych rodzajów danych.
SectionEventMediaEventPesEventTsRecordEventMmtpRecordEventTemiEventDownloadEventIpPayloadEvent
W przypadku Androida 12 z interfejsem HAL tunera 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 interfejsu 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 interfejsu 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 komunikatów 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 interfejsu 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 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ć funkcji Direct Audio w przypadku 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ń TS z multipleksowaniem 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. |
Odfiltrowane mmtp z mmtp nagłówkiemjest 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 MQ interfejsu 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 MQ interfejsu 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 |
Odfiltrowany podstrumień protokołu zasila następny filtr 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 |
Odfiltrowany ładunek protokołu jest przekazywany 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 proces używania MediaEvent z filtra
Rysunek 11. Przepływ do użycia MediaEvent z filtra
- Otwórz, skonfiguruj i uruchom filtry A/V.
- Przetwarzanie
MediaEvent. - Otrzymaj
MediaEvent. - Dodaj blok liniowy do kolejki:
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 rozpoczynający nagrywanie
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();Otrzymuj
RecordEventi pobieraj 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 Tuner HAL, a platforma używa go do komunikacji z implementacją Tuner HAL.
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 tunera. TV Input Framework (TIF) używa mechanizmu „pierwszy, który pozyska, wygrywa”, co oznacza, że aplikacja, która jako pierwsza uzyska zasób, 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)
Poniżej znajdziesz interfejsy do zamawiania i zwalniania zasobów.
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 klientów i żądań.
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 dowolną wartość priorytetu od klienta.
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. Poniżej znajdziesz listę predefiniowanych przypadków użycia.
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 wskazuje, jak pobłażliwe jest zachowanie klienta, gdy jest ono sprzeczne z zachowaniem innego klienta. Wartość nice zmniejsza priorytet klienta przed porównaniem go 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