一个用C#开发的DirectShow媒体播放器(作者:Daniel Strigl)

 
演示程序 


介绍;
由于我第一次写关于代码介绍方面的文章,请原谅我的英语很差。我只是在学校中和一些工作中接触过英文。
我希望每个人可以理解这篇文章的内容。如果有问题我很愿意解答。如果发现有错,请即使纠正-感谢帮助我学习英文;-)。
好现在开始
这个小程序演示了,用C#开发的一个DirectShow的播放软件可以播放视频和声音。
该程序包含以下控制:MainMenu, ToolBar, StatusBar, Panel, ImageList,和一个 Timer。
这些属性都是在属性栏中填好了,所以我建议你下载该项目,除非你并不是一个初学者。
另一方面,事例程序包含 DirectShow类用来播放视频和声音。

...
程序演示了以下内容:
怎样用OpenFileDialog类来在磁盘上选择一个媒体文件。
怎样激活工具栏桑的按钮。
怎样状态栏的信息。
怎样使用一个Timer控键。
怎样使用时钟控制事件。
这样使用主菜单事件。
怎样使用工具栏事件。
怎样使用窗口事件。
怎样用DirectShow播放媒体。
怎样判定媒体是否已经播放完了。

用户界面
除了3个按钮用来播放,停止视频和声音的播放,同时用菜单来选择要播放的媒体文件,所以在你要播放一个媒体文件之前,你必须打开文件在菜单"File -> Open..."下。如果文件成功加载,就可以通过按 "Play"按钮来播放。在播放过程中,程序在状态栏上显示播放进度。如果播放结束,你可以按"Play"重新播放或选择另一个文件。

 

菜单的"Info"命令用来显示信息对话框。

关于DirectShow:
我们通常用DirectShow类来播放视频和声音,它是DirectX中的一个开发工具。通过DirectShow可以非常容易的播放视频和声音文件,使用它只需要正确设置参数和方法。


不幸的是.NET和C#在DirectX中不包含官方的支持平台,所以DirectX 9中不包含DirectShow。我们用C#开发DirectX通过使用Visual Basic的类型库API版本是7到8。该文章介绍如何在C#中使用DirectX VB类库。
在开始.NET DirectShow开发之前,我们需要建立一个到DirectShow COM DLL的引用。拷贝"Interop.QuartzTypeLib.dll"到你的项目文件夹中。在 Visual Studio.NET中通过在项目菜单中选择和添加来完成。

按"Browse..." 选择DirectShow COM DLL。
using QuartzTypeLib;

关于代码:
怎样建立DirectShow并选择媒体文件?
在选择了主菜单下的"File -> Open..."后,显示"Open File"对话框然后用户可以选择一个媒体文件。在C#中通过建立一个OpenFileDialog类对象并使用ShowDialog()方法来实现。
OpenFileDialog openFileDialog = new OpenFileDialog();

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

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


在以上完成之后,我们开始建立了DirectShow并开始渲染媒体文件。
通过以下几步完成:


建立图象过滤管理(FGM)
建立图象过滤(通过FGM)
播放图象并返回事件
以下代码演示怎样建立图象过滤管理和图象过滤:
 CollapseCleanUp();

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;


 通过CleanUp()我们删除对象,如果对象存在。在我们可以开始渲染一个文件时,我们必须建立FilterGraphManager的几个新对象用新的方法。RenderFile()方法建立了一个图象过滤器用来渲染指定文件。IBasicAudio类用来设定声音的大小和质量。IVideoWindow类用来设定窗口风格,窗口位置。该函数是附加的,如果你播放声音文件,你如果调用该方法。可是播放声音文件不需要IVideoWindow类,所以将m_objVideoWindow设置成NULL。IMediaEvent和IMediaEventEx类用来侦听消息,用来发送DirectShow信息到父窗口。通过IMediaPosition类,可以设置当前的位置。通过IMediaControl类来控制开始,停止视频和声音的播放。
 想了解更多关于DirectShow的内容请读一下MSDN的文档。
怎样播放媒体文件?


用IMediaControl类的Run()方法来开始播放一个视频或声音文件。
m_objMediaControl.Run();


怎样暂停播放?


如果你想要暂停播放一个视频或声音文件,使用IMediaControl类的Pause()方法。
m_objMediaControl.Pause();


怎样停止播放?


用IMediaControl类的Stop()方法来停止播放一个视频或声音。
m_objMediaControl.Stop();

 

怎样得到文件的播放进度和持续时间?


当媒体文件被播放时,我们在状态栏指定当前的播放进度和文件长度。我们读取全部100MS内IMediaPosition类得到的当前进度并将大小显示在状态栏。为了得到文件长度我们读取了IMediaPosition类的Duration成员变量。
private void timer1_Tick(object sender, System.EventArgs e)
{
    if (m_CurrentStatus == MediaStatus.Running)
    {
        UpdateStatusBar();
    }
}


时间函数每隔100MS调用UpdateStatusBar()方法,用来显示当前位置和文件进度。
 Collapseprivate 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";
    }
}


当文件播放结束时会怎样?
为了判定,文件是在结束状态,我们重写了WndProc函数,处理EC_COMPLETE消息,当文件结束播放时,将向窗口发送DirectShow消息。
 Collapseprotected 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);
}

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值