You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Improved Keyframe Performance (#197)
* Refactor of Coorindate and Keyframe optimized for performance (much faster than previously). Also refactored FrameMapper to not use a Keyframe, and to only process frame mapping when needed... speeding up Json loading of project files. * Fixing FrameMapper linear calculation to match existing Keyframe calculation * Fixing Keyframe to pass original unit tests, and correctly calculate the Keyframe repeat fractions and deltas. * Small refactor of time mapped logic in Clip.cpp
This commit is contained in:
213
src/KeyFrame.cpp
213
src/KeyFrame.cpp
@@ -296,17 +296,48 @@ bool Keyframe::IsIncreasing(int index)
|
||||
Process();
|
||||
|
||||
// Is index a valid point?
|
||||
if (index >= 0 && index < Values.size())
|
||||
// Return value
|
||||
return long(round(Values[index].IsIncreasing()));
|
||||
else if (index < 0 && Values.size() > 0)
|
||||
// Return the minimum value
|
||||
return long(round(Values[0].IsIncreasing()));
|
||||
else if (index >= Values.size() && Values.size() > 0)
|
||||
// return the maximum value
|
||||
return long(round(Values[Values.size() - 1].IsIncreasing()));
|
||||
if (index >= 1 && (index + 1) < Values.size()) {
|
||||
int64_t current_value = GetLong(index);
|
||||
int64_t previous_value = 0;
|
||||
int64_t next_value = 0;
|
||||
int64_t previous_repeats = 0;
|
||||
int64_t next_repeats = 0;
|
||||
|
||||
// Loop backwards and look for the next unique value
|
||||
for (vector<Coordinate>::iterator backwards_it = Values.begin() + index; backwards_it != Values.begin(); backwards_it--) {
|
||||
previous_value = long(round((*backwards_it).Y));
|
||||
if (previous_value == current_value) {
|
||||
// Found same value
|
||||
previous_repeats++;
|
||||
} else {
|
||||
// Found non repeating value, no more repeats found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop forwards and look for the next unique value
|
||||
for (vector<Coordinate>::iterator forwards_it = Values.begin() + (index + 1); forwards_it != Values.end(); forwards_it++) {
|
||||
next_value = long(round((*forwards_it).Y));
|
||||
if (next_value == current_value) {
|
||||
// Found same value
|
||||
next_repeats++;
|
||||
} else {
|
||||
// Found non repeating value, no more repeats found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_value < next_value) {
|
||||
// Increasing
|
||||
return true;
|
||||
}
|
||||
else if (current_value >= next_value) {
|
||||
// Decreasing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
// return the default direction of most curves (i.e. increasing is true)
|
||||
// return default true (since most curves increase)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -385,6 +416,7 @@ void Keyframe::SetJsonValue(Json::Value root) {
|
||||
}
|
||||
|
||||
// Get the fraction that represents how many times this value is repeated in the curve
|
||||
// This is depreciated and will be removed soon.
|
||||
Fraction Keyframe::GetRepeatFraction(int64_t index)
|
||||
{
|
||||
// Check if it needs to be processed
|
||||
@@ -392,17 +424,42 @@ Fraction Keyframe::GetRepeatFraction(int64_t index)
|
||||
Process();
|
||||
|
||||
// Is index a valid point?
|
||||
if (index >= 0 && index < Values.size())
|
||||
// Return value
|
||||
return Values[index].Repeat();
|
||||
else if (index < 0 && Values.size() > 0)
|
||||
// Return the minimum value
|
||||
return Values[0].Repeat();
|
||||
else if (index >= Values.size() && Values.size() > 0)
|
||||
// return the maximum value
|
||||
return Values[Values.size() - 1].Repeat();
|
||||
if (index >= 1 && (index + 1) < Values.size()) {
|
||||
int64_t current_value = GetLong(index);
|
||||
int64_t previous_value = 0;
|
||||
int64_t next_value = 0;
|
||||
int64_t previous_repeats = 0;
|
||||
int64_t next_repeats = 0;
|
||||
|
||||
// Loop backwards and look for the next unique value
|
||||
for (vector<Coordinate>::iterator backwards_it = Values.begin() + index; backwards_it != Values.begin(); backwards_it--) {
|
||||
previous_value = long(round((*backwards_it).Y));
|
||||
if (previous_value == current_value) {
|
||||
// Found same value
|
||||
previous_repeats++;
|
||||
} else {
|
||||
// Found non repeating value, no more repeats found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop forwards and look for the next unique value
|
||||
for (vector<Coordinate>::iterator forwards_it = Values.begin() + (index + 1); forwards_it != Values.end(); forwards_it++) {
|
||||
next_value = long(round((*forwards_it).Y));
|
||||
if (next_value == current_value) {
|
||||
// Found same value
|
||||
next_repeats++;
|
||||
} else {
|
||||
// Found non repeating value, no more repeats found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t total_repeats = previous_repeats + next_repeats;
|
||||
return Fraction(previous_repeats, total_repeats);
|
||||
}
|
||||
else
|
||||
// return a blank coordinate (0,0)
|
||||
// return a blank coordinate
|
||||
return Fraction(1,1);
|
||||
}
|
||||
|
||||
@@ -414,17 +471,48 @@ double Keyframe::GetDelta(int64_t index)
|
||||
Process();
|
||||
|
||||
// Is index a valid point?
|
||||
if (index >= 0 && index < Values.size())
|
||||
// Return value
|
||||
return Values[index].Delta();
|
||||
else if (index < 0 && Values.size() > 0)
|
||||
// Return the minimum value
|
||||
return Values[0].Delta();
|
||||
else if (index >= Values.size() && Values.size() > 0)
|
||||
// return the maximum value
|
||||
return Values[Values.size() - 1].Delta();
|
||||
if (index >= 1 && (index + 1) < Values.size()) {
|
||||
int64_t current_value = GetLong(index);
|
||||
int64_t previous_value = 0;
|
||||
int64_t next_value = 0;
|
||||
int64_t previous_repeats = 0;
|
||||
int64_t next_repeats = 0;
|
||||
|
||||
// Loop backwards and look for the next unique value
|
||||
for (vector<Coordinate>::iterator backwards_it = Values.begin() + index; backwards_it != Values.begin(); backwards_it--) {
|
||||
previous_value = long(round((*backwards_it).Y));
|
||||
if (previous_value == current_value) {
|
||||
// Found same value
|
||||
previous_repeats++;
|
||||
} else {
|
||||
// Found non repeating value, no more repeats found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop forwards and look for the next unique value
|
||||
for (vector<Coordinate>::iterator forwards_it = Values.begin() + (index + 1); forwards_it != Values.end(); forwards_it++) {
|
||||
next_value = long(round((*forwards_it).Y));
|
||||
if (next_value == current_value) {
|
||||
// Found same value
|
||||
next_repeats++;
|
||||
} else {
|
||||
// Found non repeating value, no more repeats found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for matching previous value (special case for 1st element)
|
||||
if (current_value == previous_value)
|
||||
previous_value = 0;
|
||||
|
||||
if (previous_repeats == 1)
|
||||
return current_value - previous_value;
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
// return a blank coordinate (0,0)
|
||||
// return a blank coordinate
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@@ -529,7 +617,7 @@ void Keyframe::PrintValues() {
|
||||
|
||||
for (vector<Coordinate>::iterator it = Values.begin() + 1; it != Values.end(); it++) {
|
||||
Coordinate c = *it;
|
||||
cout << long(round(c.X)) << "\t" << c.Y << "\t" << c.IsIncreasing() << "\t" << c.Repeat().num << "\t" << c.Repeat().den << "\t" << c.Delta() << endl;
|
||||
cout << long(round(c.X)) << "\t" << c.Y << "\t" << IsIncreasing(c.X) << "\t" << GetRepeatFraction(c.X).num << "\t" << GetRepeatFraction(c.X).den << "\t" << GetDelta(c.X) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,69 +655,6 @@ void Keyframe::Process() {
|
||||
// process segment p1,p2
|
||||
ProcessSegment(x, p1, p2);
|
||||
}
|
||||
|
||||
// Loop through each Value, and set the direction of the coordinate. This is used
|
||||
// when time mapping, to determine what direction the audio waveforms play.
|
||||
bool increasing = true;
|
||||
int repeat_count = 1;
|
||||
int64_t last_value = 0;
|
||||
for (vector<Coordinate>::iterator it = Values.begin() + 1; it != Values.end(); it++) {
|
||||
int current_value = long(round((*it).Y));
|
||||
int64_t next_value = long(round((*it).Y));
|
||||
int64_t prev_value = long(round((*it).Y));
|
||||
if (it + 1 != Values.end())
|
||||
next_value = long(round((*(it + 1)).Y));
|
||||
if (it - 1 >= Values.begin())
|
||||
prev_value = long(round((*(it - 1)).Y));
|
||||
|
||||
// Loop forward and look for the next unique value (to determine direction)
|
||||
for (vector<Coordinate>::iterator direction_it = it + 1; direction_it != Values.end(); direction_it++) {
|
||||
int64_t next = long(round((*direction_it).Y));
|
||||
|
||||
// Detect direction
|
||||
if (current_value < next)
|
||||
{
|
||||
increasing = true;
|
||||
break;
|
||||
}
|
||||
else if (current_value > next)
|
||||
{
|
||||
increasing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set direction
|
||||
(*it).IsIncreasing(increasing);
|
||||
|
||||
// Detect repeated Y value
|
||||
if (current_value == last_value)
|
||||
// repeated, so increment count
|
||||
repeat_count++;
|
||||
else
|
||||
// reset repeat counter
|
||||
repeat_count = 1;
|
||||
|
||||
// Detect how many 'more' times it's repeated
|
||||
int additional_repeats = 0;
|
||||
for (vector<Coordinate>::iterator repeat_it = it + 1; repeat_it != Values.end(); repeat_it++) {
|
||||
int64_t next = long(round((*repeat_it).Y));
|
||||
if (next == current_value)
|
||||
// repeated, so increment count
|
||||
additional_repeats++;
|
||||
else
|
||||
break; // stop looping
|
||||
}
|
||||
|
||||
// Set repeat fraction
|
||||
(*it).Repeat(Fraction(repeat_count, repeat_count + additional_repeats));
|
||||
|
||||
// Set delta (i.e. different from previous unique Y value)
|
||||
(*it).Delta(current_value - last_value);
|
||||
|
||||
// track the last value
|
||||
last_value = current_value;
|
||||
}
|
||||
}
|
||||
|
||||
// reset flag
|
||||
|
||||
Reference in New Issue
Block a user