#!/bin/zsh
# Builds an LGPL-only, statically linked, universal (arm64 + x86_64) ffmpeg into ./vendor/ffmpeg,
# for bundling inside Dropwheel.app. No GPL or non-free code: H.264/HEVC and AAC go through
# Apple's VideoToolbox and AudioToolbox instead of libx264 and FDK.
# Needs: Xcode command line tools, nasm and pkg-config (brew install nasm pkgconf), Rosetta for x86_64.
set -euo pipefail
cd "$(dirname "$0")/.."
ROOT=$PWD

MIN_MACOS=13.0
ARCHS=(${=ARCHS:-arm64 x86_64})
JOBS=$(sysctl -n hw.ncpu)
WORK=$ROOT/build/ffmpeg-work
OUT=$ROOT/vendor/ffmpeg

# name|version|url|sha256 — pinned sources, the same ones Homebrew uses.
SOURCES=(
  "ffmpeg|9.0.2|https://ffmpeg.org/releases/ffmpeg-9.0.2.tar.xz|8c3850283eb25fa026482078a04051e0be17347b09ef81a0849bec15a96e002e"
  "lame|4.0|https://downloads.sourceforge.net/project/lame/lame/4.0/lame-4.0.tar.gz|3df5124d5ad3a98312ffd7ba6a9b36230e4f8a3e66d3ce0f425e336c32d216eb"
  "opus|1.6.1|https://ftp.osuosl.org/pub/xiph/releases/opus/opus-1.6.1.tar.gz|6ffcb593207be92584df15b32466ed64bbec99109f007c82205f0194572411a1"
  "libogg|1.3.6|https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.6.tar.gz|83e6704730683d004d20e21b8f7f55dcb3383cdf84c0daedf30bde175f774638"
  "libvorbis|1.3.7|https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.7.tar.xz|b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b"
  "libvpx|1.17.0|https://github.com/webmproject/libvpx/archive/refs/tags/v1.17.0.tar.gz|1020f184046187baa2985dbde38e0691f49c44088bca7a1842b0236c6081dc0a"
)

typeset -A VERSION TARBALL
mkdir -p "$WORK/downloads"
for entry in $SOURCES; do
  IFS='|' read -r name version url sha <<< "$entry"
  VERSION[$name]=$version
  file=$WORK/downloads/$name-$version.tar.${url##*.tar.}
  TARBALL[$name]=$file
  if [[ ! -f $file ]] || ! echo "$sha  $file" | shasum -a 256 -c --status; then
    echo "==> Downloading $name $version"
    curl -fL --retry 3 -o "$file" "$url"
    echo "$sha  $file" | shasum -a 256 -c --status || { echo "Checksum mismatch for $name"; exit 1; }
  fi
done

unpack() {  # unpack <name> <dir>
  rm -rf "$2" && mkdir -p "$2"
  tar -xf "${TARBALL[$1]}" -C "$2" --strip-components 1
}

build_arch() {
  local arch=$1 host
  [[ $arch == arm64 ]] && host=aarch64-apple-darwin || host=x86_64-apple-darwin
  local src=$WORK/$arch/src prefix=$WORK/$arch/prefix
  rm -rf "$prefix" && mkdir -p "$src" "$prefix"
  export CC="clang -arch $arch" CXX="clang++ -arch $arch"
  export CFLAGS="-O2 -mmacosx-version-min=$MIN_MACOS" CXXFLAGS="-O2 -mmacosx-version-min=$MIN_MACOS"
  export LDFLAGS="-mmacosx-version-min=$MIN_MACOS"
  export PKG_CONFIG_PATH=$prefix/lib/pkgconfig PKG_CONFIG_LIBDIR=$prefix/lib/pkgconfig
  local auto=(--host=$host --prefix=$prefix --enable-static --disable-shared)

  echo "==> [$arch] lame"
  unpack lame "$src/lame"
  (cd "$src/lame" && ./configure $auto --disable-frontend --disable-decoder >/dev/null && make -j$JOBS install >/dev/null)

  echo "==> [$arch] opus"
  unpack opus "$src/opus"
  (cd "$src/opus" && ./configure $auto --disable-doc --disable-extra-programs >/dev/null && make -j$JOBS install >/dev/null)

  echo "==> [$arch] libogg"
  unpack libogg "$src/libogg"
  (cd "$src/libogg" && ./configure $auto >/dev/null && make -j$JOBS install >/dev/null)

  echo "==> [$arch] libvorbis"
  unpack libvorbis "$src/libvorbis"
  # 1.3.7 passes -force_cpusubtype_ALL, which Apple's current linker rejects.
  sed -i '' 's/ -force_cpusubtype_ALL//g' "$src/libvorbis/configure"
  (cd "$src/libvorbis" && ./configure $auto --with-ogg=$prefix --disable-docs --disable-examples >/dev/null \
    && make -j$JOBS install >/dev/null)

  echo "==> [$arch] libvpx"
  unpack libvpx "$src/libvpx"
  (cd "$src/libvpx" && ./configure --target=$arch-darwin22-gcc --prefix=$prefix \
    --enable-static --disable-shared --enable-pic --enable-vp9-highbitdepth \
    --disable-examples --disable-tools --disable-docs --disable-unit-tests >/dev/null \
    && make -j$JOBS install >/dev/null)

  echo "==> [$arch] ffmpeg"
  unpack ffmpeg "$src/ffmpeg"
  local cross=()
  [[ $arch != $(uname -m) ]] && cross=(--enable-cross-compile)
  (cd "$src/ffmpeg" && ./configure --prefix=$prefix --arch=$arch --target-os=darwin $cross \
    --cc="clang -arch $arch" --cxx="clang++ -arch $arch" \
    --extra-cflags="-mmacosx-version-min=$MIN_MACOS -I$prefix/include" \
    --extra-ldflags="-mmacosx-version-min=$MIN_MACOS -L$prefix/lib" \
    --pkg-config=pkg-config --pkg-config-flags=--static \
    --disable-gpl --disable-nonfree --disable-autodetect \
    --enable-static --disable-shared --disable-doc --disable-debug \
    --disable-ffplay --disable-ffprobe --disable-network --disable-devices \
    --enable-videotoolbox --enable-audiotoolbox --enable-zlib --enable-bzlib \
    --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx >/dev/null \
    && make -j$JOBS >/dev/null)
  cp "$src/ffmpeg/ffmpeg" "$WORK/$arch/ffmpeg"
}

for arch in $ARCHS; do build_arch $arch; done

rm -rf "$OUT" && mkdir -p "$OUT/bin" "$OUT/licenses"
lipo -create $(for arch in $ARCHS; do echo "$WORK/$arch/ffmpeg"; done) -output "$OUT/bin/ffmpeg"
strip -x "$OUT/bin/ffmpeg"

# Licence texts and a record of exactly what went in, as the LGPL asks.
src=$WORK/${ARCHS[1]}/src
cp "$src/ffmpeg/COPYING.LGPLv2.1" "$OUT/licenses/ffmpeg-COPYING.LGPLv2.1"
cp "$src/ffmpeg/LICENSE.md" "$OUT/licenses/ffmpeg-LICENSE.md"
cp "$src/lame/COPYING" "$OUT/licenses/lame-COPYING"
cp "$src/opus/COPYING" "$OUT/licenses/opus-COPYING"
cp "$src/libogg/COPYING" "$OUT/licenses/libogg-COPYING"
cp "$src/libvorbis/COPYING" "$OUT/licenses/libvorbis-COPYING"
cp "$src/libvpx/LICENSE" "$OUT/licenses/libvpx-LICENSE"
cp "$src/libvpx/PATENTS" "$OUT/licenses/libvpx-PATENTS"
{
  echo "Dropwheel bundles an unmodified, LGPL-only build of FFmpeg and the libraries below."
  echo "Built by scripts/build_ffmpeg.sh for macOS $MIN_MACOS+ ($ARCHS)."
  echo
  for entry in $SOURCES; do
    IFS='|' read -r name version url sha <<< "$entry"
    echo "$name $version"
    echo "  source: $url"
    echo "  sha256: $sha"
  done
  echo
  echo "FFmpeg configuration:"
  "$OUT/bin/ffmpeg" -hide_banner -buildconf 2>/dev/null | sed 's/^/  /'
} > "$OUT/licenses/SOURCES.txt"

"$OUT/bin/ffmpeg" -hide_banner -L | head -3
lipo -info "$OUT/bin/ffmpeg"
du -h "$OUT/bin/ffmpeg"
