API de gestion des tampons HAL3 de la caméra

Android 10 introduit des API facultatives de gestion de tampon HAL3 de caméra qui vous permettent d'implémenter une logique de gestion de tampon pour obtenir différentes mémoires et capturer des compromis de latence dans les implémentations de caméra HAL.

La caméra HAL nécessite N requêtes (où N est égal à la profondeur du pipeline ) mises en file d'attente dans son pipeline, mais elle 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 ne nécessite que des tampons de sortie pour les deux requêtes des dernières étapes du pipeline. Sur les appareils exécutant Android 9 et versions antérieures, la structure de la caméra alloue des tampons lorsque la requête est mise en file d'attente dans la HAL, de sorte qu'il peut y avoir six ensembles de tampons dans la HAL qui ne sont pas utilisés. Dans Android 10, les API de gestion des tampons HAL3 de la caméra permettent le découplage des tampons de sortie pour libérer les six ensembles de tampons. Cela peut entraîner des économies de 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 montre un schéma de l'interface HAL de la caméra pour les appareils exécutant Android 9 et versions antérieures. La figure 2 montre l'interface HAL de la caméra dans Android 10 avec les API de gestion de tampon HAL3 de la caméra implémentées.

Gestion des buffers en 9 ou inférieur

Figure 1. Interface HAL de la caméra sous Android 9 et versions antérieures

Gestion des tampons dans Android 10

Figure 2. Interface Camera HAL dans Android 10 utilisant les API de gestion de tampon

Implémentation des API de gestion des tampons

Pour mettre en œuvre les API de gestion du buffer, la caméra HAL doit :

La caméra HAL utilise les méthodes requestStreamBuffers et returnStreamBuffers dans ICameraDeviceCallback.hal pour demander et renvoyer des tampons. Le HAL doit également implémenter la méthode signalStreamFlush dans ICameraDeviceSession.hal pour signaler au HAL de la caméra de renvoyer les tampons.

requestStreamBuffers

Utilisez la méthode requestStreamBuffers pour demander des tampons au framework de caméra. Lors de l'utilisation des API de gestion de tampon HAL3 de la caméra, les demandes de capture de la structure de la caméra ne contiennent pas de tampons de sortie, c'est-à-dire que le champ bufferId dans StreamBuffer est 0 . Par conséquent, le HAL de la caméra doit utiliser requestStreamBuffers pour demander des tampons au framework de caméra.

La méthode requestStreamBuffers permet à l'appelant de demander plusieurs tampons à partir de plusieurs flux de sortie en un seul appel, ce qui permet de réduire le nombre d'appels HIDL IPC. Cependant, les appels prennent plus de temps lorsque davantage de tampons sont demandés en même temps, ce qui peut affecter négativement la latence totale de la demande au résultat. De plus, étant donné que les appels à requestStreamBuffers sont sérialisés dans le service de caméra, il est recommandé que le HAL de la caméra utilise un thread dédié à haute priorité pour demander des tampons.

Si une demande de tampon échoue, la caméra HAL doit être capable de gérer correctement les erreurs non fatales. La liste suivante décrit les raisons courantes pour lesquelles les demandes de tampon échouent et comment elles doivent être traitées par la caméra HAL.

  • L'application se déconnecte du flux de sortie : il s'agit d'une erreur non fatale. La caméra HAL doit envoyer ERROR_REQUEST pour toute demande de capture ciblant un flux déconnecté et être prête à traiter les demandes suivantes normalement.
  • Timeout : cela peut se produire lorsqu'une application est occupée à effectuer un traitement intensif tout en conservant certains tampons. La caméra HAL doit envoyer ERROR_REQUEST pour les demandes de capture qui ne peuvent pas être satisfaites en raison d'une erreur de délai d'attente et être prête à traiter les demandes suivantes normalement.
  • Le framework de caméra prépare une nouvelle configuration de flux : le HAL de la caméra doit attendre la fin du prochain appel configureStreams avant d'appeler à nouveau requestStreamBuffers .
  • La caméra HAL a atteint sa limite de tampon (le champ maxBuffers ) : la caméra HAL doit attendre de renvoyer au moins un tampon du flux avant d'appeler à nouveau requestStreamBuffers .

returnStreamBuffers

Utilisez la méthode returnStreamBuffers pour renvoyer des tampons supplémentaires au framework de caméra. Le HAL de la caméra renvoie normalement des tampons à la structure de la caméra via la méthode processCaptureResult , mais il ne peut prendre en compte que les demandes de capture qui ont été envoyées au HAL de la caméra. Avec la méthode requestStreamBuffers , il est possible que l'implémentation HAL de la caméra conserve plus de tampons que ce qui a été demandé par le framework de la caméra. C’est à ce moment-là 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 la caméra n’a pas besoin d’appeler la méthode returnStreamBuffers .

signalStreamFlush

La méthode signalStreamFlush est appelée par le framework de caméra pour indiquer à la caméra HAL de renvoyer tous les tampons disponibles. Ceci est normalement appelé lorsque le framework de caméra est sur le point d'appeler configureStreams et doit vider le pipeline de capture de caméra. Semblable à la méthode returnStreamBuffers , si une implémentation HAL de caméra 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 de caméra a appelé signalStreamFlush , le framework arrête d'envoyer de nouvelles demandes de capture au HAL de la caméra jusqu'à ce que tous les tampons aient été renvoyés au framework de caméra. Lorsque tous les tampons sont renvoyés, les appels de la méthode requestStreamBuffers échouent et la structure de la caméra peut continuer son travail dans un état propre. Le framework de caméra appelle ensuite la méthode configureStreams ou processCaptureRequest . Si l'infrastructure de la caméra appelle la méthode configureStreams , la caméra HAL peut recommencer à demander des tampons après le retour réussi de l'appel configureStreams . Si l'infrastructure de la caméra appelle la méthode processCaptureRequest , la caméra HAL peut commencer à demander des tampons pendant 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, le HAL peut abandonner les demandes de capture en attente avec ERROR_REQUEST pour vider le pipeline dès que possible. Lorsque la méthode signalStreamFlush est appelée, le HAL doit terminer normalement toutes les demandes de capture en attente et renvoyer tous les tampons au framework de caméra.

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 la structure de la caméra peut appeler d'autres API de blocage avant que HAL ne 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 la caméra dans un ordre différent de celui dans lequel elles ont été appelées dans le cadre de la caméra. Pour résoudre ce problème d'asynchronie, le champ streamConfigCounter a été ajouté à StreamConfiguration et ajouté en tant qu'argument à la méthode signalStreamFlush . L'implémentation HAL de la caméra doit utiliser l'argument streamConfigCounter pour déterminer si un appel signalStreamFlush arrive plus tard que son appel configureStreams correspondant. Voir la figure 3 pour un exemple.

Gérer les appels qui arrivent en retard

Figure 3. Comment la caméra HAL doit détecter et gérer les appels signalStreamFlush qui arrivent en retard

Changements de comportement lors de la mise en œuvre des API de gestion des tampons

Lorsque vous utilisez les API de gestion de tampon pour implémenter la logique de gestion de tampon, tenez compte des changements de comportement possibles suivants dans la mise en œuvre de la caméra et de la caméra HAL :

  • Les demandes de capture arrivent au HAL de la caméra plus rapidement et plus fréquemment : sans API de gestion des tampons, la structure de la caméra demande des tampons de sortie pour chaque demande de capture avant d'envoyer une demande de capture au HAL de la caméra. Lors de l'utilisation des API de gestion des tampons, le framework de caméra n'a plus besoin d'attendre les tampons et peut donc envoyer plus tôt des demandes de capture au HAL de la caméra.

    De plus, sans API de gestion des tampons, la structure de la caméra arrête d'envoyer des requêtes de capture si l'un des flux de sortie de la requête de capture a atteint le nombre maximum de tampons que le HAL peut contenir en même temps (cette valeur est désignée par le HAL de la caméra dans le HalStream::maxBuffers dans la valeur de retour d'un appel configureStreams ). Avec les API de gestion de tampon, ce comportement de limitation n'existe plus et l'implémentation de la caméra HAL ne doit pas accepter les appels processCaptureRequest lorsque la HAL a trop de demandes de capture en file d'attente.

  • La latence des appels requestStreamBuffers varie considérablement : il existe de nombreuses raisons pour lesquelles un appel requestStreamBuffers peut prendre plus de temps que la moyenne. Par 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 à chaque appel.
    • L'application contient des tampons et est en cours de traitement. Cela peut entraîner un ralentissement des demandes de tampon ou un délai d'attente en raison d'un manque de tampons ou d'un processeur occupé.

Stratégies de gestion des tampons

Les API de gestion des tampons permettent de mettre en œuvre différents types de stratégies de gestion des tampons. Certains exemples sont:

  • Rétrocompatible : HAL demande des tampons pour une demande 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 de tampon, nécessitant très peu de modifications de code dans le HAL de la caméra existante.
  • Économies de mémoire maximisées : la caméra HAL ne demande que des tampons de sortie juste avant qu'il soit nécessaire d'en remplir un. Cette stratégie permet d’optimiser les économies de mémoire. L'inconvénient potentiel est davantage de perturbations dans le pipeline de caméra lorsque les demandes de tampon prennent un temps inhabituellement long à se terminer.
  • Mise en cache : la caméra HAL met en cache quelques tampons afin qu'elle soit moins susceptible d'être affectée par une demande de tampon lente occasionnelle.

La caméra HAL peut adopter différentes stratégies pour des cas d'utilisation particuliers, par exemple en utilisant la stratégie d'économie de mémoire maximisée pour les cas d'utilisation qui utilisent beaucoup de mémoire et en utilisant la stratégie de compatibilité ascendante pour d'autres cas d'utilisation.

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

La caméra externe HAL a été introduite dans Android 9 et peut être trouvée dans l'arborescence des sources à l' 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 caméra externe HAL implémente la stratégie d'économie de mémoire maximisée mentionnée dans Stratégies de gestion de tampon en quelques centaines de lignes de code C++.