[x265] [PATCH] 2-pass: Fix incorrect weighted prediction when cu-tree is enabled
Aruna Matheswaran
aruna at multicorewareinc.com
Tue Sep 10 07:57:34 CEST 2019
# HG changeset patch
# User Aruna Matheswaran
# Date 1567490246 -19800
# Tue Sep 03 11:27:26 2019 +0530
# Node ID 55bc4aa1433c01c99002e702bc49e572399cbd32
# Parent a092e82e6acfe7afe6a9a381e9ef52323e4e2467
2-pass: Fix incorrect weighted prediction when cu-tree is enabled
diff -r a092e82e6acf -r 55bc4aa1433c source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Thu Aug 01 22:55:21 2019 +0200
+++ b/source/encoder/slicetype.cpp Tue Sep 03 11:27:26 2019 +0530
@@ -437,175 +437,178 @@
curFrame->m_lowres.wp_sum[y] = 0;
}
- /* Calculate Qp offset for each 16x16 or 8x8 block in the frame */
- if ((param->rc.aqMode == X265_AQ_NONE || param->rc.aqStrength == 0) || (param->rc.bStatRead && param->rc.cuTree && IS_REFERENCED(curFrame)))
- {
- if (param->rc.aqMode && param->rc.aqStrength == 0)
- {
- if (quantOffsets)
+ if (!(param->rc.bStatRead && param->rc.cuTree && IS_REFERENCED(curFrame)))
+ {
+ /* Calculate Qp offset for each 16x16 or 8x8 block in the frame */
+ if (param->rc.aqMode == X265_AQ_NONE || param->rc.aqStrength == 0)
+ {
+ if (param->rc.aqMode && param->rc.aqStrength == 0)
+ {
+ if (quantOffsets)
+ {
+ for (int cuxy = 0; cuxy < blockCount; cuxy++)
+ {
+ curFrame->m_lowres.qpCuTreeOffset[cuxy] = curFrame->m_lowres.qpAqOffset[cuxy] = quantOffsets[cuxy];
+ curFrame->m_lowres.invQscaleFactor[cuxy] = x265_exp2fix8(curFrame->m_lowres.qpCuTreeOffset[cuxy]);
+ }
+ }
+ else
+ {
+ memset(curFrame->m_lowres.qpCuTreeOffset, 0, blockCount * sizeof(double));
+ memset(curFrame->m_lowres.qpAqOffset, 0, blockCount * sizeof(double));
+ for (int cuxy = 0; cuxy < blockCount; cuxy++)
+ curFrame->m_lowres.invQscaleFactor[cuxy] = 256;
+ }
+ }
+
+ /* Need variance data for weighted prediction and dynamic refinement*/
+ if (param->bEnableWeightedPred || param->bEnableWeightedBiPred)
{
- for (int cuxy = 0; cuxy < blockCount; cuxy++)
- {
- curFrame->m_lowres.qpCuTreeOffset[cuxy] = curFrame->m_lowres.qpAqOffset[cuxy] = quantOffsets[cuxy];
- curFrame->m_lowres.invQscaleFactor[cuxy] = x265_exp2fix8(curFrame->m_lowres.qpCuTreeOffset[cuxy]);
- }
- }
- else
- {
- memset(curFrame->m_lowres.qpCuTreeOffset, 0, blockCount * sizeof(double));
- memset(curFrame->m_lowres.qpAqOffset, 0, blockCount * sizeof(double));
- for (int cuxy = 0; cuxy < blockCount; cuxy++)
- curFrame->m_lowres.invQscaleFactor[cuxy] = 256;
+ for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
+ for (int blockX = 0; blockX < maxCol; blockX += loopIncr)
+ acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
}
- }
-
- /* Need variance data for weighted prediction and dynamic refinement*/
- if (param->bEnableWeightedPred || param->bEnableWeightedBiPred)
- {
- for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
- for (int blockX = 0; blockX < maxCol; blockX += loopIncr)
- acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
- }
- }
- else
- {
- if (param->rc.hevcAq)
- {
- // New method for calculating variance and qp offset
- xPreanalyze(curFrame);
- }
- else
- {
+ }
+ else
+ {
+ if (param->rc.hevcAq)
+ {
+ // New method for calculating variance and qp offset
+ xPreanalyze(curFrame);
+ }
+ else
+ {
#define AQ_EDGE_BIAS 0.5
#define EDGE_INCLINATION 45
- uint32_t numCuInHeight = (maxRow + param->maxCUSize - 1) / param->maxCUSize;
- int maxHeight = numCuInHeight * param->maxCUSize;
- intptr_t stride = curFrame->m_fencPic->m_stride;
- pixel *edgePic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)));
- pixel *gaussianPic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)));
- pixel *thetaPic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)));
- memset(edgePic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel));
- memset(gaussianPic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel));
- memset(thetaPic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel));
- if (param->rc.aqMode == X265_AQ_EDGE)
- edgeFilter(curFrame, edgePic, gaussianPic, thetaPic, stride, maxRow, maxCol);
-
- int blockXY = 0, inclinedEdge = 0;
- double avg_adj_pow2 = 0, avg_adj = 0, qp_adj = 0;
- double bias_strength = 0.f;
- double strength = 0.f;
- if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED || param->rc.aqMode == X265_AQ_EDGE)
- {
- double bit_depth_correction = 1.f / (1 << (2 * (X265_DEPTH - 8)));
- for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
- {
- for (int blockX = 0; blockX < maxCol; blockX += loopIncr)
- {
- uint32_t energy, edgeDensity, avgAngle;
- energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
- if (param->rc.aqMode == X265_AQ_EDGE)
- {
- pixel *edgeImage = edgePic + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX;
- pixel *edgeTheta = thetaPic + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX;
- edgeDensity = edgeDensityCu(curFrame, edgeImage, edgeTheta, avgAngle, blockX, blockY, param->rc.qgSize);
- if (edgeDensity)
- {
- qp_adj = pow(edgeDensity * bit_depth_correction + 1, 0.1);
- //Increasing the QP of a block if its edge orientation lies around the multiples of 45 degree
- if ((avgAngle >= EDGE_INCLINATION - 15 && avgAngle <= EDGE_INCLINATION + 15) || (avgAngle >= EDGE_INCLINATION + 75 && avgAngle <= EDGE_INCLINATION + 105))
- curFrame->m_lowres.edgeInclined[blockXY] = 1;
- else
- curFrame->m_lowres.edgeInclined[blockXY] = 0;
- }
- else
- {
- qp_adj = pow(energy * bit_depth_correction + 1, 0.1);
- curFrame->m_lowres.edgeInclined[blockXY] = 0;
- }
- }
- else
- qp_adj = pow(energy * bit_depth_correction + 1, 0.1);
- curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;
- avg_adj += qp_adj;
- avg_adj_pow2 += qp_adj * qp_adj;
- blockXY++;
- }
- }
- avg_adj /= blockCount;
- avg_adj_pow2 /= blockCount;
- strength = param->rc.aqStrength * avg_adj;
- avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj;
- bias_strength = param->rc.aqStrength;
- }
- else
- strength = param->rc.aqStrength * 1.0397f;
-
- X265_FREE(edgePic);
- X265_FREE(gaussianPic);
- X265_FREE(thetaPic);
- blockXY = 0;
- for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
- {
- for (int blockX = 0; blockX < maxCol; blockX += loopIncr)
- {
- if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED)
- {
- qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];
- qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj));
- }
- else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE)
- {
- qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];
- qp_adj = strength * (qp_adj - avg_adj);
- }
- else if (param->rc.aqMode == X265_AQ_EDGE)
- {
- inclinedEdge = curFrame->m_lowres.edgeInclined[blockXY];
- qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];
- if(inclinedEdge && (qp_adj - avg_adj > 0))
- qp_adj = ((strength + AQ_EDGE_BIAS) * (qp_adj - avg_adj));
- else
- qp_adj = strength * (qp_adj - avg_adj);
- }
- else
- {
- uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
- qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8)));
- }
-
- if (param->bHDROpt)
- {
- uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize);
- uint32_t lumaAvg = sum / (loopIncr * loopIncr);
- if (lumaAvg < 301)
- qp_adj += 3;
- else if (lumaAvg >= 301 && lumaAvg < 367)
- qp_adj += 2;
- else if (lumaAvg >= 367 && lumaAvg < 434)
- qp_adj += 1;
- else if (lumaAvg >= 501 && lumaAvg < 567)
- qp_adj -= 1;
- else if (lumaAvg >= 567 && lumaAvg < 634)
- qp_adj -= 2;
- else if (lumaAvg >= 634 && lumaAvg < 701)
- qp_adj -= 3;
- else if (lumaAvg >= 701 && lumaAvg < 767)
- qp_adj -= 4;
- else if (lumaAvg >= 767 && lumaAvg < 834)
- qp_adj -= 5;
- else if (lumaAvg >= 834)
- qp_adj -= 6;
- }
- if (quantOffsets != NULL)
- qp_adj += quantOffsets[blockXY];
- curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj;
- curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;
- curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj);
- blockXY++;
- }
- }
- }
- }
+ uint32_t numCuInHeight = (maxRow + param->maxCUSize - 1) / param->maxCUSize;
+ int maxHeight = numCuInHeight * param->maxCUSize;
+ intptr_t stride = curFrame->m_fencPic->m_stride;
+ pixel *edgePic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)));
+ pixel *gaussianPic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)));
+ pixel *thetaPic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)));
+ memset(edgePic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel));
+ memset(gaussianPic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel));
+ memset(thetaPic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel));
+ if (param->rc.aqMode == X265_AQ_EDGE)
+ edgeFilter(curFrame, edgePic, gaussianPic, thetaPic, stride, maxRow, maxCol);
+
+ int blockXY = 0, inclinedEdge = 0;
+ double avg_adj_pow2 = 0, avg_adj = 0, qp_adj = 0;
+ double bias_strength = 0.f;
+ double strength = 0.f;
+ if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED || param->rc.aqMode == X265_AQ_EDGE)
+ {
+ double bit_depth_correction = 1.f / (1 << (2 * (X265_DEPTH - 8)));
+ for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
+ {
+ for (int blockX = 0; blockX < maxCol; blockX += loopIncr)
+ {
+ uint32_t energy, edgeDensity, avgAngle;
+ energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
+ if (param->rc.aqMode == X265_AQ_EDGE)
+ {
+ pixel *edgeImage = edgePic + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX;
+ pixel *edgeTheta = thetaPic + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX;
+ edgeDensity = edgeDensityCu(curFrame, edgeImage, edgeTheta, avgAngle, blockX, blockY, param->rc.qgSize);
+ if (edgeDensity)
+ {
+ qp_adj = pow(edgeDensity * bit_depth_correction + 1, 0.1);
+ //Increasing the QP of a block if its edge orientation lies around the multiples of 45 degree
+ if ((avgAngle >= EDGE_INCLINATION - 15 && avgAngle <= EDGE_INCLINATION + 15) || (avgAngle >= EDGE_INCLINATION + 75 && avgAngle <= EDGE_INCLINATION + 105))
+ curFrame->m_lowres.edgeInclined[blockXY] = 1;
+ else
+ curFrame->m_lowres.edgeInclined[blockXY] = 0;
+ }
+ else
+ {
+ qp_adj = pow(energy * bit_depth_correction + 1, 0.1);
+ curFrame->m_lowres.edgeInclined[blockXY] = 0;
+ }
+ }
+ else
+ qp_adj = pow(energy * bit_depth_correction + 1, 0.1);
+ curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;
+ avg_adj += qp_adj;
+ avg_adj_pow2 += qp_adj * qp_adj;
+ blockXY++;
+ }
+ }
+ avg_adj /= blockCount;
+ avg_adj_pow2 /= blockCount;
+ strength = param->rc.aqStrength * avg_adj;
+ avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj;
+ bias_strength = param->rc.aqStrength;
+ }
+ else
+ strength = param->rc.aqStrength * 1.0397f;
+
+ X265_FREE(edgePic);
+ X265_FREE(gaussianPic);
+ X265_FREE(thetaPic);
+ blockXY = 0;
+ for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
+ {
+ for (int blockX = 0; blockX < maxCol; blockX += loopIncr)
+ {
+ if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED)
+ {
+ qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];
+ qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj));
+ }
+ else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE)
+ {
+ qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];
+ qp_adj = strength * (qp_adj - avg_adj);
+ }
+ else if (param->rc.aqMode == X265_AQ_EDGE)
+ {
+ inclinedEdge = curFrame->m_lowres.edgeInclined[blockXY];
+ qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];
+ if (inclinedEdge && (qp_adj - avg_adj > 0))
+ qp_adj = ((strength + AQ_EDGE_BIAS) * (qp_adj - avg_adj));
+ else
+ qp_adj = strength * (qp_adj - avg_adj);
+ }
+ else
+ {
+ uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
+ qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8)));
+ }
+
+ if (param->bHDROpt)
+ {
+ uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize);
+ uint32_t lumaAvg = sum / (loopIncr * loopIncr);
+ if (lumaAvg < 301)
+ qp_adj += 3;
+ else if (lumaAvg >= 301 && lumaAvg < 367)
+ qp_adj += 2;
+ else if (lumaAvg >= 367 && lumaAvg < 434)
+ qp_adj += 1;
+ else if (lumaAvg >= 501 && lumaAvg < 567)
+ qp_adj -= 1;
+ else if (lumaAvg >= 567 && lumaAvg < 634)
+ qp_adj -= 2;
+ else if (lumaAvg >= 634 && lumaAvg < 701)
+ qp_adj -= 3;
+ else if (lumaAvg >= 701 && lumaAvg < 767)
+ qp_adj -= 4;
+ else if (lumaAvg >= 767 && lumaAvg < 834)
+ qp_adj -= 5;
+ else if (lumaAvg >= 834)
+ qp_adj -= 6;
+ }
+ if (quantOffsets != NULL)
+ qp_adj += quantOffsets[blockXY];
+ curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj;
+ curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;
+ curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj);
+ blockXY++;
+ }
+ }
+ }
+ }
+ }
if (param->rc.qgSize == 8)
{
@@ -624,6 +627,11 @@
if (param->bEnableWeightedPred || param->bEnableWeightedBiPred)
{
+ if (param->rc.bStatRead && param->rc.cuTree && IS_REFERENCED(curFrame))
+ for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
+ for (int blockX = 0; blockX < maxCol; blockX += loopIncr)
+ acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
+
int hShift = CHROMA_H_SHIFT(param->internalCsp);
int vShift = CHROMA_V_SHIFT(param->internalCsp);
maxCol = ((maxCol + 8) >> 4) << 4;
@@ -1356,9 +1364,7 @@
ProfileScopeEvent(prelookahead);
m_lock.release();
preFrame->m_lowres.init(preFrame->m_fencPic, preFrame->m_poc);
- if (m_lookahead.m_param->rc.bStatRead && m_lookahead.m_param->rc.cuTree && IS_REFERENCED(preFrame))
- /* cu-tree offsets were read from stats file */;
- else if (m_lookahead.m_bAdaptiveQuant)
+ if (m_lookahead.m_bAdaptiveQuant)
tld.calcAdaptiveQuantFrame(preFrame, m_lookahead.m_param);
tld.lowresIntraEstimate(preFrame->m_lowres, m_lookahead.m_param->rc.qgSize);
preFrame->m_lowresInit = true;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265.patch
Type: text/x-patch
Size: 18122 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20190910/80e68176/attachment-0001.bin>
More information about the x265-devel
mailing list