[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