Skip to content

Latest commit

 

History

History
346 lines (285 loc) · 18.2 KB

File metadata and controls

346 lines (285 loc) · 18.2 KB

Roadmap and qualification gates

The ABI, correctness, ownership, and release-matrix bootstrap; Android compile/emulator phases; iOS compile and XCFramework integration; and Windows/macOS desktop closure are complete. Remaining integration and platform work includes:

  • migrating go-avebi from its temporary backend fork to go-ffmpeg-ffi and rerunning its playback and resource matrix;
  • Samsung Galaxy Tab A9+ physical runtime, MediaCodec, thermal, and sustained H.264/H.265 30/60 FPS qualification;
  • signed runtime, VideoToolbox, audio, lifecycle, and sustained-load tests on a named physical iPhone; and
  • native Windows ARM64 runtime evidence when a suitable runner is available.

The sections below retain the completed bootstrap plan and the evidence gates used to earn current support. Current claims are summarized in support.md.

PR 1: establish the hard-fork baseline — complete

  • Adopt the go-ffmpeg-ffi repository, package, and module identity.
  • Preserve the complete ffgo Git history, Apache-2.0 license, and upstream attribution.
  • Record the exact upstream commit from which the hard fork starts.
  • Carry the known FFmpeg 6 audio-layout, swr_convert, callback, and FFmpeg 6/7 ABI corrections into a traceable baseline.
  • Replace inherited compatibility, coverage, platform, and performance claims that have not been verified.
  • Add the hard-fork, Codex-assistance, and human-review disclosures.

Complete when a clean clone builds under the new module path and no public document presents inherited claims as go-ffmpeg-ffi guarantees.

PR 2: make FFmpeg 6-9 ABI selection safe — complete

  • Centralize library discovery and registration instead of binding the complete API from package init() functions.
  • Read the complete core and optional-library version tuple before selecting an ABI family.
  • Inventory every direct FFmpeg structure access and move verified layouts into internal/abi; no private magic offsets remain.
  • Generate or verify layouts for FFmpeg 6, 7, 8, and 9 against matching headers.
  • Establish a pinned Linux amd64 gate for the latest patch of the 6.0, 6.1, 7.0, 7.1, 8.0, 8.1, and 9.0 release lines.
  • Version the C shim by operating system, architecture, shim API, and FFmpeg family; add a startup handshake and reject mismatches.
  • Reject mixed families, FFmpeg 4, future development majors, and unknown layouts with a diagnostic error before unsafe field access.
  • Decide whether FFmpeg 5.1 earns a narrowly scoped Debian 12 legacy tier, a CI job, and a sunset date. Otherwise remove it from the matrix.

Complete when every target family initializes through the same loader and all unsupported combinations fail closed.

PR 3: correct decoder and encoder state machines — complete

  • Model the complete FFmpeg send/receive protocol, including EAGAIN retry.
  • Flush once and drain delayed video and audio output through FFmpeg EOF.
  • Preserve packets for every selected stream rather than losing interleaved data.
  • Propagate decode, encode, flush, mux, and trailer errors consistently.
  • Add focused fixtures for delayed codecs, multiple streams, seeking, EOF, and truncated input.

Complete when reference counts and timestamps demonstrate that normal and delayed frames are neither lost nor duplicated.

PR 4: make ownership, callbacks, and cancellation safe — complete

  • Define owned, borrowed, clone, Into, and zero-copy lifetimes.
  • Correct plane access, extended_data, pooling, and native cleanup.
  • Pass callback handles as integer tokens, recover callback panics, and retain the original Go error.
  • Add context-aware open/read operations and make close unblock pending I/O.
  • Document object-level concurrency guarantees.
  • Test repeated open/decode/seek/close, malformed and custom I/O, callback failure, cancellation, and concurrent independent decoders.

Complete when stress runs show no invalid callback pointers, leaked handles, unbounded native memory, file-descriptor growth, or blocked shutdowns.

PR 5: compatibility matrix complete; go-avebi migration pending

PR 2 establishes the Linux amd64 release-line gate. PR 5 expands that same matrix with the complete behavioral, resource, and downstream integration suite, using the latest patched release pinned for each line:

Line Initial pin Required
5.1 5.1.10 Only if the legacy tier is accepted.
6.0 6.0.1 Yes.
6.1 6.1.6 Yes.
7.0 7.0.3 Yes.
7.1 7.1.5 Yes.
8.0 8.0.3 Yes.
8.1 8.1.2 Yes.
9.0 9.0.1 Yes.

These pins were checked on 2026-08-13 against the official FFmpeg release index.

Testing every release line catches header and build differences without running every historical patch that shares the same stable library ABI. A scheduled job checks for newer patch releases; pin updates remain explicit and reviewable.

Each required matrix job:

  • builds a shared FFmpeg test configuration and the matching shim;
  • verifies tarball signatures or checksums and records the configure flags;
  • asserts the actual loaded versions and shim handshake;
  • runs unit and integration tests with CGO_ENABLED=0;
  • exercises decode, encode, audio resampling, custom I/O, seek, flush, and error paths with audio-only and audio/video media;
  • runs repeated lifecycle and parallel-decoder stress tests;
  • records goroutines, callback handles, file descriptors, RSS, and native allocations, with sanitizer or Valgrind coverage for the C shim;
  • tests no-shim behavior separately for features that are genuinely optional.

CI-only FFmpeg builds may enable GPL codecs needed by inherited tests. They are not distributed. Prebuilt release shims remain subject to the LGPL-only policy in Architecture.

Local validation repeats the matrix from versioned directories inside the workspace, never a transient system path. For each FFmpeg line it first tests go-ffmpeg-ffi, then points a go-avebi integration checkout at the local module with a workspace-only replace in that checkout. The existing go-ebiten-mcp examples run against the same media fixture containing both video and sound so decoding, audio conversion, playback, seeking, shutdown, and the callback path are all exercised. A machine-readable result matrix records the exact Go, FFmpeg, shim, go-avebi, and go-ebiten-mcp revisions.

Complete when every supported line passes the same required suite in CI and the local go-avebi matrix has no crashes, growing resources, or unexplained output differences.

PR 6: stabilize the public API and release process — in progress

  • Set the high-level/low-level package boundary and consolidate duplicate constructors and options.
  • Expose runtime diagnostics and capability discovery without leaking ABI details.
  • Finish the concise user documentation and migrate only validated examples.
  • Define semantic versioning, deprecation, security, and support-window policy.
  • Publish reproducible shims, manifests, source/configuration material, and checksums for validated targets.

Complete when the API has an explicit compatibility promise and the first release can be reproduced from its tag.

Platform expansion program

Platform support is earned in three separate stages:

  1. Compile: every importable package and its tests compile for the target, with the expected public API present.
  2. Integrate: an external application packages the native libraries, loads FFmpeg, and exercises representative audio/video paths on the target OS.
  3. Qualify: named hardware passes codec, stability, and performance tests.

Passing an earlier stage does not imply a later one. In particular, emulator graphics acceleration is not evidence that a physical device provides FFmpeg MediaCodec, VideoToolbox, or 60 FPS performance.

go-ffmpeg-ffi remains independent of Ebitengine. Ebitengine applications are downstream integration fixtures: the binding does not import Ebitengine, expose an Ebitengine API, or make the engine part of its platform implementation.

Target order and support floor

Order Target Architecture and floor Planned evidence
1 Android production arm64-v8a, Android 13 / API 33 Compile CI, external APK, and Samsung Galaxy Tab A9+ qualification.
1 Android emulator x86_64, Android 13 / API 33 GPU-accelerated application integration; not a shipping ABI or hardware-codec benchmark.
2 iOS iOS 13+ arm64 device; simulator arm64 and amd64 while supported by the selected Xcode Compile and Ebitengine XCFramework binding first; physical qualification waits for a named reference iPhone.
3 Windows amd64, then arm64 Replace the Unix loader calls, add compile CI, and add native runtime evidence.
Continuous macOS amd64, arm64 Preserve the existing native compile/runtime jobs as regression gates.
Continuous Linux amd64, arm64 Preserve the primary FFmpeg release-line and stress matrix.

PureGo treats Android and iOS 64-bit targets as Tier 1, but requires CGO_ENABLED=1 for them. The mobile build is therefore still PureGo-based, but it requires the Android NDK or Xcode C toolchain. Desktop targets retain the CGO-free application-build goal where PureGo supports it.

Android phase A: make the module compile — complete

  • Remove the blanket Android exclusions and replace them with capability-based build constraints.
  • Split library open, symbol lookup, close, naming, and search policy by platform. Android uses its native linker and packaged .so files rather than desktop search paths.
  • Verify every enabled ABI layout against Android FFmpeg headers for each supported FFmpeg family. Do not infer layout compatibility from Linux alone.
  • Keep the public API present. Operations that are genuinely unavailable on Android return a documented unsupported-capability error instead of disappearing behind build constraints.
  • Pin an NDK and compile all packages and test binaries with API 33 toolchains for arm64-v8a and x86_64. Native FFmpeg libraries are not required for the compile-only gate.
  • Compare the exported API with the Linux reference so a green mobile build cannot be produced by accidentally excluding most of the module.

Complete when go list ./..., package builds, and test compilation succeed for both Android targets with the intended public surface and without an Ebitengine dependency.

Current master evidence (13 August 2026): this compile gate passes for API 33 arm64 and amd64, including every root package and test binary. The external Ebitengine fixture remains a separate module.

Android phase B: emulator integration — complete

  • Maintain the external-module fixture in integration/android-ebiten and build it with apk-ebiten-builder. Packaging FFmpeg .so files belongs to that fixture or its builder, not to the Go binding.
  • Run an Android 13 / API 33 x86_64 AVD with VM acceleration and host GPU graphics where the runner exposes them.
  • Install and launch the APK through the connected Android automation tooling; retain screenshots, application state, logcat output, FFmpeg library/version diagnostics, and crash traces as test evidence.
  • Exercise library initialization, audiovisual decode, audio conversion, frame presentation through Ebitengine, seek, EOF, cancellation, and clean shutdown with the same small redistributable fixture used by desktop tests.
  • Treat emulator MediaCodec results as diagnostic only. The host GPU validates Ebitengine graphics; it does not emulate the Snapdragon video codec blocks in the reference tablet.

Complete when a reproducible APK runs through the audiovisual scenario without crashes, missing symbols, growing resources, or unexplained output differences.

Current branch evidence (12 August 2026): the API 33 x86-64 APK loads FFmpeg 8.0.3, software-decodes all 60 H.264 frames, converts and presents RGBA through Ebitengine, software-decodes all 87 AAC frames, resamples them to 96,967 S16 stereo samples at 48 kHz, and starts an Ebitengine audio player. The current host exposes neither /dev/kvm nor /dev/dri, so this run uses TCG and SwiftShader and is correctness evidence only. Stable EOF, a frame-accurate seek to one second, cancellation, and successful decoder reuse after cancellation also pass. The probe cancels and closes its FFmpeg/audio resources on Android onStop, then completes the full audiovisual path again after onStart in the same process.

The reproducible prolonged/stress runner completed 20 full lifecycle cycles in one process followed by a separate 30-cycle rapid-cancellation run and a full recovery. All 20 prolonged cycles completed the H.264/AAC scenario. The rapid run interrupted video 16 times and audio 14 times; all 30 shutdowns completed, and the final audiovisual recovery passed. The prolonged run grew from 73,848 to 84,444 KiB PSS and from 173,188 to 186,432 KiB RSS as the process warmed, but cycles 10 through 20 added only 134 KiB PSS and 308 KiB RSS. Threads finished at 37 from 33 and file descriptors returned to their baseline of 124. Across the rapid run and recovery, PSS grew 967 KiB, RSS 1,668 KiB, threads by four, and file descriptors by one. The PID remained stable and the retained logs contain no probe failure, app ANR, or native crash. This closes the emulator resource-growth gate for phase B; it remains correctness and lifecycle evidence, not GPU, MediaCodec, audible-audio, thermal, or frame-rate evidence.

Android phase C: Galaxy Tab A9+ qualification — pending physical device

The Samsung Galaxy Tab A9+ is the minimum supported Android device and the physical acceptance reference. Its launch platform, Android 13 / API 33, is the OS floor; newer Android devices and framework versions must remain compatible.

  • Install the exact APK already exercised by the emulator, using its arm64-v8a native libraries.
  • Record device model, Android build, ABI, FFmpeg configuration and versions, selected decoders/encoders, and the MediaCodec capability report.
  • Test H.264 and H.265 software and MediaCodec paths separately. A codec name or API being present is not sufficient evidence that frames stay on the hardware path.
  • Measure 30 and 60 FPS workloads separately, including dropped/late frames, audiovisual drift, CPU load, memory, temperature-related throttling, and clean resource release. Screenshots prove rendered output, not frame rate.
  • Report decode and encode results separately. A device can decode a profile or resolution in hardware without being able to encode the same combination.
  • Run a sustained test after the short correctness case so a transient 60 FPS result is not presented as stable performance.

Compilation support is complete independently of hardware acceleration. MediaCodec and 60 FPS claims are published only for the exact codec, profile, resolution, pixel format, device, Android build, and FFmpeg configuration that passed qualification.

iOS phase — compile complete, physical qualification pending

  • Reuse the platform loader boundary established by Android, with iOS-specific signed-framework naming, application-bundle resolution, and a process-image fallback for complete statically linked FFmpeg symbols.
  • Compile all packages and tests for ARM64 device and simulator targets with Xcode and CGO_ENABLED=1; retain Intel simulator coverage only while the supported Xcode toolchain provides it.
  • Verify ABI layouts against the selected iPhoneOS and simulator SDKs.
  • Use an external application fixture for runtime integration; do not add an Ebitengine dependency or XCFramework packaging responsibility to the module.
  • Qualify VideoToolbox and sustained codec performance on a named physical device. Simulator graphics and codec results are not physical-device qualification.

The deployment floor is iOS 13.0, matching Ebitengine and gomobile. The compile gate covers iphoneos/arm64, iphonesimulator/arm64, and iphonesimulator/amd64, plus a downstream Ebitengine XCFramework built from integration/ios-ebiten. FFmpeg/shim binaries stay the responsibility of the signed Xcode application.

No physical reference iPhone has been nominated yet. Until one is recorded and passes the signed-app runtime, codec, lifecycle, thermal, and sustained-load suite, iOS support claims stop at compilation and XCFramework integration.

Windows and macOS closure — complete except Windows ARM64 runtime

The platform-neutral loader boundary is implemented while keeping library family selection and PureGo symbol registration shared. Windows uses LoadLibrary, GetProcAddress, and FreeLibrary; macOS uses its native dynamic loader path. The completed closure:

  • compile every package and test binary for Windows and macOS amd64/arm64;
  • run the complete FFmpeg and shim suite natively on Windows amd64;
  • verify the C-header ABI layout and rerun the complete suite natively on macOS Intel and Apple Silicon after the loader refactor;
  • extend native runtime coverage to Windows ARM64 when a runner is available; and
  • keep hardware acceleration capability-driven: D3D11VA/DXVA2 and VideoToolbox are not implied by successful compilation.

Windows amd64 now loads the public FFmpeg 9.0.1 shared build and compatible shim through the Windows loader. Both Windows architectures pass the complete compile gate, and both macOS architectures retain native ABI/runtime evidence. Windows ARM64 remains compile-qualified, not runtime-qualified, until a native runner is available.

Unscheduled ecosystems

FreeBSD remains best-effort pending a pinned native runner. WebAssembly cannot use the current dynamic-FFmpeg/PureGo architecture and would require a distinct backend. Nintendo Switch and Xbox require their proprietary SDK and program access before feasibility can be evaluated; they are not inferred from Ebitengine application support. PlayStation is not a public Ebitengine target and is not scheduled. None of these platforms is part of the Android/iOS delivery sequence.

Review contract

Every PR states the affected FFmpeg lines, ownership or ABI implications, tests run, known gaps, and whether Codex assisted materially. Refactors do not hide unrelated features.