📄 ratecontrol.c
字号:
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->lt_rdModel_Rejected[i]) n_realSize--; } // default RD model estimation results bRC->lt_rdModel_X1 = bRC->lt_rdModel_X2= 0.0f; for (i = 0; i < n_windowSize; i++) { if (!bRC->lt_rdModel_Rejected[i]) oneSampleQ = bRC->lt_rdModel_Qstep[i]; } for (i = 0; i < n_windowSize; i++) {// if all non-rejected Q are the same, take 1st order model if ((bRC->lt_rdModel_Qstep[i] != oneSampleQ) && !bRC->lt_rdModel_Rejected[i]) estimateX2 = 1; if (!bRC->lt_rdModel_Rejected[i]) bRC->lt_rdModel_X1 += (bRC->lt_rdModel_Qstep[i] * bRC->lt_rdModel_TextureBits[i]*1.0f/bRC->lt_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->lt_rdModel_Rejected[i]) { a00 = a00 + 1.0f; a01 += 1.0f / bRC->lt_rdModel_Qstep[i]; a10 = a01; a11 += 1.0f / (bRC->lt_rdModel_Qstep[i] * bRC->lt_rdModel_Qstep[i]); b0 += (bRC->lt_rdModel_Qstep[i] * bRC->lt_rdModel_TextureBits[i]*1.0f/bRC->lt_rdModel_PictureMAD[i]); b1 += bRC->lt_rdModel_TextureBits[i]*1.0f/bRC->lt_rdModel_PictureMAD[i]; } } // solve the equation of AX = B MatrixValue=a00*a11-a01*a10; if(fabs(MatrixValue)>0.000001f) { bRC->lt_rdModel_X1 = (b0*a11-b1*a01)/MatrixValue; bRC->lt_rdModel_X2 = (b1*a00-b0*a10)/MatrixValue; } else { bRC->lt_rdModel_X1 = b0/a00; bRC->lt_rdModel_X2 = 0.0f; } } }float ComputePictureMAD(rateCtrl_s *bRC){ float TotalMAD; int i; TotalMAD=0.0; for(i=0;i<bRC->TotalNumberofMB;i++) TotalMAD +=bRC->MSEofMB[i]; //TotalMAD /=(bRC->TotalNumberofMB*256); return TotalMAD;}int getQP_UsingRDModel(int targetBits, float mad, float X1, float X2){ float deltaTemp; float Qstep; int q; deltaTemp = mad * X1 * mad * X1 + 4 * X2* mad * targetBits; if ((X2 == 0.0) || (deltaTemp < 0) || ((sqrt (deltaTemp) - X1 * mad) <= 0.0)) // fall back 1st order mode Qstep = (float) (X1 * mad / (float) targetBits); else // 2nd order mode Qstep = (float) ((2 * X2 * mad) / (sqrt (deltaTemp) - X1 * mad)); q=Qstep2QP(Qstep); return q; }int getAverageHeaderBits(rateCtrl_s *bRC, int windowSize, int lt) { int i; int headerbits=0; int *parr = bRC->rdModel_HeaderBits; if(lt == 1) parr = bRC->lt_rdModel_HeaderBits; for(i=0;i<windowSize;i++) headerbits+=parr[i]; if(windowSize>0) headerbits=headerbits/windowSize; else headerbits=0; return headerbits;}int getAverageTextureBits(rateCtrl_s *bRC, int windowSize,int lt) { int i; int texbits=0; int *parr = bRC->rdModel_TextureBits; if(lt == 1) parr = bRC->lt_rdModel_TextureBits; for(i=0;i<windowSize;i++) texbits+=parr[i]; if(windowSize>0) texbits=texbits/windowSize; else texbits=0; return texbits;}float getAverageMAD(rateCtrl_s *bRC, int windowSize,int lt) { int i; float mad=0.0; float *parr = bRC->rdModel_PictureMAD; int *prejected = bRC->rdModel_Rejected; int n_realSize = windowSize; if(lt == 1) { prejected = bRC->lt_rdModel_Rejected; parr = bRC->lt_rdModel_PictureMAD; } for (i = 0; i < windowSize; i++) {// find the number of samples which are not rejected if (prejected[i]) n_realSize--; } for(i=0;i<windowSize;i++) { if (!prejected[i]) mad+=parr[i]; } if(n_realSize>0) mad=mad/n_realSize; else mad=0; return mad;}void createBitEnvelope(rateCtrl_s *bRC){ //Creates the upper and lower limits using PI Buffer Regulator float Et = (bRC->TargetBufferLevel - bRC->CurrentBufferFullness)*1.0f / bRC->TargetBufferLevel; //Proportional float Etau=0; float PIError; int i; bRC->upperFrameLimit = (int)(bRC->bitsPerPFrame*bRC->UPPER_LIMIT_MULTIPLE); bRC->lowerFrameLimit = (int)(bRC->bitsPerPFrame/bRC->LOWER_LIMIT_MULTIPLE); if(bRC->BufferSize > bRC->bit_rate/2) { if(bRC->img_type == SLICE_I) { bRC->upperFrameLimit = (bRC->bitsPerFrame*bRC->I_P_RATIO); bRC->lowerFrameLimit = (bRC->upperFrameLimit/2); return; } if(!bRC->bufferStall ) { for(i=0;i<MIN(30,(bRC->PictureIndex-bRC->playingStartFrame));i++) { if(bRC->BufferFullnessArray[i]>0) Etau+=(bRC->TargetBufferLevel - bRC->BufferFullnessArray[i])*1.0f / bRC->TargetBufferLevel; } //Then create upper and lower limits otherwise do not touch PIError = Kp*(Et+Etau*Ki); if(PIError<0) { bRC->upperFrameLimit = (int)((1+MAX(-0.5f,PIError)) * bRC->bitsPerPFrame*bRC->UPPER_LIMIT_MULTIPLE); bRC->upperFrameLimit = MIN(bRC->BufferSize - bRC->CurrentBufferFullness , bRC->upperFrameLimit); } else { if(bRC->nalRefIdc == 1) { bRC->lowerFrameLimit = (int)((1+MIN(5,PIError*8)) * bRC->bitsPerPFrame/bRC->LOWER_LIMIT_MULTIPLE); bRC->lowerFrameLimit = MAX( (2*bRC->bitsPerPFrame - bRC->CurrentBufferFullness) , bRC->lowerFrameLimit); } else bRC->lowerFrameLimit = bRC->bitsPerPFrame - bRC->CurrentBufferFullness; } //Check if we are approaching to a start of GOP if( bRC->GOPSize - (bRC->PictureIndex%bRC->GOPSize) <= 5 ) { //Check the Buffer size, change the envelope accordingly if( (bRC->BufferSize - bRC->CurrentBufferFullness) < bRC->bitsPerFrame * 5) { bRC->upperFrameLimit = (int)(1.1 * (bRC->CurrentBufferFullness - (bRC->BufferSize - bRC->bitsPerFrame*5))/(1.0*(bRC->GOPSize - (bRC->PictureIndex%bRC->GOPSize)))); } } } else { bRC->upperFrameLimit = (int)(bRC->bitsPerPFrame*bRC->UPPER_LIMIT_MULTIPLE); bRC->lowerFrameLimit = (int)(bRC->bitsPerPFrame/bRC->LOWER_LIMIT_MULTIPLE); if(bRC->nalRefIdc == 0) bRC->lowerFrameLimit = bRC->bitsPerPFrame - bRC->CurrentBufferFullness; } /*if(bRC->upperFrameLimit < bRC->bitsPerFrame/LOWER_LIMIT_MULTIPLE) bRC->upperFrameLimit = (int)(bRC->bitsPerFrame/LOWER_LIMIT_MULTIPLE); if(bRC->lowerFrameLimit > bRC->bitsPerFrame*UPPER_LIMIT_MULTIPLE) bRC->upperFrameLimit = (int)(bRC->bitsPerFrame*UPPER_LIMIT_MULTIPLE);*/ if(bRC->lowerFrameLimit < bRC->bitsPerFrame/bRC->LOWER_LIMIT_MULTIPLE) bRC->lowerFrameLimit = (int)(bRC->bitsPerFrame/bRC->LOWER_LIMIT_MULTIPLE); if(bRC->upperFrameLimit > bRC->bitsPerFrame*bRC->UPPER_LIMIT_MULTIPLE) bRC->upperFrameLimit = (int)(bRC->bitsPerFrame*bRC->UPPER_LIMIT_MULTIPLE); } else { if(bRC->img_type == SLICE_I) { bRC->upperFrameLimit = (int)MAX(bRC->bitsPerFrame,MIN(bRC->BufferSize*0.95f-bRC->CurrentBufferFullness+bRC->bitsPerFrame, bRC->bitsPerFrame*bRC->I_P_RATIO)); bRC->lowerFrameLimit = bRC->upperFrameLimit - bRC->bitsPerFrame; return; } bRC->centerFrameBits = bRC->bitsPerPFrame; if(bRC->CurrentBufferFullness < 0) { bRC->upperFrameLimit = (int)(bRC->bitsPerFrame*bRC->UPPER_LIMIT_MULTIPLE); bRC->lowerFrameLimit = (int)(bRC->bitsPerFrame*1.5f); bRC->centerFrameBits = bRC->lowerFrameLimit; } else { if(bRC->CurrentBufferFullness >= bRC->BufferSize/2) { bRC->upperFrameLimit = (int)(bRC->bitsPerPFrame * (bRC->UPPER_LIMIT_MULTIPLE - (bRC->UPPER_LIMIT_MULTIPLE - 1)*(bRC->CurrentBufferFullness - bRC->BufferSize/2)*1.0f/bRC->BufferSize)); bRC->centerFrameBits = MIN(bRC->upperFrameLimit,bRC->bitsPerPFrame); bRC->lowerFrameLimit = (int)(bRC->centerFrameBits / bRC->LOWER_LIMIT_MULTIPLE); } else { bRC->lowerFrameLimit = (int)(bRC->bitsPerFrame * (1-1.0f/bRC->LOWER_LIMIT_MULTIPLE)*2.0f/bRC->BufferSize*bRC->CurrentBufferFullness); bRC->centerFrameBits = MIN(bRC->upperFrameLimit,bRC->bitsPerPFrame); bRC->upperFrameLimit = (int)(bRC->centerFrameBits * bRC->UPPER_LIMIT_MULTIPLE); } } if(bRC->CurrentBufferFullness + bRC->upperFrameLimit - bRC->bitsPerFrame > bRC->BufferSize - bRC->bitsPerFrame/5) { bRC->upperFrameLimit = -bRC->bitsPerFrame/5 + bRC->BufferSize - bRC->CurrentBufferFullness + bRC->bitsPerFrame; bRC->lowerFrameLimit = MAX(bRC->bitsPerFrame/4, bRC->upperFrameLimit - bRC->bitsPerFrame); bRC->centerFrameBits = (bRC->upperFrameLimit + bRC->lowerFrameLimit)/2; } if(bRC->CurrentBufferFullness + bRC->lowerFrameLimit - bRC->bitsPerFrame < bRC->bitsPerFrame/5) { bRC->lowerFrameLimit = bRC->bitsPerFrame/5 + bRC->bitsPerFrame - bRC->CurrentBufferFullness; bRC->upperFrameLimit = bRC->lowerFrameLimit + bRC->bitsPerFrame; bRC->centerFrameBits = (bRC->upperFrameLimit + bRC->lowerFrameLimit)/2; } if(bRC->lowerFrameLimit < bRC->bitsPerFrame/bRC->LOWER_LIMIT_MULTIPLE) { bRC->lowerFrameLimit = (int)(bRC->bitsPerFrame/bRC->LOWER_LIMIT_MULTIPLE); bRC->upperFrameLimit = bRC->lowerFrameLimit + bRC->bitsPerFrame/2; bRC->centerFrameBits = bRC->lowerFrameLimit + bRC->bitsPerFrame/4; } if(bRC->upperFrameLimit > bRC->bitsPerFrame*bRC->UPPER_LIMIT_MULTIPLE) { bRC->upperFrameLimit = (int)(bRC->bitsPerFrame*bRC->UPPER_LIMIT_MULTIPLE); bRC->lowerFrameLimit = bRC->upperFrameLimit - bRC->bitsPerFrame/2; bRC->centerFrameBits = bRC->upperFrameLimit - bRC->bitsPerFrame/4; } } } //Fills the necessary HRD parameter syntaxes that should be put in the bitstreamvoid fillHRDParameters(rateCtrl_s *bRC, hrd_parameters_s *hrd){ int i; hrd->cpb_cnt_minus1 = 0; //Calculate the bit_rate_scale and bit_rate_value for(i=1 ; ( ((bRC->bit_rate>>i) & (0x00000001)) != 0x00000001) ;i++); //i holds the number of zeros hrd->bit_rate_scale = MAX(0,i-6); hrd->bit_rate_value_minus1[0] = (int)(bRC->bit_rate >> i) - 1; //Calculate the bit_rate_scale and bit_rate_value for(i=1 ; ( ((bRC->BufferSize>>i) & (0x00000001)) != 0x00000001) ;i++); hrd->cpb_size_scale = MAX(0,i-4); hrd->cpb_size_value_minus1[0] = (int)(bRC->bit_rate >> (i-1) ) - 1; hrd->cbr_flag[0] = 0; hrd->initial_cpb_removal_delay_length_minus1 = 19; hrd->cpb_removal_delay_length_minus1 = 19; hrd->dpb_output_delay_length_minus1 = 19; hrd->time_offset_length = 0;}void fillBufferingPeriodSEI(rateCtrl_s *bRC){ buffering_period_SEI_s *bufperiodSEI = &bRC->bufperiodSEI; bufperiodSEI->initial_cpb_removal_delay = (unsigned int)(bRC->TargetBufferLevel* (90000*1.0/ bRC->bit_rate)) ; bufperiodSEI->initial_cpb_removal_delay_offset = bufperiodSEI->seq_parameter_set_id = 0;}void fillPictureTimingSEI(rateCtrl_s *bRC){ picture_timing_SEI_s *pic_timing_SEI = &bRC->picture_timing_SEI; if(bRC->PictureIndex == 0) { pic_timing_SEI->cpb_removal_delay = 0; pic_timing_SEI->dpb_output_delay = 0; } else { pic_timing_SEI->cpb_removal_delay = bRC->PictureIndex; pic_timing_SEI->dpb_output_delay = bRC->PictureIndex; }}void rc_printDebug(rateCtrl_s *bRC,statSlice_s *frmStat){ fprintf(bRC->rcdebug,"%6d\t%6d\t %6d\t %6d\t %6d\t %.2f\t %6d\t %6d\t %.2f\t %6d\t %6d\t %6d\t%6d\t%.2f\n", bRC->srcPicNum, staGetTotalBits(frmStat), bRC->TargetBufferLevel, bRC->CurrentBufferFullness, bRC->frameReturnedQP, bRC->averageQPforFrame, bRC->QP_LW , bRC->QP_SW, frmStat->psnrY, bRC->upperFrameLimit, bRC->lowerFrameLimit, bRC->nalRefIdc, bRC->bitsPerPFrame, bRC->rdModel_PictureMAD[0] );}void rc_update_bitrate(rateCtrl_s *bRC, int bitrate){ int i; if( abs(bitrate - bRC->bit_rate)*1.0f/bRC->bit_rate > 0.1) { bRC->use_lt_RD_Model= 0; bRC->use_sh_RD_Model= 0; for(i=0;i<MAX_RD_WINDOW_SIZE;i++) { bRC->rdModel_QP[i] = 0; bRC->rdModel_Qstep[i] = 0; bRC->rdModel_PictureMAD[i] = 0.0; bRC->rdModel_TextureBits[i] = 0; bRC->rdModel_HeaderBits[i] = 0; } bRC->rdModel_windowSize = 0; for(i=0;i<MAX_LT_RD_WINDOW_SIZE;i++) { bRC->lt_rdModel_Qstep[i] = 0; bRC->lt_rdModel_PictureMAD[i] = 0.0; bRC->lt_rdModel_TextureBits[i] = 0; bRC->lt_rdModel_HeaderBits[i] = 0; } bRC->lt_rdModel_windowSize = 0; } if(bitrate!=0) { bRC->bitsPerPFrame = (int)(bRC->bitsPerPFrame * (bitrate*1.0f/bRC->bit_rate)); bRC->bitsPerFrame = (int)(bRC->bitsPerFrame * (bitrate*1.0f/bRC->bit_rate)); bRC->BufferSize = (int)(bRC->BufferSize * (bitrate*1.0f / bRC->bit_rate)); if(bRC->CurrentBufferFullness > bRC->BufferSize) //Assume the extra portion of the underlying data transfers to the Transport Buffer bRC->CurrentBufferFullness = bRC->BufferSize; } bRC->bit_rate = bitrate; bRC->TargetBufferLevel = bRC->BufferSize/2; }void rc_updateMB(rateCtrl_s *bRC, int texbits,int headerbits,macroblock_s *mb,int mbNum){ int totalMB=0,i=0; int tx_th = 5;#ifndef DISABLE_RDO if ((bRC->modeDecision & 0x0F) != MODE_DECISION_RDO) bRC->MSEofMB[mbNum] = mb->minMSE; else#endif //bRC->MSEofMB[mbNum] = mb->minSad; bRC->MSEofMB[mbNum] = (int)(mb->minMSE)>>7; bRC->currentFrameBits += (headerbits + texbits); bRC->currentFrame_MBheaderbits[mbNum] = headerbits; bRC->currentFrame_MBtexbits[mbNum] = texbits; if(mb->type == MBK_INTER && mb->interMode == MOT_COPY) bRC->numSkippedMBs++; if(mbNum == bRC->TotalNumberofMB-1) { bRC->averageQPforFrame = 0; for(i=0;i<bRC->TotalNumberofMB;i++) { if(bRC->currentFrame_MBtexbits[i]>tx_th) { bRC->averageQPforFrame+=bRC->currentFrame_MBQp[i]; totalMB++; } } if(totalMB < bRC->TotalNumberofMB/4) { bRC->averageQPforFrame = 0; for(i=0;i<bRC->TotalNumberofMB;i++) bRC->averageQPforFrame+=bRC->currentFrame_MBQp[i]; totalMB = bRC->TotalNumberofMB; } bRC->averageQPforFrame=bRC->averageQPforFrame/totalMB; } }int rc_getMBQP(rateCtrl_s *bRC, macroblock_s* pMb, int sliceType,int mbNum){ int i=0; int validQPs[51]; int originalQP; int currentFrameGeneratedBits=0; int prevFrameGeneratedBits = 0,prevFrameBits; int upperlimit= bRC->upperFrameLimit; int lowerlimit= bRC->lowerFrameLimit; int currPredFrame; int QP_buffer; int firstChangeChance = bRC->TotalNumberofMB/5; int lastMBIndex = 4*bRC->TotalNumberofMB/5; int qpUpdateThreshold; int changeScore=0; int maxQP = MIN(50,bRC->frameReturnedQP+6); int minQP = MAX(2,bRC->frameReturnedQP-6); if(bRC->bit_rate == 0 || bRC->brcdisableMBLevel==1) return pMb->qp; //if((sliceType == SLICE_I && bRC->PictureIndex == 0) || ( (sliceType == SLICE_I && bRC->ignoreIDR)) ) if((sliceType == SLICE_I && bRC->ignoreIDR)) return bRC->frameReturnedQP; qpUpdateThreshold = bRC->TotalNumberofMB / 20; if(bRC->bit_rate < bRC->BufferSize*3) { if(mbNum > bRC->TotalNumberofMB*0.4) qpUpdateThreshold=qpUpdateThreshold/2; if(mbNum > bRC->TotalNumberofMB*0.7) qpUpdateThreshold=qpUpdateThreshold/2; if(mbNum > bRC->TotalNumberofMB*0.9) qpUpdateThreshold = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -