diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/ppm/ppmtompeg/rate.c | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/ppm/ppmtompeg/rate.c')
-rw-r--r-- | converter/ppm/ppmtompeg/rate.c | 986 |
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; +} + + + |