diff --git a/src/lib/time.cpp b/src/lib/time.cpp index 16acf2622..c9dc31a4b 100644 --- a/src/lib/time.cpp +++ b/src/lib/time.cpp @@ -1,8 +1,8 @@ /* - time.c - Utilities for handling time + Time - Utilities for handling time Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2011, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -137,26 +137,105 @@ lumiera_build_time(long millis, uint secs, uint mins, uint hours) return time; } +gavl_time_t +lumiera_build_time_fps (float fps, uint frames, uint secs, uint mins, uint hours) +{ + gavl_time_t time = frames * (1000.0 / fps) + + 1000 * secs + + 1000 * 60 * mins + + 1000 * 60 * 60 * hours; + time *= GAVL_TIME_SCALE_MS; + return time; +} + +gavl_time_t +lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours) +{ + 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) +lumiera_time_hours (gavl_time_t time) { return time / GAVL_TIME_SCALE_MS / 1000 / 60 / 60; } int -lumiera_time_minutes(gavl_time_t time) +lumiera_time_minutes (gavl_time_t time) { return (time / GAVL_TIME_SCALE_MS / 1000 / 60) % 60; } int -lumiera_time_seconds(gavl_time_t time) +lumiera_time_seconds (gavl_time_t time) { return (time / GAVL_TIME_SCALE_MS / 1000) % 60; } int -lumiera_time_millis(gavl_time_t time) +lumiera_time_millis (gavl_time_t time) { return (time / GAVL_TIME_SCALE_MS) % 1000; } + +int +lumiera_time_frames (gavl_time_t time, float fps) +{ + return (fps * (lumiera_time_millis(time))) / 1000; +} + +int +lumiera_time_frame_count (gavl_time_t time, float fps) +{ + REQUIRE (fps > 0); + + 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 6f9974dab..286e2ccb8 100644 --- a/src/lib/time.h +++ b/src/lib/time.h @@ -84,6 +84,8 @@ lumiera_frame_duration (lib::time::FrameRate const& fps); extern "C" { /* ===================== C interface ======================== */ #endif +#define NTSC_DROP_FRAME_FPS 29.97 +/* TODO: replace this by lib/time/FrameRate::NTSC */ /** * Formats a time value in H:MM:SS.mmm format into a temporary buffer. @@ -127,29 +129,87 @@ lumiera_time_of_gridpoint (long nr, gavl_time_t origin, gavl_time_t grid); /** * Builds a time value by summing up the given components. + * @param millis number of milliseconds + * @param secs number of seconds + * @param mins number of minutes + * @param hours number of hours */ gavl_time_t lumiera_build_time (long millis, uint secs, uint mins, uint hours); /** - * Extract the hour part of given time. + * Builds a time value by summing up the given components. + * @todo replace float framerates by lib::time::FrameRate */ -int lumiera_time_hours(gavl_time_t time); +gavl_time_t +lumiera_build_time_fps (float fps, uint frames, uint secs, uint mins, uint hours); /** - * Extract the minute part of given time. + * Builds a time value by summing up the given components. + * The components are interpreted as a NTSC drop-frame timecode. + * @warning take care not to specify time codes that are illegal NTSC drop-frame times. */ -int lumiera_time_minutes(gavl_time_t time); +gavl_time_t +lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours); + + +/** Extract the hour part of given time. */ +int +lumiera_time_hours (gavl_time_t time); + + +/** Extract the minute part of given time. */ +int +lumiera_time_minutes (gavl_time_t time); + + +/** Extract the seconds part of given time. */ +int +lumiera_time_seconds (gavl_time_t time); + + +/** Extract the milliseconds part of given time. */ +int +lumiera_time_millis (gavl_time_t time); /** - * Extract the seconds part of given time. + * Extract the frame part of given time, using the given fps. + * @param fps frame rate + * @todo use the rational lib::time::FrameRate instead of a float */ -int lumiera_time_seconds(gavl_time_t time); +int +lumiera_time_frames (gavl_time_t time, float fps); /** - * Extract the milliseconds part of given time. + * Extract the frame count for the given time, using the given fps. + * @todo use the rational lib::time::FrameRate instead of a float */ -int lumiera_time_millis(gavl_time_t time); +int +lumiera_time_frame_count (gavl_time_t time, float fps); + +/** + * Extract the frame part of given time, using NTSC drop-frame timecode. + */ +int +lumiera_time_ntsc_drop_frames (gavl_time_t time); + +/** + * Extract the second part of given time, using NTSC drop-frame timecode. + */ +int +lumiera_time_ntsc_drop_seconds (gavl_time_t time); + +/** + * Extract the minute part of given time, using NTSC drop-frame timecode. + */ +int +lumiera_time_ntsc_drop_minutes (gavl_time_t time); + +/** + * Extract the hour part of given time, using NTSC drop-frame timecode. + */ +int +lumiera_time_ntsc_drop_hours (gavl_time_t time); @@ -157,3 +217,4 @@ int lumiera_time_millis(gavl_time_t time); }//extern "C" #endif #endif + diff --git a/tests/15time.tests b/tests/15time.tests index 0cb57ddcc..2dcedbea9 100644 --- a/tests/15time.tests +++ b/tests/15time.tests @@ -4,3 +4,9 @@ TEST "basic functionality" basic <