GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 18.8% 114 / 0 / 606
Functions: 25.6% 10 / 0 / 39
Branches: 8.0% 110 / 0 / 1380

filters/field.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
36 #include "field.h"
37 #ifdef INTEL_INTRINSICS
38 #include "intel/resample_sse.h"
39 #else
40 #include "resample.h"
41 #endif
42 #include <avs/minmax.h>
43 #include "../core/internal.h"
44 #include "../convert/convert_helper.h"
45 #include <vector>
46
47
48 /**** Factory methods ****/
49
50 static AVSValue __cdecl Create_DoubleWeave(AVSValue args, void*, IScriptEnvironment* env);
51 static AVSValue __cdecl Create_Weave(AVSValue args, void*, IScriptEnvironment* env);
52 static AVSValue __cdecl Create_Pulldown(AVSValue args, void*, IScriptEnvironment* env);
53 static AVSValue __cdecl Create_SwapFields(AVSValue args, void*, IScriptEnvironment* env);
54 static AVSValue __cdecl Create_Bob(AVSValue args, void*, IScriptEnvironment* env);
55
56
57 /********************************************************************
58 ***** Declare index of new filters for Avisynth's filter engine *****
59 ********************************************************************/
60
61 extern const AVSFunction Field_filters[] = {
62 { "ComplementParity", BUILTIN_FUNC_PREFIX, "c", ComplementParity::Create },
63 { "AssumeTFF", BUILTIN_FUNC_PREFIX, "c", AssumeParity::Create, (void*)true },
64 { "AssumeBFF", BUILTIN_FUNC_PREFIX, "c", AssumeParity::Create, (void*)false },
65 { "AssumeFieldBased", BUILTIN_FUNC_PREFIX, "c", AssumeFieldBased::Create },
66 { "AssumeFrameBased", BUILTIN_FUNC_PREFIX, "c", AssumeFrameBased::Create },
67 { "SeparateColumns", BUILTIN_FUNC_PREFIX, "ci", SeparateColumns::Create },
68 { "WeaveColumns", BUILTIN_FUNC_PREFIX, "ci", WeaveColumns::Create },
69 { "SeparateRows", BUILTIN_FUNC_PREFIX, "ci", SeparateRows::Create },
70 { "WeaveRows", BUILTIN_FUNC_PREFIX, "ci", WeaveRows::Create },
71 { "SeparateFields", BUILTIN_FUNC_PREFIX, "c", SeparateFields::Create },
72 { "Weave", BUILTIN_FUNC_PREFIX, "c", Create_Weave },
73 { "DoubleWeave", BUILTIN_FUNC_PREFIX, "c", Create_DoubleWeave },
74 { "Pulldown", BUILTIN_FUNC_PREFIX, "cii", Create_Pulldown },
75 { "SelectEvery", BUILTIN_FUNC_PREFIX, "cii*", SelectEvery::Create },
76 { "SelectEven", BUILTIN_FUNC_PREFIX, "c", SelectEvery::Create_SelectEven },
77 { "SelectOdd", BUILTIN_FUNC_PREFIX, "c", SelectEvery::Create_SelectOdd },
78 { "Interleave", BUILTIN_FUNC_PREFIX, "c+", Interleave::Create },
79 { "SwapFields", BUILTIN_FUNC_PREFIX, "c", Create_SwapFields },
80 { "Bob", BUILTIN_FUNC_PREFIX, "c[b]f[c]f[height]i", Create_Bob },
81 { "SelectRangeEvery", BUILTIN_FUNC_PREFIX, "c[every]i[length]i[offset]i[audio]b", SelectRangeEvery::Create},
82 { NULL }
83 };
84
85
86
87
88
89 /*********************************
90 ******* SeparateColumns ******
91 *********************************/
92
93 SeparateColumns::SeparateColumns(PClip _child, int _interval, IScriptEnvironment* env)
94 : GenericVideoFilter(_child), interval(_interval)
95 {
96 if (_interval <= 0)
97 env->ThrowError("SeparateColumns: interval must be greater than zero.");
98
99 if (_interval > vi.width)
100 env->ThrowError("SeparateColumns: interval must be less than or equal width.");
101
102 if (vi.width % _interval)
103 env->ThrowError("SeparateColumns: width must be mod %d.", _interval);
104
105 vi.width /= _interval;
106 vi.MulDivFPS(_interval, 1);
107 vi.num_frames *= _interval;
108
109 if (vi.num_frames < 0)
110 env->ThrowError("SeparateColumns: Maximum number of frames exceeded.");
111
112
113 if (vi.IsYUY2() && vi.width & 1)
114 env->ThrowError("SeparateColumns: YUY2 output width must be even.");
115 if (vi.Is420() && vi.width & 1)
116 env->ThrowError("SeparateColumns: YUV420 output width must be even.");
117 if (vi.Is422() && vi.width & 1)
118 env->ThrowError("SeparateColumns: YUV422 output width must be even.");
119 if (vi.IsYV411() && vi.width & 3)
120 env->ThrowError("SeparateColumns: YV411 output width must be mod 4.");
121 }
122
123
124 PVideoFrame SeparateColumns::GetFrame(int n, IScriptEnvironment* env)
125 {
126 const int m = n%interval;
127 const int f = n/interval;
128
129 PVideoFrame src = child->GetFrame(f, env);
130 PVideoFrame dst = env->NewVideoFrameP(vi, &src);
131
132 if (vi.IsPlanar()) {
133 int planes_y[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A };
134 int planes_r[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A };
135 int *planes = (vi.IsYUV() || vi.IsYUVA()) ? planes_y : planes_r;
136 for (int p = 0; p < vi.NumComponents(); ++p) {
137 int plane = planes[p];
138 const int srcpitch = src->GetPitch(plane);
139 const int dstpitch = dst->GetPitch(plane);
140 const int height = dst->GetHeight(plane);
141 const int rowsize_pixels = dst->GetRowSize(plane) / vi.ComponentSize();
142
143 const BYTE* srcp = src->GetReadPtr(plane);
144 BYTE* dstp = dst->GetWritePtr(plane);
145
146 switch (vi.ComponentSize()) {
147 case 1:
148 for (int y = 0; y < height; y++) {
149 for (int i = m, j = 0; j < rowsize_pixels; i += interval, j += 1) {
150 dstp[j] = srcp[i];
151 }
152 srcp += srcpitch;
153 dstp += dstpitch;
154 }
155 break;
156 case 2:
157 for (int y = 0; y < height; y++) {
158 for (int i = m, j = 0; j < rowsize_pixels; i += interval, j += 1) {
159 reinterpret_cast<uint16_t *>(dstp)[j] = reinterpret_cast<const uint16_t *>(srcp)[i];
160 }
161 srcp += srcpitch;
162 dstp += dstpitch;
163 }
164 break;
165 case 4:
166 for (int y = 0; y < height; y++) {
167 for (int i = m, j = 0; j < rowsize_pixels; i += interval, j += 1) {
168 reinterpret_cast<float *>(dstp)[j] = reinterpret_cast<const float *>(srcp)[i];
169 }
170 srcp += srcpitch;
171 dstp += dstpitch;
172 }
173 break;
174 }
175 }
176 }
177 else if (vi.IsYUY2()) {
178 const int srcpitch = src->GetPitch();
179 const int dstpitch = dst->GetPitch();
180 const int height = dst->GetHeight();
181 const int rowsize = dst->GetRowSize();
182
183 const BYTE* srcp = src->GetReadPtr();
184 BYTE* dstp = dst->GetWritePtr();
185
186 const int m2 = m*2;
187 const int interval2 = interval*2;
188 const int interval4 = interval*4;
189
190 for (int y=0; y<height; y+=1) {
191 for (int i=m2, j=0; j<rowsize; i+=interval4, j+=4) {
192 // Luma
193 dstp[j+0] = srcp[i+0];
194 dstp[j+2] = srcp[i+interval2];
195 // Chroma
196 dstp[j+1] = srcp[i+m2+1];
197 dstp[j+3] = srcp[i+m2+3];
198 }
199 srcp += srcpitch;
200 dstp += dstpitch;
201 }
202 }
203 else if (vi.IsRGB24() || vi.IsRGB48()) {
204 const int srcpitch = src->GetPitch();
205 const int dstpitch = dst->GetPitch();
206 const int height = dst->GetHeight();
207 const int rowsize_pixels = dst->GetRowSize() / vi.ComponentSize();
208
209 const BYTE* srcp = src->GetReadPtr();
210 BYTE* dstp = dst->GetWritePtr();
211
212 const int m3 = m * 3;
213 const int interval3 = interval * 3;
214
215 if (vi.IsRGB24())
216 {
217 for (int y = 0; y < height; y += 1) {
218 for (int i = m3, j = 0; j < rowsize_pixels; i += interval3, j += 3) {
219 dstp[j + 0] = srcp[i + 0];
220 dstp[j + 1] = srcp[i + 1];
221 dstp[j + 2] = srcp[i + 2];
222 }
223 srcp += srcpitch;
224 dstp += dstpitch;
225 }
226 }
227 else {
228 // RGB48
229 for (int y = 0; y < height; y += 1) {
230 for (int i = m3, j = 0; j < rowsize_pixels; i += interval3, j += 3) {
231 reinterpret_cast<uint16_t *>(dstp)[j + 0] = reinterpret_cast<const uint16_t *>(srcp)[i + 0];
232 reinterpret_cast<uint16_t *>(dstp)[j + 1] = reinterpret_cast<const uint16_t *>(srcp)[i + 1];
233 reinterpret_cast<uint16_t *>(dstp)[j + 2] = reinterpret_cast<const uint16_t *>(srcp)[i + 2];
234 }
235 srcp += srcpitch;
236 dstp += dstpitch;
237 }
238 }
239 }
240 else if (vi.IsRGB32()) {
241 const int srcpitch4 = src->GetPitch()>>2;
242 const int dstpitch4 = dst->GetPitch()>>2;
243 const int height = dst->GetHeight();
244 const int rowsize4 = dst->GetRowSize()>>2;
245
246 const int* srcp4 = (const int*)src->GetReadPtr();
247 int* dstp4 = (int*)dst->GetWritePtr();
248
249 for (int y=0; y<height; y+=1) {
250 for (int i=m, j=0; j<rowsize4; i+=interval, j+=1) {
251 dstp4[j] = srcp4[i];
252 }
253 srcp4 += srcpitch4;
254 dstp4 += dstpitch4;
255 }
256 }
257 else if (vi.IsRGB64()) {
258 const int srcpitch8 = src->GetPitch()>>3;
259 const int dstpitch8 = dst->GetPitch()>>3;
260 const int height = dst->GetHeight();
261 const int rowsize8 = dst->GetRowSize()>>3;
262
263 const uint64_t* srcp8 = (const uint64_t*)src->GetReadPtr();
264 uint64_t* dstp8 = (uint64_t*)dst->GetWritePtr();
265
266 for (int y=0; y<height; y+=1) {
267 for (int i=m, j=0; j<rowsize8; i+=interval, j+=1) {
268 dstp8[j] = srcp8[i];
269 }
270 srcp8 += srcpitch8;
271 dstp8 += dstpitch8;
272 }
273 }
274 return dst;
275 }
276
277
278 AVSValue __cdecl SeparateColumns::Create(AVSValue args, void*, IScriptEnvironment* env)
279 {
280 if (args[1].AsInt() == 1)
281 return args[0];
282
283 return new SeparateColumns(args[0].AsClip(), args[1].AsInt(), env);
284 }
285
286
287
288
289
290
291
292 /*******************************
293 ******* WeaveColumns ******
294 *******************************/
295
296 WeaveColumns::WeaveColumns(PClip _child, int _period, IScriptEnvironment* env)
297 : GenericVideoFilter(_child), period(_period), inframes(vi.num_frames)
298 {
299 if (_period <= 0)
300 env->ThrowError("WeaveColumns: period must be greater than zero.");
301
302 vi.width *= _period;
303 vi.MulDivFPS(1, _period);
304 vi.num_frames += _period-1; // Ceil!
305 vi.num_frames /= _period;
306 }
307
308
309 PVideoFrame WeaveColumns::GetFrame(int n, IScriptEnvironment* env)
310 {
311 const int b = n * period;
312
313 PVideoFrame dst = env->NewVideoFrame(vi);
314
315 for (int m=0; m<period; m++) {
316 const int f = b+m < inframes ? b+m : inframes-1;
317 PVideoFrame src = child->GetFrame(f, env);
318 if(0 == m)
319 env->copyFrameProps(src, dst);
320
321 if (vi.IsPlanar()) {
322 int planes_y[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A };
323 int planes_r[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A };
324 int *planes = (vi.IsYUV() || vi.IsYUVA()) ? planes_y : planes_r;
325 for (int p = 0; p < vi.NumComponents(); ++p) {
326 int plane = planes[p];
327 BYTE *_dstp = dst->GetWritePtr(plane);
328 const int srcpitch = src->GetPitch(plane);
329 const int dstpitch = dst->GetPitch(plane);
330 const int height = src->GetHeight(plane);
331 const int rowsize_pixels = src->GetRowSize(plane) / vi.ComponentSize();
332
333 const BYTE* srcp = src->GetReadPtr(plane);
334 BYTE* dstp = _dstp;
335 switch (vi.ComponentSize()) {
336 case 1:
337 for (int y = 0; y < height; y++) {
338 for (int i = m, j = 0; j < rowsize_pixels; i += period, j += 1) {
339 dstp[i] = srcp[j];
340 }
341 srcp += srcpitch;
342 dstp += dstpitch;
343 }
344 break;
345 case 2:
346 for (int y = 0; y < height; y++) {
347 for (int i = m, j = 0; j < rowsize_pixels; i += period, j += 1) {
348 reinterpret_cast<uint16_t *>(dstp)[i] = reinterpret_cast<const uint16_t *>(srcp)[j];
349 }
350 srcp += srcpitch;
351 dstp += dstpitch;
352 }
353 break;
354 case 4:
355 for (int y = 0; y < height; y++) {
356 for (int i = m, j = 0; j < rowsize_pixels; i += period, j += 1) {
357 reinterpret_cast<float *>(dstp)[i] = reinterpret_cast<const float *>(srcp)[j];
358 }
359 srcp += srcpitch;
360 dstp += dstpitch;
361 }
362 break;
363 }
364 }
365 }
366 else if (vi.IsYUY2()) {
367 BYTE *_dstp = dst->GetWritePtr();
368 const int dstpitch = dst->GetPitch();
369
370 const int srcpitch = src->GetPitch();
371 const int height = src->GetHeight();
372 const int rowsize = src->GetRowSize();
373 const BYTE* srcp = src->GetReadPtr();
374 BYTE* dstp = _dstp;
375 const int m2 = m*2;
376 const int period2 = period*2;
377 const int period4 = period*4;
378
379 for (int y=0; y<height; y+=1) {
380 for (int i=m2, j=0; j<rowsize; i+=period4, j+=4) {
381 // Luma
382 dstp[i+0] = srcp[j+0];
383 dstp[i+period2] = srcp[j+2];
384 // Chroma
385 dstp[i+m2+1] = srcp[j+1];
386 dstp[i+m2+3] = srcp[j+3];
387 }
388 srcp += srcpitch;
389 dstp += dstpitch;
390 }
391 }
392 else if (vi.IsRGB24() || vi.IsRGB48()) {
393 BYTE *_dstp = dst->GetWritePtr();
394 const int dstpitch = dst->GetPitch();
395
396 const int srcpitch = src->GetPitch();
397 const int height = src->GetHeight();
398 const int rowsize_pixels = src->GetRowSize() / vi.ComponentSize();
399 const BYTE* srcp = src->GetReadPtr();
400 BYTE* dstp = _dstp;
401 const int m3 = m*3;
402 const int period3 = period*3;
403 if (vi.IsRGB24()) {
404 for (int y = 0; y < height; y += 1) {
405 for (int i = m3, j = 0; j < rowsize_pixels; i += period3, j += 3) {
406 dstp[i + 0] = srcp[j + 0];
407 dstp[i + 1] = srcp[j + 1];
408 dstp[i + 2] = srcp[j + 2];
409 }
410 srcp += srcpitch;
411 dstp += dstpitch;
412 }
413 }
414 else {
415 // RGB48
416 for (int y = 0; y < height; y += 1) {
417 for (int i = m3, j = 0; j < rowsize_pixels; i += period3, j += 3) {
418 reinterpret_cast<uint16_t *>(dstp)[i + 0] = reinterpret_cast<const uint16_t *>(srcp)[j + 0];
419 reinterpret_cast<uint16_t *>(dstp)[i + 1] = reinterpret_cast<const uint16_t *>(srcp)[j + 1];
420 reinterpret_cast<uint16_t *>(dstp)[i + 2] = reinterpret_cast<const uint16_t *>(srcp)[j + 2];
421 }
422 srcp += srcpitch;
423 dstp += dstpitch;
424 }
425 }
426 }
427 else if (vi.IsRGB32()) {
428 BYTE *_dstp = dst->GetWritePtr();
429 const int dstpitch = dst->GetPitch();
430
431 const int srcpitch4 = src->GetPitch()>>2;
432 const int dstpitch4 = dstpitch>>2;
433 const int height = src->GetHeight();
434 const int rowsize4 = src->GetRowSize()>>2;
435 const int* srcp4 = (const int*)src->GetReadPtr();
436 int* dstp4 = (int*)_dstp;
437
438 for (int y=0; y<height; y+=1) {
439 for (int i=m, j=0; j<rowsize4; i+=period, j+=1) {
440 dstp4[i] = srcp4[j];
441 }
442 srcp4 += srcpitch4;
443 dstp4 += dstpitch4;
444 }
445 }
446 else if (vi.IsRGB64()) {
447 BYTE *_dstp = dst->GetWritePtr();
448 const int dstpitch = dst->GetPitch();
449
450 const int srcpitch8 = src->GetPitch()>>3;
451 const int dstpitch8 = dstpitch>>3;
452 const int height = src->GetHeight();
453 const int rowsize8 = src->GetRowSize()>>3;
454 const uint64_t* srcp8 = (const uint64_t*)src->GetReadPtr();
455 uint64_t* dstp8 = (uint64_t*)_dstp;
456
457 for (int y=0; y<height; y+=1) {
458 for (int i=m, j=0; j<rowsize8; i+=period, j+=1) {
459 dstp8[i] = srcp8[j];
460 }
461 srcp8 += srcpitch8;
462 dstp8 += dstpitch8;
463 }
464 }
465 }
466 return dst;
467 }
468
469
470 AVSValue __cdecl WeaveColumns::Create(AVSValue args, void*, IScriptEnvironment* env)
471 {
472 if (args[1].AsInt() == 1)
473 return args[0];
474
475 return new WeaveColumns(args[0].AsClip(), args[1].AsInt(), env);
476 }
477
478
479
480
481
482
483
484 /*********************************
485 ******* SeparateRows ******
486 *********************************/
487
488 SeparateRows::SeparateRows(PClip _child, int _interval, IScriptEnvironment* env)
489 : NonCachedGenericVideoFilter(_child), interval(_interval)
490 {
491 if (_interval <= 0)
492 env->ThrowError("SeparateRows: interval must be greater than zero.");
493
494 if (_interval > vi.height)
495 env->ThrowError("SeparateRows: interval must be less than or equal height.");
496
497 if (vi.height % _interval)
498 env->ThrowError("SeparateRows: height must be mod %d.", _interval);
499
500 vi.height /= _interval;
501 vi.MulDivFPS(_interval, 1);
502 vi.num_frames *= _interval;
503
504 if (vi.num_frames < 0)
505 env->ThrowError("SeparateRows: Maximum number of frames exceeded.");
506
507 if (vi.Is420() && vi.height & 1)
508 env->ThrowError("SeparateRows: YUV420 output height must be even.");
509 }
510
511
512 PVideoFrame SeparateRows::GetFrame(int n, IScriptEnvironment* env)
513 {
514 const int m = (vi.IsRGB() && !vi.IsPlanar())? interval-1 - n%interval : n%interval; // RGB upside-down
515 const int f = n/interval;
516
517 PVideoFrame frame = child->GetFrame(f, env);
518
519 if (vi.IsPlanar() && !vi.IsY()) {
520 int plane0 = vi.IsRGB() ? PLANAR_G : PLANAR_Y;
521 int plane1 = vi.IsRGB() ? PLANAR_B : PLANAR_U;
522 const int Ypitch = frame->GetPitch(plane0);
523 const int UVpitch = frame->GetPitch(plane1);
524 const int Yoffset = Ypitch * m;
525 const int UVoffset = UVpitch * m;
526
527 if (vi.NumComponents() == 4) {
528 int Aoffset = frame->GetPitch(PLANAR_A) * m;
529
530 return env->SubframePlanarA(frame, Yoffset, Ypitch * interval,
531 frame->GetRowSize(plane0), vi.height,
532 UVoffset, UVoffset, UVpitch * interval, Aoffset);
533 }
534 else {
535 return env->SubframePlanar(frame, Yoffset, Ypitch * interval,
536 frame->GetRowSize(plane0), vi.height,
537 UVoffset, UVoffset, UVpitch * interval);
538 }
539 }
540 const int pitch = frame->GetPitch();
541 return env->Subframe(frame, pitch * m, pitch * interval, frame->GetRowSize(), vi.height);
542 }
543
544
545 AVSValue __cdecl SeparateRows::Create(AVSValue args, void*, IScriptEnvironment* env)
546 {
547 if (args[1].AsInt() == 1)
548 return args[0];
549
550 return new SeparateRows(args[0].AsClip(), args[1].AsInt(), env);
551 }
552
553
554
555
556
557
558
559 /****************************
560 ******* WeaveRows ******
561 ****************************/
562
563 WeaveRows::WeaveRows(PClip _child, int _period, IScriptEnvironment* env)
564 : GenericVideoFilter(_child), period(_period), inframes(vi.num_frames)
565 {
566 if (_period <= 0)
567 env->ThrowError("WeaveRows: period must be greater than zero.");
568
569 vi.height *= _period;
570 vi.MulDivFPS(1, _period);
571 vi.num_frames += _period-1; // Ceil!
572 vi.num_frames /= _period;
573 }
574
575
576 PVideoFrame WeaveRows::GetFrame(int n, IScriptEnvironment* env)
577 {
578 const int b = n * period;
579 const int e = b + period;
580
581 PVideoFrame dst = env->NewVideoFrame(vi);
582 BYTE *dstp = dst->GetWritePtr();
583 const int dstpitch = dst->GetPitch();
584
585 if (vi.IsRGB() && !vi.IsPlanar()) { // RGB upsidedown
586 dstp += dstpitch * period;
587 for (int i=b; i<e; i++) {
588 dstp -= dstpitch;
589 const int j = i < inframes ? i : inframes-1;
590 PVideoFrame src = child->GetFrame(j, env);
591 if(i==b) // very first
592 env->copyFrameProps(src, dst);
593
594 env->BitBlt( dstp, dstpitch * period,
595 src->GetReadPtr(), src->GetPitch(),
596 src->GetRowSize(), src->GetHeight() );
597 }
598 }
599 else {
600 int planes_y[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A };
601 int planes_r[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A };
602 int *planes = (vi.IsYUV() || vi.IsYUVA()) ? planes_y : planes_r;
603 bool isYUY2 = vi.IsYUY2();
604 int dstpitch[4];
605 BYTE *dstp[4];
606 for (int p = 0; p < (isYUY2 ? 1 : vi.NumComponents()); ++p) {
607 int plane = planes[p];
608 dstpitch[p] = dst->GetPitch(plane);
609 dstp[p] = dst->GetWritePtr(plane);
610 }
611
612 for (int i=b; i<e; i++) {
613 const int j = i < inframes ? i : inframes-1;
614 PVideoFrame src = child->GetFrame(j, env);
615 if (i == b) // very first
616 env->copyFrameProps(src, dst);
617 for (int p = 0; p < (isYUY2 ? 1 : vi.NumComponents()); ++p) {
618 int plane = planes[p];
619 env->BitBlt(dstp[p], dstpitch[p] * period,
620 src->GetReadPtr(plane), src->GetPitch(plane),
621 src->GetRowSize(plane), src->GetHeight(plane) );
622 dstp[p] += dstpitch[p];
623 }
624 }
625 }
626 return dst;
627 }
628
629
630 AVSValue __cdecl WeaveRows::Create(AVSValue args, void*, IScriptEnvironment* env)
631 {
632 if (args[1].AsInt() == 1)
633 return args[0];
634
635 return new WeaveRows(args[0].AsClip(), args[1].AsInt(), env);
636 }
637
638
639
640
641
642
643
644 /*********************************
645 ******* SeparateFields ******
646 *********************************/
647
648 9 SeparateFields::SeparateFields(PClip _child, IScriptEnvironment* env)
649
2/4
✓ Branch 2 → 3 taken 9 times.
✗ Branch 2 → 21 not taken.
✓ Branch 3 → 4 taken 9 times.
✗ Branch 3 → 19 not taken.
9 : NonCachedGenericVideoFilter(_child)
650 {
651
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 9 times.
9 if (vi.height & 1)
652 env->ThrowError("SeparateFields: height must be even");
653
5/8
✓ Branch 7 → 8 taken 9 times.
✗ Branch 7 → 22 not taken.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 11 taken 7 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 2 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 9 times.
9 if (vi.Is420() && vi.height & 3)
654 env->ThrowError("SeparateFields: YUV420 height must be multiple of 4");
655 9 vi.height >>= 1;
656
1/2
✓ Branch 14 → 15 taken 9 times.
✗ Branch 14 → 22 not taken.
9 vi.MulDivFPS(2, 1);
657 9 vi.num_frames *= 2;
658
659
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 9 times.
9 if (vi.num_frames < 0)
660 env->ThrowError("SeparateFields: Maximum number of frames exceeded.");
661
662
1/2
✓ Branch 17 → 18 taken 9 times.
✗ Branch 17 → 22 not taken.
9 vi.SetFieldBased(true);
663 9 }
664
665
666 28 PVideoFrame SeparateFields::GetFrame(int n, IScriptEnvironment* env)
667 {
668 #ifdef CACHE_GROWTH_INFINITELY_TEST
669 // FIXME: debug for Issue #270
670 // See other occurencies of this define
671 // When filter is combined with non-SeparateFielded frames
672 // the cache can grow infinitely, behaves like a memory leak.
673 // Tried putting n or (n-1) or (n*2) instead of n >> 1 then the problem does not occur.
674 _RPT2(0, "SeparateFields::GetFrame before %d, >>1: %d\n", n, n >> 1);
675 #endif
676
2/2
✓ Branch 3 → 4 taken 27 times.
✓ Branch 3 → 90 taken 1 time.
28 PVideoFrame frame = child->GetFrame(n>>1, env);
677 #ifdef CACHE_GROWTH_INFINITELY_TEST
678 _RPT2(0, "SeparateFields::GetFrame after %d, >>1: %d\n", n, n >> 1);
679 #endif
680
2/4
✓ Branch 4 → 5 taken 27 times.
✗ Branch 4 → 88 not taken.
✓ Branch 5 → 6 taken 27 times.
✗ Branch 5 → 58 not taken.
27 if (vi.IsPlanar()) {
681
1/2
✓ Branch 6 → 7 taken 27 times.
✗ Branch 6 → 88 not taken.
27 const bool topfield = GetParity(n);
682
683
2/4
✓ Branch 7 → 8 taken 27 times.
✗ Branch 7 → 88 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 27 times.
27 int plane0 = vi.IsRGB() ? PLANAR_G : PLANAR_Y;
684
2/4
✓ Branch 11 → 12 taken 27 times.
✗ Branch 11 → 88 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 27 times.
27 int plane1 = vi.IsRGB() ? PLANAR_B : PLANAR_U;
685
1/2
✓ Branch 16 → 17 taken 27 times.
✗ Branch 16 → 88 not taken.
27 const int Ypitch = frame->GetPitch(plane0);
686
1/2
✓ Branch 18 → 19 taken 27 times.
✗ Branch 18 → 88 not taken.
27 const int UVpitch = frame->GetPitch(plane1);
687
2/2
✓ Branch 19 → 20 taken 13 times.
✓ Branch 19 → 21 taken 14 times.
27 const int UVoffset = !topfield ? UVpitch : 0;
688
2/2
✓ Branch 22 → 23 taken 13 times.
✓ Branch 22 → 24 taken 14 times.
27 const int Yoffset = !topfield ? Ypitch : 0;
689
690
2/4
✓ Branch 25 → 26 taken 27 times.
✗ Branch 25 → 88 not taken.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 45 taken 27 times.
27 if (vi.NumComponents() == 4) {
691 int Aoffset = !topfield ? frame->GetPitch(PLANAR_A) : 0;
692
693 return env->SubframePlanarA(frame, Yoffset, frame->GetPitch() * 2, frame->GetRowSize(), frame->GetHeight() >> 1,
694 UVoffset, UVoffset, frame->GetPitch(PLANAR_U) * 2, Aoffset);
695 }
696 else {
697
2/4
✓ Branch 48 → 49 taken 27 times.
✗ Branch 48 → 88 not taken.
✓ Branch 52 → 53 taken 27 times.
✗ Branch 52 → 88 not taken.
81 return env->SubframePlanar(frame, Yoffset, frame->GetPitch() * 2, frame->GetRowSize(), frame->GetHeight() >> 1,
698
4/8
✓ Branch 46 → 47 taken 27 times.
✗ Branch 46 → 88 not taken.
✓ Branch 50 → 51 taken 27 times.
✗ Branch 50 → 88 not taken.
✓ Branch 53 → 54 taken 27 times.
✗ Branch 53 → 84 not taken.
✓ Branch 54 → 55 taken 27 times.
✗ Branch 54 → 82 not taken.
81 UVoffset, UVoffset, frame->GetPitch(PLANAR_U) * 2);
699 }
700 }
701 return env->Subframe(frame,(GetParity(n) ^ vi.IsYUY2()) ? frame->GetPitch() : 0,
702 frame->GetPitch()*2, frame->GetRowSize(), frame->GetHeight()>>1);
703 27 }
704
705
706 AVSValue __cdecl SeparateFields::Create(AVSValue args, void*, IScriptEnvironment* env)
707 {
708 PClip clip = args[0].AsClip();
709 if (clip->GetVideoInfo().IsFieldBased())
710 env->ThrowError("SeparateFields: SeparateFields should be applied on frame-based material: use AssumeFrameBased() beforehand");
711
712 return new SeparateFields(clip, env);
713 }
714
715
716
717
718
719
720
721 /******************************
722 ******* Interleave *******
723 ******************************/
724
725 2 Interleave::Interleave(const std::vector<PClip>&& _child_array, IScriptEnvironment* env)
726
1/2
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 35 not taken.
4 : num_children((int)_child_array.size()), child_array(std::move(_child_array))
727 {
728
1/2
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 33 not taken.
2 vi = child_array[0]->GetVideoInfo();
729
1/2
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 33 not taken.
2 vi.MulDivFPS(num_children, 1);
730 2 vi.num_frames = (vi.num_frames - 1) * num_children + 1;
731
1/2
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 33 not taken.
2 child_devs = GetDeviceTypes(child_array[0]);
732
2/2
✓ Branch 29 → 14 taken 2 times.
✓ Branch 29 → 30 taken 2 times.
4 for (int i=1; i<num_children; ++i)
733 {
734
1/2
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 33 not taken.
2 const VideoInfo& vi2 = child_array[i]->GetVideoInfo();
735
2/4
✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 19 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 2 times.
2 if (vi.width != vi2.width || vi.height != vi2.height)
736 env->ThrowError("Interleave: videos must be of the same size.");
737
2/4
✓ Branch 20 → 21 taken 2 times.
✗ Branch 20 → 33 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 2 times.
2 if (!vi.IsSameColorspace(vi2))
738 env->ThrowError("Interleave: video formats don't match");
739
740 2 vi.num_frames = max(vi.num_frames, (vi2.num_frames - 1) * num_children + i + 1);
741
742
1/2
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 33 not taken.
2 child_devs &= GetDeviceTypes(child_array[i]);
743
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 2 times.
2 if (child_devs == 0)
744 env->ThrowError("Interleave: device types don't match");
745 }
746
1/2
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 2 times.
2 if (vi.num_frames < 0)
747 env->ThrowError("Interleave: Maximum number of frames exceeded.");
748
749 2 }
750
751 int __stdcall Interleave::SetCacheHints(int cachehints,int frame_range)
752 {
753 AVS_UNUSED(frame_range);
754 switch (cachehints)
755 {
756 case CACHE_DONT_CACHE_ME:
757 return 1;
758 case CACHE_GET_MTMODE:
759 return MT_NICE_FILTER;
760 case CACHE_GET_DEV_TYPE:
761 return child_devs;
762 default:
763 return 0;
764 }
765 }
766
767 AVSValue __cdecl Interleave::Create(AVSValue args, void*, IScriptEnvironment* env)
768 {
769 args = args[0];
770 const int num_args = args.ArraySize();
771 if (num_args == 1)
772 return args[0];
773
774 std::vector<PClip> children(num_args);
775
776 for (int i = 0; i < (int)children.size(); ++i)
777 children[i] = args[i].AsClip();
778
779 return new Interleave(std::move(children), env);
780 }
781
782
783
784
785
786
787 /*********************************
788 ******** SelectEvery *******
789 *********************************/
790
791
792 12 SelectEvery::SelectEvery(PClip _child, int _every, int _from, IScriptEnvironment* env)
793
2/4
✓ Branch 2 → 3 taken 12 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 12 times.
✗ Branch 3 → 9 not taken.
12 : NonCachedGenericVideoFilter(_child), every(_every), from(_from)
794 {
795
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 12 times.
12 if (_every == 0)
796 env->ThrowError("Parameter 'every' of SelectEvery cannot be zero.");
797
798
1/2
✓ Branch 7 → 8 taken 12 times.
✗ Branch 7 → 12 not taken.
12 vi.MulDivFPS(1, every);
799 12 vi.num_frames = (vi.num_frames-1-from) / every + 1;
800 12 }
801
802
803 AVSValue __cdecl SelectEvery::Create(AVSValue args, void*, IScriptEnvironment* env)
804 {
805 const int num_vals = args[2].ArraySize();
806 if (num_vals <= 1)
807 return new SelectEvery(args[0].AsClip(), args[1].AsInt(), num_vals>0 ? args[2][0].AsInt() : 0, env);
808 else {
809 std::vector<PClip> children(num_vals);
810
811 for (int i = 0; i < (int)children.size(); ++i)
812 children[i] = new SelectEvery(args[0].AsClip(), args[1].AsInt(), args[2][i].AsInt(), env);
813
814 return new Interleave(std::move(children), env);
815 }
816 }
817
818
819
820
821
822
823
824
825 /**************************************
826 ******** DoubleWeaveFields *******
827 *************************************/
828
829 5 DoubleWeaveFields::DoubleWeaveFields(PClip _child)
830
2/4
✓ Branch 2 → 3 taken 5 times.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 7 not taken.
5 : GenericVideoFilter(_child)
831 {
832 5 vi.height *= 2;
833
1/2
✓ Branch 5 → 6 taken 5 times.
✗ Branch 5 → 10 not taken.
5 vi.SetFieldBased(false);
834 5 }
835
836
837 10 void copy_field(const PVideoFrame& dst, const PVideoFrame& src, bool yuv, bool planarRGB, bool parity, IScriptEnvironment* env)
838 {
839
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 10 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
10 bool noTopBottom = yuv || planarRGB;
840
841
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 10 times.
10 int plane1 = planarRGB ? PLANAR_B : PLANAR_U;
842
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 10 times.
10 int plane2 = planarRGB ? PLANAR_R : PLANAR_V;
843
844 10 const int add_pitch = dst->GetPitch() * (parity ^ noTopBottom);
845 10 const int add_pitchUV = dst->GetPitch(plane1) * (parity ^ noTopBottom);
846 10 const int add_pitchA = dst->GetPitch(PLANAR_A) * (parity ^ noTopBottom);
847
848 10 env->BitBlt(dst->GetWritePtr() + add_pitch, dst->GetPitch()*2,
849 src->GetReadPtr(), src->GetPitch(),
850 src->GetRowSize(), src->GetHeight());
851
852 10 env->BitBlt(dst->GetWritePtr(plane1) + add_pitchUV, dst->GetPitch(plane1)*2,
853 src->GetReadPtr(plane1), src->GetPitch(plane1),
854 src->GetRowSize(plane1), src->GetHeight(plane1));
855
856 10 env->BitBlt(dst->GetWritePtr(plane2) + add_pitchUV, dst->GetPitch(plane2)*2,
857 src->GetReadPtr(plane2), src->GetPitch(plane2),
858 src->GetRowSize(plane2), src->GetHeight(plane2));
859
860 10 env->BitBlt(dst->GetWritePtr(PLANAR_A) + add_pitchA, dst->GetPitch(PLANAR_A)*2,
861 src->GetReadPtr(PLANAR_A), src->GetPitch(PLANAR_A),
862 src->GetRowSize(PLANAR_A), src->GetHeight(PLANAR_A));
863 10 }
864
865
866 6 PVideoFrame DoubleWeaveFields::GetFrame(int n, IScriptEnvironment* env)
867 {
868
1/2
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 45 not taken.
6 PVideoFrame a = child->GetFrame(n, env);
869
2/2
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 43 taken 1 time.
6 PVideoFrame b = child->GetFrame(n+1, env);
870
871
1/2
✓ Branch 6 → 7 taken 5 times.
✗ Branch 6 → 41 not taken.
5 PVideoFrame result = env->NewVideoFrameP(vi, &a);
872
873
1/2
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 39 not taken.
5 const bool parity = child->GetParity(n);
874
875
7/18
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 39 not taken.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 13 not taken.
✓ Branch 11 → 12 taken 5 times.
✗ Branch 11 → 39 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 5 times.
✓ Branch 15 → 16 taken 5 times.
✗ Branch 15 → 39 not taken.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 19 taken 5 times.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 39 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 20 not taken.
✓ Branch 21 → 22 taken 5 times.
✗ Branch 21 → 39 not taken.
5 copy_field(result, a, vi.IsYUV() || vi.IsYUVA(), vi.IsPlanarRGB() || vi.IsPlanarRGBA(), parity, env);
876
7/18
✓ Branch 22 → 23 taken 5 times.
✗ Branch 22 → 39 not taken.
✓ Branch 23 → 24 taken 5 times.
✗ Branch 23 → 26 not taken.
✓ Branch 24 → 25 taken 5 times.
✗ Branch 24 → 39 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 5 times.
✓ Branch 28 → 29 taken 5 times.
✗ Branch 28 → 39 not taken.
✗ Branch 29 → 30 not taken.
✓ Branch 29 → 32 taken 5 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 39 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
✓ Branch 34 → 35 taken 5 times.
✗ Branch 34 → 39 not taken.
5 copy_field(result, b, vi.IsYUV() || vi.IsYUVA(), vi.IsPlanarRGB() || vi.IsPlanarRGBA(), !parity, env);
877
878 5 return result;
879 6 }
880
881
882
883 /**************************************
884 ******** DoubleWeaveFrames *******
885 *************************************/
886
887 2 DoubleWeaveFrames::DoubleWeaveFrames(PClip _child)
888
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 9 not taken.
2 : GenericVideoFilter(_child)
889 {
890 2 vi.num_frames *= 2;
891
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 2 times.
2 if (vi.num_frames < 0)
892 vi.num_frames = 0x7FFFFFFF; // MAXINT
893
894
1/2
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 12 not taken.
2 vi.MulDivFPS(2, 1);
895 2 }
896
897 2 void copy_alternate_lines(const PVideoFrame& dst, const PVideoFrame& src, bool yuv, bool planarRGB, bool parity, IScriptEnvironment* env)
898 {
899
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
2 bool noTopBottom = yuv || planarRGB;
900
901
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2 times.
2 int plane1 = planarRGB ? PLANAR_B : PLANAR_U;
902
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 2 times.
2 int plane2 = planarRGB ? PLANAR_R : PLANAR_V;
903
904 2 const int src_add_pitch = src->GetPitch() * (parity ^ noTopBottom);
905 2 const int src_add_pitchUV = src->GetPitch(plane1) * (parity ^ noTopBottom);
906 2 const int src_add_pitchA = src->GetPitch(PLANAR_A) * (parity ^ noTopBottom);
907
908 2 const int dst_add_pitch = dst->GetPitch() * (parity ^ noTopBottom);
909 2 const int dst_add_pitchUV = dst->GetPitch(plane1) * (parity ^ noTopBottom);
910 2 const int dst_add_pitchA = dst->GetPitch(PLANAR_A) * (parity ^ noTopBottom);
911
912 4 env->BitBlt(dst->GetWritePtr() + dst_add_pitch, dst->GetPitch()*2,
913 2 src->GetReadPtr() + src_add_pitch, src->GetPitch()*2,
914 2 src->GetRowSize(), src->GetHeight()>>1);
915
916 4 env->BitBlt(dst->GetWritePtr(plane1) + dst_add_pitchUV, dst->GetPitch(plane1)*2,
917 2 src->GetReadPtr(plane1) + src_add_pitchUV, src->GetPitch(plane1)*2,
918 2 src->GetRowSize(plane1), src->GetHeight(plane1)>>1);
919
920 4 env->BitBlt(dst->GetWritePtr(plane2) + dst_add_pitchUV, dst->GetPitch(plane2)*2,
921 2 src->GetReadPtr(plane2) + src_add_pitchUV, src->GetPitch(plane2)*2,
922 2 src->GetRowSize(plane2), src->GetHeight(plane2)>>1);
923
924 4 env->BitBlt(dst->GetWritePtr(PLANAR_A) + dst_add_pitchA, dst->GetPitch(PLANAR_A)*2,
925 2 src->GetReadPtr(PLANAR_A) + src_add_pitchA, src->GetPitch(PLANAR_A)*2,
926 2 src->GetRowSize(PLANAR_A), src->GetHeight(PLANAR_A)>>1);
927 2 }
928
929
930 4 PVideoFrame DoubleWeaveFrames::GetFrame(int n, IScriptEnvironment* env)
931 {
932
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 5 taken 2 times.
4 if (!(n&1))
933 {
934 2 return child->GetFrame(n>>1, env);
935 }
936 else {
937
1/2
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 88 not taken.
2 PVideoFrame a = child->GetFrame(n>>1, env);
938
2/2
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 86 taken 1 time.
2 PVideoFrame b = child->GetFrame((n+1)>>1, env);
939
1/2
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 84 not taken.
1 bool parity = this->GetParity(n);
940
941
2/4
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 84 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 28 taken 1 time.
1 if (a->IsWritable()) {
942 copy_alternate_lines(a, b, vi.IsYUV() || vi.IsYUVA(), vi.IsPlanarRGB() || vi.IsPlanarRGBA(), !parity, env);
943 return a;
944 }
945
2/4
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 84 not taken.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 46 taken 1 time.
1 else if (b->IsWritable()) {
946 copy_alternate_lines(b, a, vi.IsYUV() || vi.IsYUVA(), vi.IsPlanarRGB() || vi.IsPlanarRGBA(), parity, env);
947 return b;
948 }
949 else {
950
1/2
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 83 not taken.
1 PVideoFrame result = env->NewVideoFrameP(vi, &a);
951
7/18
✓ Branch 47 → 48 taken 1 time.
✗ Branch 47 → 81 not taken.
✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 51 not taken.
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 81 not taken.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 52 taken 1 time.
✓ Branch 53 → 54 taken 1 time.
✗ Branch 53 → 81 not taken.
✗ Branch 54 → 55 not taken.
✓ Branch 54 → 57 taken 1 time.
✗ Branch 55 → 56 not taken.
✗ Branch 55 → 81 not taken.
✗ Branch 56 → 57 not taken.
✗ Branch 56 → 58 not taken.
✓ Branch 59 → 60 taken 1 time.
✗ Branch 59 → 81 not taken.
1 copy_alternate_lines(result, a, vi.IsYUV() || vi.IsYUVA(), vi.IsPlanarRGB() || vi.IsPlanarRGBA(), parity, env);
952
7/18
✓ Branch 60 → 61 taken 1 time.
✗ Branch 60 → 81 not taken.
✓ Branch 61 → 62 taken 1 time.
✗ Branch 61 → 64 not taken.
✓ Branch 62 → 63 taken 1 time.
✗ Branch 62 → 81 not taken.
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 65 taken 1 time.
✓ Branch 66 → 67 taken 1 time.
✗ Branch 66 → 81 not taken.
✗ Branch 67 → 68 not taken.
✓ Branch 67 → 70 taken 1 time.
✗ Branch 68 → 69 not taken.
✗ Branch 68 → 81 not taken.
✗ Branch 69 → 70 not taken.
✗ Branch 69 → 71 not taken.
✓ Branch 72 → 73 taken 1 time.
✗ Branch 72 → 81 not taken.
1 copy_alternate_lines(result, b, vi.IsYUV() || vi.IsYUVA(), vi.IsPlanarRGB() || vi.IsPlanarRGBA(), !parity, env);
953
1/2
✓ Branch 73 → 74 taken 1 time.
✗ Branch 73 → 81 not taken.
1 return result;
954 1 }
955 2 }
956 }
957
958
959
960
961
962 /*******************************
963 ******** Bob Filter *******
964 *******************************/
965
966 Fieldwise::Fieldwise(PClip _child1, PClip _child2)
967 : NonCachedGenericVideoFilter(_child1), child2(_child2)
968 { vi.SetFieldBased(false); } // Make FrameBased, leave IT_BFF and IT_TFF alone
969
970
971 PVideoFrame __stdcall Fieldwise::GetFrame(int n, IScriptEnvironment* env)
972 {
973 return (child->GetParity(n) ? child2 : child)->GetFrame(n, env);
974 }
975
976
977 bool __stdcall Fieldwise::GetParity(int n)
978 {
979 return child->GetParity(n) ^ (n&1); // ^ = XOR
980 }
981
982
983
984
985
986
987
988 /************************************
989 ******** Factory Methods *******
990 ***********************************/
991
992 static AVSValue __cdecl Create_DoubleWeave(AVSValue args, void*, IScriptEnvironment* env)
993 {
994 AVS_UNUSED(env);
995 PClip clip = args[0].AsClip();
996 if (clip->GetVideoInfo().IsFieldBased())
997 return new DoubleWeaveFields(clip);
998 else
999 return new DoubleWeaveFrames(clip);
1000 }
1001
1002
1003 static AVSValue __cdecl Create_Weave(AVSValue args, void*, IScriptEnvironment* env)
1004 {
1005 PClip clip = args[0].AsClip();
1006 if (!clip->GetVideoInfo().IsFieldBased())
1007 env->ThrowError("Weave: Weave should be applied on field-based material: use AssumeFieldBased() beforehand");
1008 return new SelectEvery(Create_DoubleWeave(args, 0, env).AsClip(), 2, 0, env);
1009 }
1010
1011
1012 static AVSValue __cdecl Create_Pulldown(AVSValue args, void*, IScriptEnvironment* env)
1013 {
1014 PClip clip = args[0].AsClip();
1015 std::vector<PClip> children(2);
1016 children[0] = new SelectEvery(clip, 5, args[1].AsInt() % 5, env);
1017 children[1] = new SelectEvery(clip, 5, args[2].AsInt() % 5, env);
1018 return new AssumeFrameBased(new Interleave(std::move(children), env));
1019 }
1020
1021
1022 static AVSValue __cdecl Create_SwapFields(AVSValue args, void*, IScriptEnvironment* env)
1023 {
1024 return new SelectEvery(new DoubleWeaveFields(new ComplementParity(
1025 new SeparateFields(args[0].AsClip(), env))), 2, 0, env);
1026 }
1027
1028
1029 static AVSValue __cdecl Create_Bob(AVSValue args, void*, IScriptEnvironment* env)
1030 {
1031 PClip clip = args[0].AsClip();
1032 if (!clip->GetVideoInfo().IsFieldBased())
1033 clip = new SeparateFields(clip, env);
1034
1035 const VideoInfo& vi = clip->GetVideoInfo();
1036
1037 bool preserve_center = true; // default Avisynth
1038 int chroma_placement = ChromaLocation_e::AVS_CHROMA_UNUSED; // default
1039
1040 const double b = args[1].AsDblDef(1./3.);
1041 const double c = args[2].AsDblDef(1./3.);
1042 const int new_height = args[3].AsInt(vi.height*2);
1043 MitchellNetravaliFilter filter(b, c);
1044 return new Fieldwise(new FilteredResizeV(clip, -0.25, vi.height,
1045 new_height, &filter, preserve_center, chroma_placement, env),
1046 new FilteredResizeV(clip, +0.25, vi.height,
1047 new_height, &filter, preserve_center, chroma_placement, env));
1048 }
1049
1050
1051 SelectRangeEvery::SelectRangeEvery(PClip _child, int _every, int _length, int _offset, bool _audio, IScriptEnvironment* env)
1052 : NonCachedGenericVideoFilter(_child), audio(_audio), achild(_child)
1053 {
1054 const int64_t num_audio_samples = vi.num_audio_samples;
1055
1056 AVSValue trimargs[3] = { _child, _offset, 0};
1057 PClip c = env->Invoke("Trim",AVSValue(trimargs,3)).AsClip();
1058 child = c;
1059 vi = c->GetVideoInfo();
1060
1061 every = clamp(_every,1,vi.num_frames);
1062 length = clamp(_length,1,every);
1063
1064 const int n = vi.num_frames;
1065 vi.num_frames = (n/every)*length+(n%every<length?n%every:length);
1066
1067 if (audio && vi.HasAudio()) {
1068 vi.num_audio_samples = vi.AudioSamplesFromFrames(vi.num_frames);
1069 } else {
1070 vi.num_audio_samples = num_audio_samples; // Undo Trim's work!
1071 }
1072 }
1073
1074
1075 PVideoFrame __stdcall SelectRangeEvery::GetFrame(int n, IScriptEnvironment* env)
1076 {
1077 return child->GetFrame((n/length)*every+(n%length), env);
1078 }
1079
1080
1081 bool __stdcall SelectRangeEvery::GetParity(int n)
1082 {
1083 return child->GetParity((n/length)*every+(n%length));
1084 }
1085
1086
1087 void __stdcall SelectRangeEvery::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env)
1088 {
1089 if (!audio) {
1090 // Use original unTrim'd child
1091 achild->GetAudio(buf, start, count, env);
1092 return;
1093 }
1094
1095 int64_t samples_filled = 0;
1096 BYTE* samples = (BYTE*)buf;
1097 const int bps = vi.BytesPerAudioSample();
1098 int startframe = vi.FramesFromAudioSamples(start);
1099 int64_t general_offset = start - vi.AudioSamplesFromFrames(startframe); // General compensation for startframe rounding.
1100
1101 while (samples_filled < count) {
1102 const int iteration = startframe / length; // Which iteration is this.
1103 const int iteration_into = startframe % length; // How far, in frames are we into this iteration.
1104 const int iteration_left = length - iteration_into; // How many frames is left of this iteration.
1105
1106 const int64_t iteration_left_samples = vi.AudioSamplesFromFrames(iteration_left);
1107 // This is the number of samples we can get without either having to skip, or being finished.
1108 const int64_t getsamples = min(iteration_left_samples, count-samples_filled);
1109 const int64_t start_offset = vi.AudioSamplesFromFrames(iteration * every + iteration_into) + general_offset;
1110
1111 child->GetAudio(&samples[samples_filled*bps], start_offset, getsamples, env);
1112 samples_filled += getsamples;
1113 startframe = (iteration+1) * length;
1114 general_offset = 0; // On the following loops, general offset should be 0, as we are either skipping.
1115 }
1116 }
1117
1118 AVSValue __cdecl SelectRangeEvery::Create(AVSValue args, void* user_data, IScriptEnvironment* env) {
1119 AVS_UNUSED(user_data);
1120 return new SelectRangeEvery(args[0].AsClip(), args[1].AsInt(1500), args[2].AsInt(50), args[3].AsInt(0), args[4].AsBool(true), env);
1121 }
1122