/* getblk.c, DCT block decoding                                             */

/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */

/*
 * Disclaimer of Warranty
 *
 * These software programs are available to the user without any license fee or
 * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
 * any and all warranties, whether express, implied, or statuary, including any
 * implied warranties or merchantability or of fitness for a particular
 * purpose.  In no event shall the copyright-holder be liable for any
 * incidental, punitive, or consequential damages of any kind whatsoever
 * arising from the use of these programs.
 *
 * This disclaimer of warranty extends to the user of these programs and user's
 * customers, employees, agents, transferees, successors, and assigns.
 *
 * The MPEG Software Simulation Group does not represent or warrant that the
 * programs furnished hereunder are free of infringement of any third-party
 * patents.
 *
 * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
 * are subject to royalty fees to patent holders.  Many of these patents are
 * general enough such that they are unavoidable regardless of implementation
 * design.
 *
 */

#include "config.h"

#include <stdio.h>

#include "mpeg-config.h"
#include "global.h"


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

extern DCTtab _mpeg2DCTtabfirst[],_mpeg2DCTtabnext[],_mpeg2DCTtab0[],_mpeg2DCTtab1[];
extern DCTtab _mpeg2DCTtab2[],_mpeg2DCTtab3[],_mpeg2DCTtab4[],_mpeg2DCTtab5[],_mpeg2DCTtab6[];
extern DCTtab _mpeg2DCTtab0a[],_mpeg2DCTtab1a[];


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

void _mpeg2Decode_MPEG1_Intra_Block(struct mpeg2obj *m, int comp, int dc_dct_pred[])
{
  int val, i, j, sign;
  unsigned int code;
  DCTtab *tab;
  short *bp;

  bp = m->ld->block[comp];

  /* ISO/IEC 11172-2 section 2.4.3.7: Block layer. */
  /* decode DC coefficients */
  if (comp<4)
    bp[0] = (dc_dct_pred[0]+=_mpeg2Get_Luma_DC_dct_diff(m)) << 3;
  else if (comp==4)
    bp[0] = (dc_dct_pred[1]+=_mpeg2Get_Chroma_DC_dct_diff(m)) << 3;
  else
    bp[0] = (dc_dct_pred[2]+=_mpeg2Get_Chroma_DC_dct_diff(m)) << 3;

  if (m->Fault_Flag) return;

  /* D-pictures do not contain AC coefficients */
  if(m->picture_coding_type == D_TYPE)
    return;

  /* decode AC coefficients */
  for (i=1; ; i++)
  {
    code = _mpeg2Show_Bits(m,16);
    if (code>=16384)
      tab = &_mpeg2DCTtabnext[(code>>12)-4];
    else if (code>=1024)
      tab = &_mpeg2DCTtab0[(code>>8)-4];
    else if (code>=512)
      tab = &_mpeg2DCTtab1[(code>>6)-8];
    else if (code>=256)
      tab = &_mpeg2DCTtab2[(code>>4)-16];
    else if (code>=128)
      tab = &_mpeg2DCTtab3[(code>>3)-16];
    else if (code>=64)
      tab = &_mpeg2DCTtab4[(code>>2)-16];
    else if (code>=32)
      tab = &_mpeg2DCTtab5[(code>>1)-16];
    else if (code>=16)
      tab = &_mpeg2DCTtab6[code-16];
    else
    {
      if (!_mpeg2Quiet_Flag)
        printf("invalid Huffman code in Decode_MPEG1_Intra_Block()\n");
      m->Fault_Flag = 1;
      return;
    }

    _mpeg2Flush_Buffer(m, tab->len);

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

    if (tab->run==65) /* escape */
    {
      i+= _mpeg2Get_Bits(m,6);

      val = _mpeg2Get_Bits(m,8);
      if (val==0)
        val = _mpeg2Get_Bits(m,8);
      else if (val==128)
        val = _mpeg2Get_Bits(m,8) - 256;
      else if (val>128)
        val -= 256;

      if((sign = (val<0)))
        val = -val;
    }
    else
    {
      i+= tab->run;
      val = tab->level;
      sign = _mpeg2Get_Bits(m,1);
    }

    if (i>=64)
    {
      if (!_mpeg2Quiet_Flag)
        fprintf(stderr,"DCT coeff index (i) out of bounds (intra)\n");
      m->Fault_Flag = 1;
      return;
    }

    j = _mpeg2scan[ZIG_ZAG][i];
    val = (val*m->ld->quantizer_scale*m->ld->intra_quantizer_matrix[j]) >> 3;

    /* mismatch control ('oddification') */
    if (val!=0) /* should always be true, but it's not guaranteed */
      val = (val-1) | 1; /* equivalent to: if ((val&1)==0) val = val - 1; */

    /* saturation */
    if (!sign)
      bp[j] = (val>2047) ?  2047 :  val; /* positive */
    else
      bp[j] = (val>2048) ? -2048 : -val; /* negative */
  }
}


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

void _mpeg2Decode_MPEG1_Non_Intra_Block(struct mpeg2obj *m, int comp)
{
  int val, i, j, sign;
  unsigned int code;
  DCTtab *tab;
  short *bp;

  bp = m->ld->block[comp];

  /* decode AC coefficients */
  for (i=0; ; i++)
  {
    code = _mpeg2Show_Bits(m,16);
    if (code>=16384)
    {
      if (i==0)
        tab = &_mpeg2DCTtabfirst[(code>>12)-4];
      else
        tab = &_mpeg2DCTtabnext[(code>>12)-4];
    }
    else if (code>=1024)
      tab = &_mpeg2DCTtab0[(code>>8)-4];
    else if (code>=512)
      tab = &_mpeg2DCTtab1[(code>>6)-8];
    else if (code>=256)
      tab = &_mpeg2DCTtab2[(code>>4)-16];
    else if (code>=128)
      tab = &_mpeg2DCTtab3[(code>>3)-16];
    else if (code>=64)
      tab = &_mpeg2DCTtab4[(code>>2)-16];
    else if (code>=32)
      tab = &_mpeg2DCTtab5[(code>>1)-16];
    else if (code>=16)
      tab = &_mpeg2DCTtab6[code-16];
    else
    {
      if (!_mpeg2Quiet_Flag)
        printf("invalid Huffman code in Decode_MPEG1_Non_Intra_Block()\n");
      m->Fault_Flag = 1;
      return;
    }

    _mpeg2Flush_Buffer(m,tab->len);

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

    if (tab->run==65) /* escape */
    {
      i+= _mpeg2Get_Bits(m, 6);

      val = _mpeg2Get_Bits(m, 8);
      if (val==0)
        val = _mpeg2Get_Bits(m, 8);
      else if (val==128)
        val = _mpeg2Get_Bits(m, 8) - 256;
      else if (val>128)
        val -= 256;

      if((sign = (val<0)))
        val = -val;
    }
    else
    {
      i+= tab->run;
      val = tab->level;
      sign = _mpeg2Get_Bits(m, 1);
    }

    if (i>=64)
    {
      if (!_mpeg2Quiet_Flag)
        fprintf(stderr,"DCT coeff index (i) out of bounds (inter)\n");
      m->Fault_Flag = 1;
      return;
    }

    j = _mpeg2scan[ZIG_ZAG][i];
    val = (((val<<1)+1)*m->ld->quantizer_scale*m->ld->non_intra_quantizer_matrix[j]) >> 4;

    /* mismatch control ('oddification') */
    if (val!=0) /* should always be true, but it's not guaranteed */
      val = (val-1) | 1; /* equivalent to: if ((val&1)==0) val = val - 1; */

    /* saturation */
    if (!sign)
      bp[j] = (val>2047) ?  2047 :  val; /* positive */
    else
      bp[j] = (val>2048) ? -2048 : -val; /* negative */
  }
}


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

void _mpeg2Decode_MPEG2_Intra_Block(struct mpeg2obj *m, int comp, int dc_dct_pred[])
{
  int val, i, j, sign, nc, cc, run;
  unsigned int code;
  DCTtab *tab;
  short *bp;
  int *qmat;
  struct layer_data *ld1;

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

  if (m->base.scalable_mode==SC_DP)
    {
      if (m->base.priority_breakpoint<64)
	m->ld = &m->enhan;
      else
	m->ld = &m->base;
    }

  cc = (comp<4) ? 0 : (comp&1)+1;

  qmat = (comp<4 || m->chroma_format==CHROMA420)
         ? ld1->intra_quantizer_matrix
         : ld1->chroma_intra_quantizer_matrix;

  /* ISO/IEC 13818-2 section 7.2.1: decode DC coefficients */
  if (cc==0)
    val = (dc_dct_pred[0]+= _mpeg2Get_Luma_DC_dct_diff(m));
  else if (cc==1)
    val = (dc_dct_pred[1]+= _mpeg2Get_Chroma_DC_dct_diff(m));
  else
    val = (dc_dct_pred[2]+= _mpeg2Get_Chroma_DC_dct_diff(m));

  if (m->Fault_Flag) return;

  bp[0] = val << (3-m->intra_dc_precision);

  nc=0;

#ifdef TRACE
  if (Trace_Flag)
    printf("DCT(%d)i:",comp);
#endif /* TRACE */

  /* decode AC coefficients */
  for (i=1; ; i++)
  {
    code = _mpeg2Show_Bits(m,16);
    if (code>=16384 && !m->intra_vlc_format)
      tab = &_mpeg2DCTtabnext[(code>>12)-4];
    else if (code>=1024)
    {
      if (m->intra_vlc_format)
        tab = &_mpeg2DCTtab0a[(code>>8)-4];
      else
        tab = &_mpeg2DCTtab0[(code>>8)-4];
    }
    else if (code>=512)
    {
      if (m->intra_vlc_format)
        tab = &_mpeg2DCTtab1a[(code>>6)-8];
      else
        tab = &_mpeg2DCTtab1[(code>>6)-8];
    }
    else if (code>=256)
      tab = &_mpeg2DCTtab2[(code>>4)-16];
    else if (code>=128)
      tab = &_mpeg2DCTtab3[(code>>3)-16];
    else if (code>=64)
      tab = &_mpeg2DCTtab4[(code>>2)-16];
    else if (code>=32)
      tab = &_mpeg2DCTtab5[(code>>1)-16];
    else if (code>=16)
      tab = &_mpeg2DCTtab6[code-16];
    else
    {
      if (!_mpeg2Quiet_Flag)
        printf("invalid Huffman code in Decode_MPEG2_Intra_Block()\n");
      m->Fault_Flag = 1;
      return;
    }

    _mpeg2Flush_Buffer(m,tab->len);

#ifdef TRACE
    if (Trace_Flag)
    {
      printf(" (");
      Print_Bits(code,16,tab->len);
    }
#endif /* TRACE */

    if (tab->run==64) /* end_of_block */
    {
#ifdef TRACE
      if (Trace_Flag)
        printf("): EOB\n");
#endif /* TRACE */
      return;
    }

    if (tab->run==65) /* escape */
    {
#ifdef TRACE
      if (Trace_Flag)
      {
        putchar(' ');
        Print_Bits(Show_Bits(6),6,6);
      }
#endif /* TRACE */

      i+= run = _mpeg2Get_Bits(m,6);

#ifdef TRACE
      if (Trace_Flag)
      {
        putchar(' ');
        Print_Bits(Show_Bits(12),12,12);
      }
#endif /* TRACE */

      val = _mpeg2Get_Bits(m,12);
      if ((val&2047)==0)
      {
        if (!_mpeg2Quiet_Flag)
          printf("invalid escape in Decode_MPEG2_Intra_Block()\n");
        m->Fault_Flag = 1;
        return;
      }
      if((sign = (val>=2048)))
        val = 4096 - val;
    }
    else
    {
      i+= run = tab->run;
      val = tab->level;
      sign = _mpeg2Get_Bits(m, 1);

#ifdef TRACE
      if (Trace_Flag)
        printf("%d",sign);
#endif /* TRACE */
    }

    if (i>=64)
    {
      if (!_mpeg2Quiet_Flag)
        fprintf(stderr,"DCT coeff index (i) out of bounds (intra2)\n");
      m->Fault_Flag = 1;
      return;
    }

#ifdef TRACE
    if (Trace_Flag)
      printf("): %d/%d",run,sign ? -val : val);
#endif /* TRACE */

    j = _mpeg2scan[ld1->alternate_scan][i];
    val = (val * ld1->quantizer_scale * qmat[j]) >> 4;
    bp[j] = sign ? -val : val;
    nc++;

    if (m->base.scalable_mode==SC_DP && nc==m->base.priority_breakpoint-63)
      m->ld = &m->enhan;
  }
}


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

void _mpeg2Decode_MPEG2_Non_Intra_Block(struct mpeg2obj *m, int comp)
{
  int val, i, j, sign, nc, run;
  unsigned int code;
  DCTtab *tab;
  short *bp;
  int *qmat;
  struct layer_data *ld1;

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

  if (m->base.scalable_mode==SC_DP)
    {
      if (m->base.priority_breakpoint<64)
	m->ld = &m->enhan;
      else
	m->ld = &m->base;
    }

  qmat = (comp<4 || m->chroma_format==CHROMA420)
         ? ld1->non_intra_quantizer_matrix
         : ld1->chroma_non_intra_quantizer_matrix;

  nc = 0;

#ifdef TRACE
  if (Trace_Flag)
    printf("DCT(%d)n:",comp);
#endif /* TRACE */

  /* decode AC coefficients */
  for (i=0; ; i++)
  {
    code = _mpeg2Show_Bits(m,16);
    if (code>=16384)
    {
      if (i==0)
        tab = &_mpeg2DCTtabfirst[(code>>12)-4];
      else
        tab = &_mpeg2DCTtabnext[(code>>12)-4];
    }
    else if (code>=1024)
      tab = &_mpeg2DCTtab0[(code>>8)-4];
    else if (code>=512)
      tab = &_mpeg2DCTtab1[(code>>6)-8];
    else if (code>=256)
      tab = &_mpeg2DCTtab2[(code>>4)-16];
    else if (code>=128)
      tab = &_mpeg2DCTtab3[(code>>3)-16];
    else if (code>=64)
      tab = &_mpeg2DCTtab4[(code>>2)-16];
    else if (code>=32)
      tab = &_mpeg2DCTtab5[(code>>1)-16];
    else if (code>=16)
      tab = &_mpeg2DCTtab6[code-16];
    else
    {
      if (!_mpeg2Quiet_Flag)
        printf("invalid Huffman code in Decode_MPEG2_Non_Intra_Block()\n");
      m->Fault_Flag = 1;
      return;
    }

    _mpeg2Flush_Buffer(m,tab->len);

#ifdef TRACE
    if (Trace_Flag)
    {
      printf(" (");
      Print_Bits(code,16,tab->len);
    }
#endif /* TRACE */

    if (tab->run==64) /* end_of_block */
    {
#ifdef TRACE
      if (Trace_Flag)
        printf("): EOB\n");
#endif /* TRACE */
      return;
    }

    if (tab->run==65) /* escape */
    {
#ifdef TRACE
      if (Trace_Flag)
      {
        putchar(' ');
        Print_Bits(Show_Bits(6),6,6);
      }
#endif /* TRACE */

      i+= run = _mpeg2Get_Bits(m,6);

#ifdef TRACE
      if (Trace_Flag)
      {
        putchar(' ');
        Print_Bits(Show_Bits(12),12,12);
      }
#endif /* TRACE */

      val = _mpeg2Get_Bits(m,12);
      if ((val&2047)==0)
      {
        if (!_mpeg2Quiet_Flag)
          printf("invalid escape in Decode_MPEG2_Intra_Block()\n");
        m->Fault_Flag = 1;
        return;
      }
      if((sign = (val>=2048)))
        val = 4096 - val;
    }
    else
    {
      i+= run = tab->run;
      val = tab->level;
      sign = _mpeg2Get_Bits(m,1);

#ifdef TRACE
      if (Trace_Flag)
        printf("%d",sign);
#endif /* TRACE */
    }

    if (i>=64)
    {
      if (!_mpeg2Quiet_Flag)
        fprintf(stderr,"DCT coeff index (i) out of bounds (inter2)\n");
      m->Fault_Flag = 1;
      return;
    }

#ifdef TRACE
    if (Trace_Flag)
      printf("): %d/%d",run,sign?-val:val);
#endif /* TRACE */

    j = _mpeg2scan[ld1->alternate_scan][i];
    val = (((val<<1)+1) * ld1->quantizer_scale * qmat[j]) >> 5;
    bp[j] = sign ? -val : val;
    nc++;

    if (m->base.scalable_mode==SC_DP && nc==m->base.priority_breakpoint-63)
      m->ld = &m->enhan;
  }
}
