Kamera-HAL3-Zwischenspeicherverwaltungs-APIs

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.

Zwischenspeicherverwaltung in Android 9 oder niedriger

Abbildung 1. Kamera-HAL-Schnittstelle unter Android 9 und niedriger

Pufferverwaltung in Android 10

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:

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, 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 ü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.

Spät eingehende Anrufe bearbeiten

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 eines configureStreams-Aufrufs angegeben. Mit den APIs zur Zwischenspeicherverwaltung ist dieses Drosselungsverhalten nicht mehr vorhanden und die Kamera-HAL-Implementierung darf keine processCaptureRequest-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 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 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.