Repository navigation
fix: stop Intel's Media Foundation H264 encoder from crashing Windows exports and recordings - #4244
Open
richiemcilroy wants to merge 10 commits into
Open
richiemcilroy wants to merge 10 commits into
richiemcilroy wants to merge 10 commits into
Conversation
…not take away from it
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
richiemcilroy
marked this pull request as ready for review
November 14, 2026 07:12
|
Sandchest reviewed Sandchest reviews every change for vulnerabilities an attacker could use · 1 credit · Review details |
Member
Author
|
hey @greptileai, please re-review the PR |
Member
Author
|
hey @greptileai, please re-review the PR |
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.

Fixes #4016. Fixes #3928.
Intel's Media Foundation H.264 encoder (
mfx_mft_h264ve_64.dll) faults with an access violation instead of returning an error at some frame sizes. FFmpeg'sh264_mfloads it into Cap's own process during the pre-flight self-test, so the fault ends the app before any fallback can run:mfx_mft_h264ve_64.dll+0x00143100(same offset every time) at the recorded area's size, on 0.6.2 and 0.6.3. A clean 16:9 export works. The 0.6.3 log showsh264_qsvfailing its self-test, which leavesh264_mfnext in the Intel order.APPCRASHinmfx_mft_h264ve_64.dll,c0000005. Moving Cap to the NVIDIA GPU avoids it.Root cause
h264_mfcopies each frame into a tightly packed system-memory buffer at the exact output size (stride = width) and setsMF_MT_FRAME_SIZEto that size. Intel documents its encoder transform as taking widths in multiples of 16. At other widths it reads past the buffer.ProjectUniforms::get_output_size,ensure_even). So any recorded area or window that isn't a standard 16:9 size reaches the transform at an unsupported width. The 16:9 presets (1280, 1920, 3840 wide) are all multiples of 16, which is why those work.h264_qsvpads its own surfaces to 16 alignment, so it is not affected.What changed
flowchart LR A[next H264 candidate] --> B{h264_mf and Intel MFT first<br/>and width % 16 != 0 or over level 5.2?} B -- yes --> N[skip, next candidate] B -- no --> C{h264_mf on Windows<br/>and host registered?} C -- yes --> D[self-test in a child copy of Cap] D -- ok --> E[open encoder in process] D -- fail / crash / 20 s timeout --> N C -- no --> F[self-test in process, as before] --> Ecap_media_info::intel_h264_mft_accepts_frame_size): width a multiple of 16, both sides at most 4096, at most 36864 macroblocks (H.264 level 5.2). Heights such as 1080 stay allowed, because the transform pads height itself.crates/enc-ffmpeg/src/video/h264.rsunsupported_frame_size): applies only toh264_mf, and only when the first hardware H.264 transform Media Foundation lists (the one FFmpeg opens,cap_enc_mediafoundation::mft::first_hardware_h264_encoder_name) is Intel's. Selection then moves on to the next candidate (NVENC, AMF, then libx264).crates/enc-mediafoundation/src/video/h264.rs): the same check returnsNewVideoEncoderError::UnsupportedFrameSizewhen the chosen transform is Intel's. All four callers (win.rsscreen and camera muxers,win_segmented.rs,win_segmented_camera.rs) already fall back to the FFmpeg order on a constructor error.crates/enc-ffmpeg/src/video/isolated_self_test.rs). On Windows,h264_mf's pre-flight self-test runs in a child copy of the host executable: the same encoder, options, size, pixel format and gray-frame round trip. Exit code 3 with a verdict line means the test failed; any other ending (0xc0000005,0xc0000409, no verdict) or 20 s without an answer counts as a crash. Either way that candidate is skipped and the verdict is cached per process, like before.cap-gpuiandcapmaincallisolated_self_test::run_child_or_register_host()first, so a child runs only the test and exits before logging, crash capture, single-instance or any window. Executables that don't register keep testing in process, exactly as before.CAP_H264_SELF_TEST_FAULT=access_violation|abort|hang|fail[:codec]makes the self-test fault the way Intel's transform does, andCAP_DEBUG_H264_ENCODER_ORDERforces an encoder order on runners without a GPU. Neither exists in release builds.What could regress and why it doesn't
h264_nvenc,h264_amf) are untouched and still test in process. Measured below: bit-identical bitstreams at 13 sizes, recording and export settings, main vs this branch.h264_mfis reached, which on NVIDIA and AMD means their own encoder already failed. Median cost when it does run: about 100 ms (659 vs 556 ms, AMD, 13 sizes).h264_mfworks today at a 16-aligned width. Those still geth264_mf, after the child self-test passes.H264EncoderBuilder::build/build_standalone: recording (win_fragmented_m4s.rs,oop_fragmented_m4s_win.rs,win_segmented*.rs,win.rsfallbacks, instant mode), export (crates/export/src/mp4.rs, turbo) and the CLI all go through the same two selection loops, so they all get both changes. HEVC and ProRes are untouched.Tests added
cap-media-info:intel_h264_mft_frame_sizes,intel_h264_mft_names.cap-enc-ffmpeg(all OSes):isolated_self_test::tests::isolated_self_test_outcomes(pass, access violation, abort, fail, hang killed at the timeout, unknown encoder, codec-targeted faults),request_survives_the_trip_to_the_child,a_child_that_prints_no_verdict_counts_as_a_crash,only_media_foundation_self_tests_in_a_child_process,only_media_foundation_is_skipped_for_its_frame_size.cap-enc-ffmpeg(Windows):media_foundation_self_test_fault_falls_back_to_libx264_at_odd_sizesat 1438x812, 1366x768 and 1448x814. In CI it runs withCAP_H264_SELF_TEST_FAULT=access_violationand=abort, and asserts the child crashed, the test process survived and libx264 encoded the frames.cap-export(Windows):tests/windows_odd_size_export.rsexports 1446x812, 1366x770 and 1914x1078 projects through the Windows order withh264_mffirst and its self-test faulting. It checks the output size (1448x812, 1368x770, 1916x1078, none 16-aligned) and frame count..github/workflows/windows-recording-encoder.ymlonwindows-2022.Measured
Release builds of this branch and of main (
8393446fd) from the same Blacksmith Windows job. Boxes: AWS g4dn.2xlarge (Tesla T4, GRID 596.86, WDDM) and Azure NV12ads V710 (Radeon PRO V710), Windows Server 2025 and 2022, run in the logged-on console session.Encoder matrix (60 frames of a moving pattern per case, recording and export settings, 1438x812, 1366x768, 1448x814, 1914x1078, 1436x1080, 1082x1922, 2542x1078, 998x562, 1920x1080, 1280x720, 2560x1440, 3840x2160, 5120x2880):
h264_nvencup to 4K, libx264 at 5K / sameh264_amfup to 4K, libx264 at 5K / sameh264_mfself-test faulting like Intel's transform (debug build, orderh264_mf, then the vendor encoder, then libx264, all 26 cases):0xc0000005h264_nvenc+ 2 libx264 (5K), output identical to the normal run0xc00004090xc0000005h264_amf+ 2 libx264, output identical to the normal run0xc0000409Real app (release
cap-gpui,CAP_GPUI_AUTO_RECORD=studio:6area recording, then an editor export at the default 720p):h264_nvenc736x510h264_nvenc1040x720, 166 framesh264_nvenc736x510h264_nvenc1040x720, 166 framesh264_amf1436x810h264_amf1276x720, 170 framesh264_amf1436x810h264_amf1276x720, 172 frames (6 s timed recording, 2 more frames captured)cap-gpui.exeas the self-test child:h264_mf(AMD transform) answersokin 459 ms,h264_amfin 212 ms andh264_nvencin 420 ms. With no NVIDIA transform installed,h264_mfanswersfail ... Function not implemented(exit 3) in 190 ms. It creates no profile, no logs and no window.windows_odd_size_exporton both GPUs: passes with the faultingh264_mfsetup and with the default order.Not proven on Intel hardware: no cloud instance offers an Intel iGPU with its Media Foundation encoder, so the Intel transform itself has not been run. The width rule comes from Intel's documented constraint and from #4016 (16:9 works, the recorded area's size crashes), and the child-process self-test covers any size the rule misses.


Confidence Score: 5/5
The reviewed update appears safe to merge.Summary
The PR skips frame sizes that Intel’s H.264 transform cannot accept and runs Windows
h264_mfself-tests in a child process.h264_mfself-tests run in a child process.Reviews (3) · Last reviewed commit: "test(enc-ffmpeg): build the Windows test..." · Reviewed by Greptile