Search code examples
vb.netmemory-leakscameraaforge

RAM usage increasing when reading frames from camera


I'm making some tests with AForge library. I'm trying to read data coming from my usb camera(frames). It works very nice but the only problem is the RAM. It leaks. It seems taht a frame takes ~30 KB but the used memory keeps increasing.

Here's my code:

Imports AForge
Imports AForge.Controls
Imports AForge.Video
Imports AForge.Video.DirectShow
Imports System.Threading
Imports System.IO
Imports System.Collections.Concurrent
Imports System.ComponentModel

Public Class Form1
    Dim sources As New FilterInfoCollection(FilterCategory.VideoInputDevice)
    Dim WithEvents device As VideoCaptureDevice
    Dim count As Long, bit As Bitmap
    Dim read As New Thread(AddressOf read_que)
    Dim pic_que As New ConcurrentQueue(Of Bitmap)


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For Each cam As FilterInfo In sources
            ComboBox1.Items.Add(cam.Name)
        Next
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        device = New VideoCaptureDevice(sources(ComboBox1.SelectedIndex).MonikerString)
        AddHandler device.NewFrame, new Video.NewFrameEventHandler(AddressOf frame)

        device.WaitForStop()
        device.Start()
    End Sub

    Sub frame(obj As Object, args As NewFrameEventArgs)
        If bit IsNot Nothing Then
            bit.Dispose()
            bit = Nothing
        End If
        bit = New Bitmap(args.Frame)

        If PictureBox1.Image IsNot Nothing Then
            PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image.Dispose()))
        End If

        PictureBox1.Image =bit ' or ... = Imaging.Image.Clone(args.Frame)

    End Sub
End Class

I tried even to put all the frames in a concurrent queue and then in a separate thread to read it(I posted the simplified version that seems to take the least ram memory). But there's another problem (this is not that important): when I start the app the picturebox is blanck and the used ram is 16 MB (constant-so it doesn't work).

Only when I enter task manager and I press End Process(without actually closing it) it starts showing the frames. I thing it's GUI related(when I press the End Process maybe it fires an event that starts the frame-reading class?). enter image description here

Only at random times it seems to work from the first time(it's true that it might be the camera's problem because it old and works only on XP so I had to use .NET Framework 4).

Where is the problem(the priority is the ram leakeage)?


Solution

  • Solved it. Thanks for all your help but I knew that my code was working(I used before a delegate to draw on picture box so it was thread-safe-the code I provided was "quick and dirty"). The problem was...the VM. I was testing the code on a VM. It works on a normal PC.

    The code looks now like this:

    Imports AForge
    Imports AForge.Controls
    Imports AForge.Video
    Imports AForge.Video.DirectShow
    Imports System.Threading
    Imports System.IO
    Imports System.Collections.Concurrent
    Imports System.ComponentModel
    
    Public Class Form1
        Dim sources As New FilterInfoCollection(FilterCategory.VideoInputDevice)
        Dim device As VideoCaptureDevice
        Delegate Sub lp(ByRef pic As Bitmap)
        Delegate Sub lpp(nr As Integer, nr2 As Integer)
        Delegate Sub slp()
        Dim count As Long, bit As Bitmap
        Dim read As New Thread(AddressOf read_que)
        Dim pic_que As New ConcurrentQueue(Of Bitmap)
    
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            For Each cam As FilterInfo In sources
                ComboBox1.Items.Add(cam.Name)
            Next
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            device = New VideoCaptureDevice(sources(ComboBox1.SelectedIndex).MonikerString)
            AddHandler device.NewFrame, new Video.NewFrameEventHandler(AddressOf frame)
    
            'device.WaitForStop()
            device.Start()
    
            'read.IsBackground = True
            'read.Start()
        End Sub
    
        Sub frame(obj As Object, args As NewFrameEventArgs)
            'If bit IsNot Nothing Then
            '    bit.Dispose()
            '    bit = Nothing
            'End If
            'bit = New Bitmap(args.Frame)
    
            If PictureBox1.Image IsNot Nothing Then
                PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image.Dispose()))
            End If
    
            PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image = Imaging.Image.Clone(args.Frame))) 'Imaging.Image.Clone(args.Frame) ' or ...=bit
        End Sub
    End Class