/*
  File: getblk.cc


*/


#include "all.hh"


/* defined in getvlc.hh */
typedef struct {
  char run, level, len;
} DCTtab;

extern DCTtab DCTtabfirst[],DCTtabnext[],DCTtab0[],DCTtab1[];
extern DCTtab DCTtab2[],DCTtab3[],DCTtab4[],DCTtab5[],DCTtab6[];
extern DCTtab DCTtab0a[],DCTtab1a[];


// decode one intra coded MPEG-1 block

void LayerData::getintrablock(int comp, int dc_dct_pred[]){
  int val, j, sign;
  unsigned int code;
  DCTtab *tab;

  short *bp = block[comp];

  /* decode DC coefficients */
  if (comp<4)         bp[0] = (dc_dct_pred[0]+=getDClum()) << 3;
  else if (comp==4)   bp[0] = (dc_dct_pred[1]+=getDCchrom()) << 3;
  else                bp[0] = (dc_dct_pred[2]+=getDCchrom()) << 3;
#ifdef HAVE_MMX
  bp[0] <<= 4;
#endif

  if (fault) return;

  /* decode AC coefficients */
  for (int i=1; ; i++){
    code = (vs->showbits(32) >> 16);
    if (code>=16384) tab = &DCTtabnext[(code>>12)-4];
    else if (code>=1024) tab = &DCTtab0[(code>>8)-4];
    else if (code>=512) tab = &DCTtab1[(code>>6)-8];
    else if (code>=256) tab = &DCTtab2[(code>>4)-16];
    else if (code>=128) tab = &DCTtab3[(code>>3)-16];
    else if (code>=64) tab = &DCTtab4[(code>>2)-16];
    else if (code>=32) tab = &DCTtab5[(code>>1)-16];
    else if (code>=16) tab = &DCTtab6[code-16];
    else {
      if (!quiet) fprintf(stderr,"invalid Huffman code in getintrablock()\n");
      fault = 1;
      return;
    }

    vs->flushbits(tab->len);

    if (tab->run==64) break;  // end_of_block

    if (tab->run==65){         // escape
      i+= vs->getbits(6);
      if ((val=vs->getbits(8))==0) val=vs->getbits(8);
      else if (val==128)         val=vs->getbits(8) - 256;
      else if (val>128)          val-= 256;
      if ((sign=(val<0))!=0)        val= -val;
    }
    else {
      i+= tab->run;
      val = tab->level;
      sign = vs->getbits(1);
    }

    j = zig_zag_scan[i];
#ifdef HAVE_MMX
    val = (val*quant_scale*intra_quantizer_matrix[j]) << 1;
    /* if (val!=0) should always be true */
    val = (val-16) | 16;
#else
    val = (val*quant_scale*intra_quantizer_matrix[j]) >> 3;
    /* if (val!=0) should always be true */
    val = (val-1) | 1;
#endif
    bp[j] = sign ? -val : val;
  }
  if (j != 0) {
     /* not a sparse matrice ! */
     sparse[comp] = 0;
  }

}


// decode one non-intra coded MPEG-1 block

void LayerData::getinterblock(int comp){
  int val, j, sign;
  unsigned int code;
  DCTtab *tab;

  short *bp = block[comp];

  /* decode AC coefficients */
  for (int i=0; ; i++){
    code = (vs->showbits(32) >> 16);
    if (code>=16384){
      if (i==0) tab = &DCTtabfirst[(code>>12)-4];
      else      tab = &DCTtabnext[(code>>12)-4];
    }
    else if (code>=1024) tab = &DCTtab0[(code>>8)-4];
    else if (code>=512)  tab = &DCTtab1[(code>>6)-8];
    else if (code>=256)  tab = &DCTtab2[(code>>4)-16];
    else if (code>=128)  tab = &DCTtab3[(code>>3)-16];
    else if (code>=64)   tab = &DCTtab4[(code>>2)-16];
    else if (code>=32)   tab = &DCTtab5[(code>>1)-16];
    else if (code>=16)   tab = &DCTtab6[code-16];
    else {
      if (!quiet)
        fprintf(stderr,"invalid Huffman code in getinterblock()\n");
      fault = 1;
      return;
    }

    vs->flushbits(tab->len);

    if (tab->run==64)
       break;   // end of block

    if (tab->run==65){          // escape 
      i+= vs->getbits(6);
      if ((val=vs->getbits(8))==0) val=vs->getbits(8);
      else if (val==128)       val=vs->getbits(8) - 256;
      else if (val>128)        val-= 256;
      if ((sign=(val<0))!=0)      val = -val;
    }
    else {
      i+= tab->run;
      val = tab->level;
      sign = vs->getbits(1);
    }

    j = zig_zag_scan[i];
#ifdef HAVE_MMX
    val = (((val<<1)+1)*quant_scale*non_intra_quantizer_matrix[j]);
    /* if (val!=0) should always be true */
    val = (val-16) | 16;
#else
    val = (((val<<1)+1)*quant_scale*non_intra_quantizer_matrix[j]) >> 4;
    /* if (val!=0) should always be true */
    val = (val-1) | 1;
#endif
    bp[j] = sign ? -val : val;
  }
  if (j != 0) {
     /* not a sparse matrice ! */
     sparse[comp] = 0;
  }

}


// decode one intra coded MPEG-2 block

void LayerData::getmpg2intrablock(int comp, int dc_dct_pred[]){
  int val, j, sign, nc;
  unsigned int code;
  DCTtab *tab;
  short *bp;
  int *qmat;

  /* with data partitioning, data always goes to base layer */
//  ld1 = (ld->scalable_mode==SC_DP) ? &base : ld;
//  ld1=ld;
  bp = block[comp];

#ifdef ENHANCEMENT
  if (base.scalable_mode==SC_DP)
    if (base.pri_brk<64) ld = &enhan;
    else ld = &base;
#endif

  qmat = (comp<4 || chroma_format==CHROMA420)
         ? intra_quantizer_matrix
         : chroma_intra_quantizer_matrix;

  /* decode DC coefficients */
  if (comp<4)           val = (dc_dct_pred[0]+= getDClum());
  else if ((comp&1)==0) val = (dc_dct_pred[1]+= getDCchrom());
  else                  val = (dc_dct_pred[2]+= getDCchrom());

  if (fault) return;
#ifdef HAVE_MMX
  bp[0] = val << (7-dc_prec);
#else
  bp[0] = val << (3-dc_prec);
#endif
  nc=0;

  /* decode AC coefficients */
  for (int i=1; ; i++){
//    code = vs->showbits(32) >> 16;
    code = vs->showbits(16);
    if (code>=16384 && !intravlc) tab = &DCTtabnext[(code>>12)-4];
    else if (code>=1024){
      if (intravlc)     tab = &DCTtab0a[(code>>8)-4];
      else              tab = &DCTtab0[(code>>8)-4];
    }
    else if (code>=512){
      if (intravlc)     tab = &DCTtab1a[(code>>6)-8];
      else              tab = &DCTtab1[(code>>6)-8];
    }
    else if (code>=256) tab = &DCTtab2[(code>>4)-16];
    else if (code>=128) tab = &DCTtab3[(code>>3)-16];
    else if (code>=64)  tab = &DCTtab4[(code>>2)-16];
    else if (code>=32)  tab = &DCTtab5[(code>>1)-16];
    else if (code>=16)  tab = &DCTtab6[code-16];
    else {
      if (!quiet) fprintf(stderr,"invalid Huffman code in getmpg2intrablock()\n");
      fault = 1;
      return;
    }

    vs->flushbits(tab->len);

    if (tab->run==64)
       break; // end_of_block

    if (tab->run==65){        // escape
      i+= vs->getbits(6);

      val = vs->getbits(12);
      if ((val&2047)==0){
        if (!quiet) fprintf(stderr,"invalid signed_level (escape) in getmpg2intrablock()\n");
        fault = 1;
        return;
      }
      if ((sign=(val>=2048))!=0) val = 4096 - val;
    }
    else {
      i+= tab->run;
      val = tab->level;
      sign = vs->getbits(1);
    }

    j = (altscan ? alternate_scan : zig_zag_scan)[i];

#ifdef HAVE_MMX
    val = (val * quant_scale * qmat[j]);
#else
    val = (val * quant_scale * qmat[j]) >> 4;
#endif

    bp[j] = sign ? -val : val;
    nc++;

#ifdef ENHANCEMENT
    if (base.scalable_mode==SC_DP && nc==base.pri_brk-63){
      ld = &enhan;
      incnt = ld->incnt;
      bfr = vs->showbits(32);
    }
#endif
  }
  if (j != 0) {
     /* not a sparse matrice ! */
     sparse[comp] = 0;
  }

}


// decode one non-intra coded MPEG-2 block

void LayerData::getmpg2interblock(int comp){
  int val, j, sign, nc;
  unsigned int code;
  DCTtab *tab;
  short *bp;
  int *qmat;

  /* with data partitioning, data always goes to base layer */
//  ld1 = (ld->scalable_mode==SC_DP) ? &base : ld;
//  ld1=ld;
  bp = block[comp];

#ifdef ENHANCEMENT
  if (base.scalable_mode==SC_DP)
    if (base.pri_brk<64) ld = &enhan;
    else                 ld = &base;
#endif

  qmat = (comp<4 || chroma_format==CHROMA420)
         ? non_intra_quantizer_matrix
         : chroma_non_intra_quantizer_matrix;

  nc = 0;

  /* decode AC coefficients */
  for (int i=0; ; i++){
//    code = vs->showbits(32) >> 16;
    code = vs->showbits(16);
    if (code>=16384){
      if (i==0) tab = &DCTtabfirst[(code>>12)-4];
      else      tab = &DCTtabnext[(code>>12)-4];
    }
    else if (code>=1024) tab = &DCTtab0[(code>>8)-4];
    else if (code>=512)  tab = &DCTtab1[(code>>6)-8];
    else if (code>=256)  tab = &DCTtab2[(code>>4)-16];
    else if (code>=128)  tab = &DCTtab3[(code>>3)-16];
    else if (code>=64)   tab = &DCTtab4[(code>>2)-16];
    else if (code>=32)   tab = &DCTtab5[(code>>1)-16];
    else if (code>=16)   tab = &DCTtab6[code-16];
    else {
      if (!quiet) fprintf(stderr,"invalid Huffman code in getmpg2interblock()\n");
      fault = 1;
      return;
    }

    vs->flushbits(tab->len);

    if (tab->run==64)
       break;          // end_of_block

    if (tab->run==65){                 // escape
      i+= vs->getbits(6);
      val = vs->getbits(12);
      if ((val&2047)==0){
        if (!quiet) fprintf(stderr,"invalid signed_level (escape) in getmpg2intrablock()\n");
        fault = 1;
        return;
      }
      if ((sign=(val>=2048))!=0) val = 4096 - val;
    }
    else {
      i+= tab->run;
      val = tab->level;
      sign = vs->getbits(1);
    }

    j = (altscan ? alternate_scan : zig_zag_scan)[i];
#ifdef HAVE_MMX
     val = (((val<<1)+1) * quant_scale * qmat[j]) >> 1;
#else
     val = (((val<<1)+1) * quant_scale * qmat[j]) >> 5;
#endif

    bp[j] = sign ? (-val) : val ;
    nc++;

/*
    if (base.scalable_mode==SC_DP && nc==base.pri_brk-63){
      ld = &enhan;
      incnt = ld->incnt;
      bfr = vs->showbits(32);
    }
*/
  }
  if (j != 0) {
    /* not a sparse matrice ! */
    sparse[comp] = 0;
  }
}
