/*
Requantize MPEG-2 streams without recompressing.

This program 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
of the License, or (at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Code from libmpeg2 and mpeg2enc copyright by their respective owners
New code and modifications copyright Antoine Missout
Thanks to Sven Goethel for error resilience patches
*/

// toggles:

// #define LOG_RATE_CONTROL // some stats
// #define DEMO // demo mode
// #define STAT // print stats on exit
// #define USE_FD // use 2 lasts args for input/output paths

#define NDEBUG // turns off asserts
#define REMOVE_BYTE_STUFFING	// removes series of 0x00

#if defined(__ppc__) || defined(__ppc64__)
	#define USE_GLOBAL_REGISTER // assign registers to bit buffers
#elif defined(__i386__) || defined (__x86_64__)
	// #define USE_GLOBAL_REGISTER // assign registers to bit buffers
//#else
//#	#error "Unknown Architecture"
#endif

#define MAX_ERRORS 0 // if above copy slice

//#define CHANGE_BRIGHTNESS //add a param to command line, changing brightness: _will_not_recompress_, disables max_errors
//#define WIN // for windows fixes, use with USE_FD

// params:

// if not defined, non intra block in p frames are requantised
// if defined and >= 0, we keep coeff. in pos 0..n-1 in scan order
// and coeff which would have been non-null if requantised
// if defined and < 0 we drop max 1/x coeffs.
// experimental, looks better when undefined
// #define P_FRAME_NON_INTRA_DROP 8

// params for fact = 1.0, fact = 3.0 and fact = 10.0
// we'll make a linear interpolation between
static const int i_factors[3] = {  5, 15,  65 };
static const int p_factors[3] = {  5, 25,  85 };
static const int b_factors[3] = { 25, 45, 105 };

static const double i_min_stresses[3] = { 0.80, 0.50, 0.00 };
static const double p_min_stresses[3] = { 0.60, 0.35, 0.00 };
static const double b_min_stresses[3] = { 0.00, 0.00, 0.00 };

// factor up to which alt table will be used
// (though alt_table gives better psnr up to factor around ~2.5
// the result is less pleasing to watch than normal table
// so this is disabled)
static const double max_alt_table = 0.00;

// includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>

#ifndef USE_FD
#include <unistd.h>
#include <fcntl.h>
#endif

// quant table
#include "qTable.h"

// useful constants
#define I_TYPE 1
#define P_TYPE 2
#define B_TYPE 3

#ifdef WIN
	#define MINLINE
#else
	#define MINLINE inline
#endif

// gcc
#ifdef HAVE_BUILTIN_EXPECT
	#define likely(x) __builtin_expect ((x) != 0, 1)
	#define unlikely(x) __builtin_expect ((x) != 0, 0)
#else
	#define likely(x) (x)
	#define unlikely(x) (x)
#endif

// user defined types
//typedef unsigned int		uint;
typedef unsigned char		uint8;
typedef unsigned short		uint16;
typedef unsigned int		uint32;
#ifdef WIN
typedef __int64				uint64;
#else
typedef unsigned long long	uint64;
#endif

typedef char				int8;
typedef short				int16;
typedef int					int32;
#ifdef WIN
typedef __int64				int64;
#else
typedef long long			int64;
#endif


typedef signed int			sint;
typedef signed char			sint8;
typedef signed short		sint16;
typedef signed int			sint32;
#ifdef WIN
typedef __int64				sint64;
#else
typedef signed long long	sint64;
#endif

#define BITS_IN_BUF (8)




// global variables
static uint8	*cbuf, *rbuf, *wbuf, *orbuf, *owbuf;
#ifdef USE_GLOBAL_REGISTER
	register int	inbitcnt	asm ("r13");
	register int	outbitcnt   asm ("r14");
	register uint32	inbitbuf	asm ("r15");
	register uint32	outbitbuf   asm ("r16");
#else
	static int		inbitcnt, outbitcnt;
	static uint32	inbitbuf, outbitbuf;
#endif
static uint64	inbytecnt, outbytecnt;
static float	fact_x;
static int		mloka1, mloka2, eof;

static int64 orim2vsize;
static int64 bytediff;
static double stress_factor;	//	from 0.0 to 1.0

static int i_factor;
static int p_factor;
static int b_factor;
static double i_min_stress;
static double p_min_stress;
static double b_min_stress;

static short quant_table_id_data[4096];
static short *quant_table_id = &quant_table_id_data[2048];

#ifdef USE_FD
static FILE *ifd, *ofd;
#endif

#ifdef STAT
static uint64 ori_i, ori_p, ori_b;
static uint64 new_i, new_p, new_b;
static uint64 cnt_i, cnt_p, cnt_b;
static uint64 cnt_p_i, cnt_p_ni;
static uint64 cnt_b_i, cnt_b_ni;
#endif

#ifdef DEMO // gopCount variable
int gopCount;
#endif

#ifdef LOG_RATE_CONTROL
FILE* LOG_FILE;
#endif

#ifdef CHANGE_BRIGHTNESS
int delta_bright;
int dc_reset;
int old_dc_pred, new_dc_pred;
#endif

// mpeg2 state
	// seq header
	static uint horizontal_size_value;
	static uint vertical_size_value;
	
	// pic header
	static uint picture_coding_type;
	
	// pic code ext
	static uint f_code[2][2];
	static uint intra_dc_precision;
	static uint picture_structure;
	static uint frame_pred_frame_dct;
	static uint concealment_motion_vectors;
	static uint q_scale_type;
	static uint intra_vlc_format;
	static uint alternate_scan;
	
	// error
	static int validPicHeader;
	static int validSeqHeader;
	static int validExtHeader;
	static int sliceError;

	// slice or mb
	static uint quantizer_scale;
	static uint new_quantizer_scale;
	static uint last_coded_scale;
	static int  h_offset, v_offset;
	static int  mb_skip, mb_add;
	static int  mb_out;
	
	static int  mb_sav_run, mb_sav_lev, mb_sav_c;
	static short *curTable;
	
	// block data
	typedef struct
	{
		uint8 run;
		short level;
	} RunLevel;

	static RunLevel block[6][65]; // terminated by level = 0, so we need 64+1
// end mpeg2 state

#ifndef NDEBUG
	#define DEB(msg) fprintf (stderr, "%s:%d " msg, __FILE__, __LINE__)
	#define DEBF(format, args...) fprintf (stderr, "%s:%d " format, __FILE__, __LINE__, args)
#else
	#define DEB(msg)
	#ifdef WIN
		#define DEBF(format, args)
	#else
		#define DEBF(format, args...)
	#endif
#endif

#define LOG(msg) fprintf (stderr, msg)
#ifdef WIN
	#define LOGF(format, arg1) fprintf (stderr, format, arg1)
#else
	#define LOGF(format, args...) fprintf (stderr, format, args)
#endif


#define BUF_SIZE (16*1024*1024)
#define MIN_READ (4*1024*1024)
#define MIN_WRITE (8*1024*1024)
#define MAX_READ (10*1024*1024)

#define MOV_READ \
	mloka1 = rbuf - cbuf; if (mloka1) memmove(orbuf, cbuf, mloka1);\
	cbuf = rbuf = orbuf; rbuf += mloka1;

#ifdef USE_FD

	#define WRITE \
		mloka1 = wbuf - owbuf; \
		fwrite(owbuf, mloka1, 1, ofd); \
		outbytecnt += mloka1; \
		wbuf = owbuf;

	#define LOCK(x) \
		while (unlikely(x > (rbuf-cbuf))) \
		{ \
			if (!eof)\
			{ \
				mloka2 = MIN_READ; \
				while (mloka2) \
				{\
					assert(rbuf + mloka2 < orbuf + BUF_SIZE); \
					mloka1 = fread(rbuf, 1, mloka2, ifd); \
					if (mloka1 <= 0) { eof = 1; break; } \
					inbytecnt += mloka1; \
					rbuf += mloka1; \
					mloka2 -= mloka1; \
				}\
			} else { RETURN } \
		}
	
#else

	#define WRITE \
		mloka1 = wbuf - owbuf; \
		write(1, owbuf, mloka1); \
		outbytecnt += mloka1; \
		wbuf = owbuf; \
		mloka1 = rbuf - cbuf; if (mloka1) memmove(orbuf, cbuf, mloka1);\
		cbuf = rbuf = orbuf; rbuf += mloka1;
		
	#define LOCK(x) \
		while (unlikely(x > (rbuf-cbuf))) \
		{ \
			if (!eof)\
			{ \
				mloka2 = MIN_READ; \
				while (mloka2) \
				{\
					assert(rbuf + mloka2 < orbuf + BUF_SIZE); \
					mloka1 = read(0, rbuf, mloka2); \
					if (mloka1 <= 0) { eof = 1; break; } \
					inbytecnt += mloka1; \
					rbuf += mloka1; \
					mloka2 -= mloka1; \
				}\
			} else { RETURN } \
		}

#endif

#ifdef STAT

	#define RETURN \
		assert(rbuf >= cbuf);\
		mloka1 = rbuf - cbuf;\
		if (mloka1) { COPY(mloka1); }\
		WRITE \
		free(orbuf); \
		free(owbuf); \
		\
		LOG("Stats:\n");\
		\
		LOGF("Wanted fact_x: %.1f\n", fact_x);\
		\
		LOGF("cnt_i: %.0f ", (float)cnt_i); \
		if (cnt_i) LOGF("ori_i: %.0f new_i: %.0f fact_i: %.1f\n", (float)ori_i, (float)new_i, (float)ori_i/(float)new_i); \
		else LOG("\n");\
		\
		LOGF("cnt_p: %.0f ", (float)cnt_p); \
		if (cnt_p) LOGF("ori_p: %.0f new_p: %.0f fact_p: %.1f cnt_p_i: %.0f cnt_p_ni: %.0f propor: %.1f i\n", \
			(float)ori_p, (float)new_p, (float)ori_p/(float)new_p, (float)cnt_p_i, (float)cnt_p_ni, (float)cnt_p_i/((float)cnt_p_i+(float)cnt_p_ni)); \
		else LOG("\n");\
		\
		LOGF("cnt_b: %.0f ", (float)cnt_b); \
		if (cnt_b) LOGF("ori_b: %.0f new_b: %.0f fact_b: %.1f cnt_b_i: %.0f cnt_b_ni: %.0f propor: %.1f i\n", \
			(float)ori_b, (float)new_b, (float)ori_b/(float)new_b, (float)cnt_b_i, (float)cnt_b_ni, (float)cnt_b_i/((float)cnt_b_i+(float)cnt_b_ni)); \
		else LOG("\n");\
		\
		LOGF("Final fact_x: %.1f\n", (float)inbytecnt/(float)outbytecnt);\
		exit(0);

#else

	#define RETURN \
		assert(rbuf >= cbuf);\
		mloka1 = rbuf - cbuf;\
		if (mloka1) { COPY(mloka1); }\
		WRITE \
		free(orbuf); \
		free(owbuf); \
		exit(0);
	
#endif
	
#define COPY(x)\
		assert(x > 0); \
		assert(wbuf + x < owbuf + BUF_SIZE); \
		assert(cbuf + x < orbuf + BUF_SIZE); \
		assert(cbuf + x >= orbuf); \
		assert(wbuf + x >= orbuf); \
		memcpy(wbuf, cbuf, x);\
		cbuf += x; \
		wbuf += x;

#define SEEKR(x)\
		cbuf += x; \
		assert (cbuf <= rbuf); \
		assert (cbuf < orbuf + BUF_SIZE); \
		assert (cbuf >= orbuf);
	
#define SEEKW(x)\
		wbuf += x; \
		assert (wbuf < owbuf + BUF_SIZE); \
		assert (wbuf >= owbuf);

static MINLINE void putbits(uint val, int n)
{
	assert(n < 32);
	assert(!(val & (0xffffffffU << n)));

	while (unlikely(n >= outbitcnt))
	{
		wbuf[0] = (outbitbuf << outbitcnt ) | (val >> (n - outbitcnt));
		SEEKW(1);
		n -= outbitcnt;
		outbitbuf = 0;
		val &= ~(0xffffffffU << n);
		outbitcnt = BITS_IN_BUF;
	}
	
	if (likely(n))
	{
		outbitbuf = (outbitbuf << n) | val;
		outbitcnt -= n;
	}
	
	assert(outbitcnt > 0);
	assert(outbitcnt <= BITS_IN_BUF);
}

static MINLINE void Refill_bits(void)
{
	assert((rbuf - cbuf) >= 1);
	inbitbuf |= cbuf[0] << (24 - inbitcnt);
	inbitcnt += 8;
	SEEKR(1)
}

static MINLINE void Flush_Bits(uint n)
{
	assert(inbitcnt >= n);

	inbitbuf <<= n;
	inbitcnt -= n;

	assert( (!n) || ((n>0) && !(inbitbuf & 0x1)) );

	while (unlikely(inbitcnt < 24)) Refill_bits();
}

static MINLINE uint Show_Bits(uint n)
{
	return ((unsigned int)inbitbuf) >> (32 - n);
}

static MINLINE uint Get_Bits(uint n)
{
	uint Val = Show_Bits(n);
	Flush_Bits(n);
	return Val;
}

static MINLINE uint Copy_Bits(uint n)
{
	uint Val = Get_Bits(n);
	putbits(Val, n);
	return Val;
}

static MINLINE void flush_read_buffer()
{
	int i = inbitcnt & 0x7;
	if (i)
	{
		if (inbitbuf >> (32 - i))
		{
			DEBF("illegal inbitbuf: 0x%08X, %i, 0x%02X, %i\n", inbitbuf, inbitcnt, (inbitbuf >> (32 - i)), i);
			sliceError++;
		}

		inbitbuf <<= i;
		inbitcnt -= i;
	}
	SEEKR(-1 * (inbitcnt >> 3));
	inbitcnt = 0;
}

static MINLINE void flush_write_buffer()
{
	if (outbitcnt != 8) putbits(0, outbitcnt);
}

/////---- begin ext mpeg code

const uint8 non_linear_mquant_table[32] =
{
	0, 1, 2, 3, 4, 5, 6, 7,
	8,10,12,14,16,18,20,22,
	24,28,32,36,40,44,48,52,
	56,64,72,80,88,96,104,112
};
const uint8 map_non_linear_mquant[113] =
{
	0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,
	16,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,22,22,
	22,22,23,23,23,23,24,24,24,24,24,24,24,25,25,25,25,25,25,25,26,26,
	26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,29,
	29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,31,31,31,31,31
};

static int scale_quant(double quant )
{
	int iquant;
	if (q_scale_type)
	{
		iquant = (int) floor(quant+0.5);
		/* clip mquant to legal (linear) range */
		if (iquant<1) iquant = 1;
		if (iquant>112) iquant = 112;
		iquant = non_linear_mquant_table[map_non_linear_mquant[iquant]];
	}
	else
	{
		/* clip mquant to legal (linear) range */
		iquant = (int)floor(quant+0.5);
		if (iquant<2) iquant = 2;
		if (iquant>62) iquant = 62;
		iquant = (iquant/2)*2; // Must be *even*
	}
	return iquant;
}

static int increment_quant(int quant)
{
	if (q_scale_type)
	{
		if (quant < 1 || quant > 112)
		{
			DEBF("illegal quant: %d\n", quant);
			if (quant > 112) quant = 112;
			else if (quant < 1) quant = 1;
			DEBF("illegal quant changed to : %d\n", quant);
			sliceError++;
		}
		quant = map_non_linear_mquant[quant] + 1;
		if (quant > 31) quant = 31;
		quant = non_linear_mquant_table[quant];
	}
	else
	{
		if ((quant & 1) || (quant < 2) || (quant > 62))
		{
			DEBF("illegal quant: %d\n", quant);
			if (quant & 1) quant--;
			if (quant > 62) quant = 62;
			else if (quant < 2) quant = 2;
			DEBF("illegal quant changed to : %d\n", quant);
			sliceError++;
		}
		quant += 2;
		if (quant > 62) quant = 62;
	}
	return quant;
}

static MINLINE int intmax( register int x, register int y )
{ return x < y ? y : x; }

static MINLINE int intmin( register int x, register int y )
{ return x < y ? x : y; }


static int getNewQuant(int curQuant, int intra)
{
#ifdef CHANGE_BRIGHTNESS
	return curQuant;
#else
	int mquant = 0;
	double cStress;

	switch (picture_coding_type)
	{
		case I_TYPE:
			cStress = (stress_factor - i_min_stress) / (1.0 - i_min_stress);
			mquant = intmax(scale_quant(curQuant + i_factor*cStress), increment_quant(curQuant));
			break;
		
		case P_TYPE:
			cStress = (stress_factor - p_min_stress) / (1.0 - p_min_stress);
			if (intra) // since it might be used as a ref, treat it as an I frame block
				mquant = intmax(scale_quant(curQuant + i_factor*cStress), increment_quant(curQuant));
			else
				mquant = intmax(scale_quant(curQuant + p_factor*cStress), increment_quant(curQuant));
			break;
			
		case B_TYPE:
			cStress = (stress_factor - b_min_stress) / (1.0 - b_min_stress);
			mquant = intmax(scale_quant(curQuant + b_factor*cStress), increment_quant(curQuant));
			break;
			
		default:
			assert(0);
			break;
	}
		
	assert(mquant >= curQuant);
	
	return mquant;
#endif
}

static MINLINE int isNotEmpty(RunLevel *blk)
{
	return (blk->level);
}

#include "putvlc.h"

// return != 0 if error
int putAC(int run, int signed_level, int vlcformat)
{
	int level, len;
	const VLCtable *ptab = NULL;
	
	level = (signed_level<0) ? -signed_level : signed_level; /* abs(signed_level) */
	
	// assert(!(run<0 || run>63 || level==0 || level>2047));
	if(run<0 || run>63)
	{
		DEBF("illegal run: %d\n", run);
		sliceError++;
		return 1;
	}
	if(level==0 || level>2047)
	{
		DEBF("illegal level: %d\n", level);
		sliceError++;
		return 1;
	}
	
	len = 0;
	
	if (run<2 && level<41)
	{
		if (vlcformat)  ptab = &dct_code_tab1a[run][level-1];
		else ptab = &dct_code_tab1[run][level-1];
		len = ptab->len;
	}
	else if (run<32 && level<6)
	{
		if (vlcformat) ptab = &dct_code_tab2a[run-2][level-1];
		else ptab = &dct_code_tab2[run-2][level-1];
		len = ptab->len;
	}
	
	if (len) /* a VLC code exists */
	{
		putbits(ptab->code, len);
		putbits(signed_level<0, 1); /* sign */
	}
	else
	{
		putbits(1l, 6); /* Escape */
		putbits(run, 6); /* 6 bit code for run */
		putbits(((uint)signed_level) & 0xFFF, 12);
	}
	
	return 0;
}

// return != 0 if error
static MINLINE int putACfirst(int run, int val)
{
	if (run==0 && (val==1 || val==-1))
	{
		putbits(2|((val<0) ? 1 : 0), 2);
		return 0;
	}
	else return putAC(run,val,0);
}

void putnonintrablk(RunLevel *blk)
{
	assert(blk->level);
	
	if (putACfirst(blk->run, blk->level)) return;
	blk++;
	
	while(blk->level)
	{
		if (putAC(blk->run, blk->level, 0)) return;
		blk++;
	}
	
	putbits(2,2);
}

static MINLINE void putcbp(int cbp)
{
	assert(cbp > 0 && cbp < 64);
	putbits(cbptable[cbp].code,cbptable[cbp].len);
}

static void putmbtype(int mb_type)
{
	putbits(mbtypetab[picture_coding_type-1][mb_type].code,
			mbtypetab[picture_coding_type-1][mb_type].len);
}

#ifndef WIN
#include <inttypes.h>
#else
typedef uint8	uint8_t;
typedef int8	int8_t;
typedef uint32	uint32_t;
typedef int32	int32_t;
#endif
#include "getvlc.h"

static int non_linear_quantizer_scale [] =
{
     0,  1,  2,  3,  4,  5,   6,   7,
     8, 10, 12, 14, 16, 18,  20,  22,
    24, 28, 32, 36, 40, 44,  48,  52,
    56, 64, 72, 80, 88, 96, 104, 112
};

static MINLINE int get_macroblock_modes ()
{
    int macroblock_modes;
    const MBtab * tab;

    switch (picture_coding_type)
	{
		case I_TYPE:
	
			tab = MB_I + UBITS (bit_buf, 1);
			DUMPBITS (bit_buf, bits, tab->len);
			macroblock_modes = tab->modes;
		
			if ((! (frame_pred_frame_dct)) && (picture_structure == FRAME_PICTURE))
			{
				macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED;
				DUMPBITS (bit_buf, bits, 1);
			}
		
			return macroblock_modes;
	
		case P_TYPE:
	
			tab = MB_P + UBITS (bit_buf, 5);
			DUMPBITS (bit_buf, bits, tab->len);
			macroblock_modes = tab->modes;
		
			if (picture_structure != FRAME_PICTURE)
			{
				if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
				{
					macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE;
					DUMPBITS (bit_buf, bits, 2);
				}
				return macroblock_modes;
			}
			else if (frame_pred_frame_dct)
			{
				if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
					macroblock_modes |= MC_FRAME;
				return macroblock_modes;
			}
			else
			{
				if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
				{
					macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE;
					DUMPBITS (bit_buf, bits, 2);
				}
				if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))
				{
					macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED;
					DUMPBITS (bit_buf, bits, 1);
				}
				return macroblock_modes;
			}
	
		case B_TYPE:
	
			tab = MB_B + UBITS (bit_buf, 6);
			DUMPBITS (bit_buf, bits, tab->len);
			macroblock_modes = tab->modes;
		
			if (picture_structure != FRAME_PICTURE)
			{
				if (! (macroblock_modes & MACROBLOCK_INTRA))
				{
					macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE;
					DUMPBITS (bit_buf, bits, 2);
				}
				return macroblock_modes;
			}
			else if (frame_pred_frame_dct)
			{
				/* if (! (macroblock_modes & MACROBLOCK_INTRA)) */
				macroblock_modes |= MC_FRAME;
				return macroblock_modes;
			}
			else
			{
				if (macroblock_modes & MACROBLOCK_INTRA) goto intra;
				macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE;
				DUMPBITS (bit_buf, bits, 2);
				if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))
				{
					intra:
					macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED;
					DUMPBITS (bit_buf, bits, 1);
				}
				return macroblock_modes;
			}
	
		default:
			return 0;
    }

}

static MINLINE int get_quantizer_scale ()
{
    int quantizer_scale_code;

    quantizer_scale_code = UBITS (bit_buf, 5);
	DUMPBITS (bit_buf, bits, 5); 
	
	if (!quantizer_scale_code)
    {
		DEBF("illegal quant scale code: %d\n", quantizer_scale_code);
		sliceError++;
		quantizer_scale_code++;
    }
	
	if (q_scale_type) return non_linear_quantizer_scale[quantizer_scale_code];
    else return quantizer_scale_code << 1;
}

static MINLINE void get_motion_delta (const int f_code)
{
#define bit_buf (inbitbuf)
    const MVtab * tab;

    if (bit_buf & 0x80000000)
	{
		COPYBITS (bit_buf, bits, 1);
		return;
    }
	else if (bit_buf >= 0x0c000000)
	{

		tab = MV_4 + UBITS (bit_buf, 4);
		COPYBITS (bit_buf, bits, tab->len + 1);
		if (f_code) COPYBITS (bit_buf, bits, f_code);
		return;
    }
	else
	{

		tab = MV_10 + UBITS (bit_buf, 10);
		COPYBITS (bit_buf, bits, tab->len + 1);
		if (f_code) COPYBITS (bit_buf, bits, f_code);
		return;
    }
}


static MINLINE void get_dmv ()
{
    const DMVtab * tab;
    tab = DMV_2 + UBITS (bit_buf, 2);
    COPYBITS (bit_buf, bits, tab->len);
    return;
}

static MINLINE int get_coded_block_pattern ()
{
#define bit_buf (inbitbuf)
    const CBPtab * tab;

    if (bit_buf >= 0x20000000)
	{
		tab = CBP_7 + (UBITS (bit_buf, 7) - 16);
		DUMPBITS (bit_buf, bits, tab->len);
		return tab->cbp;
    }
	else
	{
		tab = CBP_9 + UBITS (bit_buf, 9);
		DUMPBITS (bit_buf, bits, tab->len);
		return tab->cbp;
    }
}

static MINLINE int get_luma_dc_dct_diff ()
{
#define bit_buf (inbitbuf)
#ifdef CHANGE_BRIGHTNESS
	#define DOBITS(x, y, z) DUMPBITS(x, y, z)
#else
	#define DOBITS(x, y, z) COPYBITS(x, y, z)
#endif
    const DCtab * tab;
    int size;
    int dc_diff;

    if (bit_buf < 0xf8000000)
	{
		tab = DC_lum_5 + UBITS (bit_buf, 5);
		size = tab->size;
		if (size)
		{
			DOBITS (bit_buf, bits, tab->len);
			//dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
			dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size);
			DOBITS (bit_buf, bits, size);
			return dc_diff;
		}
		else
		{
			DOBITS (bit_buf, bits, 3);
			return 0;
		}
    }
	else
	{
		tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0);
		size = tab->size;
		DOBITS (bit_buf, bits, tab->len);
		//dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
		dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size);
		DOBITS (bit_buf, bits, size);
		return dc_diff;
    }
}

static MINLINE int get_chroma_dc_dct_diff ()
{
#define bit_buf (inbitbuf)

    const DCtab * tab;
    int size;
    int dc_diff;

    if (bit_buf < 0xf8000000)
	{
		tab = DC_chrom_5 + UBITS (bit_buf, 5);
		size = tab->size;
		if (size)
		{
			COPYBITS (bit_buf, bits, tab->len);
			//dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
			dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size);
			COPYBITS (bit_buf, bits, size);
			return dc_diff;
		} else
		{
			COPYBITS (bit_buf, bits, 2);
			return 0;
		}
    }
	else
	{
		tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0);
		size = tab->size;
		COPYBITS (bit_buf, bits, tab->len + 1);
		//dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
		dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size);
		COPYBITS (bit_buf, bits, size);
		return dc_diff;
    }
}

#define UPDATE_VAL \
	val = curTable[val];

static void get_intra_block_B14 ()
{
#define bit_buf (inbitbuf)
    int i, li;
    int val;
    const DCTtab * tab;
	
    li = i = 0;

    while (1)
	{
		if (bit_buf >= 0x28000000)
		{
			tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
	
			i += tab->run;
			if (i >= 64) break;	/* end of block */
	
	normal_code:
			DUMPBITS (bit_buf, bits, tab->len);
			val = tab->level;
			val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
			UPDATE_VAL
			if (val)
			{
				if (putAC(i - li - 1, val, 0)) break;
				li = i;
			}
	
			DUMPBITS (bit_buf, bits, 1);
	
			continue;
		}
		else if (bit_buf >= 0x04000000)
		{
			tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
	
			i += tab->run;
			if (i < 64) goto normal_code;
	
			/* escape code */
			i += (UBITS (bit_buf, 12) & 0x3F) - 64;
			if (i >= 64) 
			{
				sliceError++;
				break;	/* illegal, check needed to avoid buffer overflow */
			}
			
			DUMPBITS (bit_buf, bits, 12);
			val = SBITS (bit_buf, 12);
			UPDATE_VAL
			if (val)
			{
				if (putAC(i - li - 1, val, 0)) break;
				li = i;
			}
	
			DUMPBITS (bit_buf, bits, 12);
	
			continue;
		}
		else if (bit_buf >= 0x02000000)
		{
			tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00800000)
		{
			tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00200000)
		{
			tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else
		{
			tab = DCT_16 + UBITS (bit_buf, 16);
			DUMPBITS (bit_buf, bits, 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		sliceError++;
		break;	/* illegal, check needed to avoid buffer overflow */
	}
	
	COPYBITS (bit_buf, bits, 2);	/* end of block code */
}

static void get_intra_block_B15 ()
{
#define bit_buf (inbitbuf)
    int i, li;
    int val;
    const DCTtab * tab;
	
    li = i = 0;

    while (1)
	{
		if (bit_buf >= 0x04000000)
		{
			tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4);
	
			i += tab->run;
			if (i < 64)
			{
	normal_code:
				DUMPBITS (bit_buf, bits, tab->len);
				
				val = tab->level;
				val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
				UPDATE_VAL
				if (val)
				{
					if (putAC(i - li - 1, val, 1)) break;
					li = i;
				}
		
				DUMPBITS (bit_buf, bits, 1);
		
				continue;
			}
			else
			{
				if (i >= 128) break; /* end of block */
			
				i += (UBITS (bit_buf, 12) & 0x3F) - 64;
				
				if (i >= 64)
				{
					sliceError++;
					break;	/* illegal, check against buffer overflow */
				}
				
				DUMPBITS (bit_buf, bits, 12);
				val = SBITS (bit_buf, 12);
				UPDATE_VAL
				if (val)
				{
					if (putAC(i - li - 1, val, 1)) break;
					li = i;
				}
		
				DUMPBITS (bit_buf, bits, 12);
		
				continue;
			}
		}
		else if (bit_buf >= 0x02000000)
		{
			tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00800000)
		{
			tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00200000)
		{
			tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else
		{
			tab = DCT_16 + UBITS (bit_buf, 16);
			DUMPBITS (bit_buf, bits, 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		sliceError++;
		break;	/* illegal, check needed to avoid buffer overflow */
	}

	COPYBITS (bit_buf, bits, 4);	/* end of block code */
}

static int get_non_intra_block_rq (RunLevel *blk)
{
#define bit_buf (inbitbuf)
	//int q = quantizer_scale;
	//int nq = new_quantizer_scale, tst = (nq / q) + ((nq % q) ? 1 : 0);
    int i, li;
    int val;
    const DCTtab * tab;

    li = i = -1;

    if (bit_buf >= 0x28000000)
	{
		tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5);
		goto entry_1;
    }
	else goto entry_2;

    while (1)
	{
		if (bit_buf >= 0x28000000)
		{
			tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
	
	entry_1:
			i += tab->run;
			if (i >= 64)
			break;	/* end of block */
	
	normal_code:
	
			DUMPBITS (bit_buf, bits, tab->len);
			val = tab->level;
			val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
			UPDATE_VAL
			if (val)
			{
				blk->level = val;
				blk->run = i - li - 1;
				li = i;
				blk++;
			}
	
			DUMPBITS (bit_buf, bits, 1);
	
			continue;
		}
	
	entry_2:
		if (bit_buf >= 0x04000000)
		{
			tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
	
			i += tab->run;
			if (i < 64) goto normal_code;
	
			/* escape code */
	
			i += (UBITS (bit_buf, 12) & 0x3F) - 64;
			
			if (i >= 64)
			{
				sliceError++;
				break;	/* illegal, check needed to avoid buffer overflow */
			}
			
			DUMPBITS (bit_buf, bits, 12);
			val = SBITS (bit_buf, 12);
			UPDATE_VAL
			if (val)
			{
				blk->level = val;
				blk->run = i - li - 1;
				li = i;
				blk++;
			}
			
			DUMPBITS (bit_buf, bits, 12);
	
			continue;
		}
		else if (bit_buf >= 0x02000000)
		{
			tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00800000)
		{
			tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00200000)
		{
			tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else
		{
			tab = DCT_16 + UBITS (bit_buf, 16);
			DUMPBITS (bit_buf, bits, 16);
			
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		
		sliceError++;
		break;	/* illegal, check needed to avoid buffer overflow */
	}
    DUMPBITS (bit_buf, bits, 2);	/* dump end of block code */
	
	blk->level = 0;

    return i;
}

#ifdef P_FRAME_NON_INTRA_DROP
	#if (P_FRAME_NON_INTRA_DROP < 0)
		#undef UPDATE_VAL
		#define UPDATE_VAL
		#define SAVE_VAL
		#define WRITE_VAL \
			blk->level = val; \
			blk->run = i - li - 1; \
			li = i; \
			blk++;
	#else
		#define SAVE_VAL oval = val;
		#define WRITE_VAL \
			if ((val) || (i < P_FRAME_NON_INTRA_DROP)) \
			{ \
				blk->level = oval; \
				blk->run = i - li - 1; \
				li = i; \
				blk++; \
			}
	#endif
#else
	#define SAVE_VAL
	#define WRITE_VAL \
		if (val) \
		{ \
			blk->level = val; \
			blk->run = i - li - 1; \
			li = i; \
			blk++; \
		}
#endif

static int get_non_intra_block_sav (RunLevel *blk, int cc)
{
#define bit_buf (inbitbuf)
    int i, li;
    int val;
    const DCTtab * tab;
	
#ifdef P_FRAME_NON_INTRA_DROP
	#if (P_FRAME_NON_INTRA_DROP < 0)
		RunLevel *oblk = blk;
	#else
		int oval;
	#endif
#endif

    li = i = -1;

    if (bit_buf >= 0x28000000)
	{
		tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5);
		goto entry_1;
    }
	else goto entry_2;

    while (1)
	{
		if (bit_buf >= 0x28000000)
		{
			tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
	
	entry_1:
			i += tab->run;
			if (i >= 64)
			break;	/* end of block */
	
	normal_code:
	
			DUMPBITS (bit_buf, bits, tab->len);
			val = tab->level;
			val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
			SAVE_VAL
			if (li == -1)
			{
				if (abs(val) < abs(mb_sav_lev))
				{
					mb_sav_c = cc;
					mb_sav_lev = val;
					mb_sav_run = i - li - 1;
				}
			}
			UPDATE_VAL
			WRITE_VAL

			DUMPBITS (bit_buf, bits, 1);
	
			continue;
		}
	
	entry_2:
		if (bit_buf >= 0x04000000)
		{
			tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
	
			i += tab->run;
			if (i < 64) goto normal_code;
	
			/* escape code */
	
			i += (UBITS (bit_buf, 12) & 0x3F) - 64;
			
			if (i >= 64)
			{
				sliceError++;
				break;	/* illegal, check needed to avoid buffer overflow */
			}
			
			DUMPBITS (bit_buf, bits, 12);
			val = SBITS (bit_buf, 12);
			SAVE_VAL
			if (li == -1)
			{
				if (abs(val) < abs(mb_sav_lev))
				{
					mb_sav_c = cc;
					mb_sav_lev = val;
					mb_sav_run = i - li - 1;
				}
			}
			UPDATE_VAL
			WRITE_VAL
			
			DUMPBITS (bit_buf, bits, 12);
	
			continue;
		}
		else if (bit_buf >= 0x02000000)
		{
			tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00800000)
		{
			tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00200000)
		{
			tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else
		{
			tab = DCT_16 + UBITS (bit_buf, 16);
			DUMPBITS (bit_buf, bits, 16);
			
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		
		sliceError++;
		break;	/* illegal, check needed to avoid buffer overflow */
	}
    DUMPBITS (bit_buf, bits, 2);	/* dump end of block code */
	
#ifdef P_FRAME_NON_INTRA_DROP
	#if (P_FRAME_NON_INTRA_DROP < 0)
		blk -= (int)((blk - oblk) * (stress_factor / P_FRAME_NON_INTRA_DROP));
		#ifdef DEMO // P_FRAME_NON_INTRA_DROP
			if ((gopCount & 0x7F) < 10) blk = oblk;
		#endif
	#endif
#endif

	blk->level = 0;
	
    return i;
}

#ifdef P_FRAME_NON_INTRA_DROP
static int get_non_intra_block_drop (RunLevel *blk, int cc)
{
#define bit_buf (inbitbuf)
    int i, li;
    int val;
    const DCTtab * tab;
	#if (P_FRAME_NON_INTRA_DROP < 0)
		RunLevel *oblk = blk;
	#else
		int oval;
	#endif

    li = i = -1;

    if (bit_buf >= 0x28000000)
	{
		tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5);
		goto entry_1;
    }
	else goto entry_2;

    while (1)
	{
		if (bit_buf >= 0x28000000)
		{
			tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
	
	entry_1:
			i += tab->run;
			if (i >= 64)
			break;	/* end of block */
	
	normal_code:
	
			DUMPBITS (bit_buf, bits, tab->len);
			val = tab->level;
			val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
			SAVE_VAL
			UPDATE_VAL
			WRITE_VAL

			DUMPBITS (bit_buf, bits, 1);
	
			continue;
		}
	
	entry_2:
		if (bit_buf >= 0x04000000)
		{
			tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
	
			i += tab->run;
			if (i < 64) goto normal_code;
	
			/* escape code */
	
			i += (UBITS (bit_buf, 12) & 0x3F) - 64;
			
			if (i >= 64)
			{
				sliceError++;
				break;	/* illegal, check needed to avoid buffer overflow */
			}
			
			DUMPBITS (bit_buf, bits, 12);
			val = SBITS (bit_buf, 12);
			SAVE_VAL
			UPDATE_VAL
			WRITE_VAL
			
			DUMPBITS (bit_buf, bits, 12);
	
			continue;
		}
		else if (bit_buf >= 0x02000000)
		{
			tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00800000)
		{
			tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else if (bit_buf >= 0x00200000)
		{
			tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		else
		{
			tab = DCT_16 + UBITS (bit_buf, 16);
			DUMPBITS (bit_buf, bits, 16);
			
			i += tab->run;
			if (i < 64) goto normal_code;
		}
		
		sliceError++;
		break;	/* illegal, check needed to avoid buffer overflow */
	}
    DUMPBITS (bit_buf, bits, 2);	/* dump end of block code */
	
	#if (P_FRAME_NON_INTRA_DROP < 0)
		blk -= (int)((blk - oblk) * (stress_factor / P_FRAME_NON_INTRA_DROP));
		#ifdef DEMO // P_FRAME_NON_INTRA_DROP
			if ((gopCount & 0x7F) < 10) blk = oblk;
		#endif
	#endif
	
	blk->level = 0;

    return i;
}
#endif

#ifdef CHANGE_BRIGHTNESS
static void putDC(const sVLCtable *tab, int val)
{
	int absval, size;
	absval = abs(val);
	size = 0;
	while (absval)
	{
		absval >>= 1;
		size++;
	}
	putbits(tab[size].code,tab[size].len);
	if (size!=0)
	{
		if (val>=0) absval = val;
		else absval = val + (1<<size) - 1; /* val + (2 ^ size) - 1 */
		putbits(absval,size);
	}
}
#endif
static MINLINE void slice_intra_DCT (const int cc)
{
#ifdef CHANGE_BRIGHTNESS
    if (cc == 0)
	{
		int val;
		int bri = get_luma_dc_dct_diff();
		if (dc_reset)
		{
			val = bri + (128 << intra_dc_precision);
			old_dc_pred = val;
				
				val += delta_bright << intra_dc_precision;
				if (val > (255 << intra_dc_precision)) val = 255 << intra_dc_precision;
				else if (val < 0) val = 0;
					
			bri = val - (128 << intra_dc_precision);
			new_dc_pred = val;
			
			dc_reset = 0;
		}
		else
		{
			val = bri + old_dc_pred;
			old_dc_pred = val;
			
				val += delta_bright << intra_dc_precision;
				if (val > (255 << intra_dc_precision)) val = 255 << intra_dc_precision;
				else if (val < 0) val = 0;
				
			bri = val - new_dc_pred;
			new_dc_pred = val;
		}
		putDC(DClumtab, bri);
	}
#else
	if (cc == 0)	get_luma_dc_dct_diff ();
#endif
    else			get_chroma_dc_dct_diff ();

    if (intra_vlc_format) get_intra_block_B15 ();
    else get_intra_block_B14 ();
}

static MINLINE void slice_non_intra_DCT (int cur_block)
{
#ifdef P_FRAME_NON_INTRA_DROP
	if (picture_coding_type == P_TYPE)
	{
		if ((h_offset == 0) || (h_offset == horizontal_size_value - 16))
			get_non_intra_block_sav(block[cur_block], cur_block);
		else
			get_non_intra_block_drop(block[cur_block], cur_block);
	}
	else
		get_non_intra_block_rq(block[cur_block]);
#else
	if ((picture_coding_type == P_TYPE) && ((h_offset == 0) || (h_offset == horizontal_size_value - 16)))
		get_non_intra_block_sav(block[cur_block], cur_block);
	else
		get_non_intra_block_rq(block[cur_block]);
#endif
}

static void motion_fr_frame ( uint f_code[2] )
{
	get_motion_delta (f_code[0]);
	get_motion_delta (f_code[1]);
}

static void motion_fr_field ( uint f_code[2] )
{
    COPYBITS (bit_buf, bits, 1);
	get_motion_delta (f_code[0]);
	get_motion_delta (f_code[1]);

    COPYBITS (bit_buf, bits, 1);
	get_motion_delta (f_code[0]);
	get_motion_delta (f_code[1]);
}

static void motion_fr_dmv ( uint f_code[2] )
{
    get_motion_delta (f_code[0]);
	get_dmv ();

	get_motion_delta (f_code[1]);
	get_dmv ();
}

static void motion_fr_conceal ( )
{
	get_motion_delta (f_code[0][0]);
	get_motion_delta (f_code[0][1]);

    COPYBITS (bit_buf, bits, 1);
}

static void motion_fi_field ( uint f_code[2] )
{
    COPYBITS (bit_buf, bits, 1);

	get_motion_delta (f_code[0]);
	get_motion_delta (f_code[1]);
}

static void motion_fi_16x8 ( uint f_code[2] )
{
    COPYBITS (bit_buf, bits, 1);

	get_motion_delta (f_code[0]);
	get_motion_delta (f_code[1]);

    COPYBITS (bit_buf, bits, 1);

	get_motion_delta (f_code[0]);
	get_motion_delta (f_code[1]);
}

static void motion_fi_dmv ( uint f_code[2] )
{
	get_motion_delta (f_code[0]);
    get_dmv ();

    get_motion_delta (f_code[1]);
	get_dmv ();
}

static void motion_fi_conceal ()
{
    COPYBITS (bit_buf, bits, 1);

	get_motion_delta (f_code[0][0]);
	get_motion_delta (f_code[0][1]);

    COPYBITS (bit_buf, bits, 1);
}

#define MOTION_CALL(routine,direction) 						\
do {														\
    if ((direction) & MACROBLOCK_MOTION_FORWARD)			\
		routine (f_code[0]);								\
    if ((direction) & MACROBLOCK_MOTION_BACKWARD)			\
		routine (f_code[1]);								\
} while (0)

#define NEXT_MACROBLOCK											\
do {															\
    h_offset += 16;												\
    if (h_offset == horizontal_size_value) 						\
	{															\
		v_offset += 16;											\
		if (v_offset > (vertical_size_value - 16)) return;		\
		h_offset = 0;											\
    }															\
} while (0)

void putmbdata(int macroblock_modes)
{
		putmbtype(macroblock_modes & 0x1F);
		
		/*switch (picture_coding_type)
		{
			case I_TYPE:
				if ((! (frame_pred_frame_dct)) && (picture_structure == FRAME_PICTURE))
					putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1);
				break;
		
			case P_TYPE:
				if (picture_structure != FRAME_PICTURE)
				{
					if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
						putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2);
					break;
				}
				else if (frame_pred_frame_dct) break;
				else
				{
					if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
						putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2);
					if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))
						putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1);
					break;
				}
		
			case B_TYPE:
				if (picture_structure != FRAME_PICTURE)
				{
					if (! (macroblock_modes & MACROBLOCK_INTRA))
						putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2);
					break;
				}
				else if (frame_pred_frame_dct) break;
				else
				{
					if (macroblock_modes & MACROBLOCK_INTRA) goto intra;
					putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2);
					if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))
					{
						intra:
						putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1);
					}
					break;
				}
		}*/

		if (macroblock_modes & (MACROBLOCK_MOTION_FORWARD | MACROBLOCK_MOTION_BACKWARD))
		{
			if (picture_structure == FRAME_PICTURE)
			{
				if (frame_pred_frame_dct == 0)
				{
					putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2);
				}
			}
			else
			{
				putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2);
			}
		}
		if ((picture_structure == FRAME_PICTURE) && (frame_pred_frame_dct == 0) && (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)))
		{
			putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1);
		}
}

static MINLINE void put_quantiser(int quantiser)
{
	putbits(q_scale_type ? map_non_linear_mquant[quantiser] : quantiser >> 1, 5);
	last_coded_scale = quantiser;
}

static void putaddrinc(int addrinc)
{
  mb_out += addrinc;
  //LOGF("mb_out: %i\n", mb_out);
  if (mb_out > (horizontal_size_value >> 4))
  {
    sliceError++;
	//LOGF("mb_out: %i, hsv: %i, curo: %i\n", mb_out, horizontal_size_value, (int)outbytecnt + (wbuf - owbuf));
  }
  while (addrinc>33)
  {
    putbits(0x08,11); /* macroblock_escape */
    addrinc-= 33;
  }
  assert( addrinc >= 1 && addrinc <= 33 );
  putbits(addrinctab[addrinc-1].code,addrinctab[addrinc-1].len);
}

static MINLINE int slice_init (int code)
{
#define bit_buf (inbitbuf)

    int offset;
    const MBAtab * mba;

	mb_out = 0;
    v_offset = (code - 1) * 16;

    quantizer_scale = get_quantizer_scale ();
	new_quantizer_scale = getNewQuant(quantizer_scale, 0);
	put_quantiser(new_quantizer_scale);
	

    /* ignore intra_slice and all the extra data */
    while (bit_buf & 0x80000000)
	{
		DUMPBITS (bit_buf, bits, 9);
    }

    /* decode initial macroblock address increment */
    offset = 0;
    while (1)
	{
		if (bit_buf >= 0x08000000)
		{
			mba = MBA_5 + (UBITS (bit_buf, 6) - 2);
			break;
		}
		else if (bit_buf >= 0x01800000)
		{
			mba = MBA_11 + (UBITS (bit_buf, 12) - 24);
			break;
		}
		else switch (UBITS (bit_buf, 12))
		{
			case 8:		/* macroblock_escape */
				offset += 33;
				DUMPBITS (bit_buf, bits, 11);
				continue;
			default:	/* error */
				sliceError++;
				return 1;
		}
    }
	mb_add = offset + mba->mba + 1;
	mb_skip = 0;
	COPYBITS (bit_buf, bits, 1);
	DUMPBITS(bit_buf, bits, mba->len);
	
    h_offset = (offset + mba->mba) << 4;

    while (h_offset - (int)horizontal_size_value >= 0)
	{
		h_offset -= horizontal_size_value;
		v_offset += 16;
    }

    if (v_offset > (vertical_size_value - 16)) return 1;

    return 0;

}

void mpeg2_slice ( const int code )
{
#define bit_buf (inbitbuf)

#ifdef CHANGE_BRIGHTNESS
	dc_reset = 1;
#endif

    if (slice_init (code)) return;

    while (1)
	{
		int macroblock_modes;
		int mba_inc;
		const MBAtab * mba;
	
		macroblock_modes = get_macroblock_modes ();
		if (macroblock_modes & MACROBLOCK_QUANT) quantizer_scale = get_quantizer_scale ();

		if (macroblock_modes & MACROBLOCK_INTRA)
		{
#ifdef STAT
			if (picture_coding_type == P_TYPE) cnt_p_i++;
			else if (picture_coding_type == B_TYPE) cnt_b_i++;
#endif

			new_quantizer_scale = getNewQuant(quantizer_scale, 1);
			if (last_coded_scale == new_quantizer_scale) macroblock_modes &= 0xFFFFFFEF; // remove MACROBLOCK_QUANT
			else macroblock_modes |= MACROBLOCK_QUANT; //add MACROBLOCK_QUANT

			putaddrinc(mb_add + mb_skip); mb_skip = 0;
			putmbdata(macroblock_modes);
			if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(new_quantizer_scale);
		
			if (concealment_motion_vectors)
			{
				if (picture_structure == FRAME_PICTURE) motion_fr_conceal ();
				else motion_fi_conceal ();
			}
			
			curTable = quant_tables[quant_equ[quantizer_scale]][quant_equ[new_quantizer_scale]];
			if (!curTable)
			{
				/*DEBF("Inv. curTable: qs: %i nqs: %i qe_qs: %i qe_nqs: %i\n", 
						quantizer_scale, new_quantizer_scale,
						quant_equ[quantizer_scale], quant_equ[new_quantizer_scale]);*/
				curTable = quant_table_id;
			}

			slice_intra_DCT ( 0);
			slice_intra_DCT ( 0);
			slice_intra_DCT ( 0);
			slice_intra_DCT ( 0);
#ifdef DEMO
			if ((gopCount & 0x7F) < 10)
			{
				// save write state
				uint8 *savedWbuf = wbuf;
				int savedOutbitcnt = outbitcnt;
				uint32 savedOutbitbuf = outbitbuf;
				
				// process u block
				slice_intra_DCT ( 1);
				
				//int dump = (wbuf - owbuf == 201);
				//if (dump) fprintf(stderr, "=====\nbyte 0x%02X, cnt %i, outbitbuf 0x%02X, outbitcnt %i\n",
				//						wbuf[-1], wbuf - savedWbuf, outbitbuf, outbitcnt);
				
				// remember how much data was converted
				int bitsToSkip = BITS_IN_BUF - savedOutbitcnt;
				int postBitsWritten = BITS_IN_BUF - outbitcnt;
				int bitsWritten = (wbuf - savedWbuf) * 8 + postBitsWritten - bitsToSkip;
				
				if (postBitsWritten) putbits(0, outbitcnt);
				int bytesToCopy = wbuf - savedWbuf;

				// copy the bytes into temp buffer
				uint8 tempBuf[1024];
				memcpy(tempBuf, savedWbuf, bytesToCopy);
				
				//if (dump) fprintf(stderr, "pos %i, byte 0x%02X, bitsToSkip %i, postBitsWritten %i, bitsWritten %i, bytesToCopy %i\n",
				//					wbuf - owbuf, savedWbuf[0], bitsToSkip, postBitsWritten, bitsWritten, bytesToCopy);
		

				// reset write buffer
				{
					wbuf = savedWbuf;
					outbitcnt = savedOutbitcnt;
					outbitbuf = savedOutbitbuf;
				}
				
				// process v block
				slice_intra_DCT ( 2);
						
				// copy bits back from temp buffer
				{
					int bi = bitsToSkip, bm = bi + bitsWritten, p = 0;
					while(bi < bm)
					{
						int to = bm - bi;
					
						int bmod = bi % 8;
						if (bmod)
						{
							if (to > 8 - bmod) to = 8 - bmod;
							putbits((tempBuf[p] & ((1 << to) - 1)) >> (8 - bmod - to), to);
							bi += to; p++; continue;
						}
						
						if (to >= 8)
						{
							putbits(tempBuf[p], 8);
							bi += 8; p++; continue;
						}
						
						putbits(tempBuf[p] >> (8 - to), to);
						bi += to; p++; continue;
					}
				}
				
				//if (dump) fprintf(stderr, "byte 0x%02X, cnt %i, outbitbuf 0x%02X, outbitcnt %i\n",
				//						wbuf[-1], wbuf - savedWbuf, outbitbuf, outbitcnt);
	
				
			}
			else
#endif
			{
				slice_intra_DCT ( 1);
				slice_intra_DCT ( 2);
			}
		}
		else
		{
			int new_coded_block_pattern = 0;

			// begin saving data
			int batb;
			uint8	n_owbuf[32], *n_wbuf, *o_owbuf, *o_wbuf;
			uint32	n_outbitcnt, n_outbitbuf, o_outbitcnt, o_outbitbuf;
			
#ifdef CHANGE_BRIGHTNESS
			dc_reset = 1;
#endif

#define PUSH_BIT_IO \
			o_owbuf = owbuf; o_wbuf = wbuf; \
			o_outbitcnt = outbitcnt; o_outbitbuf = outbitbuf; \
			owbuf = wbuf = n_owbuf; \
			outbitcnt = BITS_IN_BUF; outbitbuf = 0;
			
#define POP_BIT_IO \
			n_wbuf = wbuf; \
			n_outbitcnt = outbitcnt; n_outbitbuf = outbitbuf; \
			owbuf = o_owbuf; wbuf = o_wbuf; \
			outbitcnt = o_outbitcnt; outbitbuf = o_outbitbuf;
			
			PUSH_BIT_IO

			if (picture_structure == FRAME_PICTURE)
				switch (macroblock_modes & MOTION_TYPE_MASK)
				{
					case MC_FRAME: MOTION_CALL (motion_fr_frame, macroblock_modes); break;
					case MC_FIELD: MOTION_CALL (motion_fr_field, macroblock_modes); break;
					case MC_DMV: MOTION_CALL (motion_fr_dmv, MACROBLOCK_MOTION_FORWARD); break;
				}
			else
				switch (macroblock_modes & MOTION_TYPE_MASK)
				{
					case MC_FIELD: MOTION_CALL (motion_fi_field, macroblock_modes); break;
					case MC_16X8: MOTION_CALL (motion_fi_16x8, macroblock_modes); break;
					case MC_DMV: MOTION_CALL (motion_fi_dmv, MACROBLOCK_MOTION_FORWARD); break;
				}
				
			POP_BIT_IO
			
			// end saving data
			
#ifdef STAT
			if (picture_coding_type == P_TYPE) cnt_p_ni++;
			else if (picture_coding_type == B_TYPE) cnt_b_ni++;
#endif
			new_quantizer_scale = getNewQuant(quantizer_scale, 0);

			if (macroblock_modes & MACROBLOCK_PATTERN)
			{
				int coded_block_pattern = get_coded_block_pattern ();
				
				mb_sav_lev = 0xFFFF;
				curTable = quant_tables[quant_equ[quantizer_scale]][quant_equ[new_quantizer_scale]];
				if (!curTable)
				{
					/*DEBF("Inv. curTable: qs: %i nqs: %i qe_qs: %i qe_nqs: %i\n", 
							quantizer_scale, new_quantizer_scale,
							quant_equ[quantizer_scale], quant_equ[new_quantizer_scale]);*/
					curTable = quant_table_id;
				}

				if (coded_block_pattern & 0x20) { slice_non_intra_DCT(0); if (isNotEmpty(block[0])) new_coded_block_pattern |= 0x20; }
				if (coded_block_pattern & 0x10) { slice_non_intra_DCT(1); if (isNotEmpty(block[1])) new_coded_block_pattern |= 0x10; }
				if (coded_block_pattern & 0x08) { slice_non_intra_DCT(2); if (isNotEmpty(block[2])) new_coded_block_pattern |= 0x08; }
				if (coded_block_pattern & 0x04) { slice_non_intra_DCT(3); if (isNotEmpty(block[3])) new_coded_block_pattern |= 0x04; }
				if (coded_block_pattern & 0x02) { slice_non_intra_DCT(4); if (isNotEmpty(block[4])) new_coded_block_pattern |= 0x02; }
				if (coded_block_pattern & 0x01) { slice_non_intra_DCT(5); if (isNotEmpty(block[5])) new_coded_block_pattern |= 0x01; }
#ifdef P_FRAME_NON_INTRA_DROP
				if (picture_coding_type == P_TYPE) new_quantizer_scale = quantizer_scale;
#endif
				if (!new_coded_block_pattern)
				{
					macroblock_modes &= 0xFFFFFFED; // remove MACROBLOCK_PATTERN and MACROBLOCK_QUANT flag
					if (	(picture_coding_type == P_TYPE)
						&& !(macroblock_modes & MACROBLOCK_MOTION_FORWARD))
					{
						assert(n_wbuf == n_owbuf);
						assert(n_outbitcnt == BITS_IN_BUF);
					
						if ((h_offset == 0) || (h_offset == horizontal_size_value - 16))  // can't skip last mb
						{
							// we can't transmit mv (0,0) since PMV could be different than 0 for last block
							// so we transmit the single smallest coeff. instead unrequantised
							// anyway this is likely to take no more bit than transmiting a null mv....
							
							assert((mb_sav_lev) && (mb_sav_lev != 0xFFFF));
							
							new_coded_block_pattern = 1 << (5 - mb_sav_c);
							macroblock_modes |= MACROBLOCK_PATTERN;
							new_quantizer_scale = quantizer_scale;
							block[mb_sav_c][0].run = mb_sav_run; block[mb_sav_c][0].level = mb_sav_lev;
							block[mb_sav_c][1].run = 0; block[mb_sav_c][1].level = 0;
						}
						else
						{
							mb_skip += mb_add;
							goto skip_mb;
						}
					}
				}
			}

			if (last_coded_scale == new_quantizer_scale) macroblock_modes &= 0xFFFFFFEF; // remove MACROBLOCK_QUANT
			else if (macroblock_modes & MACROBLOCK_PATTERN) macroblock_modes |= MACROBLOCK_QUANT; //add MACROBLOCK_QUANT
			assert( (macroblock_modes & MACROBLOCK_PATTERN) || !(macroblock_modes & MACROBLOCK_QUANT) );

			putaddrinc(mb_add + mb_skip); mb_skip = 0;
			putmbdata(macroblock_modes);
			if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(new_quantizer_scale);

			// put saved motion data...
			for (batb = 0; batb < (n_wbuf - n_owbuf); batb++) putbits(n_owbuf[batb], 8);
			putbits(n_outbitbuf, BITS_IN_BUF - n_outbitcnt);
			// end saved motion data...
			
			if (macroblock_modes & MACROBLOCK_PATTERN)
			{
				putcbp(new_coded_block_pattern);
				
				if (new_coded_block_pattern & 0x20) putnonintrablk(block[0]);
				if (new_coded_block_pattern & 0x10) putnonintrablk(block[1]);
				if (new_coded_block_pattern & 0x08) putnonintrablk(block[2]);
				if (new_coded_block_pattern & 0x04) putnonintrablk(block[3]);
				if (new_coded_block_pattern & 0x02) putnonintrablk(block[4]);
				if (new_coded_block_pattern & 0x01) putnonintrablk(block[5]);
			}
		}

skip_mb:

		NEXT_MACROBLOCK;
	
		mba_inc = 0;
		while (1)
		{
			if (bit_buf >= 0x10000000)
			{
				mba = MBA_5 + (UBITS (bit_buf, 5) - 2);
				break;
			}
			else if (bit_buf >= 0x03000000)
			{
				mba = MBA_11 + (UBITS (bit_buf, 11) - 24);
				break;
			}
			else
				switch (UBITS (bit_buf, 11))
				{
					case 8:		/* macroblock_escape */
						mba_inc += 33;
						DUMPBITS (bit_buf, bits, 11);
						continue;
					default:	/* end of slice, or error */
						//LOGF("hoffset: %i, hsv: %i, curo: %i\n", h_offset, horizontal_size_value, (int)outbytecnt + (wbuf - owbuf));
						if (h_offset != 0)
							sliceError++;
						return;
				}
		}
		DUMPBITS (bit_buf, bits, mba->len); //PPP
		
		mba_inc += mba->mba;
		mb_add = mba_inc + 1;
		
#ifdef CHANGE_BRIGHTNESS
		if (mba_inc) dc_reset = 1;
#endif
	
		if (mba_inc) do { NEXT_MACROBLOCK; } while (--mba_inc);
    }

}

/////---- end ext mpeg code

#ifdef CHANGE_BRIGHTNESS
	#ifdef USE_FD
		#define USAGE \
			fprintf(stderr,\
				"\nUsage is :\n"\
				"\t%s [ignored_recompression_factor] inputM2Vsize brightness_delta input.m2v output.m2v\n\n", argv[0]);\
			return -1;
	#else
		#define USAGE \
			fprintf(stderr,\
				"\nUsage is :\n"\
				"\t%s [ignored_recompression_factor] inputM2Vsize brightness_delta\n\n", argv[0]);\
			return -1;
	#endif
#else
	#ifdef USE_FD
		#define USAGE \
			fprintf(stderr,\
				"\nUsage is :\n"\
				"\t%s recompression_factor inputM2Vsize input.m2v output.m2v\n\n", argv[0]);\
			return -1;
	#else
		#define USAGE \
			fprintf(stderr,\
				"\nUsage is :\n"\
				"\t%s recompression_factor inputM2Vsize\n\n", argv[0]);\
			return -1;
	#endif
#endif

int quantisers[42] = 
{
	1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32,
	34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 72, 80,
	88, 96, 104, 112
};

int main (int argc, const char * argv[])
{
	uint8 ID, found;
	int64 greedyFactor, greedyFactor2;
	int i;
	
#ifdef DEMO // gopCount set to 0
	gopCount = 0;
#endif

#ifdef LOG_RATE_CONTROL
	{
		int suffix = 0;
		char logFileName[256];
		do
		{
			sprintf(logFileName, "Logfile_%03i.txt", suffix);
			LOG_FILE = fopen(logFileName, "r");
			if (LOG_FILE) { fclose(LOG_FILE); suffix++; }
		} while(LOG_FILE != 0);
		LOG_FILE = fopen(logFileName, "w");
	}
#endif

#ifdef STAT
	ori_i = ori_p = ori_b = 0;
	new_i = new_p = new_b = 0;
	cnt_i = cnt_p = cnt_b = 0;
	cnt_p_i = cnt_p_ni = 0;
	cnt_b_i = cnt_b_ni = 0;
#endif

#ifdef USE_FD
	if (argc < 3) { USAGE }
	ifd = fopen(argv[argc - 2], "rb");
	ofd = fopen(argv[argc - 1], "wb");
	if (!ifd)
	{
		LOGF("Bad input path! (%s)\n", argv[argc - 2]);
		return 2;
	}
	if (!ofd)
	{
		LOGF("Bad output path! (%s)\n", argv[argc - 1]);
		return 2;
	}
	argc -= 2;
#endif

	rbuf = cbuf = orbuf = malloc(BUF_SIZE);
	wbuf = owbuf = malloc(BUF_SIZE);
	inbytecnt = outbytecnt = 0;
	
	// Progress hack
	int last_percent;
	int curr_percent;	
	last_percent = curr_percent = 0;
	
	eof = 0;
	
	validPicHeader = 0;
	validSeqHeader = 0;
	validExtHeader = 0;
	
	// argument parsing
#ifdef CHANGE_BRIGHTNESS
	if (argc < 5) { USAGE }
	delta_bright = atoi(argv[4]);
#else
	if (argc < 2) { USAGE }
#endif
	fact_x = atof(argv[1]);
	sscanf(argv[2], "%lld", &orim2vsize);
	greedyFactor = orim2vsize / 100;
	greedyFactor2 = orim2vsize / 50;
	
	if (fact_x <= 1.0)
	{
		unsigned char buf[4096];
		
		while(1)
		{		
			int i = read(0, buf, 4096);
			if (i > 0) write(1, buf, i);
			else return 0;
		}
	}
	else if (fact_x > 900.0) fact_x = 900.0;
	
	// factor and stresses setting
	if (fact_x <= 1.0)
	{
		i_factor = i_factors[0];
		p_factor = p_factors[0];
		b_factor = b_factors[0];
		i_min_stress = i_min_stresses[0];
		p_min_stress = p_min_stresses[0];
		b_min_stress = b_min_stresses[0];
	}
	else if (fact_x >= 10.0)
	{
		i_factor = i_factors[2];
		p_factor = p_factors[2];
		b_factor = b_factors[2];
		i_min_stress = i_min_stresses[2];
		p_min_stress = p_min_stresses[2];
		b_min_stress = b_min_stresses[2];
	}
	else if (fact_x <= 3.0) // 1.0 .. 3.0
	{
		double inter = (fact_x - 1.0)/(3.0 - 1.0);
		i_factor = i_factors[0] + inter * (i_factors[1] - i_factors[0]);
		p_factor = p_factors[0] + inter * (p_factors[1] - p_factors[0]);
		b_factor = b_factors[0] + inter * (b_factors[1] - b_factors[0]);
		i_min_stress = i_min_stresses[0] + inter * (i_min_stresses[1] - i_min_stresses[0]);
		p_min_stress = p_min_stresses[0] + inter * (p_min_stresses[1] - p_min_stresses[0]);
		b_min_stress = b_min_stresses[0] + inter * (b_min_stresses[1] - b_min_stresses[0]);
	}
	else // 3.0 .. 10.0
	{
		double inter = (fact_x - 3.0)/(10.0 - 3.0);
		i_factor = i_factors[1] + inter * (i_factors[2] - i_factors[1]);
		p_factor = p_factors[1] + inter * (p_factors[2] - p_factors[1]);
		b_factor = b_factors[1] + inter * (b_factors[2] - b_factors[1]);
		i_min_stress = i_min_stresses[1] + inter * (i_min_stresses[2] - i_min_stresses[1]);
		p_min_stress = p_min_stresses[1] + inter * (p_min_stresses[2] - p_min_stresses[1]);
		b_min_stress = b_min_stresses[1] + inter * (b_min_stresses[2] - b_min_stresses[1]);
	}
	
	/*LOGF(   "i_factor: %i p_factor: %i b_factor: %i\n"
			"i_min_stress: %.02f p_min_stress: %.02f b_min_stress: %.02f\n",
			i_factor, p_factor, b_factor,
			i_min_stress, p_min_stress, b_min_stress);*/
	
	// fill quant table
	// id table
	for (i = -2048; i <= 2047; i++) quant_table_id[i] = i;
	
	// other tables
	for (i = 0; i < 42; i++)
	{
		int q = quantisers[i];
		int j;
		
		for (j = i + 1; j < 42; j++)
		{
			int nq = quantisers[j];
			int k;
			short *cTab = quant_tables[quant_equ[q]][quant_equ[nq]];
			
			for (k = -2048; k <= 2047; k++)
			{
				int ov = k*q;
				int t = ov / nq;
			
				if (fact_x <= max_alt_table)
				{
					int t2, t3;
					int d, d2, d3;
					int nv, nv2, nv3;
					
					t2 = t + 1;
					t3 = t - 1;
					
					nv = t * nq;
					nv2 = t2 * nq;
					nv3 = t3 * nq;
					
					d = abs(nv - ov);
					d2 = abs(nv2 - ov);
					d3 = abs(nv3 - ov);
					
					if (d2 < d) { d = d2; t = t2; }
					if (d3 < d) t = t3;
				}
	
				if (t > 2047) t = 2047;
				else if (t < -2048) t = -2048;
	
				cTab[k] = t;
			}
		}
	}
	
	LOG("M2VRequantiser v1.1. GPLv2 License.\n");

#ifdef WIN
	fprintf(stderr, "Using %f as factor, %lld as m2v size.\n", fact_x, orim2vsize);
#else
	LOGF("Using %f as factor, %lld as m2v size.\n", fact_x, orim2vsize);
#endif
	// recoding
	while(1)
	{
		// get next start code prefix
		found = 0;
		while (!found)
		{
#ifndef REMOVE_BYTE_STUFFING
			LOCK(3)
#else
			LOCK(8)
			
			if	((cbuf[7] == 0) && (cbuf[6] == 0) && (cbuf[5] == 0) && (cbuf[4] == 0)
				&&  (cbuf[3] == 0) && (cbuf[2] == 0) && (cbuf[1] == 0) && (cbuf[0] == 0) ) { SEEKR(1) }			
			else 
#endif
			if ( (cbuf[0] == 0) && (cbuf[1] == 0) && (cbuf[2] == 1) ) found = 1; // start code !
			else { COPY(1) } // continue search
		}
		COPY(3)
		
		// get start code
		LOCK(1)
		ID = cbuf[0];
		COPY(1)

		if (ID == 0x00) // pic header
		{
			LOCK(4)
			picture_coding_type = (cbuf[1] >> 3) & 0x7;
			if (picture_coding_type < 1 || picture_coding_type > 3)
			{
				DEBF("illegal picture_coding_type: %i\n", picture_coding_type);
				validPicHeader = 0;
			}
			else
			{
				validPicHeader = 1;
				cbuf[1] |= 0x7; cbuf[2] = 0xFF; cbuf[3] |= 0xF8; // vbv_delay is now 0xFFFF
			}
			
			validExtHeader = 0;
			
			COPY(4)
		}
		else if (ID == 0xB3) // seq header
		{
			LOCK(8)
			horizontal_size_value = (cbuf[0] << 4) | (cbuf[1] >> 4);
			vertical_size_value = ((cbuf[1] & 0xF) << 8) | cbuf[2];

			if (	horizontal_size_value > 720 || horizontal_size_value < 352
				||  vertical_size_value > 576 || vertical_size_value < 480
				|| (horizontal_size_value & 0xF) || (vertical_size_value & 0xF))
			{
				DEBF("illegal size, hori: %i verti: %i\n", horizontal_size_value, vertical_size_value);
				validSeqHeader = 0;
			}
			else
				validSeqHeader = 1;
				
			validPicHeader = 0;
			validExtHeader = 0;
			
			COPY(8)
		}
		else if (ID == 0xB5) // extension
		{
			LOCK(1)
			if ((cbuf[0] >> 4) == 0x8) // pic coding ext
			{
				LOCK(5)

				f_code[0][0] = (cbuf[0] & 0xF) - 1;
				f_code[0][1] = (cbuf[1] >> 4) - 1;
				f_code[1][0] = (cbuf[1] & 0xF) - 1;
				f_code[1][1] = (cbuf[2] >> 4) - 1;
				
				intra_dc_precision = (cbuf[2] >> 2) & 0x3;
				picture_structure = cbuf[2] & 0x3;
				frame_pred_frame_dct = (cbuf[3] >> 6) & 0x1;
				concealment_motion_vectors = (cbuf[3] >> 5) & 0x1;
				q_scale_type = (cbuf[3] >> 4) & 0x1;
				intra_vlc_format = (cbuf[3] >> 3) & 0x1;
				alternate_scan = (cbuf[3] >> 2) & 0x1;
				
				if (	(f_code[0][0] > 8 && f_code[0][0] < 14)
					||  (f_code[0][1] > 8 && f_code[0][1] < 14)
					||  (f_code[1][0] > 8 && f_code[1][0] < 14)
					||  (f_code[1][1] > 8 && f_code[1][1] < 14)
					||  picture_structure == 0)
				{
					DEBF("illegal ext, f_code[0][0]: %i f_code[0][1]: %i f_code[1][0]: %i f_code[1][1]: %i picture_structure:%i\n",
							f_code[0][0], f_code[0][1], f_code[1][0], f_code[1][1], picture_structure);
					validExtHeader = 0;
				}
				else
					validExtHeader = 1;
				COPY(5)
			}
			else
			{
				COPY(1)
			}
		}
		else if (ID == 0xB8) // gop header
		{
			LOCK(4)
			COPY(4)

#ifdef DEMO // gopCount increment
			gopCount++;
#endif
		}
		else if ((ID >= 0x01) && (ID <= 0xAF) && validPicHeader && validSeqHeader && validExtHeader) // slice
		{
			uint8 *outTemp = wbuf, *inTemp = cbuf;
			int64 threshold;
			
			bytediff = (outbytecnt + (wbuf - owbuf)) - ((inbytecnt - (rbuf - cbuf)) / fact_x);
			

			if (inbytecnt < greedyFactor2) threshold = inbytecnt >> 1;
			else if (orim2vsize - inbytecnt < greedyFactor2) threshold = (orim2vsize - inbytecnt) >> 1;
			else threshold = greedyFactor;
			
			if (threshold < 1024) threshold = 1024;
			
			stress_factor = (float)(bytediff + threshold) / (float)(threshold << 1);
			if (stress_factor > 1.0f)		stress_factor = 1.0f;
			else if (stress_factor < 0.0f)	stress_factor = 0.0f;


#ifdef LOG_RATE_CONTROL
			/*fprintf(LOG_FILE, "%f%%: Requested: %f  Current: %f  Delta: %lld   Threshold: %f  Stress: %f\n", 
				(float)(100.0f*inbytecnt)/orim2vsize,		//	percent
				(float)fact_x,								//	requested
				(float)(inbytecnt - (rbuf - cbuf))/(float)(outbytecnt + (wbuf - owbuf)), //	current
				(long long)bytediff,						//	delta
				(float)threshold, 							//	threshold
				stress_factor								//	Stress
			);*/
			fprintf(LOG_FILE, "inb: %.0f inb_c: %.0f oub: %.0f oub_c: %.0f cur: %.3f dif: %.0f thr: %.0f str: %.03f\n",
				(float)inbytecnt,
				(float)(inbytecnt - (rbuf - cbuf)),
				(float)outbytecnt, 
				(float)(outbytecnt + (wbuf - owbuf)),
				(float)(inbytecnt - (rbuf - cbuf))/(float)(outbytecnt + (wbuf - owbuf)),
				(float)bytediff,
				(float)threshold,
				(float)stress_factor );
#endif


#ifndef CHANGE_BRIGHTNESS
			if (	((picture_coding_type == I_TYPE) && ( stress_factor > i_min_stress))
				||  ((picture_coding_type == P_TYPE) && ( stress_factor > p_min_stress))
				||  ((picture_coding_type == B_TYPE) && ( stress_factor > b_min_stress))
#ifdef DEMO // force processing
				||	((gopCount & 0x7F) < 10)
#endif
				)
#endif
			{

				// lock all the slice if less than 1 meg in buffer
				if (rbuf - cbuf < 1*1024*1024)
				{
					// try to read more data
					if (!eof)
					{ 
						mloka2 = MIN_READ; 
						while (mloka2) 
						{
							assert(rbuf + mloka2 < orbuf + BUF_SIZE); 
#ifdef USE_FD
							mloka1 = fread(rbuf, 1, mloka2, ifd);
#else
							mloka1 = read(0, rbuf, mloka2);
#endif							
							if (mloka1 <= 0) { eof = 1; break; } 
							inbytecnt += mloka1; 
							rbuf += mloka1; 
							mloka2 -= mloka1; 

							// Progress hack							
							curr_percent = ((float)inbytecnt / (float)orim2vsize) * 100;
							if (curr_percent != last_percent)
							{
#ifdef WIN
								fprintf(stderr, "Progress: %d%%\n", curr_percent);
#else
								LOGF("Progress: %d%%\n", curr_percent);
#endif							
							}								
							last_percent = curr_percent;							
						}
					}
					// lock slice manually
					if (rbuf - cbuf < 1*1024*1024)
					{
						uint8 *nsc = cbuf;
						int fsc = 0, toLock;
						while (!fsc)
						{
							toLock = nsc - cbuf + 3;
							LOCK(toLock)
			
							if ( (nsc[0] == 0) && (nsc[1] == 0) && (nsc[2] == 1) ) fsc = 1; // start code !
							else nsc++; // continue search
						}
					}
				}
				
				
				// init error
				sliceError = 0;
			
				// init bit buffer
				inbitbuf = 0; inbitcnt = 0;
				outbitbuf = 0; outbitcnt = BITS_IN_BUF;
				
				// get 32 bits
				Refill_bits();
				Refill_bits();
				Refill_bits();
				Refill_bits();
			
				// begin bit level recoding
				mpeg2_slice(ID);
				flush_read_buffer();
				flush_write_buffer();
				// end bit level recoding
			
#ifndef CHANGE_BRIGHTNESS
				if ((wbuf - outTemp > cbuf - inTemp) || (sliceError > MAX_ERRORS)) // yes that might happen, rarely
				{
#ifndef NDEBUG
					if (sliceError > MAX_ERRORS)
					{
						DEBF("sliceError (%i) > MAX_ERRORS (%i)\n", sliceError, MAX_ERRORS);
					}
#endif

					// in this case, we'll just use the original slice !
					memcpy(outTemp, inTemp, cbuf - inTemp);
					wbuf = outTemp + (cbuf - inTemp);
					
					// adjust outbytecnt
					outbytecnt -= (wbuf - outTemp) - (cbuf - inTemp);
				}
#endif
				
#ifdef STAT
	#ifdef LOG_RATE_CONTROL
				if (picture_coding_type == I_TYPE)
					fprintf(LOG_FILE, "-I-\n");
	#endif
				switch(picture_coding_type)
				{
					case I_TYPE:
						ori_i += cbuf - inTemp;
						new_i += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp);
						cnt_i ++;
						break;
						
					case P_TYPE:
						ori_p += cbuf - inTemp;
						new_p += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp);
						cnt_p ++;
						break;
						
					case B_TYPE:
						ori_b += cbuf - inTemp;
						new_b += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp);
						cnt_b ++;
						break;
						
					default:
						assert(0);
						break;
				}
#endif
			}
		}
		
#ifndef NDEBUG
		if ((ID >= 0x01) && (ID <= 0xAF) && (!validPicHeader || !validSeqHeader || !validExtHeader))
		{
			if (!validPicHeader) DEBF("missing pic header (%02X)\n", ID);
			if (!validSeqHeader) DEBF("missing seq header (%02X)\n", ID);
			if (!validExtHeader) DEBF("missing ext header (%02X)\n", ID);
		}
#endif
		if (rbuf - orbuf > MAX_READ) { MOV_READ }
		if (wbuf - owbuf > MIN_WRITE) { WRITE }
	}

#ifdef LOG_RATE_CONTROL
	fclose(LOG_FILE);
#endif
	// keeps gcc happy
	return 0;
}
