2013-04-15 3 views
9

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

Проблема: у меня ОГРОМНАЯ утечка памяти. Когда я запускаю видео только с помощью videoSourcePlayer, он колеблется при использовании около 30 мегабайт. Когда я запускаю растягивание кадров в виде растровых изображений, он прерывает 1 гигабайт памяти за считанные секунды.

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

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; 
} 
+8

'Bitmap' является' IDisposable' – I4V

+0

Просто быстрое предположение: возможно, событие Handle New Frame? он клонирует кадр, сколько раз и как быстро вызывается это событие? – Max

+0

Я принимаю в каждом кадре, поэтому максимум (на основе аппаратного обеспечения) 15 раз в секунду. Я проверю и удостоверьтесь, хотя –

ответ

2

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

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

+0

Awesome! Это должно помочь кучу! Тем не менее, я столкнулся с одной проблемой: получение ошибки поперечного потока в файле videoPictureBox1.Image.Dispose(). «Неверная операция поперечного потока: управление« videoPictureBox1 »осуществляется из потока, отличного от потока, на котором он был создан.» –

+0

Вы столкнулись с этой проблемой, когда вы работали с этим, случайно? –

+0

ах, да, вам нужно использовать Invoke. Я отредактировал свой ответ, поэтому он должен исправить ошибку поперечного потока. –

2

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

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; 

И ВПодключение обработчик событий, сделать это:

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

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

+0

Примечание: это только одна область кода, в которой я вижу очевидную утечку. Учитывая, что утечка памяти существенна, вы также должны посмотреть, как размещается битмап. – code4life

+0

Удивительный! Спасибо за эту информацию. И да, ваше предположение верно - я использую 4.5 –