Repository navigation
Bump FFmpegKit to 8.1.9 (FFmpeg n8.1.3) and fix the SIGXCPU freeze - #23
Merged
Merged
Conversation
FFmpegKit 8.1.9 is the newest upstream release. Upstream reports that its FFmpeg n8.1.3 closes two CVEs reachable in this build, and it restores drawtext, which the earlier builds silently left out. The version comes from the shipped libavcodec.so: n8.1.3 in all eight variants on both ABIs, so this starts a new FFmpeg line at 8.1.3.1 rather than continuing 8.1.2.x. The 8.1.2 row stays in the mapping, so FFmpegKit 8.1.7 remains rebuildable and the file stays append-only. classes.jar is byte-identical to 8.1.7 and the generated api.xml matches in all 24 variant and framework pairs, so Metadata.xml needs no change. The 8.1.9 .pom now declares smart-exception, which the comments denied; the jars stay embedded because no .NET build reads a .pom. Fixes two inaccuracies found on the way: the README said the sample builds on release, which passes verify: false, and `-t:Install` needs a framework because the sample uses plural TargetFrameworks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Running all eight variants locally failed two checks without any FFmpeg fault, so neither says anything about the package under test: ExternalLibraries must be non-empty, but min is built with no external libraries. The published 8.1.2.5 Min fails identically. The progress check stopped waiting at the first sample, which is the one at position zero, and then asserted that position had advanced. Progress<T> posts asynchronously, so the sample that advanced could still be queued. That failed 2 of 9 cold starts on 8.1.3.1 and 0 of 24 on 8.1.2.5. Waiting for an advanced sample keeps the assertion just as strict: 60 of 60 cold starts pass, each receiving both samples, so no callback is being lost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mono on Android restarts the threads it stopped for a garbage collection with SIGXCPU, and FFmpeg's term_init installs its own handler for that signal when a command runs. The restart then never reaches Mono: the next collection leaves every managed thread suspended for good, and the app ends in an ANR. The example app hit this on its first conversion, on this build and on the published 8.1.2.5 alike. Nothing caught it before because CI never deploys the sample and the device checks allocated too little to trigger a collection, so the new check forces collections after FFmpeg has run. It hangs on 8.1.2.5 and on 8.1.3.1 without this change. FFmpegKitConfig.ignoreSignal is upstream's opt-out and has to come before the first command, so the types that can start one call it from their static constructors. A module initializer would load the native libraries as soon as the assembly loads, breaking apps that gate FFmpegKit at runtime, and a failed native load is swallowed so those apps see the same error as before instead of a TypeInitializationException. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merging this file is the release: auto-release.yml tags v8.1.3.1, and release.yml maps that tag to FFmpegKit 8.1.9 through native-versions.tsv. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The regression test can pass without exercising the second managed thread’s stop/restart because garbage collection and shutdown may complete before the allocator task starts.
1 open issue
What changed in this PR
Updates the Android bindings to FFmpegKit 8.1.9 (FFmpeg n8.1.3) for package 8.1.3.1 and adds protection against the Mono garbage-collection freeze caused by FFmpeg taking over SIGXCPU.
Changes:
- Adds the native version mapping and checksum baseline while preserving older mappings.
- Introduces lazy signal protection, a garbage-collection regression check, and corrections to progress and Min-variant checks.
- Updates release notes, version examples, and dependency documentation without changing the public API.
| File | Description |
|---|---|
tests/FFmpegKit.Android.PackageTests/PackageLayoutTests.cs |
Updates comments about native filenames and runtime dependencies. |
tests/FFmpegKit.Android.DeviceTests/SmokeTests.cs |
Adds the freeze regression check and adjusts progress and library assertions. |
src/FFmpegKit.Android/Jars/FetchJars.sh |
Clarifies smart-exception dependency comments. |
src/FFmpegKit.Android/FFmpegKit.Android.csproj |
Updates comments explaining embedded jars. |
src/FFmpegKit.Android/BuildNugets.sh |
Revises usage examples and documents local version naming. |
src/FFmpegKit.Android/Additions/FFmpegKit.Signals.cs |
Adds static initialisation to protect Mono's restart signal. |
samples/FFmpegKit.Android.Example/FFmpegKit.Android.Example.csproj |
Updates version examples and explanatory comments. |
README.md |
Documents the upgrade, freeze protection, and corrected build instructions. |
docs/release-notes/8.1.3.1.md |
Records fixes, native changes, and validation results. |
Directory.Build.props |
Sets FFmpeg 8.1.3 and FFmpegKit 8.1.9 defaults. |
build/native-versions.tsv |
Appends the new version pairing. |
build/checksums/8.1.9.sha256 |
Adds checksums for eight native archives and two jars. |
.github/copilot-instructions.md |
Updates version guidance and signal-protection requirements. |
Review effort: Balanced
Task.Run only queues the work, so all three collections could finish before the allocator started. The check would then pass without any running managed thread to stop and restart, which is the condition it exists to cover. It still hangs on the published 8.1.2.5, which has no SIGXCPU opt-out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 30, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Moves FFmpegKit from 8.1.7 to 8.1.9, which is the first release on FFmpeg n8.1.3, and fixes an app freeze that also affects the published
8.1.2.5. Package 8.1.3.1, tagv8.1.3.1.Closes #21
Don't merge until you've approved it: merging
docs/release-notes/8.1.3.1.mdis the release.Please review first
1. A freeze fix that isn't part of the version bump (commit 73232f5). G4 could not pass without it. The example app froze with an ANR on its first conversion, and it does the same on the published
8.1.2.5, so this is not a regression from 8.1.9.SIGXCPU, and FFmpeg'sterm_initinstalls its own handler for that signal. The next collection after an FFmpeg command then leaves every managed thread suspended for good.FFmpegKitConfig.IgnoreSignal(Signal.Sigxcpu)from static constructors onFFmpegKit,FFmpegKitConfigandAsyncFFmpegExecuteTask. No public API changes. A module initializer was rejected because it would load the native libraries with the assembly, which breaks apps that gate FFmpegKit at runtime.8.1.2.5and on unfixed 8.1.3.1, and passes in all 10 G3 runs here.2. Two device check fixes (commit b49d886). Running all eight variants exposed them, because CI's emulator job only runs
Video:ExternalLibrarieshad to be non-empty, butminhas none. The published8.1.2.5fails the same way.The progress race failed 2 of 9 cold starts on 8.1.3.1 and 0 of 24 on
8.1.2.5, so I can't show that it predates this bump. After the fix, 60 of 60 cold starts pass, each receiving both samples, so no callback is being lost.What changed upstream
n8.1.2→n8.1.3, read fromlibavcodec.soin all 8 variants on both ABIs. Upstream reports that this closes CVE-2026-64830 and CVE-2026-64835. FFmpeg's own history has the matching VobSub and ADX fixes; the CVE numbers are upstream's claim.drawtextreturns toFull,FullGplandVideo:--enable-libharfbuzzand the filter are in the shipped libraries. This was checked in the binaries, not by running the filter on a device.-filter_complexparse error no longer kills the process. Not verified here.MinandHttpsnow shiplibc++_shared.so, about 1 MB larger.aar..pomnow declares smart-exception. The jars stay embedded, because no .NET build reads a.pom.Everything outside
jni/is identical to 8.1.7 in all 8 variants, licences included. All 160.sofiles pass a static GNU_RELRO check and are 16 KB aligned.API changes: none.
classes.jaris byte-identical to 8.1.7 in all 8 variants, and generatedapi.xmlmatches in all 24 variant and framework pairs, soMetadata.xmlis unchanged. Target frameworks, ABIs, minSdk 24 and licensing are unchanged.Mapping: added
8.1.3 8.1.9and kept8.1.2 8.1.7, so 8.1.7 stays rebuildable. The brief's replace-the-row step and its "8.1.7 can no longer be rebuilt" line don't apply, because this is a new FFmpeg.Test report — FFmpegKit.Net.*.Android 8.1.3.1-local.20261030121512
Toolchain: .NET SDK 8.0.427 / 9.0.320 / 10.0.403, android workloads 34.0.154 / 35.0.105 / 36.1.118, JDK 17.0.21, emulator
ffmpegkit_e2e(API 35 google_apis, arm64-v8a), physical Pixel 10 (Android 17, API 37, arm64-v8a). No Xcode involved..aar, licence and n8.1.3 on both ABIs in eachffmpeg=n8.1.3,package=audioffmpeg=n8.1.3,package=custom(see note)ffmpeg=n8.1.3,package=custom(see note)ffmpeg=n8.1.3,package=httpsffmpeg=n8.1.3,package=https-gplffmpeg=n8.1.3,package=minffmpeg=n8.1.3,package=min-gplffmpeg=n8.1.3,package=videoffmpeg=n8.1.3ffmpeg=n8.1.3ffmpeg=n8.1.3, GC check passed; not required, added on the maintainer's requestffmpeg=n8.1.3FFMPEGKIT_E2E_DONE PASS passed=15,ffmpeg=n8.1.3, GC check passed.targetsare unchangedNo check is SKIPPED.
Notes on the evidence:
SmokeTests.cs, a file that isn't packed.SmokeTestsonly asserts thatFFmpegVersionis non-empty, so the local G3 runner compared the logged value againstn8.1.3itself. It's still not enforced in CI.package=custom: published8.1.2.5Full reports the same, with an identical library list, so it isn't a change.reports progresscheck.Videovariant. Locally everything ran on arm64.libmonosgen,libmonodroid,libSystem.*), and net9 and net10 have none. This isn't new and this binding can't fix it. net8 apps will depend on that .NET 8 runtime on 16 KB devices.Corrections to the brief and setup
/usr/local/share/dotnet. That breaks every net8 Android build there, including cleanorigin/main. For this run the eight verified Microsoft packs came from a privateDOTNETSDK_WORKLOAD_PACK_ROOTSfolder, with no machine or repo change. The real fix needssudo, probablydotnet workload repair, which I haven't tested.-t:Installon the sample needs-f <tfm>, because it uses pluralTargetFrameworks. The README is corrected.docs/release-notes/README.mddoesn't exist, so the house style came from the existing notes.Video, and the sample is never deployed there, which is how the freeze stayed hidden. Worth a separate change.🤖 Generated with Claude Code