Пример #1
0
        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);
        }
Пример #2
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);
        }