Ramy tunera

W przypadku systemu Android 11 lub nowszego możesz użyć platformy Android Tuner do dostarczania treści audio-wideo. Framework wykorzystuje potok sprzętowy od dostawców, dzięki czemu jest odpowiedni zarówno dla low-end, jak i high-end SoC. Struktura zapewnia bezpieczny sposób dostarczania treści audio-wideo chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę medialną (SMP), umożliwiając korzystanie z niej w wysoce ograniczonym środowisku ochrony treści.

Standaryzowany interfejs między Tunerem a Android CAS zapewnia szybszą integrację między dostawcami Tunera i dostawcami 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 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 między platformą a dostawcami
  • Tuner SDK API: interfejs między platformą a aplikacjami
  • Menedżer zasobów tunera (TRM): koordynuje zasoby sprzętowe tunera

W systemie Android 11 udoskonalono następujące składniki.

  • CAS V2
  • TvInputService lub usługa wprowadzania TV (TIS)
  • TvInputManagerService lub TV Input Manager Service (TIMS)
  • MediaCodec lub kodek mediów
  • AudioTrack lub ścieżka audio
  • MediaResourceManager lub menedżer zasobów multimedialnych (MRM)

Schemat przepływu składników frameworka Tuner.

Rysunek 1. Interakcje mię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 Tuner 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 mediów
  • Wyczyść ścieżkę mediów
  • Bezpieczny zapis lokalny
  • Bezpieczne odtwarzanie lokalne

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

  • Skanowanie
  • Relacja 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
  • ES ładunek z bezpiecznym uchwytem pamięci
  • Przejść przez

Ogólny projekt

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

  • Opisuje, czego framework oczekuje od dostawcy i jak dostawca może to zrobić.
  • Eksportuje funkcje frontendu, demuksu i deszyfratora do platformy za pośrednictwem IFrontend , IDemux , IDescrambler , IFilter , IDvr i ILnb .
  • Zawiera funkcje integrujące Tuner HAL z innymi komponentami frameworka, takimi jak MediaCodec i AudioTrack .

Tworzona jest klasa Tuner Java i klasa natywna.

  • Tuner Java API 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 nagrywania lub odtwarzania za pomocą Tuner HAL.
  • Moduł Native Tuner jest pomostem między klasą Tuner Java i Tuner HAL.

Utworzona zostaje 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 w celu odzyskania niewystarczających zasobów z aplikacji. Domyślną zasadą jest wygrana na pierwszym planie.

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 wkładanie CICAM.
  • Integruje się z Tuner HAL, dostarczając tokeny klucza.

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

  • Zajmuje bezpieczną pamięć A/V jako wejście treści.
  • Skonfigurowany do sprzętowej synchronizacji A/V podczas odtwarzania tunelowego.
  • Skonfigurowana obsługa trybu ES_payload i passthrough.

Ogólny projekt tunera HAL.

Rysunek 2. Schemat komponentów w ramach Tuner HAL

Ogólny przepływ pracy

Poniższe diagramy ilustrują sekwencje połączeń do odtwarzania transmisji na żywo.

Ustawiać

Sekwencja konfiguracji schematu odtwarzania transmisji na żywo.

Rysunek 3. Sekwencja konfiguracji do odtwarzania transmisji na żywo

Obsługa A/V

Obsługa A/V dla schematu odtwarzania transmisji na żywo.

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

Obsługa zaszyfrowanej treści

Obsługa zaszyfrowanej zawartości na potrzeby schematu odtwarzania transmisji na żywo.

Rysunek 5. Obsługa zaszyfrowanej zawartości do odtwarzania transmisji na żywo

Przetwarzanie danych audio/wideo

Przetwarzaj dane A/V dla schematu odtwarzania transmisji na żywo.

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

Tuner SDK API

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

Schemat blokowy interfejsu Tuner SDK API.

Rysunek 7. Interakcje z Tuner SDK API

Wersje

Od systemu Android 12 interfejs Tuner SDK API obsługuje nową funkcję w Tuner HAL 1.1, która jest zgodną z poprzednimi wersją uaktualnienia wersji Tuner 1.0.

Użyj następującego interfejsu API, aby sprawdzić działającą wersję warstwy HAL.

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

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

Pakiety

Tuner SDK API 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 przepływu pakietów Tuner SDK API.

Rysunek 8. Pakiety Tuner SDK API

Android.media.tv.tuner

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

  • tuner() : Inicjuje instancję Tuner przez określenie parametrów useCase i sessionId .
  • tune() : Pozyskuje zasób frontendu i dostraja poprzez określenie parametru FrontendSetting .
  • openFilter() : Pobiera instancję filtra przez określenie typu filtra.
  • openDvrRecorder() : Pobiera instancję nagrywania przez określenie rozmiaru bufora.
  • openDvrPlayback() : Pobiera instancję odtwarzania przez 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 frontend. Funkcjonalności są wymienione poniżej.

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

Android.media.tv.tuner.frontend

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

Klasy

FrontendSettings wywodzi się z różnych standardów DTV według poniższych klas.

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

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

  • DtmbFrontendSettings

FrontendCapabilities jest wyprowadzany dla różnych standardów DTV według poniższych klas.

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

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

  • DtmbFrontendCapabilities

FrontendInfo pobiera informacje z frontendu. FrontendStatus pobiera aktualny stan frontendu. OnTuneEventListener nasłuchuje zdarzeń w interfejsie. Aplikacja TIS wykorzystuje ScanCallback do przetwarzania komunikatów 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 mają dostęp. TIS może używać Tuner.tune , Tuner.scan(BLIND_SCAN) lub Tuner.scan(AUTO_SCAN) do ukończenia skanowania kanałów.

Jeśli TIS ma dokładne informacje o dostarczeniu sygnału, takie jak częstotliwość, standard (na przykład T/T2, S/S2) i dodatkowe niezbędne informacje (na przykład PLD ID), wówczas jako szybszą opcję zaleca się Tuner.tune .

Gdy użytkownik wywołuje Tuner.tune , następują następujące akcje:

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

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

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

Tuner.scan(AUTO_SCAN)

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

Gdy użytkownik wywołuje Tuner.scan(AUTO_SCAN) , następują następujące akcje:

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

  • HAL zgłasza komunikaty skanowania LOCKED , jeśli sygnał jest zablokowany. HAL może również zgłaszać inne komunikaty skanowania w celu dostarczenia dodatkowych informacji o sygnale.

  • TIS używa Frontend.getStatus do zbierania niezbędnych informacji.

  • TIS wywołuje Tuner.scan w celu uzyskania warstwy HAL, aby 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 HAL używa FrontendSettings do jednorazowego skanowania i wysyła komunikat END , aby wskazać, że operacja skanowania została zakończona.

  • TIS powtarza powyższe czynności, aż wszystkie ustawienia częstotliwości zostaną wyczerpane.

  • HAL wysyła komunikat 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.

Tuner.scan(BLIND_SCAN)

Jeśli TIS nie ma listy częstotliwości, a HAL dostawcy może wyszukać częstotliwość określonego przez użytkownika frontonu, aby uzyskać zasób frontonu, 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 używa Frontend.getStatus do zbierania niezbędnych informacji.
  • TIS ponownie wywołuje Tuner.scan , aby kontynuować skanowanie. ( FrontendSettings jest ignorowany.)
  • TIS powtarza powyższe czynności, aż wszystkie ustawienia częstotliwości zostaną wyczerpane. HAL zwiększa częstotliwość bez konieczności podejmowania działań przez TIS. HAL raportuje PROGRESS .

TIS ponownie wywołuje Tuner.scan(AUTO_SCAN) aż do wyczerpania wszystkich częstotliwości. HAL raportuje 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 przepływu procesu skanowania TIS.

Rysunek 9. Schemat przepływu skanowania TIS

Android.media.tv.tuner.filtr

Pakiet filtrów to zbiór operacji filtrowania wraz z konfiguracją, ustawieniami, wywołaniami zwrotnymi i zdarzeniami. Pakiet zawiera poniższe operacje. Pełną listę operacji można znaleźć w kodzie źródłowym systemu Android.

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

Pełna lista znajduje się w kodzie źródłowym Androida.

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

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Ustawienia pochodzą z poniższych klas. Ustawienia dotyczą podtypu filtru i określają, jakie rodzaje danych filtr może wykluczyć.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent wywodzi się z poniższych klas, aby raportować zdarzenia dla różnych rodzajów danych.

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

Od systemu Android 12 z Tuner 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 wewnętrznym harmonogramem, biegnij
Filter.read(buffer, offset, adjustedSize) raz lub więcej razy.

Dane są kopiowane z MQ warstwy 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 warstwy 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 wewnętrznym harmonogramem, biegnij
Filter.read(buffer, offset, adjustedSize) raz lub więcej razy.

Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Jedno zmontowane opakowanie PES jest wypełniane w FMQ innym opakowaniem 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 warstwy 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 wewnętrznym harmonogramem, biegnij
Filter.read(buffer, offset, adjustedSize) raz lub więcej razy.

Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Jedno zmontowane opakowanie MFU jest wypełniane w FMQ innym opakowaniem 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 wewnętrznym harmonogramem, biegnij
Filter.read(buffer, offset, adjustedSize) raz lub więcej razy.

Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Odfiltrowano ts z nagłówkiem ts
jest wypełnione w 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ć Direct Audio AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
ES lub częściowe dane ES w pamięci ION.
TS.PCR
IP.NTP
ALP.PTP
Nie dotyczy Obowiązkowe: nie dotyczy
Opcjonalnie: nie dotyczy
Nie dotyczy Nie dotyczy
TS.RECORD Nie dotyczy 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 nagranych treści , zgodnie z RecordStatus::* i wewnętrznym harmonogramem, wykonaj jedną z następujących czynności:
  • Uruchom DvrRecord.write(adustedSize) jeden lub więcej razy do magazynu.
    Dane są przesyłane z MQ HAL do magazynu.
  • Uruchom DvrRecord.write(buffer, adustedSize) raz lub więcej razy, aby zbuforować.
    Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Dla danych indeksowych: Przeniesiony w ładunku zdarzenia.

W przypadku nagranych treści: Strumień Muxed TS wypełniony w 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 wewnętrznym harmonogramem, biegnij
Filter.read(buffer, offset, adjustedSize) raz lub więcej razy.

Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Odfiltrowano mmtp z nagłówkiem mmtp
jest wypełnione w 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 nagranych 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 magazynu.
    Dane są przesyłane z MQ HAL do magazynu.
  • Uruchom DvrRecord.write(buffer, adjustedSize) raz lub więcej razy, aby zbuforować.
    Dane są kopiowane z MQ warstwy HAL do bufora klienta.
Dla danych indeksowych: Przeniesiony w ładunku zdarzenia.

W przypadku nagranych treści: Nagrany strumień zmultipleksowany wypełniony w FMQ.

Jeśli źródłem filtru do nagrywania jest TLV.TLV do IP.IP z przekazywaniem, nagrany 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 warstwy HAL do bufora klienta.
Pakiet pobierania jest wypełniany w FMQ innym pakietem pobierania 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 warstwy HAL do bufora klienta.
Pakiet danych IP jest wypełniany w FMQ innym pakietem danych 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 wewnętrznym harmonogramem, biegnij
Filter.read(buffer, offset, adjustedSize) raz 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 przesyła następny filtr w łańcuchu filtrów. Nie dotyczy
Przykładowy przepływ do użycia filtra do zbudowania PSI/SI

Przykładowy przepływ za pomocą filtra do budowania PSI/SI.

Rysunek 10. Przepływ do budowy 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 do użycia MediaEvent z filtra

Przykładowy przepływ do użycia MediaEvent z filtra.

Rysunek 11. Przepływ do użycia 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ą zużyte.

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 DvrRecorder i DvrPlayback . OnPlaybackStatusChangedListener i OnRecordStatusChangedListener służą do zgłaszania stanu instancji DVR.

Przykładowy przepływ do rozpoczęcia rekordu

Przykładowy przepływ rozpoczynający rekord.

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 jest zgodny z HIDL i definiuje interfejs mię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 Kontrolki 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 CiCam 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 Tuner HAL 1.0)

Moduły Podstawowe sterowanie Kontrolki 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 przepływu interakcji między modułami Tuner HAL.

Rysunek 13. Schemat interakcji między modułami Tuner HAL

Filtruj powiązanie

Tuner HAL obsługuje łączenie filtrów, dzięki czemu filtry można łączyć z innymi filtrami dla wielu warstw. Filtry są zgodne z poniższymi zasadami.

  • Filtry są połączone w formie drzewa, zamknięta ścieżka nie jest dozwolona.
  • Węzłem głównym jest demultipleks.
  • Filtry działają niezależnie.
  • Wszystkie filtry zaczynają pobierać dane.
  • Połączenie filtra przepł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 połączenia filtra.

Rysunek 14. Schemat przepływu 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 tunera. TV Input Framework (TIF) wykorzystywał mechanizm „wygrana „pierwszy do zdobycia”, co oznacza, że ​​aplikacja, która jako pierwsza otrzyma zasób, zachowa zasób. Jednak ten mechanizm 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 tunera, TVInput i CAS dla aplikacji. TRM wykorzystuje mechanizm „wygranej na pierwszym planie”, który oblicza priorytet aplikacji na podstawie stanu pierwszego lub drugiego planu aplikacji oraz typu przypadku użycia. TRM przyznaje lub odwołuje zasób na podstawie priorytetu. TRM centralizuje zarządzanie zasobami ATV dla transmisji, OTT i DVR.

Interfejs TRM

TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl dla struktury 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 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ń 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 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. Wstępnie zdefiniowane 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 konfiguracyjny

Domyślny plik konfiguracyjny

Domyślny plik konfiguracyjny poniżej zawiera wartości priorytetów dla predefiniowanych 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 używać jako szablonu platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml .

Na przykład nowy przypadek użycia 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 .

Arbitralna wartość priorytetu i dobra wartość

TRM zapewnia updateClientPriority w celu zaktualizowania dowolnej wartości priorytetu i ładnej wartości. Dowolna wartość priorytetu zastępuje wartość priorytetu obliczoną na podstawie typu przypadku użycia i identyfikatora sesji.

Miła wartość wskazuje, jak pobłażliwe jest zachowanie klienta, gdy jest w konflikcie z innym klientem. Wartość nice zmniejsza wartość priorytetu klienta, zanim jego wartość priorytetu zostanie porównana z klientem wymagającym.

Mechanizm odzyskiwania

Poniższy diagram pokazuje, w jaki sposób zasoby są odzyskiwane i przydzielane w przypadku wystąpienia konfliktu zasobów.

Schemat procesu mechanizmu odzysku.

Rysunek 15. Schemat mechanizmu odzyskiwania konfliktu między zasobami tunera