📄 ratecontrol.c
字号:
bRC->PPictureIndexinGOP++; if(!(bRC->ignoreIDR && img_type == SLICE_I)) bRC->bitDifference += (texbits+headerbits-bRC->bitsPerFrame); bRC->TotalBits += (texbits+headerbits); if(img_type ==SLICE_P){ if( ((bRC->PictureIndex % bRC->BIT_ADJUST_FREQUENCY) == 0) && (bRC->PictureIndex > 0)) { if(bRC->numFrms>0) { //Number of frames to code is known#ifdef STRICT_FILE_SIZE_CONTROL bRC->bitsPerPFrame = bRC->bitsPerFrame - (bRC->bitDifference)/(MIN(bRC->BIT_ADJUST_WINDOW,bRC->numFrms - bRC->PictureIndex+1)) ; bRC->bitsPerPFrame = (int)((bRC->bitsPerPFrame)*(bRC->numNonref+1)*1.0/(1+0.5*bRC->numNonref)); #else bRC->bitsPerPFrame = bRC->bitsPerFrame - (bRC->bitDifference)/(bRC->BIT_ADJUST_WINDOW) ; bRC->bitsPerPFrame = (int)(bRC->bitsPerPFrame)*(bRC->numNonref+1)*1.0/(1+0.5*bRC->numNonref);#endif } else { bRC->bitsPerPFrame = bRC->bitsPerFrame - (bRC->bitDifference)/(bRC->BIT_ADJUST_WINDOW); bRC->bitsPerPFrame = (int)((bRC->bitsPerPFrame)*(bRC->numNonref+1)*1.0/(1+0.5*bRC->numNonref)); } if(bRC->bitsPerPFrame < bRC->bitsPerFrame) bRC->bitsPerPFrame = (int)(MAX(bRC->bitsPerPFrame,bRC->bitsPerFrame/2.0)); } } else if(img_type == SLICE_I) { bRC->bitsPerPFrame = bRC->bitsPerFrame - (bRC->bitDifference)/(MAX(15,bRC->GOPSize)); bRC->bitsPerPFrame = (int)((bRC->bitsPerPFrame)*(bRC->numNonref+1)*1.0/(1+0.5*bRC->numNonref)); if(bRC->bitsPerPFrame < bRC->bitsPerFrame) bRC->bitsPerPFrame = (int)(MAX(bRC->bitsPerPFrame,bRC->bitsPerFrame/2.0)); } if(bRC->PPictureIndexinGOP >= 2) bRC->use_sh_RD_Model= 1; if(bRC->PictureIndex>= 3 ||bRC->PPictureIndexinGOP >= 2) { bRC->use_lt_RD_Model= 1; } #ifdef USE_SPP if(bRC->SPPPictureCounter == 0) bRC->SPPPictureCounter = SPP_PICTURE_FREQ;#endif picqstep=QP2Qstep((int)floor(bRC->averageQPforFrame)); if(bRC->bufferStall) { // if(!(img_type == SLICE_I && bRC->ignoreIDR == 1)) bRC->CurrentBufferFullness += texbits + headerbits ; if(bRC->CurrentBufferFullness > bRC->TargetBufferLevel) { bRC->playingStartFrame = bRC->PictureIndex; bRC->CurrentBufferFullness -= bRC->bitsPerFrame; bRC->bufferStall = 0; } } else { // if(!(img_type == SLICE_I && bRC->ignoreIDR == 1)) bRC->CurrentBufferFullness += texbits + headerbits - bRC->bitsPerFrame ; } bRC->CurrentBufferFullness = MIN(bRC->BufferSize,MAX(bRC->CurrentBufferFullness,0)); //Overflow and Underflow handled elsewhere for(i=MAX_LT_RD_WINDOW_SIZE-1;i>0;i--) bRC->BufferFullnessArray[i] = bRC->BufferFullnessArray[i-1]; bRC->BufferFullnessArray[0] = bRC->CurrentBufferFullness; //Update the Model Parameters for(i=0;i<bRC->TotalNumberofMB;i++) { bRC->prevFrame_MBsad[i]=bRC->currentFrame_MBsad[i]; bRC->prevFrame_MBQp[i]=bRC->currentFrame_MBQp[i]; bRC->prevFrame_MBtexbits[i]=bRC->currentFrame_MBtexbits[i]; bRC->prevFrame_MBheaderbits[i]=bRC->currentFrame_MBheaderbits[i]; } for(i=MAX_LT_RD_WINDOW_SIZE-1;i>0;i--) bRC->framePSNR[i] = bRC->framePSNR[i-1]; bRC->framePSNR[i] = psnrY; if(img_type == SLICE_I) { if(bRC->scut != 1) { //Due to GOP start if(bRC->GOPSize > 1) { bRC->bitsPerPFrame = bRC->bitsPerFrame - (texbits+headerbits - bRC->bitsPerPFrame) / (bRC->GOPSize - 1) ; if(bRC->numFrms>0) //Number of frames to code is known bRC->bitsPerPFrame -= (bRC->bitDifference-texbits-headerbits+bRC->bitsPerFrame)/(bRC->numFrms - bRC->PictureIndex + 1) ; else bRC->bitsPerPFrame -= (bRC->bitDifference-texbits-headerbits+bRC->bitsPerFrame)/(100) ; } } else { //Due to Scene cut if(bRC->GOPSize > 1) { //Compensate the additional I frame over the course of 30 frames bRC->bitsPerPFrame = bRC->bitsPerFrame - (texbits+headerbits - bRC->bitsPerPFrame) / (30) ; if(bRC->numFrms>0) //Number of frames to code is known bRC->bitsPerPFrame -= (bRC->bitDifference-texbits-headerbits+bRC->bitsPerFrame)/(bRC->numFrms - bRC->PictureIndex + 1) ; else bRC->bitsPerPFrame -= (bRC->bitDifference-texbits-headerbits+bRC->bitsPerFrame)/(100) ; } } } else if(img_type == SLICE_P) {#ifdef USE_SPP bRC->SPPPictureCounter--;#endif //Update the Bit, MAD and RD Arrays for(i=MAX_RD_WINDOW_SIZE-1;i>0;i--) { bRC->rdModel_QP[i] = bRC->rdModel_QP[i-1]; if(texbits > 0 && headerbits > 0) { bRC->rdModel_TextureBits[i] = bRC->rdModel_TextureBits[i-1]; bRC->rdModel_HeaderBits[i] = bRC->rdModel_HeaderBits[i-1]; bRC->rdModel_PictureMAD[i] = bRC->rdModel_PictureMAD[i-1]; bRC->rdModel_Qstep[i] = bRC->rdModel_Qstep[i-1]; } } for(i=MAX_LT_RD_WINDOW_SIZE-1;i>0;i--) { if(texbits > 0 && headerbits > 0) { bRC->lt_rdModel_TextureBits[i] = bRC->lt_rdModel_TextureBits[i-1]; bRC->lt_rdModel_HeaderBits[i] = bRC->lt_rdModel_HeaderBits[i-1]; bRC->lt_rdModel_PictureMAD[i] = bRC->lt_rdModel_PictureMAD[i-1]; bRC->lt_rdModel_Qstep[i] = bRC->lt_rdModel_Qstep[i-1]; } } if(texbits > 0 || headerbits > 0) { if(headerbits > 0) { bRC->rdModel_HeaderBits[0] = headerbits; bRC->lt_rdModel_HeaderBits[0] = headerbits; } if(texbits > 0) { bRC->rdModel_TextureBits[0] = texbits; bRC->lt_rdModel_TextureBits[0] = texbits; } if(ComputePictureMAD(bRC) > 0) { bRC->rdModel_PictureMAD[0] = ComputePictureMAD(bRC); bRC->lt_rdModel_PictureMAD[0] = bRC->rdModel_PictureMAD[0]; } bRC->rdModel_Qstep[0] = picqstep; bRC->lt_rdModel_Qstep[0] = picqstep; bRC->rdModel_QP[0] = bRC->averageQPforFrame; } MADUpdateFlag=1; } if(img_type == SLICE_P) { //Compute the size of windows tempRDSize = (bRC->rdModel_PictureMAD[0]>bRC->rdModel_PictureMAD[1])?(int)(bRC->rdModel_PictureMAD[1]/bRC->rdModel_PictureMAD[0]*MAX_RD_WINDOW_SIZE) :(int)(bRC->rdModel_PictureMAD[0]/bRC->rdModel_PictureMAD[1]*MAX_RD_WINDOW_SIZE); tempRDSize=MAX(tempRDSize, 1); tempRDSize=MIN(tempRDSize,bRC->rdModel_windowSize+1); tempRDSize=MIN(tempRDSize,MAX_RD_WINDOW_SIZE); lt_tempRDSize = (bRC->lt_rdModel_PictureMAD[0]>bRC->lt_rdModel_PictureMAD[1])?(int)(bRC->lt_rdModel_PictureMAD[1]/bRC->lt_rdModel_PictureMAD[0]*MAX_LT_RD_WINDOW_SIZE) :(int)(bRC->lt_rdModel_PictureMAD[0]/bRC->lt_rdModel_PictureMAD[1]*MAX_LT_RD_WINDOW_SIZE); lt_tempRDSize=MAX(lt_tempRDSize, 1); lt_tempRDSize=MIN(lt_tempRDSize,bRC->lt_rdModel_windowSize+1); lt_tempRDSize=MIN(lt_tempRDSize,MAX_LT_RD_WINDOW_SIZE); bRC->rdModel_windowSize=tempRDSize; bRC->lt_rdModel_windowSize=lt_tempRDSize; //Update the RD Model for (i = 0; i < MAX_RD_WINDOW_SIZE; i++) bRC->rdModel_Rejected[i] = 0; // initial RD model estimator RDModelEstimator (bRC,img_type); // remove outlier for (i = 0; i < (int) tempRDSize; i++) { error[i] = 1.0f*bRC->rdModel_X1 /( bRC->rdModel_Qstep[i]) + 1.0f*bRC->rdModel_X2 /( bRC->rdModel_Qstep[i] * bRC->rdModel_Qstep[i]) - bRC->rdModel_TextureBits[i]*1.0f/bRC->rdModel_PictureMAD[i]; std += error[i] * error[i]; } threshold = (float)((tempRDSize == 2) ? 0 : sqrt (std / tempRDSize)); for (i = 0; i < (int) tempRDSize; i++) { if (fabs(error[i]) > threshold) bRC->rdModel_Rejected[i] = 1; } // always include the last data point bRC->rdModel_Rejected[0] = 0; // second RD model estimator RDModelEstimator (bRC, img_type); //************** Update the long term RD Model ******************* //Update the RD Model for (i = 0; i < MAX_LT_RD_WINDOW_SIZE; i++) bRC->lt_rdModel_Rejected[i] = 0; // initial RD model estimator lt_RDModelEstimator (bRC,img_type); // remove outlier for (i = 0; i < (int) lt_tempRDSize; i++) { lt_error[i] = bRC->lt_rdModel_X1 /( bRC->lt_rdModel_Qstep[i]) + bRC->lt_rdModel_X2 /( bRC->lt_rdModel_Qstep[i] * bRC->lt_rdModel_Qstep[i]) - bRC->lt_rdModel_TextureBits[i]*1.0f/bRC->lt_rdModel_PictureMAD[i]; lt_std += lt_error[i] * lt_error[i]; } threshold = (lt_tempRDSize == 2) ? 0 :(float) sqrt (lt_std / lt_tempRDSize); for (i = 0; i < (int) lt_tempRDSize; i++) { if (fabs(lt_error[i]) > threshold) bRC->lt_rdModel_Rejected[i] = 1; } // always include the last data point bRC->lt_rdModel_Rejected[0] = 0; // second RD model estimator lt_RDModelEstimator (bRC, img_type); } hdrSize=bRC->lt_rdModel_windowSize; hdrSize=MIN(hdrSize,MAX_LT_RD_WINDOW_SIZE); if(bRC->use_lt_RD_Model== 1 && img_type == SLICE_P) { avgHeaderBits = getAverageHeaderBits(bRC,hdrSize,1); avgTextureBits = getAverageTextureBits(bRC,hdrSize,1); avgMAD = getAverageMAD(bRC,hdrSize,1); tex = bRC->bitsPerPFrame*avgTextureBits/(avgTextureBits+avgHeaderBits); if(avgTextureBits > 0 ) { Qaver = getQP_UsingRDModel(tex, avgMAD, bRC->lt_rdModel_X1, bRC->lt_rdModel_X2); } else Qaver = (int) bRC->averageQPforFrame-1; } else Qaver = (int) bRC->averageQPforFrame; if(bRC->GOPSize == 0) { //No GOPs if(bRC->PictureIndex%bRC->LT_WINDOW_QP_UPDATE_FREQ == 0 || bRC->PictureIndex<15 || bRC->PPictureIndexinGOP == 0) { if(bRC->PictureIndex > 3) { if( avgHeaderBits<bRC->bitsPerPFrame ) { if(Qaver > bRC->QP_LW) bRC->QP_LW = MIN(Qaver, bRC->QP_LW+2); else bRC->QP_LW = MAX(Qaver, bRC->QP_LW-2); } else bRC->QP_LW++; } else if(img_type == SLICE_P) bRC->QP_LW = Qaver; } } else if(bRC->PictureIndex%bRC->GOPSize == 0 || bRC->PictureIndex%bRC->LT_WINDOW_QP_UPDATE_FREQ==0 || bRC->PictureIndex<15 || bRC->PPictureIndexinGOP == 0 || bRC->use_lt_RD_Model == 0) { if(bRC->PictureIndex > 3) { if( avgHeaderBits<bRC->bitsPerPFrame ) { if(Qaver > bRC->QP_LW) bRC->QP_LW = MIN(Qaver, bRC->QP_LW+2); else bRC->QP_LW = MAX(Qaver, bRC->QP_LW-2); } else bRC->QP_LW++; } else if(img_type == SLICE_P) bRC->QP_LW = Qaver; } bRC->QP_LW = MIN(50,MAX(1,bRC->QP_LW)); return AVCE_OK; }//compute a quantization parameter for each frameint rc_getFrameQP(rateCtrl_s *bRC, int img_type){ /*frame layer rate control*/ if(img_type==SLICE_I && bRC->PictureIndex == 0) { bRC->averageQPforFrame = (float) bRC->InitialQP; bRC->frameReturnedQP = (int)bRC->InitialQP; return bRC->frameReturnedQP; } else if(img_type == SLICE_I) return bRC->frameReturnedQP = bRC->frameComputedQP; else if((img_type==SLICE_P)&&(bRC->PPictureIndexinGOP==0)) {#ifdef USE_SPP if(bRC->SPPPictureCounter == 0) return bRC->frameReturnedQP = bRC->SPPframeComputedQP; else#endif if(bRC->BufferSize < bRC->bit_rate) return bRC->frameComputedQP = bRC->frameReturnedQP = (int)(bRC->averageQPforFrame)+2; else { if(bRC->use_lt_RD_Model == 0 && bRC->use_sh_RD_Model == 0) return bRC->frameComputedQP = bRC->frameReturnedQP = (int)(bRC->averageQPforFrame); else return bRC->frameReturnedQP=bRC->frameComputedQP; } } else #ifdef USE_SPP if(bRC->SPPPictureCounter == 0) return bRC->frameReturnedQP = bRC->SPPframeComputedQP; else#endif return bRC->frameReturnedQP = bRC->frameComputedQP; }int Qstep2QP( float Qstep ){ int q_per = 0, q_rem = 0; if( Qstep < QP2Qstep(0)) return 0; else if (Qstep > QP2Qstep(51) ) return 51; while( Qstep > QP2Qstep(5) ) { Qstep /= 2; q_per += 1; } if (Qstep <= (0.625+0.6875)/2) { Qstep = 0.625; q_rem = 0; } else if (Qstep <= (0.6875+0.8125)/2) { Qstep = 0.6875; q_rem = 1; } else if (Qstep <= (0.8125+0.875)/2) { Qstep = 0.8125; q_rem = 2; } else if (Qstep <= (0.875+1.0)/2) { Qstep = 0.875; q_rem = 3; } else if (Qstep <= (1.0+1.125)/2) { Qstep = 1.0; q_rem = 4; } else { Qstep = 1.125; q_rem = 5; } return (q_per * 6 + q_rem);}float QP2Qstep( int QP ){ int i; float Qstep; static const float QP2QSTEP[6] = { 0.625, 0.6875, 0.8125, 0.875, 1.0, 1.125 }; Qstep = QP2QSTEP[QP % 6]; for( i=0; i<(QP/6); i++) Qstep *= 2; return Qstep;}void RDModelEstimator (rateCtrl_s *bRC, int img_type){ int n_windowSize = bRC->rdModel_windowSize; int n_realSize = n_windowSize; int i; float oneSampleQ=0.0; float a00 = 0.0f, a01 = 0.0f, a10 = 0.0f, a11 = 0.0f, b0 = 0.0f, b1 = 0.0f; float MatrixValue; Boolean estimateX2 = 0; if(img_type == SLICE_I) return; for (i = 0; i < n_windowSize; i++) {// find the number of samples which are not rejected if (bRC->rdModel_Rejected[i]) n_realSize--; } // default RD model estimation results bRC->rdModel_X1 = bRC->rdModel_X2= 0.0f; for (i = 0; i < n_windowSize; i++) { if (!bRC->rdModel_Rejected[i]) oneSampleQ = bRC->rdModel_Qstep[i]; } for (i = 0; i < n_windowSize; i++) {// if all non-rejected Q are the same, take 1st order model if ((bRC->rdModel_Qstep[i] != oneSampleQ) && !bRC->rdModel_Rejected[i]) estimateX2 = 1; if (!bRC->rdModel_Rejected[i]) bRC->rdModel_X1 += (bRC->rdModel_Qstep[i] * bRC->rdModel_TextureBits[i]*1.0f/bRC->rdModel_PictureMAD[i]) / n_realSize; } // take 2nd order model to estimate X1 and X2 if ((n_realSize >= 1) && estimateX2) { for (i = 0; i < n_windowSize; i++) { if (!bRC->rdModel_Rejected[i]) { a00 = a00 + 1.0f; a01 += 1.0f / bRC->rdModel_Qstep[i]; a10 = a01; a11 += 1.0f / (bRC->rdModel_Qstep[i] * bRC->rdModel_Qstep[i]); b0 += (bRC->rdModel_Qstep[i] * bRC->rdModel_TextureBits[i]*1.0f/bRC->rdModel_PictureMAD[i]); b1 += bRC->rdModel_TextureBits[i]*1.0f/bRC->rdModel_PictureMAD[i]; } } // solve the equation of AX = B MatrixValue=a00*a11-a01*a10; if(fabs(MatrixValue)>0.000001f) { bRC->rdModel_X1 = (b0*a11-b1*a01)/MatrixValue; bRC->rdModel_X2 = (b1*a00-b0*a10)/MatrixValue; } else { bRC->rdModel_X1 = b0/a00; bRC->rdModel_X2 = 0.0f; } } }void lt_RDModelEstimator(rateCtrl_s *bRC, int img_type){ int n_windowSize = bRC->lt_rdModel_windowSize; int n_realSize = n_windowSize; int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -