/* convert from step size 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;
        q_per += 1;
    }

    if (Qstep <= (0.625 + 0.6875) / 2)
    {
        Qstep = 0.625;
        q_rem = 0;
    }
    else if (Qstep <= (0.6875 + 0.8125) / 2)
    {
        Qstep = 0.6875;
        q_rem = 1;
    }
    else if (Qstep <= (0.8125 + 0.875) / 2)
    {
        Qstep = 0.8125;
        q_rem = 2;
    }
    else if (Qstep <= (0.875 + 1.0) / 2)
    {
        Qstep = 0.875;
        q_rem = 3;
    }
    else if (Qstep <= (1.0 + 1.125) / 2)
    {
        Qstep = 1.0;
        q_rem = 4;
    }
    else
    {
        Qstep = 1.125;
        q_rem = 5;
    }

    return (q_per * 6 + q_rem);
}
Ejemplo n.º 2
0
/*!
 *************************************************************************************
 * \brief
 *    map dQstep to QP
 *
 *************************************************************************************
*/
int rc_generic::Qstep2QP( double dQstep )
{
  int q_per = 0, q_rem = 0;

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

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

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

  return (q_per * 6 + q_rem);
}
Ejemplo n.º 3
0
/*!
 *************************************************************************************
 * \brief
 *    map Qstep to QP
 *
 *************************************************************************************
*/
int Qstep2QP( double Qstep, int qp_offset )
{
  int q_per = 0, q_rem = 0;

  if( Qstep < QP2Qstep(MIN_QP))
    return MIN_QP;
  else if (Qstep > QP2Qstep(MAX_QP + qp_offset) )
    return (MAX_QP + qp_offset);

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

  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);
}
/* Mad based variable bit allocation + QP calculation with a new quadratic method */
void calculateQuantizer_Multipass(AVCEncObject *encvid, AVCCommonObj *video,
                                  AVCRateControl *rateCtrl, MultiPass *pMP)
{
    int prev_actual_bits = 0, curr_target, /*pos=0,*/i, j;
    OsclFloat Qstep, prev_QP = 0.625;

    OsclFloat curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;

    /* Mad based variable bit allocation */
    targetBitCalculation(encvid, video, rateCtrl, pMP);

    if (rateCtrl->T <= 0 || rateCtrl->totalSAD == 0)
    {
        if (rateCtrl->T < 0)    rateCtrl->Qc = RC_MAX_QUANT;
        return;
    }

    /* ---------------------------------------------------------------------------------------------------*/
    /* current frame QP estimation */
    curr_target = rateCtrl->T;
    curr_mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs;
    if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
    curr_RD  = (OsclFloat)curr_target / curr_mad;

    if (rateCtrl->skip_next_frame == -1) // previous was skipped
    {
        i = pMP->framePos;
        prev_mad = pMP->pRDSamples[i][0].mad;
        prev_QP = pMP->pRDSamples[i][0].QP;
        prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
    }
    else
    {
        /* Another version of search the optimal point */
        prev_mad = 0.0;
        i = 0;
        while (i < pMP->frameRange && prev_mad < 0.001) /* find first one with nonzero prev_mad */
        {
            prev_mad = pMP->pRDSamples[i][0].mad;
            i++;
        }

        if (i < pMP->frameRange)
        {
            prev_actual_bits = pMP->pRDSamples[i-1][0].actual_bits;

            for (j = 0; i < pMP->frameRange; i++)
            {
                if (pMP->pRDSamples[i][0].mad != 0 &&
                        AVC_ABS(prev_mad - curr_mad) > AVC_ABS(pMP->pRDSamples[i][0].mad - curr_mad))
                {
                    prev_mad = pMP->pRDSamples[i][0].mad;
                    prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
                    j = i;
                }
            }
            prev_QP = QP2Qstep(pMP->pRDSamples[j][0].QP);

            for (i = 1; i < pMP->samplesPerFrame[j]; i++)
            {
                if (AVC_ABS(prev_actual_bits - curr_target) > AVC_ABS(pMP->pRDSamples[j][i].actual_bits - curr_target))
                {
                    prev_actual_bits = pMP->pRDSamples[j][i].actual_bits;
                    prev_QP = QP2Qstep(pMP->pRDSamples[j][i].QP);
                }
            }
        }
    }

    // quadratic approximation
    if (prev_mad > 0.001) // only when prev_mad is greater than 0, otherwise keep using the same QP
    {
        prev_RD = (OsclFloat)prev_actual_bits / prev_mad;
        //rateCtrl->Qc = (Int)(prev_QP * sqrt(prev_actual_bits/curr_target) + 0.4);
        if (prev_QP == 0.625) // added this to allow getting out of QP = 0 easily
        {
            Qstep = (int)(prev_RD / curr_RD + 0.5);
        }
        else
        {
            //      rateCtrl->Qc =(Int)(prev_QP * M4VENC_SQRT(prev_RD/curr_RD) + 0.9);

            if (prev_RD / curr_RD > 0.5 && prev_RD / curr_RD < 2.0)
                Qstep = (int)(prev_QP * (oscl_sqrt(prev_RD / curr_RD) + prev_RD / curr_RD) / 2.0 + 0.9); /* Quadratic and linear approximation */
            else
                Qstep = (int)(prev_QP * (oscl_sqrt(prev_RD / curr_RD) + oscl_pow(prev_RD / curr_RD, 1.0 / 3.0)) / 2.0 + 0.9);
        }
        // lower bound on Qc should be a function of curr_mad
        // When mad is already low, lower bound on Qc doesn't have to be small.
        // Note, this doesn't work well for low complexity clip encoded at high bit rate
        // it doesn't hit the target bit rate due to this QP lower bound.
        /// if((curr_mad < 8) && (rateCtrl->Qc < 12))   rateCtrl->Qc = 12;
        //  else    if((curr_mad < 128) && (rateCtrl->Qc < 3)) rateCtrl->Qc = 3;

        rateCtrl->Qc = Qstep2QP(Qstep);

        if (rateCtrl->Qc < RC_MIN_QUANT) rateCtrl->Qc = RC_MIN_QUANT;
        if (rateCtrl->Qc > RC_MAX_QUANT)    rateCtrl->Qc = RC_MAX_QUANT;
    }

    /* active bit resource protection */
    aver_QP = (pMP->encoded_frames == 0 ? 0 : pMP->sum_QP / (OsclFloat)pMP->encoded_frames);
    average_mad = (pMP->encoded_frames == 0 ? 0 : pMP->sum_mad / (OsclFloat)pMP->encoded_frames); /* this function is called from the scond encoded frame*/
    if (pMP->diff_counter == 0 &&
            ((OsclFloat)rateCtrl->Qc <= aver_QP*1.1 || curr_mad <= average_mad*1.1) &&
            pMP->counter_BTsrc <= (pMP->counter_BTdst + (int)(pMP->framerate*1.0 + 0.5)))
    {
        rateCtrl->TMN_TH -= (int)(pMP->target_bits_per_frame / 10.0);
        rateCtrl->T = rateCtrl->TMN_TH - rateCtrl->TMN_W;
        pMP->counter_BTsrc++;
        pMP->diff_counter--;
    }

}