Kameraerweiterungen

Gerätehersteller können Drittanbietern über die Kameraerweiterungs-Schnittstelle der OEM-Anbieterbibliothek Erweiterungen wie Bokeh, Nachtmodus und HDR zur Verfügung stellen. Entwickler können die Camera2 Extensions API und die CameraX Extensions API verwenden, um auf die in der OEM-Anbieterbibliothek implementierten Erweiterungen zuzugreifen.

Eine Liste der unterstützten Erweiterungen, die für Camera2 und CameraX identisch ist, finden Sie unter CameraX Extensions API. Wenn Sie eine Erweiterung hinzufügen möchten, melden Sie einen Fehler über den Issue Tracker.

Auf dieser Seite wird beschrieben, wie Sie die OEM-Anbieterbibliothek auf Geräten implementieren und aktivieren.

Architektur

Das folgende Diagramm beschreibt die Architektur der Kameraerweiterungs-API oder extensions-interface: Architektur

Abbildung 1. Architekturdiagramm für Kameraerweiterungen

Wie im Diagramm dargestellt, müssen Sie die extensions-interface implementieren, die von der OEM-Anbieterbibliothek bereitgestellt wird, um Kameraerweiterungen zu unterstützen. Ihre OEM-Anbieterbibliothek ermöglicht zwei APIs: die CameraX Extensions API und die Camera2 Extensions API. Sie werden von CameraX- und Camera2-Apps verwendet, um auf Anbietererweiterungen zuzugreifen.

OEM-Anbieterbibliothek implementieren

Um die OEM-Anbieterbibliothek zu implementieren, kopieren Sie die Dateien camera-extensions-stub in ein Systembibliotheksprojekt. Diese Dateien definieren die Benutzeroberfläche der Kameraerweiterungen.

Die camera-extensions-stub-Dateien sind in die folgenden Kategorien unterteilt:

Wichtige Benutzeroberflächendateien (nicht ändern)

  • 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

Erforderliche Implementierungen (Implementierung hinzufügen)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Bokeh-Erweiterungsklassen (implementieren, wenn Bokeh-Erweiterung unterstützt wird)

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

Kurse für die Nachtzeiterweiterung (implementieren, wenn die Nachtzeiterweiterung unterstützt wird)

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

Auto-Extender-Klassen (implementieren, wenn die automatische Erweiterung unterstützt wird)

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

HDR-Extender-Klassen (implementieren, wenn HDR-Erweiterung unterstützt wird)

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

Erweiterungsklassen für die Gesichtsretusche (implementieren, wenn die Erweiterung für die Gesichtsretusche unterstützt wird)

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

Dienstprogramme (optional, können gelöscht werden)

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

Sie müssen nicht für jede Erweiterung eine Implementierung bereitstellen. Wenn Sie keine Erweiterung implementieren, legen Sie fest, dass isExtensionAvailable() false zurückgibt, oder entfernen Sie die entsprechenden Extender-Klassen. Die Camera2- und CameraX-Erweiterungen-APIs melden der App, dass die Erweiterung nicht verfügbar ist.

Sehen wir uns an, wie die Camera2- und CameraX-Erweiterungs-APIs mit der Anbieterbibliothek interagieren, um eine Erweiterung zu aktivieren. Das folgende Diagramm veranschaulicht den End-to-End-Ablauf anhand der Night-Erweiterung:

Mainflow

Abbildung 2. Implementierung der Nachterweiterung

  1. Versionsüberprüfung:

    Camera2/X ruft ExtensionVersionImpl.checkApiVersion() auf, um sicherzustellen, dass die vom OEM implementierte extensions-interface-Version mit den von Camera2/X unterstützten Versionen kompatibel ist.

  2. Initialisierung der Anbieterbibliothek:

    InitializerImpl hat eine Methode init(), die die Anbieterbibliothek initialisiert. Camera2/X führt die Initialisierung durch, bevor auf die Extender-Klassen zugegriffen wird.

  3. Erstellen Sie Extender-Klassen:

    Instantiiert die Extender-Klassen für die Erweiterung. Es gibt zwei Arten von Extendern: Basic Extender und Advanced Extender. Sie müssen einen Erweiterungstyp für alle Erweiterungen implementieren. Weitere Informationen finden Sie unter Einfache und erweiterte Extender vergleichen.

    Camera2/X erstellt Instanzen der Extender-Klassen und interagiert mit ihnen, um Informationen abzurufen und die Erweiterung zu aktivieren. Für eine bestimmte Erweiterung kann Camera2/X die Extender-Klassen mehrmals instanziieren. Führen Sie daher keine aufwendigen Initialisierungen im Konstruktor oder im init()-Aufruf durch. Die aufwendigen Aufgaben sollten Sie erst dann ausführen, wenn die Kamerasitzung kurz bevorsteht, z. B. wenn onInit() im Basic Extender oder initSession() im Advanced Extender aufgerufen wird.

    Für die Nachterweiterung werden die folgenden Extender-Klassen für den Typ „Basic Extender“ instanziiert:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    Für den erweiterten Extendertyp:

    • NightAdvancedExtenderImpl.java
  4. Verfügbarkeit der Erweiterung prüfen:

    Bevor die Erweiterung aktiviert wird, prüft isExtensionAvailable(), ob sie über die Extender-Instanz für die angegebene Kamera-ID verfügbar ist.

  5. Erweiterer mit Kamerainformationen initialisieren:

    Camera2/X ruft init() in der Extender-Instanz auf und übergibt die Kamera-ID und CameraCharacteristics.

  6. Abfrageinformationen:

    Ruft die Extender-Klasse auf, um Informationen wie unterstützte Auflösungen abzurufen, die geschätzte Latenz zu erfassen und Anfrageschlüssel vom Extender zu erfassen, um die Erweiterung zu aktivieren.

  7. Erweiterung auf dem Extender aktivieren:

    Die Extender-Klasse stellt alle Schnittstellen bereit, die zum Aktivieren der Klasse erforderlich sind. Es bietet einen Mechanismus, mit dem die OEM-Implementierung in die Camera2-Pipeline eingebunden werden kann, z. B. durch Einschleusen von Aufnahmeanfrageparametern oder Aktivieren eines Postprozessors.

    Beim erweiterten Extender-Typ interagiert Camera2/X mit SessionProcessorImpl, um die Erweiterung zu aktivieren. Camera2/X ruft die SessionProcessorImpl-Instanz ab, indem createSessionProcessor() auf dem Extender aufgerufen wird.

In den folgenden Abschnitten wird der Ablauf der Erweiterung ausführlicher beschrieben.

Versionsüberprüfung

Beim Laden der OEM-Anbieterbibliothek vom Gerät zur Laufzeit prüft Camera2/X, ob die Bibliothek mit der extensions-interface-Version kompatibel ist. Die extensions-interface verwendet die semantische Versionierung, also MAJOR.MINOR.PATCH, z. B. 1.1.0 oder 1.2.0. Bei der Versionsüberprüfung werden jedoch nur die Haupt- und die Nebenversion verwendet.

Zur Überprüfung der Version ruft Camera2/X ExtensionVersionImpl.checkApiVersion() mit der unterstützten extensions-interface-Version auf. Camera2/X verwendet dann die von der OEM-Bibliothek gemeldete Version, um zu ermitteln, ob die Erweiterung aktiviert werden kann und welche Funktionen sie aufrufen soll.

Kompatibilität mit Hauptversionen

Wenn sich die Hauptversionen der Erweiterungsoberfläche zwischen Camera2/X und der Anbieterbibliothek unterscheiden, wird sie als nicht kompatibel eingestuft und deaktiviert.

Abwärtskompatibilität

Solange die Hauptversion identisch ist, sorgt Camera2/X für Abwärtskompatibilität mit OEM-Bibliotheken von Anbietern, die mit früheren extensions-interface-Versionen erstellt wurden. Wenn Camera2/X beispielsweise extensions-interface 1.3.0 unterstützt, sind die OEM-Anbieterbibliotheken, die 1.0.0, 1.1.0 und 1.2.0 implementiert haben, weiterhin kompatibel. Das bedeutet auch, dass nach der Implementierung einer bestimmten Version der Anbieterbibliothek Camera2/X dafür sorgt, dass die Bibliothek abwärtskompatibel mit zukünftigen extension-interface-Versionen ist.

Vorwärtskompatibilität

Die zukünftige Kompatibilität mit Anbieterbibliotheken neuerer extensions-interface hängt von Ihnen als OEM ab. Wenn Sie einige Funktionen für die Implementierung der Erweiterungen benötigen, sollten Sie die Erweiterungen ab einer bestimmten Version aktivieren. In diesem Fall können Sie die unterstützte extensions-interface-Version zurückgeben, wenn die Camera2/X-Bibliotheksversion die Anforderungen erfüllt. Wenn die Camera2/X-Versionen nicht unterstützt werden, können Sie eine inkompatible Version wie 99.0.0 zurückgeben, um die Erweiterungen zu deaktivieren.

Initialisierung der Anbieterbibliothek

Nachdem die von der OEM-Bibliothek implementierte extensions-interface-Version überprüft wurde, startet Camera2/X den Initialisierungsprozess. Die Methode InitializerImpl.init() signalisiert der OEM-Bibliothek, dass eine App versucht, Erweiterungen zu verwenden.

Camera2/X ruft die OEM-Bibliothek (abgesehen von der Versionsprüfung) nicht noch einmal auf, bis die OEM-Anbieterbibliothek OnExtensionsInitializedCallback.onSuccess() aufruft, um über den Abschluss der Initialisierung zu informieren.

Sie müssen InitializerImpl ab extensions-interface 1.1.0 implementieren. Camera2/X überspringt den Schritt zur Bibliothekinitialisierung, wenn die OEM-Anbieterbibliothek extensions-interface 1.0.0 implementiert.

Einfacher und erweiterter Repeater im Vergleich

Es gibt zwei Arten von extensions-interface-Implementierungen: Basic Extender und Advanced Extender. Der erweiterte Extender wird seit extensions-interface 1.2.0 unterstützt.

Implementieren Sie den Basic Extender für Erweiterungen, die Bilder in der HAL der Kamera verarbeiten, oder verwenden Sie einen Postprozessor, der YUV-Streams verarbeiten kann.

Implementieren Sie den erweiterten Extender für Erweiterungen, bei denen die Camera2-Streamkonfiguration angepasst und nach Bedarf Aufnahmeanfragen gesendet werden müssen.

In der folgenden Tabelle finden Sie einen Vergleich:

Einfacher Extender Erweiterter Extender
Streamkonfigurationen Gefixt
Vorschau: PRIVATE oder YUV_420_888 (falls Prozessor vorhanden)
Standbildaufnahme: JPEG oder YUV_420_888 (falls Prozessor vorhanden)
Von OEMs anpassbar.
Aufzeichnungsanfrage senden Nur Camera2/X kann Aufnahmeanfragen senden. Sie können die Parameter für diese Anfragen festlegen. Wenn der Prozessor für die Bildaufnahme bereitgestellt wird, kann Camera2/X mehrere Aufnahmeanfragen senden und alle Bilder und Aufnahmeergebnisse an den Prozessor senden. Sie erhalten eine RequestProcessorImpl-Instanz, um die camera2-Aufnahmeanfrage auszuführen und Ergebnisse und Bilder zu erhalten.

Camera2/X ruft startRepeating und startCapture auf SessionProcessorImpl auf, um dem OEM zu signalisieren, dass er die wiederholte Anfrage für die Vorschau bzw. die Sequenz für die Standbildaufnahme starten soll.

Hooks in der Kamerapipeline
  • onPresetSession stellt Sitzungsparameter bereit.
  • onEnableSession sendet direkt nach der Konfiguration von CameraCaptureSession eine einzelne Anfrage.
  • onDisableSession sendet eine einzelne Anfrage, bevor CameraCaptureSession geschlossen wird.
  • initSession initialisiert und gibt eine benutzerdefinierte camera2-Sitzungskonfiguration zum Erstellen der Aufnahmesitzung zurück.
  • onCaptureSessionStart wird direkt nach der Konfiguration von CameraCaptureSession aufgerufen.
  • onCaptureSessionEnd wird aufgerufen, bevor CameraCaptureSession geschlossen wird.
Geeignet für Erweiterungen, die in der HAL der Kamera oder in einem Prozessor implementiert sind, der YUV-Bilder verarbeitet.
  • Sie haben Camera2-basierte Implementierungen für die Erweiterungen.
  • Erfordert eine benutzerdefinierte Streamkonfiguration, z. B. einen RAW-Stream.
  • Interaktive Aufnahmesequenz erforderlich.
Unterstützte API-Version Camera2 Extensions: Android 13 oder höher
CameraX Extensions: camera-extensions 1.1.0 oder höher
Camera2 Extensions: Android 12L oder höher
CameraX Extensions: camera-extensions 1.2.0-alpha03 oder höher

App-Abläufe

In der folgenden Tabelle sind drei Arten von App-Abläufen und die zugehörigen Camera Extensions API-Aufrufe aufgeführt. Camera2/X stellen diese APIs bereit, aber Sie müssen die Anbieterbibliothek richtig implementieren, um diese Abläufe zu unterstützen. Wie das geht, wird in einem späteren Abschnitt ausführlicher beschrieben.

Camera2-Erweiterungen CameraX-Erweiterungen
Verfügbarkeit von Suchanfragenerweiterungen CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
Abfrageinformationen CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

CameraX verarbeitet die restlichen Informationen in der Bibliothek.

Vorschau und Standbilder mit aktivierter Erweiterung CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

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

Einfacher Extender

Die Basic Extender-Oberfläche bietet mehrere Anknüpfungspunkte in der Kamerapipeline. Für jeden Erweiterungstyp gibt es entsprechende Extender-Klassen, die OEMs implementieren müssen.

In der folgenden Tabelle sind die Extender-Klassen aufgeführt, die OEMs für jede Erweiterung implementieren müssen:

Zu implementierende Erweiterungsklassen
Nacht NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Automatisch AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Gesichtsretusche BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

Im folgenden Beispiel werden PreviewExtenderImpl und ImageCaptureExtenderImpl als Platzhalter verwendet. Ersetzen Sie diese durch die Namen der tatsächlichen Dateien, die Sie implementieren.

Der einfache Extender bietet folgende Funktionen:

  • Füge Sitzungsparameter ein, wenn du CameraCaptureSession (onPresetSession) konfigurierst.
  • Sie werden über die Ereignisse zum Starten und Schließen der Aufnahmesitzung benachrichtigt und es wird eine einzelne Anfrage gesendet, um die HAL mit den zurückgegebenen Parametern (onEnableSession, onDisableSession) zu benachrichtigen.
  • Fügen Sie Erfassungsparameter für die Anfrage ein (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Fügen Sie Prozessoren für die Vorschau und die Aufzeichnung hinzu, die den YUV_420_888-Stream verarbeiten können.

Sehen wir uns an, wie Camera2/X die extensions-interface aufruft, um die drei oben genannten App-Abläufe zu erreichen.

App-Ablauf 1: Verfügbarkeit der Erweiterung prüfen

BasicExtenderAppFlow1

Abbildung 3 App-Ablauf 1 auf Basis-Extender

In diesem Ablauf ruft Camera2/X die isExtensionAvailable()-Methode von PreviewExtenderImpl und ImageCaptureExtenderImpl direkt auf, ohne init() aufzurufen. Beide Extender-Klassen müssen true zurückgeben, um die Erweiterungen zu aktivieren.

Häufig ist dies der erste Schritt, bei dem Apps prüfen, ob der angegebene Erweiterungstyp für eine bestimmte Kamera-ID unterstützt wird, bevor die Erweiterung aktiviert wird. Das liegt daran, dass einige Erweiterungen nur für bestimmte Kamera-IDs unterstützt werden.

App-Ablauf 2: Informationen abfragen

BasicExtenderAppFlow2

Abbildung 4 App-Ablauf 2 auf einfachem Extender

Nachdem festgestellt wurde, ob die Erweiterung verfügbar ist, sollten Apps die folgenden Informationen abfragen, bevor sie die Erweiterung aktivieren.

  • Bereich der Latenz bei der Aufnahme von Standbildern:ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange gibt den Bereich der Aufnahmelatenz für die App zurück, um zu beurteilen, ob die Verlängerung für das aktuelle Szenario aktiviert werden soll.

  • Unterstützte Größen für die Vorschau- und Aufnahmefläche:Mit ImageCaptureExtenderImpl.getSupportedResolutions und PreviewExtenderImpl.getSupportedResolutions wird eine Liste der Bildformate und ‑größen zurückgegeben, die für das Oberflächenformat und die Oberflächengröße unterstützt werden.

  • Unterstützte Anfrage- und Ergebnisschlüssel:Camera2/X ruft die folgenden Methoden auf, um die unterstützten Schlüssel für Aufnahmeanfragen und Ergebnisschlüssel aus Ihrer Implementierung abzurufen:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Camera2/X ruft immer zuerst init() für diese Extender-Klassen auf, bevor weitere Informationen abgefragt werden.

App-Ablauf 3: Vorschau/Standbildaufnahme mit aktivierter Erweiterung (HAL-Implementierung)

BasicExtenderAppFlow3

Abbildung 5. App-Ablauf 3 auf einem einfachen Extender

Das obige Diagramm veranschaulicht den Hauptablauf zum Aktivieren der Vorschau und der Aufnahme von Standbildern mit einer Erweiterung ohne Prozessor. Das bedeutet, dass die Kamera-HAL die Erweiterung verarbeitet.

In diesem Ablauf ruft Camera2/X zuerst init() und dann onInit auf, wodurch Sie benachrichtigt werden, dass eine Kamerasitzung mit den angegebenen Erweiterungen gestartet wird. Die aufwendige Initialisierung können Sie in onInit() vornehmen.

Bei der Konfiguration von CameraCaptureSession ruft Camera2/X onPresetSession auf, um die Sitzungsparameter abzurufen. Nachdem die Aufnahmesitzung erfolgreich konfiguriert wurde, ruft Camera2/X onEnableSession auf und gibt eine CaptureStageImpl-Instanz zurück, die die Aufnahmeparameter enthält. Camera2/X sendet sofort eine einzelne Anfrage mit diesen Aufnahmeparametern, um den HAL zu benachrichtigen. Ähnlich wird vor dem Schließen der Aufnahmesitzung onDisableSession von Camera2/X aufgerufen und dann eine einzelne Anfrage mit den zurückgegebenen Aufnahmeparametern gesendet.

Die von Camera2/X ausgelöste wiederholte Anfrage enthält die von PreviewExtenderImpl.getCaptureStage() zurückgegebenen Anfrageparameter. Außerdem enthält die Anfrage zur Aufnahme von Standbildern die von ImageCaptureExtenderImpl.getCaptureStages() zurückgegebenen Parameter.

Schließlich ruft Camera2/X onDeInit() auf, nachdem die Kamerasitzung beendet ist. Sie können Ressourcen in onDeinit() freigeben.

Vorschauprozessor

Neben der HAL für die Kamera können Sie auch Erweiterungen in einem Prozessor implementieren.

Implementieren Sie PreviewExtenderImpl.getProcessorType, um den Prozessortyp anzugeben, wie unten beschrieben:

  • PROCESSOR_TYPE_NONE:Kein Prozessor. Bilder werden im HAL der Kamera verarbeitet.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY:Mit dem Prozessortyp können Sie die wiederkehrende Anfrage mit neuen Parametern für die Erfassungsanfrage basierend auf der neuesten TotalCaptureResult aktualisieren.

    PreviewExtenderImpl.getProcessor muss eine RequestUpdateProcessorImpl-Instanz zurückgeben, die die TotalCaptureResult-Instanz verarbeitet und eine CaptureStageImpl-Instanz zurückgibt, um die wiederkehrende Anfrage zu aktualisieren. PreviewExtenderImpl.getCaptureStage() sollte auch das Ergebnis der Verarbeitung widerspiegeln und den neuesten CaptureStageImpl zurückgeben.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR:Mit diesem Typ können Sie einen Prozessor implementieren, um YUV_420_888-Bilder zu verarbeiten und die Ausgabe auf eine PRIVATE-Oberfläche zu schreiben.

    Sie müssen eine PreviewImageProcessorImpl-Instanz in PreviewExtenderImpl.getProcessor implementieren und zurückgeben. Der Zahlungsabwickler ist für die Verarbeitung von YUV_420_888 Eingabebildern verantwortlich. Die Ausgabe sollte im PRIVATE-Format der Vorschau geschrieben werden. In Camera2/X wird anstelle von PRIVATE eine YUV_420_888-Oberfläche verwendet, um die CameraCaptureSession für die Vorschau zu konfigurieren.

    Der Ablauf ist in der folgenden Abbildung dargestellt:

PreviewProcessor

Abbildung 6 Ablauf der Vorschau mit PreviewImageProcessorImpl

Die PreviewImageProcessorImpl-Schnittstelle erweitert ProcessImpl und hat drei wichtige Methoden:

  • onOutputSurface(Surface surface, int imageFormat) legt die Ausgabeoberfläche für den Prozessor fest. Bei PreviewImageProcessorImpl ist imageFormat ein Pixelformat wie PixelFormat.RGBA_8888.

  • Mit onResolutionUpdate(Size size) wird die Größe des Eingabebilds festgelegt.

  • onImageFormatUpdate(int imageFormat) legt das Bildformat des Eingabebilds fest. Derzeit ist nur YUV_420_888 zulässig.

Bilderfassungsprozessor

Für die Standbildaufnahme können Sie einen Prozessor implementieren, indem Sie mit ImageCaptureExtenderImpl.getCaptureProcessor eine CaptureProcessorImpl-Instanz zurückgeben. Der Prozessor ist dafür verantwortlich, eine Liste der erfassten YUV_420_888-Bilder und TotalCaptureResult-Instanzen zu verarbeiten und die Ausgabe auf eine YUV_420_888-Oberfläche zu schreiben.

Sie können davon ausgehen, dass die Vorschau aktiviert und aktiv ist, bevor Sie die Anfrage für die Aufnahme eines Standbilds senden.

Siehe Diagramm unten:

CaptureProcessor

Abbildung 7. Ablauf weiterhin mit CaptureProcessorImpl erfassen

  1. Camera2/X verwendet eine Oberfläche im YUV_420_888-Format für die Aufnahme von Standbildern, um die Aufnahmesitzung zu konfigurieren. Camera2/X bereitet CaptureProcessorImpl durch Aufruf von

    • CaptureProcessorImpl.onImageFormatUpdate() mit YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() durch die Größe des Eingabebilds.
    • CaptureProcessorImpl.onOutputSurface() mit einer AusgabeYUV_420_888-Oberfläche.
  2. ImageCaptureExtenderImpl.getCaptureStages gibt eine Liste von CaptureStageImpl zurück, wobei jedes Element einer CaptureRequest-Instanz mit Aufnahmeparametern zugeordnet ist, die von Camera2/X gesendet werden. Wenn beispielsweise eine Liste mit drei CaptureStageImpl-Instanzen zurückgegeben wird, sendet Camera2/X drei Aufnahmeanfragen mit den entsprechenden Aufnahmeparametern über die captureBurst API.

  3. Die empfangenen Bilder und TotalCaptureResult-Instanzen werden zusammengefasst und zur Verarbeitung an CaptureProcessorImpl gesendet.

  4. CaptureProcessorImpl schreibt das Ergebnisbild (YUV_420_888-Format) in die vom onOutputSurface()-Aufruf angegebene Ausgabefläche. Camera2/X konvertiert sie bei Bedarf in JPEG-Bilder.

Schlüssel und Ergebnisse für die Erfassungsanfrage unterstützen

Neben der Kameravorschau und -aufnahme können Apps auch den Zoom, die Blitzparameter oder das Fokussieren per Tippen festlegen. Diese Parameter sind möglicherweise nicht mit Ihrer Erweiterungsimplementierung kompatibel.

Die folgenden Methoden wurden extensions-interface 1.3.0 hinzugefügt, damit Sie die von Ihrer Implementierung unterstützten Parameter freigeben können:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() gibt die von deiner Implementierung unterstützten Schlüssel für Erfassungsanfragen zurück.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() gibt die Schlüssel des Erfassungsergebnisses zurück, die im Erfassungsergebnis enthalten sind.

Wenn die Kamera-HAL die Erweiterung verarbeitet, ruft Camera2/X die Aufnahmeergebnisse in CameraCaptureSession.CaptureCallback ab. Wenn der Prozessor jedoch implementiert ist, ruft Camera2/X die Aufnahmeergebnisse in ProcessResultImpl ab, die an die process()-Methode in PreviewImageProcessorImpl und CaptureProcessorImpl übergeben werden. Sie sind dafür verantwortlich, das Aufnahmeergebnis über ProcessResultImpl an Camera2/X zu melden.

Unten findest du ein Beispiel für die Definition der CaptureProcessorImpl-Benutzeroberfläche. In extensions-interface 1.3.0 oder höher wird der zweite process()-Aufruf aufgerufen:

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

Für gängige Kamerafunktionen wie Zoom, Fokussieren durch Tippen, Blitz und Belichtungskorrektur empfehlen wir, sowohl für die Aufnahmeanfrage als auch für das Aufnahmeergebnis die folgenden Tasten zu unterstützen:

  • Zoom:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Zum Fokussieren tippen:
    • 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
  • Belichtungskorrektur:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

Für grundlegende Extender, die Version 1.2.0 oder älter implementieren, werden alle oben genannten Schlüssel ausdrücklich von der CameraX Extensions API unterstützt. Bei extensions-interface 1.3.0 werden sowohl von CameraX als auch von Camera2 die zurückgegebenen Listen berücksichtigt und nur die darin enthaltenen Schlüssel unterstützt. Wenn Sie beispielsweise in der Implementierung von Version 1.3.0 nur CaptureRequest#CONTROL_ZOOM_RATIO und CaptureRequest#SCALER_CROP_REGION zurückgeben, bedeutet das, dass nur der Zoom für die App unterstützt wird, während das Fokussieren durch Tippen, der Blitz und die Belichtungskorrektur nicht zulässig sind.

Erweiterter Extender

„Advanced Extender“ ist eine Art Anbieterimplementierung, die auf der Camera2 API basiert. Dieser Extendertyp wurde in extensions-interface 1.2.0 hinzugefügt. Je nach Gerätehersteller werden Erweiterungen möglicherweise in der App-Ebene implementiert. Das hängt von den folgenden Faktoren ab:

  • Benutzerdefinierte Streamkonfiguration:Sie können benutzerdefinierte Streams wie einen RAW-Stream konfigurieren oder mehrere Streams für verschiedene physische Kamera-IDs verwenden.

  • Möglichkeit zum Senden von Camera2-Anfragen:Unterstützt eine komplizierte Interaktionslogik, mit der Aufnahmeanfragen mit Parametern gesendet werden können, die auf den Ergebnissen vorheriger Anfragen basieren.

Der erweiterte Extender bietet einen Wrapper oder eine Zwischenschicht, mit der du die Streamkonfiguration anpassen und Aufzeichnungsanfragen bei Bedarf senden kannst.

Zu implementierende Dateien

Wenn du zur erweiterten Implementierung des Extenders wechseln möchtest, muss die isAdvancedExtenderImplemented()-Methode in ExtensionVersionImpl true zurückgeben. Für jeden Erweiterungstyp müssen OEMs die entsprechenden Extender-Klassen implementieren. Die Implementierungsdateien für den erweiterten Extender befinden sich im Paket advanced.

Zu implementierende Extender-Klassen
Nacht advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Automatisch advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Gesichtsretusche advanced/BeautyAdvancedExtenderImpl.java

Im folgenden Beispiel verwenden wir AdvancedExtenderImpl als Platzhalter. Ersetzen Sie ihn durch den Namen der Extender-Datei für die implementierte Erweiterung.

Sehen wir uns an, wie Camera2/X die extensions-interface aufruft, um die drei App-Abläufe zu erreichen.

App-Ablauf 1: Verfügbarkeit von Erweiterungen prüfen

AdvancedAppFlow1

Abbildung 8. App-Ablauf 1 auf erweitertem Extender

Zuerst wird geprüft, ob die angegebene Erweiterung unterstützt wird.

App-Ablauf 2: Informationen abfragen

AdvancedAppFlow2

Abbildung 9. App-Ablauf 2 auf erweitertem Extender

Nach dem Aufruf von AdvancedExtenderImpl.init() kann die App die folgenden Informationen zu AdvancedExtenderImpl abfragen:

  • Geschätzte Latenz bei der Aufnahme von Standbildern:AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() gibt den Bereich der Aufnahmelatenz für die App zurück, um zu beurteilen, ob die Erweiterung für das aktuelle Szenario aktiviert werden sollte.

  • Unterstützte Auflösungen für die Vorschau und die Aufnahme von Standbildern:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() gibt eine Zuordnung des Bildformats zu der Liste der Größen zurück, die für das Format und die Größe der Vorschaufläche unterstützt werden. OEMs müssen mindestens das PRIVATE-Format unterstützen.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() gibt das unterstützte Format und die unterstützten Größen für die Oberfläche für die Standbildaufnahme zurück. OEMs müssen sowohl die Ausgabe im JPEG- als auch im YUV_420_888-Format unterstützen.

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() gibt die unterstützten Größen für einen zusätzlichen YUV_420_888-Stream für die Bildanalyse zurück. Wenn die YUV-Oberfläche für die Bildanalyse nicht unterstützt wird, sollte getSupportedYuvAnalysisResolutions() null oder eine leere Liste zurückgeben.

  • Verfügbare Schlüssel/Ergebnisse für Aufnahmeanfragen (in extensions-interface 1.3.0 hinzugefügt): Camera2/X ruft die folgenden Methoden auf, um die unterstützten Schlüssel für Aufnahmeanfragen und Ergebnisschlüssel aus Ihrer Implementierung abzurufen:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Weitere Informationen finden Sie unter Unterstützung für Anfrageschlüssel und Ergebnisse für die Erfassung.

App-Vorgang 3: Vorschau/Standbildaufnahme mit aktivierter Erweiterung

AdvancedAppFlow3

Abbildung 10. App-Ablauf 3 auf erweitertem Extender

Das obige Diagramm zeigt den Hauptablauf zum Starten der Vorschau und zum Aufnehmen von Standbildern für den erweiterten Extender. Sehen wir uns die einzelnen Schritte an.

  1. SessionProcessorImpl-Instanz

    Die Hauptimplementierung des erweiterten Extenders befindet sich in SessionProcessorImpl. Dieser ist für die Bereitstellung einer benutzerdefinierten Sitzungskonfiguration und das Senden von Erfassungsanfragen zur Initiierung der Vorschau und der Still-Aufnahme verantwortlich. AdvancedExtenderImpl.createSessionProcessor() wird aufgerufen, um die SessionProcessorImpl-Instanz zurückzugeben.

  2. initSession

    SessionProcessorImpl.initSession() initialisiert die Sitzung für die Erweiterung. Hier weisen Sie Ressourcen zu und geben eine Sitzungskonfiguration für die Vorbereitung einer CameraCaptureSession zurück.

    Für die Eingabeparameter gibt Camera2/X die Ausgabeoberflächenkonfigurationen für die Vorschau, die Standbildaufnahme und eine optionale YUV-Bildanalyse an. Diese Ausgabeoberflächenkonfiguration (OutputSurfaceImpl) enthält die Oberfläche, Größe und das Bildformat, die in AdvancedExtenderImpl mit den folgenden Methoden abgerufen werden:

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

    Du musst eine Camera2SessionConfigImpl-Instanz zurückgeben, die aus einer Liste von Camera2OutputConfigImpl-Instanzen und den Sitzungsparametern besteht, die zum Konfigurieren von CameraCaptureSession verwendet werden. Sie sind dafür verantwortlich, die richtigen Kamerabilder auf den von Camera2/X übergebenen Ausgabeoberflächen auszugeben. So aktivieren Sie die Ausgabe:

    • Verarbeitung in der Kamera-HAL:Sie können die Ausgabeoberflächen mit einer SurfaceOutputConfigImpl-Implementierung direkt zu CameraCaptureSession hinzufügen. Dadurch wird die bereitgestellte Ausgabeoberfläche für die Kamerapipeline konfiguriert und die HAL der Kamera kann das Bild verarbeiten.
    • Zwischenfläche ImageReader verarbeiten (RAW, YUV usw.): Füge die Zwischenflächen ImageReader mit einer ImageReaderOutputConfigImpl-Instanz dem CameraCaptureSession hinzu.

      Sie müssen die Zwischenbilder verarbeiten und das Ergebnisbild auf die Ausgabefläche schreiben.

    • Camera2-Oberflächenfreigabe verwenden:Wenn Sie die Oberflächenfreigabe mit einer anderen Oberfläche verwenden möchten, fügen Sie der getSurfaceSharingOutputConfigs()-Methode einer anderen Camera2OutputConfigImpl-Instanz eine beliebige Camera2OutputConfigImpl-Instanz hinzu. Format und Größe der Oberfläche müssen identisch sein.

    Alle Camera2OutputConfigImpl, einschließlich SurfaceOutputConfigImpl und ImageReaderOutputConfigImpl, müssen eine eindeutige ID (getId()) haben, mit der die Zielfläche angegeben und das Bild aus ImageReaderOutputConfigImpl abgerufen wird.

  3. onCaptureSessionStart und RequestProcessorImpl

    Wenn CameraCaptureSession gestartet wird und das Kamera-Framework onConfigured() aufruft, ruft Camera2/X SessionProcessorImpl.onCaptureSessionStart() mit dem Camera2-Anfrage-Wrapper RequestProcessImpl auf. Camera2/X implementiert RequestProcessImpl, mit dem Sie Aufnahmeanfragen ausführen und Bilder abrufen können, wenn ImageReaderOutputConfigImpl verwendet wird.

    Die RequestProcessImpl APIs ähneln den Camera2 CameraCaptureSession APIs bei der Ausführung von Anfragen. Die Unterschiede sind:

    • Die Zieloberfläche wird durch die ID der Camera2OutputConfigImpl-Instanz angegeben.
    • Die Möglichkeit, das Bild der ImageReader abzurufen.

    Sie können RequestProcessorImpl.setImageProcessor() mit einer bestimmten Camera2OutputConfigImpl-ID aufrufen, um eine ImageProcessorImpl-Instanz für den Empfang von Bildern zu registrieren.

    Die RequestProcessImpl-Instanz wird ungültig, nachdem Camera2/X SessionProcessorImpl.onCaptureSessionEnd() aufgerufen hat.

  4. Vorschau starten und ein Foto aufnehmen

    Bei der erweiterten Extender-Implementierung kannst du Aufnahmeanfragen über die RequestProcessorImpl-Oberfläche senden. Camera2/X benachrichtigt Sie, dass Sie die wiederholte Anfrage für die Vorschau oder die Sequenz für die Standbildaufnahme starten können, indem Sie jeweils SessionProcessorImpl#startRepeating und SessionProcessorImpl#startCapture aufrufen. Sie sollten Aufnahmeanfragen senden, um diese Vorschau- und Standbildanfragen zu erfüllen.

    Camera2/X setzt auch die Parameter der Aufnahmeanfrage über SessionProcessorImpl#setParameters. Sie müssen diese Anfrageparameter (sofern unterstützt) sowohl für wiederkehrende als auch für einzelne Anfragen festlegen.

    Sie müssen mindestens CaptureRequest.JPEG_ORIENTATION und CaptureRequest.JPEG_QUALITY unterstützen. extensions-interface 1.3.0 unterstützt Anfrage- und Ergebnisschlüssel, die über die folgenden Methoden freigegeben werden:

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

    Wenn Entwickler die Schlüssel in der Liste getAvailableCaptureRequestKeys festlegen, müssen Sie die Parameter aktivieren und dafür sorgen, dass das Erfassungsergebnis die Schlüssel in der Liste getAvailableCaptureResultKeys enthält.

  5. startTrigger

    SessionProcessorImpl.startTrigger() wird aufgerufen, um den Trigger zu starten, z. B. CaptureRequest.CONTROL_AF_TRIGGER und CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Schlüssel für Erfassungsanfragen, die nicht in AdvancedExtenderImpl.getAvailableCaptureRequestKeys() beworben wurden, können Sie ignorieren.

    startTrigger() wird seit extensions-interface 1.3.0 unterstützt. Sie ermöglicht es Apps, die Funktion „Auf das Display tippen, um den Fokus zu setzen“ und das Blitzen mit Erweiterungen zu implementieren.

  6. Aufräumen

    Wenn eine Aufnahmesitzung beendet wird, wird SessionProcessorImpl.onCaptureSessionEnd() aufgerufen, bevor CameraCaptureSession geschlossen wird. Nach dem Schließen der Aufnahmesitzung führt deInitSession() die Bereinigung durch.

Unterstützung von Vorschau, Standbildern und Bildanalyse

Sie sollten die Erweiterung sowohl für die Vorschau als auch für die Erfassung von Anwendungsfällen anwenden. Wenn die Latenz jedoch zu hoch ist, um die Vorschau flüssig anzuzeigen, können Sie die Verlängerung nur für die Aufnahme von Standbildern anwenden.

Für den Typ „Basic Extender“ müssen Sie unabhängig davon, ob Sie die Erweiterung für die Vorschau aktivieren, sowohl ImageCaptureExtenderImpl als auch PreviewExtenderImpl für eine bestimmte Erweiterung implementieren. Häufig verwendet eine App auch einen YUV-Stream, um den Bildinhalt zu analysieren, z. B. um QR-Codes oder Text zu finden. Um diesen Anwendungsfall besser zu unterstützen, sollten Sie die Streamkombination aus Vorschau, Standbildaufnahme und einem YUV_420_888-Stream zur Konfiguration von CameraCaptureSession unterstützen. Wenn du also einen Prozessor implementierst, musst du die Streamkombination aus drei YUV_420_888-Streams unterstützen.

Bei Advanced Extender gibt Camera2/X drei Ausgabeoberflächen an den SessionProcessorImpl.initSession()-Aufruf weiter. Diese Ausgabeoberflächen dienen jeweils der Vorschau, der Aufnahme von Standbildern und der Bildanalyse. Sie müssen dafür sorgen, dass in der Vorschau und in den Ausgabeoberflächen für Standbilder die gültige Ausgabe zu sehen ist. Achten Sie jedoch darauf, dass die Ausgabefläche für die Bildanalyse nur funktioniert, wenn der Wert nicht null ist. Wenn Ihre Implementierung den Stream für die Bildanalyse nicht unterstützt, können Sie in AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() eine leere Liste zurückgeben. So wird sichergestellt, dass die Ausgabeoberfläche der Bildanalyse in SessionProcessorImpl.initSession() immer null ist.

Videoaufnahme unterstützen

Die aktuelle Architektur der Kameraerweiterung unterstützt nur die Vorschau und die Aufnahme von Standbildern. Die Aktivierung der Erweiterung auf den Oberflächen MediaCodec oder MediaRecorder für die Videoaufzeichnung wird nicht unterstützt. Es ist jedoch möglich, dass Apps die Vorschauausgabe aufzeichnen.

Die Unterstützung von MediaCodec- und MediaRecorder-Oberflächen wird geprüft.

Erweiterungsspezifische Metadaten

Unter Android 14 und höher können Kamera-Erweiterungs-Clients mithilfe von erweiterungsspezifischen Metadaten Einstellungen und Ergebnisse für erweiterungsspezifische Aufnahmeanfragen festlegen und empfangen. Insbesondere können Kameraerweiterungs-Clients den Parameter EXTENSION_STRENGTH der Aufnahmeanfrage verwenden, um die Stärke der Erweiterung zu steuern, und das Aufnahmeergebnis EXTENSION_CURRENT_TYPE, um den aktivierten Erweiterungstyp anzugeben.

Anfragen erfassen

Mit dem Parameter für die Aufnahmeanfrage EXTENSION_STRENGTH wird die Stärke des Effekts der Nachverarbeitung der Erweiterung gesteuert. Das entsprechende Erfassungsergebnis enthält den Standardwert für die Stärke, wenn dieser Parameter nicht explizit vom Client festgelegt wird. Dieser Parameter kann für die folgenden Erweiterungstypen so angewendet werden:

  • BOKEH: Damit wird die Unschärfe gesteuert.
  • HDR und NIGHT: Damit wird die Anzahl der zusammengeführten Bilder und die Helligkeit des Endbilds gesteuert.
  • FACE_RETOUCH: Damit wird die Intensität der kosmetischen Verbesserung und Hautglättung gesteuert.

Der unterstützte Bereich für den Parameter EXTENSION_STRENGTH liegt zwischen 0 und 100. 0 steht für keine Erweiterungsverarbeitung oder einfache Weiterleitung und 100 für die maximale Erweiterungsstärke des Verarbeitungseffekts.

Wenn Sie EXTENSION_STRENGTH unterstützen möchten, verwenden Sie die anbieterspezifischen Parameter-APIs, die in Version 1.3.0 der Erweiterungsbibliotheksoberfläche eingeführt wurden. Weitere Informationen finden Sie unter getAvailableCaptureRequestKeys().

Ergebnisse erfassen

Mit dem Erfassungsergebnis EXTENSION_CURRENT_TYPE können Erweiterungsimplementierungen Clients über den aktiven Erweiterungstyp informieren.

Da Erweiterungen vom Typ AUTO je nach den Aufnahmebedingungen dynamisch zwischen Erweiterungstypen wie HDR und NIGHT wechseln, können Kamera-Erweiterungs-Apps EXTENSION_CURRENT_TYPE verwenden, um Informationen zur aktuellen Erweiterung anzuzeigen, die von der AUTO-Erweiterung ausgewählt wurde.

Schätzung der Latenz bei der Aufnahme von Standbildern in Echtzeit

Unter Android 14 und höher können Kameraerweiterungs-Clients mithilfe von getRealtimeStillCaptureLatency() Echtzeit-Schätzungen der Latenz für die Aufnahme von Standbildern basierend auf den Szenen- und Umgebungsbedingungen abfragen. Diese Methode liefert genauere Schätzungen als die statische Methode getEstimatedCaptureLatencyRangeMillis(). Basierend auf der geschätzten Latenz können Apps entscheiden, die Erweiterungsverarbeitung zu überspringen oder eine Anzeige zu schalten, um Nutzer über einen langwierigen Vorgang zu informieren.

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

Um Echtzeit-Schätzungen für die Latenz bei der Aufnahme von Standbildern zu unterstützen, implementieren Sie Folgendes:

Callbacks für den Verarbeitungsfortschritt erfassen

Unter Android 14 und höher können Clients der Kameraerweiterung Rückrufe zum Fortschritt lang laufender Verarbeitungsvorgänge für Standbilder erhalten. Apps können Nutzern den aktuellen Fortschritt anzeigen, um die Nutzerfreundlichkeit insgesamt zu verbessern.

Apps können diese Funktion mit dem folgenden Code einbinden:

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

Um Rückrufe zum Fortschritt der Aufnahmeverarbeitung zu unterstützen, muss die Implementierung Ihres Erweiterungsanbieters die folgenden Rückrufe mit dem aktuellen Fortschrittswert aufrufen:

Standbild bei Post-View-Interaktionen

Unter Android 14 und höher können Kameraerweiterungen eine Postview (Vorschaubild) mit setPostviewOutputConfiguration bereitstellen. Um die Nutzerfreundlichkeit zu verbessern, können Apps ein Postview-Bild als Platzhalter anzeigen, wenn bei einer Erweiterung eine längere Verarbeitungslatenz auftritt, und das Bild ersetzen, sobald das endgültige Bild verfügbar ist. Mit dem folgenden Referenzcode können Sie in Apps Postview-Aufzeichnungsanfragen konfigurieren und senden:

{
…
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();
…
}

Damit die Aufzeichnung von Standbildern nach der Wiedergabe unterstützt wird, muss Ihre Anbieterimplementierung Folgendes umfassen:

SurfaceView-Ausgabe unterstützen

Unter Android 14 und höher können Kameraerweiterungs-Clients energie- und leistungsoptimierte Vorschau-Renderpfade verwenden, indem sie eine SurfaceView-Instanz für die Vorschauausgabe für wiederholte Anfragen registrieren.

Damit SurfaceView-Ausgabe unterstützt wird, muss die Implementierung der Anbietererweiterung in der Lage sein, eine Vorschau an SurfaceView-Instanzen zu streamen und auszugeben. Führen Sie das SurfaceViewExtensionPreviewTest.java-CTS-Modul aus, um zu prüfen, ob dies unterstützt wird.

Anbieterspezifische Sitzungstypen

Mit dieser Funktion können bei der Implementierung von Anbietererweiterungen ein Anbieterspezifischer Sitzungstyp ausgewählt werden, der anstelle des Standardwerts in der internen Kameraaufnahmesitzung festgelegt wird.

Die Funktion funktioniert vollständig innerhalb des Frameworks und des Anbieter-Stacks und hat keine Auswirkungen auf die client-/öffentlich sichtbare API.

Wenn Sie einen anbieterspezifischen Sitzungstyp auswählen möchten, implementieren Sie Folgendes für Ihre Erweiterungsbibliotheken: * ExtenderStateListener.onSessionType() für grundlegende Erweiterungen * Camera2SessionConfigImpl.getSessionType() für erweiterte Erweiterungen

Versionsverlauf der Erweiterungsoberfläche

In der folgenden Tabelle finden Sie die Versionsgeschichte der Kameraerweiterungsoberfläche. Sie sollten die Anbieterbibliothek immer mit der neuesten Version implementieren.

Version Hinzugefügte Funktionen
1.0.0
  • Versionsüberprüfung
    • ExtensionVersionImpl
  • Einfacher Repeater
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Mediathek initialisieren
    • InitializerImpl
  • Unterstützte Auflösungen freigeben
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Geschätzte Erfassungslatenz abrufen
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Unterstützte Schlüssel für Erfassungsanfragen/Ergebnisschlüssel freigeben
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys und getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys und getAvailableCaptureResultKeys
    • Neuer process()-Aufruf, der ProcessResultImpl in PreviewImageProcessorImpl und CaptureProcessorImpl berücksichtigt
    • Supportanfrage zum Triggertyp
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Erweiterungsspezifische Metadaten
  • Schätzungen der Latenz bei der Aufnahme von dynamischen Standbildern
  • Callbacks für den Verarbeitungsfortschritt erfassen
  • Standbild bei Post-View-Interaktionen
  • Unterstützung für SurfaceView-Ausgabe
  • Anbieterspezifische Sitzungstypen

Referenzimplementierung

Die folgenden Referenzimplementierungen von OEM-Bibliotheken sind in frameworks/ex verfügbar.

  • advancedSample: Eine grundlegende Implementierung von Advanced Extender.

  • sample: Eine einfache Implementierung des Basic Extenders.

  • service_based_sample: Eine Implementierung, die zeigt, wie Kameraerweiterungen in einer Service gehostet werden. Diese Implementierung enthält die folgenden Komponenten:

    • oem_library: OEM-Bibliothek für Kameraerweiterungen für die Camera2 und CameraX Extensions APIs, die Extensions-Interface implementiert. Dies dient als Passthrough, über das Aufrufe von Extensions-Interface an den Dienst weitergeleitet werden. Diese Bibliothek bietet außerdem AIDL-Dateien und Wrapper-Klassen für die Kommunikation mit dem Dienst.

      Der erweiterte Extender ist standardmäßig aktiviert. Wenn Sie den einfachen Extender aktivieren möchten, ändern Sie ExtensionsVersionImpl#isAdvancedExtenderImplemented in false zurück.

    • extensions_service: Eine Beispielimplementierung des Erweiterungsdiensts. Fügen Sie Ihre Implementierung hier hinzu. Die im Dienst zu implementierende Schnittstelle ähnelt der Extensions-Interface. Wenn Sie beispielsweise IAdvancedExtenderImpl.Stub implementieren, werden dieselben Vorgänge wie bei AdvancedExtenderImpl ausgeführt. ImageWrapper und TotalCaptureResultWrapper sind erforderlich, damit Image und TotalCaptureResult parzelliert werden können.

Anbieterbibliothek auf einem Gerät einrichten

Die OEM-Anbieterbibliothek ist nicht in eine App eingebunden, sondern wird von Camera2/X zur Laufzeit vom Gerät geladen. In CameraX wird mit dem <uses-library>-Tag angegeben, dass die androidx.camera.extensions.impl-Bibliothek, die in der Datei AndroidManifest.xml der camera-extensions-Bibliothek definiert ist, eine Abhängigkeit von CameraX ist und zur Laufzeit geladen werden muss. In Camera2 lädt das Framework einen Erweiterungsdienst, der auch angibt, dass die <uses-library>zur Laufzeit dieselbe androidx.camera.extensions.impl-Bibliothek lädt.

So können Drittanbieter-Apps, die Erweiterungen verwenden, die OEM-Bibliothek automatisch laden. Die OEM-Bibliothek ist als optional gekennzeichnet, damit Apps auch auf Geräten ausgeführt werden können, auf denen die Bibliothek nicht installiert ist. Camera2/X verarbeitet dieses Verhalten automatisch, wenn eine App versucht, eine Kameraerweiterung zu verwenden, sofern der Gerätehersteller die OEM-Bibliothek auf dem Gerät platziert, damit sie von der App gefunden werden kann.

So richten Sie die OEM-Bibliothek auf einem Gerät ein:

  1. Füge eine Berechtigungsdatei hinzu, die für das <uses-library>-Tag erforderlich ist. Sie muss das folgende Format haben: /etc/permissions/ANY_FILENAME.xml. Beispiel: /etc/permissions/camera_extensions.xml. Die Dateien in diesem Verzeichnis stellen eine Zuordnung der in <uses-library> genannten Bibliothek zum tatsächlichen Dateipfad auf dem Gerät bereit.
  2. Verwenden Sie das folgende Beispiel, um der Datei die erforderlichen Informationen hinzuzufügen.

    • name muss androidx.camera.extensions.impl sein, da dies die Bibliothek ist, nach der CameraX sucht.
    • file ist der absolute Pfad der Datei, die die Erweiterungsimplementierung enthält (z. B. /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>
    

Unter Android 12 oder höher muss die Eigenschaft ro.camerax.extensions.enabled auf true festgelegt sein, damit Geräte, die CameraX-Erweiterungen unterstützen, abgefragt werden können. Fügen Sie dazu die folgende Zeile in die Datei „device make“ ein:

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

Zertifizierungsstufe

Wenn Sie die Implementierung der OEM-Anbieterbibliothek während der Entwicklungsphase testen möchten, verwenden Sie die Beispiel-App unter androidx-main/camera/integration-tests/extensionstestapp/, die verschiedene Anbietererweiterungen durchläuft.

Führen Sie nach Abschluss der Implementierung mit dem Validierungstool für Kameraerweiterungen automatisierte und manuelle Tests durch, um zu prüfen, ob die Anbieterbibliothek richtig implementiert ist.

Erweiterter Szenenmodus im Vergleich zu Kameraerweiterungen

Sie können die Bokeh-Erweiterung nicht nur mithilfe von Kameraerweiterungen belichten, sondern auch mit dem erweiterten Szenenmodus, der über die Taste CONTROL_EXTENDED_SCENE_MODE aktiviert wird. Weitere Informationen zur Implementierung finden Sie unter Kamera-Bokeh.

Der erweiterte Szenenmodus hat weniger Einschränkungen als Kameraerweiterungen für camera2-Apps. Sie können den erweiterten Szenenmodus beispielsweise in einer regulären CameraCaptureSession-Instanz aktivieren, die flexible Streamkombinationen und Aufnahmeanfrageparameter unterstützt. Kameraerweiterungen unterstützen dagegen nur eine feste Anzahl von Streamtypen und nur eingeschränkt die Parameter für Aufnahmeanfragen.

Ein Nachteil des erweiterten Szenenmodus ist, dass er nur in der Kamera-HAL implementiert werden kann. Das bedeutet, dass überprüft werden muss, ob er für alle orthogonalen Steuerelemente funktioniert, die App-Entwicklern zur Verfügung stehen.

Wir empfehlen, Bokeh sowohl mit dem erweiterten Szenenmodus als auch mit Kameraerweiterungen zu belichten, da Apps möglicherweise eine bestimmte API verwenden, um Bokeh zu aktivieren. Wir empfehlen, zuerst den erweiterten Szenenmodus zu verwenden, da dies die flexibelste Möglichkeit für Apps ist, die Bokeh-Erweiterung zu aktivieren. Anschließend können Sie die Benutzeroberfläche für Kameraerweiterungen basierend auf dem erweiterten Szenenmodus implementieren. Wenn die Implementierung von Bokeh in der Kamera-HAL schwierig ist, z. B. weil für die Verarbeitung von Bildern ein Nachbearbeiter in der App-Ebene erforderlich ist, empfehlen wir, die Bokeh-Erweiterung über die Kamera-Erweiterungen-Schnittstelle zu implementieren.

Häufig gestellte Fragen

Gibt es Einschränkungen für API-Ebenen?

Ja. Das hängt von den Android API-Funktionen ab, die für die Implementierung der OEM-Anbieterbibliothek erforderlich sind. In ExtenderStateListener.onPresetSession() wird beispielsweise der Aufruf SessionConfiguration.setSessionParameters() verwendet, um einen Basissatz von Tags festzulegen. Dieser Aufruf ist nur auf API-Level 28 und höher verfügbar. Weitere Informationen zu bestimmten Methoden der Benutzeroberfläche finden Sie in der API-Referenzdokumentation.