1 /*
2  *  tcyait.c
3  *
4  *  Copyright (C) Allan Snider - February 2007
5  *
6  *  This file is part of transcode, a video stream processing tool
7  *
8  *  transcode is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2, or (at your option)
11  *  any later version.
12  *
13  *  transcode is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with GNU Make; see the file COPYING.  If not, write to
20  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <math.h>
28 
29 /*
30  *	tcyait:
31  *		Yet Another Inverse Telecine filter.
32  *
33  *	Usage:
34  *		tcyait [-dnlotbwmEO] [arg...]
35  *			-d		Print debug information to stdout
36  *			-n		Do not drop frames, always de-interlace
37  *			-k		No forced keep frames
38  *			-l log		Input yait log file name
39  *			-o ops		Output yait frame ops file name
40  *			-t thresh	Interlace detection threshold (>1)
41  *			-b blend	forced blend threshold (>thresh)
42  *			-w size		Drop frame look ahead window (0-20)
43  *			-m mode		Transcode blend method (0-5)
44  *			-E thresh	Even pattern threhold [thresh]
45  *			-O thresh	Odd pattern threhold [thresh]
46  *			-N noise	minimum normalized delta, else considered noise
47  *
48  *		By default, reads "yait.log" and produces "yait.ops".
49  *
50  *	Description:
51  *
52  *		Read a yait log file (generated via -J yait=log), and analyze it to
53  *	produce a yait frame operations file.  The frame operations file contains
54  *	commands to the yait filter to drop, copy or save rows (to de-interlace),
55  *	or blend frames.  This will convert from NTSC 29.97 to 23.976 fps.  The file
56  *	generated is used as input for another transcode pass (-J yait=ops).
57  */
58 
59 
60 #define	YAIT_VERSION		"v0.2"
61 
62 #define	TRUE			1
63 #define	FALSE			0
64 
65 /* program defaults */
66 #define	Y_LOG_FN		"yait.log"	/* log file read */
67 #define	Y_OPS_FN		"yait.ops"	/* frame operation file written */
68 #define	Y_THRESH		1.2		/* even/odd ratio to detect interlace */
69 #define	Y_DROPWIN_SIZE		15		/* drop frame look ahead window */
70 #define	Y_DEINT_MODE		3		/* default transcode de-interlace mode */
71 
72 /* limits */
73 #define	Y_DEINT_MIN		0
74 #define	Y_DEINT_MAX		5
75 #define	Y_DROPWIN_MIN		0
76 #define	Y_DROPWIN_MAX		60
77 
78 #define	Y_MTHRESH		1.02		/* minimum ratio allowing de-interlace */
79 #define	Y_NOISE			0.003		/* normalized delta too weak, noise */
80 #define	Y_SCENE_CHANGE		0.15		/* normalized delta > 15% of max delta */
81 
82 /* force de-interlace */
83 #define	Y_FBLEND		1.6		/* if ratio is > this */
84 #define	Y_FWEIGHT		0.01		/* if over this weight */
85 
86 /* frame operation flags */
87 #define	Y_OP_ODD		0x10
88 #define	Y_OP_EVEN		0x20
89 #define	Y_OP_PAT		0x30
90 
91 #define	Y_OP_NOP		0x0
92 #define	Y_OP_SAVE		0x1
93 #define	Y_OP_COPY		0x2
94 #define	Y_OP_DROP		0x4
95 #define	Y_OP_DEINT		0x8
96 
97 /* group flags */
98 #define	Y_HAS_DROP		1
99 #define	Y_BANK_DROP		2
100 #define	Y_WITHDRAW_DROP		3
101 #define	Y_BORROW_DROP		4
102 #define	Y_RETURN_DROP		5
103 #define	Y_FORCE_DEINT		6
104 #define	Y_FORCE_DROP		7
105 #define	Y_FORCE_KEEP		8
106 
107 /* frame information */
108 typedef struct fi_t Fi;
109 struct fi_t
110 	{
111 	double	r;		/* even/odd delta ratio, filtered */
112 	double	ro;		/* ratio, original value */
113 	double	w;		/* statistical strength */
114 	double	nd;		/* normalized delta */
115 	int	fn;		/* frame number */
116 	int	ed;		/* even row delta */
117 	int	od;		/* odd row delta */
118 	int	gi;		/* group array index */
119 	int	ip;		/* telecine pattern */
120 	int	op;		/* frame operation, nop, save/copy row */
121 	int	drop;		/* frame is to be dropped */
122 	int	gf;		/* group flag */
123 	Fi	*next;
124 	};
125 
126 
127 /*
128  *	globals:
129  */
130 
131 char *Prog;			/* argv[0] */
132 char *LogFn;			/* log file name, default "yait.log" */
133 char *OpsFn;			/* ops file name, default "yait.ops" */
134 double Thresh;			/* row delta ratio interlace detection threshold */
135 double EThresh;			/* even interlace detection threshold */
136 double OThresh;			/* odd interlace detection threshold */
137 double Blend;			/* force frame blending over this threshold */
138 double Noise;			/* minimum normalized delta */
139 int DropWin;			/* drop frame look ahead window */
140 int DeintMode;			/* transcode de-interlace mode, (1-5) */
141 int DebugFi;			/* dump debug frame info */
142 int NoDrops;			/* force de-interlace everywhere (non vfr) */
143 int NoKeeps;			/* Don't force keep frames (allows a/v sync drift) */
144 
145 FILE *LogFp;			/* log file */
146 FILE *OpsFp;			/* ops file */
147 
148 Fi *Fl;				/* frame list */
149 Fi **Fa;			/* frame array */
150 Fi **Ga;			/* group array */
151 int *Da;			/* drop count array */
152 int Nf;				/* number of frames */
153 int Ng;				/* number of elements in Ga */
154 int Nd;				/* number of elements in Da */
155 int Md;				/* max delta */
156 
157 int Stat_nd;			/* total number of dropped frames */
158 int Stat_nb;			/* total number of blended frames */
159 int Stat_no;			/* total number of odd interlaced pairs */
160 int Stat_ne;			/* total number of even interlaced pairs */
161 int Stat_fd;			/* total number of forced drops */
162 int Stat_fk;			/* total number of forced keeps */
163 
164 
165 /*
166  *	protos:
167  */
168 
169 static void yait_parse_args( int, char** );
170 static void yait_chkac( int* );
171 static void yait_usage( void );
172 static void yait_read_log( void );
173 static double yait_calc_ratio( int, int );
174 static void yait_find_ip( void );
175 static void yait_chk_ip( int );
176 static void yait_chk_pairs( int );
177 static void yait_chk_tuplets( int );
178 static int yait_find_odd( double, int, double*, int );
179 static int yait_find_even( double, int, double*, int );
180 static int yait_ffmin( int, int );
181 static int yait_ffmax( int, int );
182 static int yait_m5( int );
183 static void yait_mark_grp( int, int, double );
184 static void yait_find_drops( void );
185 static int yait_cnt_drops( int );
186 static int yait_extra_drop( int );
187 static int yait_missing_drop( int );
188 static void yait_keep_frame( int );
189 static int yait_get_hdrop( int, int* );
190 static void yait_ivtc_keep( int );
191 static void yait_ivtc_grps( void );
192 static int yait_scan_bk( int );
193 static int yait_scan_fw( int );
194 static void yait_drop_frame( int );
195 static int yait_ivtc_grp( int, int, int );
196 static double yait_tst_ip( int, int );
197 static void yait_deint( void );
198 static void yait_write_ops( void );
199 static char *yait_write_op( Fi* );
200 static void yait_fini( void );
201 
202 static void yait_debug_fi( void );
203 static char *yait_op( int op );
204 static char *yait_drop( Fi *f );
205 static char *yait_grp( int flg );
206 
207 
208 /*
209  *	main:
210  */
211 
212 int
main(int argc,char ** argv)213 main( int argc, char **argv )
214 	{
215 	/* parse args */
216 	yait_parse_args( argc, argv );
217 
218 	LogFp = fopen( LogFn, "r" );
219 	if( !LogFp )
220 		{
221 		perror( "fopen" );
222 		fprintf( stderr, "Cannot open YAIT delta log file (%s)\n", LogFn );
223 		exit( 1 );
224 		}
225 
226 	OpsFp = fopen( OpsFn, "w" );
227 	if( !OpsFp )
228 		{
229 		perror( "fopen" );
230 		fprintf( stderr, "Cannot create YAIT frame ops file (%s)\n", OpsFn );
231 		exit( 1 );
232 		}
233 
234 	/* read the log */
235 	yait_read_log();
236 
237 	/* find interleave patterns */
238 	yait_find_ip();
239 
240 	/* find drop frames */
241 	yait_find_drops();
242 
243 	/* complete groups missing an interleave pattern */
244 	yait_ivtc_grps();
245 
246 	/* let transcode de-interlace frames we missed */
247 	yait_deint();
248 
249 	/* print frame ops file */
250 	yait_write_ops();
251 
252 	if( DebugFi )
253 		yait_debug_fi();
254 
255 	/* graceful exit */
256 	yait_fini();
257 
258 	return( 0 );
259 	}
260 
261 
262 /*
263  *	yait_parse_args:
264  */
265 
266 static void
yait_parse_args(int argc,char ** argv)267 yait_parse_args( int argc, char **argv )
268 	{
269 	int opt;
270 	char *p;
271 
272 	LogFn = Y_LOG_FN;
273 	OpsFn = Y_OPS_FN;
274 	Thresh = Y_THRESH;
275 	EThresh = 0;
276 	OThresh = 0;
277 	Blend = Y_FBLEND;
278 	Noise = Y_NOISE;
279 	DeintMode = Y_DEINT_MODE;
280 	DropWin = Y_DROPWIN_SIZE;
281 
282 	--argc;
283 	Prog = *argv++;
284 	while( (p = *argv) )
285 		{
286 		if( *p++ != '-' )
287 			break;
288 		while( (opt = *p++) )
289 			switch( opt )
290 				{
291 				case 'd':
292 					DebugFi = TRUE;
293 					break;
294 
295 				case 'n':
296 					NoDrops = TRUE;
297 					break;
298 
299 				case 'k':
300 					NoKeeps = TRUE;
301 					break;
302 
303 				case 'l':
304 					yait_chkac( &argc );
305 					LogFn = *++argv;
306 					break;
307 
308 				case 'o':
309 					yait_chkac( &argc );
310 					OpsFn = *++argv;
311 					break;
312 
313 				case 't':
314 					yait_chkac( &argc );
315 					Thresh = atof( *++argv );
316 					break;
317 
318 				case 'E':
319 					yait_chkac( &argc );
320 					EThresh = atof( *++argv );
321 					break;
322 
323 				case 'O':
324 					yait_chkac( &argc );
325 					OThresh = atof( *++argv );
326 					break;
327 
328 				case 'b':
329 					yait_chkac( &argc );
330 					Blend = atof( *++argv );
331 					break;
332 
333 				case 'N':
334 					yait_chkac( &argc );
335 					Noise = atof( *++argv );
336 					break;
337 
338 				case 'w':
339 					yait_chkac( &argc );
340 					DropWin = atoi( *++argv );
341 					break;
342 
343 				case 'm':
344 					yait_chkac( &argc );
345 					DeintMode = atoi( *++argv );
346 					break;
347 
348 				default:
349 					yait_usage();
350 					break;
351 				}
352 		--argc;
353 		argv++;
354 		}
355 
356 	if( Thresh <= 1 )
357 		{
358 		printf( "Invalid threshold specified (%g).\n\n", Thresh );
359 		yait_usage();
360 		}
361 
362 	if( Blend <= Thresh )
363 		{
364 		printf( "Invalid blend threshold specified (%g).\n\n", Blend );
365 		yait_usage();
366 		}
367 
368 	if( DropWin<Y_DROPWIN_MIN || DropWin>Y_DROPWIN_MAX )
369 		{
370 		printf( "Invalid drop window size specified (%d).\n\n", DropWin );
371 		yait_usage();
372 		}
373 
374 	if( DeintMode<Y_DEINT_MIN || DeintMode>Y_DEINT_MAX )
375 		{
376 		printf( "Invalid de-interlace method specified (%d).\n\n", DeintMode );
377 		yait_usage();
378 		}
379 
380 	if( !EThresh )
381 		EThresh = Thresh;
382 	if( !OThresh )
383 		OThresh = Thresh;
384 
385 	if( argc )
386 		yait_usage();
387 	}
388 
389 
390 /*
391  *	yait_chkac:
392  */
393 
394 static void
yait_chkac(int * ac)395 yait_chkac( int *ac )
396 	{
397 	if( *ac < 1 )
398 		yait_usage();
399 	--*ac;
400 	}
401 
402 
403 /*
404  *	yait_usage:
405  */
406 
407 static void
yait_usage(void)408 yait_usage( void )
409 	{
410 	printf( "Usage: %s [-dnklotbwmEON] [arg...] \n", Prog );
411 	printf( "\t-d\t\tPrint debug information to stdout.\n" );
412 	printf( "\t-n\t\tDo not drop frames, always de-interlace.\n" );
413 	printf( "\t-k\t\tNo forced keep frames.\n" );
414 	printf( "\t-l log\t\tInput yait log file name [%s].\n", Y_LOG_FN );
415 	printf( "\t-o ops\t\tOutput yait frame ops file name [%s].\n", Y_OPS_FN );
416 	printf( "\t-t thresh\tInterlace detection threshold (>1) [%g].\n", Y_THRESH );
417 	printf( "\t-b blend\tforced blend threshold (>thresh) [%g].\n", Y_FBLEND );
418 	printf( "\t-w size\t\tDrop frame look ahead window (0-20) [%d].\n", Y_DROPWIN_SIZE );
419 	printf( "\t-m mode\t\tTranscode blend method (0-5) [%d].\n", Y_DEINT_MODE );
420 	printf( "\t-E thresh\tEven pattern threshold [%g].\n", Y_THRESH );
421 	printf( "\t-O thresh\tOdd pattern threshold [%g].\n", Y_THRESH );
422 	printf( "\t-N noise\tMinimum normalized delta, else noise [%g].\n", Y_NOISE );
423 	printf( "\n" );
424 
425 	exit( 1 );
426 	}
427 
428 
429 /*
430  *	yait_read_log:
431  */
432 
433 static void
yait_read_log(void)434 yait_read_log( void )
435 	{
436 	Fi **fa, *pf, *f;
437 	int fn, ed, od;
438 	int s, n;
439 
440 	s = 0;
441 	pf = NULL;
442 	for( Nf=0; ; Nf++ )
443 		{
444 		n = fscanf( LogFp, "%d: e: %d, o: %d\n", &fn, &ed, &od );
445 		if( n != 3 )
446 			break;
447 
448 		/* starting frame number */
449 		if( !Nf )
450 			s = fn;
451 
452 		if( (fn-s) != Nf )
453 			{
454 			printf( "Broken log file, line %d\n", Nf );
455 			exit( 1 );
456 			}
457 
458 		f = (Fi*) malloc( sizeof(Fi) );
459 		if( !f )
460 			{
461 			perror( "malloc" );
462 			exit( 1 );
463 			}
464 
465 		memset( (void*) f, 0, sizeof(Fi) );
466 		if( !Fl )
467 			Fl = f;
468 		if( pf )
469 			pf->next = f;
470 		pf = f;
471 
472 		f->r = yait_calc_ratio( ed, od );
473 		f->ro = f->r;
474 		f->fn = fn;
475 		f->ed = ed;
476 		f->od = od;
477 		f->ip = -1;
478 		}
479 
480 	if( !Fl )
481 		{
482 		fprintf( stderr, "Invalid log file.\n" );
483 		exit( 1 );
484 		}
485 
486 	/* number of 5 frame groups */
487 	Nd = Nf / 5;
488 
489 	Fa = (Fi**) malloc( (Nf+1) * sizeof(Fi*) );
490 	Ga = (Fi**) malloc( (Nf+1) * sizeof(Fi*) );
491 	Da = (int*) malloc( Nd * sizeof(int) );
492 	if( !Fa || !Ga || !Da )
493 		{
494 		perror( "malloc" );
495 		exit( 1 );
496 		}
497 
498 	fa = Fa;
499 	for( f=Fl; f; f=f->next )
500 		*fa++ = f;
501 	*fa = NULL;
502 	}
503 
504 
505 /*
506  *	yait_calc_ratio:
507  *		Compute a ratio between even/odd row deltas.  A high ratio indicates an
508  *	interlace present.  Use the sign of the ratio to indicate even row (<0), or odd
509  *	row (>0) correlation.
510  *
511  *		If the magnitude of the ratio is > 1.1, this is usually enough to
512  *	indicate interlacing.  A value around 1.0 indicates no row correlation at
513  *	all.
514  *
515  * 		Assigning the ratios in this manner result in the following patterns
516  * 	present for interlaced material.  Assume 0 for fabs(r)<thresh, else +/- 1:
517  *
518  * 	An odd interlace pattern (for a five frame group) would appear as:
519  *
520  *			frame:  1	2	3	4	5
521  *			even:	a	a	b	c	d
522  *			odd:	a	b	c	c	d
523  *
524  *			ratio:	0	-1	0	1	0
525  *
526  * 	If we detect this pattern, we assign the following frame operations:
527  *
528  *			frame:  1	2	3	4	5
529  *			even:	a	a	b	c	d
530  *			odd:	a	b	c	c	d
531  *
532  *			ratio:	0	-1	0	1	0
533  *			op:		osd	oc
534  *
535  * 		osd = save odd rows and drop the frame
536  * 		oc  = copy in saved odd rows
537  *
538  * 	This results with:
539  *
540  *			frame:  1	|2|	3	4	5
541  *			even:	a	|a|	b	c	d
542  *			odd:	a	|b|-->	b	c	d
543  *                                     drop
544  *
545  *	For even interlace patterns, the signs are reversed, or simply:
546  *
547  *			ratio:	0	1	0	-1	0
548  *					esd	ec
549  *
550  *	The entire approach of this tool depends on these specific ratio patterns
551  *	to be present, and should be for 2:3 pulldown.  Lots of complications arise
552  *	around still and abrupt scene changes.  Again, it might be useful for the
553  *	filter to produce a combing co-efficient as well as the delta information.
554  *
555  *	Side note:
556  *		For yuv, deltas based only on luminance yeilded much stronger
557  *		interlace patterns, however, I suppose there are (rare) cases where
558  *		chroma could be the only indicator, so chroma is included in the
559  *		delta calculation, even though it results in weaker ratios.
560  */
561 
562 static double
yait_calc_ratio(int ed,int od)563 yait_calc_ratio( int ed, int od )
564 	{
565 	double r;
566 
567 	r = 1;
568 
569 	/* compute ratio, >1 odd, <-1 even */
570 	if( !ed && !od )
571 		/* duplicate frame */
572 		r = 0;
573 
574 	if( ed && !od )
575 		r = 100;
576 
577 	if( !ed && od )
578 		r = -100;
579 
580 	if( ed && od )
581 		{
582 		r = (double) ed / (double) od;
583 
584 		if( r < 1 )
585 			r = -1.0 / r;
586 
587 		if( r > 100 )
588 			r = 100;
589 		if( r < -100 )
590 			r = -100;
591 		}
592 
593 	return( r );
594 	}
595 
596 
597 /*
598  *	yait_find_ip:
599  *		- Mark isolated duplicate frames to be hard dropped.
600  *		- Create the group array which is used to processes interleave
601  *		  patterns without duplicate frames present.
602  *		- Find the maximum frame delta value.  This is used to normalize
603  *		  frame deltas to filter out weak frames (noise which may cause
604  *		  erroneous interleave patterns to be detected).
605  *		- Detect local interleave patterns.
606  */
607 
608 static void
yait_find_ip(void)609 yait_find_ip( void )
610 	{
611 	Fi *f;
612 	double w;
613 	int m, p, i;
614 
615 	/* mark obvious drop frames */
616 	if( !NoDrops )
617 		for( i=1; i<Nf-1; i++ )
618 			{
619 			f = Fa[i];
620 			if( f->r )
621 				continue;
622 
623 			if( !Fa[i-1]->r && !Fa[i+1]->r )
624 				continue;
625 
626 			f->drop = TRUE;
627 			}
628 
629 	/* create group array, ommiting drops */
630 	Ng = 0;
631 	for( i=0; i<Nf; i++ )
632 		{
633 		f = Fa[i];
634 		if( f->drop )
635 			continue;
636 
637 		f->gi = Ng;
638 		Ga[Ng++] = f;
639 		}
640 	Ga[Ng] = NULL;
641 
642 	/* find max row delta */
643 	m = 0;
644 	for( i=0; i<Nf; i++ )
645 		{
646 		f = Fa[i];
647 		if( f->ed > m )
648 			m = f->ed;
649 		if( f->od > m )
650 			m = f->od;
651 		}
652 
653 	Md = m;
654 	if( !Md )
655 		{
656 		fprintf( stderr, "All empty frames?\n" );
657 		exit( 1 );
658 		}
659 
660 	/* compute normalized row deltas and */
661 	/* filter out weak r values (noise) */
662 	for( i=0; i<Ng; i++ )
663 		{
664 		f = Ga[i];
665 		f->nd = (f->ed + f->od) / (double) Md;
666 		if( f->nd < Noise )
667 			f->r = 1;
668 		}
669 
670 	/* adjust for incomplete interleave patterns */
671 	/* (indexing Fa[0,..,i+6]) */
672 	for( i=0; i<Ng-6; i++ )
673 		yait_chk_ip( i );
674 
675 	/* find interleave patterns */
676 	for( i=0; i<Ng; i++ )
677 		{
678 		f = Ga[i];
679 		if( f->op & Y_OP_COPY )
680 			{
681 			/* finish this group before looking for another pattern */
682 			i++;
683 			continue;
684 			}
685 
686 		p = yait_find_odd( OThresh, i, &w, 4 );
687 		if( p != -1 )
688 			{
689 			yait_mark_grp( p, i, w );
690 			continue;
691 			}
692 
693 		p = yait_find_even( EThresh, i, &w, 4 );
694 		if( p != -1 )
695 			yait_mark_grp( p+10, i, w );
696 		}
697 	}
698 
699 
700 /*
701  *	yait_chk_ip:
702  *		Two cases to look for.  An isolated pair of high r's, and an
703  *	isolated tuplet of high r's.  These can be caused by interlacing over
704  *	still and abrupt scene changes.
705  */
706 
707 static void
yait_chk_ip(int n)708 yait_chk_ip( int n )
709 	{
710 	if( !NoDrops )
711 		yait_chk_pairs( n );
712 
713 	yait_chk_tuplets( n );
714 	}
715 
716 
717 /*
718  *	yait_chk_pairs:
719  *		Look for patterns of the type:
720  *			i:      0  1  2  3  4  5
721  *			odd:	0  0 -1  1  0  0
722  *			even:	0  0  1 -1  0  0
723  *
724  *	If detected, force the drop of the (single) interlaced frame.
725  *	De-interlacing would just incur a redundant copy operation.
726  */
727 
728 static void
yait_chk_pairs(int n)729 yait_chk_pairs( int n )
730 	{
731 	Fi *fa[6];
732 	double ra[6];
733 	int i;
734 
735 	for( i=0; i<6; i++ )
736 		{
737 		fa[i] = Ga[n+i];
738 		ra[i] = fabs( fa[i]->r );
739 		}
740 
741 	for( i=2; i<4; i++ )
742 		if( ra[i] < Thresh )
743 			return;
744 
745 	/* adjacent frames to the tuplet must be <thresh */
746 	if( ra[1]>Thresh || ra[4]>Thresh )
747 		return;
748 
749 	/* we only need one edge frame to be <thresh */
750 	if( ra[0]>Thresh && ra[5]>Thresh )
751 		return;
752 
753 	if( fa[2]->r>0 && fa[3]->r>0 )
754 		return;
755 
756 	if( fa[2]->r<0 && fa[3]->r<0 )
757 		return;
758 
759 	/* two isolated high r values of opposite sign */
760 	/* drop the interlaced frame, erase the pattern */
761 	fa[2]->r = 1;
762 	fa[3]->r = 1;
763 
764 	fa[2]->drop = TRUE;
765 	}
766 
767 
768 /*
769  *	yait_chk_tuplets:
770  *		Look for patterns of the type:
771  *			i:      0  1  2   3    4  5  6
772  *			odd:	0  0 -1  +/-2  1  0  0
773  *			even:	0  0  1  +/-2 -1  0  0
774  *
775  *	and complete to:
776  *
777  *			odd:	0  0 -1   0    1  0  0
778  *			even:	0  0  1   0   -1  0  0
779  */
780 
781 static void
yait_chk_tuplets(int n)782 yait_chk_tuplets( int n )
783 	{
784 	Fi *fa[7];
785 	double ra[7];
786 	int i;
787 
788 	for( i=0; i<7; i++ )
789 		{
790 		fa[i] = Ga[n+i];
791 		ra[i] = fabs( fa[i]->r );
792 		}
793 
794 	for( i=2; i<5; i++ )
795 		if( ra[i] < Thresh )
796 			return;
797 
798 	/* adjacent frames to the tuplet must be <thresh */
799 	if( ra[1]>Thresh || ra[5]>Thresh )
800 		return;
801 
802 	/* we only need one edge frame to be <thresh */
803 	if( ra[0]>Thresh && ra[6]>Thresh )
804 		return;
805 
806 	if( fa[2]->r>0 && fa[4]->r>0 )
807 		return;
808 
809 	if( fa[2]->r<0 && fa[4]->r<0 )
810 		return;
811 
812 	/* isolated tuplet of high r values of opposite sign */
813 	if( ra[3]>ra[2] || ra[3]>ra[4] )
814 		fa[3]->r = 1;
815 	}
816 
817 
818 /*
819  *	yait_find_odd:
820  */
821 
822 static int
yait_find_odd(double thresh,int n,double * w,int win)823 yait_find_odd( double thresh, int n, double *w, int win )
824 	{
825 	double re, ro;
826 	int me, mo;
827 	int p;
828 
829 	/* find max even/odd correlations */
830 	/* (r<0 - even, r>0 - odd) */
831 	me = yait_ffmin( n, win );
832 	mo = yait_ffmax( n, win );
833 
834 	p = -1;
835 	if( yait_m5(mo-2) == yait_m5(me) )
836 		{
837 		re = fabs( Ga[me]->r );
838 		ro = fabs( Ga[mo]->r );
839 		if( re>thresh && ro>thresh )
840 			{
841 			p = yait_m5( mo - 4 );
842 			if( w )
843 				*w = re + ro;
844 			}
845 		}
846 
847 	return( p );
848 	}
849 
850 
851 /*
852  *	yait_find_even:
853  */
854 
855 static int
yait_find_even(double thresh,int n,double * w,int win)856 yait_find_even( double thresh, int n, double *w, int win )
857 	{
858 	double re, ro;
859 	int me, mo;
860 	int p;
861 
862 	me = yait_ffmin( n, win );
863 	mo = yait_ffmax( n, win );
864 
865 	p = -1;
866 	if( yait_m5(me-2) == yait_m5(mo) )
867 		{
868 		re = fabs( Ga[me]->r );
869 		ro = fabs( Ga[mo]->r );
870 		if( re>thresh && ro>thresh )
871 			{
872 			p = yait_m5( me - 4 );
873 			if( w )
874 				*w = re + ro;
875 			}
876 		}
877 
878 	return( p );
879 	}
880 
881 
882 /*
883  *	yait_ffmin:
884  */
885 
886 static int
yait_ffmin(int n,int w)887 yait_ffmin( int n, int w )
888 	{
889 	Fi *f;
890 	int m, i;
891 	double r;
892 
893 	r = 0;
894 	m = 0;
895 	for( i=n; i<n+w; i++ )
896 		{
897 		if( i < 0 )
898 			break;
899 
900 		f = Ga[i];
901 		if( !f )
902 			break;
903 
904 		if( f->r < r )
905 			{
906 			r = f->r;
907 			m = i;
908 			}
909 		}
910 
911 	return( m );
912 	}
913 
914 
915 /*
916  *	yait_ffmax:
917  */
918 
919 static int
yait_ffmax(int n,int w)920 yait_ffmax( int n, int w )
921 	{
922 	Fi *f;
923 	int m, i;
924 	double r;
925 
926 	r = 0;
927 	m = 0;
928 	for( i=n; i<n+w; i++ )
929 		{
930 		if( i < 0 )
931 			break;
932 
933 		f = Ga[i];
934 		if( !f )
935 			break;
936 
937 		if( f->r > r )
938 			{
939 			r = f->r;
940 			m = i;
941 			}
942 		}
943 
944 	return( m );
945 	}
946 
947 
948 /*
949  *	yait_m5:
950  */
951 
952 static int
yait_m5(int n)953 yait_m5( int n )
954 	{
955 	while( n < 0 )
956 		n += 5;
957 	return( n % 5 );
958 	}
959 
960 
961 /*
962  *	yait_mark_grp:
963  *		Try to catch the situation where a progressive frame is missing
964  *	between interlace groups.  This will cause an erroneous (opposite) ip
965  *	pattern to be detected.  The first sequence shown below is a normal (odd)
966  *	telecine pattern.  The second shows what happens when a progressive frame
967  *	is missing.  We want to reject the even pattern detected.  Therefore, if
968  *	we find an identical pattern at n+4 we keep it.  If not, we reject if an
969  *	opposite pattern follows at n+2 of greater weight.
970  *
971  *		n:  0   1   2   3   4   0   1   2   3   4
972  *		r:  0  -1   0   1   0   0  -1   0   1   0
973  *                     odd                 odd
974  *
975  *		n:  0   1   2   3   4   1   2   3   4
976  *		r:  0  -1   0   1   0  -1   0   1   0
977  *                     odd     even    odd
978  */
979 
980 static void
yait_mark_grp(int p,int n,double w)981 yait_mark_grp( int p, int n, double w )
982 	{
983 	Fi *f;
984 	double nw;
985 	int np, t, i;
986 
987 	if( n%5 != (p+2)%5 )
988 		return;
989 
990 	/* only overwrite an existing pattern if weight is greater */
991 	f = Ga[n];
992 	if( w <= f->w )
993 		return;
994 
995 	/* check for same pattern at n+4 */
996 	if( p < 10 )
997 		np = yait_find_odd( OThresh, n+4, NULL, 5 );
998 	else
999 		np = yait_find_even( EThresh, n+4, NULL, 5 );
1000 	if( np < 0 )
1001 		{
1002 		/* no pattern at n+4, reject if opposite ip at n+2 */
1003 		if( p < 10 )
1004 			np = yait_find_even( EThresh, n+2, &nw, 5 );
1005 		else
1006 			np = yait_find_odd( OThresh, n+2, &nw, 5 );
1007 
1008 		if( np>=0 && nw>w )
1009 			return;
1010 		}
1011 
1012 	/* erase previous pattern */
1013 	if( n > 1 )
1014 		{
1015 		Ga[n-1]->op = 0;
1016 		Ga[n-2]->op = 0;
1017 		}
1018 
1019 	/* this frame and next are interlaced */
1020 	t = (p < 10) ? Y_OP_ODD : Y_OP_EVEN;
1021 	f->op = t | Y_OP_SAVE | Y_OP_DROP;
1022 	f = Ga[n+1];
1023 	f->op = t | Y_OP_COPY;
1024 
1025 	/* assume 1 progressive on either side of the tuplet */
1026 	for( i=n-1; i<n+4; i++ )
1027 		{
1028 		if( i<0 || i>=Ng )
1029 			continue;
1030 
1031 		f = Ga[i];
1032 		f->ip = p;
1033 		f->w = w;
1034 		}
1035 	}
1036 
1037 
1038 /*
1039  *	yait_find_drops:
1040  *		For every group of 5 frames, make sure we drop a frame.  Allow up to a
1041  *	DropWin (default 15) group lookahead to make up for extra or missing drops.  (The
1042  *	duplicated frames generated by --hard_fps can be quite early or late in the sequence).
1043  *	If a group requires a drop, but none exists, mark the group as requiring de-interlacing.
1044  *	Finally, consequetive marked groups inherit surrounding interleave patterns.
1045  *
1046  *	Each group will receive one of the following flags:
1047  *
1048  * 		Y_HAS_DROP		- group has a single drop frame
1049  * 		Y_BANK_DROP		- extra drop, can be used forward
1050  * 		Y_WITHDRAW_DROP		- missing drop, use banked drop from behind
1051  * 		Y_RETURN_DROP		- extra drop, can be used behind
1052  * 		Y_BORROW_DROP		- missing drop, use future extra drop
1053  * 		Y_FORCE_DEINT		- force de-interlacing, (produces a drop)
1054  * 		Y_FORCE_DROP		- missing drop, no extras and no interleave found
1055  * 		Y_FORCE_KEEP		- extra drop, no consumer so have to keep it
1056  *
1057  *	For any flags other than FORCE, no action is required.  Eeach group already has
1058  *	an available frame to drop, whether a marked duplicate, or a locally detected
1059  *	interleave pattern (which produces a drop).
1060  *
1061  *	For Y_FORCE_DEINT, assemble consecutive groups of this type and try to inherit
1062  *	adjacent interleave patterns.  If no pattern is available, mark them as
1063  *	Y_FORCE_DROP.
1064  */
1065 
1066 static void
yait_find_drops(void)1067 yait_find_drops( void )
1068 	{
1069 	Fi *f;
1070 	int d, l;
1071 
1072 	/* populate drop counts */
1073 	for( d=0; d<Nd; d++ )
1074 		Da[d] = yait_cnt_drops( d*5 );
1075 
1076 	/* balance drop counts restricted by window size */
1077 	for( d=0; d<Nd; d++ )
1078 		{
1079 		f = Fa[d*5];
1080 
1081 		/* this is what we want to see */
1082 		if( Da[d] == 1 )
1083 			{
1084 			if( !f->gf )
1085 				f->gf = Y_HAS_DROP;
1086 			continue;
1087 			}
1088 
1089 		/* group is missing a drop? */
1090 		if( !Da[d] )
1091 			{
1092 			/* look ahead for an extra drop */
1093 			l = yait_extra_drop( d );
1094 			if( l )
1095 				{
1096 				/* found one */
1097 				Da[d]++;
1098 				f->gf = Y_BORROW_DROP;
1099 
1100 				--Da[l];
1101 				Fa[l*5]->gf = Y_RETURN_DROP;
1102 				continue;
1103 				}
1104 
1105 			/* no extra drops exist, mark for de-interlacing */
1106 			f->gf = Y_FORCE_DEINT;
1107 			continue;
1108 			}
1109 
1110 		/* we have too many drops */
1111 		while( Da[d] > 1 )
1112 			{
1113 			--Da[d];
1114 
1115 			/* look ahead for a missing drop */
1116 			l = yait_missing_drop( d );
1117 			if( l )
1118 				{
1119 				/* found one */
1120 				f->gf = Y_BANK_DROP;
1121 
1122 				Da[l]++;
1123 				Fa[l*5]->gf = Y_WITHDRAW_DROP;
1124 				continue;
1125 				}
1126 
1127 			/* we have to keep a drop */
1128 			if( !NoKeeps )
1129 				{
1130 				f->gf = Y_FORCE_KEEP;
1131 				yait_keep_frame( d*5 );
1132 
1133 				Stat_fk++;
1134 				}
1135 			}
1136 		}
1137 	}
1138 
1139 
1140 /*
1141  *	yait_cnt_drops:
1142  */
1143 
1144 static int
yait_cnt_drops(int n)1145 yait_cnt_drops( int n )
1146 	{
1147 	Fi *f;
1148 	int d, i;
1149 
1150 	d = 0;
1151 	for( i=n; i<n+5 && i<Nf; i++ )
1152 		{
1153 		f = Fa[i];
1154 		if( f->drop || f->op&Y_OP_DROP )
1155 			d++;
1156 		}
1157 
1158 	return( d );
1159 	}
1160 
1161 
1162 /*
1163  *	yait_extra_drop:
1164  *		Scan DropWin groups ahead for an extra drop.
1165  */
1166 
1167 static int
yait_extra_drop(int d)1168 yait_extra_drop( int d )
1169 	{
1170 	int l, w;
1171 
1172 	for( w=0; w<DropWin; w++ )
1173 		{
1174 		l = d + w + 1;
1175 		if( l >= Nd )
1176 			return( 0 );
1177 
1178 		if( Da[l] > 1 )
1179 			return( l );
1180 		}
1181 
1182 	return( 0 );
1183 	}
1184 
1185 
1186 /*
1187  *	yait_missing_drop:
1188  *		Scan DropWin groups ahead for a missing drop.
1189  */
1190 
1191 static int
yait_missing_drop(int d)1192 yait_missing_drop( int d )
1193 	{
1194 	int l, w;
1195 
1196 	for( w=0; w<DropWin; w++ )
1197 		{
1198 		l = d + w + 1;
1199 		if( l >= Nd )
1200 			return( 0 );
1201 
1202 		if( !Da[l] )
1203 			return( l );
1204 		}
1205 
1206 	return( 0 );
1207 	}
1208 
1209 
1210 /*
1211  *	yait_keep_frame:
1212  *		Multiple drops exist.  Pick the best frame to keep.  This can be difficult,
1213  *	as we do not want to keep a duplicate of an interlaced frame.  First, try to find
1214  *	a hard dropped frame which does not follow an interlace.  If one can be found, then
1215  *	simply negate the drop flag.  If we are duplicating an interlace, alter the frame
1216  *	operations for the group to produce a non-interlaced duplicate.
1217  */
1218 
1219 static void
yait_keep_frame(int n)1220 yait_keep_frame( int n )
1221 	{
1222 	Fi *f;
1223 	int da[6], bd, d, i;
1224 
1225 	d = yait_get_hdrop( n, da );
1226 
1227 	if( !d )
1228 		{
1229 		/* no hard drop frames were found, so ... */
1230 		/* two interlace drops exist, keep one, but blend it */
1231 		for( i=n; i<n+5 && i<Nf; i++ )
1232 			{
1233 			f = Fa[i];
1234 			if( f->op & Y_OP_DROP )
1235 				{
1236 				f->op &= ~Y_OP_DROP;
1237 				f->op |= Y_OP_DEINT;
1238 				return;
1239 				}
1240 			}
1241 
1242 		/* sanity check */
1243 		f = Fa[n];
1244 		fprintf( stderr, "No drop frame can be found, frame: %d\n", f->fn );
1245 		exit( 1 );
1246 		}
1247 
1248 	/* try to use a drop frame that isn't an interlace duplicate */
1249 	bd = -1;
1250 	for( i=0; i<5; i++ )
1251 		{
1252 		d = da[i];
1253 		if( !d )
1254 			/* can't access before Fa[0] */
1255 			continue;
1256 
1257 		if( d < 0 )
1258 			/* end of drop list */
1259 			break;
1260 
1261 		f = Fa[d-1];
1262 		if( f->drop )
1263 			/* two dups in a row */
1264 			f = Fa[d-2];
1265 
1266 		if( !f->op )
1267 			{
1268 			/* good */
1269 			f = Fa[d];
1270 			f->drop = FALSE;
1271 			return;
1272 			}
1273 
1274 		if( f->op & Y_OP_COPY )
1275 			bd = d;
1276 		}
1277 
1278 	/* keeping a duplicate of an interlace, try to use one which duplicates the */
1279 	/* second of an interlace pair, as that is cleaner to deal with */
1280 	/* bd (best drop) was set earlier in the loop if such a frame was found */
1281 	if( bd < 0 )
1282 		bd = da[0];
1283 
1284 	yait_ivtc_keep( bd );
1285 	}
1286 
1287 
1288 /*
1289  *	yait_get_hdrop:
1290  *		Populate an index array of the hard dropped frames, and return
1291  *	the count of how many were found.
1292  */
1293 
1294 static int
yait_get_hdrop(int n,int * da)1295 yait_get_hdrop( int n, int *da )
1296 	{
1297 	Fi *f;
1298 	int d, i;
1299 
1300 	d = 0;
1301 	for( i=n; i<n+5 && i<Nf; i++ )
1302 		{
1303 		f = Fa[i];
1304 		if( f->drop )
1305 			{
1306 			*da++ = i;
1307 			d++;
1308 			}
1309 		}
1310 	*da = -1;
1311 
1312 	return( d );
1313 	}
1314 
1315 
1316 /*
1317  *	yait_ivtc_keep
1318  *		Depending upon the position of the DROP in the pattern, alter the
1319  *	frame ops to generate a non-interlaced frame, and keep it.
1320  *
1321  *	Case 1:
1322  *		If the duplicated frame is the second of the interlaced pair, then
1323  *		simply repeat the row copy operation and keep the frame.
1324  *
1325  *		Original (odd pattern):
1326  *				 	sd	c
1327  *			even:	2	2	3	3	4
1328  *			odd:	2	3	4	4	4
1329  *					drop		DROP
1330  *
1331  *		    yeilds (bad keep frame):
1332  *			even:	2		3	3	4
1333  *			odd:	2		3	4	4
1334  *							KEEP
1335  *		Revised:
1336  *				 	sd	c	c
1337  *			even:	2	2	3	3	4
1338  *			odd:	2	3	4	4	4
1339  *					drop		DROP
1340  *		    yeilds:
1341  *			even:	2		3	3	4
1342  *			odd:	2		3	3	4
1343  *							KEEP
1344  *
1345  *	Case 2:
1346  *		If the duplicated frame copies the first of the interlaced pair, more
1347  *		work must be done:
1348  *
1349  *		Original (odd pattern):
1350  *				 	sd		c
1351  *			even:	2	2	2	3	4
1352  *			odd:	2	3	3	4	4
1353  *					drop	DROP
1354  *
1355  *		    yeilds (bad keep frame):
1356  *			even:	2		2	3	4
1357  *			odd:	2		3	3	4
1358  *						KEEP
1359  *		Revised:
1360  *				s	c	sd	c
1361  *			even:	2	2	2	3	4
1362  *			odd:	2	3	3	4	4
1363  *						drop
1364  *		    yeilds:
1365  *			even:	2	2		3	4
1366  *			odd:	2	2		3	4
1367  *					(keep)
1368  */
1369 
1370 static void
yait_ivtc_keep(int d)1371 yait_ivtc_keep( int d )
1372 	{
1373 	Fi *fd, *fp;
1374 	int t;
1375 
1376 	fd = Fa[d];
1377 	fp = Fa[d-1];
1378 	if( fp->drop )
1379 		fp = Fa[d-2];
1380 
1381 	if( fp->op & Y_OP_COPY )
1382 		{
1383 		/* case 1 */
1384 		fd->op = fp->op;
1385 		fd->drop = FALSE;
1386 		return;
1387 		}
1388 
1389 	/* case 2 */
1390 	if( d < 2 )
1391 		{
1392 		/* can't access before Fa[0] */
1393 		/* (unlikely we would see this the first two frames of a film) */
1394 		fd->drop = FALSE;
1395 		return;
1396 		}
1397 
1398 	fd->op = fp->op;
1399 	fd->drop = FALSE;
1400 
1401 	t = fp->op & Y_OP_PAT;
1402 	fp->op = t | Y_OP_COPY;
1403 	fp = Fa[d-2];
1404 	fp->op = t | Y_OP_SAVE;
1405 	}
1406 
1407 
1408 /*
1409  *	yait_ivtc_grps:
1410  *		For each group missing an interleave pattern, scan backward and forward
1411  *	for an adjacent pattern.  Consider hard dropped frames as barriers.  If two
1412  *	different patterns exist, test the pattern against the original r values to find
1413  *	the best match.  For consecutive (forced) interleave groups, use the previously
1414  *	found pattern values, until the forward scan value is used, which is then
1415  *	propagated to the rest of the sequence.  (This avoids an O(n^2) search).
1416  *
1417  *		If no pattern can be found, force a drop of a frame in the group.
1418  *
1419  *	TODO:
1420  *		I should really be detecting scene changes as well, and consider them
1421  *		barriers.
1422  */
1423 
1424 static void
yait_ivtc_grps(void)1425 yait_ivtc_grps( void )
1426 	{
1427 	Fi *f;
1428 	int pb, pf, fg;
1429 	int p, n;
1430 
1431 	/* process by groups of 5 */
1432 	fg = TRUE;
1433 	pb = -1;
1434 	pf = -1;
1435 	for( n=0; n<Nf; n+=5 )
1436 		{
1437 		f = Fa[n];
1438 		if( f->gf != Y_FORCE_DEINT )
1439 			{
1440 			fg = TRUE;
1441 			continue;
1442 			}
1443 
1444 		if( fg )
1445 			{
1446 			/* this is the first group of a sequence, scan */
1447 			fg = FALSE;
1448 			pb = yait_scan_bk( n );
1449 			pf = yait_scan_fw( n );
1450 			}
1451 
1452 		if( pb<0 && pf<0 )
1453 			{
1454 			/* no pattern exists */
1455 			f->gf = Y_FORCE_DROP;
1456 			yait_drop_frame( n );
1457 			continue;
1458 			}
1459 
1460 		/* deinterlace the group with one of the given patterns */
1461 		/* if the pattern used is forward, keep it from now on */
1462 		p = yait_ivtc_grp( n, pb, pf );
1463 		if( p < 0 )
1464 			{
1465 			/* no pattern will match */
1466 			f->gf = Y_FORCE_DROP;
1467 			yait_drop_frame( n );
1468 			continue;
1469 			}
1470 
1471 		if( p == pf )
1472 			pb = -1;
1473 		}
1474 	}
1475 
1476 
1477 /*
1478  *	yait_scan_bk:
1479  */
1480 
1481 static int
yait_scan_bk(int n)1482 yait_scan_bk( int n )
1483 	{
1484 	Fi *f;
1485 	int i;
1486 
1487 	for( i=n-1; i>=0; --i )
1488 		{
1489 		f = Fa[i];
1490 		if( !f )
1491 			return( -1 );
1492 
1493 		if( f->drop )
1494 			return( -1 );
1495 
1496 		if( f->ip != -1 )
1497 			return( f->ip );
1498 		}
1499 
1500 	return( -1 );
1501 	}
1502 
1503 
1504 /*
1505  *	yait_scan_fw:
1506  */
1507 
1508 static int
yait_scan_fw(int n)1509 yait_scan_fw( int n )
1510 	{
1511 	Fi *f;
1512 	int i;
1513 
1514 	for( i=n+5; i<Nf; i++ )
1515 		{
1516 		f = Fa[i];
1517 
1518 		if( f->drop )
1519 			return( -1 );
1520 
1521 		if( f->ip != -1 )
1522 			return( f->ip );
1523 		}
1524 
1525 	return( -1 );
1526 	}
1527 
1528 
1529 /*
1530  *	yait_drop_frame:
1531  *		Choose a frame to drop.  We want the frame with the highest fabs(r) value,
1532  *	as it is likely an interlaced frame.  Do not use a frame which follows an assigned
1533  *	ip pattern, (it is the trailing element of a tuplet).  If no r values exceed the
1534  *	threshold, choose the frame with the minimum delta.
1535  *
1536  *		Frame:	0   1   2   3   4   |   5   6   7   8   9
1537  *		Ratio:	0   0   0  -1   0   |	1   0   0   0   0
1538  *		Op:		   sd	c   |
1539  *				      group boundary
1540  *
1541  *	In the above example, the first frame of the second group (5) may have the highest
1542  *	ratio value, but is the worst choice because it is part of the detected pattern and
1543  *	is a unique progressive frame.
1544  */
1545 
1546 static void
yait_drop_frame(int n)1547 yait_drop_frame( int n )
1548 	{
1549 	Fi *f;
1550 	double mr, r;
1551 	int md, d;
1552 	int fr, fd;
1553 	int i;
1554 
1555 	mr = 0;
1556 	md = 0;
1557 	fr = n;
1558 	fd = n;
1559 
1560 	for( i=n; i<n+5 && i<Nf-1; i++ )
1561 		{
1562 		if( !i )
1563 			/* can't access before Fa[0] */
1564 			continue;
1565 
1566 		if( Fa[i-1]->drop || Fa[i+1]->drop )
1567 			/* avoid two consequetive drops */
1568 			continue;
1569 
1570 		if( Fa[i-1]->op & Y_OP_PAT )
1571 			/* trailing tuplet element */
1572 			continue;
1573 
1574 		f = Fa[i];
1575 
1576 		r = fabs( f->ro );
1577 		if( r > mr )
1578 			{
1579 			mr = r;
1580 			fr = i;
1581 			}
1582 
1583 		d = f->ed + f->od;
1584 		if( !md || d<md )
1585 			{
1586 			md = d;
1587 			fd = i;
1588 			}
1589 		}
1590 
1591 	Fa[ (mr>Thresh)?fr:fd ]->drop = TRUE;
1592 	Stat_fd++;
1593 	}
1594 
1595 
1596 /*
1597  *	yait_ivtc_grp:
1598  *		We need to de-interlace this group.  Given are two potential patterns.
1599  *	If both are valid, test both and keep the one with the best r value matches.
1600  *	For the pattern used, mark the group, set the frame ops accordingly, and return
1601  *	it as the function value.
1602  */
1603 
1604 static int
yait_ivtc_grp(int n,int p1,int p2)1605 yait_ivtc_grp( int n, int p1, int p2 )
1606 	{
1607 	Fi *f;
1608 	double thresh, m1, m2;
1609 	int p, t, i;
1610 
1611 	m1 = (p1 < 0) ? -1 : yait_tst_ip(n,p1);
1612 	m2 = (p2 < 0) ? -1 : yait_tst_ip(n,p2);
1613 
1614 	/* yait_tst_ip() returns the sum of two ratios */
1615 	/* we want both ratios > Y_MTHRESH */
1616 	thresh = Y_MTHRESH * 2;
1617 	if( !NoDrops && m1<thresh && m2<thresh )
1618 		/* neither pattern matches, force a drop instead */
1619 		return( -1 );
1620 
1621 	p = (m1 > m2) ? p1 : p2;
1622 
1623 	/* sanity check */
1624 	if( p < 0 )
1625 		{
1626 		f = Fa[n];
1627 		fprintf( stderr, "Impossible interlace pattern computed (%d), frame: %d\n",
1628 			p, f->fn );
1629 		exit( 1 );
1630 		}
1631 
1632 	/* we have a pattern, mark group */
1633 	for( i=n; i<n+5 && i<Nf; i++ )
1634 		{
1635 		f = Fa[i];
1636 		if( f->drop )
1637 			{
1638 			fprintf( stderr,
1639 				"De-interlace, horribly confused now, frame: %d.\n", f->fn );
1640 			exit( 1 );
1641 			}
1642 		f->ip = p;
1643 		}
1644 
1645 	f = Fa[n];
1646 	n = f->gi;
1647 
1648 	/* sanity check */
1649 	if( Ga[n] != f )
1650 		{
1651 		fprintf( stderr, "Lost our frame in the group array, frame: %d\n", f->fn );
1652 		exit( 1 );
1653 		}
1654 
1655 	t = (p < 10) ? Y_OP_ODD : Y_OP_EVEN;
1656 	for( i=n; i<n+5 && i<Ng-1; i++ )
1657 		{
1658 		if( i%5 == (p+2)%5 )
1659 			{
1660 			f = Ga[i];
1661 			f->op = t | Y_OP_SAVE | Y_OP_DROP;
1662 
1663 			/* don't overwrite an existing frame drop */
1664 			f = Ga[i+1];
1665 			if( !(f->op&Y_OP_DROP) )
1666 				f->op = t | Y_OP_COPY;
1667 
1668 			break;
1669 			}
1670 		}
1671 
1672 	return( p );
1673 	}
1674 
1675 
1676 /*
1677  *	yait_tst_ip:
1678  */
1679 
1680 static double
yait_tst_ip(int n,int p)1681 yait_tst_ip( int n, int p )
1682 	{
1683 	double rs, r;
1684 	int s, i;
1685 
1686 	s = (p < 10) ? 1 : -1;
1687 	rs = 0;
1688 
1689 	n = Fa[n]->gi;
1690 	for( i=n; i<n+5 && i<Ng-2; i++ )
1691 		{
1692 		if( i%5 != (p+2)%5 )
1693 			continue;
1694 
1695 		/* strong pattern would have r[i]<-thresh and r[i+2]>thresh */
1696 		r = s * Ga[i]->ro;
1697 		if( r < 0 )
1698 			rs += fabs( r );
1699 
1700 		r = s * Ga[i+2]->ro;
1701 		if( r > 0 )
1702 			rs += r;
1703 
1704 		break;
1705 		}
1706 
1707 	return( rs );
1708 	}
1709 
1710 
1711 /*
1712  *	yait_deint:
1713  *		For non 3/2 telecine patterns, we may have let interlaced frames
1714  *	through.  Tell transcode to de-interlace (blend) these.  This is the case for
1715  *	any frame having a high ratio with no interlace pattern detected.
1716  *
1717  *	TODO:
1718  *		This was an afterthought.  Perhaps we can avoid a 32detect pass on
1719  *	the video by performing this, although it is difficult to detect out of
1720  *	pattern interlace frames solely on row delta information.  Perhaps we should
1721  *	have built 32detect into the log generation, and added an extra flag field if
1722  *	we thought the frame was interlaced.  This also would help when trying to
1723  *	assign ambiguous ip patterns.
1724  */
1725 
1726 static void
yait_deint(void)1727 yait_deint( void )
1728 	{
1729 	Fi *fp, *fn, *f;
1730 	int i;
1731 
1732 	for( i=1; i<Ng-1; i++ )
1733 		{
1734 		fp = Ga[i-1];
1735 		f = Ga[i];
1736 		fn = Ga[i+1];
1737 
1738 		if( f->op&Y_OP_PAT || f->drop )
1739 			/* already being de-interlaced or dropped */
1740 			continue;
1741 
1742 		if( fp->op & Y_OP_PAT )
1743 			/* trailing element of a tuplet */
1744 			continue;
1745 
1746 		if( fabs(f->r) < Blend )
1747 			/* it isn't interlaced (we think) */
1748 			continue;
1749 
1750 		if( f->nd < Y_FWEIGHT )
1751 			/* delta is too weak, interlace is likely not visible */
1752 			continue;
1753 
1754 		if( fp->nd>Y_SCENE_CHANGE || f->nd>Y_SCENE_CHANGE )
1755 			/* can't make a decision over scene changes */
1756 			continue;
1757 
1758 		/* this frame is interlaced with no operation assigned */
1759 		f->op = Y_OP_DEINT;
1760 
1761 		/* if the next frame ratio < thresh, it is similar, unless */
1762 		/* a scene change, therefore interlaced as well */
1763 		if( fabs(fn->r)<Thresh && fn->nd<Y_SCENE_CHANGE )
1764 			if( !(fn->op&Y_OP_PAT) && !fn->drop )
1765 				fn->op = Y_OP_DEINT;
1766 
1767 		/* if the next frame(s) are duplicates of this, mark them */
1768 		/* for blending as well, as the may eventually be force kept */
1769 		while( f->next && !f->next->gi )
1770 			{
1771 			f = f->next;
1772 			f->op = Y_OP_DEINT;
1773 			}
1774 		}
1775 	}
1776 
1777 
1778 /*
1779  *	yait_write_ops:
1780  */
1781 
1782 static void
yait_write_ops(void)1783 yait_write_ops( void )
1784 	{
1785 	Fi *f;
1786 
1787 	for( f=Fl; f; f=f->next )
1788 		fprintf( OpsFp, "%d: %s\n", f->fn, yait_write_op(f) );
1789 	}
1790 
1791 
1792 /*
1793  *	yait_write_op:
1794  */
1795 
1796 static char*
yait_write_op(Fi * f)1797 yait_write_op( Fi *f )
1798 	{
1799 	static char buf[10];
1800 	char *p;
1801 	int op;
1802 
1803 	p = buf;
1804 	if( f->drop )
1805 		{
1806 		*p++ = 'd';
1807 		*p = 0;
1808 		Stat_nd++;
1809 		return( buf );
1810 		}
1811 
1812 	op = f->op;
1813 	if( op & Y_OP_ODD )
1814 		*p++ = 'o';
1815 	if( op & Y_OP_EVEN )
1816 		*p++ = 'e';
1817 	if( op & Y_OP_SAVE )
1818 		*p++ = 's';
1819 	if( op & Y_OP_COPY )
1820 		*p++ = 'c';
1821 	if( op & Y_OP_DROP )
1822 		{
1823 		*p++ = 'd';
1824 		Stat_nd++;
1825 		if( op & Y_OP_ODD )
1826 			Stat_no++;
1827 		else
1828 			Stat_ne++;
1829 		}
1830 	if( op & Y_OP_DEINT )
1831 		{
1832 		*p++ = '0' + DeintMode;
1833 		Stat_nb++;
1834 		}
1835 	*p = 0;
1836 
1837 	return( buf );
1838 	}
1839 
1840 
1841 /*
1842  *	yait_fini:
1843  *		Free up allocations.
1844  */
1845 
1846 static void
yait_fini(void)1847 yait_fini( void )
1848 	{
1849 	int i;
1850 
1851 	for( i=0; i<Nf; i++ )
1852 		free( Fa[i] );
1853 
1854 	free( Fa );
1855 	free( Ga );
1856 	free( Da );
1857 	}
1858 
1859 
1860 /*
1861  *	Output debug information to stdout
1862  */
1863 
1864 static void
yait_debug_fi(void)1865 yait_debug_fi( void )
1866 	{
1867 	Fi *f;
1868 	int i;
1869 
1870 	printf( "Options:\n" );
1871 	printf( "\tLog file: %s\n", LogFn );
1872 	printf( "\tOps file: %s\n", OpsFn );
1873 	printf( "\tEven Threshold: %g\n", EThresh );
1874 	printf( "\tOdd Threshold: %g\n", OThresh );
1875 	printf( "\tBlend threshold: %g\n", Blend );
1876 	printf( "\tDrop window size: %d\n", DropWin );
1877 	printf( "\tDe-interlace mode: %d\n\n", DeintMode );
1878 
1879 	printf( "Stats:\n" );
1880 	printf( "\tTotal number of frames: %d\n", Nf );
1881 	printf( "\tNumber of frames divided by 5: %d\n", Nf/5 );
1882 	printf( "\tTotal dropped frames: %d\n", Stat_nd );
1883 	printf( "\tTotal blended frames: %d\n", Stat_nb );
1884 	printf( "\tTotal odd interlaced pairs: %d\n", Stat_no );
1885 	printf( "\tTotal even interlaced pairs: %d\n", Stat_ne );
1886 	printf( "\tNumber of forced frame drops: %d\n", Stat_fd );
1887 	printf( "\tNumber of forced frame keeps: %d\n\n", Stat_fk );
1888 	printf( "\tMax row delta: %d\n\n", Md );
1889 
1890 	i = 0;
1891 	for( f=Fl; f; f=f->next, i++ )
1892 		{
1893 		if( i && !(i%5) )
1894 			printf( "\n" );
1895 
1896 		printf( "Frame %6d: e: %8d, o: %8d, r: %7.3f, ro: %7.3f, w: %8.4f, "
1897 			"ip: %2d, gi: %6d, op: %-4s d: %s   %s\n",
1898 				f->fn, f->ed, f->od, f->r, f->ro, f->w, f->ip, f->gi,
1899 				yait_op(f->op), yait_drop(f), yait_grp(f->gf) );
1900 		}
1901 	}
1902 
1903 static char*
yait_op(int op)1904 yait_op( int op )
1905 	{
1906 	static char buf[10];
1907 	char *p;
1908 
1909 	p = buf;
1910 	*p = 0;
1911 	if( !op )
1912 		return( buf );
1913 
1914 	if( op & Y_OP_ODD )
1915 		*p++ = 'o';
1916 	if( op & Y_OP_EVEN )
1917 		*p++ = 'e';
1918 	if( op & Y_OP_SAVE )
1919 		*p++ = 's';
1920 	if( op & Y_OP_COPY )
1921 		*p++ = 'c';
1922 	if( op & Y_OP_DROP )
1923 		*p++ = 'd';
1924 	if( op & Y_OP_DEINT )
1925 		*p++ = '0' + DeintMode;
1926 	*p = 0;
1927 
1928 	return( buf );
1929 	}
1930 
1931 static char*
yait_drop(Fi * f)1932 yait_drop( Fi *f )
1933 	{
1934 	if( f->drop )
1935 		return( "DROP" );
1936 
1937 	if( f->op&Y_OP_ODD && f->op&Y_OP_DROP )
1938 		return( "odd " );
1939 
1940 	if( f->op&Y_OP_EVEN && f->op&Y_OP_DROP )
1941 		return( "even" );
1942 
1943 	return( "    " );
1944 	}
1945 
1946 static char*
yait_grp(int flg)1947 yait_grp( int flg )
1948 	{
1949 	switch( flg )
1950 		{
1951 		case Y_HAS_DROP:
1952 			return( "has drop" );
1953 		case Y_BANK_DROP:
1954 			return( "bank" );
1955 		case Y_WITHDRAW_DROP:
1956 			return( "withdraw" );
1957 		case Y_BORROW_DROP:
1958 			return( "borrow" );
1959 		case Y_RETURN_DROP:
1960 			return( "return" );
1961 		case Y_FORCE_DEINT:
1962 			return( "force deint" );
1963 		case Y_FORCE_DROP:
1964 			return( "force drop" );
1965 		case Y_FORCE_KEEP:
1966 			return( "force keep" );
1967 		}
1968 	return( "" );
1969 	}
1970