Утечка памяти в коде веб-камеры [закрыто]
хорошо, я пытался сделать что-то конкретное с видеопотоком с веб-камеры. У меня есть микроскоп 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 или более поздняя версия, следовательно, новый синтаксис назначения делегата.