Android 10 führt optionale Kamera HAL3-APIs zur Pufferverwaltung ein, mit denen Sie Pufferverwaltungslogik implementieren können, um bei Kamera-HAL-Implementierungen unterschiedliche Kompromisse bei Speicher und Aufnahmelatenz zu erzielen.
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 oder niedriger weist das Kamera-Framework Buffers zu, wenn die Anfrage in der HAL ansteht. Es kann also sein, dass sich sechs Buffers in der HAL befinden, 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 HAL-Schnittstelle der Kamera in Android 10 mit den implementierten HAL3-APIs zur Pufferverwaltung der Kamera.
Abbildung 1: Camera HAL-Schnittstelle in Android 9 und niedriger
Abbildung 2: Camera HAL-Schnittstelle in Android 10 mit den APIs zur Pufferverwaltung
APIs zur Pufferverwaltung implementieren
Für die Implementierung der APIs zur Pufferverwaltung muss die HAL der Kamera Folgendes tun:
- Implementieren Sie HIDL
ICameraDevice@3.5
. - Legen Sie den Schlüssel für die Kameraeigenschaften
android.info.supportedBufferManagementVersion
aufHIDL_DEVICE_3_5
fest.
Die Kamera-HAL verwendet die Methoden requestStreamBuffers
und returnStreamBuffers
in ICameraDeviceCallback.hal
, um Buffers 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. Wenn jedoch gleichzeitig mehrere Puffer angefordert werden, dauert es länger, bis die Ergebnisse zurückgegeben werden. Das 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. Die HAL der Kamera sollte für jede Aufnahmeanfrage, die auf einen getrennten Stream ausgerichtet ist,
ERROR_REQUEST
senden 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 hä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 Puffer über die Methode processCaptureResult
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. In diesem Fall sollte die returnStreamBuffers
-Methode verwendet werden. Wenn die HAL-Implementierung nie mehr Buffers als angefordert enthä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 HAL-Implementierung für die Kamera keine zusätzlichen Buffers enthält, wenn die Anzahl der angeforderten Buffers nicht erreicht wird.
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 Buffers zurückgegeben werden, schlagen die requestStreamBuffers
-Methodenaufrufe 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 configureStreams
-Methode aufruft, kann die Kamera-HAL nach erfolgreichem 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 leeren. 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 die HAL den signalStreamFlush
-Aufruf empfängt. Das bedeutet, dass die signalStreamFlush
-Methode und andere Methoden (insbesondere die configureStreams
-Methode) in einer anderen Reihenfolge an der Kamera-HAL ankommen können als in der Reihenfolge, in der sie im Kamera-Framework aufgerufen wurden. Um dieses asynchrone Problem zu beheben, wurde das Feld streamConfigCounter
zu StreamConfiguration
und als Argument zur Methode signalStreamFlush
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
Änderungen am Verhalten 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 die APIs zur Pufferverwaltung verwendet werden, 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 Pufferverwaltung gibt es dieses Drosselungsverhalten nicht mehr und die HAL-Implementierung der Kamera darf keineprocessCaptureRequest
-Aufrufe akzeptieren, wenn in der HAL zu viele Aufnahmeanfragen in der Warteschlange stehen.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 steigt proportional zur Anzahl der in jedem Aufruf angeforderten Puffer.
- Die App hält Puffer und ist gerade mit der Verarbeitung beschäftigt. Dies kann dazu führen, dass Pufferanfragen aufgrund von fehlenden Puffern oder einer überlasteten CPU verlangsamt werden oder ein Zeitlimit erreicht wird.
Strategien zur Pufferverwaltung
Mit den APIs zur Pufferverwaltung können verschiedene Arten von Pufferverwaltungsstrategien implementiert werden. Dazu einige Beispiele:
- Abwä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.
Die HAL der Kamera kann für bestimmte Anwendungsfälle unterschiedliche Strategien anwenden, z. B. die Strategie zur maximalen Speichereinsparung für Anwendungsfälle, die viel Speicher verbrauchen, und die abwärtskompatible Strategie für andere Anwendungsfälle.
Beispielimplementierung in der externen Kamera-HAL
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 Arbeitsspeichereinsparung in einigen hundert Zeilen C++-Code.