Фреймворк тюнера

В Android 11 и выше для доставки аудио- и видеоконтента можно использовать фреймворк Android Tuner. Фреймворк использует аппаратный конвейер от поставщиков, что делает его пригодным как для бюджетных, так и для высокопроизводительных SoC. Фреймворк обеспечивает безопасную доставку аудио- и видеоконтента, защищённого доверенной средой выполнения (TEE) и безопасным медиа-путем (SMP), что позволяет использовать его в строго ограниченной среде защиты контента.

Стандартизированный интерфейс между тюнером и Android CAS обеспечивает более быструю интеграцию между поставщиками тюнеров и поставщиками CAS. Интерфейс тюнера работает с MediaCodec и AudioTrack , создавая универсальное решение для Android TV. Интерфейс тюнера поддерживает как цифровое, так и аналоговое телевидение на основе основных стандартов вещания.

Компоненты

В Android 11 три компонента специально разработаны для телевизионной платформы.

  • Tuner HAL: интерфейс между фреймворком и поставщиками
  • Tuner SDK API: интерфейс между фреймворком и приложениями
  • Менеджер ресурсов тюнера (TRM): координирует ресурсы аппаратного обеспечения тюнера

В Android 11 были улучшены следующие компоненты.

  • КАС V2
  • TvInputService или Служба телевизионного ввода (TIS)
  • TvInputManagerService или служба диспетчера телевизионных входов (TIMS)
  • MediaCodec или медиакодек
  • AudioTrack или звуковая дорожка
  • MediaResourceManager или менеджер медиаресурсов (MRM)

Блок-схема компонентов инфраструктуры Tuner.

Рисунок 1. Взаимодействие между компонентами Android TV

Функции

Интерфейс поддерживает стандарты DTV, указанные ниже.

  • АТСК
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Аналоговый

Интерфейс Android 12 с Tuner HAL 1.1 или выше поддерживает стандарт DTV, указанный ниже.

  • ДТМБ

Demux поддерживает перечисленные ниже потоковые протоколы.

  • Транспортный поток (ТС)
  • Протокол передачи медиаданных MPEG (MMTP)
  • Интернет-протокол (IP)
  • Значение длины типа (TLV)
  • Протокол канального уровня ATSC (ALP)

Дескремблер поддерживает указанные ниже средства защиты контента.

  • Безопасный путь к медиа
  • Очистить путь для медиа
  • Безопасная локальная запись
  • Безопасное локальное воспроизведение

API тюнера поддерживают перечисленные ниже варианты использования.

  • Сканировать
  • Жить
  • Воспроизведение
  • Записывать

Tuner, MediaCodec и AudioTrack поддерживают указанные ниже режимы потока данных.

  • Полезная нагрузка ES с чистым буфером памяти
  • Полезная нагрузка ES с защищенным дескриптором памяти
  • Сквозной

Общий дизайн

Tuner HAL определяется между платформой Android и оборудованием поставщика.

  • Описывает, чего фреймворк ожидает от поставщика и как поставщик может это сделать.
  • Экспортирует функциональные возможности фронтенда, демультиплексора и дескремблера в фреймворк через интерфейсы IFrontend , IDemux , IDescrambler , IFilter , IDvr и ILnb .
  • Включает функции для интеграции Tuner HAL с другими компонентами фреймворка, такими как MediaCodec и AudioTrack .

Создаются класс Tuner Java и собственный класс.

  • Tuner Java API позволяет приложениям получать доступ к Tuner HAL через общедоступные API.
  • Собственный класс позволяет контролировать разрешения и обрабатывать большие объемы данных записи или воспроизведения с помощью тюнера HAL.
  • Модуль Native Tuner является мостом между классом Tuner Java и Tuner HAL.

Создан класс TRM.

  • Управляет ограниченными ресурсами тюнера, такими как Frontend, LNB, сеансы CAS и входное телевизионное устройство с телевизионного входа HAL.
  • Применяет правила для восстановления недостающих ресурсов у приложений. Правило по умолчанию — приоритет переднего плана.

Media CAS и CAS HAL улучшены за счет следующих функций.

  • Открывает сеансы CAS для различных применений и алгоритмов.
  • Поддерживает динамические системы CAS, такие как удаление и вставка CICAM.
  • Интегрируется с Tuner HAL, предоставляя ключевые токены.

MediaCodec и AudioTrack улучшены за счет следующих функций.

  • В качестве входного контента используется защищенная аудио/видео память.
  • Настроено на аппаратную синхронизацию аудио/видео при туннелированном воспроизведении.
  • Настроена поддержка ES_payload и сквозного режима.

Общая конструкция тюнера HAL.

Рисунок 2. Схема компонентов тюнера HAL

Общий рабочий процесс

На диаграммах ниже показаны последовательности вызовов для воспроизведения прямой трансляции.

Настраивать

Диаграмма последовательности настройки воспроизведения прямой трансляции.

Рисунок 3. Последовательность настройки для воспроизведения прямой трансляции

Обработка аудио/видео

Обработка A/V для диаграммы воспроизведения прямой трансляции.

Рисунок 4. Обработка аудио/видео для воспроизведения прямой трансляции

Обработка зашифрованного контента

Диаграмма обработки зашифрованного контента для воспроизведения в прямом эфире.

Рисунок 5. Обработка зашифрованного контента для воспроизведения в прямом эфире

Обработка аудио/видео данных

Схема обработки аудио/видео данных для воспроизведения в прямом эфире.

Рисунок 6. Обработка аудио/видео для воспроизведения в прямом эфире

API тюнера SDK

API Tuner SDK обеспечивает взаимодействие с Tuner JNI, Tuner HAL и TunerResourceManager . Приложение TIS использует API Tuner SDK для доступа к ресурсам и подкомпонентам Tuner, таким как фильтр и дешифратор. Интерфейс и демультиплексор являются внутренними компонентами.

Блок-схема API Tuner SDK.

Рисунок 7. Взаимодействие с API Tuner SDK

Версии

Начиная с Android 12, Tuner SDK API поддерживает новую функцию в Tuner HAL 1.1, которая представляет собой обратно совместимое обновление версии Tuner 1.0.

Используйте следующий API для проверки текущей версии HAL.

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

Минимально необходимую версию HAL можно найти в документации новых API Android 12.

Пакеты

API Tuner SDK предоставляет четыре пакета, представленных ниже.

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

Блок-схема пакетов API Tuner SDK.

Рисунок 8. Пакеты API Tuner SDK

Android.media.tv.tuner

Пакет Tuner — это точка входа для использования фреймворка Tuner. Приложение TIS использует этот пакет для инициализации и получения экземпляров ресурсов, указывая начальные настройки и обратный вызов.

  • tuner() : инициализирует экземпляр Tuner, указывая параметры useCase и sessionId .
  • tune() : получает ресурс интерфейса и настраивается путем указания параметра FrontendSetting .
  • openFilter() : получает экземпляр фильтра, указывая тип фильтра.
  • openDvrRecorder() : получает экземпляр записи, указывая размер буфера.
  • openDvrPlayback() : получает экземпляр воспроизведения, указывая размер буфера.
  • openDescrambler() : получает экземпляр дескремблера.
  • openLnb() : получает внутренний экземпляр LNB.
  • openLnbByName() : приобретает внешний экземпляр LNB.
  • openTimeFilter() : получает экземпляр фильтра времени.

Пакет Tuner предоставляет функции, которые не входят в пакеты Filter, DVR и Frontend. Эти функции перечислены ниже.

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

Android.media.tv.tuner.frontend

Пакет frontend включает в себя наборы настроек, информации, статусов, событий и возможностей, связанных с frontend.

Классы

FrontendSettings выводится для различных стандартов DTV с помощью классов, указанных ниже.

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

Начиная с Android 12 с Tuner HAL 1.1 или выше поддерживается следующий стандарт DTV.

  • DtmbFrontendSettings

FrontendCapabilities выводится для различных стандартов DTV с помощью классов, указанных ниже.

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

Начиная с Android 12 с Tuner HAL 1.1 или выше поддерживается следующий стандарт DTV.

  • DtmbFrontendCapabilities

FrontendInfo получает информацию о фронтенде. FrontendStatus получает текущее состояние фронтенда. OnTuneEventListener прослушивает события на фронтенде. Приложение TIS использует ScanCallback для обработки сообщений сканирования от фронтенда.

Сканирование каналов

Для настройки телевизора приложение сканирует возможные частоты и формирует список каналов, к которому пользователи могут получить доступ. Для завершения сканирования каналов TIS может использовать Tuner.tune , Tuner.scan(BLIND_SCAN) или Tuner.scan(AUTO_SCAN) .

Если у TIS есть точная информация о доставке сигнала, такая как частота, стандарт (например, T/T2, S/S2) и дополнительная необходимая информация (например, идентификатор PLD), то рекомендуется использовать Tuner.tune как более быстрый вариант.

Когда пользователь вызывает Tuner.tune , происходят следующие действия:

  • TIS заполняет FrontendSettings необходимой информацией с помощью Tuner.tune .
  • Если сигнал заблокирован, HAL выдает сообщение «настройка LOCKED .
  • TIS использует Frontend.getStatus для сбора необходимой информации.
  • TIS переходит на следующую доступную частоту в своем списке частот.

TIS снова вызывает Tuner.tune до тех пор, пока не будут исчерпаны все частоты.

Во время настройки вы можете вызвать stopTune() или close() чтобы приостановить или завершить вызов Tuner.tune .

Tuner.scan(AUTO_SCAN)

Если у TIS недостаточно информации для использования Tuner.tune , но есть список частот и тип стандарта (например, DVB T/C/S), то рекомендуется использовать Tuner.scan(AUTO_SCAN) .

Когда пользователь вызывает Tuner.scan(AUTO_SCAN) , происходят следующие действия:

  • TIS использует Tuner.scan(AUTO_SCAN) с FrontendSettings , заполненными частотой.

  • HAL выдаёт сообщения о блокировке сканирования (scan LOCKED , если сигнал заблокирован. HAL также может выдавать другие сообщения о сканировании, предоставляя дополнительную информацию о сигнале.

  • TIS использует Frontend.getStatus для сбора необходимой информации.

  • TIS вызывает Tuner.scan , чтобы HAL перешёл к следующей настройке на той же частоте. Если структура FrontendSettings пуста, HAL использует следующую доступную настройку. В противном случае HAL использует FrontendSettings для однократного сканирования и отправляет END , сигнализируя о завершении сканирования.

  • TIS повторяет описанные выше действия до тех пор, пока не будут исчерпаны все настройки на частоте.

  • HAL отправляет END , чтобы указать, что операция сканирования завершена.

  • TIS переходит на следующую доступную частоту в своем списке частот.

TIS снова вызывает Tuner.scan(AUTO_SCAN) до тех пор, пока не будут исчерпаны все частоты.

Во время сканирования вы можете вызвать stopScan() или close() чтобы приостановить или завершить сканирование.

Tuner.scan(BLIND_SCAN)

Если у TIS нет списка частот и поставщик HAL может выполнить поиск частоты указанного пользователем интерфейса для получения ресурса интерфейса, то рекомендуется использовать Tuner.scan(BLIND_SCAN) .

  • TIS использует Tuner.scan(BLIND_SCAN) . Частоту можно указать в FrontendSettings для начальной частоты, но TIS игнорирует другие настройки в FrontendSettings .
  • Если сигнал заблокирован, HAL выдает сообщение «сканирование LOCKED .
  • TIS использует Frontend.getStatus для сбора необходимой информации.
  • TIS снова вызывает Tuner.scan для продолжения сканирования. ( FrontendSettings игнорируется.)
  • TIS повторяет описанные выше действия, пока все настройки частоты не будут исчерпаны. HAL увеличивает частоту без каких-либо действий со стороны TIS. HAL выдаёт сообщение PROGRESS .

TIS снова вызывает Tuner.scan(AUTO_SCAN) пока все частоты не будут исчерпаны. HAL выдаёт сообщение END , сигнализируя о завершении сканирования.

Во время сканирования вы можете вызвать stopScan() или close() чтобы приостановить или завершить сканирование.

Блок-схема процесса сканирования TIS.

Рисунок 9. Блок-схема сканирования TIS

Android.media.tv.tuner.filter

Пакет фильтров представляет собой набор операций фильтрации, а также конфигурации, настроек, обратных вызовов и событий. Пакет включает в себя перечисленные ниже операции. Полный список операций см. в исходном коде Android.

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

Полный список смотрите в исходном коде Android.

FilterConfiguration является производным от перечисленных ниже классов. Конфигурации относятся к основному типу фильтра и определяют протокол, который фильтр использует для извлечения данных.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Настройки определяются на основе перечисленных ниже классов. Они относятся к подтипу фильтра и определяют, какие типы данных фильтр может исключить.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent является производным от перечисленных ниже классов и позволяет сообщать о событиях для различных типов данных.

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

Начиная с Android 12 с Tuner HAL 1.1 или выше поддерживаются следующие события.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
События и формат данных из фильтра
Тип фильтра Флаги События Операция с данными Формат данных
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Обязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Рекомендуется:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Согласно мероприятию и внутреннему расписанию, запустите
Filter.read(buffer, offset, adjustedSize) один или несколько раз.

Данные копируются из MQ HAL в клиентский буфер.
Один собранный пакет сеанса заполняется в FMQ другим пакетом сеанса.
isRaw:
false
Обязательный:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Необязательный:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


Данные копируются из MQ HAL в клиентский буфер.
TS.PES isRaw:
true
Обязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Рекомендуется:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Согласно мероприятию и внутреннему расписанию, запустите
Filter.read(buffer, offset, adjustedSize) один или несколько раз.

Данные копируются из MQ HAL в клиентский буфер.
Один собранный пакет PES заполняется в FMQ другим пакетом PES.
isRaw:
false
Обязательный:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Необязательный:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Данные копируются из MQ HAL в клиентский буфер.
MMTP.PES isRaw:
true
Обязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Рекомендуется:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Согласно мероприятию и внутреннему расписанию, запустите
Filter.read(buffer, offset, adjustedSize) один или несколько раз.

Данные копируются из MQ HAL в клиентский буфер.
Один собранный пакет MFU заполняется в FMQ другим пакетом MFU.
isRaw:
false
Обязательный:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Необязательный:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Данные копируются из MQ HAL в клиентский буфер.
TS.TS
Н/Д Обязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Рекомендуется:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Согласно мероприятию и внутреннему расписанию, запустите
Filter.read(buffer, offset, adjustedSize) один или несколько раз.

Данные копируются из MQ HAL в клиентский буфер.
Отфильтровано ts с заголовком ts
заполнено в FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Необязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Клиент может запустить MediaCodec после получения DemuxFilterStatus::DATA_READY .
Клиент может вызвать Filter.flush после получения DemuxFilterStatus::DATA_OVERFLOW .
Н/Д
isPassthrough:
false
Обязательный:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Необязательный:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Чтобы использовать MediaCodec :
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Чтобы использовать Direct Audio из AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Данные ES или частичные данные ES в памяти ION.
TS.PCR
IP.NTP
ALP.PTP
Н/Д Обязательно: Н/Д
Необязательно: Н/Д
Н/Д Н/Д
TS.RECORD Н/Д Обязательный:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Необязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Для индексных данных:
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


Для записанного контента , согласно RecordStatus::* и внутреннему расписанию, выполните одно из следующих действий:
  • Запустите DvrRecord.write(adustedSize) один или несколько раз для сохранения.
    Данные переносятся из MQ HAL в хранилище.
  • Запустите DvrRecord.write(buffer, adustedSize) один или несколько раз для буферизации.
    Данные копируются из MQ HAL в клиентский буфер.
Для индексных данных: Переносится в полезной нагрузке события.

Для записанного контента: мультиплексированный поток TS, заполненный FMQ.
TS.TEMI Н/Д Обязательный:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Необязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
Н/Д
MMTP.MMTP Н/Д Обязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Рекомендуется:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Согласно мероприятию и внутреннему расписанию, запустите
Filter.read(buffer, offset, adjustedSize) один или несколько раз.

Данные копируются из MQ HAL в клиентский буфер.
Отфильтровано mmtp с заголовком mmtp
заполнено в FMQ.
MMTP.RECORD Н/Д Обязательный:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Необязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Для индексных данных: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Для записанного контента , согласно RecordStatus::* и внутреннему расписанию, выполните одно из следующих действий:
  • Запустите DvrRecord.write(adjustedSize) один или несколько раз для сохранения.
    Данные переносятся из MQ HAL в хранилище.
  • Запустите DvrRecord.write(buffer, adjustedSize) один или несколько раз для буферизации.
    Данные копируются из MQ HAL в клиентский буфер.
Для индексных данных: Переносится в полезной нагрузке события.

Для записанного контента: Мультиплексированный записанный поток, заполненный FMQ.

Если источником фильтра для записи является TLV.TLV в IP.IP с сквозной передачей, записанный поток имеет заголовок TLV и IP.
MMTP.DOWNLOAD Н/Д Обязательный:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Необязательный:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

Данные копируются из MQ HAL в клиентский буфер.
Пакет загрузки заполняется в FMQ другим пакетом загрузки IP.
IP.IP_PAYLOAD Н/Д Обязательный:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Необязательный:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

Данные копируются из MQ HAL в клиентский буфер.
Пакет полезной нагрузки IP заполняется в FMQ другим пакетом полезной нагрузки IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Необязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Отфильтрованный подпоток протокола поступает на следующий фильтр в цепочке фильтров. Н/Д
isPassthrough:
false
Обязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Рекомендуется:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Согласно мероприятию и внутреннему расписанию, запустите
Filter.read(buffer, offset, adjustedSize) один или несколько раз.

Данные копируются из MQ HAL в клиентский буфер.
Отфильтрованный подпоток протокола с заголовком протокола заполняется в FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
Н/Д Необязательный:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Отфильтрованная полезная нагрузка протокола подается на следующий фильтр в цепочке фильтров. Н/Д
Пример использования фильтра для построения PSI/SI

Пример потока использования фильтра для построения PSI/SI.

Рисунок 10. Поток создания PSI/SI

  1. Откройте фильтр.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Настройте и запустите фильтр.

    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 .

    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); }
          }
        }
    };
    
Пример использования MediaEvent из фильтра

Пример потока использования MediaEvent из фильтра.

Рисунок 11. Поток использования MediaEvent из фильтра

  1. Откройте, настройте и запустите фильтры A/V.
  2. Процесс MediaEvent .
  3. Получите MediaEvent .
  4. Поставить линейный блок в очередь codec .
  5. После завершения обработки данных отпустите кнопку A/V.

Android.media.tv.tuner.dvr

DvrRecorder предоставляет следующие методы записи.

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

DvrPlayback предоставляет следующие методы воспроизведения.

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

DvrSettings используется для настройки DvrRecorder и DvrPlayback . OnPlaybackStatusChangedListener и OnRecordStatusChangedListener используются для сообщения о состоянии экземпляра DVR.

Пример потока для начала записи

Пример потока для начала записи.

Рисунок 12. Процесс начала записи

  1. Откройте, настройте и запустите 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. Получите RecordEvent и извлеките информацию индекса.

    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. Инициализируйте OnRecordStatusChangedListener и сохраните данные записи.

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

Тюнер HAL

Tuner HAL соответствует стандарту HIDL и определяет интерфейс между фреймворком и оборудованием поставщика. Поставщики используют этот интерфейс для реализации Tuner HAL, а фреймворк — для взаимодействия с реализацией Tuner HAL.

Модули

Тюнер HAL 1.0

Модули Основные элементы управления Элементы управления, специфичные для модуля HAL-файлы
ITuner Н/Д 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

Тюнер HAL 1.1 (на основе тюнера HAL 1.0)

Модули Основные элементы управления Элементы управления, специфичные для модуля HAL-файлы
ITuner Н/Д 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

Схема взаимодействия модулей тюнера HAL.

Рисунок 13. Схема взаимодействия модулей тюнера HAL

Фильтр-связь

Тюнер HAL поддерживает связывание фильтров, что позволяет объединять фильтры с другими фильтрами для создания нескольких слоёв. Фильтры следуют приведенным ниже правилам.

  • Фильтры связаны в виде дерева, замкнутые пути не допускаются.
  • Корневой узел — демультиплексор.
  • Фильтры работают независимо.
  • Все фильтры начинают получать данные.
  • Фильтрующее соединение промывается на последнем фильтре.

Блок кода ниже и рисунок 14 иллюстрируют пример фильтрации нескольких слоев.

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>)
}

Схема примера соединения фильтров.

Рисунок 14. Схема соединения фильтров для нескольких слоев

Менеджер ресурсов тюнера

До появления диспетчера ресурсов тюнера (TRM) для переключения между двумя приложениями требовалось одно и то же аппаратное обеспечение тюнера. В TV Input Framework (TIF) использовался механизм «первый получил победитель», который означал, что приложение, первым получившее ресурс, сохраняет его. Однако этот механизм может быть неидеальным для некоторых сложных сценариев использования.

TRM работает как системная служба, управляя аппаратными ресурсами тюнера, TVInput и CAS для приложений. TRM использует механизм «выигрыша переднего плана», который вычисляет приоритет приложения на основе его текущего состояния (в активном или фоновом режиме) и типа сценария использования. TRM предоставляет или отзывает ресурс в зависимости от приоритета. TRM централизует управление ресурсами ATV для вещания, OTT и DVR.

Интерфейс ТРМ

TRM предоставляет интерфейсы AIDL в ITunerResourceManager.aidl для фреймворка Tuner, MediaCas и TvInputHardwareManager для регистрации, запроса или освобождения ресурсов.

Интерфейсы для управления клиентами перечислены ниже.

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

Интерфейсы для запроса и освобождения ресурсов перечислены ниже.

  • 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

Классы клиентов и запросов перечислены ниже.

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

Приоритет клиента

TRM вычисляет приоритет клиента, используя параметры из его профиля и значение приоритета из файла конфигурации. Приоритет также может быть обновлен с использованием произвольного значения приоритета, полученного от клиента.

Параметры в профиле клиента

TRM извлекает идентификатор процесса из mTvInputSessionId , чтобы определить, является ли приложение активным или фоновым. Для создания mTvInputSessionId метод TvInputService.onCreateSession или TvInputService.onCreateRecordingSession инициализирует сеанс TIS.

mUseCase указывает вариант использования сеанса. Предопределенные варианты использования перечислены ниже.

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
}

Файл конфигурации

Файл конфигурации по умолчанию

Файл конфигурации по умолчанию, представленный ниже, содержит значения приоритетов для предопределённых вариантов использования. Пользователи могут изменить эти значения, используя настраиваемый файл конфигурации .

Вариант использования Передний план Фон
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Настроенный файл конфигурации

Поставщики могут настраивать файл конфигурации /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Этот файл используется для добавления, удаления или обновления типов вариантов использования и значений их приоритетов. В качестве шаблона для этого файла можно использовать platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml .

Например, новый вариант использования поставщика — VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] . Формат должен соответствовать platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd .

Произвольное значение приоритета и значение nice

TRM предоставляет updateClientPriority позволяющую клиенту обновлять произвольное значение приоритета и значение nice. Произвольное значение приоритета перезаписывает значение приоритета, рассчитанное на основе типа варианта использования и идентификатора сеанса.

Значение «доброжелательности» показывает, насколько снисходительно клиент ведёт себя в конфликте с другим клиентом. Значение «доброжелательности» снижает значение приоритета клиента перед сравнением его значения с приоритетом проблемного клиента.

Механизм возврата

На диаграмме ниже показано, как ресурсы возвращаются и распределяются при возникновении конфликта ресурсов.

Схема процесса работы механизма возврата.

Рисунок 15. Схема механизма восстановления при конфликте между ресурсами тюнера