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

Pradeep Ramachandran pradeep at multicorewareinc.com
Tue Oct 25 06:06:47 CEST 2016


Thanks Zheng. Interestingly this worked from clipboard but when I went to
patchwork to download the patch (
https://patches.videolan.org/project/x265-devel/list/), it didn't work.
Pradeep.

On Tue, Oct 25, 2016 at 8:39 AM, Zheng Wang <zheng at multicorewareinc.com>
wrote:

> 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.
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20161025/9f559615/attachment-0001.html>


More information about the x265-devel mailing list