diff --git a/src/lib/time.c b/src/lib/time.c index 337456db3..43ed80d34 100644 --- a/src/lib/time.c +++ b/src/lib/time.c @@ -34,14 +34,14 @@ lumiera_tmpbuf_print_time (gavl_time_t time) { int milliseconds, seconds, minutes, hours; int negative; - + if(time < 0) { negative = 1; time = -time; } else negative = 0; - + time /= GAVL_TIME_SCALE_MS; milliseconds = time % 1000; time /= 1000; @@ -50,10 +50,10 @@ lumiera_tmpbuf_print_time (gavl_time_t time) minutes = time % 60; time /= 60; hours = time; - + char *buffer = lumiera_tmpbuf_snprintf(64, "%s%02d:%02d:%02d.%03d", negative ? "-" : "", hours, minutes, seconds, milliseconds); - + ENSURE(buffer != NULL); return buffer; } @@ -88,6 +88,24 @@ lumiera_build_time_fps (float fps, uint frames, uint secs, uint mins, uint hours return time; } +gavl_time_t +lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours) +{ + REQUIRE (mins < 60); + REQUIRE (secs < 60); + REQUIRE (frames < 30); + REQUIRE_IF (secs == 0 && mins % 10, frames >= 2, "non-existent frame in NTSC drop-frame"); + + int total_mins = 60 * hours + mins; + int total_frames = 108000 * hours + + 1800 * mins + + 30 * secs + + frames + - 2 * (total_mins - total_mins / 10); + + return (total_frames / 29.97f) * 1000 * GAVL_TIME_SCALE_MS; +} + int lumiera_time_hours (gavl_time_t time) { @@ -125,3 +143,44 @@ lumiera_time_frame_count (gavl_time_t time, float fps) return roundf((time / GAVL_TIME_SCALE_MS / 1000.0f) * fps); } + +/** + * This function is used in the NTSC drop-frame functions to avoid code + * repetition. + * @return the frame number for given time + */ +static int +ntsc_drop_get_frame_number (gavl_time_t time) +{ + int frame = lumiera_time_frame_count (time, NTSC_DROP_FRAME_FPS); + + int d = frame / 17982; // 17982 = 600 * 29.97 + int m = frame % 17982; // 17982 = 600 * 29.97 + + return frame + 18*d + 2*((m - 2) / 1798); // 1798 = 60 * 29.97 +} + +int +lumiera_time_ntsc_drop_frames (gavl_time_t time) +{ + return ntsc_drop_get_frame_number(time) % 30; +} + +int +lumiera_time_ntsc_drop_seconds (gavl_time_t time) +{ + return ntsc_drop_get_frame_number(time) / 30 % 60; +} + +int +lumiera_time_ntsc_drop_minutes (gavl_time_t time) +{ + return ntsc_drop_get_frame_number(time) / 30 / 60 % 60; +} + +int +lumiera_time_ntsc_drop_hours (gavl_time_t time) +{ + return ntsc_drop_get_frame_number(time) / 30 / 60 / 60 % 24; +} + diff --git a/src/lib/time.h b/src/lib/time.h index df7b1dfb0..2b3e9523d 100644 --- a/src/lib/time.h +++ b/src/lib/time.h @@ -25,6 +25,8 @@ #include #include +#define NTSC_DROP_FRAME_FPS 29.97 + /** * Formats a time in a safeclib tmpbuf in HH:MM:SS:mmm format. * @param size maximal length for the string @@ -55,6 +57,18 @@ lumiera_build_time (long millis, uint secs, uint mins, uint hours); gavl_time_t lumiera_build_time_fps (float fps, uint frames, uint secs, uint mins, uint hours); +/** + * Builds a time value by summing up the given components. + * The components are interpreted as a NTSC drop-frame timecode. + * @param frames number of frames + * @param secs number of seconds + * @param mins number of minutes + * @param hours number of hours + * You must take care not to specify time codes that are illegal NTSC drop-frame times. + */ +gavl_time_t +lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours); + /** * Get the hour part of given time. * @param time the time value to use @@ -99,4 +113,32 @@ lumiera_time_frames (gavl_time_t time, float fps); int lumiera_time_frame_count (gavl_time_t time, float fps); +/** + * Get the frame part of given time, using NTSC drop-frame timecode. + * @param time the time value to use + */ +int +lumiera_time_ntsc_drop_frames (gavl_time_t time); + +/** + * Get the second part of given time, using NTSC drop-frame timecode. + * @param time the time value to use + */ +int +lumiera_time_ntsc_drop_seconds (gavl_time_t time); + +/** + * Get the minute part of given time, using NTSC drop-frame timecode. + * @param time the time value to use + */ +int +lumiera_time_ntsc_drop_minutes (gavl_time_t time); + +/** + * Get the hour part of given time, using NTSC drop-frame timecode. + * @param time the time value to use + */ +int +lumiera_time_ntsc_drop_hours (gavl_time_t time); + #endif diff --git a/tests/15time.tests b/tests/15time.tests index 30ae5515c..2dcedbea9 100644 --- a/tests/15time.tests +++ b/tests/15time.tests @@ -7,3 +7,6 @@ END TEST "frame rate dependent calculations" fps <