[x265] [PATCH] add rate control parameters to x265_param_t

sumalatha at multicorewareinc.com sumalatha at multicorewareinc.com
Wed Aug 14 10:16:18 CEST 2013


# HG changeset patch
# User sumalatha
# Date 1376468168 -19800
# Node ID 21a97bdeea8a0f250ba58f8b33c0a676b2316fa6
# Parent  a2026f0e1556e129d7c86d951b9d3e694a43fac6
add rate control parameters to x265_param_t
make corresponding changes to ratecontrol.cpp and .h
moved the macro definition of QP_BD_OFFSET from slicetype.cpp to common.h

diff -r a2026f0e1556 -r 21a97bdeea8a source/common/common.cpp
--- a/source/common/common.cpp	Tue Aug 13 22:10:41 2013 -0500
+++ b/source/common/common.cpp	Wed Aug 14 13:46:08 2013 +0530
@@ -139,6 +139,14 @@
     param->bEnableTSkipFast = 1;
     param->bFrameAdaptive = X265_B_ADAPT_FAST;
     param->lookaheadDepth = 10;
+    param->rc.bitrate = 1000;//TODO:take from CLI
+    param->rc.rateTolerance = 1;
+    param->rc.qCompress = 0.6;
+    param->rc.ipFactor = 1.4;
+    param->rc.pbFactor = 1.3;
+    param->rc.qpStep = 4;
+    param->rc.rateControlMode = X265_RC_ABR;
+
 }
 
 extern "C"
diff -r a2026f0e1556 -r 21a97bdeea8a source/common/common.h
--- a/source/common/common.h	Tue Aug 13 22:10:41 2013 -0500
+++ b/source/common/common.h	Wed Aug 14 13:46:08 2013 +0530
@@ -94,6 +94,7 @@
 #define X265_MAX3(a, b, c) X265_MAX((a), X265_MAX((b), (c)))
 #define X265_MIN4(a, b, c, d) X265_MIN((a), X265_MIN3((b), (c), (d)))
 #define X265_MAX4(a, b, c, d) X265_MAX((a), X265_MAX3((b), (c), (d)))
+#define QP_BD_OFFSET (6*(X265_DEPTH-8))
 
 #define ENABLE_CYCLE_COUNTERS 0
 #if ENABLE_CYCLE_COUNTERS
diff -r a2026f0e1556 -r 21a97bdeea8a source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Tue Aug 13 22:10:41 2013 -0500
+++ b/source/encoder/ratecontrol.cpp	Wed Aug 14 13:46:08 2013 +0530
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * Copyright (C) 2013 x265 project
  *
- * Authors: Sumalatha <sumalatha at multicorewareinc.com>
- *          Aarthi <aarthi at multicorewareinc.com>
+ * Authors: Sumalatha Polureddy <sumalatha at multicorewareinc.com>
+ *          Aarthi Priya Thirumalai <aarthi at multicorewareinc.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,23 +28,24 @@
 
 RateControl::RateControl(x265_param_t * param)
 {
-    keyFrameInterval = param->keyframeInterval;
+    keyFrameInterval = param->keyframeMax;
     fps = param->frameRate;
     bframes = param->bframes;
-    //TODO : set default value here,later can get from  param as done in x264?
-    rateTolerance = 1;
-    //TODO : introduce bitrate var in param and cli options
-    bitrate = param->bitrate * 1000;
-    fps = param->frameRate;
-    isAbrEnabled = true; // set from param later.
+    rateTolerance = param->rc.rateTolerance;
+    bitrate = param->rc.bitrate * 1000;
+    frameDuration = 1/param->frameRate;
+    rateControlMode = param->rc.rateControlMode;
     ncu = (param->sourceHeight * param->sourceWidth) / pow(2, param->maxCUSize);
     lastNonBPictType = -1;
-    //TODO : need  to confirm default val if mbtree is disabled
-    qCompress = 1;
-    if (isAbrEnabled)
+    qCompress = param->rc.qCompress;
+    ipFactor = param->rc.ipFactor;
+    pbFactor = param->rc.pbFactor;
+    totalBits = 0;
+    if (rateControlMode == X265_RC_ABR)
     {
-        //TODO : confirm this value. obtained it from x264 when crf is disabled , abr enabled.
-#define ABR_INIT_QP (24  + 6 * (param->internalBitDepth - 8));
+        //TODO : confirm this value. obtained it from x264 when crf is disabled , abr enabled. 
+        //h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24
+#define ABR_INIT_QP (24  + QP_BD_OFFSET)    
         accumPNorm = .01;
         accumPQp = (ABR_INIT_QP)*accumPNorm;
         /* estimated ratio that produces a reasonable QP for the first I-frame */
@@ -52,6 +53,16 @@
         wantedBitsWindow = 1.0 * bitrate / fps;
         lastNonBPictType = I_SLICE;
     }
+    ipOffset = 6.0 * log( param->rc.ipFactor );
+    pbOffset = 6.0 * log( param->rc.pbFactor );
+    for( int i = 0; i < 3; i++ )
+    {
+        lastQScaleFor[i] = qp2qScale( ABR_INIT_QP );
+        lmin[i] = qp2qScale( MIN_QP);
+        lmax[i] = qp2qScale( MAX_QP );
+    }
+    lstep = pow( 2, param->rc.qpStep / 6.0 );
+    cbrDecay = 1.0;
 }
 
 void RateControl::rateControlInit(TComSlice* frame)
@@ -66,15 +77,13 @@
     float q;
 
     //Always enabling ABR
-    if (isAbrEnabled)
+    if (rateControlMode == X265_RC_ABR)
     {
         q = qScale2qp(rateEstimateQscale(lFrame));
     }
     q = Clip3((int)q, MIN_QP, MAX_QP);
-
     qp = Clip3((int)(q + 0.5f), 0, MAX_QP);
-
-    qpm = q;
+    qpaRc = qpm = q;    // qpaRc is set in the rate_control_mb call in x264. we are updating here itself.
     if (rce)
         rce->newQp = qp;
 
@@ -86,7 +95,6 @@
 
 void RateControl::accumPQpUpdate()
 {
-    //x264_ratecontrol_t *rc = h->rc;
     accumPQp   *= .95;
     accumPNorm *= .95;
     accumPNorm += 1;
@@ -101,7 +109,6 @@
     float q;
     // ratecontrol_entry_t rce = UNINIT(rce);
     int pictType = frameType;
-    int64_t totalBits = 0; //CHECK:for ABR
 
     if (pictType == B_SLICE)
     {
@@ -114,8 +121,8 @@
         int dt1 = abs(curFrame->getPOC() - curFrame->getRefPic(REF_PIC_LIST_1, 0)->getPOC());
 
         //TODO:need to figure out this
-        float q0 = h->fref_nearest[0]->f_qp_avg_rc;
-        float q1 = h->fref_nearest[1]->f_qp_avg_rc;
+        float q0 = curFrame->getRefPic(REF_PIC_LIST_0, 0)->getSlice()->getSliceQp();  
+        float q1 = curFrame->getRefPic(REF_PIC_LIST_1, 0)->getSlice()->getSliceQp();  
 
         if (i0 && i1)
             q = (q0 + q1) / 2 + ipOffset;
@@ -125,13 +132,12 @@
             q = q0;
         else
             q = (q0 * dt1 + q1 * dt0) / (dt0 + dt1);
-
-        if (h->fenc->b_kept_as_ref)
+    
+        if (curFrame->isReferenced())    
             q += pbOffset / 2;
         else
             q += pbOffset;
 
-        qpNoVbv = q;
         return qp2qScale(q);
     }
     else
@@ -151,34 +157,27 @@
          * tolerances, the bit distribution approaches that of 2pass. */
 
         double wantedBits, overflow = 1;
+        lastSatd = 0;     //TODO:need to get this from lookahead  //x264_rc_analyse_slice( h );
+        rce->pCount = ncu;
 
-        lastSatd = 0;     //need to get this from lookahead  //x264_rc_analyse_slice( h );
         shortTermCplxSum *= 0.5;
         shortTermCplxCount *= 0.5;
-        //TODO:need to get the duration for each frame
-        //short_term_cplxsum += last_satd / (CLIP_DURATION(h->fenc->f_duration) / BASE_FRAME_DURATION);
-        shortTermCplxCount++;
-
-        rce->pCount = ncu;
-
+        shortTermCplxSum += lastSatd / (CLIP_DURATION(frameDuration) / BASE_FRAME_DURATION);
+        shortTermCplxCount ++;
+        rce->texBits = lastSatd;
+        rce->blurredComplexity = shortTermCplxSum / shortTermCplxCount;
+        rce->mvBits = 0;
         rce->pictType = pictType;
-
-        //TODO:wanted_bits_window, fps , h->fenc->i_reordered_pts, h->i_reordered_pts_delay, h->fref_nearest[0]->f_qp_avg_rc, h->param.rc.f_ip_factor, h->sh.i_type
         //need to checked where it is initialized
-        q = getQScale(rce, wantedBitsWindow / cplxrSum, fps);
+        q = getQScale(rce, wantedBitsWindow / cplxrSum);
 
         /* ABR code can potentially be counterproductive in CBR, so just don't bother.
          * Don't run it if the frame complexity is zero either. */
-        if ( /*!rcc->b_vbv_min_rate && */ lastSatd)
+        if ( lastSatd)       
         {
-            // TODO: need to check the thread_frames
-            int iFrameDone = fps + 1 - h->i_thread_frames;
+            // TODO: need to check the thread_frames  - add after min chen plugs in frame parallelism.
+            int iFrameDone = fps + 1 - 0;   //h->i_thread_frames;
             double timeDone = iFrameDone / fps;
-            if (iFrameDone > 0)
-            {
-                //time_done = ((double)(h->fenc->i_reordered_pts - h->i_reordered_pts_delay)) * h->param.i_timebase_num / h->param.i_timebase_den;
-                timeDone = ((double)(h->fenc->i_reordered_pts - h->i_reordered_pts_delay)) * (1 / fps);
-            }
             wantedBits = timeDone * bitrate;
             if (wantedBits > 0)
             {
@@ -193,11 +192,11 @@
             && lastNonBPictType != I_SLICE)
         {
             q = qp2qScale(accumPQp / accumPNorm);
-            q /= fabs(h->param.rc.f_ip_factor);
+            q /= fabs(ipFactor);
         }
         else if (fps > 0)
         {
-            if (1)     //assume that for ABR this is always enabled h->param.rc.i_rc_method != X264_RC_CRF )
+            if (rateControlMode != X265_RC_CRF)     
             {
                 /* Asymmetric clipping, because symmetric would prevent
                  * overflow control in areas of rapidly oscillating complexity */
@@ -212,22 +211,15 @@
             }
         }
 
-        qpNoVbv = qScale2qp(q);
-
         //FIXME use get_diff_limited_q() ?
-        //q = clip_qscale( h, pict_type, q );
         float lmin1 = lmin[pictType];
         float lmax1 = lmax[pictType];
-        Clip3(q, lmin1, lmax1);
-
+        q= Clip3(q, lmin1, lmax1);
         lastQScaleFor[pictType] =
             lastQScale = q;
 
         if (!fps == 0)
-            lastQScaleFor[P_SLICE] = q * fabs(h->param.rc.f_ip_factor);
-
-        //this is for VBV stuff
-        //frame_size_planned = predict_size( &pred[h->sh.i_type], q, last_satd );
+            lastQScaleFor[P_SLICE] = q * fabs(ipFactor);
 
         return q;
     }
@@ -239,9 +231,6 @@
 double RateControl::getQScale(RateControlEntry *rce, double rateFactor)
 {
     double q;
-
-    //x264_zone_t *zone = get_zone( h, frame_num );
-
     q = pow(rce->blurredComplexity, 1 - qCompress);
 
     // avoid NaN's in the rc_eq
@@ -253,15 +242,28 @@
         q /= rateFactor;
         lastQScale = q;
     }
-
-    /*TODO: need to check zone is required */
-    //if( zone )
-    //{
-    //    if( zone->b_force_qp )
-    //        q = qp2qscale( zone->i_qp );
-    //    else
-    //        q /= zone->f_bitrate_factor;
-    //}
-
     return q;
 }
+
+/* After encoding one frame, save stats and update ratecontrol state */
+int RateControl::rateControlEnd(int64_t bits)
+{
+    if( rateControlMode ==  X265_RC_ABR)
+    {
+        if( frameType != B_SLICE)
+            cplxrSum += bits * qp2qScale( qpaRc ) / lastRceq;
+        else
+        {
+            /* Depends on the fact that B-frame's QP is an offset from the following P-frame's.
+             * Not perfectly accurate with B-refs, but good enough. */
+            cplxrSum += bits * qp2qScale( qpaRc ) / (lastRceq * fabs( pbFactor ));         
+        }
+        cplxrSum *= cbrDecay;
+        wantedBitsWindow += frameDuration * bitrate;
+        wantedBitsWindow *= cbrDecay; 
+    }
+    totalBits += bits;  
+    return 0;
+}
+
+
diff -r a2026f0e1556 -r 21a97bdeea8a source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Tue Aug 13 22:10:41 2013 -0500
+++ b/source/encoder/ratecontrol.h	Wed Aug 14 13:46:08 2013 +0530
@@ -28,9 +28,18 @@
 #include <stdint.h>
 #include "TLibEncoder/TEncTop.h"
 #include "TLibCommon/TComRom.h"
-#include "math.h"
+
+
+
+#define BASE_FRAME_DURATION 0.04f
+/* Arbitrary limitations as a sanity check. */
+#define MAX_FRAME_DURATION 1.00f
+#define MIN_FRAME_DURATION 0.01f
+
+#define CLIP_DURATION(f) Clip3(f,MIN_FRAME_DURATION,MAX_FRAME_DURATION)
 
 namespace x265 {
+
 struct RateControlEntry
 {
     int pictType;
@@ -41,67 +50,49 @@
     float blurredComplexity;
 };
 
-struct Predictor
-{
-    float coeff;
-    float count;
-    float decay;
-    float offset;
-
-    float predictSize(float q, float var)
-    {
-        return (coeff * var + offset) / (q * count);
-    }
-};
-
 struct RateControl
 {
     int ncu;                    /* number of CUs in a frame */
     TComSlice *curFrame;        /* all info abt the current frame */
     SliceType frameType;        /* Current frame type */
     float frameDuration;        /* current frame duration in seconds */
-    int fps;          /* current frame number TODO: need to initaialize in init */
+    int fps;                    /* current frame rate TODO: need to initaialize in init */
     int keyFrameInterval;       /* TODO: need to initialize in init */
-    bool isAbrEnabled;
-
-    /* current frame */
     RateControlEntry *rce;
     int qp;                     /* updated qp for current frame */
     float qpm;                  /* qp for current macroblock: precise float for AQ */
-
+    float qpaRc;                /* average of macroblocks' qp before aq */
     double bitrate;
     double rateTolerance;
     double qCompress;
     int bframes;
-    /* ABR stuff */
     int    lastSatd;
-    double lastRceq;
     double cplxrSum;           /* sum of bits*qscale/rceq */
-    double expectedBitsSum;   /* sum of qscale2bits after rceq, ratefactor, and overflow, only includes finished frames */
-    int64_t fillerBitsSum;    /* sum in bits of finished frames' filler data */
     double wantedBitsWindow;  /* target bitrate * window */
-    double cbrDecay;
-    double shortTermCplxSum;
-    double shortTermCplxCount;
-    double rateFactorConstant;
     double ipOffset;
     double pbOffset;
-
+    float ipFactor;
+    float pbFactor;
     int lastNonBPictType;
     double accumPQp;          /* for determining I-frame quant */
     double accumPNorm;
     double lastQScale;
     double lastQScaleFor[3];  /* last qscale for a specific pict type, used for max_diff & ipb factor stuff */
-
     double lstep;
     float qpNoVbv;             /* QP for the current frame if 1-pass VBV was disabled. */
+    double lastRceq;
+    double cbrDecay;
     double lmin[3];             /* min qscale by frame type */
     double lmax[3];
-    double frameSizePlanned;
+    double shortTermCplxSum;
+    double shortTermCplxCount;
+    RcMethod rateControlMode;
+    int64_t totalBits;   /* totalbits used for already encoded frames */
 
     RateControl(x265_param_t * param);    // constructor for initializing values for ratecontrol vars
     void rateControlInit(TComSlice* frame);   // to be called for each frame to set the reqired parameters for rateControl.
     void rateControlStart(LookaheadFrame* lframe);                          // to be called for each frame to process RateCOntrol and set QP
+    int rateControlEnd(int64_t bits );
     float rateEstimateQscale(LookaheadFrame* lframe);                       // main logic for calculating QP based on ABR
     void accumPQpUpdate();
     double getQScale(RateControlEntry *rce, double rateFactor);
diff -r a2026f0e1556 -r 21a97bdeea8a source/encoder/slicetype.h
--- a/source/encoder/slicetype.h	Tue Aug 13 22:10:41 2013 -0500
+++ b/source/encoder/slicetype.h	Wed Aug 14 13:46:08 2013 +0530
@@ -29,7 +29,6 @@
 
 class TComPic;
 
-#define QP_BD_OFFSET (6 * (X265_DEPTH - 8))
 // arbitrary, but low because SATD scores are 1/4 normal
 #define X265_LOOKAHEAD_QP (12 + QP_BD_OFFSET)
 
diff -r a2026f0e1556 -r 21a97bdeea8a source/x265.h
--- a/source/x265.h	Tue Aug 13 22:10:41 2013 -0500
+++ b/source/x265.h	Wed Aug 14 13:46:08 2013 +0530
@@ -158,7 +158,17 @@
 
 #define X265_B_ADAPT_NONE       0
 #define X265_B_ADAPT_FAST       1
-#define X265_B_ADAPT_TRELLIS    2
+#define X265_B_ADAPT_TRELLIS    2
+
+/* rate tolerance method */
+typedef enum RcMethod
+{
+    X265_RC_ABR,
+    X265_RC_CQP,
+    X265_RC_CRF
+}
+X265_RC_METHODS;
+
 
 typedef struct x265_param_t
 {
@@ -228,6 +238,16 @@
 
     // debugging
     int       bEnableDecodedPictureHashSEI;    ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message
+   struct 
+    {
+        int       bitrate;
+        double    rateTolerance;
+        double    qCompress;
+        float     ipFactor;
+        float     pbFactor;
+        int       qpStep;
+        RcMethod  rateControlMode;
+    } rc;
 }
 x265_param_t;
 


More information about the x265-devel mailing list