From be0021e9b10333b8dee51b95df25f3d2d8a1536a Mon Sep 17 00:00:00 2001 From: pratham-mcw Date: Wed, 8 Apr 2026 19:33:22 +0530 Subject: [PATCH] Add Windows ARM64 support for FFmpeg videoio plugin build --- ffmpeg/build_via_docker.sh | 3 +- ffmpeg/build_videoio_plugin.sh | 51 +++++++++++- ffmpeg/docker/Dockerfile | 24 +++++- ffmpeg/make_mingw.sh | 146 +++++++++++++++++++++++++++++---- 4 files changed, 199 insertions(+), 25 deletions(-) diff --git a/ffmpeg/build_via_docker.sh b/ffmpeg/build_via_docker.sh index 5c76aee..bad5392 100755 --- a/ffmpeg/build_via_docker.sh +++ b/ffmpeg/build_via_docker.sh @@ -1,6 +1,7 @@ #!/bin/bash -e cd "$( dirname "${BASH_SOURCE[0]}" )" - +export MSYS_NO_PATHCONV=1 +export MSYS2_ARG_CONV_EXCL="*" # Build Docker image docker build -t opencv_ffmpeg_mingw_build_ubuntu2014 docker diff --git a/ffmpeg/build_videoio_plugin.sh b/ffmpeg/build_videoio_plugin.sh index d4e76aa..41f1fea 100755 --- a/ffmpeg/build_videoio_plugin.sh +++ b/ffmpeg/build_videoio_plugin.sh @@ -28,7 +28,7 @@ OPENCV_CMAKE_ARGS=( ) OPENCV_PLUGIN_CMAKE_ARGS=( - "-DCMAKE_MODULE_LINKER_FLAGS=-static -lbcrypt -static-libgcc -static-libstdc++ -Wl,--gc-sections -Wl,-Bsymbolic" + -DCMAKE_MODULE_LINKER_FLAGS="-lbcrypt -Wl,/OPT:REF -Wl,/OPT:ICF" -DCMAKE_BUILD_TYPE=Release -DOPENCV_PLUGIN_MODULE_PREFIX= -DOPENCV_FFMPEG_SKIP_DOWNLOAD=ON @@ -80,6 +80,53 @@ build_plugin_64() ) } +build_opencv_arm64() +{ +( + [[ -n "${CLEAN_BUILD_DIR}" ]] && { + rm -rf ${BUILD_DIR}/opencv_arm64 + } + + mkdir -p ${BUILD_DIR}/opencv_arm64 + pushd ${BUILD_DIR}/opencv_arm64 + rm -rf CMake* || true + + set -e + set -x + + cmake -GNinja \ + -DCMAKE_TOOLCHAIN_FILE=$CURRENT_DIR/llvm-toolchain-arm64.cmake \ + "${OPENCV_CMAKE_ARGS[@]}" -DENABLE_FP16=OFF \ + /build/opencv + + ninja opencv_modules -j${CPU_COUNT} + popd +) +} + +build_plugin_arm64() +{ +( + rm -rf ${BUILD_DIR}/opencv_ffmpeg_plugin_arm64 + mkdir -p ${BUILD_DIR}/opencv_ffmpeg_plugin_arm64 + pushd ${BUILD_DIR}/opencv_ffmpeg_plugin_arm64 + + set -e + set -x + PKG_CONFIG_PATH=${BUILD_DIR}/ffmpeg_arm64/install/lib/pkgconfig \ + RCFLAGS=-DFFMPEG_INTERNAL_NAME=opencv_videoio_ffmpeg_arm64 \ + cmake -GNinja \ + -DCMAKE_TOOLCHAIN_FILE=$CURRENT_DIR/llvm-toolchain-arm64.cmake \ + -DOpenCV_DIR=${BUILD_DIR}/opencv_arm64 \ + -DCMAKE_SHARED_LINKER_FLAGS="-lucrt" \ + "${OPENCV_PLUGIN_CMAKE_ARGS[@]}" + ninja -v + ninja install/strip + strings ./opencv_videoio_ffmpeg_64.dll | grep '/src/' | grep opencv | uniq + popd +) +} + build_opencv_32() { ( @@ -122,7 +169,7 @@ build_plugin_32() ) } -DEFAULT_TASKS=${1:-build_opencv_64 build_plugin_64 build_opencv_32 build_plugin_32} +DEFAULT_TASKS=${1:-build_opencv_arm64 build_plugin_arm64} for t in $DEFAULT_TASKS $@; do echo "Task: $t" $t diff --git a/ffmpeg/docker/Dockerfile b/ffmpeg/docker/Dockerfile index 10ec985..0269ca8 100644 --- a/ffmpeg/docker/Dockerfile +++ b/ffmpeg/docker/Dockerfile @@ -1,11 +1,16 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 +ARG APP_UID=500 +ARG APP_GID=500 + +ENV APP_UID=$APP_UID +ENV APP_GID=$APP_GID RUN \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ build-essential pkg-config \ software-properties-common \ - curl git man mc vim nano rsync \ + curl git man mc vim nano rsync file wget perl dos2unix python3 python-is-python3 \ && \ rm -rf /var/lib/apt/lists/* @@ -19,8 +24,19 @@ RUN \ RUN \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - mingw-w64 g++-mingw-w64-x86-64 g++-mingw-w64-i686 yasm nasm \ + clang lld llvm \ + yasm nasm \ && \ rm -rf /var/lib/apt/lists/* -CMD ["/app/docker/entry.sh"] +RUN \ + wget https://github.com/mstorsjo/llvm-mingw/releases/download/20251202/llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz && \ + tar -xf llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz -C /opt && \ + mv /opt/llvm-mingw-* /opt/llvm-mingw && \ + rm llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz + +ENV PATH="/opt/llvm-mingw/bin:${PATH}" + +COPY entry.sh /app/docker/entry.sh +RUN chmod +x /app/docker/entry.sh +# CMD [".","app/docker/entry.sh"] diff --git a/ffmpeg/make_mingw.sh b/ffmpeg/make_mingw.sh index 23b9585..08642b8 100755 --- a/ffmpeg/make_mingw.sh +++ b/ffmpeg/make_mingw.sh @@ -20,11 +20,6 @@ CPU_COUNT=$(nproc || echo 4) # use OPENCV_FFMPEG_DOCKER_EXTRA_ARGS="--cpuset-cp libvpx_DIR=${BUILD_DIR}/libvpx libvpx_x86_DIR=${BUILD_DIR}/libvpx_x86 libvpx_x64_DIR=${BUILD_DIR}/libvpx_x64 -libvpx_configure_OPTIONS="--disable-examples --disable-unit-tests --disable-install-bins --disable-docs --disable-shared --enable-static --enable-vp8 --enable-vp9 --disable-multithread" -if [ ! -d ${libvpx_DIR} ]; then - echo "Libvpx source tree is not found" - exit 1 -fi #[ -d ${libvpx_x86_DIR} ] || ( cd ${libvpx_DIR} @@ -46,13 +41,44 @@ make -j ${CPU_COUNT} make install ) -## Open264 - -openh264_DIR=${BUILD_DIR}/openh264 -if [ ! -d ${openh264_DIR} ]; then - echo "OpenH264 source tree is not found" +libvpx_ARM64_DIR=${BUILD_DIR}/libvpx_ARM64 +libvpx_configure_OPTIONS="--disable-examples --disable-unit-tests --disable-install-bins --disable-docs --disable-shared --enable-static --enable-vp8 --enable-vp9 --disable-multithread" +if [ ! -d ${libvpx_DIR} ]; then + echo "Libvpx source tree is not found" exit 1 fi +#[ -d ${libvpx_ARM64_DIR} ] || +( +cd /tmp +wget https://github.com/mstorsjo/llvm-mingw/releases/download/20251202/llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz +mkdir -p /app/llvm-mingw +tar -xf llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz -C /app/llvm-mingw --strip-components=1 +cd ${libvpx_DIR} +mkdir -p ${libvpx_ARM64_DIR} +rsync -a ./ ${libvpx_ARM64_DIR} --exclude .git +find ${libvpx_ARM64_DIR} -type f \( -name "*.pl" -o -name "*.c" -o -name "*.h" \) -exec dos2unix {} \; + +cd ${libvpx_ARM64_DIR} +export PATH=/app/llvm-mingw/bin:$PATH +export CROSS_PREFIX=aarch64-w64-mingw32- +export CC="${CROSS_PREFIX}gcc" +export CXX="${CROSS_PREFIX}g++" +export AR="${CROSS_PREFIX}ar" +export RANLIB="${CROSS_PREFIX}ranlib" +export STRIP="${CROSS_PREFIX}strip" + +CROSS=aarch64-w64-mingw32- ./configure \ + --target=arm64-win64-gcc \ + --disable-runtime-cpu-detect \ + ${libvpx_configure_OPTIONS} \ + --prefix=${libvpx_ARM64_DIR}/install + +make -j ${CPU_COUNT} +make install +) + +## Open264 + openh264_x86_DIR=${openh264_DIR}/install_x86 openh264_x86_64_DIR=${openh264_DIR}/install_x86_64 ( @@ -106,16 +132,53 @@ Cflags: -I${CURRENT_DIR}/openh264_wrapper -I\${prefix} -I\${includedir} EOF ) -## AOM: https://aomedia.googlesource.com/aom - -AOM_DIR=${BUILD_DIR}/aom -if [ ! -d ${AOM_DIR} ]; then - echo "AOM source tree is not found" +openh264_DIR=${BUILD_DIR}/openh264 +if [ ! -d ${openh264_DIR} ]; then + echo "OpenH264 source tree is not found" exit 1 fi +openh264_ARM64_DIR=${openh264_DIR}/install_arm64 +# ARM64 OpenH264 wrapper +( + cd /tmp + wget https://github.com/mstorsjo/llvm-mingw/releases/download/20251202/llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz + mkdir -p /app/llvm-mingw + tar -xf llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz -C /app/llvm-mingw --strip-components=1 + export PATH=/app/llvm-mingw/bin:$PATH + export CC=aarch64-w64-mingw32-gcc + export CXX=aarch64-w64-mingw32-g++ + export AR=aarch64-w64-mingw32-ar + export RANLIB=aarch64-w64-mingw32-ranlib + cd ${openh264_DIR} + if [[ "${BUILD_SKIP_DOWNLOAD_SOURCES}" == "" ]]; then + make PREFIX=${openh264_ARM64_DIR} install-headers + else + PREFIX=${openh264_ARM64_DIR} + mkdir -p ${PREFIX}/include/wels + install -m 644 ${openh264_DIR}/codec/api/svc/codec*.h ${PREFIX}/include/wels + fi + mkdir -p ${openh264_ARM64_DIR}/lib/pkgconfig + aarch64-w64-mingw32-gcc -m64 -O2 -I${CURRENT_DIR}/openh264_wrapper -I${openh264_ARM64_DIR} \ + -c ${CURRENT_DIR}/openh264_wrapper/wels/openh264_wrapper.c -o ${openh264_ARM64_DIR}/lib/openh264_wrapper.o + aarch64-w64-mingw32-ar rcs ${openh264_ARM64_DIR}/lib/libopenh264_wrapper.a ${openh264_ARM64_DIR}/lib/openh264_wrapper.o + + cat >${openh264_ARM64_DIR}/lib/pkgconfig/openh264.pc << EOF +prefix=${openh264_ARM64_DIR} +includedir=\${prefix}/include + +Name: OpenH264 +Description: OpenH264 wrapper with dynamic loading +Version: 1.8 +Libs: -L\${prefix}/lib -lopenh264_wrapper +Libs.private: +Cflags: -I${CURRENT_DIR}/openh264_wrapper -I\${prefix} -I\${includedir} +EOF +) + +## AOM: https://aomedia.googlesource.com/aom + AOM_X86_DIR=${BUILD_DIR}/aom_x86 AOM_X64_DIR=${BUILD_DIR}/aom_x64 -AOM_CONFIGURE_OPTIONS="-DENABLE_TESTS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_DOCS=OFF -DCONFIG_MULTITHREAD=1 -DCONFIG_AV1_ENCODER=1" ( mkdir -p "${AOM_X86_DIR}" cd "${AOM_X86_DIR}" @@ -125,7 +188,33 @@ AOM_CONFIGURE_OPTIONS="-DENABLE_TESTS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=O ( mkdir -p "${AOM_X64_DIR}" cd "${AOM_X64_DIR}" - cmake -GNinja -DAOM_TARGET_CPU=generic -DCMAKE_TOOLCHAIN_FILE=${AOM_DIR}/build/cmake/toolchains/x86_64-mingw-gcc.cmake -DCMAKE_INSTALL_PREFIX=${AOM_X64_DIR}/install ${AOM_CONFIGURE_OPTIONS} ${AOM_DIR} + cmake -GNinja -DAOM_TARGET_CPU=generic \ + -DCMAKE_TOOLCHAIN_FILE=${AOM_DIR}/build/cmake/toolchains/x86_64-mingw-gcc.cmake \ + -DCMAKE_INSTALL_PREFIX=${AOM_X64_DIR}/install ${AOM_CONFIGURE_OPTIONS} ${AOM_DIR} + cmake --build . --target install +) +AOM_DIR=${BUILD_DIR}/aom +if [ ! -d ${AOM_DIR} ]; then + echo "AOM source tree is not found" + exit 1 +fi +AOM_ARM64_DIR=${BUILD_DIR}/aom_arm64 +AOM_CONFIGURE_OPTIONS="-DENABLE_TESTS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TOOLS=OFF -DENABLE_DOCS=OFF -DCONFIG_MULTITHREAD=1 -DCONFIG_AV1_ENCODER=1" +( + cd /tmp + wget https://github.com/mstorsjo/llvm-mingw/releases/download/20251202/llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz + mkdir -p /app/llvm-mingw + tar -xf llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz -C /app/llvm-mingw --strip-components=1 + export PATH=/app/llvm-mingw/bin:$PATH + export CC=aarch64-w64-mingw32-gcc + export CXX=aarch64-w64-mingw32-g++ + export AR=aarch64-w64-mingw32-ar + export RANLIB=aarch64-w64-mingw32-ranlib + mkdir -p "${AOM_ARM64_DIR}" + cd "${AOM_ARM64_DIR}" + cmake -GNinja -DAOM_TARGET_CPU=generic \ + -DCMAKE_TOOLCHAIN_FILE=${AOM_DIR}/build/cmake/toolchains/arm64-mingw-gcc.cmake \ + -DCMAKE_INSTALL_PREFIX=${AOM_ARM64_DIR}/install ${AOM_CONFIGURE_OPTIONS} ${AOM_DIR} cmake --build . --target install ) @@ -139,7 +228,6 @@ fi FFMPEG_x86_DIR=${BUILD_DIR}/ffmpeg_x86 FFMPEG_x86_64_DIR=${BUILD_DIR}/ffmpeg_x86_64 -FFMPEG_CONFIGURE_OPTIONS="--pkg-config=pkg-config --enable-static --enable-avresample --enable-w32threads --enable-libopenh264 --enable-libvpx --disable-filters --disable-bsfs --disable-programs --disable-debug --disable-cuda --disable-cuvid --disable-nvenc --enable-libaom" #[ -d ${FFMPEG_x86_DIR} ] || ( cd ${FFMPEG_DIR} @@ -159,5 +247,27 @@ FFMPEG_CONFIGURE_OPTIONS="--pkg-config=pkg-config --enable-static --enable-avres make -j${CPU_COUNT} install ) +FFMPEG_ARM64_DIR=${BUILD_DIR}/ffmpeg_arm64 +FFMPEG_CONFIGURE_OPTIONS="--pkg-config=pkg-config --enable-static --enable-avresample --enable-w32threads --enable-libopenh264 --enable-libvpx --disable-filters --disable-bsfs --disable-programs --disable-debug --disable-cuda --disable-cuvid --disable-nvenc --enable-libaom" +#[ -d ${FFMPEG_ARM64_DIR} ] || +( + cd /tmp + wget https://github.com/mstorsjo/llvm-mingw/releases/download/20251202/llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz + mkdir -p /app/llvm-mingw + tar -xf llvm-mingw-20251202-ucrt-ubuntu-22.04-aarch64.tar.xz -C /app/llvm-mingw --strip-components=1 + export PATH=/app/llvm-mingw/bin:$PATH + export CC=aarch64-w64-mingw32-gcc + export CXX=aarch64-w64-mingw32-g++ + export AR=aarch64-w64-mingw32-ar + export RANLIB=aarch64-w64-mingw32-ranlib + cd ${FFMPEG_DIR} + mkdir -p ${FFMPEG_ARM64_DIR} + rsync -a ./ ${FFMPEG_ARM64_DIR} --exclude .git + cd ${FFMPEG_ARM64_DIR} + find . -type f -exec dos2unix {} \; + PKG_CONFIG_PATH=${openh264_ARM64_DIR}/lib/pkgconfig:${libvpx_ARM64_DIR}/install/lib/pkgconfig:${AOM_ARM64_DIR}/install/lib/pkgconfig ./configure --enable-cross-compile --arch=aarch64 --target-os=mingw32 --cross-prefix=aarch64-w64-mingw32- ${FFMPEG_CONFIGURE_OPTIONS} --prefix=`pwd`/install + make -j${CPU_COUNT} install +) + ## OpenCV plugins ./build_videoio_plugin.sh