APIs zur Verwaltung von HAL3-Kamerapuffern

In Android 10 werden optionale Camera HAL3-APIs für die Pufferverwaltung eingeführt, mit denen Sie die 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 Pipelinelänge entspricht), die in ihrer Pipeline in die Warteschlange gestellt werden, aber oft sind nicht alle N Sätze von Ausgabepuffern gleichzeitig erforderlich.

Beispielsweise können in der HAL acht Anfragen in der Pipeline in die Warteschlange gestellt sein, 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 APIs für die Pufferverwaltung von Camera HAL3 die Entkopplung der Ausgabepuffer, um die sechs Puffersätze freizugeben. Das kann auf High-End-Geräten zu einer Einsparung von Hunderten von Megabyte führen und auch für Geräte mit wenig Arbeitsspeicher von Vorteil sein.

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 zur 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 mehrere Puffer gleichzeitig angefordert werden, dauern die Aufrufe länger. Dies kann sich negativ auf die Latenz zwischen Anfrage und Ergebnis auswirken. 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 Pufferanfragen und die entsprechende Verarbeitung durch die Kamera-HAL beschrieben.

  • App wird vom Ausgabestream getrennt:Dies 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 erfüllt 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 normalerweise Puffer ü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 das Kamera-HAL zu benachrichtigen, dass alle verfügbaren Puffer zurückgegeben werden sollen. Diese Methode wird normalerweise aufgerufen, wenn das Kamera-Framework configureStreams aufrufen möchte und die Kamera-Aufnahmepipeline geleert werden muss. Ähnlich wie bei der returnStreamBuffers-Methode ist es möglich, eine leere Implementierung dieser Methode zu haben, wenn eine Kamera-HAL-Implementierung nicht mehr Puffer als angefordert enthält.

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 wurden, 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 signalStreamFlush-Methode und andere Methoden (insbesondere die configureStreams-Methode) möglicherweise in einer anderen Reihenfolge als der, in der sie im Kamera-Framework aufgerufen wurden, in der Kamera-HAL ankommen. Um dieses asynchrone 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. Ein Beispiel finden Sie in Abbildung 3.

Spät eingehende 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:

  • Erfassungsanfragen kommen schneller und häufiger in der Kamera-HAL an:Ohne APIs für die Pufferverwaltung fordert das Kamera-Framework Ausgabepuffer für jede Erfassungsanfrage an, bevor eine Erfassungsanfrage 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-Anrufen variiert erheblich:Es gibt viele Gründe, warum ein requestStreamBuffers-Anruf 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 ein Zeitlimit erreicht wird, weil nicht genügend Puffer vorhanden sind oder die CPU ausgelastet ist.

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 keiner Speicherplatzersparnis, 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, kurz bevor einer gefüllt werden muss. Diese Strategie ermöglicht maximale Arbeitsspeichereinsparungen. Der potenzielle Nachteil ist, dass es bei der Kamerapipeline zu Rucklern kommen 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 in der HAL für externe Kameras

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 nun 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 Speicherersparnis in einigen hundert Zeilen C++-Code.