How does OBS capture the desktop at a particular framerate? #12058
Replies: 2 comments
-
|
OBS doesn't actually control frame rate at the capture level. It uses a pretty different architecture than what you're trying to do. How OBS handles this
The display capture in OBS doesn't run in a tight loop with sleeps. It registers a video_tick callback that gets called by OBS's core timing system. If you look at duplicator-monitor-capture.c, the capture just calls
The frame rate stuff actually happens in OBS's video output subsystem, not the capture. When you set OBS to 60fps, the video output handler:
Sources are asynchronous. They push frames with timestamps using obs_source_output_video(), and OBS's compositor samples them at whatever the output rate is.
Desktop Duplication is basically tied to the Windows compositor (DWM), which runs at your monitor refresh rate. You cant really capture faster than the compositor updates. The timeout in AcquireNextFrame is a max wait time, not a frame rate limiter. If theres a frame ready it returns immediately. What to do instead maybe? Basically you want to split capture from encoding. Let capture run as fast as DXGI provides, then have your encoder pull frames at a steady rate with a precision timer. Replay buffer? This is just a circular buffer of encoded packets. When it fills up (based on your duration setting), old packets get overwritten. It stays valid because each keyframe is an entry point. When you hit save, OBS writes from the most recent keyframe forward. The implementation is in |
Beta Was this translation helpful? Give feedback.
-
|
OBS doesn't actually control frame rate at the capture level. It uses a pretty different architecture than what you're trying to do. How OBS handles this1. Tick-based capture, not a loop The display capture in OBS doesn't run in a tight loop with sleeps. It registers a 2. Video output controls the timing The frame rate stuff actually happens in OBS's video output subsystem, not the capture. When you set OBS to 60fps, the video output handler:
Sources are asynchronous. They push frames with timestamps using 3. DXGI limitations Desktop Duplication is basically tied to the Windows compositor (DWM), which runs at your monitor refresh rate. You cant really capture faster than the compositor updates. The timeout in What to do instead// This won't work well:
while (running) {
AcquireNextFrame(timeout); // returns asap if frame ready
sleep_for(calculated_delay); // unreliable
}
// Better approach:
// 1. Run capture in its own thread, grab frames as fast as DXGI gives them
// 2. Push frames with timestamps into a thread-safe queue
// 3. Have encoder thread PULL from the queue at your target rate
// using a real timing source (QueryPerformanceCounter on Windows)Basically you want to decouple capture from encoding. Let capture run as fast as DXGI provides, then have your encoder pull frames at a steady rate with a precision timer. Replay bufferThis is just a circular buffer of encoded packets. When it fills up (based on your duration setting), old packets get overwritten. It stays valid because each keyframe is an entry point. When you hit save, OBS writes from the most recent keyframe forward. The implementation is in |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm trying to use DDA on windows (AcquireNextFrame) to get frames of the screen, but I'm struggling to get it to reach a particular set framerate.
Currently if I put it into a loop, it just gets frames as quick as possible. Even if I calculate a "wait" timing like in Nvidia's example here https://github.com/NVIDIA/video-sdk-samples/blob/aa3544dcea2fe63122e4feb83bf805ea40e58dbe/nvEncDXGIOutputDuplicationSample/main.cpp#L351 it just seems to set a limit on how slow DDA will be in replying with a frame, it seems to imply that if things on screen are moving it will do nothing to limit how fast a frame can be returned, hence it captured at 150fps even though the timeout I gave to DDA was always under 17 ms (for 60fps 16.66ms)
I've also tried sleep_for but it doesn't seem consistent enough? i got about ~40fps when i aimed for 60fps.
how does OBS get an accurate capture rate using dda?
and how does the replay buffer mode work? I understand that it encodes to a memory location and then saves it to disk when a button is pressed, but once the buffer is full, how does it overwrite old data in a way which allows the whole buffer to still be a valid video stream?
Beta Was this translation helpful? Give feedback.
All reactions