put framerate caclulation in a single file

This commit is contained in:
Christian Thaeter 2007-08-25 03:46:07 +02:00
parent 9472c115e7
commit c2898d26f2
4 changed files with 172 additions and 20 deletions

79
src/lib/framerate.h Normal file
View file

@ -0,0 +1,79 @@
/*
framerate.h - framerate calculations
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
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

View file

@ -1,5 +1,5 @@
/*
time.h - Time and frame calculations
time.h - Time calculations
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
@ -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

View file

@ -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 <<END
out: 1
END
# and ends at 33365
TEST "time to frame NTSC frame 1 end" ntscframefromtime 0 33365 <<END
out: 1
END
# thus 33366 is start of frame 2
TEST "time to frame NTSC frame 2 begin" ntscframefromtime 0 33366 <<END
out: 2
END
# and 66732 is the end of frame 2
TEST "time to frame NTSC frame 2 end" ntscframefromtime 0 66732 <<END
out: 2
END
# this makes 66733 the start of frame 3
TEST "time to frame NTSC frame 3 begin" ntscframefromtime 0 66733 <<END
out: 3
END
# and 100099 the end of frame 3
TEST "time to frame NTSC frame 3 end" ntscframefromtime 0 100099 <<END
out: 3
END
# and 100100 the start of frame 4
TEST "time to frame NTSC frame 4 start" ntscframefromtime 0 100100 <<END
out: 4
END
# after 1 hour we are at frame 107893
TEST "time to frame NTSC after 1hour" ntscframefromtime 3600 0 <<END
out: 107893
END
# after 200 days we are at frame 517881601
TEST "time to frame NTSC after 200 days" ntscframefromtime 17280000 0 <<END
out: 517881601
END
TEST "frame to time NTSC frame 1" ntscframestart 1 <<END
out: 0 0
END
TEST "frame to time NTSC frame 2" ntscframestart 2 <<END
out: 0 33366
END
TEST "frame to time NTSC frame 3" ntscframestart 3 <<END
out: 0 66733
END
TEST "frame to time NTSC frame 4" ntscframestart 4 <<END
out: 0 100100
END
TEST "frame to time NTSC 1 hour" ntscframestart 107893 <<END
out: 3600 0
END
TEST "frame to time NTSC 200 days" ntscframestart 517881601 <<END
out: 17280000 0
END
# the next ones for different common framerates, check corner cases
PLANNED "time to frame"
PLANNED "frame to time"
# how long are N frames on average (beware of precision!)

View file

@ -23,6 +23,7 @@
#include <string.h>
#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;
}