MediaShow






3.69/5 (7 votes)
Oct 11, 2007
2 min read

48913

2881
An article on ‘MediaShow,’ a media player based on the famous DirectShow multimedia API from Microsoft.

Introduction
At long last I have finally made what I have wanted to make for so long. Being new to the coding world, this media player (which I call 'MediaShow') is my first working software. It is based on the famous DirectShow multimedia API from Microsoft.
DirectShow divides the processing of multimedia tasks such as video playback into a set of steps known as filters. Each filter represents a stage in the processing of the data. Filters have a number of input and output pins which connect them together. The generic design of the connection mechanism means that filters can be connected in many different ways for different tasks to build a filter graph.
It is possible to make custom filters which can be used to play a variety of media file formats; clearly displaying the power of DirectShow API. But the complexity for customization and making filters from scratch makes the use of this API rather difficult.
Features
I used a C# example of media playback with DirectShow and modified it to suit my requirements. The following features are there in MediaShow:
- Play media/audio files (WAV, WMA, **MOV, QT, AVI, DAT, MP3, MPEG/MPG)
- Playlist in a new format(*.ms)
- Voice Recorder
- CD tray Open and Close
- Subtitles Play
- Set rate of play of file
- Single frame step which displays one frame at a time until the user presses a key to move to the next frame
- Different Screen Modes
- Volume Control
- Mute option
- Position Trackbar to jump to desired position
- Displays the total duration of file
- Displays the duration of play of file
Using the Code
The code is divided into two parts:
- First part uses directshow.dll and performs: basic media playback, set rate of play of file, single frame step, volume control, different screen modes and duration of file.
private void PlayMovieInWindow(string filename)
{
int hr = 0;
if (filename == string.Empty)
return;
this.graphBuilder = (IGraphBuilder)new FilterGraph();
// Have the graph builder construct its the appropriate graph
// automatically
hr = this.graphBuilder.RenderFile(filename, null);
DsError.ThrowExceptionForHR(hr);
// QueryInterface for DirectShow interfaces
this.mediaControl = (IMediaControl)this.graphBuilder;
this.mediaEventEx = (IMediaEventEx)this.graphBuilder;
this.mediaSeeking = (IMediaSeeking)this.graphBuilder;
this.mediaPosition = (IMediaPosition)this.graphBuilder;
// Query for video interfaces, which may not be relevant for audio files
this.videoWindow = this.graphBuilder as IVideoWindow;
this.basicVideo = this.graphBuilder as IBasicVideo;
// Query for audio interfaces, which may not be relevant for
// video-only files
this.basicAudio = this.graphBuilder as IBasicAudio;
// Is this an audio-only file (no video component)?
CheckVisibility();
// Have the graph signal event via window callbacks for performance
hr = this.mediaEventEx.SetNotifyWindow(this.Handle, WMGraphNotify,
IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
if (!this.isAudioOnly)
{
this.ClientSize = new Size(379,331);
// Setup the video window
hr = this.videoWindow.put_Owner(this.Handle);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_WindowStyle(WindowStyle.Child |
WindowStyle.ClipSiblings | WindowStyle.ClipChildren);
DsError.ThrowExceptionForHR(hr);
hr = InitVideoWindow(1, 1);
DsError.ThrowExceptionForHR(hr);
GetFrameStepInterface();
}
else
{
// Initialize the default player size and enable playback menu items
hr = InitPlayerWindow();
DsError.ThrowExceptionForHR(hr);
// EnablePlaybackMenu(true, MediaType.Audio);
}
// Complete window initialization
// CheckSizeMenu(menuFileSizeNormal);
this.isFullScreen = false;
this.currentPlaybackRate = 1.0;
UpdateStatusBar();
UpdateToolStrip();
#if DEBUG
rot = new DsROTEntry(this.graphBuilder);
#endif
this.Focus();
// Run the graph to play the media file
hr = this.mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
this.currentState = PlayState.Running;
Increment.Start();
}
private void CloseClip()
{
int hr = 0;
// Stop media playback
if (this.mediaControl != null)
hr = this.mediaControl.Stop();
// Clear global flags
this.currentState = PlayState.Stopped;
this.isAudioOnly = true;
this.isFullScreen = false;
// Free DirectShow interfaces
CloseInterfaces();
// Clear file name to allow selection of new file with open dialog
this.filename = string.Empty;
// No current media state
this.currentState = PlayState.Init;
UpdateStatusBar();
UpdateToolStrip();
InitPlayerWindow();
}
private int InitVideoWindow(int nMultiplier, int nDivider)
{
int hr = 0;
int lHeight, lWidth;
if (this.basicVideo == null)
return 0;
// Read the default video size
hr = this.basicVideo.GetVideoSize(out lWidth, out lHeight);
if (hr == DsResults.E_NoInterface)
return 0;
// EnablePlaybackMenu(true, MediaType.Video);
// Account for requests of normal, half, or double size
lWidth = lWidth * nMultiplier / nDivider;
lHeight = lHeight * nMultiplier / nDivider;
if (!this.isAudioOnly)
{
panel1.Size = new Size(lWidth, lHeight);
PositionTracker.Location = new Point(0, lHeight + 52);
this.ClientSize = new Size(lWidth+1, lHeight+139);
Application.DoEvents();
hr = this.videoWindow.SetWindowPosition(panel1.Left, panel1.Top,
panel1.Width, panel1.Height);
}
return hr;
}
private void MoveVideoWindow()
{
int hr = 0;
// Track the movement of the container window and resize as needed
if (this.videoWindow != null)
{
hr = this.videoWindow.SetWindowPosition(panel1.Left,panel1.Top,
panel1.Width,panel1.Height);
DsError.ThrowExceptionForHR(hr);
}
}
private void CheckVisibility()
{
int hr = 0;
OABool lVisible;
if ((this.videoWindow == null) || (this.basicVideo == null))
{
// Audio-only files have no video interfaces. This might also
// be a file whose video component uses an unknown video codec.
this.isAudioOnly = true;
return;
}
else
{
// Clear the global flag
this.isAudioOnly = false;
}
hr = this.videoWindow.get_Visible(out lVisible);
if (hr < 0)
{
// If this is an audio-only clip, get_Visible() won't work.
//
// Also, if this video is encoded with an unsupported codec,
// we won't see any video, although the audio will work if it is
// of a supported format.
if (hr == unchecked((int)0x80004002)) //E_NOINTERFACE
{
this.isAudioOnly = true;
}
else
DsError.ThrowExceptionForHR(hr);
}
}
I could also use mciSendString
to play media/audio files but I preferred not to do so because DirectShow has the capability of playing a wider range of formats than mciSendString
.
The code on the whole is very simple to understand and well indented. But as I said before, I am new in to the field of software development and the scope of improving the quality of code is tremendous, so any suggestions regarding that would be very much appreciated.
More…
I am working on the player to make it optimized in every sense of the word. I am also trying to add better features to it. Any suggestions are most welcome. I have also have not checked for bugs which might be in the software so I request all you guys out there to please look into 'MediaShow' and please report the bugs to me.