Logo Search packages:      
Sourcecode: vamps version File versions  Download package

requant.c

// This file is part of Vamps.
//
// Vamps 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.
//
// Vamps 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 Vamps; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, 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
// Released under GPL license, see gnu.org

// toggles:

#define THREAD
// #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
// #define USE_GLOBAL_REGISTER // assign registers to bit buffers
#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
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

#ifdef THREAD
#include "requant.h"
#else
#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);
#endif

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;
#ifdef DEMO
      if ((gopCount & 0x7F) < 10) // gop is ~ 0.5 sec, so 5 sec every ~minute (127 * 0.5 = 63.5 sec)
      {
            if (q_scale_type) return 112;
            else return 62;
      }
#endif
      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)
{
#ifdef DEMO
      if ((gopCount & 0x7F) < 10)
      {
            if (q_scale_type) return 112;
            else return 62;
      }
#endif
      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
                  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
                  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);
                  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] [ignored_quality_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] [ignored_quality_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 [ignored_quality_factor] inputM2Vsize input.m2v output.m2v\n\n", argv[0]);\
                  return -1;
      #else
            #define USAGE \
                  fprintf(stderr,\
                        "\nUsage is :\n"\
                        "\t%s recompression_factor [ignored_quality_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
};

#ifdef THREAD
void *requant_thread (void *p)
#else
int main (int argc, const char * argv[])
#endif
{
      uint8 ID, found;
      int64 greedyFactor, greedyFactor2;
      int i;
      
#ifdef DEMO
      gopCount = 0;
#endif

#ifdef LOG_RATE_CONTROL
      LOG_FILE = fopen("Logfile.txt", "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

#ifndef THREAD
      rbuf = cbuf = orbuf = malloc(BUF_SIZE);
      wbuf = owbuf = malloc(BUF_SIZE);
      inbytecnt = outbytecnt = 0;
      eof = 0;
#endif
      
      validPicHeader = 0;
      validSeqHeader = 0;
      validExtHeader = 0;
      
#ifndef THREAD
      // argument parsing
#ifdef CHANGE_BRIGHTNESS
      if (argc < 5) { USAGE }
      delta_bright = atoi(argv[4]);
#else
      if (argc < 4) { USAGE }
#endif
      fact_x = atof(argv[1]);
      sscanf(argv[3], "%lld", &orim2vsize);
#endif

      greedyFactor = orim2vsize / 100;
      greedyFactor2 = orim2vsize / 50;
      
#ifndef THREAD
      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;
#endif
      
      // 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;
                  }
            }
      }
      
#ifndef THREAD
      LOG("M2VRequantiser by Makira.\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
#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++;
#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
                        ||    ((gopCount & 0x7F) < 10)
#endif
                        )
#endif
                  {

#ifndef THREAD
                        // 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; 
                                    }
                              }
                              // 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
                                    }
                              }
                        }
#endif
                        
                        // 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;
}


Generated by  Doxygen 1.6.0   Back to index