1 /***************************************************************************
2 ADM_vidDecTelecide - description
3 -------------------
4
5 email : fixounet@free.fr
6
7 Port of Donal Graft Decimate which is (c) Donald Graft
8 http://www.neuron2.net
9 http://puschpull.org/avisynth/decomb_reference_manual.html
10
11 ***************************************************************************/
12
13 /*
14 Decimate plugin for Avisynth -- performs 1-in-N
15 decimation on a stream of progressive frames, which are usually
16 obtained from the output of my Telecide plugin for Avisynth.
17 For each group of N successive frames, this filter deletes the
18 frame that is most similar to its predecessor. Thus, duplicate
19 frames coming out of Telecide can be removed using Decimate. This
20 filter adjusts the frame rate of the clip as
21 appropriate. Selection of the cycle size is selected by specifying
22 a parameter to Decimate() in the Avisynth scipt.
23
24 Copyright (C) 2003 Donald A. Graft
25
26 This program is free software; you can redistribute it and/or modify
27 it under the terms of the GNU General Public License as published by
28 the Free Software Foundation.
29
30 This program is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with this program; if not, write to the Free Software
37 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38
39 The author can be contacted at:
40 Donald Graft
41 neuron2@attbi.com.
42 */
43
44 #include "ADM_default.h"
45 #include "decimate.h"
46 #include "DIA_factory.h"
47
48 #include "dec_desc.cpp"
49
50 // Add the hook to make it valid plugin
51 DECLARE_VIDEO_FILTER( Decimate, // Class
52 1,0,0, // Version
53 ADM_UI_ALL, // UI
54 VF_INTERLACING, // Category
55 "decimate", // internal name (must be uniq!)
56 QT_TRANSLATE_NOOP("decimate","Decomb decimate"), // Display name
57 QT_TRANSLATE_NOOP("decimate","Donald Graft decimate. Remove duplicate after telecide.") // Description
58 );
59
60
61 /**
62 \fn configure
63 */
configure(void)64 bool Decimate::configure(void)
65 {
66 deciMate *_param=&configuration;
67 #define PX(x) &(configuration.x)
68 #define SZT(x) sizeof(x)/sizeof(diaMenuEntry *)
69
70 ELEM_TYPE_FLOAT t1=(ELEM_TYPE_FLOAT)_param->threshold;
71 ELEM_TYPE_FLOAT t2=(ELEM_TYPE_FLOAT)_param->threshold2;
72
73 diaMenuEntry tMode[]={
74 {0, QT_TRANSLATE_NOOP("decimate","Discard closer"),NULL},
75 {1, QT_TRANSLATE_NOOP("decimate","Replace (interpolate)"),NULL},
76 {2, QT_TRANSLATE_NOOP("decimate","Discard longer dupe (animés)"),NULL},
77 {3, QT_TRANSLATE_NOOP("decimate","Pulldown dupe removal"),NULL}
78 };
79 diaMenuEntry tQuality[]={
80 {0, QT_TRANSLATE_NOOP("decimate","Fastest (no chroma, partial luma)"),NULL},
81 // {1, QT_TRANSLATE_NOOP("decimate","Fast (partial luma and chroma)"),NULL},
82 {2, QT_TRANSLATE_NOOP("decimate","Medium (full luma, no chroma)"),NULL},
83 // {3, QT_TRANSLATE_NOOP("decimate","Slow (full luma and chroma)"),NULL}
84 };
85
86
87 diaElemMenu menuMode(PX(mode),QT_TRANSLATE_NOOP("decimate","_Mode:"), 4,tMode);
88 diaElemMenu menuQuality(PX(quality),QT_TRANSLATE_NOOP("decimate","_Quality:"), sizeof(tQuality)/sizeof(diaMenuEntry),tQuality);
89 diaElemFloat menuThresh1(&t1,QT_TRANSLATE_NOOP("decimate","_Threshold 1:"),0,100.);
90 diaElemFloat menuThresh2(&t2,QT_TRANSLATE_NOOP("decimate","T_hreshold 2:"),0,100.);
91 diaElemUInteger cycle(PX(cycle),QT_TRANSLATE_NOOP("decimate","C_ycle:"),2,40);
92 diaElemToggle show(PX(show),QT_TRANSLATE_NOOP("decimate","Sho_w"));
93 diaElem *elems[]={&cycle,&menuMode,&menuQuality,&menuThresh1,&menuThresh2,&show};
94
95 if(diaFactoryRun(QT_TRANSLATE_NOOP("decimate","Decomb Decimate"),6,elems))
96 {
97 _param->threshold=(double )t1;
98 _param->threshold2=(double )t2;
99 updateInfo();
100 reset();
101 return 1;
102 }
103 return 0;
104 }
105 /**
106 \fn getConfiguration
107 */
getConfiguration(void)108 const char *Decimate::getConfiguration(void)
109 {
110 static char strparam[255]={0};
111 snprintf(strparam,254," Decomb Decimate cycle:%d",configuration.cycle);
112 return strparam;
113 }
114 /**
115 \fn updateInfo
116 */
updateInfo(void)117 void Decimate::updateInfo(void)
118 {
119 if(configuration.cycle<2)
120 {
121 ADM_error("Telecide:bad configuration! cycle<2\n");
122 return;
123 }
124 double inc=info.frameIncrement;
125 inc*=configuration.cycle;
126 inc/=configuration.cycle-1;
127 info.frameIncrement=inc;
128
129 }
130 /**
131 \fn reset
132 \brief reset counters. Must be called each time a change is made (params/seek)
133 */
reset(void)134 void Decimate::reset(void)
135 {
136 last_request = -1;
137 firsttime = true;
138 all_video_cycle = true;
139 hints_invalid=false;
140 }
141 /**
142 \fn Ctor
143 */
Decimate(ADM_coreVideoFilter * in,CONFcouple * couples)144 Decimate::Decimate( ADM_coreVideoFilter *in,CONFcouple *couples) :
145 ADM_coreVideoFilterCached(11,in,couples)
146 {
147
148 char buf[80];
149 unsigned int *p;
150 deciMate *_param=&configuration;
151 //
152 // Init here
153 if(!couples || !ADM_paramLoad(couples,deciMate_param,&configuration))
154 {
155 _param->cycle=5;
156 _param->mode=3;
157 _param->show=false;
158 _param->debug=false;
159 _param->quality=2;
160 _param->threshold=0;
161 _param->threshold2=3.0;
162 }
163
164 ADM_assert(_param->cycle);
165
166 if (_param->mode == 0 || _param->mode == 2 || _param->mode == 3)
167 {
168 updateInfo();
169 }
170 sum = (unsigned int *) ADM_alloc(MAX_BLOCKS * MAX_BLOCKS * sizeof(unsigned int));
171 ADM_assert(sum);
172
173
174 if (configuration.debug)
175 {
176 OutputDebugString( "Decimate %s by Donald Graft, Copyright 2003\n", 0); // VERSION
177 }
178
179 reset();
180 }
181 /**
182 \fn getCoupledConf
183 */
getCoupledConf(CONFcouple ** couples)184 bool Decimate::getCoupledConf(CONFcouple **couples)
185 {
186 return ADM_paramSave(couples, deciMate_param,&configuration);
187 }
188
setCoupledConf(CONFcouple * couples)189 void Decimate::setCoupledConf(CONFcouple *couples)
190 {
191 ADM_paramLoad(couples, deciMate_param, &configuration);
192 }
193 /**
194 \fn dtor
195 */
~Decimate(void)196 Decimate::~Decimate(void)
197 {
198 if (sum != NULL) ADM_dealloc(sum);
199 sum=NULL;
200 }
201
202 /**
203 \fn getNextFrame
204 */
205
getNextFrame(uint32_t * fn,ADMImage * data)206 bool Decimate::getNextFrame(uint32_t *fn,ADMImage *data)
207 {
208 switch(configuration.mode)
209 {
210 case 0: return get0(fn,data);break;
211 case 1: return get1(fn,data);break;
212 case 2: return get2(fn,data);break;
213 case 3: return get3(fn,data);break;
214 default: ADM_assert(0);
215 }
216 return false;
217 }
218 /**
219 \fn get0
220 \brief A B C... if B is close enough to A discard it.
221 */
get0(uint32_t * fn,ADMImage * data)222 bool Decimate::get0(uint32_t *fn,ADMImage *data)
223 {
224
225 bool forced = false;
226 ADMImage *src,*next;
227 double metric;
228 char buf[256];
229 int useframe,dropframe;
230 int start;
231 deciMate *_param=&configuration;
232 /* Normal decimation. Remove the frame most similar to its preceding frame. */
233 /* Determine the correct frame to use and get it. */
234 int cycle=configuration.cycle;
235 int sourceFrame = (nextFrame*cycle)/(cycle-1);
236 int cycleStartFrame = (sourceFrame / cycle) * cycle;
237 int inframe=nextFrame;
238 *fn=nextFrame;
239 GETFRAME(sourceFrame, src);
240 if(!src)
241 {
242 ADM_info("Decimate: End of video stream, cannot get frame %d\n",useframe);
243 vidCache->unlockAll();
244 return false;
245 }
246 nextFrame++;
247
248
249 FindDuplicate(cycleStartFrame, &dropframe, &metric, &forced);
250 if (sourceFrame >= dropframe) sourceFrame++;
251 GETFRAME(sourceFrame, src);
252 if(!src)
253 {
254 vidCache->unlockAll();
255 return false;
256 }
257 data->duplicate(src);
258 vidCache->unlockAll();
259
260 if (configuration.show == true)
261 {
262 sprintf(buf, "Decimate %d", 0); DrawString(data, 0, 0, buf);
263 sprintf(buf, "Copyright 2003 Donald Graft"); DrawString(data, 0, 1, buf);
264 sprintf(buf,"%d: %3.2f", start, showmetrics[0]); DrawString(data, 0, 3, buf);
265 sprintf(buf,"%d: %3.2f", start + 1, showmetrics[1]); DrawString(data, 0, 4, buf);
266 sprintf(buf,"%d: %3.2f", start + 2, showmetrics[2]); DrawString(data, 0, 5, buf);
267 sprintf(buf,"%d: %3.2f", start + 3, showmetrics[3]); DrawString(data, 0, 6, buf);
268 sprintf(buf,"%d: %3.2f", start + 4, showmetrics[4]); DrawString(data, 0, 7, buf);
269 sprintf(buf,"in frm %d, use frm %d", inframe, useframe);DrawString(data, 0, 8, buf);
270 sprintf(buf,"dropping frm %d%s", dropframe, last_forced == true ? ", forced!" : "");
271 DrawString(data, 0, 9, buf);
272 }
273 if (configuration.debug)
274 {
275 if (!(inframe % _param->cycle))
276 {
277 OutputDebugString("Decimate: %d: %3.2f\n", start, showmetrics[0]);
278 OutputDebugString("Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
279 OutputDebugString("Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
280 OutputDebugString("Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
281 OutputDebugString("Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
282 }
283 OutputDebugString("Decimate: in frm %d, use frm %d\n", inframe, useframe);
284 OutputDebugString("Decimate: dropping frm %d%s\n", dropframe, last_forced == true ? ", forced!" : "");
285 }
286 return true;
287 }
288 /**
289 \fn get1
290 \brief mode=1, A B C D => A BC D, i.e. (B,C) is replaced by BC, blend between B & C
291 */
292
get1(uint32_t * fn,ADMImage * data)293 bool Decimate::get1(uint32_t *fn,ADMImage *data)
294 {
295 bool forced = false;
296 ADMImage *src,*next;
297 int useframe,dropframe;
298 deciMate *_param=&configuration;
299 int cycle=configuration.cycle;
300 int sourceFrame = (nextFrame*cycle)/(cycle-1);
301 int cycleStartFrame = (sourceFrame / cycle) * cycle;
302 unsigned int hint, film = 1;
303 int inframe=nextFrame;
304 double metric;
305 char buf[256];
306
307 GETFRAME(sourceFrame, src);
308 if(!src)
309 {
310 ADM_info("Decimate: End of video stream, cannot get frame %d\n",useframe);
311 vidCache->unlockAll();
312 return false;
313 }
314 *fn=nextFrame;
315 nextFrame++;
316
317
318 if (GetHintingData(YPLANE(src), &hint) == false)
319 {
320 film = hint & PROGRESSIVE;
321 }
322
323 /* Find the most similar frame as above but replace it with a blend of
324 the preceding and following frames. */
325 FindDuplicate(cycleStartFrame, &dropframe, &metric, &forced);
326 if (!film || sourceFrame != dropframe || (_param->threshold && metric > _param->threshold))
327 {
328 data->duplicate(src);
329 vidCache->unlockAll();
330 if (configuration.show == true)
331 {
332
333 sprintf(buf, "Decimate %d", 0); DrawString(data, 0, 0, buf);
334 sprintf(buf, "Copyright 2003 Donald Graft"); DrawString(data, 0, 1, buf);
335 sprintf(buf,"%d: %3.2f", cycleStartFrame, showmetrics[0]); DrawString(data, 0, 3, buf);
336 sprintf(buf,"%d: %3.2f", cycleStartFrame + 1, showmetrics[1]); DrawString(data, 0, 4, buf);
337 sprintf(buf,"%d: %3.2f", cycleStartFrame + 2, showmetrics[2]); DrawString(data, 0, 5, buf);
338 sprintf(buf,"%d: %3.2f", cycleStartFrame + 3, showmetrics[3]); DrawString(data, 0, 6, buf);
339 sprintf(buf,"%d: %3.2f", cycleStartFrame + 4, showmetrics[4]); DrawString(data, 0, 7, buf);
340 sprintf(buf,"infrm %d", inframe);
341 DrawString(data, 0, 8, buf);
342 if (last_forced == false)
343 sprintf(buf,"chose %d, passing through", dropframe);
344 else
345 sprintf(buf,"chose %d, passing through, forced!", dropframe);
346 DrawString(data, 0, 9, buf);
347 }
348 if (configuration.debug)
349 {
350 if (!(inframe % _param->cycle))
351 {
352 OutputDebugString("Decimate: %d: %3.2f\n", start, showmetrics[0]);
353 OutputDebugString("Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
354 OutputDebugString("Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
355 OutputDebugString("Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
356 OutputDebugString("Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
357 }
358 OutputDebugString("Decimate: in frm %d\n", inframe);
359
360 if (last_forced == false)
361 {
362 OutputDebugString("Decimate: chose %d, passing through\n", dropframe);
363 }
364 else
365 {
366 OutputDebugString("Decimate: chose %d, passing through, forced!\n", dropframe);
367 }
368 }
369 return true;
370 }
371 if (configuration.debug)
372 {
373 if (!(inframe % _param->cycle))
374 {
375 OutputDebugString( "Decimate: %d: %3.2f\n", start, showmetrics[0]);
376 OutputDebugString( "Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
377 OutputDebugString( "Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
378 OutputDebugString( "Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
379 OutputDebugString( "Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
380 }
381 OutputDebugString("Decimate: in frm %d\n", inframe);
382
383 if (last_forced == false)
384 {
385 OutputDebugString("Decimate: chose %d, blending %d and %d\n", dropframe, inframe, nextfrm);
386 }
387 else
388 {
389 OutputDebugString("Decimate: chose %d, blending %d and %d, forced!\n", dropframe, inframe, nextfrm);
390 }
391 }
392 // Blend current frame with next frame
393 GETFRAME(sourceFrame+1, next);
394 if(!next)
395 data->duplicate(src);
396 else
397 data->blend(src,next);
398 vidCache->unlockAll();
399 if (configuration.show == true)
400 {
401
402 sprintf(buf, "Decimate %d", 0); DrawString(data, 0, 0, buf);
403 sprintf(buf, "Copyright 2003 Donald Graft"); DrawString(data, 0, 1, buf);
404 sprintf(buf,"%d: %3.2f", cycleStartFrame, showmetrics[0]); DrawString(data, 0, 3, buf);
405 sprintf(buf,"%d: %3.2f", cycleStartFrame + 1, showmetrics[1]); DrawString(data, 0, 4, buf);
406 sprintf(buf,"%d: %3.2f", cycleStartFrame + 2, showmetrics[2]); DrawString(data, 0, 5, buf);
407 sprintf(buf,"%d: %3.2f", cycleStartFrame + 3, showmetrics[3]); DrawString(data, 0, 6, buf);
408 sprintf(buf,"%d: %3.2f", cycleStartFrame + 4, showmetrics[4]); DrawString(data, 0, 7, buf);
409 sprintf(buf,"infrm %d", inframe);
410 DrawString(data, 0, 8, buf);
411 if (last_forced == false)
412 sprintf(buf,"chose %d, blending %d and %d",dropframe, sourceFrame, sourceFrame+1);
413 else
414 sprintf(buf,"chose %d, blending %d and %d, forced!", dropframe, sourceFrame, sourceFrame+1);
415 DrawString(data, 0, 9, buf);
416 }
417
418 return true;
419 }
420 /**
421 \fn get2
422 \fn remove one frame from longest duplicate (anime)
423 */
424
get2(uint32_t * fn,ADMImage * data)425 bool Decimate::get2(uint32_t *fn,ADMImage *data)
426 {
427 bool forced = false;
428 double metric;
429 char buf[256];
430
431 deciMate *_param=&configuration;
432 int cycle=configuration.cycle;
433 int sourceFrame = (nextFrame*cycle)/(cycle-1);
434 int cycleStartFrame = (sourceFrame / cycle) * cycle;
435 int useframe,dropframe;
436 *fn=nextFrame;
437 int inframe=nextFrame;
438 ADMImage *src,*next;
439 GETFRAME(sourceFrame, src);
440 if(!src)
441 {
442 ADM_info("Decimate: End of video stream, cannot get frame %d\n",useframe);
443 vidCache->unlockAll();
444 return false;
445 }
446 nextFrame++;
447 /* Delete the duplicate in the longest string of duplicates. */
448 FindDuplicate2(cycleStartFrame, &dropframe, &forced);
449 if (sourceFrame >= dropframe)
450 sourceFrame++;
451 GETFRAME(sourceFrame, src);
452 if(!src)
453 {
454 vidCache->unlockAll();
455 return false;
456 }
457 data->duplicate(src);
458 vidCache->unlockAll();
459 if (configuration.show == true)
460 {
461 int start = (useframe / _param->cycle) * _param->cycle;
462
463
464 sprintf(buf, "Decimate %d", 0); DrawString(data, 0, 0, buf);
465 sprintf(buf, "Copyright 2003 Donald Graft"); DrawString(data, 0, 1, buf);
466 sprintf(buf,"in frm %d, use frm %d", inframe, useframe); DrawString(data, 0, 3, buf);
467 sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame, showmetrics[0], Dshow[0] ? "new" : "dup"); DrawString(data, 0, 4, buf);
468 sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 1, showmetrics[1],Dshow[1] ? "new" : "dup");DrawString(data, 0, 5, buf);
469 sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 2, showmetrics[2],Dshow[2] ? "new" : "dup");DrawString(data, 0, 6, buf);
470 sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 3, showmetrics[3],Dshow[3] ? "new" : "dup");DrawString(data, 0, 7, buf);
471 sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 4, showmetrics[4],Dshow[4] ? "new" : "dup");DrawString(data, 0, 8, buf);
472 sprintf(buf,"Dropping frm %d%s", dropframe, last_forced == true ? " forced!" : "");
473 DrawString(data, 0, 9, buf);
474 }
475 if (configuration.debug)
476 {
477 sprintf(buf,"Decimate: inframe %d useframe %d\n", inframe, useframe);
478 OutputDebugString(buf);
479 }
480 return true;
481 }
482 /**
483 \fn get3
484 \brief ivtc (after telecide)
485 */
486
get3(uint32_t * fn,ADMImage * data)487 bool Decimate::get3(uint32_t *fn,ADMImage *data)
488 {
489 bool forced = false;
490 ADMImage *src,*next;
491 int dropframe;
492 double metric;
493 char buf[256];
494
495 deciMate *_param=&configuration;
496 /* Decimate by removing a duplicate from film cycles and doing a
497 blend rate conversion on the video cycles. */
498 if (_param->cycle != 5)// env->ThrowError("Decimate: mode=3 requires cycle=5");
499 {
500 ADM_error("Decimate: mode=3 requires cycle=5\n");
501 return false;
502 }
503 int sourceFrame = (nextFrame*5)/4;
504 int cycleStartFrame = (sourceFrame /5) * 5;
505
506 *fn=nextFrame;
507 GETFRAME(sourceFrame, src);
508 if(!src)
509 {
510 ADM_info("Decimate: End of video stream, cannot get frame %d\n",sourceFrame);
511 vidCache->unlockAll();
512 return false;
513 }
514 int inframe=nextFrame;
515 nextFrame++;
516 FindDuplicate(cycleStartFrame, &dropframe, &metric, &forced);
517 /* Use hints from Telecide about film versus video. Also use the difference
518 metric of the most similar frame in the cycle; if it exceeds threshold,
519 assume it's a video cycle. */
520 if (!(inframe % 4))
521 {
522 all_video_cycle = false;
523 if (_param->threshold && metric > _param->threshold)
524 {
525 all_video_cycle = true;
526 }
527 if ((hints_invalid == false) &&
528 (!(hints[0] & PROGRESSIVE) ||
529 !(hints[1] & PROGRESSIVE) ||
530 !(hints[2] & PROGRESSIVE) ||
531 !(hints[3] & PROGRESSIVE) ||
532 !(hints[4] & PROGRESSIVE)))
533 {
534 all_video_cycle = true;
535 }
536 }
537 if (all_video_cycle == false)
538 {
539 /* It's film, so decimate in the normal way. */
540 if (sourceFrame >= dropframe) sourceFrame++;
541 GETFRAME(sourceFrame, src);
542 if(!src)
543 {
544 vidCache->unlockAll();
545 return false;
546 }
547 data->duplicate(src);
548 vidCache->unlockAll();
549 DrawShow(data, sourceFrame, forced, dropframe, metric, inframe);
550 return true; // return src;
551 }
552 else
553 {
554 switch(inframe %4)
555 {
556 case 0:
557 /* It's a video cycle. Output the first frame of the cycle. */
558 GETFRAME(sourceFrame, src);
559 data->duplicate(src);
560 vidCache->unlockAll();
561 break;
562 case 3:
563 /* It's a video cycle. Output the last frame of the cycle. */
564 GETFRAME(sourceFrame+1, src);
565 if(!src)
566 {
567 vidCache->unlockAll();
568 return false;
569 }
570 data->duplicate(src);
571 vidCache->unlockAll();
572 break;
573 case 1: case 2:
574 /* It's a video cycle. Make blends for the remaining frames. */
575 if ((inframe % 4) == 1) // MEANX dont understand the difference ?
576 {
577 GETFRAME(sourceFrame, src);
578 GETFRAME(sourceFrame+1, next);
579 if(!next) next=src;
580 }
581 else
582 {
583 GETFRAME(sourceFrame + 1, src);
584 GETFRAME(sourceFrame, next);
585 if(!src) src=next;
586 }
587 data->blend(src,next);
588 vidCache->unlockAll();
589 break;
590 default:
591 ADM_assert(0);break;
592 }
593 DrawShow(data, 0, forced, dropframe, metric, inframe);
594 return true; // return src;
595 }
596 GETFRAME(sourceFrame, src); // MEANX : not sure (jw detected a problem here)
597 data->duplicate(src);
598 vidCache->unlockAll();
599 DrawShow(data, 0, forced, dropframe, metric, inframe);
600 return true;
601 }
602
603 /**
604 \fn goToTime
605 */
goToTime(uint64_t usSeek)606 bool Decimate::goToTime(uint64_t usSeek)
607 {
608 reset();
609 return ADM_coreVideoFilterCached::goToTime(usSeek);
610 }
611 // EOF
612