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

praveen at multicorewareinc.com praveen at multicorewareinc.com
Mon May 19 13:51:38 CEST 2014


# HG changeset patch
# User Praveen Tiwari
# Date 1400500268 -19800
# Node ID 58f440b7172fedf630a329d698cdfb6d9a337c49
# Parent  c78bed701db4f1b412f6d1bf661e289049b0e6e8
noise reduction, ported from x264

diff -r c78bed701db4 -r 58f440b7172f doc/reST/cli.rst
--- a/doc/reST/cli.rst	Mon May 19 00:56:18 2014 -0500
+++ b/doc/reST/cli.rst	Mon May 19 17:21:08 2014 +0530
@@ -184,6 +184,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**
 
 .. option:: --input-res <wxh>
diff -r c78bed701db4 -r 58f440b7172f source/Lib/TLibCommon/TComRom.h
--- a/source/Lib/TLibCommon/TComRom.h	Mon May 19 00:56:18 2014 -0500
+++ b/source/Lib/TLibCommon/TComRom.h	Mon May 19 17:21:08 2014 +0530
@@ -278,6 +278,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 c78bed701db4 -r 58f440b7172f source/Lib/TLibCommon/TComTrQuant.cpp
--- a/source/Lib/TLibCommon/TComTrQuant.cpp	Mon May 19 00:56:18 2014 -0500
+++ b/source/Lib/TLibCommon/TComTrQuant.cpp	Mon May 19 17:21:08 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)
+            {
+                denoiseDct(m_tmpCoeff, nr->residualSum[0], nr->offset[0], 16);
+                nr->count[0]++;
+            }
+            else if (index == 2)
+            {
+                denoiseDct(m_tmpCoeff, nr->residualSum[1], nr->offset[1], 64);
+                nr->count[1]++;
+            }
+            else if (index == 3)
+            {
+                denoiseDct(m_tmpCoeff, nr->residualSum[2], nr->offset[2], 256);
+                nr->count[2]++;
+            }
+            else if (index == 4)
+            {
+                denoiseDct(m_tmpCoeff, nr->residualSum[3], nr->offset[3], 1024);
+                nr->count[3]++;
+            }
+        }
     }
     return xQuant(cu, m_tmpCoeff, coeff, trSize, ttype, absPartIdx, lastPos, curUseRDOQ);
 }
diff -r c78bed701db4 -r 58f440b7172f source/Lib/TLibCommon/TComTrQuant.h
--- a/source/Lib/TLibCommon/TComTrQuant.h	Mon May 19 00:56:18 2014 -0500
+++ b/source/Lib/TLibCommon/TComTrQuant.h	Mon May 19 17:21:08 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 c78bed701db4 -r 58f440b7172f source/Lib/TLibEncoder/TEncSearch.cpp
--- a/source/Lib/TLibEncoder/TEncSearch.cpp	Mon May 19 00:56:18 2014 -0500
+++ b/source/Lib/TLibEncoder/TEncSearch.cpp	Mon May 19 17:21:08 2014 +0530
@@ -447,7 +447,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, tuSize, TEXT_LUMA, absPartIdx, &lastPos, useTransformSkip);
+    absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, tuSize, TEXT_LUMA, absPartIdx, &lastPos, &(m_cfg->m_nr), useTransformSkip);
 
     //--- set coded block flag ---
     cu->setCbfSubParts((absSum ? 1 : 0) << trDepth, TEXT_LUMA, absPartIdx, fullDepth);
@@ -571,7 +571,7 @@
 
         m_trQuant->selectLambda(TEXT_CHROMA);
 
-        absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, tuSize, ttype, absPartIdx, &lastPos, useTransformSkipChroma);
+        absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, tuSize, ttype, absPartIdx, &lastPos, &(m_cfg->m_nr), useTransformSkipChroma);
 
         //--- set coded block flag ---
         cu->setCbfPartRange((((absSum > 0) ? 1 : 0) << origTrDepth), ttype, absPartIdx, absPartIdxStep);
@@ -884,7 +884,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, tuSize, TEXT_LUMA, absPartIdx, &lastPos, useTransformSkip);
+        absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, tuSize, TEXT_LUMA, absPartIdx, &lastPos, &(m_cfg->m_nr), useTransformSkip);
 
         //--- set coded block flag ---
         cu->setCbfSubParts((absSum ? 1 : 0) << trDepth, TEXT_LUMA, absPartIdx, fullDepth);
@@ -1479,7 +1479,7 @@
 
                 m_trQuant->selectLambda(TEXT_CHROMA);
 
-                absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, tuSize, ttype, absTUPartIdxC, &lastPos, useTransformSkipChroma);
+                absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, tuSize, ttype, absTUPartIdxC, &lastPos, &(m_cfg->m_nr), useTransformSkipChroma);
 
                 //--- set coded block flag ---
                 cu->setCbfPartRange((((absSum > 0) ? 1 : 0) << origTrDepth), ttype, absTUPartIdxC, tuIterator.m_absPartIdxStep);
@@ -2891,7 +2891,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);
 
@@ -2935,12 +2935,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);
@@ -3108,7 +3108,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);
 
@@ -3145,12 +3145,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);
@@ -3438,7 +3438,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)
@@ -3531,11 +3531,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 c78bed701db4 -r 58f440b7172f source/common/common.h
--- a/source/common/common.h	Mon May 19 00:56:18 2014 -0500
+++ b/source/common/common.h	Mon May 19 17:21:08 2014 +0530
@@ -177,6 +177,21 @@
 #define X265_LOG2(x)  log2(x)
 #endif
 
+struct NoiseReduction
+{
+    bool bNoiseReduction;
+
+    /* 0 = luma 4x4, 1 = luma 8x8, 2 = luma 16x16, 3 = luma 32x32
+     * 4 = chroma 4x4, 5 = chroma 8x8, 6 = chroma 16x16, 7 = chroma 32x32 */
+    uint16_t (*offset)[1024];
+    uint32_t (*residualSum)[1024];
+    uint32_t *count;
+
+    uint16_t offsetDenoise[8][1024];
+    uint32_t residualSumBuf[4][8][1024];
+    uint32_t countBuf[4][8];
+};
+
 /* defined in common.cpp */
 int64_t x265_mdate(void);
 void x265_log(const x265_param *param, int level, const char *fmt, ...);
diff -r c78bed701db4 -r 58f440b7172f source/common/param.cpp
--- a/source/common/param.cpp	Mon May 19 00:56:18 2014 -0500
+++ b/source/common/param.cpp	Mon May 19 17:21:08 2014 +0530
@@ -694,6 +694,7 @@
                          &p->vui.defDispWinRightOffset,
                          &p->vui.defDispWinBottomOffset) != 4;
     }
+    OPT("nr") p->noiseReduction = atoi(value);
     else
         return X265_PARAM_BAD_NAME;
 #undef OPT
@@ -986,6 +987,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 c78bed701db4 -r 58f440b7172f source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Mon May 19 00:56:18 2014 -0500
+++ b/source/encoder/encoder.cpp	Mon May 19 17:21:08 2014 +0530
@@ -64,6 +64,14 @@
     m_csvfpt = NULL;
     param = NULL;
 
+    memset(m_nr.offsetDenoise, 0, sizeof(m_nr.offsetDenoise[0][0]) * 8 * 1024);
+    memset(m_nr.residualSumBuf, 0, sizeof(m_nr.residualSumBuf[0][0][0]) * 4 * 8 * 1024);
+    memset(m_nr.countBuf, 0, sizeof(m_nr.countBuf[0][0]) * 4 * 8);
+
+    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;
@@ -186,6 +194,7 @@
     }
     m_lookahead->init();
     m_encodeStartTime = x265_mdate();
+    m_nr.bNoiseReduction = !!param->noiseReduction;
 }
 
 int Encoder::getStreamHeaders(NALUnitEBSP **nalunits)
@@ -218,6 +227,44 @@
     }
 }
 
+/****************************************************************************
+ * 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 transformSize[4] = {16, 64, 256, 1024};
+    int blockCount[4] = { 1 << 18, 1 << 16, 1 << 14, 1 << 12 };
+
+    int isCspI444 = (param->internalCsp == X265_CSP_I444) ? 1 : 0;
+    for (int cat = 0; cat < 7 + isCspI444; cat++)
+    {
+        int index = cat % 4;
+        int size = transformSize[index];
+
+        if (h->count[cat] > blockCount[index])
+        {
+            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] + 1);
+
+        // Don't denoise DC coefficients
+        h->offset[cat][0] = 0;
+    }
+}
+
 #define VERBOSE_RATE 0
 #if VERBOSE_RATE
 static const char* nalUnitTypeToString(NalUnitType type)
@@ -434,6 +481,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 c78bed701db4 -r 58f440b7172f source/encoder/encoder.h
--- a/source/encoder/encoder.h	Mon May 19 00:56:18 2014 -0500
+++ b/source/encoder/encoder.h	Mon May 19 17:21:08 2014 +0530
@@ -194,6 +194,8 @@
     x265_nal*          m_nals;
     char*              m_packetData;
 
+    NoiseReduction     m_nr;
+
     Encoder();
 
     virtual ~Encoder();
@@ -227,6 +229,8 @@
 
     void updateVbvPlan(RateControl* rc);
 
+    void noiseReductionUpdate(NoiseReduction* nr);
+
 protected:
 
     void finishFrameStats(TComPic* pic, FrameEncoder *curEncoder, uint64_t bits);
diff -r c78bed701db4 -r 58f440b7172f source/x265.cpp
--- a/source/x265.cpp	Mon May 19 00:56:18 2014 -0500
+++ b/source/x265.cpp	Mon May 19 17:21:08 2014 +0530
@@ -176,6 +176,7 @@
     { "qpfile",         required_argument, NULL, 0 },
     { "b-intra",              no_argument, NULL, 0 },
     { "no-b-intra",           no_argument, NULL, 0 },
+    { "nr",             required_argument, NULL, 0 },
     { 0, 0, 0, 0 }
 };
 
@@ -414,6 +415,8 @@
     H0("\nReconstructed video options (debugging):\n");
     H0("-r/--recon <filename>            Reconstructed raw image YUV or Y4M output file name\n");
     H0("   --recon-depth <integer>       Bit-depth of reconstructed raw image file. Defaults to input bit depth, or 8 if Y4M\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 c78bed701db4 -r 58f440b7172f source/x265.h
--- a/source/x265.h	Mon May 19 00:56:18 2014 -0500
+++ b/source/x265.h	Mon May 19 17:21:08 2014 +0530
@@ -646,6 +646,10 @@
      * regardless of this setting. */
     int       bIntraInBFrames;
 
+    /* An integer value in range of 100 to 1000, which denotes strength of noise
+     * reduction */
+    int       noiseReduction;
+
     /*== Rate Control ==*/
 
     struct


More information about the x265-devel mailing list