Platforma tunera

W przypadku Androida 11 lub nowszego do odtwarzania treści A/V można użyć platformy Android Tuner. Platforma wykorzystuje potok sprzętowy od dostawców, dzięki czemu jest odpowiedni zarówno dla słabszych, jak i zaawansowanych układów SOC. Platforma zapewnia bezpieczny sposób dostarczania treści audiowizualnych chronionych przez zaufane środowisko wykonawcze (TEE) i bezpieczną ścieżkę multimediów (SMP), dzięki czemu można jej używać w bardzo ograniczonym środowisku ochrony treści.

Ustandaryzowane interfejs między Tunerem a CAS zapewnia szybszą integrację między dostawcami tunerów i CAS. Interfejs tunera współpracuje z usługami MediaCodec i AudioTrack, co pozwala stworzyć uniwersalne rozwiązanie dla Androida TV. Interfejs tunera obsługuje zarówno telewizję cyfrową, jak i telewizję analogową na podstawie głównych standardów telewizyjnych.

Komponenty

W Androidzie 11 3 komponenty są specjalnie zaprojektowane na potrzeby platformy telewizyjnej.

  • Tuner HAL: interfejs między platformą a dostawcami
  • Interfejs API Tuner SDK: interfejs między platformą a aplikacjami.
  • Tuner Resource Manager (TRM): koordynuje zasoby HW Tuner.

W Androidzie 11 ulepszone są te komponenty.

  • CAS V2
  • TvInputService lub usługa wejścia TV (TIS)
  • TvInputManagerService lub usługa menedżera wejścia TV (TIMS)
  • MediaCodec lub kodek multimediów
  • AudioTrack lub ścieżka audio
  • MediaResourceManager lub menedżer zasobów medialnych (MRM)

Schemat blokowy komponentów platformy tunera.

Rysunek 1. Interakcje między komponentami Androida TV

Funkcje

Frontend obsługuje wymienione poniżej standardy DTV.

  • ATSC
  • protokół ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Analogowe

Frontend w Androidzie 12 z Tuner HAL 1.1 lub nowszym obsługuje standard DTV.

  • DTMB

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

  • Strumień transportu
  • Protokół MPEG Media Transport Protocol (MMTP)
  • Protokół internetowy (IP)
  • Typ długości wartości (TLV)
  • Protokół ATSC warstwy łącza (ALP)

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

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

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

  • Skanuj
  • Na żywo
  • Odtwarzanie
  • Nagraj

Tuner, MediaCodecAudioTrack obsługują podane niżej tryby przepływu danych.

  • Dane ES z czystym buforem pamięci
  • Payload ES z bezpiecznym uchwytem pamięci
  • Widok otoczenia

Ogólny projekt

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

  • Opisują, czego platforma oczekuje od dostawcy i w jaki sposób może to zrobić.
  • Umożliwia wyeksportowanie do platformy funkcji frontendu, demuxowania i dekodera za pomocą interfejsów IFrontend, IDemux, IDescrambler, IFilter, IDvr i ILnb.
  • Zawiera funkcje integracji interfejsu HAL Tuner z innymi komponentami platformy, takimi jak MediaCodec i AudioTrack.

Zostanie utworzona klasa Java tunera i klasa natywna.

  • Interfejs Tuner Java API umożliwia aplikacjom dostęp do interfejsu HAL Tunera za pomocą publicznych interfejsów API.
  • Klasa natywnych umożliwia kontrolę uprawnień i obsługę dużych ilości danych dotyczących nagrywania lub odtwarzania za pomocą interfejsu HAL tunera.
  • Natywczy moduł tunera stanowi łącznik między klasą Java Tunera a interfejsem HAL Tunera.

Zostanie utworzona klasa TRM.

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

Funkcje Media CAS i CAS HAL zostały uzupełnione o poniższe funkcje.

  • Otwiera sesje CAS na potrzeby różnych zastosowań i algorytmów.
  • Obsługuje dynamiczne systemy CAS, takie jak usuwanie i wstawianie CICAM.
  • Integracja z HAL Tuner zapewnia tokeny kluczy.

MediaCodec i AudioTrack zostały wzbogacone o te funkcje:

  • Odczytuje zabezpieczoną pamięć audiowizualną jako dane wejściowe.
  • Konfiguracja sprzętowego synchronizatora audio-wideo w przypadku odtwarzania tunelowanego.
  • Skonfigurowano obsługę ES_payload i trybu przepuszczania.

Ogólny projekt interfejsu Tuner HAL.

Rysunek 2. Schemat komponentów w Tuner HAL

Ogólny przepływ pracy

Na poniższych schematach przedstawiono sekwencje połączeń podczas odtwarzania transmisji na żywo.

Konfiguracja

Konfiguracja sekwencji odtwarzania transmisji na żywo.

Rysunek 3. Sekwencja konfiguracji odtwarzania transmisji na żywo

Obsługa sprzętu audiowizualnego

Schemat obsługi obrazu i wideo podczas odtwarzania transmisji na żywo.

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

Postępowanie z treściami zaszyfrowanymi

Obsługa zakodowanych treści w przypadku odtwarzania transmisji na żywo.

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

Przetwarzanie danych audio-wizualnych

Schemat przetwarzania danych audiowizualnych na potrzeby odtwarzania transmisji na żywo.

Rysunek 6. Przetwarzanie obrazu i dźwięku do odtwarzania transmisji na żywo

Interfejs API Tuner SDK

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

Diagram przepływu interfejsu API Tuner SDK.

Rysunek 7. Interakcje z interfejsem Tuner SDK API

Wersje

Od Androida 12 interfejs API pakietu Tuner SDK obsługuje nową funkcję w interfejsie Tuner HAL 1.1, który jest kompatybilny wstecz z wersją Tuner 1.0.

Użyj poniższego interfejsu API, aby sprawdzić uruchomioną wersję HAL.

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

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

Pakiety

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

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

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

Rysunek 8. Pakiety interfejsu API Tuner SDK

Android.media.tv.tuner

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

  • tuner(): inicjuje instancję tunera przez określenie parametrów useCase i sessionId.
  • tune(): pozyskuje zasób frontendu i dostrajanie przez określenie parametru FrontendSetting.
  • openFilter(): pobiera instancję filtra przez określenie typu filtra.
  • openDvrRecorder(): pozyskuje instancję nagrywania, określając rozmiar bufora.
  • openDvrPlayback(): uzyskuje instancję odtwarzania przez określenie rozmiaru bufora.
  • openDescrambler(): pobiera instancję deszyfratora.
  • openLnb(): pozyskuje wewnętrzną instancję LNB.
  • openLnbByName(): pobiera zewnętrzną instancję LNB.
  • openTimeFilter(): pobiera instancję filtra czasowego.

Pakiet Tuner udostępnia funkcje, które nie są dostępne w pakietach filtrów, DVR i interfejsu. Ich listę znajdziesz poniżej.

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

Android.media.tv.tuner.frontend

Pakiet interfejsu zawiera kolekcje ustawień, informacji, stanów, zdarzeń i możliwości dotyczących interfejsu.

Zajęcia

FrontendSettings jest określany dla różnych standardów DTV według poniższych klas.

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

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

  • DtmbFrontendSettings

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

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

Od Androida 12 z tunerem HAL 1.1 lub nowszym obsługiwany jest standard DTV.

  • DtmbFrontendCapabilities

FrontendInfo pobiera informacje o frontendzie. FrontendStatus pobiera bieżący stan frontendu. OnTuneEventListener nasłuchuje zdarzeń we frontendzie. Aplikacja TIS używa usługi ScanCallback do przetwarzania wiadomości z skanowania z frontendu.

Skanowanie kanałów

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

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

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

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

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

Podczas strojenia możesz wybrać stopTune() lub close(), aby wstrzymać lub zakończyć połączenie Tuner.tune.

Tuner.scan(AUTO_SCAN)

Jeśli TIS nie ma wystarczającej ilości informacji do użycia Tuner.tune, ale ma listę częstotliwości i typ standardu (np. DVB T/C/S), zalecamy użycie Tuner.scan(AUTO_SCAN).

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

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

  • Jeśli sygnał jest zablokowany, HAL zgłasza skanowanie wiadomości LOCKED. HAL może też przekazywać inne wiadomości skanowania, aby dostarczyć dodatkowych informacji o sygnale.

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

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

  • TIS powtarza te działania, dopóki nie wyczerpie się limit ustawień na częstotliwość.

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

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

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

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

Tuner.scan(BLIND_SCAN)

Jeśli TIS nie ma listy częstotliwości, a HAL dostawcy może wyszukać częstotliwość określonego przez użytkownika frontendu w celu pobrania zasobu frontendu, zalecamy użycie metody Tuner.scan(BLIND_SCAN).

  • TIS używa Tuner.scan(BLIND_SCAN). Częstotliwość początkową można określić w polu FrontendSettings, ale TIS ignoruje inne ustawienia w polu FrontendSettings.
  • Jeśli sygnał jest zablokowany, HAL zgłasza skanowanie LOCKED.
  • TIS używa Frontend.getStatus do zbierania niezbędnych informacji.
  • TIS ponownie wywołuje Tuner.scan, aby kontynuować skanowanie. (wartość FrontendSettings jest ignorowana).
  • TIS powtarza powyższe działania, aż wszystkie ustawienia częstotliwości zostaną wyczerpane. HAL zwiększa częstotliwość. Z TIS nie trzeba nic robić. Raporty HALPROGRESS

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

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

Schemat blokowy procesu skanowania TIS

Rysunek 9. Schemat procesu skanowania TIS

Android.media.tv.tuner.filter

Pakiet filtrów to zbiór operacji filtra wraz z konfiguracją, ustawieniami, wywołaniami zwrotnymi i zdarzeniami. Pakiet zawiera te operacje: Pełną listę operacji znajdziesz w źródle kodu Androida.

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

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

FilterConfiguration pochodzi z klas wymienionych poniżej. Konfiguracje dotyczą głównego typu filtra i określają, którego protokołu używa filtr do wyodrębniania danych.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

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

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

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

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

Od Androida 12 z tunerem HAL 1.1 lub nowszym obsługiwane są te zdarzenia.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Format zdarzeń i danych z filtra
Typ filtra Flagi Wydarzenia Operacja na danych Format danych
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Wymagane:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i wewnętrznym harmonogramem uruchom
Filter.read(buffer, offset, adjustedSize) co najmniej 1 raz.

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

Opcjonalnie:
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
Wymagane:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z harmonogramem wydarzenia i harmonogramem wewnętrznym uruchom
Filter.read(buffer, offset, adjustedSize) co najmniej raz.

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

Opcjonalnie:
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
Zgodnie z wydarzeniem i wewnętrznym harmonogramem uruchom
Filter.read(buffer, offset, adjustedSize) co najmniej 1 raz.

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

Opcjonalnie:
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.
TS.TS
Nie dotyczy Wymagane:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z harmonogramem wydarzenia i harmonogramem wewnętrznym uruchom
Filter.read(buffer, offset, adjustedSize) co najmniej raz.

Dane są kopiowane z MQ HAL do bufora klienta.
Odfiltrowane ts z nagłówkiem ts
jest wypełnione w FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Klient może rozpocząć MediaCodec po otrzymaniu DemuxFilterStatus::DATA_READY.
Po otrzymaniu wiadomości DemuxFilterStatus::DATA_OVERFLOW klient może zadzwonić pod numer Filter.flush.
Nie dotyczy
isPassthrough:
false
Obowiązkowe:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Opcjonalnie:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Aby użyć interfejsu MediaCodec:
for i=0; i<n; i++
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))
ES lub częściowe dane ES w pamięci ION.
TS.PCR
IP.NTP
ALP.PTP
Nie dotyczy Obowiązkowe: nie dotyczy
Opcjonalnie: nie dotyczy
Nie dotyczy Nie dotyczy
TS.RECORD Nie dotyczy Wymagany:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

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


W przypadku nagranych treści zgodnie z RecordStatus::* i wewnętrznym harmonogramem wykonaj jedną z tych czynności:
  • Uruchom DvrRecord.write(adustedSize)co najmniej raz w chmurze.
    Dane są przenoszone z MQ HAL do pamięci masowej.
  • Uruchom DvrRecord.write(buffer, adustedSize)kilka razy, aby przepuścić dane przez bufor.
    Dane są kopiowane z MQ HAL do bufora klienta.
Dane indeksu: są przenoszone w ładunku zdarzenia.

W przypadku treści nagranych: strumień TS zmiksowany w FMQ.
TS.TEMI Nie dotyczy Wymagany:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
Nie dotyczy
MMTP.MMTP Nie dotyczy Wymagane:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z harmonogramem wydarzenia i harmonogramem wewnętrznym uruchom
Filter.read(buffer, offset, adjustedSize) co najmniej raz.

Dane są kopiowane z MQ HAL do bufora klienta.
Odfiltrowana wartość mmtp z nagłówkiem mmtp
jest wypełniona FMQ.
MMTP.RECORD Nie dotyczy Wymagany:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Dane indeksu: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


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

W przypadku treści nagranych: zmiksowany strumień nagrania wypełniony w FMQ.

Jeśli źródłem filtra do rejestrowania jest TLV.TLVIP.IP z przekazywaniem, nagrany strumień będzie miał nagłówek TLV i nagłówek IP.
MMTP.DOWNLOAD Nie dotyczy Wymagany:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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

Dane są kopiowane z MQ HAL do bufora klienta.
Pole „Pobierz pakiet” jest wypełnione w FMQ przez inny pakiet do pobrania adresu IP.
IP.IP_PAYLOAD Nie dotyczy Obowiązkowe:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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

Dane są kopiowane z MQ HAL do bufora klienta.
Pakiet danych IP jest wypełniany w FMQ przez inny pakiet danych IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Odfiltrowano pliki danych ze strumieniem podrzędnym protokołu. Odfiltrowano je. Następny filtr w łańcuchu filtrów. Nie dotyczy
isPassthrough:
false
Wymagane:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Zalecane:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Zgodnie z wydarzeniem i wewnętrznym harmonogramem uruchom
Filter.read(buffer, offset, adjustedSize) co najmniej 1 raz.

Dane są kopiowane z MQ HAL do bufora klienta.
Filtrowany podstrumień protokołu z nagłówkiem protokołu jest wypełniany w FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
Nie dotyczy Opcjonalnie:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Odfiltrowany ładunek protokołu przekazuje dane następnemu filtrowi w łańcuchu filtrów. Nie dotyczy
Przykładowy proces z użyciem filtra do utworzenia wskaźnika PSI/SI

Przykładowy przepływ pracy z filtrem 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. Przetwarzam SectionEvent.

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

Przykładowy proces użycia obiektu MediaEvent z filtra.

Rysunek 11. Procedura użycia obiektu MediaEvent z filtra

  1. Otwórz, skonfiguruj i uruchom filtry audio/wideo.
  2. Przetwórz MediaEvent.
  3. Odbierz MediaEvent.
  4. Umieść blok liniowy w kolejce do pozycji codec.
  5. Po wykorzystaniu danych zwalniaj uchwyt A/V.

Android.media.tv.tuner.dvr

DvrRecorder udostępnia te metody nagrywania.

  • configure
  • attachFilter
  • detachFilter
  • start
  • flush
  • stop
  • setFileDescriptor
  • write

DvrPlayback udostępnia te metody odtwarzania.

  • configure
  • start
  • flush
  • stop
  • setFileDescriptor
  • read

Usługa DvrSettings jest używana do konfigurowania usług DvrRecorder i DvrPlayback. OnPlaybackStatusChangedListener i OnRecordStatusChangedListener służą do zgłaszania stanu instancji DVR.

Przykładowy proces rozpoczynania nagrywania

Przykładowy proces rozpoczynania nagrywania.

Rysunek 12. Proces rozpoczynania 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. 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 określa interfejs między frameworkem a sprzętem dostawcy. Dostawcy używają tego interfejsu do implementacji Tunera HAL, a platforma używa go do komunikacji z implementacją Tunera HAL.

Moduły

Tuner HAL 1.0

Moduły Podstawowe funkcje sterowania Ustawienia dotyczące poszczególnych modułów Pliki HAL
ITuner Nie dotyczy frontend(open, getIds, getInfo), openDemux, openDescrambler, openLnb, getDemuxCaps ITuner.hal
IFrontend setCallback, getStatus, close tune, stopTune, scan, stopScan, setLnb IFrontend.hal
IFrontendCallback.hal
IDemux close setFrontendDataSource, openFilter, openDvr, getAvSyncHwId, getAvSyncTime, connect / disconnectCiCam IDemux.hal
IDvr close, start, stop, configure attach/detachFilters, flush, getQueueDesc IDvr.hal
IDvrCallback.hal
IFilter close, start, stop, configure, getId flush, getQueueDesc, releaseAvHandle, setDataSource IFilter.hal
IFilterCallback.hal
ILnb close, setCallback setVoltage, setTone, setSatellitePosition, sendDiseqcMessage ILnb.hal
ILnbCallback.hal
IDescrambler close setDemuxSource, setKeyToken, addPid, removePid IDescrambler.hal

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

Moduły Podstawowe funkcje sterowania Ustawienia dotyczące poszczególnych modułów Pliki HAL
ITuner Nie dotyczy getFrontendDtmbCapabilities @1.1::ITuner.hal
IFrontend tune_1_1, scan_1_1, getStatusExt1_1 link/unlinkCiCam @1.1::IFrontend.hal
@1.1::IFrontendCallback.hal
IFilter getStatusExt1_1 configureIpCid, configureAvStreamType, getAvSharedHandle, configureMonitorEvent @1.1::IFilter.hal
@1.1::IFilterCallback.hal

Schemat blokowy interakcji między modułami HAL tunera.

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

Połączenie filtrów

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

  • Filtry są połączone w drzewo, więc nie można stosować ścieżki zamykania.
  • Węzeł główny jest demuxem.
  • Filtry działają niezależnie.
  • Wszystkie filtry zaczynają pobierać dane.
  • Połączenie filtra wyczyszczone jest przy ostatnim filtrze.

Blok kodu poniżej i na rys. 14 ilustrują przykład filtrowania wielu warstw.

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

Schemat przedstawiający przykład połączenia filtrów.

Rysunek 14. Schemat działania połączenia filtra w przypadku wielu warstw

Menedżer zasobów tunera

Przed wprowadzeniem usługi Tuner Resource Manager (TRM) przełączanie się między 2 aplikacjami wymagało korzystania z tego samego tunera. Platforma wprowadzania danych TV (TIF) korzystała z mechanizmu „pierwszego pozyskania”, co oznacza, że zasób zostanie zachowany w przypadku aplikacji, która otrzyma zasób jako pierwszy. Ten mechanizm może jednak nie być odpowiedni w przypadku niektórych skomplikowanych przypadków użycia.

TRM działa jako usługa systemowa zarządzająca zasobami sprzętowymi tunera, TVInput i CAS na potrzeby aplikacji. TRM korzysta z mechanizmu „wygrywania na pierwszym planie”, który oblicza priorytet aplikacji na podstawie jej stanu (czy jest na pierwszym planie czy w tle) oraz typu przypadku użycia. TRM przyznaje lub anuluje zasób na podstawie priorytetu. TRM centralizuje zasoby ATV na potrzeby transmisji, OTT i nagrywarki cyfrowej.

Interfejs TRM

TRM udostępnia interfejsy AIDL w ITunerResourceManager.aidl dla frameworku Tuner, MediaCasTvInputHardwareManager w celu rejestrowania, żądania lub uwalniania zasobów.

Poniżej znajdziesz interfejsy zarządzania klientami.

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

Poniżej znajdziesz interfejsy żądania i zwalniania zasobów.

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

Poniżej znajdziesz klasy klientów i żądań.

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

Priorytet klienta

TRM oblicza priorytet klienta, korzystając z parametrów z profilu klienta i wartości priorytetu z pliku konfiguracji. Priorytet może też być aktualizowany za pomocą dowolnej wartości priorytetu ustalonej przez klienta.

Parametry w profilu klienta

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

mUseCase wskazuje przypadek użycia sesji. Poniżej znajdziesz listę wstępnie zdefiniowanych zastosowań.

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

Plik konfiguracji

Domyślny plik konfiguracji

Poniżej znajduje się domyślny plik konfiguracji zawierający wartości priorytetów dla zdefiniowanych wstępnie przypadków użycia. Użytkownicy mogą zmieniać wartości za pomocą spersonalizowanego pliku konfiguracji.

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

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

Przykładem zastosowania dla nowego dostawcy jest VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]. Powinien mieć format platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd.

Dowolna wartość priorytetu i wartość ładna

TRM udostępnia klientowi element updateClientPriority, który umożliwia mu zaktualizowanie dowolnej wartości priorytetu i wartości wyświetlanej. Dowolna wartość priorytetu zastępuje wartość priorytetu obliczoną na podstawie typu przypadku użycia i identyfikatora sesji.

Wartość nice wskazuje, jak łagodne jest zachowanie klienta, gdy wchodzi on w konflikt z innym klientem. „Dobra wartość” zmniejsza wartość priorytetu klienta, zanim jego wartość zostanie porównana z klientem, który jest bardziej wymagający.

Mechanizm odzyskiwania

Poniższy diagram przedstawia sposób odzyskiwania i przypisywania zasobów w przypadku konfliktu zasobów.

Schemat procesu odzyskiwania.

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