[x265] x265 patch(Store commonly-used RPS in SPS)
Zheng Wang
zheng at multicorewareinc.com
Tue Oct 25 10:21:48 CEST 2016
Hi, Pradeep,
I have resend the patch to x265 mail list by using a new email "
ayacc564 at 163.com" and sending patch with ubuntu(china's network has many
problems when connected to foreign), and this time i have test download the
patch and import it, it work well.
Please check it again.
2016-10-25 12:06 GMT+08:00 Pradeep Ramachandran <
pradeep at multicorewareinc.com>:
> 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->numberOfPictures;
>>>> + 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
>>
>>
>
> _______________________________________________
> 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/94a49ce9/attachment-0001.html>
More information about the x265-devel
mailing list