diff --git a/.github/workflows/build-ffmpeg.yml b/.github/workflows/build-ffmpeg.yml index 70c3dd56..640fcc2c 100644 --- a/.github/workflows/build-ffmpeg.yml +++ b/.github/workflows/build-ffmpeg.yml @@ -93,7 +93,7 @@ jobs: - name: Install packages for macOS if: runner.os == 'macOS' run: | - brew unlink gettext libidn2 libpng libtiff libunistring libx11 libxau libxcb libxdmcp little-cms2 unbound + brew unlink gettext libidn2 libpng libtiff libunistring libx11 libxcb libxdmcp if [ "${{ matrix.os }}" = "macos-15-intel" ]; then brew install nasm fi @@ -128,13 +128,15 @@ jobs: cross-build: needs: fan - runs-on: ubuntu-24.04 + # armv7l is cross-compiled from an aarch64 host with the arm-linux-gnueabihf + # toolchain; the other arches cross-compile from x86_64. + runs-on: ${{ matrix.arch == 'armv7l' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} strategy: fail-fast: false matrix: build: [ "manylinux_", "musllinux_" ] # arch: [ "loongarch64", "ppc64le", "riscv64", "s390x" ] - arch: [ "ppc64le", "riscv64" ] + arch: [ "armv7l", "ppc64le", "riscv64" ] steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 diff --git a/README.rst b/README.rst index 7ed787c6..5c6ce7f1 100644 --- a/README.rst +++ b/README.rst @@ -7,7 +7,7 @@ users to easily install PyAV without perform error-prone compilations. The builds are provided for several platforms: -- Linux (x86_64, aarch64, ppc64le, riscv64) +- Linux (x86_64, aarch64, armv7l, ppc64le, riscv64) - macOS (x86_64, arm64) - Windows (x86_64, aarch64) @@ -24,8 +24,8 @@ Currently FFmpeg 8.1.1 is built with the following packages enabled for all plat - png 1.6.58 - webp 1.6.0 - opencore-amr 0.1.6 -- x264 32c3b801191522961102d4bea292cdb61068d0dd -- x265 4.2 +- x264 32c3b801191522961102d4bea292cdb61068d0dd (except armv7l) +- x265 4.2 (except armv7l) The following additional packages are also enabled on Linux: diff --git a/scripts/build-ffmpeg.py b/scripts/build-ffmpeg.py index 0047eee1..40fad16f 100644 --- a/scripts/build-ffmpeg.py +++ b/scripts/build-ffmpeg.py @@ -86,7 +86,8 @@ def main(): dest_dir = os.path.abspath(args.destination) machine = platform.machine().lower() - is_arm = machine in {"arm64", "aarch64"} + is_arm32 = machine in {"armv7l", "armv8l", "arm"} + is_arm = machine in {"arm64", "aarch64"} or is_arm32 is_riscv = machine in {"riscv64"} use_alsa = plat == "Linux" @@ -158,10 +159,14 @@ def main(): "--enable-libwebp", "--enable-libxcb" if plat == "Linux" else "--disable-libxcb", "--enable-zlib", - "--enable-libx264", - "--enable-libx265", ] + # x264/x265 are skipped on 32-bit ARM (armv7) + if not is_arm32: + ffmpeg_package.build_arguments.extend( + ["--enable-libx264", "--enable-libx265"] + ) + if use_cuda: ffmpeg_package.build_arguments.extend(["--enable-nvenc", "--enable-nvdec"]) @@ -181,11 +186,13 @@ def main(): ) if plat == "Linux" and "RUNNER_ARCH" in os.environ: + # FFmpeg expects "arm" for 32-bit ARM, not the uname "armv7l". + ff_arch = "arm" if is_arm32 else machine ffmpeg_package.build_arguments.extend( [ "--enable-cross-compile", "--target-os=linux", - "--arch=" + machine, + "--arch=" + ff_arch, "--cc=/opt/clang/bin/clang", "--cxx=/opt/clang/bin/clang++", ] @@ -220,7 +227,11 @@ def main(): if use_gnutls: packages += gnutls_group - packages += codec_group + if is_arm32: + # x264/x265 are not built on 32-bit ARM (armv7) + packages += [p for p in codec_group if p.name not in {"x264", "x265"}] + else: + packages += codec_group packages += [ffmpeg_package] # Disable runtime CPU detection for opus on Windows ARM64 diff --git a/scripts/install-static-clang.sh b/scripts/install-static-clang.sh index c84e494b..a85bcea4 100755 --- a/scripts/install-static-clang.sh +++ b/scripts/install-static-clang.sh @@ -51,7 +51,7 @@ esac case "${AUDITWHEEL_POLICY}-${AUDITWHEEL_ARCH}" in *-riscv64) M_ARCH="-march=rv64gc";; *-x86_64) M_ARCH="-march=x86-64";; - *-armv7l) M_ARCH="-march=armv7a";; + *-armv7l) M_ARCH="-march=armv7-a -mfpu=neon-vfpv3 -mfloat-abi=hard";; manylinux*-i686) M_ARCH="-march=k8 -mtune=generic";; # same as gcc manylinux2014 / manylinux_2_28 musllinux*-i686) M_ARCH="-march=pentium-m -mtune=generic";; # same as gcc musllinux_1_2 esac