Производители устройств могут предоставлять сторонним разработчикам доступ к таким расширениям, как эффект боке, ночной режим и HDR, через интерфейс расширений камеры, предоставляемый библиотекой OEM-производителя. Разработчики могут использовать API расширений Camera2 и API расширений CameraX для доступа к расширениям, реализованным в библиотеке OEM-производителя.
Список поддерживаемых расширений, одинаковый для Camera2 и CameraX, см. в разделе CameraX Extensions API . Если вы хотите добавить расширение, сообщите об ошибке в системе отслеживания ошибок .
На этой странице описано, как внедрить и включить библиотеку OEM-производителя на устройствах.
Архитектура
На следующей диаграмме представлена архитектура интерфейса расширений камеры или extensions-interface : 
Рисунок 1. Архитектурная схема расширений камеры.
Как показано на диаграмме, для поддержки расширений камеры необходимо реализовать extensions-interface предоставляемый библиотекой OEM-производителя. Ваша библиотека OEM-производителя поддерживает два API: CameraX Extensions API и Camera2 Extensions API , которые используются приложениями CameraX и Camera2 соответственно для доступа к расширениям поставщика.
Внедрить библиотеку OEM-поставщика.
Для внедрения библиотеки OEM-производителя скопируйте файлы camera-extensions-stub в проект системной библиотеки. Эти файлы определяют интерфейс расширений камеры.
Файлы camera-extensions-stub разделены на следующие категории:
Основные файлы интерфейса (не изменять)
-
PreviewExtenderImpl.java -
ImageCaptureExtenderImpl.java -
ExtenderStateListener.java -
ProcessorImpl.java -
PreviewImageProcessorImpl.java -
CaptureProcessorImpl.java -
CaptureStageImpl.java -
RequestUpdateProcessorImpl.java -
ProcessResultImpl.java -
advanced/AdvancedExtenderImpl.java -
advanced/Camera2OutputConfigImpl.java -
advanced/Camera2SessionConfigImpl.java -
advanced/ImageProcessorImpl.java -
advanced/ImageReaderOutputConfigImpl.java -
advanced/ImageReferenceImpl.java -
advanced/MultiResolutionImageReaderOutputConfigImpl.java -
advanced/OutputSurfaceImpl.java -
advanced/RequestProcessorImpl.java -
advanced/SessionProcessorImpl.java -
advanced/SurfaceOutputConfigImpl.java
Обязательные реализации (добавьте свою реализацию)
-
ExtensionVersionImpl.java -
InitializerImpl.java
Классы расширения эффекта боке (реализуйте их, если расширение эффекта боке поддерживается).
-
BokehImageCaptureExtenderImpl.java -
BokehPreviewExtenderImpl.java -
advanced/BokehAdvancedExtenderImpl.java
Классы расширения для ночного режима (реализуйте их, если расширение для ночного режима поддерживается).
-
NightImageCaptureExtenderImpl.java -
NightPreviewExtenderImpl.java -
advanced/NightAdvancedExtenderImpl.java
Классы автоматического расширения (реализуйте их, если автоматическое расширение поддерживается).
-
AutoImageCaptureExtenderImpl.java -
AutoPreviewExtenderImpl.java -
advanced/AutoAdvancedExtenderImpl.java
Классы расширения HDR (реализуйте их, если расширение HDR поддерживается)
-
HdrImageCaptureExtenderImpl.java -
HdrPreviewExtenderImpl.java -
advanced/HdrAdvancedExtenderImpl.java
Расширенные классы для функции Face Retouch (реализуйте их, если расширение Face Retouch поддерживается).
-
BeautyImageCaptureExtenderImpl.java -
BeautyPreviewExtenderImpl.java -
advanced/BeautyAdvancedExtenderImpl.java
Вспомогательные программы (необязательно, можно удалить)
-
advanced/Camera2OutputConfigImplBuilder.java -
advanced/Camera2SessionConfigImplBuilder.java
Вам не обязательно предоставлять реализацию для каждого расширения. Если вы не реализуете расширение, установите isExtensionAvailable() в значение false или удалите соответствующие классы Extender. API расширений Camera2 и CameraX сообщают приложению о недоступности расширения.
Давайте рассмотрим, как API расширений Camera2 и CameraX взаимодействуют с библиотекой поставщика для активации расширения. Следующая диаграмма иллюстрирует весь процесс от начала до конца, используя в качестве примера расширение Night:

Рисунок 2. Реализация ночного расширения.
Проверка версии:
Camera2/X вызывает
ExtensionVersionImpl.checkApiVersion(), чтобы убедиться, что версияextensions-interfaceреализованная производителем оборудования, совместима с версиями, поддерживаемыми Camera2/X.Инициализация библиотеки поставщика:
InitializerImplесть методinit(), который инициализирует библиотеку поставщика. Camera2/X завершает инициализацию перед доступом к классам Extender.Создание экземпляров классов-расширителей:
Создает экземпляры классов-расширителей для расширения. Существует два типа расширителей: базовый и расширенный. Для всех расширений необходимо реализовать один тип расширителя. Дополнительную информацию см. в разделе «Базовый и расширенный расширители» .
Camera2/X создает экземпляры классов Extender и взаимодействует с ними для получения информации и активации расширения. Для данного расширения Camera2/X может создавать экземпляры классов Extender несколько раз. Поэтому не следует выполнять ресурсоемкую инициализацию в конструкторе или вызове
init(). Выполняйте ресурсоемкую инициализацию только перед началом сеанса работы с камерой, например, при вызовеonInit()в базовом Extender илиinitSession()в расширенном Extender.Для расширения «Ночной режим» для типа «Базовый расширитель» создаются экземпляры следующих классов расширителей:
-
NightImageCaptureExtenderImpl.java -
NightPreviewExtenderImpl.java
А для типа Advanced Extender:
-
NightAdvancedExtenderImpl.java
-
Проверить доступность расширения:
Перед включением расширения функция
isExtensionAvailable()проверяет, доступно ли расширение для указанного идентификатора камеры через экземпляр Extender.Инициализируйте расширитель, используя информацию с камеры:
Camera2/X вызывает
init()для экземпляра Extender и передает ему идентификатор камеры иCameraCharacteristics.Информация по запросу:
Вызывает класс Extender для получения такой информации, как поддерживаемые разрешения, при этом фиксируется предполагаемая задержка, а также захватываются ключи запроса от Extender в рамках подготовки к включению расширения.
Включить расширение на расширителе:
Класс Extender предоставляет все необходимые интерфейсы для активации класса. Он предлагает механизм для подключения реализации OEM-производителя к конвейеру Camera2, например, путем внедрения параметров запроса захвата или включения постобработки.
Для типа Advanced Extender Camera2/X взаимодействует с
SessionProcessorImplдля включения расширения. Camera2/X получает экземплярSessionProcessorImpl, вызываяcreateSessionProcessor()для Extender.
В следующих разделах процесс расширения описан более подробно.
Проверка версии
При загрузке библиотеки OEM-производителя с устройства во время выполнения Camera2/X проверяет, совместима ли библиотека с версией extensions-interface . extensions-interface использует семантическое версионирование, или MAJOR.MINOR.PATCH, например, 1.1.0 или 1.2.0. Однако при проверке версии используются только основная и дополнительная версии.
Для проверки версии Camera2/X вызывает ExtensionVersionImpl.checkApiVersion() с указанием поддерживаемой версии extensions-interface . Затем Camera2/X использует версию, сообщенную библиотекой OEM, чтобы определить, можно ли включить расширение и какие возможности оно должно активировать.
совместимость основных версий
Если основные версии интерфейса расширения различаются между Camera2/X и библиотекой поставщика, то это считается несовместимым , и расширение отключается.
Обратная совместимость
Пока основная версия идентична, Camera2/X обеспечивает обратную совместимость с библиотеками OEM-производителей, созданными на основе более ранних версий extensions-interface . Например, если Camera2/X поддерживает extensions-interface 1.3.0, библиотеки OEM-производителей, в которых реализованы версии 1.0.0, 1.1.0 и 1.2.0, по-прежнему будут совместимы. Это также означает, что после внедрения определенной версии библиотеки производителя Camera2/X гарантирует обратную совместимость библиотеки с будущими версиями extension-interface .
Обратная совместимость
Обратная совместимость с библиотеками поставщиков более новых extensions-interface зависит от вас, OEM-производителя. Если вам необходимы некоторые функции для реализации расширений, вы можете включить их, начиная с определенной версии. В этом случае вы можете вернуть поддерживаемую версию extensions-interface если версия библиотеки Camera2/X соответствует требованиям. Если версии Camera2/X не поддерживаются, вы можете вернуть несовместимую версию, например 99.0.0, чтобы отключить расширения.
Инициализация библиотеки поставщика
После проверки версии extensions-interface реализованной библиотекой OEM-производителя, Camera2/X запускает процесс инициализации. Метод InitializerImpl.init() сообщает библиотеке OEM-производителя о том, что приложение пытается использовать расширения.
Camera2/X не выполняет никаких других вызовов к библиотеке OEM-производителя (кроме проверки версии) до тех пор, пока библиотека OEM-производителя не вызовет OnExtensionsInitializedCallback.onSuccess() для уведомления о завершении инициализации.
Начиная с версии extensions-interface 1.1.0, необходимо реализовать InitializerImpl . Camera2/X пропускает этап инициализации библиотеки, если библиотека OEM-производителя реализует extensions-interface 1.0.0.
Базовый расширитель против расширенного расширителя
Существует два типа реализации extensions-interface : базовый расширитель и расширенный расширитель. Поддержка расширенного расширителя появилась начиная с версии 1.2.0 extensions-interface .
Реализуйте базовый расширитель для расширений, обрабатывающих изображения в HAL камеры или использующих постпроцессор, способный обрабатывать потоки YUV.
Внедрите Advanced Extender для расширений, которым необходимо настраивать конфигурацию потока Camera2 и отправлять запросы на захват по мере необходимости.
Для сравнения см. следующую таблицу:
| Базовый расширитель | Расширенный расширитель | |
|---|---|---|
| Настройки потоков | Зафиксированный Предварительный просмотр: PRIVATE или YUV_420_888 (если процессор существует)Фото: JPEG или YUV_420_888 (если есть процессор) | Возможно изготовление на заказ производителем оригинального оборудования (OEM). |
| Отправка запроса на захват | Только Camera2/X может отправлять запросы на захват изображения. Вы можете задать параметры для этих запросов. Если для захвата изображения предоставлен процессор, Camera2/X может отправлять несколько запросов на захват и передавать все изображения и результаты захвата процессору. | Для выполнения запроса на захват изображения камерой Camera2 и получения результатов и изображения предоставляется экземпляр RequestProcessorImpl . 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. getEstimatedCaptureLatencyRangeCameraX обрабатывает остальную информацию в библиотеке. |
| Предварительный просмотр и съемка фотографий с включенным расширением. | CameraDevice. createExtensionSession | val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...) |
Базовый расширитель
Базовый интерфейс Extender обеспечивает подключение к нескольким точкам конвейера обработки данных камеры. Для каждого типа расширения существуют соответствующие классы Extender, которые производители оборудования должны реализовать.
В таблице ниже перечислены классы расширителей, которые производители оборудования должны реализовать для каждого расширения:
| Расширяющие классы для реализации | |
|---|---|
| Ночь | NightPreviewExtenderImpl.java |
| HDR | HdrPreviewExtenderImpl.java |
| Авто | AutoPreviewExtenderImpl.java |
| Боке | BokehPreviewExtenderImpl.java |
| Ретушь лица | BeautyPreviewExtenderImpl.java |
В следующем примере мы используем PreviewExtenderImpl и ImageCaptureExtenderImpl в качестве заполнителей. Замените их именами фактических файлов, которые вы используете.
Базовая версия расширителя обладает следующими возможностями:
- Внедрите параметры сессии при настройке
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.getAvailableCaptureRequestKeys -
ImageCaptureExtenderImpl.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поверхность.Вам необходимо реализовать и вернуть экземпляр
PreviewImageProcessorImplвPreviewExtenderImpl.getProcessor. Этот процессор отвечает за обработку входных изображений в формате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()withYUV_420_888. - Используйте
CaptureProcessorImpl.onResolutionUpdate()для указания размера входного изображения. -
CaptureProcessorImpl.onOutputSurface()с выходной поверхностьюYUV_420_888.
-
ImageCaptureExtenderImpl.getCaptureStagesвозвращает список объектовCaptureStageImpl, где каждый элемент соответствует экземпляруCaptureRequestс параметрами захвата, отправляемыми Camera2/X. Например, если метод возвращает список из трех экземпляровCaptureStageImpl, Camera2/X отправляет три запроса на захват с соответствующими параметрами захвата, используя APIcaptureBurst.Полученные изображения и экземпляры
TotalCaptureResultобъединяются и отправляются вCaptureProcessorImplдля обработки.CaptureProcessorImplзаписывает результирующее изображение (в формате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 . Вы отвечаете за передачу результатов захвата через ProcessResultImpl в Camera2/X.
В качестве примера см. определение интерфейса 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_RATIO -
CaptureRequest#SCALER_CROP_REGION
-
- Нажмите, чтобы сфокусироваться:
-
CaptureRequest#CONTROL_AF_MODE -
CaptureRequest#CONTROL_AF_TRIGGER -
CaptureRequest#CONTROL_AF_REGIONS -
CaptureRequest#CONTROL_AE_REGIONS -
CaptureRequest#CONTROL_AWB_REGIONS
-
- Вспышка:
-
CaptureRequest#CONTROL_AE_MODE -
CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER -
CaptureRequest#FLASH_MODE
-
- Компенсация за ущерб:
-
CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
-
Для базовых расширений, реализующих версии 1.2.0 или более ранние, API расширений CameraX явно поддерживает все вышеперечисленные ключи. Для extensions-interface 1.3.0 как CameraX, так и Camera2 учитывают возвращаемый список и поддерживают только содержащиеся в нем ключи. Например, если вы решите возвращать только CaptureRequest#CONTROL_ZOOM_RATIO и CaptureRequest#SCALER_CROP_REGION в реализации 1.3.0, это означает, что для приложения поддерживается только масштабирование, а фокусировка касанием, вспышка и компенсация экспозиции не допускаются.
Расширенный расширитель
Расширенный расширитель (Advanced Extender) — это тип реализации от производителя, основанный на API Camera2. Этот тип расширителя был добавлен в extensions-interface 1.2.0. В зависимости от производителя устройства, расширения могут быть реализованы на уровне приложения, что зависит от следующих факторов:
Настройка пользовательских потоков: Настройте пользовательские потоки, например, RAW-поток, или используйте несколько потоков для разных физических идентификаторов камер.
Возможность отправки запросов Camera2: Поддержка сложной логики взаимодействия, позволяющей отправлять запросы на захват изображения с параметрами, основанными на результатах предыдущих запросов.
Advanced Extender предоставляет оболочку или промежуточный слой, позволяющий настраивать конфигурацию потока и отправлять запросы на захват по требованию.
Файлы для реализации
Для переключения на реализацию 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 в качестве заполнителя. Замените его именем файла расширителя для внедряемого вами расширения.
Давайте посмотрим, как Camera2/X использует extensions-interface для реализации трех сценариев работы приложения.
Схема работы приложения 1: Проверка доступности расширений

Рисунок 8. Схема работы приложения 1 на Advanced Extender.
Сначала приложение проверяет, поддерживается ли данное расширение.
Схема работы приложения 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.getAvailableCaptureRequestKeys -
AdvancedExtenderImpl.getAvailableCaptureResultKeys
-
Для получения дополнительной информации см. раздел «Ключи и результаты запросов на захват данных в службе поддержки» .
Схема работы приложения 3: Предварительный просмотр/запись фотографий с включенным расширением.

Рисунок 10. Схема работы приложения 3 на Advanced Extender.
Приведенная выше диаграмма показывает основной процесс запуска предварительного просмотра и захвата неподвижных изображений для типа 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. Это настраивает предоставленную выходную поверхность для конвейера обработки изображений камерой и позволяет HAL камеры обрабатывать изображение. Обработка промежуточных поверхностей
ImageReader(RAW, YUV и т. д.): Добавьте промежуточные поверхностиImageReaderвCameraCaptureSessionс помощью экземпляраImageReaderOutputConfigImpl.Необходимо обработать промежуточные изображения и записать результирующее изображение на выходную поверхность.
- Использование совместного доступа к поверхности Camera2: Для этого добавьте любой экземпляр
Camera2OutputConfigImplв методgetSurfaceSharingOutputConfigs()другого экземпляраCamera2OutputConfigImpl. Формат и размер поверхности должны быть идентичными.
Все
Camera2OutputConfigImplвключаяSurfaceOutputConfigImplиImageReaderOutputConfigImplдолжны иметь уникальный идентификатор (getId()), который используется для указания целевой поверхности и получения изображения изImageReaderOutputConfigImpl.-
onCaptureSessionStartиRequestProcessorImplКогда запускается
CameraCaptureSessionи платформа Camera вызывает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().- Целевая поверхность задается идентификатором экземпляра
Запустите предварительный просмотр и сделайте снимок.
В реализации Advanced 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. Она позволяет приложениям реализовывать функцию фокусировки касанием и мигание с помощью расширений.Уборка
При завершении сеанса захвата вызывается
SessionProcessorImpl.onCaptureSessionEnd()перед закрытиемCameraCaptureSession. После закрытия сеанса захватаdeInitSession()выполняет очистку.
Поддержка предварительного просмотра, захвата неподвижных изображений и анализа изображений.
Расширение следует применять как для предварительного просмотра, так и для съемки фотографий. Однако, если задержка слишком велика для плавного отображения предварительного просмотра, расширение можно применять только для съемки фотографий.
For the Basic Extender type, regardless of enabling the extension for preview, you must implement both ImageCaptureExtenderImpl and PreviewExtenderImpl for a given extension. Often, an app also uses a YUV stream to analyze the image content such as finding QR codes or text. To better support this use case , you should support the stream combination of preview, still capture, and a YUV_420_888 stream for configuring CameraCaptureSession . This means that if you implement a processor, then you have to support the stream combination of three YUV_420_888 streams.
For Advanced Extender, Camera2/X passes three output surfaces to the SessionProcessorImpl.initSession() call. These output surfaces are for preview , still capture, and image analysis, respectively. You must ensure that preview and still capture output surfaces show the valid output. However, for the image analysis output surface, ensure it's working only when it's non-null. If your implementation can't support the image analysis stream, you can return an empty list in AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() . This ensures the image analysis output surface is always null in SessionProcessorImpl.initSession() .
Support video capture
The current Camera Extension architecture supports only the preview and still capture use cases. We don't support enabling the extension on the MediaCodec or MediaRecorder surfaces for recording the video. However, it's possible for apps to record the preview output.
Supporting MediaCodec and MediaRecorder surfaces is under investigation.
Extension-specific metadata
For Android 14 and higher, extension-specific metadata lets camera extension clients set and receive extension specific capture request settings and results. Specifically, camera extension clients can use the EXTENSION_STRENGTH capture request parameter to control the extension strength and the EXTENSION_CURRENT_TYPE capture result to indicate the enabled extension type.
Capture requests
The EXTENSION_STRENGTH capture request parameter controls the strength of the extension post-processing effect. The corresponding capture result includes the default strength value if this parameter isn't set explicitly by the client. This parameter can be applied as follows for these extension types:
-
BOKEH: Controls the amount of blur. -
HDRandNIGHT: Controls the amount of images fused and the brightness of the final image. -
FACE_RETOUCH: Controls the amount of cosmetic enhancement and skin smoothing.
The supported range for the EXTENSION_STRENGTH parameter is between 0 and 100 , with 0 indicating no extension processing or simple passthrough and 100 indicating the maximum extension strength of the processing effect.
To add support for EXTENSION_STRENGTH , use the vendor specific parameter APIs introduced in version 1.3.0 of the extension library interface. For more information, see getAvailableCaptureRequestKeys() .
Capture results
The EXTENSION_CURRENT_TYPE capture result lets extension implementations notify clients about the active extension type.
Because extensions using the AUTO type dynamically switch between extension types such as HDR and NIGHT depending on the scene conditions, camera extensions apps can use EXTENSION_CURRENT_TYPE to display information about the current extension selected by the AUTO extension.
Real-time still capture latency estimate
For Android 14 and higher, camera extension clients can query real-time still capture latency estimates based on the scene and environment conditions using getRealtimeStillCaptureLatency() . This method provides more accurate estimates than the static getEstimatedCaptureLatencyRangeMillis() method. Based on the latency estimate, apps can decide to skip extension processing or to display an indication to notify users about a long running operation.
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();
To support real-time still capture latency estimates, implement the following:
- Basic extensions:
ImageCaptureExtenderImpl.getRealtimeCaptureLatency() - Advanced extensions:
SessionProcessorImpl.getRealtimeCaptureLatency
Capture processing progress callbacks
For Android 14 and higher, camera extension clients can receive callbacks for the progress of long running still capture processing operations. Apps can display the current progress to users to improve the overall user experience.
Apps can use the following code to integrate this feature:
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
}
}
…
}
To support capture processing progress callbacks, your extension vendor implementation must call the following callbacks with the current progress value:
- Basic extensions:
ProcessResultImpl.onCaptureProcessProgressed() - Advanced extensions:
CaptureCallback.onCaptureProcessProgressed()
Postview still capture
For Android 14 and higher, camera extensions can supply a postview (preview image) using setPostviewOutputConfiguration . To improve the user experience, apps can display a postview image as a placeholder when an extension is experiencing increased processing latency, and replace the image when the final image is available. Apps can configure and issue postview capture requests using the following reference code:
{
…
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();
…
}
To support postview still capture, your vendor implementation must implement the following:
Basic extensions:
CaptureProcessorImpl.onPostviewOutputSurfaceandCaptureProcessorImpl.processWithPostviewAdvanced extensions:
SessionProcessorImpl.startCaptureWithPostview
Support SurfaceView output
For Android 14 and higher, camera extension clients can use power and performance optimized preview render paths by registering a SurfaceView instance for preview output for repeating requests.
To support SurfaceView output, your vendor extension implementation must be capable of streaming and outputting preview to SurfaceView instances. To verify that this is supported, run the SurfaceViewExtensionPreviewTest.java CTS module.
Vendor specific session types
The feature enables vendor extension implementations to select a vendor specific session type that will be set in the internal camera capture session instead of the default value.
The feature works entirely within the framework and vendor stack and has no client/public visible API impact.
To select a vendor-specific session type, implement the following for your extension libraries: * ExtenderStateListener.onSessionType() for basic extensions * Camera2SessionConfigImpl.getSessionType() for advanced extensions
Extensions interface version history
The following table shows the Camera Extension interface version history. You should always implement the vendor library with the latest version.
| Версия | Added features |
|---|---|
| 1.0.0 |
|
| 1.1.0 |
|
| 1.2.0 |
|
| 1.3.0 |
|
| 1.4.0 |
|
Reference implementation
The following reference OEM vendor library implementations are available in frameworks/ex .
advancedSample: A basic implementation of Advanced Extender.sample: A basic implementation of Basic Extender.service_based_sample: An implementation that demonstrates how to host Camera Extensions in aService. This implementation contains the following components:oem_library: A Camera Extensions OEM library for Camera2 and CameraX Extensions APIs that implementsExtensions-Interface. This acts as a passthrough that forwards calls fromExtensions-Interfaceto the service. This library also provides AIDL files and wrapper classes to communicate with the service.Advanced Extender is enabled by default. To enable the Basic Extender, change
ExtensionsVersionImpl#isAdvancedExtenderImplementedto returnfalse.extensions_service: A sample implementation of the Extensions Service. Add your implementation here. The interface to implement in the service is similar to theExtensions-Interface. For example, implementing theIAdvancedExtenderImpl.Stubperforms the same operations asAdvancedExtenderImpl.ImageWrapperandTotalCaptureResultWrapperare required to makeImageandTotalCaptureResultparcelable.
Set up the vendor library on a device
The OEM vendor library isn't built into an app; it's loaded from the device at runtime by Camera2/X. In CameraX, the <uses-library> tag declares that the androidx.camera.extensions.impl library, which is defined in the AndroidManifest.xml file of the camera-extensions library, is a dependency of CameraX and must be loaded at runtime. In Camera2, the framework loads an extensions service that also declares that the <uses-library> loads the same androidx.camera.extensions.impl library at runtime.
This allows third-party apps using extensions to automatically load the OEM vendor library. The OEM library is marked as optional so apps can run on devices that don't have the library on the device. Camera2/X handles this behavior automatically when an app tries to use a camera extension as long as the device manufacturer places the OEM library on the device so that it can be discovered by the app.
To set up the OEM library on a device, do the following:
- Add a permission file, which is required by the
<uses-library>tag, using the following format:/etc/permissions/ ANY_FILENAME .xml. For example,/etc/permissions/camera_extensions.xml. The files in this directory provide a mapping of the library named in<uses-library>to the actual file path on the device. Use the example below to add the required information to the file.
-
namemust beandroidx.camera.extensions.implas that's the library that CameraX searches for. -
fileis the absolute path of the file that contains the extensions implementation (for example,/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>
-
In Android 12 or higher, devices supporting CameraX extensions must have the ro.camerax.extensions.enabled property set to true , which allows for querying whether a device supports extensions. To do this, add the following line in the device make file:
PRODUCT_VENDOR_PROPERTIES += \
ro.camerax.extensions.enabled=true \
Проверка
To test your implementation of the OEM vendor library during the development stage, use the example app at androidx-main/camera/integration-tests/extensionstestapp/ , which runs through various vendor extensions.
After you complete your implementation, use the camera extensions validation tool to run automated and manual tests to verify that the vendor library is implemented correctly.
Extended scene mode versus camera extensions
For the bokeh extension, in addition to exposing it using camera extensions, you can expose the extension using the extended scene mode, which is enabled through the CONTROL_EXTENDED_SCENE_MODE key. For more implementation details, see Camera bokeh .
Extended scene mode has fewer restrictions compared to camera extensions for camera2 apps. For example, you can enable extended scene mode in a regular CameraCaptureSession instance that supports flexible stream combinations and capture request parameters. In contrast, camera extensions support only a fixed set of stream types and have limited support for capture request parameters.
A downside of extended scene mode is that you can only implement it in the camera HAL, which means that it must be verified to work across all orthogonal controls available to app developers.
We recommend exposing bokeh using both the extended scene mode and Camera Extensions because apps might prefer to use a particular API to enable bokeh. We recommend first using the extended scene mode because this is the most flexible way for apps to enable the bokeh extension. Then you can implement the camera extensions interface based on the extended scene mode. If implementing bokeh in the camera HAL is difficult, for example, because it requires a post processor running in the app layer to process images, we recommend implementing the bokeh extension using the Camera Extensions interface.
Часто задаваемые вопросы (FAQ)
Are there any restrictions on API levels?
Yes. This depends on the Android API feature set that's required by the OEM vendor library implementation. For example, ExtenderStateListener.onPresetSession() uses the SessionConfiguration.setSessionParameters() call to set a baseline set of tags. This call is available only on API level 28 and higher. For details on specific interface methods, see the API reference documentation .