[x265] x265 patch(Store commonly-used RPS in SPS)

Zheng Wang zheng at multicorewareinc.com
Tue Oct 25 05:09:10 CEST 2016


Hi Pradeep,

I have check the x265 code, and now i can pull the newlist code version is
"(0e9e52640546) limitTU: fix energy calculation used in limiting TU
recursion …"
My patch is base on this:
# Node ID 19d3c5ea8bc10d3728ba2ae06190d188fe6093a3
# Parent  0e9e5264054606a38a3fe6c87272a1737b340b1a
Store commonly-used RPS in SPS  in 2 pass mode.

I also try to import my patch base on version "(0e9e52640546)“, it success
by "Import from Clipboard" using TortoiseHg.

If there are some problem, please tell me the detailed info about it.


2016-10-24 19:33 GMT+08:00 Pradeep Ramachandran <
pradeep at multicorewareinc.com>:

> This patch doesn't apply at current x265 tip. Please fix and resend.
> Pradeep.
>
> On Mon, Oct 24, 2016 at 12:27 PM, Zheng Wang <zheng at multicorewareinc.com>
> wrote:
>
>> # HG changeset patch
>> # User ZhengWang <zheng at multicorewareinc.com>
>> # Date 1477292081 -28800
>> #      Mon Oct 24 14:54:41 2016 +0800
>> # Node ID 19d3c5ea8bc10d3728ba2ae06190d188fe6093a3
>> # Parent  0e9e5264054606a38a3fe6c87272a1737b340b1a
>> Store commonly-used RPS in SPS  in 2 pass mode.
>> Add new param --[no]-multi-pass-opt-rps to control it, default disabled.
>>
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 doc/reST/cli.rst
>> --- a/doc/reST/cli.rst Wed Oct 12 17:58:49 2016 +0530
>> +++ b/doc/reST/cli.rst Mon Oct 24 14:54:41 2016 +0800
>> @@ -1852,6 +1852,10 @@
>>   Discard optional VUI HRD info from bitstream. Default enabled when
>>   :option:`--hrd` is enabled.
>>
>> +.. option:: --[no]-multi-pass-opt-rps
>> +
>> + Enable storing commonly RPS in SPS in multi pass mode. Default
>> disabled.
>> +
>>
>>  Debugging options
>>  =================
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/CMakeLists.txt
>> --- a/source/CMakeLists.txt Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/CMakeLists.txt Mon Oct 24 14:54:41 2016 +0800
>> @@ -30,7 +30,7 @@
>>  mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
>>
>>  # X265_BUILD must be incremented each time the public API is changed
>> -set(X265_BUILD 98)
>> +set(X265_BUILD 99)
>>  configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
>>                 "${PROJECT_BINARY_DIR}/x265.def")
>>  configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/common/common.h
>> --- a/source/common/common.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/common/common.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -312,6 +312,7 @@
>>
>>  #define MAX_NUM_REF_PICS            16 // max. number of pictures used
>> for reference
>>  #define MAX_NUM_REF                 16 // max. number of entries in
>> picture reference list
>> +#define MAX_NUM_SHORT_TERM_RPS      64 // max. number of short term
>> reference picture set in SPS
>>
>>  #define REF_NOT_VALID               -1
>>
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/common/framedata.cpp
>> --- a/source/common/framedata.cpp Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/common/framedata.cpp Mon Oct 24 14:54:41 2016 +0800
>> @@ -37,6 +37,9 @@
>>      m_slice  = new Slice;
>>      m_picCTU = new CUData[sps.numCUsInFrame];
>>      m_picCsp = csp;
>> +    m_spsrpsIdx = -1;
>> +    if (param.rc.bStatWrite)
>> +        m_spsrps = const_cast<RPS*>(sps.spsrps);
>>
>>      m_cuMemPool.create(0, param.internalCsp, sps.numCUsInFrame);
>>      for (uint32_t ctuAddr = 0; ctuAddr < sps.numCUsInFrame; ctuAddr++)
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/common/framedata.h
>> --- a/source/common/framedata.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/common/framedata.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -106,6 +106,9 @@
>>      CUDataMemPool  m_cuMemPool;
>>      CUData*        m_picCTU;
>>
>> +    RPS*           m_spsrps;
>> +    int            m_spsrpsIdx;
>> +
>>      /* Rate control data used during encode and by references */
>>      struct RCStatCU
>>      {
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/common/param.cpp
>> --- a/source/common/param.cpp Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/common/param.cpp Mon Oct 24 14:54:41 2016 +0800
>> @@ -198,6 +198,7 @@
>>      param->bCULossless = 0;
>>      param->bEnableTemporalSubLayers = 0;
>>      param->bEnableRdRefine = 0;
>> +    param->bMultiPassOptRPS = 0;
>>
>>      /* Rate control options */
>>      param->rc.vbvMaxBitrate = 0;
>> @@ -915,6 +916,8 @@
>>          OPT("limit-tu") p->limitTU = atoi(value);
>>          OPT("opt-qp-pps") p->bOptQpPPS = atobool(value);
>>          OPT("opt-ref-list-length-pps") p->bOptRefListLengthPPS =
>> atobool(value);
>> +        OPT("multi-pass-opt-rps") p->bMultiPassOptRPS = atobool(value);
>> +
>>          else
>>              return X265_PARAM_BAD_NAME;
>>      }
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/common/slice.h
>> --- a/source/common/slice.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/common/slice.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -239,6 +239,10 @@
>>      uint32_t maxLatencyIncrease;
>>      int      numReorderPics;
>>
>> +    RPS      spsrps[MAX_NUM_SHORT_TERM_RPS];
>> +    int      spsrpsNum;
>> +    int      numGOPBegin;
>> +
>>      bool     bUseSAO; // use param
>>      bool     bUseAMP; // use param
>>      bool     bUseStrongIntraSmoothing; // use param
>> @@ -337,6 +341,7 @@
>>      int         m_sliceQp;
>>      int         m_poc;
>>      int         m_lastIDR;
>> +    int         m_rpsIdx;
>>
>>      uint32_t    m_colRefIdx;       // never modified
>>
>> @@ -352,6 +357,7 @@
>>
>>      int         m_iPPSQpMinus26;
>>      int         numRefIdxDefault[2];
>> +    int         m_iNumRPSInSPS;
>>
>>      Slice()
>>      {
>> @@ -365,6 +371,7 @@
>>          m_iPPSQpMinus26 = 0;
>>          numRefIdxDefault[0] = 1;
>>          numRefIdxDefault[1] = 1;
>> +        m_rpsIdx = -1;
>>      }
>>
>>      void disableWeights();
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/api.cpp
>> --- a/source/encoder/api.cpp Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/api.cpp Mon Oct 24 14:54:41 2016 +0800
>> @@ -141,6 +141,11 @@
>>          Encoder *encoder = static_cast<Encoder*>(enc);
>>          Entropy sbacCoder;
>>          Bitstream bs;
>> +        if (encoder->m_param->rc.bStatRead &&
>> encoder->m_param->bMultiPassOptRPS)
>> +        {
>> +            if (!encoder->computeSPSRPSIndex())
>> +                return -1;
>> +        }
>>          encoder->getStreamHeaders(encoder->m_nalList, sbacCoder, bs);
>>          *pp_nal = &encoder->m_nalList.m_nal[0];
>>          if (pi_nal) *pi_nal = encoder->m_nalList.m_numNal;
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/encoder.cpp
>> --- a/source/encoder/encoder.cpp Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/encoder.cpp Mon Oct 24 14:54:41 2016 +0800
>> @@ -77,6 +77,7 @@
>>      m_iFrameNum = 0;
>>      m_iPPSQpMinus26 = 0;
>>      m_iLastSliceQp = 0;
>> +    m_rpsInSpsCount = 0;
>>      for (int i = 0; i < X265_MAX_FRAME_THREADS; i++)
>>          m_frameEncoder[i] = NULL;
>>
>> @@ -905,6 +906,7 @@
>>              frameEnc->m_encData->m_slice->m_iPPSQpMinus26 =
>> m_iPPSQpMinus26;
>>              frameEnc->m_encData->m_slice->numRefIdxDefault[0] =
>> m_pps.numRefIdxDefault[0];
>>              frameEnc->m_encData->m_slice->numRefIdxDefault[1] =
>> m_pps.numRefIdxDefault[1];
>> +            frameEnc->m_encData->m_slice->m_iNumRPSInSPS =
>> m_sps.spsrpsNum;
>>
>>              curEncoder->m_rce.encodeOrder = frameEnc->m_encodeOrder =
>> m_encodedFrameNum++;
>>              if (m_bframeDelay)
>> @@ -1068,6 +1070,13 @@
>>
>>          x265_log(m_param, X265_LOG_INFO, "lossless compression ratio
>> %.2f::1\n", uncompressed / m_analyzeAll.m_accBits);
>>      }
>> +    if (m_param->bMultiPassOptRPS && m_param->rc.bStatRead)
>> +    {
>> +        x265_log(m_param, X265_LOG_INFO, "RPS in SPS: %d frames
>> (%.2f%%), RPS not in SPS: %d frames (%.2f%%)\n",
>> +            m_rpsInSpsCount, (float)100.0 * m_rpsInSpsCount /
>> m_rateControl->m_numEntries,
>> +            m_rateControl->m_numEntries - m_rpsInSpsCount,
>> +            (float)100.0 * (m_rateControl->m_numEntries -
>> m_rpsInSpsCount) / m_rateControl->m_numEntries);
>> +    }
>>
>>      if (m_analyzeAll.m_numPics)
>>      {
>> @@ -2433,3 +2442,203 @@
>>      TOOLCMP(oldParam->maxNumMergeCand, newParam->maxNumMergeCand,
>> "max-merge=%d to %d\n");
>>      TOOLCMP(oldParam->bIntraInBFrames, newParam->bIntraInBFrames,
>> "b-intra=%d to %d\n");
>>  }
>> +
>> +bool Encoder::computeSPSRPSIndex()
>> +{
>> +    RPS* rpsInSPS = m_sps.spsrps;
>> +    int* rpsNumInPSP = &m_sps.spsrpsNum;
>> +    int  beginNum = m_sps.numGOPBegin;
>> +    int  endNum;
>> +    RPS* rpsInRec;
>> +    RPS* rpsInIdxList;
>> +    RPS* thisRpsInSPS;
>> +    RPS* thisRpsInList;
>> +    RPSListNode* headRpsIdxList = NULL;
>> +    RPSListNode* tailRpsIdxList = NULL;
>> +    RPSListNode* rpsIdxListIter = NULL;
>> +    RateControlEntry *rce2Pass = m_rateControl->m_rce2Pass;
>> +    int numEntries = m_rateControl->m_numEntries;
>> +    RateControlEntry *rce;
>> +    int idx = 0;
>> +    int pos = 0;
>> +    int resultIdx[64];
>> +    memset(rpsInSPS, 0, sizeof(RPS) * MAX_NUM_SHORT_TERM_RPS);
>> +
>> +    // find out all RPS date in current GOP
>> +    beginNum++;
>> +    endNum = beginNum;
>> +    if (!m_param->bRepeatHeaders)
>> +    {
>> +        endNum = numEntries;
>> +    }
>> +    else
>> +    {
>> +        while (endNum < numEntries)
>> +        {
>> +            rce = &rce2Pass[endNum];
>> +            if (rce->sliceType == I_SLICE)
>> +            {
>> +                break;
>> +            }
>> +            endNum++;
>> +        }
>> +    }
>> +    m_sps.numGOPBegin = endNum;
>> +
>> +    // find out all kinds of RPS
>> +    for (int i = beginNum; i < endNum; i++)
>> +    {
>> +        rce = &rce2Pass[i];
>> +        rpsInRec = &rce->rpsData;
>> +        rpsIdxListIter = headRpsIdxList;
>> +        // i frame don't recode RPS info
>> +        if (rce->sliceType != I_SLICE)
>> +        {
>> +            while (rpsIdxListIter)
>> +            {
>> +                rpsInIdxList = rpsIdxListIter->rps;
>> +                if (rpsInRec->numberOfPictures ==
>> rpsInIdxList->numberOfPictures
>> +                    && rpsInRec->numberOfNegativePictures ==
>> rpsInIdxList->numberOfNegativePictures
>> +                    && rpsInRec->numberOfPositivePictures ==
>> rpsInIdxList->numberOfPositivePictures)
>> +                {
>> +                    for (pos = 0; pos < rpsInRec->numberOfPictures;
>> pos++)
>> +                    {
>> +                        if (rpsInRec->deltaPOC[pos] !=
>> rpsInIdxList->deltaPOC[pos]
>> +                            || rpsInRec->bUsed[pos] !=
>> rpsInIdxList->bUsed[pos])
>> +                            break;
>> +                    }
>> +                    if (pos == rpsInRec->numberOfPictures)    // if this
>> type of RPS has exist
>> +                    {
>> +                        rce->rpsIdx = rpsIdxListIter->idx;
>> +                        rpsIdxListIter->count++;
>> +                        // sort RPS type link after reset RPS type count.
>> +                        RPSListNode* next = rpsIdxListIter->next;
>> +                        RPSListNode* prior = rpsIdxListIter->prior;
>> +                        RPSListNode* iter = prior;
>> +                        if (iter)
>> +                        {
>> +                            while (iter)
>> +                            {
>> +                                if (iter->count > rpsIdxListIter->count)
>> +                                    break;
>> +                                iter = iter->prior;
>> +                            }
>> +                            if (iter)
>> +                            {
>> +                                prior->next = next;
>> +                                if (next)
>> +                                    next->prior = prior;
>> +                                else
>> +                                    tailRpsIdxList = prior;
>> +                                rpsIdxListIter->next = iter->next;
>> +                                rpsIdxListIter->prior = iter;
>> +                                iter->next->prior = rpsIdxListIter;
>> +                                iter->next = rpsIdxListIter;
>> +                            }
>> +                            else
>> +                            {
>> +                                prior->next = next;
>> +                                if (next)
>> +                                    next->prior = prior;
>> +                                else
>> +                                    tailRpsIdxList = prior;
>> +                                headRpsIdxList->prior = rpsIdxListIter;
>> +                                rpsIdxListIter->next = headRpsIdxList;
>> +                                rpsIdxListIter->prior = NULL;
>> +                                headRpsIdxList = rpsIdxListIter;
>> +                            }
>> +                        }
>> +                        break;
>> +                    }
>> +                }
>> +                rpsIdxListIter = rpsIdxListIter->next;
>> +            }
>> +            if (!rpsIdxListIter)  // add new type of RPS
>> +            {
>> +                RPSListNode* newIdxNode = new RPSListNode();
>> +                if (newIdxNode == NULL)
>> +                    goto fail;
>> +                newIdxNode->rps = rpsInRec;
>> +                newIdxNode->idx = idx++;
>> +                newIdxNode->count = 1;
>> +                newIdxNode->next = NULL;
>> +                newIdxNode->prior = NULL;
>> +                if (!tailRpsIdxList)
>> +                    tailRpsIdxList = headRpsIdxList = newIdxNode;
>> +                else
>> +                {
>> +                    tailRpsIdxList->next = newIdxNode;
>> +                    newIdxNode->prior = tailRpsIdxList;
>> +                    tailRpsIdxList = newIdxNode;
>> +                }
>> +                rce->rpsIdx = newIdxNode->idx;
>> +            }
>> +        }
>> +        else
>> +        {
>> +            rce->rpsIdx = -1;
>> +        }
>> +    }
>> +
>> +    // get commonly RPS set
>> +    memset(resultIdx, 0, sizeof(resultIdx));
>> +    if (idx > MAX_NUM_SHORT_TERM_RPS)
>> +        idx = MAX_NUM_SHORT_TERM_RPS;
>> +
>> +    *rpsNumInPSP = idx;
>> +    rpsIdxListIter = headRpsIdxList;
>> +    for (int i = 0; i < idx; i++)
>> +    {
>> +        resultIdx[i] = rpsIdxListIter->idx;
>> +        m_rpsInSpsCount += rpsIdxListIter->count;
>> +        thisRpsInSPS = rpsInSPS + i;
>> +        thisRpsInList = rpsIdxListIter->rps;
>> +        thisRpsInSPS->numberOfPictures = thisRpsInList->numberOfPicture
>> s;
>> +        thisRpsInSPS->numberOfNegativePictures =
>> thisRpsInList->numberOfNegativePictures;
>> +        thisRpsInSPS->numberOfPositivePictures =
>> thisRpsInList->numberOfPositivePictures;
>> +        for (pos = 0; pos < thisRpsInList->numberOfPictures; pos++)
>> +        {
>> +            thisRpsInSPS->deltaPOC[pos] = thisRpsInList->deltaPOC[pos];
>> +            thisRpsInSPS->bUsed[pos] = thisRpsInList->bUsed[pos];
>> +        }
>> +        rpsIdxListIter = rpsIdxListIter->next;
>> +    }
>> +
>> +    //reset every frame's RPS index
>> +    for (int i = beginNum; i < endNum; i++)
>> +    {
>> +        int j;
>> +        rce = &rce2Pass[i];
>> +        for (j = 0; j < idx; j++)
>> +        {
>> +            if (rce->rpsIdx == resultIdx[j])
>> +            {
>> +                rce->rpsIdx = j;
>> +                break;
>> +            }
>> +        }
>> +
>> +        if (j == idx)
>> +            rce->rpsIdx = -1;
>> +    }
>> +
>> +    rpsIdxListIter = headRpsIdxList;
>> +    while (rpsIdxListIter)
>> +    {
>> +        RPSListNode* freeIndex = rpsIdxListIter;
>> +        rpsIdxListIter = rpsIdxListIter->next;
>> +        delete freeIndex;
>> +    }
>> +    return true;
>> +
>> +fail:
>> +    rpsIdxListIter = headRpsIdxList;
>> +    while (rpsIdxListIter)
>> +    {
>> +        RPSListNode* freeIndex = rpsIdxListIter;
>> +        rpsIdxListIter = rpsIdxListIter->next;
>> +        delete freeIndex;
>> +    }
>> +    return false;
>> +}
>> +
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/encoder.h
>> --- a/source/encoder/encoder.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/encoder.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -79,6 +79,15 @@
>>      int numRefIdxl1[MAX_NUM_REF_IDX];
>>  };
>>
>> +struct RPSListNode
>> +{
>> +    int idx;
>> +    int count;
>> +    RPS* rps;
>> +    RPSListNode* next;
>> +    RPSListNode* prior;
>> +};
>> +
>>  class FrameEncoder;
>>  class DPB;
>>  class Lookahead;
>> @@ -156,6 +165,9 @@
>>      Lock               m_sliceRefIdxLock;
>>      RefIdxLastGOP      m_refIdxLastGOP;
>>
>> +    Lock               m_rpsInSpsLock;
>> +    int                m_rpsInSpsCount;
>> +
>>      Encoder();
>>      ~Encoder() {}
>>
>> @@ -196,6 +208,7 @@
>>      void initRefIdx();
>>      void analyseRefIdx(int *numRefIdx);
>>      void updateRefIdx();
>> +    bool computeSPSRPSIndex();
>>
>>  protected:
>>
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/entropy.cpp
>> --- a/source/encoder/entropy.cpp Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/entropy.cpp Mon Oct 24 14:54:41 2016 +0800
>> @@ -312,7 +312,9 @@
>>      WRITE_FLAG(sps.bUseSAO, "sample_adaptive_offset_enabled_flag");
>>
>>      WRITE_FLAG(0, "pcm_enabled_flag");
>> -    WRITE_UVLC(0, "num_short_term_ref_pic_sets");
>> +    WRITE_UVLC(sps.spsrpsNum, "num_short_term_ref_pic_sets");
>> +    for (int i = 0; i < sps.spsrpsNum; i++)
>> +        codeShortTermRefPicSet(sps.spsrps[i], i);
>>      WRITE_FLAG(0, "long_term_ref_pics_present_flag");
>>
>>      WRITE_FLAG(sps.bTemporalMVPEnabled, "sps_temporal_mvp_enable_flag");
>> @@ -614,8 +616,21 @@
>>              }
>>  #endif
>>
>> -        WRITE_FLAG(0, "short_term_ref_pic_set_sps_flag");
>> -        codeShortTermRefPicSet(slice.m_rps);
>> +        if (slice.m_rpsIdx < 0)
>> +        {
>> +            WRITE_FLAG(0, "short_term_ref_pic_set_sps_flag");
>> +            codeShortTermRefPicSet(slice.m_rps, slice.m_sps->spsrpsNum);
>> +        }
>> +        else
>> +        {
>> +            WRITE_FLAG(1, "short_term_ref_pic_set_sps_flag");
>> +            int numBits = 0;
>> +            while ((1 << numBits) < slice.m_iNumRPSInSPS)
>> +                numBits++;
>> +
>> +            if (numBits > 0)
>> +                WRITE_CODE(slice.m_rpsIdx, numBits,
>> "short_term_ref_pic_set_idx");
>> +        }
>>
>>          if (slice.m_sps->bTemporalMVPEnabled)
>>              WRITE_FLAG(1, "slice_temporal_mvp_enable_flag");
>> @@ -707,8 +722,11 @@
>>          WRITE_CODE(substreamSizes[i] - 1, offsetLen,
>> "entry_point_offset_minus1");
>>  }
>>
>> -void Entropy::codeShortTermRefPicSet(const RPS& rps)
>> +void Entropy::codeShortTermRefPicSet(const RPS& rps, int idx)
>>  {
>> +    if (idx > 0)
>> +        WRITE_FLAG(0, "inter_ref_pic_set_prediction_flag");
>> +
>>      WRITE_UVLC(rps.numberOfNegativePictures, "num_negative_pics");
>>      WRITE_UVLC(rps.numberOfPositivePictures, "num_positive_pics");
>>      int prev = 0;
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/entropy.h
>> --- a/source/encoder/entropy.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/entropy.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -149,7 +149,7 @@
>>
>>      void codeSliceHeader(const Slice& slice, FrameData& encData,
>> uint32_t slice_addr, uint32_t slice_addr_bits, int sliceQp);
>>      void codeSliceHeaderWPPEntryPoints(const uint32_t *substreamSizes,
>> uint32_t numSubStreams, uint32_t maxOffset);
>> -    void codeShortTermRefPicSet(const RPS& rps);
>> +    void codeShortTermRefPicSet(const RPS& rps, int idx);
>>      void finishSlice()                 { encodeBinTrm(1); finish();
>> dynamic_cast<Bitstream*>(m_bitIf)->writeByteAlignment(); }
>>
>>      void encodeCTU(const CUData& cu, const CUGeom& cuGeom);
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/frameencoder.cpp
>> --- a/source/encoder/frameencoder.cpp Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/frameencoder.cpp Mon Oct 24 14:54:41 2016 +0800
>> @@ -359,9 +359,23 @@
>>              ScopedLock refIdxLock(m_top->m_sliceRefIdxLock);
>>              m_top->updateRefIdx();
>>          }
>> -        m_top->getStreamHeaders(m_nalList, m_entropyCoder, m_bs);
>> +        if (m_top->m_param->rc.bStatRead  &&
>> m_top->m_param->bMultiPassOptRPS)
>> +        {
>> +            ScopedLock refIdxLock(m_top->m_rpsInSpsLock);
>> +            if (!m_top->computeSPSRPSIndex())
>> +            {
>> +                x265_log(m_param, X265_LOG_ERROR, "compute commonly RPS
>> failed!\n");
>> +                m_top->m_aborted = true;
>> +            }
>> +            m_top->getStreamHeaders(m_nalList, m_entropyCoder, m_bs);
>> +        }
>> +        else
>> +            m_top->getStreamHeaders(m_nalList, m_entropyCoder, m_bs);
>>      }
>>
>> +    if (m_top->m_param->rc.bStatRead && m_top->m_param->bMultiPassOptR
>> PS)
>> +        m_frame->m_encData->m_slice->m_rpsIdx =
>> (m_top->m_rateControl->m_rce2Pass + m_frame->m_encodeOrder)->rpsIdx;
>> +
>>      // Weighted Prediction parameters estimation.
>>      bool bUseWeightP = slice->m_sliceType == P_SLICE &&
>> slice->m_pps->bUseWeightPred;
>>      bool bUseWeightB = slice->m_sliceType == B_SLICE &&
>> slice->m_pps->bUseWeightedBiPred;
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/ratecontrol.cpp
>> --- a/source/encoder/ratecontrol.cpp Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/ratecontrol.cpp Mon Oct 24 14:54:41 2016 +0800
>> @@ -544,10 +544,27 @@
>>                  }
>>                  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",
>> -                       &picType, &qpRc, &qpAq, &qNoVbv, &qRceq,
>> &rce->coeffBits,
>> -                       &rce->mvBits, &rce->miscBits, &rce->iCuCount,
>> &rce->pCuCount,
>> -                       &rce->skipCuCount);
>> +                if (!m_param->bMultiPassOptRPS)
>> +                {
>> +                    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",
>> +                        &picType, &qpRc, &qpAq, &qNoVbv, &qRceq,
>> &rce->coeffBits,
>> +                        &rce->mvBits, &rce->miscBits, &rce->iCuCount,
>> &rce->pCuCount,
>> +                        &rce->skipCuCount);
>> +                }
>> +                else
>> +                {
>> +                    char deltaPOC[128];
>> +                    char bUsed[40];
>> +                    memset(deltaPOC, 0, sizeof(deltaPOC));
>> +                    memset(bUsed, 0, sizeof(bUsed));
>> +                    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 nump:%d numnegp:%d numposp:%d deltapoc:%s bused:%s",
>> +                        &picType, &qpRc, &qpAq, &qNoVbv, &qRceq,
>> &rce->coeffBits,
>> +                        &rce->mvBits, &rce->miscBits, &rce->iCuCount,
>> &rce->pCuCount,
>> +                        &rce->skipCuCount, &rce->rpsData.numberOfPictures,
>> &rce->rpsData.numberOfNegativePictures, &rce->rpsData.numberOfPositivePictures,
>> deltaPOC, bUsed);
>> +                    splitdeltaPOC(deltaPOC, rce);
>> +                    splitbUsed(bUsed, rce);
>> +                    rce->rpsIdx = -1;
>> +                }
>>                  rce->keptAsRef = true;
>>                  rce->isIdr = false;
>>                  if (picType == 'b' || picType == 'p')
>> @@ -2632,18 +2649,55 @@
>>      char cType = rce->sliceType == I_SLICE ?
>> (curFrame->m_lowres.sliceType == X265_TYPE_IDR ? 'I' : 'i')
>>          : 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",
>> -                rce->poc, rce->encodeOrder,
>> -                cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
>> -                rce->qpNoVbv, rce->qRceq,
>> -                curFrame->m_encData->m_frameStats.coeffBits,
>> -                curFrame->m_encData->m_frameStats.mvBits,
>> -                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_frameStats.percent8x8Skip  *
>> m_ncu) < 0)
>> -        goto writeFailure;
>> +
>> +    if (!curEncData.m_param->bMultiPassOptRPS)
>> +    {
>> +        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",
>> +            rce->poc, rce->encodeOrder,
>> +            cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
>> +            rce->qpNoVbv, rce->qRceq,
>> +            curFrame->m_encData->m_frameStats.coeffBits,
>> +            curFrame->m_encData->m_frameStats.mvBits,
>> +            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_frameStats.percent8x8Skip  * m_ncu)
>> < 0)
>> +            goto writeFailure;
>> +    }
>> +    else{
>> +        RPS* rpsWriter = &curFrame->m_encData->m_slice->m_rps;
>> +        int i, num = rpsWriter->numberOfPictures;
>> +        char deltaPOC[128];
>> +        char bUsed[40];
>> +        memset(deltaPOC, 0, sizeof(deltaPOC));
>> +        memset(bUsed, 0, sizeof(bUsed));
>> +        sprintf(deltaPOC, "deltapoc:~");
>> +        sprintf(bUsed, "bused:~");
>> +
>> +        for (i = 0; i < num; i++)
>> +        {
>> +            sprintf(deltaPOC, "%s%d~", deltaPOC, rpsWriter->deltaPOC[i]);
>> +            sprintf(bUsed, "%s%d~", bUsed, rpsWriter->bUsed[i]);
>> +        }
>> +
>> +        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 nump:%d
>> numnegp:%d numposp:%d %s %s ;\n",
>> +            rce->poc, rce->encodeOrder,
>> +            cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
>> +            rce->qpNoVbv, rce->qRceq,
>> +            curFrame->m_encData->m_frameStats.coeffBits,
>> +            curFrame->m_encData->m_frameStats.mvBits,
>> +            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_frameStats.percent8x8Skip  * m_ncu,
>> +            rpsWriter->numberOfPictures,
>> +            rpsWriter->numberOfNegativePictures,
>> +            rpsWriter->numberOfPositivePictures,
>> +            deltaPOC, bUsed) < 0)
>> +            goto writeFailure;
>> +    }
>>      /* Don't re-write the data in multi-pass mode. */
>>      if (m_param->rc.cuTree && IS_REFERENCED(curFrame) &&
>> !m_param->rc.bStatRead)
>>      {
>> @@ -2736,3 +2790,48 @@
>>      X265_FREE(m_param->rc.zones);
>>  }
>>
>> +void RateControl::splitdeltaPOC(char deltapoc[], RateControlEntry *rce)
>> +{
>> +    int idx = 0, length = 0;
>> +    char tmpStr[128];
>> +    char* src = deltapoc;
>> +    char* buf = strstr(src, "~");
>> +    while (buf)
>> +    {
>> +        memset(tmpStr, 0, sizeof(tmpStr));
>> +        length = (int)(buf - src);
>> +        if (length != 0)
>> +        {
>> +            strncpy(tmpStr, src, length);
>> +            rce->rpsData.deltaPOC[idx] = atoi(tmpStr);
>> +            idx++;
>> +            if (idx == rce->rpsData.numberOfPictures)
>> +                break;
>> +        }
>> +        src += (length + 1);
>> +        buf = strstr(src, "~");
>> +    }
>> +}
>> +
>> +void RateControl::splitbUsed(char bused[], RateControlEntry *rce)
>> +{
>> +    int idx = 0, length = 0;
>> +    char tmpStr[128];
>> +    char* src = bused;
>> +    char* buf = strstr(src, "~");
>> +    while (buf)
>> +    {
>> +        memset(tmpStr, 0, sizeof(tmpStr));
>> +        length = (int)(buf - src);
>> +        if (length != 0)
>> +        {
>> +            strncpy(tmpStr, src, length);
>> +            rce->rpsData.bUsed[idx] = atoi(tmpStr) > 0;
>> +            idx++;
>> +            if (idx == rce->rpsData.numberOfPictures)
>> +                break;
>> +        }
>> +        src += (length + 1);
>> +        buf = strstr(src, "~");
>> +    }
>> +}
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/encoder/ratecontrol.h
>> --- a/source/encoder/ratecontrol.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/encoder/ratecontrol.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -111,6 +111,8 @@
>>      bool     isIdr;
>>      SEIPictureTiming *picTimingSEI;
>>      HRDTiming        *hrdTiming;
>> +    int      rpsIdx;
>> +    RPS      rpsData;
>>  };
>>
>>  class RateControl
>> @@ -282,6 +284,8 @@
>>      bool   findUnderflow(double *fills, int *t0, int *t1, int over, int
>> framesCount);
>>      bool   fixUnderflow(int t0, int t1, double adjustment, double
>> qscaleMin, double qscaleMax);
>>      double tuneQScaleForGrain(double rcOverflow);
>> +    void   splitdeltaPOC(char deltapoc[], RateControlEntry *rce);
>> +    void   splitbUsed(char deltapoc[], RateControlEntry *rce);
>>  };
>>  }
>>  #endif // ifndef X265_RATECONTROL_H
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/x265.h
>> --- a/source/x265.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/x265.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -1323,6 +1323,9 @@
>>      /* Opitmize ref list length in PPS based on stats from previous GOP*/
>>      int bOptRefListLengthPPS;
>>
>> +    /* Enable storing commonly RPS in SPS in multi pass mode */
>> +    int       bMultiPassOptRPS;
>> +
>>  } x265_param;
>>
>>  /* x265_param_alloc:
>> diff -r 0e9e52640546 -r 19d3c5ea8bc1 source/x265cli.h
>> --- a/source/x265cli.h Wed Oct 12 17:58:49 2016 +0530
>> +++ b/source/x265cli.h Mon Oct 24 14:54:41 2016 +0800
>> @@ -236,6 +236,8 @@
>>      { "pass",           required_argument, NULL, 0 },
>>      { "slow-firstpass",       no_argument, NULL, 0 },
>>      { "no-slow-firstpass",    no_argument, NULL, 0 },
>> +    { "multi-pass-opt-rps",   no_argument, NULL, 0 },
>> +    { "no-multi-pass-opt-rps", no_argument, NULL, 0 },
>>      { "analysis-mode",  required_argument, NULL, 0 },
>>      { "analysis-file",  required_argument, NULL, 0 },
>>      { "strict-cbr",           no_argument, NULL, 0 },
>> @@ -460,6 +462,7 @@
>>      H0("   --[no-]vui-hrd-info           Discard optional HRD timing
>> information from the bistream. Default %s\n", OPT(param->bEmitVUIHRDInfo));
>>      H0("   --[no-]opt-qp-pps             Discard optional HRD timing
>> information from the bistream. Default %s\n", OPT(param->bOptQpPPS));
>>      H0("   --[no-]opt-ref-list-length-pps  Discard optional HRD timing
>> information from the bistream. Default %s\n", OPT(param->bOptRefListLengthPP
>> S));
>> +    H0("   --[no-]multi-pass-opt-rps     Enable storing commonly RPS in
>> SPS in multi pass mode. Default %s\n", OPT(param->bMultiPassOptRPS));
>>      H1("\nReconstructed video options (debugging):\n");
>>      H1("-r/--recon <filename>            Reconstructed raw image YUV or
>> Y4M output file name\n");
>>      H1("   --recon-depth <integer>       Bit-depth of reconstructed raw
>> image file. Defaults to input bit depth, or 8 if Y4M\n");
>>
>>
>> _______________________________________________
>> x265-devel mailing list
>> x265-devel at videolan.org
>> https://mailman.videolan.org/listinfo/x265-devel
>>
>>
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
>


-- 
Thanks,
Zheng Wang.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20161025/6280134a/attachment-0001.html>


More information about the x265-devel mailing list