Analyse approfondie : NON : vidéo

Dale Curtis
Dale Curtis

Je suis Dale Curtis, responsable de l'ingénierie pour la lecture de médias dans Chromium. Mon équipe est responsable des API Web pour la lecture de vidéos, telles que MSE et WebCodecs, ainsi que des éléments internes spécifiques à la plate-forme impliqués dans le démuxing, le décodage et le rendu audio et vidéo.

Dans cet article, je vais vous présenter l'architecture de rendu vidéo de Chromium. Bien que certains détails concernant l'extensibilité soient probablement spécifiques à Chromium, la plupart des concepts et conceptions abordés ici s'appliquent à d'autres moteurs de rendu et même aux applications de lecture natives.

L'architecture de lecture de Chromium a considérablement changé au fil des ans. Bien que nous n'ayons pas commencé par l'idée d'une pyramide du succès telle que décrite dans le premier article de cette série, nous avons finalement suivi des étapes similaires: fiabilité, performances, puis extensibilité.

Au début, le rendu vidéo était assez simple : il s'agissait d'une boucle For pour choisir les images vidéo décodées par logiciel à envoyer au compositeur. Pendant des années, cette solution s'est avérée suffisamment fiable, mais à mesure que la complexité du Web augmentait, la nécessité de gagner en performances et en efficacité s'est traduite par des changements d'architecture. De nombreuses améliorations nécessitaient des primitives spécifiques au système d'exploitation. Par conséquent, notre architecture a dû devenir plus extensible pour s'adapter à toutes les plates-formes de Chromium.

Schéma du flux de rendu vers différentes plates-formes Chromium.

Le rendu vidéo comporte deux étapes : le choix des éléments à diffuser et la transmission efficace de ces informations. Par souci de lisibilité, je vais vous présenter la diffusion efficace avant d'expliquer comment Chromium choisit les éléments à diffuser.

Termes et mise en page

Comme cet article est axé sur le rendu, je n'aborderai que brièvement les aspects de démuxage et de décodage du pipeline.

Octets entrants et paquets structurés en sortie.

Dans notre monde moderne axé sur la sécurité, le décodage et le démuxage nécessitent une attention particulière. Les analyseurs binaires sont des environnements cibles riches, et la lecture de contenus multimédias regorge d'analyses binaires. De ce fait, les problèmes de sécurité survenant dans les analyseurs multimédias sont extrêmement courants.

Chromium pratique une défense en profondeur afin de réduire le risque que nos utilisateurs rencontrent des problèmes de sécurité. Concrètement, cela signifie que le démuxage et le décodage logiciel s'effectuent toujours dans un processus à faible privilège, tandis que le décodage matériel s'effectue dans un processus disposant de droits suffisants pour communiquer avec le GPU du système.

Bacs à sable Chromium pour le moteur de rendu, le GPU et les processus audio.

Le mécanisme de communication interprocessus de Chromium s'appelle Mojo. Même si nous n'entrerons pas dans les détails de Mojo dans cet article, en tant que couche d'abstraction entre les processus, il s'agit d'une pierre angulaire du pipeline média extensible de Chromium. Il est important d'en tenir compte lorsque vous parcourez le pipeline de lecture, car il alimente l'orchestration complexe des composants multiprocessus qui interagissent pour recevoir, décoder, décoder et afficher les médias.

Il y a tant de bits

Pour comprendre les pipelines de rendu vidéo actuels, il faut savoir pourquoi la vidéo est spéciale: la bande passante. Une lecture avec une résolution de 3 840 x 2 160 (4K) à 60 images par seconde utilise entre 9 et 12 gigabits/seconde de bande passante mémoire. Bien que les systèmes modernes puissent avoir une bande passante maximale de l'ordre de plusieurs centaines de gigabits par seconde, la lecture vidéo représente toujours une partie importante. Sans précaution, la bande passante totale peut facilement se multiplier en raison des copies ou des trajets entre la mémoire GPU et le processeur.

L'objectif d'un moteur de lecture vidéo moderne est de minimiser la bande passante entre le décodeur et l'étape de rendu finale. Pour cette raison, le rendu vidéo est en grande partie dissocié du pipeline principal de rendu de Chromium. Plus précisément, du point de vue de notre pipeline de rendu principal, la vidéo n'est qu'un trou de taille fixe avec une opacité. Chromium y parvient à l'aide d'un concept appelé surfaces, où chaque vidéo s'adresse directement à Viz.

Page Web avec un trou et une flèche indiquant "Vidéo ici".

En raison de la popularité de l'informatique mobile, la puissance et l'efficacité sont des priorités absolues pour la génération actuelle. En conséquence, le décodage et le rendu sont plus couplés que jamais au niveau matériel, ce qui donne l'impression que la vidéo ressemble à un trou avec de l'opacité, même par rapport au système d'exploitation lui-même. Souvent, les décodeurs au niveau de la plate-forme ne fournissent que des tampons opaques que Chromium transmet au système de composition au niveau de la plate-forme sous la forme de superpositions.

Page Web avec un trou et une flèche indiquant "Vidéo ici", entourée d'une case représentant le système d'exploitation.

Chaque plate-forme possède son propre type de superpositions avec lesquelles les API de décodage de la plate-forme fonctionnent de concert. Windows dispose de Direct Composition et de Media Foundation Transforms, de CoreAnimation Layers et de VideoToolbox pour macOS, de SurfaceView et de MediaCodec pour Android, et de Linux de VASurfaces et de VA-API. Les abstractions de Chromium associées à ces concepts sont gérées respectivement par les interfaces OverlayProcessor et mojo::VideoDecoder.

Dans certains cas, il est possible que ces tampons puissent être mappés dans la mémoire système. Ils n'ont donc pas besoin d'être opaques et ne consomment aucune bande passante avant d'y accéder. Chromium les appelle GpuMemoryBuffers. Sous Windows, elles sont sauvegardées par les tampons DXGI, sur les IOSurfaces de macOS, sur les AHardwareBuffers Android et sur les tampons DMA de Linux. Bien que la lecture vidéo n'ait généralement pas besoin de cet accès, ces tampons sont importants pour l'enregistrement vidéo afin de garantir une bande passante minimale entre l'appareil de capture et les éventuels encodeurs.

Schéma des tampons mentionnés dans le texte précédent.

Étant donné que le GPU est souvent responsable du décodage et de l'affichage, l'utilisation de ces tampons opaques (également souvent) garantit que les données vidéo à bande passante élevée ne quittent jamais le GPU. Comme nous l'avons vu précédemment, la conservation des données sur le GPU est extrêmement importante pour l'efficacité, en particulier pour les résolutions et les fréquences d'images élevées.

Plus nous pouvons exploiter les primitives du système d'exploitation, telles que les superpositions et les tampons GPU, moins la bande passante est dépensée pour le brassage inutile des octets vidéo. En gardant tout au même endroit, du décodage au rendu jusqu'au rendu, vous pouvez bénéficier d'une efficacité énergétique incroyable. Par exemple, lorsque Chromium a activé les superpositions sur macOS, la consommation d'énergie lors de la lecture de vidéos en plein écran a été réduite de moitié. Sur d'autres plates-formes comme Windows, Android et ChromeOS, nous pouvons utiliser des superpositions, même dans des cas qui ne sont pas en plein écran, ce qui permet d'économiser jusqu'à 50% presque partout.

Affichage

Nous avons vu les mécanismes de diffusion optimaux. Voyons comment Chromium choisit les éléments à diffuser. La pile de lecture de Chromium utilise une architecture basée sur "pull", ce qui signifie que chaque composant de la pile demande ses entrées à celui situé en dessous, dans un ordre hiérarchique. En haut de la pile se trouve le rendu des trames audio et vidéo. En dessous, il y a le décodage, le démuxage et enfin les E/S. Chaque image audio rendue fait avancer une horloge qui permet de choisir les images vidéo à afficher lorsqu'elle est combinée à un intervalle de présentation.

À chaque intervalle de présentation (à chaque actualisation de l'écran), le moteur de rendu vidéo est invité à fournir une image vidéo par un CompositorFrameSink associé à la SurfaceLayer mentionnée précédemment. Pour les contenus dont la fréquence d'images est inférieure à la fréquence d'affichage, cela signifie afficher la même image plusieurs fois. En revanche, si la fréquence d'images est supérieure à la fréquence d'affichage, certaines images ne sont jamais affichées.

Bien d'autres choses vous permettent de synchroniser l'audio et la vidéo de façon agréable pour les spectateurs. Pour en savoir plus sur la fluidité optimale des vidéos dans Chromium, consultez le projet Beurre. Il explique comment le rendu vidéo peut être divisé en séquences idéales représentant le nombre de fois où chaque image doit être affichée. Par exemple: "1 image à chaque intervalle d'affichage ([1], 60 FPS à 60 Hz)", "1 image tous les 2 intervalles ([2], 30 FPS à 60 Hz)", ou des modèles plus complexes tels que [2:3:2:3:2] (25 FPS à 60 Hz) couvrant plusieurs images et intervalles d'affichage distincts. Plus le moteur de rendu vidéo est proche de ce schéma idéal, plus la lecture a de chances d'être fluide.

Séquence de démuxing, de décodage et de rendu.

La plupart des plates-formes Chromium effectuent un rendu frame par frame, mais ce n'est pas le cas de toutes. Notre architecture extensible permet également un rendu par lot. Le rendu par lot est une technique d'efficacité dans laquelle le compositeur de l'OS est informé à l'avance de plusieurs images et gère leur publication selon un calendrier fourni par l'application.

Maintenant, c'est l'avenir ?

Nous avons expliqué comment Chromium exploite les primitives du système d'exploitation pour offrir une expérience de lecture optimale. Mais qu'en est-il des sites Web qui souhaitent aller au-delà de la lecture de vidéos de base ? Pouvons-nous leur offrir les mêmes primitives puissantes que Chromium lui-même utilise pour inaugurer la nouvelle génération de contenus Web ?

Nous pensons que oui ! À l'heure actuelle, l'extensibilité est au cœur de notre conception de la plate-forme Web. Nous avons collaboré avec d'autres navigateurs et développeurs pour créer de nouvelles technologies, telles que WebGPU et WebCodecs, afin que les développeurs Web puissent utiliser les mêmes primitives que Chromium lorsqu'ils communiquent avec l'OS. WebGPU est compatible avec les tampons GPU, et WebCodecs fournit des primitives de décodage et d'encodage de la plate-forme compatibles avec les systèmes de superposition et de tampon GPU mentionnés ci-dessus.

Relation entre WebCodecs et WebGPU.

Fin de la diffusion

Merci de votre attention, J'espère que vous comprenez maintenant mieux les systèmes de lecture modernes et comment Chromium génère plusieurs centaines de millions d'heures de visionnage chaque jour. Si vous souhaitez en savoir plus sur les codecs et les vidéos Web modernes, je vous recommande l'article H.264 is magic de Sid Bala, How Modern Video Players Work d'Erica Beaves et Packaging primée show with a primé Technology de Cyril Concolato.

Une illustration (la jolie !) d'Una Kravets.