GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 37.7% 225 / 0 / 597
Functions: 41.1% 23 / 0 / 56
Branches: 17.8% 199 / 0 / 1115

filters/edit.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
3
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35 #include "edit.h"
36 #include "../convert/convert_audio.h"
37 #include "../core/internal.h"
38 #include "merge.h"
39 #include <climits>
40 #include <cmath>
41
42 #ifdef AVS_WINDOWS
43 #include <avs/win.h>
44 #else
45 #include <avs/posix.h>
46 #endif
47
48 #include <avs/minmax.h>
49 #include <avs/alignment.h>
50 #include <stdint.h>
51 #include <utility>
52
53
54
55 /********************************************************************
56 ***** Declare index of new filters for Avisynth's filter engine *****
57 ********************************************************************/
58
59 enum { FADE_MODE_OUT0, FADE_MODE_OUT, FADE_MODE_OUT2, FADE_MODE_IN0, FADE_MODE_IN, FADE_MODE_IN2, FADE_MODE_IO0, FADE_MODE_IO, FADE_MODE_IO2 };
60
61 extern const AVSFunction Edit_filters[] = {
62 { "AudioTrim", BUILTIN_FUNC_PREFIX, "cff[cache]b", Trim::CreateA, (void*)Trim::Default}, // start time, end time
63 { "AudioTrim", BUILTIN_FUNC_PREFIX, "cf[cache]b", Trim::CreateA, (void*)Trim::Invalid}, // Throw Invalid argument to AudioTrim because 4 parameters expected
64 { "AudioTrim", BUILTIN_FUNC_PREFIX, "cf[length]f[cache]b", Trim::CreateA, (void*)Trim::Length}, // start time, duration
65 { "AudioTrim", BUILTIN_FUNC_PREFIX, "cf[end]f[cache]b", Trim::CreateA, (void*)Trim::End}, // start time, end time
66 { "Trim", BUILTIN_FUNC_PREFIX, "cii[pad]b[cache]b", Trim::Create, (void*)Trim::Default}, // first frame, last frame[, pad audio]
67 { "Trim", BUILTIN_FUNC_PREFIX, "ci[pad]b[cache]b", Trim::Create, (void*)Trim::Invalid}, // Throw Invalid argument to Trim because 5 parameters expected
68 { "Trim", BUILTIN_FUNC_PREFIX, "ci[length]i[pad]b[cache]b", Trim::Create, (void*)Trim::Length}, // first frame, frame count[, pad audio]
69 { "Trim", BUILTIN_FUNC_PREFIX, "ci[end]i[pad]b[cache]b", Trim::Create, (void*)Trim::End}, // first frame, last frame[, pad audio]
70 { "FreezeFrame", BUILTIN_FUNC_PREFIX, "ciii", FreezeFrame::Create }, // first frame, last frame, source frame
71 { "DeleteFrame", BUILTIN_FUNC_PREFIX, "ci+", DeleteFrame::Create }, // frame #
72 { "DuplicateFrame", BUILTIN_FUNC_PREFIX, "ci+", DuplicateFrame::Create }, // frame #
73 { "UnalignedSplice", BUILTIN_FUNC_PREFIX, "cc+", Splice::CreateUnaligned }, // clips
74 { "AlignedSplice", BUILTIN_FUNC_PREFIX, "cc+", Splice::CreateAligned }, // clips
75 { "UnalignedSplice", BUILTIN_FUNC_PREFIX, "cci", Splice::CreateUnalignedNoCache }, // clips
76 { "AlignedSplice", BUILTIN_FUNC_PREFIX, "cci", Splice::CreateAlignedNoCache }, // clips
77 { "Dissolve", BUILTIN_FUNC_PREFIX, "cc+i[fps]f", Dissolve::Create }, // clips, overlap frames[, fps]
78 { "AudioDub", BUILTIN_FUNC_PREFIX, "cc", AudioDub::Create, (void*)0}, // video src, audio src
79 { "AudioDubEx", BUILTIN_FUNC_PREFIX, "cc", AudioDub::Create, (void*)1}, // video! src, audio! src
80 { "Reverse", BUILTIN_FUNC_PREFIX, "c", Reverse::Create }, // plays backwards
81 { "FadeOut0", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_OUT0 },
82 { "FadeOut", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_OUT },
83 { "FadeOut2", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_OUT2 },
84 { "FadeIn0", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_IN0 },
85 { "FadeIn", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_IN },
86 { "FadeIn2", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_IN2 },
87 { "FadeIO0", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_IO0 },
88 { "FadeIO", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_IO },
89 { "FadeIO2", BUILTIN_FUNC_PREFIX, "ci[color]i[fps]f[color_yuv]i[colors]f+", Create_Fade, (void*)FADE_MODE_IO2 },
90 { "Loop", BUILTIN_FUNC_PREFIX, "c[times]i[start]i[end]i", Loop::Create }, // number of loops, first frame, last frames
91 { NULL }
92 };
93
94
95
96 /******************************
97 ******* NonCachedGenericVideoFilter Filter ******
98 ******************************/
99
100 38 NonCachedGenericVideoFilter::NonCachedGenericVideoFilter(PClip _child) :
101
2/4
✓ Branch 2 → 3 taken 38 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 38 times.
✗ Branch 3 → 6 not taken.
38 GenericVideoFilter(_child)
102 {
103 38 };
104
105
106 6 int __stdcall NonCachedGenericVideoFilter::SetCacheHints(int cachehints, int frame_range)
107 {
108
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 6 times.
✗ Branch 2 → 5 not taken.
✗ Branch 2 → 13 not taken.
6 switch(cachehints)
109 {
110 case CACHE_DONT_CACHE_ME:
111 return 1;
112 6 case CACHE_GET_MTMODE:
113 6 return MT_NICE_FILTER;
114
115 case CACHE_GET_DEV_TYPE:
116 return (child->GetVersion() >= 5) ? child->SetCacheHints(CACHE_GET_DEV_TYPE, 0) : 0;
117
118 default:
119 return GenericVideoFilter::SetCacheHints(cachehints, frame_range);
120 }
121 }
122
123
124 /******************************
125 ******* AudioTrim Filter ******
126 ******************************/
127
128 1 Trim::Trim(double starttime, double endtime, PClip _child, trim_mode_e mode, bool _cache, IScriptEnvironment* env)
129
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 39 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 37 not taken.
1 : GenericVideoFilter(_child), cache(_cache)
130 {
131 1 int64_t esampleno = 0;
132
133
2/4
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 40 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 1 time.
1 if (!vi.HasAudio())
134 env->ThrowError("AudioTrim: Cannot trim if there is no audio.");
135
136 1 audio_offset = clamp(int64_t(starttime*vi.audio_samples_per_second + 0.5), (int64_t)0ll, vi.num_audio_samples);
137
138
1/4
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 16 taken 1 time.
✗ Branch 9 → 19 not taken.
✗ Branch 9 → 22 not taken.
1 switch (mode) {
139 case Default:
140 if (endtime == 0.0)
141 esampleno = vi.num_audio_samples;
142 else if (endtime < 0.0)
143 esampleno = int64_t((starttime-endtime)*vi.audio_samples_per_second + 0.5);
144 else
145 esampleno = int64_t(endtime*vi.audio_samples_per_second + 0.5);
146
147 break;
148 1 case Length:
149
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 1 time.
1 if (endtime < 0.0)
150 env->ThrowError("AudioTrim: Length must be >= 0");
151
152 1 esampleno = int64_t((starttime+endtime)*vi.audio_samples_per_second + 0.5);
153
154 1 break;
155 case End:
156 if (endtime < starttime)
157 env->ThrowError("AudioTrim: End must be >= Start");
158
159 esampleno = int64_t(endtime*vi.audio_samples_per_second + 0.5);
160
161 break;
162 default:
163 env->ThrowError("Script error: Invalid arguments to function \"AudioTrim\"");
164 }
165
166
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 1 time.
1 if (esampleno > vi.num_audio_samples)
167 esampleno = vi.num_audio_samples;
168
169 1 vi.num_audio_samples = esampleno - audio_offset;
170
171
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 1 time.
1 if (vi.num_audio_samples < 0)
172 vi.num_audio_samples = 0;
173
174
1/2
✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 40 not taken.
1 firstframe= vi.FramesFromAudioSamples(audio_offset); // Floor
175
176
1/4
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 31 taken 1 time.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 31 not taken.
1 if (endtime == 0.0 && mode == Default)
177 vi.num_frames -= firstframe;
178 else
179
2/4
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 40 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 40 not taken.
1 vi.num_frames = vi.FramesFromAudioSamples(vi.num_audio_samples + vi.AudioSamplesFromFrames(1) - 1); // Ceil
180
181
1/2
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 1 time.
1 if (vi.num_frames < 0)
182 vi.num_frames = 0;
183
184 1 }
185
186
187 AVSValue __cdecl Trim::CreateA(AVSValue args, void* user_arg, IScriptEnvironment* env)
188 {
189 trim_mode_e mode = (trim_mode_e)size_t(user_arg);
190 if (mode == Trim::Invalid)
191 env->ThrowError("Script error: Invalid arguments to function \"AudioTrim\"");
192
193 const bool cache = args[3].AsBool(true);
194
195 return new Trim(args[1].AsFloat(), args[2].AsFloat(), args[0].AsClip(), mode, cache, env);
196 }
197
198
199 /******************************
200 ******* Trim Filter ******
201 ******************************/
202
203 Trim::Trim(int _firstframe, int _lastframe, bool _padaudio, PClip _child, trim_mode_e mode, bool _cache, IScriptEnvironment* env)
204 : GenericVideoFilter(_child), cache(_cache)
205 {
206 int lastframe = 0;
207
208 if (!vi.HasVideo())
209 env->ThrowError("Trim: Cannot trim if there is no video.");
210
211 firstframe = clamp(_firstframe, 0, vi.num_frames-1);
212
213 switch (mode) {
214 case Default:
215 if (_lastframe == 0)
216 lastframe = vi.num_frames-1;
217 else if (_lastframe < 0)
218 lastframe = firstframe - _lastframe - 1;
219 else
220 lastframe = _lastframe;
221
222 lastframe = clamp(lastframe, firstframe, vi.num_frames-1);
223
224 break;
225
226 case Length:
227 if (_lastframe < 0)
228 env->ThrowError("Trim: Length must be >= 0");
229
230 lastframe = firstframe + _lastframe - 1;
231
232 if (lastframe > vi.num_frames-1)
233 lastframe = vi.num_frames-1;
234
235 break;
236
237 case End:
238 if (_lastframe < firstframe)
239 env->ThrowError("Trim: End must be >= Start");
240
241 lastframe = _lastframe;
242
243 if (lastframe > vi.num_frames-1)
244 lastframe = vi.num_frames-1;
245
246 break;
247
248 default:
249 env->ThrowError("Script error: Invalid arguments to function \"Trim\"");
250 }
251
252 vi.num_frames = lastframe+1 - firstframe;
253
254 audio_offset = vi.AudioSamplesFromFrames(firstframe);
255 if (_padaudio)
256 vi.num_audio_samples = vi.AudioSamplesFromFrames(lastframe+1) - audio_offset;
257 else {
258 int64_t samples;
259
260 if (_lastframe == 0 && mode == Default)
261 samples = vi.num_audio_samples;
262 else {
263 samples = vi.AudioSamplesFromFrames(lastframe+1);
264 if (samples > vi.num_audio_samples)
265 samples = vi.num_audio_samples;
266 }
267 if (audio_offset >= samples)
268 vi.num_audio_samples = 0;
269 else
270 vi.num_audio_samples = samples - audio_offset;
271 }
272 }
273
274
275 PVideoFrame Trim::GetFrame(int n, IScriptEnvironment* env)
276 {
277 return child->GetFrame(n+firstframe, env);
278 }
279
280
281 1 void __stdcall Trim::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env)
282 {
283 1 child->GetAudio(buf, start+audio_offset, count, env);
284 1 }
285
286
287 bool Trim::GetParity(int n)
288 {
289 return child->GetParity(n+firstframe);
290 }
291
292
293 AVSValue __cdecl Trim::Create(AVSValue args, void* user_arg, IScriptEnvironment* env)
294 {
295 trim_mode_e mode = (trim_mode_e)size_t(user_arg);
296
297 if (mode == Trim::Invalid)
298 env->ThrowError("Script error: Invalid arguments to function \"Trim\"");
299
300 const bool cache = args[4].AsBool(true);
301
302 return new Trim(args[1].AsInt(), args[2].AsInt(), args[3].AsBool(true), args[0].AsClip(), mode, cache, env);
303 }
304
305
306
307
308
309
310
311
312 /*******************************
313 ******* Freeze Frame ******
314 *******************************/
315
316 2 FreezeFrame::FreezeFrame(int _first, int _last, int _source, PClip _child)
317
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 6 not taken.
2 : GenericVideoFilter(_child), first(_first), last(_last), source(_source) {}
318
319
320 PVideoFrame FreezeFrame::GetFrame(int n, IScriptEnvironment* env)
321 {
322 return child->GetFrame((n >= first && n <= last) ? source : n, env);
323 }
324
325
326 bool FreezeFrame::GetParity(int n)
327 {
328 return child->GetParity((n >= first && n <= last) ? source : n);
329 }
330
331
332 2 AVSValue __cdecl FreezeFrame::Create(AVSValue args, void*, IScriptEnvironment* env)
333 {
334 AVS_UNUSED(env);
335
11/24
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 21 not taken.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 21 not taken.
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 19 not taken.
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 19 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 19 not taken.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 19 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 19 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 19 not taken.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 19 not taken.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 2 times.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
6 return new FreezeFrame(args[1].AsInt(), args[2].AsInt(), args[3].AsInt(), args[0].AsClip());
336 }
337
338
339 /******************************
340 ******* Delete Frame ******
341 ******************************/
342
343 3 DeleteFrame::DeleteFrame(int _frame, PClip _child)
344
2/4
✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 6 not taken.
3 : GenericVideoFilter(_child), frame(_frame) { --vi.num_frames; }
345
346
347 PVideoFrame DeleteFrame::GetFrame(int n, IScriptEnvironment* env)
348 {
349 return child->GetFrame(n + (n>=frame), env);
350 }
351
352
353 bool DeleteFrame::GetParity(int n)
354 {
355 return child->GetParity(n + (n>=frame));
356 }
357
358
359 3 AVSValue __cdecl DeleteFrame::Create(AVSValue args, void*, IScriptEnvironment* env)
360 {
361 AVS_UNUSED(env);
362
2/4
✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 51 not taken.
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 51 not taken.
3 const int n = args[1].ArraySize();
363 3 int m = n-1;
364
2/4
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 6 not taken.
✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 51 not taken.
3 int *frames = new int[n];
365
366
3/6
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 51 not taken.
✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 51 not taken.
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 51 not taken.
3 frames[0] = args[1][0].AsInt();
367
1/2
✗ Branch 23 → 12 not taken.
✓ Branch 23 → 24 taken 3 times.
3 for (int i=1; i<n; ++i) {
368 frames[i] = args[1][i].AsInt();
369 // Bubble insert
370 for (int j=0; j<i; ++j) {
371 // Remove duplicates
372 if (frames[i] == frames[j]) {
373 m -= 1;
374 frames[i] = INT_MAX;
375 break;
376 }
377 else if (frames[i] < frames[j]) {
378 const int t = frames[j];
379 frames[j] = frames[i];
380 frames[i] = t;
381 }
382 }
383 }
384
2/4
✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 51 not taken.
✓ Branch 25 → 26 taken 3 times.
✗ Branch 25 → 51 not taken.
3 PClip result = args[0].AsClip();
385
2/2
✓ Branch 35 → 27 taken 3 times.
✓ Branch 35 → 36 taken 3 times.
6 for (int k=m; k>=0; --k)
386
5/12
✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 49 not taken.
✓ Branch 28 → 29 taken 3 times.
✗ Branch 28 → 45 not taken.
✓ Branch 29 → 30 taken 3 times.
✗ Branch 29 → 43 not taken.
✓ Branch 30 → 31 taken 3 times.
✗ Branch 30 → 43 not taken.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 34 taken 3 times.
✗ Branch 46 → 47 not taken.
✗ Branch 46 → 48 not taken.
3 result = new DeleteFrame(frames[k], result);
387
388
1/2
✓ Branch 36 → 37 taken 3 times.
✗ Branch 36 → 38 not taken.
3 delete[] frames;
389
1/2
✓ Branch 38 → 39 taken 3 times.
✗ Branch 38 → 49 not taken.
6 return result;
390 3 }
391
392
393
394 /*********************************
395 ******* Duplicate Frame ******
396 *********************************/
397
398 2 DuplicateFrame::DuplicateFrame(int _frame, PClip _child)
399
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 6 not taken.
2 : GenericVideoFilter(_child), frame(_frame) { ++vi.num_frames; }
400
401
402 PVideoFrame DuplicateFrame::GetFrame(int n, IScriptEnvironment* env)
403 {
404 return child->GetFrame(n - (n>frame), env);
405 }
406
407
408 bool DuplicateFrame::GetParity(int n)
409 {
410 return child->GetParity(n - (n>frame));
411 }
412
413
414 2 AVSValue __cdecl DuplicateFrame::Create(AVSValue args, void*, IScriptEnvironment* env)
415 {
416 AVS_UNUSED(env);
417
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 49 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 49 not taken.
2 const int n = args[1].ArraySize();
418
2/4
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 6 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 49 not taken.
2 int *frames = new int[n];
419
420
3/6
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 49 not taken.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 49 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 49 not taken.
2 frames[0] = args[1][0].AsInt();
421
1/2
✗ Branch 21 → 12 not taken.
✓ Branch 21 → 22 taken 2 times.
2 for (int i=1; i<n; ++i) {
422 frames[i] = args[1][i].AsInt();
423 // Bubble insert
424 for (int j=0; j<i; ++j) {
425 if (frames[i] < frames[j]) {
426 const int t = frames[j];
427 frames[j] = frames[i];
428 frames[i] = t;
429 }
430 }
431 }
432
2/4
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 49 not taken.
✓ Branch 23 → 24 taken 2 times.
✗ Branch 23 → 49 not taken.
2 PClip result = args[0].AsClip();
433
2/2
✓ Branch 33 → 25 taken 2 times.
✓ Branch 33 → 34 taken 2 times.
4 for (int k=n-1; k>=0; --k)
434
5/12
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 47 not taken.
✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 43 not taken.
✓ Branch 27 → 28 taken 2 times.
✗ Branch 27 → 41 not taken.
✓ Branch 28 → 29 taken 2 times.
✗ Branch 28 → 41 not taken.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 2 times.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 46 not taken.
2 result = new DuplicateFrame(frames[k], result);
435
436
1/2
✓ Branch 34 → 35 taken 2 times.
✗ Branch 34 → 36 not taken.
2 delete[] frames;
437
1/2
✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 47 not taken.
4 return result;
438 2 }
439
440
441
442 /*******************************
443 ******* Splice Filter ******
444 *******************************/
445
446 1 Splice::Splice(PClip _child1, PClip _child2, bool realign_sound, bool _passCache, IScriptEnvironment* env)
447
3/6
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 66 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 64 not taken.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 82 not taken.
1 : GenericVideoFilter(_child1), child2(_child2), passCache(_passCache)
448 {
449
1/2
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 79 not taken.
1 VideoInfo vi2 = child2->GetVideoInfo();
450
451
3/6
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 79 not taken.
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 79 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 1 time.
1 if (vi.HasVideo() ^ vi2.HasVideo())
452 env->ThrowError("Splice: one clip has video and the other doesn't (not allowed)");
453
3/6
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 79 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 79 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 1 time.
1 if (vi.HasAudio() ^ vi2.HasAudio())
454 env->ThrowError("Splice: one clip has audio and the other doesn't (not allowed)");
455
456
457 // Check video
458
2/4
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 79 not taken.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 26 taken 1 time.
1 if (vi.HasVideo()) {
459 if (vi.width != vi2.width || vi.height != vi2.height)
460 env->ThrowError("Splice: Frame sizes don't match");
461
462 if (!vi.IsSameColorspace(vi2))
463 env->ThrowError("Splice: Video formats don't match");
464
465 double fps_v1 = (double)vi.fps_numerator / (double)vi.fps_denominator;
466 double fps_v2 = (double)vi2.fps_numerator / (double)vi2.fps_denominator;
467 if (fabs(fps_v1-fps_v2) > 0.000001)
468 env->ThrowError("Splice: Video framerate doesn't match");
469 }
470
471 // Check Audio
472
2/4
✓ Branch 26 → 27 taken 1 time.
✗ Branch 26 → 79 not taken.
✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 53 not taken.
1 if (vi.HasAudio()) {
473 // If sample types do not match they are both converted to float samples to avoid loss of precision.
474
4/8
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 72 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 71 not taken.
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 69 not taken.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 67 not taken.
1 child2 = ConvertAudio::Create(child2, vi.SampleType(), SAMPLE_FLOAT); // Clip 1 is check to be same type as clip 1, if not, convert to float samples.
475
1/2
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 79 not taken.
1 vi2 = child2->GetVideoInfo();
476
477
5/10
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 78 not taken.
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 78 not taken.
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 77 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 75 not taken.
✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 73 not taken.
1 child = ConvertAudio::Create(child, vi2.SampleType(), vi2.SampleType()); // Clip 1 is now be same type as clip 2.
478
1/2
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 79 not taken.
1 vi = child->GetVideoInfo();
479
480
3/6
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 79 not taken.
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 79 not taken.
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 1 time.
1 if (vi.AudioChannels() != vi2.AudioChannels())
481 env->ThrowError("Splice: The number of audio channels doesn't match");
482
483
3/6
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 79 not taken.
✓ Branch 50 → 51 taken 1 time.
✗ Branch 50 → 79 not taken.
✗ Branch 51 → 52 not taken.
✓ Branch 51 → 53 taken 1 time.
1 if (vi.SamplesPerSecond() != vi2.SamplesPerSecond())
484 env->ThrowError("Splice: The audio of the two clips have different samplerates! Use SSRC()/ResampleAudio()");
485 }
486
487 1 video_switchover_point = vi.num_frames;
488
489
1/2
✓ Branch 53 → 54 taken 1 time.
✗ Branch 53 → 55 not taken.
1 if (!video_switchover_point) // We don't have video, so we cannot align sound to frames
490 1 realign_sound = false;
491
492
1/2
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 58 taken 1 time.
1 if (realign_sound)
493 audio_switchover_point = vi.AudioSamplesFromFrames(video_switchover_point);
494 else
495 1 audio_switchover_point = vi.num_audio_samples;
496
497 1 vi.num_frames += vi2.num_frames;
498
499
1/2
✗ Branch 59 → 60 not taken.
✓ Branch 59 → 61 taken 1 time.
1 if (vi.num_frames < 0)
500 env->ThrowError("Splice: Maximum number of frames exceeded.");
501
502 1 vi.num_audio_samples = audio_switchover_point + vi2.num_audio_samples;
503
504
2/4
✓ Branch 61 → 62 taken 1 time.
✗ Branch 61 → 79 not taken.
✓ Branch 62 → 63 taken 1 time.
✗ Branch 62 → 79 not taken.
1 child_devs = (GetDeviceTypes(child) & GetDeviceTypes(child2));
505 1 }
506
507
508 PVideoFrame Splice::GetFrame(int n, IScriptEnvironment* env)
509 {
510 if (n < video_switchover_point)
511 return child->GetFrame(n, env);
512 else
513 return child2->GetFrame(n - video_switchover_point, env);
514 }
515
516
517 1 void Splice::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env)
518 {
519
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 1 time.
1 if (start+count <= audio_switchover_point)
520 child->GetAudio(buf, start, count, env);
521
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 1 time.
1 else if (start >= audio_switchover_point)
522 child2->GetAudio(buf, start - audio_switchover_point, count, env);
523 else {
524 1 const int64_t count1 = audio_switchover_point - start;
525 1 child->GetAudio(buf, start, count1, env);
526 1 child2->GetAudio((char*)buf+vi.BytesFromAudioSamples(count1), 0, count-count1, env);
527 }
528 1 }
529
530
531 bool Splice::GetParity(int n)
532 {
533 if (n < video_switchover_point)
534 return child->GetParity(n);
535 else
536 return child2->GetParity(n - video_switchover_point);
537 }
538
539
540 1 int Splice::SetCacheHints(int cachehints,int frame_range)
541 {
542
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
✗ Branch 2 → 5 not taken.
✗ Branch 2 → 6 not taken.
1 switch(cachehints)
543 {
544 case CACHE_DONT_CACHE_ME:
545 return 1;
546 1 case CACHE_GET_MTMODE:
547 1 return MT_NICE_FILTER;
548 case CACHE_GET_DEV_TYPE:
549 return child_devs;
550 default:
551 if (passCache) {
552 child2->SetCacheHints(cachehints, frame_range);
553 return child->SetCacheHints(cachehints, frame_range);
554 }
555 break;
556 }
557 return 0; // We do not pass cache requests upwards.
558 }
559
560
561 AVSValue __cdecl Splice::CreateUnaligned(AVSValue args, void*, IScriptEnvironment* env)
562 {
563 PClip result = args[0].AsClip();
564 for (int i=0; i<args[1].ArraySize(); ++i)
565 result = new Splice(result, args[1][i].AsClip(), false, false, env);
566 return result;
567 }
568
569
570
571 AVSValue __cdecl Splice::CreateAligned(AVSValue args, void*, IScriptEnvironment* env)
572 {
573 PClip result = args[0].AsClip();
574 for (int i=0; i<args[1].ArraySize(); ++i)
575 result = new Splice(result, args[1][i].AsClip(), true, false, env);
576 return result;
577 }
578
579
580
581 AVSValue __cdecl Splice::CreateUnalignedNoCache(AVSValue args, void*, IScriptEnvironment* env)
582 {
583 return new Splice(args[0].AsClip(), args[1].AsClip(), false, true, env);
584 }
585
586 AVSValue __cdecl Splice::CreateAlignedNoCache(AVSValue args, void*, IScriptEnvironment* env)
587 {
588 return new Splice(args[0].AsClip(), args[1].AsClip(), true, true, env);
589 }
590
591
592
593
594
595
596
597
598
599 /*********************************
600 ******* Dissolve Filter ******
601 *********************************/
602
603
604 AVSValue __cdecl Dissolve::Create(AVSValue args, void*, IScriptEnvironment* env)
605 {
606 const int overlap = args[2].AsInt();
607 const double fps = args[3].AsDblDef(24.0);
608 PClip result = args[0].AsClip();
609 for (int i=0; i < args[1].ArraySize(); ++i)
610 result = new Dissolve(result, args[1][i].AsClip(), overlap, fps, env);
611 return result;
612 }
613
614
615 1 Dissolve::~Dissolve()
616 {
617
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1 delete[] audbuffer;
618 1 audbuffer = 0;
619 1 audbufsize = 0;
620 1 }
621
622 1 Dissolve::Dissolve(PClip _child1, PClip _child2, int _overlap, double fps, IScriptEnvironment* env)
623
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 71 not taken.
2 : GenericVideoFilter(ConvertAudio::Create(_child1,SAMPLE_INT16|SAMPLE_FLOAT,SAMPLE_FLOAT)),
624 1 child2(_child2),
625 1 overlap(_overlap),
626 1 audbuffer(0),
627
3/6
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 73 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 69 not taken.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 90 not taken.
3 audbufsize(0)
628 {
629
1/2
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 87 not taken.
1 VideoInfo vi2 = child2->GetVideoInfo();
630
631
3/6
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 87 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 87 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 1 time.
1 if (vi.HasVideo() ^ vi2.HasVideo())
632 env->ThrowError("Dissolve: one clip has video and the other doesn't (not allowed)");
633
3/6
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 87 not taken.
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 87 not taken.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 1 time.
1 if (vi.HasAudio() ^ vi2.HasAudio())
634 env->ThrowError("Dissolve: one clip has audio and the other doesn't (not allowed)");
635
636
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 1 time.
1 if (overlap<0)
637 env->ThrowError("Dissolve: Cannot dissolve if overlap is less than zero");
638
639
2/4
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 87 not taken.
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 47 not taken.
1 if (vi.HasAudio()) {
640
4/8
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 80 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 79 not taken.
✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 77 not taken.
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 75 not taken.
1 child2 = ConvertAudio::Create(child2, vi.SampleType(), SAMPLE_FLOAT); // Clip 1 is check to be same type as clip 1, if not, convert to float samples.
641
1/2
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 87 not taken.
1 vi2 = child2->GetVideoInfo();
642
643
5/10
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 86 not taken.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 86 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 85 not taken.
✓ Branch 33 → 34 taken 1 time.
✗ Branch 33 → 83 not taken.
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 81 not taken.
1 child = ConvertAudio::Create(child, vi2.SampleType(), vi2.SampleType()); // Clip 1 is now be same type as clip 2.
644
1/2
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 87 not taken.
1 vi = child->GetVideoInfo();
645
646
3/6
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 87 not taken.
✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 87 not taken.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 43 taken 1 time.
1 if (vi.AudioChannels() != vi2.AudioChannels())
647 env->ThrowError("Dissolve: The number of audio channels doesn't match");
648
649
3/6
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 87 not taken.
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 87 not taken.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 1 time.
1 if (vi.SamplesPerSecond() != vi2.SamplesPerSecond())
650 env->ThrowError("Dissolve: The audio of the two clips have different samplerates! Use SSRC()/ResampleAudio()");
651 }
652
653
2/4
✓ Branch 47 → 48 taken 1 time.
✗ Branch 47 → 87 not taken.
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 60 taken 1 time.
1 if (vi.HasVideo()) {
654 if (vi.width != vi2.width || vi.height != vi2.height)
655 env->ThrowError("Dissolve: frame sizes don't match");
656 if (!(vi.IsSameColorspace(vi2)))
657 env->ThrowError("Dissolve: video formats don't match");
658
659 pixelsize = vi.ComponentSize(); // AVS16
660 bits_per_pixel = vi.BitsPerComponent();
661
662 video_fade_start = vi.num_frames - overlap;
663 video_fade_end = vi.num_frames - 1;
664
665 audio_fade_start = vi.AudioSamplesFromFrames(video_fade_start);
666 audio_fade_end = vi.AudioSamplesFromFrames(video_fade_end+1)-1;
667 }
668 else {
669 1 video_fade_start = 0;
670 1 video_fade_end = 0;
671
672
1/2
✓ Branch 60 → 61 taken 1 time.
✗ Branch 60 → 87 not taken.
1 audio_fade_start = vi.num_audio_samples - int64_t(Int32x32To64(vi.SamplesPerSecond(), overlap)/fps+0.5);
673 1 audio_fade_end = vi.num_audio_samples-1;
674 }
675 1 audio_overlap = int(audio_fade_end - audio_fade_start);
676
677
1/2
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 64 taken 1 time.
1 if (video_fade_start < 0) video_fade_start= 0;
678
1/2
✗ Branch 64 → 65 not taken.
✓ Branch 64 → 66 taken 1 time.
1 if (audio_fade_start < 0) audio_fade_start= 0;
679
680 1 vi.num_frames = video_fade_start + vi2.num_frames;
681
682
1/2
✗ Branch 66 → 67 not taken.
✓ Branch 66 → 68 taken 1 time.
1 if (vi.num_frames < 0)
683 env->ThrowError("Dissolve: Maximum number of frames exceeded.");
684
685 1 vi.num_audio_samples = audio_fade_start + vi2.num_audio_samples;
686 1 }
687
688
689 bool Dissolve::GetParity(int n)
690 {
691 return (n < video_fade_start) ? child->GetParity(n) : child2->GetParity(n - video_fade_start);
692 }
693
694
695 PVideoFrame Dissolve::GetFrame(int n, IScriptEnvironment* env)
696 {
697 if (n < video_fade_start)
698 return child->GetFrame(n, env);
699 if (n > video_fade_end)
700 return child2->GetFrame(n - video_fade_start, env);
701
702 PVideoFrame a = child->GetFrame(n, env);
703 PVideoFrame b = child2->GetFrame(n - video_fade_start, env);
704
705 const double multiplier = n - video_fade_end + overlap;
706 float weight = (float)(multiplier / (overlap + 1.0));
707
708 env->MakeWritable(&a);
709
710 const int planes_y[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A };
711 const int planes_r[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A };
712 const int *planes;
713
714 int planeCount;
715 planeCount = vi.IsPlanar() ? vi.NumComponents() : 1;
716 planes = (!vi.IsPlanar() || vi.IsYUV() || vi.IsYUVA()) ? planes_y : planes_r;
717
718 const int bits_per_pixel = vi.BitsPerComponent();
719 for (int j = 0; j < planeCount; ++j)
720 {
721 const int plane = planes[j];
722 const BYTE* b_data = b->GetReadPtr(plane);
723 int b_pitch = b->GetPitch(plane);
724 BYTE* a_data = a->GetWritePtr(plane);
725 int a_pitch = a->GetPitch(plane);
726 int row_size = a->GetRowSize(plane);
727 int height = a->GetHeight(plane);
728
729 const int pixelsize = bits_per_pixel <= 8 ? 1 : (bits_per_pixel == 32 ? 4 : 2);
730 const int width = row_size / pixelsize;
731 const int cpuFlags = env->GetCPUFlags();
732 if (bits_per_pixel == 32) {
733 get_weighted_merge_float_fn(cpuFlags)(a_data, b_data, a_pitch, b_pitch, width, height, weight);
734 } else {
735 const int weight_i = (int)(weight * 32768.0f + 0.5f);
736 get_weighted_merge_fn(cpuFlags, weight_i)(a_data, b_data, a_pitch, b_pitch, width, height, weight_i, 32768 - weight_i, bits_per_pixel);
737 }
738 }
739 return a;
740 }
741
742
743 1 void Dissolve::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env)
744 {
745
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 1 time.
1 if (start+count <= audio_fade_start) {
746 child->GetAudio(buf, start, count, env);
747 return;
748 }
749
750
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 10 taken 1 time.
1 if (start > audio_fade_end) {
751 child2->GetAudio(buf, start - audio_fade_start, count, env);
752 return;
753 }
754
755 1 const size_t bytes = (size_t)vi.BytesFromAudioSamples(count);
756
1/2
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 16 not taken.
1 if (audbufsize < bytes) {
757
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 1 time.
1 delete[] audbuffer;
758 1 audbuffer = new BYTE[bytes];
759 1 audbufsize = bytes;
760 }
761
762 1 child->GetAudio(buf, start, count, env);
763 1 child2->GetAudio(audbuffer, start - audio_fade_start, count, env);
764
765 1 const int nch = vi.AudioChannels();
766 1 const int countXnch = (int)count*nch;
767 1 const int denominator = audio_overlap;
768 1 int numerator = (int)(audio_fade_end - start);
769
770
1/2
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 33 taken 1 time.
1 if (vi.IsSampleType(SAMPLE_INT16)) {
771 short *const a = (short*)buf;
772 const short *const b = (short*)audbuffer;
773
774 int i;
775 for (i=0; i<countXnch; i+=nch) {
776 if (numerator <= 0) { // Past end of dissolve
777 break;
778 }
779 else if (numerator < denominator) { // In dissolve region
780 for (int p=0; p < nch; p++)
781 a[i+p] = short(b[i+p] + MulDiv(a[i+p]-b[i+p], numerator, denominator));
782 }
783 // else // Before begining of dissolve
784 numerator--;
785 }
786 const int nchb = (countXnch - i) * sizeof(short);
787 memcpy(a+i, b+i, nchb);
788 return;
789 }
790
791
1/2
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 45 not taken.
1 if (vi.IsSampleType(SAMPLE_FLOAT)) {
792 1 const SFLOAT frdenominator = SFLOAT(1.0/denominator);
793 1 SFLOAT *const a = (SFLOAT*)buf;
794 1 const SFLOAT *const b = (SFLOAT*)audbuffer;
795
796 int i;
797
1/2
✓ Branch 43 → 36 taken 4 times.
✗ Branch 43 → 44 not taken.
4 for (i=0; i<countXnch; i+=nch) {
798
2/2
✓ Branch 36 → 37 taken 1 time.
✓ Branch 36 → 38 taken 3 times.
4 if (numerator <= 0) { // Past end of dissolve
799 1 break;
800 }
801
2/2
✓ Branch 38 → 39 taken 2 times.
✓ Branch 38 → 42 taken 1 time.
3 else if (numerator < denominator) { // In dissolve region
802 2 const SFLOAT w = numerator * frdenominator; // How far into the fade are we?
803
2/2
✓ Branch 41 → 40 taken 2 times.
✓ Branch 41 → 42 taken 2 times.
4 for (int p=0; p < nch; p++)
804 2 a[i+p] = b[i+p] + w * (a[i+p]-b[i+p]);
805 }
806 // else // Before begining of dissolve
807 3 numerator--; // When was a float only worked for N < 2^24
808 }
809 1 const int nchb = (countXnch - i) * sizeof(SFLOAT);
810 1 memcpy(a+i, b+i, nchb);
811 1 return;
812 }
813
814 env->ThrowError("Dissolve: Wow - this should never happend!");
815
816 }
817
818
819
820
821
822
823
824
825
826 /*********************************
827 ******* AudioDub Filter ******
828 *********************************/
829
830
2/4
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 42 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 40 not taken.
1 AudioDub::AudioDub(PClip child1, PClip child2, int mode, IScriptEnvironment* env)
831 {
832
1/2
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 38 not taken.
1 const VideoInfo& vi1 = child1->GetVideoInfo();
833
1/2
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 38 not taken.
1 const VideoInfo& vi2 = child2->GetVideoInfo();
834 1 const VideoInfo *vi_video=0, *vi_audio=0;
835
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 1 time.
1 if (mode) { // Unconditionally accept audio and video
836 vchild = child1; achild = child2;
837 vi_video = &vi1; vi_audio = &vi2;
838 }
839 else {
840
5/10
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 38 not taken.
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 18 not taken.
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 38 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 18 not taken.
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 23 not taken.
1 if (vi1.HasVideo() && vi2.HasAudio()) {
841
2/4
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 38 not taken.
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 38 not taken.
1 vchild = child1; achild = child2;
842 1 vi_video = &vi1, vi_audio = &vi2;
843 } else if (vi2.HasVideo() && vi1.HasAudio()) {
844 vchild = child2; achild = child1;
845 vi_video = &vi2, vi_audio = &vi1;
846 } else {
847 env->ThrowError("AudioDub: need an audio and a video track");
848 }
849 }
850
851 1 vi = *vi_video;
852 1 vi.audio_samples_per_second = vi_audio->audio_samples_per_second;
853 1 vi.num_audio_samples = vi_audio->num_audio_samples;
854 1 vi.sample_type = vi_audio->sample_type;
855 1 vi.nchannels = vi_audio->nchannels;
856
3/6
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 38 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 38 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 38 not taken.
1 vi.SetChannelMask(vi_audio->IsChannelMaskKnown(), vi_audio->GetChannelMask());
857 1 }
858
859
860 6 const VideoInfo& AudioDub::GetVideoInfo()
861 {
862 6 return vi;
863 }
864
865
866 PVideoFrame AudioDub::GetFrame(int n, IScriptEnvironment* env)
867 {
868 return vchild->GetFrame(n, env);
869 }
870
871
872 bool AudioDub::GetParity(int n)
873 {
874 return vchild->GetParity(n);
875 }
876
877
878 1 void AudioDub::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env)
879 {
880 1 achild->GetAudio(buf, start, count, env);
881 1 }
882
883 int __stdcall AudioDub::SetCacheHints(int cachehints,int frame_range)
884 {
885 AVS_UNUSED(frame_range);
886 switch(cachehints)
887 {
888 case CACHE_DONT_CACHE_ME:
889 return 1;
890 case CACHE_GET_MTMODE:
891 return MT_NICE_FILTER;
892 case CACHE_GET_DEV_TYPE:
893 return (vchild->GetVersion() >= 5) ? vchild->SetCacheHints(CACHE_GET_DEV_TYPE, 0) : 0;
894 default:
895 return 0;
896 }
897 }
898
899
900
901 AVSValue __cdecl AudioDub::Create(AVSValue args, void* mode, IScriptEnvironment* env)
902 {
903 return new AudioDub(args[0].AsClip(), args[1].AsClip(), (int)size_t(mode), env);
904 }
905
906
907
908
909
910
911
912
913
914 /*******************************
915 ******* Reverse Filter ******
916 *******************************/
917
918
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 6 not taken.
1 Reverse::Reverse(PClip _child) : GenericVideoFilter(_child) {}
919
920
921 PVideoFrame Reverse::GetFrame(int n, IScriptEnvironment* env)
922 {
923 return child->GetFrame(vi.num_frames-n-1, env);
924 }
925
926
927 bool Reverse::GetParity(int n)
928 {
929 return child->GetParity(vi.num_frames-n-1);
930 }
931
932
933 1 void Reverse::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env)
934 {
935 1 child->GetAudio(buf, vi.num_audio_samples - start - count, count, env);
936 1 const int bytes_per_sample = vi.BytesPerAudioSample(); // includes all channels
937 1 const int bytes_per_channel_sample = vi.BytesPerChannelSample();
938 1 const int nch = vi.AudioChannels();
939 1 uint8_t* buf2 = reinterpret_cast<uint8_t*>(buf);
940
941
1/5
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 16 taken 1 time.
✗ Branch 7 → 24 not taken.
✗ Branch 7 → 35 not taken.
✗ Branch 7 → 52 not taken.
1 switch (bytes_per_channel_sample) {
942 case 1: // 8-bit
943 for (int64_t i = 0; i < count / 2; ++i) {
944 uint8_t* a_ptr = buf2 + i * bytes_per_sample;
945 uint8_t* b_ptr = buf2 + (count - 1 - i) * bytes_per_sample;
946 for (int c = 0; c < nch; ++c) {
947 std::swap(a_ptr[c], b_ptr[c]);
948 }
949 }
950 break;
951 1 case 2: // 16-bit
952
2/2
✓ Branch 22 → 17 taken 2 times.
✓ Branch 22 → 23 taken 1 time.
3 for (int64_t i = 0; i < count / 2; ++i) {
953 2 int16_t* a_ptr = reinterpret_cast<int16_t*>(buf2 + i * bytes_per_sample);
954 2 int16_t* b_ptr = reinterpret_cast<int16_t*>(buf2 + (count - 1 - i) * bytes_per_sample);
955
2/2
✓ Branch 20 → 18 taken 4 times.
✓ Branch 20 → 21 taken 2 times.
6 for (int c = 0; c < nch; ++c) {
956 4 std::swap(a_ptr[c], b_ptr[c]);
957 }
958 }
959 1 break;
960 case 3: // 24-bit, keep brute force
961 for (int64_t i = 0; i < count / 2; ++i) {
962 uint8_t* a_ptr = buf2 + i * bytes_per_sample;
963 uint8_t* b_ptr = buf2 + (count - 1 - i) * bytes_per_sample;
964 for (int c = 0; c < nch; ++c) {
965 uint8_t* a_chan = a_ptr + c * 3;
966 uint8_t* b_chan = b_ptr + c * 3;
967 for (int j = 0; j < 3; ++j) {
968 std::swap(a_chan[j], b_chan[j]);
969 }
970 }
971 }
972 break;
973 case 4: // 32-bit int or float, separate because of swap templates
974 if (vi.IsSampleType(SAMPLE_FLOAT)) {
975 for (int64_t i = 0; i < count / 2; ++i) {
976 float* a_ptr = reinterpret_cast<float*>(buf2 + i * bytes_per_sample);
977 float* b_ptr = reinterpret_cast<float*>(buf2 + (count - 1 - i) * bytes_per_sample);
978 for (int c = 0; c < nch; ++c) {
979 std::swap(a_ptr[c], b_ptr[c]);
980 }
981 }
982 }
983 else {
984 for (int64_t i = 0; i < count / 2; ++i) {
985 int32_t* a_ptr = reinterpret_cast<int32_t*>(buf2 + i * bytes_per_sample);
986 int32_t* b_ptr = reinterpret_cast<int32_t*>(buf2 + (count - 1 - i) * bytes_per_sample);
987 for (int c = 0; c < nch; ++c) {
988 std::swap(a_ptr[c], b_ptr[c]);
989 }
990 }
991 }
992 break;
993 default: // generic case, no such sample size though
994 for (int64_t i = 0; i < count / 2; ++i) {
995 uint8_t* a_ptr = buf2 + i * bytes_per_sample;
996 uint8_t* b_ptr = buf2 + (count - 1 - i) * bytes_per_sample;
997 for (int c = 0; c < nch; ++c) {
998 uint8_t* a_chan = a_ptr + c * bytes_per_channel_sample;
999 uint8_t* b_chan = b_ptr + c * bytes_per_channel_sample;
1000 for (int j = 0; j < bytes_per_channel_sample; ++j) {
1001 std::swap(a_chan[j], b_chan[j]);
1002 }
1003 }
1004 }
1005 break;
1006 }
1007 1 }
1008
1009
1010 AVSValue __cdecl Reverse::Create(AVSValue args, void*, IScriptEnvironment* env)
1011 {
1012 AVS_UNUSED(env);
1013 return new Reverse(args[0].AsClip());
1014 }
1015
1016
1017
1018
1019
1020
1021
1022
1023 /*****************************
1024 ****** Loop Filter *******
1025 *****************************/
1026
1027 1 Loop::Loop(PClip _child, int times, int _start, int _end, IScriptEnvironment* env)
1028
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 33 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 31 not taken.
1 : GenericVideoFilter(_child), start(_start), end(_end)
1029 {
1030 1 start = clamp(start,0,vi.num_frames-1);
1031 1 end = clamp(end,start,vi.num_frames-1);
1032 1 frames = end-start+1;
1033
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 18 taken 1 time.
1 if (times<0) { // Loop nearly forever
1034 vi.num_frames = 10000000;
1035 end = vi.num_frames;
1036 if (vi.HasAudio()) {
1037 if (vi.HasVideo()) {
1038 aud_start = vi.AudioSamplesFromFrames(start);
1039 aud_end = vi.AudioSamplesFromFrames(end+1) - 1; // This is the output end sample
1040 aud_count = vi.AudioSamplesFromFrames(frames); // length of each loop in samples
1041 } else {
1042 // start and end frame numbers are meaningless without video
1043 aud_start = 0;
1044 aud_count = vi.num_audio_samples;
1045 aud_end = Int32x32To64(400000, vi.audio_samples_per_second);
1046 }
1047 vi.num_audio_samples = aud_end+1;
1048 }
1049 }
1050 else {
1051 1 vi.num_frames += (times-1) * frames;
1052
1053
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 1 time.
1 if (vi.num_frames < 0)
1054 env->ThrowError("Loop: Maximum number of frames exceeded.");
1055
1056 1 end = start + times * frames - 1;
1057
2/4
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 34 not taken.
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 30 not taken.
1 if (vi.HasAudio()) {
1058
2/4
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 34 not taken.
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 28 taken 1 time.
1 if (vi.HasVideo()) {
1059 aud_start = vi.AudioSamplesFromFrames(start);
1060 aud_end = vi.AudioSamplesFromFrames(end+1) - 1; // This is the output end sample
1061 aud_count = vi.AudioSamplesFromFrames(frames); // length of each loop in samples
1062 } else {
1063 // start and end frame numbers are meaningless without video
1064 1 aud_start = 0;
1065 1 aud_count = vi.num_audio_samples;
1066 1 aud_end = vi.num_audio_samples * times;
1067 }
1068 1 vi.num_audio_samples += (times-1) * aud_count;
1069 }
1070 }
1071 1 }
1072
1073
1074 PVideoFrame Loop::GetFrame(int n, IScriptEnvironment* env)
1075 {
1076 return child->GetFrame(convert(n), env);
1077 }
1078
1079
1080 bool Loop::GetParity(int n)
1081 {
1082 return child->GetParity(convert(n));
1083 }
1084
1085 1 void Loop::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env) {
1086 int64_t get_count, get_start;
1087 1 const int bpas = vi.BytesPerAudioSample();
1088 1 char* samples = (char*)buf;
1089
1090
2/2
✓ Branch 18 → 4 taken 3 times.
✓ Branch 18 → 19 taken 1 time.
4 while (count > 0) {
1091
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 3 times.
3 if (start > aud_end) { // tail of clip
1092 get_start = aud_start + aud_count + start - (aud_end+1);
1093 get_count = count;
1094 }
1095 else {
1096
1/2
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 8 not taken.
3 if (start > aud_start) // loop part of clip
1097 3 get_start = (start - aud_start) % aud_count + aud_start;
1098 else // head of clip
1099 get_start = start;
1100
1101 3 get_count = aud_count - (get_start - aud_start); // count to end of next iteration
1102
1103
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 3 times.
3 if (get_start+get_count > aud_end+1) // loop(0) case
1104 get_count = aud_end+1 - get_start;
1105
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 3 times.
3 else if (start+get_count > aud_end)
1106 get_count = count; // if is last iteration do all of remainder
1107
1108
2/2
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 2 times.
3 if (get_count > count) get_count = count;
1109 }
1110
1111 3 child->GetAudio(samples, get_start, get_count, env);
1112
1113 3 samples += get_count * bpas; // update dest start pointer
1114 3 start += get_count;
1115 3 count -= get_count;
1116 }
1117 1 }
1118
1119 __inline int Loop::convert(int n)
1120 {
1121 if (n>end) return n - end + start + frames - 1;
1122 else if (n>=start) return ((n - start) % frames) + start;
1123 else return n;
1124 }
1125
1126
1127 AVSValue __cdecl Loop::Create(AVSValue args, void*, IScriptEnvironment* env)
1128 {
1129 if (!args[0].AsClip()->GetVideoInfo().HasVideo() &&
1130 (args[2].Defined() || args[3].Defined())) {
1131 env->ThrowError("Loop: cannot use start or end frame numbers without a video track");
1132 }
1133 return new Loop(args[0].AsClip(), args[1].AsInt(-1), args[2].AsInt(0), args[3].AsInt(10000000),env);
1134 }
1135
1136
1137
1138
1139
1140
1141
1142 /******************************
1143 ** Assorted factory methods **
1144 *****************************/
1145
1146
1147 PClip __cdecl ColorClip(PClip a, int duration, AVSValue color, AVSValue color_yuv, AVSValue colors, float fps, IScriptEnvironment* env) {
1148 if (a->GetVideoInfo().HasVideo())
1149 {
1150 AVSValue blackness_args[] = { a, duration, color, color_yuv, colors };
1151 static const char* const arg_names[5] = { 0, 0, "color", "color_yuv", "colors" };
1152 return env->Invoke("BlankClip", AVSValue(blackness_args, 5), arg_names).AsClip();
1153 }
1154 else
1155 {
1156 AVSValue blackness_args[] = { a, duration, color, fps, color_yuv, colors };
1157 static const char* const arg_names[6] = { 0, 0, "color", "fps", "color_yuv", "colors" };
1158 return env->Invoke("BlankClip", AVSValue(blackness_args, 6), arg_names).AsClip();
1159 }
1160 }
1161
1162 AVSValue __cdecl Create_Fade(AVSValue args, void* user_data, IScriptEnvironment* env) {
1163 const int fade_type = (int)(intptr_t)user_data;
1164
1165 const int duration = args[1].AsInt();
1166 const float fps = args[3].AsFloatf(24.0f);
1167
1168 int offset = 0;
1169
1170 PClip a = args[0].AsClip();
1171
1172 switch (fade_type) {
1173 case FADE_MODE_OUT0:
1174 case FADE_MODE_IN0:
1175 case FADE_MODE_IO0: offset = 0; break;
1176 case FADE_MODE_OUT:
1177 case FADE_MODE_IN:
1178 case FADE_MODE_IO: offset = 1; break;
1179 case FADE_MODE_OUT2:
1180 case FADE_MODE_IN2:
1181 case FADE_MODE_IO2: offset = 2; break;
1182 }
1183
1184 PClip b = ColorClip(a, duration + offset, args[2] /* color */, args[4] /* color_yuv */, args[5] /* colors */, fps, env);
1185
1186 if(fade_type == FADE_MODE_OUT0 || fade_type == FADE_MODE_OUT || fade_type == FADE_MODE_OUT2)
1187 return new Dissolve(a, b, duration, fps, env);
1188 else if (fade_type == FADE_MODE_IN0 || fade_type == FADE_MODE_IN || fade_type == FADE_MODE_IN2)
1189 return new Dissolve(b, a, duration, fps, env);
1190 else {
1191 /* IO In-Out */
1192 AVSValue dissolve_args[] = { b, a, b, duration, fps };
1193 return env->Invoke("Dissolve", AVSValue(dissolve_args, 5)).AsClip();
1194 }
1195 }
1196