In Android 10 werden optionale Kamera-HAL3-APIs zur Zwischenspeicherverwaltung eingeführt, mit denen Sie eine Logik zur Zwischenspeicherverwaltung implementieren können, um verschiedene Speichermengen zu erreichen und Latenz-Kompromisse in Kamera-HAL-Implementierungen zu erfassen.
Die Kamera-HAL benötigt N Anfragen (wobei N der Pipelinetiefe entspricht), die in der Pipeline anstehen. Häufig sind jedoch nicht alle N Ausgabebuffer gleichzeitig erforderlich.
Beispielsweise hat die HAL möglicherweise acht Anfragen in der Pipeline, benötigt aber nur Ausgabebuffer für die beiden Anfragen in den letzten Phasen der Pipeline. Auf Geräten mit Android 9 und niedriger weist das Kamera-Framework Puffer zu, wenn die Anfrage im HAL in die Warteschlange gestellt wird, sodass im HAL sechs Puffersätze vorhanden sein können, die nicht verwendet werden. In Android 10 ermöglichen die HAL3-APIs zur Pufferverwaltung der Kamera die Entkopplung der Ausgabepuffer, um die sechs Puffersätze freizugeben. Dies kann auf High-End-Geräten zu einer Speichereinsparung von mehreren hundert Megabyte führen und ist auch für Geräte mit wenig Arbeitsspeicher von Vorteil.
Abbildung 1 zeigt ein Diagramm der HAL-Schnittstelle der Kamera für Geräte mit Android 9 oder niedriger. Abbildung 2 zeigt die Kamera-HAL-Schnittstelle in Android 10 mit den implementierten Kamera-HAL3-Zwischenspeicherverwaltungs-APIs.
Abbildung 1. Kamera-HAL-Schnittstelle unter Android 9 und niedriger
Abbildung 2. Kamera-HAL-Schnittstelle in Android 10 mit den APIs zur Pufferverwaltung
APIs zur Pufferverwaltung implementieren
Zum Implementieren der APIs zur Zwischenspeicherverwaltung muss der Kamera-HAL:
- Implementieren Sie HIDL
ICameraDevice@3.5
. - Legen Sie den Schlüssel für die Kameraeigenschaften
android.info.supportedBufferManagementVersion
aufHIDL_DEVICE_3_5
fest.
Der Kamera-HAL verwendet die Methoden requestStreamBuffers
und returnStreamBuffers
in ICameraDeviceCallback.hal
, um Zwischenspeicher anzufordern und zurückzugeben. Die HAL muss außerdem die Methode signalStreamFlush
in ICameraDeviceSession.hal
implementieren, um der Kamera-HAL zu signalisieren, dass Buffers zurückgegeben werden sollen.
requestStreamBuffers
Verwenden Sie die Methode requestStreamBuffers
, um Buffers vom Kamera-Framework anzufordern. Wenn Sie die HAL3-APIs zur Pufferverwaltung der Kamera verwenden, enthalten Aufnahmeanfragen vom Kamera-Framework keine Ausgabebuffer. Das Feld bufferId
in StreamBuffer
ist also 0
. Daher muss die Kamera-HAL requestStreamBuffers
verwenden, um Buffers vom Kamera-Framework anzufordern.
Mit der Methode requestStreamBuffers
kann der Aufrufer mehrere Puffer aus mehreren Ausgabestreams in einem einzigen Aufruf anfordern, was weniger HIDL-IPC-Aufrufe erfordert. Aufrufe dauern jedoch länger, wenn gleichzeitig mehrere Puffer angefordert werden. Dies kann sich negativ auf die Gesamtlatenz von Anfrage bis Ergebnis auswirken.
Da Aufrufe von requestStreamBuffers
im Kameradienst serialisiert werden, wird empfohlen, dass die HAL der Kamera einen speziellen Thread mit hoher Priorität verwendet, um Buffers anzufordern.
Wenn eine Pufferanfrage fehlschlägt, muss die HAL der Kamera in der Lage sein, nicht kritische Fehler richtig zu verarbeiten. In der folgenden Liste werden häufige Gründe für fehlgeschlagene Pufferanfragen beschrieben und wie diese von der Kamera-HAL verarbeitet werden sollten.
- Die App trennt die Verbindung zum Ausgabestream:
Dies ist ein nicht schwerwiegender Fehler. Der Kamera-HAL sollte
ERROR_REQUEST
für jede Aufnahmeanfrage senden, die auf einen unterbrochenen Stream ausgerichtet ist, und bereit sein, nachfolgende Anfragen normal zu verarbeiten. - Zeitüberschreitung:Das kann passieren, wenn eine App eine intensive Verarbeitung durchführt und dabei einige Puffer behält. Die Kamera-HAL sollte
ERROR_REQUEST
für Aufnahmeanfragen senden, die aufgrund eines Zeitüberschreitungsfehlers nicht erfüllt werden können, und bereit sein, nachfolgende Anfragen normal zu verarbeiten. - Das Kamera-Framework bereitet eine neue Streamkonfiguration vor:Die HAL der Kamera sollte warten, bis der nächste
configureStreams
-Aufruf abgeschlossen ist, bevorrequestStreamBuffers
noch einmal aufgerufen wird. - Der HAL der Kamera hat sein Pufferlimit (das Feld
maxBuffers
) erreicht: Der HAL der Kamera sollte warten, bis mindestens ein Puffer des Streams zurückgegeben wurde, bevor errequestStreamBuffers
noch einmal aufruft.
returnStreamBuffers
Verwenden Sie die Methode returnStreamBuffers
, um zusätzliche Buffers an das Kamera-Framework zurückzugeben. Die Kamera-HAL gibt normalerweise über die Methode processCaptureResult
Puffer an das Kamera-Framework zurück. Sie kann jedoch nur Aufnahmeanfragen berücksichtigen, die an die Kamera-HAL gesendet wurden. Mit der requestStreamBuffers
-Methode kann die HAL-Implementierung der Kamera mehr Buffers beibehalten, als vom Kamera-Framework angefordert wurden. Zu diesem Zeitpunkt sollte die Methode returnStreamBuffers
verwendet werden. Wenn die HAL-Implementierung nie mehr Buffers als angefordert hält, muss die HAL-Implementierung der Kamera die Methode returnStreamBuffers
nicht aufrufen.
signalStreamFlush
Die Methode signalStreamFlush
wird vom Kamera-Framework aufgerufen, um die HAL der Kamera zu benachrichtigen, alle vorhandenen Buffers zurückzugeben. Diese Funktion wird normalerweise aufgerufen, wenn das Kamera-Framework configureStreams
aufrufen und die Kameraaufnahmepipeline leeren muss. Ähnlich wie bei der returnStreamBuffers
-Methode ist es möglich, dass eine leere Implementierung dieser Methode verwendet wird, wenn eine HAL-Implementierung für die Kamera nicht mehr Buffers als angefordert enthält.
Nachdem das Kamera-Framework signalStreamFlush
aufgerufen hat, sendet es keine neuen Aufnahmeanfragen mehr an die Kamera-HAL, bis alle Puffer an das Kamera-Framework zurückgegeben wurden. Wenn alle Puffer zurückgegeben werden, schlagen die Aufrufe der requestStreamBuffers
-Methode fehl und das Kamera-Framework kann seine Arbeit in einem sauberen Zustand fortsetzen. Das Kamera-Framework ruft dann entweder die Methode configureStreams
oder processCaptureRequest
auf. Wenn das Kamera-Framework die Methode configureStreams
aufruft, kann die Kamera-HAL nach dem erfolgreichen Rückgabewert des configureStreams
-Aufrufs wieder Buffers anfordern. Wenn das Kamera-Framework die processCaptureRequest
-Methode aufruft, kann die HAL der Kamera während des processCaptureRequest
-Aufrufs Buffers anfordern.
Die Semantik unterscheidet sich zwischen der signalStreamFlush
-Methode und der flush
-Methode. Wenn die flush
-Methode aufgerufen wird, kann die HAL ausstehende Aufnahmeanfragen mit ERROR_REQUEST
abbrechen, um die Pipeline so schnell wie möglich zu entleeren. Wenn die Methode signalStreamFlush
aufgerufen wird, muss die HAL alle ausstehenden Aufnahmeanfragen normal abschließen und alle Puffer an das Kamera-Framework zurückgeben.
Ein weiterer Unterschied zwischen der signalStreamFlush
-Methode und anderen Methoden besteht darin, dass signalStreamFlush
eine einseitige HIDL-Methode ist. Das bedeutet, dass das Kamera-Framework möglicherweise andere blockierende APIs aufruft, bevor der HAL den signalStreamFlush
-Aufruf empfängt. Das bedeutet, dass die signalStreamFlush
-Methode und andere Methoden (insbesondere die configureStreams
-Methode) möglicherweise in einer anderen Reihenfolge an der Kamera-HAL ankommen als in der Reihenfolge, in der sie im Kamera-Framework aufgerufen wurden. Um dieses asynchrone Problem zu beheben, wurde das Feld streamConfigCounter
zu StreamConfiguration
hinzugefügt und der Methode signalStreamFlush
als Argument hinzugefügt. Die HAL-Implementierung der Kamera sollte das Argument streamConfigCounter
verwenden, um zu ermitteln, ob ein signalStreamFlush
-Aufruf später als der entsprechende configureStreams
-Aufruf eintrifft. Abbildung 3 zeigt ein Beispiel.
Abbildung 3: So sollte die HAL der Kamera spät eintreffende signalStreamFlush-Anrufe erkennen und verarbeiten
Verhalten ändert sich bei der Implementierung der APIs zur Pufferverwaltung
Wenn Sie die APIs zur Pufferverwaltung verwenden, um die Pufferverwaltungslogik zu implementieren, sollten Sie die folgenden möglichen Verhaltensänderungen an der Kamera und der HAL-Implementierung der Kamera berücksichtigen:
Aufnahmeanfragen erreichen die Kamera-HAL schneller und häufiger:Ohne APIs zur Pufferverwaltung fordert das Kamera-Framework Ausgabe-Puffer für jede Aufnahmeanfrage an, bevor eine Aufnahmeanfrage an die Kamera-HAL gesendet wird. Wenn Sie die APIs zur Pufferverwaltung verwenden, muss das Kamera-Framework nicht mehr auf Puffer warten und kann daher früher Aufnahmeanfragen an die HAL der Kamera senden.
Außerdem sendet das Kamera-Framework ohne APIs zur Pufferverwaltung keine Aufnahmeanfragen mehr, wenn einer der Ausgabestreams der Aufnahmeanfrage die maximale Anzahl von Puffern erreicht hat, die die HAL gleichzeitig aufnehmen kann. Dieser Wert wird von der Kamera-HAL im Feld
HalStream::maxBuffers
im Rückgabewert einesconfigureStreams
-Aufrufs angegeben. Mit den APIs zur Zwischenspeicherverwaltung ist dieses Drosselungsverhalten nicht mehr vorhanden und die Kamera-HAL-Implementierung darf keineprocessCaptureRequest
-Aufrufe akzeptieren, wenn im HAL zu viele Aufnahmeanfragen in die Warteschlange gestellt wurden.Die Latenz von
requestStreamBuffers
-Anrufen variiert stark:Es gibt viele Gründe, warum einrequestStreamBuffers
-Anruf länger als durchschnittlich dauern kann. Beispiel:- Bei den ersten Buffers eines neu erstellten Streams können Aufrufe länger dauern, da das Gerät Speicher zuweisen muss.
- Die erwartete Latenz erhöht sich proportional zur Anzahl der Zwischenspeicher, die bei jedem Aufruf angefordert werden.
- Die App hält Puffer und ist gerade mit der Verarbeitung beschäftigt. Dies kann dazu führen, dass Pufferanfragen aufgrund fehlender Puffer oder einer ausgelasteten CPU verlangsamt werden oder zu einer Zeitüberschreitung führen.
Strategien zur Pufferverwaltung
Mit den APIs zur Pufferverwaltung können verschiedene Arten von Pufferverwaltungsstrategien implementiert werden. Dazu einige Beispiele:
- Rückwärtskompatibel:Die HAL fordert während des
processCaptureRequest
-Aufrufs Puffer für eine Aufnahmeanfrage an. Diese Strategie bietet keine Speichereinsparungen, kann aber als erste Implementierung der APIs zur Pufferverwaltung dienen und erfordert nur sehr wenige Codeänderungen an der vorhandenen Kamera-HAL. - Maximale Speichereinsparungen:Die HAL der Kamera fordert nur dann Ausgabebuffer an, wenn einer benötigt wird, um gefüllt zu werden. Mit dieser Strategie lassen sich die Arbeitsspeichereinsparungen maximieren. Der potenzielle Nachteil ist ein stärkeres Ruckeln der Kamerapipeline, wenn Pufferanfragen ungewöhnlich lange dauern.
- Im Cache:Die HAL der Kamera speichert einige Buffers im Cache, damit sie weniger wahrscheinlich von einer gelegentlich langsamen Bufferanfrage betroffen ist.
Der Kamera-HAL kann für bestimmte Anwendungsfälle unterschiedliche Strategien anwenden, z. B. bei Anwendungsfällen mit viel Arbeitsspeicher die Strategie mit maximiertem Speichereinsparung und für andere Anwendungsfälle die abwärtskompatible Strategie anwenden.
Beispielimplementierung im HAL der externen Kamera
Die HAL für externe Kameras wurde in Android 9 eingeführt und befindet sich im Stammbaum der Quelldateien unter hardware/interfaces/camera/device/3.5/
.
In Android 10 wurde sie um ExternalCameraDeviceSession.cpp
erweitert, eine Implementierung der Buffer Management API. Diese externe Kamera-HAL implementiert die in Strategien zur Pufferverwaltung erwähnte Strategie zur maximalen Speichereinsparung in einigen hundert Zeilen C++-Code.