首页 > 开发 > 综合 > 正文

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

2024-07-21 02:24:47
字体:
来源:转载
供稿:网友
摘要:了解如何在 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应用。
  · 包含一个“文件”菜单,文件菜单包含三个菜单项:
  · “打开”,用来打开媒体文件。
  · “循环”,是播放一次(默认),还是重复播放。
  · “退出”,退出程序。
  · 可以在多种平台上运行。
  · 核心功能通过jmf(java media framework)api实现。

  按照本文介绍的步骤,您将创建一个基于 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# projects(visual c# 项目)文件夹中单击 windows application(windows 应用程序),键入新项目的名称(最好为 directshow),然后单击 ok(确定)。

  visual c# 使用默认的 windows 窗体“form1”创建一个新的项目。

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

  在项目中添加对 directshow的引用

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

  1. 打开 visual studio 工具箱,然后单击 components(组件)显示该面板。

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

  3. 在 com components(com 组件)选项卡上,选中 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 forms(windows 窗体)面板中,为您的窗体添加一个工具栏、一个状态栏和图片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 media、mpeg、avi和wav。

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

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

  过滤器

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

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

  过滤器使用几种类型的接口,例如引脚、计数器、传送器和时钟接口,来执行它们的任务。过滤器实现和开放了许多接口。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 文件(究竟选择何种文件,取决于您在“打开”对话框中选择的文件类型)。选择某个文件并单击“确定”之后,“打开”对话框关闭,开始播放数字媒体文件,传输控制按钮的状态也随之改变。这时您就可以利用传输控制按钮来暂停、重新开始或完全停止播放。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表