From 906c476ebe1fa518e4f82139aaee85dce63b2eb6 Mon Sep 17 00:00:00 2001 From: Pierre-Adrien Lair Date: Tue, 24 Mar 2026 17:59:27 +0100 Subject: [PATCH] Fix corrupted MP4 recordings on Windows by serializing encoder writes The WGC capture session uses Direct3D11CaptureFramePool::CreateFreeThreaded, which dispatches FrameArrived callbacks on thread pool threads concurrently. MFEncoder::writeFrame() accesses non-thread-safe resources (ID3D11DeviceContext, IMFSinkWriter, shared staging texture and NV12 buffer) without synchronization, causing MP4 container corruption when callbacks overlap at high frame rates. Add a mutex to serialize writeFrame() and finalize() calls, preventing concurrent access to the D3D context and Media Foundation sink writer. Fixes #96 --- electron/native/wgc-capture/src/mf_encoder.cpp | 2 ++ electron/native/wgc-capture/src/mf_encoder.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/electron/native/wgc-capture/src/mf_encoder.cpp b/electron/native/wgc-capture/src/mf_encoder.cpp index a1474c20..1adef1b6 100644 --- a/electron/native/wgc-capture/src/mf_encoder.cpp +++ b/electron/native/wgc-capture/src/mf_encoder.cpp @@ -124,6 +124,7 @@ bool MFEncoder::initialize(const std::wstring& outputPath, int width, int height } bool MFEncoder::writeFrame(ID3D11Texture2D* texture, int64_t timestampHns) { + std::lock_guard lock(writeMutex_); if (!initialized_ || !sinkWriter_) return false; context_->CopyResource(stagingTexture_.Get(), texture); @@ -190,6 +191,7 @@ bool MFEncoder::writeFrame(ID3D11Texture2D* texture, int64_t timestampHns) { } bool MFEncoder::finalize() { + std::lock_guard lock(writeMutex_); if (!initialized_) return false; initialized_ = false; diff --git a/electron/native/wgc-capture/src/mf_encoder.h b/electron/native/wgc-capture/src/mf_encoder.h index 7eb8e642..11b9c774 100644 --- a/electron/native/wgc-capture/src/mf_encoder.h +++ b/electron/native/wgc-capture/src/mf_encoder.h @@ -8,6 +8,7 @@ #include #include #include +#include using Microsoft::WRL::ComPtr; @@ -32,4 +33,5 @@ class MFEncoder { int height_ = 0; int fps_ = 60; bool initialized_ = false; + std::mutex writeMutex_; };