Ramy tunera

W przypadku systemu Android 11 lub nowszego możesz używać platformy Android Tuner do dostarczania treści A/V. Framework wykorzystuje potok sprzętowy od dostawców, dzięki czemu nadaje się zarówno do SoC z niższej, jak i wyższej półki. Struktura zapewnia bezpieczny sposób dostarczania treści A/V chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę multimediów (SMP), umożliwiając korzystanie z nich w bardzo ograniczonym środowisku ochrony treści.

Standaryzowany interfejs pomiędzy Tunerem i Android CAS zapewnia szybszą integrację pomiędzy dostawcami tunerów i CAS. Interfejs tunera współpracuje z MediaCodec i AudioTrack , tworząc jedno światowe rozwiązanie dla Android TV. Interfejs tunera obsługuje zarówno telewizję cyfrową, jak i telewizję analogową w oparciu o główne standardy transmisji.

składniki

W przypadku Androida 11 trzy komponenty są specjalnie zaprojektowane dla platformy telewizyjnej.

  • Tuner HAL: Interfejs pomiędzy frameworkiem a dostawcami
  • Tuner SDK API: Interfejs pomiędzy frameworkiem i aplikacjami
  • Menedżer zasobów tunera (TRM): koordynuje zasoby sprzętowe tunera

W systemie Android 11 ulepszono następujące komponenty.

  • CAS V2
  • TvInputService lub usługa wejścia telewizyjnego (TIS)
  • Usługa TvInputManagerService lub usługa Menedżera wejścia telewizyjnego (TIMS)
  • MediaCodec lub kodek multimedialny
  • AudioTrack lub ścieżka audio
  • MediaResourceManager lub menedżer zasobów multimedialnych (MRM)

Schemat blokowy komponentów struktury tunera.

Rysunek 1. Interakcje pomiędzy komponentami Android TV

Cechy

Frontend obsługuje poniższe standardy DTV.

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

Frontend w systemie Android 12 z tunerem HAL 1.1 lub nowszym obsługuje poniższy standard DTV.

  • DTMB

Demux obsługuje poniższe protokoły strumieniowe.

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

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

  • Bezpieczna ścieżka multimediów
  • Wyczyść ścieżkę multimediów
  • Bezpieczny zapis lokalny
  • Bezpieczne odtwarzanie lokalne

Interfejsy API tunera obsługują poniższe przypadki użycia.

  • Skanowanie
  • Na żywo
  • Odtwarzanie nagranego dźwięku
  • Nagrywać

Tuner, MediaCodec i AudioTrack obsługują poniższe tryby przepływu danych.

  • Ładunek ES z czystym buforem pamięci
  • Ładunek ES z bezpiecznym uchwytem pamięci
  • Przejść przez

Ogólny projekt

Tuner HAL jest zdefiniowany pomiędzy platformą Android a sprzętem dostawcy.

  • Opisuje, czego platforma oczekuje od dostawcy i w jaki sposób dostawca może to zrobić.
  • Eksportuje funkcjonalności frontendu, demuxa i deszymblera do frameworka poprzez interfejsy IFrontend , IDemux , IDescrambler , IFilter , IDvr i ILnb .
  • Zawiera funkcje umożliwiające integrację tunera HAL z innymi komponentami platformy, takimi jak MediaCodec i AudioTrack .

Tworzona jest klasa Tuner Java i klasa natywna.

  • Interfejs API Tuner Java umożliwia aplikacjom dostęp do Tuner HAL za pośrednictwem publicznych interfejsów API.
  • Klasa natywna umożliwia kontrolę uprawnień i obsługę dużych ilości danych dotyczących nagrywania lub odtwarzania za pomocą tunera HAL.
  • Moduł Native Tuner jest pomostem pomiędzy klasą Tuner Java i Tuner HAL.

Tworzona jest klasa TRM.

  • Zarządza ograniczonymi zasobami tunera, takimi jak Frontend, LNB, sesje CAS i urządzenie wejściowe TV z wejścia TV HAL.
  • Stosuje reguły odzyskiwania niewystarczających zasobów z aplikacji. Domyślną zasadą jest wygrana pierwszego planu.

Media CAS i CAS HAL zostały wzbogacone o poniższe funkcje.

  • Otwiera sesje CAS dla różnych zastosowań i algorytmów.
  • Obsługuje dynamiczne systemy CAS, takie jak usuwanie i wstawianie CICAM.
  • Integruje się z tunerem HAL, udostępniając kluczowe tokeny.

MediaCodec i AudioTrack zostały ulepszone o poniższe funkcje.

  • Jako wejście zawartości pobiera bezpieczną pamięć A/V.
  • Skonfigurowany do sprzętowej synchronizacji A/V w odtwarzaniu tunelowym.
  • Skonfigurowana obsługa ES_payload i trybu przekazywania.

Ogólny projekt tunera HAL.

Rysunek 2. Schemat komponentów tunera HAL

Ogólny przepływ pracy

Poniższe diagramy ilustrują sekwencje wywołań dla odtwarzania transmisji na żywo.

Organizować coś

Ustaw sekwencję schematu odtwarzania transmisji na żywo.

Rysunek 3. Sekwencja konfiguracji odtwarzania transmisji na żywo

Obsługa A/V

Schemat obsługi A/V podczas odtwarzania transmisji na żywo.

Rysunek 4. Obsługa A/V podczas odtwarzania transmisji na żywo

Obsługa zakodowanej treści

Schemat postępowania z zakodowaną treścią w przypadku odtwarzania transmisji na żywo.

Rysunek 5. Obsługa zakodowanej zawartości podczas odtwarzania transmisji na żywo

Przetwarzanie danych A/V

Przetwarzaj dane A/V na potrzeby diagramu odtwarzania transmisji na żywo.

Rysunek 6. Przetwarzanie A/V do odtwarzania transmisji na żywo

API SDK tunera

Interfejs API Tuner SDK obsługuje interakcje z Tuner JNI, Tuner HAL i TunerResourceManager . Aplikacja TIS korzysta z interfejsu API Tuner SDK, aby uzyskać dostęp do zasobów i podzespołów Tunera, takich jak filtr i dekoder. Frontend i demux to komponenty wewnętrzne.

Schemat blokowy interfejsu API Tuner SDK.

Rysunek 7. Interakcje z API Tuner SDK

Wersje

Od systemu Android 12 interfejs API Tuner SDK obsługuje nową funkcję w Tuner HAL 1.1, która jest kompatybilną wstecz aktualizacją Tunera 1.0.

Użyj poniższego interfejsu API, aby sprawdzić działającą wersję HAL.

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

Minimalną wymaganą wersję HAL można znaleźć w dokumentacji nowych interfejsów API Androida 12.

Pakiety

Interfejs API Tuner SDK udostępnia cztery poniższe pakiety.

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

Schemat blokowy pakietów API Tuner SDK.

Rysunek 8. Pakiety API tunera SDK

Tuner Android.media.tv

Pakiet Tuner jest punktem wyjścia do korzystania ze środowiska Tuner. Aplikacja TIS używa pakietu do inicjowania i pozyskiwania instancji zasobów poprzez określenie ustawień początkowych i wywołania zwrotnego.

  • tuner() : Inicjuje instancję Tunera, określając parametry useCase i sessionId .
  • tune() : Pobiera zasób frontonu i dostraja go, określając parametr FrontendSetting .
  • openFilter() : Pobiera instancję filtru poprzez określenie typu filtra.
  • openDvrRecorder() : Pobiera instancję nagrywania poprzez określenie rozmiaru bufora.
  • openDvrPlayback() : Uzyskuje instancję odtwarzania poprzez określenie rozmiaru bufora.
  • openDescrambler() : Pobiera instancję deszyfratora.
  • openLnb() : Pozyskuje wewnętrzną instancję LNB.
  • openLnbByName() : Pozyskuje zewnętrzną instancję LNB.
  • openTimeFilter() : Pobiera instancję filtra czasu.

Pakiet Tuner zapewnia funkcje, które nie są objęte pakietami filtrów, DVR i frontendu. Poniżej wymieniono funkcjonalności.

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

Android.media.tv.tuner.frontend

Pakiet frontonu zawiera zbiory ustawień, informacji, statusów, zdarzeń i możliwości związanych z frontendem.

Zajęcia

FrontendSettings jest wyprowadzany dla różnych standardów DTV na podstawie poniższych klas.

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

Od systemu Android 12 z tunerem HAL 1.1 lub nowszym obsługiwany jest następujący standard DTV.

  • DtmbFrontendSettings

FrontendCapabilities jest wyprowadzany dla różnych standardów DTV na podstawie poniższych klas.

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

Od systemu Android 12 z tunerem HAL 1.1 lub nowszym obsługiwany jest następujący standard DTV.

  • DtmbFrontendCapabilities

FrontendInfo pobiera informacje o interfejsie. FrontendStatus pobiera bieżący stan frontonu. OnTuneEventListener nasłuchuje zdarzeń na interfejsie. Aplikacja TIS wykorzystuje ScanCallback do przetwarzania wiadomości skanowania z interfejsu użytkownika.

Skanowanie kanałów

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

Jeśli TIS ma dokładne informacje o dostawie sygnału, takie jak częstotliwość, standard (na przykład T/T2, S/S2) i dodatkowe niezbędne informacje (na przykład identyfikator PLD), wówczas Tuner.tune jest zalecany jako szybsza opcja .

Kiedy użytkownik wywołuje Tuner.tune , mają miejsce następujące działania:

  • TIS wypełnia FrontendSettings wymaganymi informacjami za pomocą Tuner.tune .
  • Raporty HAL dostrajają komunikaty LOCKED , jeśli sygnał jest zablokowany.
  • TIS korzysta z Frontend.getStatus w celu gromadzenia niezbędnych informacji.
  • TIS przechodzi do następnej dostępnej częstotliwości na swojej liście częstotliwości.

TIS ponownie wywołuje Tuner.tune , aż do wyczerpania wszystkich częstotliwości.

Podczas strojenia możesz wywołać stopTune() lub close() , aby wstrzymać lub zakończyć wywołanie Tuner.tune .

Skanowanie tunera(AUTO_SCAN)

Jeśli TIS nie ma wystarczających informacji, aby użyć Tuner.tune , ale ma listę częstotliwości i typ standardu (na przykład DVB T/C/S), zalecany jest Tuner.scan(AUTO_SCAN) .

Kiedy użytkownik wywołuje Tuner.scan(AUTO_SCAN) , wykonywane są następujące działania:

  • TIS używa Tuner.scan(AUTO_SCAN) z FrontendSettings wypełnionymi częstotliwością.

  • Raporty HAL skanują wiadomości LOCKED , jeśli sygnał jest zablokowany. HAL może również raportować inne komunikaty skanowania, aby zapewnić dodatkowe informacje o sygnale.

  • TIS korzysta z Frontend.getStatus w celu gromadzenia niezbędnych informacji.

  • TIS wywołuje Tuner.scan , aby HAL mógł przejść do następnego ustawienia na tej samej częstotliwości. Jeśli struktura FrontendSettings jest pusta, warstwa HAL używa następnego dostępnego ustawienia. W przeciwnym razie warstwa HAL używa FrontendSettings do jednorazowego skanowania i wysyła END , aby wskazać, że operacja skanowania została zakończona.

  • TIS powtarza powyższe czynności, aż do wyczerpania wszystkich ustawień częstotliwości.

  • HAL wysyła END , aby wskazać, że operacja skanowania została zakończona.

  • TIS przechodzi do następnej dostępnej częstotliwości na swojej liście częstotliwości.

TIS ponownie wywołuje Tuner.scan(AUTO_SCAN) aż do wyczerpania wszystkich częstotliwości.

Podczas skanowania możesz wywołać stopScan() lub close() , aby wstrzymać lub zakończyć skanowanie.

Skanowanie tunera(BLIND_SCAN)

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

  • TIS używa Tuner.scan(BLIND_SCAN) . Częstotliwość można określić w FrontendSettings jako częstotliwość początkową, ale TIS ignoruje inne ustawienia w FrontendSettings .
  • HAL zgłasza komunikat skanowania LOCKED , jeśli sygnał jest zablokowany.
  • TIS korzysta z Frontend.getStatus w celu gromadzenia niezbędnych informacji.
  • TIS ponownie wywołuje Tuner.scan , aby kontynuować skanowanie. ( FrontendSettings są ignorowane.)
  • TIS powtarza powyższe czynności, aż do wyczerpania wszystkich ustawień częstotliwości. HAL zwiększa częstotliwość bez konieczności podejmowania działań ze strony TIS. HAL raportuje PROGRESS .

TIS ponownie wywołuje Tuner.scan(AUTO_SCAN) aż do wyczerpania wszystkich częstotliwości. HAL zgłasza END , aby wskazać, że operacja skanowania została zakończona.

Podczas skanowania możesz wywołać stopScan() lub close() , aby wstrzymać lub zakończyć skanowanie.

Schemat blokowy procesu skanowania TIS.

Rysunek 9. Schemat blokowy skanowania TIS

Filtr.media.tv.tuner.Android.media.tv.tuner.filter

Pakiet filtrów to zbiór operacji filtrujących wraz z konfiguracją, ustawieniami, wywołaniami zwrotnymi i zdarzeniami. Pakiet zawiera poniższe operacje. Pełną listę operacji znajdziesz w kodzie źródłowym Androida.

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

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

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

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Ustawienia pochodzą z poniższych klas. Ustawienia dotyczą podtypu filtra i określają, jakiego rodzaju dane filtr może wykluczać.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent wywodzi się z poniższych klas i służy do raportowania zdarzeń dla różnych rodzajów danych.

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

Od systemu Android 12 z tunerem HAL 1.1 lub nowszym obsługiwane są następujące zdarzenia.

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

Zalecana:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnij
Filter.read(buffer, offset, adjustedSize) jeden lub więcej razy.

Dane są kopiowane z MQ HAL do bufora klienta.
Jeden złożony pakiet sesji jest wypełniany w FMQ innym pakietem sesji.
isRaw:
false
Obowiązkowy:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalny:
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ązkowy:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecana:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnij
Filter.read(buffer, offset, adjustedSize) jeden lub więcej razy.

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

Opcjonalny:
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ązkowy:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecana:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnij
Filter.read(buffer, offset, adjustedSize) jeden lub więcej razy.

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

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


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

Zalecana:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnij
Filter.read(buffer, offset, adjustedSize) jeden lub więcej razy.

Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Odfiltrowano ts z nagłówkiem ts
jest wypełniony FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Opcjonalny:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Klient może uruchomić MediaCodec po otrzymaniu DemuxFilterStatus::DATA_READY .
Klient może wywołać Filter.flush po otrzymaniu DemuxFilterStatus::DATA_OVERFLOW .
Nie dotyczy
isPassthrough:
false
Obowiązkowy:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


Aby użyć bezpośredniego dźwięku AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Dane ES lub częściowe ES w pamięci ION.
TS.PCR
IP.NTP
ALP.PTP
Nie dotyczy Obowiązkowe: nie dotyczy
Opcjonalnie: nie dotyczy
Nie dotyczy Nie dotyczy
TS.RECORD Nie dotyczy Obowiązkowy:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcjonalny:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Dla danych indeksowych:
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


W przypadku nagranej treści zgodnie z RecordStatus::* i wewnętrznym harmonogramem wykonaj jedną z następujących czynności:
  • Uruchom DvrRecord.write(adustedSize) raz lub kilka razy w celu zapisania go w pamięci.
    Dane są przesyłane z MQ HAL do pamięci.
  • Uruchom DvrRecord.write(buffer, adustedSize) jeden lub więcej razy, aby buforować.
    Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Dla danych indeksowych: Przenoszony w ładunku zdarzenia.

Dla nagranej zawartości: Muxed strumień TS wypełniony FMQ.
TS.TEMI Nie dotyczy Obowiązkowy:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

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

Zalecana:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnij
Filter.read(buffer, offset, adjustedSize) jeden lub więcej razy.

Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Odfiltrowano mmtp z nagłówkiem mmtp
jest wypełniony FMQ.
MMTP.RECORD Nie dotyczy Obowiązkowy:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcjonalny:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Dla danych indeksowych: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


W przypadku nagranej treści zgodnie z RecordStatus::* i wewnętrznym harmonogramem wykonaj jedną z następujących czynności:
  • Uruchom DvrRecord.write(adjustedSize) jeden lub więcej razy do przechowywania.
    Dane są przesyłane z MQ HAL do pamięci.
  • Uruchom DvrRecord.write(buffer, adjustedSize) jeden lub więcej razy, aby buforować.
    Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Dla danych indeksowych: Przenoszony w ładunku zdarzenia.

W przypadku nagranej zawartości: zmultiplikowany nagrany strumień wypełniony FMQ.

Jeśli źródłem filtra do nagrywania jest TLV.TLV do IP.IP z przejściem, zarejestrowany strumień ma nagłówek TLV i IP.
MMTP.DOWNLOAD Nie dotyczy Obowiązkowy:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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

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

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

Dane są kopiowane z MQ HAL do bufora klienta.
Pakiet ładunku IP jest wypełniany w FMQ przez inny pakiet ładunku IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Opcjonalny:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Odfiltrowany podstrumień protokołu zasila następny filtr w łańcuchu filtrów. Nie dotyczy
isPassthrough:
false
Obowiązkowy:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecana:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i harmonogramem wewnętrznym biegnij
Filter.read(buffer, offset, adjustedSize) jeden lub więcej razy.

Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Odfiltrowany podstrumień protokołu z nagłówkiem protokołu jest wypełniany w FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
Nie dotyczy Opcjonalny:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Odfiltrowany ładunek protokołu zasila następny filtr w łańcuchu filtrów. Nie dotyczy
Przykładowy przebieg użycia filtra do zbudowania PSI/SI

Przykładowy przebieg użycia filtra do zbudowania 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. SectionEvent procesuZdarzenie .

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

Przykładowy przebieg użycia MediaEvent z filtra.

Rysunek 11. Przebieg korzystania z MediaEvent z filtra

  1. Otwórz, skonfiguruj i uruchom filtry A/V.
  2. Przetwarzaj MediaEvent .
  3. Odbierz MediaEvent .
  4. Kolejkuj blok liniowy do 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 konfiguracji DvrRecorder i DvrPlayback . OnPlaybackStatusChangedListener i OnRecordStatusChangedListener służą do raportowania stanu instancji DVR.

Przykładowy proces uruchamiania rekordu

Przykładowy proces uruchamiania rekordu.

Rysunek 12. Przebieg rozpoczęcia zapisu

  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. 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. }
          }
        }
    };
    
  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

Tuner HAL podąża za HIDL i definiuje interfejs pomiędzy platformą a sprzętem dostawcy. Dostawcy używają interfejsu do implementacji Tuner HAL, a platforma używa go do komunikacji z implementacją Tuner HAL.

Moduły

Tuner HAL 1.0

Moduły Podstawowe sterowanie Sterowanie specyficzne dla modułu pliki HAL
ITuner Nie dotyczy frontend(open, getIds, getInfo) , openDemux , openDescrambler , openLnb , getDemuxCaps ITuner.hal
IFrontend setCallback , getStatus , close tune , stopTune , scan , stopScan , setLnb IFrontend.hal
IFrontendCallback.hal
IDemux close setFrontendDataSource , openFilter , openDvr , getAvSyncHwId , getAvSyncTime , connect / disconnectCiCam IDemux.hal
IDvr close , start , stop , configure attach/detachFilters , flush , getQueueDesc IDvr.hal
IDvrCallback.hal
IFilter close , start , stop , configure , getId flush , getQueueDesc , releaseAvHandle , setDataSource IFilter.hal
IFilterCallback.hal
ILnb close , setCallback setVoltage , setTone , setSatellitePosition , sendDiseqcMessage ILnb.hal
ILnbCallback.hal
IDescrambler close setDemuxSource , setKeyToken , addPid , removePid IDescrambler.hal

Tuner HAL 1.1 (pochodzący z Tunera HAL 1.0)

Moduły Podstawowe sterowanie Sterowanie specyficzne dla modułu pliki HAL
ITuner Nie dotyczy getFrontendDtmbCapabilities @1.1::ITuner.hal
IFrontend tune_1_1 , scan_1_1 , getStatusExt1_1 link/unlinkCiCam @1.1::IFrontend.hal
@1.1::IFrontendCallback.hal
IFilter getStatusExt1_1 configureIpCid , configureAvStreamType , getAvSharedHandle , configureMonitorEvent @1.1::IFilter.hal
@1.1::IFilterCallback.hal

Schemat blokowy interakcji pomiędzy modułami Tunera HAL.

Rysunek 13. Schemat interakcji pomiędzy modułami Tunera HAL

Połączenie filtra

Tuner HAL obsługuje łączenie filtrów, dzięki czemu filtry można łączyć z innymi filtrami w wielu warstwach. Filtry działają zgodnie z poniższymi zasadami.

  • Filtry są połączone w formie drzewa, ścieżka zamykania nie jest dozwolona.
  • Węzeł główny to demux.
  • Filtry działają niezależnie.
  • Wszystkie filtry zaczynają pobierać dane.
  • Łącznik filtra spłukuje się na ostatnim filtrze.

Poniższy blok kodu i rysunek 14 ilustrują przykład filtrowania wielu warstw.

demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
        ipFilter = ITuner.openFilter(<IP, ..>)
        mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter1.setDataSource(<ipFilter>)
        mmtpFilter2.setDataSource(<ipFilter>)
}

Schemat przykładowego podłączenia filtra.

Rysunek 14. Schemat blokowy połączenia filtra dla wielu warstw

Menedżer zasobów tunera

Przed Tuner Resource Manager (TRM) przełączanie między dwiema aplikacjami wymagało tego samego sprzętu Tuner. TV Input Framework (TIF) korzystał z mechanizmu „ kto pierwszy uzyska wygraną”, co oznacza, że ​​aplikacja, która jako pierwsza otrzyma zasób, zachowa go. Jednak mechanizm ten może nie być idealny w niektórych skomplikowanych przypadkach użycia.

TRM działa jako usługa systemowa do zarządzania zasobami sprzętowymi Tuner, TVInput i CAS dla aplikacji. TRM korzysta z mechanizmu „wygrania na pierwszym planie”, który oblicza priorytet aplikacji na podstawie statusu aplikacji na pierwszym planie lub w tle oraz typu przypadku użycia. TRM przyznaje lub odwołuje zasób w oparciu o priorytet. TRM centralizuje zarządzanie zasobami ATV dla transmisji, OTT i DVR.

Interfejs TRM

TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl dla platformy Tuner, MediaCas i TvInputHardwareManager w celu rejestrowania, żądania lub zwalniania zasobów.

Poniżej wymieniono interfejsy do zarządzania klientami.

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

Poniżej wymieniono interfejsy umożliwiające żądanie i zwolnienie zasobów.

  • requestFrontend(TunerFrontendRequest request, int[] frontendHandle) / releaseFrontend
  • requestDemux(TunerDemuxRequest request, int[] demuxHandle) / releaseDemux
  • requestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle) / releaseDescrambler
  • requestCasSession(CasSessionRequest request, int[] casSessionHandle) / releaseCasSession
  • requestLnb(TunerLnbRequest request, int[] lnbHandle) / releaseLnb

Klasy klientów i żądań są wymienione poniżej.

  • ResourceClientProfile
  • ResourcesReclaimListener
  • TunerFrontendRequest
  • TunerDemuxRequest
  • TunerDescramblerRequest
  • CasSessionRequest
  • TunerLnbRequest

Priorytet klienta

TRM oblicza priorytet klienta na podstawie parametrów z profilu klienta i wartości priorytetu z pliku konfiguracyjnego. Priorytet może być również aktualizowany przez dowolną wartość priorytetu otrzymaną od klienta.

Parametry w profilu klienta

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

mUseCase wskazuje przypadek użycia sesji. Poniżej wymieniono predefiniowane przypadki użycia.

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

Plik konfiguracyjny

Domyślny plik konfiguracyjny

Domyślny plik konfiguracyjny poniżej zapewnia wartości priorytetów dla wstępnie zdefiniowanych przypadków użycia. Użytkownicy mogą zmieniać wartości za pomocą dostosowanego pliku konfiguracyjnego .

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

Dostawcy mogą dostosować plik konfiguracyjny /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Ten plik służy do dodawania, usuwania lub aktualizowania typów przypadków użycia i wartości priorytetów przypadków użycia. Dostosowany plik może wykorzystywać jako szablon platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml .

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

Dowolna wartość priorytetu i wartość ładna

TRM udostępnia klientowi updateClientPriority możliwość aktualizacji dowolnej wartości priorytetu i wartości ładnej. Dowolna wartość priorytetu zastępuje wartość priorytetu obliczoną na podstawie typu przypadku użycia i identyfikatora sesji.

Wartość nice wskazuje, jak łagodne jest zachowanie klienta, gdy jest on w konflikcie z innym klientem. Wartość nice zmniejsza wartość priorytetu klienta przed porównaniem jego wartości priorytetu z klientem wymagającym.

Mechanizm odzyskiwania

Poniższy diagram przedstawia sposób odzyskiwania i przydzielania zasobów w przypadku wystąpienia konfliktu zasobów.

Schemat procesu mechanizmu odzyskiwania.

Rysunek 15. Schemat mechanizmu odzyskiwania konfliktu pomiędzy zasobami Tunera