CI rebuilt FFmpeg on every cold cache, which made results ambiguous: a red run could mean the code was broken or that a forty-minute cross-compile of FFmpeg, x264, x265 and SVT-AV1 had hiccuped. Those are not the same signal, and only one of them is worth a developer's attention. The archive is now checked in under bin/, so a failing run points at code. It also removes roughly forty minutes from a cold run and lets a fresh clone build without a container toolchain. bin/README.md records provenance -- upstream tag, FFmpeg version, NDK, ABIs, SHA-256 and the full configure line read back out of the shipped libavutil -- so the binary is auditable rather than opaque. The recipe in tools/ffmpeg remains the authority: this archive is its output, and is also what satisfies the GPL corresponding-source obligation. The status check is now seven independent runners: one validating the archive, one for the JVM tests, and one per API level from 33 to 37. The FFmpeg job verifies rather than builds. It asserts native libraries are present for both ABIs and that every one is 16 KB aligned, which is a Play requirement that is easy to lose in a rebuild and expensive to discover at submission. Checking for file existence alone would not do: a Git LFS pointer checked out without LFS passes that and then surfaces as an obscure linker error much later. It is a separate job rather than a step in each emulator run so a bad archive reports once, clearly, instead of five confusing emulator failures. build.yml no longer builds FFmpeg either, and keeps only its post-merge and release duties. Two costs, deliberately accepted. The repository goes from about 1 MB to 35 MB, and every future rebuild adds another 35 MB blob to history permanently, so bin/README.md says to regenerate only when the FFmpeg version or the configure flags actually change. And F-Droid's scanner flags checked-in native libraries, so submitting there needs a scandelete entry for bin/ -- noted in bin/README.md, and nothing prevents a from-source build. Verified against the relocated archive: 66 unit tests, and 40 instrumented tests on an API 36 emulator, 0 failures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
81 lines
3.1 KiB
Markdown
81 lines
3.1 KiB
Markdown
# Prebuilt FFmpeg
|
|
|
|
`ffmpeg-kit-next-8.1.1.aar` is committed here deliberately, and this file records what
|
|
it is so the binary is auditable rather than opaque.
|
|
|
|
## Why it is committed
|
|
|
|
Tests must be deterministic. When CI rebuilt FFmpeg on every run, a red build could mean
|
|
"the code is broken" or "a 40-minute cross-compile hiccuped", and those are not the same
|
|
signal. Committing the artifact removes the second possibility entirely: a test run
|
|
either passes or points at real code.
|
|
|
|
It also removes roughly forty minutes from every cold CI run.
|
|
|
|
## Provenance
|
|
|
|
| | |
|
|
|---|---|
|
|
| Upstream | [arthenica/ffmpeg-kit-next](https://github.com/arthenica/ffmpeg-kit-next) v8.1.1 |
|
|
| FFmpeg | 8.1.2 |
|
|
| NDK | r27d (27.3.13750724), pinned by the upstream flake |
|
|
| API level | 33, matching the app's minSdk |
|
|
| ABIs | arm64-v8a, x86_64 |
|
|
| Shared libraries | 20 (10 per ABI) |
|
|
| SHA-256 | `ae188c9aec3c89a1c87a169589253c85438d57cfdcc3ce8b40fb3e87de368ff2` |
|
|
|
|
Configure line, read back out of the shipped `libavutil.so`:
|
|
|
|
```
|
|
--enable-asm --enable-cross-compile --enable-gpl --enable-iconv
|
|
--enable-inline-asm --enable-jni --enable-libass --enable-libdav1d
|
|
--enable-libfontconfig --enable-libfreetype --enable-libfribidi
|
|
--enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus
|
|
--enable-libsvtav1 --enable-libvpx --enable-libx264 --enable-libx265
|
|
--enable-lto --enable-mediacodec --enable-neon --enable-optimizations
|
|
--enable-pic --enable-pthreads --enable-shared --enable-small
|
|
--enable-swscale --enable-v4l2-m2m --enable-version3 --enable-zlib
|
|
```
|
|
|
|
Every `.so` reports `LOAD align 0x4000`, so the archive satisfies the 16 KB page-size
|
|
requirement. Verify with:
|
|
|
|
```sh
|
|
unzip -o bin/ffmpeg-kit-next-8.1.1.aar 'jni/*' -d /tmp/aarcheck
|
|
for f in /tmp/aarcheck/jni/*/*.so; do
|
|
readelf -lW "$f" | awk -v f="$f" '$1=="LOAD"{print f, $NF}'
|
|
done | sort -u -k2
|
|
```
|
|
|
|
## Licensing
|
|
|
|
Built with `--enable-gpl` and `--enable-version3`, so this binary is **GPL-3.0** and the
|
|
distributed APK is GPL-3.0 with it. That is deliberate: x264 and x265 are the only route
|
|
to CRF and two-pass rate control, which no Android hardware encoder exposes. See
|
|
[`../LICENSES/README.md`](../LICENSES/README.md).
|
|
|
|
GPL-3.0 obliges us to ship corresponding source with the binary. The recipe in
|
|
[`../tools/ffmpeg`](../tools/ffmpeg) is that source, and it remains the authority: this
|
|
archive is its output, not a substitute for it.
|
|
|
|
## Rebuilding
|
|
|
|
```sh
|
|
cd tools/ffmpeg
|
|
podman build -t ffmpeg-kit-builder:local -f Containerfile .
|
|
mkdir -p out
|
|
podman run --name ffmpeg-build -v "$PWD/out":/work/out:Z localhost/ffmpeg-kit-builder:local full
|
|
cp out/ffmpeg-kit-next-*.aar ../../bin/
|
|
```
|
|
|
|
Update the SHA-256 above when you do. Note that replacing this file adds another ~34 MB
|
|
blob to git history permanently, so rebuild only when the FFmpeg version or the configure
|
|
flags actually change.
|
|
|
|
## F-Droid
|
|
|
|
F-Droid's scanner flags checked-in prebuilt native libraries. If the app is submitted
|
|
there, the metadata needs a `scandelete` entry for `bin/` so their build uses the recipe
|
|
in `tools/ffmpeg` rather than this archive. Nothing here prevents a from-source build;
|
|
the recipe is complete on its own.
|