Commit 7be065c6 authored by Christopher Hollmann's avatar Christopher Hollmann
Browse files

JVET-V0056: Changes for MCTF

parent 0046fe97
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#include <utility> #include <utility>
#include <iostream> #include <iostream>
#define JVET_V0056 1
//! \ingroup TLibCommon //! \ingroup TLibCommon
//! \{ //! \{
......
...@@ -42,7 +42,11 @@ ...@@ -42,7 +42,11 @@
// Constructor / destructor / initialization / destroy // Constructor / destructor / initialization / destroy
// ==================================================================================================================== // ====================================================================================================================
#if JVET_V0056
const Int TEncTemporalFilter::s_range = 4;
#else
const Int TEncTemporalFilter::s_range = 2; const Int TEncTemporalFilter::s_range = 2;
#endif
const Double TEncTemporalFilter::s_chromaFactor = 0.55; const Double TEncTemporalFilter::s_chromaFactor = 0.55;
const Double TEncTemporalFilter::s_sigmaMultiplier = 9.0; const Double TEncTemporalFilter::s_sigmaMultiplier = 9.0;
const Double TEncTemporalFilter::s_sigmaZeroPoint = 10.0; const Double TEncTemporalFilter::s_sigmaZeroPoint = 10.0;
...@@ -68,6 +72,15 @@ const Int TEncTemporalFilter::s_interpolationFilter[16][8] = ...@@ -68,6 +72,15 @@ const Int TEncTemporalFilter::s_interpolationFilter[16][8] =
{ 0, 0, -2, 4, 64, -3, 1, 0 } //15-->--> { 0, 0, -2, 4, 64, -3, 1, 0 } //15-->-->
}; };
#if JVET_V0056
const Double TEncTemporalFilter::s_refStrengths[3][4] =
{ // abs(POC offset)
// 1, 2 3 4
{0.85, 0.57, 0.41, 0.33}, // m_range * 2
{1.13, 0.97, 0.81, 0.57}, // m_range
{0.30, 0.30, 0.30, 0.30} // otherwise
};
#else
const Double TEncTemporalFilter::s_refStrengths[3][2] = const Double TEncTemporalFilter::s_refStrengths[3][2] =
{ // abs(POC offset) { // abs(POC offset)
// 1, 2 // 1, 2
...@@ -75,6 +88,7 @@ const Double TEncTemporalFilter::s_refStrengths[3][2] = ...@@ -75,6 +88,7 @@ const Double TEncTemporalFilter::s_refStrengths[3][2] =
{1.20, 1.00}, // s_range {1.20, 1.00}, // s_range
{0.30, 0.30} // otherwise {0.30, 0.30} // otherwise
}; };
#endif
TEncTemporalFilter::TEncTemporalFilter() : TEncTemporalFilter::TEncTemporalFilter() :
m_FrameSkip(0), m_FrameSkip(0),
...@@ -279,10 +293,10 @@ Int TEncTemporalFilter::motionErrorLuma(const TComPicYuv &orig, ...@@ -279,10 +293,10 @@ Int TEncTemporalFilter::motionErrorLuma(const TComPicYuv &orig,
const Int besterror = 8 * 8 * 1024 * 1024) const const Int besterror = 8 * 8 * 1024 * 1024) const
{ {
const Pel* origOrigin =orig.getAddr(COMPONENT_Y); const Pel* origOrigin = orig.getAddr(COMPONENT_Y);
const Int origStride =orig.getStride(COMPONENT_Y); const Int origStride = orig.getStride(COMPONENT_Y);
const Pel *buffOrigin =buffer.getAddr(COMPONENT_Y); const Pel *buffOrigin = buffer.getAddr(COMPONENT_Y);
const Int buffStride =buffer.getStride(COMPONENT_Y); const Int buffStride = buffer.getStride(COMPONENT_Y);
Int error = 0;// dx * 10 + dy * 10; Int error = 0;// dx * 10 + dy * 10;
if (((dx | dy) & 0xF) == 0) if (((dx | dy) & 0xF) == 0)
{ {
...@@ -364,15 +378,25 @@ Int TEncTemporalFilter::motionErrorLuma(const TComPicYuv &orig, ...@@ -364,15 +378,25 @@ Int TEncTemporalFilter::motionErrorLuma(const TComPicYuv &orig,
Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const TComPicYuv &orig, const TComPicYuv &buffer, const Int blockSize, Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const TComPicYuv &orig, const TComPicYuv &buffer, const Int blockSize,
const Array2D<MotionVector> *previous, const Int factor, const Bool doubleRes) const const Array2D<MotionVector> *previous, const Int factor, const Bool doubleRes) const
{ {
#if JVET_V0056
Int range = doubleRes ? 0 : 5;
#else
Int range = 5; Int range = 5;
#endif
const Int stepSize = blockSize; const Int stepSize = blockSize;
const Int origWidth = orig.getWidth(COMPONENT_Y); const Int origWidth = orig.getWidth(COMPONENT_Y);
const Int origHeight = orig.getHeight(COMPONENT_Y); const Int origHeight = orig.getHeight(COMPONENT_Y);
#if JVET_V0056
for (Int blockY = 0; blockY + blockSize <= origHeight; blockY += stepSize)
{
for (Int blockX = 0; blockX + blockSize <= origWidth; blockX += stepSize)
#else
for (Int blockY = 0; blockY + blockSize < origHeight; blockY += stepSize) for (Int blockY = 0; blockY + blockSize < origHeight; blockY += stepSize)
{ {
for (Int blockX = 0; blockX + blockSize < origWidth; blockX += stepSize) for (Int blockX = 0; blockX + blockSize < origWidth; blockX += stepSize)
#endif
{ {
MotionVector best; MotionVector best;
...@@ -382,10 +406,18 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const ...@@ -382,10 +406,18 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const
} }
else else
{ {
#if JVET_V0056
for (Int py = -1; py <= 1; py++)
#else
for (Int py = -2; py <= 2; py++) for (Int py = -2; py <= 2; py++)
#endif
{ {
Int testy = blockY / (2 * blockSize) + py; Int testy = blockY / (2 * blockSize) + py;
#if JVET_V0056
for (Int px = -1; px <= 1; px++)
#else
for (Int px = -2; px <= 2; px++) for (Int px = -2; px <= 2; px++)
#endif
{ {
Int testx = blockX / (2 * blockSize) + px; Int testx = blockX / (2 * blockSize) + px;
if ((testx >= 0) && (testx < origWidth / (2 * blockSize)) && (testy >= 0) && (testy < origHeight / (2 * blockSize))) if ((testx >= 0) && (testx < origWidth / (2 * blockSize)) && (testy >= 0) && (testy < origHeight / (2 * blockSize)))
...@@ -399,6 +431,13 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const ...@@ -399,6 +431,13 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const
} }
} }
} }
#if JVET_V0056
Int error = motionErrorLuma(orig, buffer, blockX, blockY, 0, 0, blockSize, best.error);
if (error < best.error)
{
best.set(0, 0, error);
}
#endif
} }
MotionVector prevBest = best; MotionVector prevBest = best;
for (Int y2 = prevBest.y / s_motionVectorFactor - range; y2 <= prevBest.y / s_motionVectorFactor + range; y2++) for (Int y2 = prevBest.y / s_motionVectorFactor - range; y2 <= prevBest.y / s_motionVectorFactor + range; y2++)
...@@ -425,7 +464,6 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const ...@@ -425,7 +464,6 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const
{ {
best.set(x2, y2, error); best.set(x2, y2, error);
} }
} }
} }
...@@ -440,11 +478,52 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const ...@@ -440,11 +478,52 @@ Void TEncTemporalFilter::motionEstimationLuma(Array2D<MotionVector> &mvs, const
{ {
best.set(x2, y2, error); best.set(x2, y2, error);
} }
} }
} }
}
#if JVET_V0056
if (blockY > 0)
{
MotionVector aboveMV = mvs.get(blockX / stepSize, (blockY - stepSize) / stepSize);
int error = motionErrorLuma(orig, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, best.error);
if (error < best.error)
{
best.set(aboveMV.x, aboveMV.y, error);
}
}
if (blockX > 0)
{
MotionVector leftMV = mvs.get((blockX - stepSize) / stepSize, blockY / stepSize);
int error = motionErrorLuma(orig, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, best.error);
if (error < best.error)
{
best.set(leftMV.x, leftMV.y, error);
}
}
// calculate average
double avg = 0.0;
for (int x1 = 0; x1 < blockSize; x1++)
{
for (int y1 = 0; y1 < blockSize; y1++)
{
avg = avg + *(orig.getAddr(COMPONENT_Y) + (blockX + x1 + orig.getStride(COMPONENT_Y) * (blockY + y1)));
}
}
avg = avg / (blockSize * blockSize);
// calculate variance
double variance = 0;
for (int x1 = 0; x1 < blockSize; x1++)
{
for (int y1 = 0; y1 < blockSize; y1++)
{
int pix = *(orig.getAddr(COMPONENT_Y) + (blockX + x1 + orig.getStride(COMPONENT_Y) * (blockY + y1)));
variance = variance + (pix - avg) * (pix - avg);
}
} }
best.error = 20 * ((best.error + 5.0) / (variance + 5.0)) + (best.error / (blockSize * blockSize)) / 50;
#endif
mvs.get(blockX / stepSize, blockY / stepSize) = best; mvs.get(blockX / stepSize, blockY / stepSize) = best;
} }
} }
...@@ -557,7 +636,11 @@ Void TEncTemporalFilter::applyMotion(const Array2D<MotionVector> &mvs, const TCo ...@@ -557,7 +636,11 @@ Void TEncTemporalFilter::applyMotion(const Array2D<MotionVector> &mvs, const TCo
} }
Void TEncTemporalFilter::bilateralFilter(const TComPicYuv &orgPic, Void TEncTemporalFilter::bilateralFilter(const TComPicYuv &orgPic,
#if JVET_V0056
std::deque<TemporalFilterSourcePicInfo> &srcFrameInfo,
#else
const std::deque<TemporalFilterSourcePicInfo> &srcFrameInfo, const std::deque<TemporalFilterSourcePicInfo> &srcFrameInfo,
#endif
TComPicYuv &newOrgPic, TComPicYuv &newOrgPic,
Double overallStrength) const Double overallStrength) const
{ {
...@@ -595,6 +678,9 @@ Void TEncTemporalFilter::bilateralFilter(const TComPicYuv &orgPic, ...@@ -595,6 +678,9 @@ Void TEncTemporalFilter::bilateralFilter(const TComPicYuv &orgPic,
const Double weightScaling = overallStrength * (isChroma(compID) ? s_chromaFactor : 0.4); const Double weightScaling = overallStrength * (isChroma(compID) ? s_chromaFactor : 0.4);
const Pel maxSampleValue = (1<<m_internalBitDepth[toChannelType(compID)])-1; const Pel maxSampleValue = (1<<m_internalBitDepth[toChannelType(compID)])-1;
const Double bitDepthDiffWeighting=1024.0 / (maxSampleValue+1); const Double bitDepthDiffWeighting=1024.0 / (maxSampleValue+1);
#if JVET_V0056
const Int blkSize = isLuma(compID) ? 8 : 4;
#endif
for (Int y = 0; y < height; y++, srcPelRow+=srcStride, dstPelRow+=dstStride) for (Int y = 0; y < height; y++, srcPelRow+=srcStride, dstPelRow+=dstStride)
{ {
...@@ -605,15 +691,66 @@ Void TEncTemporalFilter::bilateralFilter(const TComPicYuv &orgPic, ...@@ -605,15 +691,66 @@ Void TEncTemporalFilter::bilateralFilter(const TComPicYuv &orgPic,
const Int orgVal = (Int) *srcPel; const Int orgVal = (Int) *srcPel;
Double temporalWeightSum = 1.0; Double temporalWeightSum = 1.0;
Double newVal = (Double) orgVal; Double newVal = (Double) orgVal;
#if JVET_V0056
if ((y % blkSize == 0) && (x % blkSize == 0))
{
for (Int i = 0; i < numRefs; i++)
{
Double variance = 0, diffsum = 0;
for (Int y1 = 0; y1 < blkSize - 1; y1++)
{
for (Int x1 = 0; x1 < blkSize - 1; x1++)
{
Int pix = *(srcPel + x1);
Int pixR = *(srcPel + x1 + 1);
Int pixD = *(srcPel + x1 + srcStride);
Int ref = *(correctedPics[i].getAddr(compID) + ((y + y1) * correctedPics[i].getStride(compID) + x + x1));
Int refR = *(correctedPics[i].getAddr(compID) + ((y + y1) * correctedPics[i].getStride(compID) + x + x1 + 1));
Int refD = *(correctedPics[i].getAddr(compID) + ((y + y1 + 1) * correctedPics[i].getStride(compID) + x + x1));
Int diff = pix - ref;
Int diffR = pixR - refR;
Int diffD = pixD - refD;
variance += diff * diff;
diffsum += (diffR - diff) * (diffR - diff);
diffsum += (diffD - diff) * (diffD - diff);
}
}
srcFrameInfo[i].mvs.get(x / blkSize, y / blkSize).noise = (int) round((300 * variance + 50) / (10 * diffsum + 50));
}
}
Double minError = 9999999;
for (Int i = 0; i < numRefs; i++)
{
minError = std::min(minError, (Double) srcFrameInfo[i].mvs.get(x / blkSize, y / blkSize).error);
}
#endif
for (Int i = 0; i < numRefs; i++) for (Int i = 0; i < numRefs; i++)
{ {
#if JVET_V0056
const Int error = srcFrameInfo[i].mvs.get(x / blkSize, y / blkSize).error;
const Int noise = srcFrameInfo[i].mvs.get(x / blkSize, y / blkSize).noise;
#endif
const Pel *pCorrectedPelPtr=correctedPics[i].getAddr(compID)+(y*correctedPics[i].getStride(compID)+x); const Pel *pCorrectedPelPtr=correctedPics[i].getAddr(compID)+(y*correctedPics[i].getStride(compID)+x);
const Int refVal = (Int) *pCorrectedPelPtr; const Int refVal = (Int) *pCorrectedPelPtr;
Double diff = (Double)(refVal - orgVal); Double diff = (Double)(refVal - orgVal);
diff *= bitDepthDiffWeighting; diff *= bitDepthDiffWeighting;
Double diffSq = diff * diff; Double diffSq = diff * diff;
#if JVET_V0056
const Int index = std::min(3, std::abs(srcFrameInfo[i].origOffset) - 1);
Double ww = 1, sw = 1;
ww *= (noise < 25) ? 1 : 1.2;
sw *= (noise < 25) ? 1.3 : 0.8;
ww *= (error < 50) ? 1.2 : ((error > 100) ? 0.8 : 1);
sw *= (error < 50) ? 1.3 : 1;
ww *= ((minError + 1) / (error + 1));
const Double weight = weightScaling * s_refStrengths[refStrengthRow][index] * ww * exp(-diffSq / (2 * sw * sigmaSq));
#else
const Int index = std::min(1, std::abs(srcFrameInfo[i].origOffset) - 1); const Int index = std::min(1, std::abs(srcFrameInfo[i].origOffset) - 1);
const Double weight = weightScaling * s_refStrengths[refStrengthRow][index] * exp(-diffSq / (2 * sigmaSq)); const Double weight = weightScaling * s_refStrengths[refStrengthRow][index] * exp(-diffSq / (2 * sigmaSq));
#endif
newVal += weight * refVal; newVal += weight * refVal;
temporalWeightSum += weight; temporalWeightSum += weight;
} }
......
...@@ -50,7 +50,12 @@ struct MotionVector ...@@ -50,7 +50,12 @@ struct MotionVector
{ {
Int x, y; Int x, y;
Int error; Int error;
#if JVET_V0056
Int noise;
MotionVector() : x(0), y(0), error(INT_LEAST32_MAX), noise(0) {}
#else
MotionVector() : x(0), y(0), error(INT_LEAST32_MAX) {} MotionVector() : x(0), y(0), error(INT_LEAST32_MAX) {}
#endif
void set(Int nx, Int ny, Int ne) { x = nx; y = ny; error = ne; } void set(Int nx, Int ny, Int ne) { x = nx; y = ny; error = ne; }
}; };
...@@ -129,7 +134,11 @@ private: ...@@ -129,7 +134,11 @@ private:
static const Int s_motionVectorFactor; static const Int s_motionVectorFactor;
static const Int s_padding; static const Int s_padding;
static const Int s_interpolationFilter[16][8]; static const Int s_interpolationFilter[16][8];
#if JVET_V0056
static const Double s_refStrengths[3][4];
#else
static const Double s_refStrengths[3][2]; static const Double s_refStrengths[3][2];
#endif
// Private member variables // Private member variables
Int m_FrameSkip; Int m_FrameSkip;
...@@ -156,7 +165,11 @@ private: ...@@ -156,7 +165,11 @@ private:
const Array2D<MotionVector> *previous=0, const Int factor = 1, const Bool doubleRes = false) const; const Array2D<MotionVector> *previous=0, const Int factor = 1, const Bool doubleRes = false) const;
Void motionEstimation(Array2D<MotionVector> &mvs, const TComPicYuv &orgPic, const TComPicYuv &buffer, const TComPicYuv &origSubsampled2, const TComPicYuv &origSubsampled4) const; Void motionEstimation(Array2D<MotionVector> &mvs, const TComPicYuv &orgPic, const TComPicYuv &buffer, const TComPicYuv &origSubsampled2, const TComPicYuv &origSubsampled4) const;
#if JVET_V0056
Void bilateralFilter(const TComPicYuv &orgPic, std::deque<TemporalFilterSourcePicInfo> &srcFrameInfo, TComPicYuv &newOrgPic, Double overallStrength) const;
#else
Void bilateralFilter(const TComPicYuv &orgPic, const std::deque<TemporalFilterSourcePicInfo> &srcFrameInfo, TComPicYuv &newOrgPic, Double overallStrength) const; Void bilateralFilter(const TComPicYuv &orgPic, const std::deque<TemporalFilterSourcePicInfo> &srcFrameInfo, TComPicYuv &newOrgPic, Double overallStrength) const;
#endif
Void applyMotion(const Array2D<MotionVector> &mvs, const TComPicYuv &input, TComPicYuv &output) const; Void applyMotion(const Array2D<MotionVector> &mvs, const TComPicYuv &input, TComPicYuv &output) const;
}; // END CLASS DEFINITION TEncTemporalFilter }; // END CLASS DEFINITION TEncTemporalFilter
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment