[x265] [PATCH] Add filler bits when frame bits < vbv target in strict-cbr

aruna at multicorewareinc.com aruna at multicorewareinc.com
Wed Jan 25 14:59:44 CET 2017


# HG changeset patch
# User Aruna Matheswaran <aruna at multicorewareinc.com>
# Date 1484888261 -19800
#      Fri Jan 20 10:27:41 2017 +0530
# Node ID d1f6d9b8d6be1fb44d7d1dad7dd642c7ae95b226
# Parent  3737c70c3308c980259d60410c4231c74e892d23
Add filler bits when frame bits < vbv target in strict-cbr

diff -r 3737c70c3308 -r d1f6d9b8d6be source/common/common.h
--- a/source/common/common.h	Fri Jan 20 16:44:03 2017 +0530
+++ b/source/common/common.h	Fri Jan 20 10:27:41 2017 +0530
@@ -330,6 +330,10 @@
 
 #define INTEGRAL_PLANE_NUM          12 // 12 integral planes for 32x32, 32x24, 32x8, 24x32, 16x16, 16x12, 16x4, 12x16, 8x32, 8x8, 4x16 and 4x4.
 
+#define NAL_TYPE_OVERHEAD 2
+#define START_CODE_OVERHEAD 3 
+#define FILLER_OVERHEAD (NAL_TYPE_OVERHEAD + START_CODE_OVERHEAD + 1)
+
 namespace X265_NS {
 
 enum { SAO_NUM_OFFSET = 4 };
diff -r 3737c70c3308 -r d1f6d9b8d6be source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Fri Jan 20 16:44:03 2017 +0530
+++ b/source/encoder/frameencoder.cpp	Fri Jan 20 10:27:41 2017 +0530
@@ -969,12 +969,29 @@
     }
     m_accessUnitBits = bytes << 3;
 
+    int filler = 0;
+    /* rateControlEnd may also block for earlier frames to call rateControlUpdateStats */
+    if (m_top->m_rateControl->rateControlEnd(m_frame, m_accessUnitBits, &m_rce, &filler) < 0)
+        m_top->m_aborted = true;
+
+    if (filler > 0)
+    {
+        filler = (filler - FILLER_OVERHEAD * 8) >> 3;
+        m_bs.resetBits();
+        while (filler > 0)
+        {
+            m_bs.write(0xff, 8);
+            filler--;
+        }
+        m_bs.writeByteAlignment();
+        m_nalList.serialize(NAL_UNIT_FILLER_DATA, m_bs);
+        bytes += m_nalList.m_nal[m_nalList.m_numNal - 1].sizeBytes;
+        bytes -= 3; //exclude start code prefix
+        m_accessUnitBits = bytes << 3;
+    }
+
     m_endCompressTime = x265_mdate();
 
-    /* rateControlEnd may also block for earlier frames to call rateControlUpdateStats */
-    if (m_top->m_rateControl->rateControlEnd(m_frame, m_accessUnitBits, &m_rce) < 0)
-        m_top->m_aborted = true;
-
     /* Decrement referenced frame reference counts, allow them to be recycled */
     for (int l = 0; l < numPredDir; l++)
     {
diff -r 3737c70c3308 -r d1f6d9b8d6be source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Fri Jan 20 16:44:03 2017 +0530
+++ b/source/encoder/ratecontrol.cpp	Fri Jan 20 10:27:41 2017 +0530
@@ -2479,14 +2479,16 @@
     p->offset += new_offset;
 }
 
-void RateControl::updateVbv(int64_t bits, RateControlEntry* rce)
+int RateControl::updateVbv(int64_t bits, RateControlEntry* rce)
 {
     int predType = rce->sliceType;
+    int filler = 0;
+    double bufferBits;
     predType = rce->sliceType == B_SLICE && rce->keptAsRef ? 3 : predType;
     if (rce->lastSatd >= m_ncu && rce->encodeOrder >= m_lastPredictorReset)
         updatePredictor(&m_pred[predType], x265_qp2qScale(rce->qpaRc), (double)rce->lastSatd, (double)bits);
     if (!m_isVbv)
-        return;
+        return 0;
 
     m_bufferFillFinal -= bits;
 
@@ -2495,15 +2497,32 @@
 
     m_bufferFillFinal = X265_MAX(m_bufferFillFinal, 0);
     m_bufferFillFinal += m_bufferRate;
-    m_bufferFillFinal = X265_MIN(m_bufferFillFinal, m_bufferSize);
-    double bufferBits = X265_MIN(bits + m_bufferExcess, m_bufferRate);
-    m_bufferExcess = X265_MAX(m_bufferExcess - bufferBits + bits, 0);
-    m_bufferFillActual += bufferBits - bits;
-    m_bufferFillActual = X265_MIN(m_bufferFillActual, m_bufferSize);
+
+    if (m_bufferFillFinal > m_bufferSize) 
+    {
+        if (m_param->rc.bStrictCbr)
+        {
+            filler = (int)(m_bufferFillFinal - m_bufferSize);
+            filler += FILLER_OVERHEAD * 8;
+            m_bufferFillFinal -= filler;
+            bufferBits = X265_MIN(bits + filler + m_bufferExcess, m_bufferRate);
+            m_bufferExcess = X265_MAX(m_bufferExcess - bufferBits + bits + filler, 0);
+            m_bufferFillActual += bufferBits - bits - filler;
+        }
+        else
+        {
+            m_bufferFillFinal = X265_MIN(m_bufferFillFinal, m_bufferSize);
+            bufferBits = X265_MIN(bits + m_bufferExcess, m_bufferRate);
+            m_bufferExcess = X265_MAX(m_bufferExcess - bufferBits + bits, 0);
+            m_bufferFillActual += bufferBits - bits;
+            m_bufferFillActual = X265_MIN(m_bufferFillActual, m_bufferSize);
+        }
+    }
+    return filler;
 }
 
 /* After encoding one frame, update rate control state */
-int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* rce)
+int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* rce, int *filler)
 {
     int orderValue = m_startEndOrder.get();
     int endOrdinal = (rce->encodeOrder + m_param->frameNumThreads) * 2 - 1;
@@ -2634,7 +2653,7 @@
 
     if (m_isVbv)
     {
-        updateVbv(actualBits, rce);
+        *filler = updateVbv(actualBits, rce);
 
         if (m_param->bEmitHRDSEI)
         {
@@ -2656,9 +2675,9 @@
 
                 rce->hrdTiming->cpbInitialAT = hrd->cbrFlag ? m_prevCpbFinalAT : X265_MAX(m_prevCpbFinalAT, cpbEarliestAT);
             }
-
+            int filler_bits = *filler ? (*filler - START_CODE_OVERHEAD * 8)  : 0; 
             uint32_t cpbsizeUnscale = hrd->cpbSizeValue << (hrd->cpbSizeScale + CPB_SHIFT);
-            rce->hrdTiming->cpbFinalAT = m_prevCpbFinalAT = rce->hrdTiming->cpbInitialAT + actualBits / cpbsizeUnscale;
+            rce->hrdTiming->cpbFinalAT = m_prevCpbFinalAT = rce->hrdTiming->cpbInitialAT + (actualBits + filler_bits)/ cpbsizeUnscale;
             rce->hrdTiming->dpbOutputTime = (double)rce->picTimingSEI->m_picDpbOutputDelay * time->numUnitsInTick / time->timeScale + rce->hrdTiming->cpbRemovalTime;
         }
     }
diff -r 3737c70c3308 -r d1f6d9b8d6be source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Fri Jan 20 16:44:03 2017 +0530
+++ b/source/encoder/ratecontrol.h	Fri Jan 20 10:27:41 2017 +0530
@@ -242,7 +242,7 @@
     // to be called for each curFrame to process RateControl and set QP
     int  rateControlStart(Frame* curFrame, RateControlEntry* rce, Encoder* enc);
     void rateControlUpdateStats(RateControlEntry* rce);
-    int  rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* rce);
+    int  rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* rce, int *filler);
     int  rowVbvRateControl(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv);
     int  rateControlSliceType(int frameNum);
     bool cuTreeReadFor2Pass(Frame* curFrame);
@@ -269,7 +269,7 @@
     void   accumPQpUpdate();
 
     int    getPredictorType(int lowresSliceType, int sliceType);
-    void   updateVbv(int64_t bits, RateControlEntry* rce);
+    int    updateVbv(int64_t bits, RateControlEntry* rce);
     void   updatePredictor(Predictor *p, double q, double var, double bits);
     double clipQscale(Frame* pic, RateControlEntry* rce, double q);
     void   updateVbvPlan(Encoder* enc);


More information about the x265-devel mailing list