David McPaul added support for drop frame formats.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@806 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
52ec2aa88b
commit
6c062d1f93
@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
* AUTHOR: Marcus Overhagen, David McPaul
|
||||
* AUTHOR: David McPaul
|
||||
* FILE: TimeCode.cpp
|
||||
* DESCR:
|
||||
* DESCR: Handles all TimeCode functions.
|
||||
***********************************************************************/
|
||||
#include <TimeCode.h>
|
||||
#include "debug.h"
|
||||
@ -9,32 +9,188 @@
|
||||
|
||||
status_t us_to_timecode(bigtime_t micros, int * hours, int * minutes, int * seconds, int * frames, const timecode_info * code = NULL)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return B_ERROR;
|
||||
int fps_div;
|
||||
int32 l_frames;
|
||||
|
||||
CALLED();
|
||||
|
||||
if (code) {
|
||||
// We have a valid timecode_info
|
||||
fps_div = code->fps_div;
|
||||
} else {
|
||||
fps_div = 25; // PAL Default
|
||||
}
|
||||
|
||||
// Convert us to frames
|
||||
l_frames = (((micros % 1000) * fps_div) / 1000) + (micros / 1000 * fps_div);
|
||||
|
||||
return frames_to_timecode(l_frames, hours, minutes, seconds, frames, code);
|
||||
}
|
||||
|
||||
status_t timecode_to_us(int hours, int minutes, int seconds, int frames, bigtime_t * micros, const timecode_info * code = NULL)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
int fps_div;
|
||||
int32 l_frames;
|
||||
|
||||
CALLED();
|
||||
|
||||
if (timecode_to_frames(hours, minutes, seconds, frames, &l_frames, code) == B_OK) {
|
||||
|
||||
if (code) {
|
||||
// We have a valid timecode_info
|
||||
fps_div = code->fps_div;
|
||||
} else {
|
||||
fps_div = 25; // PAL Default
|
||||
}
|
||||
|
||||
*micros = l_frames * 1000 / fps_div;
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t frames_to_timecode(int32 l_frames, int * hours, int * minutes, int * seconds, int * frames, const timecode_info * code = NULL)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return B_ERROR;
|
||||
int fps_div;
|
||||
int total_mins;
|
||||
int32 extra_frames;
|
||||
int32 extra_frames2;
|
||||
|
||||
CALLED();
|
||||
|
||||
if (code) {
|
||||
// We have a valid timecode_info so get the fps_div
|
||||
fps_div = code->fps_div;
|
||||
|
||||
if (code->every_nth > 0) {
|
||||
// Handle Drop Frames format
|
||||
|
||||
total_mins = l_frames / fps_div / 60;
|
||||
|
||||
// "every_nth" minute we gain "drop_frames" "except_nth" minute
|
||||
extra_frames = code->drop_frames*(total_mins/code->every_nth) - code->drop_frames*(total_mins/code->except_nth);
|
||||
l_frames += extra_frames;
|
||||
|
||||
total_mins = l_frames / fps_div / 60;
|
||||
extra_frames2 = code->drop_frames*(total_mins/code->every_nth) - code->drop_frames*(total_mins/code->except_nth);
|
||||
|
||||
// Gaining frames may mean that we gain more frames so we keep adjusting until no more to adjust
|
||||
while (extra_frames != extra_frames2) {
|
||||
l_frames += extra_frames2 - extra_frames;
|
||||
extra_frames = extra_frames2;
|
||||
|
||||
total_mins = l_frames / fps_div / 60;
|
||||
extra_frames2 = code->drop_frames*(total_mins/code->every_nth) - code->drop_frames*(total_mins/code->except_nth);
|
||||
}
|
||||
|
||||
// l_frames should now include all adjusted frames
|
||||
}
|
||||
} else {
|
||||
// no timecode_info so set a default that doesn't use drop frames :-)
|
||||
fps_div = 25; // PAL Default
|
||||
}
|
||||
|
||||
// convert frames to seconds leaving the remainder as frames
|
||||
*seconds = l_frames / fps_div; // DIV
|
||||
*frames = l_frames % fps_div; // MOD
|
||||
|
||||
// Normalise to Hours Minutes Seconds Frames
|
||||
*minutes = *seconds / 60;
|
||||
*seconds = *seconds % 60;
|
||||
|
||||
*hours = *minutes / 60;
|
||||
*minutes = *minutes % 60;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t timecode_to_frames(int hours, int minutes, int seconds, int frames, int32 * l_frames, const timecode_info * code = NULL)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return B_ERROR;
|
||||
int fps_div;
|
||||
int total_mins;
|
||||
int32 extra_frames;
|
||||
|
||||
CALLED();
|
||||
|
||||
if (code) {
|
||||
// We have a valid timecode_info
|
||||
fps_div = code->fps_div;
|
||||
|
||||
total_mins = (hours * 60) + minutes;
|
||||
*l_frames = (total_mins * 60) + seconds;
|
||||
*l_frames = (*l_frames * fps_div) + frames;
|
||||
|
||||
// Adjust "every_nth" minute we lose "drop_frames" "except_nth" minute
|
||||
if (code->every_nth > 0) {
|
||||
extra_frames = code->drop_frames*(total_mins/code->every_nth) - code->drop_frames*(total_mins/code->except_nth);
|
||||
|
||||
*l_frames = *l_frames - extra_frames;
|
||||
}
|
||||
} else {
|
||||
|
||||
*l_frames = (hours * 60) + minutes;
|
||||
*l_frames = (*l_frames * 60) + seconds;
|
||||
*l_frames = (*l_frames * 25) + frames;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t get_timecode_description(timecode_type type, timecode_info * out_timecode)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return B_ERROR;
|
||||
CALLED();
|
||||
|
||||
out_timecode->type = type;
|
||||
strncpy(out_timecode->format,"%.2i:%.2i:%.2i.%.2i",31);
|
||||
out_timecode->every_nth = 0;
|
||||
out_timecode->except_nth = 0;
|
||||
|
||||
switch (type) {
|
||||
case B_TIMECODE_100:
|
||||
strncpy(out_timecode->name,"100 FPS",31);
|
||||
out_timecode->fps_div = 100;
|
||||
break;
|
||||
case B_TIMECODE_75: // CD
|
||||
strncpy(out_timecode->name,"CD",31);
|
||||
out_timecode->fps_div = 75;
|
||||
break;
|
||||
case B_TIMECODE_30: // MIDI
|
||||
strncpy(out_timecode->name,"MIDI",31);
|
||||
out_timecode->fps_div = 30;
|
||||
break;
|
||||
case B_TIMECODE_30_DROP_2: // NTSC
|
||||
strncpy(out_timecode->name,"NTSC",31);
|
||||
out_timecode->fps_div = 30; // This is supposed to be 29.97fps but can be simulated using the drop frame format below
|
||||
out_timecode->drop_frames = 2; // Drop 2 frames
|
||||
out_timecode->every_nth = 1; // every 1 minutes
|
||||
out_timecode->except_nth = 10; // except every 10 minutes
|
||||
break;
|
||||
case B_TIMECODE_30_DROP_4: // Brazil
|
||||
strncpy(out_timecode->name,"NTSC Brazil",31);
|
||||
out_timecode->fps_div = 30;
|
||||
out_timecode->drop_frames = 4; // Drop 4 frames
|
||||
out_timecode->every_nth = 1; // every 1 minutes
|
||||
out_timecode->except_nth = 10; // except every 10 minutes
|
||||
break;
|
||||
case B_TIMECODE_25: // PAL
|
||||
strncpy(out_timecode->name,"PAL",31);
|
||||
out_timecode->fps_div = 25;
|
||||
break;
|
||||
case B_TIMECODE_24: // Film
|
||||
strncpy(out_timecode->name,"FILM",31);
|
||||
out_timecode->fps_div = 24;
|
||||
break;
|
||||
case B_TIMECODE_18: // Super8
|
||||
strncpy(out_timecode->name,"Super 8",31);
|
||||
out_timecode->fps_div = 18;
|
||||
break;
|
||||
default:
|
||||
strncpy(out_timecode->name,"PAL",31);
|
||||
out_timecode->fps_div = 25;
|
||||
break;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t count_timecodes()
|
||||
@ -110,90 +266,26 @@ status_t
|
||||
BTimeCode::SetType(timecode_type type)
|
||||
{
|
||||
CALLED();
|
||||
m_info.type = type;
|
||||
strncpy(m_info.format,"%.2i:%.2i:%.2i:%.2i",31);
|
||||
m_info.every_nth = 0;
|
||||
m_info.except_nth = 0;
|
||||
|
||||
switch (type) {
|
||||
case B_TIMECODE_100:
|
||||
strncpy(m_info.name,"TIMECODE 100",31);
|
||||
m_info.fps_div = 100;
|
||||
break;
|
||||
case B_TIMECODE_75: // CD
|
||||
strncpy(m_info.name,"CD",31);
|
||||
m_info.fps_div = 75;
|
||||
break;
|
||||
case B_TIMECODE_30: // MIDI
|
||||
strncpy(m_info.name,"MIDI",31);
|
||||
m_info.fps_div = 30;
|
||||
break;
|
||||
case B_TIMECODE_30_DROP_2: // NTSC
|
||||
strncpy(m_info.name,"NTSC",31);
|
||||
m_info.fps_div = 30; // This is supposed to be 29.97fps
|
||||
m_info.drop_frames = 2; // Drop 2 frames every minute except every 10 minutes
|
||||
break;
|
||||
case B_TIMECODE_30_DROP_4: // Brazil
|
||||
strncpy(m_info.name,"NTSC Brazil",31);
|
||||
m_info.fps_div = 30;
|
||||
m_info.drop_frames = 4; // Drop 4 frames every minute except every 10 minutes
|
||||
break;
|
||||
case B_TIMECODE_25: // PAL
|
||||
strncpy(m_info.name,"PAL",31);
|
||||
m_info.fps_div = 25;
|
||||
break;
|
||||
case B_TIMECODE_24: // Film
|
||||
strncpy(m_info.name,"FILM",31);
|
||||
m_info.fps_div = 24;
|
||||
break;
|
||||
case B_TIMECODE_18: // Super8
|
||||
strncpy(m_info.name,"Super 8",31);
|
||||
m_info.fps_div = 18;
|
||||
break;
|
||||
default:
|
||||
SetType(B_TIMECODE_25); // PAL default :-)
|
||||
break;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
||||
return get_timecode_description(type, &m_info);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BTimeCode::SetMicroseconds(bigtime_t us)
|
||||
{
|
||||
// Does not handle Drop formats correctly
|
||||
CALLED();
|
||||
|
||||
m_seconds = us / 1000;
|
||||
m_frames = (us % 1000) / m_info.fps_div;
|
||||
|
||||
// Now normalise to Hours Minutes Seconds
|
||||
m_minutes = m_seconds / 60;
|
||||
m_seconds = m_seconds % 60;
|
||||
|
||||
m_hours = m_minutes / 60;
|
||||
m_minutes = m_minutes % 60;
|
||||
us_to_timecode(us, &m_hours, &m_minutes, &m_seconds, &m_frames, &m_info);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BTimeCode::SetLinearFrames(int32 linear_frames)
|
||||
{
|
||||
// Does not handle Drop formats correctly
|
||||
|
||||
CALLED();
|
||||
// First convert frames to seconds leaving the remainder as frames
|
||||
|
||||
m_seconds = linear_frames / m_info.fps_div; // DIV
|
||||
m_frames = linear_frames % m_info.fps_div; // MOD
|
||||
|
||||
// Now normalise to Hours Minutes Seconds
|
||||
m_minutes = m_seconds / 60;
|
||||
m_seconds = m_seconds % 60;
|
||||
|
||||
m_hours = m_minutes / 60;
|
||||
m_minutes = m_minutes % 60;
|
||||
frames_to_timecode(linear_frames, &m_hours, &m_minutes, &m_seconds, &m_frames, &m_info);
|
||||
}
|
||||
|
||||
|
||||
@ -335,30 +427,30 @@ BTimeCode::GetData(int *out_hours,
|
||||
bigtime_t
|
||||
BTimeCode::Microseconds() const
|
||||
{
|
||||
bigtime_t us;
|
||||
|
||||
CALLED();
|
||||
|
||||
bigtime_t us;
|
||||
if (timecode_to_us(m_hours,m_minutes,m_seconds,m_frames, &us, &m_info) == B_OK) {
|
||||
return us;
|
||||
}
|
||||
|
||||
us = m_hours*60+m_minutes;
|
||||
us = us*60+m_seconds;
|
||||
us = us*1000+m_frames*m_info.fps_div;
|
||||
|
||||
return us;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BTimeCode::LinearFrames() const
|
||||
{
|
||||
CALLED();
|
||||
|
||||
int32 linear_frames;
|
||||
|
||||
CALLED();
|
||||
|
||||
linear_frames = (m_hours * 60) + m_minutes;
|
||||
linear_frames = (linear_frames * 60) + m_seconds;
|
||||
linear_frames = (linear_frames * m_info.fps_div) + m_frames;
|
||||
|
||||
return linear_frames;
|
||||
if (timecode_to_frames(m_hours,m_minutes,m_seconds,m_frames,&linear_frames,&m_info) == B_OK) {
|
||||
return linear_frames;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -368,5 +460,3 @@ BTimeCode::GetString(char *str) const
|
||||
CALLED();
|
||||
sprintf(str,m_info.format, m_hours, m_minutes, m_seconds, m_frames);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user