# HG changeset patch # User Aruna Matheswaran <ar...@multicorewareinc.com> # Date 1571647307 -19800 # Mon Oct 21 14:11:47 2019 +0530 # Node ID 5297824e605c5eed543c2f99c41335d466d17b4b # Parent 858a6b6267e025776b18eafc3279dc5addf891e4 zone: tune base QP to achieve zone target
diff -r 858a6b6267e0 -r 5297824e605c source/encoder/api.cpp --- a/source/encoder/api.cpp Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/api.cpp Mon Oct 21 14:11:47 2019 +0530 @@ -199,6 +199,7 @@ { param->rc.zones[i].zoneParam = X265_MALLOC(x265_param, 1); memcpy(param->rc.zones[i].zoneParam, param, sizeof(x265_param)); + param->rc.zones[i].relativeComplexity = X265_MALLOC(double, param->reconfigWindowSize); } } @@ -379,17 +380,28 @@ { if (!enc || !zone_in) return -1; + Encoder* encoder = static_cast<Encoder*>(enc); + int read = encoder->zoneReadCount[encoder->m_zoneIndex].get(); + int write = encoder->zoneWriteCount[encoder->m_zoneIndex].get(); + x265_zone* zone = &(encoder->m_param->rc).zones[encoder->m_zoneIndex]; x265_param* zoneParam = zone->zoneParam; + + if (write && (read < write)) + { + read = encoder->zoneReadCount[encoder->m_zoneIndex].waitForChange(read); + } + + zone->startFrame = zone_in->startFrame; + zoneParam->rc.bitrate = zone_in->zoneParam->rc.bitrate; + zoneParam->rc.vbvMaxBitrate = zone_in->zoneParam->rc.vbvMaxBitrate; + memcpy(zone->relativeComplexity, zone_in->relativeComplexity, sizeof(double) * encoder->m_param->reconfigWindowSize); - int ret = encoder->reconfigureParam(zoneParam, zone_in->zoneParam); - if (ret) - return -1; - memcpy(zone, zone_in, sizeof(x265_zone)); - + encoder->zoneWriteCount[encoder->m_zoneIndex].incr(); encoder->m_zoneIndex++; encoder->m_zoneIndex %= encoder->m_param->rc.zonefileCount; + return 0; } diff -r 858a6b6267e0 -r 5297824e605c source/encoder/encoder.cpp --- a/source/encoder/encoder.cpp Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/encoder.cpp Mon Oct 21 14:11:47 2019 +0530 @@ -323,7 +323,13 @@ lookAheadThreadPool[i].start(); m_lookahead->m_numPools = pools; m_dpb = new DPB(m_param); - m_rateControl = new RateControl(*m_param); + m_rateControl = new RateControl(*m_param, this); + if (!m_param->bResetZoneConfig) + { + zoneReadCount = new ThreadSafeInteger[m_param->rc.zonefileCount]; + zoneWriteCount = new ThreadSafeInteger[m_param->rc.zonefileCount]; + } + initVPS(&m_vps); initSPS(&m_sps); initPPS(&m_pps); @@ -868,6 +874,11 @@ } delete m_dpb; + if (!m_param->bResetZoneConfig && m_param->rc.zonefileCount) + { + delete[] zoneReadCount; + delete[] zoneWriteCount; + } if (m_rateControl) { m_rateControl->destroy(); diff -r 858a6b6267e0 -r 5297824e605c source/encoder/encoder.h --- a/source/encoder/encoder.h Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/encoder.h Mon Oct 21 14:11:47 2019 +0530 @@ -274,6 +274,10 @@ bool m_saveCTUSize; + + ThreadSafeInteger* zoneReadCount; + ThreadSafeInteger* zoneWriteCount; + Encoder(); ~Encoder() { diff -r 858a6b6267e0 -r 5297824e605c source/encoder/ratecontrol.cpp --- a/source/encoder/ratecontrol.cpp Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/ratecontrol.cpp Mon Oct 21 14:11:47 2019 +0530 @@ -146,9 +146,10 @@ return NULL; } -RateControl::RateControl(x265_param& p) +RateControl::RateControl(x265_param& p, Encoder *top) { m_param = &p; + m_top = top; int lowresCuWidth = ((m_param->sourceWidth / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; int lowresCuHeight = ((m_param->sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; m_ncu = lowresCuWidth * lowresCuHeight; @@ -156,6 +157,7 @@ m_qCompress = (m_param->rc.cuTree && !m_param->rc.hevcAq) ? 1 : m_param->rc.qCompress; // validate for param->rc, maybe it is need to add a function like x265_parameters_valiate() + m_zoneBufferIdx = 0; m_residualFrames = 0; m_partialResidualFrames = 0; m_residualCost = 0; @@ -210,6 +212,7 @@ m_lastBsliceSatdCost = 0; m_movingAvgSum = 0.0; m_isNextGop = false; + m_relativeComplexity = NULL; // vbv initialization m_param->rc.vbvBufferSize = x265_clip3(0, 2000000, m_param->rc.vbvBufferSize); @@ -354,6 +357,16 @@ m_initVbv = true; } + if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL)) + { + m_relativeComplexity = X265_MALLOC(double, m_param->reconfigWindowSize); + if (m_relativeComplexity == NULL) + { + x265_log(m_param, X265_LOG_ERROR, "Failed to allocate memory for m_relativeComplexity\n"); + return false; + } + } + m_totalBits = 0; m_encodedBits = 0; m_framesDone = 0; @@ -699,6 +712,8 @@ { m_param->rc.vbvBufferSize = x265_clip3(0, 2000000, m_param->rc.vbvBufferSize); m_param->rc.vbvMaxBitrate = x265_clip3(0, 2000000, m_param->rc.vbvMaxBitrate); + if (m_param->reconfigWindowSize) + m_param->rc.vbvMaxBitrate = (int)(m_param->rc.vbvMaxBitrate * (double)(m_fps / m_param->reconfigWindowSize)); if (m_param->rc.vbvMaxBitrate < m_param->rc.bitrate && m_param->rc.rateControlMode == X265_RC_ABR) { @@ -753,7 +768,7 @@ m_qpConstant[P_SLICE] = m_qpConstant[I_SLICE] = m_qpConstant[B_SLICE] = m_qp; } } - m_bitrate = m_param->rc.bitrate * 1000; + m_bitrate = (double)m_param->rc.bitrate * 1000; } void RateControl::initHRD(SPS& sps) @@ -1244,17 +1259,43 @@ m_predType = getPredictorType(curFrame->m_lowres.sliceType, m_sliceType); rce->poc = m_curSlice->m_poc; - /* change ratecontrol stats for next zone if specified */ - for (int i = 0; i < m_param->rc.zonefileCount; i++) + if (!m_param->bResetZoneConfig && (rce->encodeOrder % m_param->reconfigWindowSize == 0)) { - if (m_param->rc.zones[i].startFrame == curFrame->m_encodeOrder) + int index = m_zoneBufferIdx % m_param->rc.zonefileCount; + int read = m_top->zoneReadCount[index].get(); + int write = m_top->zoneWriteCount[index].get(); + if (write <= read) + write = m_top->zoneWriteCount[index].waitForChange(write); + m_zoneBufferIdx++; + + for (int i = 0; i < m_param->rc.zonefileCount; i++) { - m_param = m_param->rc.zones[i].zoneParam; - reconfigureRC(); - if (m_param->bResetZoneConfig) - init(*m_curSlice->m_sps); + if (m_param->rc.zones[i].startFrame == rce->encodeOrder) + { + m_param->rc.bitrate = m_param->rc.zones[i].zoneParam->rc.bitrate; + m_param->rc.vbvMaxBitrate = m_param->rc.zones[i].zoneParam->rc.vbvMaxBitrate; + memcpy(m_relativeComplexity, m_param->rc.zones[i].relativeComplexity, sizeof(double) * m_param->reconfigWindowSize); + reconfigureRC(); + m_top->zoneReadCount[i].incr(); + } } } + + + if (m_param->bResetZoneConfig) + { + /* change ratecontrol stats for next zone if specified */ + for (int i = 0; i < m_param->rc.zonefileCount; i++) + { + if (m_param->rc.zones[i].startFrame == curFrame->m_encodeOrder) + { + m_param = m_param->rc.zones[i].zoneParam; + reconfigureRC(); + init(*m_curSlice->m_sps); + } + } + } + if (m_param->rc.bStatRead) { X265_CHECK(rce->poc >= 0 && rce->poc < m_numEntries, "bad encode ordinal\n"); @@ -1649,6 +1690,31 @@ return qScale; } +double RateControl::tuneQScaleForZone(RateControlEntry *rce, double qScale) +{ + rce->frameSizePlanned = predictSize(&m_pred[m_predType], qScale, (double)m_currentSatd); + int loop = 0; + + double availableBits = (double)m_param->rc.bitrate * 1000 * m_relativeComplexity[rce->encodeOrder % m_param->reconfigWindowSize]; + + // Tune qScale to adhere to the available frame bits. + for (int i = 0; i < 1000 && loop != 3; i++) + { + if (rce->frameSizePlanned < availableBits) + { + qScale = qScale / 1.01; + loop = loop | 1; + } + else if (rce->frameSizePlanned > availableBits) + { + qScale = qScale * 1.01; + loop = loop | 2; + } + rce->frameSizePlanned = predictSize(&m_pred[m_predType], qScale, (double)m_currentSatd); + } + return qScale; +} + double RateControl::tuneQScaleForGrain(double rcOverflow) { double qpstep = rcOverflow > 1.1 ? rcOverflow : m_lstep; @@ -1789,11 +1855,21 @@ qScale = x265_clip3(lmin, lmax, qScale); q = x265_qScale2qp(qScale); } + + if (!m_param->bResetZoneConfig) + { + double lqmin = m_lmin[m_sliceType]; + double lqmax = m_lmax[m_sliceType]; + qScale = tuneQScaleForZone(rce, qScale); + qScale = x265_clip3(lqmin, lqmax, qScale); + } + if (!m_2pass) { - qScale = clipQscale(curFrame, rce, qScale); /* clip qp to permissible range after vbv-lookahead estimation to avoid possible * mispredictions by initial frame size predictors */ + qScale = clipQscale(curFrame, rce, qScale); + if (m_pred[m_predType].count == 1) qScale = x265_clip3(lmin, lmax, qScale); m_lastQScaleFor[m_sliceType] = qScale; @@ -2015,7 +2091,20 @@ m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv : m_avgPFrameQp; m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2; } + + if (!m_param->bResetZoneConfig) + { + q = tuneQScaleForZone(rce, q); + q = x265_clip3(lqmin, lqmax, q); + } q = clipQscale(curFrame, rce, q); + + + if (m_2pass) + rce->frameSizePlanned = qScale2bits(rce, q); + else + rce->frameSizePlanned = predictSize(&m_pred[m_predType], q, (double)m_currentSatd); + /* clip qp to permissible range after vbv-lookahead estimation to avoid possible * mispredictions by initial frame size predictors, after each scenecut */ bool isFrameAfterScenecut = m_sliceType!= I_SLICE && m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut; @@ -2194,7 +2283,8 @@ frameQ[B_SLICE] = frameQ[P_SLICE] * m_param->rc.pbFactor; frameQ[I_SLICE] = frameQ[P_SLICE] / m_param->rc.ipFactor; /* Loop over the planned future frames. */ - for (int j = 0; bufferFillCur >= 0; j++) + bool iter = true; + for (int j = 0; bufferFillCur >= 0 && iter ; j++) { int type = curFrame->m_lowres.plannedType[j]; if (type == X265_TYPE_AUTO || totalDuration >= 1.0) @@ -2208,6 +2298,8 @@ int predType = getPredictorType(curFrame->m_lowres.plannedType[j], type); curBits = predictSize(&m_pred[predType], frameQ[type], (double)satd); bufferFillCur -= curBits; + if (!m_param->bResetZoneConfig && ((uint64_t)j == (m_param->reconfigWindowSize - 1))) + iter = false; } if (rce->vbvEndAdj) { @@ -2977,6 +3069,9 @@ X265_FREE(m_encOrder); for (int i = 0; i < 2; i++) X265_FREE(m_cuTreeStats.qpBuffer[i]); + + if (m_relativeComplexity) + X265_FREE(m_relativeComplexity); } diff -r 858a6b6267e0 -r 5297824e605c source/encoder/ratecontrol.h --- a/source/encoder/ratecontrol.h Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/ratecontrol.h Mon Oct 21 14:11:47 2019 +0530 @@ -128,6 +128,10 @@ int m_ncu; /* number of CUs in a frame */ int m_qp; /* updated qp for current frame */ + /*Zone reconfiguration*/ + double* m_relativeComplexity; + int m_zoneBufferIdx; + bool m_isAbr; bool m_isVbv; bool m_isCbr; @@ -228,6 +232,8 @@ int64_t m_predictedBits; int *m_encOrder; RateControlEntry* m_rce2Pass; + Encoder* m_top; + struct { uint16_t *qpBuffer[2]; /* Global buffers for converting MB-tree quantizer data. */ @@ -235,7 +241,7 @@ * This value is the current position (0 or 1). */ } m_cuTreeStats; - RateControl(x265_param& p); + RateControl(x265_param& p, Encoder *enc); bool init(const SPS& sps); void initHRD(SPS& sps); void reconfigureRC(); @@ -271,6 +277,7 @@ double getQScale(RateControlEntry *rce, double rateFactor); double rateEstimateQscale(Frame* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR double tuneAbrQScaleFromFeedback(double qScale); + double tuneQScaleForZone(RateControlEntry *rce, double qScale); // Tune qScale to adhere to zone budget void accumPQpUpdate(); int getPredictorType(int lowresSliceType, int sliceType); diff -r 858a6b6267e0 -r 5297824e605c source/x265.h --- a/source/x265.h Wed Aug 28 15:08:18 2019 +0530 +++ b/source/x265.h Mon Oct 21 14:11:47 2019 +0530 @@ -683,6 +683,7 @@ int qp; float bitrateFactor; struct x265_param* zoneParam; + double* relativeComplexity; } x265_zone; /* data to calculate aggregate VMAF score */
# HG changeset patch # User Aruna Matheswaran <ar...@multicorewareinc.com> # Date 1571647307 -19800 # Mon Oct 21 14:11:47 2019 +0530 # Node ID 5297824e605c5eed543c2f99c41335d466d17b4b # Parent 858a6b6267e025776b18eafc3279dc5addf891e4 zone: tune base QP to achieve zone target diff -r 858a6b6267e0 -r 5297824e605c source/encoder/api.cpp --- a/source/encoder/api.cpp Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/api.cpp Mon Oct 21 14:11:47 2019 +0530 @@ -199,6 +199,7 @@ { param->rc.zones[i].zoneParam = X265_MALLOC(x265_param, 1); memcpy(param->rc.zones[i].zoneParam, param, sizeof(x265_param)); + param->rc.zones[i].relativeComplexity = X265_MALLOC(double, param->reconfigWindowSize); } } @@ -379,17 +380,28 @@ { if (!enc || !zone_in) return -1; + Encoder* encoder = static_cast<Encoder*>(enc); + int read = encoder->zoneReadCount[encoder->m_zoneIndex].get(); + int write = encoder->zoneWriteCount[encoder->m_zoneIndex].get(); + x265_zone* zone = &(encoder->m_param->rc).zones[encoder->m_zoneIndex]; x265_param* zoneParam = zone->zoneParam; + + if (write && (read < write)) + { + read = encoder->zoneReadCount[encoder->m_zoneIndex].waitForChange(read); + } + + zone->startFrame = zone_in->startFrame; + zoneParam->rc.bitrate = zone_in->zoneParam->rc.bitrate; + zoneParam->rc.vbvMaxBitrate = zone_in->zoneParam->rc.vbvMaxBitrate; + memcpy(zone->relativeComplexity, zone_in->relativeComplexity, sizeof(double) * encoder->m_param->reconfigWindowSize); - int ret = encoder->reconfigureParam(zoneParam, zone_in->zoneParam); - if (ret) - return -1; - memcpy(zone, zone_in, sizeof(x265_zone)); - + encoder->zoneWriteCount[encoder->m_zoneIndex].incr(); encoder->m_zoneIndex++; encoder->m_zoneIndex %= encoder->m_param->rc.zonefileCount; + return 0; } diff -r 858a6b6267e0 -r 5297824e605c source/encoder/encoder.cpp --- a/source/encoder/encoder.cpp Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/encoder.cpp Mon Oct 21 14:11:47 2019 +0530 @@ -323,7 +323,13 @@ lookAheadThreadPool[i].start(); m_lookahead->m_numPools = pools; m_dpb = new DPB(m_param); - m_rateControl = new RateControl(*m_param); + m_rateControl = new RateControl(*m_param, this); + if (!m_param->bResetZoneConfig) + { + zoneReadCount = new ThreadSafeInteger[m_param->rc.zonefileCount]; + zoneWriteCount = new ThreadSafeInteger[m_param->rc.zonefileCount]; + } + initVPS(&m_vps); initSPS(&m_sps); initPPS(&m_pps); @@ -868,6 +874,11 @@ } delete m_dpb; + if (!m_param->bResetZoneConfig && m_param->rc.zonefileCount) + { + delete[] zoneReadCount; + delete[] zoneWriteCount; + } if (m_rateControl) { m_rateControl->destroy(); diff -r 858a6b6267e0 -r 5297824e605c source/encoder/encoder.h --- a/source/encoder/encoder.h Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/encoder.h Mon Oct 21 14:11:47 2019 +0530 @@ -274,6 +274,10 @@ bool m_saveCTUSize; + + ThreadSafeInteger* zoneReadCount; + ThreadSafeInteger* zoneWriteCount; + Encoder(); ~Encoder() { diff -r 858a6b6267e0 -r 5297824e605c source/encoder/ratecontrol.cpp --- a/source/encoder/ratecontrol.cpp Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/ratecontrol.cpp Mon Oct 21 14:11:47 2019 +0530 @@ -146,9 +146,10 @@ return NULL; } -RateControl::RateControl(x265_param& p) +RateControl::RateControl(x265_param& p, Encoder *top) { m_param = &p; + m_top = top; int lowresCuWidth = ((m_param->sourceWidth / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; int lowresCuHeight = ((m_param->sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; m_ncu = lowresCuWidth * lowresCuHeight; @@ -156,6 +157,7 @@ m_qCompress = (m_param->rc.cuTree && !m_param->rc.hevcAq) ? 1 : m_param->rc.qCompress; // validate for param->rc, maybe it is need to add a function like x265_parameters_valiate() + m_zoneBufferIdx = 0; m_residualFrames = 0; m_partialResidualFrames = 0; m_residualCost = 0; @@ -210,6 +212,7 @@ m_lastBsliceSatdCost = 0; m_movingAvgSum = 0.0; m_isNextGop = false; + m_relativeComplexity = NULL; // vbv initialization m_param->rc.vbvBufferSize = x265_clip3(0, 2000000, m_param->rc.vbvBufferSize); @@ -354,6 +357,16 @@ m_initVbv = true; } + if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL)) + { + m_relativeComplexity = X265_MALLOC(double, m_param->reconfigWindowSize); + if (m_relativeComplexity == NULL) + { + x265_log(m_param, X265_LOG_ERROR, "Failed to allocate memory for m_relativeComplexity\n"); + return false; + } + } + m_totalBits = 0; m_encodedBits = 0; m_framesDone = 0; @@ -699,6 +712,8 @@ { m_param->rc.vbvBufferSize = x265_clip3(0, 2000000, m_param->rc.vbvBufferSize); m_param->rc.vbvMaxBitrate = x265_clip3(0, 2000000, m_param->rc.vbvMaxBitrate); + if (m_param->reconfigWindowSize) + m_param->rc.vbvMaxBitrate = (int)(m_param->rc.vbvMaxBitrate * (double)(m_fps / m_param->reconfigWindowSize)); if (m_param->rc.vbvMaxBitrate < m_param->rc.bitrate && m_param->rc.rateControlMode == X265_RC_ABR) { @@ -753,7 +768,7 @@ m_qpConstant[P_SLICE] = m_qpConstant[I_SLICE] = m_qpConstant[B_SLICE] = m_qp; } } - m_bitrate = m_param->rc.bitrate * 1000; + m_bitrate = (double)m_param->rc.bitrate * 1000; } void RateControl::initHRD(SPS& sps) @@ -1244,17 +1259,43 @@ m_predType = getPredictorType(curFrame->m_lowres.sliceType, m_sliceType); rce->poc = m_curSlice->m_poc; - /* change ratecontrol stats for next zone if specified */ - for (int i = 0; i < m_param->rc.zonefileCount; i++) + if (!m_param->bResetZoneConfig && (rce->encodeOrder % m_param->reconfigWindowSize == 0)) { - if (m_param->rc.zones[i].startFrame == curFrame->m_encodeOrder) + int index = m_zoneBufferIdx % m_param->rc.zonefileCount; + int read = m_top->zoneReadCount[index].get(); + int write = m_top->zoneWriteCount[index].get(); + if (write <= read) + write = m_top->zoneWriteCount[index].waitForChange(write); + m_zoneBufferIdx++; + + for (int i = 0; i < m_param->rc.zonefileCount; i++) { - m_param = m_param->rc.zones[i].zoneParam; - reconfigureRC(); - if (m_param->bResetZoneConfig) - init(*m_curSlice->m_sps); + if (m_param->rc.zones[i].startFrame == rce->encodeOrder) + { + m_param->rc.bitrate = m_param->rc.zones[i].zoneParam->rc.bitrate; + m_param->rc.vbvMaxBitrate = m_param->rc.zones[i].zoneParam->rc.vbvMaxBitrate; + memcpy(m_relativeComplexity, m_param->rc.zones[i].relativeComplexity, sizeof(double) * m_param->reconfigWindowSize); + reconfigureRC(); + m_top->zoneReadCount[i].incr(); + } } } + + + if (m_param->bResetZoneConfig) + { + /* change ratecontrol stats for next zone if specified */ + for (int i = 0; i < m_param->rc.zonefileCount; i++) + { + if (m_param->rc.zones[i].startFrame == curFrame->m_encodeOrder) + { + m_param = m_param->rc.zones[i].zoneParam; + reconfigureRC(); + init(*m_curSlice->m_sps); + } + } + } + if (m_param->rc.bStatRead) { X265_CHECK(rce->poc >= 0 && rce->poc < m_numEntries, "bad encode ordinal\n"); @@ -1649,6 +1690,31 @@ return qScale; } +double RateControl::tuneQScaleForZone(RateControlEntry *rce, double qScale) +{ + rce->frameSizePlanned = predictSize(&m_pred[m_predType], qScale, (double)m_currentSatd); + int loop = 0; + + double availableBits = (double)m_param->rc.bitrate * 1000 * m_relativeComplexity[rce->encodeOrder % m_param->reconfigWindowSize]; + + // Tune qScale to adhere to the available frame bits. + for (int i = 0; i < 1000 && loop != 3; i++) + { + if (rce->frameSizePlanned < availableBits) + { + qScale = qScale / 1.01; + loop = loop | 1; + } + else if (rce->frameSizePlanned > availableBits) + { + qScale = qScale * 1.01; + loop = loop | 2; + } + rce->frameSizePlanned = predictSize(&m_pred[m_predType], qScale, (double)m_currentSatd); + } + return qScale; +} + double RateControl::tuneQScaleForGrain(double rcOverflow) { double qpstep = rcOverflow > 1.1 ? rcOverflow : m_lstep; @@ -1789,11 +1855,21 @@ qScale = x265_clip3(lmin, lmax, qScale); q = x265_qScale2qp(qScale); } + + if (!m_param->bResetZoneConfig) + { + double lqmin = m_lmin[m_sliceType]; + double lqmax = m_lmax[m_sliceType]; + qScale = tuneQScaleForZone(rce, qScale); + qScale = x265_clip3(lqmin, lqmax, qScale); + } + if (!m_2pass) { - qScale = clipQscale(curFrame, rce, qScale); /* clip qp to permissible range after vbv-lookahead estimation to avoid possible * mispredictions by initial frame size predictors */ + qScale = clipQscale(curFrame, rce, qScale); + if (m_pred[m_predType].count == 1) qScale = x265_clip3(lmin, lmax, qScale); m_lastQScaleFor[m_sliceType] = qScale; @@ -2015,7 +2091,20 @@ m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv : m_avgPFrameQp; m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2; } + + if (!m_param->bResetZoneConfig) + { + q = tuneQScaleForZone(rce, q); + q = x265_clip3(lqmin, lqmax, q); + } q = clipQscale(curFrame, rce, q); + + + if (m_2pass) + rce->frameSizePlanned = qScale2bits(rce, q); + else + rce->frameSizePlanned = predictSize(&m_pred[m_predType], q, (double)m_currentSatd); + /* clip qp to permissible range after vbv-lookahead estimation to avoid possible * mispredictions by initial frame size predictors, after each scenecut */ bool isFrameAfterScenecut = m_sliceType!= I_SLICE && m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut; @@ -2194,7 +2283,8 @@ frameQ[B_SLICE] = frameQ[P_SLICE] * m_param->rc.pbFactor; frameQ[I_SLICE] = frameQ[P_SLICE] / m_param->rc.ipFactor; /* Loop over the planned future frames. */ - for (int j = 0; bufferFillCur >= 0; j++) + bool iter = true; + for (int j = 0; bufferFillCur >= 0 && iter ; j++) { int type = curFrame->m_lowres.plannedType[j]; if (type == X265_TYPE_AUTO || totalDuration >= 1.0) @@ -2208,6 +2298,8 @@ int predType = getPredictorType(curFrame->m_lowres.plannedType[j], type); curBits = predictSize(&m_pred[predType], frameQ[type], (double)satd); bufferFillCur -= curBits; + if (!m_param->bResetZoneConfig && ((uint64_t)j == (m_param->reconfigWindowSize - 1))) + iter = false; } if (rce->vbvEndAdj) { @@ -2977,6 +3069,9 @@ X265_FREE(m_encOrder); for (int i = 0; i < 2; i++) X265_FREE(m_cuTreeStats.qpBuffer[i]); + + if (m_relativeComplexity) + X265_FREE(m_relativeComplexity); } diff -r 858a6b6267e0 -r 5297824e605c source/encoder/ratecontrol.h --- a/source/encoder/ratecontrol.h Wed Aug 28 15:08:18 2019 +0530 +++ b/source/encoder/ratecontrol.h Mon Oct 21 14:11:47 2019 +0530 @@ -128,6 +128,10 @@ int m_ncu; /* number of CUs in a frame */ int m_qp; /* updated qp for current frame */ + /*Zone reconfiguration*/ + double* m_relativeComplexity; + int m_zoneBufferIdx; + bool m_isAbr; bool m_isVbv; bool m_isCbr; @@ -228,6 +232,8 @@ int64_t m_predictedBits; int *m_encOrder; RateControlEntry* m_rce2Pass; + Encoder* m_top; + struct { uint16_t *qpBuffer[2]; /* Global buffers for converting MB-tree quantizer data. */ @@ -235,7 +241,7 @@ * This value is the current position (0 or 1). */ } m_cuTreeStats; - RateControl(x265_param& p); + RateControl(x265_param& p, Encoder *enc); bool init(const SPS& sps); void initHRD(SPS& sps); void reconfigureRC(); @@ -271,6 +277,7 @@ double getQScale(RateControlEntry *rce, double rateFactor); double rateEstimateQscale(Frame* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR double tuneAbrQScaleFromFeedback(double qScale); + double tuneQScaleForZone(RateControlEntry *rce, double qScale); // Tune qScale to adhere to zone budget void accumPQpUpdate(); int getPredictorType(int lowresSliceType, int sliceType); diff -r 858a6b6267e0 -r 5297824e605c source/x265.h --- a/source/x265.h Wed Aug 28 15:08:18 2019 +0530 +++ b/source/x265.h Mon Oct 21 14:11:47 2019 +0530 @@ -683,6 +683,7 @@ int qp; float bitrateFactor; struct x265_param* zoneParam; + double* relativeComplexity; } x265_zone; /* data to calculate aggregate VMAF score */
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel