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 <zh...@multicorewareinc.com> wrote: > # HG changeset patch > # User ZhengWang <zh...@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@videolan.org > https://mailman.videolan.org/listinfo/x265-devel > >
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel