/*****************************************************************************
 *
 * This software module was originally developed by
 *
 *   Robert Danielsen (Telenor / ACTS-MoMuSyS)
 *
 * and edited by
 * 
 *   Cor Quist (KPN / ACTS-MoMuSyS)
 *   Fernando Jaureguizar (UPM / ACTS-MoMuSyS)
 *   Karl Lillevold (Telenor / ACTS-MoMuSyS)
 *   Michael Frater (UNSW)
 *
 * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
 * This software module is an implementation of a part of one or more MPEG-4
 * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
 * 14496-2) standard.
 *
 * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
 * license to this software module or modifications thereof for use in hardware
 * or software products claiming conformance to the MPEG-4 Video (ISO/IEC
 * 14496-2) standard.
 *
 * Those intending to use this software module in hardware or software products
 * are advised that its use may infringe existing patents. The original
 * developer of this software module and his/her company, the subsequent
 * editors and their companies, and ISO/IEC have no liability for use of this
 * software module or modifications thereof in an implementation. Copyright is
 * not released for non MPEG-4 Video (ISO/IEC 14496-2) Standard conforming
 * products.
 *
 * ACTS-MoMuSys partners retain full right to use the code for his/her own
 * purpose, assign or donate the code to a third party and to inhibit third
 * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) Standard
 * conforming products. This copyright notice must be included in all copies or
 * derivative works.
 *
 * Copyright (c) 1996
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File: text_util.c
 *
 * Author: Telenor, TMN
 * Created: 
 *                                                                         
 * Description: texture encoding  
 *
 * Notes:  
 *
 * Modified: Robert Danielsen, Feb 14, 1996
 *  Cor Quist -- 26-Feb-96
 *  Cor Quist -- 11-Apr-96
 *  Cor Quist -- 16 April 96
 *   21.04.96 Robert Danielsen: Reformatted. New headers.
 *   10.09.96 Robert Danielsen: Added BlockIDCT()
 *   18.09.96 Fernando Jaureguizar: Now new B_TRANSP and MB_TRANSP defines
 *      are in mot_util.h. Their calls are modified.
 *   28.11.96 Ferran Marques: modifications to allow both block-based and 
 *      macroblock-based subsampling of the alpha plane (22.10.96)
 *    16.06.97 Angel Pacheco: unified the TRANSPARENT modes.
 *   03.01.98 Michael Frater: support for non-8-bit video
 *
 ***********************************************************HeaderEnd*********/

/************************    INCLUDE FILES    ********************************/
#include "momusys.h"
#include "text_util.h"	/* Added 19-JUN-1996, IC */
#include "mot_est.h"
#include "mot_util.h"
#define	M_PI		3.14159265358979323846


 

/***********************************************************CommentBegin******
 *
 * -- MB_clip -- clips recontructed data in macroblock to 0-255
 *
 * Author :  
 * 
 *
 * Created :  
 * 
 *
 * Purpose :  
 * clips recontructed data in macroblock to 0-255
 * 
 * Arguments in :  
 * 
 *
 * Arguments in/out : 
 * Macroblock* mblock : pointer to macroblock to be clipped
 *
 * Arguments out : 
 * 
 *
 * Return values : 
 * 
 *
 * Side effects : 
 * 
 *
 * Description : 
 * 
 *
 * See also :
 * 
 *
 * Modified :  
 * 
 *
 ***********************************************************CommentEnd********/

Void 
MB_clip (Macroblock* mblock, Int maxval)
{
  Int m,n;

  for (n = 0; n < 16; n++) {
   
    for (m = 0; m < 16; m++) {
     
      mblock->lum[n][m] = MIN(maxval,MAX(0, mblock->lum[n][m]));
    }
  }
   
  for (n = 0; n < 8; n++) {
   
    for (m = 0; m < 8; m++) {
     
      mblock->Cr[n][m] = MIN(maxval,MAX(0, mblock->Cr[n][m]));
      mblock->Cb[n][m] = MIN(maxval,MAX(0, mblock->Cb[n][m]));
    }
  }
}
 
/***********************************************************CommentBegin******
 *
 * -- MB_clear -- Fills one macrocblock with zeros
 *
 * Author :		
 *	Karl.Lillevold@nta.no
 *
 * Created :		
 *	29-Aug-94
 *
 * Purpose :		
 *	To fill one macrocblock with zeros.
 * 
 * Arguments in : 	
 *	
 *
 * Arguments in/out :	
 *	Macroblock     *mblock : macroblock (cleared)
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	28-Nov-95 Robert Inge Danielsen - C++-ifying the code. Is now a
 *					  member function.
 *
 *
 ***********************************************************CommentEnd********/

Void
MB_clear (Macroblock * mblock)

{
  Int                 n;
  Int                 m;

  for (n = 0; n < MB_SIZE; n++)
    for (m = 0; m < MB_SIZE; m++)
      mblock->lum[n][m] = 0;
  for (n = 0; n < (MB_SIZE >> 1); n++)
    for (m = 0; m < (MB_SIZE >> 1); m++)
      {
	mblock->Cr[n][m] = 0;
	mblock->Cb[n][m] = 0;
      }

}				/* MB_clear */


/***********************************************************CommentBegin******
 *
 * -- BlockIDCT -- 8x8 block Inverse DCT
 *
 * Author : Minhua Zhou		
 *
 * Created :		
 *	21.05.97
 *
 * Purpose :		
 *	8x8 block Inverse DCT
 * 
 * Arguments in : 	
 *	Int *coeff_in	transform coefficients
 *
 * Arguments in/out :	
 *
 * Arguments out :	
 *	Int block_out[][8]	inverse transformed block data
 *
 * Return values :	
 *	Void
 *
 * Side effects :	
 *
 * Description :	
 *
 * See also :
 *
 * Modified :		
 *
 ***********************************************************CommentEnd********/


Void BlockIDCT(Int *coeff_in,Int block_out[][8], Int maxval)
{
  Int                j1, i, j;
  Double tmp[8], tmp1[8];
  Double e, f, g, h,coeff[8][8],block[8][8];
  static Double c0,c1,c2,c3,c4,c5,c6,c7;
  Int v;

  for (i=0;i<8;i++)
    for (j=0;j<8;j++)
      coeff[i][j] = (Double)coeff_in[i*8+j];   

    c0=0.7071068;c1=0.4903926;c2=0.4619398;c3=0.4157348;c4=0.3535534;
    c5=0.2777851;c6=0.1913417;c7=0.0975452; 
  
  /* Horizontal */

  /* Descan coefficients first */

  for (i = 0; i < 8; i++) {
    for (j = 0; j < 8; j++) {
      tmp[j] =coeff[i][j]; 
    }
    e = tmp[1] * c7 - tmp[7] * c1;
    h = tmp[7] * c7 + tmp[1] * c1;
    f = tmp[5] * c3 - tmp[3] * c5;
    g = tmp[3] * c3 + tmp[5] * c5;

    tmp1[0] = (tmp[0] + tmp[4]) * c4;
    tmp1[1] = (tmp[0] - tmp[4]) * c4;
    tmp1[2] = tmp[2] * c6 - tmp[6] * c2;
    tmp1[3] = tmp[6] * c6 + tmp[2] * c2;
    tmp[4] = e + f;
    tmp1[5] = e - f;
    tmp1[6] = h - g;
    tmp[7] = h + g;
    
    tmp[5] = (tmp1[6] - tmp1[5]) * c0;
    tmp[6] = (tmp1[6] + tmp1[5]) * c0;
    tmp[0] = tmp1[0] + tmp1[3];
    tmp[1] = tmp1[1] + tmp1[2];
    tmp[2] = tmp1[1] - tmp1[2];
    tmp[3] = tmp1[0] - tmp1[3];

    for (j = 0; j < 4; j++) {
      j1 = 7 - j;
      block[i][j] = tmp[j] + tmp[j1];
      block[i][j1] = tmp[j] - tmp[j1];
    }
  }

  /* Vertical */
  
  for (i = 0; i < 8; i++) {
    for (j = 0; j < 8; j++) {
      tmp[j] = block[j][i];
    }
    e = tmp[1] * c7 - tmp[7] * c1;
    h = tmp[7] * c7 + tmp[1] * c1;
    f = tmp[5] * c3 - tmp[3] * c5;
    g = tmp[3] * c3 + tmp[5] * c5;

    tmp1[0] = (tmp[0] + tmp[4]) * c4;
    tmp1[1] = (tmp[0] - tmp[4]) * c4;
    tmp1[2] = tmp[2] * c6 - tmp[6] * c2;
    tmp1[3] = tmp[6] * c6 + tmp[2] * c2;
    tmp[4] = e + f;
    tmp1[5] = e - f;
    tmp1[6] = h - g;
    tmp[7] = h + g;

    tmp[5] = (tmp1[6] - tmp1[5]) * c0;
    tmp[6] = (tmp1[6] + tmp1[5]) * c0;
    tmp[0] = tmp1[0] + tmp1[3];
    tmp[1] = tmp1[1] + tmp1[2];
    tmp[2] = tmp1[1] - tmp1[2];
    tmp[3] = tmp1[0] - tmp1[3];

    for (j = 0; j < 4; j++) {
      j1 = 7 - j;
      block[j][i] = tmp[j] + tmp[j1];
      block[j1][i] = tmp[j] - tmp[j1];
    }
  }    
       for (i=0;i<8;i++)
          for(j=0;j<8;j++) {
  	    v = (Int) floor (block[i][j] + 0.5);
	    block_out[i][j] = (v<-maxval-1) ? -maxval-1 : ((v>maxval) ? maxval : v);
          }
 

 }


/***********************************************************CommentBegin******
 *
 * -- GetTranspPattern -- Find pattern for transparent blocks in a MB
 *
 * Author : 
 *	Robert Danielsen, Telenor R&D
 *
 * Created :		
 *	07.09.96
 *
 * Purpose :		
 *	Find pattern for transparent blocks in a MB
 * 
 * Arguments in : 	
 * 	Int h
 * 	Int v
 *
 * Arguments in/out :	
 *	SInt *alpha_sub
 *
 * Arguments out :	
 *	Int pattern[]
 *
 * Return values :	
 *	
 * Side effects :	
 *
 * Description :	
 *
 * See also :
 *
 * Modified :		
 *
 ***********************************************************CommentEnd********/

Void
GetTranspPattern (SInt *alpha_sub, Int vop_width, Int vop_height,
		  Int h, Int v, Int pattern[])
{
  Int i, j, br_width, br_height;

  br_width = vop_width;
  br_height = vop_height;
  
  for (j = 0; j < 2; j++)
    for (i = 0; i < 2; i++)
      if (B_TRANSP (alpha_sub, br_width/B_SIZE, h, v, i, j, MBM_TRANSPARENT))
	pattern[j*2+i] = 1;
      else
	pattern[j*2+i] = 0;
}  





/***********************************************************CommentBegin******
 *
 * -- FillMB_decisions -- Fill the MB_decisions in case in INTRA Vop encoding
 *
 * Author : Cor Quist (KPN)		
 *	
 *
 * Created :		
 *	
 *
 * Purpose :		
 *	Fill the MB_decisions in case in INTRA Vop encoding.
 * 
 * Arguments in : 	
 *	SInt *alpha (alpha plane)
 * 	Int vop_width
 * 	Int vop_height
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Image *MB_decisions
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	Only implemented for restricted use of MB_decisions.
 *      MB_decisions is '0' or '2' where '2' means transparent MB.
 *
 * See also :
 *	
 *
 * Modified :		
 *	03.09.96 Cor Quist: Added alpha_decisions as output
 *
 ***********************************************************CommentEnd********/

Void 
FillMB_decisions(SInt *alpha, Int vop_width, Int vop_height,
                                   Image *MB_decisions, Image *alpha_decisions)
{
  Int br_width, br_height; /* size of bounding box */
  Int h,v;
  SInt *alpha_sub; 
  SInt *ptr;
  Int  block_based = 1;
          
  br_width = vop_width;
  br_height = vop_height;

  ptr = (SInt *) GetImageData(MB_decisions);
  alpha_sub = (SInt *) GetImageData(alpha_decisions); 
     
  subsamp_alpha(alpha, br_width, br_height, block_based, alpha_sub);
  /* alpha_sub is used by the macro MB_TRANSP */
     
  for ( v = 0; v < vop_height/MB_SIZE; v++)
    { 
      for ( h = 0; h < vop_width/MB_SIZE; h++)
	{
     	  if ( MB_TRANSP(alpha_sub,br_width/B_SIZE,h,v,MBM_TRANSPARENT) )
	    {
	      *ptr = 2; /* transparent MB*/
	    }
	  else
	    {
	      *ptr =0; /* intra MB */
	    }
	  ptr++;
	}
    }
}

/***********************************************************CommentBegin******
 *
 * -- IntraDCSwitch_decisions -- 
 *
 * Author : Minhua Zhou		
 *	
 *
 * Created : 04.08.1997		
 *	
 *
 * Purpose :		
 *	decide whether to use inter AC table to encode DC
 * 
 * Arguments in : 	
 *	Int Mode
 * 	Int intra_dc_vlc_thr
 * 	Int Qp
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
  *
 * Return values :	
 *	 
 *
 * Side effects :	
 *	
 *
 * Description :	
  *
 * See also :
 *	
 *
 * Modified :		
  *
 ***********************************************************CommentEnd********/

Int IntraDCSwitch_Decision(Int Mode,Int intra_dc_vlc_thr,Int Qp) {
   Int switched =0;
   if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q) {
        if (intra_dc_vlc_thr==0) 
          switched=0;
         else if (intra_dc_vlc_thr==7) 
           switched=1;
          else if (Qp>=intra_dc_vlc_thr*2+11)
              switched=1;
    }
 
   return switched;
}

