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 proporcionada por la biblioteca del proveedor OEM. Los desarrolladores pueden utilizar la API de extensiones Camera2 y la API de extensiones CameraX para acceder a las extensiones implementadas en la biblioteca del proveedor OEM.
Para obtener una lista de extensiones compatibles, que es la misma en Camera2 y CameraX, consulte API de extensiones de CameraX . Si desea agregar una extensión, presente un error en Issue Tracker .
Esta página describe cómo implementar y habilitar la biblioteca de proveedores OEM en dispositivos.
Arquitectura
El siguiente diagrama describe la arquitectura de la interfaz de Camera Extensions o extensions-interface
:
Figura 1. Diagrama de arquitectura de Extensiones de cámara
Como se muestra en el diagrama, para admitir extensiones de cámara, debe implementar la extensions-interface
proporcionada por la biblioteca del proveedor OEM. Su biblioteca de proveedores OEM habilita dos API: CameraX Extensions API y Camera2 Extensions API , que utilizan las aplicaciones CameraX y Camera2, respectivamente, para acceder a las extensiones de proveedores.
Implementar la biblioteca de proveedores OEM
Para implementar la biblioteca del proveedor OEM, copie los archivos camera-extensions-stub
en un proyecto de biblioteca del sistema. Estos archivos definen la interfaz de Extensiones de cámara.
Los archivos camera-extensions-stub
se dividen en las siguientes categorías:
Archivos de interfaz esenciales (no modificar)
-
PreviewExtenderImpl.java
-
ImageCaptureExtenderImpl.java
-
ExtenderStateListener.java
-
ProcessorImpl.java
-
PreviewImageProcessorImpl.java
-
CaptureProcessorImpl.java
-
CaptureStageImpl.java
-
RequestUpdateProcessorImpl.java
-
ProcessResultImpl.java
-
advanced/AdvancedExtenderImpl.java
-
advanced/Camera2OutputConfigImpl.java
-
advanced/Camera2SessionConfigImpl.java
-
advanced/ImageProcessorImpl.java
-
advanced/ImageReaderOutputConfigImpl.java
-
advanced/ImageReferenceImpl.java
-
advanced/MultiResolutionImageReaderOutputConfigImpl.java
-
advanced/OutputSurfaceImpl.java
-
advanced/RequestProcessorImpl.java
-
advanced/SessionProcessorImpl.java
-
advanced/SurfaceOutputConfigImpl.java
Implementaciones obligatorias (agregue su implementación)
-
ExtensionVersionImpl.java
-
InitializerImpl.java
Clases de extensión de Bokeh (impleméntelas si se admite la extensión de Bokeh)
-
BokehImageCaptureExtenderImpl.java
-
BokehPreviewExtenderImpl.java
-
advanced/BokehAdvancedExtenderImpl.java
Clases de extensión nocturna (impleméntelas si se admite la extensión nocturna)
-
NightImageCaptureExtenderImpl.java
-
NightPreviewExtenderImpl.java
-
advanced/NightAdvancedExtenderImpl.java
Clases de extensión automática (impleméntelas si se admite la extensión automática)
-
AutoImageCaptureExtenderImpl.java
-
AutoPreviewExtenderImpl.java
-
advanced/AutoAdvancedExtenderImpl.java
Clases de extensión HDR (impleméntelas si se admite la extensión HDR)
-
HdrImageCaptureExtenderImpl.java
-
HdrPreviewExtenderImpl.java
-
advanced/HdrAdvancedExtenderImpl.java
Clases de extensión de Face Retouch (impleméntelas si la extensión Face Retouch es compatible)
-
BeautyImageCaptureExtenderImpl.java
-
BeautyPreviewExtenderImpl.java
-
advanced/BeautyAdvancedExtenderImpl.java
Utilidades (opcional, se puede eliminar)
-
advanced/Camera2OutputConfigImplBuilder.java
-
advanced/Camera2SessionConfigImplBuilder.java
No es necesario que proporcione una implementación para cada extensión. Si no implementa una extensión, configure isExtensionAvailable()
para devolver false
o eliminar las clases Extender correspondientes. Las API de extensiones Camera2 y CameraX informan a la aplicación que la extensión no está disponible.
Veamos cómo las API de extensiones Camera2 y CameraX interactúan con la biblioteca del proveedor para habilitar una extensión. El siguiente diagrama ilustra el flujo de un extremo a otro utilizando la extensión Noche como ejemplo:
Figura 2. Implementación de extensión nocturna
Verificación de versión:
Camera2/X llama a
ExtensionVersionImpl.checkApiVersion()
para garantizar que la versiónextensions-interface
implementada por OEM sea compatible con las versiones compatibles con 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 de Extender.Crear instancias de clases de extensor:
Crea una instancia de las clases Extender para la extensión. Hay dos tipos de extensores: extensores básicos y extensores avanzados. Debe implementar un tipo de extensor para todas las extensiones. Para obtener más información, consulte Extensor básico versus Extensor avanzado .
Camera2/X crea instancias e interactúa con las clases Extender 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 realice una inicialización pesada en el constructor o en la llamada
init()
. Haga el trabajo pesado solo cuando la sesión de la cámara esté a punto de comenzar, como cuando se llamaonInit()
en Basic Extender oinitSession()
en Advanced Extender.Para la extensión Noche, se crean instancias de las siguientes clases de Extensor para el tipo de Extensor Básico:
-
NightImageCaptureExtenderImpl.java
-
NightPreviewExtenderImpl.java
Y para el tipo Advanced Extender:
-
NightAdvancedExtenderImpl.java
-
Consultar disponibilidad de extensiones:
Antes de habilitar la extensión,
isExtensionAvailable()
comprueba si la extensión está disponible en la ID de cámara especificada a través de la instancia de Extender.Inicialice el extensor con información de la cámara:
Camera2/X llama
init()
en la instancia de Extender y le pasa el ID de la cámara yCameraCharacteristics
.Información de consulta:
Invoca la clase Extender para recuperar información como las resoluciones admitidas, capturar la latencia estimada y capturar claves de solicitud del Extender en preparación para habilitar la extensión.
Habilite la extensión en el extensor:
La clase Extender proporciona todas las interfaces necesarias para habilitar la clase. Ofrece un mecanismo para conectar la implementación OEM al canal Camera2, como inyectar parámetros de solicitud de captura o habilitar un posprocesador.
Para el tipo de extensor avanzado, Camera2/X interactúa con
SessionProcessorImpl
para habilitar la extensión. Camera2/X recupera la instanciaSessionProcessorImpl
llamando acreateSessionProcessor()
en Extender.
Las siguientes secciones describen el flujo de extensión con mayor detalle.
Verificación de versión
Al cargar la biblioteca del proveedor OEM desde el dispositivo en tiempo de ejecución, Camera2/X verifica si la biblioteca es compatible con la versión de la extensions-interface
. La extensions-interface
utiliza versiones semánticas, o MAJOR.MINOR.PATCH, por ejemplo, 1.1.0 o 1.2.0. Sin embargo, sólo se utilizan las versiones principal y secundaria durante la verificación de la versión.
Para verificar la versión, Camera2/X llama a ExtensionVersionImpl.checkApiVersion()
con la versión extensions-interface
compatible. Camera2/X luego usa la versión reportada por la biblioteca OEM para determinar si la extensión se puede habilitar y qué capacidades debe invocar.
Compatibilidad de versiones principales
Si las versiones principales de la interfaz de extensión son diferentes entre Camera2/X y la biblioteca del proveedor, entonces se considera incompatible y la extensión se desactiva.
Compatibilidad con versiones anteriores
Siempre que la versión principal sea idéntica, Camera2/X garantiza la compatibilidad con bibliotecas de proveedores OEM creadas con versiones anteriores extensions-interface
. Por ejemplo, si Camera2/X admite extensions-interface
1.3.0, las bibliotecas del proveedor OEM que implementaron 1.0.0, 1.1.0 y 1.2.0 siguen siendo compatibles. Esto también significa que después de implementar una versión específica de la biblioteca del proveedor, Camera2/X se asegura de que la biblioteca sea compatible con las próximas versiones extension-interface
.
Compatibilidad hacia adelante
La compatibilidad futura con bibliotecas de proveedores de extensions-interface
más nuevas depende de usted, el OEM. Si necesita algunas funciones para implementar las extensiones, es posible que desee habilitarlas a partir de una versión determinada. En este caso, puede devolver la versión extensions-interface
admitida cuando la versión de la biblioteca Camera2/X cumpla con los requisitos. Si las versiones de Camera2/X no son compatibles, puede devolver una versión incompatible como 99.0.0 para desactivar las extensiones.
Inicialización de la biblioteca del proveedor
Después de verificar la versión extensions-interface
implementada por la biblioteca OEM, Camera2/X inicia el proceso de inicialización. El método InitializerImpl.init()
indica a la biblioteca OEM que una aplicación está intentando utilizar extensiones.
Camera2/X no realiza otras llamadas a la biblioteca OEM (aparte de la verificación de la versión) hasta que la biblioteca del proveedor OEM llama a OnExtensionsInitializedCallback.onSuccess()
para notificar la finalización de la inicialización.
Debe implementar InitializerImpl
a partir de la extensions-interface
1.1.0. Camera2/X omite el paso de inicialización de la biblioteca si la biblioteca del proveedor OEM implementa extensions-interface
1.0.0.
Extensor básico versus extensor avanzado
Hay dos tipos de implementación extensions-interface
: Basic Extender y Advanced Extender. Advanced Extender ha sido compatible desde extensions-interface
1.2.0.
Implemente Basic Extender para extensiones que procesen imágenes en la cámara HAL o use un postprocesador capaz de procesar transmisiones YUV.
Implemente Advanced Extender para extensiones que necesiten personalizar la configuración de transmisión de Camera2 y enviar solicitudes de captura según sea necesario.
Consulte la siguiente tabla para realizar la comparación:
Extensor básico | Extensor avanzado | |
---|---|---|
Configuraciones de transmisión | Fijado Vista previa: PRIVATE o YUV_420_888 (si existe el procesador)Captura fija: JPEG o YUV_420_888 (si existe el procesador) | Personalizable por OEM. |
Enviando solicitud de captura | Sólo Camera2/X puede enviar solicitudes de captura. Puede configurar los parámetros para estas solicitudes. Cuando se proporciona el procesador para la captura de imágenes, Camera2/X puede enviar múltiples solicitudes de captura y enviar todas las imágenes y los resultados de la captura al procesador. | Se le proporciona una instancia RequestProcessorImpl para ejecutar la solicitud de captura de la cámara2 y obtener resultados e imágenes. Camera2/X invoca |
Ganchos en el tubo de la cámara |
|
|
Adecuado para | Extensiones implementadas en la cámara HAL o en un procesador que procesa imágenes YUV. |
|
Versión de API compatible | Extensiones de Camera2: Android 13 o superior Extensiones CameraX: camera-extensions 1.1.0 o superior | Extensiones Camera2: Android 12L o superior Extensiones CameraX: camera-extensions 1.2.0-alpha03 o superior |
Flujos de aplicaciones
La siguiente tabla muestra tres tipos de flujos de aplicaciones y sus correspondientes llamadas API de Camera Extensions. Si bien Camera2/X proporciona estas API, debe implementar correctamente la biblioteca del proveedor para admitir estos flujos, que describimos con más detalle en una sección posterior.
Extensiones de cámara2 | Extensiones de cámaraX | |
---|---|---|
Disponibilidad de extensión de consulta | CameraExtensionCharacteristics . getSupportedExtensions | ExtensionsManager. isExtensionAvailable |
Consultar información | CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys | ExtensionsManager. getEstimatedCaptureLatencyRange CameraX maneja el resto de la información dentro de la biblioteca. |
Vista previa y captura fija con la extensión habilitada | CameraDevice. createExtensionSession | val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector bindToLifecycle(lifecycleOwner, cameraSelector, vista previa, ...) |
Extensor básico
La interfaz del extensor básico proporciona conexiones en varios lugares del canal de la cámara. Cada tipo de extensión tiene clases de extensor correspondientes que los OEM deben implementar.
La siguiente tabla enumera las clases de extensión que los OEM deben implementar para cada extensión:
Clases extendidas para implementar | |
---|---|
Noche | NightPreviewExtenderImpl.java |
HDR | HdrPreviewExtenderImpl.java |
Auto | AutoPreviewExtenderImpl.java |
bokeh | BokehPreviewExtenderImpl.java |
retoque facial | BeautyPreviewExtenderImpl.java |
Usamos PreviewExtenderImpl
e ImageCaptureExtenderImpl
como marcadores de posición en el siguiente ejemplo. Reemplácelos con los nombres de los archivos reales que está implementando.
Basic Extender tiene las siguientes capacidades:
- Inyecte parámetros de sesión al configurar
CameraCaptureSession
(onPresetSession
). - Notificarle sobre los eventos de inicio y cierre de la sesión de captura y enviar una única solicitud para notificar al HAL con los parámetros devueltos (
onEnableSession
,onDisableSession
). - Inyecte parámetros de captura para la solicitud (
PreviewExtenderImpl.getCaptureStage
,ImageCaptureExtenderImpl.getCaptureStages
). - Agregue procesadores para obtener una vista previa y captura fija que sean capaces de procesar la transmisión
YUV_420_888
.
Veamos cómo Camera2/X invoca la extensions-interface
para lograr los tres flujos de aplicaciones mencionados anteriormente.
Flujo de aplicación 1: comprobar la disponibilidad de la extensión
Figura 3. Flujo de aplicación 1 en Basic Extender
En este flujo, Camera2/X llama directamente al método isExtensionAvailable()
de PreviewExtenderImpl
e ImageCaptureExtenderImpl
sin llamar init()
. Ambas clases de Extender deben devolver true
para habilitar las extensiones.
Este suele ser el primer paso para que las aplicaciones verifiquen si el tipo de extensión determinado es compatible con una ID de cámara determinada antes de habilitar la extensión. Esto se debe a que algunas extensiones solo son compatibles con determinadas ID de cámara.
Flujo de aplicación 2: consultar información
Figura 4. Flujo de aplicación 2 en Basic Extender
Después de determinar si la extensión está disponible, las aplicaciones deben consultar la siguiente información antes de habilitar la extensión.
Rango de latencia de captura fija:
ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
devuelve el rango de latencia de captura para que la aplicación evalúe si es apropiado habilitar la extensión para el escenario actual.Tamaños admitidos para la 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 resultados admitidas: Camera2/X invoca los siguientes métodos para recuperar las claves de solicitud de captura y de resultados admitidas de su implementación:
-
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
-
ImageCaptureExtenderImpl.getAvailableCapturetResultKeys
-
Camera2/X siempre llama init()
primero en estas clases de Extender antes de solicitar más información.
Flujo de aplicación 3: vista previa/captura fija con la extensión habilitada (implementación HAL)
Figura 5. Flujo de aplicación 3 en Basic Extender
El diagrama anterior ilustra el flujo principal para habilitar la vista previa y la captura fija con una extensión sin ningún procesador. Esto significa que la cámara HAL procesa la extensión.
En este flujo, Camera2/X primero llama init()
y luego onInit
, lo que le notifica que una sesión de cámara está a punto de comenzar con las extensiones especificadas. Puedes realizar una inicialización pesada en onInit()
.
Al configurar CameraCaptureSession
, Camera2/X invoca onPresetSession
para obtener los parámetros de la sesión. Una vez que la sesión de captura se configura correctamente, Camera2/X invoca onEnableSession
y devuelve una instancia CaptureStageImpl
que contiene los parámetros de captura. Camera2/X envía inmediatamente una única solicitud con estos parámetros de captura para notificar a HAL. De manera similar, antes de que se cierre la sesión de captura, Camera2/X invoca onDisableSession
y luego envía una única solicitud con los parámetros de captura devueltos.
La solicitud repetida activada por Camera2/X contiene los parámetros de solicitud devueltos por PreviewExtenderImpl.getCaptureStage()
. Además, la solicitud de captura fija contiene los parámetros devueltos por ImageCaptureExtenderImpl.getCaptureStages()
.
Finalmente, Camera2/X invoca onDeInit()
una vez finalizada la sesión de la cámara. Puedes liberar recursos en onDeinit()
.
Procesador de vista previa
Además de la cámara HAL, también puedes implementar extensiones en un procesador.
Implemente PreviewExtenderImpl.getProcessorType
para especificar el tipo de procesador como se explica a continuación:
PROCESSOR_TYPE_NONE
: Sin procesador. Las imágenes se procesan en la cámara HAL.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY
: el tipo de procesador le permite actualizar la solicitud repetida con nuevos parámetros de solicitud de captura basados en el últimoTotalCaptureResult
.PreviewExtenderImpl.getProcessor
debe devolver una instanciaRequestUpdateProcessorImpl
que procesa la instanciaTotalCaptureResult
y devuelve una instanciaCaptureStageImpl
para actualizar la solicitud repetida.PreviewExtenderImpl.getCaptureStage()
también debería reflejar el resultado del procesamiento y devolver el últimoCaptureStageImpl
.PROCESSOR_TYPE_IMAGE_PROCESSOR
: este tipo le permite implementar un procesador para procesar imágenesYUV_420_888
y escribir la salida en una superficiePRIVATE
.Debe implementar y devolver una instancia
PreviewImageProcessorImpl
enPreviewExtenderImpl.getProcessor
. El procesador es responsable de procesar las imágenes de entradaYUV_420_888
. Debería escribir la salida en el formatoPRIVATE
de vista previa. Camera2/X utiliza una superficieYUV_420_888
en lugar dePRIVATE
para configurarCameraCaptureSession
para la vista previa.Vea la siguiente ilustración para 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 para el procesador. ParaPreviewImageProcessorImpl
,imageFormat
es un formato de píxeles 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 fija, puede implementar un procesador devolviendo una instancia CaptureProcessorImpl
usando ImageCaptureExtenderImpl.getCaptureProcessor
. El procesador es responsable de procesar una lista de imágenes YUV_420_888
capturadas e instancias TotalCaptureResult
y escribir la salida en una superficie YUV_420_888
.
Puede asumir con seguridad que la vista previa está habilitada y ejecutándose antes de enviar la solicitud de captura de imágenes fijas.
Vea el flujo en el siguiente diagrama:
Figura 7. Todavía captura el flujo con CaptureProcessorImpl
Camera2/X utiliza una superficie de formato
YUV_420_888
para la captura fija para configurar la sesión de captura. Camera2/X preparaCaptureProcessorImpl
llamando a:-
CaptureProcessorImpl.onImageFormatUpdate()
conYUV_420_888
. -
CaptureProcessorImpl.onResolutionUpdate()
con el tamaño de la imagen de entrada. -
CaptureProcessorImpl.onOutputSurface()
con una superficie de salidaYUV_420_888
.
-
ImageCaptureExtenderImpl.getCaptureStages
devuelve una lista deCaptureStageImpl
, donde cada elemento se asigna a una instanciaCaptureRequest
con parámetros de captura enviados por Camera2/X. Por ejemplo, si devuelve una lista de tres instanciasCaptureStageImpl
, Camera2/X envía tres solicitudes de captura con los parámetros de captura correspondientes utilizando la APIcaptureBurst
.Las imágenes recibidas y las instancias
TotalCaptureResult
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 llamadaonOutputSurface()
. 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 aplicaciones pueden configurar el zoom, los parámetros del flash o activar un toque para enfocar. Es posible que estos parámetros no sean compatibles con la implementación de su extensión.
Los siguientes métodos se han agregado a extensions-interface
1.3.0 para permitirle exponer los parámetros que admite su implementación:
-
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys()
devuelve las claves de solicitud de captura admitidas por su implementación. -
ImageCaptureExtenderImpl.getAvailableCaptureResultKeys()
devuelve las claves de resultados de captura contenidas en el resultado de captura.
Si la cámara HAL procesa la extensión, Camera2/X recupera los resultados de la captura en CameraCaptureSession.CaptureCallback
. Sin embargo, si se implementa el procesador, Camera2/X recupera los resultados de la captura en ProcessResultImpl
, que se pasa al método process()
en PreviewImageProcessorImpl
y CaptureProcessorImpl
. Usted es responsable de informar el resultado de la captura a través de ProcessResultImpl
a Camera2/X.
Consulte la definición de la interfaz CaptureProcessorImpl
a continuación como ejemplo. En extensions-interface
1.3.0 o superior, se invoca la segunda llamada 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 operaciones comunes de la cámara, como zoom, tocar para enfocar, flash y compensación de exposición, recomendamos admitir las siguientes teclas tanto para la solicitud de captura como para el resultado de la captura:
- Zoom:
-
CaptureRequest#CONTROL_ZOOM_RATIO
-
CaptureRequest#SCALER_CROP_REGION
-
- Tocar para enfocar:
-
CaptureRequest#CONTROL_AF_MODE
-
CaptureRequest#CONTROL_AF_TRIGGER
-
CaptureRequest#CONTROL_AF_REGIONS
-
CaptureRequest#CONTROL_AE_REGIONS
-
CaptureRequest#CONTROL_AWB_REGIONS
-
- Destello:
-
CaptureRequest#CONTROL_AE_MODE
-
CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
-
CaptureRequest#FLASH_MODE
-
- Compensación de exposición:
-
CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
-
Para Basic Extenders que implementan 1.2.0 o versiones anteriores, la API de CameraX Extensions admite explícitamente todas las claves anteriores. Para extensions-interface
1.3.0, tanto CameraX como Camera2 respetan la lista devuelta y admiten solo las claves contenidas en ella. Por ejemplo, si decide devolver solo CaptureRequest#CONTROL_ZOOM_RATIO
y CaptureRequest#SCALER_CROP_REGION
en la implementación 1.3.0, eso significa que solo se admite el zoom para la aplicación, mientras que no se permiten tocar para enfocar, flash ni compensación de exposición.
Extensor avanzado
Advanced Extender es un tipo de implementación de proveedor basada en la API de Camera2. Este tipo de extensor se agregó en extensions-interface
1.2.0. Dependiendo del fabricante del dispositivo, es posible que se implementen extensiones en la capa de aplicación, lo que depende de los siguientes factores:
Configuración de transmisión personalizada: configure transmisiones personalizadas como transmisión RAW o tenga múltiples transmisiones para diferentes ID de cámara física.
Capacidad para enviar solicitudes de Camera2: admite una lógica de interacción complicada que puede enviar solicitudes de captura con parámetros basados en los resultados de solicitudes anteriores.
Advanced Extender proporciona un contenedor o una capa intermedia, para que pueda personalizar la configuración de la transmisión y enviar solicitudes de captura a pedido.
Archivos para implementar
Para cambiar a la implementación de Advanced Extender, el método isAdvancedExtenderImplemented()
en ExtensionVersionImpl
debe devolver true
. Para cada tipo de extensión, los OEM deben implementar las clases de extensor correspondientes. Los archivos de implementación de Advanced Extender se encuentran en el paquete avanzado .
Clases extendidas para implementar | |
---|---|
Noche | advanced/NightAdvancedExtenderImpl.java |
HDR | advanced/HdrAdvancedExtenderImpl.java |
Auto | advanced/AutoAdvancedExtenderImpl.java |
bokeh | advanced/BokehAdvancedExtenderImpl.java |
Retoque facial | advanced/BeautyAdvancedExtenderImpl.java |
Usamos AdvancedExtenderImpl
como marcador de posición en el siguiente ejemplo. Reemplácelo con el nombre del archivo Extender para la extensión que está implementando.
Veamos cómo Camera2/X invoca la extensions-interface
para lograr los tres flujos de aplicaciones.
Flujo de aplicación 1: comprobar la disponibilidad de extensiones
Figura 8. Flujo de aplicación 1 en Advanced Extender
Primero, la aplicación verifica si la extensión dada es compatible.
Flujo de aplicación 2: consultar información
Figura 9. Flujo de aplicación 2 en Advanced Extender
Después de llamar AdvancedExtenderImpl.init()
, la aplicación puede consultar la siguiente información sobre AdvancedExtenderImpl
:
Latencia estimada de captura fija:
AdvancedExtenderImpl.getEstimatedCaptureLatencyRange()
devuelve el rango de latencia de captura para que la aplicación evalúe si es apropiado habilitar la extensión para el escenario actual.Resoluciones admitidas para vista previa y captura fija:
AdvancedExtenderImpl.getSupportedPreviewOutputResolutions()
devuelve un mapa de formato de imagen a la lista de tamaños admitidos para el formato y tamaño de 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 fija. Los OEM deben admitir salida en formatoJPEG
yYUV_420_888
.AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
devuelve los tamaños admitidos para una secuenciaYUV_420_888
adicional para el análisis de imágenes. Si la superficie YUV de análisis de imágenes no es compatible,getSupportedYuvAnalysisResolutions()
debería devolvernull
o una lista vacía.
Claves/resultados de solicitud de captura disponibles (agregados en
extensions-interface
1.3.0): Camera2/X invoca los siguientes métodos para recuperar las claves de solicitud de captura y las claves de resultados admitidas de su implementación:-
AdvancedExtenderImpl.getAvailableCaptureRequestKeys
-
AdvancedExtenderImpl.getAvailableCaptureResultKeys
-
Para obtener más información, consulte Claves y resultados de solicitudes de captura de soporte .
Flujo de aplicación 3: vista previa/captura fija con la extensión habilitada
Figura 10. Flujo de aplicación 3 en Advanced Extender
El diagrama anterior muestra el flujo principal para iniciar la vista previa y capturar imágenes fijas para el tipo de extensor avanzado. Repasemos cada paso.
Instancia
SessionProcessorImpl
La implementación principal de Advanced Extender está en
SessionProcessorImpl
, que es responsable de proporcionar una configuración de sesión personalizada y enviar solicitudes de captura para iniciar la vista previa y aún así capturar la solicitud. Se invocaAdvancedExtenderImpl.createSessionProcessor()
para devolver la instanciaSessionProcessorImpl
.initSession
SessionProcessorImpl.initSession()
inicializa la sesión para la extensión. Aquí es donde asigna recursos y devuelve una configuración de sesión para preparar unaCameraCaptureSession
.Para los parámetros de entrada, Camera2/X especifica las configuraciones de la superficie de salida para vista previa, captura de fotografías y un análisis de imagen YUV opcional. Esta configuración de superficie de salida (
OutputSurfaceImpl
) contiene la superficie, el tamaño y el formato de imagen que se recuperan mediante los siguientes métodos enAdvancedExtenderImpl
:-
getSupportedPreviewOutputResolutions()
-
getSupportedCaptureOutputResolutions()
-
getSupportedYuvAnalysisResolutions()
Debe devolver una instancia
Camera2SessionConfigImpl
, que consta de una lista de instanciasCamera2OutputConfigImpl
y los parámetros de sesión utilizados para configurarCameraCaptureSession
. Usted es responsable de enviar las imágenes correctas de la cámara a las superficies de salida pasadas por Camera2/X. Aquí hay algunas opciones para habilitar la salida:- Procesamiento en cámara HAL: puede agregar directamente las superficies de salida a
CameraCaptureSession
con una implementaciónSurfaceOutputConfigImpl
. Esto configura la superficie de salida suministrada a la tubería de la cámara y permite que la cámara HAL procese la imagen. Procesamiento de la superficie intermedia
ImageReader
(RAW, YUV, etc.): agregue las superficies intermediasImageReader
aCameraCaptureSession
con una instanciaImageReaderOutputConfigImpl
.Debe procesar las imágenes intermedias y escribir la imagen resultante en la superficie de salida.
- Usar el uso compartido de superficie Camera2: use el uso compartido de superficie con otra superficie agregando cualquier instancia
Camera2OutputConfigImpl
al métodogetSurfaceSharingOutputConfigs()
de otra instancia deCamera2OutputConfigImpl
. El formato y tamaño de la superficie deben ser idénticos.
Todo
Camera2OutputConfigImpl
, incluidosSurfaceOutputConfigImpl
eImageReaderOutputConfigImpl
, debe tener un ID único (getId()
), que se utiliza para especificar la superficie de destino y recuperar la imagen deImageReaderOutputConfigImpl
.-
onCaptureSessionStart
yRequestProcessorImpl
Cuando se inicia
CameraCaptureSession
y el marco de la cámara invocaonConfigured()
, Camera2/X invocaSessionProcessorImpl.onCaptureSessionStart()
con el contenedor de solicitudes Camera2RequestProcessImpl
. Camera2/X implementaRequestProcessImpl
, que le permite ejecutar las solicitudes de captura y recuperar imágenes si se utilizaImageReaderOutputConfigImpl
.Las API
RequestProcessImpl
son similares a las APICameraCaptureSession
de Camera2 en términos de ejecución de solicitudes. Las diferencias son:- La superficie de destino se especifica mediante el ID de la instancia
Camera2OutputConfigImpl
. - La capacidad de recuperar la imagen del
ImageReader
.
Puede llamar
RequestProcessorImpl.setImageProcessor()
con un IDCamera2OutputConfigImpl
especificado para registrar una instanciaImageProcessorImpl
para recibir imágenes.La instancia
RequestProcessImpl
deja de ser válida después de que Camera2/X llamaSessionProcessorImpl.onCaptureSessionEnd()
.- La superficie de destino se especifica mediante el ID de la instancia
Inicia la vista previa y toma una foto.
En la implementación de Advanced Extender, puede enviar solicitudes de captura a través de la interfaz
RequestProcessorImpl
. Camera2/X le notifica que inicie la solicitud repetida de vista previa o la secuencia de captura fija llamando aSessionProcessorImpl#startRepeating
ySessionProcessorImpl#startCapture
respectivamente. Debe enviar solicitudes de captura para satisfacer estas solicitudes de vista previa y captura fija.Camera2/X también establece los parámetros de solicitud de captura a través de
SessionProcessorImpl#setParameters
. Debe configurar estos parámetros de solicitud (si se admiten parámetros) tanto en las solicitudes repetidas como en las únicas.Debe admitir al menos
CaptureRequest.JPEG_ORIENTATION
yCaptureRequest.JPEG_QUALITY
.extensions-interface
1.3.0 admite claves de solicitud y resultado, que se exponen mediante los siguientes métodos:-
AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
-
AdvancedExtenderImpl.getAvailableCaptureResultKeys()
Cuando los desarrolladores configuran las claves en la lista
getAvailableCaptureRequestKeys
, deben habilitar los parámetros y asegurarse de que el resultado de la captura contenga las claves de la listagetAvailableCaptureResultKeys
.-
startTrigger
Se invoca
SessionProcessorImpl.startTrigger()
para iniciar el activador, comoCaptureRequest.CONTROL_AF_TRIGGER
yCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER
. Puede ignorar cualquier clave de solicitud de captura que no se haya anunciado enAdvancedExtenderImpl.getAvailableCaptureRequestKeys()
.startTrigger()
ha sido compatible desdeextensions-interface
1.3.0. Permite que las aplicaciones implementen tocar para enfocar y flashear con extensiones.Limpiar
Al finalizar una sesión de captura, se invoca
SessionProcessorImpl.onCaptureSessionEnd()
antes de cerrarCameraCaptureSession
. Una vez cerrada la sesión de captura,deInitSession()
realiza la limpieza.
Admite vista previa, captura fija y análisis de imágenes
Debe aplicar la extensión tanto para los casos de uso de vista previa como para la captura fija. Sin embargo, si la latencia es demasiado alta para mostrar la vista previa sin problemas, puede aplicar la extensión solo para la captura de imágenes fijas.
For the Basic Extender type, regardless of enabling the extension for preview, you must implement both ImageCaptureExtenderImpl
and PreviewExtenderImpl
for a given extension. Often, an app also uses a YUV stream to analyze the image content such as finding QR codes or text. To better support this use case , you should support the stream combination of preview, still capture, and a YUV_420_888
stream for configuring CameraCaptureSession
. This means that if you implement a processor, then you have to support the stream combination of three YUV_420_888
streams.
For Advanced Extender, Camera2/X passes three output surfaces to the SessionProcessorImpl.initSession()
call. These output surfaces are for preview , still capture, and image analysis, respectively. You must ensure that preview and still capture output surfaces show the valid output. However, for the image analysis output surface, ensure it's working only when it's non-null. If your implementation can't support the image analysis stream, you can return an empty list in AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
. This ensures the image analysis output surface is always null in SessionProcessorImpl.initSession()
.
Support video capture
The current Camera Extension architecture supports only the preview and still capture use cases. We don't support enabling the extension on the MediaCodec
or MediaRecorder
surfaces for recording the video. However, it's possible for apps to record the preview output.
Supporting MediaCodec
and MediaRecorder
surfaces is under investigation.
Extension-specific metadata
For Android 14 and higher, extension-specific metadata lets camera extension clients set and receive extension specific capture request settings and results. Specifically, camera extension clients can use the EXTENSION_STRENGTH
capture request parameter to control the extension strength and the EXTENSION_CURRENT_TYPE
capture result to indicate the enabled extension type.
Capture requests
The EXTENSION_STRENGTH
capture request parameter controls the strength of the extension post-processing effect. The corresponding capture result includes the default strength value if this parameter isn't set explicitly by the client. This parameter can be applied as follows for these extension types:
-
BOKEH
: Controls the amount of blur. -
HDR
andNIGHT
: Controls the amount of images fused and the brightness of the final image. -
FACE_RETOUCH
: Controls the amount of cosmetic enhancement and skin smoothing.
The supported range for the EXTENSION_STRENGTH
parameter is between 0
and 100
, with 0
indicating no extension processing or simple passthrough and 100
indicating the maximum extension strength of the processing effect.
To add support for EXTENSION_STRENGTH
, use the vendor specific parameter APIs introduced in version 1.3.0 of the extension library interface. For more information, see getAvailableCaptureRequestKeys()
.
Capture results
The EXTENSION_CURRENT_TYPE
capture result lets extension implementations notify clients about the active extension type.
Because extensions using the AUTO
type dynamically switch between extension types such as HDR
and NIGHT
depending on the scene conditions, camera extensions apps can use EXTENSION_CURRENT_TYPE
to display information about the current extension selected by the AUTO
extension.
Real-time still capture latency estimate
For Android 14 and higher, camera extension clients can query real-time still capture latency estimates based on the scene and environment conditions using getRealtimeStillCaptureLatency()
. This method provides more accurate estimates than the static getEstimatedCaptureLatencyRangeMillis()
method. Based on the latency estimate, apps can decide to skip extension processing or to display an indication to notify users about a long running operation.
CameraExtensionSession.StillCaptureLatency latency;
latency = extensionSession.getRealtimeStillCaptureLatency();
// The capture latency from ExtensionCaptureCallback#onCaptureStarted() until ExtensionCaptureCallback#onCaptureProcessStarted().
latency.getCaptureLatency();
// The processing latency from ExtensionCaptureCallback#onCaptureProcessStarted() until the processed frame returns to the client.
latency.getProcessingLatency();
To support real-time still capture latency estimates, implement the following:
- Basic extensions:
ImageCaptureExtenderImpl.getRealtimeCaptureLatency()
- Advanced extensions:
SessionProcessorImpl.getRealtimeCaptureLatency
Capture processing progress callbacks
For Android 14 and higher, camera extension clients can receive callbacks for the progress of long running still capture processing operations. Apps can display the current progress to users to improve the overall user experience.
Apps can use the following code to integrate this feature:
import android.hardware.camera2.CameraExtensionSession.
ExtensionCaptureCallback;
{
…
class AppCallbackImpl extends ExtensionCaptureCallback {
…
@Override
public void onCaptureProcessProgressed(
@NonNull CameraExtensionSession session,
@NonNull CaptureRequest request,
@IntRange(from = 0, to = 100) int progress) {
// Update app UI with current progress
}
}
…
}
To support capture processing progress callbacks, your extension vendor implementation must call the following callbacks with the current progress value:
- Basic extensions:
ProcessResultImpl.onCaptureProcessProgressed()
- Advanced extensions:
CaptureCallback.onCaptureProcessProgressed()
Postview still capture
For Android 14 and higher, camera extensions can supply a postview (preview image) using setPostviewOutputConfiguration
. To improve the user experience, apps can display a postview image as a placeholder when an extension is experiencing increased processing latency, and replace the image when the final image is available. Apps can configure and issue postview capture requests using the following reference code:
{
…
if (!CameraExtensionCharacteristics.isPostviewAvailable()) {
continue;
}
…
ExtensionSessionConfiguration extensionConfiguration = new
ExtensionSessionConfiguration(
CameraExtensionCharacteristics.EXTENSION_NIGHT,
outputConfig,
backgroundExecutor,
extensionSessionStateCallback
);
extensionConfiguration.setPostviewOutputConfiguration(
postviewImageOutput);
…
CaptureRequest.Builder captureRequestBuilder =
cameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(stillImageReader.getSurface());
captureRequestBuilder.addTarget(postviewImageSurface);
CaptureRequest captureRequest = captureRequestBuilder.build();
…
}
To support postview still capture, your vendor implementation must implement the following:
Basic extensions:
CaptureProcessorImpl.onPostviewOutputSurface
andCaptureProcessorImpl.processWithPostview
Advanced extensions:
SessionProcessorImpl.startCaptureWithPostview
Support SurfaceView output
For Android 14 and higher, camera extension clients can use power and performance optimized preview render paths by registering a SurfaceView
instance for preview output for repeating requests.
To support SurfaceView
output, your vendor extension implementation must be capable of streaming and outputting preview to SurfaceView
instances. To verify that this is supported, run the SurfaceViewExtensionPreviewTest.java
CTS module.
Vendor specific session types
The feature enables vendor extension implementations to select a vendor specific session type that will be set in the internal camera capture session instead of the default value.
The feature works entirely within the framework and vendor stack and has no client/public visible API impact.
To select a vendor-specific session type, implement the following for your extension libraries: * ExtenderStateListener.onSessionType()
for basic extensions * Camera2SessionConfigImpl.getSessionType()
for advanced extensions
Extensions interface version history
The following table shows the Camera Extension interface version history. You should always implement the vendor library with the latest version.
Version | Added features |
---|---|
1.0.0 |
|
1.1.0 |
|
1.2.0 |
|
1.3.0 |
|
1.4.0 |
|
Reference implementation
The following reference OEM vendor library implementations are available in frameworks/ex
.
advancedSample
: A basic implementation of Advanced Extender.sample
: A basic implementation of Basic Extender.service_based_sample
: An implementation that demonstrates how to host Camera Extensions in aService
. This implementation contains the following components:oem_library
: A Camera Extensions OEM library for Camera2 and CameraX Extensions APIs that implementsExtensions-Interface
. This acts as a passthrough that forwards calls fromExtensions-Interface
to the service. This library also provides AIDL files and wrapper classes to communicate with the service.Advanced Extender is enabled by default. To enable the Basic Extender, change
ExtensionsVersionImpl#isAdvancedExtenderImplemented
to returnfalse
.extensions_service
: A sample implementation of the Extensions Service. Add your implementation here. The interface to implement in the service is similar to theExtensions-Interface
. For example, implementing theIAdvancedExtenderImpl.Stub
performs the same operations asAdvancedExtenderImpl
.ImageWrapper
andTotalCaptureResultWrapper
are required to makeImage
andTotalCaptureResult
parcelable.
Set up the vendor library on a device
The OEM vendor library isn't built into an app; it's loaded from the device at runtime by Camera2/X. In CameraX, the <uses-library>
tag declares that the androidx.camera.extensions.impl
library, which is defined in the AndroidManifest.xml
file of the camera-extensions
library, is a dependency of CameraX and must be loaded at runtime. In Camera2, the framework loads an extensions service that also declares that the <uses-library>
loads the same androidx.camera.extensions.impl
library at runtime.
This allows third-party apps using extensions to automatically load the OEM vendor library. The OEM library is marked as optional so apps can run on devices that don't have the library on the device. Camera2/X handles this behavior automatically when an app tries to use a camera extension as long as the device manufacturer places the OEM library on the device so that it can be discovered by the app.
To set up the OEM library on a device, do the following:
- Add a permission file, which is required by the
<uses-library>
tag, using the following format:/etc/permissions/ ANY_FILENAME .xml
. For example,/etc/permissions/camera_extensions.xml
. The files in this directory provide a mapping of the library named in<uses-library>
to the actual file path on the device. Use the example below to add the required information to the file.
-
name
must beandroidx.camera.extensions.impl
as that's the library that CameraX searches for. -
file
is the absolute path of the file that contains the extensions implementation (for example,/system/framework/androidx.camera.extensions.impl.jar
).
<?xml version="1.0" encoding="utf-8"?> <permissions> <library name="androidx.camera.extensions.impl" file="OEM_IMPLEMENTED_JAR" /> </permissions>
-
In Android 12 or higher, devices supporting CameraX extensions must have the ro.camerax.extensions.enabled
property set to true
, which allows for querying whether a device supports extensions. To do this, add the following line in the device make file:
PRODUCT_VENDOR_PROPERTIES += \
ro.camerax.extensions.enabled=true \
Validation
To test your implementation of the OEM vendor library during the development stage, use the example app at androidx-main/camera/integration-tests/extensionstestapp/
, which runs through various vendor extensions.
After you complete your implementation, use the Camera Extensions Validation Tool to run automated and manual tests to verify that the vendor library is implemented correctly.
Extended scene mode versus Camera Extensions
For the bokeh extension, in addition to exposing it using Camera Extensions, you can expose the extension using the extended scene mode, which is enabled through the CONTROL_EXTENDED_SCENE_MODE
key. For more implementation details, see Camera Bokeh .
Extended scene mode has fewer restrictions compared to Camera Extensions for camera2 apps. For example, you can enable extended scene mode in a regular CameraCaptureSession
instance that supports flexible stream combinations and capture request parameters. In contrast, camera extensions support only a fixed set of stream types and have limited support for capture request parameters.
A downside of extended scene mode is that you can only implement it in the camera HAL, which means that it must be verified to work across all orthogonal controls available to app developers.
We recommend exposing bokeh using both the extended scene mode and Camera Extensions because apps might prefer to use a particular API to enable bokeh. We recommend first using the extended scene mode because this is the most flexible way for apps to enable the bokeh extension. Then you can implement the camera extensions interface based on the extended scene mode. If implementing bokeh in the camera HAL is difficult, for example, because it requires a post processor running in the app layer to process images, we recommend implementing the bokeh extension using the Camera Extensions interface.
Frequently asked questions (FAQs)
Are there any restrictions on API levels?
Yes. This depends on the Android API feature set that's required by the OEM vendor library implementation. For example, ExtenderStateListener.onPresetSession()
uses the SessionConfiguration.setSessionParameters()
call to set a baseline set of tags. This call is available only on API level 28 and higher. For details on specific interface methods, see the API reference documentation .