/*****************************************************************************
 *
 * This software module was originally developed by
 *
 *   Aasmund Sandvand (Telenor / ACTS-MoMuSyS)
 *   Yuji Itoh(itoh@trdc.ti.com) @ Texas Instruments Tsukuba R&D Ctr 
 *   Kinya Oosa(oosa@lsi.nsc.co.jp) @ Nippon Steel Corporation   
 *   
 *
 * 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) 1997
 *
 *****************************************************************************/

#include <stdio.h>
#include "momusys.h"
#include "post_filter.h"

#define LG_THR1		2
#define LG_THR2		6
#define UPDATE_MAXMIN(p,max,min) if ((p) > max) max=(p); else if ((p) < min) min = (p);
#define INDEX(x,thr) (((x)>=thr)?1:0)
#define MBSIZE   16
#define BLKSIZE   8
#define DEBLOCK 1
#define DERING  2
#define COMBINED (DEBLOCK|DERING)

Void PostFilter(Vop *filter_vop, Int filter_type)
/* filter_type shall be set by caller */

{
  SInt *data;
  SInt *QP_store;
  Int pels, lines;
  Int combined_with_deblock_filter;

  QP_store = (SInt *) GetImageData(GetVopQP(filter_vop));
  pels  = (Int) GetImageSizeX(GetVopY(filter_vop));
  lines = (Int) GetImageSizeY(GetVopY(filter_vop));
  combined_with_deblock_filter = filter_type & DEBLOCK;

  /* Luma */
  data = (SInt *) GetImageData(GetVopY(filter_vop));
  if(filter_type & DEBLOCK){
    HorizDeblockFilter(data, pels, lines, QP_store, 0);
    VertDeblockFilter (data, pels, lines, QP_store, 0);
  }
  if(filter_type & DERING)
    Deringing_Luma(data, pels, lines, QP_store, combined_with_deblock_filter);
  
  /* Chroma */
  data = (SInt *) GetImageData(GetVopU(filter_vop));
  if(filter_type & DEBLOCK){
    HorizDeblockFilter(data,  pels/2, lines/2, QP_store, 1);
    VertDeblockFilter (data,  pels/2, lines/2, QP_store, 1);
  }
  if(filter_type & DERING)
    Deringing_Chroma(data, pels/2, lines/2, QP_store, combined_with_deblock_filter);
  
  data = (SInt *) GetImageData(GetVopV(filter_vop));
  if(filter_type & DEBLOCK){
    HorizDeblockFilter(data,  pels/2, lines/2, QP_store, 1);
    VertDeblockFilter (data,  pels/2, lines/2, QP_store, 1);
  }
  if(filter_type & DERING)
    Deringing_Chroma(data, pels/2, lines/2, QP_store, combined_with_deblock_filter);
  
  return;
}


/*******************************************************************************
 *                                                                             *
 *      Copyright (C) 1997 LG Semicon Co., Ltd.                                *
 *                    All Rights Reserved.                                     *
 *                                                                             *
 *  LGS is pleased that the standardisation in relation to MPEG-4 has          *
 *  reached Committee Draft level as document ISO/IEC JTC1/SC29/WG11 N1902.    *
 *  LGS hereby declares that it is prepared to license its patents, both       *
 *  granted and pending, which are necessary to manufacture, use, and sell     *
 *  implementations of the proposed MPEG-4 Systems, Visual, Audio, Reference   *
 *  Software and DMIF standards or combinations thereof.                       *
 *  LGS  hereby also declares that it is aware of the rules governing          *
 *  inclusion of patented items in international standards, as described by    *
 *  Section 5.7, part 2 of the ISO/IEC Directives, and in particular that it   *
 *  is willing to grant a license to an unlimited number of applicants         *
 *  throughout the world under reasonable terms and conditions that are        *
 *  demonstrably free of any unfair competition.                               *
 *  This statement is intended to apply to the proposed MPEG-4 standard Visual.*
 *  						                                                   *
 *******************************************************************************/

Void HorizDeblockFilter
  (SInt *rec, Int width, Int height, SInt *QP_store, Int chr)
{
  Int i,j;
  Int br, bc, QP;

  Int p1, p2, eq_cnt, max, min;
  Int v[9];
  Int a3_0, a3_1, a3_2, A3_0, d;
  Int psum;
  SInt *ptr;
  Int w1, w2, w3, w4, w5;

  w1 = width;
  w2 = 2*width;
  w3 = 3*width;
  w4 = 4*width;
  w5 = 5*width;

  for (j = 8; j < height; j += 8) 
  for (i = 0; i < width; i++) 
  {
    br = j >> 3;
    bc = i >> 3;

    if (!chr) QP = QP_store[(br>>1)*(width>>4)+(bc>>1)];
    else      QP = QP_store[(br)*(width>>3)+bc];

    ptr = (rec+i+j*width);

    /* mode decision */
    eq_cnt = 	(ABS(*(ptr-w4) - *(ptr-w5)) <= LG_THR1)
	+	(ABS(*(ptr-w3) - *(ptr-w4)) <= LG_THR1)
	+	(ABS(*(ptr-w2) - *(ptr-w3)) <= LG_THR1)
	+	(ABS(*(ptr-w1) - *(ptr-w2)) <= LG_THR1)
	+	(ABS(*(ptr   ) - *(ptr-w1)) <= LG_THR1)
	+	(ABS(*(ptr+w1) - *(ptr   )) <= LG_THR1)
	+	(ABS(*(ptr+w2) - *(ptr+w1)) <= LG_THR1)
	+	(ABS(*(ptr+w3) - *(ptr+w2)) <= LG_THR1)
	+	(ABS(*(ptr+w4) - *(ptr+w3)) <= LG_THR1);

    if (eq_cnt >= LG_THR2) 	/* DC offset mode */
    { 
      max = min = *(ptr-w4);
      UPDATE_MAXMIN(*(ptr-w3), max, min);
      UPDATE_MAXMIN(*(ptr-w2), max, min);
      UPDATE_MAXMIN(*(ptr-w1), max, min);
      UPDATE_MAXMIN(*(ptr   ), max, min);
      UPDATE_MAXMIN(*(ptr+w1), max, min);
      UPDATE_MAXMIN(*(ptr+w2), max, min);
      UPDATE_MAXMIN(*(ptr+w3), max, min);

      if (ABS(max-min) < (QP<<1)) 
      {
	p1 = (ABS(*(ptr-w4) - *(ptr-w5)) < QP ) ?  *(ptr-w5) : *(ptr-w4);
	p2 = (ABS(*(ptr+w3) - *(ptr+w4)) < QP ) ?  *(ptr+w4) : *(ptr+w3);

	/* make data */
	v[1] = *(ptr-w4);
	v[2] = *(ptr-w3);
	v[3] = *(ptr-w2);
	v[4] = *(ptr-w1);
	v[5] = *(ptr);
	v[6] = *(ptr+w1);
	v[7] = *(ptr+w2);
	v[8] = *(ptr+w3);
	
	/* low pass filtering (LPF9: 1 1 2 2 4 2 2 1 1) */
	psum = p1 + p1 + p1 + v[1] + v[2] + v[3] + v[4] + 4;
	*(ptr-w4) = (((psum + v[1]) << 1) - (v[4] - v[5])) >> 4;
	psum += v[5] - p1; 
	*(ptr-w3) = (((psum + v[2]) << 1) - (v[5] - v[6])) >> 4;
	psum += v[6] - p1; 
	*(ptr-w2) = (((psum + v[3]) << 1) - (v[6] - v[7])) >> 4;
	psum += v[7] - p1; 
	*(ptr-w1) = (((psum + v[4]) << 1) + p1 - v[1] - (v[7] - v[8])) >> 4;

	psum += v[8] - v[1]; 
	*(ptr) = (((psum + v[5]) << 1) + (v[1] - v[2]) - v[8] + p2) >> 4;
	psum += p2 - v[2]; 
	*(ptr+w1) = (((psum + v[6]) << 1) + (v[2] - v[3])) >> 4;
	psum += p2 - v[3]; 
	*(ptr+w2) = (((psum + v[7]) << 1) + (v[3] - v[4])) >> 4;
	psum += p2 - v[4]; 
	*(ptr+w3) = (((psum + v[8]) << 1) + (v[4] - v[5])) >> 4;
      }
    } 
    else  	/* Default mode */
    {
      a3_0  = *ptr - *(ptr-w1);
      a3_0 += ((*(ptr-w2) - *(ptr+w1))<<1) + (a3_0<<2);

      if (ABS(a3_0) < (QP<<3)) 
      {
	a3_1  = *(ptr-w2) - *(ptr-w3);
	a3_1 += ((*(ptr-w4) - *(ptr-w1))<<1) + (a3_1<<2);

	a3_2  = *(ptr+w2) - *(ptr+w1);
	a3_2 += ((*ptr - *(ptr+w3))<<1) + (a3_2<<2);

	A3_0 = ABS(a3_0) - MIN(ABS(a3_1), ABS(a3_2));
	if (A3_0 > 0)
	{
	  A3_0 += A3_0 << 2;
	  A3_0 = (A3_0 + 32) >> 6;
	  if (a3_0 > 0) A3_0 *= -1;

	  d = *(ptr-w1) - *ptr;
	  if (d >= 0) {
	    d = d>>1;
	    d = (A3_0>d) ? d : MAX(A3_0,0);
	  }
	  else {
	    d = -1*((-1*d)>>1);
	    d = (A3_0>0) ? 0 : MAX(A3_0,d);
	  }

	  *(ptr-w1) -= d;
	  *ptr += d;
	}
      }
    }
  }

  return;
}


Void VertDeblockFilter
  (SInt *rec, Int width, Int height, SInt *QP_store, Int chr)
{
  Int i,j;
  Int br, bc, QP;

  Int p1, p2, eq_cnt, max, min;
  Int v[9];
  Int a3_0, a3_1, a3_2, A3_0, d;
  Int psum;
  SInt *ptr;

  /* vertical edges */
  for (i = 8; i < width; i += 8) 
  for (j = 0; j < height; j++) 
  {
    br = j >> 3;
    bc = i >> 3;

    if (!chr) QP = QP_store[(br>>1)*(width>>4)+(bc>>1)];
    else      QP = QP_store[(br)*(width>>3)+bc];

    ptr = (rec+i+j*width);

    /* mode decision */
    eq_cnt = 	(ABS(*(ptr-4) - *(ptr-5)) <= LG_THR1)
	+	(ABS(*(ptr-3) - *(ptr-4)) <= LG_THR1)
	+	(ABS(*(ptr-2) - *(ptr-3)) <= LG_THR1)
	+	(ABS(*(ptr-1) - *(ptr-2)) <= LG_THR1)
	+	(ABS(*(ptr  ) - *(ptr-1)) <= LG_THR1)
	+	(ABS(*(ptr+1) - *(ptr  )) <= LG_THR1)
	+	(ABS(*(ptr+2) - *(ptr+1)) <= LG_THR1)
	+	(ABS(*(ptr+3) - *(ptr+2)) <= LG_THR1)
	+	(ABS(*(ptr+4) - *(ptr+3)) <= LG_THR1);

    if (eq_cnt >= LG_THR2) 	/* DC offset mode */
    { 
      max = min = *(ptr-4);
      UPDATE_MAXMIN(*(ptr-3), max, min);
      UPDATE_MAXMIN(*(ptr-2), max, min);
      UPDATE_MAXMIN(*(ptr-1), max, min);
      UPDATE_MAXMIN(*(ptr  ), max, min);
      UPDATE_MAXMIN(*(ptr+1), max, min);
      UPDATE_MAXMIN(*(ptr+2), max, min);
      UPDATE_MAXMIN(*(ptr+3), max, min);

      if (ABS(max-min) < (QP<<1)) 
      {
	p1 = (ABS(*(ptr-4) - *(ptr-5)) < QP ) ?
		*(ptr-5) : *(ptr-4);
	p2 = (ABS(*(ptr+3) - *(ptr+4)) < QP ) ?
		*(ptr+4) : *(ptr+3);

	/* make data */
	v[1] = *(ptr-4);
	v[2] = *(ptr-3);
	v[3] = *(ptr-2);
	v[4] = *(ptr-1);
	v[5] = *(ptr);
	v[6] = *(ptr+1);
	v[7] = *(ptr+2);
	v[8] = *(ptr+3);
  
	/* low pass filtering (LPF9: 1 1 2 2 4 2 2 1 1) */
	psum = p1 + p1 + p1 + v[1] + v[2] + v[3] + v[4] + 4;
	*(ptr-4) = (((psum + v[1]) << 1) - (v[4] - v[5])) >> 4;
	psum += v[5] - p1; 
	*(ptr-3) = (((psum + v[2]) << 1) - (v[5] - v[6])) >> 4;
	psum += v[6] - p1; 
	*(ptr-2) = (((psum + v[3]) << 1) - (v[6] - v[7])) >> 4;
	psum += v[7] - p1; 
	*(ptr-1) = (((psum + v[4]) << 1) + p1 - v[1] - (v[7] - v[8])) >> 4;

	psum += v[8] - v[1]; 
	*(ptr) = (((psum + v[5]) << 1) + (v[1] - v[2]) - v[8] + p2) >> 4;
	psum += p2 - v[2]; 
	*(ptr+1) = (((psum + v[6]) << 1) + (v[2] - v[3])) >> 4;
	psum += p2 - v[3]; 
	*(ptr+2) = (((psum + v[7]) << 1) + (v[3] - v[4])) >> 4;
	psum += p2 - v[4]; 
	*(ptr+3) = (((psum + v[8]) << 1) + (v[4] - v[5])) >> 4;
      }
    } 
    else 	/* Default mode */
    {
      a3_0  = *ptr - *(ptr-1);
      a3_0 += ((*(ptr-2) - *(ptr+1))<<1) + (a3_0<<2);

      if (ABS(a3_0) < (QP<<3)) 
      {
	a3_1  = *(ptr-2) - *(ptr-3);
	a3_1 += ((*(ptr-4) - *(ptr-1))<<1) + (a3_1<<2);

	a3_2  = *(ptr+2) - *(ptr+1);
	a3_2 += ((*ptr - *(ptr+3))<<1) + (a3_2<<2);

	A3_0 = ABS(a3_0) - MIN(ABS(a3_1), ABS(a3_2));
	if (A3_0 > 0)
	{
	  A3_0 += A3_0 << 2;
	  A3_0 = (A3_0 + 32) >> 6;
	  if (a3_0 > 0) A3_0 *= -1;

	  d = *(ptr-1) - *ptr;
	  if (d >= 0) {
	    d = d>>1;
	    d = (A3_0>d) ? d : MAX(A3_0,0);
	  }
	  else {
	    d = -1*((-1*d)>>1);
	    d = (A3_0>0) ? 0 : MAX(A3_0,d);
	  }

	  *(ptr-1) -= d;
	  *ptr += d;
	}
      }
    }
  } 

  return;
}

/*******************************************************************************
 *                                                                             *
 *  Copyright (C) 1997 Texas Instruments Tsukuba R&D Center Ltd. (TITRDC)      *
 *                     All Rights Reserved.                                    *
 *                                                                             *
 *  TITRDC is pleased that the standardisation in relation to MPEG-4 has       *
 *  reached Committee Draft level as document ISO/IEC JTC1/SC29/WG11 N1902.    *
 *  TITRDC hereby declares that it is prepared to license its patents, both    *
 *  granted and pending, which are necessary to manufacture, use, and sell     *
 *  implementations of the proposed MPEG-4 Systems, Visual, Audio, Reference   *
 *  Software and DMIF standards or combinations thereof.                       *
 *  TITRDC hereby also declares that it is aware of the rules governing        *
 *  inclusion of patented items in international standards, as described by    *
 *  Section 5.7, part 2 of the ISO/IEC Directives, and in particular that it   *
 *  is willing to grant a license to an unlimited number of applicants         *
 *  throughout the world under reasonable terms and conditions that are        *
 *  demonstrably free of any unfair competition.                               *
 *  This statement is intended to apply to the proposed MPEG-4 standard Visual.*
 *  						                                                   *
 *******************************************************************************/
/*******************************************************************************
 *                                                                             *
 * Module : deringing filter                                                   *
 *          specified in 15.3.2 of Annex F in ISO/IEC CD 14496-2               *
 *                                                                             *
 * Author : Yuji Itoh(itoh@trdc.ti.com) @ Texas Instruments Tsukuba R&D Ctr    *
 *                                                                             *
 * Co-optimized by :                                                           *
 *          Kinya Oosa(oosa@lsi.nsc.co.jp) @ Nippon Steel Corporation          *
 *                                                                             *
 * Date   : 10/08/97                                                           *
 *                                                                             *
 *******************************************************************************/

Void Deringing_Luma(SInt *Rec_Y, Int width, Int height, SInt *QP_store, Int Combined)
{
  Int thres[4], range[4], 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_pel, h_pel;
  Int max_blk, min_blk;
  Int v0, h0;
  SInt *ptr;
  SInt val;
  Int sum, sum1;
  Int thr, addr_v, blks, incr;
  Int sign_v[10], sum_v[10];
  Int *ptr2, *ptr3;
  SInt pelu, pelc, pell;

  incr = width - BLKSIZE;

  /* luminance */
  for( MB_V=0; MB_V<height; MB_V+=MBSIZE ) for( MB_H=0; MB_H<width; MB_H+=MBSIZE ){
    max_diff = (QP_store[(((MB_V*width)>>4)+MB_H)>>4]>>2)+4;

    /* threshold determination */
    max_range_blk = max_thres_blk = 0;
    blks = 0;

    for( BLK_V=0; BLK_V<MBSIZE; BLK_V+=BLKSIZE ) for( BLK_H=0; BLK_H<MBSIZE; BLK_H+=BLKSIZE ){
      ptr = &Rec_Y[(MB_V + BLK_V) * width + MB_H + BLK_H];
      max_blk = min_blk = *ptr;
      for(v_pel=0;v_pel<BLKSIZE;v_pel++){
	  for(h_pel=0;h_pel<BLKSIZE;h_pel++){
	    if((val = *ptr++) > max_blk)
	      max_blk = val;
	    else if(val < min_blk)
	      min_blk = val;
	  }
	  ptr += incr;
      }

      thres[blks] = (max_blk+min_blk+1)>>1;
      range[blks] = max_blk-min_blk; 

      if(range[blks]>=max_range_blk){
	max_range_blk = range[blks];
	max_thres_blk = thres[blks];
      }
      blks++;
    }

    blks = 0;
    for(v_blk=MB_V;v_blk<MB_V+MBSIZE;v_blk+=BLKSIZE) for(h_blk=MB_H;h_blk<MB_H+MBSIZE;h_blk+=BLKSIZE){
      v0 = ((v_blk - 1) >= 1) ? (v_blk - 1) : 1;
      h0 = ((h_blk - 1) >= 1) ? (h_blk - 1) : 1;
      
      /* threshold rearrangement for flat region adjacent to non-flat region */
      if(range[blks]<32 && max_range_blk>=64)
	thres[blks] = max_thres_blk;

      /* threshold rearrangement for deblocking (blockiness annoying at DC dominant region) */
      if(max_range_blk<16){
	if(!Combined){
	  for(v_pel=v0;v_pel<v_blk+BLKSIZE-1;v_pel++){ 
	    addr_v = v_pel * width;
	    ptr = &Rec_Y[addr_v + h0 - 1];
	    ptr2 = &sum_v[0];

	    *ptr2++ = *(ptr-width) + ((*ptr)<<1) + *(ptr+width);
	    ptr++;
	    *ptr2++ = *(ptr-width) + ((*ptr)<<1) + *(ptr+width);
	    ptr++;

	    for(h_pel=h0;h_pel<h_blk+BLKSIZE-1;h_pel++){
	      *ptr2 = *(ptr-width) + ((*ptr)<<1) + *(ptr+width);
	      sum = (*(ptr2-2) + (*(ptr2-1)<<1) + *ptr2 + 8)>>4;

	      ptr--;
	      if(abs(*ptr - sum) > max_diff){
		if(sum > *ptr)
		  sum = *ptr + max_diff;
		else
		  sum = *ptr - max_diff;
	      }
	      *ptr = sum;

	      ptr+=2;
	      ptr2++;
	    }
	  }
	}
      }
      else{
	/* adaptive smoothing */
	thr = thres[blks];

	for(v_pel=v0;v_pel<v_blk+BLKSIZE-1;v_pel++){ 
	  addr_v = v_pel * width;
	  ptr = &Rec_Y[addr_v + h0 - 1];
	  ptr2 = &sum_v[0];
	  ptr3 = &sign_v[0];

	  pelu = *(ptr-width);
	  pelc = *ptr;
	  pell = *(ptr+width);
	  ptr++;
	  *ptr2++ = pelu + (pelc<<1) + pell;
	  *ptr3++ = INDEX(pelu,thr) + INDEX(pelc,thr) + INDEX(pell,thr);

	  pelu = *(ptr-width);
	  pelc = *ptr;
	  pell = *(ptr+width);
	  ptr++;
	  *ptr2++ = pelu + (pelc<<1) + pell;
	  *ptr3++ = INDEX(pelu,thr) + INDEX(pelc,thr) + INDEX(pell,thr);
	  
	  for(h_pel=h0;h_pel<h_blk+BLKSIZE-1;h_pel++){
	    pelu = *(ptr-width);
	    pelc = *ptr;
	    pell = *(ptr+width);

	    *ptr2 = pelu + (pelc<<1) + pell;
	    *ptr3 = INDEX(pelu,thr) + INDEX(pelc,thr) + INDEX(pell,thr);

	    sum1 = *(ptr3-2) + *(ptr3-1) + *ptr3;
	    if(sum1 == 0 || sum1 == 9){
	      sum = (*(ptr2-2) + (*(ptr2-1)<<1) + *ptr2 + 8)>>4;
	    
	      ptr--;
	      if(abs(*ptr - sum) > max_diff){
		if(sum > *ptr)
		  sum = *ptr + max_diff;
		else
		  sum = *ptr - max_diff;
	      }
	      *ptr++ = sum;
	    }
	    ptr++;
	    ptr2++;
	    ptr3++;
	  }
	}
      }
      blks++;
    } /* block level (Luminance) */
  } /* macroblock level */
}

Void Deringing_Chroma(SInt *Rec_C, Int width, Int height, SInt *QP_store, Int Combined)
{
  Int thres;
  Int v_blk, h_blk;
  Int max_diff;
  Int v_pel, h_pel;
  Int max_blk, min_blk;
  Int v0, h0;
  SInt *ptr;
  SInt val;
  Int sum, sum1, addr_v, incr;
  Int sign_v[10], sum_v[10];
  Int *ptr2, *ptr3;
  SInt pelu, pelc, pell;

  incr = width - BLKSIZE;

  /* chrominance */
  for(v_blk=0;v_blk<height;v_blk+=BLKSIZE) for(h_blk=0;h_blk<width;h_blk+=BLKSIZE){
    max_diff = (QP_store[(((v_blk*width)>>3)+h_blk)>>3]>>2)+4;

    ptr = &Rec_C[v_blk * width + h_blk];
    max_blk = min_blk = *ptr;
    for(v_pel=0;v_pel<BLKSIZE;v_pel++){
	for(h_pel=0;h_pel<BLKSIZE;h_pel++){
	  if((val = *ptr++) > max_blk)
	    max_blk = val;
	  else if(val < min_blk)
	    min_blk = val;
	}
	ptr += incr;
    }
    
    v0 = ((v_blk - 1) >= 1) ? (v_blk - 1) : 1;
    h0 = ((h_blk - 1) >= 1) ? (h_blk - 1) : 1;

    if(max_blk-min_blk<4){
      if(!Combined){
	for(v_pel=v0;v_pel<v_blk+BLKSIZE-1;v_pel++){ 
	  addr_v = v_pel * width;
	  ptr = &Rec_C[addr_v + h0 - 1];
	  ptr2 = &sum_v[0];
	  
	  *ptr2++ = *(ptr-width) + ((*ptr)<<1) + *(ptr+width);
	  ptr++;
	  *ptr2++ = *(ptr-width) + ((*ptr)<<1) + *(ptr+width);
	  ptr++;
	  
	  for(h_pel=h0;h_pel<h_blk+BLKSIZE-1;h_pel++){
	    *ptr2 = *(ptr-width) + ((*ptr)<<1) + *(ptr+width);
	    sum = (*(ptr2-2) + (*(ptr2-1)<<1) + *ptr2 + 8)>>4;
	    
	    ptr--;
	    if(abs(*ptr - sum) > max_diff){
	      if(sum > *ptr)
		sum = *ptr + max_diff;
	      else
		sum = *ptr - max_diff;
	    }
	    *ptr = sum;
	    
	    ptr+=2;
	    ptr2++;
	  }
	}
      }
    }
    else{
      thres = (max_blk+min_blk+1)>>1;

      for(v_pel=v0;v_pel<v_blk+BLKSIZE-1;v_pel++){ 
	addr_v = v_pel * width;
	ptr = &Rec_C[addr_v + h0 - 1];
	ptr2 = &sum_v[0];
	ptr3 = &sign_v[0];
	
	pelu = *(ptr-width);
	pelc = *ptr;
	pell = *(ptr+width);
	ptr++;
	*ptr2++ = pelu + (pelc<<1) + pell;
	*ptr3++ = INDEX(pelu,thres) + INDEX(pelc,thres) + INDEX(pell,thres);
	
	pelu = *(ptr-width);
	pelc = *ptr;
	pell = *(ptr+width);
	ptr++;
	*ptr2++ = pelu + (pelc<<1) + pell;
	*ptr3++ = INDEX(pelu,thres) + INDEX(pelc,thres) + INDEX(pell,thres);
	
	for(h_pel=h0;h_pel<h_blk+BLKSIZE-1;h_pel++){
	  pelu = *(ptr-width);
	  pelc = *ptr;
	  pell = *(ptr+width);
	  
	  *ptr2 = pelu + (pelc<<1) + pell;
	  *ptr3 = INDEX(pelu,thres) + INDEX(pelc,thres) + INDEX(pell,thres);
	  
	  sum1 = *(ptr3-2) + *(ptr3-1) + *ptr3;
	  if(sum1 == 0 || sum1 == 9){
	    sum = (*(ptr2-2) + (*(ptr2-1)<<1) + *ptr2 + 8)>>4;
	    
	    ptr--;
	    if(abs(*ptr - sum) > max_diff){
	      if(sum > *ptr)
		sum = *ptr + max_diff;
	      else
		sum = *ptr - max_diff;
	    }
	    *ptr++ = sum;
	  }
	  ptr++;
	  ptr2++;
	  ptr3++;
	}
      }
    }
  } /* macroblock level */
}



