about summary refs log tree commit diff
path: root/converter/ppm/ppmtompeg/rate.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtompeg/rate.c')
-rw-r--r--converter/ppm/ppmtompeg/rate.c986
1 files changed, 986 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/rate.c b/converter/ppm/ppmtompeg/rate.c
new file mode 100644
index 00000000..3940956c
--- /dev/null
+++ b/converter/ppm/ppmtompeg/rate.c
@@ -0,0 +1,986 @@
+/*============================================================================*
+ * rate.c								      *
+ *									      * 
+ *	Procedures concerned with rate control                                *
+ *									      *
+ * EXPORTED PROCEDURES:							      *
+ *      initRatecontrol()                                                     *
+ *      targetRateControl()                                                   *
+ *      updateRateControl()                                                   *
+ *      MB_RateOut()                                                          *
+ *      needQScaleChange()                                                    *
+ *      incNumBlocks()                                                        *
+ *      incQuant()                                                            *
+ *	incMacroBlockBits()                                                   *
+ *      setPictureRate()                                                      *
+ *      setBitRate()                                                          *
+ *      getBitRate()                                                          *
+ *      setBufferSize()                                                       *
+ *      getBufferSize()                                                       *
+ *                                                                            *
+ * NOTES:                                                                     *
+ *	Naming conventions follow those of MPEG-2 draft algorithm (chap. 10)  *
+ *============================================================================*/
+
+
+/*
+ * Copyright (c) 1995 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+/*==============*
+ * HEADER FILES *
+ *==============*/
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/times.h>
+
+#include "ppm.h"
+#include "nstring.h"
+
+#include "all.h"
+#include "mtypes.h"
+#include "bitio.h"
+#include "frames.h"
+#include "prototypes.h"
+#include "param.h"
+#include "mheaders.h"
+#include "fsize.h"
+#include "postdct.h"
+#include "mpeg.h"
+#include "parallel.h"
+#include "dct.h"
+#include "rate.h"
+
+
+/*==================*
+ * GLOBAL VARIABLES *
+ *==================*/
+
+#define MAX_BIT_RATE 104857600		/* 18 digit number in units of 400 */
+#define MAX_BUFFER_SIZE 16760832        /* 10 digit number in units of 16k */
+#define DEFAULT_BUFFER_SIZE 327680      /* maximun for "constrained" bitstream */
+#define DEFAULT_VBV_FULLNESS 3          /* wait till 1/3 full */
+#define DEFAULT_PICT_RATE_CODE 5        /* code for 30 Frames/sec */
+#define DEFAULT_PICT_RATE 30            /* 30 frames per second */
+#define MAX_VBV_DELAY 32768             /* 16 digits */
+
+
+/*	  Variables from Parameter File */
+
+static int	RateControlMode = VARIABLE_RATE;
+static int32 buffer_size = DEFAULT_BUFFER_SIZE;
+static int32 bit_rate = -1;
+
+static bool wantVbvUnderflowWarning;
+static bool wantVbvOverflowWarning;
+
+/*   Variables for the VBV buffer defined in MPEG specs */
+static unsigned int VBV_remainingDelay; 
+    /* delay in units of 1/90000 seconds */
+static int32 VBV_buffer = 0;	  /* fullness of the theoretical VBV buffer */
+static int32 bufferFillRate = 0;    /* constant rate at which buffer filled */
+static int32 frameDelayIncrement = 0;	/* number of "delay" units/Frame */
+
+/*  Global complexity measure variables */
+static int Xi, Xp, Xb;  /*  Global complexity measure  */
+
+static int Si, Sp, Sb;  /*  Total # bits for last pict of type (Overhead?) */
+
+static float Qi, Qp, Qb; /* avg quantizaton for last picture of type  */
+     
+/*  Target bit allocations for each type of picture*/
+int Ti, Tp, Tb;
+
+int current_Tx;	/* allocation for current frame */
+
+/*  Count of number of pictures of each type remaining */
+int GOP_X;
+int GOP_I;
+int GOP_P;
+int GOP_B;
+
+int Nx = 0;
+int Ni = 0;
+int Np = 0;
+int Nb = 0;
+
+/*   Counters used while encoding frames   */
+
+int rc_numBlocks = 0;
+int rc_totalQuant = 0;
+int rc_bitsThisMB;
+int rc_totalMBBits;
+int rc_totalFrameBits;
+int rc_totalOverheadBits = 0;
+
+
+/*	Want to print out Macroblock info every Nth MB */
+int RC_MB_SAMPLE_RATE = 0;
+
+static float Ki = .7;
+static float Kp = 1;
+static float Kb = 1.4;
+static int rc_R;
+static int rc_G;
+
+/*   Rate Control variables   */
+
+/*   Virtual buffers for each frame type */
+static int d0_i;   /* Initial fullnesses */
+static int d0_p;
+static int d0_b;
+
+static int lastFrameVirtBuf;   /* fullness after last frame of this type */
+static int currentVirtBuf;     /* fullness during current encoding*/
+
+static int MB_cnt = -1;	       /* Number of MB's in picture */
+
+static int rc_Q;               /* reference quantization parameter */
+
+static int reactionParameter;  /*  Reaction parameter */
+
+/*	Adaptive Quantization variables */
+static int act_j;              /*  spatial activity measure */
+static float N_act;            /*  Normalized spacial activity */
+static int avg_act;	   /*  average activity value in last picture encoded */
+static int total_act_j;	       /*  Sum of activity values in current frame */
+
+static int var_sblk;	       /* sub-block activity */
+static int P_mean;	       /* Mean value of pixels in 8x8 sub-block */
+
+static int mquant;	       /* Raw Quantization value */
+static int Qscale;	       /* Clipped, truncated quantization value */
+
+
+
+/*  Output-related variables */
+#ifdef RC_STATS_FILE
+static FILE *RC_FILE;
+#endif
+
+static const char * const Frame_header1 = 
+"  Fm         #     Bit      GOP                    V                ";
+static const char * const Frame_header2 = 
+"   #  type   MBs   Alloc    left  Ni Np Nb  N_act  buff   Q_rc Qscale";
+static const char * const Frame_header3 = 
+"----     -  ----  ------ -------  -- -- --  -----  ------ ----   ----";
+static const char * const Frame_trailer1 = 
+"                      avg          virt     %    GOP      %     VBV";
+static const char * const Frame_trailer2 = 
+"    Sx    Qx      Xx  act N_act  buffer alloc    left  left     buf  delay";
+static const char * const Frame_trailer3 = 
+"------ --.-- -------  --- --.-- -------   --- -------   --- ------- ------";
+
+static const char * const MB_header1 = 
+"MB#  #bits  Q mqt     Dj  Q_j   actj  N_act  totbits b/MB %alloc %done";
+static const char * const MB_header2 = 
+"---  ----- -- --- ------  ---  -----  --.--   ------ ----    ---   ---";
+
+static char rc_buffer[101];
+
+/*	EXTERNAL Variables  */
+extern char *framePattern;
+extern int framePatternLen;
+
+
+/*===============================*
+ * INTERNAL PROCEDURE prototypes *
+ *===============================*/
+
+int initGOPRateControl _ANSI_ARGS_((void));
+int determineMBCount _ANSI_ARGS_((void));
+void checkBufferFullness _ANSI_ARGS_((int count));
+void checkSpatialActivity _ANSI_ARGS_((Block blk0, Block blk1, Block blk2, Block blk3));
+void incNumBlocks _ANSI_ARGS_((int num));
+void calculateVBVDelay _ANSI_ARGS_((int num));
+int BlockExperiments  _ANSI_ARGS_((int16 *OrigBlock, int16 *NewBlock, int control));
+     
+     
+
+static void
+analyzePattern(const char *  const framePattern,
+               int           const framePatternLen,
+               int *         const gop_xP,
+               int *         const gop_iP,
+               int *         const gop_pP,
+               int *         const gop_bP,
+               const char ** const errorP) {
+
+    unsigned int i;
+
+    /*  Initialize Pattern info */
+    *gop_xP = framePatternLen;    
+
+    for (i = 0, *gop_iP = 0, *gop_pP = 0, *gop_bP = 0, *errorP = NULL;
+         i < framePatternLen && !*errorP; 
+         ++i) {
+        switch(framePattern[i]) {
+        case 'i': ++*gop_iP; break;
+        case 'p': ++*gop_pP; break;
+        case 'b': ++*gop_bP; break;
+        default:
+            asprintfN(errorP, "Bad pattern - not composed of i, p, and b");
+        }
+    }
+    assert(*gop_xP == *gop_iP + *gop_pP + *gop_bP);
+}
+  
+
+
+/*===========================================================================*
+ *
+ * initRateControl
+ *
+ *	initialize the allocation parameters.
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:   many global variables 
+ *
+ * NOTES:  Get rid of the redundant pattern stuff!!
+ *===========================================================================*/
+int
+initRateControl(bool const wantUnderflowWarning,
+                bool const wantOverflowWarning) {
+    int result;
+    const char * error;
+
+    wantVbvUnderflowWarning = wantUnderflowWarning;
+    wantVbvOverflowWarning  = wantOverflowWarning;
+
+    DBG_PRINT(("Initializing Allocation Data\n"));
+  
+#ifdef RC_STATS_FILE
+    RC_FILE = fopen("RC_STATS_FILE", "w");
+    if ( RC_FILE  == NULL) {
+        DBG_PRINT(("Open of RC file failed, using stderr\n"));
+        RC_FILE = stderr;
+        fprintf(RC_FILE, "Open of RC file failed, using stderr\n");
+        fflush(RC_FILE);
+    }
+#endif
+
+    VBV_remainingDelay = 0;
+  
+    analyzePattern(framePattern, framePatternLen,
+                   &GOP_X, &GOP_I, &GOP_P, &GOP_B, &error);
+
+    if (error) {
+        pm_message("Unable to set up rate control.  Switching to variable.  "
+                   "%s", error);
+        strfree(error);
+        RateControlMode = VARIABLE_RATE;
+        return -1;
+    }
+
+
+    /* Initializing GOP bit allocation */	
+    rc_R = 0;
+    rc_G = (bit_rate * GOP_X/frameRateRounded);
+  
+    /*   Initialize the "global complexity measures" */
+    Xi = (160 * bit_rate/115);
+    Xp = (60 * bit_rate/115);
+    Xb = (42 * bit_rate/115);
+  
+    /*   Initialize MB counters */
+    rc_totalMBBits= rc_bitsThisMB= rc_totalFrameBits=rc_totalOverheadBits = 0;
+    rc_numBlocks = rc_totalQuant = 0;
+  
+    /*   init virtual buffers  */
+    reactionParameter = (2 * bit_rate / frameRateRounded);
+    d0_i = (10 * reactionParameter / 31);
+    d0_p = (Kp * d0_i);
+    d0_b = (Kb * d0_i);
+  
+    lastFrameVirtBuf = d0_i;	/*  start with I Frame */
+    rc_Q = lastFrameVirtBuf  * 31 / reactionParameter;
+  
+    /*   init spatial activity measures */
+    avg_act = 400;		/* Suggested initial value */
+    N_act = 1;
+  
+    mquant = rc_Q * N_act;
+  
+    frameDelayIncrement = (90000 / frameRateRounded);
+        /* num of "delay" units per frame */
+    bufferFillRate = bit_rate / frameRateRounded; 
+        /* VBV buf fills at constant rate */
+    VBV_buffer = buffer_size;
+    DBG_PRINT(("VBV- delay: %d, fill rate: %d, delay/Frame: %d units, "
+               "buffer size: %d\n",
+               VBV_remainginDelay, bufferFillRate, frameDelayIncrement, 
+               buffer_size));
+  
+    result = initGOPRateControl();
+  
+    return result;
+}
+
+/*===========================================================================*
+ *
+ * initGOPRateControl
+ *
+ *		(re)-initialize the RC for the a new Group of Pictures.
+ *	New bit allocation, but carry over complexity measures.
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:   many global variables 
+ *
+ *===========================================================================*/
+int
+initGOPRateControl()
+{
+    DBG_PRINT(("Initializing new GOP\n"));
+  
+    Nx = GOP_X;
+    Ni = GOP_I;
+    Np = GOP_P;
+    Nb = GOP_B;
+  
+    rc_R += rc_G;
+  
+    DBG_PRINT(("bufsize: %d, bitrate: %d, pictrate: %d, GOP bits: %d\n",
+               buffer_size, bit_rate, frameRateRounded, rc_R));
+    DBG_PRINT(("Xi: %d, Xp: %d, Xb: %d Nx: %d, Ni: %d, Np: %d, Nb: %d\n",
+               Xi, Xp, Xb, Nx,Ni,Np,Nb));
+    DBG_PRINT(("d0_i: %d, d0_p: %d, d0_b: %d, avg_act: %d, rc_Q: %d, "
+               "mquant: %d\n",
+               d0_i, d0_p, d0_b, avg_act, rc_Q, mquant));
+    return 1;
+}
+
+
+
+/*===========================================================================*
+ *
+ * targetRateControl
+ *
+ *      Determine the target allocation for given picture type, initiates
+ *  variables for rate control process.
+ *
+ * RETURNS:     nothing.
+ *
+ * SIDE EFFECTS:   many global variables
+ *
+ *===========================================================================*/
+void
+targetRateControl(MpegFrame * const frame) {
+
+    float temp1, minimumBits;
+    float tempX, tempY, tempZ;
+    int result;
+    int frameType;
+    const char *strPtr;
+  
+    minimumBits = (bit_rate / (8 * frameRateRounded));
+  
+    /*   Check if new GOP */
+    if (Nx == 0) {
+        initGOPRateControl();
+    }
+  
+    if (MB_cnt < 0) {MB_cnt = determineMBCount();}
+  
+    switch (frame->type) {
+    case TYPE_IFRAME:
+        frameType = 'I';
+    
+        tempX = ( (Np * Ki * Xp) / (Xi * Kp) );
+        tempY = ( (Nb * Ki * Xb) / (Xi*Kb) );
+        tempZ = Ni + tempX + tempY;
+        temp1 = (rc_R / tempZ);
+        result = (int) (temp1 > minimumBits ? temp1 :  minimumBits);
+        current_Tx = Ti = result;
+        lastFrameVirtBuf = d0_i;
+        break;
+    
+    case TYPE_PFRAME:
+        frameType = 'P';
+        tempX =  ( (Ni * Kp * Xi) / (Ki * Xp) );
+        tempY =  ( (Nb * Kp * Xb) / (Kb * Xp) );
+        tempZ = Np + tempX + tempY;
+        temp1 = (rc_R/ tempZ);
+        result = (int) (temp1 > minimumBits ? temp1 :  minimumBits);
+        current_Tx = Tp = result;
+        lastFrameVirtBuf = d0_p;
+        break;
+    
+    case TYPE_BFRAME:
+        frameType = 'B';
+        tempX =  ( (Ni * Kb * Xi) / (Ki * Xb) );
+        tempY =  ( (Np * Kb * Xp) / (Kp * Xb) );
+        tempZ = Nb + tempX + tempY;
+        temp1 = (rc_R/ tempZ);
+        result = (int) (temp1 > minimumBits ? temp1 :  minimumBits);
+        current_Tx = Tb = result;
+        lastFrameVirtBuf = d0_b;
+        break;
+    
+    default:
+        frameType = 'X';
+    }
+  
+    N_act = 1;
+    rc_Q = lastFrameVirtBuf  * 31 / reactionParameter;
+    mquant = rc_Q * N_act;
+    Qscale = (mquant > 31 ? 31 : mquant);
+    Qscale = (Qscale < 1 ? 1 : Qscale);
+  
+    /*   Print headers for Frame info */
+    strPtr = Frame_header1;
+    DBG_PRINT(("%s\n",strPtr));
+    strPtr = Frame_header2;
+    DBG_PRINT(("%s\n",strPtr));
+    strPtr = Frame_header3;
+    DBG_PRINT(("%s\n",strPtr));
+  
+    /*   Print Frame info */
+    sprintf(rc_buffer, "%4d     %1c  %4d  %6d %7d  "
+            "%2d %2d %2d   %2.2f  %6d %4d    %3d",
+            frame->id,frameType,MB_cnt,current_Tx,rc_R,Ni,Np,Nb, 
+            N_act, lastFrameVirtBuf, rc_Q, Qscale);
+  
+#ifdef RC_STATS_FILE
+    fprintf(RC_FILE,"%s\n", rc_buffer);
+    fflush(RC_FILE);
+#endif
+    DBG_PRINT(("%s\n",rc_buffer));
+  
+    /*  Print headers for Macroblock info */
+    if (RC_MB_SAMPLE_RATE) {
+        strPtr = MB_header1;
+        DBG_PRINT(("%s\n",strPtr));
+        strPtr = MB_header2;
+        DBG_PRINT(("%s\n",strPtr));
+    }
+}
+
+
+
+
+static void 
+updateVBVBuffer(int const frameBits) {
+/*----------------------------------------------------------------------------
+  Update the VBV buffer after each frame.  This theoretical buffer is
+  being filled at constant rate 'bufferFillRate' from an mpeg stream.
+  It is emptied as each frame is grabbed by the decoder.  Exception is
+  that the decoder will wait until the "delay" is over.
+
+  We mark the passing of one unit of time, in which 'frameBits' bits of
+  mpeg data were grabbed from the buffer by the decoder.
+-----------------------------------------------------------------------------*/
+    if (VBV_remainingDelay)
+        VBV_remainingDelay -= MIN(frameDelayIncrement, VBV_remainingDelay);
+    else
+        VBV_buffer -= frameBits;
+
+    VBV_buffer += bufferFillRate;
+    if (VBV_buffer < 0 && wantVbvUnderflowWarning)
+        pm_message("WARNING - VBV buffer underflow (%d)", VBV_buffer);
+    if (VBV_buffer > buffer_size && wantVbvOverflowWarning)
+        pm_message("WARNING - VBV buffer overflow (%d > %d)",
+                   VBV_buffer, buffer_size);
+}
+
+
+
+/*===========================================================================*
+ *
+ * updateRateControl
+ *
+ *      Update the statistics kept, after end of frame.  Resets
+ *  various global variables
+ *
+ * RETURNS:     nothing
+ *
+ * SIDE EFFECTS:   many global variables
+ *
+ *===========================================================================*/
+void
+updateRateControl(int const type) {
+    int totalBits, frameComplexity, pctAllocUsed, pctGOPUsed;
+    float avgQuant;
+    const char *strPtr;
+
+    totalBits = rc_totalFrameBits;
+    avgQuant = ((float) rc_totalQuant / (float) rc_numBlocks);
+    frameComplexity = totalBits * avgQuant;
+    pctAllocUsed = (totalBits *100 / current_Tx);
+    rc_R -= totalBits;
+    pctGOPUsed = (rc_R *100/ rc_G);
+  
+    avg_act = (total_act_j / MB_cnt);
+  
+    updateVBVBuffer(totalBits);
+  
+    switch (type) {
+    case TYPE_IFRAME:
+        Ti = current_Tx;
+        d0_i = currentVirtBuf;
+        Ni--;
+        Si = totalBits;
+        Qi = avgQuant;
+        Xi = frameComplexity;
+        break;
+    case TYPE_PFRAME:
+        Tp = current_Tx;
+        d0_p = currentVirtBuf;
+        Np--;
+        Sp = totalBits;
+        Qp = avgQuant;
+        Xp = frameComplexity;
+        break;
+    case TYPE_BFRAME:
+        Tb = current_Tx;
+        d0_b = currentVirtBuf;
+        Nb--;
+        Sb = totalBits;
+        Qb = avgQuant;
+        Xb = frameComplexity;
+        break;
+    }
+  
+  
+    /*  Print Frame info */
+    strPtr = Frame_trailer1;
+    DBG_PRINT(("%s\n",strPtr));
+    strPtr = Frame_trailer2;
+    DBG_PRINT(("%s\n",strPtr));
+    strPtr = Frame_trailer3;
+    DBG_PRINT(("%s\n",strPtr));
+  
+    sprintf(rc_buffer, "%6d  %2.2f  %6d  %3d  %2.2f %7d   "
+            "%3d %7d   %3d  %6d %6d",
+            totalBits, avgQuant, frameComplexity, avg_act, N_act, 
+            currentVirtBuf, pctAllocUsed, rc_R, pctGOPUsed, 
+            VBV_buffer, VBV_remainingDelay);
+#ifdef RC_STATS_FILE
+    fprintf(RC_FILE,"%s\n", rc_buffer);
+    fflush(RC_FILE);
+#endif
+    DBG_PRINT(("%s\n",rc_buffer));
+  
+    Nx--;
+    rc_totalMBBits= rc_bitsThisMB= rc_totalFrameBits=rc_totalOverheadBits = 0;
+    rc_numBlocks = rc_totalQuant = total_act_j = currentVirtBuf = 0;
+  
+    DBG_PRINT(("GOP now has %d bits remaining (%3d%%) for %d frames .. , "
+               "Ni= %d, Np= %d, Nb= %d\n", 
+               rc_R, (rc_R*100/rc_G), (Ni+Np+Nb), Ni, Np, Nb));
+  
+}
+
+
+/*===========================================================================*
+ *
+ * MB_RateOut
+ *
+ *      Prints out sampling of MB rate control data.  Every "nth" block
+ *	stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE
+ *	(NB. "skipped" blocks do not go through this function and thus do not
+ *		show up in the sample )
+ *
+ * RETURNS:     nothing
+ *
+ * SIDE EFFECTS:   none
+ *
+ * NOTES:
+ *
+ *===========================================================================*/
+void
+  MB_RateOut(type)
+int type;
+{
+  int totalBits;
+  int pctUsed, pctDone;
+  int bitsThisMB;
+  int bitsPerMB;
+  
+  bitsThisMB = rc_bitsThisMB;
+  totalBits = rc_totalFrameBits;
+  bitsPerMB = (totalBits / rc_numBlocks); 
+  pctDone = (rc_numBlocks * 100/ MB_cnt); 
+  pctUsed = (totalBits *100/current_Tx);
+  
+  sprintf(rc_buffer, "%3d  %5d %2d %3d %6d  %3d %6d   %2.2f   %6d %4d    %3d   %3d\n",
+	  (rc_numBlocks - 1), bitsThisMB, Qscale, mquant, currentVirtBuf, 
+	  rc_Q, act_j, N_act, totalBits, bitsPerMB, pctUsed, pctDone);
+#ifdef RC_STATS_FILE
+  fprintf(RC_FILE, "%s", rc_buffer);
+  fflush(RC_FILE);
+#endif
+  
+  if ( (RC_MB_SAMPLE_RATE) && ((rc_numBlocks -1) % RC_MB_SAMPLE_RATE)) {
+    DBG_PRINT(("%s\n", rc_buffer));
+  } else {
+    return;
+  }
+}
+
+
+
+/*===========================================================================*
+ *
+ * incNumBlocks()
+ *
+ *
+ * RETURNS:   nothing
+ *
+ * SIDE EFFECTS:  rc_numBlocks
+ *
+ * NOTES:
+ *
+ *===========================================================================*/
+void incNumBlocks(num)
+     int num;
+{
+  rc_numBlocks += num;
+}
+
+
+/*===========================================================================*
+ *
+ * incMacroBlockBits()
+ *
+ *	Increments the number of Macro Block bits and the total of Frame
+ *  bits by the number passed.
+ *
+ * RETURNS:   nothing
+ *
+ * SIDE EFFECTS:  rc_totalMBBits
+ *
+ * NOTES:
+ *
+ *===========================================================================*/
+void incMacroBlockBits(num)
+     int num;
+{
+  rc_bitsThisMB = num;
+  rc_totalMBBits += num;
+  rc_totalFrameBits += num;
+}
+
+
+/*===========================================================================*
+ *
+ *   	needQScaleChange(current Q scale, 4 luminance blocks)
+ *
+ *
+ * RETURNS:     new Qscale
+ *
+ * SIDE EFFECTS:   
+ *
+ *===========================================================================*/
+int needQScaleChange(oldQScale, blk0, blk1, blk2, blk3)
+     int oldQScale;
+     Block blk0;
+     Block blk1;
+     Block blk2;
+     Block blk3;
+{
+  
+  /*   One more MacroBlock seen */
+  rc_numBlocks++;		/* this notes each block num in MB */
+  
+  checkBufferFullness(oldQScale);
+  
+  checkSpatialActivity(blk0, blk1, blk2, blk3);
+  
+  mquant = rc_Q * N_act;
+  Qscale = (mquant > 31 ? 31 : mquant);
+  Qscale = (Qscale < 1 ? 1 : Qscale);
+  rc_totalQuant += Qscale;
+  
+  if (oldQScale == Qscale)
+    return -1;
+  else
+    return Qscale;
+}
+
+
+/*===========================================================================*
+ *
+ * determineMBCount() 
+ *
+ *      Determines number of Macro Blocks in frame from the frame sizes
+ *	passed.
+ *
+ * RETURNS:     nothing
+ *
+ * SIDE EFFECTS:   sets the count passed
+ *
+ *===========================================================================*/
+int
+  determineMBCount ()
+{
+  int y,x;
+  
+  x = (Fsize_x +15)/16;
+  y = (Fsize_y +15)/16;
+  return  (x * y);
+}
+
+
+
+/*===========================================================================*
+ *
+ * void checkBufferFullness ()
+ *
+ *      Calculates the fullness of the virtual buffer for each
+ *  frame type.  Called before encoding each macro block.  Along
+ *  with the normalized spatial activity measure (N_act), it
+ *  determine the quantization factor for the next macroblock.
+ *
+ * RETURNS:     nothing
+ *
+ * SIDE EFFECTS:   the "currentVirtBuf" variable
+ *
+ * NOTES:
+ *
+ *===========================================================================*/
+void checkBufferFullness (oldQScale)
+     int oldQScale;
+{
+  int temp;
+  
+  temp = lastFrameVirtBuf + rc_totalFrameBits;
+  temp -=  (current_Tx * rc_numBlocks / MB_cnt);
+  currentVirtBuf = temp;
+  
+  rc_Q = (currentVirtBuf * 31 / reactionParameter);
+  return;
+}
+
+
+/*===========================================================================*
+ *
+ * void checkSpatialActivity()
+ *
+ *      Calcualtes the spatial activity for the four luminance blocks of the
+ *	macroblock.  Along with the normalized reference quantization parameter 
+ *  (rc_Q) , it determines the quantization factor for the next macroblock.
+ *
+ * RETURNS:     nothing
+ *
+ * SIDE EFFECTS:   the Adaptive quantization variables- act_j, N_act.
+ *
+ * NOTES:
+ *
+ *===========================================================================*/
+void checkSpatialActivity(blk0, blk1, blk2, blk3)
+     Block blk0;
+     Block blk1;
+     Block blk2;
+     Block blk3;
+{
+  int temp;
+  int16 *blkArray[4]; 
+  int16 *curBlock;
+  int16 *blk_ptr;
+  int var[4];
+  int i, j;
+  
+  
+  blkArray[0] = (int16 *) blk0;
+  blkArray[1] = (int16 *) blk1;
+  blkArray[2] = (int16 *) blk2;
+  blkArray[3] = (int16 *) blk3;
+  
+  
+  for (i =0; i < 4; i++) {	/* Compute the activity in each block */
+    curBlock = blkArray[i];
+    blk_ptr = curBlock;
+    P_mean = 0;
+    /*  Find the mean pixel value */
+    for (j=0; j < DCTSIZE_SQ; j ++) {
+      P_mean += *(blk_ptr++);
+      /*			P_mean += curBlock[j]; 
+				if (curBlock[j] != *(blk_ptr++)) {
+				printf("ARRAY ERROR: block %d\n", j);
+				}
+				*/
+    }
+    P_mean /= DCTSIZE_SQ;
+    
+    /*  Now find the variance  */
+    curBlock = blkArray[i];
+    blk_ptr = curBlock;
+    var[i] = 0;
+    for (j=0; j < DCTSIZE_SQ; j++) {
+#ifdef notdef
+      if (curBlock[j] != *(blk_ptr++)) {
+	printf("ARRAY ERROR: block %d\n", j);
+      }
+      temp = curBlock[j] - P_mean;
+#endif      
+      temp = *(blk_ptr++) - P_mean;
+      var[i] += (temp * temp);
+    }
+    var[i] /= DCTSIZE_SQ;
+  }
+  
+  /*  Choose the minimum variance from the 4 blocks and use as the activity */
+  var_sblk  = var[0];
+  for (i=1; i < 4; i++) {
+    var_sblk = (var_sblk < var[i] ? var_sblk : var[i]);
+  }
+  
+  
+  act_j = 1 + var_sblk;
+  total_act_j += act_j;
+  temp = (2 * act_j + avg_act);
+  N_act = ( (float) temp / (float) (act_j + 2*avg_act) );
+  
+  return;
+}
+
+
+
+
+/*============================================================================*
+ *
+ * getRateMode ()
+ *
+ *      Returns the rate mode- interpreted as either Fixed or Variable
+ *
+ * RETURNS:     integer
+ *
+ * SIDE EFFECTS:   none
+ *
+ *
+ *==========================================================================*/
+int getRateMode()
+{
+  return RateControlMode;
+}
+
+
+/*===========================================================================*
+ *
+ * setBitRate ()
+ *
+ *      Checks the string parsed from the parameter file.  Verifies
+ *  number and sets global values. MPEG standard specifies that bit rate
+ *	be rounded up to nearest 400 bits/sec.
+ *
+ * RETURNS:     nothing
+ *
+ * SIDE EFFECTS:   global variables
+ *
+ * NOTES:	Should this be in the 400-bit units used in sequence header?
+ *
+ *===========================================================================*/
+void setBitRate (const char * const charPtr)
+{
+  int rate, rnd;
+  
+  rate = atoi(charPtr);
+  if (rate > 0) {
+    RateControlMode = FIXED_RATE;
+  } else {
+    printf("Parameter File Error:  invalid BIT_RATE: \"%s\", defaults to Variable ratemode\n",
+	   charPtr);
+    RateControlMode = VARIABLE_RATE;
+    bit_rate = -1;
+  }
+  rnd = (rate % 400);
+  rate += (rnd ? 400 -rnd : 0); /* round UP to nearest 400 bps */
+  rate = (rate > MAX_BIT_RATE ? MAX_BIT_RATE : rate);
+  bit_rate = rate;
+  DBG_PRINT(("Bit rate is: %d\n", bit_rate));
+} 
+
+
+
+/*===========================================================================*
+ *
+ * getBitRate ()
+ *
+ *      Returns the bit rate read from the parameter file.  This is the
+ *  real rate in bits per second, not in 400 bit units as is written to
+ *  the sequence header.
+ *
+ * RETURNS:     int (-1 if Variable mode operation)
+ *
+ * SIDE EFFECTS:   none
+ *
+ *===========================================================================*/
+int getBitRate ()
+{
+  return bit_rate;
+}
+
+
+
+
+/*===========================================================================*
+ *
+ * setBufferSize ()
+ *
+ *      Checks the string parsed from the parameter file.  Verifies
+ *  number and sets global values.
+ *
+ * RETURNS:     nothing
+ *
+ * SIDE EFFECTS:   buffer_size global variable.
+ *
+ * NOTES:	The global is in bits, NOT the 16kb units used in sequence header
+ *
+ *===========================================================================*/
+void setBufferSize (const char * const charPtr)
+{
+  int size;
+  
+  size = atoi(charPtr);
+  size = (size > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : size);
+  if (size > 0) {
+    size = (16*1024) * ((size + (16*1024 - 1)) / (16*1024));
+    buffer_size = size;
+  } else {
+    buffer_size = DEFAULT_BUFFER_SIZE;
+    printf("Parameter File Error:  invalid BUFFER_SIZE: \"%s\", defaults to : %d\n",
+	   charPtr, buffer_size);
+  }
+  DBG_PRINT(("Buffer size is: %d\n", buffer_size));
+}
+
+
+/*===========================================================================*
+ *
+ * getBufferSize ()
+ *
+ *      returns the buffer size read from the parameter file.  Size is
+ *  in bits- not in units of 16k as written to the sequence header.
+ *
+ * RETURNS:     int (or -1 if invalid)
+ *
+ * SIDE EFFECTS:   none
+ *
+ *===========================================================================*/
+int getBufferSize ()
+{
+  return buffer_size;
+}
+
+
+