/*===========================================================================* * * initRateControl * * initialize the allocation parameters. * * RETURNS: nothing * * SIDE EFFECTS: many global variables * * NOTES: Get rid of the redundant pattern stuff!! *===========================================================================*/ int initRateControl() { int index; int result; DBG_PRINT(("\tInitializing Allocation Data\n")); #ifdef RC_STATS_FILE RC_FILE = fopen("RC_STATS_FILE", "w"); if ( RC_FILE == NULL) { DBG_PRINT(("\tOpen of RC file failed, using stderr\n")); RC_FILE = stderr; fprintf(RC_FILE, "\tOpen of RC file failed, using stderr\n"); fflush(RC_FILE); } #endif /* Initialize Pattern info */ GOP_X = framePatternLen; for ( index = 0; index < framePatternLen; index++ ) { switch( framePattern[index] ) { case 'i': GOP_I++; break; case 'p': GOP_P++; break; case 'b': GOP_B++; break; default: printf("\n\tERROR rate.c - BAD PATTERN!\n"); RateControlMode = VARIABLE_RATE; return (0); } } if (GOP_X != (GOP_I + GOP_P + GOP_B )) { printf("\n\tERROR rate.c - Pattern Length Mismatch\n"); 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 = (int)(Kp * d0_i); d0_b = (int)(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 = (int)(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(("\tVBV- delay: %d, fill rate: %d, delay/Frame: %d units, buffer size: %d\n", VBV_delay, bufferFillRate, frameDelayIncrement, buffer_size)); result = initGOPRateControl(); return result; }
/*===========================================================================* * * 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 *frame) { float temp1, minimumBits; float tempX, tempY, tempZ; int result; int frameType; 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'; /* temp1 = ( rc_R / ( 1+ ((Np * Xp) / (Xi * Kp)) + ((Nb*Xb) / (Xi*Kb))))); */ 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 = (int)(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)); } else { return; } return; }
/*===========================================================================* * * 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); pm_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; }