/*
 *  This source handles parsing and supervises decoding of the blocks and
 *  passes the decoded data to the idct.
 */


#define NO_SANITY_CHECKS
#include "video.h"
#include "proto.h"
#include "decoders.h"

#define static

/* External declarations. */

extern int zigzag_direct[];


/*
 *--------------------------------------------------------------
 *
 * 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.
 *
 *--------------------------------------------------------------
 */

#define DCT_recon blockPtr->dct_recon
#define DCT_dc_y_past blockPtr->dct_dc_y_past
#define DCT_dc_cr_past blockPtr->dct_dc_cr_past
#define DCT_dc_cb_past blockPtr->dct_dc_cb_past

void ParseReconBlock(int n)
{
	Block *blockPtr = &curVidStream->block;
	int diff, level, run, pos, coeff, qscale;
	short int *reconptr=DCT_recon[0];
	unsigned short *iqmatrixptr;

	if (bufLength < 100) correct_underflow();

	clear64words(reconptr=DCT_recon[0]);

    if (curVidStream->mblock.mb_intra) {

      if (n < 4) {	/* Get the luminance bits. */

      /* Parse and decode size of first coefficient and itself. */
      DecodeDCTDCSizeLum(diff);
	coeff = diff << 3;

	if (n == 0) {
	  if (curVidStream->mblock.mb_address - curVidStream->mblock.past_intra_addr > 1) 
	    coeff += 1024;
	  else coeff += DCT_dc_y_past;
	} else
	  coeff += DCT_dc_y_past;
	DCT_dc_y_past = coeff;

      } else {
	
      /* Parse and decode size of first coefficient and itself. */
      DecodeDCTDCSizeChrom(diff);
	coeff = diff << 3;

	if (n == 4) {
	  if (curVidStream->mblock.mb_address - curVidStream->mblock.past_intra_addr > 1) 
	    coeff += 1024;
	  else
	    coeff += DCT_dc_cr_past;
	  DCT_dc_cr_past = coeff;

	} else {
	  if (curVidStream->mblock.mb_address - curVidStream->mblock.past_intra_addr > 1) 
	    coeff += 1024;
	  else
	    coeff += DCT_dc_cb_past;
	  DCT_dc_cb_past = coeff;
	}
      }

      *reconptr = coeff;
    
      if (curVidStream->picture.code_type != 4) {
	recon_intra(curVidStream->intra_quant_matrix_ptr[curVidStream->slice.quant_scale], reconptr);
      }
      else
	j_rev_dct(reconptr);

    } else { /* not an intra-frame */
      
      qscale = curVidStream->slice.quant_scale;

      DecodeDCTCoeffFirst(run, level);
      pos = zigzag_direct[run];

      if (curVidStream->non_intra_default)
      {
	qscale <<= 4;
	reconptr[pos] = ((short)level * (short)qscale) >> 3;

	if (curVidStream->picture.code_type != 4) {
	  recon_nonintra(qscale, run, reconptr);
	}
	else
	  j_rev_dct(reconptr);

      } else {
	iqmatrixptr = curVidStream->non_intra_quant_matrix_ptr[qscale];

	reconptr[pos] = ((short)level * iqmatrixptr[run]) >> 3;

	if (curVidStream->picture.code_type != 4) {
	  recon_non2intra(run, iqmatrixptr, reconptr);
	}
	else
	  j_rev_dct(reconptr); // eventually, the flush(2) must be applied here, too ? hmmm

      }
    }
}
	
#undef DCT_recon 
#undef DCT_dc_y_past 
#undef DCT_dc_cr_past 
#undef DCT_dc_cb_past 



/*
 *--------------------------------------------------------------
 *
 * ParseAwayBlock --
 *
 *	Parses off block values, throwing them away.
 *      Used with grayscale dithering.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *      None.
 *
 * To do:
 *      Move to sutils.s !!
 *
 *--------------------------------------------------------------
 */

void ParseAwayBlock(int n)
{
  unsigned int diff, run;
  int level;

  if (bufLength < 100) correct_underflow();

  if (curVidStream->mblock.mb_intra) {

    /* If the block is a luminance block... */

    if (n < 4) {
      /* Parse and decode size of first coefficient and itself. */
      DecodeDCTDCSizeLum(diff);
    }
    /* Otherwise, block is chrominance block... */
    else {
      /* Parse and decode size of first coefficient and itself. */
      DecodeDCTDCSizeChrom(diff);
    }
  }
  /* Otherwise, block is not intracoded... */
  else {

    /* Decode and set first coefficient. */
    DecodeDCTCoeffFirst(run, level);
  }

  /* If picture is not D type (i.e. I, P, or B)... */

  if (curVidStream->picture.code_type != 4) {

    /* While end of macroblock has not been reached... */

    do {
      DecodeDCTCoeffNext(run, level);	/* Get the dct_coeff_next */
    } while (run != END_OF_BLOCK);

    /* End_of_block */
    flush_bits(2);

  }
}