[x265] x265 patch(Store commonly-used RPS in SPS)
Pradeep Ramachandran
pradeep at multicorewareinc.com
Mon Oct 24 13:33:18 CEST 2016
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->bMultiPassOptRPS)
> + 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->
> bOptRefListLengthPPS));
> + 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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20161024/55ce4e1f/attachment-0001.html>
More information about the x265-devel
mailing list