[x265] Fwd: [PATCH] encoding only the focused frames in the crf 2 pass

Dakshinya T R S dakshinya at multicorewareinc.com
Mon Sep 27 12:05:04 UTC 2021


---------- Forwarded message ---------
From: Liwei Wang <liwei at multicorewareinc.com>
Date: Mon, Sep 27, 2021 at 12:47 PM
Subject: Re: [x265] [PATCH] encoding only the focused frames in the crf 2
pass
To: Dakshinya T R S <dakshinya at multicorewareinc.com>
Cc: Mahesh Pittala <mahesh at multicorewareinc.com>


Hi, Aruna

      Please find the attachment for the two patches.
      In the first patch, bEncFocusedFramesOnly will be a parameter of the
x265_param.However, it will not be a cli option or API as bEncFocusedFramesOnly
would only be used together with cappedvbr in uhdkit. It could not be used
alone in x265. So the document did not be updated in this patch.

      In the second patch, I move bEncFocusedFramesOnly to
ratecontrol instead as other parameters that cappedvbr would use are there
too.

Thanks,
Liwei

On Sun, Sep 26, 2021 at 2:14 PM Liwei Wang <liwei at multicorewareinc.com>
wrote:

> On Fri, Sep 24, 2021 at 1:34 PM Dakshinya T R S <
> dakshinya at multicorewareinc.com> wrote:
>
>> From d4ac086b18c41e6d146cd70524c581138b1186ec Mon Sep 17 00:00:00 2001
>> From: lwWang <liwei at multicorewareinc.com>
>> Date: Wed, 15 Sep 2021 10:39:51 +0800
>> Subject: [PATCH 1/2] encoding only the focused frames in the crf 2 pass
>>
>> ---
>>  source/common/frame.h          |   1 +
>>  source/common/framedata.cpp    |   2 +-
>>  source/common/param.cpp        |   1 +
>>  source/encoder/encoder.cpp     |   1 +
>>  source/encoder/ratecontrol.cpp | 240 ++++++++++++++++++---------------
>>  source/encoder/ratecontrol.h   |   3 +
>>  source/x265.h                  |   3 +
>>  7 files changed, 138 insertions(+), 113 deletions(-)
>>
>> diff --git a/source/common/frame.h b/source/common/frame.h
>> index dc5bbacf7..ac1185e81 100644
>> --- a/source/common/frame.h
>> +++ b/source/common/frame.h
>> @@ -70,6 +70,7 @@ struct RcStats
>>      double   count[4];
>>      double   offset[4];
>>      double   bufferFillFinal;
>> +    int64_t  currentSatd;
>>  };
>>
>>  class Frame
>> diff --git a/source/common/framedata.cpp b/source/common/framedata.cpp
>> index c77b017a8..70af8a248 100644
>> --- a/source/common/framedata.cpp
>> +++ b/source/common/framedata.cpp
>> @@ -62,7 +62,7 @@ bool FrameData::create(const x265_param& param, const
>> SPS& sps, int csp)
>>      }
>>      else
>>          return false;
>> -    CHECKED_MALLOC_ZERO(m_cuStat, RCStatCU, sps.numCUsInFrame);
>> +    CHECKED_MALLOC_ZERO(m_cuStat, RCStatCU, sps.numCUsInFrame + 1);
>>
> [AM] What is the significance of this additional memory?
> *[LW] to fix the random crush issue(heap corruption)*
>
>>      CHECKED_MALLOC(m_rowStat, RCStatRow, sps.numCuInHeight);
>>      reinit(sps);
>>
>> diff --git a/source/common/param.cpp b/source/common/param.cpp
>> index 6751e0aa7..2c1583d93 100755
>> --- a/source/common/param.cpp
>> +++ b/source/common/param.cpp
>> @@ -282,6 +282,7 @@ void x265_param_default(x265_param* param)
>>      param->rc.bStatRead = 0;
>>      param->rc.bStatWrite = 0;
>>      param->rc.statFileName = NULL;
>> +    param->rc.bEncFocusedFramesOnly = 0;
>>      param->rc.complexityBlur = 20;
>>      param->rc.qblur = 0.5;
>>      param->rc.zoneCount = 0;
>> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
>> index dee8fd85d..cc014a740 100644
>> --- a/source/encoder/encoder.cpp
>> +++ b/source/encoder/encoder.cpp
>> @@ -2249,6 +2249,7 @@ int Encoder::encode(const x265_picture* pic_in,
>> x265_picture* pic_out)
>>                  outFrame->m_rcData->iCuCount =
>> outFrame->m_encData->m_frameStats.percent8x8Intra * m_rateControl->m_ncu;
>>                  outFrame->m_rcData->pCuCount =
>> outFrame->m_encData->m_frameStats.percent8x8Inter * m_rateControl->m_ncu;
>>                  outFrame->m_rcData->skipCuCount =
>> outFrame->m_encData->m_frameStats.percent8x8Skip  * m_rateControl->m_ncu;
>> +                outFrame->m_rcData->currentSatd =
>> curEncoder->m_rce.coeffBits;
>>              }
>>
>>              /* Allow this frame to be recycled if no frame encoders are
>> using it for reference */
>> diff --git a/source/encoder/ratecontrol.cpp
>> b/source/encoder/ratecontrol.cpp
>> index a4756de39..2c211022d 100644
>> --- a/source/encoder/ratecontrol.cpp
>> +++ b/source/encoder/ratecontrol.cpp
>> @@ -1002,123 +1002,106 @@ bool RateControl::initPass2()
>>      uint64_t allAvailableBits = uint64_t(m_param->rc.bitrate * 1000. *
>> m_numEntries * m_frameDuration);
>>      int startIndex, framesCount, endIndex;
>>      int fps = X265_MIN(m_param->keyframeMax, (int)(m_fps + 0.5));
>> +    int distance = fps << 1;
>> +    distance = distance > m_param->keyframeMax ? (m_param->keyframeMax
>> << 1) : m_param->keyframeMax;
>>      startIndex = endIndex = framesCount = 0;
>> -    int diffQp = 0;
>>      double targetBits = 0;
>>      double expectedBits = 0;
>> -    for (startIndex = m_start, endIndex = m_start; endIndex <
>> m_numEntries; endIndex++)
>> +    double targetBits2 = 0;
>> +    double expectedBits2 = 0;
>> +    double cpxSum = 0;
>> +    double cpxSum2 = 0;
>> +
>> +    if (m_param->rc.rateControlMode == X265_RC_ABR)
>>      {
>> -        allConstBits += m_rce2Pass[endIndex].miscBits;
>> -        allCodedBits += m_rce2Pass[endIndex].coeffBits +
>> m_rce2Pass[endIndex].mvBits;
>> -        if (m_param->rc.rateControlMode == X265_RC_CRF)
>> +        for (startIndex = m_start, endIndex = m_start; endIndex <
>> m_numEntries; endIndex++)
>>          {
>> -            framesCount = endIndex - startIndex + 1;
>> -            diffQp += int (m_rce2Pass[endIndex].qpaRc -
>> m_rce2Pass[endIndex].qpNoVbv);
>> -            if (framesCount > fps)
>> -                diffQp -= int (m_rce2Pass[endIndex - fps].qpaRc -
>> m_rce2Pass[endIndex - fps].qpNoVbv);
>> -            if (framesCount >= fps)
>> -            {
>> -                if (diffQp >= 1)
>> -                {
>> -                    if (!m_isQpModified && endIndex > fps)
>> -                    {
>> -                        double factor = 2;
>> -                        double step = 0;
>> -                        if (endIndex + fps >= m_numEntries)
>> -                        {
>> -                            m_start = endIndex - (endIndex % fps);
>> -                            return true;
>> -                        }
>> -                        for (int start = endIndex + 1; start <= endIndex
>> + fps && start < m_numEntries; start++)
>> -                        {
>> -                            RateControlEntry *rce = &m_rce2Pass[start];
>> -                            targetBits += qScale2bits(rce,
>> x265_qp2qScale(rce->qpNoVbv));
>> -                            expectedBits += qScale2bits(rce,
>> rce->qScale);
>> -                        }
>> -                        if (expectedBits < 0.95 * targetBits)
>> -                        {
>> -                            m_isQpModified = true;
>> -                            m_isGopReEncoded = true;
>> -                            while (endIndex + fps < m_numEntries)
>> -                            {
>> -                                step = pow(2, factor / 6.0);
>> -                                expectedBits = 0;
>> -                                for (int start = endIndex + 1; start <=
>> endIndex + fps; start++)
>> -                                {
>> -                                    RateControlEntry *rce =
>> &m_rce2Pass[start];
>> -                                    rce->newQScale = rce->qScale / step;
>> -                                    X265_CHECK(rce->newQScale >= 0, "new
>> Qscale is negative\n");
>> -                                    expectedBits += qScale2bits(rce,
>> rce->newQScale);
>> -                                    rce->newQp =
>> x265_qScale2qp(rce->newQScale);
>> -                                }
>> -                                if (expectedBits >= targetBits && step >
>> 1)
>> -                                    factor *= 0.90;
>> -                                else
>> -                                    break;
>> -                            }
>> -
>> -                            if (m_isVbv && endIndex + fps < m_numEntries)
>> -                                if (!vbv2Pass((uint64_t)targetBits,
>> endIndex + fps, endIndex + 1))
>> -                                    return false;
>> -
>> -                            targetBits = 0;
>> -                            expectedBits = 0;
>> -
>> -                            for (int start = endIndex - fps + 1; start
>> <= endIndex; start++)
>> -                            {
>> -                                RateControlEntry *rce =
>> &m_rce2Pass[start];
>> -                                targetBits += qScale2bits(rce,
>> x265_qp2qScale(rce->qpNoVbv));
>> -                            }
>> -                            while (1)
>> -                            {
>> -                                step = pow(2, factor / 6.0);
>> -                                expectedBits = 0;
>> -                                for (int start = endIndex - fps + 1;
>> start <= endIndex; start++)
>> -                                {
>> -                                    RateControlEntry *rce =
>> &m_rce2Pass[start];
>> -                                    rce->newQScale = rce->qScale * step;
>> -                                    X265_CHECK(rce->newQScale >= 0, "new
>> Qscale is negative\n");
>> -                                    expectedBits += qScale2bits(rce,
>> rce->newQScale);
>> -                                    rce->newQp =
>> x265_qScale2qp(rce->newQScale);
>> -                                }
>> -                                if (expectedBits > targetBits && step >
>> 1)
>> -                                    factor *= 1.1;
>> -                                else
>> -                                     break;
>> -                            }
>> -                            if (m_isVbv)
>> -                                if (!vbv2Pass((uint64_t)targetBits,
>> endIndex, endIndex - fps + 1))
>> -                                    return false;
>> -                            diffQp = 0;
>> -                            m_reencode = endIndex - fps + 1;
>> -                            endIndex = endIndex + fps;
>> -                            startIndex = endIndex + 1;
>> -                            m_start = startIndex;
>> -                            targetBits = expectedBits = 0;
>> -                        }
>> -                        else
>> -                            targetBits = expectedBits = 0;
>> -                    }
>> -                }
>> -                else
>> -                    m_isQpModified = false;
>> -            }
>> +            allConstBits += m_rce2Pass[endIndex].miscBits;
>> +            allCodedBits += m_rce2Pass[endIndex].coeffBits +
>> m_rce2Pass[endIndex].mvBits;
>>          }
>> -    }
>>
>> -    if (m_param->rc.rateControlMode == X265_RC_ABR)
>> -    {
>>          if (allAvailableBits < allConstBits)
>>          {
>>              x265_log(m_param, X265_LOG_ERROR, "requested bitrate is too
>> low. estimated minimum is %d kbps\n",
>> -                     (int)(allConstBits * m_fps / framesCount * 1000.));
>> +                (int)(allConstBits * m_fps / framesCount * 1000.));
>>              return false;
>>          }
>>          if (!analyseABR2Pass(allAvailableBits))
>>              return false;
>> +
>> +        return true;
>> +    }
>> +
>> +    if (m_param->rc.rateControlMode != X265_RC_CRF)
>> +    {
>>
> [AM] This condition will never hit. Please clarify why this is required.
> *[LW] Yeah, you're right. It will never hit. I will remove this
> check.Thanks*
>
>> +        return true;
>>      }
>>
>
>> -    m_start = X265_MAX(m_start, endIndex - fps);
>> +    if (m_isQpModified)
>> +    {
>>
> [AM] This condition will always hit. Please clarify why this check is
> required.
> *[LW] m_isQpModified may be false.  And in the uhdkit, the cappedvbr would
> modify its value.*
> [AM] Please include a conformance check in Encoder::configure() to disable
> m_param->rc.bEncFocusedFramesOnly if either bStatRead or CRF is disabled.
> [*LW] OK. I will add it. By the way, **bEncFocusedFramesOnly has been set
> to be false by default in the x265_param_default()*
> [AM] Update X265_BUILD, add help document, and add an entry for the new
> param in info SEI.
> Is this a param?API only option? If so, clarify that in the document.
> Else, add a test CLI.
> *[LW] OK. However, **bEncFocusedFramesOnly would only be used together
> with cappedvbr in uhdkit. It could not be used alone in x25. So maybe it is
> better to move it from the x265_param to the encoder or rateontrol?*
>
>>          /* temporally blur quants */
>>          double    qblur;
>>
>
> On Fri, Sep 24, 2021 at 5:02 PM Dakshinya T R S <
> dakshinya at multicorewareinc.com> wrote:
>
>>
>>
>> ---------- Forwarded message ---------
>> From: Aruna Matheswaran <aruna at multicorewareinc.com>
>> Date: Fri, Sep 24, 2021 at 2:26 PM
>> Subject: Re: [x265] [PATCH] encoding only the focused frames in the crf 2
>> pass
>> To: Development for x265 <x265-devel at videolan.org>
>>
>>
>>
>>
>> On Fri, Sep 24, 2021 at 1:34 PM Dakshinya T R S <
>> dakshinya at multicorewareinc.com> wrote:
>>
>>> From d4ac086b18c41e6d146cd70524c581138b1186ec Mon Sep 17 00:00:00 2001
>>> From: lwWang <liwei at multicorewareinc.com>
>>> Date: Wed, 15 Sep 2021 10:39:51 +0800
>>> Subject: [PATCH 1/2] encoding only the focused frames in the crf 2 pass
>>>
>>> ---
>>>  source/common/frame.h          |   1 +
>>>  source/common/framedata.cpp    |   2 +-
>>>  source/common/param.cpp        |   1 +
>>>  source/encoder/encoder.cpp     |   1 +
>>>  source/encoder/ratecontrol.cpp | 240 ++++++++++++++++++---------------
>>>  source/encoder/ratecontrol.h   |   3 +
>>>  source/x265.h                  |   3 +
>>>  7 files changed, 138 insertions(+), 113 deletions(-)
>>>
>>> diff --git a/source/common/frame.h b/source/common/frame.h
>>> index dc5bbacf7..ac1185e81 100644
>>> --- a/source/common/frame.h
>>> +++ b/source/common/frame.h
>>> @@ -70,6 +70,7 @@ struct RcStats
>>>      double   count[4];
>>>      double   offset[4];
>>>      double   bufferFillFinal;
>>> +    int64_t  currentSatd;
>>>  };
>>>
>>>  class Frame
>>> diff --git a/source/common/framedata.cpp b/source/common/framedata.cpp
>>> index c77b017a8..70af8a248 100644
>>> --- a/source/common/framedata.cpp
>>> +++ b/source/common/framedata.cpp
>>> @@ -62,7 +62,7 @@ bool FrameData::create(const x265_param& param, const
>>> SPS& sps, int csp)
>>>      }
>>>      else
>>>          return false;
>>> -    CHECKED_MALLOC_ZERO(m_cuStat, RCStatCU, sps.numCUsInFrame);
>>> +    CHECKED_MALLOC_ZERO(m_cuStat, RCStatCU, sps.numCUsInFrame + 1);
>>>
>> [AM] What is the significance of this additional memory?
>>
>>>      CHECKED_MALLOC(m_rowStat, RCStatRow, sps.numCuInHeight);
>>>      reinit(sps);
>>>
>>> diff --git a/source/common/param.cpp b/source/common/param.cpp
>>> index 6751e0aa7..2c1583d93 100755
>>> --- a/source/common/param.cpp
>>> +++ b/source/common/param.cpp
>>> @@ -282,6 +282,7 @@ void x265_param_default(x265_param* param)
>>>      param->rc.bStatRead = 0;
>>>      param->rc.bStatWrite = 0;
>>>      param->rc.statFileName = NULL;
>>> +    param->rc.bEncFocusedFramesOnly = 0;
>>>      param->rc.complexityBlur = 20;
>>>      param->rc.qblur = 0.5;
>>>      param->rc.zoneCount = 0;
>>> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
>>> index dee8fd85d..cc014a740 100644
>>> --- a/source/encoder/encoder.cpp
>>> +++ b/source/encoder/encoder.cpp
>>> @@ -2249,6 +2249,7 @@ int Encoder::encode(const x265_picture* pic_in,
>>> x265_picture* pic_out)
>>>                  outFrame->m_rcData->iCuCount =
>>> outFrame->m_encData->m_frameStats.percent8x8Intra * m_rateControl->m_ncu;
>>>                  outFrame->m_rcData->pCuCount =
>>> outFrame->m_encData->m_frameStats.percent8x8Inter * m_rateControl->m_ncu;
>>>                  outFrame->m_rcData->skipCuCount =
>>> outFrame->m_encData->m_frameStats.percent8x8Skip  * m_rateControl->m_ncu;
>>> +                outFrame->m_rcData->currentSatd =
>>> curEncoder->m_rce.coeffBits;
>>>              }
>>>
>>>              /* Allow this frame to be recycled if no frame encoders are
>>> using it for reference */
>>> diff --git a/source/encoder/ratecontrol.cpp
>>> b/source/encoder/ratecontrol.cpp
>>> index a4756de39..2c211022d 100644
>>> --- a/source/encoder/ratecontrol.cpp
>>> +++ b/source/encoder/ratecontrol.cpp
>>> @@ -1002,123 +1002,106 @@ bool RateControl::initPass2()
>>>      uint64_t allAvailableBits = uint64_t(m_param->rc.bitrate * 1000. *
>>> m_numEntries * m_frameDuration);
>>>      int startIndex, framesCount, endIndex;
>>>      int fps = X265_MIN(m_param->keyframeMax, (int)(m_fps + 0.5));
>>> +    int distance = fps << 1;
>>> +    distance = distance > m_param->keyframeMax ? (m_param->keyframeMax
>>> << 1) : m_param->keyframeMax;
>>>      startIndex = endIndex = framesCount = 0;
>>> -    int diffQp = 0;
>>>      double targetBits = 0;
>>>      double expectedBits = 0;
>>> -    for (startIndex = m_start, endIndex = m_start; endIndex <
>>> m_numEntries; endIndex++)
>>> +    double targetBits2 = 0;
>>> +    double expectedBits2 = 0;
>>> +    double cpxSum = 0;
>>> +    double cpxSum2 = 0;
>>> +
>>> +    if (m_param->rc.rateControlMode == X265_RC_ABR)
>>>      {
>>> -        allConstBits += m_rce2Pass[endIndex].miscBits;
>>> -        allCodedBits += m_rce2Pass[endIndex].coeffBits +
>>> m_rce2Pass[endIndex].mvBits;
>>> -        if (m_param->rc.rateControlMode == X265_RC_CRF)
>>> +        for (startIndex = m_start, endIndex = m_start; endIndex <
>>> m_numEntries; endIndex++)
>>>          {
>>> -            framesCount = endIndex - startIndex + 1;
>>> -            diffQp += int (m_rce2Pass[endIndex].qpaRc -
>>> m_rce2Pass[endIndex].qpNoVbv);
>>> -            if (framesCount > fps)
>>> -                diffQp -= int (m_rce2Pass[endIndex - fps].qpaRc -
>>> m_rce2Pass[endIndex - fps].qpNoVbv);
>>> -            if (framesCount >= fps)
>>> -            {
>>> -                if (diffQp >= 1)
>>> -                {
>>> -                    if (!m_isQpModified && endIndex > fps)
>>> -                    {
>>> -                        double factor = 2;
>>> -                        double step = 0;
>>> -                        if (endIndex + fps >= m_numEntries)
>>> -                        {
>>> -                            m_start = endIndex - (endIndex % fps);
>>> -                            return true;
>>> -                        }
>>> -                        for (int start = endIndex + 1; start <=
>>> endIndex + fps && start < m_numEntries; start++)
>>> -                        {
>>> -                            RateControlEntry *rce = &m_rce2Pass[start];
>>> -                            targetBits += qScale2bits(rce,
>>> x265_qp2qScale(rce->qpNoVbv));
>>> -                            expectedBits += qScale2bits(rce,
>>> rce->qScale);
>>> -                        }
>>> -                        if (expectedBits < 0.95 * targetBits)
>>> -                        {
>>> -                            m_isQpModified = true;
>>> -                            m_isGopReEncoded = true;
>>> -                            while (endIndex + fps < m_numEntries)
>>> -                            {
>>> -                                step = pow(2, factor / 6.0);
>>> -                                expectedBits = 0;
>>> -                                for (int start = endIndex + 1; start <=
>>> endIndex + fps; start++)
>>> -                                {
>>> -                                    RateControlEntry *rce =
>>> &m_rce2Pass[start];
>>> -                                    rce->newQScale = rce->qScale / step;
>>> -                                    X265_CHECK(rce->newQScale >= 0,
>>> "new Qscale is negative\n");
>>> -                                    expectedBits += qScale2bits(rce,
>>> rce->newQScale);
>>> -                                    rce->newQp =
>>> x265_qScale2qp(rce->newQScale);
>>> -                                }
>>> -                                if (expectedBits >= targetBits && step
>>> > 1)
>>> -                                    factor *= 0.90;
>>> -                                else
>>> -                                    break;
>>> -                            }
>>> -
>>> -                            if (m_isVbv && endIndex + fps <
>>> m_numEntries)
>>> -                                if (!vbv2Pass((uint64_t)targetBits,
>>> endIndex + fps, endIndex + 1))
>>> -                                    return false;
>>> -
>>> -                            targetBits = 0;
>>> -                            expectedBits = 0;
>>> -
>>> -                            for (int start = endIndex - fps + 1; start
>>> <= endIndex; start++)
>>> -                            {
>>> -                                RateControlEntry *rce =
>>> &m_rce2Pass[start];
>>> -                                targetBits += qScale2bits(rce,
>>> x265_qp2qScale(rce->qpNoVbv));
>>> -                            }
>>> -                            while (1)
>>> -                            {
>>> -                                step = pow(2, factor / 6.0);
>>> -                                expectedBits = 0;
>>> -                                for (int start = endIndex - fps + 1;
>>> start <= endIndex; start++)
>>> -                                {
>>> -                                    RateControlEntry *rce =
>>> &m_rce2Pass[start];
>>> -                                    rce->newQScale = rce->qScale * step;
>>> -                                    X265_CHECK(rce->newQScale >= 0,
>>> "new Qscale is negative\n");
>>> -                                    expectedBits += qScale2bits(rce,
>>> rce->newQScale);
>>> -                                    rce->newQp =
>>> x265_qScale2qp(rce->newQScale);
>>> -                                }
>>> -                                if (expectedBits > targetBits && step >
>>> 1)
>>> -                                    factor *= 1.1;
>>> -                                else
>>> -                                     break;
>>> -                            }
>>> -                            if (m_isVbv)
>>> -                                if (!vbv2Pass((uint64_t)targetBits,
>>> endIndex, endIndex - fps + 1))
>>> -                                    return false;
>>> -                            diffQp = 0;
>>> -                            m_reencode = endIndex - fps + 1;
>>> -                            endIndex = endIndex + fps;
>>> -                            startIndex = endIndex + 1;
>>> -                            m_start = startIndex;
>>> -                            targetBits = expectedBits = 0;
>>> -                        }
>>> -                        else
>>> -                            targetBits = expectedBits = 0;
>>> -                    }
>>> -                }
>>> -                else
>>> -                    m_isQpModified = false;
>>> -            }
>>> +            allConstBits += m_rce2Pass[endIndex].miscBits;
>>> +            allCodedBits += m_rce2Pass[endIndex].coeffBits +
>>> m_rce2Pass[endIndex].mvBits;
>>>          }
>>> -    }
>>>
>>> -    if (m_param->rc.rateControlMode == X265_RC_ABR)
>>> -    {
>>>          if (allAvailableBits < allConstBits)
>>>          {
>>>              x265_log(m_param, X265_LOG_ERROR, "requested bitrate is too
>>> low. estimated minimum is %d kbps\n",
>>> -                     (int)(allConstBits * m_fps / framesCount * 1000.));
>>> +                (int)(allConstBits * m_fps / framesCount * 1000.));
>>>              return false;
>>>          }
>>>          if (!analyseABR2Pass(allAvailableBits))
>>>              return false;
>>> +
>>> +        return true;
>>> +    }
>>> +
>>> +    if (m_param->rc.rateControlMode != X265_RC_CRF)
>>> +    {
>>>
>> [AM] This condition will never hit. Please clarify why this is required.
>>
>>> +        return true;
>>>      }
>>>
>>
>>> -    m_start = X265_MAX(m_start, endIndex - fps);
>>> +    if (m_isQpModified)
>>> +    {
>>>
>> [AM] This condition will always hit. Please clarify why this check is
>> required.
>>
>>> +        return true;
>>> +    }
>>> +
>>> +    if (m_start + (fps << 1) > m_numEntries)
>>> +    {
>>> +        return true;
>>> +    }
>>> +
>>> +    for (startIndex = m_start, endIndex = m_numEntries - 1; startIndex
>>> < endIndex; startIndex++, endIndex--)
>>> +    {
>>> +        cpxSum += m_rce2Pass[startIndex].qScale /
>>> m_rce2Pass[startIndex].coeffBits;
>>> +        cpxSum2 += m_rce2Pass[endIndex].qScale /
>>> m_rce2Pass[endIndex].coeffBits;
>>> +
>>> +        RateControlEntry *rce = &m_rce2Pass[startIndex];
>>> +        targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv));
>>> +        expectedBits += qScale2bits(rce, rce->qScale);
>>> +
>>> +        rce = &m_rce2Pass[endIndex];
>>> +        targetBits2 += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv));
>>> +        expectedBits2 += qScale2bits(rce, rce->qScale);
>>> +    }
>>> +
>>> +    if (expectedBits < 0.95 * targetBits || expectedBits2 < 0.95 *
>>> targetBits2)
>>> +    {
>>> +        if (cpxSum / cpxSum2 < 0.95 || cpxSum2 / cpxSum < 0.95)
>>> +        {
>>> +            m_isQpModified = true;
>>> +            m_isGopReEncoded = true;
>>> +
>>> +            m_shortTermCplxSum = 0;
>>> +            m_shortTermCplxCount = 0;
>>> +            m_framesDone = m_start;
>>> +
>>> +            for (startIndex = m_start; startIndex < m_numEntries;
>>> startIndex++)
>>> +            {
>>> +                m_shortTermCplxSum *= 0.5;
>>> +                m_shortTermCplxCount *= 0.5;
>>> +                m_shortTermCplxSum +=
>>> m_rce2Pass[startIndex].currentSatd / (CLIP_DURATION(m_frameDuration) /
>>> BASE_FRAME_DURATION);
>>> +                m_shortTermCplxCount++;
>>> +            }
>>> +
>>> +            m_bufferFill = m_rce2Pass[m_start - 1].bufferFill;
>>> +            m_bufferFillFinal = m_rce2Pass[m_start - 1].bufferFillFinal;
>>> +            m_bufferFillActual = m_rce2Pass[m_start -
>>> 1].bufferFillActual;
>>> +
>>> +            m_reencode = m_start;
>>> +            m_start = m_numEntries;
>>> +        }
>>> +        else
>>> +        {
>>> +
>>> +            m_isQpModified = false;
>>> +            m_isGopReEncoded = false;
>>> +        }
>>> +    }
>>> +    else
>>> +    {
>>> +
>>> +        m_isQpModified = false;
>>> +        m_isGopReEncoded = false;
>>> +    }
>>> +
>>> +    m_start = X265_MAX(m_start, m_numEntries - distance +
>>> m_param->keyframeMax);
>>>
>>>      return true;
>>>  }
>>> @@ -1391,15 +1374,47 @@ int RateControl::rateControlStart(Frame*
>>> curFrame, RateControlEntry* rce, Encode
>>>              rce->frameSizeMaximum *= m_param->maxAUSizeFactor;
>>>          }
>>>      }
>>> +
>>> +    ///< regenerate the qp
>>>      if (!m_isAbr && m_2pass && m_param->rc.rateControlMode ==
>>> X265_RC_CRF)
>>>      {
>>> -        rce->qpPrev = x265_qScale2qp(rce->qScale);
>>> -        rce->qScale = rce->newQScale;
>>> -        rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq =
>>> x265_qScale2qp(rce->newQScale);
>>> -        m_qp = int(rce->qpaRc + 0.5);
>>> -        rce->frameSizePlanned = qScale2bits(rce, rce->qScale);
>>> -        m_framesDone++;
>>> -        return m_qp;
>>> +        if (!m_param->rc.bEncFocusedFramesOnly)
>>> +        {
>>> +            rce->qpPrev = x265_qScale2qp(rce->qScale);
>>> +            rce->qScale = rce->newQScale;
>>> +            rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq =
>>> x265_qScale2qp(rce->newQScale);
>>> +            m_qp = int(rce->qpaRc + 0.5);
>>> +            rce->frameSizePlanned = qScale2bits(rce, rce->qScale);
>>> +            m_framesDone++;
>>> +            return m_qp;
>>> +        }
>>> +        else
>>> +        {
>>> +            int index = m_encOrder[rce->poc];
>>> +            index++;
>>> +            double totalDuration = m_frameDuration;
>>> +            for (int j = 0; totalDuration < 1.0 && index <
>>> m_numEntries; j++)
>>> +            {
>>> +                switch (m_rce2Pass[index].sliceType)
>>> +                {
>>> +                case B_SLICE:
>>> +                    curFrame->m_lowres.plannedType[j] =
>>> m_rce2Pass[index].keptAsRef ? X265_TYPE_BREF : X265_TYPE_B;
>>> +                    break;
>>> +                case P_SLICE:
>>> +                    curFrame->m_lowres.plannedType[j] = X265_TYPE_P;
>>> +                    break;
>>> +                case I_SLICE:
>>> +                    curFrame->m_lowres.plannedType[j] =
>>> m_param->bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR;
>>> +                    break;
>>> +                default:
>>> +                    break;
>>> +                }
>>> +
>>> +                curFrame->m_lowres.plannedSatd[j] =
>>> m_rce2Pass[index].currentSatd;
>>> +                totalDuration += m_frameDuration;
>>> +                index++;
>>> +            }
>>> +        }
>>>      }
>>>
>>>      if (m_isAbr || m_2pass) // ABR,CRF
>>> @@ -1890,7 +1905,7 @@ double RateControl::rateEstimateQscale(Frame*
>>> curFrame, RateControlEntry *rce)
>>>                  qScale = x265_clip3(lqmin, lqmax, qScale);
>>>              }
>>>
>>> -            if (!m_2pass || m_param->bliveVBV2pass)
>>> +            if (!m_2pass || m_param->bliveVBV2pass || (m_2pass &&
>>> m_param->rc.rateControlMode == X265_RC_CRF &&
>>> m_param->rc.bEncFocusedFramesOnly))
>>>              {
>>>                  /* clip qp to permissible range after vbv-lookahead
>>> estimation to avoid possible
>>>                   * mispredictions by initial frame size predictors */
>>> @@ -1927,7 +1942,7 @@ double RateControl::rateEstimateQscale(Frame*
>>> curFrame, RateControlEntry *rce)
>>>      else
>>>      {
>>>          double abrBuffer = 2 * m_rateTolerance * m_bitrate;
>>> -        if (m_2pass)
>>> +        if (m_2pass && (m_param->rc.rateControlMode != X265_RC_CRF ||
>>> !m_param->rc.bEncFocusedFramesOnly))
>>>          {
>>>
>> [AM] Please include a conformance check in Encoder::configure() to
>> disable m_param->rc.bEncFocusedFramesOnly if either bStatRead or CRF is
>> disabled.
>>
>>>              double lmin = m_lmin[m_sliceType];
>>>              double lmax = m_lmax[m_sliceType];
>>> @@ -2828,7 +2843,7 @@ int RateControl::rateControlEnd(Frame* curFrame,
>>> int64_t bits, RateControlEntry*
>>>
>>>      if (m_param->rc.aqMode || m_isVbv || m_param->bAQMotion ||
>>> bEnableDistOffset)
>>>      {
>>> -        if (m_isVbv && !(m_2pass && m_param->rc.rateControlMode ==
>>> X265_RC_CRF))
>>> +        if (m_isVbv && !(m_2pass && m_param->rc.rateControlMode ==
>>> X265_RC_CRF && !m_param->rc.bEncFocusedFramesOnly))
>>>          {
>>>              double avgQpRc = 0;
>>>              /* determine avg QP decided by VBV rate control */
>>> @@ -2862,8 +2877,9 @@ int RateControl::rateControlEnd(Frame* curFrame,
>>> int64_t bits, RateControlEntry*
>>>      if (m_param->rc.rateControlMode == X265_RC_CRF)
>>>      {
>>>          double crfVal, qpRef = curEncData.m_avgQpRc;
>>> +
>>>          bool is2passCrfChange = false;
>>> -        if (m_2pass)
>>> +        if (m_2pass && !m_param->rc.bEncFocusedFramesOnly)
>>>          {
>>>              if (fabs(curEncData.m_avgQpRc - rce->qpPrev) > 0.1)
>>>              {
>>> diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
>>> index 996465eeb..204bd71e1 100644
>>> --- a/source/encoder/ratecontrol.h
>>> +++ b/source/encoder/ratecontrol.h
>>> @@ -73,6 +73,7 @@ struct RateControlEntry
>>>      Predictor  rowPreds[3][2];
>>>      Predictor* rowPred[2];
>>>
>>> +    int64_t currentSatd;
>>>      int64_t lastSatd;      /* Contains the picture cost of the previous
>>> frame, required for resetAbr and VBV */
>>>      int64_t leadingNoBSatd;
>>>      int64_t rowTotalBits;  /* update cplxrsum and totalbits at the end
>>> of 2 rows */
>>> @@ -87,6 +88,8 @@ struct RateControlEntry
>>>      double  rowCplxrSum;
>>>      double  qpNoVbv;
>>>      double  bufferFill;
>>> +    double  bufferFillFinal;
>>> +    double  bufferFillActual;
>>>      double  targetFill;
>>>      bool    vbvEndAdj;
>>>      double  frameDuration;
>>> diff --git a/source/x265.h b/source/x265.h
>>> index 3f3133536..6bb893c98 100644
>>> --- a/source/x265.h
>>> +++ b/source/x265.h
>>> @@ -1443,6 +1443,9 @@ typedef struct x265_param
>>>           * encoder will default to using x265_2pass.log */
>>>          const char* statFileName;
>>>
>>> +        /* if only the focused frames would be re-encode or not */
>>> +        int       bEncFocusedFramesOnly;
>>> +
>>>
>> [AM] Update X265_BUILD, add help document, and add an entry for the new
>> param in info SEI.
>> Is this a param?API only option? If so, clarify that in the document.
>> Else, add a test CLI.
>>
>>>          /* temporally blur quants */
>>>          double    qblur;
>>>
>>> --
>>> 2.22.0.windows.1
>>>
>>> _______________________________________________
>>> x265-devel mailing list
>>> x265-devel at videolan.org
>>> https://mailman.videolan.org/listinfo/x265-devel
>>>
>>
>>
>> --
>> Regards,
>> *Aruna Matheswaran,*
>> Video Codec Engineer,
>> Media & AI analytics BU,
>>
>>
>>
>> _______________________________________________
>> 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/20210927/87052f18/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: remain-in-x265_param-0001-Support-encoding-only-the-focused-frames-in-the-crf-2pass.patch
Type: application/x-patch
Size: 18125 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210927/87052f18/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: move-to-ratecontrol-0001-Enable-reencoding-the-focus-frames-in-the-crf-2-pass.patch
Type: application/x-patch
Size: 16883 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210927/87052f18/attachment-0003.bin>


More information about the x265-devel mailing list