Kamera-HAL3-Zwischenspeicherverwaltungs-APIs

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.

Zwischenspeicherverwaltung in Android 9 oder niedriger

Abbildung 1: Camera HAL-Schnittstelle in Android 9 und niedriger

Pufferverwaltung in Android 10

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:

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, bevor requestStreamBuffers 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 er requestStreamBuffers 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.

Spät eingehende Anrufe bearbeiten

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 eines configureStreams-Aufrufs angegeben. Mit den APIs zur Pufferverwaltung gibt es dieses Drosselungsverhalten nicht mehr und die HAL-Implementierung der Kamera darf keine processCaptureRequest-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 ein requestStreamBuffers-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.