📄 ratecontrol.c
字号:
} if(mbNum == 0) originalQP = bRC->frameReturnedQP; else originalQP = bRC->currentFrame_MBQp[mbNum - 1]; QP_buffer = originalQP; for(i=0;i<51;i++) validQPs[i]=0; for(i=MAX(minQP,originalQP-3);i<MIN(maxQP,originalQP+3);i++) validQPs[i]=1; if(mbNum - bRC->lastQPUpdateID >= qpUpdateThreshold || mbNum>=lastMBIndex ) { float ratio=0.0f; //predict the current frame bits if(bRC->PPictureIndexinGOP>0) { prevFrameBits = bRC->prevFrameBits; for(i=bRC->lastQPUpdateID;i<mbNum;i++) { prevFrameGeneratedBits += bRC->prevFrame_MBheaderbits[i]+bRC->prevFrame_MBtexbits[i]; currentFrameGeneratedBits += bRC->currentFrame_MBheaderbits[i]+bRC->currentFrame_MBtexbits[i]; } if(prevFrameBits == 0) { //Previous frame was ALL-SKIP currPredFrame = currentFrameGeneratedBits*(bRC->TotalNumberofMB - bRC->lastQPUpdateID)/(mbNum - bRC->lastQPUpdateID); for(i=0;i<bRC->lastQPUpdateID;i++) currPredFrame+=bRC->currentFrame_MBheaderbits[i]+bRC->currentFrame_MBtexbits[i]; } else { if(prevFrameGeneratedBits == 0 || currentFrameGeneratedBits == 0) { for(i=0;i<bRC->lastQPUpdateID;i++) { prevFrameGeneratedBits += bRC->prevFrame_MBheaderbits[i]+bRC->prevFrame_MBtexbits[i]; currentFrameGeneratedBits += bRC->currentFrame_MBheaderbits[i]+bRC->currentFrame_MBtexbits[i]; } ratio = MIN(4,MAX(0.25f,currentFrameGeneratedBits*1.0f/prevFrameGeneratedBits)); } else { ratio = MIN(4,MAX(0.25f,currentFrameGeneratedBits*1.0f/prevFrameGeneratedBits)); for(i=0;i<bRC->lastQPUpdateID;i++) { prevFrameGeneratedBits += bRC->prevFrame_MBheaderbits[i]+bRC->prevFrame_MBtexbits[i]; currentFrameGeneratedBits += bRC->currentFrame_MBheaderbits[i]+bRC->currentFrame_MBtexbits[i]; } } } if(currentFrameGeneratedBits > 0) { if(prevFrameGeneratedBits != 0 && currentFrameGeneratedBits != 0) currPredFrame = (int)(currentFrameGeneratedBits + ratio*(prevFrameBits - prevFrameGeneratedBits)) ; else currPredFrame = prevFrameBits; } else { prevFrameGeneratedBits = 0; for(i=0;i<bRC->TotalNumberofMB;i++) prevFrameGeneratedBits += bRC->prevFrame_MBheaderbits[i]+bRC->prevFrame_MBtexbits[i]; currPredFrame = prevFrameGeneratedBits; } } else { for(i=bRC->lastQPUpdateID;i<mbNum;i++) currentFrameGeneratedBits += bRC->currentFrame_MBheaderbits[i]+bRC->currentFrame_MBtexbits[i]; currPredFrame = currentFrameGeneratedBits*(bRC->TotalNumberofMB - bRC->lastQPUpdateID)/(mbNum - bRC->lastQPUpdateID); for(i=0;i<bRC->lastQPUpdateID;i++) currPredFrame+=bRC->currentFrame_MBheaderbits[i]+bRC->currentFrame_MBtexbits[i]; } if(currPredFrame > upperlimit) {changeScore = (int)(scoreLUT[mbNum*20/bRC->TotalNumberofMB]*currPredFrame/upperlimit);QP_buffer += 2;} else if(currPredFrame < lowerlimit) { QP_buffer -= 2; if(currPredFrame == 0) changeScore = 500; else { if(bRC->CurrentBufferFullness + currPredFrame - bRC->bitsPerFrame < 0) changeScore = (int)(scoreLUT[mbNum*20/bRC->TotalNumberofMB]*lowerlimit/currPredFrame); else changeScore = (int)(scoreLUT[mbNum*20/bRC->TotalNumberofMB]*lowerlimit/currPredFrame); } } QP_buffer = MIN(50,MAX(2,QP_buffer)); if(mbNum>firstChangeChance && changeScore>100) { if(currPredFrame > bRC->centerFrameBits) { if(validQPs[QP_buffer] == 1) { bRC->lastQPUpdateID = mbNum; return MIN(50,MAX(2,QP_buffer)); } else { int bestQP=originalQP,best_dist=51,dist; for(i=0;i<51;i++) { dist=51; if(validQPs[i]==1) dist=abs(i-QP_buffer); if(dist<best_dist) { bestQP=i; best_dist = dist; } } bRC->lastQPUpdateID = mbNum; return bestQP; } } else if(currPredFrame < bRC->centerFrameBits) { if(validQPs[(int)QP_buffer] == 1) { bRC->lastQPUpdateID = pMb->mbAddr; return MIN(50,MAX(2,QP_buffer)); } else { int bestQP=originalQP,best_dist=51; bRC->lastQPUpdateID = pMb->mbAddr; for(i=0;i<51;i++) { int dist=51; if(validQPs[i]==1) dist=abs(i-(int)QP_buffer); if(dist<best_dist) { bestQP=i; best_dist = dist; } } bRC->lastQPUpdateID = mbNum; return bestQP; } } } } return originalQP;}int getIFrameQP(rateCtrl_s *bRC){ //Calculate the QP for the I Frame depending on Buffer Fullness, and Previous Coding History int i,bufferAvail,totalSamples=0,lastFrameQP,minBits=INT_MAX,maxBits=0,maxQP=0,minQP=0; float a=0.0f,b=0.0f,c=0.0f,d=0.0f,m,y; int finalQp; if(bRC->ignoreIDR == 1) return (int)(bRC->averageQPforFrame+1.5); bufferAvail = bRC->BufferSize - bRC->CurrentBufferFullness + bRC->bitsPerFrame; if(bufferAvail > bRC->I_P_RATIO * bRC->bitsPerFrame && bRC->numConsecutiveSkips == 0) { if(bRC->PictureIndex>0) { finalQp = (int)(bRC->averageQPforFrame+2); if(finalQp > bRC->frameComputedQP) bRC->frameComputedQP=MIN(bRC->frameComputedQP + 2, finalQp); else bRC->frameComputedQP=MAX(bRC->frameComputedQP - 2, finalQp); } return bRC->frameComputedQP; } for(i=0;i<10;i++) { if(bRC->IFrameBits[i]>maxBits) { maxBits = bRC->IFrameBits[i]; maxQP = bRC->IFrameQP[i]; } if(bRC->IFrameBits[i]<minBits) { minBits = bRC->IFrameBits[i]; minQP = bRC->IFrameQP[i]; } //Use all the buffer you have if(!(bRC->IFrameQP[i] == 0 || bRC->IFrameBits[i] == 0)) { totalSamples++; a+=bRC->IFrameQP[i]*bRC->IFrameBits[i]; b+=bRC->IFrameQP[i]; c+=bRC->IFrameBits[i]; d+=bRC->IFrameQP[i]*bRC->IFrameQP[i]; } } m = (totalSamples*a-b*c)/(totalSamples*d - b*b); y = (c - m*b)/totalSamples; lastFrameQP = bRC->IFrameQP[0]; if(m>=0) { //Remove the last Sample for(i=0;i<totalSamples-1;i++) { bRC->IFrameQP[i]=bRC->IFrameQP[i+1]; bRC->IFrameBits[i]=bRC->IFrameBits[i+1]; } bRC->IFrameQP[totalSamples - 1]=0; bRC->IFrameBits[totalSamples - 1]=0; totalSamples = 0; for(i=0;i<10;i++) { if(bRC->IFrameBits[i]>maxBits) maxBits = bRC->IFrameBits[i]; if(bRC->IFrameBits[i]<minBits) minBits = bRC->IFrameBits[i]; //Use all the buffer you have if(!(bRC->IFrameQP[i] == 0 || bRC->IFrameBits[i] == 0)) { totalSamples++; a+=bRC->IFrameQP[i]*bRC->IFrameBits[i]; b+=bRC->IFrameQP[i]; c+=bRC->IFrameBits[i]; d+=bRC->IFrameQP[i]*bRC->IFrameQP[i]; } } m = (totalSamples*a-b*c)/(totalSamples*d - b*b); y = (c - m*b)/totalSamples; } if(bRC->numConsecutiveSkips > 0) return lastFrameQP+1; if (m == 0) return lastFrameQP; if(totalSamples < 2) { if(bufferAvail > 1.2*bRC->IFrameBits[0]) return bRC->IFrameQP[0]-1; else if(bufferAvail < 0.8*bRC->IFrameBits[0]) return bRC->IFrameQP[0]+1; else return bRC->IFrameQP[0]; } //Interpolation is reliable else if(bufferAvail<maxBits && bufferAvail>minBits) { int calcQP = (int)MIN(51,MAX(0,(bufferAvail - y)/m)); if(calcQP > bRC->IFrameQP[0]) return MIN(calcQP, bRC->IFrameQP[0] + 2); else return MAX(calcQP, bRC->IFrameQP[0] - 2); } //Interpolation is unreliable else { if(bufferAvail>maxBits) return maxQP; else return minQP; } }static float getAveragePSNR(rateCtrl_s *bRC,int windowSize) { float totalPSNR=0.0f; int i,totalFrm=0; for(i=0;i<windowSize;i++) { if(bRC->framePSNR[i]>0) { totalPSNR+=bRC->framePSNR[i]; totalFrm++; } } return totalPSNR/windowSize;}int checkFrameSkip(rateCtrl_s *bRC, int frmBits,float psnrY){ if(bRC->img_type == SLICE_I && bRC->ignoreIDR == 1) return AVCE_OK; //Only regular frame Skipping is used if(bRC->frameSkipEnabled == 1) { if(bRC->CurrentBufferFullness + frmBits - bRC->bitsPerFrame > bRC->BufferSize && !(bRC->numConsecutiveSkips > 2 && bRC->CurrentBufferFullness == 0)) { //Buffer overflow bRC->PictureIndex++; bRC->CurrentBufferFullness-=bRC->bitsPerFrame; bRC->CurrentBufferFullness = MAX(0,bRC->CurrentBufferFullness); bRC->bitDifference = MAX(0,bRC->bitDifference-bRC->bitsPerFrame); bRC->stat_NumberofSkips++; bRC->numConsecutiveSkips++; return AVCE_FRAME_SKIPPED; } else return AVCE_OK; } else if(bRC->frameSkipEnabled == 2) { //Advanced Frame Skipping algorithm if(bRC->CurrentBufferFullness + frmBits - bRC->bitsPerFrame > bRC->BufferSize && !(bRC->numConsecutiveSkips > 2 && bRC->CurrentBufferFullness == 0)) { //Buffer overflow bRC->PictureIndex++; bRC->CurrentBufferFullness-=bRC->bitsPerFrame; bRC->CurrentBufferFullness = MAX(0,bRC->CurrentBufferFullness); bRC->bitDifference-=bRC->bitsPerFrame; bRC->stat_NumberofSkips++; bRC->numConsecutiveSkips++; return AVCE_FRAME_SKIPPED; } else if(bRC->img_type == SLICE_I) { if( bRC->currentFramePSNR< getAveragePSNR(bRC,MIN(100,bRC->PictureIndex)) - 2 && bRC->numConsecutiveSkips < 2 && bRC->CurrentBufferFullness > bRC->BufferSize*0.1 ) { //Advanced Skip bRC->PictureIndex++; bRC->CurrentBufferFullness-=bRC->bitsPerFrame; bRC->CurrentBufferFullness = MAX(0,bRC->CurrentBufferFullness); bRC->bitDifference-=bRC->bitsPerFrame; bRC->stat_NumberofSkips++; bRC->numConsecutiveSkips++; return AVCE_FRAME_SKIPPED; } } else if(bRC->img_type == SLICE_P) { if( bRC->currentFramePSNR< getAveragePSNR(bRC,MIN(10,bRC->PictureIndex)) - 2 && bRC->numConsecutiveSkips < 1 && psnrY > 0 //avoid warning ) { bRC->PictureIndex++; bRC->CurrentBufferFullness-=bRC->bitsPerFrame; bRC->CurrentBufferFullness = MAX(0,bRC->CurrentBufferFullness); bRC->bitDifference-=bRC->bitsPerFrame; bRC->stat_NumberofSkips++; bRC->numConsecutiveSkips++; return AVCE_FRAME_SKIPPED; } } else return AVCE_OK; } return AVCE_OK; }void rc_free_mem(rateCtrl_s *bRC){ nccFree(bRC->prevFrame_MBsad); nccFree(bRC->prevFrame_MBQp); nccFree(bRC->prevFrame_MBtexbits); nccFree(bRC->prevFrame_MBheaderbits); nccFree(bRC->currentFrame_MBsad); nccFree(bRC->currentFrame_MBQp); nccFree(bRC->currentFrame_MBtexbits); nccFree(bRC->currentFrame_MBheaderbits); nccFree(bRC->MSEofMB);}void computePFrameQP(rateCtrl_s *bRC, int img_type, int nalRefIdc,int srcPicNum,int hdrSize){ int QP_SW; int tex,finalQp=0; float avg_sh_mad = getAverageMAD(bRC,hdrSize,0), gamma; if(bRC->use_lt_RD_Model == 1) { if(bRC->use_sh_RD_Model == 1) { tex = bRC->bitsPerPFrame*bRC->rdModel_TextureBits[0]/(bRC->rdModel_TextureBits[0]+bRC->rdModel_HeaderBits[0]); if(tex>0 && avg_sh_mad > 0) QP_SW = getQP_UsingRDModel(tex , avg_sh_mad , bRC->rdModel_X1, bRC->rdModel_X2); else QP_SW = (int)(bRC->averageQPforFrame - 2); if(QP_SW > bRC->QP_SW) bRC->QP_SW = MIN(bRC->QP_SW+2, QP_SW); else bRC->QP_SW = MAX(bRC->QP_SW-2, QP_SW); srcPicNum,img_type; } else bRC->QP_SW = bRC->QP_LW; gamma = (MIN(bRC->BufferSize,(bRC->CurrentBufferFullness+bRC->numConsecutiveSkips*bRC->bitsPerFrame))*1.0f/bRC->BufferSize); if(gamma < 0.9f && gamma > 0.1f) { if(gamma > 0.65f) { if(bRC->QP_LW > bRC->QP_SW) finalQp = (int)(bRC->QP_LW); else finalQp = (int)((gamma-0.5f)*2.0f * bRC->QP_SW + (1-(gamma-0.5f)*2.0f) * bRC->QP_LW ); } else if(gamma < 0.35f) { if(bRC->QP_LW < bRC->QP_SW) finalQp = (int)(bRC->QP_LW); else finalQp = (int)((1-gamma) * bRC->QP_SW + gamma * bRC->QP_LW); } else finalQp = (int)(bRC->QP_LW+ 0.5); } else if(gamma<=0.1) finalQp = MIN(bRC->QP_LW,bRC->QP_SW); else if(gamma>=0.9) finalQp = MAX(bRC->QP_LW,bRC->QP_SW); } else { if(bRC->PictureIndex == 1) finalQp = (int)bRC->averageQPforFrame + 2; else finalQp = (int)(bRC->averageQPforFrame); bRC->QP_SW = finalQp; } if(finalQp > bRC->frameComputedQP && bRC->averageQPforFrame > bRC->frameComputedQP) bRC->frameComputedQP=MIN(bRC->frameComputedQP + 2, finalQp); else if(finalQp > bRC->frameComputedQP && bRC->averageQPforFrame <= bRC->frameComputedQP) bRC->frameComputedQP=(int)(MIN(bRC->averageQPforFrame + 2, finalQp)); else if(finalQp <= bRC->frameComputedQP && bRC->averageQPforFrame <= bRC->frameComputedQP) bRC->frameComputedQP=MAX(bRC->frameComputedQP - 2, finalQp); else if(finalQp <= bRC->frameComputedQP && bRC->averageQPforFrame > bRC->frameComputedQP) bRC->frameComputedQP=(int)(MAX(bRC->averageQPforFrame , finalQp)); if(bRC->frameSkipEnabled != 0 && bRC->numConsecutiveSkips>0 && bRC->PPictureIndexinGOP<3) bRC->frameComputedQP=MIN(50,bRC->frameComputedQP+2*bRC->numConsecutiveSkips); else if(bRC->frameSkipEnabled != 0) bRC->frameComputedQP=MIN(50,bRC->frameComputedQP+bRC->numConsecutiveSkips); bRC->frameComputedQP = MIN(50,bRC->frameComputedQP); if(nalRefIdc == 0) { if(bRC->CurrentBufferFullness > bRC->bitsPerFrame*2) bRC->frameComputedQP+=2; else if(bRC->CurrentBufferFullness > bRC->bitsPerFrame) bRC->frameComputedQP++; } #ifdef USE_SPP if(bRC->SPPPictureCounter == 0) bRC->SPPframeComputedQP=bRC->frameComputedQP-SPP_QP_CHANGE; #endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -