#!/bin/bash
# Builder B69 (Eval 3, 2026-10-08): the voice scorer's ffmpeg helper for Windows x64, cross-built from the SAME sources
# and the SAME component list as the Mac helper (desktop-voice/ffmpeg-src/build_ffmpeg_floor.sh, B40), with Ubuntu 24.04
# mingw-w64 (the toolchain Eval 1 PB used for the LGPL decoder plugin). One static ffmpeg.exe, libx264 linked in,
# GPL-2.0-or-later (no --enable-version3), started only as its own process (Bhanu's option A, CONTRACT section 12).
#
#   bash build_ffmpeg_win.sh <src dir with the two tarballs + x264-b35605a-version.h> <build dir> <output dir>
#
# Differences from the Mac script, all forced by the target: --target-os=mingw32 --arch=x86_64 --cross-prefix;
# x86 assembly (nasm) instead of NEON (both are the projects' default fast paths, bit-exact to their C code by design);
# Windows threads (x264 win32thread, ffmpeg w32threads) instead of pthreads; static libgcc; no macOS version flags.
# Same: ffmpeg 8.1.1 tarball, x264 commit b35605a + its recorded version lines, -Os, the configure component list.
set -euo pipefail
SCRIPT_SHA=$(sha256sum "$0" | cut -d' ' -f1)
SRC=$(cd "${1:?src dir}" && pwd); BUILD=${2:?build dir}; OUTDIR=${3:?output dir}
X264_COMMIT=b35605ace3ddf7c1a5d67a2eb553f034aef41d55
JOBS=${JOBS:-16}
OPT=${OPT:--Os}
CROSS=x86_64-w64-mingw32-
unset CFLAGS CXXFLAGS LDFLAGS CPPFLAGS PKG_CONFIG_PATH || true
echo "== $(date '+%H:%M:%S') check sources"
[[ $(sha256sum $SRC/ffmpeg-8.1.1.tar.xz | cut -d' ' -f1) == b6863adde98898f42602017462871b5f6333e65aec803fdd7a6308639c52edf3 ]]
[[ $(sha256sum $SRC/x264-$X264_COMMIT.tar.xz | cut -d' ' -f1) == 12e9adc921f31f7500bfd5271eb2766c5f22fb20150d3ca1ed493877e1024565 ]]
mkdir -p $BUILD $OUTDIR; BUILD=$(cd $BUILD && pwd); OUTDIR=$(cd $OUTDIR && pwd)
PREFIX=$BUILD/x264-install
FF_PREFIX=/usr/local/hv-voice-ffmpeg
rm -rf $BUILD/x264-$X264_COMMIT $BUILD/ffmpeg-8.1.1 $BUILD/destdir
tar -xJf $SRC/x264-$X264_COMMIT.tar.xz -C $BUILD
tar -xJf $SRC/ffmpeg-8.1.1.tar.xz -C $BUILD

echo "== $(date '+%H:%M:%S') x264 (static; the Mac's options, cross for Windows x64)"
cd $BUILD/x264-$X264_COMMIT
if [[ -n ${X264_PATCH:-} ]]; then echo "x264 patch: $X264_PATCH ($(sha256sum $X264_PATCH | cut -d' ' -f1))"; patch -p1 < $X264_PATCH; fi
X264_CONF=(--prefix=$PREFIX --host=x86_64-w64-mingw32 --cross-prefix=$CROSS --disable-lsmash --disable-swscale
           --disable-ffms --enable-static --enable-pic --enable-strip --disable-cli "--extra-cflags=$OPT ${X264_EXTRA_CFLAGS:-}")
echo "x264 configure: ${X264_CONF[*]}"
if [[ -n ${X264_CC:-} ]]; then CC="$X264_CC" ./configure "${X264_CONF[@]}"; else ./configure "${X264_CONF[@]}"; fi
grep -v '^#define X264_VERSION \|^#define X264_POINTVER \|^#define X264_REV ' x264_config.h > x264_config.h.new
cat $SRC/x264-b35605a-version.h >> x264_config.h.new
mv x264_config.h.new x264_config.h
grep '^#define X264_\|^#define HAVE_\(WIN32THREAD\|POSIXTHREAD\|THREAD\|X86_INLINE_ASM\|MMX\)' x264_config.h config.h || true
make -j$JOBS
make install-lib-static

echo "== $(date '+%H:%M:%S') ffmpeg 8.1.1 (the Mac helper's component list)"
cd $BUILD/ffmpeg-8.1.1
FF_CONF=(--prefix=$FF_PREFIX --enable-cross-compile --target-os=mingw32 --arch=x86_64 --cross-prefix=$CROSS
         --pkg-config=pkg-config --pkg-config-flags=--static --optflags=$OPT
         --enable-gpl --enable-libx264 --enable-w32threads
         --disable-autodetect --disable-everything --disable-network --disable-doc --disable-ffplay --disable-ffprobe
         --enable-encoder=libx264,aac
         --enable-decoder=vp8,vp9,opus,aac,h264,wrapped_avframe,pcm_u8,pcm_s16le,pcm_s32le,pcm_f32le,pcm_f64le
         --enable-demuxer=matroska,mov
         --enable-muxer=mp4,mov,webm,matroska
         --enable-parser=vp8,vp9,opus,aac,h264
         --enable-bsf=aac_adtstoasc,vp9_superframe
         --enable-filter=aformat,anull,aresample,atrim,asetpts,format,null,scale,trim,setpts,transpose,hflip,vflip,color,anullsrc
         --enable-indev=lavfi
         --enable-protocol=file,pipe
         "--extra-ldflags=-static -static-libgcc -Wl,--no-insert-timestamp")
echo "ffmpeg configure: ${FF_CONF[*]}"
PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig ./configure "${FF_CONF[@]}" > $BUILD/ffmpeg-configure.out
grep -i 'license\|libx264\|External libraries\|threading' -A2 $BUILD/ffmpeg-configure.out | head -24
make -j$JOBS
make install-progs DESTDIR=$BUILD/destdir
mkdir -p $OUTDIR/bin
cp $BUILD/destdir$FF_PREFIX/bin/ffmpeg.exe $OUTDIR/bin/ffmpeg.exe
# Reproducible bytes: strip writes the current time into the PE header. Set TimeDateStamp and the (unchecked for
# programs) optional-header CheckSum to 0, so two builds of the same sources give the same file.
python3 - $OUTDIR/bin/ffmpeg.exe <<'PYEOF'
import struct, sys
b = bytearray(open(sys.argv[1], "rb").read())
pe = struct.unpack_from("<I", b, 0x3C)[0]
assert b[pe:pe + 4] == b"PE\0\0"
struct.pack_into("<I", b, pe + 8, 0)        # COFF TimeDateStamp
struct.pack_into("<I", b, pe + 24 + 64, 0)  # optional header CheckSum
open(sys.argv[1], "wb").write(b)
PYEOF
cp $BUILD/ffmpeg-configure.out $OUTDIR/ffmpeg-configure.out
cp $BUILD/x264-$X264_COMMIT/x264_config.h $OUTDIR/x264_config.h
FFSHA=$(sha256sum $OUTDIR/bin/ffmpeg.exe | cut -d' ' -f1)
python3 - "$OUTDIR/BUILD.json" <<PYEOF
import json, sys
json.dump({"target": "windows x86_64 (mingw-w64)", "x264_commit": "$X264_COMMIT", "x264_tarball": "x264-$X264_COMMIT.tar.xz",
           "x264_tarball_sha256": "$(sha256sum $SRC/x264-$X264_COMMIT.tar.xz | cut -d' ' -f1)",
           "ffmpeg_tarball_sha256": "$(sha256sum $SRC/ffmpeg-8.1.1.tar.xz | cut -d' ' -f1)",
           "x264_configure": "./configure ${X264_CONF[*]//$BUILD/<build>}", "ffmpeg_configure": "./configure ${FF_CONF[*]}",
           "opt": "$OPT", "x264_extra_cflags": "${X264_EXTRA_CFLAGS:-}", "x264_patch": "${X264_PATCH:+$(basename ${X264_PATCH:-x}) $(sha256sum ${X264_PATCH:-/dev/null} | cut -d' ' -f1)}", "x264_cc": "${X264_CC:-${CROSS}gcc}", "x264_cc_version": "$(${X264_CC:-${CROSS}gcc} --version | head -1)", "script_sha256": "$SCRIPT_SHA",
           "gcc": "$(${CROSS}gcc --version | head -1)", "nasm": "$(nasm -v)", "binutils": "$(${CROSS}ld --version | head -1)",
           "mingw_w64_packages": "$(dpkg-query -W -f='${Package}=${Version} ' mingw-w64-common gcc-mingw-w64-x86-64-posix gcc-mingw-w64-x86-64-win32 binutils-mingw-w64-x86-64 mingw-w64-x86-64-dev nasm 2>/dev/null)",
           "ffmpeg_sha256_as_built": "$FFSHA"}, open(sys.argv[1], "w"), indent=1)
PYEOF
echo "== $(date '+%H:%M:%S') done"
${CROSS}objdump -p $OUTDIR/bin/ffmpeg.exe | grep 'DLL Name' | sort -u
sha256sum $OUTDIR/bin/ffmpeg.exe
