Skip to content

Commit 4676f0d

Browse files
authored
Fix parsing and logic errors
Video clips with varying lengths are no longer valid in ReplaceFrameSimple and RemapFrames (as they shouldn't be). RemapFrames now functions properly (Fixed #3)
1 parent 0232654 commit 4676f0d

File tree

4 files changed

+68
-70
lines changed

4 files changed

+68
-70
lines changed

Common.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,19 @@ MismatchCauses findCommonVi(VSVideoInfo *outVi, VSNodeRef *node2, const VSAPI *v
101101
mismatch = MismatchCauses::DIFFERENT_DIMENSIONS;
102102
}
103103

104-
if (outVi->format != vi->format) {
104+
else if (outVi->format != vi->format) {
105105
outVi->format = 0;
106106
mismatch = MismatchCauses::DIFFERENT_FORMATS;
107107
}
108108

109-
if (outVi->fpsNum != vi->fpsNum || outVi->fpsDen != vi->fpsDen) {
109+
else if (outVi->fpsNum != vi->fpsNum || outVi->fpsDen != vi->fpsDen) {
110110
outVi->fpsDen = 0;
111111
outVi->fpsNum = 0;
112112
mismatch = MismatchCauses::DIFFERENT_FRAMERATES;
113113
}
114-
if (outVi->numFrames < vi->numFrames) {
115-
outVi->numFrames = vi->numFrames;
114+
else if (outVi->numFrames != vi->numFrames) {
115+
if(outVi->numFrames < vi->numFrames)
116+
outVi->numFrames = vi->numFrames;
116117
mismatch = MismatchCauses::DIFFERENT_LENGTHS;
117118
}
118119
}

RemapFrames.cpp

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ static const VSFrameRef *VS_CC remapGetFrame(int n, int activationReason, void *
1616
RemapData *d{ static_cast<RemapData*>(*instanceData) };
1717

1818
if (activationReason == arInitial) {
19-
//We check whether node2 is a null pointer. If it is, we use baseclip (node1).
20-
//Else, sourceclip (node2) is used.
21-
vsapi->requestFrameFilter(d->frameMap[n], (d->node2 ? d->node2 : d->node1), frameCtx);
19+
if (d->frameMap[n] == UINT_MAX)
20+
vsapi->requestFrameFilter(n, d->node1, frameCtx);
21+
else
22+
vsapi->requestFrameFilter(d->frameMap[n], d->node2, frameCtx);
2223
}
2324
else if (activationReason == arAllFramesReady) {
24-
return vsapi->getFrameFilter(d->frameMap[n], (d->node2 ? d->node2 : d->node1), frameCtx);
25+
if (d->frameMap[n] == UINT_MAX)
26+
return vsapi->getFrameFilter(n, d->node1, frameCtx);
27+
return vsapi->getFrameFilter(d->frameMap[n], d->node2, frameCtx);
2528
}
2629

2730
return nullptr;
@@ -30,7 +33,7 @@ static const VSFrameRef *VS_CC remapGetFrame(int n, int activationReason, void *
3033
static void VS_CC remapFree(void *instanceData, VSCore *core, const VSAPI *vsapi) {
3134
RemapData *d{ static_cast<RemapData*>(instanceData) };
3235
vsapi->freeNode(d->node1);
33-
if (d->node2)
36+
if (d->node1 != d->node2)
3437
vsapi->freeNode(d->node2);
3538
delete d;
3639
}
@@ -78,7 +81,7 @@ static void matchRangeToRange(const std::string &str, int &col, std::vector<unsi
7881
//
7982
//If it isn't able to parse the string as any of the above three patterns, it throws a runtime error (Parse Error).
8083
//Runtime errors (Index out of Bounds, Overflow, or Parse errors) can also be thrown from inside getInt and fillRange.
81-
static void parse(std::string name, std::vector<unsigned int> &frameMap, void *stream, bool file, int maxFrames) {
84+
static void parse(std::string name, std::vector<unsigned int> &frameMap, void *stream, bool file, int maxFrames, const VSAPI *vsapi) {
8285

8386
int line{ 0 }; //Current line. This is simply for throwing detailed errors and has no other use.
8487
int col{ 0 }; //Current column. This is used to track the current column position in the string we are at.
@@ -93,42 +96,40 @@ static void parse(std::string name, std::vector<unsigned int> &frameMap, void *s
9396
std::string temp;
9497
while (file ? std::getline(*static_cast<std::ifstream*>(stream), temp) : std::getline(*static_cast<std::stringstream*>(stream), temp)) {
9598
col = 0;
96-
skipWhitespace(temp, col);
97-
char ch{ getChar(temp, col) };
98-
if (ch != 0) {
99-
if (ch == '#')
100-
continue;
101-
else if (std::isdigit(ch) || ch == '-')
102-
matchIntToInt(temp, col, frameMap, line, file, maxFrames);
103-
else if (ch == '[') {
104-
++col;
105-
Range rangeIn;
106-
fillRange(temp, col, rangeIn, line, file, maxFrames, Filter::REMAP_FRAMES);
107-
if (rangeIn.start > rangeIn.end) {
99+
while (col < temp.size()) {
100+
skipWhitespace(temp, col);
101+
char ch{ getChar(temp, col) };
102+
if (ch != 0) {
103+
if (ch == '#')
104+
continue;
105+
else if (std::isdigit(ch) || ch == '-')
106+
matchIntToInt(temp, col, frameMap, line, file, maxFrames);
107+
else if (ch == '[') {
108+
++col;
109+
Range rangeIn;
110+
fillRange(temp, col, rangeIn, line, file, maxFrames, Filter::REMAP_FRAMES);
111+
if (rangeIn.start > rangeIn.end) {
112+
std::string location{ file ? " text file " : " mappings " };
113+
std::string error{ "RemapFrames: Index out of bounds in" + location + "at line " + std::to_string(line + 1) + ", column " + std::to_string(col + 1) };
114+
throw std::runtime_error(error);
115+
}
116+
skipWhitespace(temp, col);
117+
ch = getChar(temp, col);
118+
if (ch != 0) {
119+
if (std::isdigit(ch) || ch == '-') {
120+
matchRangeToInt(temp, col, frameMap, rangeIn, line, file, maxFrames);
121+
}
122+
else if (ch == '[') {
123+
++col;
124+
matchRangeToRange(temp, col, frameMap, rangeIn, line, file, maxFrames);
125+
}
126+
}
127+
}
128+
else {
108129
std::string location{ file ? " text file " : " mappings " };
109-
std::string error{ "RemapFrames: Index out of bounds in" + location + "at line " + std::to_string(line + 1) + ", column " + std::to_string(col + 1) };
130+
std::string error{ "RemapFrames: Parse Error in" + location + "at line " + std::to_string(line + 1) + ", column " + std::to_string(col + 1) };
110131
throw std::runtime_error(error);
111132
}
112-
skipWhitespace(temp, col);
113-
ch = getChar(temp, col);
114-
if (ch != 0) {
115-
if (std::isdigit(ch) || ch == '-')
116-
matchRangeToInt(temp, col, frameMap, rangeIn, line, file, maxFrames);
117-
else if (ch == '[')
118-
++col;
119-
matchRangeToRange(temp, col, frameMap, rangeIn, line, file, maxFrames);
120-
}
121-
}
122-
else {
123-
std::string location{ file ? " text file " : " mappings " };
124-
std::string error{ "RemapFrames: Parse Error in" + location + "at line " + std::to_string(line + 1) + ", column " + std::to_string(col + 1) };
125-
throw std::runtime_error(error);
126-
}
127-
skipWhitespace(temp, col);
128-
if (col != temp.size()) {
129-
std::string location{ file ? " text file " : " mappings " };
130-
std::string error{ "RemapFrames: Parse Error in" + location + "at line " + std::to_string(line + 1) + ", column " + std::to_string(col + 1) };
131-
throw std::runtime_error(error);
132133
}
133134
}
134135
line++;
@@ -148,18 +149,18 @@ void VS_CC remapCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core
148149
filename = "";
149150
else
150151
filename = fn;
151-
152+
152153
std::string mappings;
153154
const char* mp{ vsapi->propGetData(in, "mappings", 0, &err) };
154155
if (err)
155156
mappings = "";
156157
else
157158
mappings = mp;
158159

159-
//If sourceclip is not provided, we set node2 to a null pointer.
160+
//If sourceclip is not provided, we set sourceclip equal to baseclip.
160161
d.node2 = vsapi->propGetNode(in, "sourceclip", 0, &err);
161162
if (err)
162-
d.node2 = nullptr;
163+
d.node2 = d.node1;
163164

164165
bool mismatch{ !!vsapi->propGetInt(in, "mismatch", 0, &err) };
165166
if (err)
@@ -169,9 +170,12 @@ void VS_CC remapCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core
169170
MismatchCauses mismatchCause = findCommonVi(&d.vi, d.node2, vsapi);
170171
if (mismatchCause == MismatchCauses::DIFFERENT_LENGTHS) {
171172
vsapi->setError(out, "RemapFrames: Clip lengths don't match");
173+
//Free baseclip.
172174
vsapi->freeNode(d.node1);
173-
if (d.node2)
174-
vsapi->freeNode(d.node2); //We check whether node2 is a null pointer. If it isn't, we free the node.
175+
//If sourceclip and baseclip aren't the same, then free sourceclip.
176+
//freeNode(node) doesn't change the value of node so the comparison is safe.
177+
if (d.node1 != d.node2)
178+
vsapi->freeNode(d.node2);
175179
return;
176180
}
177181

@@ -183,19 +187,15 @@ void VS_CC remapCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core
183187
else if (mismatchCause == MismatchCauses::DIFFERENT_FRAMERATES)
184188
vsapi->setError(out, "RemapFrames: Clip frame rates don't match");
185189
vsapi->freeNode(d.node1);
186-
if (d.node2)
190+
if (d.node1 != d.node2)
187191
vsapi->freeNode(d.node2);
188192
return;
189193
}
190194

191195
//We use a vector to store frame mappings. Each index represents a frame number,
192196
//and each value at that index represents which frame it going to be replaced with.
193-
d.frameMap.resize(d.vi.numFrames);
194-
195-
//All frames map to themselves by default.
196-
for (int i = 0; i < d.frameMap.size(); i++) {
197-
d.frameMap[i] = i;
198-
}
197+
//A value of UINT_MAX indicates that the frame doesn't need to be replaced.
198+
d.frameMap.assign(d.vi.numFrames, UINT_MAX);
199199

200200
//Enclosed in a try catch block to catch any runtime errors.
201201
//Frame mappings in the mappings string have higher precedence than
@@ -207,21 +207,21 @@ void VS_CC remapCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core
207207
if (!file) {
208208
vsapi->setError(out, "RemapFrames: Failed to open the timecodes file.");
209209
vsapi->freeNode(d.node1);
210-
if (d.node2)
210+
if (d.node1 != d.node2)
211211
vsapi->freeNode(d.node2);
212212
return;
213213
}
214-
parse(filename, d.frameMap, &file, true, d.vi.numFrames);
214+
parse(filename, d.frameMap, &file, true, d.vi.numFrames, vsapi);
215215
}
216216
if (!mappings.empty()) {
217217
std::stringstream stream(mappings);
218-
parse(mappings, d.frameMap, &stream, false, d.vi.numFrames);
218+
parse(mappings, d.frameMap, &stream, false, d.vi.numFrames, vsapi);
219219
}
220220
}
221221
catch (const std::exception &ex) {
222222
vsapi->setError(out, ex.what());
223223
vsapi->freeNode(d.node1);
224-
if (d.node2)
224+
if (d.node1 != d.node2)
225225
vsapi->freeNode(d.node2);
226226
return;
227227
}

RemapFramesSimple.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ void VS_CC remapSimpleCreate(const VSMap *in, VSMap *out, void *userData, VSCore
103103
if (!filename.empty()) {
104104
std::ifstream file(filename);
105105
if (!file) {
106-
vsapi->setError(out, "RemapFrames: Failed to open the timecodes file.");
106+
vsapi->setError(out, "RemapFramesSimple: Failed to open the timecodes file.");
107107
vsapi->freeNode(d.node);
108108
return;
109109
}

ReplaceFramesSimple.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,37 +101,34 @@ void VS_CC replaceCreate(const VSMap *in, VSMap *out, void *userData, VSCore *co
101101

102102
MismatchCauses mismatchCause = findCommonVi(&d.vi, d.node2, vsapi);
103103
if (mismatchCause == MismatchCauses::DIFFERENT_LENGTHS) {
104-
vsapi->setError(out, "RemapFrames: Clip lengths don't match");
104+
vsapi->setError(out, "ReplaceFramesSimple: Clip lengths don't match");
105105
vsapi->freeNode(d.node1);
106106
vsapi->freeNode(d.node2);
107107
return;
108108
}
109109

110110
if (static_cast<bool>(mismatchCause) && (!mismatch)) {
111111
if (mismatchCause == MismatchCauses::DIFFERENT_DIMENSIONS)
112-
vsapi->setError(out, "RemapFrames: Clip dimensions don't match");
112+
vsapi->setError(out, "ReplaceFramesSimple: Clip dimensions don't match");
113113
else if (mismatchCause == MismatchCauses::DIFFERENT_FORMATS)
114-
vsapi->setError(out, "RemapFrames: Clip formats don't match");
114+
vsapi->setError(out, "ReplaceFramesSimple: Clip formats don't match");
115115
else if (mismatchCause == MismatchCauses::DIFFERENT_FRAMERATES)
116-
vsapi->setError(out, "RemapFrames: Clip frame rates don't match");
116+
vsapi->setError(out, "ReplaceFramesSimple: Clip frame rates don't match");
117117
vsapi->freeNode(d.node1);
118118
vsapi->freeNode(d.node2);
119119
return;
120120
}
121121

122-
d.frameMap.resize(d.vi.numFrames);
123-
124122
//All frames map to baseclip by default
125123
//0 = baseclip
126124
//1 = sourceclip
127-
for (int i = 0; i < d.frameMap.size(); i++) {
128-
d.frameMap[i] = 0;
129-
}
125+
d.frameMap.assign(d.vi.numFrames, 0);
126+
130127
try {
131128
if (!filename.empty()) {
132129
std::ifstream file(filename);
133130
if (!file) {
134-
vsapi->setError(out, "RemapFrames: Failed to open the timecodes file.");
131+
vsapi->setError(out, "ReplaceFramesSimple: Failed to open the timecodes file.");
135132
vsapi->freeNode(d.node1);
136133
vsapi->freeNode(d.node2);
137134
return;

0 commit comments

Comments
 (0)