Reputation: 1987
I'm using sleep like this to grab a frame every 1/25th of a second. OS is Debian 6 armel.
#define VIDEO_FRAME_RATE 25.0f
while (RECORDING) {
sprintf(buffer, "Someting from a data struct that is updated\n");
fprintf(Output, buffer);
usecTosleep = (1.0f/VIDEO_FRAME_RATE) * 1000000;
usleep(usecToSleep);
}
Question: What is the guarantee that the loop will output the buffer to Output file descriptor at every 1/25th of a second?
Is there a better way to do this in C? I need it to be as precise as possible to prevent drifting.
Thank you.
Upvotes: 2
Views: 84
Reputation: 1651
In response to your first question, there is no such guarantee. usleep()
promises only that it will sleep at least as long as you tell it to. But it may sleep longer:
The usleep() function suspends execution of the calling process for (at least) usec microseconds. The
sleep may be lengthened slightly by any system activity or by the time spent processing the call or by
the granularity of system timers.
Upvotes: 2
Reputation: 20997
Your "recording operation" still takes some time...
So you need to calculate time that should be spent on on frame (usecTosleep = (1.0f/VIDEO_FRAME_RATE) * 1000000;
) and then calculate time operation really took, adjust sleep time accordingly:
usecTosleep = (1.0f/VIDEO_FRAME_RATE) * 1000000;
lastFrameUsec = 0;
while (RECORDING) {
sprintf(buffer, "Someting from a data struct that is updated\n");
fprintf(Output, buffer);
usecTosleep = (1.0f/VIDEO_FRAME_RATE) * 1000000;
// currentFrameUec - lastFrameUsec = actual time spending on operation
currentFrameUsec = getUsecElapsedFromStart();
actualSleep = usecToSleep - (currentFrameUsec - lastFrameUsec);
// If there's time to sleep left, sleep
if(actualSleep > 0){
usleep(actualSleep);
lastFrameUsec = getUsecElepasedFromStart();
} else {
lastFrameUsec = currentFrameUsec;
}
}
I'm not aware of multi platform getUsecElapsedFromStart()
so you probably will have to implement your own for example like this one.
int getUsecElapsedFromStart(const struct timespec *tstart)
{
struct timespec *tnow;
clock_gettime(CLOCK_MONOTONIC, &tnow);
return (int)((tnow tv_sec*10.0e9 + tnow.tv_nsec) -
(tstart.tv_ses*10.0e9 + tstart.tv_nsec));
}
clock_gettime(CLOCK_MONOTONIC, &tstart);
while(RECORDING){
// ...
currentFrameUsec = getUsecElapsedFromStart(&tstart);
}
Upvotes: 2