Beispiel #1
0
        private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
        {
            int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].ToSpan());

            if (!xd.Counts.IsNull)
            {
                ++xd.Counts.Value.InterMode[ctx][mode];
            }

            return(PredictionMode.NearestMv + mode);
        }
Beispiel #2
0
        private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
        {
            PredictionMode yMode = ReadIntraMode(ref r, cm.Fc.Value.YModeProb[sizeGroup].ToSpan());

            if (!xd.Counts.IsNull)
            {
                ++xd.Counts.Value.YMode[sizeGroup][(int)yMode];
            }

            return(yMode);
        }
Beispiel #3
0
        private static PredictionMode ReadIntraModeUv(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, byte yMode)
        {
            PredictionMode uvMode = ReadIntraMode(ref r, cm.Fc.Value.UvModeProb[yMode].ToSpan());

            if (!xd.Counts.IsNull)
            {
                ++xd.Counts.Value.UvMode[yMode][(int)uvMode];
            }

            return(uvMode);
        }
Beispiel #4
0
        private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId)
        {
            int x, y;

            Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);

            for (y = 0; y < yMis; y++)
            {
                for (x = 0; x < xMis; x++)
                {
                    cm.CurrentFrameSegMap[miOffset + y * cm.MiCols + x] = (byte)segmentId;
                }
            }
        }
Beispiel #5
0
        private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr <byte> segmentIds, int miOffset, int xMis, int yMis)
        {
            int x, y, segmentId = int.MaxValue;

            for (y = 0; y < yMis; y++)
            {
                for (x = 0; x < xMis; x++)
                {
                    segmentId = Math.Min(segmentId, segmentIds[miOffset + y * cm.MiCols + x]);
                }
            }

            Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
            return(segmentId);
        }
Beispiel #6
0
        private static TxSize ReadTxSize(ref Vp9Common cm, ref MacroBlockD xd, bool allowSelect, ref Reader r)
        {
            TxMode    txMode    = cm.TxMode;
            BlockSize bsize     = xd.Mi[0].Value.SbType;
            TxSize    maxTxSize = Luts.MaxTxSizeLookup[(int)bsize];

            if (allowSelect && txMode == TxMode.TxModeSelect && bsize >= BlockSize.Block8x8)
            {
                return(ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r));
            }
            else
            {
                return((TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]));
            }
        }
Beispiel #7
0
        public static int GetReferenceModeContext(ref Vp9Common cm, ref MacroBlockD xd)
        {
            int ctx;

            // Note:
            // The mode info data structure has a one element border above and to the
            // left of the entries corresponding to real macroblocks.
            // The prediction flags in these dummy entries are initialized to 0.
            if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
            {  // both edges available
                if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
                {
                    // Neither edge uses comp pred (0/1)
                    ctx = (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef ? 1 : 0) ^
                          (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef ? 1 : 0);
                }
                else if (!xd.AboveMi.Value.HasSecondRef())
                {
                    // One of two edges uses comp pred (2/3)
                    ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock() ? 1 : 0);
                }
                else if (!xd.LeftMi.Value.HasSecondRef())
                {
                    // One of two edges uses comp pred (2/3)
                    ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
                }
                else  // Both edges use comp pred (4)
                {
                    ctx = 4;
                }
            }
            else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
            {  // One edge available
                ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;

                if (!edgeMi.HasSecondRef())
                {
                    // Edge does not use comp pred (0/1)
                    ctx = edgeMi.RefFrame[0] == cm.CompFixedRef ? 1 : 0;
                }
                else
                {
                    // Edge uses comp pred (3)
                    ctx = 3;
                }
            }
Beispiel #8
0
        private static void CopySegmentId(
            ref Vp9Common cm,
            ArrayPtr <byte> lastSegmentIds,
            ArrayPtr <byte> currentSegmentIds,
            int miOffset,
            int xMis,
            int yMis)
        {
            int x, y;

            for (y = 0; y < yMis; y++)
            {
                for (x = 0; x < xMis; x++)
                {
                    currentSegmentIds[miOffset + y * cm.MiCols + x] = (byte)(!lastSegmentIds.IsNull ? lastSegmentIds[miOffset + y * cm.MiCols + x] : 0);
                }
            }
        }
Beispiel #9
0
        private static void SetMvs(ref Vp9Common cm, ReadOnlySpan <Vp9MvRef> mvs)
        {
            if (mvs.Length > cm.PrevFrameMvs.Length)
            {
                throw new ArgumentException($"Size mismatch, expected: {cm.PrevFrameMvs.Length}, but got: {mvs.Length}.");
            }

            for (int i = 0; i < mvs.Length; i++)
            {
                ref var mv = ref cm.PrevFrameMvs[i];

                mv.Mv[0].Row = mvs[i].Mvs[0].Row;
                mv.Mv[0].Col = mvs[i].Mvs[0].Col;
                mv.Mv[1].Row = mvs[i].Mvs[1].Row;
                mv.Mv[1].Col = mvs[i].Mvs[1].Col;

                mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
                mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
            }
Beispiel #10
0
        private static TxSize ReadSelectedTxSize(ref Vp9Common cm, ref MacroBlockD xd, TxSize maxTxSize, ref Reader r)
        {
            int ctx = xd.GetTxSizeContext();
            ReadOnlySpan <byte> txProbs = GetTxProbs(ref cm.Fc.Value, maxTxSize, ctx);
            TxSize txSize = (TxSize)r.Read(txProbs[0]);

            if (txSize != TxSize.Tx4x4 && maxTxSize >= TxSize.Tx16x16)
            {
                txSize += r.Read(txProbs[1]);
                if (txSize != TxSize.Tx8x8 && maxTxSize >= TxSize.Tx32x32)
                {
                    txSize += r.Read(txProbs[2]);
                }
            }

            if (!xd.Counts.IsNull)
            {
                ++GetTxCounts(ref xd.Counts.Value, maxTxSize, ctx)[(int)txSize];
            }

            return(txSize);
        }
Beispiel #11
0
        public unsafe bool Decode(
            ref Vp9PictureInfo pictureInfo,
            ISurface output,
            ReadOnlySpan <byte> bitstream,
            ReadOnlySpan <Vp9MvRef> mvsIn,
            Span <Vp9MvRef> mvsOut)
        {
            Vp9Common cm = new Vp9Common();

            cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
            cm.IntraOnly = pictureInfo.IntraOnly;

            cm.Width        = output.Width;
            cm.Height       = output.Height;
            cm.SubsamplingX = 1;
            cm.SubsamplingY = 1;

            cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;

            cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;

            cm.BaseQindex = pictureInfo.BaseQIndex;
            cm.YDcDeltaQ  = pictureInfo.YDcDeltaQ;
            cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
            cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;

            cm.Mb.Lossless = pictureInfo.Lossless;
            cm.Mb.Bd       = 8;

            cm.TxMode = (TxMode)pictureInfo.TransformMode;

            cm.AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv;

            cm.InterpFilter = (byte)pictureInfo.InterpFilter;

            if (cm.InterpFilter != Constants.Switchable)
            {
                cm.InterpFilter = LiteralToFilter[cm.InterpFilter];
            }

            cm.ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode;

            cm.CompFixedRef = pictureInfo.CompFixedRef;
            cm.CompVarRef   = pictureInfo.CompVarRef;

            cm.Log2TileCols = pictureInfo.Log2TileCols;
            cm.Log2TileRows = pictureInfo.Log2TileRows;

            cm.Seg.Enabled        = pictureInfo.SegmentEnabled;
            cm.Seg.UpdateMap      = pictureInfo.SegmentMapUpdate;
            cm.Seg.TemporalUpdate = pictureInfo.SegmentMapTemporalUpdate;
            cm.Seg.AbsDelta       = (byte)pictureInfo.SegmentAbsDelta;
            cm.Seg.FeatureMask    = pictureInfo.SegmentFeatureEnable;
            cm.Seg.FeatureData    = pictureInfo.SegmentFeatureData;

            cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
            cm.Lf.RefDeltas           = pictureInfo.RefDeltas;
            cm.Lf.ModeDeltas          = pictureInfo.ModeDeltas;

            cm.Fc     = new Ptr <Vp9EntropyProbs>(ref pictureInfo.Entropy);
            cm.Counts = new Ptr <Vp9BackwardUpdates>(ref pictureInfo.BackwardUpdateCounts);

            cm.FrameRefs[0].Buf = (Surface)pictureInfo.LastReference;
            cm.FrameRefs[1].Buf = (Surface)pictureInfo.GoldenReference;
            cm.FrameRefs[2].Buf = (Surface)pictureInfo.AltReference;
            cm.Mb.CurBuf        = (Surface)output;

            cm.Mb.SetupBlockPlanes(1, 1);

            int tileCols = 1 << pictureInfo.Log2TileCols;
            int tileRows = 1 << pictureInfo.Log2TileRows;

            // Video usually have only 4 columns, so more threads won't make a difference for those.
            // Try to not take all CPU cores for video decoding.
            int maxThreads = Math.Min(4, Environment.ProcessorCount / 2);

            cm.AllocTileWorkerData(_allocator, tileCols, tileRows, maxThreads);
            cm.AllocContextBuffers(_allocator, output.Width, output.Height);
            cm.InitContextBuffers();
            cm.SetupSegmentationDequant();
            cm.SetupScaleFactors();

            SetMvs(ref cm, mvsIn);

            fixed(byte *dataPtr = bitstream)
            {
                try
                {
                    if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
                    {
                        DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr <byte>(dataPtr, bitstream.Length), maxThreads);
                    }
                    else
                    {
                        DecodeFrame.DecodeTiles(ref cm, new ArrayPtr <byte>(dataPtr, bitstream.Length));
                    }
                }
                catch (InternalErrorException)
                {
                    return(false);
                }
            }

            GetMvs(ref cm, mvsOut);

            cm.FreeTileWorkerData(_allocator);
            cm.FreeContextBuffers(_allocator);

            return(true);
        }
Beispiel #12
0
 private static int ReadIntraSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, ref Reader r)
 {
     ref Segmentation seg = ref cm.Seg;