lppier
lppier

Reputation: 1987

Is this a correct use of sleep()?

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

Answers (2)

Moldova
Moldova

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

Vyktor
Vyktor

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

Related Questions