Chromium Code Reviews| Index: src/ply-image.c |
| diff --git a/src/ply-image.c b/src/ply-image.c |
| index 58e1daea3d5050723e5024557fb555cbb1f46d1f..69bb802a326c006039d7a4044178b6b496b3b92a 100644 |
| --- a/src/ply-image.c |
| +++ b/src/ply-image.c |
| @@ -489,33 +489,27 @@ ply_frame_buffer_show_file_at_xy(ply_frame_buffer_t *buffer, const char *path, |
| ply_image_free (image); |
| } |
| -/* |
| - * Compute the difference in nanoseconds between two timevals. Return 0 if the |
| - * clock is not reliable. |
| - */ |
| -int64_t difference_nsec(struct timespec x, struct timespec y) |
| -{ |
| - int64_t z; |
| - if (bad_clock) |
| - { |
| - return 0; |
| - } |
| - |
| - z = x.tv_sec - y.tv_sec; |
| - z *= BILLION; |
| - z += x.tv_nsec - y.tv_nsec; |
| - return z; |
| +int64_t timespec_to_nsec(struct timespec x) |
|
Daniel Erat
2010/12/17 19:15:42
nit: better variable names ('spec' instead of 'x',
|
| +{ |
| + int64_t y; |
| + y = x.tv_sec; |
| + y *= BILLION; |
| + y += x.tv_nsec; |
| + return y; |
| } |
| -void gettime_check(struct timespec *ts) |
| +int64_t gettime_check(void) |
| { |
| - int r = clock_gettime(CLOCK_MONOTONIC, ts); |
| + struct timespec ts; |
| + int r = clock_gettime(CLOCK_MONOTONIC, &ts); |
| if (r) |
| { |
| bad_clock = 1; |
| + return 0; |
| } |
| + return timespec_to_nsec(ts); |
| } |
| @@ -584,9 +578,8 @@ main (int argc, |
| /* |
| * Animate frames. |
| */ |
| - struct timespec then, now; |
| - int64_t error_nsec; |
| - int64_t interval_nsec; |
| + int64_t draw_time_nsec, frame_period_nsec; |
| + int64_t sleep_time_nsec, now_nsec, then_nsec; |
| xoff = strtol (argv[2], &endptr, 10); |
| if (endptr == argv[2] || *endptr != '\0') |
| @@ -603,33 +596,39 @@ main (int argc, |
| * Begin animation. |
| * |
| * The first time around, we don't know how long it takes to draw a |
| - * frame, so we assume it's instantaneous. After that, we assume |
| - * that the drawing time for the previous cycle is a good estimate |
| - * for the next cycle. Errors may be introduced by different frame |
| - * size and complexity (PNG decoding). |
| + * frame, so we approximate it as 0. After that, we assume that the |
| + * drawing time for the previous cycle is a good estimate for the |
| + * next cycle. Errors may be introduced by different frame size and |
| + * complexity (PNG decoding) and by the CPU load. |
| */ |
| - error_nsec = 0; |
| - interval_nsec = BILLION / frame_rate; |
| - gettime_check (&now); |
| + draw_time_nsec = 0; |
| + frame_period_nsec = BILLION / frame_rate; |
| + now_nsec = gettime_check (); |
| for (i = 4; i < argc; i++) |
| { |
| /* |
| - * Before displaying the next frame, sleep for the inter-frame |
| - * interval, adjusted by the error in the previous cycle. |
| - * Positive error means the last cycle took longer than desired. |
| + * Before displaying the next frame, sleep for the right amount |
| + * of time so that the achieved period approximates the desired |
| + * period. |
| */ |
| - if (interval_nsec - error_nsec > 0) |
| + sleep_time_nsec = frame_period_nsec - draw_time_nsec; |
| + if (sleep_time_nsec > 0) |
| { |
| struct timespec req; |
| - req.tv_sec = (interval_nsec - error_nsec) / BILLION; |
| - req.tv_nsec = (interval_nsec - error_nsec) % BILLION; |
| + req.tv_sec = sleep_time_nsec / BILLION; |
| + req.tv_nsec = sleep_time_nsec % BILLION; |
| nanosleep (&req, NULL); |
| } |
| ply_frame_buffer_show_file_at_xy (buffer, argv[i], xoff, yoff); |
| - then = now; |
| - gettime_check (&now); |
| - error_nsec = difference_nsec (now, then) - interval_nsec; |
| + then_nsec = now_nsec; |
| + now_nsec = gettime_check (); |
| + /* |
| + * If the clock is bad (unlikely), assume draw time is |
| + * instantaneous as a rough guess. |
| + */ |
| + draw_time_nsec = bad_clock ? 0 : |
| + now_nsec - then_nsec - sleep_time_nsec; |
| } |
| } |
| } |