W przypadku Androida 11 lub nowszego do odtwarzania treści A/V można użyć platformy Android Tuner. Platforma wykorzystuje potok sprzętowy od dostawców, dzięki czemu jest odpowiedni zarówno dla słabszych, jak i zaawansowanych układów SOC. Platforma zapewnia bezpieczny sposób dostarczania treści audiowizualnych chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę multimediów (SMP), dzięki czemu można jej używać w bardzo ograniczonym środowisku ochrony treści.
Ustandaryzowane interfejs między Tunerem a CAS zapewnia szybszą integrację między dostawcami tunerów i CAS. Interfejs tunera współpracuje z usługami MediaCodec
i AudioTrack
, co pozwala stworzyć uniwersalne rozwiązanie dla Androida TV.
Interfejs tunera obsługuje zarówno telewizję cyfrową, jak i telewizję analogową na podstawie głównych standardów telewizyjnych.
Komponenty
W Androidzie 11 3 komponenty są specjalnie zaprojektowane na potrzeby platformy telewizyjnej.
- Tuner HAL: interfejs między platformą a dostawcami
- Interfejs API Tuner SDK: interfejs między platformą a aplikacjami.
- Tuner Resource Manager (TRM): koordynuje zasoby HW Tuner.
W Androidzie 11 ulepszone są te komponenty.
- CAS V2
TvInputService
lub usługa wejścia TV (TIS)TvInputManagerService
lub usługa menedżera wejścia TV (TIMS)MediaCodec
lub kodek multimediówAudioTrack
lub ścieżka audioMediaResourceManager
lub menedżer zasobów medialnych (MRM)
Rysunek 1. Interakcje między komponentami Androida TV
Funkcje
Frontend obsługuje wymienione poniżej standardy DTV.
- ATSC
- protokół ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analogowe
Frontend w Androidzie 12 z Tuner HAL 1.1 lub nowszym obsługuje standard DTV.
- DTMB
Demux obsługuje poniższe protokoły strumienia.
- Strumień transportu
- Protokół MPEG Media Transport Protocol (MMTP)
- Protokół internetowy (IP)
- Typ długości wartości (TLV)
- Protokół ATSC warstwy łącza (ALP)
Dekoder obsługuje poniższe zabezpieczenia treści.
- Bezpieczna ścieżka multimediów
- Wyczyść ścieżkę multimediów
- Zabezpieczanie rekordu lokalnego
- Bezpieczne odtwarzanie lokalne
Interfejsy API dostrajania obsługują poniższe przypadki użycia.
- Skanuj
- Na żywo
- Odtwarzanie
- Nagraj
Tuner, MediaCodec
i AudioTrack
obsługują podane niżej tryby przepływu danych.
- Dane ES z czystym buforem pamięci
- Payload ES z bezpiecznym uchwytem pamięci
- Widok otoczenia
Ogólny projekt
HAL dostrajania jest zdefiniowana między platformą Androida a sprzętem dostawcy.
- Opisują, czego platforma oczekuje od dostawcy i w jaki sposób może to zrobić.
- Umożliwia wyeksportowanie do platformy funkcji frontendu, demuxowania i dekodera za pomocą interfejsów
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
iILnb
. - Zawiera funkcje integracji interfejsu HAL Tuner z innymi komponentami platformy, takimi jak
MediaCodec
iAudioTrack
.
Zostanie utworzona klasa Java tunera i klasa natywna.
- Interfejs Tuner Java API umożliwia aplikacjom dostęp do interfejsu HAL Tunera za pomocą publicznych interfejsów API.
- Klasa natywnych umożliwia kontrolę uprawnień i obsługę dużych ilości danych dotyczących nagrywania lub odtwarzania za pomocą interfejsu HAL tunera.
- Natywczy moduł tunera stanowi łącznik między klasą Java Tunera a interfejsem HAL Tunera.
Zostanie utworzona klasa TRM.
- Zarządza ograniczonymi zasobami tunera, takimi jak frontend, LNB, sesje CAS oraz urządzenie wejściowe TV, z wejścia TV HAL.
- Zastosuj reguły, aby odzyskać zasoby z aplikacji. Regułą domyślną jest wygrana pierwszego planu.
Funkcje Media CAS i CAS HAL zostały uzupełnione o poniższe funkcje.
- Otwiera sesje CAS na potrzeby różnych zastosowań i algorytmów.
- Obsługuje dynamiczne systemy CAS, takie jak usuwanie i wstawianie CICAM.
- Integracja z HAL Tuner zapewnia tokeny kluczy.
MediaCodec
i AudioTrack
zostały wzbogacone o te funkcje:
- Odczytuje zabezpieczoną pamięć audiowizualną jako dane wejściowe.
- Konfiguracja sprzętowego synchronizatora audio-wideo w przypadku odtwarzania tunelowanego.
- Skonfigurowano obsługę
ES_payload
i trybu przepuszczania.
Rysunek 2. Schemat komponentów w Tuner HAL
Ogólny przepływ pracy
Na poniższych schematach przedstawiono sekwencje połączeń podczas odtwarzania transmisji na żywo.
Konfiguracja
Rysunek 3. Sekwencja konfiguracji odtwarzania transmisji na żywo
Obsługa sprzętu audiowizualnego
Rysunek 4. Obsługa dźwięku i obrazu w przypadku odtwarzania transmisji na żywo
Postępowanie z treściami zaszyfrowanymi
Rysunek 5. Postępowanie z zakodowanymi treściami podczas odtwarzania transmisji na żywo
Przetwarzanie danych audio-wizualnych
Rysunek 6. Przetwarzanie obrazu i dźwięku do odtwarzania transmisji na żywo
Interfejs API Tuner SDK
Interfejs API pakietu Tuner SDK obsługuje interakcje z interfejsem JNI Tunera, interfejsem HAL Tunera i interfejsem TunerResourceManager
. Aplikacja TIS korzysta z interfejsu API Tuner SDK, aby uzyskać dostęp do zasobów tunera i jego podkomponentów, 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 Tuner SDK obsługuje nową funkcję w interfejsie Tuner HAL 1.1, który jest kompatybilny wstecz z wersją Tuner 1.0.
Użyj poniższego interfejsu API, aby sprawdzić uruchomioną wersję HAL.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
Minimalną wymaganą wersję HAL znajdziesz w dokumentacji nowych interfejsów API Androida 12.
Pakiety
Interfejs API Tuner SDK udostępnia 4 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 interfejsu API Tuner SDK
Android.media.tv.tuner
Pakiet tunera to punkt wyjścia do korzystania z platformy Tuner. Aplikacja TIS używa pakietu do inicjowania i uzyskiwania instancji zasobów przez określenie początkowego ustawienia i wywołania zwrotnego.
tuner()
: inicjuje instancję tunera przez określenie parametrówuseCase
isessionId
.tune()
: pozyskuje zasób frontendu i dostrajanie przez określenie parametruFrontendSetting
.openFilter()
: pobiera instancję filtra przez określenie typu filtra.openDvrRecorder()
: pozyskuje instancję nagrywania, określając rozmiar bufora.openDvrPlayback()
: uzyskuje instancję odtwarzania przez określenie rozmiaru bufora.openDescrambler()
: pobiera instancję deszyfratora.openLnb()
: pozyskuje wewnętrzną instancję LNB.openLnbByName()
: pobiera zewnętrzną instancję LNB.openTimeFilter()
: pobiera instancję filtra czasowego.
Pakiet Tuner udostępnia funkcje, które nie są dostępne w pakietach filtrów, DVR i interfejsu. Ich listę znajdziesz poniżej.
cancelTuning
scan
/cancelScanning
getAvSyncHwId
getAvSyncTime
connectCiCam1
/disconnectCiCam
shareFrontendFromTuner
updateResourcePriority
setOnTuneEventListener
setResourceLostListener
Android.media.tv.tuner.frontend
Pakiet interfejsu zawiera kolekcje ustawień, informacji, stanów, zdarzeń i możliwości dotyczących interfejsu.
Zajęcia
FrontendSettings
jest określany dla różnych standardów DTV według poniższych klas.
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
Od Androida 12 z Tuner HAL 1.1 lub nowszym obsługiwany jest następujący standard DTV.
DtmbFrontendSettings
FrontendCapabilities
jest obliczana dla różnych standardów DTV na podstawie klas wymienionych poniżej.
AnalogFrontendCapabilities
Atsc3FrontendCapabilities
AtscFrontendCapabilities
DvbcFrontendCapabilities
DvbsFrontendCapabilities
DvbtFrontendCapabilities
Isdbs3FrontendCapabilities
IsdbsFrontendCapabilities
IsdbtFrontendCapabilities
Od Androida 12 z tunerem HAL 1.1 lub nowszym obsługiwany jest standard DTV.
DtmbFrontendCapabilities
FrontendInfo
pobiera informacje o frontendzie.
FrontendStatus
pobiera bieżący stan frontendu.
OnTuneEventListener
nasłuchuje zdarzeń we frontendzie.
Aplikacja TIS używa usługi ScanCallback
do przetwarzania wiadomości z 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łu.
Jeśli TIS ma dokładne informacje o dostawie sygnału, takie jak częstotliwość, standard (np. T/T2, S/S2) i dodatkowe 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:
- TIS wypełnia pole
FrontendSettings
wymaganymi informacjami za pomocą polaTuner.tune
. - Raport HAL dostraja komunikaty
LOCKED
, jeśli sygnał jest zablokowany. - TIS używa
Frontend.getStatus
do zbierania niezbędnych informacji. - TIS przechodzi do następnej dostępnej częstotliwości na liście.
TIS wywołuje metodę Tuner.tune
ponownie, aż zostaną wyczerpane wszystkie częstotliwości.
Podczas strojenia możesz wybrać stopTune()
lub close()
, aby wstrzymać lub zakończyć połączenie Tuner.tune
.
Tuner.scan(AUTO_SCAN)
Jeśli TIS nie ma wystarczającej ilości informacji do użycia Tuner.tune
, ale ma listę częstotliwości i typ standardu (np. DVB T/C/S), zalecamy użycie Tuner.scan(AUTO_SCAN)
.
Gdy użytkownik zadzwoni pod numer Tuner.scan(AUTO_SCAN)
, nastąpią te działania:
TIS używa kolumny
Tuner.scan(AUTO_SCAN)
z polemFrontendSettings
wypełnionym częstotliwością.Jeśli sygnał jest zablokowany, HAL zgłasza skanowanie wiadomości
LOCKED
. HAL może też przekazywać inne wiadomości skanowania, aby dostarczyć dodatkowych informacji o sygnale.TIS używa
Frontend.getStatus
do zbierania niezbędnych informacji.TIS wywołuje
Tuner.scan
, aby HAL kontynuował ustawienie następnego kanału o tej samej częstotliwości. Jeśli strukturaFrontendSettings
jest pusta, HAL używa następnego dostępnego ustawienia. W przeciwnym razie HAL używa identyfikatoraFrontendSettings
do jednorazowego skanowania i wysyłaEND
, aby wskazać, że operacja skanowania została zakończona.TIS powtarza te działania, dopóki nie wyczerpie się limit ustawień na częstotliwość.
HAL wysyła wiadomość
END
, aby wskazać, że operacja skanowania została zakończona.TIS przechodzi do następnej dostępnej częstotliwości na liście.
TIS ponownie wywołuje Tuner.scan(AUTO_SCAN)
, aż wyczerpią się wszystkie częstotliwości.
Podczas skanowania możesz wywołać 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 wyszukać częstotliwość określonego przez użytkownika frontendu w celu pobrania zasobu frontendu, zalecamy użycie metody Tuner.scan(BLIND_SCAN)
.
- TIS używa
Tuner.scan(BLIND_SCAN)
. Częstotliwość początkową można określić w poluFrontendSettings
, ale TIS ignoruje inne ustawienia w poluFrontendSettings
. - Jeśli sygnał jest zablokowany, HAL zgłasza skanowanie
LOCKED
. - TIS używa
Frontend.getStatus
do zbierania niezbędnych informacji. - TIS ponownie wywołuje
Tuner.scan
, aby kontynuować skanowanie. (wartośćFrontendSettings
jest ignorowana). - TIS powtarza powyższe działania, aż wszystkie ustawienia częstotliwości zostaną wyczerpane. HAL zwiększa częstotliwość. Z TIS nie trzeba nic robić.
Raporty HAL
PROGRESS
TIS ponownie wywołuje Tuner.scan(AUTO_SCAN)
, aż wyczerpią się wszystkie 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 procesu skanowania TIS
Android.media.tv.tuner.filter
Pakiet filtrów to zbiór operacji filtra wraz z konfiguracją, ustawieniami, wywołaniami zwrotnymi i zdarzeniami. Pakiet zawiera te operacje: Pełną listę operacji znajdziesz w źródle kodu Androida.
configure()
start()
stop()
flush()
read()
Pełną listę znajdziesz w kodzie źródłowym Androida.
FilterConfiguration
pochodzi z klas wymienionych poniżej. Konfiguracje dotyczą głównego typu filtra i określają, którego protokołu używa filtr do wyodrębniania danych.
AlpFilterConfiguration
IpFilterConfiguration
MmtpFilterConfiguration
TlvFilterConfiguration
TsFilterConfiguration
Ustawienia pochodzą z poniższych klas. Ustawienia te dotyczą podtypu filtra i określają, jakie dane może wykluczać.
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
FilterEvent
pochodzi z klas wymienionych poniżej i służy do raportowania zdarzeń dotyczących różnych rodzajów danych.
SectionEvent
MediaEvent
PesEvent
TsRecordEvent
MmtpRecordEvent
TemiEvent
DownloadEvent
IpPayloadEvent
Od Androida 12 z tunerem HAL 1.1 lub nowszym obsługiwane są te zdarzenia.
IpCidChangeEvent
RestartEvent
ScramblingStatusEvent
Format zdarzeń i danych z filtra
Typ filtra | Flagi | Wydarzenia | Operacja na danych | Format danych |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION |
isRaw: |
Wymagane:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Zgodnie z wydarzeniem i wewnętrznym harmonogramem uruchomFilter.read(buffer, offset, adjustedSize) co najmniej 1 raz.Dane są kopiowane z MQ HAL do bufora klienta. |
Jeden gotowy pakiet sesji jest wypełniany przez FMQ przez inny pakiet sesji. |
isRaw: |
Obowiązkowe:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalnie: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Dane są kopiowane z MQ HAL do bufora klienta. |
||
TS.PES |
isRaw: |
Wymagane:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Zgodnie z harmonogramem wydarzenia i harmonogramem wewnętrznym uruchomFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z MQ HAL do bufora klienta. |
Jeden gotowy pakiet PES jest wypełniany FMQ przez inny pakiet PES. |
isRaw: |
Obowiązkowe:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalnie: 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 |
Zgodnie z wydarzeniem i wewnętrznym harmonogramem uruchomFilter.read(buffer, offset, adjustedSize) co najmniej 1 raz.Dane są kopiowane z 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 Opcjonalnie: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Dane są kopiowane z MQ HAL do bufora klienta. |
||
TS.TS |
Nie dotyczy | Wymagane:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Zgodnie z harmonogramem wydarzenia i harmonogramem wewnętrznym uruchomFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z MQ HAL do bufora klienta. |
Odfiltrowane ts z nagłówkiem ts jest 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 .Po otrzymaniu wiadomości DemuxFilterStatus::DATA_OVERFLOW klient może zadzwonić pod numer Filter.flush . |
Nie dotyczy |
isPassthrough: |
Obowiązkowe:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalnie: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Aby użyć interfejsu MediaCodec :for i=0; i<n; i++ Aby użyć bezpośredniego dźwięku AudioTrack :for i=0; i<n; i++ |
ES lub częściowe dane 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 | Wymagany: DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opcjonalnie: 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:
|
Dane indeksu: są przenoszone w ładunku zdarzenia. W przypadku treści nagranych: strumień TS zmiksowany w FMQ. |
TS.TEMI |
Nie dotyczy | Wymagany:DemuxFilterEvent::DemuxFilterTemiEvent[n] Opcjonalnie: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
Nie dotyczy |
MMTP.MMTP |
Nie dotyczy | Wymagane:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Zgodnie z harmonogramem wydarzenia i harmonogramem wewnętrznym uruchomFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z MQ HAL do bufora klienta. |
Odfiltrowana wartość mmtp z nagłówkiem mmtp jest wypełniona FMQ. |
MMTP.RECORD |
Nie dotyczy | Wymagany:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER Opcjonalnie: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Dane 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: przenoszone w ładunku zdarzenia. W przypadku treści nagranych: zmiksowany strumień nagrania wypełniony w FMQ. Jeśli źródłem filtra do rejestrowania jest TLV.TLV –IP.IP z przekazywaniem, nagrany strumień będzie miał nagłówek TLV i nagłówek IP. |
MMTP.DOWNLOAD |
Nie dotyczy | Wymagany:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalnie: 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. |
Pole „Pobierz pakiet” jest wypełnione w FMQ przez inny pakiet do pobrania adresu IP. |
IP.IP_PAYLOAD |
Nie dotyczy | Obowiązkowe:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalnie: 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 danych IP jest wypełniany w FMQ przez inny pakiet danych IP. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Opcjonalnie:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Odfiltrowano pliki danych ze strumieniem podrzędnym protokołu. Odfiltrowano je. Następny filtr w łańcuchu filtrów. | Nie dotyczy |
isPassthrough: |
Wymagane:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Zalecane: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Zgodnie z wydarzeniem i wewnętrznym harmonogramem uruchomFilter.read(buffer, offset, adjustedSize) co najmniej 1 raz.Dane są kopiowane z MQ HAL do bufora klienta. |
Filtrowany podstrumień protokołu z nagłówkiem protokołu jest wypełniany w FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
Nie dotyczy | Opcjonalnie:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Odfiltrowany ładunek protokołu przekazuje dane następnemu filtrowi w łańcuchu filtrów. | Nie dotyczy |
Przykładowy proces z użyciem filtra do utworzenia wskaźnika 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();
Przetwarzam
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życia obiektu MediaEvent z filtra
Rysunek 11. Procedura użycia obiektu MediaEvent z filtra
- Otwórz, skonfiguruj i uruchom filtry audio/wideo.
- Przetwórz
MediaEvent
. - Odbierz
MediaEvent
. - Umieść blok liniowy w kolejce do pozycji
codec
. - Po wykorzystaniu danych zwalniaj uchwyt A/V.
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
Usługa DvrSettings
jest używana do konfigurowania usług DvrRecorder
i DvrPlayback
.
OnPlaybackStatusChangedListener
i OnRecordStatusChangedListener
służą do zgłaszania stanu instancji DVR.
Przykładowy proces rozpoczynania nagrywania
Rysunek 12. Proces rozpoczynania 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();
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 jest zgodny z HIDL i określa interfejs między frameworkem a sprzętem dostawcy. Dostawcy używają tego interfejsu do implementacji Tunera HAL, a platforma używa go do komunikacji z implementacją Tunera HAL.
Moduły
Tuner HAL 1.0
Moduły | Podstawowe funkcje sterowania | Ustawienia dotyczące poszczególnych modułów | 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 funkcje sterowania | Ustawienia dotyczące poszczególnych modułów | 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 między modułami HAL tunera
Połączenie filtrów
Tuner HAL obsługuje łączenie filtrów, dzięki czemu można je łączyć z innymi filtrami w wielu warstwach. Filtry działają zgodnie z podanymi niżej zasadami.
- Filtry są połączone w drzewo, więc nie można stosować ścieżki zamykania.
- Węzeł główny jest demuxem.
- Filtry działają niezależnie.
- Wszystkie filtry zaczynają pobierać dane.
- Połączenie filtra wyczyszczone jest przy ostatnim filtrze.
Blok kodu poniżej i na rys. 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 działania połączenia filtra w przypadku wielu warstw
Menedżer zasobów tunera
Przed wprowadzeniem usługi Tuner Resource Manager (TRM) przełączanie się między 2 aplikacjami wymagało korzystania z tego samego tunera. Platforma wprowadzania danych TV (TIF) korzystała z mechanizmu „pierwszego pozyskania”, co oznacza, że zasób zostanie zachowany w przypadku aplikacji, która otrzyma zasób jako pierwszy. Ten mechanizm może jednak nie być odpowiedni w przypadku niektórych skomplikowanych przypadków użycia.
TRM działa jako usługa systemowa zarządzająca zasobami sprzętowymi tunera, TVInput
i CAS na potrzeby aplikacji. TRM korzysta z mechanizmu „wygrywania na pierwszym planie”, który oblicza priorytet aplikacji na podstawie jej stanu (czy jest na pierwszym planie czy w tle) oraz typu przypadku użycia. TRM przyznaje lub anuluje zasób na podstawie priorytetu. TRM centralizuje zasoby ATV na potrzeby transmisji, OTT i nagrywarki cyfrowej.
Interfejs TRM
TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl
dla frameworku Tuner, MediaCas
i TvInputHardwareManager
w celu rejestrowania, żądania lub uwalniania zasobów.
Poniżej znajdziesz interfejsy zarządzania klientami.
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
unregisterClientProfile(in int clientId)
Poniżej znajdziesz interfejsy żądania i zwalniania 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
Poniżej znajdziesz klasy klientów i żądań.
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
Priorytet klienta
TRM oblicza priorytet klienta, korzystając z parametrów z profilu klienta i wartości priorytetu z pliku konfiguracji. Priorytet może też być aktualizowany za pomocą dowolnej wartości priorytetu ustalonej przez klienta.
Parametry w profilu klienta
TRM pobiera identyfikator procesu z mTvInputSessionId
, aby zdecydować, czy aplikacja jest aplikacją na pierwszym planie czy w tle. Tworzenie mTvInputSessionId
, TvInputService.onCreateSession
lub TvInputService.onCreateRecordingSession
inicjuje sesję TIS.
mUseCase
wskazuje przypadek użycia sesji. Poniżej znajdziesz listę wstępnie zdefiniowanych zastosowań.
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żej znajduje się domyślny plik konfiguracji zawierający wartości priorytetów dla zdefiniowanych wstępnie przypadków użycia. Użytkownicy mogą zmieniać wartości za pomocą spersonalizowanego pliku konfiguracji.
Przypadek użycia | Pierwszy plan | Tło |
---|---|---|
LIVE |
490 | 400 |
PLAYBACK |
480 | 300 |
RECORD |
600 | 500 |
SCAN |
450 | 200 |
BACKGROUND |
180 | 100 |
Plik konfiguracji niestandardowej
Dostawcy mogą dostosować plik konfiguracji /vendor/etc/tunerResourceManagerUseCaseConfig.xml
. Służy on do dodawania, usuwania i aktualizowania typów przypadków użycia oraz wartości priorytetów przypadków użycia.
Dostosowany plik może używać platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
jako szablonu.
Przykładem zastosowania dla nowego dostawcy jest VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
.
Powinien mieć format platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
.
Dowolna wartość priorytetu i wartość ładna
TRM udostępnia klientowi element updateClientPriority
, który umożliwia mu zaktualizowanie dowolnej wartości priorytetu i wartości wyświetlanej.
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 wchodzi on w konflikt z innym klientem. „Dobra wartość” zmniejsza wartość priorytetu klienta, zanim jego wartość zostanie porównana z klientem, który jest bardziej wymagający.
Mechanizm odzyskiwania
Poniższy diagram przedstawia sposób odzyskiwania i przypisywania zasobów w przypadku konfliktu zasobów.
Rysunek 15. Schemat mechanizmu odzyskiwania konfliktu między zasobami tunera