/*****************************************************************************/
/*                                                            		     */
/* Copyright (c) 1997 ISO/IEC All Rights Reserved                	     */
/*                                                            		     */
/* This software module was originally developed by                          */
/*                                                            		     */
/* Aasmund Sandvand (Telenor / ACTS-MoMuSyS)                    	     */
/*                                                            		     */
/* 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.                                */
/*                                                            		     */
/*****************************************************************************/




/*****************************************************************************
 *                                                                           *
 *      Copyright (C) 1997 LG Semicon Co., Ltd.                              *
 *                    All Rights Reserved.                                   *
 *                                                                           *
 *    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.            *
 *                                                                           *
 *    The authors make NO WARRANTY or representation, either expressed       *
 *    or implied, with respect to this software, its quality, accuracy,      *
 *    merchantability, or fitness for any particular purposes.               *
 *                                                                           *
 *                                                                           *
 *****************************************************************************/


#define CLIP2(x,a,b)    MNINT(((x)>MAX(a,b))? MAX(a,b):MAX(x,MIN(a,b)))
#define LG_THR1		2
#define LG_THR2		6
#ifndef MONO
#define MONO 0
#endif
#ifndef SINT
#define SINT int
#endif
typedef	unsigned char	BYTE;
/* typedef short    int    SInt; */
typedef long    int     Int;

#include <stdio.h>

#define MBSIZE   16
#define BLKSIZE   8




/************************************************************************ 
     If you want to experiment LG deblocking filter 
     	without Samsung Deringing filter,
     Comment out the following define statement.
*************************************************************************/

#define __DO_DERING__

/*****************************************************************************
 *                                                                           *
 *      Copyright (C) Texas Instruments Inc.                                 *
 *                    All Rights Reserved.                                   *
 *                                                                           *
 *    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.            *
 *                                                                           *
 *    The authors make NO WARRANTY or representation, either expressed       *
 *    or implied, with respect to this software, its quality, accuracy,      *
 *    merchantability, or fitness for any particular purposes.               *
 *                                                                           *
 *****************************************************************************/
/*************************************************************
 *                                                           *
 * Module : deringing_filter.c                               *
 *                                                           *
 *          deringing filter of VM7.0 (IIR filter version)   *
 *                                                           *
 * Author : Yuji Itoh @ Texas Instruments Tsukuba R&D Center *
 *          itoh@trdc.ti.com                                 *
 *                                                           *
 * Version(Date): 1.0 (05/09/97)                             *
 *                1.1 (05/19/97)                             *
 *************************************************************/


/* explanation about interface 
void Deringing(SInt *Rec_Y, SInt *Rec_Cb, SInt *Rec_Cr, 
Int width, Int height, int levels, Int *quant, int colors, int bit_depth)

 Rec_*[]:   decoded VOP in 1D array like Rec_Y[v*width+h]
 width:     horizontal VOP size (in pel)
 height:    vertical VOP size (in pel)
 *QP_store: quantizer parameter in 1D array
 colors:    number of colors SL:
*/


void smoothing(SINT *, char [][10], int, int, int, int, int, int, int, int, int);
void Deringing(SINT *, SINT *, SINT *, int, int, int, int *, int, int);


void smoothing(SINT *Pel, char Idx[][10], int width, int height,
	       int v, int h, int v_idx, int h_idx, int diff , int window, int bit_depth)
{
  int i, j, sum, result, shift, weight;

  /*
  if(h<1|| v<1){
    return;
 }
 */

  if (h < window || v >= height-window || v < window || h >= width-window)
    return;

  for(i=-1;i<=1;i++) for(j=-1;j<=1;j++)
    if(Idx[v_idx][h_idx]!=Idx[v_idx+i][h_idx+j])
      return;


  weight =0;
  sum = 0;
  for(i=-window;i<=window;i++) for(j=-window;j<=window;j++){
    shift = 0;
    if(i==0)
      shift++;
    if(j==0)
      shift++;
    weight += 1<<shift;
    sum += Pel[(v+i)*width+h+j]<<shift;
  }

    result = (sum+weight/2)/weight;

  if(abs(Pel[v*width+h]-result)>diff){
    if(Pel[v*width+h]<result)
      result = Pel[v*width+h]+diff;
    else
      result = Pel[v*width+h]-diff;
  }

  if (result > (1<< bit_depth)-1)
  {
    fprintf(stderr,"Bad result in smoothing %d\n",  result);
    result = (1<< bit_depth)-1;
  }
  else if (result < 0)
  {
    fprintf(stderr,"Bad result in smoothing %d\n",  result);
    result = 0;
  }

  Pel[v*width+h] = result;
}

void Deringing(SINT *Rec_Y, SINT *Rec_Cb, SINT *Rec_Cr, int width, int height,
	       int levels, int *quant, int colors, int bit_depth)
{
  unsigned char max_blk, min_blk;
  char index[10][10];
  int thres[2][2], range[2][2], max_range_blk, max_thres_blk;
  int MB_V, MB_H, BLK_V, BLK_H;
  int v_blk, h_blk;
  int max_diff;
  int  v, h, v_pel, h_pel;
  int window =levels;


  max_diff = quant[0];
  
  fprintf(stderr,"Deringing with (Window=%d,Threshold=%d)\n",window, max_diff);


  for( MB_V=0; MB_V<height/MBSIZE; MB_V++ )
        for( MB_H=0; MB_H<width/MBSIZE; MB_H++ ){
/*    window = depth[MB_V*width/MBSIZE+MB_H]/2;
*/

    /* luminance */
    /* threshold determination */
	  max_range_blk = 0;
	  max_thres_blk = 0;
	  for( BLK_V=0; BLK_V<2; BLK_V++ ) 
	    for( BLK_H=0; BLK_H<2; BLK_H++ ){
	      v_blk = MB_V*MBSIZE + BLK_V*BLKSIZE;
	      h_blk = MB_H*MBSIZE + BLK_H*BLKSIZE;
	      
	      max_blk = 0; 
	      min_blk = (1<<bit_depth)-1/*8*/;
     
	      
	      for(v_pel=v_blk;v_pel<v_blk+BLKSIZE;v_pel++) 
		for(h_pel=h_blk;h_pel<h_blk+BLKSIZE;h_pel++){
		  /* initialization for not filtered case */
		  if(Rec_Y[v_pel*width+h_pel]>=max_blk)
		    max_blk = Rec_Y[v_pel*width+h_pel];
		  if(Rec_Y[v_pel*width+h_pel]<=min_blk)
		    min_blk = Rec_Y[v_pel*width+h_pel];
		}
	      
	      thres[BLK_V][BLK_H] = (max_blk+min_blk+1)/2;
	      range[BLK_V][BLK_H] = max_blk-min_blk; 

	      if(range[BLK_V][BLK_H]>=max_range_blk){
		max_range_blk = range[BLK_V][BLK_H];
		max_thres_blk = thres[BLK_V][BLK_H];
	      }
	    }
	  
	  for( BLK_V=0; BLK_V<2; BLK_V++ ) 
	    for( BLK_H=0; BLK_H<2; BLK_H++ ){
	      v_blk = MB_V*MBSIZE + BLK_V*BLKSIZE;
	      h_blk = MB_H*MBSIZE + BLK_H*BLKSIZE;
	      /* threshold rearrangement for flat region adjacent to high energy block */
	      if(range[BLK_V][BLK_H]<32 && max_range_blk>=64){
		thres[BLK_V][BLK_H] = max_thres_blk;
	      }

      /* threshold rearrangement for deblocking (blockiness annoying at DC dominant region) */
	      if(max_range_blk<16){
		range[BLK_V][BLK_H] = 0;
		thres[BLK_V][BLK_H] = 0;
	      }
	      
	      /* index acquisition */
	      for(v=-2;v<BLKSIZE;v++) for(h=-2;h<BLKSIZE;h++){
		if(v_blk+v>=0 && h_blk+h>=0){
		  if(Rec_Y[(v_blk+v)*width+h_blk+h]>=thres[BLK_V][BLK_H])
		    index[v+2][h+2] = 1;
		  else
		    index[v+2][h+2] = 0;
		}
	      }
	      /* adaptive smoothing */
	      for(v_pel=v_blk-1;v_pel<v_blk+BLKSIZE-1;v_pel++){ 
		for(h_pel=h_blk-1;h_pel<h_blk+BLKSIZE-1;h_pel++){
		  smoothing(Rec_Y, index, width, height,
			    v_pel, h_pel, v_pel-v_blk+2, h_pel-h_blk+2, 
			    max_diff, window , bit_depth);
		}
	      }
	      
	    } /* block level (Luminance) */
	  if(colors!=MONO) {
	    /* chrominance */
	    BLK_V = BLK_H = 0;
	    v_blk = MB_V*MBSIZE/2;
	    h_blk = MB_H*MBSIZE/2;
	    
	    /* Cb */
	    max_blk = 0; 
	    min_blk = (1<<bit_depth)-1/*8*/;
	    for(v_pel=v_blk;v_pel<v_blk+BLKSIZE;v_pel++) 
	      for(h_pel=h_blk;h_pel<h_blk+BLKSIZE;h_pel++){
		if(Rec_Cb[v_pel*width/2+h_pel]>=max_blk)
		  max_blk = Rec_Cb[v_pel*width/2+h_pel];
		if(Rec_Cb[v_pel*width/2+h_pel]<=min_blk)
		  min_blk = Rec_Cb[v_pel*width/2+h_pel];
	      }
	    
	    thres[BLK_V][BLK_H] = (max_blk+min_blk+1)/2;
	    range[BLK_V][BLK_H] = max_blk-min_blk; 
	    
	    for(v=-2;v<BLKSIZE;v++) 
	      for(h=-2;h<BLKSIZE;h++){
	      if(v_blk+v>=0 && h_blk+h>=0){
		if(Rec_Cb[(v_blk+v)*width/2+h_blk+h]>=thres[BLK_V][BLK_H])
		  index[v+2][h+2] = 1;
		else
		  index[v+2][h+2] = 0;
	      }
	    }
	    
	    for(v_pel=v_blk-1;v_pel<v_blk+BLKSIZE-1;v_pel++){ 
	      for(h_pel=h_blk-1;h_pel<h_blk+BLKSIZE-1;h_pel++){
		smoothing(Rec_Cb, index, width/2, height/2,
			  v_pel, h_pel, v_pel-v_blk+2, h_pel-h_blk+2, 
			  max_diff, window , bit_depth);
	      }
	    }
	    
	    /* Cr */
	    max_blk = 0; 
	    min_blk = (1<<bit_depth)-1;
	    for(v_pel=v_blk;v_pel<v_blk+BLKSIZE;v_pel++) 
	      for(h_pel=h_blk;h_pel<h_blk+BLKSIZE;h_pel++){
	      if(Rec_Cr[v_pel*width/2+h_pel]>=max_blk)
		max_blk = Rec_Cr[v_pel*width/2+h_pel];
	      if(Rec_Cr[v_pel*width/2+h_pel]<=min_blk)
		min_blk = Rec_Cr[v_pel*width/2+h_pel];
	    }
	    
	    thres[BLK_V][BLK_H] = (max_blk+min_blk+1)/2;
	    range[BLK_V][BLK_H] = max_blk-min_blk; 
	    
	    for(v=-2;v<BLKSIZE;v++) for(h=-2;h<BLKSIZE;h++){
	      if(v_blk+v>=0 && h_blk+h>=0){
		if(Rec_Cr[(v_blk+v)*width/2+h_blk+h]>=thres[BLK_V][BLK_H])
		  index[v+2][h+2] = 1;
		else
		  index[v+2][h+2] = 0;
	      }
	    }
	    
	    for(v_pel=v_blk-1;v_pel<v_blk+BLKSIZE-1;v_pel++){ 
	      for(h_pel=h_blk-1;h_pel<h_blk+BLKSIZE-1;h_pel++){
		smoothing(Rec_Cr, index, width/2, height/2,
			  v_pel, h_pel, v_pel-v_blk+2, h_pel-h_blk+2, 
			  max_diff, window, bit_depth);
	      }
	    }
	  }
	} /* macroblock level */
  
  
}



