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 del OEM. Los desarrolladores pueden usar la API de Camera2 Extensions y la API de CameraX Extensions para acceder a las extensiones implementadas en la biblioteca de proveedores 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 Issue Tracker.
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 Camera Extensions o extensions-interface
:
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. La biblioteca de proveedores de OEM habilita dos APIs: la API de Extensions para CameraX y la API de Extensions para Camera2, que las apps de CameraX y Camera2 usan, 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 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 (agrega tu implementación)
ExtensionVersionImpl.java
InitializerImpl.java
Clases de extensión de bokeh (implementa si se admite la extensión de bokeh)
BokehImageCaptureExtenderImpl.java
BokehPreviewExtenderImpl.java
advanced/BokehAdvancedExtenderImpl.java
Clases de ampliación nocturna (implementa esto si se admite la extensión nocturna)
NightImageCaptureExtenderImpl.java
NightPreviewExtenderImpl.java
advanced/NightAdvancedExtenderImpl.java
Clases de autoextensión (implementa esta opción si se admite la extensión automática)
AutoImageCaptureExtenderImpl.java
AutoPreviewExtenderImpl.java
advanced/AutoAdvancedExtenderImpl.java
Clases de extensión de HDR (implementa esto si se admite la extensión de HDR)
HdrImageCaptureExtenderImpl.java
HdrPreviewExtenderImpl.java
advanced/HdrAdvancedExtenderImpl.java
Clases de extensión de Face Retouch (implementa esto si se admite la extensión de Face Retouch)
BeautyImageCaptureExtenderImpl.java
BeautyPreviewExtenderImpl.java
advanced/BeautyAdvancedExtenderImpl.java
Utilidades (opcional, se puede 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 devuelva false
o quita las clases Extender correspondientes. Las APIs de Camera2 y CameraX Extensions informan a la app que la extensión no está disponible.
Veamos cómo interactúan las APIs de Camera2 y CameraX Extensions 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 Noche como ejemplo:
Figura 2: Implementación de la extensión de noche
Verificación de la versión:
Camera2/X llama a
ExtensionVersionImpl.checkApiVersion()
para garantizar que la versión deextensions-interface
implementada por el OEM sea compatible con las versiones admitidas de Camera2/X.Inicialización de la biblioteca del proveedor:
InitializerImpl
tiene un métodoinit()
que inicializa la biblioteca del proveedor. Camera2/X completa la inicialización antes de acceder a las clases Extender.Crea instancias de las clases de Extender:
Crea instancias de las clases Extender para la extensión. Existen dos tipos de amplificadores: amplificador básico y amplificador avanzado. Debes implementar un tipo de Extender para todas las extensiones. Para obtener más información, consulta Comparación entre el amplificador básico y el amplificador avanzado.
Camera2/X crea instancias de las clases Extender y se comunica con ellas para recuperar información y habilitar la extensión. Para una extensión determinada, Camera2/X puede crear instancias de las clases Extender varias veces. Como resultado, no realices una inicialización pesada en el constructor ni en la llamada a
init()
. Realiza el trabajo pesado solo cuando esté a punto de comenzar la sesión de la cámara, por ejemplo, cuando se llama aonInit()
en Basic Extender o ainitSession()
en Advanced Extender.Para la extensión Noche, se crean instancias de las siguientes clases de Extender para el tipo de Extender básico:
NightImageCaptureExtenderImpl.java
NightPreviewExtenderImpl.java
Y para el tipo de amplificador avanzado:
NightAdvancedExtenderImpl.java
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.Inicializa el Extender 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 yCameraCharacteristics
.Información de la búsqueda:
Invoca la clase Extender para recuperar información, como las resoluciones admitidas, la latencia estimada de captura de imágenes fijas y las claves de solicitud del Extender en preparación para habilitar la extensión.
Habilita la extensión en el amplificador:
La clase Extender 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 la inserción de parámetros de solicitud de captura o la habilitación de un posprocesador.
En el caso del tipo de Extensor avanzado, Camera2/X interactúa con
SessionProcessorImpl
para habilitar la extensión. Camera2/X recupera la instancia deSessionProcessorImpl
llamando acreateSessionProcessor()
en el Extender.
En las siguientes secciones, se describe el flujo de la extensión con más 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 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
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é capacidades debe invocar.
Compatibilidad con versiones principales
Si las versiones principales de extension-interface 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 OEM que implementaron 1.0.0, 1.1.0 y 1.2.0 seguirán 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 versiones posteriores de las bibliotecas del proveedor de extensions-interface
más recientes depende de ti, el OEM. Si necesitas algunas funciones para implementar las extensiones, es posible que quieras habilitarlas a partir de una versión determinada. En este caso, puedes devolver la versión de extensions-interface
compatible cuando la versión de la biblioteca de Camera2/X cumpla con los requisitos. Si no se admiten las versiones de Camera2/X, puedes devolver una versión incompatible, como 99.0.0, para inhabilitar las extensiones.
Inicialización de la biblioteca del proveedor
Después de verificar la versión de extensions-interface
implementada por la biblioteca del OEM, Camera2/X inicia el proceso de inicialización. El método InitializerImpl.init()
indica a la biblioteca del OEM que una app está intentando usar extensiones.
Camera2/X no realiza otras llamadas a la biblioteca del OEM (aparte de la verificación de la versión) hasta que la biblioteca del OEM llama a OnExtensionsInitializedCallback.onSuccess()
para notificar la finalización de 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 OEM implementa extensions-interface
1.0.0.
Comparación entre el amplificador básico y el amplificador avanzado
Existen dos tipos de implementación de extensions-interface
: Basic Extender y Advanced Extender. El Advanced Extender es compatible desde extensions-interface
1.2.0.
Implementa Basic Extender para las extensiones que procesan imágenes en el HAL de la cámara o usan un posprocesador capaz de procesar transmisiones YUV.
Implementa Advanced Extender 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 | Amplificador avanzado | |
---|---|---|
Configuraciones de transmisión | Fijo Vista previa: PRIVATE o YUV_420_888 (si existe el procesador) Captura de imagen fija: JPEG o YUV_420_888 (si existe el procesador)
|
El OEM puede personalizarlo. |
Enviando 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 e imágenes.
Camera2/X invoca |
Hooks en la canalización de la cámara |
|
|
Adecuado para | Extensiones implementadas en la HAL de la cámara o en un procesador que procesa imágenes YUV. |
|
Versión de 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 Camera Extensions. Si bien Camera2/X proporciona estas APIs, debes implementar correctamente la biblioteca del proveedor para admitir estos flujos, que describimos con más detalle en una sección posterior.
Extensiones de Camera2 | Extensiones de CameraX | |
---|---|---|
Disponibilidad de la extensión de búsqueda | CameraExtensionCharacteristics
.getSupportedExtensions
|
ExtensionsManager.
isExtensionAvailable
|
Información de la búsqueda | 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
|
val cameraSelector = ExtensionsManager.
getExtensionEnabledCameraSelector
|
Amplificador básico
La interfaz Basic Extender proporciona hooks en varios lugares de la canalización de la cámara. Cada tipo de extensión tiene clases Extender correspondientes que los OEM deben implementar.
En la siguiente tabla, se enumeran las clases de Extender que los OEM deben implementar para cada extensión:
Clases de extensión para implementar | |
---|---|
Noche | NightPreviewExtenderImpl.java
|
HDR | HdrPreviewExtenderImpl.java
|
Automático | AutoPreviewExtenderImpl.java
|
Bokeh | BokehPreviewExtenderImpl.java
|
Retoque facial | BeautyPreviewExtenderImpl.java
|
En el siguiente ejemplo, usamos PreviewExtenderImpl
y ImageCaptureExtenderImpl
como marcadores de posición. Reemplaza estos nombres por los de los archivos reales que implementarás.
El amplificador básico tiene las siguientes capacidades:
- Incorpora parámetros de sesión cuando configures
CameraCaptureSession
(onPresetSession
). - Notificarte sobre 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
). - Inserta parámetros de captura para la solicitud (
PreviewExtenderImpl.getCaptureStage
,ImageCaptureExtenderImpl.getCaptureStages
). - Agrega procesadores para la vista previa y la captura de imágenes que puedan procesar el flujo de
YUV_420_888
.
Veamos cómo Camera2/X invoca extensions-interface
para lograr los tres flujos de la app mencionados anteriormente.
Flujo de la app 1: Verifica la disponibilidad de la extensión
Figura 3: Flujo de la 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 Extender deben devolver true
para habilitar las extensiones.
Este suele ser el primer paso para que las apps verifiquen 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 se admiten en ciertos IDs de cámara.
Flujo de la app 2: Información de la consulta
Figura 4: Flujo de la app 2 en Basic Extender
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 estática:
ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
devuelve el rango de la latencia de captura para que la app evalúe si es adecuado habilitar la extensión para la situación actual.Tamaños admitidos para la superficie de vista previa y captura:
ImageCaptureExtenderImpl.getSupportedResolutions
yPreviewExtenderImpl.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 y resultado de captura admitidas de tu implementación:
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
ImageCaptureExtenderImpl.getAvailableCapturetResultKeys
Camera2/X siempre llama a init()
primero en estas clases de Extender antes de consultar 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)
Figura 5: Flujo de la app 3 en Basic Extender
En el diagrama anterior, se ilustra el flujo principal para habilitar la captura de vista previa y de fotos con una extensión sin ningún procesador. Esto significa que el HAL de la cámara procesa la extensión.
En este flujo, Camera2/X primero llama a init()
y, luego, a onInit
, lo 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 onPresetSession
para obtener los parámetros de la sesión. Después de configurar correctamente la sesión de captura, Camera2/X invoca onEnableSession
y devuelve una instancia de CaptureStageImpl
que contiene los parámetros de captura. Camera2/X envía de inmediato una sola solicitud con estos parámetros de captura para notificar al HAL. Del mismo modo, 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 que activan Camera2/X contiene los parámetros de solicitud que devuelve PreviewExtenderImpl.getCaptureStage()
. Además, la solicitud de captura de imagen contiene los parámetros que devuelve ImageCaptureExtenderImpl.getCaptureStages()
.
Por último, Camera2/X invoca 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 repetida con nuevos parámetros de solicitud de captura basados en elTotalCaptureResult
más reciente.PreviewExtenderImpl.getProcessor
debe devolver una instancia deRequestUpdateProcessorImpl
que procese la instancia deTotalCaptureResult
y devuelva una instancia deCaptureStageImpl
para actualizar la solicitud repetida.PreviewExtenderImpl.getCaptureStage()
también debe reflejar el resultado del procesamiento y devolver elCaptureStageImpl
más reciente.PROCESSOR_TYPE_IMAGE_PROCESSOR
: Este tipo te permite implementar un procesador para procesar imágenesYUV_420_888
y escribir el resultado en una superficiePRIVATE
.Debes implementar y devolver una instancia de
PreviewImageProcessorImpl
enPreviewExtenderImpl.getProcessor
. El procesador es responsable de procesar las imágenes de entradaYUV_420_888
. Debería escribir el resultado en el formatoPRIVATE
de la vista previa. Camera2/X usa una superficieYUV_420_888
en lugar dePRIVATE
para configurar elCameraCaptureSession
para la vista previa.Consulta la siguiente ilustración para ver el flujo:
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 del procesador. EnPreviewImageProcessorImpl
,imageFormat
es un formato de píxel, comoPixelFormat.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 serYUV_420_888
.
Procesador de captura de imágenes
Para la captura de imágenes, puedes implementar un procesador devolviendo una instancia de CaptureProcessorImpl
con ImageCaptureExtenderImpl.getCaptureProcessor
. El procesador es responsable de procesar una lista de imágenes YUV_420_888
capturadas y de instancias TotalCaptureResult
, y de escribir el resultado en una superficie 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 imagen.
Consulta el flujo en el siguiente diagrama:
Figura 7: Flujo de captura de imágenes fijas con CaptureProcessorImpl
Camera2/X usa una superficie de formato
YUV_420_888
para la captura de imágenes fijas y configurar la sesión de captura. Camera2/X preparaCaptureProcessorImpl
con la siguiente llamada:CaptureProcessorImpl.onImageFormatUpdate()
conYUV_420_888
.CaptureProcessorImpl.onResolutionUpdate()
con el tamaño de la imagen de entradaCaptureProcessorImpl.onOutputSurface()
con una superficie de salidaYUV_420_888
.
ImageCaptureExtenderImpl.getCaptureStages
devuelve una lista deCaptureStageImpl
, en la que cada elemento se asigna a una instancia deCaptureRequest
con parámetros de captura que envían Camera2 o CameraX. Por ejemplo, si devuelve una lista de tres instancias deCaptureStageImpl
, Camera2/X envía tres solicitudes de captura con los parámetros de captura correspondientes a través de la API decaptureBurst
.Las imágenes y las instancias de
TotalCaptureResult
recibidas se agrupan y se envían aCaptureProcessorImpl
para su procesamiento.CaptureProcessorImpl
escribe la imagen resultante (formatoYUV_420_888
) en la superficie de salida especificada por la llamada aonOutputSurface()
. 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 enfoque con un toque. 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()
devuelve las claves de solicitud de captura admitidas por tu implementación.ImageCaptureExtenderImpl.getAvailableCaptureResultKeys()
devuelve las claves de los resultados de captura que se incluyen 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, recomendamos admitir las siguientes claves tanto para la solicitud de captura como para el resultado de 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. En el caso de extensions-interface
1.3.0, tanto CameraX como Camera2 respetan la lista que se devuelve y solo admiten las claves que contiene. Por ejemplo, si decides devolver 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 en la app, mientras que no se permiten la función de tocar para enfocar, el flash ni la compensación de exposición.
Amplificador avanzado
Advanced Extender es un tipo de implementación del proveedor basada en la API de Camera2.
Este tipo de Extender se agregó en extensions-interface
1.2.0. Según el fabricante del dispositivo, es posible que las extensiones se implementen en la capa de la app, lo que depende de los siguientes factores:
Configuración de transmisión personalizada: Configura transmisiones personalizadas, como la transmisión RAW, o ten varias transmisiones para diferentes IDs de cámara física.
Capacidad para enviar solicitudes de Camera2: Admite una lógica de interacción compleja que puede enviar solicitudes de captura con parámetros basados en los resultados de solicitudes anteriores.
Advanced Extender proporciona un wrapper o una capa intermedia para que puedas personalizar la configuración de la transmisión y enviar solicitudes de captura según sea necesario.
Archivos para implementar
Para cambiar a la implementación del Extensor avanzado, 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 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 facial | advanced/BeautyAdvancedExtenderImpl.java
|
En el siguiente ejemplo, usamos AdvancedExtenderImpl
como marcador de posición.
Reemplázalo por el nombre del archivo del Extender para la extensión que estás implementando.
Veamos cómo Camera2/X invoca extensions-interface
para lograr los tres flujos de la app.
Flujo de la app 1: Comprueba la disponibilidad de las extensiones
Figura 8: Flujo de la app 1 en Advanced Extender
Primero, la app verifica si se admite la extensión proporcionada.
Flujo de la app 2: Información de la consulta
Figura 9: Flujo de la app 2 en Advanced Extender
Después de llamar a AdvancedExtenderImpl.init()
, la app puede consultar la siguiente información sobre AdvancedExtenderImpl
:
Latencia estimada de captura estática:
AdvancedExtenderImpl.getEstimatedCaptureLatencyRange()
devuelve el rango de la latencia de captura para que la app evalúe si es adecuado habilitar la extensión para la situación actual.Resoluciones admitidas para la vista previa y la captura estática:
AdvancedExtenderImpl.getSupportedPreviewOutputResolutions()
devuelve un mapa del formato de imagen a la lista de tamaños que se admiten para el formato y el tamaño de la superficie de vista previa. Los OEM deben admitir al menos el formatoPRIVATE
.AdvancedExtenderImpl.getSupportedCaptureOutputResolutions()
devuelve el formato y los tamaños admitidos para la superficie de captura de imágenes fijas. Los OEM deben admitir el formato de salidaJPEG
yYUV_420_888
.AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
devuelve los tamaños admitidos para un flujoYUV_420_888
adicional para el análisis de imágenes. Si no se admite la superficie YUV de análisis de imágenes,getSupportedYuvAnalysisResolutions()
debería devolvernull
o una lista vacía.
Claves y resultados de solicitudes de captura disponibles (se agregaron en
extensions-interface
1.3.0): Camera2/X invoca los siguientes métodos para recuperar las claves de solicitudes de captura y las claves de resultados admitidas 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 la app 3: Vista previa o captura de imágenes fijas con la extensión habilitada
Figura 10: Flujo de la app 3 en Advanced Extender
En el diagrama anterior, se muestra el flujo principal para iniciar la vista previa y la captura de imágenes fijas para el tipo de amplificador avanzado. Analicemos cada paso.
Instancia de
SessionProcessorImpl
La implementación principal de Advanced Extender se encuentra en
SessionProcessorImpl
, que es responsable de proporcionar la configuración de sesión personalizada y enviar solicitudes de captura para iniciar la vista previa y la solicitud de captura de imágenes. Se invocaAdvancedExtenderImpl.createSessionProcessor()
para devolver la instancia deSessionProcessorImpl
.initSession
SessionProcessorImpl.initSession()
inicializa la sesión para la extensión. Aquí es donde asignas recursos y devuelves una configuración de sesión para preparar unCameraCaptureSession
.En cuanto a 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 con los siguientes métodos enAdvancedExtenderImpl
:getSupportedPreviewOutputResolutions()
getSupportedCaptureOutputResolutions()
getSupportedYuvAnalysisResolutions()
Debes devolver una instancia de
Camera2SessionConfigImpl
, que consta de una lista de instancias deCamera2OutputConfigImpl
y los parámetros de sesión que se usan para configurarCameraCaptureSession
. Eres responsable de generar las imágenes de cámara correctas para las superficies de salida que pasan Camera2/X. Estas son algunas opciones para habilitar el resultado:- Procesamiento en la HAL de la cámara: Puedes agregar directamente las superficies de salida a
CameraCaptureSession
con una implementación deSurfaceOutputConfigImpl
. 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 intermedia
ImageReader
(RAW, YUV, etc.): Agrega las superficies intermediasImageReader
alCameraCaptureSession
con una instancia deImageReaderOutputConfigImpl
.Debes procesar las imágenes intermedias y escribir la imagen resultante en la superficie de salida.
- Usa el uso compartido de superficies de Camera2: Usa el uso compartido de superficies con otra superficie agregando cualquier instancia de
Camera2OutputConfigImpl
al métodogetSurfaceSharingOutputConfigs()
de otra instancia deCamera2OutputConfigImpl
. El formato y el tamaño de la superficie deben ser idénticos.
Todos los
Camera2OutputConfigImpl
, incluidosSurfaceOutputConfigImpl
yImageReaderOutputConfigImpl
, deben tener un ID único (getId()
), que se usa para especificar la superficie de destino y recuperar la imagen deImageReaderOutputConfigImpl
.onCaptureSessionStart
yRequestProcessorImpl
Cuando se inicia
CameraCaptureSession
y el framework de Camera invocaonConfigured()
, Camera2/X invocaSessionProcessorImpl.onCaptureSessionStart()
con el wrapper de solicitud de Camera2RequestProcessImpl
. Camera2/X implementaRequestProcessImpl
, lo que te permite ejecutar las solicitudes de captura y recuperar imágenes si se usaImageReaderOutputConfigImpl
.Las APIs de
RequestProcessImpl
son similares a las APIs deCameraCaptureSession
de Camera2 en cuanto a la ejecución de solicitudes. Las diferencias son las siguientes:- La superficie de destino se especifica con el ID de la instancia de
Camera2OutputConfigImpl
. - Es la capacidad de recuperar la imagen de
ImageReader
.
Puedes llamar a
RequestProcessorImpl.setImageProcessor()
con un ID deCamera2OutputConfigImpl
especificado para registrar una instancia deImageProcessorImpl
y recibir imágenes.La instancia de
RequestProcessImpl
deja de ser válida después de que Camera2/X llama aSessionProcessorImpl.onCaptureSessionEnd()
.- La superficie de destino se especifica con el ID de la instancia de
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 repetida para la vista previa o la secuencia de captura de imágenes fijas llamando aSessionProcessorImpl#startRepeating
ySessionProcessorImpl#startCapture
, respectivamente. Debes enviar solicitudes de captura para satisfacer estas solicitudes de vista previa y captura de imágenes.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
yCaptureRequest.JPEG_QUALITY
.extensions-interface
1.3.0 admite claves de solicitud y resultado, que se exponen a través de 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 en la listagetAvailableCaptureResultKeys
.startTrigger
Se invoca
SessionProcessorImpl.startTrigger()
para iniciar el activador, comoCaptureRequest.CONTROL_AF_TRIGGER
yCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER
. Puedes ignorar cualquier clave de solicitud de captura que no se haya anunciado enAdvancedExtenderImpl.getAvailableCaptureRequestKeys()
.startTrigger()
es compatible desdeextensions-interface
1.3.0. Permite que las apps implementen la función de tocar para enfocar y el flash con extensiones.Realiza una limpieza
Cuando finaliza una sesión de captura, se invoca
SessionProcessorImpl.onCaptureSessionEnd()
antes de cerrarCameraCaptureSession
. Después de que se cierra la sesión de captura,deInitSession()
realiza la limpieza.
Admite la vista previa, la captura de imágenes fijas y el análisis de imágenes
Debes aplicar la extensión para los casos de uso de vista previa y 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.
Para el tipo de ampliador 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 un flujo YUV para analizar el contenido de la imagen, como la búsqueda de códigos QR o texto. Para brindar una mejor compatibilidad con este caso de uso, debes admitir la combinación de transmisión de vista previa, captura de imagen y una transmisión de YUV_420_888
para configurar CameraCaptureSession
. Esto significa que, si implementas un procesador, debes admitir la combinación de transmisión de tres transmisiones YUV_420_888
.
En el caso de Advanced Extender, Camera2/X pasa tres superficies de salida a la llamada SessionProcessorImpl.initSession()
. Estas superficies 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 superficies de salida de la vista previa y la captura de imágenes muestren la salida válida. Sin embargo, para la superficie de salida del análisis de imágenes, asegúrate de que funcione solo cuando no sea nula. Si tu implementación no admite la transmisión de análisis de imágenes, puedes devolver 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()
.
Admite la captura de video
La arquitectura actual de las extensiones de cámara solo admite los casos de uso de vista previa y captura de fotos. No admitimos la habilitación de la extensión en las plataformas de 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 habilitado.
Captura de solicitudes
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
yNIGHT
: Controlan la cantidad de imágenes fusionadas y el brillo de la imagen final.FACE_RETOUCH
: Controla la cantidad de mejora estética y suavizado de la piel.
El rango admitido para el parámetro EXTENSION_STRENGTH
es entre 0
y 100
, donde 0
indica que no hay procesamiento de extensión o que se realiza un simple paso directo, y 100
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 extensión. Para obtener más información, consulta getAvailableCaptureRequestKeys()
.
Resultados de la captura
El resultado de captura EXTENSION_CURRENT_TYPE
permite que las implementaciones de extensiones notifiquen a los clientes sobre el tipo de extensión activa.
Dado que las extensiones que usan el tipo AUTO
cambian de forma dinámica entre tipos de extensión, como HDR
y NIGHT
, según las condiciones de la escena, las apps de extensiones de la cámara pueden usar EXTENSION_CURRENT_TYPE
para mostrar información sobre la extensión actual seleccionada por la extensión AUTO
.
Estimación de latencia de capturas estáticas en tiempo real
En Android 14 y versiones posteriores, los clientes de extensiones de 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 getEstimatedCaptureLatencyRangeMillis()
estático. 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:
- Extensiones básicas:
ImageCaptureExtenderImpl.getRealtimeCaptureLatency()
- Extensiones avanzadas:
SessionProcessorImpl.getRealtimeCaptureLatency
Devoluciones de llamada del progreso de procesamiento de la captura
En Android 14 y versiones posteriores, los clientes de extensiones de cámara pueden recibir devoluciones de llamada sobre el progreso de las operaciones de procesamiento de captura de imágenes fijas de larga duración. Las apps pueden mostrar el progreso actual a los usuarios para mejorar la 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 las 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:
- Extensiones básicas:
ProcessResultImpl.onCaptureProcessProgressed()
- Extensiones avanzadas:
CaptureCallback.onCaptureProcessProgressed()
Captura estática de la imagen de vista previa
En Android 14 y versiones posteriores, las extensiones de la cámara pueden proporcionar una postvista (imagen de vista previa) con setPostviewOutputConfiguration
.
Para mejorar la experiencia del usuario, las apps pueden mostrar una imagen de postview 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 posterior a la visualización 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 después de la visualización, la implementación del proveedor debe incluir lo siguiente:
Extensiones básicas:
CaptureProcessorImpl.onPostviewOutputSurface
yCaptureProcessorImpl.processWithPostview
Extensiones avanzadas:
SessionProcessorImpl.startCaptureWithPostview
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 el consumo de energía registrando una instancia de SurfaceView
para la salida de vista previa de solicitudes repetidas.
Para admitir la salida de SurfaceView
, la implementación de la extensión del proveedor debe poder transmitir y generar vistas previas en instancias de SurfaceView
. Para verificar que se admita, ejecuta el módulo SurfaceViewExtensionPreviewTest.java
de las CTS.
Tipos de sesión específicos del proveedor
La función permite que las implementaciones de extensiones del proveedor seleccionen un tipo de sesión específico del proveedor que se establecerá en la sesión de captura interna de la cámara en lugar del valor predeterminado.
La función opera completamente dentro del framework y la pila del proveedor, y no tiene 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 Camera Extension. Siempre debes implementar la biblioteca del proveedor con la versión más reciente.
Versión | Funciones agregadas |
---|---|
1.0.0 |
|
1.1.0 |
|
1.2.0 |
|
1.3.0 |
|
1.4.0 |
|
Implementación de referencia
Las siguientes implementaciones de referencia de la biblioteca del proveedor del OEM están disponibles en frameworks/ex
.
advancedSample
: Es una implementación básica de Advanced Extender.sample
: Es una implementación básica de Basic Extender.service_based_sample
: Es una implementación que demuestra cómo alojar extensiones de cámara en unService
. Esta implementación contiene los siguientes componentes:oem_library
: Una biblioteca de OEM de Camera Extensions para las APIs de Camera2 y CameraX Extensions que implementaExtensions-Interface
. Actúa como un paso a través que reenvía las llamadas deExtensions-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 devuelvafalse
.extensions_service
: Es un ejemplo de implementación del servicio de extensiones. Agrega tu implementación aquí. La interfaz que se implementará en el servicio es similar aExtensions-Interface
. Por ejemplo, implementarIAdvancedExtenderImpl.Stub
realiza las mismas operaciones queAdvancedExtenderImpl
.ImageWrapper
yTotalCaptureResultWrapper
son obligatorios para queImage
yTotalCaptureResult
sean parcelables.
Cómo configurar la biblioteca del proveedor en un dispositivo
La biblioteca del OEM no está integrada en una app, sino que Camera2/X la carga desde el dispositivo en 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 se debe cargar en 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
en el tiempo de ejecución.
Esto permite que las apps de terceros que usan extensiones carguen automáticamente la biblioteca del proveedor del OEM. La biblioteca del OEM está marcada como opcional para que las apps puedan ejecutarse 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 detectarla.
Para configurar la biblioteca del OEM en un dispositivo, haz lo siguiente:
- Agrega un archivo de permisos, 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 denominada en<uses-library>
a la ruta de acceso real del archivo en el dispositivo. Usa el siguiente ejemplo para agregar la información requerida al archivo.
name
debe serandroidx.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 las 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 y versiones posteriores, los dispositivos que admiten extensiones de CameraX deben tener la propiedad ro.camerax.extensions.enabled
configurada en true
, lo que permite consultar si un dispositivo admite extensiones.
Para ello, agrega la siguiente línea al archivo de compilación 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 ejecuta varias extensiones del proveedor.
Después de completar la implementación, usa la herramienta de validación de extensiones de cámara para ejecutar pruebas manuales y automáticas que permitan verificar que la biblioteca del proveedor se implementó correctamente.
Modo panorámico extendido en comparación con las extensiones de la cámara
En el caso de la extensión de bokeh, además de exponerla con las extensiones de cámara, puedes exponerla con el modo panorámico extendido, que se habilita a través de 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 las apps de camera2. Por ejemplo, puedes habilitar el modo de escena extendido en una instancia CameraCaptureSession
normal que admita combinaciones de transmisiones flexibles y parámetros de solicitud de captura. Por el contrario, las extensiones de cámara solo admiten un conjunto fijo de tipos de transmisiones y tienen compatibilidad limitada con los parámetros de solicitud de captura.
Una desventaja del modo de escena extendido es que solo se puede implementar en el HAL de la cámara, lo que significa que se debe verificar que funcione en todos los controles ortogonales disponibles para los desarrolladores de apps.
Recomendamos exponer el bokeh con el modo de escena extendido y las extensiones de CameraX, ya que es posible que las apps prefieran usar una API en particular para habilitar el bokeh. Te recomendamos que primero uses el modo de escena extendido, ya que es la forma más flexible para que las apps habiliten la extensión de bokeh. 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 el HAL de la cámara, por ejemplo, porque requiere un posprocesador que se ejecute en la capa de la app para procesar imágenes, te recomendamos que implementes la extensión de bokeh con la interfaz de Camera Extensions.
Preguntas frecuentes
¿Hay alguna restricción en los niveles de API?
Sí. Esto depende del conjunto de funciones de la API de Android que requiere la implementación de la biblioteca del proveedor del 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.