I'm currently using AForge dll to render the video on the picture box for the live view. I do have a video frame function to whether WriteFrame or Screenshot the current picturebox frame as a JPG.
But i met a problem when sometime the program will prompt out an error of Parameter is not valid or Object is been used elsewhere. I did try to find solution to solve it and i pretty sure i did dispose on the image and the clone image, but the problem still exist.
Could you assist me on what i had done wrong with my program?
void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
//your code using bmp object
if (D1Pic.BackColor == Color.Green)
{
video = (Bitmap)eventArgs.Frame.Clone();
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); }));
}
livePreview.Image = (Bitmap)eventArgs.Frame.Clone();
imgclone = (Image)livePreview.Image.Clone();
FileWriter.WriteVideoFrame(video);
}
else
{
video = (Bitmap)eventArgs.Frame.Clone();
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); }));
this.Invoke(new MethodInvoker(delegate() { video.Dispose(); }));
}
livePreview.Image = (Bitmap)eventArgs.Frame.Clone();
imgclone = (Image)livePreview.Image.Clone();
}
video.Dispose();
livePreview.Refresh();
Here are the stack trace error :
{"Parameter is not valid."}
at System.Drawing.Image.get_Width()
at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
UPDATED CODE :
var newFrame = (Bitmap)eventArgs.Frame.Clone();
this.Invoke(new MethodInvoker(delegate()
{
if (livePreview.Image != null)
{
livePreview.Image.Dispose();
}
livePreview.Image = newFrame;
}));
imgclone = (Bitmap)eventArgs.Frame.Clone();
//Write frame into video
if (D1Pic.BackColor == Color.Green)
{
video = (Bitmap)eventArgs.Frame.Clone();
FileWriter.WriteVideoFrame(video);
}
You are calling livePreview.Image.Dispose()
in the UI thread, but you're not setting livePreview.Image
to null afterwards.
So between the time that you dispose livePreview.Image
and the time that you assign a new image to it, livePreview.Image
points to a disposed object.
So I think occasionally your picturebox tries to draw itself during this time, and fails when it attempts to access its (disposed) Image property.
The solution would be:
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() {
livePreview.Image.Dispose();
livePreview.Image = null;
}));
}
Or even better, assign the new image in the same step:
var newFrame = (Bitmap)eventArgs.Frame.Clone();
this.Invoke(new MethodInvoker(delegate() {
if (livePreview.Image != null)
{
livePreview.Image.Dispose();
}
livePreview.Image = newFrame;
}));
In general, you need to understand what's happening with your various Bitmap objects. Anything that keeps a reference to a Bitmap that has been disposed will be a problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With