Fix minor error in vfr.cpp: lines which end exactly on a frame's start time are not visible on that frame.

Originally committed to SVN as r4649.
This commit is contained in:
Thomas Goyne 2010-06-30 06:29:27 +00:00
parent be1ed9e672
commit 65d40e2408
1 changed files with 23 additions and 41 deletions

View File

@ -268,60 +268,42 @@ void FrameRate::SetVFR(std::vector<int> newTimes) {
/// @brief Gets frame number at time /// @brief Gets frame number at time
/// @param ms /// @param ms
/// @param useceil /// @param start
/// @return /// @return
int FrameRate::PFrameAtTime(int ms,bool useceil) const { int FrameRate::PFrameAtTime(int ms,bool start) const {
// Check if it's loaded
if (!loaded) return -1; if (!loaded) return -1;
// Get for constant frame rate // Lines begin on the first frame whose start time is greater than or equal
// to the line's start time, and are last visible on the last frame whose
// start time is less than (note: not equal) the line's end time
if (FrameRateType == CFR || Frame.size() == 0 || ms < 0) { if (FrameRateType == CFR || Frame.size() == 0 || ms < 0) {
double value = double(ms) * AverageFrameRate / 1000.0; double value = double(ms) * AverageFrameRate / 1000.;
if (useceil) return (int)ceil(value); if (start) return (int)ceil(value);
else return (int)floor(value); else return (int)floor(value - .0001);
} }
// Get for variable frame rate
else if (FrameRateType == VFR) { else if (FrameRateType == VFR) {
// Get last
double trueLast;
//if (useceil) trueLast = ceil(last_time);
//else trueLast = floor(last_time);
trueLast = Frame[Frame.size()-1];
// Inside VFR range // Inside VFR range
if (ms <= trueLast) { if (ms <= Frame.back()) {
// Prepare binary search int frame = std::distance(Frame.begin(), std::lower_bound(Frame.begin(), Frame.end(), ms));
size_t start = 0; if (!start && frame > 0) {
size_t end = last_frame; // In the end case, frame is the first frame in which the line
size_t cur; // is no longer visible, so subtract 1
bool largerEqual;
// Do binary search // Don't need to worry about the equal case here as lower_bound
while (start <= end) { // finds the entry >= ms
// Current frame being checked
cur = (start+end)>>1;
// Is it larger or equal to searched time? // The frame > 0 check isn't actually correct -- the frame
largerEqual = Frame[cur] >= ms; // ending at time 0 should be -1, but parts of the program
// (like PTimeAtFrame below) assume that frames are positive
// If it is, is the previous smaller? --frame;
// If so, this is the frame we're looking for
if (largerEqual && (cur == 0 || Frame[cur-1] < ms)) {
if (useceil) return (int)cur;
return (int)(cur)-1;
} }
return frame;
// Not found, continue search
if (largerEqual) end = cur-1;
else start = cur+1;
} }
}
// After VFR range // After VFR range
else { else {
if (useceil) return (int)(last_frame + ceil((ms-last_time) * AverageFrameRate / 1000)); if (start) return (int)(last_frame + ceil((ms-last_time) * AverageFrameRate / 1000.));
else return (int)(last_frame + floor((ms-last_time) * AverageFrameRate / 1000)); else return (int)(last_frame + floor((ms-last_time - .0001) * AverageFrameRate / 1000.));
} }
} }
return -1; return -1;