// aviinit.cpp
//
// MPEG2AVI
// --------
//  v0.16B31 calls cAVIwriter->reset_counters(), if >1 AVI file is created,
//    corrected printf() to use %lu instead of %ld
//    fixed the default autosplit size if none is specified (now 2000MB, to
//    be consistent with MPEG2DEC.C)
//  v0.16B3 added user-query for overwrite into avi_fileopen()
//    (used to be located in the cAVIwriter object)
//    removed use of getchar() and _getch(), which caused problems with
//    other portions of MPEG2AVI (because the other input routines use
//    scanf(), which seems to leave a few keystrokes in the input buffer,
//    causing getchar() and _getch() to read previous keystrokes.)
//  v0.16B22 updated avi_fileclose() to check for existant object cAVIwriter
//    prior to calling member-function.
//  v0.16B1 initial release,
//    added some entries to fps_table
//
// wrapper so C-functions can interact with C++ object "cAVIwriter"
//

#define _AVIINIT_CPP 1 // for global.h

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

#include<stdio.h>
#include<string.h>
#include<conio.h>

#include<windows.h>

/* private variables and functions */
static cAVIwriter *m_poAVIwriter = NULL;
static DWORD get_fps( LPDWORD lpfpsRate, LPDWORD lpfpsScale,
	tUserOption UserOptFPS );
static DWORD avi_init( BITMAPINFO bmi, const char szName[], 
	tUserOption UserOptFPS );

static DWORD m_dwAVISplitLength = 0;

// these vars are for get_fps()
#define _AVIRATE_TABLELENGTH 7
static DWORD fps_table[][2] = { 
	{24000, 1001},	// [0] = 23.976fps NTSC film 
	{30000, 1001},  // [1] = 29.97 fps NTSC video
	{25   , 1   },  // [2] = 25.000fps PAL film
	{24   , 1   },  // [3] = 24.000fps
	{30   , 1   },  // [4] = 30.000fps
	{23976, 1000},	// [5] = 23.976fps (exact)
	{29970, 1000},  // [6] = 29.970fps (exact)
	{ 0  , 0  }  /* end of table */
};


DWORD 
avi_init( BITMAPINFO bmi, const char szName[], tUserOption UserOptFPS )
{
	DWORD m_dwRate = 0;
	DWORD m_dwScale = 0;
	DWORD dwrc = 0;	// dword return code

	if ( m_poAVIwriter == NULL )
	{
		fprintf( stderr, "\navi_init() : (m_poAVIwriter == NULL ) !");
		exit( ERROR );
	}

	// read frame-per-second from global variables
	dwrc = get_fps( &m_dwRate, &m_dwScale, UserOptFPS );
	if ( dwrc != 0 )
	{
		fprintf( stderr, "\navi_init() : get_fps() failed!" );
		exit( ERROR );
	}

	// now set the cAVIwriter's fps variable
	dwrc = m_poAVIwriter->set_fps( m_dwRate, m_dwScale );
	if ( dwrc != AVWERR_OK )
	{
		fprintf( stderr, "\navi_init() : set_fps() failed!" );
		exit( ERROR );
	}

	// set the cAVIwriter's bitmap format
	dwrc = m_poAVIwriter->set_bmi( bmi );
	if ( dwrc != AVWERR_OK )
	{
		fprintf( stderr, "\navi_init() : set_bmi() failed!" );
		exit( ERROR );
	}

	dwrc = m_poAVIwriter->set_avistring( szName );
	if ( dwrc != AVWERR_OK )
	{
		fprintf( stderr, "\navi_init() : set_avistring() failed!" );
		exit( ERROR );
	}
	
	return AVWERR_OK;	// success
}

extern "C" DWORD 
avi_fileopen( const char aviFilename[], const char szName[], 
	LPRECT CropRect, BITMAPINFO bmi, tUserOption UserOptFPS, tUserOption 
	UserOptAVISplitLength, BOOL fCodecSelect )
{
	FILE *fpavi;
	char  ch;	// temporary char
	DWORD dwrc = 0; // dword return code

	if ( m_poAVIwriter != NULL )
	{
		fprintf( stderr, "\navi_fileopen() : odd, AVIwriter already exists!");
		exit( ERROR );
	}

	m_poAVIwriter = new cAVIwriter;
	if ( m_poAVIwriter == NULL )
	{
		fprintf( stderr, "\navi_fileopen() : Could not create cAVIwriter!");
		exit( ERROR );
	}

//SVE 03.06.2001
	m_poAVIwriter->m_pRunState=&st_RunState;

	// avi_init() takes care of setting szName, bmi, and fps
	dwrc = avi_init( bmi, szName, UserOptFPS );
	if ( dwrc != 0 )
	{
		fprintf( stderr, "\navi_fileopen() : avi_init() failed!" );
		exit( ERROR );
	}

	/*
	fpavi = fopen( aviFilename, "rb" );
	if ( fpavi != NULL )
	{
		printf("\n'%s' already exists, overwrite (Y/N) ? ", aviFilename );
		scanf( " %c", &ch );
		if ( ch != 'Y' && ch != 'y' )
		{
			printf("\nYou typed '%c'", ch );
			exit( ERROR );
		}
	}*/

	m_poAVIwriter->set_fileoverwrite( TRUE ); // enable file overwrite

	// call user-interface for codec-selection, TRUE=select new codec
	dwrc = m_poAVIwriter->ui_codec( TRUE );  
	if ( dwrc != AVWERR_OK )	// did ui_codec() fail?
	{
		fprintf( stderr, "avi_fileopen() : ui_codec() failed.");
		exit( ERROR );
	}

	dwrc = m_poAVIwriter->avi_fileopen( aviFilename, CropRect );
	if ( dwrc != AVWERR_OK )
	{
		fprintf( stderr, "\navi_fileopen() : avi_fileopen() failed!" );
		exit( ERROR );
	}

	// get AVI-split length for auto segmenting
	if CHECKOPT( UserOptAVISplitLength )
		m_dwAVISplitLength = GETOPT( UserOptAVISplitLength );
	else
		m_dwAVISplitLength = 0; //2000 * 1024 * 1024; // v0.16B31

//SVE 03.06.2001	st_RunState.startTime = m_poAVIwriter->m_start_time;

	return AVWERR_OK; // success
}

extern "C" DWORD
avi_fileclose( void )
{
	DWORD dwrc = 0; // dword return code

	if ( m_poAVIwriter == NULL )
	{
		fprintf( stderr, "\navi_fileclose() : m_poAVIwriter == NULL !");
		return AVWERR_FAIL;
	}

	dwrc = m_poAVIwriter->avi_fileclose();
	if ( dwrc != AVWERR_OK )
	{
		fprintf( stderr, "\navi_fileclose() : avi_fileclose() failed!" );
		return dwrc;
	}

	delete m_poAVIwriter;
	m_poAVIwriter = NULL;

	return AVWERR_OK;
}

//SVE 20.05.2001 Neuer Parameter: Erzeungener Keyframe
extern "C" DWORD
store_avi_one( const char aviFilename[], unsigned char *source_frame,
	LPRECT CropRect, long FrameNumber, BOOL bKeyFrame )
// SVE ENDE
{
	static DWORD dwrc = 0; // dword return code
	static DWORD dwFileCount = 1;
	static char newaviFilename[ 1024 ];
	static DWORD i;
	static time_t CurrentTime; // Added PX3 for FPS Counter 


	if ( m_dwAVISplitLength && m_poAVIwriter->get_cbWritten() >= m_dwAVISplitLength )
	{
		newaviFilename[0] = '\0';
		++dwFileCount;
		//printf("\nstore_avi_one() : auto-splitting to new avi-file.");
		dwrc = m_poAVIwriter->avi_fileclose();
		if ( dwrc != AVWERR_OK )
		{
			fprintf( stderr, "  Couldn't close current AVI-file!");
			exit( ERROR );
		}

		i = 0; // copy string up until '.'
		while ( aviFilename[ i ] != '.' && aviFilename[ i ] != 0 )
		{
			newaviFilename[ i ] = aviFilename[ i ];
			++i;
		}
		newaviFilename[ i ] = 0;	// terminate the copied string

		// form new string name "abc32.avi"
		sprintf( newaviFilename, "%s%lu.avi", newaviFilename, dwFileCount );

		dwrc = m_poAVIwriter->ui_codec( FALSE ); // reuse old codec
		if ( dwrc != AVWERR_OK )
		{
			fprintf( stderr, "\navi_fileopen() : couldn't reopen old codec!");
			exit( ERROR );
		}

		m_poAVIwriter->reset_counters(); // v0.16B31 reset byte counters
		dwrc = m_poAVIwriter->avi_fileopen( newaviFilename, CropRect );
		printf(" ... autosplitting to file#%lu : '%s'\n", dwFileCount, 
			newaviFilename );
	}

//SVE 20.05.2001 Neuer Parameter: Erzeungener Keyframe
	dwrc = m_poAVIwriter->store_avi_one( aviFilename, source_frame, CropRect,
		FrameNumber, bKeyFrame );
//SVE ENDE
	if ( dwrc != AVWERR_OK )
	{
		fprintf( stderr, "\nstore_avi_one() : store_avi_one() failed!" );
		return dwrc;
	}
//SVE 20.05.2001 Merken, wann der erste Frame geschrieben wurde
//SVE 03.06.2001	if ( !(m_poAVIwriter->m_dwFrameCount %10) )	// PX3
//SVE 03.06.2001	{
	st_RunState.encFrames = m_poAVIwriter->m_dwFrameCount;
	st_RunState.kbWritten = (m_poAVIwriter->m_cbWritten)/1024;
	st_RunState.keyFrames = m_poAVIwriter->m_dwKFCount;
//SVE 20.05.2001	st_RunState.FPS = (m_poAVIwriter->m_dwFrameCount/(difftime(CurrentTime,st_RunState.startTime)));
//SVE 20.05.2001 Ausgabe am Bildschirm hier!
//SVE 03.06.2001			printf("\rFrame %6lu (%.0f KB) KF=%lu FPS=%.2f ET=%s TT=%s    ",
//SVE 03.06.2001			FrameNumber,
//SVE 03.06.2001			st_RunState.kbWritten,
//SVE 03.06.2001			st_RunState.keyFrames,
//SVE 03.06.2001			st_RunState.FPS,
//SVE 03.06.2001			st_RunState.ElapsedTime,
//SVE 03.06.2001			st_RunState.RemainTime );
//SVE 03.06.2001		}

	return AVWERR_OK;
} // store_avi_one()


/* private functions */

/*
 * get_fps()  [ this code was originally part of avi_fileopen() ]
 * parse fps from user (or command-line option)
 */
DWORD
get_fps( LPDWORD lpfpsRate, LPDWORD lpfpsScale, tUserOption UserOptFPS )
{
	DWORD fpsRate = 0, fpsScale = 0;
	int i;
	char ch;

	if ( CHECKOPT( UserOptFPS ) )
		i = GETOPT( UserOptFPS ) ;
	else
	{	// AVIrate wasn't specified by command-line, so ask NOW
		i = 0;
		do {
			printf("\n\t(%d) = %.3f fps   <%lu/%lu>", i, 
				(double)fps_table[ i ][ 0 ] / fps_table[ i ][ 1 ],
				fps_table[ i ][ 0 ] , fps_table[ i ][ 1 ] );
			i++;
		} while ( i < _AVIRATE_TABLELENGTH );
		printf("\n\t(%d) = Custom frame-rate ", _AVIRATE_TABLELENGTH );

	/* 
		if ( CHECKOPT( UserOptIVTC ) ) // IVTC in use?
			printf("\n\t(IVTC active, recommendation is 23.976 or 24 fps)");
	*/
		printf("\n\tSelect AVI frame-rate : ");
		scanf( " %d", &i );
	}

	if ( i < 0 || i > _AVIRATE_TABLELENGTH )
	{
		fprintf( stderr, "\nERROR : %d is an invalid frame-rate selection!",
			i );
		return ERROR;
	}

	if ( i < _AVIRATE_TABLELENGTH )
	{
//SVE 20.05.2001		printf( " \nAVI frame rate ('-f%d') = %.3f (fps), ", i, (double) 
//SVE 20.05.2001			fps_table[ i ][ 0 ] / fps_table[ i ][ 1 ] );
		fpsScale = fps_table[ i ][ 1 ];
		fpsRate = fps_table[ i ][ 0 ];
	}
	else 
	{	/* 0.15B2 custom AVI-frame rate selection */
	  printf("\nCustom selection : fps = ( dwRate / dwScale )" );
	  do {
		printf("\nChoose dwRate (decimal) : " );
		scanf( " %lu", &fpsRate );
		printf("Choose dwScale (decimal) : " );
		scanf( " %lu", &fpsScale );
		printf("Chosen frame rate = %.3f (fps)  ... Acceptable?", (double) fpsRate /
			fpsScale );
		scanf( " %c", &ch );
	  } while ( toupper( ch ) != 'Y' );
	}

	*lpfpsRate = fpsRate;
	*lpfpsScale = fpsScale;
	return 0; // OK, != ERROR
} // endfunction get_fps()
