问题
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?
回答1:
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).
来源:https://stackoverflow.com/questions/28844658/c-sharp-how-can-i-play-a-video-from-a-memory-stream-using-directshowquartz-dll