I am trying to create a video recorder with Qt. What I did so far was taking a screenshot of a rectangle on the screen and save it. At the end I use ffmpeg to get a video file out of the images.
I connected a timer's signal timeout()
to my custom slot which takes the snapshot and saves it to my tmp folder. The timer has an intervall of 1000 / 30. That should be 30 times per second. But 1000 / 30 is a little bit more than 33 milliseconds so I cannot really get 30 fps. It's a bit more.
I recorded a youtube video with my recorder and everything was smooth but a little bit faster / slower depending on the intervall.
So my question basically is how do I get really 30 / 40 / 50 / ... fps?
Start a QElapsedTimer when you start the capture.
When you are done capturing a frame (at the end of your snapshot slot), multiply the next frame number by the approximate frame duration (a double precision floating point value) in milliseconds (e.g. for 30 fps, it is ~33.33333333333
, but don't write that - write (double)1000/30
). Call this value next_timestamp
.
Call elapsed()
on your QElapsedTimer. Call this value current_timestamp
.
Call the static function QTimer::singleShot()
to sleep for next_timestamp - current_timestamp
. Set the slot argument to your snapshot slot again. Note that if the time to sleep is <= 0, you are falling behind; your system can't keep up with the load of capturing that fast.
When QTimer::singleShot()
fires, your snapshot slot will be called again with some error in timing. However, this error is inevitable under non-realtime operating systems such as Windows and Unix (OS X/Linux/etc). This is because you don't get to decide when code executes - the OS kernel does. On average, though, you will end up with exactly 30 frames per second (assuming your computer can keep up with the load!), because the time elapsed reported by the QElapsedTimer will be quite accurate, and if the system falls behind, it will capture frames more quickly, and if it gets ahead, it will capture frames more slowly.