W przypadku systemu Android 11 lub nowszego możesz używać platformy Android Tuner do dostarczania treści A/V. Framework wykorzystuje potok sprzętowy od dostawców, dzięki czemu nadaje się zarówno do SoC z niższej, jak i wyższej półki. Struktura zapewnia bezpieczny sposób dostarczania treści A/V chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę multimediów (SMP), umożliwiając korzystanie z nich w bardzo ograniczonym środowisku ochrony treści.
Standaryzowany interfejs pomiędzy Tunerem i Android CAS zapewnia szybszą integrację pomiędzy dostawcami tunerów i CAS. Interfejs tunera współpracuje z MediaCodec
i AudioTrack
, tworząc jedno światowe rozwiązanie dla Android TV. Interfejs tunera obsługuje zarówno telewizję cyfrową, jak i telewizję analogową w oparciu o główne standardy transmisji.
składniki
W przypadku Androida 11 trzy komponenty są specjalnie zaprojektowane dla platformy telewizyjnej.
- Tuner HAL: Interfejs pomiędzy frameworkiem a dostawcami
- Tuner SDK API: Interfejs pomiędzy frameworkiem i aplikacjami
- Menedżer zasobów tunera (TRM): koordynuje zasoby sprzętowe tunera
W systemie Android 11 ulepszono następujące komponenty.
- CAS V2
-
TvInputService
lub usługa wejścia telewizyjnego (TIS) - Usługa
TvInputManagerService
lub usługa Menedżera wejścia telewizyjnego (TIMS) -
MediaCodec
lub kodek multimedialny -
AudioTrack
lub ścieżka audio -
MediaResourceManager
lub menedżer zasobów multimedialnych (MRM)
Rysunek 1. Interakcje pomiędzy komponentami Android TV
Cechy
Frontend obsługuje poniższe standardy DTV.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analog
Frontend w systemie Android 12 z tunerem HAL 1.1 lub nowszym obsługuje poniższy standard DTV.
- DTMB
Demux obsługuje poniższe protokoły strumieniowe.
- Strumień transportowy (TS)
- Protokół transportu multimediów MPEG (MMTP)
- Protokół internetowy (IP)
- Wpisz wartość długości (TLV)
- Protokół warstwy łącza ATSC (ALP)
Descrambler obsługuje poniższe zabezpieczenia treści.
- Bezpieczna ścieżka multimediów
- Wyczyść ścieżkę multimediów
- Bezpieczny zapis lokalny
- Bezpieczne odtwarzanie lokalne
Interfejsy API tunera obsługują poniższe przypadki użycia.
- Skanowanie
- Na żywo
- Odtwarzanie nagranego dźwięku
- Nagrywać
Tuner, MediaCodec
i AudioTrack
obsługują poniższe tryby przepływu danych.
- Ładunek ES z czystym buforem pamięci
- Ładunek ES z bezpiecznym uchwytem pamięci
- Przejść przez
Ogólny projekt
Tuner HAL jest zdefiniowany pomiędzy platformą Android a sprzętem dostawcy.
- Opisuje, czego platforma oczekuje od dostawcy i w jaki sposób dostawca może to zrobić.
- Eksportuje funkcjonalności frontendu, demuxa i deszymblera do frameworka poprzez interfejsy
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
iILnb
. - Zawiera funkcje umożliwiające integrację tunera HAL z innymi komponentami platformy, takimi jak
MediaCodec
iAudioTrack
.
Tworzona jest klasa Tuner Java i klasa natywna.
- Interfejs API Tuner Java umożliwia aplikacjom dostęp do Tuner HAL za pośrednictwem publicznych interfejsów API.
- Klasa natywna umożliwia kontrolę uprawnień i obsługę dużych ilości danych dotyczących nagrywania lub odtwarzania za pomocą tunera HAL.
- Moduł Native Tuner jest pomostem pomiędzy klasą Tuner Java i Tuner HAL.
Tworzona jest klasa TRM.
- Zarządza ograniczonymi zasobami tunera, takimi jak Frontend, LNB, sesje CAS i urządzenie wejściowe TV z wejścia TV HAL.
- Stosuje reguły odzyskiwania niewystarczających zasobów z aplikacji. Domyślną zasadą jest wygrana pierwszego planu.
Media CAS i CAS HAL zostały wzbogacone o poniższe funkcje.
- Otwiera sesje CAS dla różnych zastosowań i algorytmów.
- Obsługuje dynamiczne systemy CAS, takie jak usuwanie i wstawianie CICAM.
- Integruje się z tunerem HAL, udostępniając kluczowe tokeny.
MediaCodec
i AudioTrack
zostały ulepszone o poniższe funkcje.
- Jako wejście zawartości pobiera bezpieczną pamięć A/V.
- Skonfigurowany do sprzętowej synchronizacji A/V w odtwarzaniu tunelowym.
- Skonfigurowana obsługa
ES_payload
i trybu przekazywania.
Rysunek 2. Schemat komponentów tunera HAL
Ogólny przepływ pracy
Poniższe diagramy ilustrują sekwencje wywołań dla odtwarzania transmisji na żywo.
Organizować coś
Rysunek 3. Sekwencja konfiguracji odtwarzania transmisji na żywo
Obsługa A/V
Rysunek 4. Obsługa A/V podczas odtwarzania transmisji na żywo
Obsługa zakodowanej treści
Rysunek 5. Obsługa zakodowanej zawartości podczas odtwarzania transmisji na żywo
Przetwarzanie danych A/V
Rysunek 6. Przetwarzanie A/V do odtwarzania transmisji na żywo
API SDK tunera
Interfejs API Tuner SDK obsługuje interakcje z Tuner JNI, Tuner HAL i TunerResourceManager
. Aplikacja TIS korzysta z interfejsu API Tuner SDK, aby uzyskać 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 API Tuner SDK
Wersje
Od systemu Android 12 interfejs API Tuner SDK obsługuje nową funkcję w Tuner HAL 1.1, która jest kompatybilną wstecz aktualizacją Tunera 1.0.
Użyj poniższego interfejsu API, aby sprawdzić działającą wersję HAL.
-
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
Minimalną wymaganą wersję HAL można znaleźć w dokumentacji nowych interfejsów API Androida 12.
Pakiety
Interfejs API Tuner SDK udostępnia cztery poniższe pakiety.
-
android.media.tv.tuner
-
android.media.tv.tuner.frontend
-
android.media.tv.tuner.filter
-
android.media.tv.tuner.dvr
Rysunek 8. Pakiety API tunera SDK
Tuner Android.media.tv
Pakiet Tuner jest punktem wyjścia do korzystania ze środowiska Tuner. Aplikacja TIS używa pakietu do inicjowania i pozyskiwania instancji zasobów poprzez określenie ustawień początkowych i wywołania zwrotnego.
-
tuner()
: Inicjuje instancję Tunera, określając parametryuseCase
isessionId
. -
tune()
: Pobiera zasób frontonu i dostraja go, określając parametrFrontendSetting
. -
openFilter()
: Pobiera instancję filtru poprzez określenie typu filtra. -
openDvrRecorder()
: Pobiera instancję nagrywania poprzez określenie rozmiaru bufora. -
openDvrPlayback()
: Uzyskuje instancję odtwarzania poprzez określenie rozmiaru bufora. -
openDescrambler()
: Pobiera instancję deszyfratora. -
openLnb()
: Pozyskuje wewnętrzną instancję LNB. -
openLnbByName()
: Pozyskuje zewnętrzną instancję LNB. -
openTimeFilter()
: Pobiera instancję filtra czasu.
Pakiet Tuner zapewnia funkcje, które nie są objęte pakietami filtrów, DVR i frontendu. Poniżej wymieniono funkcjonalności.
-
cancelTuning
-
scan
/cancelScanning
-
getAvSyncHwId
-
getAvSyncTime
-
connectCiCam1
/disconnectCiCam
-
shareFrontendFromTuner
-
updateResourcePriority
-
setOnTuneEventListener
-
setResourceLostListener
Android.media.tv.tuner.frontend
Pakiet frontonu zawiera zbiory ustawień, informacji, statusów, zdarzeń i możliwości związanych z frontendem.
Zajęcia
FrontendSettings
jest wyprowadzany dla różnych standardów DTV na podstawie poniższych klas.
-
AnalogFrontendSettings
-
Atsc3FrontendSettings
-
AtscFrontendSettings
-
DvbcFrontendSettings
-
DvbsFrontendSettings
-
DvbtFrontendSettings
-
Isdbs3FrontendSettings
-
IsdbsFrontendSettings
-
IsdbtFrontendSettings
Od systemu Android 12 z tunerem HAL 1.1 lub nowszym obsługiwany jest następujący standard DTV.
-
DtmbFrontendSettings
FrontendCapabilities
jest wyprowadzany dla różnych standardów DTV na podstawie poniższych klas.
-
AnalogFrontendCapabilities
-
Atsc3FrontendCapabilities
-
AtscFrontendCapabilities
-
DvbcFrontendCapabilities
-
DvbsFrontendCapabilities
-
DvbtFrontendCapabilities
-
Isdbs3FrontendCapabilities
-
IsdbsFrontendCapabilities
-
IsdbtFrontendCapabilities
Od systemu Android 12 z tunerem HAL 1.1 lub nowszym obsługiwany jest następujący standard DTV.
-
DtmbFrontendCapabilities
FrontendInfo
pobiera informacje o interfejsie. FrontendStatus
pobiera bieżący stan frontonu. OnTuneEventListener
nasłuchuje zdarzeń na interfejsie. Aplikacja TIS wykorzystuje ScanCallback
do przetwarzania wiadomości skanowania z interfejsu użytkownika.
Skanowanie kanałów
Aby skonfigurować telewizor, aplikacja skanuje możliwe częstotliwości i tworzy listę kanałów, do których użytkownicy będą mieli dostęp. TIS może używać Tuner.tune
, Tuner.scan(BLIND_SCAN)
lub Tuner.scan(AUTO_SCAN)
do zakończenia skanowania kanałów.
Jeśli TIS ma dokładne informacje o dostawie sygnału, takie jak częstotliwość, standard (na przykład T/T2, S/S2) i dodatkowe niezbędne informacje (na przykład identyfikator PLD), wówczas Tuner.tune
jest zalecany jako szybsza opcja .
Kiedy użytkownik wywołuje Tuner.tune
, mają miejsce następujące działania:
- TIS wypełnia
FrontendSettings
wymaganymi informacjami za pomocąTuner.tune
. - Raporty HAL dostrajają komunikaty
LOCKED
, jeśli sygnał jest zablokowany. - TIS korzysta z
Frontend.getStatus
w celu gromadzenia niezbędnych informacji. - TIS przechodzi do następnej dostępnej częstotliwości na swojej liście częstotliwości.
TIS ponownie wywołuje Tuner.tune
, aż do wyczerpania wszystkich częstotliwości.
Podczas strojenia możesz wywołać stopTune()
lub close()
, aby wstrzymać lub zakończyć wywołanie Tuner.tune
.
Skanowanie tunera(AUTO_SCAN)
Jeśli TIS nie ma wystarczających informacji, aby użyć Tuner.tune
, ale ma listę częstotliwości i typ standardu (na przykład DVB T/C/S), zalecany jest Tuner.scan(AUTO_SCAN)
.
Kiedy użytkownik wywołuje Tuner.scan(AUTO_SCAN)
, wykonywane są następujące działania:
TIS używa
Tuner.scan(AUTO_SCAN)
zFrontendSettings
wypełnionymi częstotliwością.Raporty HAL skanują wiadomości
LOCKED
, jeśli sygnał jest zablokowany. HAL może również raportować inne komunikaty skanowania, aby zapewnić dodatkowe informacje o sygnale.TIS korzysta z
Frontend.getStatus
w celu gromadzenia 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, warstwa HAL używa następnego dostępnego ustawienia. W przeciwnym razie warstwa HAL używaFrontendSettings
do jednorazowego skanowania i wysyłaEND
, aby wskazać, że operacja skanowania została zakończona.TIS powtarza powyższe czynności, aż do wyczerpania wszystkich ustawień częstotliwości.
HAL wysyła
END
, aby wskazać, że operacja skanowania została zakończona.TIS przechodzi do następnej dostępnej częstotliwości na swojej liście częstotliwości.
TIS ponownie wywołuje Tuner.scan(AUTO_SCAN)
aż do wyczerpania wszystkich częstotliwości.
Podczas skanowania możesz wywołać stopScan()
lub close()
, aby wstrzymać lub zakończyć skanowanie.
Skanowanie tunera(BLIND_SCAN)
Jeśli TIS nie ma listy częstotliwości, a warstwa HAL dostawcy może wyszukać częstotliwość frontendu określonego przez użytkownika, aby uzyskać zasób frontendu, zalecany jest Tuner.scan(BLIND_SCAN)
.
- TIS używa
Tuner.scan(BLIND_SCAN)
. Częstotliwość można określić wFrontendSettings
jako częstotliwość początkową, ale TIS ignoruje inne ustawienia wFrontendSettings
. - HAL zgłasza komunikat skanowania
LOCKED
, jeśli sygnał jest zablokowany. - TIS korzysta z
Frontend.getStatus
w celu gromadzenia niezbędnych informacji. - TIS ponownie wywołuje
Tuner.scan
, aby kontynuować skanowanie. (FrontendSettings
są ignorowane.) - TIS powtarza powyższe czynności, aż do wyczerpania wszystkich ustawień częstotliwości. HAL zwiększa częstotliwość bez konieczności podejmowania działań ze strony TIS. HAL raportuje
PROGRESS
.
TIS ponownie wywołuje Tuner.scan(AUTO_SCAN)
aż do wyczerpania wszystkich częstotliwości. HAL zgłasza END
, aby wskazać, że operacja skanowania została zakończona.
Podczas skanowania możesz wywołać stopScan()
lub close()
, aby wstrzymać lub zakończyć skanowanie.
Rysunek 9. Schemat blokowy skanowania TIS
Filtr.media.tv.tuner.Android.media.tv.tuner.filter
Pakiet filtrów to zbiór operacji filtrujących wraz z konfiguracją, ustawieniami, wywołaniami zwrotnymi i zdarzeniami. Pakiet zawiera poniższe operacje. 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
wywodzi się z poniższych 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 poniższych klas. Ustawienia dotyczą podtypu filtra i określają, jakiego rodzaju dane filtr może wykluczać.
-
SectionSettings
-
AvSettings
-
PesSettings
-
RecordSettings
-
DownloadSettings
FilterEvent
wywodzi się z poniższych klas i służy do raportowania zdarzeń dla różnych rodzajów danych.
-
SectionEvent
-
MediaEvent
-
PesEvent
-
TsRecordEvent
-
MmtpRecordEvent
-
TemiEvent
-
DownloadEvent
-
IpPayloadEvent
Od systemu Android 12 z tunerem HAL 1.1 lub nowszym obsługiwane są następujące zdarzenia.
-
IpCidChangeEvent
-
RestartEvent
-
ScramblingStatusEvent
Zdarzenia i format danych z filtra
Typ filtra | Flagi | Wydarzenia | Operacja danych | Format danych |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION | isRaw: | Obowiązkowy:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecana: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnijFilter.read(buffer, offset, adjustedSize) jeden lub więcej razy.Dane są kopiowane z MQ HAL do bufora klienta. | Jeden złożony pakiet sesji jest wypełniany w FMQ innym pakietem sesji. |
isRaw: | Obowiązkowy:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalny: 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ązkowy:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecana: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnijFilter.read(buffer, offset, adjustedSize) jeden lub więcej razy.Dane są kopiowane z MQ warstwy HAL do bufora klienta. | Jeden zmontowany pakiet PES jest wypełniany w FMQ innym pakietem PES. |
isRaw: | Obowiązkowy:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalny: 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ązkowy:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecana: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnijFilter.read(buffer, offset, adjustedSize) jeden lub więcej razy.Dane są kopiowane z MQ warstwy HAL do bufora klienta. | Jeden zmontowany pakiet MFU jest wypełniany FMQ przez inny pakiet MFU. |
isRaw: | Obowiązkowy:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalny: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Dane są kopiowane z MQ warstwy HAL do bufora klienta. | ||
TS.TS | Nie dotyczy | Obowiązkowy:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecana: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnijFilter.read(buffer, offset, adjustedSize) jeden lub więcej razy.Dane są kopiowane z MQ warstwy HAL do bufora klienta. | Odfiltrowano ts z nagłówkiem ts jest wypełniony FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video | isPassthrough: | Opcjonalny:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Klient może uruchomić MediaCodec po otrzymaniu DemuxFilterStatus::DATA_READY .Klient może wywołać Filter.flush po otrzymaniu DemuxFilterStatus::DATA_OVERFLOW . | Nie dotyczy |
isPassthrough: | Obowiązkowy:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalny: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Aby użyć MediaCodec :for i=0; i<n; i++ Aby użyć bezpośredniego dźwięku AudioTrack :for i=0; i<n; i++ | Dane ES lub częściowe ES w pamięci ION. | |
TS.PCR IP.NTP ALP.PTP | Nie dotyczy | Obowiązkowe: nie dotyczy Opcjonalnie: nie dotyczy | Nie dotyczy | Nie dotyczy |
TS.RECORD | Nie dotyczy | Obowiązkowy:DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opcjonalny: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Dla danych indeksowych:for i=0; i<n; i++ W przypadku nagranej treści zgodnie z RecordStatus::* i wewnętrznym harmonogramem wykonaj jedną z następujących czynności:
| Dla danych indeksowych: Przenoszony w ładunku zdarzenia. Dla nagranej zawartości: Muxed strumień TS wypełniony FMQ. |
TS.TEMI | Nie dotyczy | Obowiązkowy:DemuxFilterEvent::DemuxFilterTemiEvent[n] Opcjonalny: 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ązkowy:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecana: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnijFilter.read(buffer, offset, adjustedSize) jeden lub więcej razy.Dane są kopiowane z MQ warstwy HAL do bufora klienta. | Odfiltrowano mmtp z nagłówkiem mmtp jest wypełniony FMQ. |
MMTP.RECORD | Nie dotyczy | Obowiązkowy:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opcjonalny: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Dla danych indeksowych: for i=0; i<n; i++ W przypadku nagranej treści zgodnie z RecordStatus::* i wewnętrznym harmonogramem wykonaj jedną z następujących czynności:
| Dla danych indeksowych: Przenoszony w ładunku zdarzenia. W przypadku nagranej zawartości: zmultiplikowany nagrany strumień wypełniony FMQ. Jeśli źródłem filtra do nagrywania jest TLV.TLV do IP.IP z przejściem, zarejestrowany strumień ma nagłówek TLV i IP. |
MMTP.DOWNLOAD | Nie dotyczy | Obowiązkowy:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalny: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size) Dane są kopiowane z MQ HAL do bufora klienta. | Pakiet do pobrania jest wypełniany w FMQ przez inny pakiet do pobrania IP. |
IP.IP_PAYLOAD | Nie dotyczy | Obowiązkowy:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalny: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size) Dane są kopiowane z MQ HAL do bufora klienta. | Pakiet ładunku IP jest wypełniany w FMQ przez inny pakiet ładunku IP. |
IP.IP TLV.TLV ALP.ALP | isPassthrough: | Opcjonalny:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Odfiltrowany podstrumień protokołu zasila następny filtr w łańcuchu filtrów. | Nie dotyczy |
isPassthrough: | Obowiązkowy:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecana: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnijFilter.read(buffer, offset, adjustedSize) jeden lub więcej razy.Dane są kopiowane z MQ warstwy HAL do bufora klienta. | Odfiltrowany podstrumień protokołu z nagłówkiem protokołu jest wypełniany w FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH | Nie dotyczy | Opcjonalny:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Odfiltrowany ładunek protokołu zasila następny filtr w łańcuchu filtrów. | Nie dotyczy |
Przykładowy przebieg użycia filtra do zbudowania 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();
SectionEvent
procesuZdarzenie .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 przebieg użycia MediaEvent z filtra
Rysunek 11. Przebieg korzystania z MediaEvent z filtra
- Otwórz, skonfiguruj i uruchom filtry A/V.
- Przetwarzaj
MediaEvent
. - Odbierz
MediaEvent
. - Kolejkuj blok liniowy do
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 konfiguracji DvrRecorder
i DvrPlayback
. OnPlaybackStatusChangedListener
i OnRecordStatusChangedListener
służą do raportowania stanu instancji DVR.
Przykładowy proces uruchamiania rekordu
Rysunek 12. Przebieg rozpoczęcia zapisu
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();
Odbierz
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
Tuner HAL podąża za HIDL i definiuje interfejs pomiędzy platformą a sprzętem dostawcy. Dostawcy używają interfejsu do implementacji Tuner HAL, a platforma używa go do komunikacji z implementacją Tuner HAL.
Moduły
Tuner HAL 1.0
Moduły | Podstawowe sterowanie | Sterowanie specyficzne dla 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 (pochodzący z Tunera HAL 1.0)
Moduły | Podstawowe sterowanie | Sterowanie specyficzne dla 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. Schemat interakcji pomiędzy modułami Tunera HAL
Połączenie filtra
Tuner HAL obsługuje łączenie filtrów, dzięki czemu filtry można łączyć z innymi filtrami w wielu warstwach. Filtry działają zgodnie z poniższymi zasadami.
- Filtry są połączone w formie drzewa, ścieżka zamykania nie jest dozwolona.
- Węzeł główny to demux.
- Filtry działają niezależnie.
- Wszystkie filtry zaczynają pobierać dane.
- Łącznik filtra spłukuje się na ostatnim filtrze.
Poniższy blok kodu i rysunek 14 ilustrują 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 blokowy połączenia filtra dla wielu warstw
Menedżer zasobów tunera
Przed Tuner Resource Manager (TRM) przełączanie między dwiema aplikacjami wymagało tego samego sprzętu Tuner. TV Input Framework (TIF) korzystał z mechanizmu „ kto pierwszy uzyska wygraną”, co oznacza, że aplikacja, która jako pierwsza otrzyma zasób, zachowa go. Jednak mechanizm ten może nie być idealny w niektórych skomplikowanych przypadkach użycia.
TRM działa jako usługa systemowa do zarządzania zasobami sprzętowymi Tuner, TVInput
i CAS dla aplikacji. TRM korzysta z mechanizmu „wygrania na pierwszym planie”, który oblicza priorytet aplikacji na podstawie statusu aplikacji na pierwszym planie lub w tle oraz typu przypadku użycia. TRM przyznaje lub odwołuje zasób w oparciu o priorytet. TRM centralizuje zarządzanie zasobami ATV dla transmisji, OTT i DVR.
Interfejs TRM
TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl
dla platformy Tuner, MediaCas
i TvInputHardwareManager
w celu rejestrowania, żądania lub zwalniania zasobów.
Poniżej wymieniono interfejsy do zarządzania klientami.
-
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
-
unregisterClientProfile(in int clientId)
Poniżej wymieniono interfejsy umożliwiające żądanie i zwolnienie zasobów.
-
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
Klasy klientów i żądań są wymienione poniżej.
-
ResourceClientProfile
-
ResourcesReclaimListener
-
TunerFrontendRequest
-
TunerDemuxRequest
-
TunerDescramblerRequest
-
CasSessionRequest
-
TunerLnbRequest
Priorytet klienta
TRM oblicza priorytet klienta na podstawie parametrów z profilu klienta i wartości priorytetu z pliku konfiguracyjnego. Priorytet może być również aktualizowany przez dowolną wartość priorytetu otrzymaną od klienta.
Parametry w profilu klienta
TRM pobiera identyfikator procesu z mTvInputSessionId
, aby zdecydować, czy aplikacja jest aplikacją na pierwszym planie, czy w tle. Aby utworzyć mTvInputSessionId
, TvInputService.onCreateSession
lub TvInputService.onCreateRecordingSession
inicjuje sesję TIS.
mUseCase
wskazuje przypadek użycia sesji. Poniżej wymieniono predefiniowane przypadki 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 konfiguracyjny
Domyślny plik konfiguracyjny
Domyślny plik konfiguracyjny poniżej zapewnia 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 | Pierwszoplanowy | Tło |
---|---|---|
LIVE | 490 | 400 |
PLAYBACK | 480 | 300 |
RECORD | 600 | 500 |
SCAN | 450 | 200 |
BACKGROUND | 180 | 100 |
Dostosowany plik konfiguracyjny
Dostawcy mogą dostosować plik konfiguracyjny /vendor/etc/tunerResourceManagerUseCaseConfig.xml
. Ten plik służy do dodawania, usuwania lub aktualizowania typów przypadków użycia i wartości priorytetów przypadków użycia. Dostosowany plik może wykorzystywać jako szablon platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
.
Na przykład przypadek użycia nowego dostawcy to VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
. Format powinien być zgodny z platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
.
Dowolna wartość priorytetu i wartość ładna
TRM udostępnia klientowi updateClientPriority
możliwość aktualizacji dowolnej wartości priorytetu i wartości ładnej. Dowolna wartość priorytetu zastępuje wartość priorytetu obliczoną na podstawie typu przypadku użycia i identyfikatora sesji.
Wartość nice wskazuje, jak łagodne jest zachowanie klienta, gdy jest on w konflikcie z innym klientem. Wartość nice zmniejsza wartość priorytetu klienta przed porównaniem jego wartości priorytetu z klientem wymagającym.
Mechanizm odzyskiwania
Poniższy diagram przedstawia sposób odzyskiwania i przydzielania zasobów w przypadku wystąpienia konfliktu zasobów.
Rysunek 15. Schemat mechanizmu odzyskiwania konfliktu pomiędzy zasobami Tunera