Для Android 11 или выше вы можете использовать фреймворк Android Tuner для доставки A/V-контента. Фреймворк использует аппаратный конвейер от поставщиков, что делает его пригодным как для бюджетных, так и для высокопроизводительных SoC. Фреймворк обеспечивает безопасный способ доставки A/V-контента, защищенного доверенной средой выполнения (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)
Рисунок 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.
- Собственный класс позволяет контролировать разрешения и обрабатывать большие объемы данных записи или воспроизведения с помощью Tuner 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
и режима сквозной передачи.
Рисунок 2. Схема компонентов тюнера HAL
Общий рабочий процесс
На схемах ниже показаны последовательности вызовов для воспроизведения прямой трансляции.
Настраивать
Рисунок 3. Последовательность настройки для воспроизведения прямой трансляции
Обработка аудио/видео
Рисунок 4. Обработка аудио/видео для воспроизведения прямой трансляции
Обработка зашифрованного контента
Рисунок 5. Обработка зашифрованного контента для воспроизведения в прямом эфире
Обработка аудио/видео данных
Рисунок 6. Обработка аудио/видео для воспроизведения прямой трансляции
API-интерфейс SDK тюнера
Tuner SDK API обрабатывает взаимодействия с Tuner JNI, Tuner HAL и TunerResourceManager
. Приложение TIS использует Tuner SDK API для доступа к ресурсам Tuner и подкомпонентам, таким как фильтр и дешифратор. Фронтенд и демультиплексор являются внутренними компонентами.
Рисунок 7. Взаимодействие с API Tuner SDK
Версии
Начиная с Android 12, Tuner SDK API поддерживает новую функцию в Tuner HAL 1.1, которая представляет собой обратно совместимую версию Tuner 1.0.
Для проверки текущей версии HAL используйте следующий API.
-
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
Рисунок 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
Пакет интерфейса включает в себя наборы настроек, информации, статусов, событий и возможностей, связанных с интерфейсом.
Классы
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
.
Тюнер.сканирование(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 также может сообщать о других сообщениях scan, чтобы предоставить дополнительную информацию о сигнале.TIS использует
Frontend.getStatus
для сбора необходимой информации.TIS вызывает
Tuner.scan
для HAL, чтобы продолжить к следующей настройке на той же частоте. Если структураFrontendSettings
пуста, HAL использует следующую доступную настройку. В противном случае HAL используетFrontendSettings
для одноразового сканирования и отправляетEND
, чтобы указать, что операция сканирования завершена.TIS повторяет описанные выше действия до тех пор, пока не будут исчерпаны все настройки частоты.
HAL отправляет
END
, чтобы указать, что операция сканирования завершена.TIS переходит на следующую доступную частоту в своем списке частот.
TIS снова вызывает Tuner.scan(AUTO_SCAN)
до тех пор, пока все частоты не будут исчерпаны.
Во время сканирования вы можете вызвать stopScan()
или close()
чтобы приостановить или завершить сканирование.
Тюнер.сканирование(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()
чтобы приостановить или завершить сканирование.
Рисунок 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: | Обязательный:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Рекомендуется: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Согласно расписанию мероприятия и внутреннему графику, запуститеFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из MQ HAL в клиентский буфер. | Один собранный пакет сеанса заполняется в FMQ другим пакетом сеанса. |
isRaw: | Обязательный:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Необязательный: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Данные копируются из MQ HAL в клиентский буфер. | ||
TS.PES | isRaw: | Обязательный:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Рекомендуется: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Согласно расписанию мероприятия и внутреннему графику, запуститеFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из MQ HAL в клиентский буфер. | Один собранный пакет PES заполняется в FMQ другим пакетом PES. |
isRaw: | Обязательный:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Необязательный: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Данные копируются из MQ HAL в клиентский буфер. | ||
MMTP.PES | isRaw: | Обязательный:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Рекомендуется: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Согласно расписанию мероприятия и внутреннему графику, запуститеFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из MQ HAL в клиентский буфер. | Один собранный пакет MFU заполняется в FMQ другим пакетом MFU. |
isRaw: | Обязательный:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Необязательный: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Данные копируются из 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: | Необязательный:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Клиент может запустить MediaCodec после получения DemuxFilterStatus::DATA_READY .Клиент может вызвать Filter.flush после получения DemuxFilterStatus::DATA_OVERFLOW . | Н/Д |
isPassthrough: | Обязательный:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Необязательный: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | Чтобы использовать MediaCodec :for i=0; i<n; i++ Чтобы использовать Direct Audio из AudioTrack :for i=0; i<n; i++ | Данные 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++ Для записанного контента , согласно RecordStatus::* и внутреннему расписанию, выполните одно из следующих действий:
| Для индексных данных: Переносится в полезной нагрузке события. Для записанного контента: мультиплексированный поток 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++ | Н/Д |
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++ Для записанного контента , согласно RecordStatus::* и внутреннему расписанию, выполните одно из следующих действий:
| Для индексных данных: Переносится в полезной нагрузке события. Для записанного контента: мультиплексированный записанный поток, заполненный 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: | Необязательный:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW | Отфильтрованный подпоток протокола подается на следующий фильтр в цепочке фильтров. | Н/Д |
isPassthrough: | Обязательный: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
Рисунок 10. Поток для построения PSI/SI
Откройте фильтр.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
Настройте и запустите фильтр.
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();
Процесс
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 из фильтра
Рисунок 11. Поток использования MediaEvent из фильтра
- Откройте, настройте и запустите фильтры A/V.
- Процесс
MediaEvent
. - Получаем
MediaEvent
. - Поставьте линейный блок в очередь
codec
. - Отпустите кнопку 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. Поток для начала записи
Откройте, настройте и запустите
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();
Получите
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. } } } };
Инициализируйте
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 |
Рисунок 13. Схема взаимодействия модулей Tuner HAL
Фильтр связи
Tuner 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. Схема соединения фильтров для нескольких слоев
Менеджер ресурсов тюнера
До Tuner Resource Manager (TRM) переключение между двумя приложениями требовало одного и того же оборудования Tuner. TV Input Framework (TIF) использовал механизм «первый получил победу», что означает, что приложение, которое первым получило ресурс, сохраняет его. Однако этот механизм может быть неидеальным для некоторых сложных случаев использования.
TRM работает как системная служба для управления аппаратными ресурсами Tuner, 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
.
Произвольное значение приоритета и приятное значение
TRM предоставляет updateClientPriority
для клиента, чтобы обновить произвольное значение приоритета и значение nice. Произвольное значение приоритета перезаписывает значение приоритета, вычисленное на основе типа варианта использования и идентификатора сеанса.
Значение nice указывает, насколько снисходительно поведение клиента, когда он находится в конфликте с другим клиентом. Значение nice уменьшает значение приоритета клиента, прежде чем его значение приоритета сравнивается с проблемным клиентом.
Механизм возврата
На схеме ниже показано, как ресурсы возвращаются и распределяются при возникновении конфликта ресурсов.
Рисунок 15. Схема механизма восстановления при конфликте между ресурсами Tuner