0

With this code i can play video files from my hard disk and show the video in pictureBox1. But i wonder how can i save all the frames of the video to images files on the hard disk ? While playing the video or without playing i need somehow to extract the frames and save them.

This is my used code so far:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        IGraphBuilder m_graphBuilder = null;
        IMediaControl m_mediaCtrl = null;
        IMediaEventEx m_mediaEvt = null;
        IMediaPosition m_mediaPos = null;
        IMediaSeeking m_mediaSeeking = null;

        public Form1()
        {
            InitializeComponent();
        }

        void InitInterfaces()
        {
            try
            {
                m_graphBuilder = (IGraphBuilder)new FilterGraph();
                m_mediaCtrl = (IMediaControl)m_graphBuilder;
                m_mediaEvt = (IMediaEventEx)m_graphBuilder;
                m_mediaPos = (IMediaPosition)m_graphBuilder;
                m_mediaSeeking = (IMediaSeeking)m_graphBuilder;
            }
            catch (Exception)
            {
                MessageBox.Show("Couldn't start directshow graph");
            }
        }


        void CloseInterfaces()
        {
            if (m_mediaCtrl != null)
            {
                m_mediaCtrl.StopWhenReady();
            }
            m_mediaCtrl = null;
            m_mediaEvt = null;
            m_mediaPos = null;

            m_mediaSeeking = null;

            if (m_graphBuilder != null)
                Marshal.ReleaseComObject(this.m_graphBuilder);
            m_graphBuilder = null;
        }   


        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void SetuupVideoRenderer()
        {
            IBaseFilter vmrFilter = null;

            vmrFilter = (IBaseFilter)new VideoMixingRenderer();
            m_graphBuilder.AddFilter(vmrFilter, "Video Renderer");

            IVMRFilterConfig FilterConfig = (IVMRFilterConfig)vmrFilter;
            FilterConfig.SetRenderingMode(VMRMode.Windowless);

            IVMRWindowlessControl windowlessCtrl = (IVMRWindowlessControl)vmrFilter;
            windowlessCtrl.SetVideoClippingWindow(this.pictureBox1.Handle);
            windowlessCtrl.SetVideoPosition(null, DsRect.FromRectangle(pictureBox1.ClientRectangle));
            windowlessCtrl.SetAspectRatioMode(VMRAspectRatioMode.LetterBox);

        }
        private void buttonLoad_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "All Files (*.*)|*.*|mp4 (*.mp4)|*.mp4|mov (*.mov)|*.mov||";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                CloseInterfaces();
                InitInterfaces();

                SetuupVideoRenderer();
                m_graphBuilder.RenderFile(openFileDialog1.FileName, null);

                textBoxDur.Text = ( getDuration() * 0.0000001).ToString();
                m_mediaCtrl.Run();

                timer1.Enabled = true;

            }
        }

        private void GetPosition(out long CurrentPos,out long StopPos)
        {

            m_mediaSeeking.GetPositions(out CurrentPos, out StopPos);

        }
        private long getDuration()
        {
            long duration;
            m_mediaSeeking.GetDuration(out duration);

            return duration;

        }

        private void SetPos(double fPos)
        {
             DsLong startPosition = (DsLong)(10000000 * fPos); 

            m_mediaSeeking.SetPositions(startPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);


        }
        private void buttonPause_Click(object sender, EventArgs e)
        {
            m_mediaCtrl.Pause();
        }

        private void buttonPlay_Click(object sender, EventArgs e)
        {
            m_mediaCtrl.Run();

        }
        private void OnVideoCompleted()
        {
            MessageBox.Show("Video Playback Completed");
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            long iCurPos, iStopPos;

            GetPosition(out iCurPos, out iStopPos);

            if (iCurPos >= iStopPos)
            {
                timer1.Enabled = false;
                OnVideoCompleted();
                return;
            }
            textBoxCurPos.Text = (iCurPos * 0.0000001 ).ToString();


        }

        private void buttonGo_Click(object sender, EventArgs e)
        {
            SetPos(Convert.ToDouble(textBoxNewPos.Text));
            timer1.Enabled = true;
        }
    }
}
L. Guthardt
  • 1,990
  • 6
  • 22
  • 44
Farud Sam
  • 15
  • 5
  • What have you tried on ur own so far? – L. Guthardt Oct 30 '17 at 08:36
  • @L.Guthardt not much since i'm new to directshowlib. So far i just tried to check all the variables global variables like m_mediaSeeking and m_mediaPos but you can get only information with it. I also tried to make pictureBox1.Image.Save....inside a timer or when start playing but it seems not logic to play it and then save the images from the pictureBox1. if i have a video of an hour it will take a lot of time to save all frames. – Farud Sam Oct 30 '17 at 08:40
  • @L.Guthardt Not sure even where to start. Let's say it's possible but i'm not sure how to start. – Farud Sam Oct 30 '17 at 08:41

1 Answers1

0

I think this is excatly what you are looking for: extract frames of a video

Have a look as well at this SO question and the links provided on this webpage.

The easiest way to do it is indeed using an FFMPEG, since its alredy includes some of the most common codecs (if you dont mind extra 30+Mb added to your app). As for wrappers, i used AForge wrapper in the past and really liked it, because of how simple it is to work with. Here is an example from its docs:

// create instance of video reader
VideoFileReader reader = new VideoFileReader();

// open video file
reader.Open( "test.avi");

// read 100 video frames out of it
for ( int i = 0; i < 100; i++)
{
    Bitmap videoFrame = reader.ReadVideoFrame();

    videoFrame.Save(i + ".bmp")

    // dispose the frame when it is no longer required
    videoFrame.Dispose( );
}

reader.Close();
L. Guthardt
  • 1,990
  • 6
  • 22
  • 44