@@ -16,12 +16,15 @@ static const VSFrameRef *VS_CC remapGetFrame(int n, int activationReason, void *
16
16
RemapData *d{ static_cast <RemapData*>(*instanceData) };
17
17
18
18
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);
22
23
}
23
24
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);
25
28
}
26
29
27
30
return nullptr ;
@@ -30,7 +33,7 @@ static const VSFrameRef *VS_CC remapGetFrame(int n, int activationReason, void *
30
33
static void VS_CC remapFree (void *instanceData, VSCore *core, const VSAPI *vsapi) {
31
34
RemapData *d{ static_cast <RemapData*>(instanceData) };
32
35
vsapi->freeNode (d->node1 );
33
- if (d->node2 )
36
+ if (d->node1 != d-> node2 )
34
37
vsapi->freeNode (d->node2 );
35
38
delete d;
36
39
}
@@ -78,7 +81,7 @@ static void matchRangeToRange(const std::string &str, int &col, std::vector<unsi
78
81
//
79
82
// If it isn't able to parse the string as any of the above three patterns, it throws a runtime error (Parse Error).
80
83
// 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 ) {
82
85
83
86
int line{ 0 }; // Current line. This is simply for throwing detailed errors and has no other use.
84
87
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
93
96
std::string temp;
94
97
while (file ? std::getline (*static_cast <std::ifstream*>(stream), temp) : std::getline (*static_cast <std::stringstream*>(stream), temp)) {
95
98
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 {
108
129
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 ) };
110
131
throw std::runtime_error (error);
111
132
}
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);
132
133
}
133
134
}
134
135
line++;
@@ -148,18 +149,18 @@ void VS_CC remapCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core
148
149
filename = " " ;
149
150
else
150
151
filename = fn;
151
-
152
+
152
153
std::string mappings;
153
154
const char * mp{ vsapi->propGetData (in, " mappings" , 0 , &err) };
154
155
if (err)
155
156
mappings = " " ;
156
157
else
157
158
mappings = mp;
158
159
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 .
160
161
d.node2 = vsapi->propGetNode (in, " sourceclip" , 0 , &err);
161
162
if (err)
162
- d.node2 = nullptr ;
163
+ d.node2 = d. node1 ;
163
164
164
165
bool mismatch{ !!vsapi->propGetInt (in, " mismatch" , 0 , &err) };
165
166
if (err)
@@ -169,9 +170,12 @@ void VS_CC remapCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core
169
170
MismatchCauses mismatchCause = findCommonVi (&d.vi , d.node2 , vsapi);
170
171
if (mismatchCause == MismatchCauses::DIFFERENT_LENGTHS) {
171
172
vsapi->setError (out, " RemapFrames: Clip lengths don't match" );
173
+ // Free baseclip.
172
174
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 );
175
179
return ;
176
180
}
177
181
@@ -183,19 +187,15 @@ void VS_CC remapCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core
183
187
else if (mismatchCause == MismatchCauses::DIFFERENT_FRAMERATES)
184
188
vsapi->setError (out, " RemapFrames: Clip frame rates don't match" );
185
189
vsapi->freeNode (d.node1 );
186
- if (d.node2 )
190
+ if (d.node1 != d. node2 )
187
191
vsapi->freeNode (d.node2 );
188
192
return ;
189
193
}
190
194
191
195
// We use a vector to store frame mappings. Each index represents a frame number,
192
196
// 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);
199
199
200
200
// Enclosed in a try catch block to catch any runtime errors.
201
201
// 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
207
207
if (!file) {
208
208
vsapi->setError (out, " RemapFrames: Failed to open the timecodes file." );
209
209
vsapi->freeNode (d.node1 );
210
- if (d.node2 )
210
+ if (d.node1 != d. node2 )
211
211
vsapi->freeNode (d.node2 );
212
212
return ;
213
213
}
214
- parse (filename, d.frameMap , &file, true , d.vi .numFrames );
214
+ parse (filename, d.frameMap , &file, true , d.vi .numFrames , vsapi );
215
215
}
216
216
if (!mappings.empty ()) {
217
217
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 );
219
219
}
220
220
}
221
221
catch (const std::exception &ex) {
222
222
vsapi->setError (out, ex.what ());
223
223
vsapi->freeNode (d.node1 );
224
- if (d.node2 )
224
+ if (d.node1 != d. node2 )
225
225
vsapi->freeNode (d.node2 );
226
226
return ;
227
227
}
0 commit comments