[x265] vbv rate control

Aarthi Priya Thirumalai aarthi at multicorewareinc.com
Thu Feb 20 14:04:10 CET 2014


Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 0 of 6 ] introduce cu level vbv ratecontrol
Message-Id: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:20 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org


Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 1 of 6] vbv: Introduce states to hold row data for row level
 VBV ratecontrol
X-Mercurial-Node: 39efc006d3efa89df765b3d62e810854b41fe401
Message-Id: <39efc006d3efa89df765.1392901341 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:21 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org

# HG changeset patch
# User Aarthi Thirumalai
# Date 1392895417 -19800
#      Thu Feb 20 16:53:37 2014 +0530
# Node ID 39efc006d3efa89df765b3d62e810854b41fe401
# Parent  fec3cab870437c101b409425b6c2d6c403bd0efa
vbv: Introduce states to hold row data for row level VBV ratecontrol.

diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComDataCU.cpp
--- a/source/Lib/TLibCommon/TComDataCU.cpp Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComDataCU.cpp Thu Feb 20 16:53:37 2014 +0530
@@ -99,6 +99,7 @@
     m_mvpIdx[0] = NULL;
     m_mvpIdx[1] = NULL;
     m_chromaFormat = 0;
+    m_baseQp = 0;
 }

 TComDataCU::~TComDataCU()
@@ -235,6 +236,7 @@
     m_totalBits        = 0;
     m_numPartitions    = pic->getNumPartInCU();
     int qp             = pic->m_lowres.invQscaleFactor ?
pic->getCU(getAddr())->getQP(0) : m_slice->getSliceQp();
+    m_baseQp           = pic->getCU(getAddr())->m_baseQp;
     for (int i = 0; i < 4; i++)
     {
         m_avgCost[i] = 0;
diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComDataCU.h
--- a/source/Lib/TLibCommon/TComDataCU.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComDataCU.h Thu Feb 20 16:53:37 2014 +0530
@@ -179,6 +179,7 @@
     uint64_t      m_avgCost[4];      // stores the avg cost of CU's in
frame for each depth
     uint32_t      m_count[4];
     uint64_t      m_sa8dCost;
+    double        m_baseQp;          //Qp of Cu set from RateControl/Vbv.

     //
-------------------------------------------------------------------------------------------------------------------
     // create / destroy / initialize / copy
diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComPic.cpp
--- a/source/Lib/TLibCommon/TComPic.cpp Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComPic.cpp Thu Feb 20 16:53:37 2014 +0530
@@ -56,6 +56,13 @@
     , m_bUsedByCurr(false)
     , m_bIsLongTerm(false)
     , m_bCheckLTMSB(false)
+    , m_rowDiagQp(NULL)
+    , m_rowDiagQScale(NULL)
+    , m_rowDiagSatd(NULL)
+    , m_rowSatdForVbv(NULL)
+    , m_cuCostsForVbv(NULL)
+    , m_rowEncodedBits(NULL)
+    , m_numEncodedCusPerRow(NULL)
 {
     m_reconRowCount = 0;
     m_countRefEncoders = 0;
@@ -69,6 +76,9 @@
     m_ssimCnt = 0;
     m_frameTime = 0.0;
     m_elapsedCompressTime = 0.0;
+    m_qpaAq = 0;
+    m_qpaRc = 0;
+    m_avgQpRc = 0;
     m_bChromaPlanesExtended = false;
 }

@@ -94,7 +104,46 @@
     ok &= m_origPicYuv->create(cfg->param.sourceWidth,
cfg->param.sourceHeight, cfg->param.internalCsp, g_maxCUWidth,
g_maxCUHeight, g_maxCUDepth);
     ok &= m_reconPicYuv->create(cfg->param.sourceWidth,
cfg->param.sourceHeight, cfg->param.internalCsp, g_maxCUWidth,
g_maxCUHeight, g_maxCUDepth);
     ok &= m_lowres.create(m_origPicYuv, cfg->param.bframes,
&cfg->param.rc.aqMode);
+
+    if (ok && cfg->param.rc.vbvBufferSize > 0 &&
cfg->param.rc.vbvMaxBitrate > 0)
+    {
+        int numRows = m_picSym->getFrameHeightInCU();
+        int numCols = m_picSym->getFrameWidthInCU();
+        CHECKED_MALLOC(m_rowDiagQp, double, numRows);
+        CHECKED_MALLOC(m_rowDiagQScale, double, numRows);
+        CHECKED_MALLOC(m_rowDiagSatd, uint32_t, numRows);
+        CHECKED_MALLOC(m_rowEncodedBits, uint32_t, numRows);
+        CHECKED_MALLOC(m_numEncodedCusPerRow, uint32_t, numRows);
+        CHECKED_MALLOC(m_rowSatdForVbv, uint32_t, numRows);
+        CHECKED_MALLOC(m_cuCostsForVbv, uint32_t, numRows * numCols);
+        CHECKED_MALLOC(m_qpaRc, double, numRows);
+        CHECKED_MALLOC(m_qpaAq, int, numRows);
+        reInit(cfg);
+    }
+
     return ok;
+
+fail :
+    ok = false;
+    return ok;
+}
+
+void TComPic::reInit(TEncCfg* cfg)
+{
+    if (cfg->param.rc.vbvBufferSize > 0 && cfg->param.rc.vbvMaxBitrate > 0)
+    {
+        int numRows = m_picSym->getFrameHeightInCU();
+        int numCols = m_picSym->getFrameWidthInCU();
+        memset(m_rowDiagQp, 0, numRows * sizeof(double));
+        memset(m_rowDiagQScale, 0, numRows * sizeof(double));
+        memset(m_rowDiagSatd, 0, numRows * sizeof(uint32_t));
+        memset(m_rowEncodedBits, 0, numRows * sizeof(uint32_t));
+        memset(m_numEncodedCusPerRow, 0, numRows * sizeof(uint32_t));
+        memset(m_rowSatdForVbv, 0, numRows * sizeof(uint32_t));
+        memset(m_cuCostsForVbv, 0,  numRows * numCols * sizeof(uint32_t));
+        memset(m_qpaRc, 0, numRows * sizeof(double));
+        memset(m_qpaAq, 0, numRows * sizeof(uint32_t));
+    }
 }

 void TComPic::destroy(int bframes)
@@ -121,6 +170,16 @@
     }

     m_lowres.destroy(bframes);
+
+    X265_FREE(m_rowDiagQp);
+    X265_FREE(m_rowDiagQScale);
+    X265_FREE(m_rowDiagSatd);
+    X265_FREE(m_rowEncodedBits);
+    X265_FREE(m_numEncodedCusPerRow);
+    X265_FREE(m_rowSatdForVbv);
+    X265_FREE(m_cuCostsForVbv);
+    X265_FREE(m_qpaAq);
+    X265_FREE(m_qpaRc);
 }

 //! \}
diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComPic.h
--- a/source/Lib/TLibCommon/TComPic.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComPic.h Thu Feb 20 16:53:37 2014 +0530
@@ -104,6 +104,16 @@
     uint32_t              m_checksum[3];

     bool                  m_bChromaPlanesExtended; // orig chroma planes
motion extended for weightp analysis
+    double*               m_rowDiagQp;
+    double*               m_rowDiagQScale;
+    uint32_t*             m_rowDiagSatd;
+    uint32_t*             m_rowEncodedBits;
+    uint32_t*             m_numEncodedCusPerRow;
+    uint32_t*             m_rowSatdForVbv;
+    uint32_t*             m_cuCostsForVbv;
+    int*                  m_qpaAq;
+    double*               m_qpaRc;
+    double                m_avgQpRc;

     TComPic();
     virtual ~TComPic();
@@ -112,6 +122,8 @@

     virtual void  destroy(int bframes);

+    void          reInit(TEncCfg* cfg);
+
     bool          getUsedByCurr()           { return m_bUsedByCurr; }

     void          setUsedByCurr(bool bUsed) { m_bUsedByCurr = bUsed; }
diff -r fec3cab87043 -r 39efc006d3ef source/common/lowres.h
--- a/source/common/lowres.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/common/lowres.h Thu Feb 20 16:53:37 2014 +0530
@@ -117,6 +117,7 @@
     int       intraMbs[X265_BFRAME_MAX + 2];
     int32_t*  intraCost;
     int64_t   satdCost;
+    uint16_t* lowresCostForRc;
     uint16_t(*lowresCosts[X265_BFRAME_MAX + 2][X265_BFRAME_MAX + 2]);
     int32_t*  lowresMvCosts[2][X265_BFRAME_MAX + 1];
     MV*       lowresMvs[2][X265_BFRAME_MAX + 1];
diff -r fec3cab87043 -r 39efc006d3ef source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu Feb 20 15:54:52 2014 +0530
+++ b/source/encoder/encoder.cpp Thu Feb 20 16:53:37 2014 +0530
@@ -280,6 +280,7 @@

         /* Copy input picture into a TComPic, send to lookahead */
         pic->getSlice()->setPOC(++m_pocLast);
+        pic->reInit(this);
         pic->getPicYuvOrg()->copyFromPicture(*pic_in, m_pad);
         pic->m_userData = pic_in->userData;
         pic->m_pts = pic_in->pts;
diff -r fec3cab87043 -r 39efc006d3ef source/encoder/encoder.h
--- a/source/encoder/encoder.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/encoder/encoder.h Thu Feb 20 16:53:37 2014 +0530
@@ -84,7 +84,6 @@
     Lookahead*         m_lookahead;
     FrameEncoder*      m_frameEncoder;
     DPB*               m_dpb;
-    RateControl*       m_rateControl;

     /* frame parallelism */
     int                m_curEncoder;
@@ -145,6 +144,8 @@

     void signalReconRowCompleted(int poc);

+    RateControl*       m_rateControl;
+
 protected:

     // Returns total number of bits for encoded pic
diff -r fec3cab87043 -r 39efc006d3ef source/x265.h
--- a/source/x265.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/x265.h Thu Feb 20 16:53:37 2014 +0530
@@ -801,6 +801,8 @@
          * across frames and assigns more bits to these CUs. Improves
encode efficiency.
          * Default: OFF (0) */
         int       cuTree;
+        /* In CRF mode, maximum CRF as caused by VBV */
+        double    rfConstantMax;
     } rc;
 } x265_param;


Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 2 of 6] vbv: enable vbvLookahead for Keyframes;
 accumulate frame rowSatds from lowres rowSatds
X-Mercurial-Node: 1c037c64274dce2f39db348967259d7d623c1b18
Message-Id: <1c037c64274dce2f39db.1392901342 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:22 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org

# HG changeset patch
# User Aarthi Thirumalai
# Date 1392896018 -19800
#      Thu Feb 20 17:03:38 2014 +0530
# Node ID 1c037c64274dce2f39db348967259d7d623c1b18
# Parent  39efc006d3efa89df765b3d62e810854b41fe401
vbv: enable vbvLookahead for Keyframes; accumulate frame rowSatds from
lowres rowSatds.

diff -r 39efc006d3ef -r 1c037c64274d source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Thu Feb 20 16:53:37 2014 +0530
+++ b/source/encoder/slicetype.cpp Thu Feb 20 17:03:38 2014 +0530
@@ -173,11 +173,39 @@
     }

     if (cfg->param.rc.cuTree)
+    {
         pic->m_lowres.satdCost = frameCostRecalculate(frames, p0, p1, b);
+        if (b && cfg->param.rc.vbvBufferSize)
+            frameCostRecalculate(frames,b, b, b);
+    }
+
     else if (cfg->param.rc.aqMode)
         pic->m_lowres.satdCost = pic->m_lowres.costEstAq[b - p0][p1 - b];
     else
         pic->m_lowres.satdCost = pic->m_lowres.costEst[b - p0][p1 - b];
+
+    if (cfg->param.rc.vbvBufferSize > 0 && cfg->param.rc.vbvMaxBitrate > 0)
+    {
+        pic->m_lowres.lowresCostForRc = pic->m_lowres.lowresCosts[b -
p0][p1 - b];
+        uint32_t lowresRow = 0 , lowresCol = 0, lowresCuIdx = 0, sum = 0;
+        uint32_t scale = cfg->param.maxCUSize / (2 * X265_LOWRES_CU_SIZE);
+        uint32_t widthInLowresCu = (uint32_t)widthInCU, heightInLowresCu =
(uint32_t)heightInCU;
+
+        for (uint32_t row = 0; row < pic->getFrameHeightInCU(); row++)
+        {
+            lowresRow = row * scale;
+            for (uint32_t cnt = 0 ; cnt < scale && lowresRow <
heightInLowresCu; lowresRow++, cnt++)
+            {
+                sum = 0;
+                lowresCuIdx = lowresRow * widthInLowresCu ;
+                for (lowresCol = 0; lowresCol < widthInLowresCu;
lowresCol++, lowresCuIdx++)
+                {
+                    sum +=  pic->m_lowres.lowresCostForRc[lowresCuIdx];
+                }
+                pic->m_rowSatdForVbv[row] += sum;
+            }
+          }
+      }
     return pic->m_lowres.satdCost;
 }

@@ -186,6 +214,7 @@
     Lowres *frames[X265_LOOKAHEAD_MAX];
     TComPic *list[X265_LOOKAHEAD_MAX];
     TComPic *ipic = inputQueue.first();
+    bool isKeyFrameAnalyse = (cfg->param.rc.cuTree ||
(cfg->param.rc.vbvBufferSize && cfg->param.lookaheadDepth));

     if (!est.rows && ipic)
         est.init(cfg, ipic);
@@ -371,6 +400,10 @@
             outputQueue.pushBack(*list[i]);
         }
     }
+    if (isKeyFrameAnalyse && IS_X265_TYPE_I(lastNonB->sliceType))
+    {
+        slicetypeAnalyse(frames,true);
+    }
 }

 void Lookahead::vbvLookahead(Lowres **frames, int numFrames, int keyframe)

Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 3 of 6] vbv: Add row predictors, rc states for vbv
X-Mercurial-Node: ebc23ec5ac1c5f8e2abe0d0b88414fabd2fdf1bb
Message-Id: <ebc23ec5ac1c5f8e2abe.1392901343 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:23 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org

# HG changeset patch
# User Aarthi Thirumalai
# Date 1392898673 -19800
#      Thu Feb 20 17:47:53 2014 +0530
# Node ID ebc23ec5ac1c5f8e2abe0d0b88414fabd2fdf1bb
# Parent  1c037c64274dce2f39db348967259d7d623c1b18
vbv: Add row predictors, rc states for vbv.

diff -r 1c037c64274d -r ebc23ec5ac1c source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu Feb 20 17:03:38 2014 +0530
+++ b/source/encoder/encoder.cpp Thu Feb 20 17:47:53 2014 +0530
@@ -218,6 +218,7 @@
         FrameEncoder *encoder = &m_frameEncoder[encIdx];
         double bits;
         bits = encoder->m_rce.frameSizePlanned;
+        bits = X265_MAX(bits, m_rateControl->frameSizeEstimated);
         rc->bufferFill -= bits;
         rc->bufferFill = X265_MAX(rc->bufferFill, 0);
         rc->bufferFill += encoder->m_rce.bufferRate;
diff -r 1c037c64274d -r ebc23ec5ac1c source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Thu Feb 20 17:03:38 2014 +0530
+++ b/source/encoder/ratecontrol.cpp Thu Feb 20 17:47:53 2014 +0530
@@ -243,11 +243,12 @@
     lastNonBPictType = I_SLICE;
     isAbrReset = false;
     lastAbrResetPoc = -1;
+    frameSizeEstimated = 0;
     // vbv initialization
     cfg->param.rc.vbvBufferSize = Clip3(0, 2000000,
cfg->param.rc.vbvBufferSize);
     cfg->param.rc.vbvMaxBitrate = Clip3(0, 2000000,
cfg->param.rc.vbvMaxBitrate);
     cfg->param.rc.vbvBufferInit = Clip3(0.0, 2000000.0,
cfg->param.rc.vbvBufferInit);
-
+    vbvMinRate = 0;
     if (cfg->param.rc.vbvBufferSize)
     {
         if (cfg->param.rc.rateControlMode == X265_RC_CQP)
@@ -318,6 +319,14 @@
         pred[i].offset = 0.0;
     }

+    for (int i = 0; i < 4; i++)
+    {
+        rowPreds[i].coeff = 0.25;
+        rowPreds[i].count = 1.0;
+        rowPreds[i].decay = 0.5;
+        rowPreds[i].offset = 0.0;
+    }
+
     predBfromP = pred[0];
     bframes = cfg->param.bframes;
     bframeBits = 0;
@@ -376,7 +385,11 @@
     rce->poc = curSlice->getPOC();

     if (isVbv)
+    {
+        rowPred[0] = &rowPreds[sliceType];
+        rowPred[1] = &rowPreds[3];
         updateVbvPlan(enc);
+    }

     if (isAbr) //ABR,CRF
     {
@@ -385,9 +398,10 @@
         rce->lastSatd = currentSatd;
         double q = qScale2qp(rateEstimateQscale(pic, rce));
         qp = Clip3(MIN_QP, MAX_MAX_QP, (int)(q + 0.5));
-        rce->qpaRc = q;
+        rce->qpaRc = pic->m_avgQpRc = q;
         /* copy value of lastRceq into thread local rce struct *to be used
in RateControlEnd() */
         rce->qRceq = lastRceq;
+        rce->qpNoVbv = qpNoVbv;
         accumPQpUpdate();
     }
     else //CQP
@@ -399,7 +413,11 @@
     }

     if (sliceType != B_SLICE)
+    {
         lastNonBPictType = sliceType;
+        leadingNoBSatd = currentSatd;
+    }
+    rce->leadingNoBSatd = leadingNoBSatd;
     framesDone++;
     /* set the final QP to slice structure */
     curSlice->setSliceQp(qp);
@@ -462,9 +480,11 @@
         else
             q += pbOffset;

-        rce->frameSizePlanned = predictSize(&predBfromP, qp2qScale(q),
leadingNoBSatd);
-
-        return qp2qScale(q);
+        qpNoVbv = q;
+        double qScale = qp2qScale(qpNoVbv);
+        rce->frameSizePlanned = predictSize(&predBfromP, qScale,
(double)leadingNoBSatd);
+        frameSizeEstimated = rce->frameSizePlanned;
+        return qScale;
     }
     else
     {
@@ -555,7 +575,7 @@
             if (qCompress != 1 && framesDone == 0)
                 q = qp2qScale(ABR_INIT_QP) / fabs(cfg->param.rc.ipFactor);
         }
-
+        qpNoVbv = qScale2qp(q);
         double lmin1 = lmin[sliceType];
         double lmax1 = lmax[sliceType];
         q = Clip3(lmin1, lmax1, q);
@@ -840,7 +860,7 @@
             if (rce->bLastMiniGopBFrame)
             {
                 if (rce->bframes != 0)
-                    updatePredictor(&predBfromP, qp2qScale(rce->qpaRc),
(double)rce->lastSatd, (double)bframeBits / rce->bframes);
+                    updatePredictor(&predBfromP, qp2qScale(rce->qpaRc),
(double)rce->leadingNoBSatd, (double)bframeBits / rce->bframes);
                 bframeBits = 0;
             }
         }
diff -r 1c037c64274d -r ebc23ec5ac1c source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Thu Feb 20 17:03:38 2014 +0530
+++ b/source/encoder/ratecontrol.h Thu Feb 20 17:47:53 2014 +0530
@@ -53,7 +53,7 @@
     int mvBits;
     int bframes;
     int poc;
-
+    int64_t leadingNoBSatd;
     bool bLastMiniGopBFrame;
     double blurredComplexity;
     double qpaRc;
@@ -61,6 +61,7 @@
     double frameSizePlanned;
     double bufferRate;
     double movingAvgSum;
+    double qpNoVbv;
 };

 struct Predictor
@@ -94,9 +95,10 @@
     bool isVbv;
     Predictor pred[5];
     Predictor predBfromP;
+    Predictor rowPreds[4];
+    Predictor *rowPred[2];
     int bframes;
     int bframeBits;
-    double leadingNoBSatd;
     bool isAbrReset;
     int lastAbrResetPoc;
     int64_t currentSatd;
@@ -106,6 +108,7 @@
     double ipOffset;
     double pbOffset;
     int lastNonBPictType;
+    int64_t leadingNoBSatd;
     double accumPQp;          /* for determining I-frame quant */
     double accumPNorm;
     double lastQScaleFor[3];  /* last qscale for a specific pict type,
used for max_diff & ipb factor stuff */
@@ -118,6 +121,8 @@
     double lastRceq;
     int framesDone;           /* framesDone keeps track of # of frames
passed through RateCotrol already */
     double qCompress;
+    double qpNoVbv;             /* QP for the current frame if 1-pass VBV
was disabled. */
+    double frameSizeEstimated;  /* hold synched frameSize, updated from cu
level vbv rc */
     RateControl(TEncCfg * _cfg);

     // to be called for each frame to process RateControl and set QP

Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 4 of 6] vbv: fix bugs in vbv flow with single pass ABR
X-Mercurial-Node: c5c07a3ee7fcf0f331f06f83b7b3bc0b1bcc1668
Message-Id: <c5c07a3ee7fcf0f331f0.1392901344 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:24 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org

# HG changeset patch
# User Aarthi Thirumalai
# Date 1392899993 -19800
#      Thu Feb 20 18:09:53 2014 +0530
# Node ID c5c07a3ee7fcf0f331f06f83b7b3bc0b1bcc1668
# Parent  ebc23ec5ac1c5f8e2abe0d0b88414fabd2fdf1bb
vbv: fix bugs in vbv flow with single pass ABR

diff -r ebc23ec5ac1c -r c5c07a3ee7fc source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/encoder.cpp Thu Feb 20 18:09:53 2014 +0530
@@ -367,7 +367,7 @@
         // Allow this frame to be recycled if no frame encoders are using
it for reference
         ATOMIC_DEC(&out->m_countRefEncoders);

-        m_rateControl->rateControlEnd(bits, &(curEncoder->m_rce));
+        m_rateControl->rateControlEnd(out, bits, &(curEncoder->m_rce));

         m_dpb->recycleUnreferenced(m_freeList);

diff -r ebc23ec5ac1c -r c5c07a3ee7fc source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/ratecontrol.cpp Thu Feb 20 18:09:53 2014 +0530
@@ -207,7 +207,9 @@
 RateControl::RateControl(TEncCfg * _cfg)
 {
     this->cfg = _cfg;
-    ncu = (int)((cfg->param.sourceHeight * cfg->param.sourceWidth) /
pow((int)16, 2.0));
+    int lowresCuWidth = ((cfg->param.sourceWidth/2) + X265_LOWRES_CU_SIZE
- 1) >> X265_LOWRES_CU_BITS;
+    int lowresCuHeight = ((cfg->param.sourceHeight/2)  +
X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
+    ncu = lowresCuWidth * lowresCuHeight;

     if (cfg->param.rc.cuTree)
     {
@@ -445,12 +447,12 @@
          * average QP of the two adjacent P-frames + an offset */
         TComSlice* prevRefSlice = curSlice->getRefPic(REF_PIC_LIST_0,
0)->getSlice();
         TComSlice* nextRefSlice = curSlice->getRefPic(REF_PIC_LIST_1,
0)->getSlice();
+        double q0 = curSlice->getRefPic(REF_PIC_LIST_0, 0)->m_avgQpRc;
+        double q1 = curSlice->getRefPic(REF_PIC_LIST_1, 0)->m_avgQpRc;
         bool i0 = prevRefSlice->getSliceType() == I_SLICE;
         bool i1 = nextRefSlice->getSliceType() == I_SLICE;
         int dt0 = abs(curSlice->getPOC() - prevRefSlice->getPOC());
         int dt1 = abs(curSlice->getPOC() - nextRefSlice->getPOC());
-        double q0 = prevRefSlice->m_avgQpRc;
-        double q1 = nextRefSlice->m_avgQpRc;

         // Skip taking a reference frame before the Scenecut if ABR has
been reset.
         if (lastAbrResetPoc >= 0 && !isVbv)
@@ -522,7 +524,7 @@
         {
             if (!isVbv)
             {
-                checkAndResetABR(rce);
+                checkAndResetABR(pic, rce);
             }
             q = getQScale(rce, wantedBitsWindow / cplxrSum);

@@ -552,23 +554,22 @@
         if (cfg->param.rc.rateControlMode != X265_RC_CRF)
         {
             double lqmin = 0, lqmax = 0;
-            if (totalBits == 0)
+            if (totalBits == 0 && !isVbv)
             {
                 lqmin = qp2qScale(ABR_INIT_QP_MIN) / lstep;
                 lqmax = qp2qScale(ABR_INIT_QP_MAX) * lstep;
+                q = Clip3(lqmin, lqmax, q);
             }
-            else
+            else if(totalBits > 0 || (isVbv && rce->poc > 0 ))
             {
                 lqmin = lastQScaleFor[sliceType] / lstep;
                 lqmax = lastQScaleFor[sliceType] * lstep;
+                if (overflow > 1.1 && framesDone > 3)
+                    lqmax *= lstep;
+                else if (overflow < 0.9)
+                    lqmin /= lstep;
+                q = Clip3(lqmin, lqmax, q);
             }
-
-            if (overflow > 1.1 && framesDone > 3)
-                lqmax *= lstep;
-            else if (overflow < 0.9)
-                lqmin /= lstep;
-
-            q = Clip3(lqmin, lqmax, q);
         }
         else
         {
@@ -593,7 +594,7 @@
     }
 }

-void RateControl::checkAndResetABR(RateControlEntry* rce)
+void RateControl::checkAndResetABR(TComPic* pic, RateControlEntry* rce)
 {
     double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;

@@ -604,7 +605,7 @@
         {
             // Reset ABR if prev frames are blank to prevent further
sudden overflows/ high bit rate spikes.
             double underflow = 1.0 + (totalBits - wantedBitsWindow) /
abrBuffer;
-            if (underflow < 1 && curSlice->m_avgQpRc == 0)
+            if (underflow < 1 && pic->m_avgQpRc == 0)
             {
                 totalBits = 0;
                 framesDone = 0;
@@ -659,9 +660,9 @@
                 double bufferFillCur = bufferFill - curBits;
                 double targetFill;
                 double totalDuration = 0;
-                frameQ[0] = sliceType == I_SLICE ? q *
cfg->param.rc.ipFactor : q;
-                frameQ[1] = frameQ[0] * cfg->param.rc.pbFactor;
-                frameQ[2] = frameQ[0] / cfg->param.rc.ipFactor;
+                frameQ[P_SLICE] = sliceType == I_SLICE ? q *
cfg->param.rc.ipFactor : q;
+                frameQ[B_SLICE] = frameQ[P_SLICE] * cfg->param.rc.pbFactor;
+                frameQ[I_SLICE] = frameQ[P_SLICE] / cfg->param.rc.ipFactor;

                 /* Loop over the planned future frames. */
                 for (int j = 0; bufferFillCur >= 0 && bufferFillCur <=
bufferSize; j++)
@@ -807,9 +808,8 @@

 void RateControl::updateVbv(int64_t bits, RateControlEntry* rce)
 {
-    int mbCount = (int)((cfg->param.sourceHeight * cfg->param.sourceWidth)
/ pow((int)16, 2.0));

-    if  (rce->lastSatd >= mbCount)
+    if (rce->lastSatd >= ncu)
         updatePredictor(&pred[rce->sliceType], qp2qScale(rce->qpaRc),
(double)rce->lastSatd, (double)bits);

     if (!isVbv)
@@ -826,17 +826,27 @@
 }

 /* After encoding one frame, update rate control state */
-int RateControl::rateControlEnd(int64_t bits, RateControlEntry* rce)
+int RateControl::rateControlEnd(TComPic* pic, int64_t bits,
RateControlEntry* rce)
 {
     if (isAbr)
     {
         if (!isVbv && cfg->param.rc.rateControlMode == X265_RC_ABR)
         {
-            checkAndResetABR(rce);
+            checkAndResetABR(pic, rce);
         }

         if (!isAbrReset)
         {
+            if (pic->m_qpaRc)
+            {
+                for (uint32_t i = 0; i < pic->getFrameHeightInCU(); i++)
+                {
+                    pic->m_avgQpRc += pic->m_qpaRc[i];
+                }
+                pic->m_avgQpRc /= (pic->getFrameHeightInCU() *
pic->getFrameWidthInCU());
+                rce->qpaRc = pic->m_avgQpRc;
+            }
+
             if (rce->sliceType != B_SLICE)
                 /* The factor 1.5 is to tune up the actual bits, otherwise
the cplxrSum is scaled too low
                  * to improve short term compensation for next frame. */
diff -r ebc23ec5ac1c -r c5c07a3ee7fc source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/ratecontrol.h Thu Feb 20 18:09:53 2014 +0530
@@ -128,7 +128,7 @@
     // to be called for each frame to process RateControl and set QP
     void rateControlStart(TComPic* pic, Lookahead *, RateControlEntry*
rce, Encoder* enc);
     void calcAdaptiveQuantFrame(TComPic *pic);
-    int rateControlEnd(int64_t bits, RateControlEntry* rce);
+    int rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce);

 protected:

@@ -142,7 +142,7 @@
     double clipQscale(TComPic* pic, double q);
     void updateVbvPlan(Encoder* enc);
     double predictSize(Predictor *p, double q, double var);
-    void checkAndResetABR(RateControlEntry* rce);
+    void checkAndResetABR(TComPic* pic, RateControlEntry* rce);
 };
 }


Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 5 of 6] vbv: implement row wise vbvRateControl at each row
 diagonal
X-Mercurial-Node: 49b90667f050a7dd9c28b5017f389f5c29a1c191
Message-Id: <49b90667f050a7dd9c28.1392901345 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:25 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org

# HG changeset patch
# User Aarthi Thirumalai
# Date 1392900828 -19800
#      Thu Feb 20 18:23:48 2014 +0530
# Node ID 49b90667f050a7dd9c28b5017f389f5c29a1c191
# Parent  c5c07a3ee7fcf0f331f06f83b7b3bc0b1bcc1668
vbv: implement row wise vbvRateControl at each row diagonal.

diff -r c5c07a3ee7fc -r 49b90667f050 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Thu Feb 20 18:09:53 2014 +0530
+++ b/source/encoder/ratecontrol.cpp Thu Feb 20 18:23:48 2014 +0530
@@ -221,6 +221,10 @@

     // validate for cfg->param.rc, maybe it is need to add a function like
x265_parameters_valiate()
     cfg->param.rc.rfConstant = Clip3((double)-QP_BD_OFFSET, (double)51,
cfg->param.rc.rfConstant);
+    cfg->param.rc.rfConstantMax = Clip3((double)-QP_BD_OFFSET, (double)51,
cfg->param.rc.rfConstantMax);
+    rateFactorMaxIncrement = 0;
+    vbvMinRate = 0;
+
     if (cfg->param.rc.rateControlMode == X265_RC_CRF)
     {
         cfg->param.rc.qp = (int)cfg->param.rc.rfConstant + QP_BD_OFFSET;
@@ -230,6 +234,15 @@
         double mbtree_offset = cfg->param.rc.cuTree ? (1.0 -
cfg->param.rc.qCompress) * 13.5 : 0;
         rateFactorConstant = pow(baseCplx, 1 - qCompress) /
             qp2qScale(cfg->param.rc.rfConstant + mbtree_offset +
QP_BD_OFFSET);
+        if (cfg->param.rc.rfConstantMax)
+        {
+            rateFactorMaxIncrement = cfg->param.rc.rfConstantMax -
cfg->param.rc.rfConstant;
+            if (rateFactorMaxIncrement <= 0)
+            {
+                x265_log(&cfg->param, X265_LOG_WARNING, "CRF max must be
greater than CRF\n");
+                rateFactorMaxIncrement = 0;
+            }
+        }
     }

     isAbr = cfg->param.rc.rateControlMode != X265_RC_CQP; // later add
2pass option
@@ -760,6 +773,181 @@
     return Clip3(lmin1, lmax1, q);
 }

+ double RateControl::predictRowsSizeSum(TComPic* pic, double qpVbv,
int32_t & encodedBitsSoFar)
+{
+    uint32_t rowSatdCostSoFar = 0 ,totalSatdBits = 0;
+    encodedBitsSoFar = 0;
+    double qScale = qp2qScale(qpVbv);
+    int sliceType = pic->getSlice()->getSliceType();
+    TComPic* refPic = pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0);
+    int maxRows = pic->getPicSym()->getFrameHeightInCU();
+    for (int row = 0 ; row < maxRows; row++)
+    {
+        encodedBitsSoFar += pic->m_rowEncodedBits[row];
+        rowSatdCostSoFar = pic->m_rowDiagSatd[row];
+        uint32_t satdCostForPendingCus = pic->m_rowSatdForVbv[row] -
rowSatdCostSoFar;
+        if (satdCostForPendingCus  > 0)
+        {
+            double pred_s = predictSize(rowPred[0], qScale,
satdCostForPendingCus);
+            uint32_t refRowSatdCost= 0 , refRowBits = 0;
+            double refQScale=0;
+
+            if (sliceType != I_SLICE)
+            {
+                for (uint32_t cuAddr = pic->m_numEncodedCusPerRow[row] +
1; cuAddr < pic->getPicSym()->getFrameWidthInCU() * (row + 1); cuAddr++)
+                {
+                    refRowSatdCost += refPic->m_cuCostsForVbv[cuAddr];
+                    refRowBits = refPic->getCU(cuAddr)->m_totalBits;
+                }
+                refQScale = row == maxRows - 1 ?
refPic->m_rowDiagQScale[row] : refPic->m_rowDiagQScale[row + 1];
+            }
+
+            if (sliceType == I_SLICE || qScale >= refQScale)
+            {
+                if (sliceType == P_SLICE
+                    && refPic->getSlice()->getSliceType() == sliceType
+                    && refQScale > 0
+                    && refRowSatdCost > 0)
+                {
+                    if (abs(int32_t(refRowSatdCost -
satdCostForPendingCus)) < (int32_t)satdCostForPendingCus / 2)
+                    {
+                        double pred_t = refRowBits * satdCostForPendingCus
/ refRowSatdCost
+                                        * refQScale / qScale;
+                        totalSatdBits += int32_t((pred_s + pred_t) * 0.5);
+                    }
+                }
+
+                else
+                    totalSatdBits += int32_t(pred_s);
+            }
+            else
+            {
+                 /* Our QP is lower than the reference! */
+                double pred_intra = predictSize(rowPred[1], qScale,
refRowSatdCost);
+                /* Sum: better to overestimate than underestimate by using
only one of the two predictors. */
+                totalSatdBits += int32_t(pred_intra + pred_s);
+            }
+        }
+    }
+    return totalSatdBits + encodedBitsSoFar;
+ }
+
+int RateControl::rowDiagonalVbvRateControl(TComPic* pic, uint32_t row,
RateControlEntry* rce, double& qpVbv)
+{
+    fprintf(fp,"\n poc :%d , type : %d , slice Qp : %d , row : %d ,
startvbv : %f ", pic->getPOC(), rce->sliceType,
pic->getSlice()->getSliceQp(), row, qpVbv);
+    if (rce->poc == 24)
+    {
+        int i=0; i++;
+    }
+    double qScaleVbv = qp2qScale(qpVbv);
+    pic->m_rowDiagQp[row] = qpVbv;
+    pic->m_rowDiagQScale[row] = qScaleVbv;
+    //TODO  : check whther we gotto update prodictor using whole Row Satd
or only satd of blocks upto the diagonal in row.
+    updatePredictor(rowPred[0], qScaleVbv,
(double)pic->m_rowDiagSatd[row], (double)pic->m_rowEncodedBits[row]);
+    if (pic->getSlice()->getSliceType() == P_SLICE)
+    {
+        TComPic* refSlice = pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0);
+        if (qpVbv < refSlice->m_rowDiagQp[row])
+        {
+            updatePredictor(rowPred[1], qScaleVbv,
refSlice->m_rowDiagSatd[row], refSlice->m_rowEncodedBits[row]);
+        }
+    }
+
+    int canReencodeRow = 1;
+    /* tweak quality based on difference from predicted size */
+    double prevRowQp = qpVbv;
+    double qpAbsoluteMax = MAX_MAX_QP;
+    if (rateFactorMaxIncrement)
+        qpAbsoluteMax = X265_MIN(qpAbsoluteMax, rce->qpNoVbv +
rateFactorMaxIncrement);
+    double qpMax = X265_MIN(prevRowQp + cfg->param.rc.qpStep,
qpAbsoluteMax );
+    double qpMin = X265_MAX(prevRowQp - cfg->param.rc.qpStep, MIN_QP );
+    double stepSize = 0.5;
+    double bufferLeftPlanned = bufferFill - rce->frameSizePlanned;
+    if (bufferLeftPlanned < 0 )
+    { int i=0; i ++;
+    }
+    double maxFrameError = X265_MAX(0.05, 1.0 / pic->getFrameHeightInCU());
+
+    if (row < pic->getPicSym()->getFrameHeightInCU() - 1)
+    {
+        /* B-frames shouldn't use lower QP than their reference frames. */
+        if (rce->sliceType == B_SLICE)
+        {
+            TComPic* refSlice1 =
pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0);
+            TComPic* refSlice2 =
pic->getSlice()->getRefPic(REF_PIC_LIST_1, 0);
+            qpMin = X265_MAX(qpMin, X265_MAX(refSlice1->m_rowDiagQp[row],
refSlice2->m_rowDiagQp[row]));
+            qpVbv = X265_MAX(qpVbv, qpMin);
+        }
+        /* More threads means we have to be more cautious in letting
ratecontrol use up extra bits. */
+        double rcTol = bufferLeftPlanned / cfg->param.frameNumThreads *
cfg->param.rc.rateTolerance;
+        int32_t encodedBitsSoFar = 0;
+        double b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+
+        /* Don't increase the row QPs until a sufficent amount of the bits
of the frame have been processed, in case a flat */
+        /* area at the top of the frame was measured inaccurately. */
+        if (encodedBitsSoFar < 0.05f * rce->frameSizePlanned)
+            qpMax = qpAbsoluteMax = prevRowQp;
+
+        if (rce->sliceType != I_SLICE)
+            rcTol *= 0.5;
+
+        if (!vbvMinRate)
+            qpMin = X265_MAX(qpMin, rce->qpNoVbv);
+
+        while (qpVbv < qpMax
+              && ((b1 > rce->frameSizePlanned + rcTol) ||
+                  (bufferFill - b1 < bufferLeftPlanned * 0.5) ||
+                  (b1 > rce->frameSizePlanned && qpVbv < rce->qpNoVbv)))
+        {
+            qpVbv += stepSize;
+            b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+        }
+
+        while (qpVbv > qpMin
+               && (qpVbv > pic->m_rowDiagQp[0] || singleFrameVbv)
+               && ((b1 < rce->frameSizePlanned * 0.8f && qpVbv <=
prevRowQp)
+               || b1 < (bufferFill - bufferSize + bufferRate) * 1.1))
+        {
+            qpVbv -= stepSize;
+            b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+        }
+        /* avoid VBV underflow */
+        while ((qpVbv < qpAbsoluteMax)
+               && (bufferFill - b1 < bufferRate * maxFrameError))
+        {
+            qpVbv += stepSize;
+            b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+        }
+        frameSizeEstimated = b1;
+
+        /* If the current row was large enough to cause a large QP jump,
try re-encoding it. */
+        if (qpVbv > qpMax && prevRowQp < qpMax && canReencodeRow)
+        {
+            /* Bump QP to halfway in between... close enough. */
+            qpVbv = Clip3(prevRowQp + 1.0f, qpMax, (prevRowQp +
qpVbv)*0.5);
+            fprintf(fp,", endvbv : %f ", qpVbv);
+            return -1;
+        }
+    }
+    else
+    {
+        int32_t encodedBitsSoFar = 0;
+        frameSizeEstimated = predictRowsSizeSum(pic, qpVbv,
encodedBitsSoFar);
+        /* Last-ditch attempt: if the last row of the frame underflowed
the VBV,
+         * try again. */
+        if((frameSizeEstimated > (bufferFill - bufferRate * maxFrameError)
&&
+            qpVbv < qpMax && canReencodeRow))
+        {
+            qpVbv = qpMax;
+            fprintf(fp,", endvbv : %f ", qpVbv);
+            return -1;
+        }
+    }
+    fprintf(fp,", endvbv : %f ", qpVbv);
+    return 0;
+}
+
+
 /* modify the bitrate curve from pass1 for one frame */
 double RateControl::getQScale(RateControlEntry *rce, double rateFactor)
 {
diff -r c5c07a3ee7fc -r 49b90667f050 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Thu Feb 20 18:09:53 2014 +0530
+++ b/source/encoder/ratecontrol.h Thu Feb 20 18:23:48 2014 +0530
@@ -92,6 +92,7 @@
     double vbvMaxRate;       /* in kbps */
     double vbvMinRate;       /* in kbps */
     bool singleFrameVbv;
+    double rateFactorMaxIncrement; /* Don't allow RF above (CRF + this
value). */
     bool isVbv;
     Predictor pred[5];
     Predictor predBfromP;
@@ -129,6 +130,7 @@
     void rateControlStart(TComPic* pic, Lookahead *, RateControlEntry*
rce, Encoder* enc);
     void calcAdaptiveQuantFrame(TComPic *pic);
     int rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce);
+    int rowDiagonalVbvRateControl(TComPic* pic, uint32_t row,
RateControlEntry* rce, double& qpVbv);

 protected:

@@ -143,6 +145,7 @@
     void updateVbvPlan(Encoder* enc);
     double predictSize(Predictor *p, double q, double var);
     void checkAndResetABR(TComPic* pic, RateControlEntry* rce);
+    double predictRowsSizeSum(TComPic* pic, double qpm , int32_t&
encodedBits);
 };
 }


Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 6 of 6] vbv: integrate row level vbv ratecontrol at each
major
 row diagonal
X-Mercurial-Node: 650d5f835e417f45bd8a9f86465ca1909eaa9526
Message-Id: <650d5f835e417f45bd8a.1392901346 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:26 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org

# HG changeset patch
# User Aarthi Thirumalai
# Date 1392901254 -19800
#      Thu Feb 20 18:30:54 2014 +0530
# Node ID 650d5f835e417f45bd8a9f86465ca1909eaa9526
# Parent  49b90667f050a7dd9c28b5017f389f5c29a1c191
vbv: integrate row level vbv ratecontrol at each major row diagonal.

diff -r 49b90667f050 -r 650d5f835e41 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Thu Feb 20 18:23:48 2014 +0530
+++ b/source/encoder/frameencoder.cpp Thu Feb 20 18:30:54 2014 +0530
@@ -1057,6 +1057,7 @@
     CTURow& codeRow = m_rows[m_cfg->param.bEnableWavefront ? row : 0];
     const uint32_t numCols = m_pic->getPicSym()->getFrameWidthInCU();
     const uint32_t lineStartCUAddr = row * numCols;
+    double qpBase = m_pic->m_avgQpRc;
     for (uint32_t col = curRow.m_completed; col < numCols; col++)
     {
         const uint32_t cuAddr = lineStartCUAddr + col;
@@ -1067,24 +1068,42 @@
         codeRow.m_entropyCoder.resetEntropy();

         TEncSbac *bufSbac = (m_cfg->param.bEnableWavefront && col == 0 &&
row > 0) ? &m_rows[row - 1].m_bufferSbacCoder : NULL;
-        if (m_cfg->param.rc.aqMode)
+
+        if ((uint32_t)row >= col && (row !=0))
+            qpBase = m_pic->getCU(cuAddr - numCols + 1)->m_baseQp;
+
+        if (m_cfg->param.rc.aqMode || (m_cfg->param.rc.vbvBufferSize >0 &&
m_cfg->param.rc.vbvMaxBitrate >0))
         {
-            int qp = calcQpForCu(m_pic, cuAddr);
+            int qp = calcQpForCu(m_pic, cuAddr , qpBase);
             setLambda(qp, row);
-            if (qp > MAX_QP)
-                qp = MAX_QP;
-            cu->setQP(0, (char)qp);
+            qp = X265_MIN(qp, MAX_QP);
+            cu->setQP(0,char(qp));
+            cu->m_baseQp = qpBase;
         }
         codeRow.processCU(cu, m_pic->getSlice(), bufSbac,
m_cfg->param.bEnableWavefront && col == 1);

-        // TODO: Keep atomic running totals for rate control?
-        // cu->m_totalBits;
-        // cu->m_totalCost;
-        // cu->m_totalDistortion;
+        if (m_cfg->param.rc.vbvBufferSize && m_cfg->param.rc.vbvMaxBitrate)
+        {
+            // Update encoded bits, satdCost, baseQP for each CU
+            m_pic->m_rowDiagSatd[row] += m_pic->m_cuCostsForVbv[cuAddr];
+            m_pic->m_rowEncodedBits[row] += cu->m_totalBits;
+            m_pic->m_numEncodedCusPerRow[row] = cuAddr;
+            m_pic->m_qpaAq[row] += cu->getQP(0);
+            m_pic->m_qpaRc[row] += cu->m_baseQp;
+
+            if ((uint32_t)row == col)
+                m_pic->m_rowDiagQp[row] = qpBase;
+
+            // If current block is at row diagonal checkpoint, call vbv
ratecontrol.
+            if ((uint32_t)row == col && row != 0 )
+            {
+                 m_top->m_rateControl->rowDiagonalVbvRateControl(m_pic,
row, &m_rce, qpBase);
+                 qpBase = Clip3((double)MIN_QP, (double)MAX_MAX_QP,
qpBase);
+            }
+        }

         // Completed CU processing
         m_rows[row].m_completed++;
-
         if (m_rows[row].m_completed >= 2 && row < m_numRows - 1)
         {
             ScopedLock below(m_rows[row + 1].m_lock);
@@ -1128,34 +1147,43 @@
     curRow.m_busy = false;
 }

-int FrameEncoder::calcQpForCu(TComPic *pic, uint32_t cuAddr)
+int FrameEncoder::calcQpForCu(TComPic *pic, uint32_t cuAddr, double baseQp)
 {
     x265_emms();
-    double qp = pic->getSlice()->m_avgQpRc;
-    if (m_cfg->param.rc.aqMode)
+    double qp = baseQp;
+
+    /* Derive qpOffet for each CU by averaging offsets for all 16x16
blocks in the cu. */
+    double qp_offset = 0;
+    int maxBlockCols = (pic->getPicYuvOrg()->getWidth() + (16 - 1)) / 16;
+    int maxBlockRows = (pic->getPicYuvOrg()->getHeight() + (16 - 1)) / 16;
+    int noOfBlocks = g_maxCUWidth / 16;
+    int block_y = (cuAddr / pic->getPicSym()->getFrameWidthInCU()) *
noOfBlocks;
+    int block_x = (cuAddr * noOfBlocks) - block_y *
pic->getPicSym()->getFrameWidthInCU();
+
+    double *qpoffs = (pic->getSlice()->isReferenced() &&
m_cfg->param.rc.cuTree) ? pic->m_lowres.qpOffset : pic->m_lowres.qpAqOffset;
+    int cnt = 0, idx =0;
+    for (int h = 0; h < noOfBlocks && block_y < maxBlockRows; h++,
block_y++)
     {
-        /* Derive qpOffet for each CU by averaging offsets for all 16x16
blocks in the cu. */
-        double qp_offset = 0;
-        int maxBlockCols = (pic->getPicYuvOrg()->getWidth() + (16 - 1)) /
16;
-        int maxBlockRows = (pic->getPicYuvOrg()->getHeight() + (16 - 1)) /
16;
-        int noOfBlocks = g_maxCUWidth / 16;
-        int block_y = (cuAddr / pic->getPicSym()->getFrameWidthInCU()) *
noOfBlocks;
-        int block_x = (cuAddr * noOfBlocks) - block_y *
pic->getPicSym()->getFrameWidthInCU();
+        for (int w = 0; w < noOfBlocks && (block_x + w) < maxBlockCols;
w++)
+        {
+            idx = block_x + w + (block_y * maxBlockCols);
+            if (m_cfg->param.rc.aqMode)
+                qp_offset += qpoffs[idx];

-        double *qpoffs = (pic->getSlice()->isReferenced() &&
m_cfg->param.rc.cuTree) ? pic->m_lowres.qpOffset : pic->m_lowres.qpAqOffset;
-        int cnt = 0;
-        for (int h = 0; h < noOfBlocks && block_y < maxBlockRows; h++,
block_y++)
-        {
-            for (int w = 0; w < noOfBlocks && (block_x + w) <
maxBlockCols; w++)
+            if (m_cfg->param.rc.vbvBufferSize > 0 &&
m_cfg->param.rc.vbvMaxBitrate > 0)
             {
-                qp_offset += qpoffs[block_x + w + (block_y *
maxBlockCols)];
-                cnt++;
+                m_pic->m_cuCostsForVbv[cuAddr] +=
m_pic->m_lowres.lowresCostForRc[idx];
+                if (!m_cfg->param.rc.cuTree)
+                    m_pic->m_cuCostsForVbv[cuAddr] +=
m_pic->m_lowres.intraCost[idx];
             }
+            cnt++;
         }
+    }

-        qp_offset /= cnt;
-        qp += qp_offset;
-    }
+    qp_offset /= cnt;
+    qp += qp_offset;
+
+
     return Clip3(MIN_QP, MAX_MAX_QP, (int)(qp + 0.5));
 }

diff -r 49b90667f050 -r 650d5f835e41 source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h Thu Feb 20 18:23:48 2014 +0530
+++ b/source/encoder/frameencoder.h Thu Feb 20 18:30:54 2014 +0530
@@ -173,7 +173,7 @@
 protected:

     void determineSliceBounds();
-    int calcQpForCu(TComPic *pic, uint32_t cuAddr);
+    int calcQpForCu (TComPic *pic, uint32_t cuAddr, double baseQp);
     Encoder*                 m_top;
     TEncCfg*                 m_cfg;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20140220/4e443202/attachment-0001.html>


More information about the x265-devel mailing list