[x265] [PATCH] 2-pass: Fix incorrect weighted prediction when cu-tree is enabled

Aruna Matheswaran aruna at multicorewareinc.com
Thu Sep 12 12:38:52 CEST 2019


Pushed into Release_3.1 and grafted to default.

On Tue, Sep 10, 2019 at 11:27 AM Aruna Matheswaran <
aruna at multicorewareinc.com> wrote:

> # 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;
>


-- 
Regards,
Aruna
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20190912/f99e3434/attachment-0001.html>


More information about the x265-devel mailing list