Reputation: 2020
I am trying to write the captured video to a file using VideoWriter and Capture from emguCV, the problem is: If i playback the video that I have just recorded it plays to fast or to slow. How can i fix this, so the video I record will be playbacked/recorded in realtime, so not to slow or to fast?
this is my code:
Capture capture = new Capture();
VideoWriter vw;
Size ms_hd_cam_5000_resolution = new Size(1280, 720);
Label width_label, height_label, recordingTime;
Button record;
Thread isRecording;
Image<Bgr, byte> imageFrame;
int seconds;
int minutes;
public Form1()
{
InitializeComponent();
InitializeConrols();
//Cam_Properties
capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, 1280);
capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, 720);
capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS, 30);
//VideoWriting_Properties
vw = new VideoWriter("test.avi", 30, ms_hd_cam_5000_resolution.Width, ms_hd_cam_5000_resolution.Height, true);
}
private void InitializeConrols()
{
this.BackColor = Color.Black;
this.ClientSize = new Size(ms_hd_cam_5000_resolution.Width + 25, ms_hd_cam_5000_resolution.Height + 75);
this.Picture_box.Size = ms_hd_cam_5000_resolution;
width_label = new Label();
width_label.Location = new Point(10, ms_hd_cam_5000_resolution.Height + 15);
width_label.ForeColor = Color.White;
width_label.Text = "width: " + capture.Width.ToString();
height_label = new Label();
height_label.Location = new Point(10, ms_hd_cam_5000_resolution.Height + 40);
height_label.ForeColor = Color.White;
height_label.Text = "height: " + capture.Height.ToString();
recordingTime = new Label();
recordingTime.Location = new Point(225, ms_hd_cam_5000_resolution.Height + 40);
recordingTime.ForeColor = Color.White;
recordingTime.Text = "time: 0";
record = new Button();
record.Location = new Point(225, ms_hd_cam_5000_resolution.Height + 15);
record.ForeColor = Color.White;
record.Text = "record";
Controls.Add(width_label);
Controls.Add(height_label);
Controls.Add(record);
Controls.Add(recordingTime);
record.Click += Record_Click;
}
private void Form1_Load(object sender, EventArgs e)
{
captureCamImage(sender, e);
Application.Idle += captureCamImage;
}
private void Record_Click(object sender, EventArgs e)
{
if (isRecording == null)
{
recordingTime.Text = "Time: 0";
record.Text = "stop";
isRecording = new Thread(this.Record);
isRecording.Start();
}
else
{
record.Text = "record";
isRecording = null;
}
}
private void captureCamImage(object sender, EventArgs e)
{
imageFrame = capture.QueryFrame();
Picture_box.Image = imageFrame.ToBitmap();
recordTime();
}
private void recordTime()
{
recordingTime.Text = "Time: " + minutes.ToString() + " : " + seconds.ToString();
}
private void Record()
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Reset();
stopWatch.Start();
while (isRecording != null)
{
seconds = stopWatch.Elapsed.Seconds;
minutes = stopWatch.Elapsed.Minutes;
vw.WriteFrame(imageFrame);
Thread.Sleep(1000 / 30);
}
}
Upvotes: 0
Views: 3442
Reputation: 706
Code makes no sense. Hooking to Application.Idle
is not a good idea.
Throw code to garbage, have 1 recording thread that capture.QueryFrame()
and saves it immediately.
Hell don't even bother with a thread use a timer, set it according to FPS. It won't be exact but better than what you have now.
Upvotes: 0
Reputation: 31
Try reducing the FPS value.In
vw = new VideoWriter("test.avi", 30, ms_hd_cam_5000_resolution.Width, ms_hd_cam_5000_resolution.Height, true);
Instead of 30 frames/sec provide a lower value.
Upvotes: 3