<div dir="ltr">Does it make sense to try this for DC coefficients?<br><div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jul 22, 2014 at 9:24 PM, Steve Borho <span dir="ltr"><<a href="mailto:steve@borho.org" target="_blank">steve@borho.org</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On 07/22, <a href="mailto:sumalatha@multicorewareinc.com">sumalatha@multicorewareinc.com</a> wrote:<br>


> # HG changeset patch<br>
> # User Sumalatha Polureddy<<a href="mailto:sumalatha@multicorewareinc.com">sumalatha@multicorewareinc.com</a>><br>
> # Date 1406032149 -19800<br>
> # Node ID 37e03dcd2e4f0b5894880ff8c097bd6e11590459<br>
> # Parent  d303b4d860e9f06396a156726dd518d0f41fe796<br>
> psyrdoq: implementation of psyrdoq<br>
><br>
> diff -r d303b4d860e9 -r 37e03dcd2e4f source/Lib/TLibCommon/TComTrQuant.cpp<br>
> --- a/source/Lib/TLibCommon/TComTrQuant.cpp   Mon Jul 21 22:43:38 2014 -0500<br>
> +++ b/source/Lib/TLibCommon/TComTrQuant.cpp   Tue Jul 22 17:59:09 2014 +0530<br>
> @@ -64,6 +64,8 @@<br>
>      return y + ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // min(x, y)<br>
>  }<br>
><br>
> +#define SIGN(x,y) ((x^(y >> 31))-(y >> 31))<br>
> +<br>
>  // ====================================================================================================================<br>
>  // TComTrQuant class member functions<br>
>  // ====================================================================================================================<br>
> @@ -307,6 +309,8 @@<br>
>  }<br>
><br>
>  uint32_t TComTrQuant::transformNxN(TComDataCU* cu,<br>
> +                                   pixel*      fenc,<br>
> +                                   uint32_t    fencStride,<br>
>                                     int16_t*    residual,<br>
>                                     uint32_t    stride,<br>
>                                     coeff_t*    coeff,<br>
> @@ -316,10 +320,10 @@<br>
>                                     bool        useTransformSkip,<br>
>                                     bool        curUseRDOQ)<br>
>  {<br>
> +    int trSize = 1 << log2TrSize;<br>
>      if (cu->getCUTransquantBypass(absPartIdx))<br>
>      {<br>
>          uint32_t numSig = 0;<br>
> -        int trSize = 1 << log2TrSize;<br>
>          for (int k = 0; k < trSize; k++)<br>
>          {<br>
>              for (int j = 0; j < trSize; j++)<br>
> @@ -339,6 +343,12 @@<br>
>          const uint32_t sizeIdx = log2TrSize - 2;<br>
>          int useDST = (sizeIdx == 0 && ttype == TEXT_LUMA && cu->getPredictionMode(absPartIdx) == MODE_INTRA);<br>
>          int index = DCT_4x4 + sizeIdx - useDST;<br>
> +        if (psyRdoqEnabled())<br>
> +        {<br>
> +            // converting pixel to int and putting in separate buffer to take dct<br>
> +            primitives.square_copy_ps[sizeIdx](m_tmpfencBuf, MAX_CU_SIZE, fenc, fencStride);<br>
> +            primitives.dct[index](m_tmpfencBuf, m_tmpfencCoeff, stride);<br>
> +        }<br>
>          primitives.dct[index](residual, m_tmpCoeff, stride);<br>
>          if (m_nr->bNoiseReduction)<br>
>          {<br>
> @@ -356,7 +366,7 @@<br>
><br>
>      if (m_useRDOQ && curUseRDOQ)<br>
>      {<br>
> -        return xRateDistOptQuant(cu, m_tmpCoeff, coeff, log2TrSize, ttype, absPartIdx);<br>
> +        return xRateDistOptQuant(cu, m_tmpfencCoeff, m_tmpCoeff, coeff, log2TrSize, ttype, absPartIdx);<br>
>      }<br>
>      return xQuant(cu, m_tmpCoeff, coeff, log2TrSize, ttype, absPartIdx);<br>
>  }<br>
> @@ -505,7 +515,7 @@<br>
>   * Rate distortion optimized quantization for entropy<br>
>   * coding engines using probability models like CABAC<br>
>   */<br>
> -uint32_t TComTrQuant::xRateDistOptQuant(TComDataCU* cu, int32_t* srcCoeff, coeff_t* dstCoeff, uint32_t log2TrSize,<br>
> +uint32_t TComTrQuant::xRateDistOptQuant(TComDataCU* cu, int32_t* fencCoeff, int32_t* srcCoeff, coeff_t* dstCoeff, uint32_t log2TrSize,<br>
>                                          TextType ttype, uint32_t absPartIdx)<br>
>  {<br>
>      uint32_t trSize = 1 << log2TrSize;<br>
> @@ -614,7 +624,7 @@<br>
>                  {<br>
>                      level = xGetCodedLevel(costCoeff[scanPos], curCostSig, costSig[scanPos],<br>
>                                             levelDouble, maxAbsLevel, baseLevel, greaterOneBits, levelAbsBits, goRiceParam,<br>
> -                                           c1c2Idx, qbits, scaleFactor, 1);<br>
> +                                           c1c2Idx, qbits, scaleFactor, 1, srcCoeff[blkPos], fencCoeff[blkPos]);<br>
>                      sigRateDelta[blkPos] = 0;<br>
>                  }<br>
>                  else<br>
> @@ -631,7 +641,7 @@<br>
>                          curCostSig = xGetRateSigCoef(1, ctxSig);<br>
>                          level = xGetCodedLevel(costCoeff[scanPos], curCostSig, costSig[scanPos],<br>
>                                                 levelDouble, maxAbsLevel, baseLevel, greaterOneBits, levelAbsBits, goRiceParam,<br>
> -                                               c1c2Idx, qbits, scaleFactor, 0);<br>
> +                                               c1c2Idx, qbits, scaleFactor, 0, srcCoeff[blkPos], fencCoeff[blkPos]);<br>
>                      }<br>
>                      else<br>
>                      {<br>
> @@ -1126,7 +1136,9 @@<br>
>                                              uint32_t     c1c2Idx,<br>
>                                              int          qbits,<br>
>                                              double       scaleFactor,<br>
> -                                            bool         last) const<br>
> +                                            bool         last,<br>
> +                                            int          signCoef,<br>
> +                                            int          origCoef) const<br>
>  {<br>
>      uint32_t   bestAbsLevel = 0;<br>
><br>
> @@ -1155,7 +1167,18 @@<br>
>      for (int absLevel = maxAbsLevel; absLevel >= minAbsLevel; absLevel--)<br>
>      {<br>
>          X265_CHECK(fabs((double)err2 - double(levelDouble  - (absLevel << qbits)) * double(levelDouble  - (absLevel << qbits)) * scaleFactor) < 1e-5, "err2 check failure\n");<br>
> -        double curCost = err2 + xGetICRateCost(absLevel, diffLevel, greaterOneBits, levelAbsBits, absGoRice, c1c2Idx);<br>
> +        double curCost = 0;<br>
<br>
</div></div>in x264, psy-trellis is not applied to the DC coeff nor to chroma; we<br>
need to at least try to do that here to measure the effect.<br>
<div class=""><br>
> +        if (psyRdoqEnabled())<br>
> +        {<br>
> +            int unquantAbsLevel = (maxAbsLevel << qbits);<br>
> +            int predictedCoef = origCoef - signCoef;<br>
> +            int psyValue = abs(unquantAbsLevel + SIGN(predictedCoef, signCoef)); // test with differnt cases to check whether SIGN is required<br>
> +            curCost = err2 + xGetICRateCost(absLevel, diffLevel, greaterOneBits, levelAbsBits, absGoRice, c1c2Idx) - (m_psyRdoqScale * psyValue * m_lambda);<br>
> +        }<br>
> +        else<br>
> +        {<br>
> +            curCost = err2 + xGetICRateCost(absLevel, diffLevel, greaterOneBits, levelAbsBits, absGoRice, c1c2Idx);<br>
> +        }<br>
<br>
</div>style: no braces around single-line expressions<br>
<div class=""><br>
>          curCost       += curCostSig;<br>
><br>
>          if (curCost < bestCodedCost)<br>
> diff -r d303b4d860e9 -r 37e03dcd2e4f source/Lib/TLibCommon/TComTrQuant.h<br>
> --- a/source/Lib/TLibCommon/TComTrQuant.h     Mon Jul 21 22:43:38 2014 -0500<br>
> +++ b/source/Lib/TLibCommon/TComTrQuant.h     Tue Jul 22 17:59:09 2014 +0530<br>
> @@ -120,8 +120,18 @@<br>
>      // initialize class<br>
>      void init(bool useRDOQ);<br>
><br>
> +    void setPsyRdoqScale(double scale)<br>
> +    {<br>
> +        m_psyRdoqScale = scale;<br>
> +    }<br>
> +<br>
> +    inline bool psyRdoqEnabled() const<br>
> +    {<br>
> +        return m_psyRdoqScale != 0;<br>
> +    }<br>
<br>
</div>Don't use access methods for an internal member variable; I intend to<br>
remove the similar methods from RDCost. It may be faster to keep a bool<br>
for whether psy-rdoq is enabled, instead of a double comparison<br>
<div class=""><br>
> +<br>
>      // transform & inverse transform functions<br>
> -    uint32_t transformNxN(TComDataCU* cu, int16_t* residual, uint32_t stride, coeff_t* coeff, uint32_t log2TrSize,<br>
> +    uint32_t transformNxN(TComDataCU* cu, pixel* fenc, uint32_t fencStride, int16_t* residual, uint32_t stride, coeff_t* coeff, uint32_t log2TrSize,<br>
>                            TextType ttype, uint32_t absPartIdx, bool useTransformSkip = false, bool curUseRDOQ = true);<br>
><br>
>      void invtransformNxN(bool transQuantBypass, int16_t* residual, uint32_t stride, coeff_t* coeff, uint32_t log2TrSize, TextType ttype, bool bIntra, bool useTransformSkip, uint32_t numSig);<br>
> @@ -207,7 +217,11 @@<br>
>      bool     m_useRDOQ;<br>
>      bool     m_scalingListEnabledFlag;<br>
><br>
> -    int32_t* m_tmpCoeff;<br>
> +    double   m_psyRdoqScale;<br>
> +    int32_t* m_tmpCoeff; // tmp buffer which stores the dct of residual<br>
> +    int32_t  m_tmpfencCoeff[MAX_CU_SIZE * MAX_CU_SIZE]; // tmp buffer which stores the dct of orig pix buffer<br>
> +    int16_t m_tmpfencBuf[MAX_CU_SIZE * MAX_CU_SIZE]; // tmp buffer which stores short of orig pixel<br>
<br>
</div>These buffers should have better names so they don't require trailing<br>
comments, and use MAX_TS_SIZE.<br>
<br>
coeff_t m_resiDctCoeff[MAX_TS_SIZE * MAX_TS_SIZE];<br>
coeff_t m_fencDctCoeff[MAX_TS_SIZE * MAX_TS_SIZE];<br>
int16_t m_fencShortBuf[MAX_TS_SIZE * MAX_TS_SIZE];<br>
<div class=""><br>
>      int32_t* m_quantCoef[ScalingList::NUM_SIZES][ScalingList::NUM_LISTS][ScalingList::NUM_REM];     ///< array of quantization matrix coefficient 4x4<br>
>      int32_t* m_dequantCoef[ScalingList::NUM_SIZES][ScalingList::NUM_LISTS][ScalingList::NUM_REM];   ///< array of dequantization matrix coefficient 4x4<br>
><br>
> @@ -221,11 +235,11 @@<br>
>      uint32_t xQuant(TComDataCU* cu, int32_t* src, coeff_t* dst, uint32_t log2TrSize, TextType ttype, uint32_t absPartIdx);<br>
><br>
>      // RDOQ functions<br>
> -    uint32_t xRateDistOptQuant(TComDataCU* cu, int32_t* srcCoeff, coeff_t* dstCoeff, uint32_t log2TrSize, TextType ttype, uint32_t absPartIdx);<br>
> +    uint32_t xRateDistOptQuant(TComDataCU* cu, int32_t* fencCoeff, int32_t* srcCoeff, coeff_t* dstCoeff, uint32_t log2TrSize, TextType ttype, uint32_t absPartIdx);<br>
><br>
>      inline uint32_t xGetCodedLevel(double& codedCost, const double curCostSig, double& codedCostSig, int levelDouble,<br>
>                                     uint32_t maxAbsLevel, uint32_t baseLevel, const int *greaterOneBits, const int *levelAbsBits, uint32_t absGoRice,<br>
> -                                   uint32_t c1c2Idx, int qbits, double scale, bool bLast) const;<br>
> +                                   uint32_t c1c2Idx, int qbits, double scale, bool bLast, int sign_coef, int orig_coef) const;<br>
><br>
>      inline double xGetICRateCost(uint32_t absLevel, int32_t  diffLevel, const int *greaterOneBits, const int *levelAbsBits, uint32_t absGoRice, uint32_t c1c2Idx) const;<br>
><br>
> diff -r d303b4d860e9 -r 37e03dcd2e4f source/Lib/TLibEncoder/TEncSearch.cpp<br>
> --- a/source/Lib/TLibEncoder/TEncSearch.cpp   Mon Jul 21 22:43:38 2014 -0500<br>
> +++ b/source/Lib/TLibEncoder/TEncSearch.cpp   Tue Jul 22 17:59:09 2014 +0530<br>
> @@ -438,7 +438,7 @@<br>
<br>
</div><snip TEncSearch diffs><br>
<div class=""><br>
> diff -r d303b4d860e9 -r 37e03dcd2e4f source/common/param.cpp<br>
> --- a/source/common/param.cpp Mon Jul 21 22:43:38 2014 -0500<br>
> +++ b/source/common/param.cpp Tue Jul 22 17:59:09 2014 +0530<br>
> @@ -163,6 +163,7 @@<br>
>      param->crQpOffset = 0;<br>
>      param->rdPenalty = 0;<br>
>      param->psyRd = 0.0;<br>
> +    param->psyRdoq = 0.5;<br>
<br>
</div>The patch which is pushed should have the default be 0.0 - enabing the<br>
psycho-visual optimations by default should be a seperate patch<br>
<div class=""><br>
>      param->bIntraInBFrames = 1;<br>
>      param->bLossless = 0;<br>
>      param->bCULossless = 0;<br>
> @@ -413,11 +414,13 @@<br>
>          {<br>
>              param->rc.aqStrength = 0.0;<br>
>              param->psyRd = 0.0;<br>
> +            param->psyRdoq = 0.0;<br>
>          }<br>
>          else if (!strcmp(tune, "ssim"))<br>
>          {<br>
>              param->rc.aqMode = X265_AQ_AUTO_VARIANCE;<br>
>              param->psyRd = 0.0;<br>
> +            param->psyRdoq = 0.0;<br>
>          }<br>
>          else if (!strcmp(tune, "fastdecode") ||<br>
>                   !strcmp(tune, "fast-decode"))<br>
<br>
</div>later in this file are warnings that are emitted if psy-rd is enabled<br>
and SSIM or PSNR are being reported. those checks need to include<br>
psy-rdoq<br>
<br>
also, the psy-rdoq scale factor must be logged, if it is enabled.<br>
<div class=""><br>
> diff -r d303b4d860e9 -r 37e03dcd2e4f source/encoder/analysis.cpp<br>
> --- a/source/encoder/analysis.cpp     Mon Jul 21 22:43:38 2014 -0500<br>
> +++ b/source/encoder/analysis.cpp     Tue Jul 22 17:59:09 2014 +0530<br>
> @@ -49,6 +49,7 @@<br>
>  {<br>
>      m_param = top->m_param;<br>
>      m_trQuant.init(top->m_bEnableRDOQ);<br>
> +    m_trQuant.setPsyRdoqScale(top->m_param->psyRdoq);<br>
<br>
</div>nit: drop top-><br>
<div><div class="h5"><br>
>      if (!top->m_scalingList.m_bEnabled)<br>
>      {<br>
> @@ -1874,7 +1875,7 @@<br>
>              primitives.chroma[m_param->internalCsp].sub_ps[part](dst, dststride, src1, src2, src1stride, src2stride);<br>
><br>
>              // Residual encoding<br>
> -            residualTransformQuantInter(cu, 0, m_tmpResiYuv[depth], cu->getDepth(0), true);<br>
> +            residualTransformQuantInter(cu, 0, m_origYuv[0], m_tmpResiYuv[depth], cu->getDepth(0), true);<br>
>              checkDQP(cu);<br>
><br>
>              if (lcu->getMergeFlag(absPartIdx) && cu->getPartitionSize(0) == SIZE_2Nx2N && !cu->getQtRootCbf(0))<br>
> diff -r d303b4d860e9 -r 37e03dcd2e4f source/encoder/encoder.cpp<br>
> --- a/source/encoder/encoder.cpp      Mon Jul 21 22:43:38 2014 -0500<br>
> +++ b/source/encoder/encoder.cpp      Tue Jul 22 17:59:09 2014 +0530<br>
> @@ -1296,8 +1296,17 @@<br>
>          p->crQpOffset += 6;<br>
>      }<br>
><br>
> -    // disable RDOQ if psy-rd is enabled; until we make it psy-aware<br>
> -    m_bEnableRDOQ = p->psyRd == 0.0 && p->rdLevel >= 4;<br>
> +    // disable RDOQ when rdlevel < 4<br>
> +    // disable RDOQ when psyrd is enabled and psyrdoq is disabled<br>
> +    if (p->rdLevel >= 4)<br>
> +    {<br>
> +        if (p->psyRd && !p->psyRdoq)<br>
> +            m_bEnableRDOQ = 0;<br>
> +        else<br>
> +            m_bEnableRDOQ = 1;<br>
> +    }<br>
> +    else<br>
> +        m_bEnableRDOQ = 0;<br>
<br>
</div></div>conciseness is a virtue:<br>
<br>
    // disable RDOQ if rdlevel < 4 or if psy-rd is enabled without psy-rdoq<br>
    m_bEnableRDOQ = p->rdLevel >= 4 ? (p->psyRdoq || !p->psyRd) : 0;<br>
<div class=""><br>
>      if (p->bLossless)<br>
>      {<br>
> diff -r d303b4d860e9 -r 37e03dcd2e4f source/x265.h<br>
> --- a/source/x265.h   Mon Jul 21 22:43:38 2014 -0500<br>
> +++ b/source/x265.h   Tue Jul 22 17:59:09 2014 +0530<br>
> @@ -613,6 +613,10 @@<br>
>       * energy of the source, at the cost of lost compression. Default 0.0 */<br>
>      double    psyRd;<br>
><br>
> +    /* Psycho-visual rate-distortion opt quantize strength. Only has an effect in presets<br>
> +    * which use RDOQ. Default 0.0 */<br>
<br>
</div>white-space<br>
<br>
> +    double    psyRdoq;<br>
<br>
And of course, the final patch must bump X265_BUILD, add the CLI option and<br>
param_parse support, and update doc/reST/cli.txt<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Steve Borho<br>
</font></span><div class="HOEnZb"><div class="h5">_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</div></div></blockquote></div><br></div></div></div>