[x265] [PATCH] noise reduction feature, ported from x264
praveen at multicorewareinc.com
praveen at multicorewareinc.com
Thu May 8 13:11:35 CEST 2014
# HG changeset patch
# User Praveen Tiwari
# Date 1399547477 -19800
# Node ID 9ee52ef9f0dd4981fd866a8774527bd1e965096e
# Parent 8e64aa56d6352a1a8cfb6fb57cb547607bcec9b1
noise reduction feature, ported from x264
diff -r 8e64aa56d635 -r 9ee52ef9f0dd doc/reST/cli.rst
--- a/doc/reST/cli.rst Thu May 08 11:01:04 2014 +0530
+++ b/doc/reST/cli.rst Thu May 08 16:41:17 2014 +0530
@@ -184,6 +184,14 @@
**CLI ONLY**
+.. 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.
+
.. option:: --input-res <wxh>
YUV only: Source picture size [w x h]
diff -r 8e64aa56d635 -r 9ee52ef9f0dd source/Lib/TLibCommon/TComRom.cpp
--- a/source/Lib/TLibCommon/TComRom.cpp Thu May 08 11:01:04 2014 +0530
+++ b/source/Lib/TLibCommon/TComRom.cpp Thu May 08 16:41:17 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 8e64aa56d635 -r 9ee52ef9f0dd source/Lib/TLibCommon/TComRom.h
--- a/source/Lib/TLibCommon/TComRom.h Thu May 08 11:01:04 2014 +0530
+++ b/source/Lib/TLibCommon/TComRom.h Thu May 08 16:41:17 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 8e64aa56d635 -r 9ee52ef9f0dd source/Lib/TLibCommon/TComTrQuant.cpp
--- a/source/Lib/TLibCommon/TComTrQuant.cpp Thu May 08 11:01:04 2014 +0530
+++ b/source/Lib/TLibCommon/TComTrQuant.cpp Thu May 08 16:41:17 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 8e64aa56d635 -r 9ee52ef9f0dd source/Lib/TLibCommon/TComTrQuant.h
--- a/source/Lib/TLibCommon/TComTrQuant.h Thu May 08 11:01:04 2014 +0530
+++ b/source/Lib/TLibCommon/TComTrQuant.h Thu May 08 16:41:17 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 8e64aa56d635 -r 9ee52ef9f0dd source/Lib/TLibEncoder/TEncSearch.cpp
--- a/source/Lib/TLibEncoder/TEncSearch.cpp Thu May 08 11:01:04 2014 +0530
+++ b/source/Lib/TLibEncoder/TEncSearch.cpp Thu May 08 16:41:17 2014 +0530
@@ -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);
@@ -1492,7 +1492,7 @@
m_trQuant->selectLambda(TEXT_CHROMA);
- absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, ttype, absTUPartIdxC, &lastPos, useTransformSkipChroma);
+ absSum = m_trQuant->transformNxN(cu, residual, stride, coeff, width, ttype, absTUPartIdxC, &lastPos, &(m_cfg->m_nr), useTransformSkipChroma);
//--- set coded block flag ---
cu->setCbfPartRange((((absSum > 0) ? 1 : 0) << origTrDepth), ttype, absTUPartIdxC, tuIterator.m_absPartIdxStep);
@@ -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 8e64aa56d635 -r 9ee52ef9f0dd source/common/common.h
--- a/source/common/common.h Thu May 08 11:01:04 2014 +0530
+++ b/source/common/common.h Thu May 08 16:41:17 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 8e64aa56d635 -r 9ee52ef9f0dd source/common/param.cpp
--- a/source/common/param.cpp Thu May 08 11:01:04 2014 +0530
+++ b/source/common/param.cpp Thu May 08 16:41:17 2014 +0530
@@ -689,6 +689,7 @@
&p->vui.defDispWinRightOffset,
&p->vui.defDispWinBottomOffset) != 4;
}
+ OPT("nr") p->noiseReduction = atoi(value);
else
return X265_PARAM_BAD_NAME;
#undef OPT
@@ -981,6 +982,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 8e64aa56d635 -r 9ee52ef9f0dd source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu May 08 11:01:04 2014 +0530
+++ b/source/encoder/encoder.cpp Thu May 08 16:41:17 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 8e64aa56d635 -r 9ee52ef9f0dd source/encoder/encoder.h
--- a/source/encoder/encoder.h Thu May 08 11:01:04 2014 +0530
+++ b/source/encoder/encoder.h Thu May 08 16:41:17 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 8e64aa56d635 -r 9ee52ef9f0dd source/x265.cpp
--- a/source/x265.cpp Thu May 08 11:01:04 2014 +0530
+++ b/source/x265.cpp Thu May 08 16:41:17 2014 +0530
@@ -171,6 +171,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 }
};
@@ -407,6 +408,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 8e64aa56d635 -r 9ee52ef9f0dd source/x265.h
--- a/source/x265.h Thu May 08 11:01:04 2014 +0530
+++ b/source/x265.h Thu May 08 16:41:17 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
More information about the x265-devel
mailing list