OLD | NEW |
1 /* ply-image.c - png file loader | 1 /* ply-image.c - png file loader |
2 * | 2 * |
3 * Copyright (C) 2006, 2007 Red Hat, Inc. | 3 * Copyright (C) 2006, 2007 Red Hat, Inc. |
4 * Copyright (C) 2003 University of Southern California | 4 * Copyright (C) 2003 University of Southern California |
5 * | 5 * |
6 * This program is free software; you can redistribute it and/or modify | 6 * This program is free software; you can redistribute it and/or modify |
7 * it under the terms of the GNU General Public License as published by | 7 * it under the terms of the GNU General Public License as published by |
8 * the Free Software Foundation; either version 2, or (at your option) | 8 * the Free Software Foundation; either version 2, or (at your option) |
9 * any later version. | 9 * any later version. |
10 * | 10 * |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 ply_frame_buffer_get_size (buffer, &area); | 482 ply_frame_buffer_get_size (buffer, &area); |
483 area.x = (area.width / 2) - (width / 2); // + x; | 483 area.x = (area.width / 2) - (width / 2); // + x; |
484 area.y = (area.height / 2) - (height / 2); // + y; | 484 area.y = (area.height / 2) - (height / 2); // + y; |
485 area.width = width; | 485 area.width = width; |
486 area.height = height; | 486 area.height = height; |
487 | 487 |
488 ply_frame_buffer_fill (buffer, &area, x, y, data); | 488 ply_frame_buffer_fill (buffer, &area, x, y, data); |
489 ply_image_free (image); | 489 ply_image_free (image); |
490 } | 490 } |
491 | 491 |
492 /* | 492 |
493 * Compute the difference in nanoseconds between two timevals. Return 0 if the | 493 int64_t timespec_to_nsec(struct timespec ts) |
494 * clock is not reliable. | |
495 */ | |
496 int64_t difference_nsec(struct timespec x, struct timespec y) | |
497 { | 494 { |
498 int64_t z; | 495 int64_t nsec; |
499 | 496 nsec = ts.tv_sec; |
500 if (bad_clock) | 497 nsec *= BILLION; |
501 { | 498 nsec += ts.tv_nsec; |
502 return 0; | 499 return nsec; |
503 } | |
504 | |
505 z = x.tv_sec - y.tv_sec; | |
506 z *= BILLION; | |
507 z += x.tv_nsec - y.tv_nsec; | |
508 return z; | |
509 } | 500 } |
510 | 501 |
511 | 502 |
512 void gettime_check(struct timespec *ts) | 503 int64_t gettime_check(void) |
513 { | 504 { |
514 int r = clock_gettime(CLOCK_MONOTONIC, ts); | 505 struct timespec ts; |
| 506 int r = clock_gettime(CLOCK_MONOTONIC, &ts); |
515 if (r) | 507 if (r) |
516 { | 508 { |
517 bad_clock = 1; | 509 bad_clock = 1; |
| 510 return 0; |
518 } | 511 } |
| 512 return timespec_to_nsec(ts); |
519 } | 513 } |
520 | 514 |
521 | 515 |
522 int usage(void) | 516 int usage(void) |
523 { | 517 { |
524 fprintf(stderr, | 518 fprintf(stderr, |
525 "usage: ply-image --clear\n" | 519 "usage: ply-image --clear\n" |
526 " ply-image <background> [<x-offset> <y-offset> " | 520 " ply-image <background> [<x-offset> <y-offset> " |
527 "<frame-1> ... <frame-n>]\n"); | 521 "<frame-1> ... <frame-n>]\n"); |
528 exit(1); | 522 exit(1); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 /* | 571 /* |
578 * Display main image. | 572 * Display main image. |
579 */ | 573 */ |
580 ply_frame_buffer_show_file_at_xy (buffer, argv[1], 0, 0); | 574 ply_frame_buffer_show_file_at_xy (buffer, argv[1], 0, 0); |
581 | 575 |
582 if (argc >= 4) | 576 if (argc >= 4) |
583 { | 577 { |
584 /* | 578 /* |
585 * Animate frames. | 579 * Animate frames. |
586 */ | 580 */ |
587 struct timespec then, now; | 581 int64_t draw_time_nsec, frame_period_nsec; |
588 int64_t error_nsec; | 582 int64_t sleep_time_nsec, now_nsec, then_nsec; |
589 int64_t interval_nsec; | |
590 | 583 |
591 xoff = strtol (argv[2], &endptr, 10); | 584 xoff = strtol (argv[2], &endptr, 10); |
592 if (endptr == argv[2] || *endptr != '\0') | 585 if (endptr == argv[2] || *endptr != '\0') |
593 { | 586 { |
594 usage (); | 587 usage (); |
595 } | 588 } |
596 yoff = strtol (argv[3], &endptr, 10); | 589 yoff = strtol (argv[3], &endptr, 10); |
597 if (endptr == argv[3] || *endptr != '\0') | 590 if (endptr == argv[3] || *endptr != '\0') |
598 { | 591 { |
599 usage (); | 592 usage (); |
600 } | 593 } |
601 | 594 |
602 /* | 595 /* |
603 * Begin animation. | 596 * Begin animation. |
604 * | 597 * |
605 * The first time around, we don't know how long it takes to draw a | 598 * The first time around, we don't know how long it takes to draw a |
606 * frame, so we assume it's instantaneous. After that, we assume | 599 * frame, so we approximate it as 0. After that, we assume that the |
607 * that the drawing time for the previous cycle is a good estimate | 600 * drawing time for the previous cycle is a good estimate for the |
608 * for the next cycle. Errors may be introduced by different frame | 601 * next cycle. Errors may be introduced by different frame size and |
609 * size and complexity (PNG decoding). | 602 * complexity (PNG decoding) and by the CPU load. |
610 */ | 603 */ |
611 error_nsec = 0; | 604 draw_time_nsec = 0; |
612 interval_nsec = BILLION / frame_rate; | 605 frame_period_nsec = BILLION / frame_rate; |
613 gettime_check (&now); | 606 now_nsec = gettime_check (); |
614 | 607 |
615 for (i = 4; i < argc; i++) | 608 for (i = 4; i < argc; i++) |
616 { | 609 { |
617 /* | 610 /* |
618 * Before displaying the next frame, sleep for the inter-frame | 611 * Before displaying the next frame, sleep for the right amount |
619 * interval, adjusted by the error in the previous cycle. | 612 * of time so that the achieved period approximates the desired |
620 * Positive error means the last cycle took longer than desired. | 613 * period. |
621 */ | 614 */ |
622 if (interval_nsec - error_nsec > 0) | 615 sleep_time_nsec = frame_period_nsec - draw_time_nsec; |
| 616 if (sleep_time_nsec > 0) |
623 { | 617 { |
624 struct timespec req; | 618 struct timespec req; |
625 req.tv_sec = (interval_nsec - error_nsec) / BILLION; | 619 req.tv_sec = sleep_time_nsec / BILLION; |
626 req.tv_nsec = (interval_nsec - error_nsec) % BILLION; | 620 req.tv_nsec = sleep_time_nsec % BILLION; |
627 nanosleep (&req, NULL); | 621 nanosleep (&req, NULL); |
628 } | 622 } |
629 ply_frame_buffer_show_file_at_xy (buffer, argv[i], xoff, yoff); | 623 ply_frame_buffer_show_file_at_xy (buffer, argv[i], xoff, yoff); |
630 then = now; | 624 then_nsec = now_nsec; |
631 gettime_check (&now); | 625 now_nsec = gettime_check (); |
632 error_nsec = difference_nsec (now, then) - interval_nsec; | 626 /* |
| 627 * If the clock is bad (unlikely), assume draw time is |
| 628 * instantaneous as a rough guess. |
| 629 */ |
| 630 draw_time_nsec = bad_clock ? 0 : |
| 631 now_nsec - then_nsec - sleep_time_nsec; |
633 } | 632 } |
634 } | 633 } |
635 } | 634 } |
636 | 635 |
637 // Skip these to save time. | 636 // Skip these to save time. |
638 // ply_frame_buffer_close (buffer); | 637 // ply_frame_buffer_close (buffer); |
639 // ply_frame_buffer_free (buffer); | 638 // ply_frame_buffer_free (buffer); |
640 | 639 |
641 return exit_code; | 640 return exit_code; |
642 } | 641 } |
OLD | NEW |