Logo Search packages:      
Sourcecode: tela version File versions  Download package

quantize.C

/* quantize.c, quantization / inverse quantization                          */

/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */

/*
 * Disclaimer of Warranty
 *
 * These software programs are available to the user without any license fee or
 * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
 * any and all warranties, whether express, implied, or statuary, including any
 * implied warranties or merchantability or of fitness for a particular
 * purpose.  In no event shall the copyright-holder be liable for any
 * incidental, punitive, or consequential damages of any kind whatsoever
 * arising from the use of these programs.
 *
 * This disclaimer of warranty extends to the user of these programs and user's
 * customers, employees, agents, transferees, successors, and assigns.
 *
 * The MPEG Software Simulation Group does not represent or warrant that the
 * programs furnished hereunder are free of infringement of any third-party
 * patents.
 *
 * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
 * are subject to royalty fees to patent holders.  Many of these patents are
 * general enough such that they are unavoidable regardless of implementation
 * design.
 *
 */

#include <stdio.h>
#include "mpegintf.H"
#include "global.h"

static void iquant1_intra(short *src, short *dst,
  int dc_prec, unsigned char *quant_mat, int mquant);
static void iquant1_non_intra(short *src, short *dst,
  unsigned char *quant_mat, int mquant);

/* Test Model 5 quantization
 *
 * this quantizer has a bias of 1/8 stepsize towards zero
 * (except for the DC coefficient)
 */
int MPEG::quant_intra(short *src, short *dst,
                                int dc_prec, unsigned char *quant_mat,
                                int mquant)
{
      int i;
      int x, y, d;

      x = src[0];
      d = 8>>dc_prec; /* intra_dc_mult */
      dst[0] = (x>=0) ? (x+(d>>1))/d : -((-x+(d>>1))/d); /* round(x/d) */

      for (i=1; i<64; i++)
      {
            x = src[i];
            d = quant_mat[i];
            y = (32*(x>=0 ? x : -x) + (d>>1))/d; /* round(32*x/quant_mat) */
            d = (3*mquant+2)>>2;
            y = (y+d)/(2*mquant); /* (y+0.75*mquant) / (2*mquant) */

            /* clip to syntax limits */
            if (y > 255)
            {
                  if (mpeg1)
                        y = 255;
                  else if (y > 2047)
                        y = 2047;
            }

            dst[i] = (x>=0) ? y : -y;

#if 0
            /* this quantizer is virtually identical to the above */
            if (x<0)
                  x = -x;
            d = mquant*quant_mat[i];
            y = (16*x + ((3*d)>>3)) / d;
            dst[i] = (src[i]<0) ? -y : y;
#endif
      }

      return 1;
}

int MPEG::quant_non_intra(short *src, short *dst, unsigned char *quant_mat, int mquant)
{
      int i;
      int x, y, d;
      int nzflag;

      nzflag = 0;

      for (i=0; i<64; i++)
      {
            x = src[i];
            d = quant_mat[i];
            y = (32*(x>=0 ? x : -x) + (d>>1))/d; /* round(32*x/quant_mat) */
            y /= (2*mquant);

            /* clip to syntax limits */
            if (y > 255)
            {
                  if (mpeg1)
                        y = 255;
                  else if (y > 2047)
                        y = 2047;
            }

            if ((dst[i] = (x>=0 ? y : -y)) != 0)
                  nzflag=1;
      }

      return nzflag;
}

/* MPEG-2 inverse quantization */
void MPEG::iquant_intra(short *src, short *dst,
                                    int dc_prec, unsigned char *quant_mat,
                                    int mquant)
{
      int i, val, sum;

      if (mpeg1)
            iquant1_intra(src,dst,dc_prec,quant_mat,mquant);
      else
      {
            sum = dst[0] = src[0] << (3-dc_prec);
            for (i=1; i<64; i++)
            {
                  val = (int)(src[i]*quant_mat[i]*mquant)/16;
                  sum+= dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
            }

            /* mismatch control */
            if ((sum&1)==0)
                  dst[63]^= 1;
      }
}

void MPEG::iquant_non_intra(short *src, short *dst, unsigned char *quant_mat, int mquant)
{
      int i, val, sum;

      if (mpeg1)
            iquant1_non_intra(src,dst,quant_mat,mquant);
      else
      {
            sum = 0;
            for (i=0; i<64; i++)
            {
                  val = src[i];
                  if (val!=0)
                        val = (int)((2*val+(val>0 ? 1 : -1))*quant_mat[i]*mquant)/32;
                  sum+= dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
            }

            /* mismatch control */
            if ((sum&1)==0)
                  dst[63]^= 1;
      }
}

/* MPEG-1 inverse quantization */
static void iquant1_intra(short *src, short *dst, int dc_prec, unsigned char *quant_mat, int mquant)
{
      int i, val;

      dst[0] = src[0] << (3-dc_prec);
      for (i=1; i<64; i++)
      {
            val = (int)(src[i]*quant_mat[i]*mquant)/16;

            /* mismatch control */
            if ((val&1)==0 && val!=0)
                  val+= (val>0) ? -1 : 1;

            /* saturation */
            dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
      }
}

static void iquant1_non_intra(short *src, short *dst, unsigned char *quant_mat, int mquant)
{
      int i, val;

      for (i=0; i<64; i++)
      {
            val = src[i];
            if (val!=0)
            {
                  val = (int)((2*val+(val>0 ? 1 : -1))*quant_mat[i]*mquant)/32;

                  /* mismatch control */
                  if ((val&1)==0 && val!=0)
                        val+= (val>0) ? -1 : 1;
            }

            /* saturation */
            dst[i] = (val>2047) ? 2047 : ((val<-2048) ? -2048 : val);
      }
}

Generated by  Doxygen 1.6.0   Back to index