diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 56dff6cef..91327cdf5 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -24,8 +24,9 @@ libcin3_a_CPPFLAGS = -I$(top_srcdir)/src/ libcin3_a_SOURCES = \ $(libcin3_a_srcdir)/plugin.c \ $(libcin3_a_srcdir)/error.c \ - $(libcin3_a_srcdir)/time.c - + $(libcin3_a_srcdir)/time.c \ + $(libcin3_a_srcdir)/framerate.c + noinst_HEADERS += \ $(libcin3_a_srcdir)/plugin.h \ $(libcin3_a_srcdir)/error.h \ diff --git a/src/lib/framerate.c b/src/lib/framerate.c new file mode 100644 index 000000000..138a338a3 --- /dev/null +++ b/src/lib/framerate.c @@ -0,0 +1,25 @@ +/* + framerate.c - 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. +*/ + +#include "lib/error.h" + +CINELERRA_ERROR_DEFINE(FRAMERATE_ILLEGAL_TIME, "invalid time given"); +CINELERRA_ERROR_DEFINE(FRAMERATE_ILLEGAL_FRAME, "invalid frame given"); diff --git a/src/lib/framerate.h b/src/lib/framerate.h index ef3561f87..2df5971fb 100644 --- a/src/lib/framerate.h +++ b/src/lib/framerate.h @@ -22,6 +22,8 @@ #ifndef CINELERRA_FRAMERATE_H #define CINELERRA_FRAMERATE_H +#include + #include "lib/error.h" #include "lib/time.h" @@ -38,17 +40,30 @@ struct cinelerra_framerate_struct typedef struct cinelerra_framerate_struct cinelerra_framerate; typedef cinelerra_framerate* CinelerraFramerate; -typedef unsigned long cinelerra_framepos; +typedef signed long cinelerra_framepos; + +CINELERRA_ERROR_DECLARE(FRAMERATE_ILLEGAL_TIME); +CINELERRA_ERROR_DECLARE(FRAMERATE_ILLEGAL_FRAME); + +#define CINELERRA_FRAMEPOS_ERROR LONG_MIN /** * Get the frame number of a given time at a given frame rate. * frame indexing starts with 1 + * @param framerate is a pointer to the framerate used, defined as rational number. Must be given. + * @param time is a pointer to a cinelerra_time which shall be converted. + * @return frame at the given time or CINELERRA_FRAMEPOS_ERROR on error. */ static inline cinelerra_framepos cinelerra_framerate_frame_get_time (const CinelerraFramerate framerate, CinelerraTime time) { REQUIRE (framerate); - TODO ("if(!time).."); + if (!time || time->tv_sec == (time_t)-1) + { + cinelerra_error_set(CINELERRA_ERROR_FRAMERATE_ILLEGAL_TIME); + return CINELERRA_FRAMEPOS_ERROR; + } + /* 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. */ @@ -58,6 +73,10 @@ cinelerra_framerate_frame_get_time (const CinelerraFramerate framerate, Cinelerr /** * Get the start time for a frame. * frame indexing starts with 1 + * @param framerate is a pointer to the framerate used, defined as rational number. Must be given. + * @param time is a pointer to a cinelerra_time which shall take the result. + * @param frame frame number to be converted to time. This frame number must be greater than 0. + * @return the pointer given in time or NULL on error (or when it was given as time). */ static inline CinelerraTime cinelerra_framerate_time_get_time_frame (const CinelerraFramerate framerate, @@ -65,14 +84,19 @@ cinelerra_framerate_time_get_time_frame (const CinelerraFramerate framerate, cinelerra_framepos frame) { REQUIRE (framerate); - REQUIRE (frame>0); - TODO ("if(!time).."); + if (time) + { + if (frame < 1) + { + cinelerra_error_set(CINELERRA_ERROR_FRAMERATE_ILLEGAL_FRAME); + return NULL; + } - unsigned long long usec = ((frame-1) * framerate->d * 1000000ULL - (/*magic*/frame>1?1:0)) / framerate->n; - - time->tv_sec = usec / 1000000; - time->tv_usec = usec % 1000000; + unsigned long long usec = ((frame-1) * framerate->d * 1000000ULL - (/*magic*/frame>1?1:0)) / framerate->n; + time->tv_sec = usec / 1000000; + time->tv_usec = usec % 1000000; + } return time; } diff --git a/tests/time/test-time.c b/tests/time/test-time.c index 6bbc84833..519a65781 100644 --- a/tests/time/test-time.c +++ b/tests/time/test-time.c @@ -114,9 +114,8 @@ main (int argc, char** argv) cinelerra_framerate ntsc = {30000, 1001}; 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)); + if(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)); } if (!strcmp(argv[1], "ntscframecheck")) @@ -132,14 +131,16 @@ main (int argc, char** argv) frame = atol (argv[2]); - cinelerra_framerate_time_get_time_frame (&ntsc, &time1, frame); - printf("frame %lu ", frame1 = cinelerra_framerate_frame_get_time (&ntsc, &time1)); + if (cinelerra_framerate_time_get_time_frame (&ntsc, &time1, frame)) + { + printf("frame %lu ", frame1 = cinelerra_framerate_frame_get_time (&ntsc, &time1)); - cinelerra_time_init (&time2, 0, 1); - cinelerra_time_sub (&time1, &time2); - printf("%lu\n", frame2 = cinelerra_framerate_frame_get_time (&ntsc, &time1)); + cinelerra_time_init (&time2, 0, 1); + cinelerra_time_sub (&time1, &time2); + printf("%lu\n", frame2 = cinelerra_framerate_frame_get_time (&ntsc, &time1)); + ENSURE (frame1 == frame2+1); + } - ENSURE (frame1 == frame2+1); } return 0;