Kamera-HAL3-Pufferverwaltungs-APIs

Android 10 führt optionale Kamera-HAL3 -Pufferverwaltungs-APIs ein, mit denen Sie Pufferverwaltungslogik implementieren können, um unterschiedliche Speicher- und Erfassungslatenz-Kompromisse in Kamera-HAL-Implementierungen zu erzielen.

Die Kamera-HAL benötigt N Anfragen (wobei N gleich der Pipeline-Tiefe ist), die in ihrer Pipeline in die Warteschlange gestellt werden, aber sie benötigt oft nicht alle N Sätze von Ausgangspuffern gleichzeitig.

Zum Beispiel könnte die HAL acht Anfragen in der Pipeline haben, aber sie benötigt nur Ausgangspuffer für die zwei Anfragen in den letzten Stufen der Pipeline. Auf Geräten mit Android 9 und niedriger weist das Kamera-Framework Puffer zu, wenn die Anforderung in der HAL in die Warteschlange gestellt wird, sodass sechs Puffersätze in der HAL vorhanden sein können, 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 zu Hunderten von Megabyte an Speichereinsparungen auf High-End-Geräten führen und kann auch für Geräte 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 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

Implementieren 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. Die HAL muss auch die signalStreamFlush Methode in ICameraDeviceSession.hal , um der Kamera-HAL zu signalisieren, Puffer zurückzugeben.

RequestStreamBuffers

Verwenden Sie die Methode „ requestStreamBuffers “, um Puffer vom Kamera-Framework anzufordern. Bei Verwendung der Kamera-HAL3-Pufferverwaltungs-APIs 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.

Die Methode „ requestStreamBuffers “ ermöglicht es dem Aufrufer, mehrere Puffer von mehreren Ausgabeströmen in einem einzigen Aufruf anzufordern, was weniger HIDL-IPC-Aufrufe ermöglicht. Aufrufe nehmen jedoch mehr Zeit in Anspruch, wenn mehr Puffer gleichzeitig angefordert werden, und dies kann sich negativ auf die gesamte Latenzzeit zwischen Anforderung und 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 verwendet, um Puffer anzufordern.

Wenn eine Pufferanforderung fehlschlägt, muss die Kamera-HAL in der Lage sein, nicht schwerwiegende Fehler richtig zu behandeln. Die folgende Liste beschreibt häufige Gründe, warum Pufferanforderungen fehlschlagen, und wie sie von der Kamera-HAL gehandhabt werden sollten.

  • Die App wird vom Ausgabestream getrennt: Dies ist ein nicht schwerwiegender Fehler. Die Kamera-HAL sollte ERROR_REQUEST für jede Erfassungsanforderung senden, die auf einen getrennten Stream abzielt, und bereit sein, nachfolgende Anforderungen normal zu verarbeiten.
  • Zeitüberschreitung: Dies kann auftreten, wenn eine App mit intensiver Verarbeitung beschäftigt ist, während einige Puffer beibehalten werden. Die Kamera-HAL sollte ERROR_REQUEST für Aufnahmeanforderungen senden, die aufgrund eines Zeitüberschreitungsfehlers nicht erfüllt werden können, und bereit sein, nachfolgende Anforderungen normal zu verarbeiten.
  • Das Kamera-Framework bereitet eine neue Stream-Konfiguration vor: Die Kamera-HAL sollte warten, bis der nächste configureStreams -Aufruf abgeschlossen ist, bevor sie erneut requestStreamBuffers aufruft.
  • Die Kamera-HAL hat ihre Puffergrenze erreicht (das Feld maxBuffers ): Die Kamera-HAL sollte warten, bis sie mindestens einen Puffer des Streams zurückgibt, bevor sie requestStreamBuffers erneut aufruft.

returnStreamBuffers

Verwenden Sie die returnStreamBuffers Methode, um zusätzliche Puffer an das Kamera-Framework zurückzugeben. Die Kamera-HAL gibt normalerweise über die Methode processCaptureResult Puffer an das Kamera-Framework zurück, aber sie kann nur Aufnahmeanforderungen berücksichtigen, die an die Kamera-HAL gesendet wurden. Mit der requestStreamBuffers -Methode ist es der Kamera-HAL-Implementierung möglich, mehr Puffer zu behalten, 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 Kamera-HAL-Implementierung die returnStreamBuffers Methode 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 Kameraerfassungspipeline entleeren 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 hat, hört das Framework auf, neue Aufnahmeanforderungen an die Kamera-HAL zu senden, 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 configureStreams -Methode aufruft, kann die Kamera-HAL erneut mit dem Anfordern von Puffern beginnen, nachdem der configureStreams -Aufruf erfolgreich zurückgegeben wurde. Wenn das Kamera-Framework die Methode „ processCaptureRequest “ aufruft, kann die Kamera-HAL während des Aufrufs „ processCaptureRequest “ Puffer anfordern.

Die Semantik ist für die signalStreamFlush Methode und die flush -Methode unterschiedlich. Wenn die flush -Methode aufgerufen wird, kann die HAL anstehende Erfassungsanforderungen mit ERROR_REQUEST , um die Pipeline so schnell wie möglich zu leeren. Wenn die signalStreamFlush Methode aufgerufen wird, muss die HAL alle anstehenden Aufnahmeanforderungen normal beenden 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 bei der Kamera-HAL ankommen als in der Reihenfolge, in der sie im Kamera-Framework aufgerufen wurden. Um dieses Asynchronieproblem zu beheben, wurde das Feld streamConfigCounter zu StreamConfiguration und als Argument zur signalStreamFlush Methode hinzugefügt. Die Kamera-HAL-Implementierung sollte das Argument streamConfigCounter verwenden, um zu bestimmen, ob ein signalStreamFlush -Aufruf später als der entsprechende configureStreams -Aufruf ankommt. Siehe Abbildung 3 für ein Beispiel.

Umgang mit verspäteten Anrufen

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

Verhaltensänderungen beim Implementieren 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:

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

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

  • requestStreamBuffers von requestStreamBuffers variiert erheblich: Es gibt viele Gründe, warum ein Aufruf von requestStreamBuffers überdurchschnittlich lange 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 hält Puffer und ist mit der Verarbeitung beschäftigt. Dies kann dazu führen, dass Pufferanforderungen aufgrund fehlender Puffer oder einer ausgelasteten CPU langsamer werden oder eine Zeitüberschreitung erreichen.

Pufferverwaltungsstrategien

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

  • Abwärtskompatibel: Die HAL fordert Puffer für eine Erfassungsanforderung während des Aufrufs von processCaptureRequest an. Diese Strategie bietet keine Speichereinsparungen, kann aber als erste Implementierung der Pufferverwaltungs-APIs dienen und erfordert nur sehr wenige Codeänderungen an der vorhandenen Kamera-HAL.
  • Maximale Speichereinsparungen: Die Kamera-HAL fordert Ausgabepuffer nur an, unmittelbar bevor einer gefüllt werden muss. Diese Strategie ermöglicht maximale Speichereinsparungen. Der potenzielle Nachteil ist mehr Kamera-Pipeline-Ruck, wenn Pufferanforderungen ungewöhnlich lange dauern, bis sie abgeschlossen sind.
  • Zwischengespeichert: Die Kamera-HAL speichert einige Puffer zwischen, sodass sie weniger wahrscheinlich von einer gelegentlichen langsamen Pufferanforderung betroffen ist.

Die Kamera-HAL kann unterschiedliche Strategien für bestimmte Anwendungsfälle annehmen, beispielsweise die Maximierungs-Speichersparstrategie für Anwendungsfälle verwenden, die viel Speicher verwenden, und die Abwärtskompatibilitätsstrategie für andere Anwendungsfälle verwenden.

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, um ExternalCameraDeviceSession.cpp , eine Implementierung der Pufferverwaltungs-API. Diese externe Kamera-HAL implementiert die in Pufferverwaltungsstrategien erwähnte maximierte Speichersparstrategie in einigen hundert Zeilen C++-Code.