Beispiel #1
0
        private static void RunHadamardTransformTest()
        {
            // arrange
            byte[] a =
            {
                27,   27,  28,  29,  29,  28,  27,  27,  27,  28,  28,  29,  29,  28,  28,  27, 129, 129, 129, 129, 129, 129, 129,
                129, 128, 128, 128, 128, 128, 128, 128, 128,  27,  27,  27,  27,  27,  27,  27,  27,  27,  28,  28,  29,  29,  28,
                28,   27, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128,  27,  27,  26,
                26,   26,  26,  27,  27,  27,  28,  28,  29,  29,  28,  28,  27, 129, 129, 129, 129, 129, 129, 129, 129, 128,
                128, 128, 128, 128, 128, 128, 128,  28,  27,  27,  26,  26,  27,  27,  28,  27,  28,  28,  29,  29,  28,  28, 27
            };

            byte[] b =
            {
                28,   28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28, 204, 204, 204, 204, 204, 204, 204,
                204, 204, 204, 204, 204, 204, 204, 204, 204,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,
                28,   28, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,  28,  28,  28,
                28,   28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28, 204, 204, 204, 204, 204, 204, 204, 204, 204,
                204, 204, 204, 204, 204, 204, 204,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28,  28, 28
            };

            ushort[] w        = { 38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2 };
            int      expected = 2;

            // act
            int actual = LossyUtils.Vp8Disto4X4(a, b, w, new int[16]);

            // assert
            Assert.Equal(expected, actual);
        }
Beispiel #2
0
        public static bool PickBestIntra4(Vp8EncIterator it, ref Vp8ModeScore rd, Vp8SegmentInfo[] segmentInfos, Vp8EncProba proba, int maxI4HeaderBits)
        {
            Vp8SegmentInfo dqm             = segmentInfos[it.CurrentMacroBlockInfo.Segment];
            int            lambda          = dqm.LambdaI4;
            int            tlambda         = dqm.TLambda;
            Span <byte>    src0            = it.YuvIn.AsSpan(Vp8EncIterator.YOffEnc);
            Span <byte>    bestBlocks      = it.YuvOut2.AsSpan(Vp8EncIterator.YOffEnc);
            Span <int>     scratch         = it.Scratch3;
            int            totalHeaderBits = 0;
            var            rdBest          = new Vp8ModeScore();

            if (maxI4HeaderBits == 0)
            {
                return(false);
            }

            rdBest.InitScore();
            rdBest.H = 211;  // '211' is the value of VP8BitCost(0, 145)
            rdBest.SetRdScore(dqm.LambdaMode);
            it.StartI4();
            var          rdi4      = new Vp8ModeScore();
            var          rdTmp     = new Vp8ModeScore();
            var          res       = new Vp8Residual();
            Span <short> tmpLevels = new short[16];

            do
            {
                int numBlocks = 1;
                rdi4.Clear();
                int         mode;
                int         bestMode  = -1;
                Span <byte> src       = src0.Slice(WebpLookupTables.Vp8Scan[it.I4]);
                short[]     modeCosts = it.GetCostModeI4(rd.ModesI4);
                Span <byte> bestBlock = bestBlocks.Slice(WebpLookupTables.Vp8Scan[it.I4]);
                Span <byte> tmpDst    = it.Scratch.AsSpan();
                tmpDst.Clear();

                rdi4.InitScore();
                it.MakeIntra4Preds();
                for (mode = 0; mode < WebpConstants.NumBModes; ++mode)
                {
                    rdTmp.Clear();
                    tmpLevels.Clear();

                    // Reconstruct.
                    rdTmp.Nz = (uint)ReconstructIntra4(it, dqm, tmpLevels, src, tmpDst, mode);

                    // Compute RD-score.
                    rdTmp.D  = LossyUtils.Vp8_Sse4X4(src, tmpDst);
                    rdTmp.SD = tlambda != 0 ? Mult8B(tlambda, LossyUtils.Vp8Disto4X4(src, tmpDst, WeightY, scratch)) : 0;
                    rdTmp.H  = modeCosts[mode];

                    // Add flatness penalty, to avoid flat area to be mispredicted by a complex mode.
                    if (mode > 0 && IsFlat(tmpLevels, numBlocks, WebpConstants.FlatnessLimitI4))
                    {
                        rdTmp.R = WebpConstants.FlatnessPenality * numBlocks;
                    }
                    else
                    {
                        rdTmp.R = 0;
                    }

                    // Early-out check.
                    rdTmp.SetRdScore(lambda);
                    if (bestMode >= 0 && rdTmp.Score >= rdi4.Score)
                    {
                        continue;
                    }

                    // Finish computing score.
                    rdTmp.R += it.GetCostLuma4(tmpLevels, proba, res);
                    rdTmp.SetRdScore(lambda);

                    if (bestMode < 0 || rdTmp.Score < rdi4.Score)
                    {
                        rdi4.CopyScore(rdTmp);
                        bestMode = mode;
                        Span <byte> tmp = tmpDst;
                        tmpDst    = bestBlock;
                        bestBlock = tmp;
                        tmpLevels.CopyTo(rdBest.YAcLevels.AsSpan(it.I4 * 16, 16));
                    }
                }

                rdi4.SetRdScore(dqm.LambdaMode);
                rdBest.AddScore(rdi4);
                if (rdBest.Score >= rd.Score)
                {
                    return(false);
                }

                totalHeaderBits += (int)rdi4.H;   // <- equal to modeCosts[bestMode];
                if (totalHeaderBits > maxI4HeaderBits)
                {
                    return(false);
                }

                // Copy selected samples to the right place.
                LossyUtils.Vp8Copy4X4(bestBlock, bestBlocks.Slice(WebpLookupTables.Vp8Scan[it.I4]));

                rd.ModesI4[it.I4]   = (byte)bestMode;
                it.TopNz[it.I4 & 3] = it.LeftNz[it.I4 >> 2] = rdi4.Nz != 0 ? 1 : 0;
            }while (it.RotateI4(bestBlocks));

            // Finalize state.
            rd.CopyScore(rdBest);
            it.SetIntra4Mode(rd.ModesI4);
            it.SwapOut();
            rdBest.YAcLevels.AsSpan().CopyTo(rd.YAcLevels);

            // Select intra4x4 over intra16x16.
            return(true);
        }