From 5457e99bb78e16151f3f7e2bc41fd31a5bac7f12 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 22 Mar 2026 14:28:34 -0700 Subject: [PATCH] ffmpeg: add hardware-accelerated video decoders (#62) --- ffmpeg/build.sh | 98 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/ffmpeg/build.sh b/ffmpeg/build.sh index 9bc11da..41ac0d4 100755 --- a/ffmpeg/build.sh +++ b/ffmpeg/build.sh @@ -4,9 +4,12 @@ set -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" cd "$DIR" +PLATFORM="$(uname -s)" FFMPEG_VERSION="7.1" ZLIB_VERSION="da607da739fa6047df13e66a2af6b8bec7c2a498" # v1.3.2 X264_BRANCH="stable" +LIBDRM_VERSION="libdrm-2.4.124" +LIBVA_VERSION="2.22.0" INSTALL_DIR="$DIR/ffmpeg/install" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" @@ -48,6 +51,59 @@ make -j"$NJOBS" make install cd "$DIR" +# --- Build nv-codec-headers (Linux only, for CUDA/NVDEC) --- +if [ "$PLATFORM" = "Linux" ]; then + if [ ! -d "nv-codec-headers-src/.git" ]; then + rm -rf nv-codec-headers-src + git clone --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git nv-codec-headers-src + fi + make -C nv-codec-headers-src PREFIX="$PREFIX" install +fi + +# --- Build Vulkan-Headers from source (Linux only, need >= 1.3.277 for FFmpeg 7.1) --- +if [ "$PLATFORM" = "Linux" ]; then + if [ ! -d "vulkan-headers-src/.git" ]; then + rm -rf vulkan-headers-src + git clone --depth 1 https://github.com/KhronosGroup/Vulkan-Headers.git vulkan-headers-src + fi + cmake -S vulkan-headers-src -B vulkan-headers-src/build -DCMAKE_INSTALL_PREFIX="$PREFIX" >/dev/null + cmake --install vulkan-headers-src/build >/dev/null +fi + +# --- Build libdrm + libva statically (Linux only, for VAAPI without runtime deps) --- +if [ "$PLATFORM" = "Linux" ]; then + if ! command -v meson &>/dev/null; then + pip3 install --quiet meson ninja 2>/dev/null || python3 -m pip install --quiet meson ninja 2>/dev/null || true + command -v meson &>/dev/null || { echo "error: meson is required (apt install meson or pip install meson)" >&2; exit 1; } + fi + + if [ ! -d "libdrm-src/.git" ]; then + rm -rf libdrm-src + git clone --depth 1 --branch "$LIBDRM_VERSION" https://gitlab.freedesktop.org/mesa/drm.git libdrm-src + fi + rm -rf libdrm-src/builddir + meson setup libdrm-src/builddir libdrm-src \ + --prefix="$PREFIX" --libdir=lib --default-library=static \ + -Dintel=disabled -Dradeon=disabled -Damdgpu=disabled -Dnouveau=disabled \ + -Dvmwgfx=disabled -Dtests=false -Dman-pages=disabled -Dcairo-tests=disabled \ + -Dvalgrind=disabled + ninja -C libdrm-src/builddir install + + if [ ! -d "libva-src/.git" ]; then + rm -rf libva-src + git clone --depth 1 --branch "$LIBVA_VERSION" https://github.com/intel/libva.git libva-src + fi + rm -rf libva-src/builddir + # libva hardcodes shared_library(); patch to library() so --default-library=static works + sed -i 's/shared_library(/library(/g' libva-src/va/meson.build + PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \ + meson setup libva-src/builddir libva-src \ + --prefix="$PREFIX" --libdir=lib --default-library=static \ + -Ddisable_drm=false -Dwith_x11=no -Dwith_glx=no -Dwith_wayland=no \ + -Dwith_win32=no -Denable_docs=false + ninja -C libva-src/builddir install +fi + # --- Build FFmpeg --- if [ ! -d "ffmpeg-src/.git" ]; then rm -rf ffmpeg-src @@ -57,6 +113,39 @@ git -C ffmpeg-src fetch --depth 1 origin "n${FFMPEG_VERSION}" git -C ffmpeg-src checkout --force FETCH_HEAD cd ffmpeg-src + +# Platform-specific hardware acceleration flags +HW_FLAGS=() +if [ "$PLATFORM" = "Linux" ]; then + HW_FLAGS+=( + # NVIDIA CUDA/NVDEC (uses dlopen at runtime) + --enable-ffnvcodec --enable-cuda --enable-cuvid --enable-nvdec + --enable-hwaccel=h264_nvdec,hevc_nvdec + --enable-decoder=h264_cuvid,hevc_cuvid + + # VAAPI (Intel/AMD — libva linked statically, driver loaded via dlopen at runtime) + --enable-vaapi + --enable-hwaccel=h264_vaapi,hevc_vaapi + + # V4L2 Memory-to-Memory (embedded: RPi, Qualcomm, Rockchip) + --enable-v4l2-m2m + --enable-decoder=h264_v4l2m2m,hevc_v4l2m2m + --enable-encoder=h264_v4l2m2m,hevc_v4l2m2m + + # Vulkan video decode/encode (uses dlopen at runtime) + --enable-vulkan + --enable-hwaccel=h264_vulkan,hevc_vulkan + --enable-encoder=h264_vulkan,hevc_vulkan + ) +elif [ "$PLATFORM" = "Darwin" ]; then + HW_FLAGS+=( + # VideoToolbox (Apple Silicon / macOS) + --enable-videotoolbox + --enable-hwaccel=h264_videotoolbox,hevc_videotoolbox + --enable-encoder=h264_videotoolbox,hevc_videotoolbox + ) +fi + PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \ ./configure \ --cc="${CC:-cc}" \ @@ -80,7 +169,8 @@ PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \ --enable-filter=blend,vflip,format,scale,aformat,anull,aresample,null \ --enable-bsf=extract_extradata,h264_mp4toannexb,hevc_mp4toannexb \ --extra-cflags="-I$PREFIX/include" \ - --extra-ldflags="-L$PREFIX/lib" + --extra-ldflags="-L$PREFIX/lib" \ + "${HW_FLAGS[@]}" make -j"$NJOBS" make install cd "$DIR" @@ -94,7 +184,11 @@ cp "$PREFIX/bin/ffmpeg" "$INSTALL_DIR/bin/" cp "$PREFIX/bin/ffprobe" "$INSTALL_DIR/bin/" # Libraries -for lib in libavformat.a libavcodec.a libavutil.a libswresample.a libx264.a libz.a; do +LIBS="libavformat.a libavcodec.a libavutil.a libswresample.a libx264.a libz.a" +if [ "$PLATFORM" = "Linux" ]; then + LIBS="$LIBS libva.a libva-drm.a libdrm.a" +fi +for lib in $LIBS; do cp "$PREFIX/lib/$lib" "$INSTALL_DIR/lib/" done