/*
  class for decoders
  Copyright (C) 1999  Martin Vogt

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU Library General Public License as published by
  the Free Software Foundation.

  For more information look at the file COPYRIGHT in this package

 */


#include "decoderClass.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif



#define NDEBUG
#include <assert.h>

/* Array mapping zigzag to array pointer offset. */


static const int zigzag_direct_nommx[64] = {
  0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};


static const int zigzag_direct_mmx[64] = {

    0*8+0/* 0*/, 1*8+0/* 1*/, 0*8+1/* 8*/, 0*8+2/*16*/, 1*8+1/* 9*/, 2*8+0/* 2*/, 3*8+0/* 3*/, 2*8+1/*10*/,
    1*8+2/*17*/, 0*8+3/*24*/, 0*8+4/*32*/, 1*8+3/*25*/, 2*8+2/*18*/, 3*8+1/*11*/, 4*8+0/* 4*/, 5*8+0/* 5*/,
    4*8+1/*12*/, 5*8+2/*19*/, 2*8+3/*26*/, 1*8+4/*33*/, 0*8+5/*40*/, 0*8+6/*48*/, 1*8+5/*41*/, 2*8+4/*34*/,
    3*8+3/*27*/, 4*8+2/*20*/, 5*8+1/*13*/, 6*8+0/* 6*/, 7*8+0/* 7*/, 6*8+1/*14*/, 5*8+2/*21*/, 4*8+3/*28*/,
    3*8+4/*35*/, 2*8+5/*42*/, 1*8+6/*49*/, 0*8+7/*56*/, 1*8+7/*57*/, 2*8+6/*50*/, 3*8+5/*43*/, 4*8+4/*36*/,
    5*8+3/*29*/, 6*8+2/*22*/, 7*8+1/*15*/, 7*8+2/*23*/, 6*8+3/*30*/, 5*8+4/*37*/, 4*8+5/*44*/, 3*8+6/*51*/,
    2*8+7/*58*/, 3*8+7/*59*/, 4*8+6/*52*/, 5*8+5/*45*/, 6*8+4/*38*/, 7*8+3/*31*/, 7*8+4/*39*/, 6*8+5/*46*/,
    7*8+6/*53*/, 4*8+7/*60*/, 5*8+7/*61*/, 6*8+6/*54*/, 7*8+5/*47*/, 7*8+6/*55*/, 6*8+7/*62*/, 7*8+7/*63*/
};





/* Bit masks used by bit i/o operations. */



static unsigned int bitMask[] = {0xffffffff,0x7fffffff,0x3fffffff,0x1fffffff, 
			    0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
			    0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
			    0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
			    0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
			    0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
			    0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
			    0x0000000f, 0x00000007, 0x00000003, 0x00000001};

static unsigned int rBitMask[] = {0xffffffff,0xfffffffe,0xfffffffc,0xfffffff8, 
			    0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 
			    0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, 
			    0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 
			    0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, 
			    0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 
			    0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, 
			    0xf0000000, 0xe0000000, 0xc0000000, 0x80000000};

static unsigned int bitTest[] = { 0x80000000,0x40000000,0x20000000,0x10000000, 
			    0x08000000, 0x04000000, 0x02000000, 0x01000000,
			    0x00800000, 0x00400000, 0x00200000, 0x00100000,
			    0x00080000, 0x00040000, 0x00020000, 0x00010000,
			    0x00008000, 0x00004000, 0x00002000, 0x00001000,
			    0x00000800, 0x00000400, 0x00000200, 0x00000100,
			    0x00000080, 0x00000040, 0x00000020, 0x00000010,
			    0x00000008, 0x00000004, 0x00000002, 0x00000001};





DecoderClass::DecoderClass(VideoDecoder* vid_stream,
			   MpegVideoStream* mpegVideoStream) {

  this->vid_stream=vid_stream;
  this->mpegVideoStream=mpegVideoStream;


#ifdef INTEL
  lmmx=mm_support();
#else
  lmmx=false;
  cout << "no INTEL arch- disable MMX in decoderClass"<<endl;

#endif

  if (lmmx==true) {
    lmmx=4;
  }
  
  int i;
  for(i=0;i<64;i++) {
    zigzag_direct[i]=zigzag_direct_nommx[i];
  }  
  if (lmmx) {
    for(i=0;i<64;i++) {
      // they are different !!!
      zigzag_direct[i]=zigzag_direct_mmx[i];
    }
  } 
  for(i=64;i<256;i++) {
      zigzag_direct[i]=0;
  }
  resetDCT();
  reconptr = dct_recon[0];

}
 

DecoderClass::~DecoderClass() {
}
 


int DecoderClass::decodeDCTDCSizeLum() {
  unsigned int macro_val;
  unsigned int index;
  index=mpegVideoStream->showBits(5);
  if (index < 31) {
    macro_val = dct_dc_size_luminance[index].value;
    mpegVideoStream->flushBits(dct_dc_size_luminance[index].num_bits);
  } else {
    index=mpegVideoStream->showBits(9);	
    index -= 0x1f0;
    macro_val = dct_dc_size_luminance1[index].value;
    mpegVideoStream->flushBits(dct_dc_size_luminance1[index].num_bits);
  }	
  return macro_val;
}


int DecoderClass::decodeDCTDCSizeChrom() {
  unsigned int macro_val;
  unsigned int index;
  index=mpegVideoStream->showBits(5);
  if (index < 31) {
    macro_val = dct_dc_size_chrominance[index].value;
    mpegVideoStream->flushBits(dct_dc_size_chrominance[index].num_bits);
  }else {
    index=mpegVideoStream->showBits(10);
    index -= 0x3e0;
    macro_val = dct_dc_size_chrominance1[index].value;
    mpegVideoStream->flushBits(dct_dc_size_chrominance1[index].num_bits);
  }
  return macro_val;
}

/*
 *--------------------------------------------------------------
 *
 * DecodeMBAddrInc --
 *
 *      Huffman DecoderClass for macro_block_address_increment; the location
 *      in which the result will be placed is being passed as argument.
 *      The decoded value is obtained by doing a table lookup on
 *      mb_addr_inc.
 *
 * Results:
 *      The decoded value for macro_block_address_increment or MPGDECODE_ERROR
 *      for unbound values will be placed in the location specified.
 *
 * Side effects:
 *      Bit stream is irreversibly parsed.
 *
 *--------------------------------------------------------------
 */
int DecoderClass::decodeMBAddrInc() {
  unsigned int index;
  int val;
  index=mpegVideoStream->showBits(11);
  val = mb_addr_inc[index].value;
  mpegVideoStream->flushBits(mb_addr_inc[index].num_bits);
  if (mb_addr_inc[index].num_bits==0) {
    printf("num_bits==0\n");
    val=1;
  }

  if (val == -1) {
    cout <<"EROR: decodeMBAddrInc"<<endl;
    val=MB_STUFFING;
  }
  return val;

}


/*
 *--------------------------------------------------------------
 *
 * DecodeMotionVectors --
 *
 *      Huffman DecoderClass for the various motion vectors, including
 *      motion_horizontal_forward_code, motion_vertical_forward_code,
 *      motion_horizontal_backward_code, motion_vertical_backward_code.
 *      Location where the decoded result will be placed is being passed
 *      as argument. The decoded values are obtained by doing a table
 *      lookup on motion_vectors.
 *
 * Results:
 *      The decoded value for the motion vector or MPGDECODE_ERROR for unbound
 *      values will be placed in the location specified.
 *
 * Side effects:
 *      Bit stream is irreversibly parsed.
 *
 *--------------------------------------------------------------
 */
int DecoderClass::decodeMotionVectors() {
  unsigned int index;
  int value;
  index=mpegVideoStream->showBits(11);
  value = motion_vectors[index].code;

  mpegVideoStream->flushBits(motion_vectors[index].num_bits);
  return value;
}


/*
 *--------------------------------------------------------------
 *
 * DecodeCBP --
 *
 *      Huffman DecoderClass for coded_block_pattern; location in which the
 *      decoded result will be placed is being passed as argument. The
 *      decoded values are obtained by doing a table lookup on
 *      coded_block_pattern.
 *
 * Results:
 *      The decoded value for coded_block_pattern or MPGDECODE_ERROR for unbound
 *      values will be placed in the location specified.
 *
 * Side effects:
 *      Bit stream is irreversibly parsed.
 *
 *--------------------------------------------------------------
 */
int DecoderClass::decodeCBP() {
  unsigned int index;
  unsigned int coded_bp;
  index=mpegVideoStream->showBits(9);
  coded_bp = coded_block_pattern[index].cbp;
  mpegVideoStream->flushBits(coded_block_pattern[index].num_bits);
  return coded_bp;
}







/*
 *--------------------------------------------------------------
 *
 * DecodeMBTypeB --
 *
 *      Huffman Decoder for macro_block_type in bidirectionally-coded
 *      pictures;locations in which the decoded results: macroblock_quant,
 *      macroblock_motion_forward, macro_block_motion_backward,
 *      macroblock_pattern, macro_block_intra, will be placed are
 *      being passed as argument. The decoded values are obtained by
 *      doing a table lookup on mb_type_B.
 *
 * Results:
 *      The various decoded values for macro_block_type in
 *      bidirectionally-coded pictures or MPGDECODE_ERROR for unbound values will
 *      be placed in the locations specified.
 *
 * Side effects:
 *      Bit stream is irreversibly parsed.
 *
 *--------------------------------------------------------------
 */
void DecoderClass::decodeMBTypeB(int& quant,int& motion_fwd,
				 int& motion_bwd,int& pat,int& intra){
  unsigned int index;							
									
  index=mpegVideoStream->showBits(6);
									
  quant = mb_type_B[index].mb_quant;					
  motion_fwd = mb_type_B[index].mb_motion_forward;			
  motion_bwd = mb_type_B[index].mb_motion_backward;			
  pat = mb_type_B[index].mb_pattern;					
  intra = mb_type_B[index].mb_intra;					
  if (index == 0) {
    cout << "error in decodeMBTypeB"<<endl;
  }
  mpegVideoStream->flushBits(mb_type_B[index].num_bits);	
}


/*
 *--------------------------------------------------------------
 *
 * DecodeMBTypeI --
 *
 *      Huffman Decoder for macro_block_type in intra-coded pictures;
 *      locations in which the decoded results: macroblock_quant,
 *      macroblock_motion_forward, macro_block_motion_backward,
 *      macroblock_pattern, macro_block_intra, will be placed are
 *      being passed as argument.
 *
 * Results:
 *      The various decoded values for macro_block_type in intra-coded
 *      pictures or MPGDECODE_ERROR for unbound values will be placed in the
 *      locations specified.
 *
 * Side effects:
 *      Bit stream is irreversibly parsed.
 *
 *--------------------------------------------------------------
 */
void DecoderClass::decodeMBTypeI(int& quant,int& motion_fwd,
				 int& motion_bwd,int& pat,int& intra) {

  unsigned int index;							
  static int quantTbl[4] = {MPGDECODE_ERROR, 1, 0, 0};				
									
  index=mpegVideoStream->showBits(2);
									
  motion_fwd = 0;							
  motion_bwd = 0;							
  pat = 0;								
  intra = 1;								
  quant = quantTbl[index];						
  if (quant == MPGDECODE_ERROR) {
    cout << "decodeMBTypeI Error"<<endl;
  }
  if (index) {								
    mpegVideoStream->flushBits (1 + quant);
  }									

}



/*
 *--------------------------------------------------------------
 *
 * DecodeMBTypeP --
 *
 *      Huffman Decoder for macro_block_type in predictive-coded pictures;
 *      locations in which the decoded results: macroblock_quant,
 *      macroblock_motion_forward, macro_block_motion_backward,
 *      macroblock_pattern, macro_block_intra, will be placed are
 *      being passed as argument. The decoded values are obtained by
 *      doing a table lookup on mb_type_P.
 * 
 * Results:
 *      The various decoded values for macro_block_type in
 *      predictive-coded pictures or MPGDECODE_ERROR for unbound values will be
 *      placed in the locations specified.
 *
 * Side effects:
 *      Bit stream is irreversibly parsed.
 *
 *--------------------------------------------------------------
 */
void DecoderClass::decodeMBTypeP(int& quant,int& motion_fwd,
				 int& motion_bwd,int& pat,int& intra) {

  unsigned int index;							
  
  index=mpegVideoStream->showBits(6);
  
  quant = mb_type_P[index].mb_quant;					
  motion_fwd = mb_type_P[index].mb_motion_forward;			
  motion_bwd = mb_type_P[index].mb_motion_backward;			
  pat = mb_type_P[index].mb_pattern;					
  intra = mb_type_P[index].mb_intra;					
  if (index == 0) {
    cout << "error in decodeMBTypeP"<<endl;
  }
  mpegVideoStream->flushBits(mb_type_P[index].num_bits);	
}

/*
 *--------------------------------------------------------------
 *
 * decodeDCTCoeff --
 *
 *      Huffman Decoder for dct_coeff_first and dct_coeff_next;
 *      locations where the results of decoding: run and level, are to
 *      be placed and also the type of DCT coefficients, either
 *      dct_coeff_first or dct_coeff_next, are being passed as argument.
 *      
 *      The decoder first examines the next 8 bits in the input stream,
 *      and perform according to the following cases:
 *      
 *      '0000 0000' - examine 8 more bits (i.e. 16 bits total) and
 *                    perform a table lookup on dct_coeff_tbl_0.
 *                    One more bit is then examined to determine the sign
 *                    of level.
 *
 *      '0000 0001' - examine 4 more bits (i.e. 12 bits total) and 
 *                    perform a table lookup on dct_coeff_tbl_1.
 *                    One more bit is then examined to determine the sign
 *                    of level.
 *      
 *      '0000 0010' - examine 2 more bits (i.e. 10 bits total) and
 *                    perform a table lookup on dct_coeff_tbl_2.
 *                    One more bit is then examined to determine the sign
 *                    of level.
 *
 *      '0000 0011' - examine 2 more bits (i.e. 10 bits total) and 
 *                    perform a table lookup on dct_coeff_tbl_3.
 *                    One more bit is then examined to determine the sign
 *                    of level.
 *
 *      otherwise   - perform a table lookup on dct_coeff_tbl. If the
 *                    value of run is not ESCAPE, extract one more bit
 *                    to determine the sign of level; otherwise 6 more
 *                    bits will be extracted to obtain the actual value 
 *                    of run , and then 8 or 16 bits to get the value of level.
 *                    
 *      
 *
 * Results:
 *      The decoded values of run and level or MPGDECODE_ERROR 
 *      for unbound values
 *      are placed in the locations specified.
 *
 * Side effects:
 *      Bit stream is irreversibly parsed.
 *
 *--------------------------------------------------------------
 */

void DecoderClass::decodeDCTCoeff(unsigned short int* dct_coeff_tbl,
				  unsigned RUNTYPE& run,int& level) {


  unsigned int temp, index;
  unsigned int value, next32bits, flushed;

    /*
   * Grab the next 32 bits and use it to improve performance of
   * getting the bits to parse. Thus, calls are translated as:
   *
   *	show_bitsX  <-->   next32bits >> (32-X)
   *	get_bitsX   <-->   val = next32bits >> (32-flushed-X);
   *			   flushed += X;
   *			   next32bits &= bitMask[flushed];
   *	flush_bitsX <-->   flushed += X;
   *			   next32bits &= bitMask[flushed];
   *
   */
  next32bits=mpegVideoStream->showBits32();

  flushed = 0;

  /* show_bits8(index); */
  index = next32bits >> 24;

  if (index > 3) {
    value = dct_coeff_tbl[index];
    run = (value & RUN_MASK) >> RUN_SHIFT;
    if (run == END_OF_BLOCK) {
      level = END_OF_BLOCK;
    }
    else {
      /* num_bits = (value & NUM_MASK) + 1; */
      /* flush_bits(num_bits); */
      flushed = (value & NUM_MASK) + 1;
      next32bits &= bitMask[flushed];
      if (run != ESCAPE) {
         level = (value & LEVEL_MASK) >> LEVEL_SHIFT;
	 /* get_bits1(value); */
	 /* if (value) *level = -*level; */
	 if (next32bits >> (31-flushed)) level = -level;
	 flushed++;
	 /* next32bits &= bitMask[flushed];  last op before update */
       }
       else {    /* *run == ESCAPE */
         /* get_bits14(temp); */
	 temp = next32bits >> (18-flushed);
	 flushed += 14;
	 next32bits &= bitMask[flushed];
	 run = temp >> 8;
	 temp &= 0xff;
	 if (temp == 0) {
            /* get_bits8(*level); */
	    level = next32bits >> (24-flushed);
	    flushed += 8;
	    /* next32bits &= bitMask[flushed];  last op before update */
 	    assert(level >= 128);
	 } else if (temp != 128) {
	    /* Grab sign bit */
	    level = ((int) (temp << 24)) >> 24;
	 } else {
            /* get_bits8(*level); */
	    level = next32bits >> (24-flushed);
	    flushed += 8;
	    /* next32bits &= bitMask[flushed];  last op before update */
	    level = level - 256;
	    assert(level <= -128 && level >= -255);
	 }
       }
       /* Update bitstream... */
       mpegVideoStream->flushBitsDirect(flushed);
    }
  }
  else {
    if (index == 2) { 
      /* show_bits10(index); */
      index = next32bits >> 22;
      value = dct_coeff_tbl_2[index & 3];
    }
    else if (index == 3) { 
      /* show_bits10(index); */
      index = next32bits >> 22;
      value = dct_coeff_tbl_3[index & 3];
    }
    else if (index) {	/* index == 1 */
      /* show_bits12(index); */
      index = next32bits >> 20;
      value = dct_coeff_tbl_1[index & 15];
    }
    else {   /* index == 0 */
      /* show_bits16(index); */
      index = next32bits >> 16;
      value = dct_coeff_tbl_0[index & 255];
    }
    run = (value & RUN_MASK) >> RUN_SHIFT;
    level = (value & LEVEL_MASK) >> LEVEL_SHIFT;

    /*
     * Fold these operations together to make it fast...
     */
    /* num_bits = (value & NUM_MASK) + 1; */
    /* flush_bits(num_bits); */
    /* get_bits1(value); */
    /* if (value) *level = -*level; */

    flushed = (value & NUM_MASK) + 2;
    if ((next32bits >> (32-flushed)) & 0x1) level = -level;

    /* Update bitstream ... */
    mpegVideoStream->flushBitsDirect(flushed);

  }

}


void DecoderClass::resetDCT() {
  /* Reset past dct dc y, cr, and cb values. */

  dct_dc_y_past = 1024 << 3;
  dct_dc_cr_past = 1024 << 3;
  dct_dc_cb_past = 1024 << 3;
  
}



/*
 *--------------------------------------------------------------
 *
 * ParseReconBlock --
 *
 *    Parse values for block structure from bitstream.
 *      n is an indication of the position of the block within
 *      the macroblock (i.e. 0-5) and indicates the type of 
 *      block (i.e. luminance or chrominance). Reconstructs
 *      coefficients from values parsed and puts in 
 *      block.dct_recon array in vid stream structure.
 *      sparseFlag is set when the block contains only one
 *      coeffictient and is used by the IDCT.
 *
 * Results:
 *    
 *
 * Side effects:
 *      Bit stream irreversibly parsed.
 *
 *--------------------------------------------------------------
 */


void DecoderClass::ParseReconBlock(int& n,int& mb_intra,
				   unsigned int& qscale,
				   int& lflag,
				   unsigned int* iqmatrixptr,
				   unsigned int* niqmatrixptr) {

   


  int coeffCount=0;
  if (mpegVideoStream->hasBytes(512) == false) {
    cout << "cannot get 512 raw bytes"<<endl;
    return;
  }

  {
    /*
     * Copy the VideoDecoder fields curBits, bitOffset, and bitBuffer
     * into local variables with the same names, so the macros use the
     * local variables instead.  This allows register allocation and
     * can provide 1-2 fps speedup.  On machines with not so many registers,
     * don't do this.
     */
    int size,  pos, coeff;
    int level;
    unsigned RUNTYPE run;
    unsigned RUNTYPE i;


    memset((char *) dct_recon, 0, 64*sizeof(short int));

    if (mb_intra) {
          
      if (n < 4) {
	
	/*
	 * Get the luminance bits.  This code has been hand optimized to
	 * get by the normal bit parsing routines.  We get some speedup
	 * by grabbing the next 16 bits and parsing things locally.
	 * Thus, calls are translated as:
	 *
	 *    show_bitsX  <-->   next16bits >> (16-X)
	 *    get_bitsX   <-->   val = next16bits >> (16-flushed-X);
	 *               flushed += X;
	 *               next16bits &= bitMask[flushed];
	 *    flush_bitsX <-->   flushed += X;
	 *               next16bits &= bitMask[flushed];
	 *
	 * I've streamlined the code a lot, so that we don't have to mask
	 * out the low order bits and a few of the extra adds are removed.
	 *    bsmith
	 */
	unsigned int next16bits, index, flushed;
        next16bits=mpegVideoStream->showBits16();

        index = next16bits >> (16-5);
        if (index < 31) {
          size = dct_dc_size_luminance[index].value;
          flushed = dct_dc_size_luminance[index].num_bits;
        } else {
          index = next16bits >> (16-9);
          index -= 0x1f0;
          size = dct_dc_size_luminance1[index].value;
          flushed = dct_dc_size_luminance1[index].num_bits;
        }
        next16bits &= bitMask[(16+flushed)&0x1f];
        if (size != 0) {
          flushed += size;
          coeff = next16bits >> (16-flushed);
          if (!(coeff & bitTest[32-size])) {
	    coeff++;
            coeff|= rBitMask[size&0x1f];
          }
	  coeff <<= 3;
        } else {
          coeff = 0;
        }
        mpegVideoStream->flushBitsDirect(flushed);
	
        if ( (n == 0) && (lflag) ) {
	  coeff += 1024;
	} else {
	  coeff += dct_dc_y_past;
	}
	dct_dc_y_past = coeff;

      } else { /* n = 4 or 5 */
	/*
	 * Get the chrominance bits.  This code has been hand optimized to
	 * as described above
	 */
	
	unsigned int next16bits, index, flushed;
        next16bits=mpegVideoStream->showBits16();
	
        index = next16bits >> (16-5);
        if (index < 31) {
          size = dct_dc_size_chrominance[index].value;
          flushed = dct_dc_size_chrominance[index].num_bits;
        } else {
          index = next16bits >> (16-10);
          index -= 0x3e0;
          size = dct_dc_size_chrominance1[index].value;
          flushed = dct_dc_size_chrominance1[index].num_bits;
        }
        next16bits &= bitMask[(16+flushed)&0x1f];

        if (size != 0) {
          flushed += size;
          coeff = next16bits >> (16-flushed);
          if (!(coeff & bitTest[32-size])) {
	    coeff++;
            coeff|=rBitMask[size&0x1f];
          }
	  coeff <<= 3;
        } else {
          coeff = 0;
        }
        mpegVideoStream->flushBitsDirect(flushed);
	
	/* We test 5 first; a result of the mixup of Cr and Cb */

        if (n == 5) {
	  if (lflag) {
	    coeff += 1024;
	  } else {
	    coeff += dct_dc_cr_past;
	  }
	  dct_dc_cr_past = coeff;
	} else {
          if (lflag) {
            coeff += 1024;
          } else {
            coeff += dct_dc_cb_past;
          }
          dct_dc_cb_past = coeff;
        }
      }

      coeff <<= lmmx;
      reconptr[0] = coeff;

      pos=0;
      i = 0; 
      coeffCount = (coeff != 0);


      // we never have d_types so there is no check
      

      while(1) {
	decodeDCTCoeff(dct_coeff_next,run,level);
	
	if (run >=END_OF_BLOCK) {
	  break;
	}
	i++;
	i+=run;
	pos = zigzag_direct[i&0x3f];


	coeff = (level * qscale * iqmatrixptr[pos]) >> 3 ;
	
	if (level < 0) {
	  coeff += (1 - (coeff & 1));
	} else {
	  coeff -= (1 - (coeff & 1));
	}	

	coeff <<= lmmx;

	reconptr[pos] = coeff;
	coeffCount++;
	
      }
      mpegVideoStream->flushBitsDirect(2);
      
      goto end;
    
    } else { /* non-intra-coded macroblock */

      decodeDCTCoeff(dct_coeff_first,run,level);
      i = run;

      pos = zigzag_direct[i&0x3f];
      
      /* quantizes and oddifies each coefficient */
      if (level < 0) {
        coeff = ((level - 1) * qscale * niqmatrixptr[pos]) >>3;
        if ((coeff & 1) == 0) {coeff++;}
      } else {    
        coeff = ((level + 1) * qscale * niqmatrixptr[pos]) >>3;
        coeff = (coeff-1) | 1; 
      }

      coeff <<= lmmx;

      reconptr[pos] = coeff;
      coeffCount = (coeff!=0);

      // we never have d_type pictures here, we do not support them
      
      while(1) {
	decodeDCTCoeff(dct_coeff_next,run,level);
	
	if (run >= END_OF_BLOCK) {
	  break;
	}
	i++;
	i+=run;
	pos = zigzag_direct[i&0x3f];

	if (level < 0) {
	  coeff = ((level - 1) * qscale * niqmatrixptr[pos]) >>3;
	  if ((coeff & 1) == 0) {coeff++;}
	} else {
	  coeff = ((level + 1) * qscale * niqmatrixptr[pos]) >> 3;
	  coeff = (coeff-1) | 1; 
	}

	coeff <<= lmmx;

	reconptr[pos] = coeff;
	coeffCount++;
      } /* end while */
      
      mpegVideoStream->flushBitsDirect(2);
      goto end;
    }
  
  end:
    if (coeffCount == 1) {
      if (lmmx) {
	emms();
	reconptr[pos]>>=lmmx;
	j_rev_dct_sparse (reconptr, pos);
	//IDCT_mmx(reconptr);
      } else {
	j_rev_dct_sparse (reconptr, pos);
      }

    } else {

      if (lmmx) {
	IDCT_mmx(reconptr);
      } else {
	j_rev_dct(reconptr);
      }

    }
  }

  // we call this at the edn of the "critical sections"
  /*
  if (lmmx) {
    emms();
  }
  */

  return;

}

    



void DecoderClass::print() {
  int i;
  for(i=0;i<64;i++) {
    printf(" %d ",zigzag_direct[i]);
  }  
  printf("\n");
}


















