Kamera-HAL3-Pufferverwaltungs-APIs

Android 10 führt optionale Kamera-HAL3- Pufferverwaltungs-APIs ein, die es Ihnen ermöglichen, Pufferverwaltungslogik zu implementieren, um unterschiedliche Speicher- und Erfassungslatenz-Kompromisse in Kamera-HAL-Implementierungen zu erreichen.

Der Kamera-HAL benötigt N Anfragen (wobei N gleich der Pipeline-Tiefe ist), die in seiner Pipeline in der Warteschlange stehen, benötigt aber oft nicht alle N Sätze von Ausgabepuffern gleichzeitig.

Der HAL könnte beispielsweise acht Anfragen in der Pipeline in der Warteschlange haben, benötigt aber nur Ausgabepuffer 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 Anforderung im HAL in die Warteschlange gestellt wird, sodass es im HAL möglicherweise sechs Puffersätze gibt, die nicht verwendet werden. In Android 10 ermöglichen die HAL3-Pufferverwaltungs-APIs der Kamera die Entkopplung der Ausgabepuffer, um die sechs Puffersätze freizugeben. Dies kann bei High-End-Geräten zu Speichereinsparungen von Hunderten Megabyte führen und kann auch bei Geräten mit wenig Speicher 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-Pufferverwaltungs-APIs.

Pufferverwaltung in 9 oder niedriger

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

Pufferverwaltung in Android 10

Abbildung 2. Kamera-HAL-Schnittstelle in Android 10 unter Verwendung der Pufferverwaltungs-APIs

Implementierung der Pufferverwaltungs-APIs

Um die Pufferverwaltungs-APIs zu implementieren, muss die Kamera-HAL:

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

requestStreamBuffers

Verwenden Sie die Methode requestStreamBuffers , um Puffer vom Kamera-Framework anzufordern. Bei Verwendung der HAL3-Pufferverwaltungs-APIs der Kamera enthalten Aufnahmeanforderungen vom Kamera-Framework keine Ausgabepuffer, d. h. das Feld bufferId in StreamBuffer ist 0 . Daher muss die Kamera-HAL requestStreamBuffers verwenden, um Puffer vom Kamera-Framework anzufordern.

Mit der Methode requestStreamBuffers kann der Aufrufer in einem einzigen Aufruf mehrere Puffer von mehreren Ausgabestreams anfordern, wodurch weniger HIDL-IPC-Aufrufe erforderlich sind. Allerdings nehmen Aufrufe mehr Zeit in Anspruch, wenn mehr Puffer gleichzeitig angefordert werden, und dies kann sich negativ auf die Gesamtlatenz von der Anfrage bis zum Ergebnis auswirken. Da Aufrufe von requestStreamBuffers im Kameradienst serialisiert werden, wird außerdem empfohlen, dass die Kamera-HAL einen dedizierten Thread mit hoher Priorität zum Anfordern von Puffern verwendet.

Wenn eine Pufferanforderung fehlschlägt, muss der Kamera-HAL in der Lage sein, nicht schwerwiegende Fehler ordnungsgemäß zu verarbeiten. Die folgende Liste beschreibt häufige Gründe dafür, dass Pufferanforderungen fehlschlagen, und wie sie vom Kamera-HAL behandelt 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 getrennten Stream abzielt, und bereit sein, nachfolgende Anfragen normal zu verarbeiten.
  • Zeitüberschreitung: Dies kann auftreten, wenn eine App mit intensiver Verarbeitung beschäftigt ist und gleichzeitig einige Puffer behält. Der 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 Stream-Konfiguration vor: Der Kamera-HAL sollte warten, bis der nächste configureStreams Aufruf abgeschlossen ist, bevor er erneut requestStreamBuffers aufruft.
  • Der Kamera-HAL hat sein Pufferlimit erreicht (das Feld maxBuffers ): Der Kamera-HAL sollte warten, bis er mindestens einen Puffer des Streams zurückgibt, bevor er requestStreamBuffers erneut aufruft.

returnStreamBuffers

Verwenden Sie die Methode returnStreamBuffers , um zusätzliche Puffer an das Kamera-Framework zurückzugeben. Der Kamera-HAL gibt normalerweise Puffer über die Methode processCaptureResult an das Kamera-Framework zurück, kann jedoch nur Aufnahmeanforderungen berücksichtigen, die an den Kamera-HAL gesendet wurden. Mit der Methode requestStreamBuffers ist es möglich, dass die HAL-Implementierung der Kamera mehr Puffer behält, als vom Kamera-Framework angefordert wurden. In diesem Fall sollte die returnStreamBuffers -Methode verwendet werden. Wenn die HAL-Implementierung nie mehr Puffer enthält als angefordert, muss die HAL-Implementierung der Kamera die Methode returnStreamBuffers nicht aufrufen.

signalStreamFlush

Die signalStreamFlush Methode wird vom Kamera-Framework aufgerufen, um die Kamera-HAL zu benachrichtigen, alle verfügbaren Puffer zurückzugeben. Dies wird normalerweise aufgerufen, wenn das Kamera-Framework im Begriff ist, configureStreams aufzurufen, und die Kamera-Erfassungspipeline leeren muss. Ähnlich wie bei der returnStreamBuffers Methode ist es möglich, dass eine leere Implementierung dieser Methode vorhanden ist, wenn eine Kamera-HAL-Implementierung nicht mehr Puffer als angefordert enthält.

Nachdem das Kamera-Framework signalStreamFlush aufruft, sendet das Framework keine neuen Aufnahmeanforderungen 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 erneut mit der Anforderung von Puffern beginnen, nachdem der Aufruf configureStreams erfolgreich zurückgegeben wurde. Wenn das Kamera-Framework die Methode processCaptureRequest aufruft, kann die Kamera-HAL während des Aufrufs processCaptureRequest mit der Anforderung von Puffern beginnen.

Die Semantik unterscheidet sich für die signalStreamFlush Methode und die flush Methode. Wenn die flush Methode aufgerufen wird, kann die HAL ausstehende Erfassungsanforderungen mit ERROR_REQUEST abbrechen, um die Pipeline so schnell wie möglich zu entleeren. Wenn die signalStreamFlush Methode aufgerufen wird, muss die HAL alle ausstehenden Erfassungsanforderungen 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 unidirektionale HIDL-Methode ist, was bedeutet, dass das Kamera-Framework möglicherweise andere blockierende APIs aufruft, bevor die HAL den signalStreamFlush Aufruf empfängt. Dies bedeutet, dass die signalStreamFlush Methode und andere Methoden (insbesondere die configureStreams Methode) möglicherweise in einer anderen Reihenfolge beim Kamera-HAL ankommen als in der Reihenfolge, in der sie im Kamera-Framework aufgerufen wurden. Um dieses Asynchronitätsproblem zu beheben, wurde das Feld streamConfigCounter zu StreamConfiguration hinzugefügt und als Argument zur signalStreamFlush Methode hinzugefügt. Die HAL-Implementierung der Kamera sollte das Argument streamConfigCounter verwenden, um zu bestimmen, ob ein signalStreamFlush Aufruf später als der entsprechende configureStreams Aufruf eintrifft. Ein Beispiel finden Sie in Abbildung 3.

Bearbeitung verspäteter Anrufe

Abbildung 3. Wie die Kamera-HAL verspätete signalStreamFlush-Aufrufe erkennen und verarbeiten soll

Verhaltensänderungen bei der Implementierung der Pufferverwaltungs-APIs

Berücksichtigen Sie bei der Verwendung der Pufferverwaltungs-APIs zur Implementierung der Pufferverwaltungslogik die folgenden möglichen Verhaltensänderungen an der Kamera und der Kamera-HAL-Implementierung:

  • Aufnahmeanfragen kommen schneller und häufiger beim Kamera-HAL an: Ohne Pufferverwaltungs-APIs fordert das Kamera-Framework Ausgabepuffer für jede Aufnahmeanfrage an, bevor es eine Aufnahmeanfrage an den Kamera-HAL sendet. Bei Verwendung der Pufferverwaltungs-APIs muss das Kamera-Framework nicht mehr auf Puffer warten und kann daher Aufnahmeanforderungen früher an die Kamera-HAL senden.

    Ohne Pufferverwaltungs-APIs stoppt das Kamera-Framework außerdem das Senden von Aufnahmeanfragen, wenn einer der Ausgabeströme der Aufnahmeanfrage die maximale Anzahl von Puffern erreicht hat, die die HAL gleichzeitig halten kann (dieser Wert wird von der Kamera-HAL in angegeben). HalStream::maxBuffers Feld im Rückgabewert eines configureStreams Aufrufs). Mit den Pufferverwaltungs-APIs existiert dieses Drosselungsverhalten nicht mehr und die HAL-Implementierung der Kamera darf keine processCaptureRequest Aufrufe akzeptieren, wenn in der HAL zu viele Aufnahmeanforderungen in der Warteschlange stehen.

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

    • Für die ersten Puffer 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 bei jedem Aufruf angeforderten Puffer.
    • Die App hat Puffer und ist mit der Verarbeitung beschäftigt. Dies kann dazu führen, dass Pufferanforderungen langsamer werden oder aufgrund fehlender Puffer oder einer ausgelasteten CPU eine Zeitüberschreitung erleiden.

Strategien zur Pufferverwaltung

Die Pufferverwaltungs-APIs ermöglichen die Implementierung verschiedener Arten von Pufferverwaltungsstrategien. Einige Beispiele sind:

  • Abwärtskompatibel: Die HAL fordert während des Aufrufs processCaptureRequest Puffer für eine Erfassungsanforderung an. Diese Strategie bietet keine Speichereinsparungen, kann jedoch als erste Implementierung der Pufferverwaltungs-APIs dienen und erfordert nur sehr wenige Codeänderungen am vorhandenen Kamera-HAL.
  • Maximale Speichereinsparung: Der Kamera-HAL fordert Ausgabepuffer nur unmittelbar bevor einer gefüllt werden muss. Diese Strategie ermöglicht maximale Speichereinsparungen. Der potenzielle Nachteil besteht darin, dass die Kamera-Pipeline stärker gestört wird, wenn Pufferanforderungen ungewöhnlich lange dauern.
  • Zwischengespeichert: Der HAL der Kamera speichert einige Puffer zwischen, sodass die Wahrscheinlichkeit geringer ist, dass er von einer gelegentlichen langsamen Pufferanforderung beeinträchtigt wird.

Der Kamera-HAL kann für bestimmte Anwendungsfälle unterschiedliche Strategien anwenden, z. B. die Strategie zur maximierten Speichereinsparung für Anwendungsfälle, die viel Speicher verbrauchen, und die Strategie der Abwärtskompatibilität für andere Anwendungsfälle.

Beispielimplementierung in der externen Kamera HAL

Die externe Kamera-HAL wurde in Android 9 eingeführt und ist im Quellbaum unter hardware/interfaces/camera/device/3.5/ zu finden. In Android 10 wurde es aktualisiert und enthält jetzt ExternalCameraDeviceSession.cpp , eine Implementierung der Pufferverwaltungs-API. Diese externe Kamera-HAL implementiert die in Pufferverwaltungsstrategien erwähnte Strategie zur maximierten Speichereinsparung in ein paar hundert Zeilen C++-Code.