/***************************************************************** * ratectlr.c, TMN4 Rate Control Routines * Note : This program was modified from rate conrol of MPEG * Modified to fit TMN4 public domain coder of Telenor R&D * * Date: 1/5/95 Author: Anurag Bist * Rockwell International * 950118 Modified: Karl.Lillevold@nta.no *****************************************************************/ #include #include #include "sim.h" /* rate control static variables */ static float B_prev; /* number of bits spent for the previous frame */ static float B_target; /* target number of bits/picture */ static float new_target_framerate;/* target frame rate */ static float global_adj; /* due to bits spent for the previous frame */ static int buffer_content;/* buffer content */ /************************************************************************* * Name: InitializePictureRate * * Description: This routine computes the target bit rate and the target * frame rate for the current picture being coded. * It also computes the adjustment due to bit spent for the * previous picture. This is done at start of each frame. * * Input: Mean Quantizer parameter value from past picture, * pic type (intra or inter), * bit rate, source frame rate & current total bit count. * * Returns: * * Side effects: Computes adjustment due to bit spent for the * previous picture, target * frame rate and target bit rate. * * Date:1/5/95 Author: Anurag Bist * **************************************************************************/ void InitializePictureRate(float QP_mean, int pict_type, float bit_rate, int src_frame_rate, int bitcount) /* QP_mean = mean quantizer parameter for the previous picture */ /* bitcount = current total bit count */ /* To calculate bitcount in coder.c, do something like this : */ /* int bitcount; */ /* AddBitsPicture(bits); */ /* bitcount = bits->total; */ { if (pict_type == PCT_INTRA) { new_target_framerate = target_framerate; B_target = bit_rate / new_target_framerate; } else if (pict_type == PCT_INTER) { new_target_framerate = (target_framerate+4 - (QP_mean/4.0) + 0.5); /* clip target frame rate value */ if (new_target_framerate < 3) new_target_framerate = 4.0; if (new_target_framerate > 15) new_target_framerate = 15.0; B_target = bit_rate / new_target_framerate; /* compute picture buffer descrepency as of the previous picture */ global_adj = (B_prev - B_target) / (2*B_target); } else { fprintf(stderr,"Error (InitializePictureRate): picture type unkown.\n"); } #if 0 printf("global_adj = %.4f \n",global_adj); #endif fprintf(stdout,"Target frame rate: %.2f\n",new_target_framerate); fprintf(stdout,"Target no. of bits: %.2f\n", B_target); } /********************************************************************* * Name: UpdateQuantizer * * * Description: This function generates a new quantizer step size based * on bits spent up until current macroblock and bits * spent from the previous picture. Note: this * routine should be called at the beginning of each * macroblock line as specified by TMN4. However, this * can be done at any macroblock if so desired. * * Input: current macroblock number (raster scan), mean quantizer * paramter for previous picture, bit rate, source frame rate, * hor. number of macroblocks, vertical number of macroblocks, total # * of bits used until now in the current picture. * * Returns: Returns a new quantizer step size for the use of current * macroblock Note: adjustment to fit with 2-bit DQUANT should be done * in the calling program. * * Side Effects: * * Date: 1/5/95 Author: Anurag Bist * **********************************************************************/ int UpdateQuantizer(int mb, float QP_mean, int pict_type, float bit_rate, int mb_width, int mb_height, int bitcount) /* mb = macroblock index number */ /* QP_mean = mean quantizer parameter for the previous picture */ /* bitcount = total # of bits used until now in the current picture */ { int QP_new=16; float local_adj, descrepency, projection; if (pict_type == PCT_INTRA) { QP_new = 16; } else if (pict_type == PCT_INTER) { /* compute expected buffer fullness */ projection = mb * (B_target / (mb_width*mb_height)); /* measure descrepency between current fullness and projection */ descrepency= (bitcount - projection); /* scale */ local_adj = 12 * descrepency / bit_rate; #if 0 printf("mb = %d\n",mb); printf("bit_count = %d projection = %.2f \n",bitcount,projection); printf("B_target = %.2f local_adj = %.2f \n",B_target,local_adj); #endif QP_new = (int)(QP_mean * (1 + global_adj + local_adj) + 0.5); /* the update equation for QP_new in TMN4 document section 3.7 */ } else { fprintf(stderr,"Error (UpdateQuantizer): picture type unkown.\n"); } #if 0 printf("mb = %d QP_new = %d \n",mb,QP_new); #endif return QP_new; } /************************************************************************** * Name: UpdatePictureRate * * Description: This routine updates buffer content and determines * frame skips * * Input: pict type, bit rate, source frame rate, bit count * * Side Effects: updates buffer_content, B_prev * * Result: Returns frames skip (frame_incr) * * Date: 1/5/95 Author: Anurag Bist * * ****************************************************************************/ int UpdatePictureRate(int pict_type, float bit_rate, int src_frame_rate, int bitcount) { int frame_inc = 1; /* set frame_incr at least to 1 */ fprintf(stdout,"\nActual number of bits spent: %d\n",bitcount); if (pict_type == PCT_INTRA) { buffer_content = bit_rate/new_target_framerate + 3*(bit_rate/src_frame_rate); B_prev = B_target; /* why not the B for the INTRA coded frame? */ } else { /* INTER */ buffer_content += bitcount; B_prev = bitcount; } buffer_content -= (bit_rate/src_frame_rate); /* frame_inc is at least one */ fprintf(stdout,"Buffer contents before skipping: %d\n", buffer_content); while (buffer_content > 3*(bit_rate/src_frame_rate)) { buffer_content -= (bit_rate/src_frame_rate); frame_inc++; } fprintf(stdout,"Frame increment: %d\n", frame_inc); fprintf(stdout,"Buffer contents after skipping: %d\n", buffer_content); return frame_inc; }