[x265] [PATCH 1 of 3] optimize: rewrite TComTrQuant::xGetCodedLevel

Steve Borho steve at borho.org
Fri Mar 21 02:41:39 CET 2014


On Tue, Mar 18, 2014 at 7:34 PM, Min Chen <chenm003 at 163.com> wrote:
> # HG changeset patch
> # User Min Chen <chenm003 at 163.com>
> # Date 1395189192 25200
> # Node ID e9f08d038ff0dc17152002d2b2b70138d08465d7
> # Parent  dc700298419d382e58c49d4ea62a3d7398b4beaf
> optimize: rewrite TComTrQuant::xGetCodedLevel
>
> diff -r dc700298419d -r e9f08d038ff0 source/Lib/TLibCommon/TComTrQuant.cpp
> --- a/source/Lib/TLibCommon/TComTrQuant.cpp     Tue Mar 18 08:46:15 2014 -0500
> +++ b/source/Lib/TLibCommon/TComTrQuant.cpp     Tue Mar 18 17:33:12 2014 -0700
> @@ -630,19 +630,34 @@
>                  uint32_t level;
>                  uint32_t oneCtx = 4 * ctxSet + c1;
>                  uint32_t absCtx = ctxSet + c2;
> +                double curCostSig = 0;
>
> +                costCoeff[scanPos] = MAX_DOUBLE;
>                  if (scanPos == lastScanPos)
>                  {
> -                    level = xGetCodedLevel(costCoeff[scanPos], costCoeff0[scanPos], costSig[scanPos],
> -                                           levelDouble, maxAbsLevel, baseLevel, 0, oneCtx, absCtx, goRiceParam,
> +                    level = xGetCodedLevel(costCoeff[scanPos], curCostSig, costSig[scanPos],
> +                                           levelDouble, maxAbsLevel, baseLevel, oneCtx, absCtx, goRiceParam,
>                                             c1c2Idx, qbits, scaleFactor, 1);
>                  }
>                  else
>                  {
> -                    uint16_t ctxSig = getSigCtxInc(patternSigCtx, log2TrSize, trSize, blkPos, codingParameters);
> -                    level           = xGetCodedLevel(costCoeff[scanPos], costCoeff0[scanPos], costSig[scanPos],
> -                                                     levelDouble, maxAbsLevel, baseLevel, ctxSig, oneCtx, absCtx, goRiceParam,
> -                                                     c1c2Idx, qbits, scaleFactor, 0);
> +                    const uint32_t ctxSig = getSigCtxInc(patternSigCtx, log2TrSize, trSize, blkPos, codingParameters);
> +                    if (maxAbsLevel < 3)
> +                    {
> +                        costSig[scanPos] = xGetRateSigCoef(0, ctxSig);
> +                        costCoeff[scanPos] = costCoeff0[scanPos] + costSig[scanPos];
> +                    }
> +                    if (maxAbsLevel != 0)
> +                    {
> +                        curCostSig = xGetRateSigCoef(1, ctxSig);
> +                        level = xGetCodedLevel(costCoeff[scanPos], curCostSig, costSig[scanPos],
> +                                               levelDouble, maxAbsLevel, baseLevel, oneCtx, absCtx, goRiceParam,
> +                                               c1c2Idx, qbits, scaleFactor, 0);
> +                    }
> +                    else
> +                    {
> +                        level = 0;
> +                    }
>                      sigRateDelta[blkPos] = m_estBitsSbac->significantBits[ctxSig][1] - m_estBitsSbac->significantBits[ctxSig][0];
>                  }
>                  deltaU[blkPos] = (levelDouble - ((int)level << qbits)) >> (qbits - 8);
> @@ -1125,12 +1140,11 @@
>   * This method calculates the best quantized transform level for a given scan position.
>   */
>  inline uint32_t TComTrQuant::xGetCodedLevel(double&  codedCost,
> -                                            double&  codedCost0,
> +                                            const double curCostSig,
>                                              double&  codedCostSig,
>                                              int      levelDouble,
>                                              uint32_t maxAbsLevel,
>                                              uint32_t baseLevel,
> -                                            uint32_t ctxNumSig,
>                                              uint32_t ctxNumOne,
>                                              uint32_t ctxNumAbs,
>                                              uint32_t absGoRice,
> @@ -1139,43 +1153,45 @@
>                                              double   scaleFactor,
>                                              bool     last) const
>  {
> -    double curCostSig   = 0;
>      uint32_t   bestAbsLevel = 0;
>
> -    if (!last && maxAbsLevel < 3)
> +    if (!last && maxAbsLevel == 0)
>      {
> -        codedCostSig = xGetRateSigCoef(0, ctxNumSig);
> -        codedCost    = codedCost0 + codedCostSig;
> -        if (maxAbsLevel == 0)
> -        {
> -            return bestAbsLevel;
> -        }
> -    }
> -    else
> -    {
> -        codedCost = MAX_DOUBLE;
> +        assert(0);
>      }
>
> -    if (!last)
> -    {
> -        curCostSig = xGetRateSigCoef(1, ctxNumSig);
> -    }
> +    int32_t minAbsLevel = maxAbsLevel - 1;
> +    if (minAbsLevel < 1)
> +        minAbsLevel = 1;
>
> -    uint32_t minAbsLevel = (maxAbsLevel > 1 ? maxAbsLevel - 1 : 1);
> +    // NOTE: (A + B) ^ 2 = (A ^ 2) + 2 * A * B + (B ^ 2)
> +    assert(abs((double)levelDouble - (maxAbsLevel << qbits)) < INT_MAX);
> +    const int32_t err1 = levelDouble - (maxAbsLevel << qbits);            // A
> +          double err2 = (double)((int64_t)err1 * err1);                   // A^ 2
> +    const int64_t err3 = (int64_t)2 * err1 * ((int64_t)1 << qbits);       // 2 * A * B
> +    const int64_t err4 = ((int64_t)1 << qbits) * ((int64_t)1 << qbits);   // B ^ 2
> +    const double errInc = (err3 + err4) * scaleFactor;
> +
> +    err2 *= scaleFactor;
> +
> +    double bestCodedCost = codedCost;
> +    double bestCodedCostSig = codedCostSig;
>      for (int absLevel = maxAbsLevel; absLevel >= minAbsLevel; absLevel--)
>      {
> -        double err     = double(levelDouble  - (absLevel << qbits));
> -        double curCost = err * err * scaleFactor + xGetICRateCost(absLevel, absLevel - baseLevel, ctxNumOne, ctxNumAbs, absGoRice, c1c2Idx);
> +        assert(fabs((double)err2 - double(levelDouble  - (absLevel << qbits)) * double(levelDouble  - (absLevel << qbits)) * scaleFactor) < 1e-5);
> +        double curCost = err2 + xGetICRateCost(absLevel, absLevel - baseLevel, ctxNumOne, ctxNumAbs, absGoRice, c1c2Idx);
>          curCost       += curCostSig;
>
> -        if (curCost < codedCost)
> +        if (curCost < bestCodedCost)
>          {
>              bestAbsLevel = absLevel;
> -            codedCost    = curCost;
> -            codedCostSig = curCostSig;
> +            bestCodedCost = curCost;
> +            bestCodedCostSig = curCostSig;
>          }
> +        err2 += errInc;
>      }
> -
> +    codedCost = bestCodedCost;
> +    codedCostSig = bestCodedCostSig;
>      return bestAbsLevel;
>  }
>
> @@ -1186,7 +1202,7 @@
>   * \param absGoRice Rice parameter for coeff_abs_level_minus3
>   * \returns cost of given absolute transform level
>   */
> -inline double TComTrQuant::xGetICRateCost(uint32_t absLevel,
> +FORCEINLINE double TComTrQuant::xGetICRateCost(uint32_t absLevel,

this macro isn't defined for all compilers:

/Users/steve/repos/x265/source/Lib/TLibCommon/TComTrQuant.cpp:1204:1:
error: unknown type name 'FORCEINLINE'

>                                            int32_t  diffLevel,
>                                            uint32_t ctxNumOne,
>                                            uint32_t ctxNumAbs,
> diff -r dc700298419d -r e9f08d038ff0 source/Lib/TLibCommon/TComTrQuant.h
> --- a/source/Lib/TLibCommon/TComTrQuant.h       Tue Mar 18 08:46:15 2014 -0500
> +++ b/source/Lib/TLibCommon/TComTrQuant.h       Tue Mar 18 17:33:12 2014 -0700
> @@ -62,7 +62,7 @@
>  typedef struct
>  {
>      int significantCoeffGroupBits[NUM_SIG_CG_FLAG_CTX][2];
> -    int significantBits[NUM_SIG_FLAG_CTX][2];
> +    uint32_t significantBits[NUM_SIG_FLAG_CTX][2];
>      int lastXBits[10];
>      int lastYBits[10];
>      int greaterOneBits[NUM_ONE_FLAG_CTX][2];
> @@ -193,8 +193,8 @@
>      // RDOQ functions
>      uint32_t xRateDistOptQuant(TComDataCU* cu, int32_t* srcCoeff, TCoeff* dstCoeff, uint32_t trSize, TextType ttype, uint32_t absPartIdx, int32_t *lastPos);
>
> -    inline uint32_t xGetCodedLevel(double& codedCost, double& codedCost0, double& codedCostSig, int levelDouble,
> -                                   uint32_t maxAbsLevel, uint32_t baseLevel, uint32_t ctxNumSig, uint32_t ctxNumOne, uint32_t ctxNumAbs, uint32_t absGoRice,
> +    inline uint32_t xGetCodedLevel(double& codedCost, const double curCostSig, double& codedCostSig, int levelDouble,
> +                                   uint32_t maxAbsLevel, uint32_t baseLevel, uint32_t ctxNumOne, uint32_t ctxNumAbs, uint32_t absGoRice,
>                                     uint32_t c1c2Idx, int qbits, double scale, bool bLast) const;
>
>      inline double xGetICRateCost(uint32_t absLevel, int32_t  diffLevel, uint32_t ctxNumOne, uint32_t ctxNumAbs, uint32_t absGoRice, uint32_t c1c2Idx) const;
> @@ -205,7 +205,7 @@
>
>      inline double xGetRateSigCoeffGroup(uint16_t sigCoeffGroup, uint16_t ctxNumSig) const { return m_lambda * m_estBitsSbac->significantCoeffGroupBits[ctxNumSig][sigCoeffGroup]; }
>
> -    inline double xGetRateSigCoef(uint16_t sig, uint16_t ctxNumSig) const { return m_lambda * m_estBitsSbac->significantBits[ctxNumSig][sig]; }
> +    inline double xGetRateSigCoef(uint32_t sig, uint32_t ctxNumSig) const { return m_lambda * m_estBitsSbac->significantBits[ctxNumSig][sig]; }
>
>      inline double xGetICost(double rage) const { return m_lambda * rage; } ///< Get the cost for a specific rate
>
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel



-- 
Steve Borho


More information about the x265-devel mailing list