public unsafe static void Decode(NvdecDevice device, ResourceManager rm, ref NvdecRegisters state) { PictureInfo pictureInfo = rm.Gmm.DeviceRead <PictureInfo>(state.SetPictureInfoOffset); EntropyProbs entropy = rm.Gmm.DeviceRead <EntropyProbs>(state.SetVp9EntropyProbsOffset); ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size) { return(rm.Cache.Get(_decoder, CodecId.Vp9, lumaOffset, chromaOffset, size.Width, size.Height)); } ISurface lastSurface = Rent(state.SetSurfaceLumaOffset[0], state.SetSurfaceChromaOffset[0], pictureInfo.LastFrameSize); ISurface goldenSurface = Rent(state.SetSurfaceLumaOffset[1], state.SetSurfaceChromaOffset[1], pictureInfo.GoldenFrameSize); ISurface altSurface = Rent(state.SetSurfaceLumaOffset[2], state.SetSurfaceChromaOffset[2], pictureInfo.AltFrameSize); ISurface currentSurface = Rent(state.SetSurfaceLumaOffset[3], state.SetSurfaceChromaOffset[3], pictureInfo.CurrentFrameSize); Vp9PictureInfo info = pictureInfo.Convert(); info.LastReference = lastSurface; info.GoldenReference = goldenSurface; info.AltReference = altSurface; entropy.Convert(ref info.Entropy); ReadOnlySpan <byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetBitstreamOffset, (int)pictureInfo.BitstreamSize); ReadOnlySpan <Vp9MvRef> mvsIn = ReadOnlySpan <Vp9MvRef> .Empty; if (info.UsePrevInFindMvRefs) { mvsIn = GetMvsInput(rm.Gmm, pictureInfo.CurrentFrameSize, state.SetVp9LastFrameMvsOffset); } int miCols = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Width, 8); int miRows = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Height, 8); using var mvsRegion = rm.Gmm.GetWritableRegion(ExtendOffset(state.SetVp9CurrFrameMvsOffset), miRows * miCols * 16); Span <Vp9MvRef> mvsOut = MemoryMarshal.Cast <byte, Vp9MvRef>(mvsRegion.Memory.Span); uint lumaOffset = state.SetSurfaceLumaOffset[3]; uint chromaOffset = state.SetSurfaceChromaOffset[3]; if (_decoder.Decode(ref info, currentSurface, bitstream, mvsIn, mvsOut)) { SurfaceWriter.Write(rm.Gmm, currentSurface, lumaOffset, chromaOffset); device.OnFrameDecoded(CodecId.Vp9, lumaOffset, chromaOffset); } WriteBackwardUpdates(rm.Gmm, state.SetVp9BackwardUpdatesOffset, ref info.BackwardUpdateCounts); rm.Cache.Put(lastSurface); rm.Cache.Put(goldenSurface); rm.Cache.Put(altSurface); rm.Cache.Put(currentSurface); }
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); }