Расширения камеры

Производители устройств могут предоставлять специальные эффекты, такие как боке, ночной режим и HDR, сторонним разработчикам через интерфейс Camera Extensions, предоставляемый библиотекой OEM-поставщика. Разработчики могут использовать API Camera2 Extensions и CameraX Extensions для включения эффектов, которые реализованы как расширения в библиотеке 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.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

Классы расширения Bokeh (реализуйте его, если расширение Bokeh поддерживается)

  • 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 или удалите соответствующие классы-расширители. API расширений Camera2 и CameraX сообщают приложению, что расширение недоступно.

Давайте рассмотрим, как API расширений Camera2 и CameraX взаимодействуют с библиотекой поставщика, чтобы включить расширение. Следующая диаграмма иллюстрирует сквозной поток на примере ночного расширения:

Основной поток

Рисунок 2. Реализация ночного расширения

  1. Проверка версии:

    Camera2/X вызывает ExtensionVersionImpl.checkApiVersion() , чтобы убедиться, что версия extensions-interface реализованная OEM, совместима с версиями, поддерживаемыми Camera2/X.

  2. Инициализация библиотеки поставщика:

    У InitializerImpl есть метод init() , который инициализирует библиотеку поставщика. Camera2/X завершает инициализацию перед доступом к классам Extender.

  3. Создание экземпляров классов-расширителей:

    Создает экземпляры классов Extender для расширения. Существует два типа расширителя: базовый расширитель и расширенный расширитель. Вы должны реализовать один тип расширителя для всех расширений. Дополнительные сведения см. в разделе Базовый расширитель и Расширенный расширитель .

    Camera2/X создает экземпляры классов Extender и взаимодействует с ними для получения информации и включения расширения. Для данного расширения Camera2/X может создавать экземпляры классов Extender несколько раз. Поэтому не выполняйте громоздкую инициализацию в конструкторе или вызове init() . Выполняйте тяжелую работу только перед началом сеанса камеры, например, когда onInit() в базовом расширителе или initSession() в расширенном расширителе.

    Для ночного расширения создаются экземпляры следующих классов расширений для базового типа расширений:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    И для типа Advanced Extender:

    • NightAdvancedExtenderImpl.java
  4. Проверить наличие расширения:

    Перед включением расширения isExtensionAvailable() проверяет, доступно ли расширение для указанного идентификатора камеры через экземпляр Extender.

  5. Инициализируйте расширитель информацией о камере:

    Camera2/X вызывает init() экземпляра Extender и передает ему идентификатор камеры и CameraCharacteristics .

  6. Информация о запросе:

    Вызывает класс Extender для получения информации, такой как поддерживаемые разрешения, по-прежнему фиксирует предполагаемую задержку и получает ключи запросов от Extender в рамках подготовки к включению расширения.

  7. Включите расширение на повторителе:

    Класс Extender предоставляет все интерфейсы, необходимые для включения класса. Он предлагает механизм подключения OEM-реализации к конвейеру Camera2, например, ввод параметров запроса захвата или включение постпроцессора.

    Для типа Advanced Extender Camera2/X взаимодействует с SessionProcessorImpl , чтобы включить расширение. Camera2/X извлекает экземпляр SessionProcessorImpl , вызывая createSessionProcessor() в расширителе.

В следующих разделах процесс расширения описывается более подробно.

Проверка версии

При загрузке библиотеки поставщика 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() , чтобы уведомить о завершении инициализации.

Вы должны реализовать InitializerImpl , extensions-interface 1.1.0. Camera2/X пропускает этап инициализации библиотеки, если библиотека поставщика OEM реализует extensions-interface 1.0.0.

Базовый расширитель против расширенного расширителя

Существует два типа реализации extensions-interface : Basic Extender и Advanced 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 вызывает startRepeating и startCapture на SessionProcessorImpl , чтобы сигнализировать OEM о запуске повторяющегося запроса для предварительного просмотра и запуска последовательности захвата неподвижных изображений соответственно.

Хуки в конвейере камеры
  • onPresetSession предоставляет параметры сеанса.
  • onEnableSession отправляет один запрос сразу после настройки CameraCaptureSession .
  • onDisableSession отправляет один запрос перед CameraCaptureSession .
  • initSession инициализирует и возвращает настроенную конфигурацию сеанса camera2 для создания сеанса захвата.
  • onCaptureSessionStart вызывается сразу после настройки CameraCaptureSession .
  • onCaptureSessionEnd вызывается перед CameraCaptureSession .
Подходит для Расширения реализованы в камере HAL или в процессоре, обрабатывающем изображения YUV.
  • Имеет реализацию эффектов на основе Camera2.
  • Требуется индивидуальная конфигурация потока, например поток RAW.
  • Требуется интерактивная последовательность захвата.
Поддерживаемая версия API Расширения Camera2: Android T (экспериментальная версия AOSP) или выше
CameraX Extensions: camera-extensions 1.1.0 или выше
Расширения Camera2: Android 12L или выше
CameraX Extensions: camera-extensions 1.2.0-alpha03 или выше

Потоки приложений

В следующей таблице показаны три типа потоков приложений и соответствующие им вызовы Camera Extensions API. Хотя Camera2/X предоставляет эти API, вы должны правильно реализовать библиотеку поставщика для поддержки этих потоков, которые мы опишем более подробно в следующем разделе.

Расширения Camera2 Расширения CameraX
Доступность расширения запроса CameraExtensionCharacteristics . getSupportedExtensions ExtensionsManager. isExtensionAvailable
Информация о запросе CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

CameraX обрабатывает остальную информацию в библиотеке.

Предварительный просмотр и фотосъемка с включенным расширением CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle (lifecycleOwner, cameraSelector, предварительный просмотр, ...)

Базовый удлинитель

Интерфейс Basic Extender обеспечивает подключение к нескольким местам конвейера камеры. У каждого типа расширения есть соответствующие классы-расширители, которые должны реализовать OEM-производители.

В следующей таблице перечислены классы расширителей, которые OEMS должны реализовать для каждого расширения:

Классы-расширители для реализации
Ночь NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Авто AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Боке BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Ретушь лица BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

Мы используем PreviewExtenderImpl и ImageCaptureExtenderImpl в качестве заполнителей в следующем примере. Замените их именами реальных файлов, которые вы реализуете.

Basic Extender имеет следующие возможности:

  • Внедрить параметры сеанса при настройке CameraCaptureSession ( onPresetSession ).
  • Уведомлять вас о событиях начала и закрытия сеанса захвата и отправлять один запрос для уведомления HAL с возвращенными параметрами ( onEnableSession , onDisableSession ).
  • Введите параметры захвата для запроса ( PreviewExtenderImpl.getCaptureStage , ImageCaptureExtenderImpl.getCaptureStages ).
  • Добавьте процессоры для предварительного просмотра и сохраняйте захват, способный обрабатывать поток YUV_420_888 .

Давайте посмотрим, как Camera2/X вызывает extensions-interface для достижения трех упомянутых выше потоков приложений.

Поток приложения 1: проверьте доступность расширения

BasicExtenderAppFlow1

Рис. 3. Поток приложения 1 в Basic Extender

В этом потоке Camera2/X напрямую вызывает метод isExtensionAvailable() как PreviewExtenderImpl , так и ImageCaptureExtenderImpl без вызова init() . Оба класса Extender должны возвращать значение true , чтобы включить расширения.

Это часто является первым шагом для приложений, чтобы проверить, поддерживается ли данный тип расширения для данного идентификатора камеры, прежде чем включать расширение. Это связано с тем, что некоторые расширения поддерживаются только для определенных идентификаторов камер.

Поток приложения 2: запрос информации

BasicExtenderAppFlow2

Рис. 4. Поток приложения 2 в Basic Extender

Определив, доступно ли расширение, приложения должны запросить следующую информацию, прежде чем включать расширение.

  • Диапазон задержки захвата по- прежнему: ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange возвращает диапазон задержки захвата, чтобы приложение могло оценить, уместно ли включить расширение для текущего сценария.

  • Поддерживаемые размеры для предварительного просмотра и захвата поверхности: ImageCaptureExtenderImpl.getSupportedResolutions и PreviewExtenderImpl.getSupportedResolutions возвращают список форматов изображений и размеров, которые поддерживаются для формата и размера поверхности.

  • Поддерживаемые ключи запроса и результата: Camera2/X вызывает следующие методы для извлечения поддерживаемых ключей запроса захвата и ключей результата из вашей реализации:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Camera2/X всегда сначала вызывает init() для этих классов-расширителей, прежде чем запрашивать дополнительную информацию.

Поток приложения 3: Предварительный просмотр/неподвижный захват с включенным расширением (реализация HAL)

BasicExtenderAppFlow3

Рис. 5. Поток приложения 3 в Basic Extender

На приведенной выше диаграмме показан основной процесс включения предварительного просмотра и неподвижного захвата с расширением без какого-либо процессора. Это означает, что камера 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 для предварительного просмотра.

    См. следующую иллюстрацию потока:

PreviewProcessor

Рисунок 6. Поток предварительного просмотра с PreviewImageProcessorImpl

Интерфейс PreviewImageProcessorImpl расширяет ProcessImpl и имеет три важных метода:

  • onOutputSurface(Surface surface, int imageFormat) устанавливает выходную поверхность для процессора. Для PreviewImageProcessorImpl imageFormat — это формат пикселей, такой как PixelFormat.RGBA_8888 .

  • onResolutionUpdate(Size size) устанавливает размер входного изображения.

  • onImageFormatUpdate(int imageFormat) устанавливает формат входного изображения. В настоящее время это может быть только YUV_420_888 .

Процессор захвата изображения

Для неподвижного захвата вы можете реализовать процессор, возвращая экземпляр CaptureProcessorImpl с помощью ImageCaptureExtenderImpl.getCaptureProcessor . Процессор отвечает за обработку списка захваченных изображений YUV_420_888 и экземпляров TotalCaptureResult и запись вывода на поверхность YUV_420_888 .

Вы можете с уверенностью предположить, что предварительный просмотр включен и запущен перед отправкой запроса на захват неподвижных изображений.

См. поток на диаграмме ниже:

ЗахватПроцессор

Рис. 7. Неподвижный поток захвата с помощью CaptureProcessorImpl

  1. Camera2/X использует поверхность формата YUV_420_888 для неподвижного захвата, чтобы настроить сеанс захвата. Camera2/X подготавливает CaptureProcessorImpl , вызывая:

    • CaptureProcessorImpl.onImageFormatUpdate() с YUV_420_888 .
    • CaptureProcessorImpl.onResolutionUpdate() с размером входного изображения.
    • CaptureProcessorImpl.onOutputSurface() с выходной поверхностью YUV_420_888 .
  2. ImageCaptureExtenderImpl.getCaptureStages возвращает список CaptureStageImpl , где каждый элемент сопоставляется с экземпляром CaptureRequest с параметрами захвата, отправленными Camera2/X. Например, если он возвращает список из трех экземпляров CaptureStageImpl , Camera2/X отправляет три запроса на захват с соответствующими параметрами захвата с использованием API-интерфейса captureBurst .

  3. Полученные изображения и экземпляры TotalCaptureResult объединяются и отправляются в CaptureProcessorImpl для обработки.

  4. 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 — это тип реализации поставщика, основанный на Camera2 API. Этот тип расширителя был добавлен в extensions-interface 1.2.0. В зависимости от производителя устройства расширения могут быть реализованы на уровне приложений, что зависит от следующих факторов:

  • Конфигурация пользовательского потока: настройте пользовательские потоки, такие как поток RAW, или создайте несколько потоков для разных идентификаторов физических камер.

  • Возможность отправки запросов Camera2: поддержка сложной логики взаимодействия, которая может отправлять запросы захвата с параметрами, основанными на результатах предыдущих запросов.

Advanced Extender предоставляет оболочку или промежуточный уровень, поэтому вы можете настроить конфигурацию потока и отправлять запросы на захват по требованию.

Файлы для реализации

Чтобы переключиться на реализацию Advanced Extender, метод isAdvancedExtenderImplemented() в ExtensionVersionImpl должен возвращать значение true . Для каждого типа расширения OEM-производители должны реализовать соответствующие классы расширений. Файлы реализации Advanced Extender находятся в расширенном пакете.

Классы-расширители для реализации
Ночь advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Авто advanced/AutoAdvancedExtenderImpl.java
Боке advanced/BokehAdvancedExtenderImpl.java
Ретушь лица advanced/BeautyAdvancedExtenderImpl.java

Мы используем AdvancedExtenderImpl в качестве заполнителя в следующем примере. Замените его именем файла расширения для расширения, которое вы реализуете.

Давайте посмотрим, как Camera2/X вызывает extensions-interface для достижения трех потоков приложений.

Поток приложения 1: проверьте доступность расширений

AdvancedAppFlow1

Рис. 8. Поток приложения 1 в Advanced Extender

Сначала приложение проверяет, поддерживается ли данное расширение.

Поток приложения 2: запрос информации

AdvancedAppFlow2

Рисунок 9. Поток приложения 2 в Advanced Extender

После вызова AdvancedExtenderImpl.init() приложение может запросить следующую информацию о AdvancedExtenderImpl :

  • Предполагаемая задержка захвата: AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() возвращает диапазон задержки захвата, чтобы приложение могло оценить, подходит ли расширение для текущего сценария.

  • Поддерживаемые разрешения для предварительного просмотра и фотосъемки:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() возвращает карту формата изображения в список размеров, которые поддерживаются для формата и размера поверхности предварительного просмотра. OEM-производители должны поддерживать как минимум формат PRIVATE .

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() возвращает поддерживаемый формат и размеры для неподвижной поверхности захвата. OEM-производители должны поддерживать выходные форматы JPEG и YUV_420_888 .

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() возвращает поддерживаемые размеры для дополнительного потока YUV_420_888 для анализа изображения. Если поверхность YUV для анализа изображений не поддерживается, getSupportedYuvAnalysisResolutions() должен возвращать null или пустой список.

  • Доступные ключи/результаты запроса захвата (добавлены в extensions-interface 1.3.0): Camera2/X вызывает следующие методы для получения поддерживаемых ключей запроса захвата и ключей результатов из вашей реализации:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Дополнительные сведения см. в разделе Ключи и результаты запроса захвата поддержки .

Поток приложения 3: Предварительный просмотр/неподвижный захват с включенным расширением

AdvancedAppFlow3

Рисунок 10. Поток приложения 3 в Advanced Extender

На приведенной выше диаграмме показан основной процесс запуска предварительного просмотра и захвата для типа Advanced Extender. Давайте пройдемся по каждому шагу.

  1. SessionProcessorImpl

    Основная реализация Advanced Extender находится в SessionProcessorImpl , который отвечает за предоставление индивидуальной конфигурации сеанса и отправку запросов на захват для инициирования предварительного просмотра и все еще запроса на захват. AdvancedExtenderImpl.createSessionProcessor() вызывается для возврата экземпляра SessionProcessorImpl .

  2. initSession

    SessionProcessorImpl.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 .

  3. onCaptureSessionStart и RequestProcessorImpl

    Когда CameraCaptureSession запускается и платформа Camera вызывает onConfigured() , затем Camera2/X вызывает SessionProcessorImpl.onCaptureSessionStart() с оболочкой запроса Camera2 RequestProcessImpl . Camera2/X реализует RequestProcessImpl , который позволяет вам выполнять запросы захвата и извлекать изображения , если используется ImageReaderOutputConfigImpl .

    API-интерфейсы RequestProcessImpl аналогичны API-интерфейсам Camera2 CameraCaptureSession с точки зрения выполнения запросов. Различия:

    • Целевая поверхность определяется идентификатором экземпляра Camera2OutputConfigImpl .
    • Возможность получения изображения ImageReader .

    Вы можете вызвать RequestProcessorImpl.setImageProcessor() с указанным идентификатором Camera2OutputConfigImpl , чтобы зарегистрировать экземпляр ImageProcessorImpl для получения изображений.

    Экземпляр RequestProcessImpl становится недействительным после того, как Camera2/X вызывает SessionProcessorImpl.onCaptureSessionEnd() .

  4. Запустите предварительный просмотр и сделайте снимок

    В реализации Advanced Extender вы можете отправлять запросы на захват через интерфейс RequestProcessorImpl . Camera2/X уведомляет вас о запуске повторяющегося запроса на предварительный просмотр или последовательность захвата неподвижных изображений, вызывая SessionProcessorImpl#startRepeating и SessionProcessorImpl#startCapture соответственно. Вы должны отправлять запросы на захват, чтобы удовлетворить эти запросы на предварительный просмотр и неподвижный захват.

    Camera2/X также устанавливает параметры запроса захвата с помощью SessionProcessorImpl#setParameters . Вы должны установить эти параметры запроса (если параметры поддерживаются) как для повторяющихся, так и для одиночных запросов.

    Вы должны поддерживать как минимум CaptureRequest.JPEG_ORIENTATION и CaptureRequest.JPEG_QUALITY . extensions-interface 1.3.0 поддерживает ключи запроса и результата, которые предоставляются следующими методами:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys()

    Когда разработчики устанавливают ключи в списке getAvailableCaptureRequestKeys , необходимо включить параметры и убедиться, что результат захвата содержит ключи в списке getAvailableCaptureResultKeys .

  5. startTrigger

    SessionProcessorImpl.startTrigger() вызывается для запуска триггера, такого как CaptureRequest.CONTROL_AF_TRIGGER и CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER . Вы можете игнорировать любые ключи запроса захвата, которые не были объявлены в AdvancedExtenderImpl.getAvailableCaptureRequestKeys() .

    startTrigger() поддерживается начиная с extensions-interface 1.3.0. Это позволяет приложениям реализовывать фокусировку касанием и вспышку с расширениями.

  6. Очистить

    При завершении сеанса захвата SessionProcessorImpl.onCaptureSessionEnd() вызывается перед закрытием CameraCaptureSession . После закрытия сеанса захвата deInitSession() выполняет очистку.

Поддержка предварительного просмотра, фотосъемки и анализа изображений.

Вы должны применить расширение как для предварительного просмотра, так и для фиксирования вариантов использования. Однако, если задержка слишком велика для плавного отображения предварительного просмотра, вы можете применить эффект только для неподвижного захвата.

Для типа Basic Extender, независимо от включения эффекта для предварительного просмотра, необходимо реализовать как ImageCaptureExtenderImpl , так и PreviewExtenderImpl для данного расширения. 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.

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.

Version Added features
1.0.0
  • Version verification
    • ExtensionVersionImpl
  • Basic Extender
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Library initialization
    • InitializerImpl
  • Expose supported resolutions
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Get estimated capture latency
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Expose supported capture request keys/results keys
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys and getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys and getAvailableCaptureResultKeys
    • New process() call that takes ProcessResultImpl in PreviewImageProcessorImpl and CaptureProcessorImpl
    • Support trigger type request
      • AdvancedExtenderImpl.startTrigger

Reference implementation

For a reference OEM vendor library implementation, see camera-testlib-extensions . Note that this implementation performs passthroughs without actually implementing the effects.

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:

  1. 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.
  2. Use the example below to add the required information to the file.

    • name must be androidx.camera.extensions.impl as that's the library that CameraX searches for.
    • file is 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 \

Validation

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.

Frequently asked questions (FAQs)

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 .