Kameraerweiterungen

Gerätehersteller können Erweiterungen wie Bokeh, Nachtmodus und HDR über die von der OEM-Anbieterbibliothek bereitgestellte Camera Extensions-Schnittstelle für Drittanbieter-Entwickler verfügbar machen. Entwickler können über die Camera2 Extensions API und die CameraX Extensions API auf die in der OEM-Anbieterbibliothek implementierten Erweiterungen zugreifen.

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 in der Problemverfolgung.

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

Architektur

Das folgende Diagramm beschreibt die Architektur der Camera Extensions-Schnittstelle oder extensions-interface: Architektur

Abbildung 1: Architekturdiagramm für Kamera-Erweiterungen

Wie im Diagramm dargestellt, müssen Sie zur Unterstützung von Kameraerweiterungen die extensions-interface implementieren, die von der OEM-Anbieterbibliothek bereitgestellt werden. Die OEM-Anbieterbibliothek ermöglicht zwei APIs: die CameraX Extensions API und die Camera2 Extensions API. Diese werden von CameraX- bzw. 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 Systembibliotheks-Projekt. Diese Dateien definieren die Camera Extensions-Schnittstelle.

Die camera-extensions-stub-Dateien sind in folgende Kategorien unterteilt:

Wichtige Schnittstellendateien (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 die Bokeh-Erweiterung unterstützt wird)

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

Klassen für die Nachtverlängerung (implementieren, wenn die Nachtverlängerung 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-Erweiterungsklassen (implementieren, wenn die HDR-Erweiterung unterstützt wird)

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

Erweiterungsklassen für die Gesichtsretusche (implementieren, wenn die Erweiterung „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 vornehmen. Wenn Sie keine Erweiterung implementieren, legen Sie isExtensionAvailable() so fest, dass false zurückgegeben wird, oder entfernen Sie die entsprechenden Extender-Klassen. Die Camera2- und CameraX-Erweiterungs-APIs melden der App, dass die Erweiterung nicht verfügbar ist.

Sehen wir uns an, wie die Camera2- und CameraX Extensions APIs mit der Anbieterbibliothek interagieren, um eine Erweiterung zu ermöglichen. Das folgende Diagramm veranschaulicht den End-to-End-Ablauf am Beispiel der Erweiterung „Nacht“:

Mainflow

Abbildung 2: Implementierung der Nachtfunktion

  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(), mit der die Anbieterbibliothek initialisiert wird. Camera2/X schließt die Initialisierung ab, bevor auf die Extender-Klassen zugegriffen wird.

  3. Extender-Klassen instanziieren:

    Instanziiert die Extender-Klassen für die Erweiterung. Es gibt zwei Arten von Extendern: Basic Extender und Advanced Extender. Sie müssen einen Extender-Typ für alle Erweiterungen implementieren. Weitere Informationen finden Sie unter Basic Extender im Vergleich zu Advanced Extender.

    Camera2/X instanziiert die Extender-Klassen und interagiert mit ihnen, um Informationen abzurufen und die Erweiterung zu aktivieren. Bei einer bestimmten Erweiterung kann Camera2/X die Extender-Klassen mehrmals instanziieren. Führen Sie daher keine rechenintensiven Initialisierungen im Konstruktor oder im init()-Aufruf durch. Führe die rechenintensiven Aufgaben erst aus, wenn die Kamerasitzung gestartet wird, z. B. wenn onInit() im Basic Extender oder initSession() im Advanced Extender aufgerufen wird.

    Für die Night-Erweiterung werden die folgenden Extender-Klassen für den Basic Extender-Typ instanziiert:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    Für den Advanced Extender-Typ:

    • NightAdvancedExtenderImpl.java
  4. Verfügbarkeit von Erweiterungen prüfen:

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

  5. Extender mit Kamerainformationen initialisieren:

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

  6. Informationen zur Anfrage:

    Ruft die Extender-Klasse auf, um Informationen wie unterstützte Auflösungen und die geschätzte Latenz abzurufen und Anforderungsschlü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, um die OEM-Implementierung in die Camera2-Pipeline einzubinden, z. B. durch Einfügen von Parametern für Aufnahmeanfragen 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() für den Extender aufgerufen wird.

In den folgenden Abschnitten wird der Ablauf der Erweiterung genauer 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. Für die extensions-interface wird die semantische Versionierung verwendet, z. B. MAJOR.MINOR.PATCH, also 1.1.0 oder 1.2.0. Bei der Versionsüberprüfung werden jedoch nur die Haupt- und Nebenversion verwendet.

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

Kompatibilität mit Hauptversionen

Wenn sich die Hauptversionen der extension-interface zwischen Camera2/X und der Anbieterbibliothek unterscheiden, gilt die Erweiterung als inkompatibel und wird deaktiviert.

Abwärtskompatibilität

Solange die Hauptversion identisch ist, sorgt Camera2/X für Abwärtskompatibilität mit OEM-Anbieterbibliotheken, 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 Camera2/X nach der Implementierung einer bestimmten Version der Anbieterbibliothek dafür sorgt, dass die Bibliothek mit zukünftigen extension-interface-Versionen abwärtskompatibel ist.

Vorwärtskompatibilität

Die Vorwärtskompatibilität mit Anbieterbibliotheken neuerer extensions-interface hängt von Ihnen als OEM ab. Wenn Sie bestimmte 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.

Anbieterbibliothek initialisieren

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

Camera2/X führt keine anderen Aufrufe an die OEM-Bibliothek aus (abgesehen von der Versionsprüfung), bis die OEM-Anbieterbibliothek OnExtensionsInitializedCallback.onSuccess() aufruft, um den Abschluss der Initialisierung zu melden.

Sie müssen InitializerImpl ab extensions-interface 1.1.0 implementieren. Bei Camera2/X wird der Schritt zur Initialisierung der Bibliothek übersprungen, wenn die OEM-Anbieterbibliothek extensions-interface 1.0.0 implementiert.

Basic Extender im Vergleich zu Advanced Extender

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

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

Implementieren Sie „Advanced Extender“ für Erweiterungen, die die Camera2-Streamkonfiguration anpassen und bei Bedarf Aufnahmeanfragen senden müssen.

Die folgende Tabelle zeigt einen Vergleich:

Basic Extender Erweiterter Extender
Streamkonfigurationen Fest
Vorschau: PRIVATE oder YUV_420_888 (falls Prozessor vorhanden)
Standbild: JPEG oder YUV_420_888 (falls Prozessor vorhanden)
Kann vom OEM angepasst werden.
Aufnahmeanfrage wird gesendet 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. Eine RequestProcessorImpl-Instanz wird Ihnen zur Verfügung gestellt, um die camera2-Aufnahmeanfrage auszuführen und Ergebnisse und ein Bild 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 und die Aufnahme von Standbildern 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 Kamera-HAL oder in einem Prozessor implementiert sind, der YUV-Bilder verarbeitet.
  • Hat Camera2-basierte Implementierungen für die Erweiterungen.
  • Benötigt eine benutzerdefinierte Streamkonfiguration, z. B. einen RAW-Stream.
  • Interaktive Aufnahmesequenz erforderlich.
Unterstützte API-Version Camera2-Erweiterungen: Android 13 oder höher 
CameraX-Erweiterungen: camera-extensions 1.1.0 oder höher
Camera2-Erweiterungen: Android 12L oder höher
CameraX-Erweiterungen: 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 entsprechenden Camera Extensions API-Aufrufe aufgeführt. Camera2/X bietet zwar diese APIs, Sie müssen die Anbieterbibliothek jedoch richtig implementieren, um diese Abläufe zu unterstützen. Das wird in einem späteren Abschnitt genauer beschrieben.

Camera2-Erweiterungen CameraX-Erweiterungen
Verfügbarkeit von Abfrageerweiterungen prüfen 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 Standbildaufnahme mit aktivierter Erweiterung CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

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

Basic Extender

Die Basic Extender-Schnittstelle bietet Hooks an mehreren Stellen 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 Extender-Klassen
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 verwenden wir PreviewExtenderImpl und ImageCaptureExtenderImpl als Platzhalter. Ersetzen Sie diese durch die Namen der tatsächlichen Dateien, die Sie implementieren.

Basic Extender bietet die folgenden Funktionen:

  • Fügen Sie Sitzungsparameter ein, wenn Sie CameraCaptureSession ( onPresetSession) konfigurieren.
  • Sie werden über den Start und das Schließen der Aufnahmesitzung benachrichtigt und senden eine einzelne Anfrage, um die HAL mit den zurückgegebenen Parametern (onEnableSession, onDisableSession) zu benachrichtigen.
  • Erfassen Sie Parameter für die Anfrage (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Fügen Sie Prozessoren für die Vorschau und die Aufnahme von Standbildern 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 Basic 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, damit die Erweiterungen aktiviert werden.

Dies ist oft der erste Schritt für Apps, um zu 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 Basic Extender

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

  • Still capture latency range (Latenzbereich für Standbildaufnahme): ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange gibt den Bereich der Aufnahmelatenz für die App zurück, um zu bewerten, ob es angemessen ist, die Erweiterung für das aktuelle Szenario zu aktivieren.

  • Unterstützte Größen für die Vorschau- und Aufnahmefläche:Mit ImageCaptureExtenderImpl.getSupportedResolutions und PreviewExtenderImpl.getSupportedResolutions wird eine Liste der Bildformate und der 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 Ergebnisse aus Ihrer Implementierung abzurufen:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

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

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

BasicExtenderAppFlow3

Abbildung 5: App-Ablauf 3 auf Basic Extender

Das obige Diagramm veranschaulicht den Hauptablauf zum Aktivieren der Vorschau und zum Aufnehmen 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. Dadurch werden Sie darüber informiert, dass eine Kamerasitzung mit den angegebenen Erweiterungen gestartet wird. Sie können die Initialisierung 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 das HAL zu benachrichtigen. Bevor die Aufnahmesitzung geschlossen wird, ruft Camera2/X onDisableSession auf und sendet dann eine einzelne Anfrage mit den zurückgegebenen Aufnahmeparametern.

Die wiederholte Anfrage, die von Camera2/X ausgelöst wird, enthält die von PreviewExtenderImpl.getCaptureStage() zurückgegebenen Anfrageparameter. Außerdem enthält die Anfrage zum Aufnehmen eines Standbilds die von ImageCaptureExtenderImpl.getCaptureStages() zurückgegebenen Parameter.

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

Vorschauprozessor

Zusätzlich zum Kamera-HAL 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 Kamera-HAL verarbeitet.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY:Mit dem Prozessortyp können Sie die wiederholte Anfrage mit neuen Parametern für die Aufnahme aktualisieren, die auf dem neuesten TotalCaptureResult basieren.

    PreviewExtenderImpl.getProcessor muss eine RequestUpdateProcessorImpl-Instanz zurückgeben, die die TotalCaptureResult-Instanz verarbeitet und eine CaptureStageImpl-Instanz zurückgibt, um die wiederholte 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 Prozessor ist für die Verarbeitung von YUV_420_888-Eingabebildern verantwortlich. Die Ausgabe sollte im PRIVATE-Format der Vorschau erfolgen. Camera2/X verwendet anstelle von PRIVATE eine YUV_420_888-Oberfläche, um CameraCaptureSession für die Vorschau zu konfigurieren.

    Die folgende Abbildung zeigt den Ablauf:

PreviewProcessor

Abbildung 6 Ablauf mit PreviewImageProcessorImpl in der Vorschau ansehen

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

  • Mit onOutputSurface(Surface surface, int imageFormat) wird die Ausgabefläche für den Prozessor festgelegt. Für PreviewImageProcessorImpl ist imageFormat ein Pixelformat wie PixelFormat.RGBA_8888.

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

  • Mit onImageFormatUpdate(int imageFormat) wird das Bildformat des Eingabebilds festgelegt. Derzeit kann nur YUV_420_888 ausgewählt werden.

Prozessor für die Bildaufnahme

Für die Aufnahme von Standbildern 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 ist und läuft, bevor Sie die Anfrage zum Aufnehmen eines Standbilds senden.

Der Ablauf ist im Diagramm unten dargestellt:

CaptureProcessor

Abbildung 7. Still Capture-Ablauf mit CaptureProcessorImpl

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

    • CaptureProcessorImpl.onImageFormatUpdate() mit YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() durch die Größe des Eingabebilds.
    • CaptureProcessorImpl.onOutputSurface() mit einer Ausgabefläche YUV_420_888.
  2. ImageCaptureExtenderImpl.getCaptureStages gibt eine Liste von CaptureStageImpl zurück, wobei jedes Element einer CaptureRequest-Instanz mit Erfassungsparametern entspricht, die von Camera2/X gesendet werden. Wenn beispielsweise eine Liste mit drei CaptureStageImpl-Instanzen zurückgegeben wird, sendet Camera2/X drei Aufnahmeanfragen mit 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 Ergebnis „Bild“ (YUV_420_888-Format) auf die Ausgabefläche, die durch den onOutputSurface()-Aufruf angegeben wird. Camera2/X konvertiert es bei Bedarf in JPEG-Bilder.

Erfassung von Anfrageschlüsseln und ‑ergebnissen unterstützen

Neben der Kameravorschau und der Aufnahme können Apps auch Zoom- und Blitzparameter festlegen oder einen Tap-to-Focus-Vorgang auslösen. 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 verfügbar machen können:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() gibt die von Ihrer Implementierung unterstützten Schlüssel für Erfassungsanfragen zurück.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() gibt die Schlüssel für das Aufnahmeergebnis zurück, die im Aufnahmeergebnis 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 Methode process() in PreviewImageProcessorImpl und CaptureProcessorImpl übergeben wird. Sie sind dafür verantwortlich, das Aufnahmeergebnis über ProcessResultImpl an Camera2/X zu melden.

Unten sehen Sie ein Beispiel für die Definition der CaptureProcessorImpl-Schnittstelle. 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 häufige Kameravorgänge wie Zoom, Tippen zum Fokussieren, Blitz und Belichtungskorrektur empfehlen wir, die folgenden Tasten sowohl für die Aufnahmeanfrage als auch für das Aufnahmeergebnis 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
  • Blitz:
    • CaptureRequest#CONTROL_AE_MODE
    • CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
    • CaptureRequest#FLASH_MODE
  • Belichtungskorrektur:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

Für Basic Extenders, die Version 1.2.0 oder frühere Versionen implementieren, werden alle oben genannten Schlüssel von der CameraX Extensions API explizit unterstützt. Bei extensions-interface 1.3.0 berücksichtigen sowohl CameraX als auch Camera2 die zurückgegebene Liste und unterstützen nur die darin enthaltenen Schlüssel. Wenn Sie beispielsweise in der Implementierung von Version 1.3.0 nur CaptureRequest#CONTROL_ZOOM_RATIO und CaptureRequest#SCALER_CROP_REGION zurückgeben, wird für die App nur das Zoomen unterstützt. Tippen zum Fokussieren, Blitz und Belichtungskorrektur sind dann nicht zulässig.

Erweiterter Extender

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

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

  • Möglichkeit zum Senden von Camera2-Anfragen:Unterstützung einer komplexen Interaktionslogik, mit der Erfassungsanfragen mit Parametern gesendet werden können, die auf den Ergebnissen vorheriger Anfragen basieren.

Advanced Extender bietet einen Wrapper oder eine Zwischenschicht, mit der Sie die Streamkonfiguration anpassen und Aufnahmeanfragen bei Bedarf senden können.

Zu implementierende Dateien

Wenn Sie zur Implementierung des erweiterten Extenders wechseln möchten, muss die Methode isAdvancedExtenderImplemented() in ExtensionVersionImpl true zurückgeben. Für jeden Erweiterungstyp müssen OEMs die entsprechenden Extender-Klassen implementieren. Die Implementierungsdateien für Advanced 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 sie durch den Namen der Extender-Datei für die Erweiterung, die Sie implementieren.

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

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

AdvancedAppFlow1

Abbildung 8. App-Ablauf 1 auf Advanced Extender

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

App-Ablauf 2: Informationen abfragen

AdvancedAppFlow2

Abbildung 9. App-Ablauf 2 auf Advanced Extender

Nach dem Aufrufen 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 Aufnahme-Latenz für die App zurück, um zu bewerten, ob es angemessen ist, die Erweiterung für das aktuelle Szenario zu aktivieren.

  • Unterstützte Auflösungen für Vorschau und Standbildaufnahme:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() gibt eine Map des Bildformats zur Liste der Größen zurück, die für das Vorschauoberflächenformat und die Vorschauoberflächengröße unterstützt werden. OEMs must support at least the PRIVATE format.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() gibt das unterstützte Format und die unterstützten Größen für die Oberfläche für Standbilder 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 für Erfassungsanfragen/Ergebnisse (hinzugefügt in extensions-interface 1.3.0): Camera2/X ruft die folgenden Methoden auf, um die unterstützten Schlüssel für Erfassungsanfragen und Ergebnisschlüssel aus Ihrer Implementierung abzurufen:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Weitere Informationen finden Sie unter Support Capture-Anfrageschlüssel und ‑Ergebnisse.

App-Ablauf 3: Vorschau/Standbildaufnahme mit aktivierter Erweiterung

AdvancedAppFlow3

Abbildung 10. App-Ablauf 3 auf Advanced Extender

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

  1. SessionProcessorImpl-Instanz

    Die Kernimplementierung von Advanced Extender befindet sich in SessionProcessorImpl. Diese Klasse ist dafür verantwortlich, eine benutzerdefinierte Sitzungskonfiguration bereitzustellen und Erfassungsanfragen zu senden, um die Vorschau und die Standbildaufnahme zu starten. AdvancedExtenderImpl.createSessionProcessor() wird aufgerufen, um die SessionProcessorImpl-Instanz zurückzugeben.

  2. initSession

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

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

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

    Sie müssen 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 die Ausgabeflächen auszugeben, die von Camera2/X übergeben werden. Hier sind einige Optionen zum Aktivieren der Ausgabe:

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

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

    • Camera2-Oberflächenfreigabe verwenden:Sie können die Oberflächenfreigabe mit einer anderen Oberfläche verwenden, indem Sie eine beliebige Camera2OutputConfigImpl-Instanz der getSurfaceSharingOutputConfigs()-Methode einer anderen Camera2OutputConfigImpl-Instanz hinzufügen. Das Oberflächenformat und die Größe müssen identisch sein.

    Alle Camera2OutputConfigImpl, einschließlich SurfaceOutputConfigImpl und ImageReaderOutputConfigImpl, müssen eine eindeutige ID (getId()) haben, mit der die Zieloberflä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, sodass Sie Aufnahmeanfragen ausführen und Bilder abrufen können, wenn ImageReaderOutputConfigImpl verwendet wird.

    Die RequestProcessImpl-APIs ähneln den Camera2-CameraCaptureSession-APIs in Bezug auf die Ausführung von Anfragen. Die Unterschiede sind:

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

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

    Die RequestProcessImpl-Instanz wird nach Camera2/X-Aufrufen von SessionProcessorImpl.onCaptureSessionEnd() ungültig.

  4. Vorschau starten und Foto aufnehmen

    Bei der erweiterten Extender-Implementierung können Sie Erfassungsanfragen über die RequestProcessorImpl-Schnittstelle senden. Camera2/X benachrichtigt Sie, dass Sie den sich wiederholenden Antrag für die Vorschau oder die Sequenz für die Aufnahme von Standbildern starten müssen, indem Sie SessionProcessorImpl#startRepeating bzw. SessionProcessorImpl#startCapture aufrufen. Sie sollten Erfassungsanfragen senden, um diese Vorschau- und Standbildanfragen zu erfüllen.

    Camera2/X legt die Parameter für die Aufnahmeanfrage auch über SessionProcessorImpl#setParameters fest. Sie müssen diese Anfrageparameter (sofern Parameter unterstützt werden) sowohl für die wiederholten als auch für die einzelnen Anfragen festlegen.

    Sie müssen mindestens CaptureRequest.JPEG_ORIENTATION und CaptureRequest.JPEG_QUALITY unterstützen. extensions-interface 1.3.0 unterstützt Anforderungs- und Ergebnisschlüssel, die von den folgenden Methoden bereitgestellt 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 Erfassungsresultat 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. Sie können alle Schlüssel für Erfassungsanfragen ignorieren, die nicht in AdvancedExtenderImpl.getAvailableCaptureRequestKeys() beworben wurden.

    startTrigger() wird seit extensions-interface 1.3.0 unterstützt. Damit können Apps mit Erweiterungen die Funktionen „Fokus durch Tippen“ und „Blitz“ implementieren.

  6. Aufräumen

    Wenn Sie eine Aufzeichnungssitzung beenden, wird SessionProcessorImpl.onCaptureSessionEnd() vor dem Schließen von CameraCaptureSession aufgerufen. Nachdem die Aufnahmesitzung geschlossen wurde, führt deInitSession() die Bereinigung durch.

Unterstützung von Vorschau, Standbildaufnahme 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 Erweiterung nur für die Aufnahme von Standbildern verwenden.

Beim 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 für die Konfiguration von CameraCaptureSession unterstützen. Wenn Sie einen Prozessor implementieren, müssen Sie also die Streamkombination von drei YUV_420_888-Streams unterstützen.

Bei Advanced Extender übergibt Camera2/X drei Ausgabeflächen an den SessionProcessorImpl.initSession()-Aufruf. Diese Ausgabeflächen sind für die Vorschau, die Aufnahme von Einzelbildern bzw. die Bildanalyse vorgesehen. Sie müssen dafür sorgen, dass auf den Ausgabeflächen für Vorschau und Standbild die gültige Ausgabe angezeigt wird. Achten Sie jedoch darauf, dass die Ausgabefläche für die Bildanalyse nur funktioniert, wenn sie nicht null ist. Wenn Ihre Implementierung den Bildanalysestream 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.

Videoaufnahmen unterstützen

Die aktuelle Camera Extension-Architektur unterstützt nur die Anwendungsfälle „Vorschau“ und „Standbildaufnahme“. Die Aktivierung der Erweiterung auf den Plattformen MediaCodec oder MediaRecorder zur Aufzeichnung des Videos wird nicht unterstützt. Es ist jedoch möglich, dass Apps die Vorschauausgabe aufzeichnen.

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

Erweiterungsspezifische Metadaten

Unter Android 14 und höher können Kameraerweiterungsclients mit erweiterungsspezifischen Metadaten erweiterungsspezifische Einstellungen für Aufnahmeanfragen festlegen und Ergebnisse empfangen. Insbesondere können Kameraerweiterungsclients den Erfassungsanfrageparameter EXTENSION_STRENGTH verwenden, um die Stärke der Erweiterung zu steuern, und das Erfassungsergebnis EXTENSION_CURRENT_TYPE, um den aktivierten Erweiterungstyp anzugeben.

Anfragen erfassen

Mit dem Erfassungsanfrageparameter EXTENSION_STRENGTH wird die Stärke des Effekts der Erweiterungsnachbearbeitung gesteuert. Das entsprechende Aufnahmeergebnis 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: Hiermit wird die Stärke der Unschärfe gesteuert.
  • HDR und NIGHT: Hiermit wird die Anzahl der zusammengefügten Bilder und die Helligkeit des endgültigen Bilds gesteuert.
  • FACE_RETOUCH: Steuert das Ausmaß der kosmetischen Optimierung und der Hautglättung.

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

Wenn Sie Unterstützung für EXTENSION_STRENGTH hinzufügen möchten, verwenden Sie die anbieterspezifischen Parameter-APIs, die in Version 1.3.0 der Erweiterungsbibliothekschnittstelle eingeführt wurden. Weitere Informationen finden Sie unter getAvailableCaptureRequestKeys().

Ergebnisse erfassen

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

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

Geschätzte Latenz bei der Aufnahme von Standbildern in Echtzeit

Unter Android 14 und höher können Kameraerweiterungsclients mithilfe von getRealtimeStillCaptureLatency() Echtzeit-Schätzungen der Latenz bei der Aufnahme von Standbildern basierend auf der Szene und den Umgebungsbedingungen abfragen. Diese Methode liefert genauere Schätzungen als die statische getEstimatedCaptureLatencyRangeMillis()-Methode. Anhand der Latenzschätzung können Apps entscheiden, ob die Verarbeitung der Erweiterung übersprungen oder den Nutzern ein Hinweis auf einen lang andauernden Vorgang angezeigt werden soll.

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 Latenzschätzungen für die Echtzeit-Standbildaufnahme zu unterstützen, müssen Sie Folgendes implementieren:

Callbacks für den Fortschritt der Erfassung verarbeiten

Unter Android 14 und höher können Kameraerweiterungs-Clients Rückrufe für den Fortschritt von lang andauernden Verarbeitungsvorgängen für Standbilder erhalten. Apps können den aktuellen Fortschritt für Nutzer anzeigen, um die allgemeine Nutzerfreundlichkeit 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 für den Fortschritt der Erfassung zu unterstützen, muss die Implementierung Ihres Erweiterungsanbieters die folgenden Rückrufe mit dem aktuellen Fortschrittswert aufrufen:

Postview-Standbild

Unter Android 14 und höher können Kameraerweiterungen mit setPostviewOutputConfiguration eine Postview (Vorschaubild) bereitstellen. Um die Nutzerfreundlichkeit zu verbessern, können Apps ein Postview-Bild als Platzhalter anzeigen, wenn bei einer Erweiterung eine erhöhte Verarbeitungslatenz auftritt. Das Bild kann dann ersetzt werden, wenn das endgültige Bild verfügbar ist. Apps können Post-View-Erfassungsanfragen mit dem folgenden Referenzcode 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 Aufnahme von Standbildern nach der Aufnahme unterstützt wird, muss in der Implementierung des Anbieters Folgendes implementiert werden:

SurfaceView-Ausgabe unterstützen

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

Damit die Ausgabe SurfaceView unterstützt wird, muss Ihre Anbietererweiterung in der Lage sein, Vorschauen 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 Implementierungen von Anbietererweiterungen einen anbieterspezifischen Sitzungstyp auswählen, der anstelle des Standardwerts in der internen Kameraaufnahmesitzung festgelegt wird.

Die Funktion wird vollständig innerhalb des Frameworks und des Anbieter-Stacks ausgeführt und hat keine Auswirkungen auf clientseitige oder öffentliche APIs.

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

Versionsverlauf der Erweiterungsschnittstelle

In der folgenden Tabelle ist der Versionsverlauf der Camera Extension-Schnittstelle aufgeführt. Sie sollten die Anbieterbibliothek immer mit der neuesten Version implementieren.

Version Hinzugefügte Funktionen
1.0.0
  • Versionsüberprüfung
    • ExtensionVersionImpl
  • Basic Extender
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Initialisierung der Bibliothek
    • InitializerImpl
  • Unterstützte Auflösungen verfügbar machen
    • 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/Ergebnisse verfügbar machen
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys und getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys und getAvailableCaptureResultKeys
    • Neuer process()-Anruf, der ProcessResultImpl in PreviewImageProcessorImpl und CaptureProcessorImpl entgegennimmt
    • Supportanfrage für Triggertyp
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Erweiterungsspezifische Metadaten
  • Latenzschätzungen für dynamische Standbilder
  • Callbacks für den Fortschritt der Erfassung verarbeiten
  • Postview-Standbild
  • Unterstützung für die SurfaceView-Ausgabe
  • Anbieterspezifische Sitzungstypen

Referenzimplementierung

Die folgenden Referenzimplementierungen der OEM-Anbieterbibliothek sind in frameworks/ex verfügbar.

  • advancedSample: Eine einfache Implementierung von Advanced Extender.

  • sample: Eine einfache Implementierung von Basic Extender.

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

    • oem_library: Eine OEM-Bibliothek für Kameraerweiterungen für die Camera2- und CameraX-Erweiterungs-APIs, die Extensions-Interface implementiert. Dies dient als Passthrough, der Aufrufe von Extensions-Interface an den Dienst weiterleitet. Diese Bibliothek bietet auch AIDL-Dateien und Wrapper-Klassen für die Kommunikation mit dem Dienst.

      Der erweiterte Repeater ist standardmäßig aktiviert. Wenn Sie den Basic Extender aktivieren möchten, ändern Sie ExtensionsVersionImpl#isAdvancedExtenderImplemented so, dass false zurückgegeben wird.

    • extensions_service: Eine Beispielimplementierung des Extensions Service. Fügen Sie hier Ihre Implementierung hinzu. Die im Dienst zu implementierende Schnittstelle ähnelt der Extensions-Interface. Die Implementierung von IAdvancedExtenderImpl.Stub führt beispielsweise dieselben Vorgänge aus wie AdvancedExtenderImpl. ImageWrapper und TotalCaptureResultWrapper sind erforderlich, damit Image und TotalCaptureResult parcelable sind.

Anbieterbibliothek auf einem Gerät einrichten

Die OEM-Anbieterbibliothek ist nicht in eine App eingebunden, sondern wird zur Laufzeit von Camera2/X vom Gerät geladen. In CameraX deklariert das <uses-library>-Tag, 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 deklariert, dass die <uses-library>zur Laufzeit dieselbe androidx.camera.extensions.impl-Bibliothek lädt.

Dadurch können Drittanbieter-Apps, die Erweiterungen verwenden, die OEM-Anbieterbibliothek automatisch laden. Die OEM-Bibliothek ist als optional gekennzeichnet, damit Apps auf Geräten ausgeführt werden können, auf denen die Bibliothek nicht vorhanden 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 erkannt werden kann.

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

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

    • name muss androidx.camera.extensions.impl sein, da CameraX nach dieser Bibliothek sucht.
    • file ist der absolute Pfad der Datei, die die Implementierung der Erweiterungen 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>

In Android 12 oder höher muss für Geräte, die CameraX-Erweiterungen unterstützen, die Eigenschaft ro.camerax.extensions.enabled auf true festgelegt sein. So kann abgefragt werden, ob ein Gerät Erweiterungen unterstützt. Fügen Sie dazu der Make-Datei des Geräts die folgende Zeile hinzu:

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

Zertifizierungsstufe

Um Ihre Implementierung der OEM-Anbieterbibliothek während der Entwicklungsphase zu testen, verwenden Sie die Beispiel-App unter androidx-main/camera/integration-tests/extensionstestapp/, in der verschiedene Anbietererweiterungen durchlaufen werden.

Nachdem Sie die Implementierung abgeschlossen haben, können Sie mit dem Validierungstool für Kameraerweiterungen automatisierte und manuelle Tests durchführen, um zu prüfen, ob die Anbieterbibliothek richtig implementiert wurde.

Erweiterter Szenenmodus im Vergleich zu Kameraerweiterungen

Für die Bokeh-Erweiterung können Sie sie nicht nur über Kameraerweiterungen, sondern auch über den erweiterten Szenenmodus verfügbar machen, der über den Schlüssel 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 beispielsweise den erweiterten Szenenmodus in einer regulären CameraCaptureSession-Instanz aktivieren, die flexible Streamkombinationen und Parameter für Erfassungsanfragen unterstützt. Im Gegensatz dazu unterstützen Kameraerweiterungen nur eine feste Anzahl von Streamtypen und nur eine begrenzte Anzahl von Parametern für Erfassungsanfragen.

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

Wir empfehlen, Bokeh sowohl über den erweiterten Szenenmodus als auch über Camera Extensions verfügbar zu machen, da Apps möglicherweise eine bestimmte API bevorzugen, 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 Kameraerweiterungsschnittstelle basierend auf dem erweiterten Szenenmodus implementieren. Wenn die Implementierung von Bokeh in der Kamera-HAL schwierig ist, z. B. weil ein Postprozessor in der App-Ebene zum Verarbeiten von Bildern erforderlich ist, empfehlen wir, die Bokeh-Erweiterung über die Camera Extensions-Schnittstelle zu implementieren.

Häufig gestellte Fragen

Gibt es Einschränkungen hinsichtlich der API-Ebenen?

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