diff --git a/src/lib/framerate.h b/src/lib/framerate.h new file mode 100644 index 000000000..f7f075f91 --- /dev/null +++ b/src/lib/framerate.h @@ -0,0 +1,79 @@ +/* + framerate.h - framerate calculations + + Copyright (C) CinelerraCV + 2007, 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 + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CINELERRA_FRAMERATE_H +#define CINELERRA_FRAMERATE_H + +#include "lib/error.h" +#include "lib/time.h" + +/** + * framerates are defined as a rational number + * for example NTSC with 29.97fps is {2997, 100} + */ +struct cinelerra_framerate_struct +{ + unsigned n; //numerator + unsigned d; //denominator +}; + +typedef struct cinelerra_framerate_struct cinelerra_framerate; +typedef cinelerra_framerate* CinelerraFramerate; + +typedef unsigned long cinelerra_framepos; + +/** + * Get the frame number of a given time at a given frame rate. + * frame indexing starts with 1 + */ +static inline cinelerra_framepos +cinelerra_framerate_frame_get_time (const CinelerraFramerate framerate, CinelerraTime time) +{ + REQUIRE (framerate); + TODO ("if(!time).."); + /* we add a magic microsecond for rounding, because of integer truncation frames may be calculated at most 1us earlier, + the idea is to compensate odd framerates which fall out off microsecond precision. + */ + return ((time->tv_sec * 1000000ULL + time->tv_usec + /*magic*/1) * framerate->n)/(framerate->d * 1000000ULL) + 1; +} + +/** + * Get the start time for a frame. + * frame indexing starts with 1 + */ +static inline CinelerraTime +cinelerra_framerate_time_get_time_frame (const CinelerraFramerate framerate, + CinelerraTime time, + cinelerra_framepos frame) +{ + REQUIRE (framerate); + REQUIRE (frame>0); + TODO ("if(!time).."); + + unsigned long long usec = (frame-1) * (framerate->d * 1000000ULL) / framerate->n; + + time->tv_sec = usec / 1000000; + time->tv_usec = usec % 1000000; + + return time; +} + +#endif diff --git a/src/lib/time.h b/src/lib/time.h index 78f0854e1..a2dea483b 100644 --- a/src/lib/time.h +++ b/src/lib/time.h @@ -1,5 +1,5 @@ /* - time.h - Time and frame calculations + time.h - Time calculations Copyright (C) CinelerraCV 2007, Christian Thaeter @@ -49,22 +49,6 @@ CINELERRA_ERROR_DECLARE(TIME_NEGATIVE); typedef struct timeval cinelerra_time; typedef cinelerra_time* CinelerraTime; -/** - * framerates are defined as a rational number - * for example NTSC with 29.97fps is {2997, 100} - */ -struct cinelerra_framerate_struct -{ - unsigned numerator; - unsigned denominator; -}; - -typedef struct cinelerra_framerate_struct cinelerra_framerate; -typedef cinelerra_framerate* CinelerraFramerate; - -typedef unsigned long cinelerra_frame; - - /** * normalize time after operations. * used internally diff --git a/tests/10timefunctions.tests b/tests/10timefunctions.tests index e2582ddc6..fe4603e0a 100644 --- a/tests/10timefunctions.tests +++ b/tests/10timefunctions.tests @@ -44,10 +44,76 @@ END PLANNED "overflow" PLANNED "underflow" +# frame 1 begins at time 0 +TEST "time to frame NTSC frame 1 begin" ntscframefromtime 0 0 < #include "lib/time.h" +#include "lib/frames.h" CINELERRA_ERROR_DEFINE(TEST, "test error"); @@ -30,6 +31,8 @@ CINELERRA_ERROR_DEFINE(TEST, "test error"); int main (int argc, char** argv) { + NOBUG_INIT; + if (argc == 1) return 0; @@ -96,6 +99,26 @@ main (int argc, char** argv) printf ("%lu %lu\n", (long)cinelerra_time_sec (&time1), (long)cinelerra_time_usec (&time1)); } + if (!strcmp(argv[1], "ntscframefromtime")) + { + cinelerra_framerate ntsc = {2997, 100}; + cinelerra_time time; + + cinelerra_time_init (&time, atol (argv[2]), atol (argv[3])); + + printf ("%lu\n", (long)cinelerra_framerate_frame_get_time (&ntsc, &time)); + } + + if (!strcmp(argv[1], "ntscframestart")) + { + cinelerra_framerate ntsc = {2997, 100}; + cinelerra_time time; + + cinelerra_framerate_time_get_time_frame (&ntsc, &time, atol (argv[2])); + + printf ("%lu %lu\n", (long)cinelerra_time_sec(&time), (long)cinelerra_time_usec(&time)); + } + return 0; }