API de gestion des tampons HAL3 de l'appareil photo

Android 10 introduit des API de gestion des tampons camera HAL3 facultatives qui vous permettent d'implémenter une logique de gestion des tampons pour obtenir différents compromis de latence de mémoire et de capture dans les implémentations camera HAL.

Le HAL de l'appareil photo nécessite que N requêtes (où N est égal à la profondeur du pipeline) soient mises en file d'attente dans son pipeline, mais il ne nécessite souvent pas les N ensembles de tampons de sortie en même temps.

Par exemple, la HAL peut avoir huit requêtes en file d'attente dans le pipeline, mais elle n'a besoin de tampons de sortie que pour les deux requêtes des dernières étapes du pipeline. Sur les appareils équipés d'Android 9 ou d'une version antérieure, le framework de l'appareil photo alloue des tampons lorsque la requête est mise en file d'attente dans la HAL. Il peut donc y avoir six ensembles de tampons inutilisés dans la HAL. Dans Android 10, les API de gestion des tampons HAL3 de l'appareil photo permettent de dissocier les tampons de sortie pour libérer les six ensembles de tampons. Cela peut permettre d'économiser des centaines de mégaoctets de mémoire sur les appareils haut de gamme et peut également être bénéfique pour les appareils à faible mémoire.

La figure 1 présente un schéma de l'interface HAL de l'appareil photo pour les appareils exécutant Android 9 ou une version antérieure. La figure 2 montre l'interface HAL de l'appareil photo dans Android 10 avec les API de gestion des tampons HAL3 de l'appareil photo implémentées.

Gestion du tampon dans la version 9 ou antérieure

Figure 1 : Interface HAL de l'appareil photo dans Android 9 et versions antérieures

Gestion des tampons dans Android 10

Figure 2. Interface HAL de l'appareil photo dans Android 10 utilisant les API de gestion des tampons

Implémenter les API de gestion du tampon

Pour implémenter les API de gestion des tampons, le HAL de l'appareil photo doit :

La HAL de l'appareil photo utilise les méthodes requestStreamBuffers et returnStreamBuffers dans ICameraDeviceCallback.hal pour demander et renvoyer des tampons. La HAL doit également implémenter la méthode signalStreamFlush dans ICameraDeviceSession.hal pour signaler à la HAL de l'appareil photo de renvoyer les tampons.

requestStreamBuffers

Utilisez la méthode requestStreamBuffers pour demander des tampons au framework de l'appareil photo. Lorsque vous utilisez les API de gestion des tampons HAL3 de l'appareil photo, les requêtes de capture du framework de l'appareil photo ne contiennent pas de tampons de sortie, c'est-à-dire que le champ bufferId dans StreamBuffer est 0. Par conséquent, la HAL de l'appareil photo doit utiliser requestStreamBuffers pour demander des tampons au framework de l'appareil photo.

La méthode requestStreamBuffers permet à l'appelant de demander plusieurs tampons à partir de plusieurs flux de sortie en un seul appel, ce qui réduit le nombre d'appels HIDL IPC. Toutefois, les appels prennent plus de temps lorsque plusieurs tampons sont demandés en même temps, ce qui peut avoir un impact négatif sur la latence totale entre la requête et le résultat. De plus, comme les appels à requestStreamBuffers sont sérialisés dans le service de caméra, il est recommandé que la HAL de la caméra utilise un thread dédié à haute priorité pour demander des tampons.

Si une requête de tampon échoue, la HAL de l'appareil photo doit être en mesure de gérer correctement les erreurs non fatales. La liste suivante décrit les raisons courantes pour lesquelles les requêtes de mémoire tampon échouent et la manière dont elles doivent être gérées par la HAL de l'appareil photo.

  • L'application se déconnecte du flux de sortie : Il s'agit d'une erreur non fatale. La HAL de l'appareil photo doit envoyer ERROR_REQUEST pour toute demande de capture ciblant un flux déconnecté et être prête à traiter normalement les demandes ultérieures.
  • Délai avant expiration : cela peut se produire lorsqu'une application est occupée à effectuer un traitement intensif tout en conservant certains tampons. Le HAL de l'appareil photo doit envoyer ERROR_REQUEST pour les requêtes de capture qui ne peuvent pas être traitées en raison d'une erreur de délai avant expiration et être prêt à traiter normalement les requêtes suivantes.
  • Le framework de l'appareil photo prépare une nouvelle configuration de flux : Le HAL de l'appareil photo doit attendre la fin du prochain appel configureStreams avant d'appeler à nouveau requestStreamBuffers.
  • La HAL de l'appareil photo a atteint sa limite de mémoire tampon (champ maxBuffers) : la HAL de l'appareil photo doit attendre d'avoir renvoyé au moins une mémoire tampon du flux avant d'appeler à nouveau requestStreamBuffers.

returnStreamBuffers

Utilisez la méthode returnStreamBuffers pour renvoyer des tampons supplémentaires au framework de l'appareil photo. L'HAL de la caméra renvoie normalement les tampons au framework de la caméra via la méthode processCaptureResult, mais il ne peut prendre en compte que les requêtes de capture qui ont été envoyées à l'HAL de la caméra. Avec la méthode requestStreamBuffers, il est possible que l'implémentation HAL de l'appareil photo conserve plus de tampons que ceux demandés par le framework de l'appareil photo. C'est alors que la méthode returnStreamBuffers doit être utilisée. Si l'implémentation HAL ne contient jamais plus de tampons que demandé, l'implémentation HAL de l'appareil photo n'a pas besoin d'appeler la méthode returnStreamBuffers.

signalStreamFlush

La méthode signalStreamFlush est appelée par le framework de l'appareil photo pour notifier à la HAL de l'appareil photo de renvoyer tous les tampons disponibles. Cette méthode est normalement appelée lorsque le framework de l'appareil photo est sur le point d'appeler configureStreams et doit vider le pipeline de capture de l'appareil photo. Comme pour la méthode returnStreamBuffers, si une implémentation HAL de l'appareil photo ne contient pas plus de tampons que demandé, il est possible d'avoir une implémentation vide de cette méthode.

Une fois que le framework d'appareil photo appelle signalStreamFlush, il cesse d'envoyer de nouvelles requêtes de capture à la HAL de l'appareil photo jusqu'à ce que tous les tampons aient été renvoyés au framework d'appareil photo. Lorsque tous les tampons sont renvoyés, les appels de méthode requestStreamBuffers échouent et le framework de l'appareil photo peut poursuivre son travail dans un état propre. Le framework de la caméra appelle ensuite la méthode configureStreams ou processCaptureRequest. Si le framework de l'appareil photo appelle la méthode configureStreams, le HAL de l'appareil photo peut recommencer à demander des tampons une fois que l'appel configureStreams est renvoyé avec succès. Si le framework de l'appareil photo appelle la méthode processCaptureRequest, le HAL de l'appareil photo peut commencer à demander des tampons lors de l'appel processCaptureRequest.

La sémantique est différente pour la méthode signalStreamFlush et la méthode flush. Lorsque la méthode flush est appelée, la HAL peut annuler les requêtes de capture en attente avec ERROR_REQUEST pour vider le pipeline dès que possible. Lorsque la méthode signalStreamFlush est appelée, la HAL doit terminer normalement toutes les requêtes de capture en attente et renvoyer tous les tampons au framework de l'appareil photo.

Une autre différence entre la méthode signalStreamFlush et les autres méthodes est que signalStreamFlush est une méthode HIDL unidirectionnelle, ce qui signifie que le framework de l'appareil photo peut appeler d'autres API de blocage avant que le HAL reçoive l'appel signalStreamFlush. Cela signifie que la méthode signalStreamFlush et d'autres méthodes (en particulier la méthode configureStreams) peuvent arriver au HAL de l'appareil photo dans un ordre différent de celui dans lequel elles ont été appelées dans le framework de l'appareil photo. Pour résoudre ce problème d'asynchronie, le champ streamConfigCounter a été ajouté à StreamConfiguration et en tant qu'argument à la méthode signalStreamFlush. L'implémentation de la HAL de l'appareil photo doit utiliser l'argument streamConfigCounter pour déterminer si un appel signalStreamFlush arrive après son appel configureStreams correspondant. Pour consulter un exemple, voir la figure 3.

Gérer les appels qui arrivent en retard

Figure 3. Comment la HAL de l'appareil photo doit détecter et gérer les appels signalStreamFlush qui arrivent en retard

Changements de comportement lors de l'implémentation des API de gestion du tampon

Lorsque vous utilisez les API de gestion des tampons pour implémenter la logique de gestion des tampons, tenez compte des modifications de comportement possibles suivantes pour l'implémentation de la caméra et de la HAL de la caméra :

  • Les demandes de capture arrivent plus rapidement et plus fréquemment au HAL de l'appareil photo : sans les API de gestion des tampons, le framework de l'appareil photo demande des tampons de sortie pour chaque demande de capture avant d'envoyer une demande de capture au HAL de l'appareil photo. Lorsque vous utilisez les API de gestion des tampons, le framework de l'appareil photo n'a plus besoin d'attendre les tampons et peut donc envoyer des requêtes de capture au HAL de l'appareil photo plus tôt.

    De plus, sans API de gestion des tampons, le framework de l'appareil photo cesse d'envoyer des requêtes de capture si l'un des flux de sortie de la requête de capture a atteint le nombre maximal de tampons que le HAL peut contenir à la fois (cette valeur est désignée par le HAL de l'appareil photo dans le champ HalStream::maxBuffers de la valeur renvoyée d'un appel configureStreams). Avec les API de gestion des tampons, ce comportement de limitation n'existe plus et l'implémentation HAL de l'appareil photo ne doit pas accepter les appels processCaptureRequest lorsque la HAL a trop de requêtes de capture en file d'attente.

  • La latence des appels requestStreamBuffers varie considérablement : un appel requestStreamBuffers peut prendre plus de temps que la moyenne pour de nombreuses raisons. Exemple :

    • Pour les premiers tampons d'un flux nouvellement créé, les appels peuvent prendre plus de temps, car l'appareil doit allouer de la mémoire.
    • La latence attendue augmente proportionnellement au nombre de tampons demandés dans chaque appel.
    • L'application contient des tampons et est occupée à traiter des données. Cela peut entraîner un ralentissement ou un délai avant expiration des requêtes de mémoire tampon en raison d'un manque de mémoire tampon ou d'un processeur occupé.

Stratégies de gestion du tampon

Les API de gestion des tampons permettent d'implémenter différents types de stratégies de gestion des tampons. Par exemple :

  • Rétrocompatibilité : le HAL demande des tampons pour une requête de capture lors de l'appel processCaptureRequest. Cette stratégie ne permet pas d'économiser de la mémoire, mais peut servir de première implémentation des API de gestion des tampons, ce qui nécessite très peu de modifications du code du HAL de l'appareil photo existant.
  • Économies de mémoire maximales : le HAL de l'appareil photo ne demande des tampons de sortie qu'immédiatement avant qu'ils ne doivent être remplis. Cette stratégie permet de maximiser les économies de mémoire. L'inconvénient potentiel est un pipeline de caméras plus saccadé lorsque les demandes de mémoire tampon prennent un temps anormalement long à se terminer.
  • Mise en cache : la couche HAL de l'appareil photo met en cache quelques tampons afin d'être moins susceptible d'être affectée par une demande de tampon lente occasionnelle.

La HAL de l'appareil photo peut adopter différentes stratégies pour des cas d'utilisation spécifiques. Par exemple, elle peut utiliser la stratégie d'économie de mémoire maximale pour les cas d'utilisation qui consomment beaucoup de mémoire et la stratégie rétrocompatible pour les autres cas d'utilisation.

Exemple d'implémentation dans le HAL de la caméra externe

Le HAL de caméra externe a été introduit dans Android 9 et se trouve dans l'arborescence source à l'adresse hardware/interfaces/camera/device/3.5/. Dans Android 10, il a été mis à jour pour inclure ExternalCameraDeviceSession.cpp, une implémentation de l'API de gestion des tampons. Cette HAL de caméra externe implémente la stratégie d'économie de mémoire maximisée mentionnée dans Stratégies de gestion des tampons en quelques centaines de lignes de code C++.