0

I have a C# Visual Studio WinForms .NET app that plays video using the QuartzTypeLib (quartz.dll). With the code I've written, I can play any video file from the hard drive.

Here's the code at the top that executes when the app starts:

    public const int WS_CHILD = 0x40000000;
    public const int WS_CLIPCHILDREN = 0x2000000;
    public QuartzTypeLib.IMediaControl mc;
    public QuartzTypeLib.IVideoWindow videoWindow = null;
    IMediaPosition mp = null;

And here's the code that opens the video file:

    private void openMediaToolStripMenuItem_Click(object sender, EventArgs e)
    {
        // Open a media file.
        OpenFileDialog ofd = new OpenFileDialog();
        ofd.Filter = "Video Files|*.mpg;*.avi;*;*.wmv;*.mov";
        ofd.FilterIndex = 1;
        if (DialogResult.OK == ofd.ShowDialog())
        { 
            // Stop the playback for the current movie if a video is currently playing.
            if (mc != null)
                mc.Stop();
            if (pbVideoDisplay.Image != null)
                pbVideoDisplay.Image = null;
            // Load the movie file.
            FilgraphManager graphManager = new FilgraphManager();
            graphManager.RenderFile(ofd.FileName);
            mp = graphManager as IMediaPosition;
            mc = (IMediaControl)graphManager;
            tsbtnPlay.Enabled = tsbtnPause.Enabled = tsbtnStop.Enabled = true;

            // Attach the view to the picture box (pbVideoDisplay) on frmMain.
            try
            {
                videoWindow = (IVideoWindow)graphManager;
                videoWindow.Owner = (int)pbVideoDisplay.Handle;
                videoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;
                videoWindow.SetWindowPosition(
                pbVideoDisplay.ClientRectangle.Left,
                pbVideoDisplay.ClientRectangle.Top,
                pbVideoDisplay.ClientRectangle.Width,
                pbVideoDisplay.ClientRectangle.Height);
            }
            catch //(Exception Ex)
            {
                // I'll write code for this when I have a need to.
            }
            // Now we convert the video to a byte array.
            FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
            try
            {
                // Here we convert the video to Base 64.
                VideoInBytes = new byte[fs.Length];
                VideoInBytes = System.Text.Encoding.UTF8.GetBytes(ofd.FileName);
                VideoInBase64 = Convert.ToBase64String(VideoInBytes);
            }
            catch //(Exception Ex)
            {
                //throw new Exception("Error in base64Encode" + Ex.Message);
            }
        }
    }

Notice that I have code that converts the video to a Base64 string. This string will obviously have to be loaded into a memory stream. I'd like to add code that will allow me to play a video from a memory stream. Is that even possible with DirectShow and if so, what code would I need to add and where would I put it?

manicdrummer
  • 161
  • 3
  • 14
  • 1
    Why would you do this, if you have the file on your harddisk? Anyway here is a similar question and an answer: ["Rendering from memory using DirectShow"](http://stackoverflow.com/questions/24476826/rendering-from-memory-using-directshow) – CPlusSharp Mar 04 '15 at 05:43
  • Thanks for your reply, CPlusSharp. The reason I want to play a video from a memory stream is because I have to store the video as a Base64 string. the video and a whole mess of other data must be saved into a single binary file so they can be uploaded and downloaded to/from various locations. I'll check out the link you provided. Thanks for the link too! – manicdrummer Mar 04 '15 at 18:12
  • The way I would do this: pack the video and your metadata as a zip-file and extract it temporary on the client side. Base64 encoding a video needs more space (x 1.333)! – CPlusSharp Mar 05 '15 at 07:26

1 Answers1

2

The DirectShow way is to create a special so-called filter (source filter) that outputs video data and then add it to the graph chain.

Usually a filter is written in C++. Of course almost any code that can be written in C++ can be rewritten in C#. It could take a lot of work, for instance look at this article:

http://www.codeproject.com/Articles/421167/Pure-NET-DirectShow-Filters-in-Csharp

Another way is file emulation. In this case you would need 3rd party solution like BoxedApp.

The idea is to intercept some file functions like SetFilePointer and ReadFile, to provide data as it is written from a real file (but in fact it is read from memory).

Artem Razin
  • 1,234
  • 8
  • 22