Index: src/ply-image.c |
diff --git a/src/ply-image.c b/src/ply-image.c |
index 58e1daea3d5050723e5024557fb555cbb1f46d1f..3395c9200b6d3697678562d79b786d510cf27e8f 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 ts) |
+{ |
+ int64_t nsec; |
+ nsec = ts.tv_sec; |
+ nsec *= BILLION; |
+ nsec += ts.tv_nsec; |
+ return nsec; |
} |
-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; |
} |
} |
} |