# Cross-compilation image for ARMv7 based on Debian 11 # Build on Debian 11 (GLIBC 2.31) for maximum runtime compatibility ARG DEBIAN_IMAGE=debian:11 FROM ${DEBIAN_IMAGE} ARG CHINAMIRRO=0 ARG GH_PROXY=https://gh-proxy.com/ ARG RUSTUP_DIST_SERVER_CN=https://rsproxy.cn ARG RUSTUP_UPDATE_ROOT_CN=https://rsproxy.cn/rustup ARG CARGO_INDEX_CN=https://rsproxy.cn/crates.io-index ARG CARGO_REGISTRY_CN=sparse+https://rsproxy.cn/index/ ARG LIBJPEG_TURBO_VERSION=3.1.4.1 ARG LIBYUV_REV=957f295ea946cbbd13fcfc46e7066f2efa801233 ARG LIBVPX_VERSION=1.16.0 ARG X265_VERSION=3.4 ARG OPUS_VERSION=1.5.2 ARG FFMPEG_ROCKCHIP_REV=40c412daccf08164493da0de990eb99a8948116b # Optionally use China mirrors for builds in China. RUN if [ "$CHINAMIRRO" = "1" ]; then \ sed -i -E \ -e 's|http://deb.debian.org/debian([[:space:]])|http://mirrors.tuna.tsinghua.edu.cn/debian\1|g' \ /etc/apt/sources.list; \ fi # Install Rust toolchain RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ ca-certificates \ && if [ "$CHINAMIRRO" = "1" ]; then \ export RUSTUP_DIST_SERVER=${RUSTUP_DIST_SERVER_CN}; \ export RUSTUP_UPDATE_ROOT=${RUSTUP_UPDATE_ROOT_CN}; \ fi \ && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable \ && if [ "$CHINAMIRRO" = "1" ]; then \ mkdir -p /root/.cargo; \ printf '%s\n' \ '[source.crates-io]' \ "replace-with = 'rsproxy-sparse'" \ '[source.rsproxy]' \ "registry = '${CARGO_INDEX_CN}'" \ '[source.rsproxy-sparse]' \ "registry = '${CARGO_REGISTRY_CN}'" \ '[registries.rsproxy]' \ "index = '${CARGO_INDEX_CN}'" \ '[net]' \ 'git-fetch-with-cli = true' \ > /root/.cargo/config.toml; \ fi \ && rm -rf /var/lib/apt/lists/* ENV PATH="/root/.cargo/bin:${PATH}" # Add armhf architecture RUN dpkg --add-architecture armhf # Install cross-compiler and native build tools RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ pkg-config \ cmake \ nasm \ git \ libclang-dev \ llvm \ meson \ ninja-build \ wget \ xz-utils \ file \ rsync \ gcc-arm-linux-gnueabihf \ g++-arm-linux-gnueabihf \ libc6-dev-armhf-cross \ # Autotools for libopus (requires autoreconf) autoconf \ automake \ libtool \ && rm -rf /var/lib/apt/lists/* # Install ARMv7 development libraries (without VAAPI/X11 for ARM) RUN apt-get update && apt-get install -y --no-install-recommends \ libssl1.1 \ libssl1.1:armhf \ libasound2-dev:armhf \ libv4l-dev:armhf \ libudev-dev:armhf \ linux-libc-dev:armhf \ zlib1g-dev:armhf \ libdrm-dev:armhf \ && rm -rf /var/lib/apt/lists/* # Build static libjpeg-turbo from source (cross-compile for ARMv7) RUN github_prefix="" \ && if [ "$CHINAMIRRO" = "1" ]; then github_prefix="${GH_PROXY%/}/"; fi \ && git init /tmp/libjpeg-turbo \ && cd /tmp/libjpeg-turbo \ && git remote add origin "${github_prefix}https://github.com/libjpeg-turbo/libjpeg-turbo.git" \ && git fetch --depth 1 origin "refs/tags/${LIBJPEG_TURBO_VERSION}" \ && git checkout --detach FETCH_HEAD \ && mkdir build && cd build \ && cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ -DCMAKE_INSTALL_PREFIX=/usr/arm-linux-gnueabihf \ -DCMAKE_INSTALL_LIBDIR=lib \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_SYSTEM_PROCESSOR=arm \ -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \ -DENABLE_SHARED=OFF -DENABLE_STATIC=ON \ && make -j$(nproc) \ && make install \ && rm -rf /tmp/libjpeg-turbo # Build static libyuv from source (cross-compile for ARMv7) RUN git init /tmp/libyuv \ && cd /tmp/libyuv \ && github_prefix="" \ && if [ "$CHINAMIRRO" = "1" ]; then github_prefix="${GH_PROXY%/}/"; fi \ && git remote add origin "${github_prefix}https://github.com/lemenkov/libyuv" \ && git fetch --depth 1 origin ${LIBYUV_REV} \ && git checkout --detach FETCH_HEAD \ && mkdir build && cd build \ && cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ -DCMAKE_INSTALL_PREFIX=/usr/arm-linux-gnueabihf \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_SYSTEM_PROCESSOR=arm \ -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \ -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \ -DJPEG_FOUND=TRUE \ -DJPEG_INCLUDE_DIR=/usr/arm-linux-gnueabihf/include \ -DJPEG_LIBRARY=/usr/arm-linux-gnueabihf/lib/libjpeg.a \ -DCMAKE_C_FLAGS="-DHAVE_JPEG -I/usr/arm-linux-gnueabihf/include" \ -DCMAKE_CXX_FLAGS="-DHAVE_JPEG -I/usr/arm-linux-gnueabihf/include" \ && make -j$(nproc) \ && make install \ && rm -rf /tmp/libyuv # Build static libvpx from source (cross-compile for ARMv7) RUN github_prefix="" \ && if [ "$CHINAMIRRO" = "1" ]; then github_prefix="${GH_PROXY%/}/"; fi \ && git init /tmp/libvpx \ && cd /tmp/libvpx \ && git remote add origin "${github_prefix}https://github.com/webmproject/libvpx.git" \ && git fetch --depth 1 origin "refs/tags/v${LIBVPX_VERSION}" \ && git checkout --detach FETCH_HEAD \ && export CC=arm-linux-gnueabihf-gcc \ && export CXX=arm-linux-gnueabihf-g++ \ && export LD=arm-linux-gnueabihf-ld \ && export AR=arm-linux-gnueabihf-ar \ && export CROSS=arm-linux-gnueabihf- \ && ./configure \ --prefix=/usr/arm-linux-gnueabihf \ --target=armv7-linux-gcc \ --enable-static --disable-shared --enable-pic \ --disable-examples --disable-tools --disable-docs \ --disable-unit-tests \ && make -j$(nproc) \ && make install \ && rm -rf /tmp/libvpx # Build static libx264 from source (cross-compile for ARMv7) RUN github_prefix="" \ && if [ "$CHINAMIRRO" = "1" ]; then github_prefix="${GH_PROXY%/}/"; fi \ && git clone --depth 1 "${github_prefix}https://github.com/mirror/x264.git" /tmp/x264 \ && cd /tmp/x264 \ && export CC=arm-linux-gnueabihf-gcc \ && export AR=arm-linux-gnueabihf-ar \ && export RANLIB=arm-linux-gnueabihf-ranlib \ && ./configure \ --prefix=/usr/arm-linux-gnueabihf \ --host=arm-linux-gnueabihf \ --cross-prefix=arm-linux-gnueabihf- \ --enable-static --disable-shared \ --enable-pic \ --disable-cli \ && make -j$(nproc) \ && make install \ && rm -rf /tmp/x264 # Build static libx265 from source (cross-compile for ARMv7) RUN github_prefix="" \ && if [ "$CHINAMIRRO" = "1" ]; then github_prefix="${GH_PROXY%/}/"; fi \ && git init /tmp/x265 \ && cd /tmp/x265 \ && git remote add origin "${github_prefix}https://github.com/videolan/x265.git" \ && git fetch --depth 1 origin "refs/tags/${X265_VERSION}" \ && git checkout --detach FETCH_HEAD \ && cd source \ && mkdir -p build \ && cd build \ && cmake .. -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_ASM_NASM_FLAGS="-w-macro-params-legacy" \ -DCMAKE_INSTALL_PREFIX=/usr/arm-linux-gnueabihf \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_SYSTEM_PROCESSOR=arm \ -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \ -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \ -DENABLE_SHARED=OFF \ -DENABLE_CLI=OFF \ -DBUILD_SHARED_LIBS=OFF \ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ && make -j$(nproc) \ && make install \ && rm -rf /tmp/x265 # Create pkg-config file for x265 (required by FFmpeg) RUN mkdir -p /usr/arm-linux-gnueabihf/lib/pkgconfig && \ cat > /usr/arm-linux-gnueabihf/lib/pkgconfig/x265.pc < /tmp/armhf-cross.txt \ && echo "c = 'arm-linux-gnueabihf-gcc'" >> /tmp/armhf-cross.txt \ && echo "cpp = 'arm-linux-gnueabihf-g++'" >> /tmp/armhf-cross.txt \ && echo "ar = 'arm-linux-gnueabihf-ar'" >> /tmp/armhf-cross.txt \ && echo "strip = 'arm-linux-gnueabihf-strip'" >> /tmp/armhf-cross.txt \ && echo "pkgconfig = 'pkg-config'" >> /tmp/armhf-cross.txt \ && echo '[host_machine]' >> /tmp/armhf-cross.txt \ && echo "system = 'linux'" >> /tmp/armhf-cross.txt \ && echo "cpu_family = 'arm'" >> /tmp/armhf-cross.txt \ && echo "cpu = 'armv7'" >> /tmp/armhf-cross.txt \ && echo "endian = 'little'" >> /tmp/armhf-cross.txt \ && cd rkrga \ && meson setup build --prefix=/usr/arm-linux-gnueabihf --libdir=lib \ --cross-file=/tmp/armhf-cross.txt \ --buildtype=release \ --default-library=static \ -Dcpp_args=-fpermissive \ -Dlibdrm=false \ -Dlibrga_demo=false \ && ninja -C build \ && ninja -C build install \ # Create static librga.a from built objects (rkrga uses shared_library) && ar rcs /usr/arm-linux-gnueabihf/lib/librga.a $(find build -name '*.o') \ && ranlib /usr/arm-linux-gnueabihf/lib/librga.a \ && sed -i 's/^Libs:.*$/& -lstdc++ -lm -lpthread/' /usr/arm-linux-gnueabihf/lib/pkgconfig/librga.pc \ && cd .. \ # Create pkg-config wrapper for cross-compilation && echo '#!/bin/sh' > /tmp/armhf-pkg-config \ && echo 'export PKG_CONFIG_LIBDIR=/usr/arm-linux-gnueabihf/lib/pkgconfig:/usr/arm-linux-gnueabihf/lib/pkgconfig:/usr/lib/arm-linux-gnueabihf/pkgconfig' >> /tmp/armhf-pkg-config \ && echo 'export PKG_CONFIG_PATH=""' >> /tmp/armhf-pkg-config \ && echo 'export PKG_CONFIG_SYSROOT_DIR=""' >> /tmp/armhf-pkg-config \ && echo 'exec pkg-config "$@"' >> /tmp/armhf-pkg-config \ && chmod +x /tmp/armhf-pkg-config \ # Build FFmpeg with RKMPP (minimal build for encoding only) && cd ffmpeg-rockchip \ && ./configure \ --prefix=/usr/arm-linux-gnueabihf \ --cross-prefix=arm-linux-gnueabihf- \ --arch=arm \ --target-os=linux \ --enable-cross-compile \ --pkg-config=/tmp/armhf-pkg-config \ --enable-gpl \ --enable-version3 \ --disable-shared \ --enable-static \ --enable-pic \ # Hardware acceleration (ARM: RKMPP + V4L2, no VAAPI) --enable-libdrm \ --enable-rkmpp \ --enable-rkrga \ --disable-vaapi \ --enable-v4l2-m2m \ # Software encoding libraries --enable-libx264 \ --enable-libx265 \ --enable-libvpx \ # Disable programs and docs --disable-programs \ --disable-doc \ --disable-htmlpages \ --disable-manpages \ --disable-podpages \ --disable-txtpages \ # Disable network --disable-network \ --disable-protocols \ # Disable unused libraries --disable-avformat \ --disable-swscale \ --disable-swresample \ --disable-avfilter \ --disable-avdevice \ --disable-postproc \ # Disable all decoders (re-enable only what we need) --disable-decoders \ --enable-decoder=mjpeg \ --enable-decoder=mjpeg_rkmpp \ # Disable all encoders, enable only needed ones --disable-encoders \ --enable-encoder=h264_rkmpp \ --enable-encoder=hevc_rkmpp \ --enable-encoder=h264_v4l2m2m \ --enable-encoder=hevc_v4l2m2m \ --enable-encoder=libx264 \ --enable-encoder=libx265 \ --enable-encoder=libvpx_vp8 \ --enable-encoder=libvpx_vp9 \ # Disable muxers/demuxers --disable-muxers \ --disable-demuxers \ # Disable parsers except needed ones --disable-parsers \ --enable-parser=h264 \ --enable-parser=hevc \ --enable-parser=vp8 \ --enable-parser=vp9 \ # Disable BSFs except needed ones --disable-bsfs \ --enable-bsf=h264_mp4toannexb \ --enable-bsf=hevc_mp4toannexb \ # Hardware decoding uses explicit rkmpp decoder (no hwaccel flag) # Disable other unused features --disable-indevs \ --disable-outdevs \ --disable-filters \ --disable-debug \ && make -j$(nproc) \ && make install \ && cd / \ && rm -rf /tmp/ffmpeg-build /tmp/armhf-cross.txt /tmp/armhf-pkg-config # Add Rust target RUN if [ "$CHINAMIRRO" = "1" ]; then \ export RUSTUP_DIST_SERVER=${RUSTUP_DIST_SERVER_CN}; \ export RUSTUP_UPDATE_ROOT=${RUSTUP_UPDATE_ROOT_CN}; \ fi \ && rustup target add armv7-unknown-linux-gnueabihf # Configure environment for cross-compilation ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \ CC_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ CXX_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ \ AR_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \ PKG_CONFIG_LIBDIR=/usr/arm-linux-gnueabihf/lib/pkgconfig:/usr/lib/arm-linux-gnueabihf/pkgconfig \ PKG_CONFIG_PATH="" \ PKG_CONFIG_ALLOW_CROSS=1 \ FFMPEG_STATIC=1 \ LIBYUV_STATIC=1 \ OPUS_STATIC=1 \ PKG_CONFIG_ALL_STATIC=1 \ RUSTFLAGS="-C linker=arm-linux-gnueabihf-gcc" # Default command CMD ["bash"]