65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 进行媒体文件转换

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.21/5 (14投票s)

2005年7月27日

5分钟阅读

viewsIcon

355316

downloadIcon

12286

演示构建 DirectShow 过滤器图以进行文件转换。

引言

GraphEdit 工具来自 DirectShow SDK,是在 Windows 平台上模拟媒体文件处理的流行工具。最近,开源的 DirectShow .NET 包装器 DirectShowLib 发布了。DirectShowLib 1.0 版本封装了最重要的接口,并且比从 Quartz.dll 生成的互操作程序集提供了更多的功能。在本文中,我们将介绍一个使用 C# 构建过滤器图以进行媒体文件转换的应用程序。因此,我们将展示如何使用 C# 创建提供 GraphEdit 部分功能的应用程序。

背景

多媒体应用程序有多种文件格式。最受欢迎的是 MPEG 系列(MPEG-1/2、MPEG 4(第 2 部分或第 10 部分)...)、Microsoft 系列(AVI、ASF、WMV...)、QuickTime 系列(QT、MOV...)和 RealMedia(RM、RAM,...)。每种格式都有其优点和缺点。此外,一些格式受到称为“软件专利”的愚蠢事物的限制(可能由大型公司中那些懒惰的中层经理发明,他们发现将工作交给法律部门比实际开发客户想要的产品更容易 ;-)。

因此,对于这个应用程序,我决定编写一个转换实用程序,可以将许多媒体文件转换为 Windows Media Video(.wmv)格式。此外,由于 Microsoft 拥有 ASF 格式(.wmv 基于此格式)的专利,我编写了代码以转换为称为 Matroska 的开放格式倡议。

使用代码

此网站提供了许多使用 .NET 中 DirectShow 的资源。DirectShowLib 的前身是该网站上的 .netmaster 的一个项目。我研究了他们的代码,您可以参考他们,了解我在本文中尚未解释的内容。

首先,编译应用程序的命令行(在 build.cmd 中提供,并假设 C# 编译器可从当前路径访问)引用 DirectShowLib 程序集。在代码中,我们开始于

using DirectShowLib;

然后,我们使用以下变量来构建过滤器图

// The main com object
FilterGraph fg = null;
// The graphbuilder interface ref
IGraphBuilder gb = null;
// The mediacontrol interface ref
IMediaControl mc = null;
// The mediaevent interface ref
IMediaEventEx me = null;

在进行一些初始步骤(对于所有 C# 中的 DirectShow 应用程序都相同)后,我们使用以下代码将媒体文件转换为 .wmv 文件

// here we use the asf writer to create wmv files
WMAsfWriter asf_filter = new WMAsfWriter();
IFileSinkFilter fs = (IFileSinkFilter)asf_filter;
        
hr = fs.SetFileName( fileName + ".wmv", null );
DsError.ThrowExceptionForHR( hr );

hr = gb.AddFilter( (IBaseFilter)asf_filter, "WM Asf Writer" );
DsError.ThrowExceptionForHR( hr );
        
hr = gb.RenderFile( fileName + fExt, null );
DsError.ThrowExceptionForHR( hr );

hr = mc.Run();          
DsError.ThrowExceptionForHR( hr );

此代码创建了一个 WMAsfWriter 对象,并访问其 IFileSinkFilter 接口来设置文件名。然后,它使用 GraphBuilder 接口方法 AddFilter 将过滤器添加到图中。在此之后,我们使用“智能连接”(通过调用 RenderFile 实现)让 DirectShow 运行时构建图的其余部分。然后,当我们调用 MediaControl 接口上的 Run 方法时,我们实际上正在写入文件,因为此图中的渲染器过滤器是文件写入器。

关注点

从我之前的评论中,您可能已经猜到我不是软件专利的忠实粉丝。在编写了转换为 .wmv 文件的代码后,我了解到 Microsoft 对其基础文件格式拥有专利。所以我寻找替代方案,我意识到这个领域充斥着这些“愚蠢的小东西”。所以我决定增加对转换为 Matroska 文件格式的支持,该格式在我所知是“无专利”的。

Matroska 支持

用于构建写入 .mkv 文件的过滤器图的代码与写入 .wmv 文件的代码类似。除了我们不创建 WMAsfWriter 而是创建一个 FileWriter 对象(再次,访问其 IFileSinkFilter 接口来设置名称)。然后,我们使用以下代码添加 Matroska Mux 过滤器

// create an instance of the matroska multiplex filter and add it
// Matroska Mux Clsid = {1E1299A2-9D42-4F12-8791-D79E376F4143}
Guid guid = new Guid( "1E1299A2-9D42-4F12-8791-D79E376F4143" );
Type comtype = Type.GetTypeFromCLSID( guid );
IBaseFilter matroska_mux = (IBaseFilter)Activator.CreateInstance( comtype );

如果您已在系统上安装了 Matroska 支持(如果您不认为编解码器包是“邪恶的”,请从 www.matroska.org 下载编解码器包),Matroska Muxer 的 CLSID 将包含在您的注册表中。然后,您可以创建一个类型对象并调用 Activator.CreateInstance 来获取一个可以添加到过滤器图中的 IBaseFilter 对象。

再次使用 GraphBuilder.RenderFile 将尝试从源媒体文件构建图的其余部分。此过程并非总能如预期般工作,您应该将 Matroska 支持视为实验性的,主要用于说明目的。

局限性和已知问题

我最初开发此应用程序是因为我有一些 Real Media 文件想转换为 .wmv。我在 GraphEdit 工具中手动构建了过滤器图,并为每个文件重新构建。所以我决定编写一个执行相同操作的小应用程序会很方便。如果您在系统上安装了 Real Media 分割器(通过 Real Player 或 Real Alternative),可以将 Real Media 文件无缝转换为 Windows Media 文件。

Windows Media 文件到 Matroska 文件的转换似乎进行得相当顺利。但是 MPEG 文件无法通过此应用程序转换为 Matroska 文件(我还没有研究这个问题)。但是您可以将 MPEG 转换为 WMV,然后再转换为 Matroska 文件。(第二次转换在某些文件上似乎会挂起,但文件不会损坏,可以在您喜欢的播放器中播放。GraphEdit 在这些文件上也有类似的困难。)如前所述,Matroska 支持是实验性的,主要用于说明目的。所以我不能保证我会支持应用程序的这项功能。

安装带有外壳扩展功能的 Matroska 编解码器包在我的系统上造成了问题(在其他机器上也似乎存在此问题)。但默认安装脚本不包含此功能。尽管如此,通过 Google 搜索发现,在 XP 上安装 Matroska 编解码器包后,其他人也遇到了问题。

某些 Matroska 文件的时序看起来很奇怪,我打算研究这个问题。

如果文件很大,转换可能需要一些时间。我使用任务管理器应用程序并检查 CPU 使用率来确定转换何时完成。

© . All rights reserved.