APIs zur Verwaltung von HAL3-Kamerapuffern

In Android 10 werden optionale Camera HAL3-APIs für die Pufferverwaltung eingeführt, mit denen Sie eine Logik für die Pufferverwaltung implementieren können, um in Camera HAL-Implementierungen unterschiedliche Kompromisse zwischen Arbeitsspeicher und Erfassungsverzögerung zu erzielen.

Die Kamera-HAL erfordert N Anfragen (wobei N der Pipeline-Tiefe entspricht), die in der Pipeline in die Warteschlange gestellt werden. Oft sind jedoch nicht alle N Sätze von Ausgabepuffern gleichzeitig erforderlich.

Beispielsweise können in der HAL acht Anfragen in der Pipeline in der Warteschlange stehen, aber es sind nur Ausgabepuffer für die beiden Anfragen in den letzten Phasen der Pipeline erforderlich. Auf Geräten mit Android 9 und niedriger weist das Kamera-Framework Puffer zu, wenn die Anfrage in der HAL in die Warteschlange gestellt wird. Daher kann es in der HAL sechs Puffergruppen geben, die nicht verwendet werden. In Android 10 ermöglichen die HAL3-APIs für die Pufferverwaltung der Kamera die Entkopplung der Ausgabepuffer, um die sechs Puffersätze freizugeben. Das kann auf High-End-Geräten zu einer Speicherplatzersparnis von Hunderten von Megabyte führen und ist auch für Geräte mit wenig Arbeitsspeicher von Vorteil.

Abbildung 1 zeigt ein Diagramm der Kamera-HAL-Schnittstelle für Geräte mit Android 9 und niedriger. Abbildung 2 zeigt die Kamera-HAL-Schnittstelle in Android 10 mit den implementierten Kamera-HAL3-APIs für die Pufferverwaltung.

Pufferverwaltung in Android 9 oder niedriger

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

Pufferspeicherverwaltung in Android 10

Abbildung 2: Camera HAL-Schnittstelle in Android 10 mit den APIs für die Pufferverwaltung

Pufferverwaltungs-APIs implementieren

Um die APIs für die Pufferverwaltung zu implementieren, muss die Kamera-HAL Folgendes tun:

Die Kamera-HAL verwendet die Methoden requestStreamBuffers und returnStreamBuffers in ICameraDeviceCallback.hal, um Puffer anzufordern und zurückzugeben. Das HAL muss auch die Methode signalStreamFlush in ICameraDeviceSession.hal implementieren, um dem Kamera-HAL zu signalisieren, dass Puffer zurückgegeben werden sollen.

requestStreamBuffers

Verwenden Sie die Methode requestStreamBuffers, um Puffer vom Kamera-Framework anzufordern. Bei Verwendung der Kamera HAL3-APIs für die Pufferverwaltung enthalten Erfassungsanfragen des Kamera-Frameworks keine Ausgabepuffer. Das Feld bufferId in StreamBuffer ist also 0. Daher muss die Kamera-HAL requestStreamBuffers verwenden, um Puffer vom Kamera-Framework anzufordern.

Mit der Methode requestStreamBuffers kann der Aufrufer mehrere Puffer aus mehreren Ausgabestreams in einem einzigen Aufruf anfordern, sodass weniger HIDL-IPC-Aufrufe erforderlich sind. Wenn jedoch mehr Puffer gleichzeitig angefordert werden, dauern die Aufrufe länger, was sich negativ auf die Latenz zwischen Anfrage und Ergebnis auswirken kann. Da Aufrufe von requestStreamBuffers im Kameradienst serialisiert werden, wird empfohlen, dass die Kamera-HAL einen dedizierten Thread mit hoher Priorität verwendet, um Puffer anzufordern.

Wenn eine Pufferanfrage fehlschlägt, muss die Kamera-HAL nicht schwerwiegende Fehler richtig verarbeiten können. In der folgenden Liste werden häufige Gründe für das Fehlschlagen von Pufferanforderungen und die Art und Weise beschrieben, wie sie von der Kamera-HAL behandelt werden sollten.

  • App wird vom Ausgabestream getrennt:Das ist ein nicht schwerwiegender Fehler. Die Kamera-HAL sollte ERROR_REQUEST für jede Aufnahmeanfrage senden, die auf einen getrennten Stream abzielt, und bereit sein, nachfolgende Anfragen normal zu verarbeiten.
  • Zeitüberschreitung:Dies kann auftreten, wenn eine App intensive Verarbeitungsvorgänge ausführt und dabei einige Puffer belegt. Die Kamera-HAL sollte ERROR_REQUEST für Aufnahmeanfragen senden, die aufgrund eines Zeitüberschreitungsfehlers nicht ausgeführt werden können, und bereit sein, nachfolgende Anfragen normal zu verarbeiten.
  • Das Kamera-Framework bereitet eine neue Streamkonfiguration vor:Die Kamera-HAL sollte warten, bis der nächste configureStreams-Aufruf abgeschlossen ist, bevor requestStreamBuffers noch einmal aufgerufen wird.
  • Die Kamera-HAL hat ihr Pufferlimit (das Feld maxBuffers) erreicht: Die Kamera-HAL sollte warten, bis sie mindestens einen Puffer des Streams zurückgibt, bevor sie requestStreamBuffers noch einmal aufruft.

returnStreamBuffers

Verwenden Sie die Methode returnStreamBuffers, um zusätzliche Puffer an das Kamera-Framework zurückzugeben. Die Kamera HAL gibt Puffer normalerweise über die Methode processCaptureResult an das Kamera-Framework zurück. Sie kann jedoch nur Erfassungsanfragen berücksichtigen, die an die Kamera HAL gesendet wurden. Mit der requestStreamBuffers-Methode kann die Kamera-HAL-Implementierung mehr Puffer beibehalten, als vom Kamera-Framework angefordert wurde. In diesem Fall sollte die returnStreamBuffers-Methode verwendet werden. Wenn die HAL-Implementierung nie mehr Puffer als angefordert enthält, muss die Kamera-HAL-Implementierung die returnStreamBuffers-Methode nicht aufrufen.

signalStreamFlush

Die Methode signalStreamFlush wird vom Kamera-Framework aufgerufen, um die Kamera-HAL zu benachrichtigen, alle verfügbaren Puffer zurückzugeben. Diese Methode wird normalerweise aufgerufen, wenn das Kamera-Framework configureStreams aufrufen möchte und die Kamera-Aufnahmepipeline geleert werden muss. Ähnlich wie bei der Methode returnStreamBuffers kann es sein, dass eine Kamera-HAL-Implementierung nicht mehr Puffer als angefordert enthält. In diesem Fall ist eine leere Implementierung dieser Methode möglich.

Nachdem das Kamera-Framework signalStreamFlush aufgerufen hat, sendet es keine neuen Erfassungsanfragen mehr an die Kamera-HAL, bis alle Puffer an das Kamera-Framework zurückgegeben wurden. Wenn alle Puffer 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 die Methode processCaptureRequest auf. Wenn das Kamera-Framework die Methode configureStreams aufruft, kann die Kamera-HAL nach der erfolgreichen Rückgabe des configureStreams-Aufrufs wieder Puffer anfordern. Wenn das Kamera-Framework die Methode processCaptureRequest aufruft, kann die Kamera-HAL während des processCaptureRequest-Aufrufs mit dem Anfordern von Puffern beginnen.

Die Semantik für die Methode signalStreamFlush und die Methode flush ist unterschiedlich. Wenn die Methode flush aufgerufen wird, kann das HAL ausstehende Erfassungsanfragen mit ERROR_REQUEST abbrechen, um die Pipeline so schnell wie möglich zu leeren. Wenn die Methode signalStreamFlush aufgerufen wird, muss das HAL alle ausstehenden Erfassungsanfragen normal abschließen und alle Puffer an das Kamera-Framework zurückgeben.

Ein weiterer Unterschied zwischen der Methode signalStreamFlush und anderen Methoden besteht darin, dass signalStreamFlush eine unidirektionale HIDL-Methode ist. Das bedeutet, dass das Kamera-Framework möglicherweise andere blockierende APIs aufruft, bevor das HAL den signalStreamFlush-Aufruf empfängt. Das bedeutet, dass die Methode signalStreamFlush und andere Methoden (insbesondere die Methode configureStreams) möglicherweise in einer anderen Reihenfolge als der, in der sie im Kamera-Framework aufgerufen wurden, im Kamera-HAL ankommen. Um dieses Problem zu beheben, wurde das Feld streamConfigCounter zu StreamConfiguration hinzugefügt und als Argument zur Methode signalStreamFlush hinzugefügt. Die Kamera-HAL-Implementierung sollte das streamConfigCounter-Argument verwenden, um zu ermitteln, ob ein signalStreamFlush-Aufruf später als der entsprechende configureStreams-Aufruf erfolgt. Abbildung 3 zeigt ein Beispiel.

Verspätete Anrufe bearbeiten

Abbildung 3: So sollte die Kamera-HAL SignalStreamFlush-Aufrufe erkennen und verarbeiten, die zu spät eingehen

Verhaltensänderungen bei der Implementierung der APIs zur Pufferverwaltung

Wenn Sie die APIs für die Pufferverwaltung verwenden, um die Logik für die Pufferverwaltung zu implementieren, sollten Sie die folgenden möglichen Verhaltensänderungen der Kamera und der Kamera-HAL-Implementierung berücksichtigen:

  • Aufnahmeanfragen kommen schneller und häufiger in der Kamera-HAL an:Ohne APIs für die Pufferverwaltung fordert das Kamera-Framework Ausgabepuffer für jede Aufnahmeanfrage an, bevor eine Aufnahmeanfrage an die Kamera-HAL gesendet wird. Bei Verwendung der APIs für die Pufferverwaltung muss das Kamera-Framework nicht mehr auf Puffer warten und kann daher Erfassungsanfragen früher an das Kamera-HAL senden.

    Ohne APIs für die Pufferverwaltung beendet das Kamera-Framework außerdem das Senden von Aufnahmeanfragen, wenn einer der Ausgabestreams der Aufnahmeanfrage die maximale Anzahl von Puffern erreicht hat, die das HAL gleichzeitig enthalten kann. Dieser Wert wird vom Kamera-HAL im Feld HalStream::maxBuffers im Rückgabewert eines configureStreams-Aufrufs angegeben. Mit den APIs für die Pufferverwaltung ist dieses Drosselungsverhalten nicht mehr vorhanden und die Camera HAL-Implementierung darf keine processCaptureRequest-Aufrufe akzeptieren, wenn in der HAL zu viele Erfassungsanfragen in der Warteschlange stehen.

  • Die Latenz von requestStreamBuffers-Aufrufen variiert erheblich:Es gibt viele Gründe, warum ein requestStreamBuffers-Aufruf länger als durchschnittlich dauern kann. Beispiel:

    • Bei den ersten Puffern 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 mit der Verarbeitung beschäftigt. Dies kann dazu führen, dass Pufferanfragen langsamer werden oder aufgrund fehlender Puffer oder einer ausgelasteten CPU ein Zeitlimit erreicht wird.

Strategien für die Pufferverwaltung

Die APIs für die Pufferverwaltung ermöglichen die Implementierung verschiedener Strategien für die Pufferverwaltung. Dazu einige Beispiele:

  • Abwärtskompatibel:Das HAL fordert Puffer für eine Aufnahmeanfrage während des processCaptureRequest-Aufrufs an. Diese Strategie führt zu keinen Speicherersparnissen, kann aber als erste Implementierung der APIs für die Pufferverwaltung dienen, da nur sehr wenige Codeänderungen am vorhandenen Kamera-HAL erforderlich sind.
  • Maximale Speichereinsparungen:Die Kamera-HAL fordert Ausgabepuffer erst an, wenn einer gefüllt werden muss. Diese Strategie ermöglicht maximale Arbeitsspeichereinsparungen. Der potenzielle Nachteil ist, dass die Kamerapipeline ruckeln kann, wenn Pufferanfragen ungewöhnlich lange dauern.
  • Im Cache:Die Kamera-HAL speichert einige Puffer im Cache, damit sie weniger wahrscheinlich von einer gelegentlichen langsamen Pufferanfrage betroffen ist.

Die Kamera-HAL kann für bestimmte Anwendungsfälle unterschiedliche Strategien anwenden, z. B. die Strategie zur Maximierung der Speicherplatzersparnis für Anwendungsfälle, die viel Speicherplatz benötigen, und die abwärtskompatible Strategie für andere Anwendungsfälle.

Beispielimplementierung im externen Kamera-HAL

Die HAL für externe Kameras wurde in Android 9 eingeführt und befindet sich im Quellbaum unter hardware/interfaces/camera/device/3.5/. In Android 10 wurde sie aktualisiert und enthält jetzt ExternalCameraDeviceSession.cpp, eine Implementierung der API zur Pufferverwaltung. Diese externe Kamera-HAL implementiert die in Strategien für die Pufferverwaltung erwähnte Strategie zur Maximierung der Arbeitsspeicherersparnis in einigen hundert Zeilen C++-Code.