Search code examples
c#image-processingframe-rateaforge

Decrease framerate of an AVI file in AForge


I am completely new to video input, and just started working with AForge a few days ago. Working with live video is comfortable, but I need to do something with files for a project now.

Using the Windows Media Video 9 VCM codec, saving has not been a problem. The output file works normally with every player I have, but my program always plays it back at about double the frame rate. This is especially odd since there is never any indication that the frame rate is changed: both the default the video was saved with and the new player indicate that the frame rate is 25 fps.

The only suggestions I have found are to change the frame rate before the video is captured, but this seems to do nothing.

Looking around in the AVIFileVideoSource documentation, I found the FrameIntervalFromSource and FrameInterval properties which, together, should give me the results I am looking for, but I can't get them to work, either. Everything else has been a dead end, and I am out of ideas. Here is the code that I am using to read the file:

    public partial class Form1 : Form
{
    AVIReader input = new AVIReader();
    AVIFileVideoSource source = new AVIFileVideoSource("test.avi");

    public Form1()
    {
        InitializeComponent();
    }

    public void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        input.Open("test.avi");
        for (int i = 0; i < input.Length; i++)
        {
            pictureBox1.Image = input.GetNextFrame();
        }
        source.Stop();
        input.Close();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        source.NewFrame += new NewFrameEventHandler(cam_NewFrame);
        source.Start();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        source.Stop();
        input.Close();

    }
}

Any other suggestions would be greatly appreciated. Thank you for your time.


Solution

  • I found a working solution to the problem by looking into some other areas of the library. In this solution, there were two other classes that I was overlooking: DirectShow, which was already referenced, and Control. Specifically, I needed to use instances of FileVideoSource and VideoSourcePlayer to get the video into something I could work with.

    This version is different from the above in that both the read and write functions have been combined into one program. Furthermore, I was in something of a rush to get this done, so it is still quite fragile. Nevertheless, here is my solution:

        public partial class Form1 : Form
    {
        public Bitmap newBitmap;
        public VideoCaptureDevice cam = null;
        public FilterInfoCollection usbCams;
    
        AVIReader reader = new AVIReader();
        AVIWriter writer = new AVIWriter("wmv3");
        AVIFileVideoSource source = new AVIFileVideoSource("test.avi");
    
        FileVideoSource normSource = new FileVideoSource("test.avi");
        VideoSourcePlayer player = new VideoSourcePlayer();
    
        public Form1()
        {
            InitializeComponent();
        }
    
        public void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            Bitmap image = (Bitmap)eventArgs.Frame.Clone();
            writer.AddFrame(image);
    
            pictureBox1.Image = image;
        }
    
        public void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            newBitmap = (Bitmap)eventArgs.Frame.Clone();
            pictureBox1.Image = newBitmap;
        }
    
        private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image)
        {
            videoSourcePlayer1.VideoSource = normSource;
            videoSourcePlayer1.GetCurrentVideoFrame();
    
            videoSourcePlayer1.DrawToBitmap(newBitmap,
                new Rectangle(0, 0, image.Width, image.Height));
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            source.NewFrame += new NewFrameEventHandler(video_NewFrame);
            source.Start();
            videoSourcePlayer1.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(videoSourcePlayer_NewFrame);
            videoSourcePlayer1.Start();
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
            if (source.IsRunning == true)
            {
                source.Stop();
                videoSourcePlayer1.Stop();
            }
    
            if (cam != null)
            {
                cam.Stop();
                writer.Close();
            }
        }
    
        private void button3_Click(object sender, EventArgs e)
        {
            usbCams = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            cam = new VideoCaptureDevice(usbCams[0].MonikerString);
            cam.DesiredFrameSize = new Size(320, 240);
    
            writer.Open("test.avi", 320, 240);
    
            cam.NewFrame += new NewFrameEventHandler(cam_NewFrame);
            cam.DesiredFrameRate = 25;
            cam.Start();
        }
    }
    

    Thank you for reading.