Extensiones de la cámara

Los fabricantes de dispositivos pueden exponer extensiones como bokeh, modo nocturno y HDR a desarrolladores externos a través de la interfaz de extensiones de cámara que proporciona la biblioteca de proveedores del OEM. Los desarrolladores pueden usar la API de extensiones de Camera2 y la API de extensiones de CameraX para acceder a las extensiones implementadas en la biblioteca del proveedor del OEM.

Para obtener una lista de las extensiones compatibles, que es la misma en Camera2 y CameraX, consulta la API de Extensions para CameraX. Si quieres agregar una extensión, informa un error en la Herramienta de seguimiento de errores.

En esta página, se describe cómo implementar y habilitar la biblioteca del proveedor del OEM en los dispositivos.

Arquitectura

En el siguiente diagrama, se describe la arquitectura de la interfaz de extensiones de cámara o extensions-interface: Arquitectura

Figura 1: Diagrama de arquitectura de las extensiones de cámara

Como se muestra en el diagrama, para admitir extensiones de cámara, debes implementar el extensions-interface que proporciona la biblioteca del proveedor del OEM. Tu biblioteca de proveedores de OEM habilita dos APIs: la API de Extensions para CameraX y la API de Extensions para Camera2, que usan las apps de CameraX y Camera2, respectivamente, para acceder a las extensiones de proveedores.

Implementa la biblioteca del proveedor del OEM

Para implementar la biblioteca del proveedor del OEM, copia los archivos camera-extensions-stub en un proyecto de biblioteca del sistema. Estos archivos definen la interfaz de Camera Extensions.

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

Archivos de interfaz esenciales (no los modifiques)

  • 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 (agrega tu implementación)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Clases de Bokeh Extender (implementa si se admite la extensión de Bokeh)

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

Clases de amplificadores nocturnos (implementarla si se admite la extensión Night)

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

Clases de amplificadores automáticos (implementa esta función si se admite la extensión automática)

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

Clases de amplificadores de HDR (implementa si se admite la extensión de HDR)

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

Clases de extensión de Face Retouch (implementa esta función si la extensión de Face Retouch es compatible)

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

Utilidades (opcionales, se pueden borrar)

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

No es necesario que proporciones una implementación para cada extensión. Si no implementas una extensión, configura isExtensionAvailable() para que muestre false o quita las clases correspondientes del amplificador. Las APIs de Camera2 y CameraX Extensions informan a la app que la extensión no está disponible.

Analicemos cómo las APIs de Camera2 y CameraX Extensions interactúan con la biblioteca del proveedor para habilitar una extensión. En el siguiente diagrama, se ilustra el flujo de extremo a extremo con la extensión Night como ejemplo:

Flujo principal

Figura 2: Implementación de la extensión nocturna

  1. Verificación de versión:

    Camera2/X llama a ExtensionVersionImpl.checkApiVersion() para garantizar que la versión de 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. Crea instancias de clases de Extender:

    Crea instancias de las clases de amplificador para la extensión. Existen dos tipos de amplificadores: básico y avanzado. Debes implementar un tipo de elemento de extensión para todas las extensiones. Para obtener más información, consulta Diferencias entre el amplificador básico y el amplificador avanzado.

    Camera2/X crea instancias de las clases del amplificador e interactúa con ellas para recuperar información y habilitar la extensión. Para una extensión determinada, Camera2/X puede crear instancias de las clases de Extender varias veces. Como resultado, no realices la inicialización de tareas pesadas en el constructor ni en la llamada a init(). Realiza las tareas pesadas solo cuando esté a punto de comenzar la sesión de la cámara, por ejemplo, cuando se llame a onInit() en el amplificador básico o a initSession() en el amplificador avanzado.

    Para la extensión Night, se crean instancias de las siguientes clases de amplificador para el tipo de amplificador básico:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    Y para el tipo de amplificador avanzado:

    • NightAdvancedExtenderImpl.java
  4. Verifica la disponibilidad de la extensión:

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

  5. Inicializa el amplificador 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. Consulta información:

    Invoca la clase de amplificador para recuperar información, como las resoluciones compatibles, capturar la latencia estimada y capturar las claves de solicitud del amplificador en preparación para habilitar la extensión.

  7. Habilita la extensión en el amplificador:

    La clase de amplificador proporciona todas las interfaces necesarias para habilitar la clase. Ofrece un mecanismo para conectar la implementación del OEM a la canalización de Camera2, como insertar parámetros de solicitud de captura o habilitar un postprocesador.

    En el caso del 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 amplificador.

En las siguientes secciones, se describe el flujo de extensión con mayor detalle.

Verificación de la versión

Cuando se carga la biblioteca del proveedor del OEM desde el dispositivo en el tiempo de ejecución, Camera2/X verifica si la biblioteca es compatible con la versión de extensions-interface. extensions-interface usa el control de versiones semántico o MAJOR.MINOR.PATCH, por ejemplo, 1.1.0 o 1.2.0. Sin embargo, solo se usan las versiones principales y secundarias durante la verificación de versiones.

Para verificar la versión, Camera2/X llama a ExtensionVersionImpl.checkApiVersion() con la versión extensions-interface compatible. Luego, Camera2/X usa la versión que informa la biblioteca del OEM para determinar si se puede habilitar la extensión y qué funciones 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, se considera incompatible y se inhabilita la extensión.

Retrocompatibilidad

Siempre que la versión principal sea idéntica, Camera2/X garantiza la retrocompatibilidad con las bibliotecas de proveedores de OEM compiladas con versiones anteriores de extensions-interface. Por ejemplo, si Camera2/X admite extensions-interface 1.3.0, las bibliotecas del proveedor del 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 retrocompatible con las próximas versiones de extension-interface.

Compatibilidad con versiones posteriores

La compatibilidad con las bibliotecas de proveedores de la versión extensions-interface más reciente depende de ti, el OEM. Si necesitas algunas funciones para implementar las extensiones, te recomendamos que las habilites a partir de una versión determinada. En este caso, puedes mostrar la versión compatible de extensions-interface cuando la versión de la biblioteca de Camera2/X cumpla con los requisitos. Si las versiones de Camera2/X no son compatibles, puedes mostrar una versión incompatible, como la 99.0.0, para inhabilitar las extensiones.

Inicialización de la biblioteca de proveedores

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

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

Debes 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 del OEM implementa extensions-interface 1.0.0.

Amplificador básico frente a amplificador avanzado

Existen dos tipos de implementación de extensions-interface: el amplificador básico y el amplificador avanzado. El amplificador avanzado es compatible desde extensions-interface 1.2.0.

Implementa el extensor básico para extensiones que procesan imágenes en el HAL de la cámara o usan un postprocesador capaz de procesar transmisiones YUV.

Implementa el amplificador avanzado para las extensiones que necesitan personalizar la configuración de transmisión de Camera2 y enviar solicitudes de captura según sea necesario.

Consulta la siguiente tabla para ver la comparación:

Amplificador básico Extensor avanzado
Parámetros de configuración de las transmisiones Corregido
Vista previa: PRIVATE o YUV_420_888 (si existe procesador)
Captura aún: JPEG o YUV_420_888 (si existe procesador)
Personalizable por el OEM.
Cómo enviar una solicitud de captura Solo Camera2/X puede enviar solicitudes de captura. Puedes 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 captura al procesador. Se te proporciona una instancia de RequestProcessorImpl para ejecutar la solicitud de captura de camera2 y obtener resultados y una imagen.

Camera2/X invoca startRepeating y startCapture en SessionProcessorImpl para indicarle al OEM que inicie la solicitud repetida de vista previa y la secuencia de captura de imágenes fijas, respectivamente.

Enganches 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 que se configura CameraCaptureSession.
  • onDisableSession envía una sola solicitud antes de que se cierre CameraCaptureSession.
  • initSession inicializa y muestra una configuración de sesión personalizada de Camera2 para crear la sesión de captura.
  • Se invoca onCaptureSessionStart inmediatamente después de que se configura CameraCaptureSession.
  • Se invoca a onCaptureSessionEnd antes de que se cierre CameraCaptureSession.
Adecuado para Extensiones implementadas en el HAL de la cámara o en un procesador que procesa imágenes YUV
  • Tiene implementaciones basadas en Camera2 para las extensiones.
  • Necesita una configuración de transmisión personalizada, como una transmisión RAW.
  • Necesita una secuencia de captura interactiva.
Versión de la API compatible Extensiones de Camera2: Android 13 o versiones posteriores
Extensiones de CameraX: camera-extensions 1.1.0 o versiones posteriores
Extensiones de Camera2: Android 12L o versiones posteriores
Extensiones de CameraX: camera-extensions 1.2.0-alpha03 o versiones posteriores

Flujos de la app

En la siguiente tabla, se muestran tres tipos de flujos de apps y sus correspondientes llamadas a la API de Extensiones de cámara. Si bien Camera2/X proporciona estas APIs, debes implementar correctamente la biblioteca del proveedor para admitir estos flujos, que describiremos con más detalle en una sección posterior.

Extensiones de Camera2 Extensiones de CameraX
Consulta la disponibilidad de las extensiones CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
Consulta información CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

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

Vista previa y captura estática con la extensión habilitada CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...)

Amplificador básico

La interfaz del amplificador básico proporciona hooks en varios lugares de la canalización de la cámara. Cada tipo de extensión tiene las clases de amplificador correspondientes que los OEMs deben implementar.

En la siguiente tabla, se enumeran las clases de amplificadores que los OEMs deben implementar para cada extensión:

Clases de extensión para implementar
Noche NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Automático AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Retoque facial BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

En el siguiente ejemplo, usamos PreviewExtenderImpl y ImageCaptureExtenderImpl como marcadores de posición. Reemplaza estos valores por los nombres de los archivos reales que implementarás.

El amplificador básico tiene las siguientes funciones:

  • Inyecta parámetros de sesión cuando configures CameraCaptureSession (onPresetSession).
  • Notificarte 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 que se muestran (onEnableSession, onDisableSession)
  • Inyecta parámetros de captura para la solicitud (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Agrega procesadores para la vista previa y la captura fija que puedan procesar la transmisión de YUV_420_888.

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

Flujo de la app 1: Comprueba la disponibilidad de la extensión

BasicExtenderAppFlow1

Figura 3: Flujo de app 1 en el amplificador básico

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

A menudo, este es el primer paso que deben dar las apps para verificar si el tipo de extensión determinado es compatible con un ID de cámara determinado antes de habilitar la extensión. Esto se debe a que algunas extensiones solo son compatibles con ciertos IDs de cámara.

Flujo de la app 2: Consulta información

BasicExtenderAppFlow2

Figura 4: Flujo de la app 2 en el amplificador básico

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

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

  • Tamaños admitidos para la vista previa y la superficie de captura: ImageCaptureExtenderImpl.getSupportedResolutions y PreviewExtenderImpl.getSupportedResolutions muestran 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 resultados admitidas: Camera2/X invoca los siguientes métodos para recuperar las claves de solicitud de captura y de resultados admitidas de tu implementación:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

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

Flujo de la app 3: Vista previa o captura de imágenes fijas con la extensión habilitada (implementación de HAL)

BasicExtenderAppFlow3

Figura 5: Flujo de la app 3 en el amplificador básico

En el diagrama anterior, se ilustra el flujo principal para habilitar la vista previa y la captura de imágenes fijas con una extensión sin ningún procesador. Esto significa que la HAL de la cámara procesa la extensión.

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

Cuando se configura CameraCaptureSession, Camera2/X invoca a onPresetSession para obtener los parámetros de la sesión. Después de que la sesión de captura se configure correctamente, Camera2/X invoca a onEnableSession y muestra una instancia de CaptureStageImpl que contiene los parámetros de captura. Camera2/X envía inmediatamente una sola solicitud con estos parámetros de captura para notificar al HAL. De manera similar, antes de que se cierre la sesión de captura, Camera2/X invoca a onDisableSession y, luego, envía una sola solicitud con los parámetros de captura que se devuelven.

La solicitud repetida que activa Camera2/X contiene los parámetros de solicitud que muestra PreviewExtenderImpl.getCaptureStage(). Además, la solicitud de captura de imágenes fijas contiene los parámetros que muestra ImageCaptureExtenderImpl.getCaptureStages().

Por último, Camera2/X invoca a onDeInit() después de que finaliza la sesión de la cámara. Puedes liberar recursos en onDeinit().

Procesador de vista previa

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

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

  • PROCESSOR_TYPE_NONE: No hay procesador. Las imágenes se procesan en el HAL de la cámara.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY: El tipo de procesador te permite actualizar la solicitud recurrente con nuevos parámetros de solicitud de captura según el TotalCaptureResult más reciente.

    PreviewExtenderImpl.getProcessor debe mostrar una instancia de RequestUpdateProcessorImpl que procese la instancia de TotalCaptureResult y muestre una instancia de CaptureStageImpl para actualizar la solicitud recurrente. PreviewExtenderImpl.getCaptureStage() también debe reflejar el resultado del procesamiento y mostrar el CaptureStageImpl más reciente.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR: Este tipo te permite implementar un procesador para procesar imágenes YUV_420_888 y escribir el resultado en una superficie PRIVATE.

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

    Consulta la siguiente ilustración para ver el flujo:

PreviewProcessor

Figura 6: Flujo de vista previa con PreviewImageProcessorImpl

La interfaz PreviewImageProcessorImpl extiende 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íxeles, 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 imágenes

Para la captura de imágenes fijas, puedes implementar un procesador devolviendo una instancia de CaptureProcessorImpl con ImageCaptureExtenderImpl.getCaptureProcessor. El procesador es responsable de procesar una lista de las imágenes YUV_420_888 y las instancias de TotalCaptureResult capturadas, y de escribir el resultado en una plataforma YUV_420_888.

Puedes suponer con seguridad que la vista previa está habilitada y en ejecución antes de enviar la solicitud de captura de imágenes fijas.

Observa el flujo en el siguiente diagrama:

CaptureProcessor

Figura 7: Captura de flujo continuo con CaptureProcessorImpl

  1. Camera2/X usa una superficie de formato YUV_420_888 para la captura de imágenes fijas para configurar la sesión de captura. Camera2/X prepara CaptureProcessorImpl con una llamada a lo siguiente:

    • CaptureProcessorImpl.onImageFormatUpdate() con YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() por el tamaño de la imagen de entrada
    • CaptureProcessorImpl.onOutputSurface() con una superficie YUV_420_888 de salida.
  2. ImageCaptureExtenderImpl.getCaptureStages muestra una lista de CaptureStageImpl, en la que cada elemento se asigna a una instancia de CaptureRequest con parámetros de captura que envía Camera2/X. Por ejemplo, si muestra 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 de 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 del resultado (formato YUV_420_888) en la superficie de salida especificada por la llamada a onOutputSurface(). Camera2/X lo convierte en imágenes JPEG si es necesario.

Admite claves y resultados de solicitudes de captura

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

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

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() muestra las claves de solicitud de captura compatibles con tu implementación.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() muestra las claves de resultados de captura que se contienen 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. Eres responsable de informar el resultado de la captura a través de ProcessResultImpl a Camera2/X.

Consulta la definición de la interfaz CaptureProcessorImpl a continuación como ejemplo. En extensions-interface 1.3.0 o versiones posteriores, se invoca la segunda llamada a 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 el zoom, el enfoque con un toque, el flash y la compensación de exposición, te recomendamos que admitas las siguientes claves para la solicitud de captura y el resultado de la captura:

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

En el caso de los amplificadores básicos que implementan la versión 1.2.0 o versiones anteriores, la API de CameraX Extensions admite de forma explícita todas las claves anteriores. Para extensions-interface 1.3.0, CameraX y Camera2 respetan la lista que se muestra y solo admiten las claves que contiene. Por ejemplo, si decides mostrar solo CaptureRequest#CONTROL_ZOOM_RATIO y CaptureRequest#SCALER_CROP_REGION en la implementación de la versión 1.3.0, eso significa que solo se admite el zoom para la app, mientras que no se permiten la función de presionar para enfocar, el flash ni la compensación de exposición.

Extensor avanzado

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

  • Configuración de transmisión personalizada: Configura transmisiones personalizadas, como transmisiones RAW, o establece varias transmisiones para diferentes IDs 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.

El amplificador avanzado proporciona un wrapper o una capa intermedia para que puedas personalizar la configuración de la transmisión y enviar solicitudes de captura a pedido.

Archivos para implementar

Para cambiar a la implementación del amplificador avanzado, el método isAdvancedExtenderImplemented() en ExtensionVersionImpl debe mostrar true. Para cada tipo de extensión, los OEMs deben implementar las clases de amplificador correspondientes. Los archivos de implementación del amplificador avanzado se encuentran en el paquete advanced.

Clases de extensión para implementar
Noche advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Automático advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Retoque de rostro advanced/BeautyAdvancedExtenderImpl.java

En el siguiente ejemplo, usamos AdvancedExtenderImpl como marcador de posición. Reemplázalo por el nombre del archivo del amplificador de la extensión que vas a implementar.

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

Flujo de la app 1: Comprueba la disponibilidad de las extensiones

AdvancedAppFlow1

Figura 8: Flujo de la app 1 en el amplificador avanzado

Primero, la app comprueba si la extensión en cuestión es compatible.

Flujo de la app 2: Consulta información

AdvancedAppFlow2

Figura 9: Flujo de la app 2 en el amplificador avanzado

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

  • Latencia estimada de captura de imágenes estáticas: AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() muestra el rango de latencia de captura para que la app evalúe si es apropiado habilitar la extensión para la situación actual.

  • Resoluciones admitidas para la vista previa y la captura de imágenes estáticas:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() muestra un mapa de formato de imagen para la lista de tamaños compatibles con el formato y el tamaño de la superficie de vista previa. Los OEMs deben admitir al menos el formato PRIVATE.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() muestra el formato y los tamaños admitidos para la superficie de captura de imágenes fijas. Los OEMs deben admitir resultados en formato JPEG y YUV_420_888.

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() muestra los tamaños compatibles para un flujo 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() debe mostrar null o una lista vacía.

  • Claves o resultados de solicitud de captura disponibles (se agregó 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 tu implementación:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Para obtener más información, consulta Cómo admitir claves y resultados de solicitudes de captura.

Flujo de app 3: Vista previa o captura estática con la extensión habilitada

Flujo de aplicación avanzado3

Figura 10: Flujo de la app 3 en el amplificador avanzado

En el diagrama anterior, se muestra el flujo principal para iniciar la vista previa y capturar imágenes fijas del tipo de amplificador avanzado. Veamos cada paso.

  1. Instancia de SessionProcessorImpl

    La implementación principal del amplificador avanzado se encuentra en SessionProcessorImpl, que es responsable de proporcionar la configuración de la sesión personalizada y enviar solicitudes de captura para iniciar la vista previa y capturar la solicitud. AdvancedExtenderImpl.createSessionProcessor() se invoca para mostrar la instancia SessionProcessorImpl.

  2. initSession

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

    Para los parámetros de entrada, Camera2/X especifica las configuraciones de la superficie de salida para la vista previa, la captura de imágenes fijas y un análisis de imágenes 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()

    Debes mostrar una instancia de Camera2SessionConfigImpl, que consta de una lista de instancias de Camera2OutputConfigImpl y los parámetros de sesión que se usan para configurar CameraCaptureSession. Eres responsable de generar las imágenes de cámara correctas en las superficies de salida que pasa Camera2/X. Estas son algunas opciones para habilitar el resultado:

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

      Debes procesar las imágenes intermedias y escribir la imagen del resultado en la superficie de salida.

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

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

  3. onCaptureSessionStart y RequestProcessorImpl

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

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

    • El ID de la instancia de Camera2OutputConfigImpl especifica la plataforma de destino.
    • La capacidad de recuperar la imagen de ImageReader

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

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

  4. Cómo iniciar la vista previa y tomar una foto

    En la implementación del amplificador avanzado, puedes enviar solicitudes de captura a través de la interfaz RequestProcessorImpl. Camera2/X te notifica que debes iniciar la solicitud de repetición para la vista previa o la secuencia de captura de imágenes fijas llamando a SessionProcessorImpl#startRepeating y SessionProcessorImpl#startCapture, respectivamente. Debes enviar solicitudes de captura para satisfacer estas solicitudes de vista previa y captura de imágenes fijas.

    Camera2/X también establece los parámetros de solicitud de captura a través de SessionProcessorImpl#setParameters. Debes configurar estos parámetros de solicitud (si se admiten) en las solicitudes únicas y repetidas.

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

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

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

  5. startTrigger

    Se invoca a SessionProcessorImpl.startTrigger() para iniciar el activador, como CaptureRequest.CONTROL_AF_TRIGGER y CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Puedes ignorar las claves de solicitud de captura que no se anunciaron en AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    startTrigger() es compatible desde extensions-interface 1.3.0. Permite que las apps implementen el enfoque con un toque y la función de flash con extensiones.

  6. Realiza una limpieza

    Cuando finalizas una sesión de captura, se invoca a SessionProcessorImpl.onCaptureSessionEnd() antes de cerrar CameraCaptureSession. Después de que se cierre la sesión de captura, deInitSession() realizará la limpieza.

Compatibilidad con la vista previa, la captura estática y el análisis de imágenes

Deberías aplicar la extensión tanto para la vista previa como para los casos de uso de la captura de imágenes. Sin embargo, si la latencia es demasiado alta para mostrar la vista previa sin problemas, puedes aplicar la extensión solo para la captura de imágenes fijas.

En el caso del tipo de amplificador básico, independientemente de que habilites la extensión para la vista previa, debes implementar ImageCaptureExtenderImpl y PreviewExtenderImpl para una extensión determinada. A menudo, una app también usa una transmisión YUV para analizar el contenido de la imagen, como encontrar códigos QR o texto. Para admitir mejor este caso de uso, debes admitir la combinación de transmisión de vista previa, captura de imágenes fijas y una transmisión de YUV_420_888 para configurar CameraCaptureSession. Esto significa que, si implementas un procesador, debes admitir la combinación de flujos de tres flujos de YUV_420_888.

En el caso del amplificador avanzado, Camera2/X pasa tres superficies de salida a la llamada a SessionProcessorImpl.initSession(). Estas plataformas de salida son para la vista previa, la captura de imágenes fijas y el análisis de imágenes, respectivamente. Debes asegurarte de que las plataformas de salida de vista previa y captura de imágenes fijas muestren el resultado válido. Sin embargo, para la superficie de salida del análisis de imágenes, asegúrate de que funcione solo cuando no sea nulo. Si tu implementación no puede admitir el flujo de análisis de imágenes, puedes mostrar una lista vacía en AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). Esto garantiza que la superficie de salida del análisis de imágenes siempre sea nula en SessionProcessorImpl.initSession().

Compatibilidad con la captura de video

La arquitectura actual de la extensión de cámara solo admite la vista previa y los casos de uso de captura de todos modos. No se admite habilitar la extensión en las plataformas MediaCodec o MediaRecorder para grabar el video. Sin embargo, es posible que las apps graben el resultado de la vista previa.

Se está investigando la compatibilidad con las plataformas MediaCodec y MediaRecorder.

Metadatos específicos de la extensión

En Android 14 y versiones posteriores, los metadatos específicos de la extensión permiten que los clientes de la extensión de la cámara establezcan y reciban la configuración y los resultados de la solicitud de captura específicos de la extensión. Específicamente, los clientes de extensiones de cámara pueden usar el parámetro de solicitud de captura EXTENSION_STRENGTH para controlar la intensidad de la extensión y el resultado de captura EXTENSION_CURRENT_TYPE para indicar el tipo de extensión habilitada.

Solicitudes de captura

El parámetro de solicitud de captura EXTENSION_STRENGTH controla la intensidad del efecto de procesamiento posterior de la extensión. El resultado de captura correspondiente incluye el valor de intensidad predeterminado si el cliente no establece este parámetro de forma explícita. Este parámetro se puede aplicar de la siguiente manera para estos tipos de extensiones:

  • BOKEH: Controla la cantidad de desenfoque.
  • HDR y NIGHT: Controlan la cantidad de imágenes fusionadas y el brillo de la imagen final.
  • FACE_RETOUCH: Controla la cantidad de mejora cosmética y suavización de la piel.

El rango admitido para el parámetro EXTENSION_STRENGTH es entre 0 y 100, con 0 que indica que no hay procesamiento de extensión ni transferencia directa simple, y 100 que indica la intensidad máxima de extensión del efecto de procesamiento.

Para agregar compatibilidad con EXTENSION_STRENGTH, usa las APIs de parámetros específicos del proveedor que se introdujeron en la versión 1.3.0 de la interfaz de la biblioteca de extensiones. Para obtener más información, consulta getAvailableCaptureRequestKeys().

Captura los resultados

El resultado de captura de EXTENSION_CURRENT_TYPE permite que las implementaciones de extensiones notifiquen a los clientes sobre el tipo de extensión activo.

Debido a que las extensiones que usan el tipo AUTO cambian de forma dinámica entre tipos de extensiones, como HDR y NIGHT, según las condiciones de la escena, las apps de extensiones de cámara pueden usar EXTENSION_CURRENT_TYPE para mostrar información sobre la extensión actual que seleccionó la extensión AUTO.

Estimación de latencia de capturas estáticas en tiempo real

En Android 14 y versiones posteriores, los clientes de la extensión de la cámara pueden consultar estimaciones de latencia de capturas estáticas en tiempo real según las condiciones de la escena y el entorno con getRealtimeStillCaptureLatency(). Este método proporciona estimaciones más precisas que el método estático getEstimatedCaptureLatencyRangeMillis(). Según la estimación de latencia, las apps pueden decidir omitir el procesamiento de la extensión o mostrar una indicación para notificar a los usuarios sobre una operación de larga duración.

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();

Para admitir estimaciones de latencia de capturas estáticas en tiempo real, implementa lo siguiente:

Devoluciones de llamada del progreso de procesamiento de la captura

En Android 14 y versiones posteriores, los clientes de extensión de cámara pueden recibir devoluciones de llamada para el progreso de las operaciones de procesamiento de capturas de imágenes fijas de larga duración. Las apps pueden mostrar el progreso actual a los usuarios para mejorar su experiencia general.

Las apps pueden usar el siguiente código para integrar esta función:

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
    }
  }

}

Para admitir devoluciones de llamada del progreso de procesamiento de la captura, la implementación del proveedor de la extensión debe llamar a las siguientes devoluciones de llamada con el valor de progreso actual:

Captura estática de la vista previa

En Android 14 y versiones posteriores, las extensiones de cámara pueden proporcionar una vista posterior (imagen de vista previa) con setPostviewOutputConfiguration. Para mejorar la experiencia del usuario, las apps pueden mostrar una imagen de vista posterior como marcador de posición cuando una extensión experimenta una mayor latencia de procesamiento y reemplazar la imagen cuando la imagen final esté disponible. Las apps pueden configurar y emitir solicitudes de captura de vistas posteriores con el siguiente código de referencia:

{

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();

}

Para admitir la captura de imágenes fijas de vistas posteriores, la implementación de tu proveedor debe implementar lo siguiente:

Compatibilidad con el resultado de SurfaceView

En Android 14 y versiones posteriores, los clientes de extensiones de cámara pueden usar rutas de renderización de vista previa optimizadas para el rendimiento y la energía registrando una instancia de SurfaceView para el resultado de la vista previa de las solicitudes repetidas.

Para admitir el resultado de SurfaceView, la implementación de la extensión de tu proveedor debe poder transmitir y generar vistas previas en instancias de SurfaceView. Para verificar que esto sea compatible, ejecuta el módulo CTS SurfaceViewExtensionPreviewTest.java.

Tipos de sesión específicos del proveedor

La función permite que las implementaciones de extensiones de proveedores seleccionen un tipo de sesión específico del proveedor que se configurará en la sesión de captura de cámara interna en lugar del valor predeterminado.

La función funciona por completo dentro del framework y la pila de proveedores, y no tiene ningún impacto en la API visible para el cliente o el público.

Para seleccionar un tipo de sesión específico del proveedor, implementa lo siguiente en tus bibliotecas de extensiones: * ExtenderStateListener.onSessionType() para extensiones básicas * Camera2SessionConfigImpl.getSessionType() para extensiones avanzadas

Historial de versiones de la interfaz de extensiones

En la siguiente tabla, se muestra el historial de versiones de la interfaz de la extensión de cámara. Siempre debes implementar la biblioteca del proveedor con la versión más reciente.

Versión Funciones agregadas
1.0.0
  • Verificación de la versión
    • ExtensionVersionImpl
  • Repetidor básico
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Inicialización de la biblioteca
    • InitializerImpl
  • Cómo exponer las resoluciones compatibles
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Obtén la latencia de captura estimada
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Se expusieron las claves de solicitud de captura o de resultados compatibles.
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys y getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys y getAvailableCaptureResultKeys
    • Nueva llamada a process() que toma ProcessResultImpl en PreviewImageProcessorImpl y CaptureProcessorImpl
    • Solicitud de tipo de activador de asistencia
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Metadatos específicos de la extensión
  • Estimaciones de latencia de capturas estáticas dinámicas
  • Captura devoluciones de llamada del progreso de procesamiento
  • Captura estática de la vista previa
  • Compatibilidad con la salida SurfaceView
  • Tipos de sesión específicos del proveedor

Implementación de referencia

Las siguientes implementaciones de bibliotecas de proveedores de OEM de referencia están disponibles en frameworks/ex.

  • advancedSample: Es una implementación básica del amplificador avanzado.

  • sample: Una implementación básica del amplificador básico.

  • service_based_sample: Una implementación que demuestra cómo alojar extensiones de la cámara en un Service. Esta implementación contiene los siguientes componentes:

    • oem_library: Una biblioteca OEM de extensiones de cámara para las APIs de Camera2 y CameraX Extensions que implementa Extensions-Interface. Esto actúa como un puente que reenvía las llamadas de Extensions-Interface al servicio. Esta biblioteca también proporciona archivos AIDL y clases de wrapper para comunicarse con el servicio.

      El amplificador avanzado está habilitado de forma predeterminada. Para habilitar el amplificador básico, cambia ExtensionsVersionImpl#isAdvancedExtenderImplemented para que muestre false.

    • extensions_service: Es una implementación de ejemplo del servicio de extensiones. Agrega tu implementación aquí. La interfaz que se implementará en el servicio es similar a Extensions-Interface. Por ejemplo, implementar IAdvancedExtenderImpl.Stub realiza las mismas operaciones que AdvancedExtenderImpl. ImageWrapper y TotalCaptureResultWrapper son obligatorios para que Image y TotalCaptureResult sean particionables.

Cómo configurar la biblioteca del proveedor en un dispositivo

La biblioteca del proveedor del OEM no está integrada en una app; Camera2/X la carga desde el dispositivo durante el tiempo de ejecución. En CameraX, la etiqueta <uses-library> declara que la biblioteca androidx.camera.extensions.impl, que se define en el archivo AndroidManifest.xml de la biblioteca camera-extensions, es una dependencia de CameraX y debe cargarse durante el tiempo de ejecución. En Camera2, el framework carga un servicio de extensiones que también declara que <uses-library> carga la misma biblioteca androidx.camera.extensions.impl durante el tiempo de ejecución.

Esto permite que las apps de terceros que usan extensiones carguen automáticamente la biblioteca de proveedores del OEM. La biblioteca del OEM se marca como opcional para que las apps se ejecuten en dispositivos que no la tengan. Camera2/X controla este comportamiento automáticamente cuando una app intenta usar una extensión de cámara, siempre y cuando el fabricante del dispositivo coloque la biblioteca del OEM en el dispositivo para que la app pueda descubrirla.

Para configurar la biblioteca del OEM en un dispositivo, haz lo siguiente:

  1. Agrega un archivo de permiso, que requiere la etiqueta <uses-library>, con el siguiente formato: /etc/permissions/ANY_FILENAME.xml. Por ejemplo, /etc/permissions/camera_extensions.xml. Los archivos de este directorio proporcionan una asignación de la biblioteca nombrada en <uses-library> a la ruta de acceso real del archivo en el dispositivo.
  2. Usa el siguiente ejemplo para agregar la información requerida al archivo.

    • name debe ser androidx.camera.extensions.impl, ya que esa es la biblioteca que busca CameraX.
    • file es la ruta de acceso absoluta del archivo que contiene la implementación de extensiones (por ejemplo, /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>

En Android 12 o versiones posteriores, los dispositivos que admiten extensiones de CameraX deben tener la propiedad ro.camerax.extensions.enabled configurada en true, que permite consultar si un dispositivo admite extensiones. Para ello, agrega la siguiente línea al archivo make del dispositivo:

PRODUCT_VENDOR_PROPERTIES += \
    ro.camerax.extensions.enabled=true \

Validación

Para probar la implementación de la biblioteca del proveedor del OEM durante la etapa de desarrollo, usa la app de ejemplo en androidx-main/camera/integration-tests/extensionstestapp/, que se ejecuta a través de varias extensiones de proveedores.

Después de completar la implementación, usa la herramienta de validación de extensiones de cámara para ejecutar pruebas manuales y automatizadas y verificar que la biblioteca del proveedor se implemente correctamente.

Modo panorámico extendido en comparación con las extensiones de cámara

En el caso de la extensión de desenfoque, además de exponerla con extensiones de cámara, puedes exponerla con el modo panorámico extendido, que se habilita con la clave CONTROL_EXTENDED_SCENE_MODE. Para obtener más detalles sobre la implementación, consulta Bokeh de la cámara.

El modo panorámico extendido tiene menos restricciones en comparación con las extensiones de cámara para apps de Camera2. Por ejemplo, puedes habilitar el modo de escena extendido en una instancia CameraCaptureSession normal que admita combinaciones de transmisiones flexibles y capture parámetros de solicitud. Por el contrario, las extensiones de cámara solo admiten un conjunto fijo de tipos de transmisión y tienen compatibilidad limitada con los parámetros de solicitud de captura.

Una desventaja del modo de escena extendida es que solo puedes implementarlo en el HAL de la cámara, lo que significa que se debe verificar para que funcione en todos los controles ortogonales disponibles para los desarrolladores de apps.

Recomendamos exponer el bokeh con el modo de escena extendida y las extensiones de Camera, ya que las apps pueden preferir usar una API en particular para habilitar el bokeh. Te recomendamos que primero uses el modo de escena extendida, ya que es la forma más flexible en que las apps pueden habilitar la extensión de desenfoque. Luego, puedes implementar la interfaz de extensiones de cámara según el modo panorámico extendido. Si es difícil implementar el bokeh en la HAL de la cámara, por ejemplo, porque requiere un postprocesador que se ejecuta en la capa de la app para procesar imágenes, recomendamos implementar la extensión bokeh con la interfaz de extensiones de la cámara.

Preguntas frecuentes

¿Existen restricciones para los niveles de API?

Sí. Esto depende del conjunto de funciones de la API de Android que requiere la implementación de la biblioteca de proveedores de OEM. Por ejemplo, ExtenderStateListener.onPresetSession() usa la llamada SessionConfiguration.setSessionParameters() para establecer un conjunto de etiquetas de referencia. Esta llamada solo está disponible en el nivel de API 28 y versiones posteriores. Para obtener detalles sobre métodos de interfaz específicos, consulta la documentación de referencia de la API.