W przypadku Androida 11 lub nowszego możesz używać platformy Android Tuner do przesyłania treści audiowizualnych. Framework korzysta z przesyłu sprzętowego od dostawców, dzięki czemu jest odpowiedni zarówno do nisko-, jak i wysoko zaawansowanych układów SoC. Framework zapewnia bezpieczny sposób dostarczania treści audiowizualnych chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę multimediów (SMP), co pozwala na jego używanie w bardzo ograniczonym środowisku chroniącym treści.
Standardowy interfejs między Tunerem a Android CAS umożliwia szybszą integrację między dostawcami tunerów a dostawcami CAS. Interfejs Tunera współpracuje z MediaCodec
i AudioTrack
, aby tworzyć jedno uniwersalne rozwiązanie na Androida TV.
Interfejs tunera obsługuje telewizję cyfrową i analogową zgodnie z głównymi standardami nadawania.
Komponenty
W Androidzie 11 3 komponenty są specjalnie zaprojektowane pod kątem platformy TV.
- Tuner HAL: interfejs między frameworkiem a dostawcami.
- Tuner SDK API: interfejs między platformą a aplikacjami.
- Menedżer zasobów tunera (TRM): koordynuje zasoby sprzętowe tunera.
W Androidzie 11 ulepszono te komponenty:
- CAS V2
TvInputService
lub usługa wprowadzania danych w telewizorze (TIS)TvInputManagerService
lub usługa TIMS (TV Input Manager Service)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 te standardy DTV:
- ATSC
- 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 te protokoły strumieniowe:
- strumień transportu (TS);
- MPEG Media Transfer Protocol (MMTP)
- Protokół internetowy (IP)
- Typ długości wartości (TLV)
- Protokół warstwy łącza ATSC (ALP)
Descrambler obsługuje te zabezpieczenia treści.
- Bezpieczna ścieżka multimediów
- Wyczyść ścieżkę multimediów
- Zabezpieczanie rekordu lokalnego
- Bezpieczne odtwarzanie lokalne
Interfejsy API tunera obsługują te zastosowania.
- Skanuj
- Na żywo
- Odtwarzanie
- Nagrywaj
Tuner, MediaCodec
i AudioTrack
obsługują te tryby przepływu danych:
- Dane ładunku ES z buforem pamięci o czystej pamięci
- Payload ES z bezpiecznym uchwytem pamięci
- Widok otoczenia
Ogólny projekt
Interfejs HAL tunera jest definiowany między platformą Androida a sprzętem dostawcy.
- Opisuje, czego oczekuje się od dostawcy w ramach tej ramy, i jak może on to osiągnąć.
- Eksportuje funkcje interfejsu frontendu, demuxera i dekoderu do frameworku za pomocą interfejsów
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
iILnb
. - Zawiera funkcje umożliwiające zintegrowanie interfejsu HAL Tunera z innymi komponentami frameworku, takimi jak
MediaCodec
iAudioTrack
.
Tworzona jest klasa Java 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.
Tworzona jest klasa TRM.
- Zarządza ograniczonymi zasobami tunera, takimi jak front-end, LNB, sesje CAS i urządzenie wejściowe TV z poziomu interfejsu HAL wejścia TV.
- Stosuje reguły, aby odzyskać zasoby z aplikacji, których jest za mało. Regułą domyślną jest wygrana pierwszego planu.
Media CAS i CAS HAL zostały ulepszone o te funkcje.
- Otwiera sesje CAS na potrzeby różnych zastosowań i algorytmów.
- Obsługuje dynamiczne systemy CAS, takie jak usuwanie i wstawianie CICAM.
- Integruje się z Tuner HAL, udostępniając 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
Diagramy poniżej przedstawiają sekwencje wywołań podczas odtwarzania transmisji na żywo.
Konfiguracja
Rysunek 3. Sekwencja konfiguracji odtwarzania transmisji na żywo
Obsługa A/V
Rysunek 4. Obsługa dźwięku i obrazu podczas 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 w celu odtworzenia 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.
Aby sprawdzić wersję interfejsu 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 Tuner SDK udostępnia 4 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 pakietu Tuner SDK
Android.media.tv.tuner
Pakiet Tuner to punkt wejścia do korzystania z ramy Tuner. Aplikacja TIS używa pakietu do inicjowania i uzyskiwania instancji zasobów przez określenie początkowego ustawienia i wywołania zwrotnego.
tuner()
: inicjalizuje wystąpienie Tunera przez podanie parametrówuseCase
isessionId
.tune()
: pobiera zasób interfejsu i dostosowuje go przez podanie parametruFrontendSetting
.openFilter()
: pobiera instancję filtra przez określenie typu filtra.openDvrRecorder()
: umożliwia uzyskanie instancji nagrywania przez określenie rozmiaru bufora.openDvrPlayback()
: pobiera instancję odtwarzania, podając rozmiar bufora.openDescrambler()
: pobiera instancję deszyfratora.openLnb()
: pobiera wewnętrzną instancję LNB.openLnbByName()
: uzyskuje zewnętrzne wystąpienie LNB.openTimeFilter()
: pobiera instancję filtra czasowego.
Pakiet Tuner udostępnia funkcje, które nie są dostępne w pakietach filtrów, DVR i interfejsu. Funkcje te 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 związanych z interfejsem.
Zajęcia
FrontendSettings
jest obliczana dla różnych standardów DTV według klas wymienionych poniżej.
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
Wartość 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 Tuner HAL 1.1 lub nowszym obsługiwany jest następujący standard DTV.
DtmbFrontendCapabilities
FrontendInfo
pobiera informacje z interfejsu.
FrontendStatus
pobiera bieżący stan frontendu.
OnTuneEventListener
nasłuchuje zdarzeń na interfejsie.
Aplikacja TIS używa usługi ScanCallback
do przetwarzania wiadomości z skanowania z poziomu 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 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
FrontendSettings
wymaganymi informacjami za pomocąTuner.tune
. - Jeśli sygnał jest zablokowany, HAL zgłasza komunikaty dotyczące strojenia
LOCKED
. - TIS używa
Frontend.getStatus
do 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ż wyczerpią się 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
Tuner.scan(AUTO_SCAN)
zFrontendSettings
wypełnionym częstotliwością.Jeśli sygnał jest zablokowany, HAL zgłasza skanowanie wiadomości
LOCKED
. HAL może też przekazywać inne komunikaty 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 na tej samej częstotliwości. Jeśli strukturaFrontendSettings
jest pusta, HAL używa następnego dostępnego ustawienia. W przeciwnym razie HAL używaFrontendSettings
do jednorazowego skanowania i wysyłaEND
, aby wskazać, że operacja skanowania została zakończona.TIS powtarza te działania, dopóki nie wyczerpią się wszystkie ustawienia 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 liście częstotliwości.
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 interfejs HAL dostawcy może wyszukać częstotliwość interfejsu użytkownika, aby uzyskać zasób interfejsu, zalecamy użycie Tuner.scan(BLIND_SCAN)
.
- TIS używa
Tuner.scan(BLIND_SCAN)
. Częstotliwość rozpoczęcia można określić w parametryeFrontendSettings
, ale TIS ignoruje inne ustawienia w parametryeFrontendSettings
. - 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 te 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ż 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 blokowy 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ódełku 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 klas wymienionych poniżej. 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 Tuner 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 harmonogramem wydarzenia i harmonogramem wewnętrznym uruchomFilter.read(buffer, offset, adjustedSize) co najmniej raz.Dane są kopiowane z MQ HAL do bufora klienta. |
Jeden z zmontowanych pakietów sesji jest wypełniany w FMQ przez inny pakiet sesji. |
isRaw: |
Wymagane: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 zmontowany pakiet PES jest wypełniany w FMQ przez inny pakiet PES. |
isRaw: |
Wymagane: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: |
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 zmontowany pakiet MFU jest wypełniany w FMQ przez inny pakiet MFU. |
isRaw: |
Wymagane: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: |
Wymagane:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcjonalnie: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Aby użyć MediaCodec :for i=0; i<n; i++ Aby użyć Direct Audio z 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 | Wymagany: nie dotyczy
Opcjonalny: nie dotyczy |
Nie dotyczy | Nie dotyczy |
TS.RECORD |
Nie dotyczy | Wymagane: 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 |
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:
|
Dane indeksu: są przenoszone w ładunku zdarzenia. W przypadku treści nagranych: strumień TS zmiksowany wypełniony w FMQ. |
TS.TEMI |
Nie dotyczy | Wymagane: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. |
Odfiltrowane mmtp z nagłówkiem mmtp jest wypełnione w FMQ. |
MMTP.RECORD |
Nie dotyczy | Wymagane: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:
|
Dane indeksu: są przenoszone w ładunku zdarzenia. W przypadku treści nagranych: zmiksowany strumień nagrania wypełniony w FMQ. Jeśli źródło filtra do nagrywania to TLV.TLV do IP.IP z przepuszczaniem, nagrany strumień zawiera nagłówek TLV i IP. |
MMTP.DOWNLOAD |
Nie dotyczy | Wymagane: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. |
Pakiet pobierania jest wypełniany w FMQ przez inny pakiet pobierania IP. |
IP.IP_PAYLOAD |
Nie dotyczy | Wymagane: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 |
Filtrowany podstrumień protokołu przekazuje dane do następnego filtra w łańcuchu filtrów. | Nie dotyczy |
isPassthrough: |
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. |
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 tworzenia PSI/SI za pomocą filtra
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 sposób korzystania z MediaEvent z filtra
Rysunek 11. Sposób używania filtra MediaEvent
- Otwórz, skonfiguruj i uruchom filtry A/V.
- Przetwarzam
MediaEvent
. - Odbieranie
MediaEvent
. - Umieść blok liniowy w kolejce do
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
Wartość DvrSettings
służy do konfigurowania wartości DvrRecorder
i DvrPlayback
.
Wartości OnPlaybackStatusChangedListener
i OnRecordStatusChangedListener
służą do raportowania stanu wystąpienia DVR.
Przykładowy przepływ pracy, aby rozpocząć nagrywanie
Rysunek 12. Procedura rozpoczęcia nagrywania
Otwórz, skonfiguruj i uruchom
DvrRecorder
.DvrRecorder recorder = openDvrRecorder(/* bufferSize */ 1000, executor, listener); DvrSettings dvrSettings = DvrSettings .builder() .setDataFormat(DvrSettings.DATA_FORMAT_TS) .setLowThreshold(100) .setHighThreshold(900) .setPacketSize(188) .build(); recorder.configure(dvrSettings); recorder.attachFilter(filter); recorder.setFileDescriptor(fd); recorder.start();
Otrzymaj
RecordEvent
i pobierz informacje indeksu.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. } } } };
Inicjowanie
OnRecordStatusChangedListener
i przechowywanie danych 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
Interfejs HAL tunera jest zgodny z HIDL i określa interfejs między frameworkem a sprzętem dostawcy. Dostawcy używają tego interfejsu do implementowania Tunera HAL, a ramka 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 (wyprowadzony z Tuner 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
Filtrowanie połączeń
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 podanymi niżej zasadami.
- Filtry są połączone w drzewo, więc nie można stosować ścieżki zamykania.
- Węzłem głównym jest demux.
- Filtry działają niezależnie.
- Wszystkie filtry zaczynają pobierać dane.
- Powiązanie filtrów jest opróżniane w ostatnim filtrze.
Poniżej znajduje się blok kodu, a na rysunku 14 widać 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 Menedżera zasobów tunera (TRM) przełączanie się między 2 aplikacjami wymagało korzystania z tego samego sprzętu tunera. Ramy danych wejściowych TV (TIF) używały mechanizmu „pierwszy lepszy”, co oznacza, że aplikacja, która jako pierwsza uzyskała zasób, zatrzymuje go. Ten mechanizm może jednak nie być odpowiedni w przypadku niektórych skomplikowanych przypadków użycia.
TRM działa jako usługa systemowa, która zarządza zasobami sprzętowymi tunera, TVInput
i CAS dla 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 odwołuje zasób na podstawie priorytetu. TRM centralizuje zarządzanie zasobami ATV na potrzeby transmisji, OTT i DVR.
Interfejs TRM
TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl
dla frameworku Tuner, MediaCas
i TvInputHardwareManager
w celu rejestrowania, żądania lub uwalniania zasobów.
Interfejsy do zarządzania klientami:
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
unregisterClientProfile(in int clientId)
Poniżej znajdziesz interfejsy do żą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
Klasy klientów i żądań znajdziesz poniżej.
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
Priorytet klienta
TRM oblicza priorytet klienta na podstawie parametrów z jego profilu i wartości priorytetu z pliku konfiguracyjnego. Priorytet może też być aktualizowany przez dowolną wartość priorytetu z klienta.
Parametry w profilu klienta
TRM pobiera identyfikator procesu z mTvInputSessionId
, aby określić, czy aplikacja jest na pierwszym czy drugim planie. Aby utworzyć mTvInputSessionId
, TvInputService.onCreateSession
lub TvInputService.onCreateRecordingSession
, inicjuje sesję TIS.
mUseCase
oznacza 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ć te 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 |
Niestandardowy 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 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]
.
Format powinien być zgodny z platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
.
dowolna wartość priorytetu i przyjazna wartość
TRM udostępnia klientowi element updateClientPriority
, który umożliwia mu zaktualizowanie dowolnej wartości priorytetu i wartości wyświetlanej.
Wartość dowolnego 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. Wartość nice zmniejsza priorytet klienta przed porównaniem jego wartości priorytetu z wartością trudnego klienta.
Mechanizm odzyskiwania
Diagram poniżej pokazuje, jak zasoby są odzyskiwane i przypisywane, gdy wystąpi konflikt zasobów.
Rysunek 15. Schemat mechanizmu odzyskiwania zasobów w przypadku konfliktu między zasobami tunera