В Android 11 или более поздней версии вы можете использовать платформу Android Tuner для доставки аудио/видео контента. Платформа использует аппаратный конвейер от поставщиков, что делает ее подходящей как для SoC начального, так и для начального уровня. Эта платформа обеспечивает безопасный способ доставки аудио/видео контента, защищенного доверенной средой выполнения (TEE) и безопасным путем передачи данных (SMP), что позволяет использовать его в строго ограниченной среде защиты контента.
Стандартизированный интерфейс между Tuner и Android CAS обеспечивает более быструю интеграцию между поставщиками тюнеров и поставщиками CAS. Интерфейс Tuner работает с MediaCodec
и AudioTrack
создавая единое мировое решение для Android TV. Интерфейс тюнера поддерживает как цифровое, так и аналоговое телевидение на основе основных стандартов вещания.
Компоненты
Для Android 11 три компонента специально разработаны для телевизионной платформы.
- Тюнер HAL: интерфейс между платформой и поставщиками.
- API Tuner SDK: интерфейс между платформой и приложениями.
- Менеджер ресурсов тюнера (TRM): координирует аппаратные ресурсы тюнера.
В Android 11 были улучшены следующие компоненты.
- КАС В2
-
TvInputService
или Служба ТВ-входа (TIS) -
TvInputManagerService
или служба диспетчера ТВ-входа (TIMS) -
MediaCodec
или медиакодек -
AudioTrack
или звуковая дорожка -
MediaResourceManager
или менеджер медиаресурсов (MRM)
Рисунок 1. Взаимодействие между компонентами Android TV
Функции
Интерфейс поддерживает указанные ниже стандарты DTV.
- АТСК
- АТСК3
- ДВБ С/С/Т
- ИСДБ С/С3/Т
- Аналоговый
Интерфейс Android 12 с тюнером HAL 1.1 или более поздней версии поддерживает указанный ниже стандарт DTV.
- ДТМБ
Demux поддерживает протоколы потоков, указанные ниже.
- Транспортный поток (ТС)
- Транспортный протокол мультимедиа MPEG (MMTP)
- Интернет-протокол (IP)
- Введите значение длины (TLV)
- Протокол канального уровня ATSC (ALP)
Дескремблер поддерживает указанные ниже средства защиты контента.
- Безопасный путь к медиафайлам
- Очистить путь мультимедиа
- Безопасная локальная запись
- Безопасное локальное воспроизведение
API-интерфейсы тюнера поддерживают приведенные ниже варианты использования.
- Сканировать
- Жить
- Воспроизведение
- Записывать
Tuner, MediaCodec
и AudioTrack
поддерживают указанные ниже режимы потока данных.
- Полезная нагрузка ES с очисткой буфера памяти
- Полезная нагрузка ES с безопасным дескриптором памяти
- Сквозное прохождение
Общий дизайн
Тюнер HAL определяется между платформой Android и оборудованием поставщика.
- Описывает, что платформа ожидает от поставщика и как поставщик может это сделать.
- Экспортирует функциональные возможности внешнего интерфейса, демультиплексора и дескремблера в платформу через интерфейсы
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
иILnb
. - Включает функции для интеграции Tuner HAL с другими компонентами платформы, такими как
MediaCodec
иAudioTrack
.
Создаются Java-класс Tuner и собственный класс.
- API Tuner Java позволяет приложениям получать доступ к Tuner HAL через общедоступные API.
- Класс Native позволяет управлять разрешениями и обрабатывать большие объемы данных записи или воспроизведения с помощью Tuner HAL.
- Модуль Native Tuner является мостом между Java-классом Tuner и Tuner HAL.
Создается класс TRM.
- Управляет ограниченными ресурсами тюнера, такими как Frontend, LNB, сеансы CAS и устройство ТВ-входа из ТВ-входа HAL.
- Применяет правила для возврата недостаточных ресурсов из приложений. Правило по умолчанию — победа на переднем плане.
Media CAS и CAS HAL дополнены приведенными ниже функциями.
- Открывает сеансы CAS для различных вариантов использования и алгоритмов.
- Поддерживает динамические системы CAS, такие как удаление и вставка CICAM.
- Интегрируется с Tuner HAL, предоставляя токены ключей.
MediaCodec
и AudioTrack
дополнены приведенными ниже функциями.
- В качестве входного контента используется безопасная память A/V.
- Настроен для аппаратной синхронизации A/V при туннельном воспроизведении.
- Настроена поддержка
ES_payload
и режима passthrough.
Рисунок 2. Схема компонентов Tuner HAL.
Общий рабочий процесс
На диаграммах ниже показаны последовательности вызовов для воспроизведения в прямом эфире.
Настраивать
Рисунок 3. Последовательность настройки для воспроизведения прямой трансляции
Обработка аудио/видео
Рисунок 4. Обработка A/V для воспроизведения в прямом эфире
Обработка зашифрованного контента
Рисунок 5. Обработка зашифрованного контента для воспроизведения в прямом эфире
Обработка аудио/видео данных
Рисунок 6. Обработка A/V для воспроизведения в прямом эфире
API SDK тюнера
API Tuner SDK обрабатывает взаимодействие с Tuner JNI, Tuner HAL и TunerResourceManager
. Приложение TIS использует API Tuner SDK для доступа к ресурсам и подкомпонентам Tuner, таким как фильтр и дешифратор. Фронтенд и демультиплексор являются внутренними компонентами.
Рисунок 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
Рисунок 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 предоставляет функции, которые не входят в пакеты фильтров, DVR и внешнего интерфейса. Функциональные возможности перечислены ниже.
-
cancelTuning
-
scan
/cancelScanning
-
getAvSyncHwId
-
getAvSyncTime
-
connectCiCam1
/disconnectCiCam
-
shareFrontendFromTuner
-
updateResourcePriority
-
setOnTuneEventListener
-
setResourceLostListener
Android.media.tv.tuner.frontend
Пакет внешнего интерфейса включает в себя наборы настроек, информации, статусов, событий и возможностей, связанных с внешним интерфейсом.
Классы
FrontendSettings
создается для различных стандартов цифрового телевидения с помощью приведенных ниже классов.
-
AnalogFrontendSettings
-
Atsc3FrontendSettings
-
AtscFrontendSettings
-
DvbcFrontendSettings
-
DvbsFrontendSettings
-
DvbtFrontendSettings
-
Isdbs3FrontendSettings
-
IsdbsFrontendSettings
-
IsdbtFrontendSettings
Начиная с Android 12 с тюнером HAL 1.1 или выше, поддерживается следующий стандарт DTV.
-
DtmbFrontendSettings
FrontendCapabilities
создается для различных стандартов цифрового телевидения с помощью приведенных ниже классов.
-
AnalogFrontendCapabilities
-
Atsc3FrontendCapabilities
-
AtscFrontendCapabilities
-
DvbcFrontendCapabilities
-
DvbsFrontendCapabilities
-
DvbtFrontendCapabilities
-
Isdbs3FrontendCapabilities
-
IsdbsFrontendCapabilities
-
IsdbtFrontendCapabilities
Начиная с Android 12 с тюнером 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 сканируют сообщения
LOCKED
если сигнал заблокирован. HAL может также сообщать о других сообщениях сканирования, чтобы предоставить дополнительную информацию о сигнале.TIS использует
Frontend.getStatus
для сбора необходимой информации.TIS вызывает
Tuner.scan
для HAL, чтобы перейти к следующей настройке на той же частоте. Если структураFrontendSettings
пуста, HAL использует следующий доступный параметр. В противном случае HAL используетFrontendSettings
для однократного сканирования и отправляетEND
, чтобы указать, что операция сканирования завершена.ТИС повторяет вышеописанные действия до тех пор, пока не будут исчерпаны все настройки по частоте.
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
игнорируется.) - ТИС повторяет вышеописанные действия до тех пор, пока не будут исчерпаны все настройки по частоте. HAL увеличивает частоту без каких-либо действий со стороны TIS.
PROGRESS
сообщает HAL.
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++ Чтобы использовать прямое аудио 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
Тюнер 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 указывает, насколько снисходительно поведение клиента в случае конфликта с другим клиентом. Значение «приятно» уменьшает значение приоритета клиента до того, как его значение приоритета сравнивается со значением приоритета «сложного» клиента.
Механизм возврата
На диаграмме ниже показано, как ресурсы освобождаются и назначаются при возникновении конфликта ресурсов.
Рисунок 15. Схема механизма восстановления при конфликте ресурсов тюнера
,В Android 11 или более поздней версии вы можете использовать платформу Android Tuner для доставки аудио- и видеоконтента. Платформа использует аппаратный конвейер от поставщиков, что делает ее подходящей как для SoC начального, так и для начального уровня. Эта платформа обеспечивает безопасный способ доставки аудио/видео контента, защищенного доверенной средой выполнения (TEE) и безопасным путем передачи данных (SMP), что позволяет использовать его в строго ограниченной среде защиты контента.
Стандартизированный интерфейс между Tuner и Android CAS обеспечивает более быструю интеграцию между поставщиками тюнеров и поставщиками CAS. Интерфейс Tuner работает с MediaCodec
и AudioTrack
создавая единое мировое решение для Android TV. Интерфейс тюнера поддерживает как цифровое, так и аналоговое телевидение на основе основных стандартов вещания.
Компоненты
Для Android 11 три компонента специально разработаны для телевизионной платформы.
- Тюнер HAL: интерфейс между платформой и поставщиками.
- API Tuner SDK: интерфейс между платформой и приложениями.
- Менеджер ресурсов тюнера (TRM): координирует аппаратные ресурсы тюнера.
В Android 11 были улучшены следующие компоненты.
- КАС В2
-
TvInputService
или Служба ТВ-входа (TIS) -
TvInputManagerService
или служба диспетчера ТВ-входа (TIMS). -
MediaCodec
или медиакодек -
AudioTrack
или звуковая дорожка -
MediaResourceManager
или менеджер медиаресурсов (MRM)
Рисунок 1. Взаимодействие между компонентами Android TV
Функции
Интерфейс поддерживает указанные ниже стандарты DTV.
- АТСК
- АТСК3
- ДВБ С/С/Т
- ИСДБ С/С3/Т
- Аналоговый
Интерфейс Android 12 с тюнером HAL 1.1 или более поздней версии поддерживает указанный ниже стандарт DTV.
- ДТМБ
Demux поддерживает протоколы потоков, указанные ниже.
- Транспортный поток (ТС)
- Транспортный протокол мультимедиа MPEG (MMTP)
- Интернет-протокол (IP)
- Введите значение длины (TLV)
- Протокол канального уровня ATSC (ALP)
Дескремблер поддерживает указанные ниже средства защиты контента.
- Безопасный путь к медиафайлам
- Очистить путь мультимедиа
- Безопасная локальная запись
- Безопасное локальное воспроизведение
API-интерфейсы тюнера поддерживают приведенные ниже варианты использования.
- Сканировать
- Жить
- Воспроизведение
- Записывать
Tuner, MediaCodec
и AudioTrack
поддерживают указанные ниже режимы потока данных.
- Полезная нагрузка ES с очисткой буфера памяти
- Полезная нагрузка ES с безопасным дескриптором памяти
- Сквозное прохождение
Общий дизайн
Тюнер HAL определяется между платформой Android и оборудованием поставщика.
- Описывает, что платформа ожидает от поставщика и как поставщик может это сделать.
- Экспортирует функциональные возможности внешнего интерфейса, демультиплексора и дескремблера в платформу через интерфейсы
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
иILnb
. - Включает функции для интеграции Tuner HAL с другими компонентами платформы, такими как
MediaCodec
иAudioTrack
.
Создаются Java-класс Tuner и собственный класс.
- API Tuner Java позволяет приложениям получать доступ к Tuner HAL через общедоступные API.
- Класс Native позволяет управлять разрешениями и обрабатывать большие объемы данных записи или воспроизведения с помощью Tuner HAL.
- Модуль Native Tuner является мостом между Java-классом Tuner и Tuner HAL.
Создается класс TRM.
- Управляет ограниченными ресурсами тюнера, такими как Frontend, LNB, сеансы CAS и устройство ТВ-входа из ТВ-входа HAL.
- Применяет правила для возврата недостаточных ресурсов из приложений. Правило по умолчанию — победа на переднем плане.
Media CAS и CAS HAL дополнены приведенными ниже функциями.
- Открывает сеансы CAS для различных вариантов использования и алгоритмов.
- Поддерживает динамические системы CAS, такие как удаление и вставка CICAM.
- Интегрируется с Tuner HAL, предоставляя токены ключей.
MediaCodec
и AudioTrack
дополнены приведенными ниже функциями.
- В качестве входного контента используется безопасная память A/V.
- Настроен для аппаратной синхронизации A/V при туннельном воспроизведении.
- Настроена поддержка
ES_payload
и режима passthrough.
Рисунок 2. Схема компонентов Tuner HAL.
Общий рабочий процесс
На диаграммах ниже показаны последовательности вызовов для воспроизведения в прямом эфире.
Настраивать
Рисунок 3. Последовательность настройки для воспроизведения прямой трансляции
Обработка аудио/видео
Рисунок 4. Обработка A/V для воспроизведения в прямом эфире
Обработка зашифрованного контента
Рисунок 5. Обработка зашифрованного контента для воспроизведения в прямом эфире
Обработка аудио/видео данных
Рисунок 6. Обработка A/V для воспроизведения в прямом эфире
API SDK тюнера
API Tuner SDK обрабатывает взаимодействие с Tuner JNI, Tuner HAL и TunerResourceManager
. Приложение TIS использует API Tuner SDK для доступа к ресурсам и подкомпонентам Tuner, таким как фильтр и дешифратор. Фронтенд и демультиплексор являются внутренними компонентами.
Рисунок 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
Рисунок 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 предоставляет функции, которые не входят в пакеты фильтров, DVR и внешнего интерфейса. Функциональные возможности перечислены ниже.
-
cancelTuning
-
scan
/cancelScanning
-
getAvSyncHwId
-
getAvSyncTime
-
connectCiCam1
/disconnectCiCam
-
shareFrontendFromTuner
-
updateResourcePriority
-
setOnTuneEventListener
-
setResourceLostListener
Android.media.tv.tuner.frontend
Пакет внешнего интерфейса включает в себя наборы настроек, информации, статусов, событий и возможностей, связанных с внешним интерфейсом.
Классы
FrontendSettings
создается для различных стандартов цифрового телевидения с помощью приведенных ниже классов.
-
AnalogFrontendSettings
-
Atsc3FrontendSettings
-
AtscFrontendSettings
-
DvbcFrontendSettings
-
DvbsFrontendSettings
-
DvbtFrontendSettings
-
Isdbs3FrontendSettings
-
IsdbsFrontendSettings
-
IsdbtFrontendSettings
Начиная с Android 12 с тюнером HAL 1.1 или более поздней версии поддерживается следующий стандарт DTV.
-
DtmbFrontendSettings
FrontendCapabilities
создается для различных стандартов цифрового телевидения с помощью приведенных ниже классов.
-
AnalogFrontendCapabilities
-
Atsc3FrontendCapabilities
-
AtscFrontendCapabilities
-
DvbcFrontendCapabilities
-
DvbsFrontendCapabilities
-
DvbtFrontendCapabilities
-
Isdbs3FrontendCapabilities
-
IsdbsFrontendCapabilities
-
IsdbtFrontendCapabilities
Начиная с Android 12 с тюнером 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 сканируют сообщения
LOCKED
, если сигнал заблокирован. HAL может также сообщать о других сообщениях сканирования, чтобы предоставить дополнительную информацию о сигнале.TIS использует
Frontend.getStatus
для сбора необходимой информации.TIS вызывает
Tuner.scan
для HAL, чтобы перейти к следующей настройке на той же частоте. Если структураFrontendSettings
пуста, HAL использует следующий доступный параметр. В противном случае HAL используетFrontendSettings
для однократного сканирования и отправляетEND
, чтобы указать, что операция сканирования завершена.ТИС повторяет вышеописанные действия до тех пор, пока не будут исчерпаны все настройки по частоте.
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
игнорируется.) - ТИС повторяет вышеописанные действия до тех пор, пока не будут исчерпаны все настройки по частоте. HAL увеличивает частоту без каких-либо действий со стороны TIS.
PROGRESS
сообщает HAL.
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 с тюнером 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) один или несколько раз.Данные копируются из HAL's MQ в клиентский буфер. | Один собранный пакет сеансов заполняется в FMQ другим пакетом сеансов. |
isRaw: | Обязательный:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Необязательный: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Данные копируются из HAL's MQ в клиентский буфер. | ||
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++ Данные копируются из HAL's MQ в клиентский буфер. | ||
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++ Чтобы использовать прямой звук AudioTrack :for i=0; i<n; i++ | ES или частичные данные ES в ионной памяти. | |
TS.PCR IP.NTP ALP.PTP | Н/Д | Обязательно: н/а Необязательно: N/A. | Н/Д | Н/Д |
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::* и внутреннее расписание, сделайте одно из следующих:
| Для данных индекса: переносится в полезной нагрузке. Для записанного контента: MUXED Записанный поток, заполненный в FMQ. Если источник фильтра для записи равен TLV.TLV to IP.IP с PassThrough, записанный поток имеет заголовок 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) Данные копируются из HAL's MQ в клиентский буфер. | Скачать пакет заполнен в 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) Данные копируются из HAL's MQ в клиентский буфер. | Пакет 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); } } } };
Пример потока для использования среднеэвер из фильтра
Рисунок 11. Поток для использования среднеэверных из фильтра
- Откройте, настройте и запустите фильтры 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); } } };
Тюнер Хэл
Tuner HAL следует HIDL и определяет интерфейс между оборудованием Framework и поставщика. Поставщики используют интерфейс для реализации Tuner HAL, и Framework использует его для связи с реализацией 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. Диаграмма взаимодействий между модулями тюнера HAL
Фильтруя связь
Tuner HAL поддерживает связь фильтра, так что фильтры могут быть связаны с другими фильтрами для нескольких слоев. Фильтры следуют правилам ниже.
- Фильтры связаны как дерево, близкий путь не допускается.
- Корневой узел - Demux.
- Фильтры работают независимо.
- Все фильтры начинают получать данные.
- Связанка фильтра промывает на последнем фильтре.
Кодовый блок ниже и рисунок 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
Перед Tuner Resource Manager (TRM) переключение между двумя приложениями требовало одного и того же оборудования тюнера. Входной фреймворк (TIF) использовал механизм «первого к приобретению», что означает, какое приложение получит ресурс в первую очередь сохраняет ресурс. Тем не менее, этот механизм не может быть идеальным для некоторых сложных случаев использования.
TRM работает как системная служба для управления тюнером, TVInput
и CAS -аппаратными ресурсами для приложений. TRM использует механизм «победа переднего плана», который вычисляет приоритет приложения на основе переднего плана приложения или статуса фонового и типа использования. TRM предоставляет или отменяет ресурс на основе приоритета. TRM централизует управление ресурсами ATV для вещания, OTT и DVR.
Интерфейс TRM
TRM разоблачает интерфейсы AIDL в ITunerResourceManager.aidl
для фреймворта, 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
для обновления произвольного значения приоритета и хорошего значения. Произвольное значение приоритета перезаписывает значение приоритета, рассчитанное по типу использования и идентификатором сеанса.
Хорошая ценность указывает, насколько снисходительным является поведение клиента, когда оно вступает в конфликт с другим клиентом. Хорошая стоимость уменьшается, что значение приоритета клиента до того, как его приоритетная стоимость сравнивается с сложным клиентом.
Исправление механизма
Приведенная ниже диаграмма показывает, как ресурсы восстанавливаются и назначены, когда происходит конфликт ресурсов.
Рисунок 15. Диаграмма механизма Reclaim для конфликта между ресурсами тюнера