[x265] [PATCH] noise reduction, ported from x264

Steve Borho steve at borho.org
Wed May 7 21:53:18 CEST 2014


On Wed, May 7, 2014 at 8:24 AM,  <praveen at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Praveen Tiwari
> # Date 1399469049 -19800
> # Node ID a81311047a4d3176d16c07a0ca01be931141ab24
> # Parent  7773ee321539810625636bb0a163004225040707
> noise reduction, ported from x264
>
> diff -r 7773ee321539 -r a81311047a4d doc/reST/cli.rst
> --- a/doc/reST/cli.rst  Wed May 07 10:49:02 2014 +0530
> +++ b/doc/reST/cli.rst  Wed May 07 18:54:09 2014 +0530
> @@ -182,6 +182,14 @@
>         picture. Only applicable when the input bit depth is larger than
>         8bits and internal bit depth is 8bits. Default disabled
>
> +.. option:: --nr
> +
> +    It's just an adaptive deadzone applied after DCT (subtracting from DCT coefficients),
> +    before quantization, on inter blocks. It does no pixel-level filtering, doesn't cross
> +    DCT block boundaries, has no overlap, doesn't affect intra blocks.
> +
> +    **Values:** any value in range of 100 to 1000. Default disabled.
> +
>         **CLI ONLY**

this option isn't CLI only but the option above was (you've stolen
this line from its description)

>
>  .. option:: --input-res <wxh>
> diff -r 7773ee321539 -r a81311047a4d source/Lib/TLibCommon/TComRom.cpp
> --- a/source/Lib/TLibCommon/TComRom.cpp Wed May 07 10:49:02 2014 +0530
> +++ b/source/Lib/TLibCommon/TComRom.cpp Wed May 07 18:54:09 2014 +0530
> @@ -590,5 +590,38 @@
>      106,  110,  114,  118,  122,  126,  130,  135,  139,  143,  147,  152,  156,  161,  165,  170,
>      175,  179,  184,  189,  194,  198,  203,  208,  214,  219,  224,  229,  234,  240,  245,  250
>  };
> +
> +/* inverse squared */
> +#define W(i) (i == 0 ? FIX8(3.125) : \
> +              i == 1 ? FIX8(1.25) : \
> +              i == 2 ? FIX8(0.5) : 0)
> +
> +const uint32_t g_dctDenoiseWeight4x4[16] = {
> +    W(0), W(1), W(0), W(1),
> +    W(1), W(2), W(1), W(2),
> +    W(0), W(1), W(0), W(1),
> +    W(1), W(2), W(1), W(2)
> +};
> +#undef W
> +
> +#define W(i) (i == 0 ? FIX8(1.00000) : \
> +              i == 1 ? FIX8(0.78487) : \
> +              i == 2 ? FIX8(2.56132) : \
> +              i == 3 ? FIX8(0.88637) : \
> +              i == 4 ? FIX8(1.60040) : \
> +              i == 5 ? FIX8(1.41850) : 0)
> +
> +const uint32_t g_dctDenoiseWeight8x8[64] = {
> +    W(0), W(3), W(4), W(3),  W(0), W(3), W(4), W(3),
> +    W(3), W(1), W(5), W(1),  W(3), W(1), W(5), W(1),
> +    W(4), W(5), W(2), W(5),  W(4), W(5), W(2), W(5),
> +    W(3), W(1), W(5), W(1),  W(3), W(1), W(5), W(1),
> +
> +    W(0), W(3), W(4), W(3),  W(0), W(3), W(4), W(3),
> +    W(3), W(1), W(5), W(1),  W(3), W(1), W(5), W(1),
> +    W(4), W(5), W(2), W(5),  W(4), W(5), W(2), W(5),
> +    W(3), W(1), W(5), W(1),  W(3), W(1), W(5), W(1)
> +};
> +#undef W
>  }
>  //! \}
> diff -r 7773ee321539 -r a81311047a4d source/Lib/TLibCommon/TComRom.h
> --- a/source/Lib/TLibCommon/TComRom.h   Wed May 07 10:49:02 2014 +0530
> +++ b/source/Lib/TLibCommon/TComRom.h   Wed May 07 18:54:09 2014 +0530
> @@ -200,6 +200,9 @@
>  #define MAX_MATRIX_COEF_NUM 64     ///< max coefficient number for quantization matrix
>  #define MAX_MATRIX_SIZE_NUM 8      ///< max size number for quantization matrix
>  #define SCALING_LIST_DC 16         ///< default DC value
> +
> +#define FIX8(f) ((int)(f * (1 << 8) + .5))
> +
>  enum ScalingListSize
>  {
>      SCALING_LIST_4x4 = 0,
> @@ -278,6 +281,10 @@
>  // CABAC tables
>  extern const uint8_t g_lpsTable[64][4];
>  extern const uint8_t x265_exp2_lut[64];
> +
> +// DCT denoise tables
> +extern const uint32_t g_dctDenoiseWeight4x4[16];
> +extern const uint32_t g_dctDenoiseWeight8x8[64];
>  }
>
>  #endif  //ifndef X265_TCOMROM_H
> diff -r 7773ee321539 -r a81311047a4d source/Lib/TLibCommon/TComTrQuant.cpp
> --- a/source/Lib/TLibCommon/TComTrQuant.cpp     Wed May 07 10:49:02 2014 +0530
> +++ b/source/Lib/TLibCommon/TComTrQuant.cpp     Wed May 07 18:54:09 2014 +0530
> @@ -95,6 +95,19 @@
>      destroyScalingList();
>  }
>
> +static void denoiseDct(coeff_t* dctCoef, uint32_t* resSum, uint16_t* offset, int size)
> +{
> +    for (int i = 0; i < size; i++)
> +    {
> +        int level = dctCoef[i];
> +        int sign = level >> 31;
> +        level = (level + sign) ^ sign;
> +        resSum[i] += level;
> +        level -= offset[i];
> +        dctCoef[i] = level < 0 ? 0 : (level ^ sign) - sign;
> +    }
> +}
> +
>  /** Set qP for Quantization.
>   * \param qpy QPy
>   * \param bLowpass
> @@ -300,16 +313,17 @@
>      m_useTransformSkipFast = useTransformSkipFast;
>  }
>
> -uint32_t TComTrQuant::transformNxN(TComDataCU* cu,
> -                                   int16_t*    residual,
> -                                   uint32_t    stride,
> -                                   coeff_t*    coeff,
> -                                   uint32_t    trSize,
> -                                   TextType    ttype,
> -                                   uint32_t    absPartIdx,
> -                                   int32_t*    lastPos,
> -                                   bool        useTransformSkip,
> -                                   bool        curUseRDOQ)
> +uint32_t TComTrQuant::transformNxN(TComDataCU*     cu,
> +                                   int16_t*        residual,
> +                                   uint32_t        stride,
> +                                   coeff_t*        coeff,
> +                                   uint32_t        trSize,
> +                                   TextType        ttype,
> +                                   uint32_t        absPartIdx,
> +                                   int32_t*        lastPos,
> +                                   NoiseReduction* nr,
> +                                   bool            useTransformSkip,
> +                                   bool            curUseRDOQ)
>  {
>      if (cu->getCUTransquantBypass(absPartIdx))
>      {
> @@ -346,6 +360,30 @@
>          // TODO: this may need larger data types for X265_DEPTH > 8
>          const uint32_t log2BlockSize = g_convertToBit[trSize];
>          primitives.dct[DCT_4x4 + log2BlockSize - ((trSize == 4) && (mode != REG_DCT))](residual, m_tmpCoeff, stride);
> +        if (nr->bNoiseReduction)
> +        {
> +            int index = (DCT_4x4 + log2BlockSize - ((trSize == 4) && (mode != REG_DCT)));
> +            if (index == 1 || index == 4)
> +            {
> +                for (int count = 0; count < (index * index * index); count++)
> +                {
> +                    denoiseDct(m_tmpCoeff + (count * 16), nr->residualSum[0], nr->offset[0], 16);
> +                }
> +            }
> +            else if (index == 2)
> +            {
> +                nr->count[1] += 1 * 8;
> +                denoiseDct(m_tmpCoeff, nr->residualSum[1], nr->offset[1], 64);
> +            }
> +            else if (index == 3)
> +            {
> +                for (int count = 0; count < (X265_CSP_I444 ? 8 : 16); count++)
> +                {
> +                    nr->count[0] += 1 * 4;
> +                    denoiseDct(m_tmpCoeff + (count * 16), nr->residualSum[0], nr->offset[0], 16);
> +                }
> +            }
> +        }
>      }
>      return xQuant(cu, m_tmpCoeff, coeff, trSize, ttype, absPartIdx, lastPos, curUseRDOQ);
>  }
> diff -r 7773ee321539 -r a81311047a4d source/Lib/TLibCommon/TComTrQuant.h
> --- a/source/Lib/TLibCommon/TComTrQuant.h       Wed May 07 10:49:02 2014 +0530
> +++ b/source/Lib/TLibCommon/TComTrQuant.h       Wed May 07 18:54:09 2014 +0530
> @@ -128,7 +128,7 @@
>
>      // transform & inverse transform functions
>      uint32_t transformNxN(TComDataCU* cu, int16_t* residual, uint32_t stride, coeff_t* coeff, uint32_t trSize,
> -                          TextType ttype, uint32_t absPartIdx, int32_t* lastPos, bool useTransformSkip = false, bool curUseRDOQ = true);
> +                          TextType ttype, uint32_t absPartIdx, int32_t* lastPos, NoiseReduction* nr, bool useTransformSkip = false, bool curUseRDOQ = true);
>
>      void invtransformNxN(bool transQuantBypass, uint32_t mode, int16_t* residual, uint32_t stride, coeff_t* coeff, uint32_t trSize, int scalingListType, bool useTransformSkip = false, int lastPos = MAX_INT);
>
> diff -r 7773ee321539 -r a81311047a4d source/Lib/TLibEncoder/TEncSearch.cpp
> --- a/source/Lib/TLibEncoder/TEncSearch.cpp     Wed May 07 10:49:02 2014 +0530
> +++ b/source/Lib/TLibEncoder/TEncSearch.cpp     Wed May 07 18:54:09 2014 +0530

clang triggers a really ugly looking warning for this file:

/Users/steve/repos/x265/source/Lib/TLibEncoder/TEncSearch.cpp:1495:118:
warning: initialization of pointer of type 'NoiseReduction *' to null
from a constant boolean expression [-Wbool-conversion]

  ...= m_trQuant->transformNxN(cu, residual, stride, coeff, width,
ttype, absTUPartIdxC, &lastPos, useTransformSkipChroma);

Please look into this.  It certainly smells like a bug

> @@ -456,7 +456,7 @@
>      m_trQuant->setQPforQuant(cu->getQP(0), TEXT_LUMA, QP_BD_OFFSET, 0, chFmt);
>      m_trQuant->selectLambda(TEXT_LUMA);
>
> -    absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, TEXT_LUMA, absPartIdx, &lastPos, useTransformSkip);
> +    absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, TEXT_LUMA, absPartIdx, &lastPos, &(m_cfg->m_nr), useTransformSkip);
>
>      //--- set coded block flag ---
>      cu->setCbfSubParts((absSum ? 1 : 0) << trDepth, TEXT_LUMA, absPartIdx, fullDepth);
> @@ -581,7 +581,7 @@
>
>          m_trQuant->selectLambda(TEXT_CHROMA);
>
> -        absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, ttype, absPartIdx, &lastPos, useTransformSkipChroma);
> +        absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, ttype, absPartIdx, &lastPos, &(m_cfg->m_nr), useTransformSkipChroma);
>
>          //--- set coded block flag ---
>          cu->setCbfPartRange((((absSum > 0) ? 1 : 0) << origTrDepth), ttype, absPartIdx, absPartIdxStep);
> @@ -896,7 +896,7 @@
>
>          m_trQuant->setQPforQuant(cu->getQP(0), TEXT_LUMA, QP_BD_OFFSET, 0, chFmt);
>          m_trQuant->selectLambda(TEXT_LUMA);
> -        absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, TEXT_LUMA, absPartIdx, &lastPos, useTransformSkip);
> +        absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, TEXT_LUMA, absPartIdx, &lastPos, &(m_cfg->m_nr), useTransformSkip);
>
>          //--- set coded block flag ---
>          cu->setCbfSubParts((absSum ? 1 : 0) << trDepth, TEXT_LUMA, absPartIdx, fullDepth);
> @@ -2890,7 +2890,7 @@
>          m_trQuant->selectLambda(TEXT_LUMA);
>
>          absSumY = m_trQuant->transformNxN(cu, resiYuv->getLumaAddr(absTUPartIdx), resiYuv->m_width, coeffCurY,
> -                                          trWidth, TEXT_LUMA, absPartIdx, &lastPosY, false, curuseRDOQ);
> +                                          trWidth, TEXT_LUMA, absPartIdx, &lastPosY, &(m_cfg->m_nr), false, curuseRDOQ);
>
>          cu->setCbfSubParts(absSumY ? setCbf : 0, TEXT_LUMA, absPartIdx, depth);
>
> @@ -2934,12 +2934,12 @@
>                  m_trQuant->selectLambda(TEXT_CHROMA);
>
>                  absSumU = m_trQuant->transformNxN(cu, resiYuv->getCbAddr(absTUPartIdxC), resiYuv->m_cwidth, coeffCurU + subTUBufferOffset,
> -                                                  trWidthC, TEXT_CHROMA_U, absTUPartIdxC, &lastPosU, false, curuseRDOQ);
> +                                                  trWidthC, TEXT_CHROMA_U, absTUPartIdxC, &lastPosU, &(m_cfg->m_nr), false, curuseRDOQ);
>
>                  curChromaQpOffset = cu->getSlice()->getPPS()->getChromaCrQpOffset() + cu->getSlice()->getSliceQpDeltaCr();
>                  m_trQuant->setQPforQuant(cu->getQP(0), TEXT_CHROMA, cu->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset, chFmt);
>                  absSumV = m_trQuant->transformNxN(cu, resiYuv->getCrAddr(absTUPartIdxC), resiYuv->m_cwidth, coeffCurV + subTUBufferOffset,
> -                                                  trWidthC, TEXT_CHROMA_V, absTUPartIdxC, &lastPosV, false, curuseRDOQ);
> +                                                  trWidthC, TEXT_CHROMA_V, absTUPartIdxC, &lastPosV, &(m_cfg->m_nr), false, curuseRDOQ);
>
>                  cu->setCbfPartRange(absSumU ? setCbf : 0, TEXT_CHROMA_U, absTUPartIdxC, tuIterator.m_absPartIdxStep);
>                  cu->setCbfPartRange(absSumV ? setCbf : 0, TEXT_CHROMA_V, absTUPartIdxC, tuIterator.m_absPartIdxStep);
> @@ -3107,7 +3107,7 @@
>          m_trQuant->selectLambda(TEXT_LUMA);
>
>          absSum[TEXT_LUMA][0] = m_trQuant->transformNxN(cu, resiYuv->getLumaAddr(absTUPartIdx), resiYuv->m_width, coeffCurY,
> -                                                       trWidth, TEXT_LUMA, absPartIdx, &lastPos[TEXT_LUMA][0], false, curuseRDOQ);
> +                                                       trWidth, TEXT_LUMA, absPartIdx, &lastPos[TEXT_LUMA][0], &(m_cfg->m_nr), false, curuseRDOQ);
>
>          cu->setCbfSubParts(absSum[TEXT_LUMA][0] ? setCbf : 0, TEXT_LUMA, absPartIdx, depth);
>
> @@ -3144,12 +3144,12 @@
>                  m_trQuant->selectLambda(TEXT_CHROMA);
>
>                  absSum[TEXT_CHROMA_U][tuIterator.m_section] = m_trQuant->transformNxN(cu, resiYuv->getCbAddr(tuIterator.m_absPartIdxTURelCU), resiYuv->m_cwidth, coeffCurU + subTUBufferOffset,
> -                                                                                      widthC, TEXT_CHROMA_U, tuIterator.m_absPartIdxTURelCU, &lastPos[TEXT_CHROMA_U][tuIterator.m_section], false, curuseRDOQ);
> +                                                                                      widthC, TEXT_CHROMA_U, tuIterator.m_absPartIdxTURelCU, &lastPos[TEXT_CHROMA_U][tuIterator.m_section], &(m_cfg->m_nr), false, curuseRDOQ);
>                  //Cr transform
>                  curChromaQpOffset = cu->getSlice()->getPPS()->getChromaCrQpOffset() + cu->getSlice()->getSliceQpDeltaCr();
>                  m_trQuant->setQPforQuant(cu->getQP(0), TEXT_CHROMA, cu->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset, chFmt);
>                  absSum[TEXT_CHROMA_V][tuIterator.m_section] = m_trQuant->transformNxN(cu, resiYuv->getCrAddr(tuIterator.m_absPartIdxTURelCU), resiYuv->m_cwidth, coeffCurV + subTUBufferOffset,
> -                                                                                      widthC, TEXT_CHROMA_V, tuIterator.m_absPartIdxTURelCU, &lastPos[TEXT_CHROMA_V][tuIterator.m_section], false, curuseRDOQ);
> +                                                                                      widthC, TEXT_CHROMA_V, tuIterator.m_absPartIdxTURelCU, &lastPos[TEXT_CHROMA_V][tuIterator.m_section], &(m_cfg->m_nr), false, curuseRDOQ);
>
>                  cu->setCbfPartRange(absSum[TEXT_CHROMA_U][tuIterator.m_section] ? setCbf : 0, TEXT_CHROMA_U, tuIterator.m_absPartIdxTURelCU, tuIterator.m_absPartIdxStep);
>                  cu->setCbfPartRange(absSum[TEXT_CHROMA_V][tuIterator.m_section] ? setCbf : 0, TEXT_CHROMA_V, tuIterator.m_absPartIdxTURelCU, tuIterator.m_absPartIdxStep);
> @@ -3440,7 +3440,7 @@
>
>              m_trQuant->selectLambda(TEXT_LUMA);
>              absSumTransformSkipY = m_trQuant->transformNxN(cu, resiYuv->getLumaAddr(absTUPartIdx), resiYuv->m_width, coeffCurY,
> -                                                           trWidth, TEXT_LUMA, absPartIdx, &lastPosTransformSkip[TEXT_LUMA][0], true, curuseRDOQ);
> +                                                           trWidth, TEXT_LUMA, absPartIdx, &lastPosTransformSkip[TEXT_LUMA][0], &(m_cfg->m_nr), true, curuseRDOQ);
>              cu->setCbfSubParts(absSumTransformSkipY ? setCbf : 0, TEXT_LUMA, absPartIdx, depth);
>
>              if (absSumTransformSkipY != 0)
> @@ -3533,11 +3533,11 @@
>                  m_trQuant->selectLambda(TEXT_CHROMA);
>
>                  absSumTransformSkipU = m_trQuant->transformNxN(cu, resiYuv->getCbAddr(tuIterator.m_absPartIdxTURelCU), resiYuv->m_cwidth, coeffCurU + subTUBufferOffset,
> -                                                               widthC, TEXT_CHROMA_U, tuIterator.m_absPartIdxTURelCU, &lastPosTransformSkip[TEXT_CHROMA_U][tuIterator.m_section], true, curuseRDOQ);
> +                                                               widthC, TEXT_CHROMA_U, tuIterator.m_absPartIdxTURelCU, &lastPosTransformSkip[TEXT_CHROMA_U][tuIterator.m_section], &(m_cfg->m_nr), true, curuseRDOQ);
>                  curChromaQpOffset = cu->getSlice()->getPPS()->getChromaCrQpOffset() + cu->getSlice()->getSliceQpDeltaCr();
>                  m_trQuant->setQPforQuant(cu->getQP(0), TEXT_CHROMA, cu->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset, chFmt);
>                  absSumTransformSkipV = m_trQuant->transformNxN(cu, resiYuv->getCrAddr(tuIterator.m_absPartIdxTURelCU), resiYuv->m_cwidth, coeffCurV + subTUBufferOffset,
> -                                                               widthC, TEXT_CHROMA_V, tuIterator.m_absPartIdxTURelCU, &lastPosTransformSkip[TEXT_CHROMA_V][tuIterator.m_section], true, curuseRDOQ);
> +                                                               widthC, TEXT_CHROMA_V, tuIterator.m_absPartIdxTURelCU, &lastPosTransformSkip[TEXT_CHROMA_V][tuIterator.m_section], &(m_cfg->m_nr), true, curuseRDOQ);
>
>                  cu->setCbfPartRange(absSumTransformSkipU ? setCbf : 0, TEXT_CHROMA_U, tuIterator.m_absPartIdxTURelCU, tuIterator.m_absPartIdxStep);
>                  cu->setCbfPartRange(absSumTransformSkipV ? setCbf : 0, TEXT_CHROMA_V, tuIterator.m_absPartIdxTURelCU, tuIterator.m_absPartIdxStep);
> diff -r 7773ee321539 -r a81311047a4d source/common/common.h
> --- a/source/common/common.h    Wed May 07 10:49:02 2014 +0530
> +++ b/source/common/common.h    Wed May 07 18:54:09 2014 +0530
> @@ -166,6 +166,20 @@
>  #define X265_LOG2(x)  log2(x)
>  #endif
>
> +struct NoiseReduction
> +{
> +    bool bNoiseReduction;
> +
> +    /* 0 = luma 4x4, 1 = luma 8x8, 2 = chroma 4x4, 3 = chroma 8x8 */
> +    uint16_t (*offset)[64];
> +    uint32_t (*residualSum)[64];
> +    uint32_t *count;
> +
> +    uint16_t offsetDenoise[4][64];
> +    uint32_t residualSumBuf[2][4][64];
> +    uint32_t countBuf[2][4];
> +};
> +
>  /* defined in common.cpp */
>  int64_t x265_mdate(void);
>  void x265_log(const x265_param *param, int level, const char *fmt, ...);
> diff -r 7773ee321539 -r a81311047a4d source/common/param.cpp
> --- a/source/common/param.cpp   Wed May 07 10:49:02 2014 +0530
> +++ b/source/common/param.cpp   Wed May 07 18:54:09 2014 +0530
> @@ -688,6 +688,7 @@
>                           &p->vui.defDispWinRightOffset,
>                           &p->vui.defDispWinBottomOffset) != 4;
>      }
> +    OPT("nr") p->noiseReduction = atoi(value);
>      else
>          return X265_PARAM_BAD_NAME;
>  #undef OPT
> @@ -980,6 +981,8 @@
>      CHECK(param->rc.bitrate < 0,
>            "Target bitrate can not be less than zero");
>      CHECK(param->bFrameBias < 0, "Bias towards B frame decisions must be 0 or greater");
> +    if (param->noiseReduction)
> +        CHECK(100 > param->noiseReduction || param->noiseReduction > 1000, "Valid noise reduction range 100 - 1000");
>      return check_failed;
>  }
>
> diff -r 7773ee321539 -r a81311047a4d source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp        Wed May 07 10:49:02 2014 +0530
> +++ b/source/encoder/encoder.cpp        Wed May 07 18:54:09 2014 +0530
> @@ -72,6 +72,14 @@
>      m_csvfpt = NULL;
>      param = NULL;
>
> +    memset(m_nr.offsetDenoise, 0, sizeof(m_nr.offsetDenoise[0][0]) * 4 * 64);
> +    memset(m_nr.residualSumBuf, 0, sizeof(m_nr.residualSumBuf[0][0][0]) * 2 * 4 * 64);
> +    memset(m_nr.countBuf, 0, sizeof(m_nr.countBuf[0][0]) * 2 * 4);
> +
> +    m_nr.offset = m_nr.offsetDenoise;
> +    m_nr.residualSum = m_nr.residualSumBuf[0];
> +    m_nr.count = m_nr.countBuf[0];
> +
>  #if ENC_DEC_TRACE
>      g_hTrace = fopen("TraceEnc.txt", "wb");
>      g_bJustDoIt = g_bEncDecTraceDisable;
> @@ -194,6 +202,7 @@
>      }
>      m_lookahead->init();
>      m_encodeStartTime = x265_mdate();
> +    m_nr.bNoiseReduction = !!param->noiseReduction;
>  }
>
>  int Encoder::getStreamHeaders(NALUnitEBSP **nalunits)
> @@ -226,6 +235,42 @@
>      }
>  }
>
> +/****************************************************************************
> + * DCT-domain noise reduction / adaptive deadzone
> + * from libavcodec
> + ****************************************************************************/
> +
> +void Encoder::noiseReductionUpdate(NoiseReduction* h)
> +{
> +    h->offset = h->offsetDenoise;
> +    h->residualSum = h->residualSumBuf[0];
> +    h->count = h->countBuf[0];
> +
> +    int isCspI444 = (param->internalCsp == X265_CSP_I444) ? 1 : 0;
> +    for (int cat = 0; cat < 3 + isCspI444; cat++)
> +    {
> +        int dct8x8 = cat&1;
> +        int size = dct8x8 ? 64 : 16;
> +        const uint32_t* weight = dct8x8 ? g_dctDenoiseWeight4x4 : g_dctDenoiseWeight8x8;
> +
> +        if (h->count[cat] > (dct8x8 ? (1 << 16) : (1 << 18)))
> +        {
> +            for (int i = 0; i < size; i++)
> +                h->residualSum[cat][i] >>= 1;
> +            h->count[cat] >>= 1;
> +        }
> +
> +        for (int i = 0; i < size; i++)
> +            h->offset[cat][i] =
> +                ((uint64_t)param->noiseReduction * h->count[cat]
> +                 + h->residualSum[cat][i] / 2)
> +              / ((uint64_t)h->residualSum[cat][i] * weight[i] / 256 + 1);
> +
> +        // Don't denoise DC coefficients
> +        h->offset[cat][0] = 0;
> +    }
> +}
> +
>  #define VERBOSE_RATE 0
>  #if VERBOSE_RATE
>  static const char* nalUnitTypeToString(NalUnitType type)
> @@ -442,6 +487,9 @@
>          m_rateControl->rateControlEnd(out, bits, &curEncoder->m_rce);
>          finishFrameStats(out, curEncoder, bits);
>
> +        if (m_nr.bNoiseReduction)
> +            noiseReductionUpdate(&m_nr);
> +
>          // Allow this frame to be recycled if no frame encoders are using it for reference
>          ATOMIC_DEC(&out->m_countRefEncoders);
>          m_dpb->recycleUnreferenced(m_freeList);
> diff -r 7773ee321539 -r a81311047a4d source/encoder/encoder.h
> --- a/source/encoder/encoder.h  Wed May 07 10:49:02 2014 +0530
> +++ b/source/encoder/encoder.h  Wed May 07 18:54:09 2014 +0530
> @@ -195,6 +195,8 @@
>      x265_nal*          m_nals;
>      char*              m_packetData;
>
> +    NoiseReduction     m_nr;
> +
>      Encoder();
>
>      virtual ~Encoder();
> @@ -228,6 +230,8 @@
>
>      void updateVbvPlan(RateControl* rc);
>
> +    void noiseReductionUpdate(NoiseReduction* nr);
> +
>  protected:
>
>      void finishFrameStats(TComPic* pic, FrameEncoder *curEncoder, uint64_t bits);
> diff -r 7773ee321539 -r a81311047a4d source/x265.cpp
> --- a/source/x265.cpp   Wed May 07 10:49:02 2014 +0530
> +++ b/source/x265.cpp   Wed May 07 18:54:09 2014 +0530
> @@ -170,6 +170,7 @@
>      { "aud",                  no_argument, NULL, 0 },
>      { "no-aud",               no_argument, NULL, 0 },
>      { "qpfile",         required_argument, NULL, 0 },
> +    { "nr",             required_argument, NULL, 0 },
>      { 0, 0, 0, 0 }
>  };
>
> @@ -404,6 +405,8 @@
>      H0("                                 Format of each line: framenumber frametype QP\n");
>      H0("                                 QP is optional (none lets x265 choose). Frametypes: I,i,P,B,b.\n");
>      H0("                                 QPs are restricted by qpmin/qpmax.\n");
> +    H0("\nNoiseReduction option:\n");
> +    H0("   --nr <integer>                An integer value in range of 100 to 1000, which denotes strength of noise reduction. Default disabled\n");
>  #undef OPT
>  #undef H0
>      printf("\n\nFull documentation may be found at http://x265.readthedocs.org/en/default/cli.html\n");
> diff -r 7773ee321539 -r a81311047a4d source/x265.h
> --- a/source/x265.h     Wed May 07 10:49:02 2014 +0530
> +++ b/source/x265.h     Wed May 07 18:54:09 2014 +0530
> @@ -635,6 +635,10 @@
>       * Default is 0, which is recommended */
>      int       crQpOffset;
>
> +    /* An integer value in range of 100 to 1000, which denotes strength of noise
> +     * reduction */
> +    int       noiseReduction;
> +
>      /*== Rate Control ==*/
>
>      struct
> _______________________________________________
> 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