# HG changeset patch
# User weixuan
# Date 1474441963 -28800
#      Wed Sep 21 15:12:43 2016 +0800
# Node ID f0901bc79c1a80dfb3e79673e33f2faa2cd0f488
# Parent  f29d88d93c2c23802bf4f99f923afc0e411de71f
store most frequently used list in ref list in PPS

diff -r f29d88d93c2c -r f0901bc79c1a source/common/slice.h
--- a/source/common/slice.h	Tue Sep 20 09:53:47 2016 +0530
+++ b/source/common/slice.h	Wed Sep 21 15:12:43 2016 +0800
@@ -282,6 +282,9 @@
 
     bool     bDeblockingFilterControlPresent;
     bool     bPicDisableDeblockingFilter;
+
+    int      ppsId;
+    int      numRefIdxDefault[2];
 };
 
 struct WeightParam
diff -r f29d88d93c2c -r f0901bc79c1a source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Tue Sep 20 09:53:47 2016 +0530
+++ b/source/encoder/encoder.cpp	Wed Sep 21 15:12:43 2016 +0800
@@ -216,6 +216,12 @@
 
     initVPS(&m_vps);
     initSPS(&m_sps);
+
+    if (m_param->bEmitHRDSEI)
+        m_rateControl->initHRD(m_sps);
+    if (!m_rateControl->init(m_sps))
+        m_aborted = true;
+
     initPPS(&m_pps);
    
     if (m_param->rc.vbvBufferSize)
@@ -311,10 +317,6 @@
         m_frameEncoder[i]->m_done.wait(); /* wait for thread to initialize */
     }
 
-    if (m_param->bEmitHRDSEI)
-        m_rateControl->initHRD(m_sps);
-    if (!m_rateControl->init(m_sps))
-        m_aborted = true;
     if (!m_lookahead->create())
         m_aborted = true;
 
@@ -1428,6 +1430,15 @@
     bs.writeByteAlignment();
     list.serialize(NAL_UNIT_SPS, bs);
 
+    m_pps.ppsId++;
+    if (m_param->rc.bStatRead)
+    {
+        if (m_pps.ppsId == m_rateControl->m_rcePPS2Pass[m_pps.ppsId].ppsId)
+        {
+            m_pps.numRefIdxDefault[0] = m_rateControl->m_rcePPS2Pass[m_pps.ppsId].numRefIdxDefault[0];
+            m_pps.numRefIdxDefault[1] = m_rateControl->m_rcePPS2Pass[m_pps.ppsId].numRefIdxDefault[1];
+        }
+    }
     bs.resetBits();
     sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1));
     bs.writeByteAlignment();
@@ -1621,6 +1632,10 @@
     pps->deblockingFilterTcOffsetDiv2 = m_param->deblockingFilterTCOffset;
 
     pps->bEntropyCodingSyncEnabled = m_param->bEnableWavefront;
+
+    pps->ppsId = 0;
+    pps->numRefIdxDefault[0] = 1;
+    pps->numRefIdxDefault[1] = 1;
 }
 
 void Encoder::configure(x265_param *p)
diff -r f29d88d93c2c -r f0901bc79c1a source/encoder/entropy.cpp
--- a/source/encoder/entropy.cpp	Tue Sep 20 09:53:47 2016 +0530
+++ b/source/encoder/entropy.cpp	Wed Sep 21 15:12:43 2016 +0800
@@ -333,8 +333,8 @@
     WRITE_CODE(0, 3,                       "num_extra_slice_header_bits");
     WRITE_FLAG(pps.bSignHideEnabled,       "sign_data_hiding_flag");
     WRITE_FLAG(0,                          "cabac_init_present_flag");
-    WRITE_UVLC(0,                          "num_ref_idx_l0_default_active_minus1");
-    WRITE_UVLC(0,                          "num_ref_idx_l1_default_active_minus1");
+    WRITE_UVLC(pps.numRefIdxDefault[0] - 1, "num_ref_idx_l0_default_active_minus1");
+    WRITE_UVLC(pps.numRefIdxDefault[1] - 1, "num_ref_idx_l1_default_active_minus1");
 
     WRITE_SVLC(0, "init_qp_minus26");
     WRITE_FLAG(pps.bConstrainedIntraPred, "constrained_intra_pred_flag");
@@ -633,7 +633,7 @@
 
     if (!slice.isIntra())
     {
-        bool overrideFlag = (slice.m_numRefIdx[0] != 1 || (slice.isInterB() && slice.m_numRefIdx[1] != 1));
+        bool overrideFlag = (slice.m_numRefIdx[0] != slice.m_pps->numRefIdxDefault[0] || (slice.isInterB() && slice.m_numRefIdx[1] != slice.m_pps->numRefIdxDefault[1]));
         WRITE_FLAG(overrideFlag, "num_ref_idx_active_override_flag");
         if (overrideFlag)
         {
diff -r f29d88d93c2c -r f0901bc79c1a source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Tue Sep 20 09:53:47 2016 +0530
+++ b/source/encoder/ratecontrol.cpp	Wed Sep 21 15:12:43 2016 +0800
@@ -542,9 +542,10 @@
                 }
                 rce = &m_rce2Pass[encodeOrder];
                 m_encOrder[frameNumber] = encodeOrder;
-                e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf scu:%lf",
+                e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf ppsId:%d numl0:%d numl1:%d scu:%lf",
                        &picType, &qpRc, &qpAq, &qNoVbv, &qRceq, &rce->coeffBits,
                        &rce->mvBits, &rce->miscBits, &rce->iCuCount, &rce->pCuCount,
+                       &rce->ppsId, &rce->numRefIdxDefault[0], &rce->numRefIdxDefault[1],
                        &rce->skipCuCount);
                 rce->keptAsRef = true;
                 rce->isIdr = false;
@@ -573,6 +574,7 @@
                 rce->qRceq = qRceq;
                 p = next;
             }
+            analyseRefIdx2Pass();
             X265_FREE(statsBuf);
             if (m_param->rc.rateControlMode != X265_RC_CQP)
             {
@@ -849,6 +851,106 @@
     return false;
 }
 
+#define MAX_NUM_REF_IDX 64
+
+void RateControl::analyseRefIdx2Pass()
+{
+    int numRefIdxl0[MAX_NUM_REF_IDX];
+    int numRefIdxl1[MAX_NUM_REF_IDX];
+    int i_max_l0 = 0;
+    int i_max_l1 = 0;
+    int i = 0;
+    int j = 0;
+    int ppsId = 0;
+    int i_l0 = 0;
+    int i_l1 = 0;
+
+    m_rcePPS2Pass = X265_MALLOC(RateControlEntryPPS, m_rce2Pass[m_numEntries - 1].ppsId + 1);
+    if (!m_rcePPS2Pass)
+    {
+        x265_log(m_param, X265_LOG_ERROR, "Rce PPS Entries for 2 pass cannot be allocated\n");
+        return;
+    }
+
+    for (j = 0; j < MAX_NUM_REF_IDX; j++)
+    {
+        numRefIdxl0[j] = 0;
+        numRefIdxl1[j] = 0;
+    }
+    ppsId = m_rce2Pass[i].ppsId;
+
+    for (i = 0; i < m_numEntries; i++)
+    {
+        if (m_rce2Pass[i].ppsId == ppsId)
+        {
+            i_l0 = m_rce2Pass[i].numRefIdxDefault[0];
+            i_l1 = m_rce2Pass[i].numRefIdxDefault[1];
+
+            if ((0 < i_l0) && (MAX_NUM_REF_IDX > i_l0))
+                numRefIdxl0[i_l0]++;
+            if ((0 < i_l1) && (MAX_NUM_REF_IDX > i_l1))
+                numRefIdxl1[i_l1]++;
+        }
+        else
+        {
+            i_max_l0 = 0;
+            i_max_l1 = 0;
+            m_rcePPS2Pass[ppsId].numRefIdxDefault[0] = 1;
+            m_rcePPS2Pass[ppsId].numRefIdxDefault[1] = 1;
+            for (j = 0; j < MAX_NUM_REF_IDX; j++)
+            {
+                if (i_max_l0 < numRefIdxl0[j])
+                {
+                    i_max_l0 = numRefIdxl0[j];
+                    m_rcePPS2Pass[ppsId].numRefIdxDefault[0] = j;
+                }
+                if (i_max_l1 < numRefIdxl1[j])
+                {
+                    i_max_l1 = numRefIdxl1[j];
+                    m_rcePPS2Pass[ppsId].numRefIdxDefault[1] = j;
+                }
+            }
+            m_rcePPS2Pass[ppsId].ppsId = ppsId;
+
+            for (j = 0; j < MAX_NUM_REF_IDX; j++)
+            {
+                numRefIdxl0[j] = 0;
+                numRefIdxl1[j] = 0;
+            }
+            ppsId = m_rce2Pass[i].ppsId;
+
+            i_l0 = m_rce2Pass[i].numRefIdxDefault[0];
+            i_l1 = m_rce2Pass[i].numRefIdxDefault[1];
+
+            if ((0 < i_l0) && (MAX_NUM_REF_IDX > i_l0))
+                numRefIdxl0[i_l0]++;
+            if ((0 < i_l1) && (MAX_NUM_REF_IDX > i_l1))
+                numRefIdxl1[i_l1]++;
+        }
+    }
+
+    i_max_l0 = 0;
+    i_max_l1 = 0;
+    m_rcePPS2Pass[ppsId].numRefIdxDefault[0] = 1;
+    m_rcePPS2Pass[ppsId].numRefIdxDefault[1] = 1;
+    for (j = 0; j < MAX_NUM_REF_IDX; j++)
+    {
+        if (i_max_l0 < numRefIdxl0[j])
+        {
+            i_max_l0 = numRefIdxl0[j];
+            m_rcePPS2Pass[ppsId].numRefIdxDefault[0] = j;
+        }
+        if (i_max_l1 < numRefIdxl1[j])
+        {
+            i_max_l1 = numRefIdxl1[j];
+            m_rcePPS2Pass[ppsId].numRefIdxDefault[1] = j;
+        }
+    }
+    m_rcePPS2Pass[ppsId].ppsId = ppsId;
+
+    return;
+}
+
 bool RateControl::initPass2()
 {
     uint64_t allConstBits = 0, allCodedBits = 0;
@@ -2619,7 +2721,7 @@
         : rce->sliceType == P_SLICE ? 'P'
         : IS_REFERENCED(curFrame) ? 'B' : 'b';
     if (fprintf(m_statFileOut,
-                "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d icu:%.2f pcu:%.2f scu:%.2f ;\n",
+                "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d icu:%.2f pcu:%.2f ppsId:%d numl0:%d numl1:%d scu:%.2f ;\n",
                 rce->poc, rce->encodeOrder,
                 cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
                 rce->qpNoVbv, rce->qRceq,
@@ -2628,6 +2730,9 @@
                 curFrame->m_encData->m_frameStats.miscBits,
                 curFrame->m_encData->m_frameStats.percent8x8Intra * m_ncu,
                 curFrame->m_encData->m_frameStats.percent8x8Inter * m_ncu,
+                curFrame->m_encData->m_slice->m_pps->ppsId,
+                curFrame->m_encData->m_slice->m_numRefIdx[0],
+                curFrame->m_encData->m_slice->m_numRefIdx[1],
                 curFrame->m_encData->m_frameStats.percent8x8Skip  * m_ncu) < 0)
         goto writeFailure;
     /* Don't re-write the data in multi-pass mode. */
@@ -2715,6 +2820,10 @@
         fclose(m_cutreeStatFileIn);
 
     X265_FREE(m_rce2Pass);
+    if (m_param->rc.bStatRead)
+    {
+        X265_FREE(m_rcePPS2Pass);
+    }
     X265_FREE(m_encOrder);
     for (int i = 0; i < 2; i++)
         X265_FREE(m_cuTreeStats.qpBuffer[i]);
diff -r f29d88d93c2c -r f0901bc79c1a source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Tue Sep 20 09:53:47 2016 +0530
+++ b/source/encoder/ratecontrol.h	Wed Sep 21 15:12:43 2016 +0800
@@ -109,10 +109,20 @@
     bool     keptAsRef;
     bool     scenecut;
     bool     isIdr;
+
+    int      ppsId;
+    int      numRefIdxDefault[2];
+
     SEIPictureTiming *picTimingSEI;
     HRDTiming        *hrdTiming;
 };
 
+struct RateControlEntryPPS
+{
+    int      ppsId;
+    int      numRefIdxDefault[2];
+};
+
 class RateControl
 {
 public:
@@ -220,6 +230,7 @@
     int64_t m_predictedBits;
     int     *m_encOrder;
     RateControlEntry* m_rce2Pass;
+    RateControlEntryPPS* m_rcePPS2Pass;
     struct
     {
         uint16_t *qpBuffer[2]; /* Global buffers for converting MB-tree quantizer data. */
@@ -273,6 +284,7 @@
     void   checkAndResetABR(RateControlEntry* rce, bool isFrameDone);
     double predictRowsSizeSum(Frame* pic, RateControlEntry* rce, double qpm, int32_t& encodedBits);
     bool   analyseABR2Pass(uint64_t allAvailableBits);
+    void   analyseRefIdx2Pass();
     void   initFramePredictors();
     double getDiffLimitedQScale(RateControlEntry *rce, double q);
     double countExpectedBits(int startPos, int framesCount);
