Пример #1
0
        private void SetSegmentProbas()
        {
            int[] p = new int[NumMbSegments];
            int   n;

            for (n = 0; n < this.Mbw * this.Mbh; ++n)
            {
                Vp8MacroBlockInfo mb = this.MbInfo[n];
                ++p[mb.Segment];
            }

            if (this.SegmentHeader.NumSegments > 1)
            {
                byte[] probas = this.Proba.Segments;
                probas[0] = (byte)GetProba(p[0] + p[1], p[2] + p[3]);
                probas[1] = (byte)GetProba(p[0], p[1]);
                probas[2] = (byte)GetProba(p[2], p[3]);

                this.SegmentHeader.UpdateMap = probas[0] != 255 || probas[1] != 255 || probas[2] != 255;
                if (!this.SegmentHeader.UpdateMap)
                {
                    this.ResetSegments();
                }

                this.SegmentHeader.Size = (p[0] * (LossyUtils.Vp8BitCost(0, probas[0]) + LossyUtils.Vp8BitCost(0, probas[1]))) +
                                          (p[1] * (LossyUtils.Vp8BitCost(0, probas[0]) + LossyUtils.Vp8BitCost(1, probas[1]))) +
                                          (p[2] * (LossyUtils.Vp8BitCost(1, probas[0]) + LossyUtils.Vp8BitCost(0, probas[2]))) +
                                          (p[3] * (LossyUtils.Vp8BitCost(1, probas[0]) + LossyUtils.Vp8BitCost(1, probas[2])));
            }
            else
            {
                this.SegmentHeader.UpdateMap = false;
                this.SegmentHeader.Size      = 0;
            }
        }
Пример #2
0
        public int FinalizeSkipProba(int mbw, int mbh)
        {
            int nbMbs    = mbw * mbh;
            int nbEvents = this.NbSkip;

            this.SkipProba    = (byte)CalcSkipProba(nbEvents, nbMbs);
            this.UseSkipProba = this.SkipProba < SkipProbaThreshold;

            int size = 256;

            if (this.UseSkipProba)
            {
                size += (nbEvents * LossyUtils.Vp8BitCost(1, this.SkipProba)) + ((nbMbs - nbEvents) * LossyUtils.Vp8BitCost(0, this.SkipProba));
                size += 8 * 256;   // cost of signaling the skipProba itself.
            }

            return(size);
        }
Пример #3
0
        private static int VariableLevelCost(int level, Span <byte> probas)
        {
            int pattern = WebpLookupTables.Vp8LevelCodes[level - 1][0];
            int bits    = WebpLookupTables.Vp8LevelCodes[level - 1][1];
            int cost    = 0;

            for (int i = 2; pattern != 0; i++)
            {
                if ((pattern & 1) != 0)
                {
                    cost += LossyUtils.Vp8BitCost(bits & 1, probas[i]);
                }

                bits    >>= 1;
                pattern >>= 1;
            }

            return(cost);
        }
Пример #4
0
        public int FinalizeTokenProbas()
        {
            bool hasChanged = false;
            int  size       = 0;

            for (int t = 0; t < WebpConstants.NumTypes; ++t)
            {
                for (int b = 0; b < WebpConstants.NumBands; ++b)
                {
                    for (int c = 0; c < WebpConstants.NumCtx; ++c)
                    {
                        for (int p = 0; p < WebpConstants.NumProbas; ++p)
                        {
                            uint stats       = this.Stats[t][b].Stats[c].Stats[p];
                            int  nb          = (int)((stats >> 0) & 0xffff);
                            int  total       = (int)((stats >> 16) & 0xffff);
                            int  updateProba = WebpLookupTables.CoeffsUpdateProba[t, b, c, p];
                            int  oldP        = WebpLookupTables.DefaultCoeffsProba[t, b, c, p];
                            int  newP        = CalcTokenProba(nb, total);
                            int  oldCost     = BranchCost(nb, total, oldP) + LossyUtils.Vp8BitCost(0, (byte)updateProba);
                            int  newCost     = BranchCost(nb, total, newP) + LossyUtils.Vp8BitCost(1, (byte)updateProba) + (8 * 256);
                            bool useNewP     = oldCost > newCost;
                            size += LossyUtils.Vp8BitCost(useNewP ? 1 : 0, (byte)updateProba);
                            if (useNewP)
                            {
                                // Only use proba that seem meaningful enough.
                                this.Coeffs[t][b].Probabilities[c].Probabilities[p] = (byte)newP;
                                hasChanged |= newP != oldP;
                                size       += 8 * 256;
                            }
                            else
                            {
                                this.Coeffs[t][b].Probabilities[c].Probabilities[p] = (byte)oldP;
                            }
                        }
                    }
                }
            }

            this.Dirty = hasChanged;
            return(size);
        }
Пример #5
0
        public void CalculateLevelCosts()
        {
            if (!this.Dirty)
            {
                return; // Nothing to do.
            }

            for (int ctype = 0; ctype < WebpConstants.NumTypes; ++ctype)
            {
                for (int band = 0; band < WebpConstants.NumBands; ++band)
                {
                    for (int ctx = 0; ctx < WebpConstants.NumCtx; ++ctx)
                    {
                        Vp8ProbaArray p        = this.Coeffs[ctype][band].Probabilities[ctx];
                        Vp8CostArray  table    = this.LevelCost[ctype][band].Costs[ctx];
                        int           cost0    = ctx > 0 ? LossyUtils.Vp8BitCost(1, p.Probabilities[0]) : 0;
                        int           costBase = LossyUtils.Vp8BitCost(1, p.Probabilities[1]) + cost0;
                        int           v;
                        table.Costs[0] = (ushort)(LossyUtils.Vp8BitCost(0, p.Probabilities[1]) + cost0);
                        for (v = 1; v <= MaxVariableLevel; ++v)
                        {
                            table.Costs[v] = (ushort)(costBase + VariableLevelCost(v, p.Probabilities));
                        }

                        // Starting at level 67 and up, the variable part of the cost is actually constant
                    }
                }

                for (int n = 0; n < 16; ++n)
                {
                    for (int ctx = 0; ctx < WebpConstants.NumCtx; ++ctx)
                    {
                        Vp8CostArray dst = this.RemappedCosts[ctype][n].Costs[ctx];
                        Vp8CostArray src = this.LevelCost[ctype][WebpConstants.Vp8EncBands[n]].Costs[ctx];
                        src.Costs.CopyTo(dst.Costs.AsSpan());
                    }
                }
            }

            this.Dirty = false;
        }
Пример #6
0
 // Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability.
 private static int BranchCost(int nb, int total, int proba) => (nb * LossyUtils.Vp8BitCost(1, (byte)proba)) + ((total - nb) * LossyUtils.Vp8BitCost(0, (byte)proba));