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

praveen at multicorewareinc.com praveen at multicorewareinc.com
Tue May 20 09:20:43 CEST 2014


# HG changeset patch
# User Praveen Tiwari
# Date 1400570170 -19800
# Node ID 5dd459c0b7a0c4d7a4c194323d00fdc044f2ba13
# Parent  b35a5d8f012b5d2d45865bf2a1419df2cd8087d6
noise reduction feature, ported from x264

diff -r b35a5d8f012b -r 5dd459c0b7a0 doc/reST/cli.rst
--- a/doc/reST/cli.rst	Sun May 18 15:02:27 2014 +0900
+++ b/doc/reST/cli.rst	Tue May 20 12:46:10 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 b35a5d8f012b -r 5dd459c0b7a0 source/Lib/TLibCommon/TComRom.h
--- a/source/Lib/TLibCommon/TComRom.h	Sun May 18 15:02:27 2014 +0900
+++ b/source/Lib/TLibCommon/TComRom.h	Tue May 20 12:46:10 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 b35a5d8f012b -r 5dd459c0b7a0 source/Lib/TLibCommon/TComTrQuant.cpp
--- a/source/Lib/TLibCommon/TComTrQuant.cpp	Sun May 18 15:02:27 2014 +0900
+++ b/source/Lib/TLibCommon/TComTrQuant.cpp	Tue May 20 12:46:10 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,15 @@
         // 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 > 0 && index < 5)
+            {
+                denoiseDct(m_tmpCoeff, nr->residualSum[index - 1], nr->offset[index - 1], (16 << (index - 1) * 2 ));
+                nr->count[index - 1]++;
+            }
+        }
     }
     return xQuant(cu, m_tmpCoeff, coeff, trSize, ttype, absPartIdx, lastPos, curUseRDOQ);
 }
diff -r b35a5d8f012b -r 5dd459c0b7a0 source/Lib/TLibCommon/TComTrQuant.h
--- a/source/Lib/TLibCommon/TComTrQuant.h	Sun May 18 15:02:27 2014 +0900
+++ b/source/Lib/TLibCommon/TComTrQuant.h	Tue May 20 12:46:10 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 b35a5d8f012b -r 5dd459c0b7a0 source/Lib/TLibEncoder/TEncSearch.cpp
--- a/source/Lib/TLibEncoder/TEncSearch.cpp	Sun May 18 15:02:27 2014 +0900
+++ b/source/Lib/TLibEncoder/TEncSearch.cpp	Tue May 20 12:46:10 2014 +0530
@@ -465,7 +465,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);
@@ -589,7 +589,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);
@@ -902,7 +902,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);
@@ -1497,7 +1497,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);
@@ -2901,7 +2901,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);
 
@@ -2945,12 +2945,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);
@@ -3118,7 +3118,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);
 
@@ -3156,12 +3156,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);
@@ -3451,7 +3451,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)
@@ -3544,11 +3544,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 b35a5d8f012b -r 5dd459c0b7a0 source/common/common.h
--- a/source/common/common.h	Sun May 18 15:02:27 2014 +0900
+++ b/source/common/common.h	Tue May 20 12:46:10 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 b35a5d8f012b -r 5dd459c0b7a0 source/common/param.cpp
--- a/source/common/param.cpp	Sun May 18 15:02:27 2014 +0900
+++ b/source/common/param.cpp	Tue May 20 12:46:10 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 b35a5d8f012b -r 5dd459c0b7a0 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Sun May 18 15:02:27 2014 +0900
+++ b/source/encoder/encoder.cpp	Tue May 20 12:46:10 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};
+    uint32_t 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] =
+                (uint16_t)(((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 b35a5d8f012b -r 5dd459c0b7a0 source/encoder/encoder.h
--- a/source/encoder/encoder.h	Sun May 18 15:02:27 2014 +0900
+++ b/source/encoder/encoder.h	Tue May 20 12:46:10 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 b35a5d8f012b -r 5dd459c0b7a0 source/x265.cpp
--- a/source/x265.cpp	Sun May 18 15:02:27 2014 +0900
+++ b/source/x265.cpp	Tue May 20 12:46:10 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 b35a5d8f012b -r 5dd459c0b7a0 source/x265.h
--- a/source/x265.h	Sun May 18 15:02:27 2014 +0900
+++ b/source/x265.h	Tue May 20 12:46:10 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