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

📄 rc_quadratic.c

📁 This program can encode the YUV vdieo format to H.264 and decode it.
💻 C
📖 第 1 页 / 共 5 页
字号:

/*!
 ***************************************************************************
 * \file rc_quadratic.c
 *
 * \brief
 *    Rate Control algorithm
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *     - Siwei Ma             <swma@jdl.ac.cn>
 *     - Zhengguo LI          <ezgli@lit.a-star.edu.sg>
 *     - Athanasios Leontaris <aleon@dolby.com>
 *
 * \date
 *   16 Jan. 2003
 **************************************************************************
 */

#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <memory.h>
#include <limits.h>

#include "global.h"
#include "ratectl.h"
#include "rc_quadratic.h"

static const float THETA = 1.3636F;
static const float OMEGA = 0.9F;
static const float MINVALUE = 4.0F;
/*!
 *************************************************************************************
 * \brief
 *    Dynamically allocate memory needed for rate control
 *
 *************************************************************************************
 */
void rc_alloc( rc_quadratic **prc )
{
  int rcBufSize = img->FrameSizeInMbs / input->basicunit;
  rc_quadratic *lprc;

  (*prc) = (rc_quadratic *) malloc ( sizeof( rc_quadratic ) );
  if (NULL==(*prc))
  {
    no_mem_exit("init_global_buffers: (*prc)");
  }
  lprc = *prc;

  lprc->PreviousFrameMAD = 1.0;
  lprc->CurrentFrameMAD = 1.0;
  lprc->Pprev_bits = 0;
  lprc->Iprev_bits = 0;
  lprc->Target = 0;
  lprc->TargetField = 0;
  lprc->LowerBound = 0;
  lprc->UpperBound1 = INT_MAX;
  lprc->UpperBound2 = INT_MAX;
  lprc->Wp = 0.0;
  lprc->Wb = 0.0;
  lprc->AveWb = 0.0;
  lprc->PAveFrameQP   = input->qp0;
  lprc->m_Qc          = lprc->PAveFrameQP;
  lprc->FieldQPBuffer = lprc->PAveFrameQP;
  lprc->FrameQPBuffer = lprc->PAveFrameQP;
  lprc->PAverageQp    = lprc->PAveFrameQP;
  lprc->MyInitialQp   = lprc->PAveFrameQP;

  lprc->RC_MAX_QUANT = input->RCMaxQP;
  lprc->RC_MIN_QUANT = input->RCMinQP; //-img->bitdepth_luma_qp_scale;//clipping

  lprc->AveWb = 0.0;

  lprc->BUPFMAD = (double*) calloc ((rcBufSize), sizeof (double));
  if (NULL==lprc->BUPFMAD)
  {
    no_mem_exit("rc_alloc: lprc->BUPFMAD");
  }

  lprc->BUCFMAD = (double*) calloc ((rcBufSize), sizeof (double));
  if (NULL==lprc->BUCFMAD)
  {
    no_mem_exit("rc_alloc: lprc->BUCFMAD");
  }

  lprc->FCBUCFMAD = (double*) calloc ((rcBufSize), sizeof (double));
  if (NULL==lprc->FCBUCFMAD)
  {
    no_mem_exit("rc_alloc: lprc->FCBUCFMAD");
  }

  lprc->FCBUPFMAD = (double*) calloc ((rcBufSize), sizeof (double));
  if (NULL==lprc->FCBUPFMAD)
  {
    no_mem_exit("rc_alloc: lprc->FCBUPFMAD");
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Copy JVT rate control objects
 *
 *************************************************************************************
 */
void copy_rc_jvt( rc_quadratic *dst, rc_quadratic *src )
{
  int rcBufSize = img->FrameSizeInMbs / input->basicunit;
  /* buffer original addresses for which memory has been allocated */
  double   *tmpBUPFMAD = dst->BUPFMAD;
  double   *tmpBUCFMAD = dst->BUCFMAD;
  double *tmpFCBUPFMAD = dst->FCBUPFMAD;
  double *tmpFCBUCFMAD = dst->FCBUCFMAD;

  /* copy object */
  memcpy( (void *)dst, (void *)src, sizeof(rc_quadratic) );

  /* restore original addresses */
  dst->BUPFMAD   = tmpBUPFMAD;
  dst->BUCFMAD   = tmpBUCFMAD;
  dst->FCBUPFMAD = tmpFCBUPFMAD;
  dst->FCBUCFMAD = tmpFCBUCFMAD;

  /* copy MADs */
  memcpy( (void *)dst->BUPFMAD,   (void *)src->BUPFMAD,   (rcBufSize) * sizeof (double) );
  memcpy( (void *)dst->BUCFMAD,   (void *)src->BUCFMAD,   (rcBufSize) * sizeof (double) );
  memcpy( (void *)dst->FCBUPFMAD, (void *)src->FCBUPFMAD, (rcBufSize) * sizeof (double) );
  memcpy( (void *)dst->FCBUCFMAD, (void *)src->FCBUCFMAD, (rcBufSize) * sizeof (double) );
}

/*!
 *************************************************************************************
 * \brief
 *    Free memory needed for rate control
 *
 *************************************************************************************
*/
void rc_free(rc_quadratic **prc)
{
  if (NULL!=(*prc)->BUPFMAD)
  {
    free ((*prc)->BUPFMAD);
    (*prc)->BUPFMAD = NULL;
  }
  if (NULL!=(*prc)->BUCFMAD)
  {
    free ((*prc)->BUCFMAD);
    (*prc)->BUCFMAD = NULL;
  }
  if (NULL!=(*prc)->FCBUCFMAD)
  {
    free ((*prc)->FCBUCFMAD);
    (*prc)->FCBUCFMAD = NULL;
  }
  if (NULL!=(*prc)->FCBUPFMAD)
  {
    free ((*prc)->FCBUPFMAD);
    (*prc)->FCBUPFMAD = NULL;
  }
  if (NULL!=(*prc))
  {
    free ((*prc));
    (*prc) = NULL;
  }
}


/*!
 *************************************************************************************
 * \brief
 *    Initialize rate control parameters
 *
 *************************************************************************************
*/
void rc_init_seq(rc_quadratic *prc)
{
  double L1,L2,L3,bpp;
  int qp, i;

  switch ( input->RCUpdateMode )
  {
  case RC_MODE_0:
    updateQP = updateQPRC0;
    break;
  case RC_MODE_1:
    updateQP = updateQPRC1;
    break;
  case RC_MODE_2:
    updateQP = updateQPRC2;
    break;
  case RC_MODE_3:
    updateQP = updateQPRC3;
    break;
  default:
    updateQP = updateQPRC0;
    break;
  }

  prc->Xp=0;
  prc->Xb=0;

  prc->bit_rate = (float) input->bit_rate;
  prc->frame_rate = (img->framerate *(float)(input->successive_Bframe + 1)) / (float) (input->jumpd + 1);
  prc->PrevBitRate = prc->bit_rate;

  /*compute the total number of MBs in a frame*/
  if(input->basicunit > img->FrameSizeInMbs)
    input->basicunit = img->FrameSizeInMbs;
  if(input->basicunit < img->FrameSizeInMbs)
    prc->TotalNumberofBasicUnit = img->FrameSizeInMbs/input->basicunit;
  else
    prc->TotalNumberofBasicUnit = 1;

  /*initialize the parameters of fluid flow traffic model*/
  generic_RC->CurrentBufferFullness = 0;
  prc->GOPTargetBufferLevel = (double) generic_RC->CurrentBufferFullness;

  /*initialize the previous window size*/
  prc->m_windowSize    = 0;
  prc->MADm_windowSize = 0;
  generic_RC->NumberofCodedBFrame = 0;
  prc->NumberofCodedPFrame = 0;
  generic_RC->NumberofGOP         = 0;
  /*remaining # of bits in GOP */
  generic_RC->RemainingBits = 0;
  /*control parameter */
  if(input->successive_Bframe>0)
  {
    prc->GAMMAP=0.25;
    prc->BETAP=0.9;
  }
  else
  {
    prc->GAMMAP=0.5;
    prc->BETAP=0.5;
  }

  /*quadratic rate-distortion model*/
  prc->PPreHeader=0;

  prc->Pm_X1 = prc->bit_rate * 1.0;
  prc->Pm_X2 = 0.0;
  /* linear prediction model for P picture*/
  prc->PMADPictureC1 = 1.0;
  prc->PMADPictureC2 = 0.0;

  // Initialize values
  for(i=0;i<21;i++)
  {
    prc->Pm_rgQp[i] = 0;
    prc->Pm_rgRp[i] = 0.0;
    prc->PPictureMAD[i] = 0.0;
  }

  //Define the largest variation of quantization parameters
  prc->PMaxQpChange=2;

  /*basic unit layer rate control*/
  prc->PAveHeaderBits1 = 0;
  prc->PAveHeaderBits3 = 0;
  prc->DDquant = (prc->TotalNumberofBasicUnit>=9 ? 1 : 2);

  prc->MBPerRow = img->PicWidthInMbs;

  /*adaptive field/frame coding*/
  generic_RC->FieldControl=0;  

  if (input->SeinitialQP==0)
  {
    /*compute the initial QP*/
    bpp = 1.0*prc->bit_rate /(prc->frame_rate*img->size);

    if (img->width == 176)
    {
      L1 = 0.1;
      L2 = 0.3;
      L3 = 0.6;
    }
    else if (img->width == 352)
    {
      L1 = 0.2;
      L2 = 0.6;
      L3 = 1.2;
    }
    else
    {
      L1 = 0.6;
      L2 = 1.4;
      L3 = 2.4;
    }
    if (bpp<= L1)
      qp = 35;
    else if(bpp<=L2)
      qp = 25;
    else if(bpp<=L3)
      qp = 20;
    else
      qp = 10;
    input->SeinitialQP = qp;
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Initialize one GOP
 *
 *************************************************************************************
*/
void rc_init_GOP(rc_quadratic *prc, int np, int nb)
{
  Boolean Overum=FALSE;
  int OverBits, OverDuantQp;
  int AllocatedBits, GOPDquant;

  // bit allocation for RC_MODE_3
  switch( input->RCUpdateMode )
  {
  case RC_MODE_3:
    {
      int sum = 0, tmp, level, levels = 0, num_frames[RC_MAX_TEMPORAL_LEVELS];
      float numer, denom;
      int gop = input->successive_Bframe + 1;
      memset( num_frames, 0, RC_MAX_TEMPORAL_LEVELS * sizeof(int) );
      // are there any B frames?
      if ( input->successive_Bframe )
      {
        if ( input->HierarchicalCoding == 1 ) // two layers: even/odd
        {
          levels = 2;
          num_frames[0] = input->successive_Bframe >> 1;
          num_frames[1] = (input->successive_Bframe - num_frames[0]) >= 0 ? (input->successive_Bframe - num_frames[0]) : 0;
        }
        else if ( input->HierarchicalCoding == 2 ) // binary hierarchical structure
        {
          // check if gop is power of two
          tmp = gop;
          while ( tmp )
          {
            sum += tmp & 1;
            tmp >>= 1;
          }
          assert( sum == 1 );

          // determine number of levels
          levels = 0;
          tmp = gop;
          while ( tmp > 1 )
          {
            tmp >>= 1; // divide by 2          
            num_frames[levels] = 1 << levels;
            levels++;          
          }
          assert( levels >= 1 && levels <= RC_MAX_TEMPORAL_LEVELS );        
        }
        else if ( input->HierarchicalCoding == 3 )
        {
          fprintf(stderr, "\n RCUpdateMode=3 and HierarchicalCoding == 3 are currently not supported"); // This error message should be moved elsewhere and have proper memory deallocation
          exit(1);
        }
        else // all frames of the same priority - level
        {
          levels = 1;
          num_frames[0] = input->successive_Bframe;
        }
        generic_RC->temporal_levels = levels;      
      }
      else
      {
        for ( level = 0; level < RC_MAX_TEMPORAL_LEVELS; level++ )
        {
          input->RCBSliceBitRatio[level] = 0.0F;
        }
        generic_RC->temporal_levels = 0;
      }
      // calculate allocated bits for each type of frame
      numer = (float)(( (!input->intra_period ? 1 : input->intra_period) * gop) * ((double)input->bit_rate / input->FrameRate));
      denom = 0.0F;

      for ( level = 0; level < levels; level++ )
      {
        denom += (float)(num_frames[level] * input->RCBSliceBitRatio[level]);
        generic_RC->hierNb[level] = num_frames[level] * np;
      }
      denom += 1.0F;
      if ( input->intra_period >= 1 )
      {
        denom *= (float)input->intra_period;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -