Click here to Skip to main content
15,891,473 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
Hi.
I have an application that captures the video from my webcam and bufferes it using a queue. I am using aforge.net to capture the video. I have a problem with the program taking up a lot of memory. Even when the buffer is full it still continues to eat on the memory. I would think that it would stop at a certain level and stay within that since the queue never grows more than a certain threshold.

Here is some code from my program:

C#
Queue framebuffer = new Queue();

private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {

            
            
            framebuffer.Enqueue(eventArgs.Frame.Clone());
          
            if (seconds > Convert.ToInt16(toolStripTextBoxOptionsDelay.Text))
            {
                

                Bitmap bufferedframe = (Bitmap)framebuffer.Dequeue();
                bufferedframe.RotateFlip(RotateFlipType.RotateNoneFlipX);
                pictureBox.Image = bufferedframe;
                

            }
            if (stopwatch.Elapsed.Seconds > seconds)
            {
               
                Console.WriteLine("Elapsed: " + stopwatch.Elapsed + "  Frames received: " + videoSource.FramesReceived);
                Console.WriteLine("Queue size: " + framebuffer.Count+ "  Frame size: "+eventArgs.Frame.Size);
                
                seconds++;
            }
        }


Every time a new frame arrives from the webcam the "video_NewFrame" method runs. It takes that frame and queues it in "framebuffer". Then after a certain amount of seconds (5 seconds default value) I start dequeuing the buffer and displaying the frame in a pictureBox.

I expect the memory usage to grow while the queue is not being dequeued (ofcourse) but once those seconds have passed and I start dequeuing then the memory usage should stop growing, right?

Does someone have a solution for this or knows what is going on? I would also like to know if I can shrink the bitmap file before queueing it.

Thank you.
Posted
Updated 25-Mar-13 5:53am
v2
Comments
Sergey Alexandrovich Kryukov 25-Mar-13 11:51am    
Is it System.Drawing or WPF? Or something else? Tag it.
—SA
sigsand 25-Mar-13 11:55am    
Sorry.
It is a Windows Forms Application. I am using the Aforge.Controls.PictureBox to display the buffered frames and Aforge.Controls.VideoSourcePlayer to render the real time image.
Sergey Alexandrovich Kryukov 25-Mar-13 12:05pm    
Please always tag it in your question. Better do it now.
Also, you should provide fully-qualified names of types. I did not know it's AForge.Controls.PictureBox. I'll have to update my answer.
—SA

1 solution

It looks like you are using System.Drawing and System.Windows.Forms. You should always tag the libraries you use for UI and graphics.

Look at the Bitmap class. It implements System.IDisposable. It means that, whatever you do, you should eventually call System.IDisposable.Dispose for each Bitmap object when you no longer use it.

Some background:

You never need to free managed memory. It is reclaimed by a Garbage Collector. It does not mean that managed memory leak is impossible. It is possible, but it can be a result of some design bugs. Please see my past answers:
Garbage collectotion takes care of all the memory management[^],
deferring varirable inside the loop can cuase memory leak?[^],
Best way to get rid of a public static List Causing an Out of Memory[^],
Memory management in MDI forms[^].

In contrast, the unrelated System.IDisposable mechanism is designed to help the developers to guarantee that some clean up action is always called, on a universal basis. The clean up action itself can be absolutely anything. One application of it is reclaiming of unmanaged resources, which is needed for Image and many other objects, in particular, GDI, and a lot more.

Finally, your other problem is using the class PictureBox. It is poorly redundant and should be used only to simplify the simplest cases, such as showing some static image. In most more complex cases, it only presents hassles and use resources giving nothing in return. You should use your own rendering of graphics, which is really simple. Please see my past answers:
How do I clear a panel from old drawing[^],
draw a rectangle in C#[^],
Append a picture within picturebox[^].

[EDIT]

After OP's clarification:

The last paragraph above is about System.Windows.Forms.PictureBox: don't use it for anything dynamic/interactive/animated.

I did not mean AForge.Controls.PictureBox (which I did not use so far).

Again, please always provide fully-qualified type names when asking questions.

—SA
 
Share this answer
 
v2
Comments
sigsand 25-Mar-13 12:39pm    
Thank you very much for a quick and precise answer. Calling the dispose on the picture frames image before rendering another one solved the memory issue.

Now when I have 5 seconds of buffer I use around 135MB of memory and it never goes more than a few megabytes up and down.

I accept this as the solution.

I would like to further improve my application by not using Aforge.Control.PictureBox. I have read some of your links but I am not sure where to begin. Is there a simple tutorial explaining how to do display an image properly?
Sergey Alexandrovich Kryukov 25-Mar-13 12:51pm    
You are very welcome.

I did not say using AForge.Control.PictureBox. Look at its documentation and use the general ideas I explained, that's all.
I don't know why should anyone would write a tutorial just on a bitmap; just read its documentation, it should be more than enough.

Good luck, call again.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900