⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ratecontrol.c

📁 Nokia H.264/AVC Encoder/Decoder Usage Manual
💻 C
📖 第 1 页 / 共 4 页
字号:
  }    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 + -