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