利用Visual C#开发一个媒体播放器

利用Visual C#开发一个媒体播放器

 

 

 

           

 

 

 

摘要:了解如何在 Microsoft Visual C# .NET 中使用 DirectShow 控件,如何开发一个媒体播放器。按照本文介绍的操作步骤,您可以创建一个简单 Visual C# 应用程序,用来播放数字音频和视频。

  

 

 

简介

  Microsoft Visual C# 是世界上最流行的编程语言,利用 Visual C# 的最新版本 Visual C# .NET,您能够快速、有效地开发基于 Windows 窗体的应用程序,还可以为嵌入了 Microsoft Windows Media? Player 9 Series ActiveX 控件的应用程序添加新鲜、有趣而又非常实用的功能。

  DirectShow 控件是一个标准的 ActiveX 控件,提供了大量的功能。DirectShow控件提供的功能包括:

  · 数字媒体文件和流媒体的高级播放功能。     

  · 使用播放列表的功能。
  · 播放 DVD CD 的功能。
  · 访问 Windows Media Player 中的 Media Library(媒体库)。
  · 处理元数据的功能。
  · 支持字幕。
  · 支持多种语言的音频。
  · 控制网络连通性和访问相关统计信息的功能。

  下面我们来看看构造这个媒体播放器要达到什么样的目标,确定了目标也就确定了代码量和程序的复杂程度。本文的媒体播放器要达到如下目标:

  · 是一个菜单驱动的简单AWT应用。
  · 包含一个文件菜单,文件菜单包含三个菜单项:
  · “打开,用来打开媒体文件
  · “循环,是播放一次(默认),还是重复播放。
  · “退出,退出程序
  · 可以在多种平台上运行。
  · 核心功能通过JMFJava Media FrameworkAPI实现。

  按照本文介绍的步骤,您将创建一个基于 Windows 窗体的基本应用程序,并在其中嵌入 Player 控件。您创建的示例应用程序具有如下特点:

  · 创建 DirectShow 控件的一个实例。
  · 利用 Windows Media Player 主互操作程序集提供组件对象模型 (COM) 互操作性。
  · 允许用户打开并播放 Windows Media 文件,尤其是文件扩展名为 .wma .wmv 文件
  · 创建供用户播放、暂停和停止数字媒体内容的传输控制按钮。
  · 显示当前数字媒体文件的标题。
  · 演示如何使用 Player 对象模型,包括使用属性、方法和事件的示例。

  我的这个程序仅仅只是告诉大家如何用DirectShow C#中做一个播放机,

  在这个程序中我们经要解决的一些小问题:

  1.如何从你的磁盘上打开媒体文件

  2.如何让工具条上的按钮起用和禁用

  3.如何设置状态栏的显示文字

  4.如何控制时间 

  5.如何使用时间控件的事件
 
  6.如何用DirectShow来播放媒体文件

  7.如何确定播放状态等等...

  下图显示了您将要创建的应用程序,其中正在播放名为“Melow”的数字音频文件,同时呈现了可视化效果。


1


  · 本文假设您已经具备一定的 Visual C# Visual Studio.NET 集成开发环境知识。



  准备工作

  在开始创建应用程序之前,您需要安装必要的软件并注册主互操作程序 (QuartzTypeLib)

  这里简单介绍DirectShow 接口:

  播放视屏和声音文件我们要用到DiectX为我们提供的DirectShow组件.使用这个接口可以让你方便的播放那些共用的影像和声音文件.你要做的仅仅只是安装DirectShow接口和使用它的功能函数和配置正确的接口参数而已.

  不幸的是.NET并不正式支持DirectX.是的也许你听说DirectX9支持是吗?是的,不过在最终版敲定的那一天还没来,我们都得不到最好的效果.但无论如何我们还是要用的不是吗?要不这篇文章得作废了.是的,也许你用过VB,对了,就是它,我们正是要用到那个.

  开始项目

  在安装必要软件并注册 QuartzTypeLib之后,您就可以启动 Visual C#,开始为示例应用程序创建项目。下面我将给大家介绍这一过程的操作步骤。

  创建项目

  按以下步骤创建一个空的项目:

  1. 启动 Visual Studio .NET,然后单击 New Project(新建项目)。

  2. Visual C# ProjectsVisual C# 项目)文件夹中单击 Windows ApplicationWindows 应用程序),键入新项目的名称(最好为 DirectShow),然后单击 OK(确定)。

  Visual C# 使用默认的 Windows 窗体“Form1”创建一个新的项目。

  3. 这个名称并没有特别的意义或用处,所以请在 Properties(属性)窗口中将窗体名称更改为 frmPlayMedia,将窗体文本更改为媒体播放器

  在项目中添加对 DirectShow的引用

  按照以下步骤在项目中添加一个对 DirectShow的引用:

  1. 打开 Visual Studio 工具箱,然后单击 Components(组件)显示该面板。

  2. 右击面板,然后单击 Customize Toolbox(自定义工具箱),显示对话框。

  3. COM ComponentsCOM 组件)选项卡上,选中 Interop.QuartzTypeLib.dll。(如果 Interop.QuartzTypeLib.dll 由于某种原因未列出,则单击 Browse [浏览] 并查找名为 QuartzTypeLib.dll文件。)

  4. 单击 OK(确定)关闭对话框。


2


  要在代码中使用 DirectShow,您需要添加一行代码,以引用 DirectShow命名空间。在窗体代码窗口的顶部,将以下代码添加到所有声明语句之前:

using QuartzTypeLib;


  using语句必须在所有 Options 语句(本项目中并未使用)之后,并且在所有其他代码之前。添加该语句后。


  开发应用程序

  创建通过 PIA Framework 连接的 Player 控件实例之后,您可以向窗体中添加所需的其他元素,并编写完成实际操作的代码。
添加 Windows 窗体控件

  1. View(视图)菜单中,单击 Designer(设计器),或者单击 Solution Explorer(解决方案资源管理器)中的 View Designer(视图设计器)按钮,切换到窗体设计器。

  2. 在窗体上增加文件、播放、信息等菜单。

  3. 在工具箱的 Windows FormsWindows 窗体)面板中,为您的窗体添加一个工具栏、一个状态栏和图片imageList

  4. Properties(属性)窗口中,将工具栏的名称更改为 toolBar1,将在Buttons上增加4个按钮。状态栏的名称更改为 statusBar1,并分别增加三个Panel

  5. 在工具箱的面板中,为您的窗体添加一个面版panel1

  6. 增加一个定时器timer1

  7. 调整控件在窗体中的排列方式,使之符合您的需要而且方便用户使用。下图为 Visual Studio Designer(设计器)中完成后的窗体布局。


3


  编写代码

  如何打开你想要媒体文件?

  第一步是编写在 frmPlayMedia中打开 Windows Media 文件的代码。要自动切换到 Code(代码)视图并编辑打开菜单的 Click 事件处理程序 (menuItem2_Click) 的代码,请双击窗体上的工具栏按钮。将以下代码添加到事件处理程序中:

  还记得吗"文件 -> 打开..." 是的几乎每个使用windows的人都会这样操作.如何实现?

  很简单看看下面的代码:

OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Media Files|*.mpg;*.avi;*.wma;*.mov;*.wav;*.mp2;*.mp3|All Files|*.*";
if (DialogResult.OK == openFileDialog.ShowDialog())
{
….
}


  看吧很简单是吗?记得写一个函数把它放进去。当你点击OK按钮的时候,DirectShow接口就会得到你想要播放的文件。下图解释了它是如何工作的。

  DirectShow为多媒体流回放提供最基本的服务,这些多媒体流可以是本地文件,还可以是服务器传输过来的。特别的,DirectShow可以支持视频回放,支持以不同的文件和流格式压缩视频内容,包括Windows MediaMPEGAVIWAV

  在DirectShow的核心处,服务是组件的模块化集合,称为过滤器,可以根据媒体类型排列成过滤器图。过滤器可以操作数据流,如读入、分析、解码、格式化或渲染。

  过滤器以树型进行排列,这棵树称为过滤器树,通过过滤器树管理器(Filter Graph Manager,简称FGM)进行管理。使用FGM应用程序可以通过使用Microsoft Windows Media Player控件间接控制过滤器树,还可以通过调用COM接口方法直接控制。DirectShow过滤器树(参阅图1)由从源到目标渲染器的有向过滤器序列组成,所有这些通过输入和输出过滤器引脚连接。过滤器引脚协商它们将支持哪些媒体类型。FGM控制树过滤器之间的多媒体数据流。因为DirectShow有一个灵活的、可重配置的过滤器树体系结构,因此DirectShow可以使用同样的软件成分支持多种媒体类型的回放和分流。开发人员还可以通过编写自己的过滤器扩展DirectShow多媒体支持。

  过滤器

  过滤器是注册的DirectShow类,它执行许多媒体信息处理任务。这些任务包括:

   获得源信息(例如,获得媒体流)
   分析(例如,在流上执行包读入、分离和格式化)
   转换(例如,解码WMAMPEG-4音频和视频流)
   渲染(例如,在适当的时候产生音频PCM或者视频RGB/YUV输出,将数据传给DirectSoundDirectDraw)

  过滤器使用几种类型的接口,例如引脚、计数器、传送器和时钟接口,来执行它们的任务。过滤器实现和开放了许多接口。FGM可以使用这些接口创建、连接和控制树。过滤器经常实现包含下列方法的IBaseFilter接口:

   运行、停止和暂停过滤器状态。
   恢复过滤器和厂商信息。
   得到和设置参考时钟。
   恢复过滤器状态信息。
   枚举过滤器引线。
   重建过滤器树时定位引脚

  用户单击打开时,这段代码将显示一个对话框,供用户在计算机上浏览并选择要播放的 .wma .wmv 文件。用户选择文件(并单击确定)时,代码将 Player URL 属性设置为用户选择的文件。由于 Player autoStart 属性在默认情况下设置为 True,所以 Player 立即打开并播放用户选择的数字媒体文件

  接下来,添加播放/暂停按钮的代码。在代码窗口中,在停止、暂停菜单中单击,然后,在方法名称列表中单击 Click。将以下代码添加到 Visual C# 为您创建的Click 事件处理程序中:

  看看下面的代码是如何实现的:

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;

//

如何来播放,暂停,停止?
简单这些函数看字面也知道.
//

m_objMediaControl.Run();//
播放
m_objMediaControl.Pause();//
暂停
m_objMediaControl.Stop();//
停止

//
这段代码非常简单。当用户单击播放/暂停按钮时,代码将检查 Player playState 属性。如果 Player 正在播放数字媒体文件,代码就会暂停文件的播放; 如果 Player 已经暂停或停止,代码就再次启动 Player 播放文件
OK,
在来看我们是如何控制时间进度的?
//

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


  看见上面那个 UpdateStatusBar();这里是让它没100ms更新一次状态栏.

  代码如下:

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";
 }
}


  还有一个问题程序怎么能够知道它播放完了?

  这会有点麻烦了,想想看有什么办法呢?对了,windows是消息驱动的。那找找看有什么消息。有的就EC_COMPLETE。还记得"WndProc" 它吗?是的,我的老朋友,这次我们必须要改写它来捕获EC_COMPLETE消息。这个消息是DirectShow通知父窗体,播放结束了。

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);
}


  只要播放状态改变,上述代码就会运行。如果 Player 正在播放(用户打开文件时就处于播放状态,因为 autoStart 设置为 True),代码将启用播放/暂停按钮和停止按钮,以便用户执行操作。之后,代码将播放/暂停按钮的文字更改为暂停,这样用户就可以使用该按钮暂停播放过程。最后,代码检索当前数字媒体文件的标题,并更新标题标签的文字以显示标题。

  如果 Player 被暂停(用户单击了播放/暂停按钮),代码会将播放/暂停按钮的文字更改为播放,以提示用户使用该按钮可以恢复播放。

  如果 Player 被停止(用户单击了停止按钮),代码将禁用停止按钮(因 Player 已经停止工作)并将播放/暂停按钮的文字恢复为默认值播放

  一切都结束了,现在要做的事就是做些来找一部影片来享受一下自己的成果了.

  编写完示例项目的代码之后,您可以生成并运行解决方案。

  生成解决方案

  在 Build(生成)菜单中单击 Build Solution(生成解决方案)。Visual Studio 开始编译并生成项目。如果键入内容全部正确,生成过程将顺利完成,不会出现任何错误。如果生成报告错误,则请检查您的代码并纠正错误。

  使用示例应用程序

  要在调试器中运行项目,请按键盘上的 F5 键。如果出现查看生成的代码主题中介绍的未处理的异常,则应该停止调试会话,删除或注释掉生成代码中的相应行,然后再按 F5 键。

  您可以单击打开查找 .wma .wmv 文件(究竟选择何种文件,取决于您在打开对话框中选择的文件类型)。选择某个文件并单击确定之后,打开对话框关闭,开始播放数字媒体文件,传输控制按钮的状态也随之改变。这时您就可以利用传输控制按钮来暂停、重新开始或完全停止播放。

 

 

你可能感兴趣的:(利用Visual C#开发一个媒体播放器)