Skip to content

fix: allow core-mt WASM memory to grow to avoid OOM on 4K frames (#946) - #948

Open
ousamabenyounes wants to merge 1 commit into
ffmpegwasm:mainfrom
ousamabenyounes:fix/issue-946
Open

ousamabenyounes wants to merge 1 commit into
ffmpegwasm:mainfrom
ousamabenyounes:fix/issue-946

Conversation

@ousamabenyounes

Copy link
Copy Markdown

The multi-threaded core build pinned INITIAL_MEMORY=1024MB with no growth, so decoding a single high-resolution (e.g. 4K) frame aborted with Aborted(OOM). Enable bounded -sALLOW_MEMORY_GROWTH -sMAXIMUM_MEMORY=2GB for the FFMPEG_MT build (growable SharedArrayBuffer is supported by modern browsers/Emscripten).

Test verification (RED → GREEN)

With the fix reverted, the new test fails (RED):



  [build] core-mt memory growth (#946)
core-mt build flags: ${FFMPEG_MT:+ -sINITIAL_MEMORY=1024MB}   # ALLOW_MEMORY_GROWTH is not recommended when using threads, thus we use a large initial memory
    1) allows memory growth up to a maximum for the multi-threaded build


  0 passing (7ms)
  1 failing

  1) [build] core-mt memory growth (#946)
       allows memory growth up to a maximum for the multi-threaded build:
     AssertionError [ERR_ASSERTION]: core-mt build must pass -sALLOW_MEMORY_GROWTH to avoid OOM on large frames
      at Context.<anonymous> (tests/build-mt-memory-growth.test.js:25:12)
      at process.processImmediate (node:internal/timers:484:21)

With the fix applied, the test passes (GREEN):

GREEN attempt 1/2 (exit 0)


  [build] core-mt memory growth (#946)
core-mt build flags: ${FFMPEG_MT:+ -sINITIAL_MEMORY=1024MB -sALLOW_MEMORY_GROWTH -sMAXIMUM_MEMORY=2GB} # start with a large initial memory, but still allow growth (up to 2GB) so decoding high-resolution input (e.g. 4K) does not abort with OOM (#946)
    ✔ allows memory growth up to a maximum for the multi-threaded build


  1 passing (6ms)

Full local suite

Command: npm run lint && npm run build && npm test


> lint
> npm-run-all lint:*

sh: 1: npm-run-all: not found

Fix #946

@netlify

netlify Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for ffmpegwasm canceled.

Name Link
🔨 Latest commit c8d67c5
🔍 Latest deploy log https://app.netlify.com/projects/ffmpegwasm/deploys/6aa1e2c82fcd7b0008df1638

Project516 added a commit to Project516/ffmpeg.wasm that referenced this pull request Sep 24, 2026
Bumps every vendored third-party library to its latest stable tag,
switching mirrored libraries (x265, libvpx, ogg, theora, opus, vorbis,
zlib, libwebp, freetype2) to canonical upstream where a diff showed the
ffmpegwasm/* mirror carries no emscripten-specific patch. x264 stays on
the ffmpegwasm mirror (diverged too far from upstream to reconcile) and
lame stays on its mirror (upstream has no maintained git tags). harfbuzz
is pinned at 8.5.0, the last release with an autotools build; 9.0+ is
meson-only and needs build/harfbuzz.sh rewritten separately.

Also demotes a few C dialect checks the newer clang in emsdk 6.0.10
turned into hard errors, and lets the core-mt build's wasm memory grow
(bounded at 2GB) instead of a fixed 1GB, so decoding a single 4K frame
does not abort with OOM (ffmpegwasm#948).

Co-authored-by: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com>
Project516 added a commit to Project516/ffmpeg.wasm that referenced this pull request Sep 24, 2026
Bumps every vendored third-party library to its latest stable tag,
switching mirrored libraries (x265, libvpx, ogg, theora, opus, vorbis,
zlib, libwebp, freetype2) to canonical upstream where a diff showed the
ffmpegwasm/* mirror carries no emscripten-specific patch. x264 stays on
the ffmpegwasm mirror (diverged too far from upstream to reconcile) and
lame stays on its mirror (upstream has no maintained git tags). harfbuzz
is pinned at 8.5.0, the last release with an autotools build; 9.0+ is
meson-only and needs build/harfbuzz.sh rewritten separately.

Also demotes a few C dialect checks the newer clang in emsdk 6.0.10
turned into hard errors, and lets the core-mt build's wasm memory grow
(bounded at 2GB) instead of a fixed 1GB, so decoding a single 4K frame
does not abort with OOM (ffmpegwasm#948).

Co-authored-by: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com>
Project516 added a commit to Project516/ffmpeg.wasm that referenced this pull request Sep 24, 2026
* build: bump emsdk to 6.0.10 and ffmpeg to n5.1.10

Bumps every vendored third-party library to its latest stable tag,
switching mirrored libraries (x265, libvpx, ogg, theora, opus, vorbis,
zlib, libwebp, freetype2) to canonical upstream where a diff showed the
ffmpegwasm/* mirror carries no emscripten-specific patch. x264 stays on
the ffmpegwasm mirror (diverged too far from upstream to reconcile) and
lame stays on its mirror (upstream has no maintained git tags). harfbuzz
is pinned at 8.5.0, the last release with an autotools build; 9.0+ is
meson-only and needs build/harfbuzz.sh rewritten separately.

Also demotes a few C dialect checks the newer clang in emsdk 6.0.10
turned into hard errors, and lets the core-mt build's wasm memory grow
(bounded at 2GB) instead of a fixed 1GB, so decoding a single 4K frame
does not abort with OOM (ffmpegwasm#948).

Co-authored-by: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com>

* fix: free exec()/ffprobe() argv and restore the wasm stack pointer

ffmpeg and ffprobe exit via exit(), which Emscripten implements by
throwing. The exception unwinds the JS frames but not the WebAssembly
stack, so every call leaked stack space (ffmpegwasm#943);
separately, the malloc'd argv strings and argv array from stringsToPtr()
were never freed. Repeated calls in one session exhausted the heap and
stack until 'memory access out of bounds'. Both are now cleaned up in a
finally block. Needs a new core build to take effect.

Co-authored-by: Mrmaxmeier <Mrmaxmeier@gmail.com>

* fix: drop the ffmpeg-core.worker.js codepath

emsdk >= 3.1.58 stopped needing a separate worker.js for multi-threaded
cores (folded into the main core script), and >= 3.1.68 stops emitting
even a stub. bind.js's _locateFile no longer routes .worker.js lookups,
worker.ts no longer computes or forwards a workerURL to the core, and
core-mt's package.json drops the now-nonexistent './worker' export.
FFMessageLoadConfig.workerURL stays as an accepted-but-unused, deprecated
option so existing callers do not break.

* fix: stop x265 from injecting -march=i686 under emscripten

Emscripten's toolchain file reports CMAKE_SYSTEM_PROCESSOR=x86 for legacy
bitness-check compatibility. x265 4.x's CMakeLists.txt treats any 32-bit
x86 target as real ia32 and force-adds -march=i686, which emcc's clang
rejects outright for wasm32 ('unsupported option -march= for target
wasm32-unknown-emscripten'). Report a processor name x265 has no x86
special case for instead.

* fix: run vorbis configure as a separate step

Canonical upstream's autogen.sh (autoreconf -if) no longer runs configure
itself the way the old ffmpegwasm mirror's did, so passing configure
flags straight to autogen.sh silently dropped them and left no Makefile.

* fix: pass --static to pkg-config for ffmpeg's configure

Canonical vorbis (and likely others) now list transitive deps under
Requires.private in their .pc files instead of the old ffmpegwasm
mirror's plain Requires:. Plain `pkg-config --libs` ignores private
requires, so linking against e.g. vorbisenc alone dropped -lvorbis/-logg
and ffmpeg's configure reported 'vorbisenc not found using pkg-config'.
--pkg-config-flags=--static makes pkg-config include private deps, which
is what every one of these libraries is built as (static-only).

* build(x265): drop host-only libs from x265.pc Libs.private

FFmpeg's configure runs pkg-config with --static, which pulls in
Libs.private. x265 lists gcc_s, rt, and dl there; emscripten has none of
them, so the x265 link check failed.

* build(ffmpeg): print config.log tail when configure fails

* build: link libc++ for x265 with -sDEFAULT_TO_CXX

* build: stub sem_close/sem_unlink for st x265 and install zlib.pc

* build: static-only zlib and full config.log on configure failure

* build: let the core run on a page and spawn UMD pthreads from the core script

* docs(agents): write down the FFmpeg upgrade plan

---------

Co-authored-by: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com>
Co-authored-by: Mrmaxmeier <Mrmaxmeier@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core-mt: RuntimeError: Aborted(OOM) decoding a single 4K (2160x3840) H.264 frame, even before any filter runs

1 participant