BogdanovKirill / RtspClientSharp

Pure C# RTSP client for .NET Standard without external dependencies and with true async nature. I welcome contributions.
MIT License
706 stars 284 forks source link

Memory leak when open 10+ rtsp video #40

Closed wangning08115 closed 4 years ago

wangning08115 commented 5 years ago

Describe the bug I have 100+ rtsp source. I will show 9 rtsp videos on WPF UI once. When after 5 seconds will show next 9 rtsp videos on WPF UI. Repeat the above steps. When after 30min, Memory leak. I see memory in Windows TaskManager ,It's going up. I use memory tools see : the unmanaged memory is going up.

Whenn stop the all rtsp videos, The unmanaged memory is not release.

Screenshots image

image

Desktop (please complete the following information): Windows 10 OS

This is my stop every video code: _rawFramesSource.Stop(); _realtimeVideoSource.SetRawFramesSource(null); _rawFramesSource = null;

i think i cant release all memory use this code. can you help me?

wangning08115 commented 5 years ago

@BogdanovKirill can you help me.

wangning08115 commented 5 years ago

And some more info: When start them WPF Demo.

The init unmanaged memory is 66MB

1 Open one rtsp video:

unmanaged memory is 138MB

2 Close video:

unmanaged memory is 77MB

3 After 5 min, Open one rtsp video:

unmanaged memory is 187MB

4 Close video:

unmanaged memory is 91MB

Open once the unmanaged memory going up, And then will going up to more an more.
Memory leak.

BogdanovKirill commented 5 years ago

Hello,

If I understand correctly your problem is connected with code responsible for display only? Can you see this problem if only frame receiving + frame decoding are enabled (without display)?

BogdanovKirill commented 5 years ago

Any news?

wangning08115 commented 5 years ago

I'm sorry for not giving you timely feedback on the problem.

Thanks for your replay. I'm currently working on other bugs in the system. I'm not sure yet this problem is lead by FFMPEG decode. I will try only frame receiving + frame decoding are enabled (without display) to research this problem. If get any more info ,i will tell you. Very thanks for you.

BogdanovKirill commented 5 years ago

Any news or we could close that ?

BogdanovKirill commented 4 years ago

Please reopen if you will find exact problem

zoekatakuzinos commented 7 months ago

Hi @BogdanovKirill

I am also wondering about this memory leak issue. I am using the decoding github project "rtspcapture - working" which gives me the SnapshotMaker example. I changed it to a Winforms project so I could stream to a picture box, and then take a snapshot, and put it in another picture box.

I commented out the ToImage() function so I took out all displaying of Images in my picture boxes. The memory seems more stable.

My memory spikes up when taking shapshots, even though I am clearing my Picture Boxes. As I take more snapshots, the memory climbs higher.

It never come down, even when calling the GC explicitly. I am not sure how to clean up ? Can you help?

(This code comes from my crude test program)

    private void OnFrameReceived(object sender, RawFrame rawFrame)
    {
        if (!(rawFrame is RawVideoFrame rawVideoFrame))
            return;

        FFmpegVideoDecoder decoder = GetDecoderForFrame(rawVideoFrame);
        if (!decoder.TryDecode(rawVideoFrame, out DecodedVideoFrameParameters decodedFrameParameters))
            return;

        int bufferSize;

        bufferSize = decodedFrameParameters.Height *
                     ImageUtils.GetStride(decodedFrameParameters.Width, RawFramesDecoding.PixelFormat.Abgr32);

        if (_decodedFrameBuffer.Length != bufferSize)
            _decodedFrameBuffer = new byte[bufferSize];

        var bufferSegment = new ArraySegment<byte>(_decodedFrameBuffer);

        var postVideoDecodingParameters = new PostVideoDecodingParameters(RectangleF.Empty,
            new Size(decodedFrameParameters.Width, decodedFrameParameters.Height),
            ScalingPolicy.Stretch, RawFramesDecoding.PixelFormat.Bgr24, ScalingQuality.Bicubic);

        IDecodedVideoFrame decodedFrame = decoder.GetDecodedFrame(bufferSegment, postVideoDecodingParameters);

        //ArraySegment<byte> frameSegment = decodedFrame.DecodedBytes;
        //string snapshotName = decodedFrame.Timestamp.ToString("O").Replace(":", "_") + ".jpg";

        //ToImage(decodedFrameParameters.Width, decodedFrameParameters.Height, snapshotName, System.Drawing.Imaging.PixelFormat.Format24bppRgb, frameSegment.Array);

    }

    private void ToImage(int Width, int Height, string imgName, System.Drawing.Imaging.PixelFormat pixelFormat, byte[] rgbValues)
    {
        Bitmap bitMap = new Bitmap(Width, Height, pixelFormat);

        Rectangle BoundsRect = new Rectangle(0, 0, Width, Height);

        BitmapData bitmapData = bitMap.LockBits(BoundsRect, ImageLockMode.WriteOnly, bitMap.PixelFormat);

        IntPtr _dataPointer = bitmapData.Scan0;

        int _byteData = bitmapData.Stride * bitMap.Height;

        System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, _dataPointer, _byteData);

        bitMap.UnlockBits(bitmapData);

        if (pictureBox1.Image != null)
        {
            pictureBox1.Image.Dispose();
            pictureBox1.Image = null;
        }

        pictureBox1.Image = bitMap;
        pictureBox1.Refresh();

        if (MustTakeSnapshot)
        {
            Thread t = new Thread(new ParameterizedThreadStart(TakeSnapshot));
            t.Start(bitMap);
        }
    }

    private void TakeSnapshot(object bitMap)
    {

        Bitmap b = (Bitmap)bitMap;

        ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

        System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.Quality;

        EncoderParameters encoderParams = new EncoderParameters(1);

        EncoderParameter myEncoderParameter = new EncoderParameter(encoder, 50L);

        encoderParams.Param[0] = myEncoderParameter;

        string filename = @"c:\capture\frame" + DateTime.Now.Millisecond.ToString();
        b.Save(filename, jgpEncoder, encoderParams);

        if (pictureBox2.Image != null)
        {
            pictureBox2.Image.Dispose();
            pictureBox2.Image = null;
        }

        pictureBox2.Image = Image.FromFile(filename);

        b.Dispose();
        b = null;
        bitMap = null;

        MustTakeSnapshot = false;
    }