Extensiones de cámara

Los fabricantes de dispositivos pueden exponer efectos especiales como bokeh, modo nocturno y HDR a desarrolladores externos a través de la interfaz Camera Extensions proporcionada por la biblioteca de proveedores OEM. Los desarrolladores pueden usar las API Camera2 Extensions y CameraX Extensions para habilitar los efectos, que se implementan como extensiones en la biblioteca de proveedores OEM en el dispositivo.

Para obtener una lista de extensiones admitidas, que es la misma en Camera2 y CameraX, consulte API de extensiones de CameraX . Si desea agregar una extensión, registre un error aquí .

Esta página describe cómo implementar y habilitar la biblioteca de proveedores OEM en los dispositivos.

Arquitectura

El siguiente diagrama describe la arquitectura de la interfaz Camera Extensions o extensions-interface : Arquitectura

Figura 1. Diagrama de arquitectura de extensiones de cámara

Como se muestra en el diagrama, para admitir extensiones de cámara, debe implementar la extensions-interface proporcionada por la biblioteca del proveedor OEM. Su biblioteca de proveedores OEM habilita dos API: CameraX Extensions API y Camera2 Extensions API , que utilizan las aplicaciones CameraX y Camera2, respectivamente, para acceder a las extensiones del proveedor.

Implementar la biblioteca de proveedores de OEM

Para implementar la biblioteca de proveedores OEM, copie los archivos camera-extensions-stub en un proyecto de biblioteca del sistema. Estos archivos definen la interfaz de extensiones de cámara.

Los archivos camera-extensions-stub se dividen en las siguientes categorías:

Archivos de interfaz esenciales (no modificar)

  • 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

Implementaciones obligatorias (agregue su implementación)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Clases de extensión de Bokeh (impleméntelas si se admite la extensión de Bokeh)

  • BokehImageCaptureExtenderImpl.java
  • BokehPreviewExtenderImpl.java
  • advanced/BokehAdvancedExtenderImpl.java

Clases de extensión nocturna (impleméntalo si se admite la extensión nocturna)

  • NightImageCaptureExtenderImpl.java
  • NightPreviewExtenderImpl.java
  • advanced/NightAdvancedExtenderImpl.java

Clases de extensión automática (impleméntela si se admite la extensión automática)

  • AutoImageCaptureExtenderImpl.java
  • AutoPreviewExtenderImpl.java
  • advanced/AutoAdvancedExtenderImpl.java

Clases de extensores HDR (impleméntelo si se admite la extensión HDR)

  • HdrImageCaptureExtenderImpl.java
  • HdrPreviewExtenderImpl.java
  • advanced/HdrAdvancedExtenderImpl.java

Clases de extensión de Face Retouch (impleméntalo si se admite la extensión Face Retouch)

  • BeautyImageCaptureExtenderImpl.java
  • BeautyPreviewExtenderImpl.java
  • advanced/BeautyAdvancedExtenderImpl.java

Utilidades (opcional, se puede eliminar)

  • advanced/Camera2OutputConfigImplBuilder.java
  • advanced/Camera2SessionConfigImplBuilder.java

No es necesario que proporcione una implementación para cada extensión. Si no implementa una extensión, configure isExtensionAvailable() para que devuelva false o elimine las clases Extender correspondientes. Las API de Camera2 y CameraX Extensions informan a la aplicación que la extensión no está disponible.

Veamos cómo interactúan las API de Camera2 y CameraX Extensions con la biblioteca del proveedor para habilitar una extensión. El siguiente diagrama ilustra el flujo de un extremo a otro usando la extensión Night como ejemplo:

Flujo principal

Figura 2. Implementación de extensión nocturna

  1. Verificación de la versión:

    Camera2/X llama a ExtensionVersionImpl.checkApiVersion() para asegurarse de que la versión extensions-interface implementada por el OEM sea compatible con las versiones compatibles con Camera2/X.

  2. Inicialización de la biblioteca del proveedor:

    InitializerImpl tiene un método init() que inicializa la biblioteca del proveedor. Camera2/X completa la inicialización antes de acceder a las clases de Extender.

  3. Crear instancias de clases Extender:

    Instancia las clases Extender para la extensión. Hay dos tipos de extensores: extensor básico y extensor avanzado. Debe implementar un tipo de extensor para todas las extensiones. Para obtener más información, consulte Extensor básico frente a Extensor avanzado .

    Camera2/X instancia e interactúa con las clases Extender para recuperar información y habilitar la extensión. Para una extensión determinada, Camera2/X puede instanciar las clases Extender varias veces. Como resultado, no realice una inicialización pesada en el constructor o en la llamada init() . Realice el trabajo pesado solo cuando la sesión de la cámara esté a punto de comenzar, como cuando se llama onInit() en Basic Extender o initSession() en Advanced Extender.

    Para la extensión Noche, se instancian las siguientes clases de extensores para el tipo de extensor básico:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    Y para el tipo Extensor Avanzado:

    • NightAdvancedExtenderImpl.java
  4. Consultar disponibilidad de extensiones:

    Antes de habilitar la extensión, isExtensionAvailable() verifica si la extensión está disponible en la ID de cámara especificada a través de la instancia de Extender.

  5. Inicialice el extensor con la información de la cámara:

    Camera2/X llama a init() en la instancia de Extender y le pasa el ID de la cámara y CameraCharacteristics .

  6. Información de la consulta:

    Invoca la clase Extender para recuperar información como las resoluciones admitidas, aún captura la latencia estimada y captura las claves de solicitud del Extender en preparación para habilitar la extensión.

  7. Habilitar extensión en el extensor:

    La clase Extender proporciona todas las interfaces necesarias para habilitar la clase. Ofrece un mecanismo para vincular la implementación de OEM en la canalización de Camera2, como inyectar parámetros de solicitud de captura o habilitar un posprocesador.

    Para el tipo de extensor avanzado, Camera2/X interactúa con SessionProcessorImpl para habilitar la extensión. Camera2/X recupera la instancia de SessionProcessorImpl llamando a createSessionProcessor() en el extensor.

Las siguientes secciones describen el flujo de extensión con mayor detalle.

Verificación de versión

Al cargar la biblioteca del proveedor OEM desde el dispositivo en tiempo de ejecución, Camera2/X verifica si la biblioteca es compatible con la versión extensions-interface . La extensions-interface utiliza el control de versiones semántico o PRINCIPAL.MENOR.PARCHE, por ejemplo, 1.1.0 o 1.2.0. Sin embargo, solo se utilizan las versiones principal y secundaria durante la verificación de la versión.

Para verificar la versión, Camera2/X llama a ExtensionVersionImpl.checkApiVersion() con la versión extensions-interface . Camera2/X luego usa la versión informada por la biblioteca OEM para determinar si la extensión se puede habilitar y qué capacidades debe invocar.

Compatibilidad con versiones principales

Si las versiones principales de la interfaz de extensión son diferentes entre Camera2/X y la biblioteca del proveedor, entonces se considera incompatible y la extensión está deshabilitada.

Compatibilidad con versiones anteriores

Siempre que la versión principal sea idéntica, Camera2/X garantiza la compatibilidad con las bibliotecas de proveedores OEM creadas con versiones anteriores extensions-interface . Por ejemplo, si Camera2/X es compatible extensions-interface 1.3.0, las bibliotecas de proveedores OEM que implementaron 1.0.0, 1.1.0 y 1.2.0 siguen siendo compatibles. Esto también significa que después de implementar una versión específica de la biblioteca del proveedor, Camera2/X se asegura de que la biblioteca sea compatible con versiones anteriores extension-interface .

Compatibilidad hacia adelante

La compatibilidad hacia adelante con las bibliotecas de proveedores de extensions-interface más nueva depende de usted, el OEM. Si necesita algunas funciones para implementar las extensiones, es posible que desee habilitar las extensiones a partir de una determinada versión. En este caso, puede devolver la versión extensions-interface cuando la versión de la biblioteca Camera2/X cumpla con los requisitos. Si las versiones de Camera2/X no son compatibles, puede devolver una versión incompatible como 99.0.0 para deshabilitar las extensiones.

Inicialización de la biblioteca del proveedor

Después de verificar la versión de la extensions-interface implementada por la biblioteca OEM, Camera2/X inicia el proceso de inicialización. El método InitializerImpl.init() le indica a la biblioteca OEM que una aplicación está tratando de usar extensiones.

Camera2/X no realiza otras llamadas a la biblioteca OEM (aparte de la verificación de la versión) hasta que la biblioteca del proveedor OEM llama a OnExtensionsInitializedCallback.onSuccess() para notificar la finalización de la inicialización.

Debe implementar InitializerImpl a partir de extensions-interface 1.1.0. Camera2/X omite el paso de inicialización de la biblioteca si la biblioteca del proveedor OEM implementa extensions-interface 1.0.0.

Extensor básico versus extensor avanzado

Hay dos tipos de implementación extensions-interface : extensor básico y extensor avanzado. Advanced Extender ha sido compatible desde extensions-interface 1.2.0.

Implemente Basic Extender para extensiones que procesan imágenes en la cámara HAL o use un posprocesador capaz de procesar flujos YUV.

Implemente Advanced Extender para extensiones que necesiten personalizar la configuración de transmisión de Camera2 y enviar solicitudes de captura según sea necesario.

Consulte la siguiente tabla para la comparación:

Extensor básico Extensor avanzado
Configuraciones de transmisión Fijado
Vista previa: PRIVATE o YUV_420_888 (si existe un procesador)
Captura fija: JPEG o YUV_420_888 (si existe un procesador)
Personalizable por OEM.
Enviando solicitud de captura Solo Camera2/X puede enviar solicitudes de captura. Puede establecer los parámetros para estas solicitudes. Cuando se proporciona el procesador para la captura de imágenes, Camera2/X puede enviar varias solicitudes de captura y enviar todas las imágenes y los resultados de la captura al procesador. Se le proporciona una instancia de RequestProcessorImpl para ejecutar la solicitud de captura de camera2 y obtener resultados e imágenes.

Camera2/X invoca startRepeating y startCapture en SessionProcessorImpl para indicar al OEM que inicie la solicitud repetida de vista previa e inicie la secuencia de captura fija, respectivamente.

Ganchos en la canalización de la cámara
  • onPresetSession proporciona parámetros de sesión.
  • onEnableSession envía una sola solicitud justo después de configurar CameraCaptureSession .
  • onDisableSession envía una sola solicitud antes de que se cierre CameraCaptureSession .
  • initSession inicializa y devuelve una configuración de sesión camera2 personalizada para crear la sesión de captura.
  • onCaptureSessionStart se invoca justo después de configurar CameraCaptureSession .
  • onCaptureSessionEnd se invoca antes de que se cierre CameraCaptureSession .
Adecuado para Extensiones implementadas en la cámara HAL o en un procesador que procese imágenes YUV.
  • Tiene implementaciones basadas en Camera2 para los efectos.
  • Necesita una configuración de transmisión personalizada, como la transmisión RAW.
  • Necesita secuencia de captura interactiva.
Versión de API compatible Extensiones Camera2: Android T (AOSP experimental) o superior
Extensiones de CameraX: extensiones camera-extensions 1.1.0 o superior
Extensiones Camera2: Android 12L o superior
Extensiones de CameraX: extensiones camera-extensions 1.2.0-alpha03 o superior

Flujos de aplicaciones

La siguiente tabla muestra tres tipos de flujos de aplicaciones y sus correspondientes llamadas a la API de extensiones de cámara. Si bien Camera2/X proporciona estas API, debe implementar correctamente la biblioteca del proveedor para admitir estos flujos, que describimos con más detalle en una sección posterior.

Extensiones de cámara2 Extensiones de cámara X
Disponibilidad de la extensión de consulta CameraExtensionCharacteristics . getSupportedExtensions ExtensionsManager. isExtensionAvailable
Consultar información CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

CameraX maneja el resto de la información dentro de la biblioteca.

Vista previa y captura fija con la extensión habilitada CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle(lifecycleOwner, cameraSelector, vista previa, ...)

Extensor básico

La interfaz de Basic Extender proporciona enlaces en varios lugares de la canalización de la cámara. Cada tipo de extensión tiene clases de Extender correspondientes que los OEM deben implementar.

La siguiente tabla enumera las clases de Extender que los OEM deben implementar para cada extensión:

Extender clases para implementar
Noche NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Auto AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

retoque facial BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

Usamos PreviewExtenderImpl e ImageCaptureExtenderImpl como marcadores de posición en el siguiente ejemplo. Reemplácelos con los nombres de los archivos reales que está implementando.

Basic Extender tiene las siguientes capacidades:

  • Inyecte parámetros de sesión al configurar CameraCaptureSession ( onPresetSession ).
  • Notificarle los eventos de inicio y cierre de la sesión de captura y enviar una sola solicitud para notificar a la HAL con los parámetros devueltos ( onEnableSession , onDisableSession ).
  • Inyecte parámetros de captura para la solicitud ( PreviewExtenderImpl.getCaptureStage , ImageCaptureExtenderImpl.getCaptureStages ).
  • Agregue procesadores para la vista previa y la captura fija que sea capaz de procesar la transmisión YUV_420_888 .

Veamos cómo Camera2/X invoca la extensions-interface para lograr los tres flujos de aplicaciones mencionados anteriormente.

Flujo de la aplicación 1: verificar la disponibilidad de la extensión

BasicExtenderAppFlow1

Figura 3. Flujo de aplicación 1 en Basic Extender

En este flujo, Camera2/X llama directamente al método isExtensionAvailable() de PreviewExtenderImpl e ImageCaptureExtenderImpl sin llamar a init() . Ambas clases de extensores deben devolver true para habilitar las extensiones.

Este suele ser el primer paso para que las aplicaciones verifiquen si el tipo de extensión dado es compatible con una ID de cámara determinada antes de habilitar la extensión. Esto se debe a que algunas extensiones solo son compatibles con ciertas ID de cámara.

Flujo de aplicación 2: consulta de información

BasicExtenderAppFlow2

Figura 4. Flujo de aplicación 2 en Basic Extender

Después de determinar si la extensión está disponible, las aplicaciones deben consultar la siguiente información antes de habilitar la extensión.

  • Rango de latencia de captura aún: ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange devuelve el rango de latencia de captura para que la aplicación evalúe si es apropiado habilitar la extensión para el escenario actual.

  • Tamaños admitidos para la vista previa y la superficie de captura: ImageCaptureExtenderImpl.getSupportedResolutions y PreviewExtenderImpl.getSupportedResolutions devuelven una lista de formatos de imagen y los tamaños admitidos para el formato y el tamaño de la superficie.

  • Claves de solicitud y resultado admitidas: Camera2/X invoca los siguientes métodos para recuperar las claves de solicitud de captura y las claves de resultado admitidas de su implementación:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Camera2/X siempre llama a init() primero en estas clases Extender antes de consultar para obtener más información.

Flujo de aplicación 3: Vista previa/captura fija con extensión habilitada (implementación HAL)

BasicExtenderAppFlow3

Figura 5. Flujo de aplicaciones 3 en Basic Extender

El diagrama anterior ilustra el flujo principal de habilitar la vista previa y la captura fija con una extensión sin ningún procesador. Esto significa que la cámara HAL procesa la extensión.

En este flujo, Camera2/X primero llama a init() y luego onInit , lo que le notifica que una sesión de cámara está a punto de comenzar con las extensiones especificadas. Puede realizar una inicialización pesada en onInit() .

Al configurar CameraCaptureSession , Camera2/X invoca onPresetSession para obtener los parámetros de la sesión. Una vez que la sesión de captura se configura correctamente, Camera2/X invoca onEnableSession y devuelve una instancia de CaptureStageImpl que contiene los parámetros de captura. Camera2/X envía inmediatamente una única solicitud con estos parámetros de captura para notificar a la HAL. De manera similar, antes de que se cierre la sesión de captura, Camera2/X invoca onDisableSession y luego envía una sola solicitud con los parámetros de captura devueltos.

La solicitud repetida activada por Camera2/X contiene los parámetros de solicitud devueltos por PreviewExtenderImpl.getCaptureStage() . Además, la solicitud de captura fija contiene los parámetros devueltos por ImageCaptureExtenderImpl.getCaptureStages() .

Finalmente, Camera2/X invoca onDeInit() después de que finaliza la sesión de la cámara. Puede liberar recursos en onDeinit() .

Procesador de vista previa

Además de la cámara HAL, también puede implementar extensiones en un procesador.

Implemente PreviewExtenderImpl.getProcessorType para especificar el tipo de procesador como se explica a continuación:

  • PROCESSOR_TYPE_NONE : Sin procesador. Las imágenes se procesan en la cámara HAL.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY : el tipo de procesador le permite actualizar la solicitud repetitiva con nuevos parámetros de solicitud de captura basados ​​en el último TotalCaptureResult .

    PreviewExtenderImpl.getProcessor debe devolver una instancia de RequestUpdateProcessorImpl que procesa la instancia de TotalCaptureResult y devuelve una instancia de CaptureStageImpl para actualizar la solicitud repetitiva. PreviewExtenderImpl.getCaptureStage() también debe reflejar el resultado del procesamiento y devolver el CaptureStageImpl más reciente.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR : este tipo le permite implementar un procesador para procesar imágenes YUV_420_888 y escribir la salida en una superficie PRIVATE .

    Debe implementar y devolver una instancia de PreviewImageProcessorImpl en PreviewExtenderImpl.getProcessor . El procesador es responsable de procesar las imágenes de entrada YUV_420_888 . Debe escribir la salida en el formato PRIVATE de vista previa. Camera2/X usa una superficie YUV_420_888 en lugar de PRIVATE para configurar CameraCaptureSession para la vista previa.

    Vea la siguiente ilustración para el flujo:

Procesador de vista previa

Figura 6. Flujo de vista previa con PreviewImageProcessorImpl

La interfaz PreviewImageProcessorImpl amplía ProcessImpl y tiene tres métodos importantes:

  • onOutputSurface(Surface surface, int imageFormat) establece la superficie de salida para el procesador. Para PreviewImageProcessorImpl , imageFormat es un formato de píxel como PixelFormat.RGBA_8888 .

  • onResolutionUpdate(Size size) establece el tamaño de la imagen de entrada.

  • onImageFormatUpdate(int imageFormat) establece el formato de imagen de la imagen de entrada. Actualmente, solo puede ser YUV_420_888 .

Procesador de captura de imagen

Para la captura de imágenes fijas, puede implementar un procesador devolviendo una instancia de CaptureProcessorImpl mediante ImageCaptureExtenderImpl.getCaptureProcessor . El procesador es responsable de procesar una lista de imágenes YUV_420_888 capturadas e instancias de TotalCaptureResult y escribir la salida en una superficie YUV_420_888 .

Puede asumir con seguridad que la vista previa está habilitada y ejecutándose antes de enviar la solicitud de captura fija.

Vea el flujo en el siguiente diagrama:

Procesador de captura

Figura 7. Flujo de captura fija con CaptureProcessorImpl

  1. Camera2/X utiliza una superficie de formato YUV_420_888 para captura fija para configurar la sesión de captura. Camera2/X prepara CaptureProcessorImpl llamando:

    • CaptureProcessorImpl.onImageFormatUpdate() con YUV_420_888 .
    • CaptureProcessorImpl.onResolutionUpdate() con el tamaño de la imagen de entrada.
    • CaptureProcessorImpl.onOutputSurface() con una superficie de salida YUV_420_888 .
  2. ImageCaptureExtenderImpl.getCaptureStages devuelve una lista de CaptureStageImpl , donde cada elemento se asigna a una instancia de CaptureRequest con parámetros de captura que envía Camera2/X. Por ejemplo, si devuelve una lista de tres instancias de CaptureStageImpl , Camera2/X envía tres solicitudes de captura con los parámetros de captura correspondientes mediante la API captureBurst .

  3. Las imágenes recibidas y las instancias de TotalCaptureResult se agrupan y se envían a CaptureProcessorImpl para su procesamiento.

  4. CaptureProcessorImpl escribe la imagen de resultado (formato YUV_420_888 ) en la superficie de salida especificada por la llamada onOutputSurface() . Camera2/X lo convierte en imágenes JPEG si es necesario.

Admite claves de solicitud de captura y resultados

Además de la vista previa y la captura de la cámara, las aplicaciones pueden configurar el zoom, los parámetros del flash o activar un toque para enfocar. Es posible que estos parámetros no sean compatibles con la implementación de su extensión.

Se agregaron los siguientes métodos a extensions-interface 1.3.0 para permitirle exponer los parámetros que admite su implementación:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() devuelve las claves de solicitud de captura admitidas por su implementación.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() devuelve las claves de resultado de captura que están contenidas en el resultado de captura.

Si la HAL de la cámara procesa la extensión, Camera2/X recupera los resultados de la captura en CameraCaptureSession.CaptureCallback . Sin embargo, si se implementa el procesador, Camera2/X recupera los resultados de la captura en ProcessResultImpl , que se pasa al método process() en PreviewImageProcessorImpl y CaptureProcessorImpl . Usted es responsable de informar el resultado de la captura a través de ProcessResultImpl a Camera2/X.

Consulte la definición de la interfaz CaptureProcessorImpl a continuación como ejemplo. En extensions-interface 1.3.0 o superior, se invoca la segunda llamada de 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);
}

Para las operaciones comunes de la cámara, como zoom, tocar para enfocar, flash y compensación de exposición, recomendamos admitir las siguientes teclas tanto para la solicitud de captura como para el resultado de la captura:

  • Zoom:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Tocar para enfocar:
    • CaptureRequest#CONTROL_AF_MODE
    • CaptureRequest#CONTROL_AF_TRIGGER
    • CaptureRequest#CONTROL_AF_REGIONS
    • CaptureRequest#CONTROL_AE_REGIONS
    • CaptureRequest#CONTROL_AWB_REGIONS
  • Destello:
    • CaptureRequest#CONTROL_AE_MODE
    • CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
    • CaptureRequest#FLASH_MODE
  • Compensación de exposición:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

Para los extensores básicos que implementan 1.2.0 o versiones anteriores, la API de extensiones de CameraX admite explícitamente todas las claves anteriores. Para extensions-interface 1.3.0, tanto CameraX como Camera2 respetan la lista devuelta y admiten solo las claves contenidas en ella. Por ejemplo, si decide devolver solo CaptureRequest#CONTROL_ZOOM_RATIO y CaptureRequest#SCALER_CROP_REGION en la implementación 1.3.0, eso significa que solo se admite el zoom para la aplicación, mientras que no se permite la compensación de exposición, flash y tocar para enfocar.

Extensor avanzado

Advanced Extender es un tipo de implementación de proveedor basada en la API de Camera2. Este tipo de extensor se agregó en extensions-interface 1.2.0. Según el fabricante del dispositivo, las extensiones pueden implementarse en la capa de la aplicación, lo que depende de los siguientes factores:

  • Configuración de transmisión personalizada : configure transmisiones personalizadas como transmisión RAW o tenga múltiples transmisiones para diferentes ID de cámara física.

  • Capacidad para enviar solicitudes de Camera2: admite una lógica de interacción complicada que puede enviar solicitudes de captura con parámetros basados ​​en los resultados de solicitudes anteriores.

Advanced Extender proporciona un contenedor, o una capa intermedia, para que pueda personalizar la configuración de transmisión y enviar solicitudes de captura a pedido.

Archivos a implementar

Para cambiar a la implementación de Advanced Extender, el método isAdvancedExtenderImplemented() en ExtensionVersionImpl debe devolver true . Para cada tipo de extensión, los OEM deben implementar las clases Extender correspondientes. Los archivos de implementación de Advanced Extender están en el paquete avanzado .

Extender clases para implementar
Noche advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Auto advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Retoque facial advanced/BeautyAdvancedExtenderImpl.java

Usamos AdvancedExtenderImpl como marcador de posición en el siguiente ejemplo. Reemplácelo con el nombre del archivo Extender para la extensión que está implementando.

Veamos cómo Camera2/X invoca la extensions-interface para lograr los tres flujos de aplicaciones.

Flujo de aplicación 1: comprobar la disponibilidad de extensiones

AdvancedAppFlow1

Figura 8. Flujo de aplicación 1 en Advanced Extender

Primero, la aplicación verifica si la extensión dada es compatible.

Flujo de aplicación 2: consulta de información

AdvancedAppFlow2

Figura 9. Flujo de aplicación 2 en Advanced Extender

Después de llamar a AdvancedExtenderImpl.init() , la aplicación puede consultar la siguiente información en AdvancedExtenderImpl :

  • Latencia estimada de captura fija: AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() devuelve el rango de latencia de captura para que la aplicación evalúe si es apropiado habilitar la extensión para el escenario actual.

  • Resoluciones admitidas para vista previa y captura fija:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() devuelve un mapa de formato de imagen a la lista de tamaños que se admiten para el tamaño y formato de superficie de vista previa. Los OEM deben admitir al menos el formato PRIVATE .

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() devuelve el formato y los tamaños admitidos para la superficie de captura fija. Los OEM deben admitir la salida en formato JPEG y YUV_420_888 .

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() devuelve los tamaños admitidos para una transmisión YUV_420_888 adicional para el análisis de imágenes. Si la superficie YUV de análisis de imágenes no es compatible, getSupportedYuvAnalysisResolutions() debería devolver un null o una lista vacía.

  • Claves/resultados de solicitud de captura disponibles (agregados en extensions-interface 1.3.0): Camera2/X invoca los siguientes métodos para recuperar las claves de solicitud de captura y las claves de resultado compatibles de su implementación:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Para obtener más información, consulte Claves y resultados de solicitud de captura de soporte .

Flujo de aplicación 3: Vista previa/captura fija con extensión habilitada

AdvancedAppFlow3

Figura 10. Flujo de aplicaciones 3 en Advanced Extender

El diagrama anterior muestra el flujo principal para iniciar la vista previa y la captura fija para el tipo Extensor avanzado. Recorramos cada paso.

  1. Instancia SessionProcessorImpl

    La implementación central de Advanced Extender está en SessionProcessorImpl , que es responsable de proporcionar una configuración de sesión personalizada y enviar solicitudes de captura para iniciar la solicitud de vista previa y captura fija. Se invoca AdvancedExtenderImpl.createSessionProcessor() para devolver la instancia de SessionProcessorImpl .

  2. initSession

    SessionProcessorImpl.initSession() inicializa la sesión para la extensión. Aquí es donde asigna recursos y devuelve una configuración de sesión para preparar una CameraCaptureSession .

    Para los parámetros de entrada, Camera2/X especifica las configuraciones de la superficie de salida para la vista previa, la captura fija y un análisis de imagen YUV opcional. Esta configuración de superficie de salida ( OutputSurfaceImpl ) contiene la superficie, el tamaño y el formato de imagen que se recuperan mediante los siguientes métodos en AdvancedExtenderImpl :

    • getSupportedPreviewOutputResolutions()
    • getSupportedCaptureOutputResolutions()
    • getSupportedYuvAnalysisResolutions()

    Debe devolver una instancia de Camera2SessionConfigImpl , que consta de una lista de instancias de Camera2OutputConfigImpl y los parámetros de sesión utilizados para configurar CameraCaptureSession . Usted es responsable de enviar las imágenes de cámara correctas a las superficies de salida que pasa Camera2/X. Aquí hay algunas opciones para habilitar la salida:

    • Procesamiento en cámara HAL: puede agregar directamente las superficies de salida a CameraCaptureSession con una implementación de SurfaceOutputConfigImpl . Esto configura la superficie de salida suministrada a la canalización de la cámara y permite que la HAL de la cámara procese la imagen.
    • Procesamiento de la superficie intermedia de ImageReader (RAW, YUV, etc.): agregue las superficies intermedias de ImageReader a CameraCaptureSession con una instancia de ImageReaderOutputConfigImpl .

      Debe procesar las imágenes intermedias y escribir la imagen resultante en la superficie de salida.

    • Usar el uso compartido de superficie de Camera2: use el uso compartido de superficie con otra superficie agregando cualquier instancia de Camera2OutputConfigImpl al método getSurfaceSharingOutputConfigs() de otra instancia de Camera2OutputConfigImpl . El formato de la superficie y el tamaño deben ser idénticos.

    Todos los Camera2OutputConfigImpl incluidos SurfaceOutputConfigImpl e ImageReaderOutputConfigImpl , deben tener un ID único ( getId() ), que se utiliza para especificar la superficie de destino y recuperar la imagen de ImageReaderOutputConfigImpl .

  3. onCaptureSessionStart y RequestProcessorImpl

    Cuando se inicia CameraCaptureSession y el marco de Camera invoca onConfigured() , Camera2/X invoca SessionProcessorImpl.onCaptureSessionStart() con el contenedor de solicitud RequestProcessImpl . Camera2/X implementa RequestProcessImpl , que le permite ejecutar las solicitudes de captura y recuperar imágenes si se usa ImageReaderOutputConfigImpl .

    Las API de RequestProcessImpl son similares a las API de CameraCaptureSession en términos de ejecución de solicitudes. Las diferencias son:

    • La superficie de destino se especifica mediante el ID de la instancia de Camera2OutputConfigImpl .
    • La capacidad de recuperar la imagen de ImageReader .

    Puede llamar a RequestProcessorImpl.setImageProcessor() con un ID de Camera2OutputConfigImpl especificado para registrar una instancia de ImageProcessorImpl para recibir imágenes.

    La instancia RequestProcessImpl ser válida después de que Camera2/X llame a SessionProcessorImpl.onCaptureSessionEnd() .

  4. Inicie la vista previa y tome una foto

    En la implementación de Advanced Extender, puede enviar solicitudes de captura a través de la interfaz RequestProcessorImpl . Camera2/X le notifica que inicie la solicitud repetitiva de vista previa o la secuencia de captura fija llamando a SessionProcessorImpl#startRepeating y SessionProcessorImpl#startCapture respectivamente. Debe enviar solicitudes de captura para satisfacer estas solicitudes de vista previa y captura fija.

    Camera2/X también establece los parámetros de solicitud de captura a través SessionProcessorImpl#setParameters . Debe configurar estos parámetros de solicitud (si los parámetros son compatibles) tanto en las solicitudes repetidas como en las únicas.

    Debe admitir al menos CaptureRequest.JPEG_ORIENTATION y CaptureRequest.JPEG_QUALITY . extensions-interface 1.3.0 admite claves de solicitud y resultado, que se exponen mediante los siguientes métodos:

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

    Cuando los desarrolladores configuran las claves en la lista getAvailableCaptureRequestKeys , debe habilitar los parámetros y asegurarse de que el resultado de la captura contenga las claves en la lista getAvailableCaptureResultKeys .

  5. startTrigger

    SessionProcessorImpl.startTrigger() se invoca para iniciar el activador, como CaptureRequest.CONTROL_AF_TRIGGER y CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER . Puede ignorar cualquier clave de solicitud de captura que no se haya anunciado en AdvancedExtenderImpl.getAvailableCaptureRequestKeys() .

    startTrigger() ha sido compatible desde extensions-interface 1.3.0. Permite que las aplicaciones implementen tap-to-focus y flash con extensiones.

  6. Limpiar

    Al finalizar una sesión de captura, se invoca SessionProcessorImpl.onCaptureSessionEnd() antes de cerrar CameraCaptureSession . Una vez cerrada la sesión de captura, deInitSession() realiza la limpieza.

Admite vista previa, captura fija y análisis de imágenes

Debe aplicar la extensión tanto para la vista previa como para los casos de uso de captura fija. Sin embargo, si la latencia es demasiado alta para mostrar la vista previa sin problemas, puede aplicar el efecto solo para la captura fija.

Para el tipo de extensor básico, independientemente de habilitar el efecto para la vista previa, debe implementar ImageCaptureExtenderImpl y PreviewExtenderImpl para una extensión determinada. 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 .