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

DirectShow 编辑服务 (DES) 和组合 AVI 文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (4投票s)

2011年9月9日

CPOL

5分钟阅读

viewsIcon

37144

downloadIcon

5889

一个示例 C++ 项目,它使用 DES 合并两个或多个 AVI 文件。

DESCombine.gif

引言

我最早的 DirectShow (DS) 项目之一是使用 DirectShow 编辑服务 (DES) 来合并多个媒体(* .AVI)文件。我找不到一个完整的 C++ 项目使用 DES,因此基于 DES 文档编写了几个测试程序。不出所料,它们都不起作用。我随后发现了 DirectShowNet(http://directshownet.sourceforge.net/about.html),其中包含说明许多 DES 概念的 DESCombine 示例项目。代码是用 C# 和 VB 编写的。我将其移植到 C++,不出所料,它仍然不起作用——细节决定成败。经过多杯咖啡和一次微软支持电话后,我才能够让这个 C++ 版本工作起来。

对于刚开始编写多媒体应用程序的人来说,编写 DS/DES 应用程序并非易事。原因有很多,但我发现最令人惊讶的是,仅仅理解为什么你的应用程序不起作用就如此困难。例如,我收到过一些模糊到毫无意义的错误代码。在这种时候,你最好的朋友是一个可以用于比较目的的有效测试项目。C# 版本的 DESCombine 很有帮助,但当我刚开始时,我真正需要的是 C++ 版本。我将我的 C++ 版本提供出来,以此回馈开发社区,并希望对其他 DS/DES 新手有所帮助。

运行示例程序

  1. avi 目录中创建 demo.avi 文件的三个副本,因为这些副本将用作输入。(注意:我的要求是所有媒体文件具有相同数量和顺序的媒体流)。
  2. 你可以运行 bin 目录中的 DSCombine.exe。或者,如果你想在 VS2008 中编译和运行此测试项目,则需要
    1. 安装 VS2008、Windows SDK V7.0A 和 DirectX(2007 年 8 月)。
    2. 以管理员身份运行 VS2008。然后,项目可以启用 DS 基类调试/日志记录功能(即 DbgInitialise/DbgTerminate),当然,前提是你进行了相关的注册表更改。更具体地说,第一次运行此应用程序将会在注册表中创建以下键:
    3. [HKLM][Software][Microsoft][DirectShow][DESCombine.dll] and [HKLM][Software][Microsoft][DirectShow][DESCombineTest.exe]

      然后,你可以在注册表中为每个不同的测试类别设置日志记录级别。实现细节可以在 DS 基类文件 wxdebug.cpp 中找到。

    4. 设置 03 DESCombine 测试项目配置选项
    5. 将 [Configuration Properties][Debugging][Working Directory] 设置为 $OutputSet [Configuration Properties][Link][Additional Library Directories] 设置为 $Output

  3. 在主窗口中,单击“添加”按钮。这将显示一个标准的 Windows 文件选择窗口。选择你在步骤 1 中创建的 demo.avi 文件的三个副本。单击“保存”按钮。
  4. 将显示媒体文件数据间隔对话框,在此输入开始/结束时间间隔(以秒为单位),以指定将处理媒体文件的哪个部分。默认的开始/结束时间 0 和 -1 表示将处理整个文件。单击“确定”按钮返回到主窗口。
  5. 你可以通过单击“预览”单选按钮来预览选定的媒体文件。或者,要将媒体文件合并到一个输出文件中,请单击“到 AVI”单选按钮。在这种情况下,你可以通过单击省略号 (...) 按钮来选择输出文件的名称。
  6. 单击“合并文件”按钮开始处理选定的媒体文件。如果选择了“预览”按钮,则将显示两个视频流,如上面的图像所示。你也应该听到相应的音频。如果选择了“到 AVI”单选按钮,则合并后的媒体将输出到 AVI 文件,并且 GUI 只会显示 DS 事件通知代码列表。

关注点

调用 DES 的主类是 DESCombine(请参阅项目 02 DESCombine - DLL 中的文件 DESCombine.cpp)。使用此类中的关键步骤如下:

  1. 通过调用成员函数 DESCombine::initialize 并传入输入文件名来初始化该类。
  2. 下一个要调用的函数取决于 DES 是渲染到窗口还是输出文件。要预览,请调用成员函数 DESCombine::renderToWindow。要将合并的输入文件写入单个媒体文件,请调用成员函数 DESCombine::renderToAVI
  3. 要开始处理输入文件,请调用成员函数 DESCombine::startRendering

你可以在测试项目 03 DESCombine Test 的 CCombineFilesDLG::_initialize() 中找到执行此函数序列的地方。这些是新 DES 用户可能需要特别关注的重要函数。

如果你将此 C++ 版本与 C# 版本进行比较,你会发现存在一些差异,这反映了我的偏好:

  1. C# 版本创建一个专用线程(DESCombine::EventWait())来轮询或查询事件,而 DES 在工作。相比之下,此 C++ 版本启用事件通知,使用消息处理程序,如 MSDN 文档中所述。
  2. 此 C++ 版本添加了许多辅助类(例如 InputFilesStreamInformationVideoInformation)。
  3. C# 和 C++ 版本都使用 MyCallback::BufferCB() 回调函数来监视 DES 的进度。C# 版本直接更新 GUI 字段,而此 C++ 版本将消息发布到父窗口,因此父窗口负责更新 GUI 字段。

文件压缩

如果选择了“到 AVI”单选按钮,以便 DES 将时间线渲染到输出文件,则输出文件将包含未压缩的媒体,体积会很大。要启用文件压缩,必须先在计算机上安装 K-Lite Codec Pack。安装完成后,必须在 03 DESCombine Test 项目的文件 CombineFilesDLG.cpp 中将常量 COMPRESS_OUTPUT_FILE 设置为非零值。

一个小插曲

此项目是用学习和测试 DES 的方式编写的。最终,决定不使用 DES,并且我停止了对这个测试项目的开发。有一个我意识到的未解决的问题。有时,DES 在开始处理第一个文件时会立即停止。当这种情况发生时,我只需关闭窗口(即单击“关闭”按钮),然后重新启动该过程(即单击“合并文件”按钮)。尽管如此,该项目仍将为任何开始使用 DES 的人提供一个有价值的起点。

© . All rights reserved.