Для Android 11 или более поздней версии вы можете использовать платформу Android Tuner для доставки аудио- и видеоконтента. Фреймворк использует аппаратный конвейер от поставщиков, что делает его подходящим как для недорогих, так и для высокопроизводительных SoC. Платформа обеспечивает безопасный способ доставки аудио- и видеоконтента, защищенного доверенной средой выполнения (TEE) и безопасным путем передачи мультимедиа (SMP), что позволяет использовать его в строго ограниченной среде защиты контента.
Стандартизированный интерфейс между Tuner и Android CAS обеспечивает более быструю интеграцию между поставщиками Tuner и поставщиками CAS. Интерфейс Tuner работает с 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
Функции
Frontend поддерживает указанные ниже стандарты DTV.
- АТСК
- ATSC3
- ДВБ К/С/Т
- ИСДБ С/С3/Т
- Аналоговый
Внешний интерфейс в Android 12 с Tuner HAL 1.1 или более поздней версии поддерживает стандарт DTV, указанный ниже.
- ДТМБ
Demux поддерживает перечисленные ниже потоковые протоколы.
- Транспортный поток (TS)
- Протокол передачи мультимедиа 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
.
Создаются Java-класс Tuner и собственный класс.
- Tuner Java API позволяет приложениям получать доступ к Tuner HAL через общедоступные API.
- Собственный класс позволяет управлять разрешениями и обрабатывать большие объемы данных записи или воспроизведения с помощью Tuner HAL.
- Модуль Native Tuner — это мост между Java-классом Tuner и Tuner HAL.
Создается класс TRM.
- Управляет ограниченными ресурсами тюнера, такими как внешний интерфейс, LNB, сеансы CAS и устройство ввода телевизора с HAL входа телевизора.
- Применяет правила для восстановления недостаточных ресурсов приложений. Правило по умолчанию — победа на переднем плане.
Медиа CAS и CAS HAL дополнены перечисленными ниже функциями.
- Открывает сеансы CAS для различных вариантов использования и алгоритмов.
- Поддерживает динамические системы CAS, такие как удаление и вставка CICAM.
- Интегрируется с Tuner HAL, предоставляя токены ключей.
MediaCodec
и AudioTrack
дополнены перечисленными ниже функциями.
- Принимает защищенную аудио/видео память в качестве входного содержимого.
- Настроен на аппаратную синхронизацию аудио/видео при туннелированном воспроизведении.
- Настроена поддержка
ES_payload
и сквозного режима.
Рис. 2. Схема компонентов Tuner HAL
Общий рабочий процесс
На приведенных ниже диаграммах показаны последовательности вызовов для воспроизведения в прямом эфире.
Настраивать
Рис. 3. Последовательность настройки воспроизведения прямой трансляции
Обработка аудио/видео
Рис. 4. Обработка аудио/видео для воспроизведения в прямом эфире
Обработка зашифрованного контента
Рисунок 5. Обработка зашифрованного контента для воспроизведения в прямом эфире
Обработка аудио/видео данных
Рис. 6. Обработка аудио/видео для воспроизведения в прямом эфире
API SDK для тюнера
Tuner SDK API обрабатывает взаимодействие с Tuner JNI, Tuner HAL и TunerResourceManager
. Приложение TIS использует API Tuner SDK для доступа к ресурсам и подкомпонентам Tuner, таким как фильтр и дескремблер. Фронтенд и демультиплексор являются внутренними компонентами.
Рисунок 7. Взаимодействие с Tuner SDK API
Версии
Начиная с Android 12 API Tuner SDK поддерживает новую функцию в Tuner HAL 1.1, которая представляет собой обновление версии Tuner 1.0 с обратной совместимостью.
Используйте следующий API для проверки работающей версии HAL.
-
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
Минимальную требуемую версию HAL можно найти в документации новых API Android 12.
Пакеты
Tuner SDK API предоставляет четыре пакета, указанные ниже.
-
android.media.tv.tuner
-
android.media.tv.tuner.frontend
-
android.media.tv.tuner.filter
-
android.media.tv.tuner.dvr
Рисунок 8. Пакеты Tuner SDK API
Android.media.tv.tuner
Пакет Tuner — это отправная точка для использования платформы Tuner. Приложение TIS использует пакет для инициализации и получения экземпляров ресурсов путем указания начальной настройки и обратного вызова.
- Tuner
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 сканируют сообщения
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()
, чтобы приостановить или завершить сканирование.
Тюнер.скан(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 (производный от Tuner 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 указывает, насколько снисходительно ведет себя клиент, когда он конфликтует с другим клиентом. Хорошее значение уменьшает значение приоритета клиента до того, как его значение приоритета сравнивается с вызывающим клиентом.
Механизм восстановления
На приведенной ниже диаграмме показано, как ресурсы освобождаются и назначаются при возникновении конфликта ресурсов.
Рисунок 15. Схема механизма восстановления при конфликте между ресурсами Tuner