Утечка памяти в коде веб-камеры [закрыто]

хорошо, я пытался сделать что-то конкретное с видеопотоком с веб-камеры. У меня есть микроскоп Lumenera Infinity 2, из которого я пытаюсь вытащить корм, и хочу иметь возможность изменять корм по мере его поступления. Поскольку я не мог найти способ сделать это с помощью видеоплеера, я решил вместо этого вытащить каждый кадр (максимум 15 кадров в секунду для камеры) в качестве растрового изображения, чтобы я мог делать там свои изменения.

проблема в том, что у меня огромная утечка памяти. Когда я запускаю видео с помощью videoSourcePlayer, он зависает при использовании около 30 мегабайт. Когда я запускаю вытягивание кадров в виде растровых изображений, он разбивает 1 гигабайт памяти за считанные секунды.

что я пропустил здесь? Я полагал, что автоматическая сборка мусора будет собирать старые кадры, когда они станут недоступными. Должен ли я попытаться принудительно собрать мусор на bitmap? Или это что-то совсем другое, и я по нему скучаю.

FilterInfoCollection captureDevices;
VideoCaptureDevice cam;
Bitmap bitmap;

public Form1()
{
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
  try
  {
    captureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

    if (captureDevices.Count == 0)
      throw new ApplicationException();

    CameraSelectComboBox.Items.Clear();

    foreach (FilterInfo device in captureDevices)
    {
      CameraSelectComboBox.Items.Add(device.Name);
    }

    CameraSelectComboBox.SelectedIndex = 0;
    CameraSelectComboBox.Enabled = true;
  }
  catch (ApplicationException)
  {
    CameraSelectComboBox.Enabled = false;
  }
}

private void connectButton_Click(object sender, EventArgs e)
{
  cam = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
  cam.NewFrame -= Handle_New_Frame; //Just to avoid the possibility of a second event handler being put on
  cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
  videoSourcePlayer1.Visible = false;
  cam.Start();

  //videoPictureBox1.Visible = false;
  //videoSourcePlayer1.VideoSource = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
  //videoSourcePlayer1.Start();
}

private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
  bitmap = (Bitmap)eventArgs.Frame.Clone();

  videoPictureBox1.Image = bitmap;
}

2 ответов


попробуйте это:

private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
    if(bitmap != null)
        bitmap.Dispose();
    bitmap = new Bitmap(eventArgs.Frame);

    if(videoPictureBox1.Image != null)
        this.Invoke(new MethodInvoker(delegate() {videoPictureBox1.Image.Dispose();}));
    videoPictureBox1.Image = bitmap;
}

он решил некоторые утечки памяти, которые я испытал с Aforge и PictureBoxes, но VideoSourcePlayer намного лучше, когда речь идет о потреблении памяти.


Я думаю, что это одна область, которая может использовать улучшение:

cam = new 
  VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);

cam.NewFrame -= Handle_New_Frame; // you're pointing to the new instance of VCD, so this will have no effect.

cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
videoSourcePlayer1.Visible = false;
cam.Start();

этот блок кода кровоточит память каждый раз, когда вы нажимаете кнопку подключения.

вам в значительной степени нужно иметь ссылку на VCD на основном уровне. Поэтому определите переменную-член на уровне класса Form1:

private VideoCaptureDevice _cameraContext;

и в обработчике событий connect сделайте следующее:

if (_camerContext != null)
{
  _cameraContext.NewFrame -= Handle_New_Frame;
}
_cameraContext = new VideoCaptureDevice(blah blah blah);
_cameraContext.NewFrame += Handle_New_Frame;
videoSourcePlayer1.Visible = false;
_cameraContext.Start();

кстати, я предполагаю, что вы .NET 3.5 или более поздняя версия, следовательно, новый синтаксис назначения делегата.