HandBrake et décodage matériel sous macOS

J’en ai parlé sur MacG récemment, la version 1.7 d’HandBrake améliore un point intéressant sur Mac : il est possible de passer par le décodeur matériel pour les vidéos.

Depuis une quinzaine d’années, les Mac peuvent décoder de la vidéo matériellement, d’abord dans le GPU puis au fil des années avec des blocs dédiés dans les puces Apple. Cette solution permet de décoder facilement le H.264 puis le H.265 (HEVC) et même l’AV1 sur les derniers Mac. En parallèle du décodage, on a aussi de l’encodage depuis un moment, dans les GPU ou les puces Apple (encore une fois). HandBrake peut encoder matériellement depuis un moment (j’en avais parlé en 2020) mais le décodage, lui, passait encore par un décodeur logiciel.

La version 1.7.1 (pour les tests) amène donc deux choses. Des presets pour l’encodage matériel (ça simplifie les choses, pas besoin de sélectionner VideoToolbox manuellement) et une option pour décoder matériellement.

Pour l’encodage, il suffit d’afficher les préréglages : la section Hardware propose soit H.265 Apple VideoToolbox 2160p 4K, soit H.265 Apple VideoToolbox 1080p (je n’ai pas le H.264 sur mes trois Mac).

Pour le décodage, il faut aller dans HandBrake -> Réglages -> Avancé et cocher deux cases. La première (Activer les décodeur matériels VideoToolbox) active le décodage en parallèle de l’encodage. La seconde, Utiliser également en combinaison avec des encodeurs logiciels, fait ce qu’elle dit : c’est pour décoder matériellement et encoder logiciellement.

Ce n’est pas activé par défaut et pour une bonne raison, on va le voir : dans certains cas, ça peut ralentir l’encodage. C’est un peu la conclusion, mais le décodeur matériel n’est généralement pas fait pour décoder rapidement mais pour décoder sans employer le CPU. Comme on veut généralement du temps réel, il n’y a pas nécessairement besoin de décoder plusieurs centaines d’images par seconde. Malgré tout, ça de l’intérêt dans un cas précis : on peut encoder rapidement pratiquement sans utiliser le CPU quand on combine encodeur et décodeur. Ce n’est pas nécessairement le plus rapide, mais c’est transparent à l’usage.

Quelques essais

J’ai d’abord effectué plusieurs essais sur plusieurs Mac, en partant de Big Buck Bunny encodé en 4K et en H.264.

Sur un Mac mini M1, l’encodage logiciel (preset Apple TV 1080p30) prend 470 secondes sans aides. C’est du pur software dépendant uniquement du processeur. Un Mac mini 2018 (Core i5) prend 788 secondes avec ses six coeurs, un MacBook Pro 2017 (Core i7) 891 secondes avec ses quatre coeurs avec Hyper-Threading. Sur le coup, les optimisations sur le M1 fonctionnent bien…

Avec le preset H.265 1080p (qui passe par l’encodeur matériel, donc), le Mac mini M1 prend 90 secondes, mais il y a une bonne charge CPU tout de même pour le décodage. Le Mac mini 2018 encode avec sa puce T2 et prend 147 secondes avec une charge encore élevée. Le MacBook Pro 2017 avec son GPU Intel HD, qui est beaucoup plus lent : 478 secondes. J’ai aussi relié le MacBook Pro à un eGPU à base de Radeon RX 6600, et c’est nettement plus rapide : 180 secondes. Il est amusant de noter que l’encodage matériel sur le MacBook Pro prend à peu près le même temps que l’encodage logiciel sur un simple M1.

Avec le décodage matériel

Maintenant, avec le décodeur matériel. Pour l’encodage logiciel, on a toujours une forte charge CPU avec le Mac mini, ce qui est logique, et le temps de calcul est équivalent (480 secondes). Avec le Mac mini 2018, c’est la même chose : on gagne 4 secondes (784 secondes). Et avec le MacBook Pro 2017 (et son GPU Intel), on reste dans la même zone : 879 secondes. En fait, le point qui bloque ici est l’encodage logiciel : on est largement en-dessous des capacités du décodeur et même en partant d’un fichier en 4K (et en H.264), le décodage logiciel n’est en réalité pas un souci.

Avec l’encodage matériel, c’est plus lent sur le Mac mini M1 si on décode matériellement (210 secondes) mais l’usage CPU est très faible (une petite partie des coeurs basse consommation). En fait, le décodeur logiciel décode probablement beaucoup plus lentement que l’encodeur matériel n’encode et on a donc un goulet d’étranglement. Sur le Mac mini 2018, on reste dans le même ordre de grandeur (142 secondes, un gain faible) mais on gagne en utilisation CPU. C’est la même chose sur le MacBook pro : l’usage CPU est très faible et l’encodage est donc transparent, même si ça prend pas mal de temps à cause des limites du GPU d’Intel : 395 secondes. On gagne un peu de temps, mais beaucoup de CPU. Avec un eGPU, on gagne par contre pas mal : 129 secondes avec l’encodage et le décodage.

Une seconde série

Pour vérifier l’intérêt du décodage, j’ai donc pris le même fichier, mais en H.265 (qui est un peu plus compliqué à décoder logiciellement). Je n’ai pas pris l’AV1 (lourd à décoder) pour une bonne raison : Apple n’intègre le décodage AV1 que dans les MacBook Pro M3.

J’ai testé uniquement sur l’encodage logiciel : il prend 670 secondes sur le Mac mini M1 avec le décodage logiciel et 568 secondes avec le décodage matériel, un gain important. Sur le Mac mini 2018, 844 secondes sans assistance, 848 secondes avec. Et sur le MacBook Pro 2017, on est à 999 secondes sans assistance, 943 secondes avec le GPU Intel et 960 secondes avec l’eGPU qui décode matériellement. C’est sur le CPU le plus faible que c’est logiquement le plus visible : on perd un peu plus pour le décodage logiciel.

On le voit, la différence est (un peu) plus grande. Mais en pratique, on a deux limites : dans un encodage logiciel, c’est le CPU qui limite : il encode lentement et les quelques cycles gagnés en évitant de décoder ne permettent pas un gain faramineux. C’est (un peu) mieux mais pas beaucoup. Dans un encodage matériel, c’est le décodeur qui limite : il décode moins vite qu’un CPU. Le cas intéressant, donc, c’est essentiellement un décodage matériel couplé à l’encodage matériel quand le temps de calcul n’est pas important : on évite d’utiliser le CPU, qui est disponible pour d’autres tâches. Ce qui explique probablement que l’option n’est pas cochée par défaut.