Click here to Skip to main content
Click here to Skip to main content

DirectShow MediaPlayer in C#

By , 16 Dec 2003
 

Sample Image

Introduction

Since this is my first article on The Code Project, I would like to apologize for my bad English. It is based only on some "school english" and a few words which I snapped during my leisure job as a Ski Instructor and a Rafting Guide during my education.

I hope everyone can understand this article. Still if questions should exist, I will gladly answer these. And if someone should find some errors, please send me the correct version of the wrong text - thanks for the help when improving my English knowledge spoke ;-).

So, let's start...

This small sample program shows, how simple it is to play a video or an audio track with DirectShow and C#.

The program uses the following controls: MainMenu, ToolBar, StatusBar, Panel, ImageList, and a Timer.

Many of the properties are set using the designer, so I would suggest that you download the project, unless of course you are not a beginner.

On the other side, the sample program includes the DirectShow Interface to play videos or audio tracks.

The program demonstrates the following

  • How to select a media file on the disk, using the OpenFileDialog instance class.
  • How to enable or disable the buttons of the ToolBar Control.
  • How to change the text in the StatusBar Control.
  • How to use a basic Timer.
  • How to use the Events of the Timer Control.
  • How to use the Events of the MainMenu Control.
  • How to use the Events of the ToolBar Control.
  • How to use the Events of the Windows Form.
  • How to play a media file with DirectShow.
  • How to determine, if the media file were finished played.
  • ...

The user interface

Beside the 3 buttons to play and stop a video or an audio track, there are also a menu option to select the desired media file. So, before you can play the desired media file you have to open this file with the "File -> Open..." Command in the MainMenu Control. If the file was duly loaded, it can be played now with the "Play" Button in the ToolBar Control. During playing the video or the audio track, the application shows the current position and the duration of the media file in the StatusBar Control. If the media file were finished played, you can restart playing the media file with the "Play" Button. To select another media file, you can use the "File -> Open..." Command of the MainMenu Control.

The user interface - ToolBar The user interface - MainMenu

With the "Info" Command of the MainMenu Control the Info-Dialog of the application will be displayed.

The Info Dialog

The DirectShow Interface:

To play videos or audio files we use the DirectShow Component of the DirectX Package. With the DirectShow Interface it is very simple to play a video or an audio file, most of the work is doing the Interface for you. You only have to setting up the Interface and calling the Interface methods with the correct parameters.

DirectShow Overview

Unfortunately .NET and C# is not an officially supported platform for DirectX development and will not be until DirectX 9 is released at the end of the year. However we can use DirectX with C# in the meantime by using the Visual Basic type library's that come with version 7 and 8 of the API. This article demonstrate how to use the DirectX VB Type Lib in C#.

Before we can begin a .NET DirectShow application we need to create a reference to the DirectShow COM DLL. So, copy the "Interop.QuartzTypeLib.dll" DLL into your project folder and add a reference to this DLL. In Visual Studio.NET this is done by choosing Add Reference from the project menu. As next choose the "Browse..." Button of the Add reference Dialog and select the DirectShow COM DLL.

The Add Reference Dialog

So, after the reference to the DirectShow COM DLL is created add the following code line to your project, to make the DirectShow Interface Classes visible.

using QuartzTypeLib;

The Code

How to select the media file and create the DirectShow Interface?

After the user pressed the "File -> Open..." Command of the MainMenu Control, a "Open File" Dialog is shown and the user can select the desired media file. In C# this is done by creating a instance of the OpenFileDialog class and call the ShowDialog() function.

OpenFileDialog openFileDialog = new OpenFileDialog();

openFileDialog.Filter = "Media Files|*.mpg;*.avi;*.wma;*.mov;" + 
                        "*.wav;*.mp2;*.mp3|All Files|*.*";

if (DialogResult.OK == openFileDialog.ShowDialog())
{
    .
    .
    .

After the user terminated the dialog with OK, we begin to create the DirectShow Interface and to render the selected media file.

This is done in three steps:

DirectShow Overview

  1. Create the filter graph manager (FGM)
  2. Create the filter graph (through FGM)
  3. Run the graph and respond to event

In the following code you see how to create the filter graph manager and the filter graph:

CleanUp();

m_objFilterGraph = new FilgraphManager();
m_objFilterGraph.RenderFile(openFileDialog.FileName);

m_objBasicAudio = m_objFilterGraph as IBasicAudio;

try
{
	m_objVideoWindow = m_objFilterGraph as IVideoWindow;
	m_objVideoWindow.Owner = (int) panel1.Handle;
	m_objVideoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;
	m_objVideoWindow.SetWindowPosition(panel1.ClientRectangle.Left,
		panel1.ClientRectangle.Top,
		panel1.ClientRectangle.Width,
		panel1.ClientRectangle.Height);
}
catch (Exception ex)
{
	m_objVideoWindow = null;
}

m_objMediaEvent = m_objFilterGraph as IMediaEvent;

m_objMediaEventEx = m_objFilterGraph as IMediaEventEx;
m_objMediaEventEx.SetNotifyWindow((int) this.Handle, WM_GRAPHNOTIFY, 0);

m_objMediaPosition = m_objFilterGraph as IMediaPosition;

m_objMediaControl = m_objFilterGraph as IMediaControl;

With the CleanUp() method we try to delete the old interfaces, if someone exists. Before we can start to render the file we have to create an new instance of the FilterGraphManager with the new method. The RenderFile() method builds a filter graph that renders the specified file. The IBasicAudio Interface is to set the volume and the balance of the sound. With the IVideoWindow Interface you can set the window style, the owner window and the position of video window. This functions are enclosed by a try because, if you render a audio file and you try to set the owner window the method throws an exception. So, to play a audio track we don't need the IVideoWindow Interface and we set the m_objVideoWindow member to null. The IMediaEvent and the IMediaEventEx Interface serves for interception of message, which sends DirectShow to the parent window. With the IMediaPosition Interface the current position of the file can be determined. To start and stop the video or the audio track we use the IMediaControl Interface.

For more information about the Interface read the DirectShow documentation on MSDN.

How to play a media file?

The Play Button

To start a video or an audio track use the Run() method of the IMediaControl Interface.

m_objMediaControl.Run();

How to break the media file?

The Pause Button

If you want to break the playing video or audio track just use the Pause() method of the IMediaControl Interface.

m_objMediaControl.Pause();

How to stop the media file?

The Stop Button

To stop the video or the audio track use the Stop() method of the IMediaControl Interface.

m_objMediaControl.Stop();

How to get the position and the duration of the media file?

The StatusBar

While the media file is played, we indicate the current position and the length of the file in the StatusBar Control. In addition we read all 100ms the CurrentPosition member of the IMediaPosition Interface over a timer and represent its value in the statusbar. To get the length of the file we read the Duration member of the IMediaPosition Interface.

private void timer1_Tick(object sender, System.EventArgs e)
{
    if (m_CurrentStatus == MediaStatus.Running)
    {
        UpdateStatusBar();
    }
}

The timer function calls every 100ms the UpdateStatusBar() method, who is displaying the current position and and the duration of the media files in the panels of the statusbar.

private void UpdateStatusBar()
{
    switch (m_CurrentStatus)
    {
        case MediaStatus.None   : statusBarPanel1.Text = "Stopped"; break;
        case MediaStatus.Paused : statusBarPanel1.Text = "Paused "; break;
        case MediaStatus.Running: statusBarPanel1.Text = "Running"; break;
        case MediaStatus.Stopped: statusBarPanel1.Text = "Stopped"; break;
    }

    if (m_objMediaPosition != null)
    {
        int s = (int) m_objMediaPosition.Duration;
        int h = s / 3600;
        int m = (s  - (h * 3600)) / 60;
        s = s - (h * 3600 + m * 60);

        statusBarPanel2.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);

        s = (int) m_objMediaPosition.CurrentPosition;
        h = s / 3600;
        m = (s  - (h * 3600)) / 60;
        s = s - (h * 3600 + m * 60);

        statusBarPanel3.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);
    }
    else
    {
        statusBarPanel2.Text = "00:00:00";
        statusBarPanel3.Text = "00:00:00";
    }
}

When is the end of the file reached?

In order to determine, when the file was finished played, we overwrite the WndProc method, to intercept the EC_COMPLETE message, which sends DirectShow to the parent window, when the end of the file is reached.

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_GRAPHNOTIFY)
    {
        int lEventCode;
        int lParam1, lParam2;

        while (true)
        {
            try
            {
                m_objMediaEventEx.GetEvent(out lEventCode,
                    out lParam1,
                    out lParam2,
                    0);

                m_objMediaEventEx.FreeEventParams(lEventCode, lParam1, lParam2);

                if (lEventCode == EC_COMPLETE)
                {
                    m_objMediaControl.Stop();
                    m_objMediaPosition.CurrentPosition = 0;
                    m_CurrentStatus = MediaStatus.Stopped;
                    UpdateStatusBar();
                    UpdateToolBar();
                }
            }
            catch (Exception)
            {
                break;
            }
        }
    }

    base.WndProc(ref m);
}

History

  • 19.07.2002 - posted (first version)
  • 26.07.2002 - some changes in design and code

Links

Bugs and comments

If you have any comments or find some bugs, I would love to hear about it and make it better.

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

About the Author

Daniel Strigl
Austria Austria
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalvideo result is noise how should i domemberMember 428602626 Aug '10 - 2:28 
when I try it the video result is noise in full screen mode but in window media player movie picture is smooth. How should I do.
 
Thnks
Generalvolume control in intervallsmembergulagos13 Aug '10 - 13:24 
hi,
i would like to change volume by an interval of 500 on each designated keyevent. here's what i tried:
 
public partial class Form1 : Form
 
private IBasicAudio sound = null;
public int cvl = -5000; //(CurrentVolumeLevel)
...
if (e.KeyData == Keys.Up)

if (cvl < 0)
sound.Volume = cvl+500;
 
if (e.KeyData == Keys.Down)
 
if (cvl > -10000)
sound.volume = cvl-500;
 
I think this only assigns the values -4500 and -5500 each time i hit up or down. But i also tried:
...
static void louder(int mInt) //my interval
mInt = mInt + 500;
 
static void quiter(int mInt)
mInt = mInt - 500;
...
if (e.KeyData == Keys.Up)
 
if (cvl < 0)
sound.Volume = louder(cvl);
...
in this case i get the error "cannot convert type 'void' to 'int'". i am new to programming so maybe there is a simple solution to that. i hope it's understandable what i'm trying to do and i am very thankful for any help.
greetz gulagos
GeneralLoop VideomemberKeith Bertolino22 May '10 - 11:35 
Can anyone tell me how to have the video auto-start itself after its done playing? Is there a loop option?
GeneralException HRESULT : 0x80040255memberLefebvreOli5 Mar '10 - 0:15 
Hi,
I have an exception in "m_objFilterGraph.RenderFile(openFileDialog.FileName);"
HRESULT : 0x80040255.
I can read the incriminated file with any other player however...
Any idea ?
Thanks
GeneralRe: Exception HRESULT : 0x80040255memberMember 740216628 Jun '11 - 10:30 
I had this problem too, the issue for me was some missing codecs. Installing [this codec pack] solved the problem for me.
GeneralHellomembergigo 29 Feb '10 - 4:30 
How I can play backward and forward in c# player.please give me the code project.
but this player I made in using QuartzTypeLib .please help me.
GeneralRe: Hellomembercool_kp24 Mar '12 - 7:46 
If you got this solution, pls rply me I also need it.
QuestionURL code?memberpapand138 Jan '10 - 11:05 
What is the code for changing the URL by the use of a button?
 
For an example if you were using the windows media component it would be something like this:
 
axWindowsMediaPlayer1.URL = "C:/users/public/videos/sample videos/example.wmv";
 
So i tried to figure it out for this but i couldn't.
AnswerRe: URL code?membermehdi357619 May '10 - 23:15 
you have to use of this code:
axWindowsMediaPlayer1.URL = "C://users//public//videos//sample videos//example.wmv";
Generalsome mp3s not playingmembergl_media12 Oct '09 - 22:38 
Hi,
 
i cannot hear audio with directshow on some mp3s - I don't know whats wrong with this mp3s since other software like winamp, windows media player, VLC, Cool Edit is playing them right - also WindowsMedia.NET Library plays them - but DShow does not! Not with Quartz.dll as shown in your article, and neither with DirectShow.NET.
 
The Problem appears on different pcs with different mp3 archives.
 
Anyone had this problem yet?
 
Greetings
GeneralRe: some mp3s not playingmemberMichael900019 Jan '10 - 21:38 
Yes, also with commercial apps.
 
DirectShow can have problems decoding Mp3's, if the bitrates is higher than 192kbps. The used encoder has to follow the Standard (IIRC it was called something like 'strict iso' in a older version of ?lame?).
 
Also bad(or big) ID3-tags can create problems.
 
A possible (not so clean) workaround for some mp3's, where the position increases and you don't hear anything, is to change the position
mediaControl.Run();
mediaPosition.put_CurrentPosition(0.01);
 

Edit:
WinAmp/CoolEdit/Audition uses it's own mp3-decoder - not the one that comes with Windows.
GeneralTo play video using direct show in .netmembersarithads28 Sep '09 - 19:37 
Hi..., I am trying to play video using directshow in .net. I am trying to develop the smart device application in .net. I used the code as follows:
 

m_objFilterGraph = new FilgraphManager();
m_objFilterGraph.RenderFile(openFileDialog.FileName);
 
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
 

it throws an exception while rendering a file saying no such interfaces found... i am very new to this field.. please help me in this regard...
 
thanks in advance
GeneralGive Strong Namememberdivyesh143231 Jul '09 - 19:22 
Hi,
 
I want to give strong name to DirectShow dll. I have created the signed file but it is throwing error like Interop.QuartzTypeLib.dll does not have strong name !
 
How can I give strong name to pre-compiled dll ?
 
Thanks & Best Regards,
Divyesh Chapaneri
GeneralRe: Give Strong NamememberMystery12317 Nov '09 - 22:22 
Hi,
 
it has been a time since you've asked, but maybe for someone else, who will search for answer:
 
Use ILDASM (typically located in c:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin\) to decompile Interop.Quartztypelib.dll , choose File->Dump. Leave all details untouched and name it QuartzTypeLib.il.
 
Two files are generated: QuartzTypeLib.il and QuartzTypeLib.res.
 
Now you have to use ILASM tool (without D) located typically in c:\Windows\Microsoft.NET\Framework\v2.0.50727\. Use this command:
 
ilasm /key:keypair.snk /dll /resource:QuartzTypeLib.res QuartzTypeLib.il
 
Keypair.snk is your key pair for strong assemblies.
 
Hope this helps...
 
Michal

GeneralVideo Overlaymemberi-developer of Istanbul15 Jun '09 - 22:04 
Hi,
 
I have an application which push videos to Windows Media Services using Windows SDK. I want to put logos on my vidoes live stream. Is that possible with DirectShow and it's yes then how ?
 
Thanks in advance.
 
®esult ++

GeneralOperations on playing videomemberanki1232 Dec '08 - 23:21 
Hi
 
I want to perform some operations on playing video like Forward &
Rewind.
How can i do this?
 
Thanks
GeneralHere is One FREE, RTSP DirectShow Source Filter with full source codememberGUI Developer26 Oct '08 - 4:52 
Hi,
 
There are several free for commercial use, published RTSP DirectShow Source Filters, with full source code in C++. i must admit that it took a LOT of searching to find them!
 
I will tell you about one that I think is the best. Look at the source code for VLC (VideoLAN) and pull out the files:
 
access.c
real.c
rtsp.c
rtsp.h
 
That's all you need.
 
Look at the sample Microsoft has for a source filter for DirectShow and add these files and compile and VIOLA! you have a DirectShow Source Filter that will play any RTSP stream !!!
 
It's easy to compile this in Visual Studio 6.0--it will compile in later versions of VisualStudio but you have to know what you are doing and you have to tweek the code.
 
This makes it easy to use DirectShow to play RTSP streams from ip cameras.
 
I am amazed that nobody has posted this code before.
 
Enjoy
 
www.SlickSkins.net GUI Guy

Questionduration is not correct if playing a vbr mp3membergl_media24 Sep '08 - 0:02 
Hi,
 
it's great and helped me in getting started with directshow and c#. Thank you!
 
I recognized that if you are playing vbr (variable bitrate) mp3s, the duration is not correct.
 
It shows a longer time than the file can play. This makes it hard to do some action at a fixed time before the end of the audiofile. (I wanna do a crossfade to the next player instance 10 seconds before the file in the player ends).
 
Anyone solved this problem?
 
Thanks in advance!
Generalcompact frameworkmemberMember 210738620 Jun '08 - 20:36 
hey, can I use this code on compact framework for smart devices?!?
GeneralMuliplt Sample Grabbermemberkazim bhai11 Jun '08 - 5:40 
I am using Buffer CB function using two sample Grabber objects,
How may I know the buffer called is video or Audio as I want to process both of them while redering one file with both audio and Video.
 
Thanks in Advance
 
It is Kazim

GeneralRe: Muliplt Sample GrabbermemberMember 374705815 Jul '10 - 2:02 
As I know the sampel grabber recives an object of IMediaSampel you could get the Media Type from it and know what data you are proccesing
Questionhow to control soundmemberMember 353117223 Apr '08 - 22:15 
hoow do i control sound in this application directshow
AnswerRe: how to control soundmembersuperbem17 Jun '08 - 13:11 
That's a mute:
 
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
try { m_objBasicAudio.Volume = -10000; }catch{}
 
That's max vol:
 
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
try { m_objBasicAudio.Volume = 0; }catch{}
QuestionRe: how to control soundmemberstu__pearce9 Jul '08 - 12:12 
what if there are multiple audio tracks i.e. multiple sound renderers, how do i adjust individually ?
GeneralEnglish hintmemberSentonal20 Mar '08 - 15:23 
"thanks for the help when improving my English knowledge spoke Wink | ;-) . "
 
Should be written
 
"Thanks for any help in improving my written English."
OR
"Thank you in advance for helping me with my written English." (a bit more formal)
OR
"I would appricate any help in improving my English."
 
I didnt see anyone mentioning the grammer issues, so I figured I would mention them. Although your statement was understandable from a readability standpoint, it was not proper english.
 
GREAT ARTICLE!!!! Thank you for the article and for the tips, also for taking the time to show the technique to everyone. Your article helped me a great deal.

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 17 Dec 2003
Article Copyright 2002 by Daniel Strigl
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid