Click here to Skip to main content
15,884,629 members
Articles / Programming Languages / C#
Article

MediaShow

Rate me:
Please Sign up or sign in to vote.
3.69/5 (7 votes)
11 Oct 20072 min read 47.9K   2.9K   34   10
An article on ‘MediaShow,’ a media player based on the famous DirectShow multimedia API from Microsoft.
Screenshot - MediaShow.jpg

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.
C#
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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCOMexception error Pin
Member 115726741-Apr-15 1:00
Member 115726741-Apr-15 1:00 
GeneralFast Forward ,Slow forward doesn't work Pin
chetan Chaudhary30-Dec-09 1:39
chetan Chaudhary30-Dec-09 1:39 
Generalplay VBR MP3s shows false length [modified] Pin
gl_media12-Aug-09 2:38
gl_media12-Aug-09 2:38 
QuestionLike to Join Efforts with Me??? Pin
Sukhjinder_K26-Oct-07 7:05
Sukhjinder_K26-Oct-07 7:05 
GeneralGetting following Error Pin
S.S.Cheral19-Oct-07 2:50
S.S.Cheral19-Oct-07 2:50 
GeneralIt doesn't work on Multi-monitor system Pin
Lev Pavlas18-Oct-07 3:59
Lev Pavlas18-Oct-07 3:59 
QuestionNice application, but how to record with it? Pin
Tongle The Great18-Oct-07 1:58
Tongle The Great18-Oct-07 1:58 
GeneralJust to let you know... Pin
98z2817-Oct-07 8:33
98z2817-Oct-07 8:33 
QuestionWhat about Windows CE? Pin
Win32nipuh16-Oct-07 7:14
professionalWin32nipuh16-Oct-07 7:14 
Hi, great code,

can it work under Windows CE?

Thanx.
GeneralCompare to ..... Pin
fwsouthern11-Oct-07 13:32
fwsouthern11-Oct-07 13:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.