Compiler FFmpeg sur Linux pour des Architectures Variées : GCC, Emscripten et MinGW-w64

La compilation de FFmpeg, une suite logicielle libre et open-source permettant d'enregistrer, convertir et diffuser des contenus audio et vidéo numériques, implique l'utilisation de l'outil de configuraton configure. Cet outil génère un Makefile adopté à l'environnement cible, en fonction des options spécifiées.

Les options de configuration se répartissent en plusieurs catégories principales :

  • Options d'aide et d'information : Pour lister les décodeurs, encodeurs, filtres, protocoles, etc. disponibles (ex: --list-decoders).
  • Options standard : Pour définir les chemins d'installation (--prefix, --bindir, --libdir) ou gérer la journalisation (--logfile).
  • Options de licence : Pour activer l'utilisation de code sous licence GPL (--enable-gpl) ou non-libre (--enable-nonfree).
  • Options de configuration générale : Pour contrôler la construction de bibliothèques statiques/partagées (--enable-static, --enable-shared), l'optimisation de la taille (--enable-small), ou la détection des fonctionnalités CPU (--disable-runtime-cpudetect).
  • Options de programmes et de documentation : Pour inclure ou exclure des outils comme ffmpeg, ffplay, ffprobe, ou la documentation.
  • Options de composants : Pour activer ou désactiver des bibliothèques spécifiques (libavcodec, libavformat, libswscale) ou des fonctionnalités comme le threading (--disable-pthreads).
  • Options de support de bibliothèques externes : Pour lier FFmpeg à des bibliothèques tierces comme libx264, libfdk-aac, libopus, etc. Ces options sont généralement préfixées par --enable-lib.
  • Options d'accélération matérielle : Pour activer des API comme CUDA, VAAPI, DXVA2, etc. (--enable-cuda-sdk, --disable-vaapi).
  • Options de chaîne d'outils (Toolchain) : Cruciales pour la compilation croisée, elles permettent de spécifier le compilateur (--cc), l'architecture (--arch), le système d'exploitation cible (--target-os), et les drapeaux supplémentaires (--extra-cflags, --extra-ldflags).
  • Options d'optimisation et de débogage : Pour contrôler l'utilisation de l'assembleur (--disable-asm), des instructions CPU spécifiques (--disable-sse2), ou des symboles de débogage (--disable-debug).

Pour une liste exhaustive et détaillée de toutes les options, il est recommandé d'exécuter ./configure --help dans le répertoire source de FFmpeg.

Compilation de FFmpeg avec GCC natif sur Linux

La compilation de FFmpeg en utilisant GCC sur un système Linux est le scénario le plus courant, produisant des binaires exécutables nativement sur la machine de compilation.

1. Installation des dépendances

Avant de commencer, installez les outils et bibliothèques nécessaires pour les encodeurs et fonctionnalités souhaitées. L'exemple suivant inclut YASM (assembleur), pkg-config et les bibliothèques de développement pour SDL2, H.264 (x264), H.265 (x265) et FDK-AAC.

sudo apt update
sudo apt install -y yasm pkg-config libsdl2-dev libx264-dev libx265-dev libfdk-aac-dev

2. Configuration et Compilation

Naviguez vers le répertoire source de FFmpeg. Utilisez le script configure avec les options appropriées pour activer les fonctionnalités désirées. Ici, nous activons les bibliothèques partagées, les encodeurs x264, x265 et fdk-aac, ainsi que les licences GPL et non-libres. Le préfixe d'installation est défini à /usr/local/ffmpeg.

./configure \
   --prefix=/usr/local/ffmpeg \
   --enable-shared \
   --enable-libx264 \
   --enable-libx265 \
   --enable-gpl \
   --enable-libfdk-aac \
   --enable-nonfree

make -j$(nproc)
sudo make install
  • --prefix=/usr/local/ffmpeg : Spécifie le répertoire d'installation.
  • --enable-shared : Construit les bibliothèques partagées.
  • --enable-libx264, --enable-libx265, --enable-libfdk-aac : Active le support pour les encodeurs H.264, H.265 et AAC (via FDK-AAC).
  • --enable-gpl, --enable-nonfree : Active l'utilisation de code sous licence GPL et non-libre, ce qui est nécessaire pour certains encodeurs comme FDK-AAC.

3. Configuration des chemins d'exécution

Après l'installation, assurez-vous que le système peut trouver les nouveaux exécutables et bibliothèques.

# Ajouter le chemin des binaires au PATH pour la session courante
export PATH="/usr/local/ffmpeg/bin:$PATH"

# Ajouter le chemin des bibliothèques au cache dynamique (pour toutes les sessions après redémarrage ou 'ldconfig')
echo "/usr/local/ffmpeg/lib" | sudo tee /etc/ld.so.conf.d/ffmpeg.conf
sudo ldconfig

Compilation de FFmpeg avec Emscripten pour WebAssembly

Emscripten est un compilateur permettant de convertir du code C/C++ en WebAssembly (Wasm), rendant ainsi FFmpeg exécutable dans un navigateur web ou d'autres environnements Wasm.

1. Installation et activation d'Emscripten SDK

Clonez le dépôt Emscripten SDK, installez la dernière version et activez l'environnement.

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
git pull
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
emcc -v # Vérifie si l'activation est réussie

2. Script de Configuration pour Emscripten (WebAssembly)

La configuration de FFmpeg pour Emscripten nécessite l'utilisation d'emconfigure et des options spécifiques à la compilation croisée. Ce script est conçu pour produire une version de FFmpeg optimisée pour le web, avec des fonctionnalités réduites pour minimiser la taille du binaire WebAssembly.

#!/bin/bash

echo "Démarrage de la configuration FFmpeg pour WebAssembly..."

# Répertoire de construction pour les artefacts Wasm
WASM_BUILD_DIR=$(pwd)/ffmpeg_wasm_build
mkdir -p "${WASM_BUILD_DIR}"

emconfigure ./configure \
   --cc="emcc" \
   --cxx="em++" \
   --ar="emar" \
   --ranlib="emranlib" \
   --prefix="${WASM_BUILD_DIR}" \
   --enable-cross-compile \
   --target-os=none \
   --arch=x86_32 \
   --cpu=generic \
   --enable-gpl \
   --enable-version3 \
   --enable-swresample \
   --disable-postproc \
   --disable-logging \
   --disable-programs \
   --disable-asm \
   --disable-doc \
   --disable-network \
   --disable-debug \
   --disable-iconv \
   --disable-sdl2 \
   --enable-avdevice \
   --enable-avformat \
   --disable-avfilter \
   --disable-decoders \
   --disable-encoders \
   --disable-hwaccels \
   --enable-demuxers \
   --disable-muxers \
   --disable-parsers \
   --disable-protocols \
   --disable-indevs \
   --disable-outdevs \
   --disable-filters \
   --enable-decoder=hevc \
   --enable-parser=hevc \
   --enable-decoder=h264 \
   --enable-parser=h264 \
   --enable-parser=aac \
   --enable-decoder=aac

echo "Configuration FFmpeg pour WebAssembly terminée."

  • --prefix="${WASM_BUILD_DIR}" : Définit le répertoire d'installation des bibliothèques compilées par Emscripten.
  • --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic : Indiquent à configure qu'il s'agit d'une compilation croisée pour une cible non native, avec une architecture générique.
  • Les nombreuses options --disable-* suivies par des --enable-* spécifiques : Une approche courante pour réduire la taille du binaire Wasm est de désactiver toutes les fonctionnalités par défaut puis d'activer uniquement ce qui est strictement nécessaire (par exemple, décoder HEVC, H.264, AAC).
  • --disable-programs : Empêche la construction des outils en ligne de commande (ffmpeg, ffplay, ffprobe), car ils ne sont généralement pas utiles dans un contexte Wasm.
  • --disable-asm : Désactive l'optimisation par code assembleur, souvent incompatible avec Emscripten ou inutile pour les performances WebAssembly.

3. Script de Compilation et Lien avec Emscripten

Après la configuration, compilez FFmpeg en utilisant emmake make et emmake make install. Ensuite, un script est utilisé pour lier les bibliothèques compilées et un fichier source C (par exemple, entry_point.c) en un fichier WebAssembly (ffmpeg_module.wasm) et son fichier JavaScript d'accompagnement (ffmpeg_module.js).

#!/bin/bash

# Exécute la compilation FFmpeg avec Emscripten
# Cela doit être fait après la phase de 'configure'
emmake make -j$(nproc)
emmake make install

echo "Démarrage de la compilation WebAssembly..."

# Répertoire des bibliothèques compilées par Emscripten
WASM_LIBS_DIR=$(pwd)/ffmpeg_wasm_build/lib
# Répertoire des includes
WASM_INCLUDE_DIR=$(pwd)/ffmpeg_wasm_build/include

# Définition des options pour le compilateur Emscripten
MEMORY_SIZE=167772160 # Taille totale de la mémoire en octets (160 Mo)
# Fonctions C/C++ à exporter pour qu'elles soient appelables depuis JavaScript
EXPORTED_JS_FUNCTIONS="[ \
   '_initialize_ffmpeg_decoder', \
   '_process_media_frame', \
   '_release_ffmpeg_resources', \
   '_get_video_width', \
   '_get_video_height', \
   '_wasm_malloc', \
   '_wasm_free' \
]"

# Exemple de contenu pour entry_point.c (à titre indicatif):
/*
// entry_point.c - Fichier d'entrée pour l'intégration FFmpeg WebAssembly
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <emscripten.h> // Nécessaire pour EMSCRIPTEN_KEEPALIVE et les utilitaires Emscripten

// Variables globales pour le décodeur FFmpeg
AVFormatContext *global_format_context = NULL;
AVCodecContext *global_codec_context = NULL;
AVFrame *global_frame = NULL;
AVPacket *global_packet = NULL;
struct SwsContext *global_sws_context = NULL;
int global_video_stream_index = -1;

// Fonction exportée pour initialiser le décodeur
EMSCRIPTEN_KEEPALIVE
int _initialize_ffmpeg_decoder(const char* format_name) {
   av_register_all(); // Déprécié, mais assure la compatibilité pour certains projets
   avcodec_register_all(); // Idem
   avformat_network_init(); // Pour les protocoles réseau si --enable-network était activé

   global_format_context = avformat_alloc_context();
   if (!global_format_context) return -1;

   // Ici, vous devriez ouvrir une source (fichier, URL)
   // Pour une application WebAssembly, cela impliquerait souvent de lire depuis la mémoire
   // ou un système de fichiers virtuel. Exemple simplifié:
   // avformat_open_input(&global_format_context, "input.mp4", NULL, NULL);

   // Initialisation simplifiée pour un décodage brut (ex: H.264/HEVC brut)
   // Dans un cas réel, vous analyseriez le format ou recevriez un flux brut.
   AVCodec *codec = avcodec_find_decoder_by_name(format_name); // e.g., "h264" or "hevc"
   if (!codec) return -2;

   global_codec_context = avcodec_alloc_context3(codec);
   if (!global_codec_context) return -3;

   if (avcodec_open2(global_codec_context, codec, NULL) < 0) return -4;

   global_frame = av_frame_alloc();
   global_packet = av_packet_alloc();
   if (!global_frame || !global_packet) return -5;

   return 0; // Succès
}

// Fonction exportée pour traiter une trame média (paquet)
EMSCRIPTEN_KEEPALIVE
int _process_media_frame(uint8_t *input_buffer, int buffer_size) {
   if (!global_codec_context || !global_frame || !global_packet) return -1;

   // Définir les données du paquet
   global_packet->data = input_buffer;
   global_packet->size = buffer_size;

   int ret = avcodec_send_packet(global_codec_context, global_packet);
   if (ret < 0) return ret;

   ret = avcodec_receive_frame(global_codec_context, global_frame);
   if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
       return 1; // Pas de trame complète disponible, ou fin de fichier
   } else if (ret < 0) {
       return ret; // Erreur de décodage
   }

   // Ici, 'global_frame' contient une trame vidéo décodée
   // Vous pouvez la convertir (ex: avec swscale) et la renvoyer ou la traiter.
   // Pour cet exemple, nous signalons juste qu'une trame a été reçue.
   return 0; // Trame décodée avec succès
}

// Fonction exportée pour libérer les ressources
EMSCRIPTEN_KEEPALIVE
void _release_ffmpeg_resources() {
   if (global_packet) av_packet_free(&global_packet);
   if (global_frame) av_frame_free(&global_frame);
   if (global_codec_context) avcodec_free_context(&global_codec_context);
   if (global_format_context) avformat_close_input(&global_format_context);
   if (global_sws_context) sws_freeContext(global_sws_context);
   avformat_network_deinit();
}

// Fonctions exportées pour obtenir des informations sur la vidéo
EMSCRIPTEN_KEEPALIVE
int _get_video_width() { return global_codec_context ? global_codec_context->width : 0; }

EMSCRIPTEN_KEEPALIVE
int _get_video_height() { return global_codec_context ? global_codec_context->height : 0; }

// Fonctions exportées pour l'allocation/libération de mémoire via le runtime Emscripten
EMSCRIPTEN_KEEPALIVE
void *_wasm_malloc(size_t size) { return malloc(size); }

EMSCRIPTEN_KEEPALIVE
void _wasm_free(void *ptr) { free(ptr); }
*/


emcc entry_point.c \
   "${WASM_LIBS_DIR}/libavcodec.a" \
   "${WASM_LIBS_DIR}/libavutil.a" \
   "${WASM_LIBS_DIR}/libswscale.a" \
   "${WASM_LIBS_DIR}/libavformat.a" \
   "${WASM_LIBS_DIR}/libavdevice.a" \
   "${WASM_LIBS_DIR}/libswresample.a" \
   -O2 \
   -I "${WASM_INCLUDE_DIR}" \
   -s WASM=1 \
   -s ASSERTIONS=1 \
   -s LLD_REPORT_UNDEFINED \
   -s NO_EXIT_RUNTIME=1 \
   -s DISABLE_EXCEPTION_CATCHING=1 \
   -s TOTAL_MEMORY="${MEMORY_SIZE}" \
   -s EXPORTED_FUNCTIONS="${EXPORTED_JS_FUNCTIONS}" \
   -s EXTRA_EXPORTED_RUNTIME_METHODS="['addFunction', 'removeFunction']" \
   -s RESERVED_FUNCTION_POINTERS=14 \
   -s FORCE_FILESYSTEM=1 \
   -s ALLOW_MEMORY_GROWTH \
   -o ffmpeg_module.js

echo "Compilation WebAssembly terminée : ffmpeg_module.js et ffmpeg_module.wasm générés."

  • -O2 : Niveau d'optimisation du compilateur.
  • -I "${WASM_INCLUDE_DIR}" : Spécifie le chemin des fichiers d'en-tête de FFmpeg compilés.
  • -s WASM=1 : Active la génération de WebAssembly.
  • -s TOTAL_MEMORY="${MEMORY_SIZE}" : Définit la taille initiale de la mémoire Wasm.
  • -s EXPORTED_FUNCTIONS="${EXPORTED_JS_FUNCTIONS}" : Liste les fonctions C/C++ qui seront accessibles depuis JavaScript.
  • -s ALLOW_MEMORY_GROWTH : Permet à la mémoire WebAssembly de s'étendre dynamiquement si nécessaire.
  • -o ffmpeg_module.js : Nom du fichier de sortie JavaScript (qui inclut le chargement du fichier .wasm).

Note: Le fichier entry_point.c n'est pas fourni et doit être écrit par l'utilisateur pour interagir avec les API FFmpeg et exporter les fonctions nécessaires à l'application web. L'exemple commenté montre une structure possible.

Compilation de FFmpeg avec MinGW-w64 pour Windows (depuis Linux)

La compilation croisée de FFmpeg pour Windows depuis un environnement Linux est pratique pour les développeurs travaillant sur Linux mais ciblant des applications Windows. MinGW-w64 est la chaîne d'outils de choix pour cette tâche.

1. Installation de MinGW-w64

Installez le compilateur MinGW-w64 sur votre système Linux. Ce paquet fournit les outils nécessaires pour la compilation croisée vers les cibles Windows 64 bits.

sudo apt update
sudo apt install -y mingw-w64-x86-64-dev

2. Script de Configuration pour MinGW-w64

Utilisez le script configure de FFmpeg avec des options de compilation croisée spécifiques à MinGW-w64. Le préfixe croisé indique à configure d'utiliser les outils MinGW (par exemple, x86_64-w64-mingw32-gcc).

#!/bin/bash

echo "Démarrage de la configuration FFmpeg pour MinGW-w64..."

# Répertoire de construction pour les artefacts MinGW
MINGW_BUILD_DIR=$(pwd)/ffmpeg_mingw_build
mkdir -p "${MINGW_BUILD_DIR}"

./configure \
   --arch=x86_64 \
   --target-os=mingw32 \
   --cross-prefix=x86_64-w64-mingw32- \
   --disable-x86asm \
   --enable-shared \
   --prefix="${MINGW_BUILD_DIR}"

echo "Configuration FFmpeg pour MinGW-w64 terminée."

  • --arch=x86_64 : Spécifie l'architecture cible comme 64 bits.
  • --target-os=mingw32 : Indique le système d'exploitation cible comme MinGW (Windows).
  • --cross-prefix=x86_64-w64-mingw32- : Définit le préfixe pour les outils de la chaîne de compilation croisée (par exemple, x86_64-w64-mingw32-gcc).
  • --disable-x86asm : Désactive l'utilisation de l'assembleur x86 natif de FFmpeg, car il peut y avoir des incompatibilités ou des difficultés de configuration avec la chaîne d'outils croisée MinGW.
  • --enable-shared : Construit les bibliothèques partagées (DLLs sur Windows).
  • --prefix="${MINGW_BUILD_DIR}" : Spécifie le répertoire d'instalation.

Après l'exécution de ce script de configuration, vous pouvez compiler FFmpeg pour Windows en utilisant make -j$(nproc) et installer les binaires avec make install. Les fichiers résultants (exécutables et DLLs) se trouveront dans le répertoire ${MINGW_BUILD_DIR}.

Étiquettes: FFmpeg compilation Linux GCC Emscripten

Publié le 9 juillet à 05h58