/* $Id: decQM.c,v 1.21 1998/03/06 14:36:57 hatrack Exp $ */
/****************************************************************************/
/*   MPEG4 Visual Texture Coding (VTC) Mode Software                        */
/*                                                                          */
/*   This software was developed by                                         */
/*   Sarnoff Coporation                   and    Texas Instruments          */
/*   Iraj Sodagar   (iraj@sarnoff.com)           Jie Liang (liang@ti.com)   */
/*   Hung-Ju Lee    (hjlee@sarnoff.com)                                     */
/*   Paul Hatrack   (hatrack@sarnoff.com)                                   */
/*   Shipeng Li     (shipeng@sarnoff.com)                                   */
/*   Bing-Bing Chai (bchai@sarnoff.com)                                     */
/*                                                                          */
/* In the course of development of the MPEG-4 standard. This software       */
/* module is an implementation of a part of one or more MPEG-4 tools as     */
/* specified by the MPEG-4 standard.                                        */
/*                                                                          */
/* The copyright of this software belongs to ISO/IEC. ISO/IEC gives use     */
/* of the MPEG-4 standard free license to use this  software module or      */
/* modifications thereof for hardware or software products claiming         */
/* conformance to the MPEG-4 standard.                                      */
/*                                                                          */
/* Those intending to use this software module in hardware or software      */
/* products are advised that use may infringe existing  patents. The        */
/* original developers of this software module and their companies, the     */
/* subsequent editors and their companies, and ISO/IEC have no liability    */
/* and ISO/IEC have no liability for use of this software module or         */
/* modification thereof in an implementation.                               */
/*                                                                          */
/* Permission is granted to MPEG memebers to use, copy, modify,             */
/* and distribute the software modules ( or portions thereof )              */
/* for standardization activity within ISO/IEC JTC1/SC29/WG11.              */
/*                                                                          */
/* Copyright (C) 1998  Sarnoff Coporation and Texas Instruments             */ 
/****************************************************************************/

/************************************************************/
/*     Sarnoff Very Low Bit Rate Still Image Coder          */
/*     Copyright 1995, 1996, 1997, 1998 Sarnoff Corporation */
/************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dataStruct.h"
#include "globals.h"
#include "states.h"
#include "quant.h"
#include "QMUtils.h"
#include "decQM.h"
#include "errorHandler.h"


/* 
   Function Name
   -------------
   static Void iQuantizeCoeff(Int x, Int y)

   Arguments 
   ---------
   Int x, Int y - Index of wavelet coefficient (row, col) to quantize.

   Description
   -----------
   Quantize the coefficent at (x,y). Also get maximum number of residual 
   levels for arithmetic coding in SE module.

   coeffinfo Updates:
     1. quantized_value
     2. qState

   Functions Called
   ----------------
   none

   Return Value
   ------------
   none

   Source File
   -----------
   decQM.c
*/

static Void iQuantizeCoeff(Int x, Int y, Int c)
{
  /* assign new quantization value - update quant state */
  COEFF_RECVAL(x,y,c) = 
    invQuantSingleStage(COEFF_VAL(x,y,c), USER_Q(c), &COEFF_QSTATE(x,y,c),
			&prevQList2[c][coordToSpatialLev(x,y,c)], 0);
}

/* 
   Function Name
   -------------
   static Void iQuantizeCoeffs(Int x, Int y)

   Arguments 
   ---------
   Int x, Int y - Index of wavelet coefficient (row, col) to mark.

   Description
   -----------
   Inverse quantize coefficient at (x,y) and all of it's descendents.
   Uses recursion to accomplish this.

   Functions Called
   ----------------
   findChild
   iQuantizeCoeffs (recursive call)
   iQuantizeCoeff

   Return Value
   ------------
   none.

   Source File
   -----------
   decQM.c
*/

static Void iQuantizeCoeffs(Int x, Int y, Int c)
{
  Int i;
  Int xc[4], yc[4]; /* coords of children */
  Int nc; /* number of children */

  /* Are we at a leaf? */
  if ((nc = findChild(x, y, xc, yc, c)) > 0)
  {
    /* No - mark descendents in all branches */
    for (i = 0; i < nc; ++i)
      iQuantizeCoeffs(xc[i], yc[i], c);
  }

  /* inverse quantize the current coefficent */
  iQuantizeCoeff(x,y, c);    
}


/* 
   Function Name
   -------------
   Int decIQuantizeDC()

   Arguments 
   ---------
   none

   Description
   -----------
   Inverse quantize all DC coefficients.

   Functions Called
   ----------------
   invQuantSingleStage

   Return Value
   ------------
   0, if everything's ok. <0, if error.

   Source File
   -----------
   decQM.c
*/

Int decIQuantizeDC(Int c)
{
  Int err;
  Int x, y;
 
  err=0;

  /* loop through DC */
  noteDetail("Inverse Quantizing DC band....");
  for (x = 0; x < mzte_codec.dcWidth; ++x)
    for (y = 0; y < mzte_codec.dcHeight; ++y)
    {
       /* assign new quantization value */

#ifdef _NEW_DC_QUANT_
      {
	Int prevQ;
	
	prevQ=0;

	COEFF_RECVAL(x,y,c) = invQuantSingleStage(COEFF_VAL(x,y,c),
						  mzte_codec.Qdc[c], 
						  &COEFF_QSTATE(x,y,c),
						  &prevQ, 0);
      }
#else
      COEFF_RECVAL(x,y,c) = COEFF_VAL(x,y,c) * mzte_codec.Qdc[c];
#endif
    }

  noteDetail("Completed inverse Quantizing DC bands.");

  return err;
}

/* 
   Function Name
   -------------
   Int decIQuantizeAC()

   Arguments 
   ---------
   none

   Description
   -----------
   Inverse quantize all AC coefficients.

   Functions Called
   ----------------
   iQuantizeCoeffs

   Return Value
   ------------
   0, if everything's ok. <0, if error.

   Source File
   -----------
   decQM.c
*/

Int decIQuantizeAC(Int c)
{
  Int err;
  Int x, y;
  Int nc;
  Int xc[3], yc[3];

  err=0;

  /* loop through DC */
  noteDetail("Inverse quantizing AC bands....");
  for (x = 0; x < mzte_codec.dcWidth; ++x)
    for (y = 0; y < mzte_codec.dcHeight; ++y)
    {
      if ((nc = findChild(x, y, xc, yc,c)) != 3)
      {
	noteError("DC band coefficient has %d children instead of 3.", nc);
	exit(-1);
      }
	
      iQuantizeCoeffs(xc[0], yc[0],c);
      iQuantizeCoeffs(xc[1], yc[1],c);
      iQuantizeCoeffs(xc[2], yc[2],c);
    }

  noteDetail("Completed inverse quantizing of AC bands.");

  return err;
}


/* 
   Function Name
   -------------
   Int decUpdateStateAC()

   Arguments 
   ---------
   none

   Description
   -----------
   Update state and prob model of all AC coefficients.

   Functions Called
   ----------------
   updateCoeffStateAndModel

   Return Value
   ------------
   0, if everything's ok. <0, if error.

   Source File
   -----------
   decQM.c
*/

Int decUpdateStateAC(Int c)
{
  Int err;
  Int x, y;
  Int nc;
  Int xc[3], yc[3];

  err=0;

  if (!ALL_ZERO(c))
  {
    /* loop through DC */
    noteDetail("Updating state of AC bands....");
    for (x = 0; x < mzte_codec.dcWidth; ++x)
      for (y = 0; y < mzte_codec.dcHeight; ++y)
      {
	if ((nc = findChild(x, y, xc, yc,c)) != 3)
	{
	  noteError("DC band coefficient has %d children instead of 3.", nc);
	  exit(-1);
	}
	
	updateCoeffAndDescState(xc[0], yc[0], c);
	updateCoeffAndDescState(xc[1], yc[1], c);
	updateCoeffAndDescState(xc[2], yc[2], c);
      }

    noteDetail("Completed updating state of AC bands.");
  }

  return err;
}


/* 
   Function Name
   -------------
   static Int markCoeffs(Int x, Int y, Int c)

   Arguments 
   ---------
   Int x, Int y - Index of wavelet coefficient (row, col) to mark.
   Int c - Color component.

   Description
   -----------
   Mark the coefficient at (x,y) and all of it's descendents.
   Uses recursion to accomplish this. This is used at decoder for all zero
   condition only to keep types in sync with encoder.

   Functions Called
   ----------------
   findChild
   markCoeffs (recursive call)
   markCoeff

   Return Value
   ------------
   Returns 1, if there are non-zero descendents, and 0, if not.

   Source File
   -----------
   decQM.c
*/

static Int markCoeffs(Int x, Int y, Int c)
{
  Int i;
  UChar valDes, valDesOneBranch; /* 'some non-zero descendent' 
					    flags */
  UChar isLeaf; /* is (x,y) a leaf (no children) */
  Int xc[4], yc[4]; /* coords of children */
  Int nc; /* number of children */

  valDes = 0;

  /* Are we at a leaf? */
  if ((nc = findChild(x, y, xc, yc, c)) == 0)
    isLeaf = 1;
  else
  {
    isLeaf = 0;
    /* No - mark descendents in all branches */
    for (i = 0; i < nc; ++i)
    {
      valDesOneBranch = markCoeffs(xc[i], yc[i], c);
      valDes = valDes || valDesOneBranch;
    }
  }
  
  /* Updates type in coeffTable */
  markCoeff(x, y, valDes, c);

  /* return zero status of current coeff and all descendents */
  return COEFF_VAL(x,y,c) || valDes;
}



/* 
   Function Name
   -------------
   Int decMarkAC(Int c)

   Arguments 
   ---------
   Int c - Color component.

   Description
   -----------
   Mark all AC coefficients in current spatial layer for all zero condition.
   This is used at decoder for all zero condition only to keep types in sync
   with encoder.
   
   Functions Called
   ----------------
   markCoeffs

   Return Value
   ------------
   0, if everything's ok. <0, if error.

   Source File
   -----------
   decQM.c
*/

Int decMarkAC(Int c)
{
  Int err;
  Int x, y;
  Int nc;
  Int xc[3], yc[3];

  err=0;

 /* loop through DC */
  noteDetail("Marking AC bands for all zero condition....");
  for (x = 0; x < mzte_codec.dcWidth; ++x)
    for (y = 0; y < mzte_codec.dcHeight; ++y)
    {
      if ((nc = findChild(x, y, xc, yc, c)) != 3)
	errorHandler("DC band coefficient has %d children instead of 3.", nc);
	
      markCoeffs(xc[0], yc[0], c);
      markCoeffs(xc[1], yc[1], c);
      markCoeffs(xc[2], yc[2], c);
    }

  noteDetail("Completed marking of AC bands for all zero condition.");

  return err;
}
