/*
	MPEGInfo v1.1 © 1998 Fredrik Rambris. All rights reserved.
	** Use on your own RISC! ** ( hehe )

	This little piece of code searches a file for a MPEG Header
	and extracts all the info it can and prints it.

	You may use it in your own programs if you like. But be sure
	to give me proper credits.

	NOTE: This is written for StormC but can aswell be used in
	other compilers such as SAS/C, Dice, etc.
*/

#include <clib/dos_protos.h>
#include <clib/exec_protos.h> /* Only needed for SetSignal */

#include "Date.h" /* My library of useful date/time-functions */

void main(void)
{
	UBYTE Template[7]="FILE/A";
	UBYTE ReadError[14]="Read error!\n", Yes[4]="Yes", No[3]="No", Time[10]="", NoMPEG[33]="This is not a valid MPEG file\n";
	BOOL sync=FALSE;
	LONG Args[1]={0};
	struct RDArgs *rdargs;
	BPTR file;
	WORD Char;
	struct FileInfoBlock *fib=NULL;
	BOOL ExSucc=FALSE;
	struct HMS hms;

	UWORD Bitrates[2][3][16]= /* In Kilos */
	{
		/* MPEG-I */
		{
			/* Layer 1 */
			{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},

			/* Layer 2 */
			{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},

			/* Layer 3 */
			{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}
		},

		/* MPEG-II */
		{
			/* Layer 1 */
			{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},

			/* Layer 2 */
			{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},

			/* Layer 3 */
			{0,8,16,24,32,64,80,56,64,128,160,112,128,256,320,0}
		}
	};

	UWORD Frequencies[2][4]=
	{
		/* MPEG-I */
		{ 44100, 48000, 32000, 0 },

		/* MPEG-II */
		{ 22050, 24000, 16000, 0 }
	};

	STRPTR Modes[4]=
	{
		(STRPTR)"Stereo",
		(STRPTR)"Joint Stereo",
		(STRPTR)"Dual channel",
		(STRPTR)"Mono"
	};

	/* These are seldom used */
	STRPTR Emphasis[4]=
	{
		(STRPTR)"None",
		(STRPTR)"50/15ms",
		(STRPTR)"", /* Couldn't find info about this one */
		(STRPTR)"CCITT j.17"
	};

	/* The Frame-header fields */
	UBYTE MPEG_ID;
	UBYTE MPEG_Layer;
	BOOL MPEG_Protection;
	UWORD MPEG_Bitrate;
	UWORD MPEG_Frequency;
	BOOL MPEG_Pad;
	BOOL MPEG_Private;
	UBYTE MPEG_Mode;
	UBYTE MPEG_ModeExtension;
	BOOL MPEG_Copyright;
	BOOL MPEG_Home;
	UBYTE MPEG_Emphasis;
	/* End of The Frame-header fields */

	ULONG Duration;
	ULONG Framesize;

	Printf("MPEGInfo v1.1 © 1998 Fredrik Rambris\n");

	/* Make it possible for us to get the filesize later */
	fib=AllocDosObject( DOS_FIB, NULL );

	if( rdargs=ReadArgs( Template, Args, NULL ) )
	{
		if( file=Open( (char *)Args[0], MODE_OLDFILE ) )
		{
			SetSignal( 0L, SIGBREAKF_CTRL_C );
			while( ( Char=FGetC( file ) ) != -1 )
			{
				/* Make it possible to break */
				if( SetSignal( 0L, SIGBREAKF_CTRL_C )&SIGBREAKF_CTRL_C )
				{
					Printf("\n***BREAK\n");
					break;
				}
				if( sync )
				{
					if( ((Char & 240)==240)|((Char & 240)==224) )
					{
						/* Were in sync! */
						MPEG_ID=(Char&8)?1:2;
						MPEG_Layer=4-( (Char&6) >> 1 );
						if( (MPEG_Layer==4) | (MPEG_Layer==0) )
						{
							Printf(NoMPEG);
							break;
						}

						MPEG_Protection=Char&1;

						/* Read in another byte */
						if( ( Char=FGetC( file ) ) == -1 )
						{
							Printf(ReadError);
							break;
						}

						MPEG_Bitrate=Bitrates[MPEG_ID-1][MPEG_Layer-1][( (Char&240) >> 4 )];
						if( MPEG_Bitrate==0 )
						{
							Printf(NoMPEG);
							break;
						}

						MPEG_Frequency=Frequencies[MPEG_ID-1][( (Char&12) >> 2 )];
						if( MPEG_Frequency==0 )
						{
							Printf(NoMPEG);
							break;
						}

						MPEG_Pad=Char&2;
						MPEG_Private=Char&1;

						/* Read in another byte */
						if( ( Char=FGetC( file ) ) == -1 )
						{
							Printf(ReadError);
							break;
						}

						MPEG_Mode=(Char&192) >> 6;
						MPEG_ModeExtension=(Char&48) >> 4;
						MPEG_Copyright=Char&8;
						MPEG_Home=Char&4;
						MPEG_Emphasis=Char&3;

						ExSucc=ExamineFH( file, fib );

						if( (MPEG_Layer==4)|(MPEG_Layer==0)|(MPEG_Bitrate==0)|(MPEG_Frequency==0) )
						{
							Printf(NoMPEG);
						}
						else
						{
							Framesize=(144*(MPEG_Bitrate*1000)/MPEG_Frequency)+(MPEG_Pad?1:0);

							Printf("\n--[MPEG Header]---------\n");
							Printf("ID: %ld\n",MPEG_ID);
							Printf("Layer: %ld\n",MPEG_Layer);
							Printf("Protection: %s\n",MPEG_Protection?Yes:No);
							Printf("Bitrate: %ld\n",MPEG_Bitrate);
							Printf("Frequency: %ld\n",MPEG_Frequency);
							Printf("Pad: %s\n",MPEG_Pad?Yes:No);
							Printf("Private: %s\n",MPEG_Private?Yes:No);
							Printf("Mode: %s\n", Modes[MPEG_Mode] );
							Printf("Mode Extension: %%%ld%ld\n", MPEG_ModeExtension&2,MPEG_ModeExtension&1 );
							Printf("Copyright: %s\n",MPEG_Copyright?Yes:No);
							Printf("Home: %s\n",MPEG_Home?Yes:No);
							Printf("Emphasis: %s\n",Emphasis[MPEG_Emphasis]);
							Printf("\n--[Other info]----------\n");
							Printf("Framesize: %ld\n", Framesize );

							if( ExSucc )
							{
								/* Duration in Secs */
								/* This version subtracts all the frameheaders
									before calculating the duration
									Duration=(fib->fib_Size-((fib->fib_Size/Framesize)*4))/( (MPEG_Bitrate*1000)/8 ); */
								Duration=fib->fib_Size/( (MPEG_Bitrate*1000)/8 );
								HMSToStr( SecsToHMS( Duration, &hms ), Time );
								Printf("Filesize: %ld\n", fib->fib_Size );
								Printf("Duration: %s\n", Time );
							}
						}
						break;
					}
					else sync=FALSE;
				}

				if( !sync ) if( Char==255 ) sync=TRUE;

			}
			Close( file );
		}
		FreeArgs( rdargs );
	}
	else Printf("Usage: MPEGInfo %s\n", Template);

	if( fib ) FreeDosObject( DOS_FIB, fib );
}