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); }
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); }
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); }
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; } } }
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); }
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])); } }
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; } }
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); } } }
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]; }
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); }
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); }
private static int ReadIntraSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, ref Reader r) { ref Segmentation seg = ref cm.Seg;