Extensions pour l'appareil photo

Les fabricants d'appareils peuvent exposer des extensions telles que le bokeh, le mode Nuit et le HDR à des développeurs tiers via l'interface Camera Extensions fournie par la bibliothèque du fournisseur OEM. Les développeurs peuvent utiliser l'API Extensions Camera2 et l'API Extensions CameraX pour accéder aux extensions implémentées dans la bibliothèque du fournisseur OEM.

Pour obtenir la liste des extensions compatibles, qui est la même pour Camera2 et CameraX, consultez la section API Extensions CameraX. Si vous souhaitez ajouter une extension, signalez un bug à l'aide de l'outil Issue Tracker.

Cette page explique comment implémenter et activer la bibliothèque du fournisseur OEM sur les appareils.

Architecture

Le diagramme suivant décrit l'architecture de l'interface Camera Extensions ou extensions-interface : Architecture

Figure 1 : Schéma de l'architecture des extensions de caméra

Comme indiqué dans le diagramme, pour prendre en charge les extensions d'appareil photo, vous devez implémenter le extensions-interface fourni par la bibliothèque du fournisseur OEM. Votre bibliothèque de fournisseurs OEM active deux API : l'API Extensions de CameraX et l'API Extensions de Camera2, qui sont utilisées respectivement par les applications CameraX et Camera2 pour accéder aux extensions du fournisseur.

Implémenter la bibliothèque de fournisseurs OEM

Pour implémenter la bibliothèque du fournisseur OEM, copiez les fichiers camera-extensions-stub dans un projet de bibliothèque système. Ces fichiers définissent l'interface Camera Extensions.

Les fichiers camera-extensions-stub sont répartis dans les catégories suivantes:

Fichiers d'interface essentiels (ne pas modifier)

  • 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

Implémentations obligatoires (ajoutez votre implémentation)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Classes d'extension Bokeh (implémentez-les si l'extension Bokeh est prise en charge)

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

Classes de prolongation de la nuit (implémentez-les si la prolongation de la nuit est prise en charge)

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

Classes d'extensions automatiques (à implémenter si l'extension automatique est compatible)

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

Classes d'extension HDR (implémentez-les si l'extension HDR est prise en charge)

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

Classes d'extension de la retouche du visage (implémentez-les si l'extension de la retouche du visage est prise en charge)

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

Utilitaires (facultatif, peuvent être supprimés)

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

Vous n'êtes pas tenu de fournir une implémentation pour chaque extension. Si vous n'implémentez pas d'extension, définissez isExtensionAvailable() pour renvoyer false ou supprimez les classes Extender correspondantes. Les API Extensions de Camera2 et CameraX indiquent à l'application que l'extension n'est pas disponible.

Voyons comment les API Camera2 et CameraX Extensions interagissent avec la bibliothèque du fournisseur pour activer une extension. Le schéma suivant illustre le flux de bout en bout avec l'extension Night à titre d'exemple:

Mainflow

Figure 2. Implémentation d'une extension de nuit

  1. Validation de la version:

    Camera2/X appelle ExtensionVersionImpl.checkApiVersion() pour s'assurer que la version extensions-interface implémentée par l'OEM est compatible avec les versions compatibles avec Camera2/X.

  2. Initialisation de la bibliothèque fournisseur:

    InitializerImpl dispose d'une méthode init() qui initialise la bibliothèque du fournisseur. Camera2/X termine l'initialisation avant d'accéder aux classes Extender.

  3. Instanciation des classes d'extension:

    Instanciation des classes Extender pour l'extension. Il existe deux types d'extenders: l'extender de base et l'extender avancé. Vous devez implémenter un type d'Extender pour toutes les extensions. Pour en savoir plus, consultez la page Extendeur de base par rapport à l'extendeur avancé.

    Camera2/X instancie les classes Extender et interagit avec elles pour récupérer des informations et activer l'extension. Pour une extension donnée, Camera2/X peut instancier les classes Extender plusieurs fois. Par conséquent, évitez d'effectuer une initialisation intensive dans le constructeur ou l'appel init(). N'effectuez les tâches lourdes que lorsque la session de l'appareil photo est sur le point de commencer, par exemple lorsque onInit() est appelé dans l'extension de base ou initSession() dans l'extension avancée.

    Pour l'extension Night, les classes Extender suivantes sont instanciées pour le type Extender de base:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    Pour le type d'extension Advanced Extender:

    • NightAdvancedExtenderImpl.java
  4. Vérifier la disponibilité des extensions :

    Avant d'activer l'extension, isExtensionAvailable() vérifie si l'extension est disponible sur l'ID de caméra spécifié via l'instance de l'extension.

  5. Initialisez l'extendeur avec les informations de la caméra:

    Camera2/X appelle init() sur l'instance de l'extension et lui transmet l'ID de l'appareil photo et CameraCharacteristics.

  6. Informations sur la requête:

    Elle appelle la classe Extender pour récupérer des informations telles que les résolutions compatibles, capturer la latence estimée et capturer les clés de requête de l'Extender en vue de l'activation de l'extension.

  7. Activez l'extension sur l'extendeur:

    La classe Extender fournit toutes les interfaces nécessaires pour activer la classe. Il offre un mécanisme permettant d'intégrer l'implémentation OEM au pipeline Camera2, par exemple en injectant des paramètres de requête de capture ou en activant un post-processeur.

    Pour le type d'extension avancée, Camera2/X interagit avec SessionProcessorImpl pour activer l'extension. Camera2/X récupère l'instance SessionProcessorImpl en appelant createSessionProcessor() sur le répéteur.

Les sections suivantes décrivent plus en détail le flux d'extension.

Validation des versions

Lors du chargement de la bibliothèque du fournisseur OEM à partir de l'appareil au moment de l'exécution, Camera2/X vérifie si la bibliothèque est compatible avec la version extensions-interface. extensions-interface utilise la gestion sémantique des versions, ou MAJEURE.MINEURE.CORRECTIF, par exemple 1.1.0 ou 1.2.0. Toutefois, seules les versions majeure et mineure sont utilisées lors de la validation de la version.

Pour vérifier la version, Camera2/X appelle ExtensionVersionImpl.checkApiVersion() avec la version extensions-interface compatible. Camera2/X utilise ensuite la version signalée par la bibliothèque OEM pour déterminer si l'extension peut être activée et quelles fonctionnalités elle doit appeler.

Compatibilité des versions majeures

Si les versions majeures de l'extension-interface sont différentes entre Camera2/X et la bibliothèque du fournisseur, elle est considérée comme incompatible et l'extension est désactivée.

Rétrocompatibilité.

Tant que la version majeure est identique, Camera2/X assure la rétrocompatibilité avec les bibliothèques des fournisseurs OEM créées avec des versions extensions-interface antérieures. Par exemple, si Camera2/X est compatible avec extensions-interface 1.3.0, les bibliothèques du fournisseur OEM qui ont implémenté les versions 1.0.0, 1.1.0 et 1.2.0 sont toujours compatibles. Cela signifie également qu'après avoir implémenté une version spécifique de la bibliothèque du fournisseur, Camera2/X s'assure que la bibliothèque est rétrocompatible avec les versions à venir de extension-interface.

Compatibilité ascendante

La rétrocompatibilité avec les bibliothèques de fournisseurs des extensions-interface plus récentes dépend de vous, l'OEM. Si vous avez besoin de certaines fonctionnalités pour implémenter les extensions, vous pouvez les activer à partir d'une certaine version. Dans ce cas, vous pouvez renvoyer la version extensions-interface compatible lorsque la version de la bibliothèque Camera2/X répond aux exigences. Si les versions Camera2/X ne sont pas compatibles, vous pouvez renvoyer une version incompatible telle que 99.0.0 pour désactiver les extensions.

Initialisation de la bibliothèque du fournisseur

Après avoir vérifié la version extensions-interface implémentée par la bibliothèque OEM, Camera2/X démarre le processus d'initialisation. La méthode InitializerImpl.init() indique à la bibliothèque OEM qu'une application tente d'utiliser des extensions.

Camera2/X n'effectue aucun autre appel à la bibliothèque OEM (à l'exception de la vérification de la version) tant que la bibliothèque du fournisseur OEM n'a pas appelé OnExtensionsInitializedCallback.onSuccess() pour signaler la fin de l'initialisation.

Vous devez implémenter InitializerImpl à partir de extensions-interface 1.1.0. Camera2/X ignore l'étape d'initialisation de la bibliothèque si la bibliothèque du fournisseur OEM implémente extensions-interface 1.0.0.

Prolongateur de base et prolongateur avancé

Il existe deux types d'implémentation de extensions-interface: Basic Extender et Advanced Extender. L'extension avancée est compatible depuis la version 1.2.0 de extensions-interface.

Implémentez l'extension de base pour les extensions qui traitent les images dans le HAL de la caméra ou utilisez un post-processeur capable de traiter les flux YUV.

Implémentez l'extension avancée pour les extensions qui doivent personnaliser la configuration du flux Camera2 et envoyer des requêtes de capture si nécessaire.

Reportez-vous au tableau suivant pour comparer les performances:

Répéteur de base Prolongateur avancé
Configurations de flux Fixé
Aperçu: PRIVATE ou YUV_420_888 (si un processeur existe)
Capture d'image: JPEG ou YUV_420_888 (si un processeur existe)
Personnalisable par l'OEM.
Envoi de la requête de capture Seul Camera2/X peut envoyer des requêtes de capture. Vous pouvez définir les paramètres pour ces requêtes. Lorsque le processeur est fourni pour la capture d'images, Camera2/X peut envoyer plusieurs requêtes de capture et envoyer toutes les images et les résultats de capture au processeur. Une instance RequestProcessorImpl vous est fournie pour exécuter la requête de capture camera2 et obtenir les résultats et l'image.

Camera2/X appelle startRepeating et startCapture sur SessionProcessorImpl pour indiquer à l'OEM de démarrer la requête répétée pour l'aperçu et de démarrer la séquence de capture d'image fixe, respectivement.

Hooks dans le pipeline de la caméra
  • onPresetSession fournit des paramètres de session.
  • onEnableSession envoie une seule requête juste après la configuration de CameraCaptureSession.
  • onDisableSession envoie une seule requête avant la fermeture de CameraCaptureSession.
  • initSession initialise et renvoie une configuration de session camera2 personnalisée pour créer la session de capture.
  • onCaptureSessionStart est appelé juste après la configuration de CameraCaptureSession.
  • onCaptureSessionEnd est appelé avant la fermeture de CameraCaptureSession.
Convient pour Extensions implémentées dans le HAL de l'appareil photo ou dans un processeur qui traite les images YUV.
  • Possède des implémentations basées sur Camera2 pour les extensions.
  • Nécessite une configuration de flux personnalisée, telle qu'un flux RAW.
  • Nécessite une séquence de capture interactive.
Version d'API compatible Extensions Camera2: Android 13 ou version ultérieure
Extensions CameraX: camera-extensions 1.1.0 ou version ultérieure
Camera2 Extensions: Android 12L ou version ultérieure
CameraX Extensions: camera-extensions 1.2.0-alpha03 ou version ultérieure

Flux d'application

Le tableau suivant présente trois types de flux d'application et leurs appels d'API Camera Extensions correspondants. Bien que Camera2/X fournisse ces API, vous devez implémenter correctement la bibliothèque du fournisseur pour prendre en charge ces flux, que nous décrirons plus en détail dans une section ultérieure.

Extensions Camera2 Extensions CameraX
Disponibilité des extensions de requête CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
Informations sur la requête CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

CameraX gère le reste des informations dans la bibliothèque.

Prévisualisation et capture d'images fixes avec l'extension activée CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

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

Rallonge de base

L'interface de l'extension de base fournit des crochets à plusieurs endroits du pipeline de la caméra. Chaque type d'extension possède des classes Extender correspondantes que les OEM doivent implémenter.

Le tableau suivant répertorie les classes d'extension que les OEM doivent implémenter pour chaque extension:

Classes d'extension à implémenter
Nuit NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Automatique AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Retouche du visage BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

Dans l'exemple suivant, nous utilisons PreviewExtenderImpl et ImageCaptureExtenderImpl comme espaces réservés. Remplacez-les par les noms des fichiers que vous mettez en œuvre.

Basic Extender offre les fonctionnalités suivantes:

  • Injectez des paramètres de session lors de la configuration de CameraCaptureSession (onPresetSession).
  • Vous informe des événements de début et de fin de la session de capture et envoie une seule requête pour informer le HAL des paramètres renvoyés (onEnableSession, onDisableSession).
  • Injectez des paramètres de capture pour la requête (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Ajoutez des processeurs pour l'aperçu et la capture, qui sont capables de traiter le flux YUV_420_888.

Voyons comment Camera2/X appelle extensions-interface pour réaliser les trois flux d'application mentionnés ci-dessus.

Parcours de l'application 1: Vérifier la disponibilité de l'extension

BasicExtenderAppFlow1

Figure 3. Flux d'application 1 sur l'Extendeur de base

Dans ce flux, Camera2/X appelle directement la méthode isExtensionAvailable() de PreviewExtenderImpl et ImageCaptureExtenderImpl sans appeler init(). Les deux classes d'extension doivent renvoyer true pour activer les extensions.

Il s'agit souvent de la première étape pour que les applications vérifient si le type d'extension donné est compatible avec un ID d'appareil photo donné avant d'activer l'extension. En effet, certaines extensions ne sont compatibles qu'avec certains ID de caméra.

Flux de l'application 2: Interroger des informations

BasicExtenderAppFlow2

Figure 4. Flux d'application 2 sur l'extendeur de base

Après avoir déterminé si l'extension est disponible, les applications doivent interroger les informations suivantes avant de l'activer.

  • Plage de latence de capture fixe:ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange renvoie la plage de latence de capture pour l'application afin d'évaluer s'il est approprié d'activer l'extension pour le scénario actuel.

  • Tailles compatibles pour la surface d'aperçu et de capture:ImageCaptureExtenderImpl.getSupportedResolutions et PreviewExtenderImpl.getSupportedResolutions renvoient une liste des formats d'image et des tailles compatibles pour le format et la taille de la surface.

  • Clés de requête et de résultat compatibles:Camera2/X appelle les méthodes suivantes pour récupérer les clés de requête de capture et les clés de résultat compatibles à partir de votre implémentation:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Camera2/X appelle toujours init() en premier sur ces classes d'extension avant d'interroger pour en savoir plus.

Flux d'application 3: Aperçu/capture d'image avec extension activée (implémentation HAL)

BasicExtenderAppFlow3

Figure 5. Déroulement des opérations de l'application 3 sur l'extendeur de base

Le schéma ci-dessus illustre le flux principal d'activation de l'aperçu et de la capture d'image avec une extension sans processeur. Cela signifie que le HAL de la caméra traite l'extension.

Dans ce flux, Camera2/X appelle d'abord init(), puis onInit, ce qui vous informe qu'une session d'appareil photo est sur le point de commencer avec les extensions spécifiées. Vous pouvez effectuer l'initialisation lourde dans onInit().

Lors de la configuration de CameraCaptureSession, Camera2/X appelle onPresetSession pour obtenir les paramètres de session. Une fois la session de capture configurée, Camera2/X appelle onEnableSession, qui renvoie une instance CaptureStageImpl contenant les paramètres de capture. Camera2/X envoie immédiatement une seule requête avec ces paramètres de capture pour informer le HAL. De même, avant la fermeture de la session de capture, Camera2/X appelle onDisableSession, puis envoie une seule requête avec les paramètres de capture renvoyés.

La requête répétée déclenchée par Camera2/X contient les paramètres de requête renvoyés par PreviewExtenderImpl.getCaptureStage(). De plus, la requête de capture d'image fixe contient les paramètres renvoyés par ImageCaptureExtenderImpl.getCaptureStages().

Enfin, Camera2/X appelle onDeInit() une fois la session d'appareil photo terminée. Vous pouvez libérer des ressources dans onDeinit().

Prévisualiser le processeur

En plus du HAL de la caméra, vous pouvez également implémenter des extensions dans un processeur.

Implémentez PreviewExtenderImpl.getProcessorType pour spécifier le type de processeur, comme expliqué ci-dessous:

  • PROCESSOR_TYPE_NONE:aucun processeur. Les images sont traitées dans le HAL de l'appareil photo.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY:le type de processeur vous permet de mettre à jour la requête répétée avec de nouveaux paramètres de requête de capture en fonction du dernier TotalCaptureResult.

    PreviewExtenderImpl.getProcessor doit renvoyer une instance RequestUpdateProcessorImpl qui traite l'instance TotalCaptureResult et renvoie une instance CaptureStageImpl pour mettre à jour la requête récurrente. PreviewExtenderImpl.getCaptureStage() doit également refléter le résultat du traitement et renvoyer le dernier CaptureStageImpl.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR:ce type vous permet d'implémenter un processeur pour traiter les images YUV_420_888 et écrire la sortie sur une surface PRIVATE.

    Vous devez implémenter et renvoyer une instance PreviewImageProcessorImpl dans PreviewExtenderImpl.getProcessor. Le processeur est chargé de traiter les images d'entrée YUV_420_888. Il doit écrire la sortie au format PRIVATE de l'aperçu. Camera2/X utilise une surface YUV_420_888 au lieu de PRIVATE pour configurer CameraCaptureSession pour l'aperçu.

    Pour connaître le flux, consultez l'illustration suivante:

PreviewProcessor

Figure 6. Prévisualiser le flux avec PreviewImageProcessorImpl

L'interface PreviewImageProcessorImpl étend ProcessImpl et comporte trois méthodes importantes:

  • onOutputSurface(Surface surface, int imageFormat) définit la surface de sortie pour le processeur. Pour PreviewImageProcessorImpl, imageFormat est un format de pixel tel que PixelFormat.RGBA_8888.

  • onResolutionUpdate(Size size) définit la taille de l'image d'entrée.

  • onImageFormatUpdate(int imageFormat) définit le format de l'image d'entrée. Actuellement, il ne peut s'agir que de YUV_420_888.

Processeur de capture d'image

Pour la capture d'image, vous pouvez implémenter un processeur en renvoyant une instance CaptureProcessorImpl à l'aide de ImageCaptureExtenderImpl.getCaptureProcessor. Le processeur est chargé de traiter une liste d'images YUV_420_888 et d'instances TotalCaptureResult capturées, puis d'écrire la sortie sur une surface YUV_420_888.

Vous pouvez supposer sans risque que l'aperçu est activé et en cours d'exécution avant d'envoyer la requête de capture d'image.

Consultez le flux dans le diagramme ci-dessous:

CaptureProcessor

Figure 7. Capturer toujours le flux avec CaptureProcessorImpl

  1. Camera2/X utilise une surface au format YUV_420_888 pour la capture fixe afin de configurer la session de capture. Camera2/X prépare CaptureProcessorImpl en appelant:

    • CaptureProcessorImpl.onImageFormatUpdate() correspond à YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() par la taille de l'image d'entrée.
    • CaptureProcessorImpl.onOutputSurface() avec une surface YUV_420_888 de sortie.
  2. ImageCaptureExtenderImpl.getCaptureStages renvoie une liste de CaptureStageImpl, où chaque élément est mappé sur une instance CaptureRequest avec des paramètres de capture envoyés par Camera2/X. Par exemple, s'il renvoie une liste de trois instances CaptureStageImpl, Camera2/X envoie trois requêtes de capture avec les paramètres de capture correspondants à l'aide de l'API captureBurst.

  3. Les images reçues et les instances TotalCaptureResult sont regroupées et envoyées à CaptureProcessorImpl pour traitement.

  4. CaptureProcessorImpl écrit l'image de résultat (format YUV_420_888) sur la surface de sortie spécifiée par l'appel onOutputSurface(). Camera2/X les convertit en images JPEG si nécessaire.

Prise en charge des clés et des résultats de requête de capture

En plus de l'aperçu et de la capture de l'appareil photo, les applications peuvent définir le zoom, les paramètres du flash ou déclencher la mise au point en appuyant sur l'écran. Il est possible que ces paramètres ne soient pas compatibles avec l'implémentation de votre extension.

Les méthodes suivantes ont été ajoutées à extensions-interface 1.3.0 pour vous permettre d'exposer les paramètres compatibles avec votre implémentation:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() renvoie les clés de requête de capture compatibles avec votre implémentation.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() renvoie les clés de résultat de capture contenues dans le résultat de capture.

Si le HAL de l'appareil photo traite l'extension, Camera2/X récupère les résultats de capture dans CameraCaptureSession.CaptureCallback. Toutefois, si le processeur est implémenté, Camera2/X récupère les résultats de capture dans ProcessResultImpl, qui est transmis à la méthode process() dans PreviewImageProcessorImpl et CaptureProcessorImpl. Il vous incombe de signaler le résultat de la capture via ProcessResultImpl à Camera2/X.

Consultez la définition de l'interface CaptureProcessorImpl ci-dessous à titre d'exemple. Dans extensions-interface 1.3.0 ou version ultérieure, le deuxième appel process() est appelé:

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

Pour les opérations d'appareil photo courantes telles que le zoom, la mise au point par appui, le flash et la compensation de l'exposition, nous vous recommandons de prendre en charge les clés suivantes à la fois pour la requête de capture et le résultat de capture:

  • Zoom:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Appuyer pour effectuer la mise au point:
    • 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
  • Correction d'exposition:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

Pour les répéteurs de base qui implémentent la version 1.2.0 ou des versions antérieures, l'API Extensions de CameraX prend en charge explicitement toutes les clés ci-dessus. Pour extensions-interface 1.3.0, CameraX et Camera2 respectent la liste renvoyée et n'acceptent que les clés qu'elle contient. Par exemple, si vous décidez de ne renvoyer que CaptureRequest#CONTROL_ZOOM_RATIO et CaptureRequest#SCALER_CROP_REGION dans l'implémentation 1.3.0, cela signifie que seul le zoom est compatible avec l'application, tandis que le focus par appui, le flash et la compensation d'exposition ne sont pas autorisés.

Extension avancée

Advanced Extender est un type d'implémentation fournisseur basé sur l'API Camera2. Ce type d'extension a été ajouté dans extensions-interface 1.2.0. Selon le fabricant de l'appareil, les extensions peuvent être implémentées dans la couche d'application, en fonction des facteurs suivants:

  • Configuration de flux personnalisé:configurez des flux personnalisés tels que le flux RAW ou utilisez plusieurs flux pour différents ID de caméra physique.

  • Possibilité d'envoyer des requêtes Camera2:prise en charge d'une logique d'interaction complexe pouvant envoyer des requêtes de capture avec des paramètres en fonction des résultats des requêtes précédentes.

L'extension avancée fournit un wrapper, ou une couche intermédiaire, qui vous permet de personnaliser la configuration du flux et d'envoyer des requêtes de capture à la demande.

Fichiers à implémenter

Pour passer à l'implémentation de l'extension avancée, la méthode isAdvancedExtenderImplemented() dans ExtensionVersionImpl doit renvoyer true. Pour chaque type d'extension, les OEM doivent implémenter les classes Extender correspondantes. Les fichiers d'implémentation de l'Extender avancé se trouvent dans le package advanced.

Classes d'extension à implémenter
Nuit advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Automatique advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Retouche du visage advanced/BeautyAdvancedExtenderImpl.java

Dans l'exemple suivant, nous utilisons AdvancedExtenderImpl comme espace réservé. Remplacez-le par le nom du fichier Extender de l'extension que vous implémentez.

Voyons comment Camera2/X appelle extensions-interface pour obtenir les trois flux d'application.

Parcours de l'application 1: Vérifier la disponibilité des extensions

AdvancedAppFlow1

Figure 8. Flux d'application 1 sur l'extension avancée

L'application vérifie d'abord si l'extension donnée est compatible.

Flux de l'application 2: Interroger des informations

AdvancedAppFlow2

Figure 9. Flux d'application 2 sur l'Extendeur avancé

Après avoir appelé AdvancedExtenderImpl.init(), l'application peut interroger les informations suivantes sur AdvancedExtenderImpl:

  • Estimation de la latence de capture:AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() renvoie la plage de latence de capture permettant à l'application d'évaluer s'il convient d'activer l'extension pour le scénario actuel.

  • Résolutions compatibles pour l'aperçu et la capture fixe:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() renvoie une carte de format d'image à la liste des tailles compatibles avec le format et la taille de la surface d'aperçu. Les OEM doivent être compatibles avec au moins le format PRIVATE.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() renvoie le format et les tailles compatibles pour la surface de capture. Les OEM doivent prendre en charge les formats de sortie JPEG et YUV_420_888.

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() renvoie les tailles acceptées pour un flux YUV_420_888 supplémentaire destiné à l'analyse d'image. Si la surface YUV d'analyse d'image n'est pas compatible, getSupportedYuvAnalysisResolutions() doit renvoyer null ou une liste vide.

  • Clés/résultats de requête de capture disponibles (ajouté dans extensions-interface 1.3.0) : Camera2/X appelle les méthodes suivantes pour récupérer les clés de requête de capture et les clés de résultat compatibles à partir de votre implémentation:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Pour en savoir plus, consultez la section Prendre en charge les clés et les résultats de capture de requête.

Parcours de l'application 3: Aperçu/Capture d'image avec extension activée

AdvancedAppFlow3

Figure 10. Flux d'application 3 sur l'Extendeur avancé

Le diagramme ci-dessus montre le flux principal pour démarrer l'aperçu et la capture d'image pour le type d'extension avancé. Passons en revue chaque étape.

  1. Instance SessionProcessorImpl

    L'implémentation de base de l'Extendeur avancé se trouve dans SessionProcessorImpl, qui est chargé de fournir une configuration de session personnalisée et d'envoyer des requêtes de capture pour lancer l'aperçu et la requête de capture. AdvancedExtenderImpl.createSessionProcessor() est appelé pour renvoyer l'instance SessionProcessorImpl.

  2. initSession

    SessionProcessorImpl.initSession() initialise la session pour l'extension. C'est ici que vous allouez des ressources et renvoyez une configuration de session pour préparer un CameraCaptureSession.

    Pour les paramètres d'entrée, Camera2/X spécifie les configurations de la surface de sortie pour l'aperçu, la capture d'image fixe et une analyse d'image YUV facultative. Cette configuration de surface de sortie (OutputSurfaceImpl) contient la surface, la taille et le format d'image récupérés par les méthodes suivantes dans AdvancedExtenderImpl:

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

    Vous devez renvoyer une instance Camera2SessionConfigImpl, qui consiste en une liste d'instances Camera2OutputConfigImpl et des paramètres de session utilisés pour configurer CameraCaptureSession. Il vous incombe de générer les images de caméra appropriées sur les surfaces de sortie transmises par Camera2/X. Voici quelques options pour activer la sortie:

    • Traitement dans la couche HAL de la caméra:vous pouvez ajouter directement les surfaces de sortie à CameraCaptureSession avec une implémentation SurfaceOutputConfigImpl. Cela configure la surface de sortie fournie sur le pipeline de l'appareil photo et permet au HAL de l'appareil photo de traiter l'image.
    • Traitement de la surface ImageReader intermédiaire (RAW, YUV, etc.) : ajoutez les surfaces ImageReader intermédiaires à CameraCaptureSession avec une instance ImageReaderOutputConfigImpl.

      Vous devez traiter les images intermédiaires et écrire l'image de résultat sur la surface de sortie.

    • Utiliser le partage de surface Camera2:utilisez le partage de surface avec une autre surface en ajoutant une instance Camera2OutputConfigImpl à la méthode getSurfaceSharingOutputConfigs() d'une autre instance Camera2OutputConfigImpl. Le format et la taille de la surface doivent être identiques.

    Tous les Camera2OutputConfigImpl, y compris SurfaceOutputConfigImpl et ImageReaderOutputConfigImpl, doivent avoir un ID unique (getId()), qui permet de spécifier la surface cible et de récupérer l'image à partir de ImageReaderOutputConfigImpl.

  3. onCaptureSessionStart et RequestProcessorImpl

    Lorsque CameraCaptureSession démarre et que le framework de l'appareil photo appelle onConfigured(), Camera2/X appelle SessionProcessorImpl.onCaptureSessionStart() avec le wrapper de requête Camera2 RequestProcessImpl. Camera2/X implémente RequestProcessImpl, ce qui vous permet d'exécuter les requêtes de capture et de récupérer des images si ImageReaderOutputConfigImpl est utilisé.

    Les API RequestProcessImpl sont semblables aux API CameraCaptureSession de Camera2 en termes d'exécution de requêtes. Les différences sont les suivantes:

    • La surface cible est spécifiée par l'ID de l'instance Camera2OutputConfigImpl.
    • Capacité à récupérer l'image de l'ImageReader.

    Vous pouvez appeler RequestProcessorImpl.setImageProcessor() avec un ID Camera2OutputConfigImpl spécifié pour enregistrer une instance ImageProcessorImpl afin de recevoir des images.

    L'instance RequestProcessImpl devient non valide après les appels SessionProcessorImpl.onCaptureSessionEnd() de Camera2/X.

  4. Démarrer l'aperçu et prendre une photo

    Dans l'implémentation de l'extension avancée, vous pouvez envoyer des requêtes de capture via l'interface RequestProcessorImpl. Camera2/X vous avertit pour démarrer la requête répétée d'aperçu ou la séquence de capture d'image en appelant respectivement SessionProcessorImpl#startRepeating et SessionProcessorImpl#startCapture. Vous devez envoyer des requêtes de capture pour répondre à ces requêtes d'aperçu et de capture d'image.

    Camera2/X définit également les paramètres de requête de capture via SessionProcessorImpl#setParameters. Vous devez définir ces paramètres de requête (si les paramètres sont compatibles) à la fois pour les requêtes répétées et les requêtes uniques.

    Vous devez prendre en charge au moins CaptureRequest.JPEG_ORIENTATION et CaptureRequest.JPEG_QUALITY. extensions-interface 1.3.0 est compatible avec les clés de requête et de résultat, qui sont exposées par les méthodes suivantes:

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

    Lorsque les développeurs définissent les clés dans la liste getAvailableCaptureRequestKeys, vous devez activer les paramètres et vous assurer que le résultat de la capture contient les clés de la liste getAvailableCaptureResultKeys.

  5. startTrigger

    SessionProcessorImpl.startTrigger() est appelé pour démarrer le déclencheur, tel que CaptureRequest.CONTROL_AF_TRIGGER et CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Vous pouvez ignorer toutes les clés de requête de capture qui n'ont pas été annoncées dans AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    startTrigger() est compatible depuis la version 1.3.0 de extensions-interface. Il permet aux applications d'implémenter la mise au point tactile et le flash avec des extensions.

  6. Nettoyage

    À la fin d'une session de capture, SessionProcessorImpl.onCaptureSessionEnd() est appelé avant la fermeture de CameraCaptureSession. Une fois la session de capture fermée, deInitSession() effectue le nettoyage.

Prise en charge de l'aperçu, de la capture fixe et de l'analyse d'images

Vous devez appliquer l'extension pour les cas d'utilisation d'aperçu et de capture d'image. Toutefois, si la latence est trop élevée pour afficher correctement l'aperçu, vous ne pouvez appliquer l'extension qu'à la capture d'image.

Pour le type d'extension de base, que vous ayez activé l'aperçu pour l'extension, vous devez implémenter à la fois ImageCaptureExtenderImpl et PreviewExtenderImpl pour une extension donnée. Souvent, une application utilise également un flux YUV pour analyser le contenu de l'image, par exemple pour trouver des codes QR ou du texte. Pour mieux prendre en charge ce cas d'utilisation, vous devez prendre en charge la combinaison de flux d'aperçu, de capture d'image et d'un flux YUV_420_888 pour configurer CameraCaptureSession. Cela signifie que si vous implémentez un processeur, vous devez prendre en charge la combinaison de flux de trois flux YUV_420_888.

Pour l'extension avancée, Camera2/X transmet trois surfaces de sortie à l'appel SessionProcessorImpl.initSession(). Ces surfaces de sortie sont destinées respectivement à l'aperçu, à la capture d'images fixes et à l'analyse d'images. Vous devez vous assurer que les surfaces de sortie d'aperçu et toujours de capture affichent le résultat valide. Toutefois, pour la surface de sortie de l'analyse d'image, assurez-vous qu'elle ne fonctionne que lorsqu'elle n'est pas nulle. Si votre implémentation n'est pas compatible avec le flux d'analyse d'images, vous pouvez renvoyer une liste vide dans AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). Cela garantit que la surface de sortie de l'analyse d'image est toujours nulle dans SessionProcessorImpl.initSession().

Prise en charge de la capture vidéo

L'architecture actuelle de l'extension de caméra n'est compatible qu'avec les cas d'utilisation de prévisualisation et de capture. L'extension n'est pas compatible avec les surfaces MediaCodec ou MediaRecorder pour enregistrer la vidéo. Toutefois, les applications peuvent enregistrer la sortie d'aperçu.

La prise en charge des surfaces MediaCodec et MediaRecorder est en cours d'étude.

Métadonnées spécifiques aux extensions

Pour Android 14 et les versions ultérieures, les métadonnées spécifiques aux extensions permettent aux clients des extensions d'appareil photo de définir et de recevoir des paramètres et des résultats de requête de capture spécifiques à l'extension. Plus précisément, les clients d'extension de l'appareil photo peuvent utiliser le paramètre de requête de capture EXTENSION_STRENGTH pour contrôler l'intensité de l'extension et le résultat de capture EXTENSION_CURRENT_TYPE pour indiquer le type d'extension activé.

Requêtes de capture

Le paramètre de requête de capture EXTENSION_STRENGTH contrôle l'intensité de l'effet de post-traitement de l'extension. Le résultat de capture correspondant inclut la valeur de force par défaut si ce paramètre n'est pas défini explicitement par le client. Ce paramètre peut être appliqué comme suit pour ces types d'extensions:

  • BOKEH: contrôle le degré de floutage.
  • HDR et NIGHT: contrôle la quantité d'images fusionnées et la luminosité de l'image finale.
  • FACE_RETOUCH: contrôle l'intensité de l'amélioration cosmétique et de l'adoucissement de la peau.

La plage acceptée pour le paramètre EXTENSION_STRENGTH est comprise entre 0 et 100, 0 indiquant l'absence de traitement d'extension ou un passthrough simple, et 100 indiquant l'intensité d'extension maximale de l'effet de traitement.

Pour ajouter la compatibilité avec EXTENSION_STRENGTH, utilisez les API de paramètres spécifiques au fournisseur introduites dans la version 1.3.0 de l'interface de la bibliothèque d'extensions. Pour en savoir plus, consultez getAvailableCaptureRequestKeys().

Enregistrer les résultats

Le résultat de la capture EXTENSION_CURRENT_TYPE permet aux implémentations d'extension d'informer les clients du type d'extension active.

Étant donné que les extensions utilisant le type AUTO basculent dynamiquement entre les types d'extensions tels que HDR et NIGHT en fonction des conditions de la scène, les applications d'extensions d'appareil photo peuvent utiliser EXTENSION_CURRENT_TYPE pour afficher des informations sur l'extension actuelle sélectionnée par l'extension AUTO.

Estimation de la latence de capture d'une photo en temps réel

Pour Android 14 et versions ultérieures, les clients d'extension d'appareil photo peuvent interroger les estimations de latence de capture d'image fixe en temps réel en fonction des conditions de la scène et de l'environnement à l'aide de getRealtimeStillCaptureLatency(). Cette méthode fournit des estimations plus précises que la méthode statique getEstimatedCaptureLatencyRangeMillis(). En fonction de l'estimation de la latence, les applications peuvent décider de ne pas traiter l'extension ou d'afficher une indication pour avertir les utilisateurs d'une opération de longue durée.

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

Pour prendre en charge les estimations de latence de capture d'image fixe en temps réel, implémentez les éléments suivants:

Capturer les rappels de progression du traitement

Pour Android 14 et les versions ultérieures, les clients de l'extension d'appareil photo peuvent recevoir des rappels pour la progression des opérations de traitement de capture et de capture de l'image de longue durée. Les applications peuvent afficher la progression actuelle aux utilisateurs pour améliorer leur expérience globale.

Les applications peuvent utiliser le code suivant pour intégrer cette fonctionnalité:

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

}

Pour prendre en charge les rappels de progression du traitement de la capture, l'implémentation du fournisseur d'extension doit appeler les rappels suivants avec la valeur de progression actuelle:

Capture d'image après affichage

Pour Android 14 et versions ultérieures, les extensions d'appareil photo peuvent fournir un postview (image d'aperçu) à l'aide de setPostviewOutputConfiguration. Pour améliorer l'expérience utilisateur, les applications peuvent afficher une image post-vue en tant qu'espace réservé lorsqu'une extension connaît une latence de traitement accrue, et la remplacer lorsque l'image finale est disponible. Les applications peuvent configurer et émettre des requêtes de capture post-vue à l'aide du code de référence suivant:

{

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

}

Pour prendre en charge la capture d'images après visionnage, votre implémentation de fournisseur doit inclure les éléments suivants:

Prendre en charge la sortie SurfaceView

Pour Android 14 et versions ultérieures, les clients d'extension d'appareil photo peuvent utiliser des chemins de rendu d'aperçu optimisés pour la consommation d'énergie et les performances en enregistrant une instance SurfaceView pour la sortie d'aperçu des requêtes répétées.

Pour prendre en charge la sortie SurfaceView, l'implémentation de votre extension de fournisseur doit pouvoir diffuser et générer un aperçu vers les instances SurfaceView. Pour vérifier que cette fonctionnalité est prise en charge, exécutez le module CTS SurfaceViewExtensionPreviewTest.java.

Types de sessions spécifiques au fournisseur

Cette fonctionnalité permet aux implémentations d'extensions de fournisseurs de sélectionner un type de session spécifique au fournisseur qui sera défini dans la session de capture de la caméra interne au lieu de la valeur par défaut.

Cette fonctionnalité s'intègre entièrement dans le framework et la pile de fournisseurs, et n'a aucun impact visible sur le client ou le public sur les API.

Pour sélectionner un type de session spécifique au fournisseur, implémentez les éléments suivants pour vos bibliothèques d'extensions : * ExtenderStateListener.onSessionType() pour les extensions de base * Camera2SessionConfigImpl.getSessionType() pour les extensions avancées

Historique des versions de l'interface des extensions

Le tableau suivant présente l'historique des versions de l'interface d'extension de l'appareil photo. Vous devez toujours implémenter la bibliothèque du fournisseur avec la dernière version.

Version Fonctionnalités ajoutées
1.0.0
  • Vérification de la version
    • ExtensionVersionImpl
  • Amplificateur de base
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Initialisation de la bibliothèque
    • InitializerImpl
  • Exposer les résolutions compatibles
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender 
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Obtenir la latence de capture estimée
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Exposer les clés de requête de capture/de résultats compatibles
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys et getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys et getAvailableCaptureResultKeys
    • Nouvel appel process() qui prend ProcessResultImpl dans PreviewImageProcessorImpl et CaptureProcessorImpl
    • Demande de prise en charge du type de déclencheur
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Métadonnées spécifiques à l'extension
  • Estimations de latence de capture d'image fixe dynamique
  • Capturer les rappels de progression du traitement
  • Capture d'image après affichage
  • Prise en charge de la sortie SurfaceView
  • Types de sessions spécifiques au fournisseur

Implémentation de référence

Les implémentations de bibliothèques de fournisseurs OEM de référence suivantes sont disponibles dans frameworks/ex.

  • advancedSample: implémentation de base de Advanced Extender.

  • sample: implémentation de base de l'extension de base.

  • service_based_sample: implémentation qui montre comment héberger des extensions d'appareil photo dans un Service. Cette implémentation contient les composants suivants:

    • oem_library : bibliothèque OEM d'extensions Camera pour les API d'extensions Camera2 et CameraX qui implémente Extensions-Interface. Il s'agit d'un passthrough qui transfère les appels de Extensions-Interface vers le service. Cette bibliothèque fournit également des fichiers AIDL et des classes de wrapper pour communiquer avec le service.

      L'extension avancée est activée par défaut. Pour activer l'extension de base, remplacez ExtensionsVersionImpl#isAdvancedExtenderImplemented par false.

    • extensions_service : exemple d'implémentation du service d'extensions. Ajoutez votre implémentation ici. L'interface à implémenter dans le service est semblable à Extensions-Interface. Par exemple, l'implémentation de IAdvancedExtenderImpl.Stub effectue les mêmes opérations que AdvancedExtenderImpl. ImageWrapper et TotalCaptureResultWrapper sont obligatoires pour rendre Image et TotalCaptureResult parcellables.

Configurer la bibliothèque du fournisseur sur un appareil

La bibliothèque du fournisseur OEM n'est pas intégrée à une application. Elle est chargée à partir de l'appareil au moment de l'exécution par Camera2/X. Dans CameraX, la balise <uses-library> déclare que la bibliothèque androidx.camera.extensions.impl, définie dans le fichier AndroidManifest.xml de la bibliothèque camera-extensions, est une dépendance de CameraX et doit être chargée au moment de l'exécution. Dans Camera2, le framework charge un service d'extensions qui déclare également que <uses-library> charge la même bibliothèque androidx.camera.extensions.impl au moment de l'exécution.

Cela permet aux applications tierces utilisant des extensions de charger automatiquement la bibliothèque du fournisseur OEM. La bibliothèque OEM est marquée comme facultative afin que les applications puissent s'exécuter sur les appareils qui ne disposent pas de la bibliothèque. Camera2/X gère ce comportement automatiquement lorsqu'une application tente d'utiliser une extension d'appareil photo, à condition que le fabricant de l'appareil place la bibliothèque OEM sur l'appareil afin qu'elle puisse être détectée par l'application.

Pour configurer la bibliothèque OEM sur un appareil, procédez comme suit:

  1. Ajoutez un fichier d'autorisation, qui est requis par la balise <uses-library>, au format suivant : /etc/permissions/ANY_FILENAME.xml. Par exemple, /etc/permissions/camera_extensions.xml. Les fichiers de ce répertoire fournissent un mappage de la bibliothèque nommée dans <uses-library> au chemin d'accès au fichier réel sur l'appareil.
  2. Utilisez l'exemple ci-dessous pour ajouter les informations requises au fichier.

    • name doit être androidx.camera.extensions.impl, car c'est la bibliothèque que CameraX recherche.
    • file correspond au chemin d'accès absolu du fichier contenant l'implémentation des extensions (par exemple, /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>

Sous Android 12 ou version ultérieure, la propriété ro.camerax.extensions.enabled doit être définie sur true pour les appareils compatibles avec les extensions CameraX. Cela permet de vérifier si un appareil est compatible avec les extensions. Pour ce faire, ajoutez la ligne suivante dans le fichier de compilation de l'appareil:

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

Validation

Pour tester votre implémentation de la bibliothèque du fournisseur OEM lors de la phase de développement, utilisez l'exemple d'application sur androidx-main/camera/integration-tests/extensionstestapp/, qui exécute diverses extensions du fournisseur.

Une fois l'implémentation terminée, utilisez l'outil de validation des extensions d'appareil photo pour exécuter des tests automatiques et manuels afin de vérifier que la bibliothèque du fournisseur est implémentée correctement.

Mode scène étendu par rapport aux extensions d'appareil photo

Pour l'extension bokeh, en plus de l'exposer à l'aide d'extensions de caméra, vous pouvez l'exposer à l'aide du mode Scène étendu, qui est activé via la clé CONTROL_EXTENDED_SCENE_MODE. Pour en savoir plus sur l'implémentation, consultez Bokeh de l'appareil photo.

Le mode scène étendu présente moins de restrictions que les extensions d'appareil photo pour les applications camera2. Par exemple, vous pouvez activer le mode scène étendu dans une instance CameraCaptureSession standard compatible avec les combinaisons de flux flexibles et les paramètres de requête de capture. En revanche, les extensions d'appareil photo ne sont compatibles qu'avec un ensemble fixe de types de flux et ne sont pas entièrement compatibles avec les paramètres de requête de capture.

L'inconvénient du mode scène étendu est que vous ne pouvez l'implémenter que dans le HAL de l'appareil photo, ce qui signifie qu'il doit être vérifié pour fonctionner avec toutes les commandes orthogonales disponibles pour les développeurs d'applications.

Nous vous recommandons d'exposer le bokeh à l'aide du mode Scène étendu et des extensions Camera, car les applications peuvent préférer utiliser une API particulière pour activer le bokeh. Nous vous recommandons d'utiliser d'abord le mode scène étendu, car il s'agit du moyen le plus flexible pour les applications d'activer l'extension bokeh. Vous pouvez ensuite implémenter l'interface des extensions de l'appareil photo en fonction du mode Scène étendu. Si l'implémentation du bokeh dans le HAL de l'appareil photo est difficile, par exemple, car elle nécessite un post-processeur exécuté dans la couche application pour traiter les images, nous vous recommandons d'implémenter l'extension bokeh à l'aide de l'interface Camera Extensions.

Questions fréquentes

Existe-t-il des restrictions concernant les niveaux d'API ?

Oui. Cela dépend de l'ensemble de fonctionnalités de l'API Android requis par l'implémentation de la bibliothèque du fournisseur OEM. Par exemple, ExtenderStateListener.onPresetSession() utilise l'appel SessionConfiguration.setSessionParameters() pour définir un ensemble de balises de référence. Cet appel n'est disponible qu'à partir du niveau d'API 28. Pour en savoir plus sur des méthodes d'interface spécifiques, consultez la documentation de référence de l'API.