/*
 * telecine.c
 *
 * inverse_telecine() = performs IVTC algorithm 
 *
 * MPEG2AVI
 * --------
 * v0.16B35
 *   increased memory-padding from +1 to +2 (in calloc calls)
 *    allow ivtc to be initialized to odd-polarity
 *    s0 - s4 are even polarity, s5-s9 are odd polarity
 * v0.16B34 converted malloc() calls to calloc() calls
 * v0.16B31
 *   There is a lot of "funny code" in the state-machine control.  It's for
 *   the "improved" auto-IVTC.  For several days, I tried to fine-tune the
 *   auto-IVTC to maintain proper field-sync with a test bitstream which
 *   was hopelessly confused.  I've given up on it for now.
 * v0.16B23
 *   changed the memory-clear code to memset()
 * v0.15B5
 *   due to code restructuring, ivtc_half_8bpp() has been retired
 * v0.15
 *   added "on-the-fly" control mechanism, keyboard is read during
 *      display_dib(), then sent to telecine.c through the variable
 *      g_cmd_ivtc.  if ( g_cmd_ivtc != 0 ), then we have some new input from 
 *      keyboard.
 *
 *   process_ivtc_cmd( ) - parses g_cmd_ivtc, and resets it.
 *      orders auto-shutdown of IVTC(), if repeat_first_field detected
 *
 *   added FIR-lowpass filter, supposed to provide high-quality downsampling
 *      as far as I can tell, it wastes CPU-time without producing tangibly
 *      better output!  But it's there for people to use.
 *      (these FIR filters are taken straight from MSSG MPEG2V12 readpic.c)
 *
 * v0.14 
 *   substantial changes since last update.
 *   the original function inverse_telecine(), is no longer used!
 *   (It's only here as an algorithmic reference to help others
 *    understand the basic IVTC algorithm.)
 *
 *   There are now two new functions : ivtc_full_8bpp() & ivtc_half_8bpp()
 *
 *   ivtc_full_8bpp() - performs IVTC on an 8bpp sequence of images.
 *     The input sequence ( y_src[] = 1 frame of input sequence ) is assumed 
 *     to be "WEAVE de-interlaced"  In other words, y_src[] is composed of
 *     two different fields (odd and even), "weaved" together by scanline.
 *     (Even-scanlines form even-field.  Odd-scanlines form odd-field.)
 *     The two fields are separated in time, 1/60sec apart.
 *     
 *
 *   ivtc_half_8bpp() - similar to ivtc_full_8bpp(), except the output
 *     is *downsampled* 1/2-resolution.  (eg. if input is 720x480, output
 *     is 360x240.)
 *
 *
 * v0.10 initial release

   This file was added to the original MSSG (MPEG Software Simulation
   Group) MPEG2V12 codec.  It performs an inverse-telecine algorithm,
   also known as reverse 3:2 pulldown.  The code requires a user
   selection for the state-machine's initial "frame offset."  
   
   Since the MPEG2codec must decode all frames starting from 0, the
   "frame-offset" is used to set IVTC's start-state.  The net effect
   is the same; the user can control the IVTC's relative skew with
   respect to the decoded-frames' position.

   This file is *NOT* part of the original MSSG MPEG2V12 distribution!

 */

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>

#include"config.h"
#include"global.h"


/* int g_cmd_ivtc ... in mpeg2dec.c */

/* private functions */
unsigned char * 
inverse_telecine_retired( unsigned char source_picture[], long height, long width,
				 long FrameNum );
BOOL process_ivtc_cmd( int *ivtc_counter, long FrameNum );
static void set_sync_state( DWORD fieldOffset, BOOL b_tff );

// private definitions
#define KEY_IVTC_PAUSE  257 // for autodisable IVTC mode
#define KEY_IVTC_RESUME0  258 // for autodisable IVTC mode
#define KEY_IVTC_RESUME1  259 // for autodisable IVTC mode
#define KEY_IVTC_RESUME2  260 // for autodisable IVTC mode
#define KEY_IVTC_RESUME3  261 // for autodisable IVTC mode
#define KEY_IVTC_RESUME4  262 // for autodisable IVTC mode
#define _EVEN 1
#define _ODD 2


static unsigned long m_fieldCounter = 1 ;
static DWORD g_ivtc_polarity = _EVEN;

/* as of v0.14, inverse_telecine() has been retired!  
   inverse_telecine() - accepts 24bpp packed images, RGB24 or YUV888

   Why was inverse_telecine() retried?  Observed "Color bleed" in the 
   transition frame of the IVTC frame-sequence (0.1.2.3.4.0.1.2.3.4, etc.)
   Chroma-fields (U/V) from two temporally adjacent frames, 
   alternating by scanline are messed together.  (even scanline = previous
   frame, odd scanline = current)  This suggests that the IVTC algorithm
   is pulling chroma-data the *wrong* field.

   Function modifies the source picture data (source_picture[])
*/

unsigned char * 
inverse_telecine_retired( unsigned char source_picture[], long height, long width,
		long FrameNum )
{
	static int j, ivtc_counter = _DISABLE_IVTC;	
	static int first_iteration = 1; 

	/* Input picture is a 24bpp packed-pixel array.  RGB or YUV */

   static unsigned char *fbstore = NULL;
  
  if ( first_iteration )
  {
	first_iteration = 0;	/* disable this flag */
	if ( CHECKOPT( UserOptIVTC ) )
		ivtc_counter = GETOPT( UserOptIVTC ); /* initialize ivtc_counter */

	fbstore = (unsigned char *)calloc(  2+ ((height * width * 3)>>5), 32 ); 
	
	/* allocate memory for framebuffer */
	if ( fbstore == NULL )
	{
		fprintf( stderr, "\nCouldn't allocate fbstore[] space!");
		exit( ERROR );
	}
	else	/* clear memory */
		memset( fbstore, 0, Coded_Picture_Width*Coded_Picture_Height*3 );

  }

	/* algorithm for inverse_telecine

  If you're not already familiar with film/video transfer issues, there
  are many web-sites with good papers on on this subject.
	


  
  INVERSE-TELECINE ALGORITHM

    INPUT SEQUENCE
    MPEG CODED PICTURES (source material with redundant information)
	|-------|-------|-------|-------|-------|-------|-------+---+---+---+---+---+---
SRC | E | O | E | O | E | O | E | O | E | O | E | even/odd status
(IN)| 0 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 5 | picture# (2fields=1picture)
	|-------|-------|-------|-------|-------|-------|-------+---+---+---+---+---+---
    | Frame |     2   R : Frame : R   4     | Frame |         R :
  	|   1   |   Frame   :   3   :   Frame   |   5   |           :
	+-------+-----------+-------+-----------+-------+
	  |   |   |   |       |   |       |   |   |   |
    +---+---+---+---+---+---+---+---+---+---+---+---+
OUT | E0.O0 |  E1.O1    : O2.E3 :   E4.O4   | E5.O5 |           
    +--#0---+-----#1----+--#2---+-----#3----+---#4--+----#5-----+...
    extracted pictures (redundant fields *removed*)
    OUTPUT SEQUENCE


	Definitions (note these are arbitrary definitions to explain my diagram...
	don't take these defs as the "industry convention"! )
	
	"Picture" = MPEG-2 coded image (720x480 for NTSC MP@ML)
	"field" = an interlaced image consisting of every other "picture" scanline,
			= an ODD + EVEN field form one PICTURE
	"frame" = one image from a motion picture film (usually shot @ 24fps)
	  
	"R"     = redundant field (note, either field of equal-polarity [even/odd]
            can be removed)


    MPEG-2 NTSC video (29.97Hz) and film-content (24fps)

    "3:2 pulldown" uses 5 NTSC fields to store 2 film frames.  For a given
	adjacent pair of (film) frames, the odd #fields forces one frame
	to be displayed longer than the other.  Thus, a film-source which
	has been transferred to NTSC-video will play like this :

	Frame#1   Frame#2  Frame#3  Frame#4  ...  (source frame#)
    2/60      3/60      2/60     3/60    ...  (display period in seconds)

    Over the playing time of the entire movie, the effective picture-rate 
	converges to ~23.976fps (assuming an accurate NTSC clock @ 29.97Hz.)
	There is a small residual difference (23.976fps vs 24fps) in 
	playback/source rates.  I am not totally certain what happens to
	this difference.  After 24 minutes, the film source and its 
	3:2 representation will diverge by ~1.5 seconds.  
	My guess is the difference is simply ignored.  In other words, 
	the 3:2 representation is played without any adjustment.  Hence 
	a 24.00second film segment will play for 23.976 seconds on TV.

    (Compared to PAL film conversion (25fps), NTSC 3:2 pulldown does a
	much better job of retaining the source film's (24fps) frame rate. 
	The simplest PAL-conversion technique copies one film frame per
	PAL frame.  Thus, the copied PAL-video plays the source film at 
	25fps, or a 4% speedup.  More sophisticated equipment analyzes the
	film, and duplicates a frame whenever a "static scene" (i.e. no
	change between adjacent frames) is detected.)
	
	Here's an illustration of the 3:2 pulldown process...

    FILM SOURCE +------#1------+------#2------+------#3------+------#4------+
        |||     |             /               |             /               |
        |||     | picture#1  /    picture#2   | picture#3  /    picture#4   |
        VVV     |           /                 |           /                 |
    NTSC video  |--O--+--E--|--O--+--E--|--O--+--E--+--O--|--E--+--O--|--E--+
                |     v1    |     v2    |    v3     |     v4    |     v5    |


	#1...#4 = film frame # (23.976fps)
	v1...v5 = NTSC video frame # (29.97Hz)
	*/

	/* This switch statement embodies the entire inverse-telecine algorithm 
	   The algorithm cycles repeatedly through 5 states : 0..1..2..3..4..0..1..
	   Currently, user must specify a starting "frame-offset", which is
	   the starting-state (0, 1, 2, 3, or 4.) 
	 */


	process_ivtc_cmd( &ivtc_counter, FrameNum ); /* process <commands> for IVTC-processor */

	switch ( ivtc_counter )	
	{
		case _DISABLE_IVTC : /* don't use inverse telecine algorithm */
			return source_picture;
			break;
	  /* IVTC algorithm state 0 - "PASSTHROUGH" */
		case 0 : /* return the original picture as the next displayed frame */
			++ivtc_counter;  /* move to next state */
			return source_picture;
			break;

	  /* IVTC algorithm state 1 - "PASSTHROUGH" */
		case 1 : /* return the original picture as the next displayed frame */
			++ivtc_counter;	/* move to next state */
			return source_picture;
			break;

	  /* IVTC algorithm state 2 - "PASSTHROUGH" */
		case 2 : /* return the original picture as the next displayed frame */
			++ivtc_counter;	/* move to next state */
			return source_picture;
			break;

	  /* IVTC algorithm state 3 - "STORE AND DELETE" */
		case 3 :	/* extract the odd-field of current picture & store it */
			++ivtc_counter;	/* move to next state */
			if ( !memcpy( fbstore, source_picture, width * height * 3) )
			{
				fprintf(stderr, "\ninverse_telecine() memcpy failure" );
				exit( ERROR );
			}
			return NULL;	/* return *NOTHING*, signals the calling function */
			break;			/* delete current frame from displayed sequence */

	  /* IVTC algorithm state 4 - "TRANSITION" */
		case 4 :	/* merge even field [n] with odd field [ n-1 ] */
			ivtc_counter=0;	/* cycle back to state 0 */
			/* copy the *past* odd-field [#n-1] into the current [#n] */
			for ( j =0; j < height ; j=j+2 )
			{
				if ( !memcpy( fbstore + j*width*3, source_picture+j*width*3,
					width * 3) )
				{
					fprintf(stderr, "\ninverse_telecine() memcpy failure" );
					exit( ERROR );
				}
			}
			return fbstore;  /* current frame[#n] = even[#n] + odd[#n-1] */
			break;

		default:	/* reset the state-machine to state0 */
			ivtc_counter = 0;
			return NULL;	
	}
}

/* ivtc_full_8bpp()
 * performs IVTC on an 8bpp-packed sequence of images, 
 * 
    eg. INPUT SEQUENCE : 720x480 8bpp packed (1 frame per call)
        OUTPUT SEQUENCE: 720x480 8bpp packed
 * 
 * after 4 calls, ivtc_full_8bpp() deletes curernt frame on
 * 5th call.  Thus, for every 5 frames from input-sequence,
 * ivtc_full_8bpp() writes 4-frames to output-sequence.
 *
 * The function assumes input-sequence ( y_src[] is 1 frame )
 * is "weave-deinterlaced."  This means alternating y_src[]'s
 * EVEN-scanlines correspond to 1 field, and y_src[]'s ODD-
 * scanlines correspond to the other field.  These two
 * fields are "weaved" together to form the final image.
 * The key-point is that the image's two constituent fields
 * may be separated in time (1/60 sec apart.)
 *
 * "weave-deinterlaced" sequences are generally produced by
 * MPEG-2 interlaced sequences.  They *cannot* be produced
 * by MPEG-1 sequences (MPEG-1 has no support for "fields.")
 * 

 * Output : returns NULL (current picture deleted)
 *		<or>
 *        pointer to the downsampled/downscaled Y component 
 *      u_src[] and v_src[] may be changed by the function
 */


unsigned char * 
ivtc_full_8bpp( unsigned char y_src[], long FrameNum )
{
	long x = 0, y = 0;
	static int ivtc_counter= _DISABLE_IVTC ;
	static long s_x = 0, s_y = 0;
	/* s_x = source width, s_y = source height */
	static int first_iteration = 1; 

	/* Input is an 8bpp packed-pixel array!  */

   static unsigned char *y_store = NULL;
   /* static unsigned char *v_store = NULL, *u_store=NULL; */
  
  if ( first_iteration )
  {
	first_iteration = 0;	/* disable this flag */
	s_y= Coded_Picture_Height;
	s_x = Coded_Picture_Width;
	if ( CHECKOPT( UserOptIVTC ) )
	{
		ivtc_counter = GETOPT( UserOptIVTC ); /* initialize ivtc_counter */
		// v0.16B35, user to select odd polarity 
		g_ivtc_polarity  = ( ivtc_counter > 4 ) ? _ODD : _EVEN;
		ivtc_counter = ivtc_counter % 5;
	}

	/* allocate memory for framebuffer, 8bpp for each plane Y/U/V */
	y_store = (unsigned char *)calloc( ((s_x * s_y)>>5)+2, 32 );  
	/*
	u_store = (unsigned char *)malloc(   (long) (s_x * s_y ) ); 
	v_store = (unsigned char *)malloc(   (long) (s_x * s_y ) ); 
	
	if ( !( y_store || u_store || v_store ) ) */
	if ( y_store == NULL )
	{
		fprintf( stderr, "\nivtc_full_8bpp() : Couldn't allocate memory!");
		exit( ERROR );
	}
	memset( y_store, 0, s_x*s_y ); // clear memory
  }

	/* This switch statement embodies the entire inverse-telecine algorithm 
	   The algorithm cycles repeatedly through 5 states : 0..1..2..3..4..0..1..
	   Currently, user must specify a starting "frame-offset", which is
	   the starting-state (0, 1, 2, 3, or 4.) 
	 */

  /* process <commands> for IVTC-processor */
  process_ivtc_cmd( &ivtc_counter, FrameNum ); 

  if ( GETOPTAUX( UserOptIVTC ) == _IVTC_AUTODISABLE && 
	  ivtc_counter == _DISABLE_IVTC && !g_mpvpcur.brff )
  {
	if ( !memcpy( y_store, y_src, (s_x * s_y) ) )
	{
		fprintf( stderr, "\nivtc_full_8bpp() memcpy failed!");
			exit( ERROR );
	}
}

	switch ( ivtc_counter )	
	{
		case _DISABLE_IVTC : /* don't use inverse telecine algorithm */
			return y_src;
			break;

	  /* IVTC algorithm state 0 - "PASSTHROUGH" */
		case 0 : /* return the original picture as the next displayed frame */
			++ivtc_counter;	/* move to next state */
			return y_src;
			break;

	  /* IVTC algorithm state 1 - "PASSTHROUGH" */
		case 1 : /* return the original picture as the next displayed frame */
			++ivtc_counter;	/* move to next state */
			return y_src;
			break;

	  /* IVTC algorithm state 2 - "PASSTHROUGH" */
		case 2 : /* return the original picture as the next displayed frame */
			++ivtc_counter;	/* move to next state */
			return y_src;
			break;

	  /* IVTC algorithm state 3 - "STORE AND DELETE" */
		case 3 :	/* extract the odd-field of current picture, store it */
			++ivtc_counter;	/* move to next state */

			/* copy y_src[] plane to frame_storage buffer */
			if ( !memcpy( y_store, y_src, (s_x * s_y) ) )
			{
				fprintf( stderr, "\nivtc_full_8bpp() memcpy failed!");
				exit( ERROR );
			}

			/* if ( !memcpy( u_store, u_src, (s_x * s_y) )
			{
				fprintf( stderr, "\nivtc_full_yuv420() memcpy failed!");
				exit( ERROR );
			}

			if ( !memcpy( v_store, v_src, (s_x * s_y) )
			{
				fprintf( stderr, "\nivtc_full_yuv420() memcpy failed!");
				exit( ERROR );
			} */
			return NULL;	/* return *NOTHING*, signals the calling function */
			break;			/* delete current frame from output sequence */

	  /* IVTC algorithm state 4 - "TRANSITION" */
		case 4 :	/* merge even field [n] with odd field [ n-1 ] */
			ivtc_counter=0;	/* cycle back to state 0 */

   /* To my surprise, the IVTC works best if the U/V components of the
    * current-frame [#n] of the input-sequence are 
	* passed without modification.  the original inverse_telecine()
	* function exhibited "color-bleed" because the "transition" frame
	* contained U/V data from both previous [n-1] and current [n] 
	* input-sequence frames. Through trial and error, I determined the 
	* optimum output is obtained by passing the curent U/V data unmodified.
	* That is why the current ivtc-functions ignore the U/V planes
	* altogether.
	*
	* The calling function should be smart enough to discard U/V fields
	* for the deleted-frame.
	*/
			
			/* copy the current even-field of [#n] into the past [#n-1] */
			if ( g_ivtc_polarity == _EVEN )
				//|| GETOPTAUX( UserOptIVTC ) == _IVTC_AUTO_DISABLE )
				for ( y =0; y < s_y ; y=y+2 )
				{
					memcpy( y_store + y*s_x, y_src + y*s_x, s_x );
				}
			else	// odd polarity 
				for ( y =1; y < s_y ; y=y+2 )
				{
					memcpy( y_store + y*s_x, y_src + y*s_x, s_x );
				}

			return y_store;  /* current frame[#n] = even[#n] + odd[#n-1] */
			break;

		default:	/* reset the state-machine to state0 */
			ivtc_counter = 0;
			return NULL;	
	}
}



/* read the control-variable, g_cmd_ivtc.  Then clear it. */
BOOL
process_ivtc_cmd( int *ivtc_counter, long FrameNum )
{
	BOOL fCommand = TRUE; /* was there a recognized command? */
	long temp;
	static BOOL m_flag1 = FALSE;


	// update internal field counter, assumes '-f' mode is active
	if ( g_mpvpcur.brff )
		m_fieldCounter += 3; // repeat_first_field, frame is displayed 3 fields
	else
		m_fieldCounter += 2; // frame is only displayed 2 fields

	m_fieldCounter = m_fieldCounter % 10;

	if ( g_cmd_ivtc == KEY_IVTC_ENABLE && (!CHECKOPT( UserOptIVTC ) ))
	{
		SETOPT( UserOptIVTC, 0 ); /* init IVTC start-state to 0 */
		(*ivtc_counter) = (FrameNum % 5);
		printf("\r<IVTC on > \"-s%d\" @ F:%ld\n", GETOPT( UserOptIVTC ),
			FrameNum );
	}
	else
	{
		// 0.16B31 switches off IVTC, if rff is detected
		// shutdown ivtc if repeat_first_field (mpv_pinfo.brff) is detected!
		if ( CHECKOPT( UserOptIVTC ) && (*ivtc_counter) != _DISABLE_IVTC && 
			(GETOPTAUX( UserOptIVTC ) == _IVTC_AUTODISABLE ) &&
			g_mpvpcur.brff && g_mpvpcur.bpf )
		{
//			printf("rff, process_ivtc_cmd() : pause IVTC. (fC = %lu)\n", 
//				m_fieldCounter);
			g_cmd_ivtc = KEY_IVTC_PAUSE;	// 0.16B31
		}

		// 0.16B31, if we see two consecutive progressive-frames, both NON rff,
		// then activate IVTC @ state-2
		// 0.16B35, activate IVTC @ state-3
/*		if ( CHECKOPT( UserOptIVTC ) )
			//&& g_mpvpcur.bpf && g_mpvplast.bpf )
		{
			if ( g_mpvpcur.brff==0 && g_mpvplast.brff==0 && 
				(*ivtc_counter) == _DISABLE_IVTC )
			{
				// set the IVTC starting-offset to a value derived from
				// the current field's absolute position

				set_sync_state( m_fieldCounter );
//				printf("no rff, process_ivtc_cmd() : resume IVTC, fc=%lu.\n",
//					m_fieldCounter );
			}
			else
			if ( g_mpvpcur.brff==0 && g_mpvpcur.btff == 0 
				&& (*ivtc_counter) == _DISABLE_IVTC )
			{
				set_sync_state( m_fieldCounter );
			}

			if ( g_mpvplast.brff==0 && g_mpvpcur.brff == 1 && 
				g_mpvpcur.btff == 0  )
			{
				g_cmd_ivtc = KEY_IVTC_PAUSE;
				m_flag1 = FALSE;
			}
		}*/

		if ( CHECKOPT( UserOptIVTC ) )
		{
			if ( g_mpvpcur.brff==0 && g_mpvplast.brff==0 && 
				(*ivtc_counter) == _DISABLE_IVTC )
			{
				// set the IVTC starting-offset to a value derived from
				// the current field's absolute position

				set_sync_state( m_fieldCounter, g_mpvpcur.btff );
//				printf("no rff, process_ivtc_cmd() : resume IVTC, fc=%lu.\n",
//					m_fieldCounter );
			}

			if ( ( *ivtc_counter) != _DISABLE_IVTC && g_mpvpcur.brff==1 )
			{
				g_cmd_ivtc = KEY_IVTC_PAUSE;
			}
		}


		switch ( g_cmd_ivtc )
		{
			case KEY_IVTC_RESUME0 : // 0.16B31 IVTC resume @ IVTC state2
				(*ivtc_counter) = 0;
				printf("<IVTCres0> @ F:%ld (fc=%ld)\n", FrameNum, m_fieldCounter );
				break;
			case KEY_IVTC_RESUME1 : // 0.16B31 IVTC resume @ IVTC state2
				(*ivtc_counter) = 1;
				printf("<IVTCres1> @ F:%ld (fc=%ld)\n", FrameNum, m_fieldCounter );
				break;
			case KEY_IVTC_RESUME2 : // 0.16B31 IVTC resume @ IVTC state2
				(*ivtc_counter) = 2;
				printf("<IVTCres2> @ F:%ld (fc=%ld)\n", FrameNum, m_fieldCounter );
				break;
			case KEY_IVTC_RESUME3 : // 0.16B31 IVTC resume @ IVTC state2
				(*ivtc_counter) = 3;
				printf("<IVTCres3> @ F:%ld (fc=%ld)\n", FrameNum, m_fieldCounter );
				break;
			case KEY_IVTC_RESUME4 : // 0.16B31 IVTC resume @ IVTC state2
				(*ivtc_counter) = 4;
				printf("<IVTCres4> @ F:%ld (fc=%ld)\n", FrameNum, m_fieldCounter );
				break;
			case KEY_IVTC_PAUSE : // 0.16B31 IVTC in standby mode
				(*ivtc_counter) = _DISABLE_IVTC;
				printf("<IVTCpaus> @ F:%ld\n", FrameNum );
				break;
			case KEY_IVTC_DISABLE :
				CLEAROPT( UserOptIVTC );
				(*ivtc_counter) = _DISABLE_IVTC;
				printf("<IVTC off> @ F:%ld\n", FrameNum );
				break;
			case KEY_IVTC_UP :
				(*ivtc_counter) = ((*ivtc_counter ) + 1) % 5;
				SETOPT( UserOptIVTC, (GETOPT( UserOptIVTC ) + 1) % 5 );
				printf("<IVTC (+)> \"-s%d\"\n", GETOPT( UserOptIVTC ) );
				break;
			case KEY_IVTC_DOWN :
				(*ivtc_counter) = ((*ivtc_counter ) <= 0 ) ? 4 :
					((*ivtc_counter ) - 1);
				temp = GETOPT( UserOptIVTC );
				SETOPT( UserOptIVTC, ( (temp <= 0 ) ? 4 : (temp - 1 ) ) );
				printf("<IVTC (-)> \"-s%d\"\n", GETOPT( UserOptIVTC ) );
				break;
			case KEY_IVTC_TG_AUTODISABLE :
				if ( CHECKOPT( UserOptIVTC ) ) /* 1st, check if IVTC is on */
				{
					if ( GETOPTAUX( UserOptIVTC ) == _IVTC_AUTODISABLE )
					{
						SETOPTAUX( UserOptIVTC, 0 ); /* disable AutoDis */
					}
					else
					{
						SETOPTAUX( UserOptIVTC, _IVTC_AUTODISABLE );
					}
					printf("<IVTC> (AutoDis mode) : " );
					if ( GETOPTAUX( UserOptIVTC ) == _IVTC_AUTODISABLE )
						printf( " ON  \"-s%dD\"\n", GETOPT( UserOptIVTC ));
					else
						printf("OFF  \"-s%d\"\n", GETOPT( UserOptIVTC ) );
				}
				break;
			case 0 : /* no command */
				break;
			default :
				printf("<IVTC> unknown command!\n");
				fCommand = FALSE;
		}  /* endswitch */
	}  /* end else */
	
	g_cmd_ivtc = 0;  /* clear g_cmd_ivtc */

	if ( !CHECKOPT( UserOptIVTC ) ) /* final check on desired ivtc state */
		(*ivtc_counter) = _DISABLE_IVTC;

	return fCommand;
}


void
set_sync_state( DWORD fieldOffset, BOOL b_tff )
{
	if ( b_tff )	// top field first?
	{	// yes, top field-first =1
		g_cmd_ivtc = KEY_IVTC_RESUME2;
		g_ivtc_polarity = _EVEN;
	}
	else
	{	// no, top field-first = 0
		g_cmd_ivtc = KEY_IVTC_RESUME2;
		g_ivtc_polarity = _ODD;
	}
}


/*
this junk came about because I used a "bad" bitstream to prototype the
inverse-telecine routines.  The bitstream in question is the theatrical
trailer from Disney's Region1 DVD "George of the Jungle"  The MPEG-encoder/
authoring-system that generated this bitstream is totally broken.

Several interlaced segments within the bitstream switch sync-states.  In
other words, the MPEG-bitstream is coded inconsistently, causing playback
stutters when displayed on a reference-decoder. 

void
set_sync_state( DWORD fieldOffset, BOOL b_tff )
{
	switch ( fieldOffset ) // m_fieldCounter = 0..9 
	{
	  case 8 :	// originally case 0
		g_cmd_ivtc = KEY_IVTC_RESUME3;
		g_ivtc_polarity = _ODD;
		break;
	  case 9 :
		  // 4e fails with later clips
		g_cmd_ivtc = KEY_IVTC_RESUME1;  // 
		g_ivtc_polarity = _EVEN;  //
		break; 
	  case 0 :
		g_cmd_ivtc = KEY_IVTC_RESUME3; // not ok with 3e, or 3o
		g_ivtc_polarity = _ODD;
		break;
	  case 1 :
		g_cmd_ivtc = KEY_IVTC_RESUME2; // 
		g_ivtc_polarity = _EVEN;	// 
		break;
	  case 2 :
		g_cmd_ivtc = KEY_IVTC_RESUME4; 
		g_ivtc_polarity = _ODD;
		break;
	  case 3 :
		g_cmd_ivtc = KEY_IVTC_RESUME3; // 1o, 2o, 3o didn't work
		g_ivtc_polarity = _EVEN; // 2e works sort of later
		break;
	  case 4 :
		g_cmd_ivtc = KEY_IVTC_RESUME1;	
		g_ivtc_polarity = _ODD;
		break;
	  case 5 :
		g_cmd_ivtc = KEY_IVTC_RESUME3; //good
		g_ivtc_polarity = _EVEN;
		break;
	  case 6 :
		g_cmd_ivtc = KEY_IVTC_RESUME2; // 
		g_ivtc_polarity = _ODD; // 
		break;
	  case 7 :
		g_cmd_ivtc = KEY_IVTC_RESUME4; // 1o, 3o didn't work
		g_ivtc_polarity = _EVEN;
		break;
	  default:
		;
	} // switch ( m_fieldCounter )

}
*/