Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion electron/native/wgc-capture/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ int main(int argc, char* argv[]) {
int64_t nextWebcamWriteDueHns = 0;
const int64_t nominalWebcamIntervalHns =
static_cast<int64_t>(10'000'000ULL / std::max(1, webcamCapture.fps()));
auto nextFrameDue = std::chrono::steady_clock::now();

while (!control.stopRequested && !encodeFailed) {
Microsoft::WRL::ComPtr<IMFSample> videoSample;
Expand Down Expand Up @@ -890,8 +891,25 @@ int main(int argc, char* argv[]) {
}

frameIndex += 1;
std::this_thread::sleep_for(frameDuration);
// Pace to a deadline, not `sleep_for(frameDuration)` after the work:
// capturing, converting and encoding a 1080p frame costs ~11 ms, so
// sleeping a whole period on top of it made the real period
// `work + 1/fps` -- 30 fps requested delivered 22.5 measured.
nextFrameDue += frameDuration;
const auto now = std::chrono::steady_clock::now();
if (nextFrameDue < now) {
// Fell behind (slow frame, or waiting on the first one). Resync
// to now rather than firing a burst of catch-up frames, same as
// the webcam cadence above.
nextFrameDue = now;
}
std::this_thread::sleep_until(nextFrameDue);
Comment on lines +898 to +906

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reset the deadline when a pause ends.

When control.paused is true, nextFrameDue becomes stale. After a long pause, Line 904 sets it to now, and Line 906 does not wait. Because latestFrameTexture is still set, the loop submits two frames without one frameDuration interval after resume. Reset the deadline on the paused-to-running transition separately from slow-frame resynchronization.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@electron/native/wgc-capture/src/main.cpp` around lines 898 - 906, Update the
capture loop’s paused-to-running transition around control.paused and
nextFrameDue so resuming resets the deadline to now plus frameDuration before
submitting a frame. Track the prior paused state as needed, keeping the existing
slow-frame resynchronization for normal running frames and ensuring the first
post-resume frame is separated by one frame interval.

}
std::cerr << "[pacing] frames=" << frameIndex << " elapsed_ms="
<< std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - control.recordingStartedAt)
.count()
<< std::endl;
Comment on lines +908 to +912

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Exclude shutdown time from the pacing metric.

The writer logs this interval after control.recordingStartedAt, while the main thread can perform WGC, audio, and webcam shutdown before stopVideoWriter() joins it. If the writer is still running during that work, teardown time is included in elapsed_ms, which under-reports loop pacing. Record the stop-request timestamp before teardown or use a writer-local measurement boundary.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@electron/native/wgc-capture/src/main.cpp` around lines 908 - 912, Update the
pacing metric around the writer loop and stopVideoWriter() so teardown work is
excluded from elapsed_ms. Record the stop-request timestamp before WGC, audio,
and webcam shutdown, or establish a writer-local timing boundary, and use that
boundary instead of control.recordingStartedAt while preserving the existing
frame logging.

};

std::thread videoWriterThread;
Expand Down
Loading