Platforma tunera

W przypadku Androida 11 lub nowszego możesz używać platformy Android Tuner do przesyłania treści audio-wideo. Platforma korzysta z potoku sprzętowego dostawców, dzięki czemu nadaje się zarówno do układów SoC z niższej, jak i z wyższej półki. Zapewnia bezpieczny sposób dostarczania treści audio-wideo chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę multimediów (SMP), co umożliwia jej używanie w wysoce ograniczonym środowisku ochrony treści.

Standardowy interfejs między tunerem a systemem CAS na Androidzie przyspiesza integrację między dostawcami tunerów i dostawcami systemów CAS. Interfejs Tuner współpracuje z MediaCodecAudioTrack, aby stworzyć jedno rozwiązanie dla Androida TV. Interfejs tunera obsługuje zarówno telewizję cyfrową, jak i analogową w oparciu o główne standardy transmisji.

Komponenty

W przypadku Androida 11 3 komponenty zostały zaprojektowane specjalnie z myślą o platformie TV.

  • Tuner HAL: interfejs między platformą a dostawcami.
  • Interfejs API pakietu SDK tunera: interfejs między platformą a aplikacjami.
  • Menedżer zasobów tunera (TRM): koordynuje zasoby sprzętowe tunera.

W Androidzie 11 ulepszyliśmy te komponenty:

  • CAS V2
  • TvInputService lub Usługa wprowadzania danych w TV (TIS)
  • TvInputManagerService lub Usługa zarządzania wejściami telewizora (TIMS).
  • MediaCodec lub kodek multimedialny.
  • AudioTrack lub ścieżkę audio.
  • MediaResourceManager lub menedżer zasobów multimedialnych (MRM).

Schemat blokowy komponentów platformy Tuner.

Rysunek 1. Interakcje między komponentami Androida TV

Funkcje

Frontend obsługuje te standardy DTV:

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Analogowe

Interfejs w Androidzie 12 z Tuner HAL w wersji 1.1 lub nowszej obsługuje poniższy standard DTV.

  • DTMB

Demux obsługuje te protokoły strumieniowe:

  • Strumień transportowy (TS)
  • Protokół transportu multimediów MPEG (MMTP)
  • Protokół internetowy (IP)
  • Wartość długości typu (TLV)
  • Protokół warstwy łącza ATSC (ALP)

Dekoder obsługuje poniższe zabezpieczenia treści.

  • Bezpieczna ścieżka multimediów
  • Wyczyść ścieżkę multimediów
  • Zabezpieczanie lokalnego rekordu
  • Bezpieczne odtwarzanie lokalne

Interfejsy API tunera obsługują te przypadki użycia:

  • Skanowanie
  • Na żywo
  • Odtwarzanie
  • Nagrywaj

Tuner, MediaCodecAudioTrack obsługują te tryby przepływu danych:

  • Ładunek ES z wyczyszczonym buforem pamięci
  • Ładunek ES z bezpiecznym uchwytem pamięci
  • Widok otoczenia

Ogólny projekt

Warstwa HAL tunera jest zdefiniowana między platformą Androida a sprzętem dostawcy.

  • Opisuje, czego oczekuje od dostawcy platforma i jak dostawca może to osiągnąć.
  • Eksportuje funkcje frontendu, demultipleksera i dekodera do platformy za pomocą interfejsów IFrontend, IDemux, IDescrambler, IFilter, IDvrILnb.
  • Zawiera funkcje integrujące Tuner HAL z innymi komponentami platformy, takimi jak MediaCodecAudioTrack.

Tworzone są klasa Java Tuner i klasa natywna.

  • Interfejs Tuner Java API umożliwia aplikacjom dostęp do Tuner HAL za pomocą publicznych interfejsów API.
  • Klasa natywna umożliwia sterowanie uprawnieniami i obsługę dużych ilości danych nagrywania lub odtwarzania za pomocą interfejsu HAL tunera.
  • Moduł Native Tuner to pomost między klasą Tuner Java a warstwą HAL tunera.

Tworzona jest klasa TRM.

  • Zarządza ograniczonymi zasobami tunera, takimi jak interfejs, LNB, sesje CAS i urządzenie wejściowe TV z poziomu HAL wejścia TV.
  • Stosuje reguły, aby odzyskać niewystarczające zasoby z aplikacji. Regułą domyślną jest wygrana pierwszego planu.

Media CAS i CAS HAL zostały wzbogacone o te funkcje:

  • Otwiera sesje CAS dla różnych zastosowań i algorytmów.
  • Obsługuje dynamiczne systemy CAS, takie jak wyjmowanie i wkładanie modułów CICAM.
  • Integruje się z Tuner HAL, udostępniając tokeny kluczy.

MediaCodecAudioTrack zostały ulepszone o funkcje wymienione poniżej.

  • Przyjmuje bezpieczną pamięć A/V jako dane wejściowe treści.
  • Skonfigurowane do synchronizacji sprzętowej audio-wideo w odtwarzaniu tunelowanym.
  • Skonfigurowana obsługa ES_payload i trybu przekazywania.

Ogólna konstrukcja interfejsu HAL tunera.

Rysunek 2. Diagram komponentów w warstwie HAL tunera

Ogólny przepływ pracy

Poniższe diagramy przedstawiają sekwencje wywołań w przypadku odtwarzania transmisji na żywo.

Konfiguracja

Diagram sekwencji konfiguracji odtwarzania transmisji na żywo.

Rysunek 3. Konfigurowanie sekwencji odtwarzania transmisji na żywo

Obsługa sprzętu audio-wideo

Schemat obsługi dźwięku i obrazu podczas odtwarzania transmisji na żywo.

Rysunek 4. Obsługa dźwięku i obrazu podczas odtwarzania transmisji na żywo

Postępowanie w przypadku zaszyfrowanych treści

Diagram obsługi zaszyfrowanych treści podczas odtwarzania transmisji na żywo.

Rysunek 5. Postępowanie z zaszyfrowanymi treściami podczas odtwarzania transmisji na żywo

Przetwarzanie danych audio-wideo

Schemat przetwarzania danych audio-wideo na potrzeby odtwarzania transmisji na żywo.

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.

Diagram przepływu interfejsu Tuner SDK API.

Rysunek 7. Interakcje z interfejsem Tuner SDK API

Wersje

Od Androida 12 interfejs API pakietu SDK Tuner obsługuje nową funkcję w Tuner HAL 1.1, która jest wstecznie zgodną aktualizacją wersji Tuner 1.0.

Aby sprawdzić działającą wersję HAL, użyj tego interfejsu API.

  • android.media.tv.tuner.TunerVersionChecker.getTunerVersion()

Minimalną wymaganą wersję HAL znajdziesz w dokumentacji nowych interfejsów API Androida 12.

Pakiety

Interfejs API pakietu SDK Tuner udostępnia 4 pakiety wymienione poniżej.

  • android.media.tv.tuner
  • android.media.tv.tuner.frontend
  • android.media.tv.tuner.filter
  • android.media.tv.tuner.dvr

Diagram przepływu pakietów interfejsu Tuner SDK API.

Rysunek 8. Pakiety interfejsu API pakietu SDK Tuner

Android.media.tv.tuner

Pakiet Tuner to punkt wejścia do korzystania z platformy Tuner. Aplikacja TIS używa pakietu do inicjowania i pozyskiwania instancji zasobów przez określenie ustawienia początkowego i wywołania zwrotnego.

  • tuner(): inicjuje instancję Tunera, określając parametry useCasesessionId.
  • tune(): pobiera zasób interfejsu i dostraja go, określając parametr FrontendSetting.
  • openFilter(): pobiera instancję filtra, określając jego typ.
  • openDvrRecorder(): Pobiera instancję nagrywania, określając rozmiar bufora.
  • openDvrPlayback(): Pobiera instancję odtwarzania, określając rozmiar bufora.
  • openDescrambler(): pobiera instancję dekodera.
  • openLnb(): pobiera wewnętrzną instancję LNB.
  • openLnbByName(): uzyskuje instancję zewnętrznego konwertera LNB.
  • openTimeFilter(): Pobiera instancję filtra czasu.

Pakiet Tuner udostępnia funkcje, które nie są objęte pakietami filtrów, DVR i frontend. Funkcje te są wymienione poniżej.

  • cancelTuning
  • scan/cancelScanning
  • getAvSyncHwId
  • getAvSyncTime
  • connectCiCam1/disconnectCiCam
  • shareFrontendFromTuner
  • updateResourcePriority
  • setOnTuneEventListener
  • setResourceLostListener

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.

  • AnalogFrontendSettings
  • Atsc3FrontendSettings
  • AtscFrontendSettings
  • DvbcFrontendSettings
  • DvbsFrontendSettings
  • DvbtFrontendSettings
  • Isdbs3FrontendSettings
  • IsdbsFrontendSettings
  • IsdbtFrontendSettings

W przypadku Androida 12 z Tuner HAL w wersji 1.1 lub nowszej obsługiwany jest ten standard DTV:

  • DtmbFrontendSettings

FrontendCapabilities jest obliczany dla różnych standardów DTV na podstawie klas poniżej.

  • AnalogFrontendCapabilities
  • Atsc3FrontendCapabilities
  • AtscFrontendCapabilities
  • DvbcFrontendCapabilities
  • DvbsFrontendCapabilities
  • DvbtFrontendCapabilities
  • Isdbs3FrontendCapabilities
  • IsdbsFrontendCapabilities
  • IsdbtFrontendCapabilities

W przypadku Androida 12 z Tuner HAL w wersji 1.1 lub nowszej obsługiwany jest ten standard DTV:

  • DtmbFrontendCapabilities

FrontendInfo pobiera informacje z interfejsu. FrontendStatus pobiera bieżący stan interfejsu. OnTuneEventListener nasłuchuje zdarzeń w interfejsie. Aplikacja TIS używa ScanCallback do przetwarzania wiadomości ze skanowania z frontendu.

Skanowanie kanałów

Aby skonfigurować telewizor, aplikacja skanuje możliwe częstotliwości i tworzy listę kanałów, do których użytkownicy mają dostęp. TIS może używać Tuner.tune, Tuner.scan(BLIND_SCAN) lub Tuner.scan(AUTO_SCAN) do skanowania kanałów.

Jeśli TIS ma dokładne informacje o dostawie sygnału, takie jak częstotliwość, standard (np. T/T2, S/S2) i dodatkowe niezbędne informacje (np. identyfikator PLD), zalecamy użycie opcji Tuner.tune, ponieważ jest szybsza.

Gdy użytkownik zadzwoni pod numer Tuner.tune, nastąpią te działania:

  • TIS wypełnia pole FrontendSettings wymaganymi informacjami za pomocą Tuner.tune.
  • Jeśli sygnał jest zablokowany, HAL zgłasza komunikaty LOCKED.
  • TIS używa Frontend.getStatus do zbierania niezbędnych informacji.
  • TIS przełącza się na następną dostępną częstotliwość na liście częstotliwości.

TIS ponownie wywołuje Tuner.tune, aż wszystkie częstotliwości zostaną wyczerpane.

Podczas dostrajania możesz zadzwonić pod numer stopTune() lub close(), aby wstrzymać lub zakończyć połączenie Tuner.tune.

Tuner.scan(AUTO_SCAN)

Jeśli usługa TIS nie ma wystarczających informacji, aby użyć Tuner.tune, ale ma listę częstotliwości i standardowy typ (np. DVB T/C/S), zalecane jest Tuner.scan(AUTO_SCAN).

Gdy użytkownik zadzwoni pod numer Tuner.scan(AUTO_SCAN), nastąpią te działania:

  • TIS używa Tuner.scan(AUTO_SCAN) z wypełnionym polem FrontendSettings, które zawiera częstotliwość.

  • Skanowanie raportów HAL LOCKED wiadomości, jeśli sygnał jest zablokowany. Warstwa HAL może też zgłaszać inne komunikaty skanowania, aby dostarczać dodatkowych informacji o sygnałach.

  • TIS używa Frontend.getStatus do 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 struktura FrontendSettings jest pusta, HAL używa następnego dostępnego ustawienia. W przeciwnym razie HAL używa FrontendSettings do jednorazowego skanowania i wysyła END, aby wskazać, że operacja skanowania została zakończona.

  • TIS powtarza powyższe działania, dopóki nie wyczerpią się wszystkie ustawienia częstotliwości.

  • HAL wysyła END, aby wskazać, że skanowanie zostało zakończone.

  • TIS przełącza się na następną dostępną częstotliwość na liście częstotliwości.

TIS ponownie wywołuje Tuner.scan(AUTO_SCAN), aż wszystkie częstotliwości zostaną wyczerpane.

Podczas skanowania możesz zadzwonić pod numer stopScan() lub close(), aby wstrzymać lub zakończyć skanowanie.

Tuner.scan(BLIND_SCAN)

Jeśli TIS nie ma listy częstotliwości, a HAL dostawcy może wyszukiwać częstotliwość określonego przez użytkownika interfejsu, aby uzyskać zasób interfejsu, zalecana jest opcja Tuner.scan(BLIND_SCAN).

  • TIS używa Tuner.scan(BLIND_SCAN). Częstotliwość można określić w FrontendSettings dla częstotliwości początkowej, ale TIS ignoruje inne ustawienia w FrontendSettings.
  • Jeśli sygnał jest zablokowany, HAL zgłasza skanowanie LOCKED.
  • TIS używa Frontend.getStatus do zbierania niezbędnych informacji.
  • TIS ponownie dzwoni Tuner.scan, aby kontynuować skanowanie. (FrontendSettings jest 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.

Schemat procesu skanowania TIS.

Rysunek 9. Schemat blokowy skanowania TIS

Android.media.tv.tuner.filter

Pakiet filtrów to zbiór operacji filtrowania wraz z konfiguracją, ustawieniami, wywołaniami zwrotnymi i zdarzeniami. Pakiet obejmuje te działania: Pełną listę operacji znajdziesz w kodzie źródłowym Androida.

  • configure()
  • start()
  • stop()
  • flush()
  • read()

Pełną listę znajdziesz w kodzie źródłowym Androida.

FilterConfiguration pochodzi z tych klas: Konfiguracje dotyczą głównego typu filtra i określają, jakiego protokołu używa filtr do wyodrębniania danych.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Ustawienia pochodzą z tych klas: Ustawienia dotyczą podtypu filtra i określają, jakie rodzaje danych może on wykluczać.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent pochodzi z klas poniżej i służy do raportowania zdarzeń dotyczących różnych rodzajów danych.

  • SectionEvent
  • MediaEvent
  • PesEvent
  • TsRecordEvent
  • MmtpRecordEvent
  • TemiEvent
  • DownloadEvent
  • IpPayloadEvent

W przypadku Androida 12 z Tuner HAL w wersji 1.1 lub nowszej obsługiwane są te zdarzenia:

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Zdarzenia i format danych z filtra
Typ filtra Flagi Wydarzenia Operacja na danych Format danych
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Obowiązkowe:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiaj
Filter.read(buffer, offset, adjustedSize) co najmniej raz.

Dane są kopiowane z kolejki MQ HAL do bufora klienta.
Jeden zmontowany pakiet sesji jest wypełniany w FMQ przez inny pakiet sesji.
isRaw:
false
Obowiązkowe:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalne:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


Dane są kopiowane z MQ HAL do bufora klienta.
TS.PES isRaw:
true
Obowiązkowe:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiaj
Filter.read(buffer, offset, adjustedSize) co najmniej raz.

Dane są kopiowane z kolejki MQ HAL do bufora klienta.
Jeden zmontowany pakiet PES jest wypełniany w FMQ przez inny pakiet PES.
isRaw:
false
Obowiązkowe:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalne:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Dane są kopiowane z MQ HAL do bufora klienta.
MMTP.PES isRaw:
true
Obowiązkowe:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiaj
Filter.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:
false
Obowiązkowe:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalne:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Dane są kopiowane z kolejki MQ HAL do bufora klienta.
TS.TS
Nie dotyczy Obowiązkowe:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiaj
Filter.read(buffer, offset, adjustedSize) co najmniej raz.

Dane są kopiowane z kolejki MQ HAL do bufora klienta.
Odfiltrowane tsts nagłówkiem
jest wypełnione w FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::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:
false
Obowiązkowe:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalne:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Aby użyć MediaCodec:
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Aby użyć bezpośredniego dźwięku z AudioTrack:
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Dane ES lub częściowe dane ES w pamięci ION.
TS.PCR
IP.NTP
ALP.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_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcjonalne:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W przypadku danych indeksu:
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


W przypadku nagranych treści, zgodnie z RecordStatus::* i harmonogramem wewnętrznym, wykonaj jedną z tych czynności:
  • Uruchom DvrRecord.write(adustedSize) co najmniej raz, aby zapisać dane.
    Dane są przesyłane z kolejki MQ HAL do pamięci.
  • Uruchom DvrRecord.write(buffer, adustedSize) co najmniej raz, aby utworzyć bufor.
    Dane są kopiowane z kolejki MQ interfejsu HAL do bufora klienta.
W przypadku danych indeksu: są one przesyłane w ładunku zdarzenia.

W przypadku nagranych treści: strumień Muxed TS wypełniony w FMQ.
TS.TEMI Nie dotyczy Obowiązkowe:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Opcjonalne:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
Nie dotyczy
MMTP.MMTP Nie dotyczy Obowiązkowe:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiaj
Filter.read(buffer, offset, adjustedSize) co najmniej raz.

Dane są kopiowane z kolejki MQ HAL do bufora klienta.
Pole „Filtered out mmtp with mmtp header
” jest wypełnione w FMQ.
MMTP.RECORD Nie dotyczy Obowiązkowe:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcjonalne:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W przypadku danych indeksu: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


W przypadku nagranych treści, zgodnie z RecordStatus::* i wewnętrznym harmonogramem, wykonaj jedną z tych czynności:
  • Uruchom DvrRecord.write(adjustedSize) co najmniej raz, aby zapisać dane.
    Dane są przesyłane z kolejki MQ HAL do pamięci.
  • Uruchom DvrRecord.write(buffer, adjustedSize)co najmniej raz, aby utworzyć bufor.
    Dane są kopiowane z kolejki MQ warstwy HAL do bufora klienta.
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_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalne:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

Dane są kopiowane z kolejki komunikatów HAL do bufora klienta.
Pakiet pobierania jest wypełniany w FMQ przez inny pakiet pobierania IP.
IP.IP_PAYLOAD Nie dotyczy Obowiązkowe:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalne:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

Dane są kopiowane z kolejki komunikatów HAL do bufora klienta.
Pakiet danych IP jest zastępowany w FMQ przez inny pakiet danych IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Podstrumień protokołu po zastosowaniu filtra przekazuje dane do następnego filtra w łańcuchu filtrów. Nie dotyczy
isPassthrough:
false
Obowiązkowe:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
W zależności od wydarzenia i harmonogramu wewnętrznego uruchamiaj
Filter.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_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
Nie dotyczy Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Odfiltrowane dane protokołu są przekazywane do następnego filtra w łańcuchu filtrów. Nie dotyczy
Przykładowy proces używania filtra do tworzenia PSI/SI

Przykładowy proces używania filtra do tworzenia PSI/SI.

Rysunek 10. Proces tworzenia PSI/SI

  1. Otwórz filtr.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. 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();
    
  3. Przetwarzanie SectionEvent.

    FilterCallback filterCallback = new FilterCallback() {
      @Override
      public void onFilterEvent(Filter filter, FilterEvent[] events) {
        for (FilterEvent event : events) {
          if (event instanceof SectionEvent) {
            SectionEvent sectionEvent = (SectionEvent) event;
            int tableId = sectionEvent.getTableId();
            int version = sectionEvent.getVersion();
            int dataLength = sectionEvent.getDataLength();
            int sectionNumber = sectionEvent.getSectionNumber();
            filter.read(buffer, 0, dataLength); }
          }
        }
    };
    
Przykładowy przepływ użycia MediaEvent z filtra

Przykładowy przepływ korzystania z MediaEvent z filtra.

Rysunek 11. Flow to use MediaEvent from filter

  1. Otwórz, skonfiguruj i uruchom filtry A/V.
  2. Przetwarzanie MediaEvent.
  3. Otrzymaj MediaEvent.
  4. Umieść blok liniowy w kolejce na pozycji codec.
  5. 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 konfigurowania DvrRecorderDvrPlayback. OnPlaybackStatusChangedListenerOnRecordStatusChangedListener służą do raportowania stanu instancji DVR.

Przykładowy przepływ rozpoczynania nagrywania

Przykładowy proces rozpoczynania nagrywania.

Rysunek 12. Flow do rozpoczęcia nagrywania

  1. 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();
    
  2. Otrzymaj 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. }
          }
        }
    };
    
  3. 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

Warstwa HAL tunera jest zgodna z HIDL i określa interfejs między platformą a sprzętem dostawcy. Dostawcy używają tego interfejsu do implementowania HAL tunera, a platforma używa go do komunikacji z implementacją HAL tunera.

Moduły

Tuner HAL 1.0

Moduły Podstawowe funkcje sterowania Ustawienia dotyczące modułu Pliki HAL
ITuner Nie dotyczy frontend(open, getIds, getInfo), openDemux, openDescrambler, openLnb, getDemuxCaps ITuner.hal
IFrontend setCallback, getStatus, close tune, stopTune, scan, stopScan, setLnb IFrontend.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 (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

Schemat blokowy interakcji między modułami Tuner 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>)
}

Diagram przykładu połączenia filtrów.

Rysunek 14. Schemat połączenia filtrów dla wielu warstw

Menedżer zasobów tunera

Przed wprowadzeniem Menedżera zasobów tunera (TRM) przełączanie między dwiema aplikacjami wymagało tego samego sprzętu tunera. TV Input Framework (TIF) używa mechanizmu „pierwszy, który pozyska, wygrywa”, co oznacza, że aplikacja, która jako pierwsza uzyska dostęp do zasobu, zachowuje go. Ten mechanizm może jednak nie być idealny w przypadku niektórych skomplikowanych zastosowań.

TRM działa jako usługa systemowa, która zarządza tunerem, TVInput i zasobami sprzętowymi CAS na potrzeby aplikacji. TRM korzysta z mechanizmu „zwycięstwa na pierwszym planie”, który oblicza priorytet aplikacji na podstawie jej stanu (na pierwszym planie lub w tle) i typu przypadku użycia. TRM przyznaje lub odbiera zasób na podstawie priorytetu. TRM centralizuje zarządzanie zasobami ATV w przypadku transmisji, OTT i DVR.

Interfejs TRM

TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl dla platformy Tuner, MediaCasTvInputHardwareManager, aby rejestrować, żądać lub zwalniać zasoby.

Poniżej znajdziesz listę interfejsów do zarządzania klientami.

  • registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
  • unregisterClientProfile(in int clientId)

Interfejsy do wysyłania próśb o zasoby i ich zwalniania są wymienione poniżej.

  • requestFrontend(TunerFrontendRequest request, int[] frontendHandle) / 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 klienta i żądania.

  • 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ż zostać zaktualizowany przez klienta za pomocą dowolnej wartości priorytetu.

Parametry w profilu klienta

TRM pobiera identyfikator procesu z mTvInputSessionId, aby określić, czy aplikacja jest aplikacją na pierwszym planie czy w tle. Aby utworzyć mTvInputSessionId, TvInputService.onCreateSession lub TvInputService.onCreateRecordingSession, usługa TIS inicjuje sesję.

mUseCase – wskazuje przypadek użycia sesji. Predefiniowane przypadki użycia są wymienione poniżej.

TvInputService.PriorityHintUseCaseType  {
  PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
  PRIORITY_HINT_USE_CASE_TYPE_LIVE
  PRIORITY_HINT_USE_CASE_TYPE_RECORD,
  PRIORITY_HINT_USE_CASE_TYPE_SCAN,
  PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
}

Plik konfiguracji

Domyślny plik konfiguracji

Poniższy domyślny plik konfiguracyjny zawiera wartości priorytetów dla wstępnie zdefiniowanych przypadków użycia. Użytkownicy mogą zmieniać wartości za pomocą dostosowanego pliku konfiguracyjnego.

Przypadek użycia Pierwszy plan Tło
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Dostosowany plik konfiguracji

Dostawcy mogą dostosowywać plik konfiguracji/vendor/etc/tunerResourceManagerUseCaseConfig.xml. Ten plik służy do dodawania, usuwania i aktualizowania typów przypadków użycia oraz wartości priorytetu przypadków użycia. Dostosowany plik może używać platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml jako szablonu.

Na przykład nowy przypadek użycia dostawcy to VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]. Format powinien być zgodny z tym wzorcem: platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd.

Dowolna wartość priorytetu i wartość nice

TRM udostępnia updateClientPriority, aby klient mógł zaktualizować dowolną wartość priorytetu i wartość nice. Dowolna wartość priorytetu zastępuje wartość priorytetu obliczoną na podstawie typu przypadku użycia i identyfikatora sesji.

Wartość nice określa, jak pobłażliwe jest zachowanie klienta, gdy jest ono sprzeczne z zachowaniem innego klienta. Wartość nice zmniejsza priorytet klienta, zanim zostanie on porównany z priorytetem klienta wymagającego.

Mechanizm odzyskiwania

Diagram poniżej pokazuje, jak zasoby są odzyskiwane i przypisywane w przypadku konfliktu zasobów.

Diagram procesu mechanizmu odzyskiwania.

Rysunek 15. Diagram mechanizmu odzyskiwania w przypadku konfliktu między zasobami Tuner