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

📄 ratectl.c

📁 H.264编码实现
💻 C
字号:

/*!
 ***************************************************************************
 * \file ratectl.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>
 *
 * \date
 *   16 Jan. 2003
 **************************************************************************
 */

#include <math.h>
#include <limits.h>

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


/*!
 *************************************************************************************
 * \brief
 *    Update Rate Control Parameters
 *************************************************************************************
 */
void rc_store_mad(Macroblock *currMB)
{
  generic_RC->MADofMB[img->current_mb_nr] = ComputeMBMAD();

  if(params->basicunit < img->FrameSizeInMbs)
  {
    generic_RC->TotalMADBasicUnit += generic_RC->MADofMB[img->current_mb_nr];
  }  
}

/*!
 *************************************************************************************
 * \brief
 *    Update QP Parameters (in case of SKIP MBs or MBAFF)
 *************************************************************************************
 */

void update_qp_cbp(Macroblock *currMB, short best_mode)
{
  // delta_qp is present only for non-skipped macroblocks
  if ((currMB->cbp!=0 || best_mode == I16MB) && (best_mode != IPCM))
    currMB->prev_cbp = 1;
  else
  {
    currMB->prev_cbp = 0;
    currMB->delta_qp = 0;
    currMB->qp       = currMB->prev_qp;
    img->qp          = currMB->qp;
    update_qp(img, currMB);    

  }

  if (params->MbInterlace)
  {
    // update rdopt buffered qps...
    rdopt->qp        = currMB->qp;
    rdopt->delta_qp  = currMB->delta_qp;
    rdopt->prev_cbp  = currMB->prev_cbp;
  }  
}

/*!
 *************************************************************************************
 * \brief
 *    map QP to Qstep
 *
 *************************************************************************************
*/
double QP2Qstep( int QP )
{
  int i;
  double Qstep;
  static const double 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;
}


/*!
 *************************************************************************************
 * \brief
 *    map Qstep to QP
 *
 *************************************************************************************
*/
int Qstep2QP( double Qstep )
{
  int q_per = 0, q_rem = 0;

  //  assert( Qstep >= QP2Qstep(0) && Qstep <= QP2Qstep(51) );
  if( Qstep < QP2Qstep(0))
    return 0;
  else if (Qstep > QP2Qstep(51) )
    return 51;

  while( Qstep > QP2Qstep(5) )
  {
    Qstep /= 2.0;
    q_per += 1;
  }

  if (Qstep <= 0.65625)
  {
    Qstep = 0.625;
    q_rem = 0;
  }
  else if (Qstep <= 0.75)
  {
    Qstep = 0.6875;
    q_rem = 1;
  }
  else if (Qstep <= 0.84375)
  {
    Qstep = 0.8125;
    q_rem = 2;
  }
  else if (Qstep <= 0.9375)
  {
    Qstep = 0.875;
    q_rem = 3;
  }
  else if (Qstep <= 1.0625)
  {
    Qstep = 1.0;
    q_rem = 4;
  }
  else
  {
    Qstep = 1.125;
    q_rem = 5;
  }

  return (q_per * 6 + q_rem);
}

/*!
 ************************************************************************************
 * \brief
 *    calculate MAD for the current macroblock
 *
 * \return
 *    calculated MAD
 *
 *************************************************************************************
*/
int ComputeMBMAD()
{
  int k, l, sum = 0;

  for (k = 0; k < 16; k++)
    for (l = 0; l < 16; l++)
      sum += iabs(diffy[k][l]);

  return sum;
}

/*!
 *************************************************************************************
 * \brief
 *    Compute Frame MAD
 *
 *************************************************************************************
*/
double ComputeFrameMAD()
{
  int64 TotalMAD = 0;
  unsigned int i;
  for(i = 0; i < img->FrameSizeInMbs; i++)
    TotalMAD += generic_RC->MADofMB[i];
  return (double)TotalMAD / (256.0 * (double)img->FrameSizeInMbs);
}


/*!
 *************************************************************************************
 * \brief
 *    Copy JVT rate control objects
 *
 *************************************************************************************
*/
void rc_copy_generic( rc_generic *dst, rc_generic *src )
{
  /* buffer original addresses for which memory has been allocated */
  int *tmpMADofMB = dst->MADofMB;

  /* copy object */

  // This could be written as: *dst = *src;
  memcpy( (void *)dst, (void *)src, sizeof(rc_generic) );

  /* restore original addresses */
  dst->MADofMB = tmpMADofMB;

  /* copy MADs */
  memcpy( (void *)dst->MADofMB, (void *)src->MADofMB, img->FrameSizeInMbs * sizeof (int) );
}

/*!
 *************************************************************************************
 * \brief
 *    Dynamically allocate memory needed for generic rate control
 *
 *************************************************************************************
 */
void rc_alloc_generic( rc_generic **prc )
{
  *prc = (rc_generic *) malloc ( sizeof( rc_generic ) );
  if (NULL == *prc)
  {
    no_mem_exit("init_global_buffers: rc_alloc_generic");
  }
  (*prc)->MADofMB = (int *) calloc (img->FrameSizeInMbs, sizeof (int));
  if (NULL == (*prc)->MADofMB)
  {
    no_mem_exit("init_global_buffers: (*prc)->MADofMB");
  }
  (*prc)->FieldFrame = 1;
}


/*!
 *************************************************************************************
 * \brief
 *    Free memory needed for generic rate control
 *
 *************************************************************************************
 */
void rc_free_generic(rc_generic **prc)
{
  if (NULL!=(*prc)->MADofMB)
  {
    free ((*prc)->MADofMB);
    (*prc)->MADofMB = NULL;
  }
  if (NULL!=(*prc))
  {
    free ((*prc));
    (*prc) = NULL;
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Initialize GOP Level Rate Control parameters
 *
 *************************************************************************************
 */
void rc_init_gop_params(void)
{
  int np, nb; 

  switch( params->RCUpdateMode )
  {
  case RC_MODE_1: case RC_MODE_3: 
    if ( !(img->number) )
    {
      /* number of P frames */
      np = params->no_frames - 1;
      /* number of B frames */
      nb = np * params->successive_Bframe;

      rc_init_GOP(quadratic_RC, np, nb);
    }
    break;
  case RC_MODE_0: case RC_MODE_2:
    if (params->idr_period == 0)
    {
      if ( !(img->number) )
      {
        /* number of P frames */
        np = params->no_frames - 1;
        /* number of B frames */
        nb = np * params->successive_Bframe;
        rc_init_GOP(quadratic_RC, np, nb);
      }
    }
    else if ( (!params->adaptive_idr_period && ( img->frm_number - img->lastIDRnumber ) % params->idr_period == 0)
      || (params->adaptive_idr_period == 1 && ( img->frm_number - imax(img->lastIntraNumber, img->lastIDRnumber) ) % params->idr_period == 0) )  
    {
      int M = params->successive_Bframe + 1;
      int N = M * params->idr_period;      
      int n = (img->number == 0) ? N - ( M - 1) : N;

      /* last GOP may contain less frames */
      if ((img->number / params->idr_period) >= (params->no_frames / params->idr_period))
      {
        if (img->number != 0)
          n = (params->no_frames - img->number) * (params->successive_Bframe + 1);
        else
          n = params->no_frames  + (params->no_frames - 1) * params->successive_Bframe;
      }

      /* number of P frames */
      np = (img->number == 0) ? 1 + ((n - 2) / M) : (n - 1) / M; 
      /* number of B frames */
      nb = n - np - 1;
      rc_init_GOP(quadratic_RC, np, nb);
    }
    break;
  default:
    break;
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Initialize Frame Level Rate Control parameters
 *
 *************************************************************************************
 */

void rc_init_frame(int FrameNumberInFile)
{
  switch( params->RCUpdateMode )
  {
  case RC_MODE_0:  case RC_MODE_1:  case RC_MODE_2:  case RC_MODE_3:

  // update the number of MBs in the basic unit for MBAFF coding
  if( (params->MbInterlace) && (params->basicunit < img->FrameSizeInMbs) && (img->type == P_SLICE || (params->RCUpdateMode == RC_MODE_1 && img->number) ) )
    img->BasicUnit = params->basicunit << 1;
  else
    img->BasicUnit = params->basicunit;

    if ( params->RDPictureDecision )
    {    
      rc_copy_quadratic( quadratic_RC_init, quadratic_RC ); // store rate allocation quadratic...    
      rc_copy_generic( generic_RC_init, generic_RC ); // ...and generic model
    }
    rc_init_pict_ptr(quadratic_RC, 1,0,1, 1.0F);

    if( active_sps->frame_mbs_only_flag)
      generic_RC->TopFieldFlag=0;

    img->qp = updateQP(quadratic_RC, 0);
    break;
  default:
    break;
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Initialize Sequence Level Rate Control parameters
 *
 *************************************************************************************
 */

void rc_init_sequence(void)
{
  switch( params->RCUpdateMode )
  {
  case RC_MODE_0:  case RC_MODE_1:  case RC_MODE_2:  case RC_MODE_3:
    rc_init_seq(quadratic_RC);
    break;
  default:
    break;
  }
}

void rc_store_slice_header_bits( int len )
{
  switch (params->RCUpdateMode)
  {
  case RC_MODE_0:  case RC_MODE_1:  case RC_MODE_2:  case RC_MODE_3:
    generic_RC->NumberofHeaderBits +=len;

    // basic unit layer rate control
    if(img->BasicUnit < img->FrameSizeInMbs)
      generic_RC->NumberofBasicUnitHeaderBits +=len;
    break;
  default:
    break;
  }
}

void update_qp_cbp_tmp(Macroblock *currMB, int cbp, int best_mode)
{
  if (((cbp!=0 || best_mode==I16MB) && (best_mode!=IPCM) ))
    currMB->prev_cbp = 1;
  else if ((cbp==0) || (best_mode==IPCM))
  {
    currMB->prev_cbp  = 0;
    currMB->delta_qp  = 0;
    currMB->qp        = currMB->prev_qp;
    img->qp           = currMB->qp;
    update_qp(img, currMB);        
  }
}

/*!
*************************************************************************************
* \brief
*    Update Rate Control Difference
*************************************************************************************
*/
void rc_store_diff(int cpix_x, int cpix_y, imgpel prediction[16][16])
{
  int i, j;
  int *iDst;
  imgpel *Src1, *Src2;

  for(j = 0; j < MB_BLOCK_SIZE; j++)
  {
    iDst = diffy[j];
    Src1 = &pCurImg[cpix_y + j][cpix_x];
    Src2 = prediction[j];
    for (i = 0; i < MB_BLOCK_SIZE; i++)
    {
      iDst[i] = Src1[i] - Src2[i];
    }
  }
}

⌨️ 快捷键说明

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