C# (Aforge.Video) MJPEGStream and high disk space consuming - c#

I have following code:
MJPEGStream stream = new MJPEGStream("http://192.168.88.252/cgi-bin/mjpeg?resolution=1920x1080&quality=1&page=1517608886020&Language=0");
stream.NewFrame += Stream_NewFrame;
stream.Start();
and
private void Stream_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
Bitmap bitmap = eventArgs.Frame.Clone() as Bitmap;
pictureBox1.Image = bitmap;
}
catch (Exception e)
{
}
}
Is there any chance that the stream is leaking? I realized that disk space on C drive (Windows) is disapearing very quick. I know that is possible by stream, but how to clear reference or clear that data from temp files? GC.Collect seems to be not working. If I close the stream all that space is back again. I'm stuck at this problem...
I found 4 files in location C:\Windows\Temp that named httC18F.tmp, httBD96.tmp, httC411.tmp, httBDE5.tmp and there are increasing itself weight (starts at 31 MB per file, then after while 255 MB...)

You have to dispose the current Image you have in the picture box before replacing it, this way :
pictureBox1.Image.Dispose();
pictureBox1.Image = bitmap;
Please ensure to have a default Image in your picturebox first to avoid Image to be null at the very first frame.

Related

How to load image in RichTextBox more effective?

I am drag and drop a heavy image (95729 kb) in my RichTextBox. But memory usage is so incomprehensible: Why it stores more than 700 mb?
My Drag and Drop code:
private void RtbEditor_PreviewDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
if (files != null && files.Length > 0)
{
foreach (var file in files)
{
// Filter out non-image files.
if (IsValidImageFile(file))
{
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(file, UriKind.Absolute);
bitmap.EndInit();
Image image = new Image();
image.Source = bitmap;
var container = new InlineUIContainer(image, rtbEditor.CaretPosition);
rtbEditor.CaretPosition = container.ElementEnd;
}
}
}
}
}
For image check, I took only image header: Check only header What am I doing wrong?
This heavy image probably has an enormous resolution and uses a format like PNG or JPEG. These formats compress the pixel data to make the final file size smaller. However, in order to render an image, the renderer needs to decompress the image into actual pixels with (A)RGB values.
An uncompressed 3000x3000 image with 32 bits per pixel weighs in at ~ 36 MB. So your image must be even larger.
Why do you want to render such a large image in a textbox anyway?
You definitely don't need that much of pixels. Just set BitmapImage.DecodePixelHeight or BitmapImage.DecodePixelHeight to appropriate value between BitmapImage.BeginInit() and BitmapImage.BeginInit(). And don't set both unless you don't care about original aspect ratio.

WriteVideoFrame() with Videocodec.Raw change pixel value

I'm using Accord.Video.ffmpeg to record a video in c#. It is actually a depth video with pixels indicating the depth magnitude. From depth array I create a bitmap and the save the bitmap with WriteVideoFrame method.
Afterward, I open the video in Matlab reading frame by frame. The problem is that I have differences between the bitmap in c# and the frame in Matlab?! The difference is more or less of 10 (in a range of 255 it's a big deal)(testing at the moment if it's constant).
Since from the bitmap to videoframe I do not perform any operation I think that the problem is in the video encoder. Is is possible even though the format is Raw?!
Hints?
Alex
UPDATE
If I run this code in a new project everything is fine
unsafe private void Button_Click_1(object sender, RoutedEventArgs e)
{
writerdepth.Open("testvideo.avi", 512, 424, 15, VideoCodec.Raw);
for (int i = 0; i <depthPixels.Length; i++)
{
this.depthPixels[i] = (byte)100;
}
try
{
fixed (byte* p = depthPixels)
{
IntPtr unmanagedPointer = (IntPtr)p;
depthbm = new Bitmap(512, 424, 512, System.Drawing.Imaging.PixelFormat.Format8bppIndexed, unmanagedPointer);
}
}
catch (Exception ex)
{
Debug.WriteLine("Errore");
}
writerdepth.WriteVideoFrame(depthbm);
writerdepth.Close();
}
}
going back to my code when I try to read the image instead of RGB = [100 100 100] I have [96 94 99].
My starting code is saving depth image from kinect v2, the function is called when a new valid frame arrives.
I have no idea of the reason for this difference...
Solved... was the Nuget package I had version 3.4.2-alpha in the older project (strange behavior) and new 3.5.0 is the last one (working). Updating the package solved the problem

How can we capture and save in local disk with Aforge video?

I want to save video which capturing from webcam into local disk. I wrote code it shows webcam but It can't save into local disk. The error is Failed creating compressed stream.. What should I do in here?
writer = new AVIWriter("wmv3");
writer.FrameRate = 30;
writer.Open("video.avi", Convert.ToInt32(640), Convert.ToInt32(480)); // ERROR İS HERE **Failed creating compressed stream.**
//Create NewFrame event handler
//(This one triggers every time a new frame/image is captured
videoSource.NewFrame += new AForge.Video.NewFrameEventHandler(videoSource_NewFrame);
//Start recording
videoSource.Start();
}
}
void videoSource_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
//Cast the frame as Bitmap object and don't forget to use ".Clone()" otherwise
//you'll probably get access violation exceptions
pictureBoxVideo.BackgroundImage = (Bitmap)eventArgs.Frame.Clone();
writer.AddFrame((Bitmap)eventArgs.Frame.Clone());
}
Have you ever consider the size of the stream of your webcam? I have the same problem, too. I know you set your video size into 640 and 480, but the video stream size which comes from your webcam(I guess) would be never the same. I also guess you set your container such as picturebox or imagebox into 640 and 480, but that doesn't mean the video stream would be the same. I use savedialog to check the video stream that comes out of my webcam, and guess what? The size would be (648, 486). Who would ever set such a strange number set? But I set my code into this :
writer.Open("video.avi", Convert.ToInt32(648), Convert.ToInt32(486));
And it works fine!
I do not know the rest of your code is correct or not, but I'm sure my bug is in the set of size :)
Four years later I'm having this same issue. After hours I figured out if I didn't specify wmv3 for the codec and just left it blank writer = new AVIWriter(); then everything worked.
AVIWriter write = new AVIWriter();
write.Open("newTestVideo.avi", Convert.ToInt32(320), Convert.ToInt32(240));
Bitmap bit = new Bitmap(320, 240);
for (int tt = 0; tt < 240; tt++) {
bit.SetPixel(tt, tt, System.Drawing.Color.FromArgb((int)(UnityEngine.Random.value * 255f), (int)(UnityEngine.Random.value * 255f), (int)(UnityEngine.Random.value * 255f)));
write.AddFrame(bit);
}
write.Close();

Picturebox getting big red X but I can't detect or fix it

I am currently working with AForge, and have an on new frame event that posts the frame, as a bitmap, into a picturebox. 90% of the time it works great... UNLESS I fiddle with something on the winform. Changing a combo box, moving the window, or anything like that risks causing the Picturebox to switch from the video to a big red X. Code sample below:
private void connectButton_Click(object sender, EventArgs e)
{
try
{
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);
cam.Start();
}
catch
{
MessageBox.Show("An error has occured with connecting to the specified webcam. The application will now close!");
Application.Exit();
}
}
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
try
{
if (bitmap != null)
bitmap.Dispose(); //Without this, memory goes nuts
bitmap = new Bitmap(eventArgs.Frame);
}
catch { }
//Draw some stuff on the images
bitmap = AdjustBrightness(bitmap, brightnessMeter);
bitmap = ApplyContrast(contrastMeter, bitmap);
bitmap = Draw_Top_Line(bitmap);
bitmap = Draw_Bottom_Line(bitmap);
//Set the image into the picturebox
this.Invoke((MethodInvoker)delegate
{
videoPictureBox1.Image = bitmap;
frameRate++; //Keep track of the frame rate
});
GC.Collect(); //Without this, memory goes nuts
this.Invoke((MethodInvoker)delegate {
videoPictureBox1.Refresh(); //NOT NECESSARY. JUST TRYING TO FIX THE BIG RED X!
});
if (videoPictureBox1.Image == videoPictureBox1.ErrorImage)
{
cam.Stop(); //ALSO NOT NECESSARY> AGAIN, JUST TRYING TO FIX THE BIG RED X!
cam.Start();
}
}
I put a break on the if (videoPictureBox1.Image == videoPictureBox1.ErrorImage) and it is evaluating to false, even when the big red X is up, because the image is actually being set to the bitmap. So cam.Stop() and cam.Start() never run (not sure if that would even help, but I figured I would give it a try).
videoPictureBox1.Refresh() is running every time, but again- it's not making a difference. Still have the big red X.
As I said before: if I start the video and touch nothing, the big red X will never happen. But the moment I start changing combo boxes, or dragging the form itself around, the chance of the big red X goes up exponentially. Sometimes I can flip through the combo box 10-12 times before it happens, other times it happens the second I click the combobox. :-\
Can anyone explain what is happening here and perhaps offer a suggestion on the best method to go about fixing it? I'm still very new to threading, so I've been struggling to wrap my head around exactly what is happening here and the best way to fix the issue! Any nudges in the right direction would be a huge help!
In the end, I wrapped EVERYTHING in in the Handle_New_Frame in an invoke. It completely removed the big red X issue, permanently. >_>
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
this.Invoke((MethodInvoker)delegate
{
try
{
if (bitmap != null)
{
bitmap.Dispose(); //Without this, memory goes nuts
}
bitmap = new Bitmap(eventArgs.Frame);
}
catch { }
//Draw some stuff on the images
bitmap = AdjustBrightness(bitmap, brightnessMeter);
bitmap = ApplyContrast(contrastMeter, bitmap);
bitmap = Draw_Top_Line(bitmap);
bitmap = Draw_Bottom_Line(bitmap);
//Set the image into the picturebox
this.Invoke((MethodInvoker)delegate
{
videoPictureBox1.Image = bitmap;
frameRate++; //Keep track of the frame rate
});
GC.Collect(); //Without this, memory goes nuts
});
}
Shawn Hargreaves has an excellent, concise writeup of the "big red X of doom". I found it very helpful in the general case of dealing with WinForm components suddenly showing the red "X".
In summary:
This is caused by a control throwing an exception out of the OnPaint event.
Once it is thrown, that control will continue to show the red X and skip firing OnPaint.
To debug, set the debugger to catch Common Language Runtime Exceptions, and then do whatever you normally do to get the red X. The debugger will stop right where it is happening, allowing you to investigate and hopefully figure out a way to prevent it.
try using the clone in places where you use the bitmap.
Ex:
videoPictureBox1.Image = (Bitmap)bitmap.Clone();
Just to sum it up, this is a tested bare minimum that shows no red cross for me, even when resized, started, stoped or resolution changed.
public partial class PictureBoxVideo : Form
{
public PictureBoxVideo()
{
InitializeComponent();
var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
var videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoSource.NewFrame += Handle_Very_New_Frame;
videoSource.Start();
}
private void Handle_Very_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
this.Invoke((MethodInvoker)delegate {
pictureBox.Image = new Bitmap(eventArgs.Frame);
});
}
}
Please note, that we call videoSource.Start(); from the GUI-(creation)-thread, but the call back handler (Handle_Very_New_Frame) is called from the video (worker) thread.
I think that's why we need both, the Invoke and the new Bitmap, so the new bmp will also be generated from the gui-thread. But I'm just guessing here, as I couldn't come up with a proof.

MediaLibrary.SavePicture fails when fed with a used stream

I need to save the photo that was captured with the CameraCaptureTask, in the Media Library of the phone, and at the same time I want to show this photo in an Image control. The thing is that I first try to rotate the image by accessing its Exif data, so as it appears with the correct orientation in the Image control.
private void cameraTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
int angle = GetAngleFromExif(e.ChosenPhoto);
WriteableBitmap currentImage = DecodeImage(e.ChosenPhoto, angle);
photoImage.Source = currentImage;
MediaLibrary medialibrary = new MediaLibrary();
medialibrary.SavePicture("test.jpg", e.ChosenPhoto);
}
}
The code crashes in the last line, with the error:
Value does not fall within the expected range.
What is possibly going wrong here?
Thank you in advance.
Before calling the SavePicture method, you should set the Stream back at the beginning, like this:
e.ChosenPhoto.Seek(0, System.IO.SeekOrigin.Begin);

Categories

Resources