梁志斌的专栏

游戏开发 DirectX技术

 
首页>>
关于作者

作  者:梁  志  斌

QQ   :3055720

QQ群:14739153

友情链接
搜索日志
访问计数
最新评论

DVR-MS 文件介绍和应用

   DirectX开发2006-9-25 13:47

--玩转 DVR-MS

发布日期: 6/7/2005 | 更新日期: 6/7/2005

Stephen Toub
Microsoft Corporation

适用于:
Microsoft Windows XP Media Center Edition 2005
Microsoft DirectShow
DirectX 9.0 SDK

摘要:Stephen Toub 讨论了 Windows XP Media Center 2005 生成的 DVR-MS 文件格式,介绍了 DirectShow 并展示了如何使用后者处理前者。

下载 DVR-MS 示例 Code.msi

 

几年前我拥有一台 TiVo。它已经不知藏在公寓壁橱的哪个角落了,我想现在一定是布满灰尘,诚然,就是现在我也可能这样对待它。占据电视旁宝贵空位的是一个更漂亮、更复杂的现代化软件和电子产品 — Microsoft Windows XP Media Center 2005。我的家人为该设备取了个既得体又人性化的名字 —“米老鼠”,它有许多神奇的功能。然而,当我建议我的“技术娴熟”的朋友们放弃他们现在使用的任一款数字摄像机 (DVR) 而转为使用此平台时,只要他们让我说明一个理由,我的回答都很简单:可以对录制的电视节目进行文件访问。

DVR-MS 文件是由 Windows XP Service Pack 1 引入的流缓冲引擎(Stream Buffer EngineSBE)创建的,Media Center 用它存储录制的电视节目。在本文中,我将向您演示如何通过托管代码使用 DirectShow 来处理和操作 DVR-MS 文件。在此过程中,我将向您介绍我为处理 DVR-MS 文件而创建的一些有用的实用工具,并为您提供您在编写自己的代码时需要的工具和库。所以,请打开 Visual Studio .NET,抓一把爆米花,享受这个过程吧。

注 本文假定您的系统中有一个正在工作的 MPEG2 解码器,并且您使用的是 NTSC 而非 HD 内容(虽然这里讨论的大多数概念适用于 PAL HD,但示例代码可能无法正确地处理这些格式)。另外,由于内容所有者或广播公司所设置的策略,一些 DVR-MS 文件受到复制保护。这种保护是在生成文件时通过检查广播公司的复制保护标志 (CGMS-A) 确定的,它会限制您访问特定 DVR-MS 文件的方式和时间。例如,在收费台(如 HBO)录制的电影可能是加密的,因此本文描述的技术就不适用了。最后,与本文相关联的代码示例和应用程序是针对 .NET Framework 1.1 编译的。然而,默认情况下 Windows XP Media Center 2005 并没有附带安装 .NET Framework 1.1,而是安装 1.0。因此,要在您的 Media Center 中使用这些示例,您必须安装 .NET Framework 1.1(可通过 Windows Update 获得)或者重新编译该示例以适用 .NET Framework 1.0

播放 DVR-MS 文件

谈到视频文件时,播放或许是可以执行的最重要的操作,所以我将从此入手。在您自己的应用程序中可以有多种播放 DVR-MS 文件的方式,这里我将演示其中的一些。为此,我创建了一个简单的应用程序,您可以在与本文有关的代码下载中获得。

 

播放 DVR-MS 文件的第一种方式也是最简单的方式是,使用 System.Diagnostics.Process 类来执行它。由于 Process.Start 包装了来自 shell32.dll ShellExecuteEx 非托管函数,因此这种方式利用了与从 Windows Explorer 双击一个文件相同的功能来播放 DVR-MS 文件:

private void btnProcessStart_Click(object sender, System.EventArgs e){Process.Start(txtDvrmsPath.Text);}

这也意味着,视频将在一个独立的进程中播放,这个进程在 DVR-MS 文件的任何默认处理程序中运行;对于大多数机器和我的机器来说,它就是 Windows Media Player(我使用 Windows Media Player 10,如果您没有,我建议您从 http://www.microsoft.com/windows/windowsmedia/mp10/default.aspx 免费升级到该版本)。当然,Process.Start 有另一个同时接受可执行路径和参数的重载,可以使用它在任何您想要的播放机中启动 DVR-MS 文件,不管它是否是 .dvr-ms 扩展名的默认处理程序:

private void btnProcessStart_Click(object sender, System.EventArgs e){Process.Start(@"c:\\Program Files\\Windows Media Player\\wmplayer.exe","\\"" + txtDvrmsPath.Text + "\\"");}

您应该注意到,当这样做时,有必要对 DVR-MS 文件的路径加上引号(正如此处名为 txtDvrmsPath TextBox 的内容所提供的),因为要使用的内容是 wmplayer.exe 的一个命令行参数。否则,路径中的任何空格都会使路径被分隔并解释为多个参数。

Process.Start 返回一个代表启动进程的 Process 实例,这意味着您可以利用 Process 提供的功能来与 Windows Media Player 进一步交互。例如,在您的应用程序中,您可能想先等待视频停止再让用户继续,可以使用 Process.WaitForExit 方法来完成这样的任务:

private void btnProcessStart_Click(object sender, System.EventArgs e){using(Process p = Process.Start(txtDvrmsPath.Text)){p.WaitForExit();}}

当然,这只是等待 Media Player 关闭,而不是像初始请求那样播放您指定的文件,因为您的应用程序没有真正的视图可以查看 Media Player 执行的内容。当打开 Media Player 时,按上述方法编码也会冻结应用程序的 GUI,这个问题可以通过订阅 Process Exited 事件加以解决,而不是用 WaitForExit 方法阻止。

总而言之,该解决方案编码简单方便,但非常不灵活,而且是在应用程序的外部播放视频。它可能只在以下情况下才适用,您想允许用户查看指定的文件,不过是在应用程序不必关心视频内容而且应用程序根本不与视频交互的情况下查看。例如,如果您的应用程序是一个下载代理,而且您想允许用户查看已经复制到本地的视频文件,则可能适合采用这种方式。

由于我们知道 Windows Media Player 可以播放 DVR-MS 文件,因此对于大多数情况,更好的解决方案是在应用程序中宿主 Windows Media Player ActiveX 控件的一个实例。在 Visual Studio .NET 中,只需右键单击工具箱,选择添加控件并选择 Windows Media Player COM 控件。这样它就会出现在工具箱中,当窗体中有一个 ActiveX 控件的实例时,让它播放 DVR-MS 文件就只需设置播放器的 URL 属性:

player.URL = txtDvrmsPath.Text;

在我的示例应用程序中,我选择让它更进一步。我创建了一个 System.Windows.Forms.Panel,它位于想要显示视频的窗体中。当用户请求使用 Media Player 播放选定的视频时,我就新建一个 Media Player 控件的实例,将它添加到 Panel 的子控件集合中,使其保持在最大化,并设置其 URL 属性。这种方案允许我完全控制 Media Player 的生存期,而且可以轻松管理它在窗体中的位置,而不用担心它的绝对定位值(这种方案也使演示播放视频的其他方法变得轻松,稍后您将看到)。下面显示的是我使用的代码:

private void btnWmp_Click(object sender, System.EventArgs e){AxWindowsMediaPlayer player = new AxWindowsMediaPlayer();pnlVideo.Controls.Add(player);player.Dock = DockStyle.Fill;player.PlayStateChange += new _WMPOCXEvents_PlayStateChangeEventHandler(player_PlayStateChange); player.URL = txtDvrmsPath.Text;}private void player_PlayStateChange(object sender, _WMPOCXEvents_PlayStateChangeEvent e){AxWindowsMediaPlayer player = (AxWindowsMediaPlayer)sender;if (e.newState == (int)WMPLib.WMPPlayState.wmppsMediaEnded ||e.newState == (int)WMPLib.WMPPlayState.wmppsStopped){player.Parent = null; // removes the control from the panelThreadPool.QueueUserWorkItem(new WaitCallback(CleanupVideo), sender);}} private void CleanupVideo(object video){((IDisposable)video).Dispose();}

要阻止显示 Media Player 工具栏,您可以更改控件的 uiMode 属性:

player.uiMode = "none";

要在用户右键单击控件时阻止显示 Media Player 上下文菜单,可以将其 enableContextMenu 属性设置为 false

player.enableContextMenu = false;

您将注意到,在播放 DVR-MS 文件的前一刻,我为播放器的 PlayStateChange 事件注册了一个事件处理程序。这可以使我在播放停止时从 Panel 删除播放器。在 PlayStateChange 事件的处理程序中,我检查播放是否结束,如果结束,就将播放器从其父控件(面板)删除,并将一个工作项排入 .NET ThreadPool 队列中。这个工作项的作用只是处置播放器控件。我是在后台线程中进行此次处置的,因为无法在 PlayStateChange 事件处理程序中直接处置。在此事件处理程序中处置控件会在控件本身中引发异常,因为事件处理程序是在控件中引发的,控件在执行完我的处理程序之后还需要进行更多的处理。在处理程序中处置播放器控件会导致功能被破坏,所以我让该操作在事件处理程序完成之后稍微延迟一会,以便留出必要的时间。您将看到,在使用所演示的下一个播放机制时,就需要用到同一技术。

宿主 Windows Media Player ActiveX 控件有许多好处。它使用起来非常方便,而且提供了大量的功能。然而,Windows Media Player 使用 DirectX(特别是 DirectShow)来播放 DVR-MS 文件(本文后面我将更详细地讨论 DirectShow)。您不是依赖 Windows Media Player DirectX 交互,而是在您的应用程序中使用 Managed DirectX,完全跳过 Windows Media Player

在写作本文时 Managed DirectX 的最新版本是 DirectX 9.0 SDK Update February 2005 下载的一部分。(要获得本文后面介绍的内容,您还需要 February 2005 Extras 下载。)此 SDK 在您的全局程序集缓存 (GAC) 中安装了 AudioVideoPlayback.dll 程序集,使其可用于您的应用程序(DirectX 运行库安装也安装了此 DLL 以使您的最终用户可以访问它)。AudioVideoPlayback 是一个高级包装,它含有您在 .NET 应用程序中播放视频和音频文件所需要的最少的 DirectShow 功能。

有了 Windows Media Player ActiveX 控件后,使用 AudioVideoPlayback 变得非常简单。

private void btnManagedDirectX_Click(object sender, System.EventArgs e){Video v = new Video(txtDvrmsPath.Text);Size s = pnlVideo.Size;v.Owner

 

标签集:TAGS:
回复Comments()点击Count()

回复Comments

{commenttime}{commentauthor}

{CommentUrl}
{commentcontent}
 

 Copyright  @  好想~~~~好想 2005.03