/* 
 *	Copyright (C) Chia-chen Kuo - April 2001
 *
 *  This file is part of DVD2AVI, a free MPEG-2 decoder
 *	
 *  DVD2AVI is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  DVD2AVI is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

//#include "global.h"
#include "getbit.h"


#include "store.h"
#include "wavefs44.h"




unsigned char Rdbfr[BUFFER_SIZE], *Rdptr, *Rdmax;
unsigned int BitsLeft, CurrentBfr, NextBfr, Val, Read;


static char l_szBuffer[_MAX_PATH];


#define LOCATE												\
while (Rdptr >= (Rdbfr + BUFFER_SIZE))						\
{															\
	Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE);	\
	if (Read < BUFFER_SIZE) Next_File();					\
	Rdptr -= BUFFER_SIZE;									\
}

#define DECODE_AC3																\
{																				\
	size = 0;																	\
	while (Packet_Length > 0)													\
	{																			\
		if (Packet_Length+Rdptr > BUFFER_SIZE+Rdbfr)							\
		{																		\
			size = g_AC3Dec.decode_data(Rdptr, BUFFER_SIZE+Rdbfr-Rdptr, size,g_DVDGlobals.Sound_Max,&g_Ac3Context);		\
			Packet_Length -= BUFFER_SIZE+Rdbfr-Rdptr;							\
			Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE);				\
			if (Read < BUFFER_SIZE) Next_File();								\
			Rdptr = Rdbfr;														\
		}																		\
		else																	\
		{																		\
			size = g_AC3Dec.decode_data(Rdptr, Packet_Length, size,g_DVDGlobals.Sound_Max,&g_Ac3Context);					\
			Rdptr += Packet_Length;												\
			Packet_Length = 0;													\
		}																		\
	}																			\
}

#define DECODE_AC3_2																\
{																				\
	size = 0;																	\
	while (Packet_Length > 0)													\
	{																			\
		if (Packet_Length+Rdptr > BUFFER_SIZE+Rdbfr)							\
		{																		\
			size = g_AC3Dec2.decode_data(Rdptr, BUFFER_SIZE+Rdbfr-Rdptr, size,g_DVDGlobals.Sound_Max,&g_Ac3Context2);		\
			Packet_Length -= BUFFER_SIZE+Rdbfr-Rdptr;							\
			Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE);				\
			if (Read < BUFFER_SIZE) Next_File();								\
			Rdptr = Rdbfr;														\
		}																		\
		else																	\
		{																		\
			size = g_AC3Dec2.decode_data(Rdptr, Packet_Length, size,g_DVDGlobals.Sound_Max,&g_Ac3Context2);					\
			Rdptr += Packet_Length;												\
			Packet_Length = 0;													\
		}																		\
	}																			\
}

#define DEMUX_AC3															\
while (Packet_Length > 0)													\
{																			\
	if (Packet_Length+Rdptr > BUFFER_SIZE+Rdbfr)							\
	{																		\
		fwrite(Rdptr, BUFFER_SIZE+Rdbfr-Rdptr, 1, g_DVDGlobals.ac3[AC3_Track].file);		\
		Packet_Length -= BUFFER_SIZE+Rdbfr-Rdptr;							\
		Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE);				\
		if (Read < BUFFER_SIZE) Next_File();								\
		Rdptr = Rdbfr;														\
	}																		\
	else																	\
	{																		\
		fwrite(Rdptr, Packet_Length, 1, g_DVDGlobals.ac3[AC3_Track].file);				\
		Rdptr += Packet_Length;												\
		Packet_Length = 0;													\
	}																		\
}

#define DEMUX_AC3_2 DEMUX_AC3

#define DEMUX_PCM														\
{																		\
	unsigned char tmp;													\
	size = 0;															\
	while (Packet_Length > 0)											\
	{																	\
		if (Packet_Length+Rdptr > BUFFER_SIZE+Rdbfr)					\
		{																\
			memcpy(PCM_Buffer+size, Rdptr, BUFFER_SIZE+Rdbfr-Rdptr);	\
			size += BUFFER_SIZE+Rdbfr-Rdptr;							\
			Packet_Length -= BUFFER_SIZE+Rdbfr-Rdptr;					\
			Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE);		\
			if (Read < BUFFER_SIZE) Next_File();						\
			Rdptr = Rdbfr;												\
		}																\
		else															\
		{																\
			memcpy(PCM_Buffer+size, Rdptr, Packet_Length);				\
			Rdptr += Packet_Length;										\
			size += Packet_Length;										\
			Packet_Length = 0;											\
		}																\
	}																	\
	for (i=0; i<size; i+=2)												\
	{																	\
		tmp = PCM_Buffer[i];											\
		PCM_Buffer[i] = PCM_Buffer[i+1];								\
		PCM_Buffer[i+1] = tmp;											\
	}																	\
}

#define DEMUX_PCM_2 DEMUX_PCM

#define DEMUX_MPA															\
while (Packet_Length > 0)													\
{																			\
	if (Packet_Length+Rdptr > BUFFER_SIZE+Rdbfr)							\
	{																		\
		fwrite(Rdptr, BUFFER_SIZE+Rdbfr-Rdptr, 1, g_DVDGlobals.mpa[MPA_Track].file);		\
		Packet_Length -= BUFFER_SIZE+Rdbfr-Rdptr;							\
		Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE);				\
		if (Read < BUFFER_SIZE) Next_File();								\
		Rdptr = Rdbfr;														\
	}																		\
	else																	\
	{																		\
		fwrite(Rdptr, Packet_Length, 1, g_DVDGlobals.mpa[MPA_Track].file);				\
		Rdptr += Packet_Length;												\
		Packet_Length = 0;													\
	}																		\
}

// skips ahead by "Packet_Length" bytes
#define SKIP_TRANSPORT_PACKET_BYTES( bytes_to_skip ) \
{ int temp = (bytes_to_skip);							\
	while (temp  > 0) 											\
	{ 																			\
		if (temp +Rdptr > BUFFER_SIZE+Rdbfr)	\
		{ 																		\
			temp  -= BUFFER_SIZE+Rdbfr-Rdptr;		\
			Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE); \
			if (Read < BUFFER_SIZE) Next_File();								 \
			Rdptr = Rdbfr;				\
		} 											\
		else										\
		{ 											\
			Rdptr += temp ; 			\
			temp  = 0;						\
		} 											\
	}													\
	Packet_Length -= (bytes_to_skip);	\
}

//			memcpy( (void *) bs_buffer, (const void *) Rdbfr, BUFFER_SIZE ); 


static char *FTType[5] = {
	"48KHz", "44.1KHz", "44.1KHz", "44.1KHz", "44.1KHz"
};

static char *AC3ModeDash[8] = {
	"1+1", "1_0", "2_0", "3_0", "2_1", "3_1", "2_2", "3_2"
};

static unsigned char PCM_Buffer[BUFFER_SIZE];
static short *ptrPCM_Buffer = (short*)PCM_Buffer;

void Initialize_Buffer(void)
{
	Rdptr = Rdbfr + BUFFER_SIZE;
	Rdmax = Rdptr;

	if (g_Flags.SystemStream_Flag)
	{
		if (Rdptr >= Rdmax)
			Next_Packet();
		CurrentBfr = *Rdptr++ << 24;

		if (Rdptr >= Rdmax)
			Next_Packet();
		CurrentBfr += *Rdptr++ << 16;

		if (Rdptr >= Rdmax)
			Next_Packet();
		CurrentBfr += *Rdptr++ << 8;

		if (Rdptr >= Rdmax)
			Next_Packet();
		CurrentBfr += *Rdptr++;

		Fill_Next();
	}
	else
	{
		Fill_Buffer();

		CurrentBfr = (*Rdptr << 24) + (*(Rdptr+1) << 16) + (*(Rdptr+2) << 8) + *(Rdptr+3);
		Rdptr += 4;

		Fill_Next();
	}

	BitsLeft = 32;
}




typedef struct {			
	// 1 byte
	unsigned char sync_byte; // 		8	bslbf

	// 2 bytes
	unsigned char transport_error_indicator;//		1	bslbf
	unsigned char payload_unit_start_indicator;//		1	bslbf
	unsigned char transport_priority; //		1	bslbf
	unsigned short pid;	//	13	uimsbf

	// 1 byte
	unsigned char transport_scrambling_control;//		2	bslbf
	unsigned char adaptation_field_control;//		2	bslbf
	unsigned char continuity_counter;//		4	uimsbf

	// VVV (only valid if adaptation_field_control != 1)
	// 1 byte
		unsigned char adaptation_field_length; // 8 uimsbf 
	
		// VVV (only valid if adaptation_field_length != 0)
		// 1 byte
			unsigned char discontinuity_indicator; //	1	bslbf
			unsigned char random_access_indicator; //	1	bslbf
			unsigned char elementary_stream_priority_indicator; //	1	bslbf
			unsigned char PCR_flag; //	1	bslbf
			unsigned char OPCR_flag; //	1	bslbf
			unsigned char splicing_point_flag; //	1	bslbf
			unsigned char transport_private_data_flag; //	1	bslbf
			unsigned char adaptation_field_extension_flag; //	1	bslbf

	/*
	if(adaptation_field_control=='10'  || adaptation_field_control=='11'){			
		adaptation_field()			
	}			
	if(adaptation_field_control=='01' || adaptation_field_control=='11') {			
		for (i=0;i<N;i++){			
			data_byte		8	bslbf
		}			
	}			
	*/
	
} transport_packet;


// MPEG-2 transport stream processor
//  ok, the function Next_Transport_Packet() assumes the following:
//    1) we already have a stream target (AudioPID and VideoPID),
//      (g_Flags.MPEG2_Transport_VideoPID, g_Flags.MPEG2_Transport_AudioPID)
//      these vars are setup from the dvd2avi.ini file
//    2) The Audio-stream is assumed to be AC3.  (This is only true for
//       US ATSC DTV bitstreams!)
//    3) ignore the 'continuity counter'...with some DTV broadcasters,
//       this really isn't a reliable indicator

void Next_Transport_Packet(void)
{
	static int i, Packet_Length, Packet_Header_Length, size;
	static unsigned int code, AUDIO_ID, VOBCELL_Count, AC3_Track, MPA_Track;
	__int64 PCR, OPCR, PES_PTS = 0;  // =0 to avoid warning
//	__int64 PCR_base, PCR_ext, code64;
	int PCR_base, PCR_ext, OPCR_base, OPCR_ext, code64;
	unsigned int bytes_left; // temp vars
	int tp_previous_continuity_counter = 0;

	const transport_packet tp_zero ={0};  // 'empty'
	transport_packet tp ={0};  // temporary holding struct, zero it out
	int flag_PCR_is_here, flag_OPCR_is_here, flag_PES_PTS_is_here ;  // flag


	for (;;)
	{
		// 0) init some random vars
		tp = tp_zero;
		flag_PCR_is_here = 0; flag_OPCR_is_here = 0; flag_PES_PTS_is_here = 0;
		bytes_left = 0;
		Packet_Length = 188; // total length of 1 MPEG-2 transport packet

		// 1) search for sync-byte
		do {
		  tp.sync_byte = Get_Byte();
		}	while ( tp.sync_byte != 0x47 );
//		} while ( tp.sync_byte != 0x47 && tp.sync_byte  != 0x72 && tp.sync_byte != 0x29);

		--Packet_Length; // decrement the sync_byte;

		// update continuity counter (from previous packet)
		tp_previous_continuity_counter = tp.continuity_counter;

		// get pid, transport_error_indicator, payload_unit_start_indicator
		code = Get_Short();
		Packet_Length = Packet_Length - 2; // decrement the two bytes we just got;
		tp.pid = (unsigned short)(code & 0x1FFF); // bits [12:0]
		tp.transport_error_indicator = (unsigned char)((code >> 15) & 0x01);  // bit#15
		tp.payload_unit_start_indicator = (unsigned char)((code >> 14) & 0x01); // bit#14
		tp.transport_priority = (unsigned char)((code >> 13) & 0x01); // bit#13

		// 2) check the error-flag
		if ( tp.transport_error_indicator )
		{
			// skip remaining bytes in current packet
			SKIP_TRANSPORT_PACKET_BYTES( Packet_Length )
			continue; // abort, and circle back to top of 'for() loop'
		}

		code = Get_Byte();
		--Packet_Length; // decrement the 1 byte we just got;
		tp.transport_scrambling_control = (unsigned char)((code >> 6) & 0x03);//		2	bslbf
		tp.adaptation_field_control = (unsigned char)((code >> 4 ) & 0x03);//		2	bslbf
		tp.continuity_counter = (unsigned char)(code & 0x0F);//		4	uimsbf

		// we don't care about the continuity counter
		// if ( tp.continuity_counter != previous_continuity_counter ) ...

		if ( tp.adaptation_field_control == 0 ) //|| 
					//tp.adaptation_field_control == 2 ) // no payload
		{
			// skip remaining bytes in current packet
			SKIP_TRANSPORT_PACKET_BYTES( Packet_Length )
			continue; // abort, and circle back to top of 'for() loop'
		}

		// 3) check the Adaptation-header, only so we can determine
		//    the exact #bytes to skip
		if ( tp.adaptation_field_control == 2 || tp.adaptation_field_control == 3)
		{
			// adaptation field is present
			tp.adaptation_field_length = Get_Byte(); // 8-bits
			--Packet_Length; // decrement the 1 byte we just got;

			if ( tp.adaptation_field_length != 0 ) // end of field already?
			{
				// if we made it this far, we no longer need to decrement
				// Packet_Length.  We took care of it up there!
				code = Get_Byte();
				--Packet_Length; // decrement the 1 byte we just got;
				tp.discontinuity_indicator = (unsigned char)((code >> 7) & 0x01); //	1	bslbf
				tp.random_access_indicator = (unsigned char)((code >> 6) & 0x01); //	1	bslbf
				tp.elementary_stream_priority_indicator = (unsigned char)((code >> 5) & 0x01); //	1	bslbf
				tp.PCR_flag = (unsigned char)((code >> 4) & 0x01); //	1	bslbf
				tp.OPCR_flag = (unsigned char)((code >> 3) & 0x01); //	1	bslbf
				tp.splicing_point_flag = (unsigned char)((code >> 2) & 0x01); //	1	bslbf
				tp.transport_private_data_flag = (unsigned char)((code >> 1) & 0x01); //	1	bslbf
				tp.adaptation_field_extension_flag = (unsigned char)((code >> 0) & 0x01); //	1	bslbf
				bytes_left = tp.adaptation_field_length - 1;

				// Get PCR
				if ( tp.PCR_flag )
				{
					// we will read the next 6 bytes, to extract the program-clock-register
					code64 = Get_Byte() & 0xFF; // 32..25
					--Packet_Length;
					PCR_base = code64;

					code64 = Get_Byte() & 0xFF; // 24..17
					--Packet_Length;
					PCR_base = (PCR_base << 8) | code64;
					
					code64 = Get_Byte() & 0xFF; // 16..9
					--Packet_Length;
					PCR_base = (PCR_base << 8) | code64;
					
					code64 = Get_Byte() & 0xFF; // 8..1
					--Packet_Length;
					PCR_base = (PCR_base << 8) | code64;

					code64 = Get_Byte() & 0xFF; // 0
					--Packet_Length;
					PCR_base = (PCR_base << 1) | (code64 >> 7);

					PCR_ext = (code64 & 0x80) << 1; // 8

					code64 = Get_Byte() & 0xFF; // 7..0
					--Packet_Length;
					PCR_ext = (PCR_base << 8) | code64; // 

					PCR = PCR_base * 300 + PCR_ext;
					flag_PCR_is_here = 1; // set flag

					// we've crunched 6-bytes of the Adaptation-header.  Make a note of it.					
					bytes_left = bytes_left - 6;
				}

				// Get original PCR
				if ( tp.OPCR_flag )
				{
					// we will read the next 6 bytes, to extract the program-clock-register
					code64 = Get_Byte() & 0xFF; // 32..25
					--Packet_Length;
					OPCR_base = code64;

					code64 = Get_Byte() & 0xFF; // 24..17
					--Packet_Length;
					OPCR_base = (OPCR_base << 8) | code64;
					
					code64 = Get_Byte() & 0xFF; // 16..9
					--Packet_Length;
					OPCR_base = (OPCR_base << 8) | code64;
					
					code64 = Get_Byte() & 0xFF; // 8..1
					--Packet_Length;
					OPCR_base = (OPCR_base << 8) | code64;

					code64 = Get_Byte() & 0xFF; // 0
					--Packet_Length;
					OPCR_base = (OPCR_base << 1) | (code64 >> 7);

					OPCR_ext = (code64 & 0x80) << 1; // 8

					code64 = Get_Byte() & 0xFF; // 7..0
					--Packet_Length;
					OPCR_ext = (OPCR_base << 8) | code64; // 

					OPCR = OPCR_base * 300 + OPCR_ext;
					flag_OPCR_is_here = 1; // set flag

					// we've crunched 6-bytes of the Adaptation-header.  Make a note of it.					
					bytes_left = bytes_left - 6;
				}
				
				// skip the remainder of the adaptation_field
				SKIP_TRANSPORT_PACKET_BYTES( bytes_left )
			} // if ( tp.adaptation_field_length != 0 )
		} // if ( tp.adaptation_field_control != 1 )

		/////////////////////////////////////////////////////////////////
		// we've processed the MPEG-2 transport header, 
		// ...now, just the payload is left...

		// Any data left in the current transport-packet?
		if ( Packet_Length == 0 )
			continue;  // NO, skip back to top of for() loop

		// Still have data left in packet, continue processing...
		
		// VIDEO STREAM
		if ( (tp.pid == g_Flags.MPEG2_Transport_VideoPID ) ) 
		{
			LOCATE

			code = Get_Short();
			code = (code & 0xffff)<<16 | Get_Short();
			Packet_Length = Packet_Length - 4; // remove these two bytes

			// check for MPEG2-PES packet header... this contains a 'PTS'
			if (code != 0x000001E0 ) // 'VIDEO ELEMENTARY STREAM 1'? 
			{
				// nope, move the buffer-pointer 'backward'
				Rdptr -= 4; 
				Packet_Length = Packet_Length + 4; // restore these four bytes
			}
			else
			{
				// YES, pull out PTS 
				//Packet_Length = Get_Short();
				Get_Short(); // MPEG2-PES total Packet_Length
				Get_Byte(); // skip a byte
				code = Get_Byte();
				Packet_Header_Length = Get_Byte();
				Packet_Length = Packet_Length - 5; // compensate the bytes we extracted
	
				// get PTS, and skip rest of PES-header
				if (code>=0x80 && Packet_Header_Length > 4 ) // Extension_flag ?
				{
					flag_PES_PTS_is_here = 1; // set flag
					code = Get_Byte();
					PES_PTS = (code & 0x0e) << 29;
					PES_PTS |= (Get_Short() & 0xfffe) << 14;
					PES_PTS |= (Get_Short()>>1) & 0x7fff;

					Packet_Length = Packet_Length - 5;
					SKIP_TRANSPORT_PACKET_BYTES( Packet_Header_Length-5 )
				}
				else
					SKIP_TRANSPORT_PACKET_BYTES( Packet_Header_Length )
				//AUDIO_ID = Get_Byte();  // nope, this is not in transport-packet!
			} // if ( code != 0x000001E0 )

			if ( flag_PES_PTS_is_here ) 
				g_PicInfo.VideoPTS = (int)PES_PTS; // get PTS

			Rdmax = Rdptr + Packet_Length;
			// maximum MPEG-2 bitrate for ATSC is 19.2MBps, we normalize this by
			// dividing by 2.
			g_DVDGlobals.Bitrate_Meter += ((Rdmax - Rdptr) >> 1);
			return;
		}  // if ( (tp.pid == g_Flags.MPEG2_Transport_VideoPID ) ) 
		// END VIDEO STREAM

		// AUDIOSTREAM 
		if ( tp.pid == g_Flags.MPEG2_Transport_AudioPID ) 
		{

		// search for an MPEG-PES packet header
		if ( tp.random_access_indicator || tp.payload_unit_start_indicator )
		{
			LOCATE

			code = Get_Short();
			code = (code & 0xffff)<<16 | Get_Short();
			Packet_Length = Packet_Length - 4; // remove these two bytes

				// check for MPEG2-PES packet header... this contains a 'PTS'
				if (code != PRIVATE_STREAM_1 ) // 'PRIVATE STREAM 1'? 0x0000_01BD
				{
					// nope, move the buffer-pointer 'backward'
					Rdptr -= 4; 
					Packet_Length = Packet_Length + 4; // restore these four bytes
				}
				else
				{
					// YES, pull out PTS 
					//Packet_Length = Get_Short();
					Get_Short(); // MPEG2-PES total Packet_Length
					Get_Byte(); // skip a byte
	
					code = Get_Byte();
					Packet_Header_Length = Get_Byte();
					Packet_Length = Packet_Length - 5; // compensate the bytes we extracted
	
					// get PTS, and skip rest of PES-header
					if (code>=0x80 && Packet_Header_Length > 4 ) // Extension_flag ?
					{
						flag_PES_PTS_is_here = 1; // set flag
						code = Get_Byte();
						PES_PTS = (code & 0x0e) << 29;
	
						PES_PTS |= (Get_Short() & 0xfffe) << 14;
						PES_PTS |= (Get_Short()>>1) & 0x7fff;
						Packet_Length = Packet_Length - 5;
	
						SKIP_TRANSPORT_PACKET_BYTES( Packet_Header_Length-5 )
					}
					else
						SKIP_TRANSPORT_PACKET_BYTES( Packet_Header_Length )
							//AUDIO_ID = Get_Byte();  // nope, this is not in transport-packet!
				} // if ( code != PRIVATE_STREAM_1 ) // 0x0000_01BD
			} // end if ( tp.random_access_indicator || tp.payload_unit_start_indicator)

			// Done processing the MPEG-2 PES header, now for the *real* audio-data
		
			// for now, we'll just assume this stream carries an AC3-payload
			// This is true for US ATSC MPEG-2 transport streams (but FALSE for DVB-T!)
			// Excuse us 'yanks for assuming the world revolves around us...
				AUDIO_ID = SUB_AC3;

				if (AUDIO_ID>=SUB_AC3 && AUDIO_ID<SUB_AC3+CHANNEL)
				{
					//Rdptr += 3; Packet_Length -= 3; 
					AC3_Track = 0;
					// Assume the audio stream is AC3
					if ( flag_PES_PTS_is_here ) 
						g_PicInfo.AudioPTS = (int)PES_PTS; // get lower 32-bits of PCR_base


					LOCATE
					// if this is AC3_Track's *first* observation, we will seek to the
					// first valid AC3-frame, then decode its header.  
					// We tried checking for tp.payload_unit_start_indicator, but this
					// indicator isn't reliable on a lot of DTV-stations!
					// Instead, we'll manually search for an AC3-sync word.
					if (!g_DVDGlobals.ac3[AC3_Track].rip
						&& g_Flags.Rip_Flag
						&& !g_DVDGlobals.CH[AC3_Track]
						&& ( tp.random_access_indicator || tp.payload_unit_start_indicator)
						&& Packet_Length > 5 )
					{

						code = Get_Byte();
						code = (code & 0xff)<<8 | Get_Byte();
						Packet_Length = Packet_Length - 2; // remove these two bytes
						i = 0;

						// search for an AC3-sync word.  We wouldn't have to do this if
						// DTV-stations made proper use of tp.payload_unit_start_indicator;
						while (code!=0xb77 && Packet_Length > 0 )
						{
							code = (code & 0xff)<<8 | Get_Byte();
							--Packet_Length;
							++i;
						}

						if ( code !=0xb77 )  // did we find the sync-header?
						{
							// no, we searched the *ENTIRE* transport-packet and came up empty!
							SKIP_TRANSPORT_PACKET_BYTES( Packet_Length )
							continue;  
						}

						// First time that we detected this particular channel? yes
						g_DVDGlobals.CH[AC3_Track] = FORMAT_AC3;

						//Packet_Length = Packet_Length - 5; // remove five bytes
						Get_Short(); 
						g_DVDGlobals.ac3[AC3_Track].rate = (Get_Byte()>>1) & 0x1f;
						Get_Byte();
						g_DVDGlobals.ac3[AC3_Track].mode = (Get_Byte()>>5) & 0x07;
						//Packet_Length = Packet_Length + 5; // restore these five bytes
						Rdptr -= 5; // restore these five bytes

						// ok, now move "backward" by two more bytes, so we're back at the
						// start of the AC3-sync header

						Packet_Length += 2;
						Rdptr -= 2; 

						if ((g_Flags.Format_Flag==FORMAT_AC3 || !g_Flags.Format_Flag) && (g_Flags.AVI_Flag || g_Flags.D2V_Flag /*|| g_Ac3Context.Decision_Flag*/))
						{
							//if (g_Ac3Context.Decision_Flag && AC3_Track==g_Flags.Track_Flag)
							//{
							//	InitialAC3(g_Ac3Context.DRC_Flag);
							//
							//	DECODE_AC3
							//
							//	g_DVDGlobals.ac3[AC3_Track].rip = 1;
							//}
							//else
							if (g_Ac3Context.AC3_Flag==AUDIO_DECODE && AC3_Track==g_Flags.Track_Flag)
							{
								sprintf(l_szBuffer, "%s%s AC3 T%02d %sch %dKbps %s.wav", g_GuiGlobals.szPath,g_GuiGlobals.szOutput, g_Flags.Track_Flag+1, 
									AC3ModeDash[g_DVDGlobals.ac3[AC3_Track].mode], AC3Rate[g_DVDGlobals.ac3[AC3_Track].rate], FTType[g_Ac3Context.SRC_Flag]);

								strcpy(pcm.filename, l_szBuffer);
								pcm.file = fopen(l_szBuffer, "wb");

								fwrite(WAVHeader, sizeof(WAVHeader), 1, pcm.file);
								pcm.delay = ((g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90) * 192;

								if (pcm.delay > 0)
								{
									for (i=0; i<pcm.delay; i++)
										fputc(0, pcm.file);

									pcm.size += pcm.delay;
									pcm.delay = 0;
								}

								g_AC3Dec.Init(g_Ac3Context.DRC_Flag);

								DECODE_AC3

								if (-pcm.delay > size)
									pcm.delay += size;
								else
								{
									fwrite(g_Ac3Context.AC3Dec_Buffer-pcm.delay, size+pcm.delay, 1, pcm.file);

									pcm.size += size+pcm.delay;
									pcm.delay = 0;
								}

								g_DVDGlobals.ac3[AC3_Track].rip = 1;
							}
							else if (!g_Ac3Context.AC3_Flag || (g_Ac3Context.AC3_Flag==AUDIO_DEMUXONE && AC3_Track==g_Flags.Track_Flag))
							{
								sprintf(l_szBuffer, "%s%s AC3 T%02d %sch %dKbps DELAY %dms.ac3", g_GuiGlobals.szPath,g_GuiGlobals.szOutput, AC3_Track+1, 
									AC3ModeDash[g_DVDGlobals.ac3[AC3_Track].mode], AC3Rate[g_DVDGlobals.ac3[AC3_Track].rate], (g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90);
								g_DVDGlobals.ac3[AC3_Track].file = fopen(l_szBuffer, "wb");
								DEMUX_AC3
								g_DVDGlobals.ac3[AC3_Track].rip = 1;
							} // if (Decision_Flag && AC3_Track==g_Flags.Track_Flag)
						} // if ((g_Flags.Format_Flag==FORMAT_AC3 || !g_Flags.Format_Flag) && (g_Flags.AVI_Flag || g_Flags.D2V_Flag || Decision_Flag))

					} // if (!g_DVDGlobals.ac3[AC3_Track].rip && g_Flags.Rip_Flag && !g_DVDGlobals.CH[AC3_Track] && tp.)
					else if (g_DVDGlobals.ac3[AC3_Track].rip)
					{
						//if (g_Ac3Context.Decision_Flag)
						//	DECODE_AC3
						//else 
						if (g_Ac3Context.AC3_Flag==AUDIO_DECODE)
						{
							DECODE_AC3

							if (-pcm.delay > size)
								pcm.delay += size;
							else
							{
								//if (g_Ac3Context.SRC_Flag)
								//	Wavefs44(pcm.file, size+pcm.delay, g_Ac3Context.AC3Dec_Buffer-pcm.delay);
								//else
									fwrite(g_Ac3Context.AC3Dec_Buffer-pcm.delay, size+pcm.delay, 1, pcm.file);

								pcm.size += size+pcm.delay;
								pcm.delay = 0;
							}
						}
						else
							DEMUX_AC3
					} // else if (g_DVDGlobals.ac3[AC3_Track].rip)
				} // if (AUDIO_ID>=SUB_AC3 && AUDIO_ID<SUB_AC3+CHANNEL)
		} // if ( (tp.pid == 0x0024 || tp.pid == 0x0014 ) && (Packet_Length > 0) ) 

		// fallthrough case
		// skip remaining bytes in current packet
		SKIP_TRANSPORT_PACKET_BYTES( Packet_Length )
		continue;

/*
				break;
			case AUDIO_ELEMENTARY_STREAM_7:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_6:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_5:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_4:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_3:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_2:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_1:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_0:
				Packet_Length = Get_Short()-1;
				code = Get_Byte();

				if ((code & 0xc0)==0x80 && (g_Flags.Track_Flag==MPA_Track || !g_Flags.MPA_Flag))
				{
					g_DVDGlobals.CH[MPA_Track] = FORMAT_MPA;

					code = Get_Byte();
					Packet_Header_Length = Get_Byte();

					if (code>=0x80)
					{
						code = Get_Byte();

						g_PicInfo.AudioPTS = (code & 0x0e) << 29;
						g_PicInfo.AudioPTS |= (Get_Short() & 0xfffe) << 14;
						g_PicInfo.AudioPTS |= (Get_Short()>>1) & 0x7fff;

						Rdptr += Packet_Header_Length-5;
					}
					else
						Rdptr += Packet_Header_Length;

					Packet_Length -= Packet_Header_Length+2;

					LOCATE

					if (!g_DVDGlobals.mpa[MPA_Track].rip && g_Flags.Rip_Flag)
					{
						if ((g_Flags.Format_Flag==FORMAT_MPA || !g_Flags.Format_Flag) && (g_Flags.AVI_Flag || g_Flags.D2V_Flag))
						{
							code = Get_Byte();
							code = (code & 0xff)<<8 | Get_Byte();
							i = 0;

							while (code<0xfff0)
							{
								code = (code & 0xff)<<8 | Get_Byte();
								i++;
							}

							sprintf(l_szBuffer, "%s MPA T%02d DELAY %dms.mpa", g_GuiGlobals.szOutput, MPA_Track+1, (g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90);
							g_DVDGlobals.mpa[MPA_Track].file = fopen(l_szBuffer, "wb");

							Rdptr -= 2; Packet_Length -= i;

							DEMUX_MPA

							g_DVDGlobals.mpa[MPA_Track].rip = 1; 				
						}
					}
					else if (g_DVDGlobals.mpa[MPA_Track].rip)
						DEMUX_MPA
				}

				Rdptr += Packet_Length;
				MPA_Track = 0;
				break;
*/
/*
			case VIDEO_ELEMENTARY_STREAM:
				//Packet_Length = Get_Short();
				Rdmax = Rdptr + Packet_Length;

				code = Get_Byte();

				if ((code & 0xc0)==0x80)
				{
					code = Get_Byte();
					Packet_Header_Length = Get_Byte();

					if (code>=0x80 && !g_Flags.Rip_Flag)
					{
						code = Get_Byte();
						g_PicInfo.VideoPTS = (code & 0x0e) << 29;
						g_PicInfo.VideoPTS |= (Get_Short() & 0xfffe) << 14;
						g_PicInfo.VideoPTS |= (Get_Short()>>1) & 0x7fff;

						Rdptr += Packet_Header_Length-5;
					}
					else
						Rdptr += Packet_Header_Length;

					g_DVDGlobals.Bitrate_Meter += Rdmax-Rdptr;
					return;
				}
				else
					Rdptr += Packet_Length-1;
				break;

			default:
				if (code>=SYSTEM_START_CODE)
				{
					Packet_Length = Get_Short();
					Rdptr += Packet_Length;
				}
				break;
		}
		*/
	} // for(;;)
}  // Next_Transport_Packet()



void Next_Packet(void)
{
	static int i, Packet_Length, Packet_Header_Length, size;
	static unsigned int code, AUDIO_ID, VOBCELL_Count, AC3_Track, MPA_Track;

	if ( g_Flags.SystemStream_Flag == 2 )
	{
		Next_Transport_Packet();
		return;
	}

	for (;;)
	{
		code = Get_Short();
		code = (code<<16) + Get_Short();

		while ((code & 0xffffff00) != 0x00000100)
			code = (code<<8) + Get_Byte();

		switch (code)
		{
			case PACK_START_CODE:
				Rdptr += 8;
				VOBCELL_Count = 0;
				break;

			case PRIVATE_STREAM_2:
				Packet_Length = Get_Short();

				if (++VOBCELL_Count==2)
				{
					Rdptr += 25;
					g_PicInfo.VOB_ID = Get_Short();
					g_PicInfo.CELL_ID = Get_Short();
					Rdptr += Packet_Length - 29;

					sprintf(l_szBuffer, "%d", g_PicInfo.VOB_ID);
//					g_InfoFunctions.VobId(l_szBuffer);

					sprintf(l_szBuffer, "%d", g_PicInfo.CELL_ID);
//					g_InfoFunctions.CellId(l_szBuffer);
				}
				else
					Rdptr += Packet_Length;
				break;

			case PRIVATE_STREAM_1:
				Packet_Length = Get_Short();

				Rdptr ++;
				code = Get_Byte();
				Packet_Header_Length = Get_Byte();

				if (code>=0x80)
				{
					code = Get_Byte();
					g_PicInfo.AudioPTS = (code & 0x0e) << 29;

					g_PicInfo.AudioPTS |= (Get_Short() & 0xfffe) << 14;
					g_PicInfo.AudioPTS |= (Get_Short()>>1) & 0x7fff;

					Rdptr += Packet_Header_Length-5;
				}
				else
					Rdptr += Packet_Header_Length;

				AUDIO_ID = Get_Byte();
				Packet_Length -= Packet_Header_Length+4;

				if (AUDIO_ID>=SUB_AC3 && AUDIO_ID<SUB_AC3+CHANNEL)
				{
					Rdptr += 3; Packet_Length -= 3; AC3_Track = AUDIO_ID-SUB_AC3;

					LOCATE

					if (!g_DVDGlobals.ac3[AC3_Track].rip && g_Flags.Rip_Flag && !g_DVDGlobals.CH[AC3_Track])
					{
						g_DVDGlobals.CH[AC3_Track] = FORMAT_AC3;

						code = Get_Byte();
						code = (code & 0xff)<<8 | Get_Byte();
						i = 0;

						while (code!=0xb77)
						{
							code = (code & 0xff)<<8 | Get_Byte();
							i++;
						}

						Get_Short();
						g_DVDGlobals.ac3[AC3_Track].rate = (Get_Byte()>>1) & 0x1f;
						Get_Byte();
						g_DVDGlobals.ac3[AC3_Track].mode = (Get_Byte()>>5) & 0x07;

						Rdptr -= 7; Packet_Length -= i;

						if ((g_Flags.Format_Flag==FORMAT_AC3 || !g_Flags.Format_Flag) && (g_Flags.AVI_Flag || g_Flags.D2V_Flag))
						{
							if (AC3_Track==g_Flags.Track_Flag)
							{
								if (g_Ac3Context.AC3_Flag==AUDIO_DECODE)
								{
									sprintf(l_szBuffer, "%s%s AC3 Audio1 Track%02d %sch %dKbps %s.wav", g_GuiGlobals.szPath,g_GuiGlobals.szOutput, g_Flags.Track_Flag+1, 
										AC3ModeDash[g_DVDGlobals.ac3[AC3_Track].mode], AC3Rate[g_DVDGlobals.ac3[AC3_Track].rate], FTType[g_Ac3Context.SRC_Flag]);

									strcpy(pcm.filename, l_szBuffer);
									pcm.file = fopen(l_szBuffer, "wb");

									fwrite(WAVHeader, sizeof(WAVHeader), 1, pcm.file);
									pcm.delay = ((g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90) * 192;

									if (pcm.delay > 0)
									{
										for (i=0; i<pcm.delay; i++)
											fputc(0, pcm.file);
										pcm.size += pcm.delay;
										pcm.delay = 0;
									}
									g_AC3Dec.Init(g_Ac3Context.DRC_Flag);
									DECODE_AC3
									if (-pcm.delay > size)
										pcm.delay += size;
									else
									{
										fwrite(g_Ac3Context.AC3Dec_Buffer-pcm.delay, size+pcm.delay, 1, pcm.file);
										pcm.size += size+pcm.delay;
 										pcm.delay = 0;
									}
									g_DVDGlobals.ac3[AC3_Track].rip = 1;
								}
								else if (g_Ac3Context.AC3_Flag==AUDIO_DEMUXONE)
								{
									sprintf(l_szBuffer, "%s%s AC3 T%02d %sch %dKbps DELAY %dms.ac3",g_GuiGlobals.szPath, g_GuiGlobals.szOutput, AC3_Track+1, 
										AC3ModeDash[g_DVDGlobals.ac3[AC3_Track].mode], AC3Rate[g_DVDGlobals.ac3[AC3_Track].rate], (g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90);
									g_DVDGlobals.ac3[AC3_Track].file = fopen(l_szBuffer, "wb");
									DEMUX_AC3
									g_DVDGlobals.ac3[AC3_Track].rip = 1;
								}
							}
							else if (AC3_Track==g_Flags.Track_Flag2)
							{
								if (g_Ac3Context2.AC3_Flag==AUDIO_DECODE)
								{
									sprintf(l_szBuffer, "%s%s AC3 Audio2 Track%02d %sch %dKbps %s.wav", g_GuiGlobals.szPath,g_GuiGlobals.szOutput, g_Flags.Track_Flag2+1, 
										AC3ModeDash[g_DVDGlobals.ac3[AC3_Track].mode], AC3Rate[g_DVDGlobals.ac3[AC3_Track].rate], FTType[g_Ac3Context2.SRC_Flag]);

									strcpy(pcm2.filename, l_szBuffer);
									pcm2.file = fopen(l_szBuffer, "wb");

									fwrite(WAVHeader, sizeof(WAVHeader), 1, pcm2.file);
									pcm2.delay = ((g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90) * 192;

									if (pcm2.delay > 0)
									{
										for (i=0; i<pcm2.delay; i++)
											fputc(0, pcm2.file);
										pcm2.size += pcm2.delay;
										pcm2.delay = 0;
									}
									g_AC3Dec2.Init(g_Ac3Context2.DRC_Flag);
									DECODE_AC3_2
									if (-pcm2.delay > size)
										pcm2.delay += size;
									else
									{
										fwrite(g_Ac3Context2.AC3Dec_Buffer-pcm2.delay, size+pcm2.delay, 1, pcm2.file);
										pcm2.size += size+pcm2.delay;
 										pcm2.delay = 0;
									}
									g_DVDGlobals.ac3[AC3_Track].rip = 1;
								}
								else if (g_Ac3Context2.AC3_Flag==AUDIO_DEMUXONE)
								{
									sprintf(l_szBuffer, "%s%s AC3 T%02d %sch %dKbps DELAY %dms.ac3", g_GuiGlobals.szPath,g_GuiGlobals.szOutput, AC3_Track+1, 
										AC3ModeDash[g_DVDGlobals.ac3[AC3_Track].mode], AC3Rate[g_DVDGlobals.ac3[AC3_Track].rate], (g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90);
									g_DVDGlobals.ac3[AC3_Track].file = fopen(l_szBuffer, "wb");
									DEMUX_AC3_2
									g_DVDGlobals.ac3[AC3_Track].rip = 1;
								}
							}
						}
					}
					else if (g_DVDGlobals.ac3[AC3_Track].rip)
					{
						if (AC3_Track==g_Flags.Track_Flag)
						{
							if (g_Ac3Context.AC3_Flag==AUDIO_DECODE)
							{
								DECODE_AC3

								if (-pcm.delay > size)
									pcm.delay += size;
								else
								{
									fwrite(g_Ac3Context.AC3Dec_Buffer-pcm.delay, size+pcm.delay, 1, pcm.file);
									pcm.size += size+pcm.delay;
 									pcm.delay = 0;
								}
							}
							else if (g_Ac3Context.AC3_Flag==AUDIO_DEMUXONE)
								DEMUX_AC3
						}
						else if (AC3_Track==g_Flags.Track_Flag2)
						{
							if (g_Ac3Context2.AC3_Flag==AUDIO_DECODE)
							{
								DECODE_AC3_2

								if (-pcm2.delay > size)
									pcm2.delay += size;
								else
								{
									fwrite(g_Ac3Context2.AC3Dec_Buffer-pcm2.delay, size+pcm2.delay, 1, pcm2.file);
									pcm2.size += size+pcm2.delay;
 									pcm2.delay = 0;
								}
							}
							else if (g_Ac3Context2.AC3_Flag==AUDIO_DEMUXONE)
								DEMUX_AC3_2
						}
					}
				}
				else if (AUDIO_ID-SUB_PCM == g_Flags.Track_Flag)
				{
					g_DVDGlobals.CH[g_Flags.Track_Flag] = FORMAT_LPCM;
					Rdptr += 6; Packet_Length -= 6;
					LOCATE
					if (!pcm.rip && g_Flags.Rip_Flag)
					{
						if ((g_Flags.Format_Flag==FORMAT_LPCM || !g_Flags.Format_Flag) && (g_Flags.AVI_Flag || g_Flags.D2V_Flag))
						{
							pcm.delay = ((g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90) * 192;
							sprintf(l_szBuffer, "%s%s LPCM T%02d %s.wav",g_GuiGlobals.szPath, g_GuiGlobals.szOutput, g_Flags.Track_Flag+1, FTType[g_Ac3Context.SRC_Flag]);
							strcpy(pcm.filename, l_szBuffer);
							pcm.file = fopen(l_szBuffer, "wb");
							fwrite(WAVHeader, sizeof(WAVHeader), 1, pcm.file);

							if (pcm.delay > 0)
							{
								for (i=0; i<pcm.delay; i++)
									fputc(0, pcm.file);
								pcm.size += pcm.delay;
								pcm.delay = 0;
							}
							if (-pcm.delay > Packet_Length)
								pcm.delay += Packet_Length;
							else
							{
								DEMUX_PCM
								fwrite(PCM_Buffer-pcm.delay, size+pcm.delay, 1, pcm.file);
								pcm.size += size+pcm.delay;
								pcm.delay = 0;
							}
							pcm.rip = 1;
						}
					}
					else if (pcm.rip)
					{
						if (-pcm.delay > Packet_Length)
							pcm.delay += Packet_Length;
						else
						{
							DEMUX_PCM
							{
								fwrite(PCM_Buffer-pcm.delay, size+pcm.delay, 1, pcm.file);
								if (g_Ac3Context.Normalization_Flag)
									for (i=0; i<(size>>1); i++)
										if (g_DVDGlobals.Sound_Max < abs(ptrPCM_Buffer[i]))
											g_DVDGlobals.Sound_Max = (short)abs(ptrPCM_Buffer[i]);
							}
							pcm.size += size+pcm.delay;
							pcm.delay = 0;
						}
					}
				}
				else if (AUDIO_ID-SUB_PCM == g_Flags.Track_Flag2)
				{
					g_DVDGlobals.CH[g_Flags.Track_Flag2] = FORMAT_LPCM;
					Rdptr += 6; Packet_Length -= 6;
					LOCATE
					if (!pcm2.rip && g_Flags.Rip_Flag)
					{
						if ((g_Flags.Format_Flag==FORMAT_LPCM || !g_Flags.Format_Flag) && (g_Flags.AVI_Flag || g_Flags.D2V_Flag))
						{
							pcm2.delay = ((g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90) * 192;
							sprintf(l_szBuffer, "%s%s LPCM T%02d %s.wav", g_GuiGlobals.szPath,g_GuiGlobals.szOutput, g_Flags.Track_Flag2+1, FTType[g_Ac3Context2.SRC_Flag]);
							strcpy(pcm2.filename, l_szBuffer);
							pcm2.file = fopen(l_szBuffer, "wb");
							fwrite(WAVHeader, sizeof(WAVHeader), 1, pcm2.file);

							if (pcm2.delay > 0)
							{
								for (i=0; i<pcm2.delay; i++)
									fputc(0, pcm2.file);
								pcm2.size += pcm2.delay;
								pcm2.delay = 0;
							}
							if (-pcm2.delay > Packet_Length)
								pcm2.delay += Packet_Length;
							else
							{
								DEMUX_PCM_2
								fwrite(PCM_Buffer-pcm2.delay, size+pcm2.delay, 1, pcm2.file);
								pcm2.size += size+pcm2.delay;
								pcm2.delay = 0;
							}
							pcm2.rip = 1;
						}
					}
					else if (pcm2.rip)
					{
						if (-pcm2.delay > Packet_Length)
							pcm2.delay += Packet_Length;
						else
						{
							DEMUX_PCM_2
							{
								fwrite(PCM_Buffer-pcm2.delay, size+pcm2.delay, 1, pcm2.file);
								if (g_Ac3Context2.Normalization_Flag)
									for (i=0; i<(size>>1); i++)
										if (g_DVDGlobals.Sound_Max < abs(ptrPCM_Buffer[i]))
											g_DVDGlobals.Sound_Max = (short)abs(ptrPCM_Buffer[i]);
							}
							pcm2.size += size+pcm2.delay;
							pcm2.delay = 0;
						}
					}
				}
				else if (AUDIO_ID-SUB_DTS == g_Flags.Track_Flag2)
					g_DVDGlobals.CH[g_Flags.Track_Flag2] = FORMAT_DTS;

				Rdptr += Packet_Length;
				break;

			case AUDIO_ELEMENTARY_STREAM_7:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_6:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_5:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_4:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_3:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_2:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_1:
				MPA_Track++;
			case AUDIO_ELEMENTARY_STREAM_0:
				Packet_Length = Get_Short()-1;
				code = Get_Byte();

				if ((code & 0xc0)==0x80 && (g_Flags.Track_Flag==MPA_Track || !g_Flags.MPA_Flag))
				{
					g_DVDGlobals.CH[MPA_Track] = FORMAT_MPA;

					code = Get_Byte();
					Packet_Header_Length = Get_Byte();

					if (code>=0x80)
					{
						code = Get_Byte();

						g_PicInfo.AudioPTS = (code & 0x0e) << 29;
						g_PicInfo.AudioPTS |= (Get_Short() & 0xfffe) << 14;
						g_PicInfo.AudioPTS |= (Get_Short()>>1) & 0x7fff;

						Rdptr += Packet_Header_Length-5;
					}
					else
						Rdptr += Packet_Header_Length;

					Packet_Length -= Packet_Header_Length+2;

					LOCATE

					if (!g_DVDGlobals.mpa[MPA_Track].rip && g_Flags.Rip_Flag)
					{
						if ((g_Flags.Format_Flag==FORMAT_MPA || !g_Flags.Format_Flag) && (g_Flags.AVI_Flag || g_Flags.D2V_Flag))
						{
							code = Get_Byte();
							code = (code & 0xff)<<8 | Get_Byte();
							i = 0;

							while (code<0xfff0)
							{
								code = (code & 0xff)<<8 | Get_Byte();
								i++;
							}

							sprintf(l_szBuffer, "%s%s MPA T%02d DELAY %dms.mpa",g_GuiGlobals.szPath, g_GuiGlobals.szOutput, MPA_Track+1, (g_PicInfo.AudioPTS-g_PicInfo.VideoPTS)/90);
							g_DVDGlobals.mpa[MPA_Track].file = fopen(l_szBuffer, "wb");

							Rdptr -= 2; Packet_Length -= i;

							DEMUX_MPA

							g_DVDGlobals.mpa[MPA_Track].rip = 1;					
						}
					}
					else if (g_DVDGlobals.mpa[MPA_Track].rip)
						DEMUX_MPA
				}

				Rdptr += Packet_Length;
				MPA_Track = 0;
				break;

			case VIDEO_ELEMENTARY_STREAM:
				Packet_Length = Get_Short();
				Rdmax = Rdptr + Packet_Length;

				code = Get_Byte();

				if ((code & 0xc0)==0x80)
				{
					code = Get_Byte();
					Packet_Header_Length = Get_Byte();

					if (code>=0x80 && !g_Flags.Rip_Flag)
					{
						code = Get_Byte();
						g_PicInfo.VideoPTS = (code & 0x0e) << 29;
						g_PicInfo.VideoPTS |= (Get_Short() & 0xfffe) << 14;
						g_PicInfo.VideoPTS |= (Get_Short()>>1) & 0x7fff;

						Rdptr += Packet_Header_Length-5;
					}
					else
						Rdptr += Packet_Header_Length;

					g_DVDGlobals.Bitrate_Meter += Rdmax-Rdptr;
					return;
				}
				else
					Rdptr += Packet_Length-1;
				break;

			default:
				if (code>=SYSTEM_START_CODE)
				{
					Packet_Length = Get_Short();
					Rdptr += Packet_Length;
				}
				break;
		}
	}
}

unsigned int Get_Bits_All(unsigned int N)
{
	N -= BitsLeft;
	Val = (CurrentBfr << (32 - BitsLeft)) >> (32 - BitsLeft);

	if (N)
		Val = (Val << N) + (NextBfr >> (32 - N));

	CurrentBfr = NextBfr;
	BitsLeft = 32 - N;
	Fill_Next();

	return Val;
}

void Flush_Buffer_All(unsigned int N)
{
	CurrentBfr = NextBfr;
	BitsLeft = BitsLeft + 32 - N;
	Fill_Next();
}

void Fill_Buffer(void)
{
	Read = _read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr, BUFFER_SIZE);

	if (Read < BUFFER_SIZE)
		Next_File();

	/*if (g_Flags.KeyOp_Flag && (Rdbfr[20] & 0x10))
	{
		BufferOp(Rdbfr, g_Flags.lfsr0, g_Flags.lfsr1);
		Rdbfr[20] &= ~0x10;
	}*/

	Rdptr = Rdbfr;

	if (g_Flags.SystemStream_Flag)
		Rdmax -= BUFFER_SIZE;
	else
		g_DVDGlobals.Bitrate_Meter += Read;
}

void Next_File(void)
{
	int i;

	if (g_Flags.File_Flag < g_Flags.File_Limit-1)
	{
		g_Flags.File_Flag++;

		process.run = 0;
		for (i=0; i<g_Flags.File_Flag; i++)
			process.run += process.length[i];

		_lseeki64(g_DVDGlobals.Infile[g_Flags.File_Flag], 0, SEEK_SET);
		_read(g_DVDGlobals.Infile[g_Flags.File_Flag], Rdbfr + Read, BUFFER_SIZE - Read);
	}
	else
	{
		g_Flags.Fault_Flag = 98;
		Write_Frame(NULL, g_DVDGlobals.d2v_current, 0);
	}
}
