Found while benchmarking against the software encoder for #572. Nothing is broken today — this is a landmine for the hardware-encode work, filed now so it is not rediscovered from a crash report.
What happens
The vendored build's VAAPI encoders abort the process — SIGABRT, not an AVERROR — the first time a frame is mapped:
implib-gen: libva.so.2: failed to resolve symbol 'vaMapBuffer2' via dlsym:
/lib/x86_64-linux-gnu/libva.so.2: undefined symbol: vaMapBuffer2
ffmpeg: libva.so.2.init.c:290: _libva_so_2_tramp_resolve:
Assertion `0 && "Assertion in generated code"' failed.
BtbN does not link libva; it generates implib stubs that dlopen by bare soname and resolve each symbol on first call. When a symbol is missing the generated trampoline calls abort(). There is no return code to check and nothing Rust can catch.
Reproduced with the vendored binary:
LD_LIBRARY_PATH=crates/thirdparty/ffmpeg-linux64-lgpl-shared/lib \
crates/thirdparty/ffmpeg-linux64-lgpl-shared/bin/ffmpeg \
-vaapi_device /dev/dri/renderD128 -f rawvideo -pix_fmt yuv420p -s 1920x1080 -r 60 \
-i in.yuv -frames:v 60 -vf "format=nv12,hwupload" -c:v h264_vaapi -b:v 8M out.mp4
The hardware is fine. The same encode through the system ffmpeg 6.1 (which links libva normally) works and honours the bitrate — 2 Mbps requested → 2.012 delivered, 8 → 2.802.
Why it is harmless right now
VideoEncoder::try_open (crates/compositor/src/pipeline_linux.rs) sets AV_PIX_FMT_YUV420P and never allocates a hw_frames_ctx, so ff_vaapi_encode_init refuses before any libva symbol is resolved:
[h264_vaapi] Specified pixel format yuv420p is not supported by the h264_vaapi encoder.
avcodec_open2(h264_vaapi) = -22
Clean EINVAL, process alive. So OPENSCREEN_EXPORT_ENCODER=h264_vaapi today just falls through to aucun encodeur video utilisable — annoying, not dangerous. The abort only becomes reachable once someone wires a hardware frames context, which is exactly what the hardware ladder on the roadmap would do.
Why it will bite
The affected base is not exotic. vaMapBuffer2 is absent from libva 2.20.0, which is Ubuntu 24.04 LTS (libva2 2.20.0-2ubuntu0.2) — the most common Linux desktop base there is. A ladder that probes h264_vaapi first would take the whole Electron process down mid-export on those machines, with no log and no catchable error.
Two consequences worth noting now:
- A successful
avcodec_open2 will not be proof of usability for VAAPI. The device opens fine; the abort comes later. Any probe has to survive a real frame, or check dlsym for vaMapBuffer2 before going near the encoder.
scripts/fetch-ffmpeg.mjs declares WANTED_ENCODERS.linux = ["h264_nvenc", "h264_vaapi"], so the vendor-time gate asserts the presence of an encoder that aborts on Ubuntu 24.04. Presence in -encoders is not usability — the same lesson as trap 5 in technical-documentation/architecture/export-pipeline.md.
Possible mitigation, untested
Ship a libva.so.2 ≥ the release that introduced vaMapBuffer2 in crates/thirdparty/ffmpeg-linux64-lgpl-shared/lib. The mechanism is plausible — the dlopen is by bare soname, that directory is already on LD_LIBRARY_PATH, and libva is MIT so there is no conflict with the LGPL vendoring gate. I could not test it (no newer libva available offline), and I could not confirm which libva release added the symbol — only that 2.20.0 lacks it and whatever BtbN built against has it. A symbol probe is safer than a version check either way.
Measured on AMD Ryzen 5 7520U / Radeon 610M, Ubuntu 24.04, Mesa 25.2 radeonsi, /dev/dri/renderD128 present, against BtbN n8.1.2-34-g9b6c8969e0-20260731.
Related: #572, #575.
Found while benchmarking against the software encoder for #572. Nothing is broken today — this is a landmine for the hardware-encode work, filed now so it is not rediscovered from a crash report.
What happens
The vendored build's VAAPI encoders abort the process —
SIGABRT, not anAVERROR— the first time a frame is mapped:BtbN does not link
libva; it generates implib stubs thatdlopenby bare soname and resolve each symbol on first call. When a symbol is missing the generated trampoline callsabort(). There is no return code to check and nothing Rust can catch.Reproduced with the vendored binary:
LD_LIBRARY_PATH=crates/thirdparty/ffmpeg-linux64-lgpl-shared/lib \ crates/thirdparty/ffmpeg-linux64-lgpl-shared/bin/ffmpeg \ -vaapi_device /dev/dri/renderD128 -f rawvideo -pix_fmt yuv420p -s 1920x1080 -r 60 \ -i in.yuv -frames:v 60 -vf "format=nv12,hwupload" -c:v h264_vaapi -b:v 8M out.mp4The hardware is fine. The same encode through the system ffmpeg 6.1 (which links libva normally) works and honours the bitrate — 2 Mbps requested → 2.012 delivered, 8 → 2.802.
Why it is harmless right now
VideoEncoder::try_open(crates/compositor/src/pipeline_linux.rs) setsAV_PIX_FMT_YUV420Pand never allocates ahw_frames_ctx, soff_vaapi_encode_initrefuses before any libva symbol is resolved:Clean
EINVAL, process alive. SoOPENSCREEN_EXPORT_ENCODER=h264_vaapitoday just falls through toaucun encodeur video utilisable— annoying, not dangerous. The abort only becomes reachable once someone wires a hardware frames context, which is exactly what the hardware ladder on the roadmap would do.Why it will bite
The affected base is not exotic.
vaMapBuffer2is absent from libva 2.20.0, which is Ubuntu 24.04 LTS (libva2 2.20.0-2ubuntu0.2) — the most common Linux desktop base there is. A ladder that probesh264_vaapifirst would take the whole Electron process down mid-export on those machines, with no log and no catchable error.Two consequences worth noting now:
avcodec_open2will not be proof of usability for VAAPI. The device opens fine; the abort comes later. Any probe has to survive a real frame, or checkdlsymforvaMapBuffer2before going near the encoder.scripts/fetch-ffmpeg.mjsdeclaresWANTED_ENCODERS.linux = ["h264_nvenc", "h264_vaapi"], so the vendor-time gate asserts the presence of an encoder that aborts on Ubuntu 24.04. Presence in-encodersis not usability — the same lesson as trap 5 intechnical-documentation/architecture/export-pipeline.md.Possible mitigation, untested
Ship a
libva.so.2≥ the release that introducedvaMapBuffer2incrates/thirdparty/ffmpeg-linux64-lgpl-shared/lib. The mechanism is plausible — thedlopenis by bare soname, that directory is already onLD_LIBRARY_PATH, and libva is MIT so there is no conflict with the LGPL vendoring gate. I could not test it (no newer libva available offline), and I could not confirm which libva release added the symbol — only that 2.20.0 lacks it and whatever BtbN built against has it. A symbol probe is safer than a version check either way.Measured on AMD Ryzen 5 7520U / Radeon 610M, Ubuntu 24.04, Mesa 25.2 radeonsi,
/dev/dri/renderD128present, against BtbNn8.1.2-34-g9b6c8969e0-20260731.Related: #572, #575.