== Core ==

This adds fractional FPS support to blender and should finally
make NTSC work correctly.

NTSC has an FPS of 30.0/1.001 which is approximately 29.97 FPS.
Therefore, it is not enough to simply make frs_sec a float, since
you can't represent this accurately enough. 
I added a seperate variable frs_sec_base and FPS is now 
frs_sec / frs_sec_base.

I changed all the places, where frs_sec was used to my best knowledge.

For convenience sake, I added several macros, that should make life
easier in the future:

FRA2TIME(a) : convert frame number to a double precision time in seconds
TIME2FRA(a) : the same in the opposite direction
FPS         : return current FPS as a double precision number 
              (last resort)

This closes bug #6715 
Standard framerates not supported / breaks sync -- 23.967 29.967 etc.

https://projects.blender.org/tracker/?func=detail&aid=6715&group_id=9&atid=125

Please give this heavy testing with NTSC files, quicktime in/export
and the python interface.
Errors are most probably only spotted on longer timelines, so that is
also important.

The patch was tested by Troy Sobotka and me, so it most probably should
work out of the box, but wider testing is important, since errors are
very subtle.

Enjoy!
This commit is contained in:
Peter Schlaile 2007-10-21 15:42:08 +00:00
parent bacfc9eb91
commit a0390e5cc3
29 changed files with 188 additions and 101 deletions

View File

@ -99,8 +99,8 @@ AviError AVI_set_compress_option (AviMovie *movie, int option_type, int stream,
break;
case AVI_OPTION_FRAMERATE:
if (1000000/(*((int *) opt_data)))
movie->header->MicroSecPerFrame = 1000000/(*((int *) opt_data));
if (1000000/(*((double *) opt_data)))
movie->header->MicroSecPerFrame = 1000000/(*((double *) opt_data));
for (i=0; i < movie->header->Streams; i++) {
if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {

View File

@ -197,6 +197,7 @@ Scene *add_scene(char *name)
sce->r.images= 100;
sce->r.framelen= 1.0;
sce->r.frs_sec= 25;
sce->r.frs_sec_base= 1;
sce->r.ocres = 128;
sce->r.bake_mode= 1; /* prevent to include render stuff here */

View File

@ -138,7 +138,8 @@ void start_avi(RenderData *rd, int rectx, int recty)
int x, y;
char name[256];
AviFormat format;
int quality, framerate;
int quality;
double framerate;
makeavistring(rd, name);
@ -147,7 +148,7 @@ void start_avi(RenderData *rd, int rectx, int recty)
y = recty;
quality= rd->quality;
framerate= rd->frs_sec;
framerate= (double) rd->frs_sec / (double) rd->frs_sec_base;
avi = MEM_mallocN (sizeof(AviMovie), "avimovie");

View File

@ -355,18 +355,26 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of,
if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
c->time_base.den = 2997;
c->time_base.num = 100;
} else {
} else if ((double) ((int) G.scene->r.frs_sec_base) ==
G.scene->r.frs_sec_base) {
c->time_base.den = G.scene->r.frs_sec;
c->time_base.num = 1;
c->time_base.num = (int) G.scene->r.frs_sec_base;
} else {
c->time_base.den = G.scene->r.frs_sec * 100000;
c->time_base.num = ((double) G.scene->r.frs_sec_base) * 100000;
}
#else
/* FIXME: Really bad hack (tm) for NTSC support */
if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
c->frame_rate = 2997;
c->frame_rate_base = 100;
} else {
} else if ((double) ((int) G.scene->r.frs_sec_base) ==
G.scene->r.frs_sec_base) {
c->frame_rate = G.scene->r.frs_sec;
c->frame_rate_base = 1;
c->frame_rate_base = G.scene->r.frs_sec_base;
} else {
c->frame_rate = G.scene->r.frs_sec * 100000;
c->frame_rate_base = ((double) G.scene->r.frs_sec_base)*100000;
}
#endif

View File

@ -6743,11 +6743,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) {
Image *ima;
Image *ima;
Scene *sce;
/* initialize 1:1 Aspect */
for(ima= main->image.first; ima; ima= ima->id.next) {
ima->aspx = ima->aspy = 1.0f;
}
/* fix frs_sec_base */
for(sce= main->scene.first; sce; sce= sce->id.next) {
if (sce->r.frs_sec_base == 0) {
sce->r.frs_sec_base = 1;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 4)) {

View File

@ -71,7 +71,7 @@ void sound_set_position(void *object,
struct hdaudio * sound_open_hdaudio(char * name);
struct hdaudio * sound_copy_hdaudio(struct hdaudio * c);
long sound_hdaudio_get_duration(struct hdaudio * hdaudio, int frame_rate);
long sound_hdaudio_get_duration(struct hdaudio * hdaudio, double frame_rate);
void sound_hdaudio_extract(struct hdaudio * hdaudio,
short * target_buffer,
int sample_position /* units of target_rate */,

View File

@ -113,6 +113,9 @@
#define EFRA (G.scene->r.efra)
#define PSFRA ((G.scene->r.psfra != 0)? (G.scene->r.psfra): (G.scene->r.sfra))
#define PEFRA ((G.scene->r.psfra != 0)? (G.scene->r.pefra): (G.scene->r.efra))
#define FRA2TIME(a) ((((double) G.scene->r.frs_sec_base) * (a)) / G.scene->r.frs_sec)
#define TIME2FRA(a) ((((double) G.scene->r.frs_sec) * (a)) / G.scene->r.frs_sec_base)
#define FPS (((double) G.scene->r.frs_sec) / G.scene->r.frs_sec_base)
#define ISPOIN(a, b, c) ( (a->b) && (a->c) )
#define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) )

View File

@ -241,16 +241,17 @@ typedef struct RenderData {
*/
short osa;
short frs_sec, edgeint;
/* safety, border and display rect */
rctf safety, border;
rcti disprect;
/* information on different layers to be rendered */
ListBase layers;
short actlay, pad;
int pad2;
short actlay, pad2;
short edgeint;
short frs_sec;
float frs_sec_base;
/**
* Value used to define filter size for all filter options */

View File

@ -75,6 +75,7 @@ enum rend_constants {
EXPP_RENDER_ATTR_SFRAME,
EXPP_RENDER_ATTR_EFRAME,
EXPP_RENDER_ATTR_FPS,
EXPP_RENDER_ATTR_FPS_BASE,
EXPP_RENDER_ATTR_SIZEX,
EXPP_RENDER_ATTR_SIZEY,
EXPP_RENDER_ATTR_GAUSSFILTER,
@ -285,7 +286,8 @@ static PyObject *M_Render_GetSetAttributeInt( PyObject * args, int *structure,
static void M_Render_DoSizePreset( BPy_RenderData * self, short xsch,
short ysch, short xasp, short yasp,
short size, short xparts, short yparts,
short frames, float a, float b, float c,
short fps, float fps_base,
float a, float b, float c,
float d )
{
self->renderContext->xsch = xsch;
@ -293,7 +295,8 @@ static void M_Render_DoSizePreset( BPy_RenderData * self, short xsch,
self->renderContext->xasp = xasp;
self->renderContext->yasp = yasp;
self->renderContext->size = size;
self->renderContext->frs_sec = frames;
self->renderContext->frs_sec = fps;
self->renderContext->frs_sec_base = fps_base;
self->renderContext->xparts = xparts;
self->renderContext->yparts = yparts;
@ -1022,6 +1025,12 @@ PyObject *RenderData_FramesPerSec( BPy_RenderData * self, PyObject * args )
120 );
}
PyObject *RenderData_FramesPerSecBase( BPy_RenderData * self, PyObject * args )
{
return M_Render_GetSetAttributeFloat(
args, &self->renderContext->frs_sec_base, 1.0f, 120.0f );
}
PyObject *RenderData_EnableGrayscale( BPy_RenderData * self )
{
self->renderContext->planes = R_PLANESBW;
@ -1057,20 +1066,24 @@ PyObject *RenderData_SizePreset( BPy_RenderData * self, PyObject * args )
if( type == B_PR_PAL ) {
M_Render_DoSizePreset( self, 720, 576, 54, 51, 100,
self->renderContext->xparts,
self->renderContext->yparts, 25, 0.1f,
self->renderContext->yparts, 25, 1.0f,
0.1f,
0.9f, 0.1f, 0.9f );
self->renderContext->mode &= ~R_PANORAMA;
BLI_init_rctf( &self->renderContext->safety, 0.1f, 0.9f, 0.1f,
0.9f );
} else if( type == B_PR_NTSC ) {
M_Render_DoSizePreset( self, 720, 480, 10, 11, 100, 1, 1,
30, 0.1f, 0.9f, 0.1f, 0.9f );
30, 1.001f,
0.1f, 0.9f, 0.1f, 0.9f );
self->renderContext->mode &= ~R_PANORAMA;
BLI_init_rctf( &self->renderContext->safety, 0.1f, 0.9f, 0.1f,
0.9f );
} else if( type == B_PR_PRESET ) {
M_Render_DoSizePreset( self, 720, 576, 54, 51, 100, 1, 1,
self->renderContext->frs_sec, 0.1f, 0.9f,
self->renderContext->frs_sec,
self->renderContext->frs_sec_base,
0.1f, 0.9f,
0.1f, 0.9f );
self->renderContext->mode = R_OSA + R_SHADOW + R_FIELDS;
self->renderContext->imtype = R_TARGA;
@ -1078,34 +1091,42 @@ PyObject *RenderData_SizePreset( BPy_RenderData * self, PyObject * args )
0.9f );
} else if( type == B_PR_PRV ) {
M_Render_DoSizePreset( self, 640, 512, 1, 1, 50, 1, 1,
self->renderContext->frs_sec, 0.1f, 0.9f,
self->renderContext->frs_sec,
self->renderContext->frs_sec_base,
0.1f, 0.9f,
0.1f, 0.9f );
self->renderContext->mode &= ~R_PANORAMA;
BLI_init_rctf( &self->renderContext->safety, 0.1f, 0.9f, 0.1f,
0.9f );
} else if( type == B_PR_PC ) {
M_Render_DoSizePreset( self, 640, 480, 100, 100, 100, 1, 1,
self->renderContext->frs_sec, 0.0f, 1.0f,
self->renderContext->frs_sec,
self->renderContext->frs_sec_base,
0.0f, 1.0f,
0.0f, 1.0f );
self->renderContext->mode &= ~R_PANORAMA;
BLI_init_rctf( &self->renderContext->safety, 0.0f, 1.0f, 0.0f,
1.0f );
} else if( type == B_PR_PAL169 ) {
M_Render_DoSizePreset( self, 720, 576, 64, 45, 100, 1, 1,
25, 0.1f, 0.9f, 0.1f, 0.9f );
25, 1.0f, 0.1f, 0.9f, 0.1f, 0.9f );
self->renderContext->mode &= ~R_PANORAMA;
BLI_init_rctf( &self->renderContext->safety, 0.1f, 0.9f, 0.1f,
0.9f );
} else if( type == B_PR_PANO ) {
M_Render_DoSizePreset( self, 36, 176, 115, 100, 100, 16, 1,
self->renderContext->frs_sec, 0.1f, 0.9f,
self->renderContext->frs_sec,
self->renderContext->frs_sec_base,
0.1f, 0.9f,
0.1f, 0.9f );
self->renderContext->mode |= R_PANORAMA;
BLI_init_rctf( &self->renderContext->safety, 0.1f, 0.9f, 0.1f,
0.9f );
} else if( type == B_PR_FULL ) {
M_Render_DoSizePreset( self, 1280, 1024, 1, 1, 100, 1, 1,
self->renderContext->frs_sec, 0.1f, 0.9f,
self->renderContext->frs_sec,
self->renderContext->frs_sec_base,
0.1f, 0.9f,
0.1f, 0.9f );
self->renderContext->mode &= ~R_PANORAMA;
BLI_init_rctf( &self->renderContext->safety, 0.1f, 0.9f, 0.1f,
@ -1729,9 +1750,11 @@ PyObject *RenderData_NewMapValue( BPy_RenderData * self, PyObject * args )
static PyObject *RenderData_getTimeCode( BPy_RenderData * self) {
char tc[12];
int h, m, s, fps, cfa;
int h, m, s, cfa;
double fps;
fps = self->renderContext->frs_sec;
fps = (double) self->renderContext->frs_sec /
self->renderContext->frs_sec_base;
cfa = self->renderContext->cfra-1;
s = cfa / fps;
m = s / 60;
@ -1739,7 +1762,8 @@ static PyObject *RenderData_getTimeCode( BPy_RenderData * self) {
if( h > 99 )
return PyString_FromString("Time Greater than 99 Hours!");
sprintf( tc, "%02d:%02d:%02d:%02d", h%60, m%60, s%60, cfa%fps);
sprintf( tc, "%02d:%02d:%02d:%02d", h%60, m%60, s%60,
(int) (cfa - ((int) (cfa / fps) * fps)));
return PyString_FromString(tc);
}
@ -1762,6 +1786,9 @@ static PyObject *RenderData_getFloatAttr( BPy_RenderData *self, void *type )
case EXPP_RENDER_ATTR_MBLURFACTOR:
param = self->renderContext->blurfac;
break;
case EXPP_RENDER_ATTR_FPS_BASE:
param = self->renderContext->frs_sec_base;
break;
default:
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
"undefined type constant in RenderData_getFloatAttr" );
@ -1790,6 +1817,11 @@ static int RenderData_setFloatAttrClamp( BPy_RenderData *self, PyObject *value,
max = 5.0f;
param = &self->renderContext->blurfac;
break;
case EXPP_RENDER_ATTR_FPS_BASE:
min = 1.0f;
max = 120.0f;
param = &self->renderContext->frs_sec_base;
break;
default:
return EXPP_ReturnIntError( PyExc_RuntimeError,
"undefined type constant in RenderData_setFloatAttrClamp" );
@ -2540,6 +2572,10 @@ static PyGetSetDef BPy_RenderData_getseters[] = {
(getter)RenderData_getIValueAttr, (setter)RenderData_setIValueAttrClamp,
"Frames per second",
(void *)EXPP_RENDER_ATTR_FPS},
{"fps_base",
(getter)RenderData_getFloatAttr, (setter)RenderData_setFloatAttrClamp,
"Frames per second base",
(void *)EXPP_RENDER_ATTR_FPS_BASE},
{"sizeX",
(getter)RenderData_getIValueAttr, (setter)RenderData_setIValueAttrClamp,
"Image width (in pixels)",
@ -2782,6 +2818,8 @@ static PyMethodDef BPy_RenderData_methods[] = {
"(int) - get/set quality get/setting for JPEG images, AVI Jpeg and SGI movies"},
{"framesPerSec", ( PyCFunction ) RenderData_FramesPerSec, METH_VARARGS,
"(int) - get/set frames per second"},
{"framesPerSecBase", ( PyCFunction ) RenderData_FramesPerSecBase, METH_VARARGS,
"(float) - get/set frames per second base"},
{"enableGrayscale", ( PyCFunction ) RenderData_EnableGrayscale,
METH_NOARGS,
"() - images are saved with BW (grayscale) data"},

View File

@ -169,7 +169,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce)
seq->type= SEQ_RAM_SOUND;
seq->sound = sound;
totframe= (int) ( ((float)(sound->streamlen-1)/( (float)sce->audio.mixrate*4.0 ))* (float)sce->r.frs_sec);
totframe= (int) ( ((float)(sound->streamlen-1)/( (float)sce->audio.mixrate*4.0 ))* (float)sce->r.frs_sec / sce->r.frs_sec_base);
sound->flags |= SOUND_FLAGS_SEQUENCE;

View File

@ -566,20 +566,21 @@ static void check_renderbutton_framerate(void) {
(qtdata->gTemporalSettings.frameRate == 1571553 ||
qtdata->gTemporalSettings.frameRate == 1964113 ||
qtdata->gTemporalSettings.frameRate == 3928227)) {;} else
qtdata->gTemporalSettings.frameRate = G.scene->r.frs_sec << 16;
qtdata->gTemporalSettings.frameRate =
(G.scene->r.frs_sec << 16) / G.scene->r.frs_sec_base ;
err = SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings);
CheckError( err, "SCSetInfo error" );
if(qtdata->gTemporalSettings.frameRate == 1571553) { // 23.98 fps
qtdata->kVideoTimeScale = 2398;
qtdata->duration = 100;
qtdata->kVideoTimeScale = 2400;
qtdata->duration = 1001;
} else if (qtdata->gTemporalSettings.frameRate == 1964113) { // 29.97 fps
qtdata->kVideoTimeScale = 2997;
qtdata->duration = 100;
qtdata->kVideoTimeScale = 3000;
qtdata->duration = 1001;
} else if (qtdata->gTemporalSettings.frameRate == 3928227) { // 59.94 fps
qtdata->kVideoTimeScale = 5994;
qtdata->duration = 100;
qtdata->kVideoTimeScale = 6000;
qtdata->duration = 1001;
} else {
qtdata->kVideoTimeScale = (qtdata->gTemporalSettings.frameRate >> 16) * 100;
qtdata->duration = 100;
@ -641,25 +642,37 @@ int get_qtcodec_settings(void)
// framerate jugglin'
if(qtdata->gTemporalSettings.frameRate == 1571553) { // 23.98 fps
qtdata->kVideoTimeScale = 2398;
qtdata->duration = 100;
qtdata->kVideoTimeScale = 24000;
qtdata->duration = 1001;
G.scene->r.frs_sec = 24;
G.scene->r.frs_sec_base = 1.001;
} else if (qtdata->gTemporalSettings.frameRate == 1964113) { // 29.97 fps
qtdata->kVideoTimeScale = 2997;
qtdata->duration = 100;
qtdata->kVideoTimeScale = 3000;
qtdata->duration = 1001;
G.scene->r.frs_sec = 30;
G.scene->r.frs_sec_base = 1.001;
} else if (qtdata->gTemporalSettings.frameRate == 3928227) { // 59.94 fps
qtdata->kVideoTimeScale = 5994;
qtdata->duration = 100;
qtdata->kVideoTimeScale = 6000;
qtdata->duration = 1001;
G.scene->r.frs_sec = 60;
G.scene->r.frs_sec_base = 1.001;
} else {
double fps = qtdata->gTemporalSettings.frameRate;
qtdata->kVideoTimeScale = 600;
qtdata->duration = qtdata->kVideoTimeScale / (qtdata->gTemporalSettings.frameRate / 65536);
G.scene->r.frs_sec = (qtdata->gTemporalSettings.frameRate / 65536);
if ((qtdata->gTemporalSettings.frameRate & 0xffff) == 0) {
G.scene->r.frs_sec = fps / 65536;
G.scene->r.frs_sec_base = 1;
} else {
/* we do our very best... */
G.scene->r.frs_sec = (fps * 10000 / 65536);
G.scene->r.frs_sec_base = 10000;
}
}
return 1;

View File

@ -612,6 +612,7 @@ void do_render_panels(unsigned short event)
G.scene->r.yasp= 51;
G.scene->r.size= 100;
G.scene->r.frs_sec= 25;
G.scene->r.frs_sec_base= 1;
G.scene->r.mode &= ~R_PANORAMA;
G.scene->r.xparts= G.scene->r.yparts= 4;
#ifdef WITH_FFMPEG
@ -718,6 +719,7 @@ void do_render_panels(unsigned short event)
G.scene->r.yasp= 45;
G.scene->r.size= 100;
G.scene->r.frs_sec= 25;
G.scene->r.frs_sec_base= 1;
G.scene->r.mode &= ~R_PANORAMA;
G.scene->r.xparts= G.scene->r.yparts= 4;
#ifdef WITH_FFMPEG
@ -780,6 +782,7 @@ void do_render_panels(unsigned short event)
G.scene->r.yasp= 11;
G.scene->r.size= 100;
G.scene->r.frs_sec= 30;
G.scene->r.frs_sec_base = 1.001;
G.scene->r.mode &= ~R_PANORAMA;
G.scene->r.xparts= G.scene->r.yparts= 2;
#ifdef WITH_FFMPEG
@ -1641,7 +1644,7 @@ static void render_panel_format(void)
uiDefBut(block, LABEL, 0, "Codec: not set", 892,yofs+44,225,20, 0, 0, 0, 0, 0, "");
else
uiDefBut(block, LABEL, 0, G.scene->r.qtcodecdata->qtcodecname, 892,yofs+44,225,20, 0, 0, 0, 0, 0, "");
uiDefBut(block, BUT,B_SELECTCODEC, "Set codec", 892,yofs,112,20, 0, 0, 0, 0, 0, "Set codec settings for Quicktime");
uiDefBut(block, BUT,B_SELECTCODEC, "Set codec", 892,yofs,74,20, 0, 0, 0, 0, 0, "Set codec settings for Quicktime");
#endif
#endif /* WITH_QUICKTIME */
} else {
@ -1653,7 +1656,7 @@ static void render_panel_format(void)
else
uiDefBut(block, LABEL, 0, avicodec_str(), 892,yofs+43,225,20, 0, 0, 0, 0, 0, "");
#endif
uiDefBut(block, BUT,B_SELECTCODEC, "Set codec", 892,yofs,112,20, 0, 0, 0, 0, 0, "Set codec settings for AVI");
uiDefBut(block, BUT,B_SELECTCODEC, "Set codec", 892,yofs,74,20, 0, 0, 0, 0, 0, "Set codec settings for AVI");
}
#ifdef WITH_OPENEXR
}
@ -1668,15 +1671,16 @@ static void render_panel_format(void)
uiDefButBitS(block, TOG, R_PREVIEW_JPG, B_NOP,"Preview",1027,yofs+44,90,20, &G.scene->r.subimtype, 0, 0, 0, 0, "When animation render, save JPG preview images in same directory");
}
uiDefButS(block, MENU,B_NOP, "Codec %t|None %x0|Pxr24 (lossy) %x1|ZIP (lossless) %x2|PIZ (lossless) %x3|RLE (lossless) %x4",
892,yofs,112,20, &G.scene->r.quality, 0, 0, 0, 0, "Set codec settings for OpenEXR");
892,yofs,74,20, &G.scene->r.quality, 0, 0, 0, 0, "Set codec settings for OpenEXR");
#endif
} else {
if(G.scene->r.quality < 5) G.scene->r.quality = 90; /* restore from openexr */
uiDefButS(block, NUM,B_DIFF, "Quality:", 892,yofs,112,20, &G.scene->r.quality, 10.0, 100.0, 0, 0, "Quality setting for JPEG images, AVI Jpeg and SGI movies");
uiDefButS(block, NUM,B_DIFF, "Q:", 892,yofs,74,20, &G.scene->r.quality, 10.0, 100.0, 0, 0, "Quality setting for JPEG images, AVI Jpeg and SGI movies");
}
uiDefButS(block, NUM,B_FRAMEMAP,"Frs/sec:", 1006,yofs,113,20, &G.scene->r.frs_sec, 1.0, 120.0, 100.0, 0, "Frames per second");
uiDefButS(block, NUM,B_FRAMEMAP,"FPS:", 968,yofs,75,20, &G.scene->r.frs_sec, 1.0, 120.0, 100.0, 0, "Frames per second");
uiDefButF(block, NUM,B_FRAMEMAP,"/", 1043,yofs,75,20, &G.scene->r.frs_sec_base, 1.0, 120.0, 0.1, 3, "Frames per second base");
uiBlockBeginAlign(block);
@ -2027,7 +2031,9 @@ void anim_panels()
uiDefButI(block, NUM,B_FRAMEMAP,"Map New:", 160,160,150,20,&G.scene->r.images,1.0,900.0, 0, 0, "Specify how many frames the Map Old will last");
uiBlockBeginAlign(block);
uiDefButS(block, NUM,B_FRAMEMAP,"Frs/sec:", 10,130,150,20, &G.scene->r.frs_sec, 1.0, 120.0, 100.0, 0, "Frames per second");
uiDefButS(block, NUM,B_FRAMEMAP,"FPS:", 10,130,75,20, &G.scene->r.frs_sec, 1.0, 120.0, 100.0, 0, "Frames per second");
uiDefButF(block, NUM,B_FRAMEMAP,"/", 85,130,75,20, &G.scene->r.frs_sec_base, 1.0, 120.0, 0.1, 3, "Frames per second base");
uiDefButBitS(block, TOG, AUDIO_SYNC, B_SOUND_CHANGED, "Sync",160,130,150,20, &G.scene->audio.flag, 0, 0, 0, 0, "Use sample clock for syncing animation to audio");
uiBlockBeginAlign(block);

View File

@ -210,7 +210,7 @@ void calc_ipogrid()
SpaceTime *stime= curarea->spacedata.first;
if(!(stime->flag & TIME_DRAWFRAMES)) {
secondgrid= 1;
secondiv= 0.01 * (float)G.scene->r.frs_sec;
secondiv= 0.01 * FPS;
}
break;
}
@ -218,7 +218,7 @@ void calc_ipogrid()
SpaceSeq * sseq = curarea->spacedata.first;
if (!(sseq->flag & SEQ_DRAWFRAMES)) {
secondgrid = 1;
secondiv = 0.01 * (float)G.scene->r.frs_sec;
secondiv = 0.01 * FPS;
}
break;
}
@ -226,7 +226,7 @@ void calc_ipogrid()
SpaceAction *saction = curarea->spacedata.first;
if (saction->flag & SACTION_DRAWTIME) {
secondgrid = 1;
secondiv = 0.01 * (float)G.scene->r.frs_sec;
secondiv = 0.01 * FPS;
}
break;
}
@ -234,7 +234,7 @@ void calc_ipogrid()
SpaceNla *snla = curarea->spacedata.first;
if (snla->flag & SNLA_DRAWTIME) {
secondgrid = 1;
secondiv = 0.01 * (float)G.scene->r.frs_sec;
secondiv = 0.01 * FPS;
}
break;
}
@ -863,7 +863,7 @@ void draw_view2d_numbers_horiz(int drawframes)
scroll_prstr(fac, 2.0+(float)(G.v2d->mask.ymin), val, 'h', 0);
}
else {
fac2= val/(float)G.scene->r.frs_sec;
fac2= val/FPS;
scroll_prstr(fac, 2.0+(float)(G.v2d->mask.ymin), fac2, 'h', 0);
}
@ -934,10 +934,10 @@ void drawscroll(int disptype)
ipomachtx = 1;
scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
} else {
fac2= val/(float)G.scene->r.frs_sec;
fac2= val/FPS;
tim= floor(fac2);
fac2= fac2-tim;
scroll_prstr(fac, 3.0+(float)(hor.ymin), tim+G.scene->r.frs_sec*fac2/100.0, 'h', disptype);
scroll_prstr(fac, 3.0+(float)(hor.ymin), tim+FPS*fac2/100.0, 'h', disptype);
}
}
else if (curarea->spacetype==SPACE_SOUND) {
@ -948,7 +948,7 @@ void drawscroll(int disptype)
scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
}
else {
fac2= val/(float)G.scene->r.frs_sec;
fac2= val/FPS;
scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
}
}
@ -960,7 +960,7 @@ void drawscroll(int disptype)
scroll_prstr(fac, 3.0+(float)(hor.ymin), val, 'h', disptype);
}
else {
fac2= val/(float)G.scene->r.frs_sec;
fac2= val/FPS;
scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
}
}
@ -983,7 +983,7 @@ void drawscroll(int disptype)
SpaceAction *saction= curarea->spacedata.first;
if (saction->flag & SACTION_DRAWTIME) {
fac2= val/(float)G.scene->r.frs_sec;
fac2= val/FPS;
scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
}
else {
@ -995,7 +995,7 @@ void drawscroll(int disptype)
SpaceNla *snla= curarea->spacedata.first;
if (snla->flag & SNLA_DRAWTIME) {
fac2= val/(float)G.scene->r.frs_sec;
fac2= val/FPS;
scroll_prstr(fac, 3.0+(float)(hor.ymin), fac2, 'h', disptype);
}
else {

View File

@ -308,8 +308,8 @@ static void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2, i
if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
sofs = ((int)( (((float)(seq->startdisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
eofs = ((int)( (((float)(seq->enddisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
sofs = ((int)( FRA2TIME(seq->startdisp-seq->start)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
eofs = ((int)( FRA2TIME(seq->enddisp-seq->start)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
/* clip the drawing area to the screen bounds to save time */
sample_step= (G.v2d->cur.xmax - G.v2d->cur.xmin)/winx;

View File

@ -58,6 +58,8 @@
#include "BSE_time.h"
#include "BMF_Api.h"
#include "blendef.h"
/* local */
void drawsoundspace(ScrArea *sa, void *spacedata);
@ -99,7 +101,7 @@ static void draw_sample(bSample *sample)
short *sp, sampdx;
/* one sample is where in v2d space? (v2d space in frames!) */
sampfac= ((float)G.scene->r.frs_sec)/(sample->rate);
sampfac= FPS/(sample->rate);
/* how many samples? */
samples= sample->len/(sample->channels*(sample->bits/8));
@ -161,8 +163,8 @@ static void draw_cfra_sound(SpaceSound *ssound)
areamouseco_to_ipoco(G.v2d, mval, &x, &y);
if(ssound->flag & SND_DRAWFRAMES)
sprintf(str, " %d\n", (G.scene->r.cfra));
else sprintf(str, " %.2f\n", (G.scene->r.cfra/(float)G.scene->r.frs_sec));
sprintf(str, " %d\n", CFRA);
else sprintf(str, " %.2f\n", FRA2TIME(CFRA));
glRasterPos2f(x, y);
glColor3ub(0, 0, 0);

View File

@ -112,8 +112,8 @@ static void draw_cfra_time(SpaceTime *stime)
areamouseco_to_ipoco(G.v2d, mval, &x, &y);
if(stime->flag & TIME_DRAWFRAMES)
sprintf(str, " %d", (G.scene->r.cfra));
else sprintf(str, " %.2f", (G.scene->r.cfra/(float)G.scene->r.frs_sec));
sprintf(str, " %d", CFRA);
else sprintf(str, " %.2f", FRA2TIME(CFRA));
/* HACK! somehow the green color won't go away... */
glColor4ub(0, 0, 0, 0);

View File

@ -3264,7 +3264,7 @@ void inner_play_anim_loop(int init, int mode)
/* init */
if(init) {
oldsa= curarea;
swaptime= 1.0/(float)G.scene->r.frs_sec;
swaptime= 1.0/FPS;
tottime= 0.0;
curmode= mode;
last_cfra = -1;

View File

@ -5290,7 +5290,7 @@ void ipo_record(void)
waitcursor(1);
tottime= 0.0;
swaptime= 1.0/(float)G.scene->r.frs_sec;
swaptime= 1.0/FPS;
cfrao= CFRA;
cfra=efra= SFRA;

View File

@ -577,7 +577,7 @@ static int snap_bezier_nearest(BezTriple *bezt)
static int snap_bezier_nearestsec(BezTriple *bezt)
{
float secf = (float)(G.scene->r.frs_sec);
float secf = FPS;
if(bezt->f2 & SELECT)
bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]/secf + 0.5f) * secf);
return 0;

View File

@ -429,7 +429,7 @@ void snap_action_strips(int snap_mode)
}
else if (snap_mode==3) {
/* nearest second */
float secf = (float)(G.scene->r.frs_sec);
float secf = FPS;
strip->start= (float)(floor(strip->start/secf + 0.5f) * secf);
strip->end= (float)(floor(strip->end/secf + 0.5f) * secf);
}

View File

@ -1138,7 +1138,7 @@ int do_screenhandlers(bScreen *sc)
short a, done= 0;
time = PIL_check_seconds_timer();
swaptime= 1.0/(float)G.scene->r.frs_sec;
swaptime= 1.0/FPS;
/* only now do the handlers */
if(swaptime < time-ltime || ltime==0.0) {

View File

@ -1101,7 +1101,8 @@ static Sequence *sfile_to_ramsnd_sequence(SpaceFile *sfile,
sound->flags |= SOUND_FLAGS_SEQUENCE;
audio_makestream(sound);
totframe= (int) ( ((float)(sound->streamlen-1)/( (float)G.scene->audio.mixrate*4.0 ))* (float)G.scene->r.frs_sec);
totframe= (int) ( ((float)(sound->streamlen-1)/
( (float)G.scene->audio.mixrate*4.0 ))* FPS);
/* make seq */
seq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
@ -1168,7 +1169,7 @@ static int sfile_to_hdsnd_sequence_load(SpaceFile *sfile, int cfra,
return(cfra);
}
totframe= sound_hdaudio_get_duration(hdaudio, G.scene->r.frs_sec);
totframe= sound_hdaudio_get_duration(hdaudio, FPS);
/* make seq */
seq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);

View File

@ -208,7 +208,7 @@ void transform_markers(int mode, int smode) // mode and smode unused here, for c
fac= (((float)(mval[0] - pmval[0]))*dx);
if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND))
apply_keyb_grid(&fac, 0.0, (float)G.scene->r.frs_sec, 0.1*(float)G.scene->r.frs_sec, 0);
apply_keyb_grid(&fac, 0.0, FPS, 0.1*FPS, 0);
else
apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
offs= (int)fac;
@ -225,11 +225,11 @@ void transform_markers(int mode, int smode) // mode and smode unused here, for c
if (stime->flag & TIME_DRAWFRAMES)
sprintf(str, "Marker %d offset %d", selmarker->frame, offs);
else
sprintf(str, "Marker %.2f offset %.2f", (selmarker->frame/(float)G.scene->r.frs_sec), (offs/(float)G.scene->r.frs_sec));
sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
}
else if (slink->spacetype == SPACE_ACTION) {
if (saction->flag & SACTION_DRAWTIME)
sprintf(str, "Marker %.2f offset %.2f", (selmarker->frame/(float)G.scene->r.frs_sec), (offs/(float)G.scene->r.frs_sec));
sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
else
sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
}
@ -242,11 +242,11 @@ void transform_markers(int mode, int smode) // mode and smode unused here, for c
if (stime->flag & TIME_DRAWFRAMES)
sprintf(str, "Marker offset %d ", offs);
else
sprintf(str, "Marker offset %.2f ", (offs/(float)G.scene->r.frs_sec));
sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
}
else if (slink->spacetype == SPACE_ACTION) {
if (saction->flag & SACTION_DRAWTIME)
sprintf(str, "Marker offset %.2f ", (offs/(float)G.scene->r.frs_sec));
sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
else
sprintf(str, "Marker offset %.2f ", (double)(offs));
}

View File

@ -200,7 +200,7 @@ struct hdaudio * sound_copy_hdaudio(struct hdaudio * c)
#endif
}
long sound_hdaudio_get_duration(struct hdaudio * hdaudio, int frame_rate)
long sound_hdaudio_get_duration(struct hdaudio * hdaudio, double frame_rate)
{
#ifdef WITH_FFMPEG
return hdaudio->pFormatCtx->duration * frame_rate / AV_TIME_BASE;

View File

@ -136,7 +136,7 @@ static void do_time_redrawmenu(void *arg, int event)
}
else {
if(event==1001) {
button(&G.scene->r.frs_sec,1,120,"Frames/Second:");
button(&G.scene->r.frs_sec,1,120,"FPS:");
}
}
}
@ -180,7 +180,7 @@ static uiBlock *time_redrawmenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
sprintf(str, "Set Frames/Sec (%d)", G.scene->r.frs_sec);
sprintf(str, "Set Frames/Sec (%d/%f)", G.scene->r.frs_sec, G.scene->r.frs_sec_base);
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, str, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1001, "");

View File

@ -140,7 +140,7 @@ void audio_mixdown()
strcpy(buf, "RIFFlengWAVEfmt fmln01ccRATEbsecBP16dataDLEN");
totframe = (EFRA - SFRA + 1);
totlen = (int) ( ((float)totframe / (float)G.scene->r.frs_sec) * (float)G.scene->audio.mixrate * 4.0);
totlen = (int) ( FRA2TIME(totframe) * (float)G.scene->audio.mixrate * 4.0);
printf(" totlen %d\n", totlen+36+8);
totlen+= 36; /* len is filesize-8 in WAV spec, total header is 44 bytes */
@ -183,7 +183,7 @@ void audio_mixdown()
memset(buf+i, 0, 64);
CFRA=(int) ( ((float)(audio_pos-64)/( G.scene->audio.mixrate*4 ))*(float)G.scene->r.frs_sec );
CFRA=(int) ( ((float)(audio_pos-64)/( G.scene->audio.mixrate*4 ))*FPS );
audio_fill(buf+i, NULL, 64);
if (G.order == B_ENDIAN) {
@ -217,7 +217,7 @@ void audiostream_fill(Uint8 *mixdown, int len)
for (i = 0; i < len; i += 64) {
CFRA = (int) ( ((float)(audio_pos-64)
/( G.scene->audio.mixrate*4 ))
*(float)G.scene->r.frs_sec );
* FPS );
audio_fill(mixdown + i, NULL,
(len - i) > 64 ? 64 : (len - i));
@ -453,9 +453,8 @@ static int audiostream_play_seq(Sequence * seq, Uint32 startframe)
}
if ((seq->type == SEQ_RAM_SOUND) && (seq->sound)) {
have_sound = 1;
seq->curpos = (int)( (((float)((float)startframe
-(float)seq->start)
/ (float)G.scene->r.frs_sec)
seq->curpos = (int)( (FRA2TIME((double) startframe -
(double) seq->start)
* ((float)G.scene->audio.mixrate)
* 4 ));
}
@ -468,9 +467,8 @@ static int audiostream_play_seq(Sequence * seq, Uint32 startframe)
seq->hdaudio = sound_open_hdaudio(name);
}
seq->curpos = (int)( (((float)((float)startframe
- (float)seq->start)
/ (float)G.scene->r.frs_sec)
seq->curpos = (int)( (FRA2TIME((double) startframe -
(double) seq->start)
* ((float)G.scene->audio.mixrate)
* 4 ));
}
@ -508,8 +506,7 @@ void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown)
}
audio_startframe = startframe;
audio_pos = ( ((int)( (( (double)startframe)
/(double)G.scene->r.frs_sec)
audio_pos = ( ((int)( FRA2TIME(startframe)
*(G.scene->audio.mixrate)*4 )) & (~3) );
audio_scrub = duration;
@ -541,7 +538,7 @@ int audiostream_pos(void)
pos = (int) (((double)(audio_pos-U.mixbufsize)
/ ( G.scene->audio.mixrate*4 ))
* (double)G.scene->r.frs_sec );
* FPS );
if (pos < audio_startframe) pos = audio_startframe;
return ( pos );

View File

@ -3445,7 +3445,7 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
/* snap key to nearest frame? */
if (autosnap == SACTSNAP_FRAME) {
short doTime= getAnimEdit_DrawTime(t);
float secf= ((float)G.scene->r.frs_sec);
double secf= FPS;
float val;
/* convert frame to nla-action time (if needed) */
@ -3496,7 +3496,7 @@ static void headerTimeTranslate(TransInfo *t, char *str)
else {
short autosnap= getAnimEdit_SnapMode(t);
short doTime = getAnimEdit_DrawTime(t);
float secf= ((float)G.scene->r.frs_sec);
double secf= FPS;
float val= t->fac;
/* take into account scaling (for Action Editor only) */
@ -3535,7 +3535,7 @@ static void applyTimeTranslate(TransInfo *t, float sval)
int i;
short doTime= getAnimEdit_DrawTime(t);
float secf= ((float)G.scene->r.frs_sec);
double secf= FPS;
short autosnap= getAnimEdit_SnapMode(t);
float cval= sval + t->fac;
@ -3770,7 +3770,7 @@ static void applyTimeScale(TransInfo *t) {
short autosnap= getAnimEdit_SnapMode(t);
short doTime= getAnimEdit_DrawTime(t);
float secf= ((float)G.scene->r.frs_sec);
double secf= FPS;
for (i = 0 ; i < t->total; i++, td++) {

View File

@ -605,7 +605,9 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
ketsjiengine->SetUseFixedTime(true);
ketsjiengine->SetTicRate(blscene->r.frs_sec);
ketsjiengine->SetTicRate(
(double) blscene->r.frs_sec /
(double) blscene->r.frs_sec_base);
// the mainloop
while ((blscene->r.cfra<=blscene->r.efra)&&(!exitrequested))
@ -663,4 +665,4 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
} while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
if (bfd) BLO_blendfiledata_free(bfd);
}
}

View File

@ -1913,10 +1913,14 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
eulxyzPrev[0]=blenderobject->rot[0];
eulxyzPrev[1]=blenderobject->rot[1];
eulxyzPrev[2]=blenderobject->rot[2];
tmp.scale((float)blenderscene->r.frs_sec,(float)blenderscene->r.frs_sec,(float)blenderscene->r.frs_sec);
double fps = (double) blenderscene->r.frs_sec/
(double) blenderscene->r.frs_sec_base;
tmp.scale(fps, fps, fps);
inivel.push_back(tmp);
tmp=eulxyz-eulxyzPrev;
tmp.scale((float)blenderscene->r.frs_sec,(float)blenderscene->r.frs_sec,(float)blenderscene->r.frs_sec);
tmp.scale(fps, fps, fps);
iniang.push_back(tmp);
blenderscene->r.cfra=blenderscene->r.sfra;
update_for_newframe();