Changes most of the VFR handling to ints and clean up stuff
Originally committed to SVN as r96.
This commit is contained in:
parent
cbc7b57669
commit
24a7e9ba91
5 changed files with 165 additions and 352 deletions
|
@ -68,7 +68,7 @@ void AssTransformFramerateFilter::Init() {
|
||||||
void AssTransformFramerateFilter::ProcessSubs(AssFile *subs) {
|
void AssTransformFramerateFilter::ProcessSubs(AssFile *subs) {
|
||||||
// Transform frame rate
|
// Transform frame rate
|
||||||
if (Input->loaded && Output->loaded) {
|
if (Input->loaded && Output->loaded) {
|
||||||
if (Output->FrameRateType == VFR || Output->AverageFrameRate != Input->AverageFrameRate) {
|
if (Output->FrameRateType == VFR || Output->GetAverage() != Input->GetAverage()) {
|
||||||
TransformFrameRate(subs);
|
TransformFrameRate(subs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ wxWindow *AssTransformFramerateFilter::GetConfigDialogWindow(wxWindow *parent) {
|
||||||
wxSizer *InputSizer = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer *InputSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
wxString initialInput;
|
wxString initialInput;
|
||||||
wxButton *FromVideo = new wxButton(base,Get_Input_From_Video,_("From Video"));
|
wxButton *FromVideo = new wxButton(base,Get_Input_From_Video,_("From Video"));
|
||||||
if (VFR_Input.loaded) initialInput = wxString::Format(_T("%2.3f"),VFR_Input.AverageFrameRate);
|
if (VFR_Input.loaded) initialInput = wxString::Format(_T("%2.3f"),VFR_Input.GetAverage());
|
||||||
else {
|
else {
|
||||||
initialInput = _T("23.976");
|
initialInput = _T("23.976");
|
||||||
FromVideo->Enable(false);
|
FromVideo->Enable(false);
|
||||||
|
|
|
@ -259,7 +259,7 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
|
||||||
MenuBar->Enable(Menu_Video_AR_Default,state);
|
MenuBar->Enable(Menu_Video_AR_Default,state);
|
||||||
MenuBar->Enable(Menu_Video_AR_Full,state);
|
MenuBar->Enable(Menu_Video_AR_Full,state);
|
||||||
MenuBar->Enable(Menu_Video_AR_Wide,state);
|
MenuBar->Enable(Menu_Video_AR_Wide,state);
|
||||||
MenuBar->Enable(Menu_File_Close_VFR,VFR_Output.loaded && VFR_Output.vfr);
|
MenuBar->Enable(Menu_File_Close_VFR,VFR_Output.loaded && VFR_Output.FrameRateType == VFR); //fix me, wrong?
|
||||||
|
|
||||||
// Set AR radio
|
// Set AR radio
|
||||||
if (videoBox->videoDisplay->arType == 0) MenuBar->Check(Menu_Video_AR_Default,true);
|
if (videoBox->videoDisplay->arType == 0) MenuBar->Check(Menu_Video_AR_Default,true);
|
||||||
|
|
427
core/vfr.cpp
427
core/vfr.cpp
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -37,175 +37,36 @@
|
||||||
///////////
|
///////////
|
||||||
// Headers
|
// Headers
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
|
#include "utils.h"
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////// V1 //////////////////////
|
|
||||||
//////////////////
|
|
||||||
// V1 Constructor
|
|
||||||
VFR_v1::VFR_v1 () {
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////
|
|
||||||
// V1 Destructor
|
|
||||||
VFR_v1::~VFR_v1 () {
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////
|
|
||||||
// V1 Clear function
|
|
||||||
void VFR_v1::Clear () {
|
|
||||||
Range.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////
|
|
||||||
// V1 Add range
|
|
||||||
void VFR_v1::AddRange(int start,int end,double fps,bool isdefault) {
|
|
||||||
VFR_v1_Range newRange;
|
|
||||||
newRange.start = start;
|
|
||||||
newRange.end = end;
|
|
||||||
newRange.fps = fps;
|
|
||||||
newRange.isDefault = isdefault;
|
|
||||||
if (isdefault) DefaultFPS = fps;
|
|
||||||
Range.push_back(newRange);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// V1 Get frame at time
|
|
||||||
int VFR_v1::GetFrameAtTime(int _ms) {
|
|
||||||
double ms = _ms;
|
|
||||||
double curms = 0;
|
|
||||||
double prevms = 0;
|
|
||||||
int curframe = 0;
|
|
||||||
double fpms;
|
|
||||||
for (std::list<VFR_v1_Range>::iterator cur=Range.begin();cur!=Range.end();cur++) {
|
|
||||||
fpms = (*cur).fps/1000.0;
|
|
||||||
curms += double((*cur).end - (*cur).start + 1) / fpms;
|
|
||||||
if (curms > ms) {
|
|
||||||
//return curframe + floor((ms - prevms) * fpms + 0.5);
|
|
||||||
//return curframe + floor((ms - prevms) * fpms);
|
|
||||||
double msValue = (ms - prevms) * fpms;
|
|
||||||
double floorValue = ceil(msValue);
|
|
||||||
int final = curframe + floorValue;
|
|
||||||
return final;
|
|
||||||
}
|
|
||||||
curframe = (*cur).end+1;
|
|
||||||
prevms = curms;
|
|
||||||
}
|
|
||||||
//return curframe + floor((ms - prevms) * DefaultFPS/1000.0 + 0.5);
|
|
||||||
return curframe + floor((ms - prevms) * DefaultFPS/1000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// V1 Get time at frame
|
|
||||||
int VFR_v1::GetTimeAtFrame(int frame) {
|
|
||||||
double acum = 0;
|
|
||||||
int last = 0;
|
|
||||||
for (std::list<VFR_v1_Range>::iterator cur=Range.begin();cur!=Range.end();cur++) {
|
|
||||||
if (frame <= (*cur).end) {
|
|
||||||
acum += double(frame - (*cur).start) / (*cur).fps;
|
|
||||||
//return floor(acum*1000.0+0.5);
|
|
||||||
return floor(acum*1000.0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
acum += double((*cur).end - (*cur).start + 1) / (*cur).fps;
|
|
||||||
last = (*cur).end+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acum += double(frame - last) / DefaultFPS;
|
|
||||||
//return floor(acum*1000.0+0.5);
|
|
||||||
return floor(acum*1000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
|
||||||
// V1 Get Average
|
|
||||||
double VFR_v1::GetAverage () {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////// V2 //////////////////////
|
|
||||||
//////////////////
|
|
||||||
// V2 Constructor
|
|
||||||
VFR_v2::VFR_v2 () {
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////
|
|
||||||
// V2 Destructor
|
|
||||||
VFR_v2::~VFR_v2 () {
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// V2 Clear function
|
// V2 Clear function
|
||||||
void VFR_v2::Clear () {
|
void FrameRate::Clear () {
|
||||||
Frame.clear();
|
Frame.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// V2 Add frame
|
// V2 Add frame
|
||||||
void VFR_v2::AddFrame(double fps) {
|
void FrameRate::AddFrame(int ms) {
|
||||||
Frame.push_back(fps);
|
Frame.push_back(ms);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// V2 Get frame at time
|
|
||||||
int VFR_v2::GetFrameAtTime(int ms) {
|
|
||||||
// Binary search
|
|
||||||
size_t start = 0;
|
|
||||||
size_t end = Frame.size()-1;
|
|
||||||
size_t cur;
|
|
||||||
bool largerEqual;
|
|
||||||
while (start <= end) {
|
|
||||||
cur = (start+end)>>1;
|
|
||||||
largerEqual = floor(Frame[cur]) + 0.5 >= ms;
|
|
||||||
|
|
||||||
// Found
|
|
||||||
if (largerEqual && (cur == 0 || floor(Frame[cur-1]) + 0.5 < ms)) return cur;
|
|
||||||
|
|
||||||
// Not found
|
|
||||||
if (largerEqual) end = cur-1;
|
|
||||||
else start = cur+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Couldn't find
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// V2 Get time at frame
|
|
||||||
int VFR_v2::GetTimeAtFrame(int frame) {
|
|
||||||
if (Frame.size() > (size_t) frame) return floor(Frame.at(frame));
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// V2 Get Average
|
// V2 Get Average
|
||||||
double VFR_v2::GetAverage () {
|
void FrameRate::CalcAverage() {
|
||||||
double last = 0.0;
|
double last = 0.0;
|
||||||
int frames = 0;
|
int frames = 0;
|
||||||
for (std::vector<double>::iterator cur=Frame.begin();cur!=Frame.end();cur++) {
|
for (std::vector<int>::iterator cur=Frame.begin();cur!=Frame.end();cur++) {
|
||||||
last = *cur;
|
last = *cur;
|
||||||
frames++;
|
frames++;
|
||||||
}
|
}
|
||||||
return double(frames)*1000.0/last;
|
|
||||||
|
AverageFrameRate = double(frames)*1000.0/last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,19 +74,14 @@ double VFR_v2::GetAverage () {
|
||||||
///////////////
|
///////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
FrameRate::FrameRate() {
|
FrameRate::FrameRate() {
|
||||||
loaded = false;
|
Unload();
|
||||||
FrameRateType = NONE;
|
|
||||||
AverageFrameRate = 0;
|
|
||||||
vfr = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
// Destructor
|
// Destructor
|
||||||
FrameRate::~FrameRate() {
|
FrameRate::~FrameRate() {
|
||||||
if (vfr) delete vfr;
|
Clear();
|
||||||
vfr = NULL;
|
|
||||||
loaded = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,13 +90,33 @@ FrameRate::~FrameRate() {
|
||||||
int FrameRate::GetFrameAtTime(int ms) {
|
int FrameRate::GetFrameAtTime(int ms) {
|
||||||
if (!loaded) return -1;
|
if (!loaded) return -1;
|
||||||
|
|
||||||
|
ms = MAX(ms,0); //fix me, unsafe for CorrectFrame... for frame 0?
|
||||||
|
|
||||||
if (FrameRateType == CFR) {
|
if (FrameRateType == CFR) {
|
||||||
//return int((double(ms)/1000.0) * AverageFrameRate + 0.5);
|
|
||||||
return floor((double(ms)/1000.0) * AverageFrameRate);
|
return floor((double(ms)/1000.0) * AverageFrameRate);
|
||||||
}
|
}
|
||||||
else if (FrameRateType == VFR) {
|
else if (FrameRateType == VFR) {
|
||||||
if (vfr) return vfr->GetFrameAtTime(ms);
|
if (ms < floor(last_time)) {
|
||||||
else throw _T("VFR error");
|
// Binary search
|
||||||
|
size_t start = 0;
|
||||||
|
size_t end = last_frame;
|
||||||
|
size_t cur;
|
||||||
|
bool largerEqual;
|
||||||
|
while (start <= end) {
|
||||||
|
cur = (start+end)>>1;
|
||||||
|
largerEqual = Frame[cur] >= ms;
|
||||||
|
|
||||||
|
// Found
|
||||||
|
if (largerEqual && (cur == 0 || Frame[cur-1] < ms))
|
||||||
|
return cur;
|
||||||
|
|
||||||
|
// Not found
|
||||||
|
if (largerEqual) end = cur-1;
|
||||||
|
else start = cur+1;
|
||||||
|
}
|
||||||
|
} else if (assumefps != 0) {
|
||||||
|
return last_frame + floor((ms-last_time) * assumefps / 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -251,13 +127,15 @@ int FrameRate::GetFrameAtTime(int ms) {
|
||||||
int FrameRate::GetTimeAtFrame(int frame) {
|
int FrameRate::GetTimeAtFrame(int frame) {
|
||||||
if (!loaded) return -1;
|
if (!loaded) return -1;
|
||||||
|
|
||||||
|
wxASSERT(frame >= 0);
|
||||||
|
|
||||||
if (FrameRateType == CFR) {
|
if (FrameRateType == CFR) {
|
||||||
//return int(double(frame) / AverageFrameRate * 1000 + 0.5);
|
|
||||||
return floor(double(frame) / AverageFrameRate * 1000);
|
return floor(double(frame) / AverageFrameRate * 1000);
|
||||||
}
|
} else if (FrameRateType == VFR) {
|
||||||
else if (FrameRateType == VFR) {
|
if (frame < last_frame)
|
||||||
if (vfr) return vfr->GetTimeAtFrame(frame);
|
return Frame.at(frame);
|
||||||
else throw _T("VFR error");
|
else if (assumefps != 0)
|
||||||
|
return floor(last_time + (frame-last_frame+1) / assumefps * 1000);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -277,123 +155,112 @@ void FrameRate::Load(wxString filename) {
|
||||||
file.open(filename.mb_str(wxConvLocal));
|
file.open(filename.mb_str(wxConvLocal));
|
||||||
if (!file.is_open()) throw _T("Could not open file.");
|
if (!file.is_open()) throw _T("Could not open file.");
|
||||||
|
|
||||||
|
//fix me, will b0rk if loading the file fails
|
||||||
|
Unload();
|
||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
char buffer[65536];
|
char buffer[65536];
|
||||||
file.getline(buffer,65536);
|
file.getline(buffer,65536);
|
||||||
wxString header(buffer,wxConvUTF8);
|
wxString header(buffer,wxConvUTF8);
|
||||||
header.LowerCase();
|
|
||||||
header.Trim(true);
|
|
||||||
header.Trim(false);
|
|
||||||
bool forceV1 = false;
|
|
||||||
if (header.Left(17) != _T("# timecode format")) {
|
|
||||||
if (header.Left(6) == _T("assume")) forceV1 = true;
|
|
||||||
else {
|
|
||||||
file.close();
|
|
||||||
throw _T("Unknown file format.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// V1
|
// V1, code converted from avcvfr9
|
||||||
if (forceV1 || header.Mid(18,2) == _T("v1")) {
|
if (header == _T("# timecode format v1")) {
|
||||||
// Read "assume" line
|
//locate the default fps line
|
||||||
wxString curLine;
|
|
||||||
if (!forceV1) {
|
|
||||||
file.getline(buffer,65536);
|
|
||||||
wxString tmp(buffer,wxConvUTF8);
|
|
||||||
curLine = tmp;
|
|
||||||
}
|
|
||||||
else curLine = header;
|
|
||||||
|
|
||||||
// Process "assume" line
|
|
||||||
curLine.LowerCase();
|
|
||||||
curLine.Trim(true);
|
|
||||||
curLine.Trim(false);
|
|
||||||
if (curLine.Left(6) != _T("assume")) {
|
|
||||||
file.close();
|
|
||||||
throw _T("Error parsing file.");
|
|
||||||
}
|
|
||||||
double temp;
|
|
||||||
curLine.Mid(6).ToDouble(&temp);
|
|
||||||
double assume = GetTrueRate(temp);
|
|
||||||
|
|
||||||
// Assigns new VFR file
|
|
||||||
if (vfr) delete vfr;
|
|
||||||
VFR_v1 *workvfr = new VFR_v1;
|
|
||||||
vfr = workvfr;
|
|
||||||
FrameRateType = VFR;
|
|
||||||
|
|
||||||
// Reads body
|
|
||||||
wxString curline;
|
|
||||||
size_t pos;
|
|
||||||
size_t end;
|
|
||||||
int startf = -1;
|
|
||||||
int endf = -1;
|
|
||||||
double fps;
|
|
||||||
//int n = 0;
|
|
||||||
while (!file.eof()) {
|
while (!file.eof()) {
|
||||||
file.getline(buffer,65536);
|
file.getline(buffer,65536);
|
||||||
wxString wxbuffer (buffer,wxConvUTF8);
|
wxString curLine(buffer,wxConvUTF8);
|
||||||
curline = wxbuffer;
|
|
||||||
if (curline.IsEmpty()) continue;
|
|
||||||
wxString temp;
|
|
||||||
|
|
||||||
// Get start frame
|
//skip empty lines and comments
|
||||||
pos = 0;
|
if (curLine == _T("") || curLine.Left(1) == _T("#"))
|
||||||
end = curline.find(_T(","),pos);
|
continue;
|
||||||
//startf = atoi(curline.substr(pos,end-pos).c_str());
|
//fix me? should be case insensitive comparison
|
||||||
temp = curline.substr(pos,end-pos);
|
else if (curLine.Left(7) != _T("Assume "))
|
||||||
long templ;
|
throw _T("Encountered data before 'Assume <fps>' line");
|
||||||
temp.ToLong(&templ);
|
else {
|
||||||
startf = templ;
|
curLine.Mid(6).ToDouble(&assumefps);
|
||||||
|
break;
|
||||||
// Fill default's blank
|
|
||||||
if (endf != startf-1) workvfr->AddRange(endf+1,startf-1,assume,true);
|
|
||||||
|
|
||||||
// Get end frame
|
|
||||||
pos = end+1;
|
|
||||||
end = curline.find(_T(","),pos);
|
|
||||||
//endf = atoi(curline.substr(pos,end-pos).c_str());
|
|
||||||
temp = curline.substr(pos,end-pos);
|
|
||||||
temp.ToLong(&templ);
|
|
||||||
endf = templ;
|
|
||||||
|
|
||||||
// Get fps
|
|
||||||
pos = end+1;
|
|
||||||
end = curline.find(_T(","),pos);
|
|
||||||
//fps = atof(curline.substr(pos,end-pos).c_str());
|
|
||||||
temp = curline.substr(pos,end-pos);
|
|
||||||
temp.ToDouble(&fps);
|
|
||||||
fps = GetTrueRate(fps);
|
|
||||||
|
|
||||||
//n++;
|
|
||||||
//wxLogMessage(wxString::Format(_T("Range %i added: %i -> %i at %f fps"),n,startf,endf,fps));
|
|
||||||
workvfr->AddRange(startf,endf,fps,false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//read and expand all timecodes to v2
|
||||||
|
wxString curline;
|
||||||
|
|
||||||
|
double currenttime = 0;
|
||||||
|
int lposition = -1;
|
||||||
|
|
||||||
|
long lstart;
|
||||||
|
long lend;
|
||||||
|
double lfps;
|
||||||
|
|
||||||
|
while (!file.eof()) {
|
||||||
|
file.getline(buffer,65536);
|
||||||
|
wxString curLine(buffer,wxConvUTF8);
|
||||||
|
|
||||||
|
//skip empty lines and comments
|
||||||
|
if (curLine == _T("") || curLine.Left(1) == _T("#"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wxString tmp = curLine.AfterFirst(_T(','));
|
||||||
|
wxString temp = curLine.BeforeFirst(_T(','));
|
||||||
|
temp.ToLong(&lstart);
|
||||||
|
temp = tmp.BeforeLast(_T(','));
|
||||||
|
temp.ToLong(&lend);
|
||||||
|
temp = tmp.AfterLast(_T(','));
|
||||||
|
temp.ToDouble(&lfps);
|
||||||
|
|
||||||
|
for (int i = 0; i <= lstart - lposition - 2; i++)
|
||||||
|
AddFrame(floor(currenttime+(i*1000) / assumefps));
|
||||||
|
|
||||||
|
currenttime += ((lstart - lposition - 1)*1000) / assumefps;
|
||||||
|
|
||||||
|
for (int i = 0; i <= lend - lstart; i++)
|
||||||
|
AddFrame(floor(currenttime+(i*1000) / lfps));
|
||||||
|
|
||||||
|
currenttime += ((lend - lstart + 1)*1000) / lfps;
|
||||||
|
|
||||||
|
lposition = lend;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_time = currenttime;
|
||||||
|
last_frame = Frame.size();
|
||||||
|
}
|
||||||
|
|
||||||
// V2
|
// V2
|
||||||
else if (header.Mid(18,2) == _T("v2")) {
|
else if (header == _T("# timecode format v2")) {
|
||||||
// Assigns new VFR file
|
// Assigns new VFR file
|
||||||
if (vfr) delete vfr;
|
|
||||||
VFR_v2 *workvfr = new VFR_v2;
|
|
||||||
vfr = workvfr;
|
|
||||||
FrameRateType = VFR;
|
FrameRateType = VFR;
|
||||||
|
|
||||||
|
long lftime = -1;
|
||||||
|
long cftime = 0;
|
||||||
|
last_frame = 0;
|
||||||
|
|
||||||
// Reads body
|
// Reads body
|
||||||
while (!file.eof()) {
|
while (!file.eof()) {
|
||||||
file.getline (buffer,65536);
|
file.getline (buffer,65536);
|
||||||
if (strcmp(buffer,"") == 0) continue;
|
wxString curLine(buffer,wxConvUTF8);
|
||||||
workvfr->AddFrame(atof(buffer));
|
|
||||||
|
//skip empty lines and comments
|
||||||
|
if (curLine == _T("") || curLine.Left(1) == _T("#"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wxString tmp = curLine.BeforeFirst(_T('.'));
|
||||||
|
tmp.ToLong(&cftime);
|
||||||
|
wxASSERT(lftime < cftime);
|
||||||
|
AddFrame(cftime);
|
||||||
|
lftime = cftime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sorts vector
|
last_time = cftime;
|
||||||
sort(workvfr->Frame.begin(),workvfr->Frame.end());
|
last_frame = Frame.size();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unknown
|
// Unknown
|
||||||
else {
|
else {
|
||||||
file.close();
|
file.close();
|
||||||
throw _T("Unsupported file version.");
|
Unload();
|
||||||
|
throw _T("Unknown file format.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run test
|
// Run test
|
||||||
|
@ -402,9 +269,9 @@ void FrameRate::Load(wxString filename) {
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
int res;
|
int res;
|
||||||
for (int i=0;i<1000;i++) {
|
for (int i=0;i<1000;i++) {
|
||||||
res = vfr->GetFrameAtTime(vfr->GetTimeAtFrame(i));
|
res = GetFrameAtTime(GetTimeAtFrame(i));
|
||||||
if (res != i) {
|
if (res != i) {
|
||||||
wxLogMessage(wxString::Format(_T("Expected %i but got %i (%i)"),i,res,vfr->GetTimeAtFrame(i)));
|
wxLogMessage(wxString::Format(_T("Expected %i but got %i (%i)"),i,res,GetTimeAtFrame(i)));
|
||||||
fail++;
|
fail++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,7 +283,8 @@ void FrameRate::Load(wxString filename) {
|
||||||
file.close();
|
file.close();
|
||||||
loaded = true;
|
loaded = true;
|
||||||
vfrFile = filename;
|
vfrFile = filename;
|
||||||
AverageFrameRate = vfr->GetAverage();
|
FrameRateType = VFR;
|
||||||
|
CalcAverage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -425,8 +293,10 @@ void FrameRate::Load(wxString filename) {
|
||||||
void FrameRate::Unload () {
|
void FrameRate::Unload () {
|
||||||
FrameRateType = NONE;
|
FrameRateType = NONE;
|
||||||
AverageFrameRate = 0;
|
AverageFrameRate = 0;
|
||||||
if (vfr) delete vfr;
|
assumefps = 0;
|
||||||
vfr = NULL;
|
last_time = 0;
|
||||||
|
last_frame = 0;
|
||||||
|
Clear();
|
||||||
loaded = false;
|
loaded = false;
|
||||||
vfrFile = _T("");
|
vfrFile = _T("");
|
||||||
}
|
}
|
||||||
|
@ -437,30 +307,17 @@ void FrameRate::Unload () {
|
||||||
void FrameRate::SetCFR(double fps,bool ifunset) {
|
void FrameRate::SetCFR(double fps,bool ifunset) {
|
||||||
if (loaded && ifunset) return;
|
if (loaded && ifunset) return;
|
||||||
|
|
||||||
if (vfr) delete vfr;
|
Unload();
|
||||||
vfr = NULL;
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
vfrFile = _T("");
|
vfrFile = _T("");
|
||||||
FrameRateType = CFR;
|
FrameRateType = CFR;
|
||||||
AverageFrameRate = fps;
|
AverageFrameRate = fps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////
|
|
||||||
// Improve precision of fps
|
|
||||||
double FrameRate::GetTrueRate(double rate) {
|
|
||||||
//if (rate == 23.976) {
|
|
||||||
// rate = 24.0 / 1.001;
|
|
||||||
//}
|
|
||||||
//if (rate == 29.97) {
|
|
||||||
// rate = 30.0 / 1.001;
|
|
||||||
//}
|
|
||||||
return rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// Get correct frame at time
|
// Get correct frame at time
|
||||||
|
// returns the adjusted time for end frames when start=false
|
||||||
|
// otherwise for start frames
|
||||||
int FrameRate::CorrectFrameAtTime(int ms,bool start) {
|
int FrameRate::CorrectFrameAtTime(int ms,bool start) {
|
||||||
int frame;
|
int frame;
|
||||||
|
|
||||||
|
@ -476,10 +333,8 @@ int FrameRate::CorrectFrameAtTime(int ms,bool start) {
|
||||||
|
|
||||||
// VFR
|
// VFR
|
||||||
else {
|
else {
|
||||||
int delta = 0;
|
frame = GetFrameAtTime(ms);
|
||||||
if (!start) delta = -1;
|
if (!start) frame--;
|
||||||
//frame = GetFrameAtTime(ms-delta)+delta;
|
|
||||||
frame = GetFrameAtTime(ms)+delta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
|
@ -488,16 +343,12 @@ int FrameRate::CorrectFrameAtTime(int ms,bool start) {
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// Get correct time at frame
|
// Get correct time at frame
|
||||||
|
// compensates and returns an end time when start=false
|
||||||
int FrameRate::CorrectTimeAtFrame(int frame,bool start) {
|
int FrameRate::CorrectTimeAtFrame(int frame,bool start) {
|
||||||
//int startDelta = 0;
|
if (start)
|
||||||
//if (start) startDelta = -1;
|
return GetTimeAtFrame(frame);
|
||||||
//int delta = 1;
|
else
|
||||||
//if (FrameRateType == VFR) delta = 1;
|
return GetTimeAtFrame(frame+1);
|
||||||
//return GetTimeAtFrame(frame+delta+startDelta)+startDelta;
|
|
||||||
|
|
||||||
int delta = 0;
|
|
||||||
if (!start) delta = 1;
|
|
||||||
return GetTimeAtFrame(frame+delta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
76
core/vfr.h
76
core/vfr.h
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -33,6 +33,10 @@
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
// Contact: mailto:zeratul@cellosoft.com
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// The FrameRate class stores all times internally as ints in ms precision
|
||||||
|
// V1 timecodes are partially expanded to v2 up until their last override line
|
||||||
|
// V2 timecodes are kept as is and if n frames beyond the end is requested a
|
||||||
|
// time is calculated by last_time+n/average_fps
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -52,71 +56,28 @@ enum ASS_FrameRateType {
|
||||||
VFR
|
VFR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// Base abstract class
|
|
||||||
class VFR_Base {
|
|
||||||
public:
|
|
||||||
virtual int GetFrameAtTime(int ms)=0;
|
|
||||||
virtual int GetTimeAtFrame(int frame)=0;
|
|
||||||
virtual double GetAverage()=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// V1 Timecodes Classes
|
|
||||||
class VFR_v1_Range {
|
|
||||||
public:
|
|
||||||
bool isDefault;
|
|
||||||
int start;
|
|
||||||
int end;
|
|
||||||
double fps;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VFR_v1 : public VFR_Base {
|
|
||||||
private:
|
|
||||||
std::list<VFR_v1_Range> Range;
|
|
||||||
double DefaultFPS;
|
|
||||||
|
|
||||||
public:
|
|
||||||
VFR_v1();
|
|
||||||
~VFR_v1();
|
|
||||||
void Clear();
|
|
||||||
void AddRange(int start,int end,double fps,bool isdefault);
|
|
||||||
int GetFrameAtTime(int ms);
|
|
||||||
int GetTimeAtFrame(int frame);
|
|
||||||
double GetAverage();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// V2 Timecodes Class
|
|
||||||
class VFR_v2 : public VFR_Base {
|
|
||||||
public:
|
|
||||||
std::vector<double> Frame;
|
|
||||||
|
|
||||||
VFR_v2();
|
|
||||||
~VFR_v2();
|
|
||||||
void Clear();
|
|
||||||
void AddFrame(double fps);
|
|
||||||
int GetFrameAtTime(int ms);
|
|
||||||
int GetTimeAtFrame(int frame);
|
|
||||||
double GetAverage();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// Framerate class
|
// Framerate class
|
||||||
class FrameRate {
|
class FrameRate {
|
||||||
|
private:
|
||||||
|
double last_time;
|
||||||
|
int last_frame;
|
||||||
|
std::vector<int> Frame;
|
||||||
|
double assumefps;
|
||||||
|
double AverageFrameRate;
|
||||||
|
|
||||||
|
void AddFrame(int ms);
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
void CalcAverage();
|
||||||
public:
|
public:
|
||||||
FrameRate();
|
FrameRate();
|
||||||
~FrameRate();
|
~FrameRate();
|
||||||
|
|
||||||
|
|
||||||
wxString vfrFile;
|
wxString vfrFile;
|
||||||
bool loaded;
|
bool loaded;
|
||||||
ASS_FrameRateType FrameRateType;
|
ASS_FrameRateType FrameRateType;
|
||||||
double AverageFrameRate;
|
|
||||||
VFR_Base *vfr;
|
|
||||||
|
|
||||||
void SetCFR(double fps,bool ifunset=false);
|
void SetCFR(double fps,bool ifunset=false);
|
||||||
void Load(wxString file);
|
void Load(wxString file);
|
||||||
|
@ -125,7 +86,8 @@ public:
|
||||||
int GetTimeAtFrame(int frame);
|
int GetTimeAtFrame(int frame);
|
||||||
int CorrectFrameAtTime(int ms,bool start);
|
int CorrectFrameAtTime(int ms,bool start);
|
||||||
int CorrectTimeAtFrame(int frame,bool start);
|
int CorrectTimeAtFrame(int frame,bool start);
|
||||||
double GetTrueRate(double fps);
|
|
||||||
|
double GetAverage() { return AverageFrameRate; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ void VideoDisplay::SetVideo(const wxString &filename) {
|
||||||
if (filename.IsEmpty()) {
|
if (filename.IsEmpty()) {
|
||||||
delete provider;
|
delete provider;
|
||||||
provider = NULL;
|
provider = NULL;
|
||||||
if (VFR_Output.vfr == NULL) VFR_Output.Unload();
|
if (VFR_Output.FrameRateType == VFR) VFR_Output.Unload();
|
||||||
VFR_Input.Unload();
|
VFR_Input.Unload();
|
||||||
|
|
||||||
videoName = _T("");
|
videoName = _T("");
|
||||||
|
|
Loading…
Reference in a new issue