Software decoding — le processus de décompression des données multimédia par le CPU à l'aide de bibliothèques logicielles, sans utiliser les blocs matériels du SoC. Les décodeurs logiciels sont implémentés comme des bibliothèques multiplateformes : FFmpeg avec libavcodec et dav1d pour AV1. Selon la documentation FFmpeg (2026), libavcodec prend en charge plus de 200 codecs, ce qui fait du software decoding le seul moyen de lire les formats rares.
Points clés
Software decoding est une méthode de décompression des données multimédia où toutes les opérations de calcul sont effectuées sur les cœurs CPU polyvalents. Contrairement au décodage matériel, où chaque codec possède un bloc physique dédié, un décodeur logiciel est un code ordinaire qui exécute les mêmes algorithmes à l'aide d'instructions du processeur.
Les décodeurs logiciels sont écrits en C/C++ avec des optimisations pour des architectures CPU spécifiques : instructions SIMD ARM NEON pour les appareils mobiles, Intel SSE/AVX pour les ordinateurs de bureau. La bibliothèque libavcodec de FFmpeg contient des dizaines de milliers de lignes de code assembleur optimisé pour différentes plateformes, permettant au décodage logiciel d'atteindre des performances décentes même pour des formats lourds comme AV1 sur des CPUs puissants.
Le principal avantage du décodage logiciel est sa polyvalence. Si un décodeur matériel ne prend en charge que 4 à 5 formats principaux (H.264, H.265, VP9, AV1), FFmpeg peut décoder plus de 200 codecs : des AV1 et H.265 modernes aux Sorenson Spark, RealVideo et Motion JPEG d'archives. Cela fait du décodage logiciel un outil indispensable pour les applications travaillant avec des données multimédia non standard — comme les éditeurs vidéo professionnels, les systèmes de vidéosurveillance et les lecteurs spécialisés.
Le décodage logiciel suit les mêmes étapes que le décodage matériel, mais sur un CPU polyvalent. Chaque étape est implémentée sous forme de fonctions appelées séquentiellement pour chaque macrobloc ou trame. La différence clé est la flexibilité : le développeur peut modifier le pipeline, ajouter des filtres et du post-traitement entre les étapes de décodage.
Un décodeur logiciel typique se compose de modules qui implémentent des étapes d'algorithme individuelles. Le module de décodage entropique lit le flux binaire et reconstruit les coefficients DCT quantifiés. Pour H.264, ce module implémente CABAC (Codage Arithmétique Binaire Adaptatif au Contexte) — un algorithme complexe avec des branches conditionnelles difficile à accélérer matériellement mais qui s'exécute efficacement sur un CPU avec un bon prédicteur de branchement.
Le module de quantification inverse multiplie les coefficients par le pas de quantification, et le module DCT inverse applique la transformée en cosinus discrète. L'implémentation logicielle de la DCT inverse utilise l'algorithme rapide de Chen ou l'algorithme de Loeffler, qui réduisent le nombre d'opérations de multiplication-accumulation de 4096 à 256 pour un bloc 8x8. Les instructions SIMD NEON (ARM) ou SSE (x86) permettent de traiter 4 à 8 coefficients par instruction, offrant une accélération de 4 à 8 fois par rapport au code scalaire.
Le module de compensation de mouvement est le plus gourmand en mémoire. Il extrait des régions des trames de référence selon les vecteurs de mouvement et applique une interpolation subpixel. Pour H.265, la précision d'interpolation atteint 1/8 de pixel, nécessitant un filtre FIR à 8 taps pour la luminance et 4 taps pour la chrominance. L'implémentation logicielle doit charger de grandes quantités de données de trames de référence depuis le cache, faisant de la compensation de mouvement un goulot d'étranglement lors du décodage de hautes résolutions sur CPU.
Les processeurs mobiles modernes, comme l'Apple A17 ou le Qualcomm Snapdragon 8 Gen 2, disposent de 6 à 8 cœurs avec des performances suffisantes pour le décodage logiciel de 1080p H.264 sans perte de trames. Cependant, pour le contenu 4K, surtout aux formats H.265 et AV1, le décodage logiciel sur CPU peut rencontrer des difficultés : la charge typique sur tous les cœurs atteint 70 à 90 %, ce qui est critique pour le multitâche. Les gros cœurs (Apple Performance, Qualcomm Kryo Prime) offrent environ 4 à 5 fois les performances par rapport aux petits cœurs économes, mais consomment proportionnellement plus d'énergie.
Le marché des décodeurs logiciels compte plusieurs bibliothèques clés, chacune optimisée pour son créneau. Le choix du décodeur dépend des formats requis, de la plateforme et des restrictions de licence.
FFmpeg est la norme de facto pour le décodage logiciel dans l'industrie. La bibliothèque libavcodec inclut des décodeurs pour tous les codecs principaux et la plupart des codecs rares, prend en charge tous les conteneurs (MP4, MKV, AVI, MOV, WebM) et fonctionne sur toutes les plateformes. FFmpeg est sous licence LGPL/GPL, ce qui nécessite le respect des conditions de licence pour une utilisation commerciale. Sur les appareils mobiles, FFmpeg est utilisé via des wrappers : ffmpeg-kit pour iOS et Android, mobile-ffmpeg pour React Native.
Dav1d est un décodeur logiciel AV1 de VideoLAN (développeurs de VLC), écrit en C avec des optimisations SIMD. Son objectif principal est le décodage logiciel le plus rapide possible d'AV1 sur des CPUs sans support matériel. Dav1d est 30 à 50 % plus rapide que le décodeur de référence libaom de l'Alliance for Open Media grâce à des optimisations agressives : gestion manuelle du cache, compilation JIT pour les filtres de post-traitement et vectorisation des fonctions critiques.
Sur les appareils mobiles, dav1d peut décoder du 1080p AV1 en temps réel sur les SoCs phares (Apple A16+, Snapdragon 8 Gen 2+), mais le 4K nécessite un CPU puissant. Par exemple, sur Apple M1, dav1d logiciel atteint environ 60 FPS pour du 4K AV1, tandis que sur Snapdragon 8 Gen 2 il atteint environ 35 FPS. Pour une lecture stable du 4K AV1 sur les appareils mobiles, le support matériel est toujours recommandé.
| Décodeur | Formats | Plateformes | Licence |
|---|---|---|---|
| libavcodec | 200+ codecs | Toutes | LGPL/GPL |
| dav1d | AV1 | Toutes | BSD 2-Clause |
| libaom | AV1 | Toutes | BSD 2-Clause |
| MediaFoundation | H.264, H.265 | Windows | Propriétaire |
Le choix entre décodage logiciel et matériel est un compromis entre compatibilité et efficacité. Le tableau ci-dessous présente une comparaison détaillée des caractéristiques clés.
| Paramètre | Software Decoding | Hardware Decoding |
|---|---|---|
| Formats pris en charge | 200+ codecs | 4–6 codecs |
| Consommation énergétique | 1,5–5 W | 0,2–0,8 W |
| Personnalisation | Contrôle total du pipeline | Uniquement via API |
| Latence | 30–80 ms | 5–15 ms |
| Dissipation thermique | Élevée (45–50 C) | Faible (35–40 C) |
| Mise à jour des codecs | Via mise à jour de la bibliothèque | Uniquement avec nouveau SoC |
Le décodage logiciel offre une flexibilité maximale : le développeur peut modifier les algorithmes, ajouter des filtres personnalisés et implémenter ses propres pipelines de traitement. Par exemple, dans les applications de montage vidéo, chaque étape de décodage peut être redirigée vers le GPU pour la correction des couleurs ou la superposition d'effets — cela n'est possible qu'avec un contrôle logiciel sur le décodage.
Cependant, le prix de la flexibilité est la consommation d'énergie. Pour les appareils mobiles avec une batterie de 3000–5000 mAh, le décodage logiciel continu réduit le temps de visionnage de 10–15 heures (matériel) à 2–4 heures. L'échauffement du CPU à 45–50 degrés peut également provoquer un throttling — une réduction de la fréquence du processeur pour éviter la surchauffe, entraînant des chutes de trames et une dégradation de l'expérience utilisateur.
Examinons une implémentation pratique du décodage logiciel sur les deux plateformes mobiles. Sur iOS, le décodage logiciel est utilisé via FFmpeg, et sur Android — via la même bibliothèque avec un wrapper Java/Kotlin.
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
class SoftwareDecoder {
AVCodecContext* codecCtx;
public:
bool init(const char* filename) {
AVFormatContext* fmtCtx = nullptr;
avformat_open_input(&fmtCtx, filename, nullptr, nullptr);
avformat_find_stream_info(fmtCtx, nullptr);
int videoStream = av_find_best_stream(
fmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0
);
AVCodec* decoder = avcodec_find_decoder(
fmtCtx->streams[videoStream]->codecpar->codec_id
);
codecCtx = avcodec_alloc_context3(decoder);
avcodec_parameters_to_context(codecCtx,
fmtCtx->streams[videoStream]->codecpar);
avcodec_open2(codecCtx, decoder, nullptr);
return true;
}
AVFrame* decodePacket(AVPacket* packet) {
avcodec_send_packet(codecCtx, packet);
AVFrame* frame = av_frame_alloc();
int ret = avcodec_receive_frame(codecCtx, frame);
return (ret >= 0) ? frame : nullptr;
}
};
Le code montre un pipeline FFmpeg minimal pour le décodage logiciel. avformat_open_input ouvre le fichier et détermine le format du conteneur, avcodec_find_decoder trouve automatiquement un décodeur approprié pour n'importe quel codec. La méthode decodePacket utilise la nouvelle API (avcodec_send_packet / avcodec_receive_frame), qui prend en charge le décodage multithread avec le drapeau AV_CODEC_FLAG_LOW_DELAY activé pour les applications en temps réel.
class SoftwareDecoder(private val context: Context) {
fun decodeVideo(inputPath: String, outputFolder: String) {
val cmd = "-i $inputPath -vf fps=1 $outputFolder/frame_%04d.jpg"
FFmpegExecutor(context).executeCommand(cmd) { rc ->
Log.d("Decoder", "Finished with rc: $rc")
}
}
fun getFrameCount(filePath: String): Int {
val probe = MediaMetadataRetriever()
probe.setDataSource(filePath)
val duration = probe.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_DURATION
)?.toIntOrNull() ?: 0
val fps = probe.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT
)?.toIntOrNull() ?: 0
probe.release()
return fps
}
}
L'exemple en Kotlin utilise FFmpegExecutor pour extraire une trame par seconde d'une vidéo. Le paramètre -vf fps=1 crée un filtre qui ignore 59 trames sur 60, réduisant la charge CPU. Cette approche est utile pour créer des aperçus et des placeholders dans les applications mobiles. Pour le décodage logiciel en temps réel, il est recommandé d'utiliser l'API bas niveau de libavcodec directement via JNI.
#include <dav1d/dav1d.h>
int decode_av1_frame(const uint8_t* data, size_t size) {
Dav1dContext* ctx = nullptr;
Dav1dSettings settings = { 0 };
dav1d_default_settings(&settings);
settings.n_threads = 4;
dav1d_open(&ctx, &settings);
Dav1dData dav1d_data = { 0 };
dav1d_data_wrap(&dav1d_data, data, size, nullptr, nullptr);
Dav1dPicture pic = { 0 };
if (dav1d_send_data(ctx, &dav1d_data) == 0) {
dav1d_get_picture(ctx, &pic);
}
dav1d_close(&ctx);
return pic.p.w;
}
Dav1d fournit une API minimaliste : dav1d_open crée un contexte de décodeur avec un nombre spécifié de threads, dav1d_send_data accepte le flux binaire compressé, dav1d_get_picture renvoie la trame décodée au format YUV420. Pour les appareils mobiles, le nombre optimal de threads (n_threads) est le nombre de cœurs CPU de performance moins un, pour laisser des ressources au thread de l'interface utilisateur. Dav1d prend également en charge Dav1dPicAllocator pour la gestion de la mémoire et éviter les copies inutiles lors du transfert de trames vers le GPU.
Malgré une consommation d'énergie plus élevée, le décodage logiciel est indispensable dans plusieurs scénarios où le décodage matériel ne peut pas fournir la fonctionnalité requise. Comprendre ces scénarios aide les développeurs à prendre des décisions architecturales.
Les décodeurs matériels ne prennent en charge que les formats modernes. Si l'application travaille avec des enregistrements d'archives, de la vidéosurveillance (MJPEG, H.263), des codecs professionnels (ProRes, DNxHD, CineForm) ou du contenu provenant de sources tierces — le décodage logiciel via FFmpeg sera la seule option. ProRes est décodé uniquement par logiciel sur tous les appareils sauf les puces Apple A13+ avec support matériel. Pour H.263, il n'y a aucun support matériel sur aucun SoC moderne — seulement le décodage logiciel.
Le décodage logiciel fournit un accès complet à chaque étape de traitement de la trame. C'est essentiel pour les applications qui doivent appliquer des filtres (flou, réduction de bruit, accentuation) directement sur les données décodées avant la sortie. Les filtres FFmpeg permettent de construire des chaînes complexes : décodage -> correction des couleurs -> redimensionnement -> superposition de sous-titres -> encodage — le tout au sein d'une seule bibliothèque sans transfert de données entre différentes API.
L'architecture recommandée pour un lecteur multimédia est hybride : décodage matériel comme principal, décodage logiciel comme fallback. Avant la lecture, l'application vérifie la disponibilité d'un décodeur matériel pour le codec donné. Si aucun décodeur n'est trouvé, le décodage logiciel est lancé via FFmpeg. Cette stratégie garantit une compatibilité maximale sans sacrifier les performances pour les formats principaux. Les vérifications de disponibilité doivent être effectuées à chaque lancement, car le support matériel peut varier même sur des appareils du même modèle en raison de différentes révisions de SoC.
Foire aux questions
Le CPU est un processeur polyvalent qui effectue de nombreuses tâches différentes. Pour le décodage, il utilise des unités de calcul partagées et une mémoire cache, qui consomment de l'énergie même lors de l'exécution d'une seule tâche. Un décodeur matériel est un circuit hautement spécialisé avec un pipeline fixe, où chaque transistor est dédié uniquement au décodage, ce qui réduit radicalement la consommation d'énergie.
Pour H.264/H.265 — libavcodec de FFmpeg avec optimisations SIMD activées. Pour AV1 — dav1d, qui est 30 à 50 % plus rapide que le libaom de référence. Sur les appareils mobiles, les performances de dav1d permettent le décodage en temps réel de 1080p AV1 sur les SoCs phares (A16+, Dimensity 9200+).
Oui, FFmpeg est porté sur les deux plateformes. Pour iOS, utilisez ffmpeg-kit — une compilation prête avec prise en charge de tous les codecs et formats. Pour Android — mobile-ffmpeg ou compilez FFmpeg via le NDK. Tenez compte des restrictions de licence GPL/LGPL pour la distribution commerciale.
Le décodage en temps réel signifie que le CPU peut décoder les trames plus vite qu'elles ne sont affichées à l'écran (généralement 30 ou 60 FPS). Pour du 1080p H.264, un CPU mobile moderne gère cela avec une marge, utilisant environ 30 à 50 % d'un cœur de performance. Pour du 4K H.265, le temps réel sur CPU n'est possible que sur les SoCs phares avec 70 à 90 % de charge sur tous les cœurs.
Utilisez le décodage multithread (parallélisme au niveau des trames) via FFmpeg avec le drapeau thread_count, définissez skip_frame sur les B-frames (si acceptable pour le scénario), réduisez la résolution via le filtre scale avant le décodage. Pour AV1 avec dav1d, utilisez n_threads = nombre de cœurs CPU moins un.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi