Производители устройств могут предоставлять сторонним разработчикам доступ к таким расширениям, как боке, ночной режим и HDR, через интерфейс Camera Extensions, который входит в библиотеку поставщика оригинального оборудования. Разработчики могут использовать Camera2 Extensions API и CameraX Extensions API, чтобы получить доступ к расширениям, реализованным в библиотеке OEM-производителя.
Список поддерживаемых расширений, одинаковый для Camera2 и CameraX, приведен в документации по CameraX Extensions API. Если вы хотите добавить расширение, сообщите об ошибке в систему отслеживания ошибок.
На этой странице рассказывается, как реализовать и включить библиотеку OEM-поставщика на устройствах.
Архитектура
На следующей схеме показана архитектура интерфейса Camera Extensions или extensions-interface:
Рисунок 1. Схема архитектуры расширений камеры
Как показано на диаграмме, для поддержки Camera Extensions необходимо реализовать extensions-interface, предоставляемый библиотекой поставщика OEM. Ваша библиотека поставщика OEM позволяет использовать два API: CameraX Extensions API и Camera2 Extensions API. Они используются приложениями CameraX и Camera2 соответственно для доступа к расширениям поставщика.
Как реализовать библиотеку поставщика OEM
Чтобы реализовать библиотеку поставщика OEM, скопируйте файлы camera-extensions-stub в проект системной библиотеки. Эти файлы определяют интерфейс Camera Extensions.
Файлы camera-extensions-stub разделены на следующие категории:
Основные файлы интерфейса (не изменяйте их)
PreviewExtenderImpl.javaImageCaptureExtenderImpl.javaExtenderStateListener.javaProcessorImpl.javaPreviewImageProcessorImpl.javaCaptureProcessorImpl.javaCaptureStageImpl.javaRequestUpdateProcessorImpl.javaProcessResultImpl.javaadvanced/AdvancedExtenderImpl.javaadvanced/Camera2OutputConfigImpl.javaadvanced/Camera2SessionConfigImpl.javaadvanced/ImageProcessorImpl.javaadvanced/ImageReaderOutputConfigImpl.javaadvanced/ImageReferenceImpl.javaadvanced/MultiResolutionImageReaderOutputConfigImpl.javaadvanced/OutputSurfaceImpl.javaadvanced/RequestProcessorImpl.javaadvanced/SessionProcessorImpl.javaadvanced/SurfaceOutputConfigImpl.java
Обязательные реализации (добавьте свою реализацию)
ExtensionVersionImpl.javaInitializerImpl.java
Классы расширения Bokeh (реализуйте, если поддерживается расширение Bokeh)
BokehImageCaptureExtenderImpl.javaBokehPreviewExtenderImpl.javaadvanced/BokehAdvancedExtenderImpl.java
Классы Night extender (реализуйте, если расширение Night поддерживается)
NightImageCaptureExtenderImpl.javaNightPreviewExtenderImpl.javaadvanced/NightAdvancedExtenderImpl.java
Классы автоматического расширения (реализуйте, если поддерживается автоматическое расширение)
AutoImageCaptureExtenderImpl.javaAutoPreviewExtenderImpl.javaadvanced/AutoAdvancedExtenderImpl.java
Классы расширения HDR (реализуйте, если поддерживается расширение HDR)
HdrImageCaptureExtenderImpl.javaHdrPreviewExtenderImpl.javaadvanced/HdrAdvancedExtenderImpl.java
Классы расширения ретуши лица (реализуйте, если расширение ретуши лица поддерживается)
BeautyImageCaptureExtenderImpl.javaBeautyPreviewExtenderImpl.javaadvanced/BeautyAdvancedExtenderImpl.java
Утилиты (необязательно, можно удалить)
advanced/Camera2OutputConfigImplBuilder.javaadvanced/Camera2SessionConfigImplBuilder.java
Вы не обязаны реализовывать все расширения. Если вы не используете расширение, настройте isExtensionAvailable() так, чтобы возвращалось значение false, или удалите соответствующие классы Extender. API Camera2 и CameraX Extensions сообщают приложению, что расширение недоступно.
Давайте посмотрим, как API расширений Camera2 и CameraX взаимодействуют с библиотекой поставщика, чтобы включить расширение. На приведенной ниже диаграмме показан весь процесс с использованием расширения Night в качестве примера.
Рисунок 2. Как реализовать ночное расширение
Проверка версии
Вызовы Camera2/X
ExtensionVersionImpl.checkApiVersion(), чтобы убедиться, что реализованная OEM-производителем версияextensions-interfaceсовместима с версиями, поддерживаемыми Camera2/X.Инициализация библиотеки поставщика
InitializerImplимеет методinit(), который инициализирует библиотеку поставщика. Camera2/X завершает инициализацию до доступа к классам Extender.Создание экземпляров классов Extender
Создает экземпляры классов Extender для расширения. Существует два типа расширителей: базовый и расширенный. Для всех расширений необходимо реализовать один тип Extender. Подробнее о базовом и расширенном удлинителе…
Camera2/X создает экземпляры классов Extender и взаимодействует с ними, чтобы получить информацию и включить расширение. Для определенного расширения Camera2/X может несколько раз создавать экземпляры классов Extender. Поэтому не выполняйте ресурсоемкую инициализацию в конструкторе или вызове
init(). Выполняйте ресурсоемкие операции только перед началом сеанса камеры, например при вызове методаonInit()в Basic Extender илиinitSession()в Advanced Extender.Для расширения "Ночь" создаются следующие классы расширений для базового типа расширения:
NightImageCaptureExtenderImpl.javaNightPreviewExtenderImpl.java
Для расширенного типа:
NightAdvancedExtenderImpl.java
Как проверить доступность расширения
Перед включением расширения
isExtensionAvailable()проверяет, доступно ли оно для указанного идентификатора камеры, через экземпляр Extender.Инициализируйте удлинитель, указав информацию о камере:
Camera2/X вызывает
init()в экземпляре Extender и передает ему идентификатор камеры иCameraCharacteristics.Информация о запросе:
Вызывает класс Extender, чтобы получить информацию, например поддерживаемые разрешения, оценить задержку при съемке и получить ключи запроса от Extender для подготовки к включению расширения.
Как включить расширение на устройстве Extender
Класс Extender предоставляет все интерфейсы, необходимые для включения класса. Он позволяет подключать реализацию OEM к конвейеру Camera2, например добавлять параметры запроса на съемку или включать постпроцессор.
Для типа Advanced Extender Camera2/X взаимодействует с
SessionProcessorImpl, чтобы включить расширение. Camera2/X получает экземплярSessionProcessorImpl, вызываяcreateSessionProcessor()в Extender.
Ниже подробно описан процесс работы расширения.
Проверка версии
При загрузке библиотеки поставщика OEM-производителя с устройства во время выполнения Camera2/X проверяет, совместима ли библиотека с версией extensions-interface.
В extensions-interface используется семантическое управление версиями в формате "МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ", например 1.1.0 или 1.2.0. Однако при проверке версии используются только основные и промежуточные версии.
Чтобы проверить версию, Camera2/X вызывает
ExtensionVersionImpl.checkApiVersion() с поддерживаемой
extensions-interface версией. Затем Camera2/X использует версию, указанную библиотекой OEM, чтобы определить, можно ли включить расширение и какие возможности оно должно вызывать.
Совместимость с основными версиями
Если основные версии интерфейса расширения в Camera2/X и библиотеке поставщика не совпадают, расширение считается несовместимым и отключается.
Обратная совместимость
Если основные версии совпадают, Camera2/X обеспечивает обратную совместимость с библиотеками поставщиков OEM, созданными с помощью более ранних версий extensions-interface. Например, если Camera2/X поддерживает версию 1.3.0, то библиотеки поставщика оборудования, в которых реализованы версии 1.0.0, 1.1.0 и 1.2.0, по-прежнему совместимы.extensions-interface Это также означает, что после того, как вы реализуете определенную версию библиотеки поставщика, Camera2/X обеспечивает обратную совместимость библиотеки с будущими версиями extension-interface.
Прямая совместимость
Обратная совместимость с библиотеками поставщиков более новых версий extensions-interface зависит от вас, производителя оборудования. Если для работы расширений требуются определенные функции, вы можете включить расширения, начиная с определенной версии. В этом случае вы можете вернуть поддерживаемую версию extensions-interface, если версия библиотеки Camera2/X соответствует требованиям. Если версии Camera2/X не поддерживаются, вы можете вернуть несовместимую версию, например 99.0.0, чтобы отключить расширения.
Инициализация библиотеки поставщика
После проверки версии extensions-interface, реализованной библиотекой OEM, Camera2/X начинает процесс инициализации. Метод InitializerImpl.init() сообщает библиотеке OEM, что приложение пытается использовать расширения.
Camera2/X не выполняет других вызовов библиотеки OEM (кроме проверки версии), пока библиотека поставщика OEM не вызовет OnExtensionsInitializedCallback.onSuccess(), чтобы сообщить о завершении инициализации.
Вы должны реализовать
InitializerImpl
в версии extensions-interface 1.1.0. Camera2/X пропускает шаг инициализации библиотеки, если библиотека поставщика оборудования реализует extensions-interface 1.0.0.
Базовый и расширенный удлинитель
Существует два типа реализации extensions-interface: Basic Extender и Advanced Extender. Расширенный удлинитель поддерживается с версии extensions-interface 1.2.0.
Реализуйте Basic Extender для расширений, которые обрабатывают изображения в HAL камеры или используют постпроцессор, способный обрабатывать потоки YUV.
Реализуйте Advanced Extender для расширений, которым нужно настроить конфигурацию потока Camera2 и при необходимости отправлять запросы на съемку.
Сравнение приведено в таблице ниже.
| Базовый расширитель | Расширенный экстендер | |
|---|---|---|
| Настройки трансляции | Фиксированный Предварительный просмотр: PRIVATE или YUV_420_888 (если есть процессор)Фотосъемка: JPEG или YUV_420_888 (если есть процессор)
|
Настраивается OEM. |
| Отправка запроса на списание средств | Запросы на съемку может отправлять только Camera2/X. Вы можете задать параметры для этих запросов. Если процессор предоставляется для фотосъемки, Camera2/X может отправлять несколько запросов на захват и отправлять все изображения и результаты захвата процессору. | Экземпляр RequestProcessorImpl предоставляется вам для выполнения запроса на захват camera2 и получения результатов и изображения.
Camera2/X вызывает |
| Хуки в конвейере камеры |
|
|
| Подходит для | Расширения, реализованные в HAL камеры или в процессоре, который обрабатывает изображения YUV. |
|
| Поддерживаемая версия API | Расширения Camera2: Android 13 или более поздней версии. Расширения CameraX: camera-extensions 1.1.0 или более поздней версии. |
Расширения Camera2: Android 12L или более поздней версии. Расширения CameraX: camera-extensions 1.2.0-alpha03 или более поздней версии. |
Пути в приложении
В таблице ниже показаны три типа потоков приложений и соответствующие им вызовы API расширений камеры. Хотя Camera2/X предоставляет эти API, вам необходимо правильно реализовать библиотеку поставщика, чтобы поддерживать эти потоки, которые мы более подробно описываем в следующем разделе.
| Расширения Camera2 | Расширения CameraX | |
|---|---|---|
| Доступность расширения запросов | CameraExtensionCharacteristics
.getSupportedExtensions
|
ExtensionsManager.
isExtensionAvailable
|
| Информация о запросе | CameraExtensionCharacteristics.
getExtensionSupportedSizes
CameraExtensionCharacteristics.
getEstimatedCaptureLatencyRangeMillis
CameraExtensionCharacteristics.
getAvailableCaptureRequestKeys
CameraExtensionCharacteristics.
getAvailableCaptureResultKeys
|
ExtensionsManager.
getEstimatedCaptureLatencyRange
Остальную информацию обрабатывает библиотека CameraX. |
| Предварительный просмотр и фотосъемка с включенным расширением | CameraDevice.
createExtensionSession
|
val cameraSelector = ExtensionsManager.
getExtensionEnabledCameraSelector
|
Базовый расширитель
Интерфейс Basic Extender предоставляет хуки для нескольких мест в конвейере камеры. Для каждого типа расширения есть соответствующие классы Extender, которые должны реализовать OEM-производители.
В таблице ниже перечислены классы Extender, которые OEM-производители должны реализовать для каждого расширения.
| Классы расширений для реализации | |
|---|---|
| Ночь | NightPreviewExtenderImpl.java
|
| HDR | HdrPreviewExtenderImpl.java
|
| Авто | AutoPreviewExtenderImpl.java
|
| Боке | BokehPreviewExtenderImpl.java
|
| Ретушь лица | BeautyPreviewExtenderImpl.java
|
В следующем примере мы используем плейсхолдеры PreviewExtenderImpl и ImageCaptureExtenderImpl. Замените их названиями файлов, которые вы используете.
У Basic Extender есть следующие возможности:
- Добавьте параметры сеанса при настройке
CameraCaptureSession(onPresetSession). - Уведомлять вас о начале и завершении сеанса захвата и отправлять один запрос в HAL с возвращенными параметрами (
onEnableSession,onDisableSession). - Внедрите параметры записи для запроса (
PreviewExtenderImpl.getCaptureStage,ImageCaptureExtenderImpl.getCaptureStages). - Добавьте обработчики для предварительного просмотра и фотосъемки, которые могут обрабатывать поток
YUV_420_888.
Давайте посмотрим, как Camera2/X вызывает extensions-interface для реализации трех упомянутых выше сценариев использования приложений.
Сценарий 1. Проверка доступности расширения
Рисунок 3. Поток приложения 1 на базовом расширителе
В этом случае Camera2/X напрямую вызывает метод isExtensionAvailable() для PreviewExtenderImpl и ImageCaptureExtenderImpl, не вызывая init(). Оба класса Extender должны возвращать true, чтобы включить расширения.
Это часто первый шаг для приложений, чтобы проверить, поддерживается ли данный тип расширения для данного идентификатора камеры, прежде чем включать расширение. Это связано с тем, что некоторые расширения поддерживаются только определенными идентификаторами камер.
Схема 2. Запрос информации
Рисунок 4. Поток приложений 2 на базовом расширителе
Определив, доступно ли расширение, приложения должны запросить следующую информацию, прежде чем включать его.
Диапазон задержки захвата.
ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRangeвозвращает диапазон задержки захвата, чтобы приложение могло определить, подходит ли он для включения расширения в текущем сценарии.Поддерживаемые размеры для поверхности предварительного просмотра и захвата:
ImageCaptureExtenderImpl.getSupportedResolutionsиPreviewExtenderImpl.getSupportedResolutionsвозвращают список графических форматов и размеров, поддерживаемых для формата и размера поверхности.Поддерживаемые ключи запросов и результатов. Camera2/X вызывает следующие методы, чтобы получить поддерживаемые ключи запросов и результатов захвата из вашей реализации:
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeysImageCaptureExtenderImpl.getAvailableCapturetResultKeys
Camera2/X всегда сначала вызывает init() для этих классов Extender, прежде чем запрашивать дополнительную информацию.
Схема работы приложения 3: предварительный просмотр или съемка с включенным расширением (реализация HAL)
Рисунок 5. Приложение 3 на базовом расширителе
На приведенной выше схеме показан основной процесс включения предпросмотра и захвата неподвижного изображения с помощью расширения без процессора. Это означает, что HAL камеры обрабатывает расширение.
В этом случае Camera2/X сначала вызывает init(), а затем onInit, чтобы уведомить вас о том, что сеанс камеры будет запущен с указанными расширениями.
Вы можете выполнять ресурсоемкую инициализацию в onInit().
При настройке CameraCaptureSession Camera2/X вызывает onPresetSession, чтобы получить параметры сеанса. После успешной настройки сеанса захвата Camera2/X вызывает onEnableSession, возвращая экземпляр CaptureStageImpl, содержащий параметры захвата. Camera2/X
немедленно отправляет один запрос с этими параметрами захвата, чтобы уведомить HAL. Аналогично, перед закрытием сеанса съемки Camera2/X вызывает onDisableSession, а затем отправляет один запрос с возвращенными параметрами съемки.
Повторяющийся запрос, запущенный Camera2/X, содержит параметры запроса, возвращенные PreviewExtenderImpl.getCaptureStage(). Кроме того, запрос на съемку содержит параметры, возвращенные функцией ImageCaptureExtenderImpl.getCaptureStages().
Наконец, Camera2/X вызывает onDeInit() после завершения сеанса камеры.
Освободить ресурсы можно в приложении "onDeinit()".
Процессор предварительного просмотра
Помимо HAL камеры, вы также можете реализовать расширения в процессоре.
Чтобы указать тип процессора, используйте PreviewExtenderImpl.getProcessorType, как описано ниже.
PROCESSOR_TYPE_NONE: нет процессора. Изображения обрабатываются в HAL камеры.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY: Тип процессора позволяет обновлять повторяющийся запрос с новыми параметрами запроса на захват на основе последнихTotalCaptureResult.PreviewExtenderImpl.getProcessorдолжен возвращать экземплярRequestUpdateProcessorImpl, который обрабатывает экземплярTotalCaptureResultи возвращает экземплярCaptureStageImplдля обновления повторяющегося запроса.PreviewExtenderImpl.getCaptureStage()также должен отражать результат обработки и возвращать последнее значениеCaptureStageImpl.PROCESSOR_TYPE_IMAGE_PROCESSOR: этот тип позволяет реализовать процессор для обработки изображенийYUV_420_888и записи выходных данных на поверхностьPRIVATE.В
PreviewExtenderImpl.getProcessorнеобходимо реализовать и вернуть экземплярPreviewImageProcessorImpl. Процессор отвечает за обработку входных изображенийYUV_420_888. Выходные данные должны быть представлены в форматеPRIVATE. Camera2/X использует поверхностьYUV_420_888вместоPRIVATE, чтобы настроитьCameraCaptureSessionдля предварительного просмотра.Ниже показана схема процесса.
Рисунок 6. Предварительный просмотр процесса с PreviewImageProcessorImpl
Интерфейс PreviewImageProcessorImpl расширяет ProcessImpl и имеет три важных метода:
onOutputSurface(Surface surface, int imageFormat)задает выходную поверхность для процессора. ДляPreviewImageProcessorImplimageFormat– это формат изображения, напримерPixelFormat.RGBA_8888.onResolutionUpdate(Size size)– размер исходного изображения.onImageFormatUpdate(int imageFormat)задает графический формат входного изображения. В настоящее время поддерживается только значениеYUV_420_888.
Процессор обработки изображений
Для фотосъемки можно реализовать процессор, возвращающий экземпляр CaptureProcessorImpl с помощью ImageCaptureExtenderImpl.getCaptureProcessor. Процессор отвечает за обработку списка захваченных изображений YUV_420_888 и экземпляров TotalCaptureResult и запись выходных данных на поверхность YUV_420_888.
Вы можете быть уверены, что предварительный просмотр включен и работает, прежде чем отправлять запрос на захват изображения.
Ниже показана схема процесса.
Рисунок 7. Как сделать снимок с помощью приложения "CaptureProcessorImpl"
Camera2/X использует поверхность формата
YUV_420_888для фотосъемки, чтобы настроить сеанс съемки. Camera2/X подготавливаетCaptureProcessorImpl, вызывая:CaptureProcessorImpl.onImageFormatUpdate()сYUV_420_888.CaptureProcessorImpl.onResolutionUpdate()с размером входного изображения.CaptureProcessorImpl.onOutputSurface()с выходной поверхностьюYUV_420_888.
ImageCaptureExtenderImpl.getCaptureStagesвозвращает список объектовCaptureStageImpl, где каждый элемент сопоставляется с экземпляромCaptureRequestс параметрами съемки, которые отправляются Camera2/X. Например, если возвращается список из трех экземпляровCaptureStageImpl, Camera2/X отправляет три запроса на съемку с соответствующими параметрами, используя APIcaptureBurst.Полученные изображения и экземпляры
TotalCaptureResultобъединяются и отправляются вCaptureProcessorImplдля обработки.CaptureProcessorImplзаписывает результат Image (форматYUV_420_888) в выходную поверхность, указанную вызовомonOutputSurface(). При необходимости Camera2/X преобразует его в изображения JPEG.
Поддержка ключей запросов и результатов захвата
Помимо предпросмотра и съемки, приложения могут настраивать масштаб, параметры вспышки и запускать фокусировку по нажатию. Эти параметры могут быть несовместимы с реализацией расширения.
В extensions-interface 1.3.0 добавлены следующие методы, позволяющие передавать параметры, поддерживаемые вашей реализацией:
- Запрос
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys()возвращает ключи запроса на съемку, поддерживаемые вашей реализацией. ImageCaptureExtenderImpl.getAvailableCaptureResultKeys()возвращает ключи результатов съемки, которые содержатся в результате съемки.
Если HAL камеры обрабатывает расширение, Camera2/X получает результаты съемки в CameraCaptureSession.CaptureCallback. Однако если процессор реализован, то Camera2/X получает результаты съемки в ProcessResultImpl, который передается методу process() в PreviewImageProcessorImpl и CaptureProcessorImpl.
Вы должны передавать результат съемки в Camera2/X через ProcessResultImpl.
Ниже приведено определение интерфейса CaptureProcessorImpl.
В extensions-interface версии 1.3.0 или более поздней вызывается второй вызов process():
Interface CaptureProcessorImpl extends ProcessorImpl {
// invoked when extensions-interface version < 1.3.0
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
// invoked when extensions-interface version >= 1.3.0
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor);
}
Для распространенных операций с камерой, таких как масштабирование, фокусировка по нажатию, вспышка и компенсация экспозиции, мы рекомендуем поддерживать следующие ключи как для запроса на съемку, так и для результата съемки:
- Масштаб:
CaptureRequest#CONTROL_ZOOM_RATIOCaptureRequest#SCALER_CROP_REGION
- Фокусировка по нажатию.
CaptureRequest#CONTROL_AF_MODECaptureRequest#CONTROL_AF_TRIGGERCaptureRequest#CONTROL_AF_REGIONSCaptureRequest#CONTROL_AE_REGIONSCaptureRequest#CONTROL_AWB_REGIONS
- Flash:
CaptureRequest#CONTROL_AE_MODECaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGERCaptureRequest#FLASH_MODE
- Экспокоррекция:
CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
Для базовых расширений, в которых реализована версия 1.2.0 или более ранние версии, API CameraX Extensions явно поддерживает все перечисленные выше ключи. В версии extensions-interface 1.3.0 и CameraX, и Camera2 учитывают возвращенный список и поддерживают только ключи, которые в нем содержатся. Например, если вы решите вернуть только CaptureRequest#CONTROL_ZOOM_RATIO и CaptureRequest#SCALER_CROP_REGION в реализации 1.3.0, это будет означать, что для приложения поддерживается только масштабирование, а такие функции, как фокусировка по нажатию, вспышка и компенсация экспозиции, не разрешены.
Расширитель Advanced
Advanced Extender – это тип реализации поставщика на основе Camera2 API.
Этот тип Extender был добавлен в extensions-interface 1.2.0. В зависимости от производителя устройства расширения могут быть реализованы на уровне приложения, что зависит от следующих факторов:
Пользовательская конфигурация потока. Настройте пользовательские потоки, например RAW, или несколько потоков для разных идентификаторов физических камер.
Возможность отправлять запросы Camera2. Поддержка сложной логики взаимодействия, которая может отправлять запросы на съемку с параметрами на основе результатов предыдущих запросов.
Advanced Extender предоставляет оболочку или промежуточный слой, поэтому вы можете настроить конфигурацию потока и отправлять запросы на захват по требованию.
Файлы для реализации
Чтобы перейти на расширенную реализацию, метод isAdvancedExtenderImplemented() в ExtensionVersionImpl должен возвращать значение true. Для каждого типа расширения производители оригинального оборудования должны реализовать соответствующие классы Extender. Файлы реализации Advanced Extender находятся в пакете advanced.
| Классы расширения для реализации | |
|---|---|
| Ночь | advanced/NightAdvancedExtenderImpl.java
|
| HDR | advanced/HdrAdvancedExtenderImpl.java
|
| Авто | advanced/AutoAdvancedExtenderImpl.java
|
| Боке | advanced/BokehAdvancedExtenderImpl.java
|
| Ретушь лица | advanced/BeautyAdvancedExtenderImpl.java
|
В следующем примере мы используем плейсхолдер AdvancedExtenderImpl.
Замените его названием файла Extender для расширения, которое вы реализуете.
Давайте посмотрим, как Camera2/X вызывает extensions-interface для трех сценариев использования приложения.
Процесс в приложении 1. Проверка доступности расширений
Рисунок 8. Процесс в приложении 1 на расширенном повторителе
Сначала приложение проверяет, поддерживается ли расширение.
Схема 2. Запрос информации
Рисунок 9. Приложение 2 на устройстве Advanced Extender
После вызова метода AdvancedExtenderImpl.init() приложение может запросить следующую информацию о AdvancedExtenderImpl:
Ориентировочная задержка при съемке неподвижных изображений.
AdvancedExtenderImpl.getEstimatedCaptureLatencyRange()возвращает диапазон задержки съемки, чтобы приложение могло оценить, подходит ли расширение для текущего сценария.Поддерживаемые разрешения для предварительного просмотра и съемки фотографий:
AdvancedExtenderImpl.getSupportedPreviewOutputResolutions()возвращает карту графического формата в список размеров, поддерживаемых для формата и размера поверхности предварительного просмотра. Производители устройств должны поддерживать хотя бы форматPRIVATE.AdvancedExtenderImpl.getSupportedCaptureOutputResolutions()возвращает поддерживаемые форматы и размеры для поверхности захвата неподвижного изображения. Производители оригинального оборудования должны поддерживать вывод в форматахJPEGиYUV_420_888.AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()возвращает поддерживаемые размеры для дополнительного потокаYUV_420_888, используемого для анализа изображений. Если поверхность YUV для анализа изображений не поддерживается, функцияgetSupportedYuvAnalysisResolutions()должна возвращатьnullили пустой список.
Доступные ключи/результаты запроса на съемку (добавлено в
extensions-interface1.3.0). Camera2/X вызывает следующие методы, чтобы получить поддерживаемые ключи запроса на съемку и ключи результатов из вашей реализации:AdvancedExtenderImpl.getAvailableCaptureRequestKeysAdvancedExtenderImpl.getAvailableCaptureResultKeys
Подробнее о ключах запросов и результатах захвата…
Сценарий 3. Предпросмотр или съемка с включенным расширением
Рисунок 10. Приложение 3 на устройстве Advanced Extender
На приведенной выше схеме показан основной процесс запуска предварительного просмотра и захвата неподвижного изображения для расширенного типа удлинителя. Давайте рассмотрим каждый шаг.
Экземпляр
SessionProcessorImplОсновная реализация Advanced Extender находится в
SessionProcessorImpl, который отвечает за предоставление настраиваемой конфигурации сеанса и отправку запросов на захват для запуска предварительного просмотра и запроса на захват неподвижного изображения.AdvancedExtenderImpl.createSessionProcessor()вызывается для возврата экземпляраSessionProcessorImpl.initSessionSessionProcessorImpl.initSession()инициализирует сеанс для расширения. Здесь вы выделяете ресурсы и возвращаете конфигурацию сеанса для подготовкиCameraCaptureSession.Для входных параметров Camera2/X задает конфигурации выходной поверхности для предварительного просмотра, съемки и анализа изображений YUV (необязательно). Эта конфигурация выходной поверхности (
OutputSurfaceImpl) содержит поверхность, размер и формат изображения, которые извлекаются с помощью следующих методов вAdvancedExtenderImpl:getSupportedPreviewOutputResolutions()getSupportedCaptureOutputResolutions()getSupportedYuvAnalysisResolutions()
Вы должны вернуть экземпляр
Camera2SessionConfigImpl, который состоит из списка экземпляровCamera2OutputConfigImplи параметров сеанса, использованных для настройкиCameraCaptureSession. Вы отвечаете за вывод правильных изображений с камеры на выходные поверхности, переданные Camera2/X. Вот несколько вариантов:- Обработка в HAL камеры. Вы можете напрямую добавить выходные поверхности в
CameraCaptureSessionс помощью реализацииSurfaceOutputConfigImpl. Это позволяет настроить предоставленную выходную поверхность для конвейера камеры и разрешить аппаратно-зависимому уровню камеры обработать изображение. Обработка промежуточной поверхности
ImageReader(RAW, YUV и т. д.). Добавьте промежуточные поверхностиImageReaderвCameraCaptureSessionс экземпляромImageReaderOutputConfigImpl.Вам нужно обработать промежуточные изображения и записать результат на выходную поверхность.
- Используйте совместное использование Surface в Camera2. Используйте совместное использование Surface с другим Surface, добавив любой экземпляр
Camera2OutputConfigImplв методgetSurfaceSharingOutputConfigs()другого экземпляраCamera2OutputConfigImpl. Формат и размер поверхности должны быть одинаковыми.
У всех элементов
Camera2OutputConfigImpl, включаяSurfaceOutputConfigImplиImageReaderOutputConfigImpl, должен быть уникальный идентификатор (getId()), который используется для указания целевой платформы и получения изображения изImageReaderOutputConfigImpl.onCaptureSessionStartиRequestProcessorImplКогда запускается
CameraCaptureSessionи фреймворк камеры вызываетonConfigured(), Camera2/X вызываетSessionProcessorImpl.onCaptureSessionStart()с оберткой запроса Camera2RequestProcessImpl. Camera2/X реализуетRequestProcessImpl, что позволяет выполнять запросы на съемку и получать изображения, если используетсяImageReaderOutputConfigImpl.API
RequestProcessImplпохожи на API Camera2CameraCaptureSessionв плане выполнения запросов. Вот в чем разница:- Целевая поверхность определяется идентификатором экземпляра
Camera2OutputConfigImpl. - Возможность получить изображение
ImageReader.
Вы можете вызвать
RequestProcessorImpl.setImageProcessor()с указанным идентификаторомCamera2OutputConfigImpl, чтобы зарегистрировать экземплярImageProcessorImplдля получения изображений.Экземпляр
RequestProcessImplстановится недействительным после того, как Camera2/X вызываетSessionProcessorImpl.onCaptureSessionEnd().- Целевая поверхность определяется идентификатором экземпляра
Как запустить предварительный просмотр и сделать снимок
В расширенной реализации Extender вы можете отправлять запросы на захват через интерфейс
RequestProcessorImpl. Camera2/X уведомляет вас о необходимости запустить повторяющийся запрос для предпросмотра или последовательность захвата неподвижного изображения, вызываяSessionProcessorImpl#startRepeatingиSessionProcessorImpl#startCaptureсоответственно. Чтобы выполнить эти запросы предварительного просмотра и запросы на получение снимков, вам нужно отправить запросы на захват.Camera2/X также задает параметры запроса на съемку через
SessionProcessorImpl#setParameters. Эти параметры запроса (если они поддерживаются) необходимо задать как для повторяющихся, так и для однократных запросов.Вы должны поддерживать как минимум
CaptureRequest.JPEG_ORIENTATIONиCaptureRequest.JPEG_QUALITY.extensions-interface1.3.0 поддерживает ключи запросов и результатов, которые доступны с помощью следующих методов:AdvancedExtenderImpl.getAvailableCaptureRequestKeys()AdvancedExtenderImpl.getAvailableCaptureResultKeys()
Когда разработчики задают ключи в списке
getAvailableCaptureRequestKeys, вы должны включить параметры и убедиться, что результат захвата содержит ключи из спискаgetAvailableCaptureResultKeys.startTriggerSessionProcessorImpl.startTrigger()вызывается для запуска триггера, напримерCaptureRequest.CONTROL_AF_TRIGGERиCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Вы можете игнорировать ключи запроса на захват, которые не были указаны вAdvancedExtenderImpl.getAvailableCaptureRequestKeys().startTrigger()поддерживается с версииextensions-interface1.3.0. Она позволяет приложениям использовать фокусировку по нажатию и вспышку с расширениями.Удаление ненужных объектов
При завершении сеанса захвата перед закрытием
CameraCaptureSessionвызываетсяSessionProcessorImpl.onCaptureSessionEnd(). После завершения сеанса захватаdeInitSession()выполняет очистку.
Поддержка предварительного просмотра, фотосъемки и анализа изображений.
Расширение следует применять как для предварительного просмотра, так и для съемки. Однако если задержка слишком велика, чтобы плавно показывать предпросмотр, вы можете применить расширение только для фотосъемки.
Для типа "Базовый расширитель" независимо от того, включено ли расширение для предварительного просмотра, необходимо реализовать оба параметра: ImageCaptureExtenderImpl и PreviewExtenderImpl. Часто приложение также использует поток YUV для анализа содержимого изображения, например для поиска QR-кодов или текста. Чтобы лучше поддерживать этот вариант использования, вам следует реализовать комбинацию потоков предварительного просмотра, захвата неподвижного изображения и потока YUV_420_888 для настройки CameraCaptureSession. Это означает, что если вы используете обработчик, то должны поддерживать комбинацию из трех потоков YUV_420_888.
В случае с Advanced Extender Camera2/X передает три выходные поверхности в вызов SessionProcessorImpl.initSession(). Эти поверхности используются для предварительного просмотра, съемки фотографий и анализа изображений соответственно. Убедитесь, что на поверхностях вывода предварительного просмотра и захвата неподвижных изображений отображаются допустимые выходные данные. Однако для выходной поверхности анализа изображений убедитесь, что она работает только тогда, когда она не равна null. Если ваша реализация не поддерживает поток анализа изображений, вы можете вернуть пустой список в AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). Это гарантирует, что выходная поверхность анализа изображений всегда будет иметь значение null в SessionProcessorImpl.initSession().
Поддержка записи видео
Текущая архитектура расширения камеры поддерживает только предварительный просмотр и съемку фотографий. Мы не поддерживаем включение расширения на страницах MediaCodec
или MediaRecorder для записи видео. Однако приложения могут записывать предварительный просмотр.
Мы рассматриваем возможность поддержки платформ MediaCodec и MediaRecorder.
Метаданные, относящиеся к расширениям
В Android 14 и более поздних версиях метаданные, относящиеся к расширению, позволяют клиентам расширения камеры задавать и получать настройки запроса на съемку и результаты, относящиеся к расширению. В частности, клиенты расширения камеры могут использовать параметр запроса на съемку EXTENSION_STRENGTH, чтобы управлять интенсивностью расширения, и результат съемки EXTENSION_CURRENT_TYPE, чтобы указать тип включенного расширения.
Запросы на получение данных
Параметр запроса EXTENSION_STRENGTH
capture
определяет силу эффекта постобработки расширения. Если клиент не задал этот параметр явно, соответствующий результат съемки будет включать значение интенсивности по умолчанию. Этот параметр можно применять к следующим типам расширений:
BOKEH– позволяет управлять степенью размытия.HDRиNIGHT– позволяют управлять количеством объединенных изображений и яркостью финального изображения.FACE_RETOUCH– позволяет управлять степенью улучшения внешности и сглаживания кожи.
Параметр EXTENSION_STRENGTH может принимать значения от 0 до 100. Значение 0 означает, что обработка расширения не выполняется или выполняется простое сквозное преобразование, а значение 100 – что эффект расширения применяется с максимальной интенсивностью.
Чтобы добавить поддержку EXTENSION_STRENGTH, используйте API параметров, относящихся к поставщику, которые появились в версии 1.3.0 интерфейса библиотеки расширений. Дополнительную информацию вы найдете в статье getAvailableCaptureRequestKeys().
Результаты сканирования
Результат захвата EXTENSION_CURRENT_TYPE позволяет реализациям расширений уведомлять клиентов об активном типе расширения.
Поскольку расширения типа AUTO динамически переключаются между типами расширений, такими как HDR и NIGHT, в зависимости от условий съемки, приложения для расширений камеры могут использовать EXTENSION_CURRENT_TYPE, чтобы показывать информацию о текущем расширении, выбранном расширением AUTO.
Оценка задержки при съемке в реальном времени
В Android 14 и более поздних версий клиенты расширения камеры могут запрашивать оценки задержки при съемке неподвижных объектов в реальном времени на основе условий сцены и окружающей среды с помощью getRealtimeStillCaptureLatency(). Этот метод позволяет получать более точные оценки, чем статический метод getEstimatedCaptureLatencyRangeMillis(). На основе оценки задержки приложения могут пропускать обработку расширения или показывать пользователям уведомление о том, что операция выполняется долго.
CameraExtensionSession.StillCaptureLatency latency;
latency = extensionSession.getRealtimeStillCaptureLatency();
// The capture latency from ExtensionCaptureCallback#onCaptureStarted() until ExtensionCaptureCallback#onCaptureProcessStarted().
latency.getCaptureLatency();
// The processing latency from ExtensionCaptureCallback#onCaptureProcessStarted() until the processed frame returns to the client.
latency.getProcessingLatency();
Чтобы поддерживать оценку задержки при съемке фотографий в реальном времени, реализуйте следующее:
- Базовые расширения:
ImageCaptureExtenderImpl.getRealtimeCaptureLatency() - Расширенные расширения:
SessionProcessorImpl.getRealtimeCaptureLatency
Обратные вызовы для отслеживания прогресса обработки захвата
В Android 14 и более поздних версий клиенты расширений камеры могут получать обратные вызовы для отслеживания прогресса длительных операций обработки неподвижных изображений. Приложения могут показывать пользователям текущий прогресс, чтобы улучшить общее впечатление от работы с ними.
Чтобы интегрировать эту функцию в приложение, используйте следующий код:
import android.hardware.camera2.CameraExtensionSession.
ExtensionCaptureCallback;
{
…
class AppCallbackImpl extends ExtensionCaptureCallback {
…
@Override
public void onCaptureProcessProgressed(
@NonNull CameraExtensionSession session,
@NonNull CaptureRequest request,
@IntRange(from = 0, to = 100) int progress) {
// Update app UI with current progress
}
}
…
}
Чтобы поддерживать обратные вызовы для отслеживания прогресса обработки захвата, реализация поставщика расширения должна вызывать следующие обратные вызовы с текущим значением прогресса:
- Базовые расширения:
ProcessResultImpl.onCaptureProcessProgressed() - Расширенные расширения:
CaptureCallback.onCaptureProcessProgressed()
Конверсии после просмотра
В Android 14 и более поздних версиях расширения камеры могут предоставлять изображение для предпросмотра с помощью setPostviewOutputConfiguration.
Чтобы улучшить удобство использования [*], приложения могут показывать изображение после просмотра в качестве плейсхолдера, когда у расширения наблюдается повышенная задержка обработки, и заменять его, когда будет доступно финальное изображение. Приложения могут настраивать и отправлять запросы на сбор данных о конверсиях после просмотра с помощью следующего кода:
{
…
if (!CameraExtensionCharacteristics.isPostviewAvailable()) {
continue;
}
…
ExtensionSessionConfiguration extensionConfiguration = new
ExtensionSessionConfiguration(
CameraExtensionCharacteristics.EXTENSION_NIGHT,
outputConfig,
backgroundExecutor,
extensionSessionStateCallback
);
extensionConfiguration.setPostviewOutputConfiguration(
postviewImageOutput);
…
CaptureRequest.Builder captureRequestBuilder =
cameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(stillImageReader.getSurface());
captureRequestBuilder.addTarget(postviewImageSurface);
CaptureRequest captureRequest = captureRequestBuilder.build();
…
}
Чтобы поддерживать захват неподвижного изображения после просмотра, реализация поставщика должна включать следующие компоненты:
Базовые расширения:
CaptureProcessorImpl.onPostviewOutputSurfaceиCaptureProcessorImpl.processWithPostviewРасширенные расширения:
SessionProcessorImpl.startCaptureWithPostview
Поддержка вывода SurfaceView
В Android 14 и более поздних версий клиенты расширения камеры могут использовать оптимизированные по энергопотреблению и производительности пути отрисовки предварительного просмотра, зарегистрировав экземпляр SurfaceView для вывода предварительного просмотра для повторяющихся запросов.
Чтобы поддерживать вывод в формате SurfaceView, реализация расширения поставщика должна быть способна передавать и выводить предварительный просмотр в экземпляры SurfaceView. Чтобы проверить, поддерживается ли эта функция, запустите модуль SurfaceViewExtensionPreviewTest.javaCTS.
Типы сеансов, относящиеся к поставщику
Эта функция позволяет реализациям расширений поставщиков выбирать тип сеанса, который будет задан во внутреннем сеансе захвата камеры вместо значения по умолчанию.
Функция работает полностью в рамках платформы и стека поставщика и не влияет на общедоступные API.
Чтобы выбрать тип сеанса, относящийся к определенному поставщику, реализуйте следующие библиотеки расширений:
* ExtenderStateListener.onSessionType() – для базовых расширений;
* Camera2SessionConfigImpl.getSessionType() – для расширенных расширений.
История версий интерфейса расширений
В таблице ниже приведена история версий интерфейса Camera Extension. Всегда используйте последнюю версию библиотеки поставщика.
| Версия | Добавленные функции |
|---|---|
| 1.0.0 |
|
| 1.1.0 |
|
| 1.2.0 |
|
| 1.3.0 |
|
| 1.4.0 |
|
Пример реализации
В frameworks/ex доступны следующие реализации справочных библиотек поставщиков оборудования:
advancedSample– базовая реализация расширенного расширителя.sample: базовый вариант расширителя.service_based_sample– реализация, демонстрирующая, как размещать расширения камеры вService. Эта реализация содержит следующие компоненты:oem_library: Библиотека OEM-расширений камеры для Camera2 и CameraX Extensions API, реализующаяExtensions-Interface. Он действует как шлюз, который перенаправляет вызовы изExtensions-Interfaceв сервис. Эта библиотека также содержит файлы AIDL и классы-оболочки для взаимодействия с сервисом.Расширенный экстендер включен по умолчанию. Чтобы включить базовый расширитель, измените
ExtensionsVersionImpl#isAdvancedExtenderImplementedтак, чтобы возвращалось значениеfalse.extensions_service: Пример реализации сервиса расширений. Добавьте сюда свою реализацию. Интерфейс, который нужно реализовать в сервисе, похож наExtensions-Interface. Например, реализацияIAdvancedExtenderImpl.Stubвыполняет те же операции, что иAdvancedExtenderImpl.ImageWrapperиTotalCaptureResultWrapperнеобходимы для того, чтобы объектыImageиTotalCaptureResultможно было сериализовать.
Как настроить библиотеку поставщика на устройстве
Библиотека поставщика OEM не встроена в приложение. Она загружается из устройства во время выполнения Camera2/X. В CameraX тег <uses-library> указывает, что библиотека androidx.camera.extensions.impl, определенная в файле AndroidManifest.xml библиотеки camera-extensions, является зависимостью CameraX и должна быть загружена во время выполнения. В Camera2 фреймворк загружает сервис расширений, который также объявляет, что <uses-library> загружает ту же библиотеку androidx.camera.extensions.impl во время выполнения.
Это позволяет сторонним приложениям, использующим расширения, автоматически загружать библиотеку поставщика OEM. Библиотека OEM помечена как необязательная, чтобы приложения могли работать на устройствах, на которых она не установлена. Camera2/X автоматически обрабатывает эту ситуацию, когда приложение пытается использовать расширение камеры, если производитель устройства разместил на нем библиотеку OEM, чтобы приложение могло ее обнаружить.
Чтобы настроить библиотеку OEM на устройстве, выполните следующие действия:
- Добавьте файл разрешений, который требуется для тега
<uses-library>, в следующем формате:/etc/permissions/ANY_FILENAME.xml. Например,/etc/permissions/camera_extensions.xml. Файлы в этом каталоге содержат сопоставление библиотеки, указанной в<uses-library>, с фактическим путем к файлу на устройстве. Ниже приведен пример того, как добавить в файл необходимую информацию.
nameдолжно бытьandroidx.camera.extensions.impl, так как это библиотека, которую ищет CameraX.file– это абсолютный путь к файлу, в котором реализованы расширения (например,/system/framework/androidx.camera.extensions.impl.jar).
<?xml version="1.0" encoding="utf-8"?> <permissions> <library name="androidx.camera.extensions.impl" file="OEM_IMPLEMENTED_JAR" /> </permissions>
В Android 12 и более поздних версиях на устройствах, поддерживающих расширения CameraX, свойство ro.camerax.extensions.enabled должно иметь значение true. Это позволяет запрашивать информацию о том, поддерживает ли устройство расширения.
Для этого добавьте в файл производителя устройства следующую строку:
PRODUCT_VENDOR_PROPERTIES += \
ro.camerax.extensions.enabled=true \
Проверка
Чтобы протестировать реализацию библиотеки поставщика оборудования на этапе разработки, используйте пример приложения по адресу androidx-main/camera/integration-tests/extensionstestapp/, в котором выполняются различные расширения поставщика.
После завершения реализации используйте инструмент проверки расширений камеры для запуска автоматических и ручных тестов, чтобы убедиться, что библиотека поставщика реализована правильно.
Режим расширенной сцены и расширения камеры
Чтобы использовать расширение боке, его можно добавить не только с помощью расширений камеры, но и с помощью расширенного режима съемки, который включается с помощью ключа CONTROL_EXTENDED_SCENE_MODE.
Подробнее о боке камеры…
У расширенного режима сцены меньше ограничений, чем у расширений камеры для приложений camera2. Например, вы можете включить расширенный режим сцены в обычном экземпляре CameraCaptureSession, который поддерживает гибкие комбинации потоков и параметры запроса на съемку. Расширения камеры поддерживают только фиксированный набор типов потоков и имеют ограниченную поддержку параметров запроса на захват.
Недостаток расширенного режима сцены заключается в том, что его можно реализовать только на уровне HAL камеры. Это означает, что необходимо проверить его работу со всеми ортогональными элементами управления, доступными разработчикам приложений.
Мы рекомендуем реализовать эффект боке с помощью расширенного режима съемки и расширений Camera, поскольку приложения могут предпочитать определенный API для включения этого эффекта. Мы рекомендуем сначала использовать расширенный режим сцены, поскольку это самый гибкий способ включить расширение боке в приложениях. Затем вы можете реализовать интерфейс расширений камеры на основе расширенного режима сцены. Если реализовать эффект боке в HAL камеры сложно, например потому что для обработки изображений требуется постпроцессор, работающий на уровне приложения, мы рекомендуем реализовать расширение боке с помощью интерфейса Camera Extensions.
Часто задаваемые вопросы
Есть ли ограничения на уровни API?
Да. Это зависит от набора функций Android API, необходимых для реализации библиотеки поставщика оригинального оборудования. Например, в ExtenderStateListener.onPresetSession() для установки базового набора тегов используется вызов SessionConfiguration.setSessionParameters(). Этот вызов доступен только на устройствах с уровнем API 28 и выше. Подробную информацию о методах интерфейса можно найти в справочной документации по API.