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






4.64/5 (4投票s)
一个示例 C++ 项目,它使用 DES 合并两个或多个 AVI 文件。
引言
我最早的 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 新手有所帮助。
运行示例程序
- 在 avi 目录中创建 demo.avi 文件的三个副本,因为这些副本将用作输入。(注意:我的要求是所有媒体文件具有相同数量和顺序的媒体流)。
- 你可以运行 bin 目录中的 DSCombine.exe。或者,如果你想在 VS2008 中编译和运行此测试项目,则需要
- 安装 VS2008、Windows SDK V7.0A 和 DirectX(2007 年 8 月)。
- 以管理员身份运行 VS2008。然后,项目可以启用 DS 基类调试/日志记录功能(即
DbgInitialise
/DbgTerminate
),当然,前提是你进行了相关的注册表更改。更具体地说,第一次运行此应用程序将会在注册表中创建以下键: - 设置 03 DESCombine 测试项目配置选项
- 在主窗口中,单击“添加”按钮。这将显示一个标准的 Windows 文件选择窗口。选择你在步骤 1 中创建的 demo.avi 文件的三个副本。单击“保存”按钮。
- 将显示媒体文件数据间隔对话框,在此输入开始/结束时间间隔(以秒为单位),以指定将处理媒体文件的哪个部分。默认的开始/结束时间 0 和 -1 表示将处理整个文件。单击“确定”按钮返回到主窗口。
- 你可以通过单击“预览”单选按钮来预览选定的媒体文件。或者,要将媒体文件合并到一个输出文件中,请单击“到 AVI”单选按钮。在这种情况下,你可以通过单击省略号 (...) 按钮来选择输出文件的名称。
- 单击“合并文件”按钮开始处理选定的媒体文件。如果选择了“预览”按钮,则将显示两个视频流,如上面的图像所示。你也应该听到相应的音频。如果选择了“到 AVI”单选按钮,则合并后的媒体将输出到 AVI 文件,并且 GUI 只会显示 DS 事件通知代码列表。
[HKLM][Software][Microsoft][DirectShow][DESCombine.dll] and [HKLM][Software][Microsoft][DirectShow][DESCombineTest.exe]
然后,你可以在注册表中为每个不同的测试类别设置日志记录级别。实现细节可以在 DS 基类文件 wxdebug.cpp 中找到。
将 [Configuration Properties][Debugging][Working Directory] 设置为 $OutputSet [Configuration Properties][Link][Additional Library Directories] 设置为 $Output
关注点
调用 DES 的主类是 DESCombine
(请参阅项目 02 DESCombine - DLL 中的文件 DESCombine.cpp)。使用此类中的关键步骤如下:
- 通过调用成员函数
DESCombine::initialize
并传入输入文件名来初始化该类。 - 下一个要调用的函数取决于 DES 是渲染到窗口还是输出文件。要预览,请调用成员函数
DESCombine::renderToWindow
。要将合并的输入文件写入单个媒体文件,请调用成员函数DESCombine::renderToAVI
。 - 要开始处理输入文件,请调用成员函数
DESCombine::startRendering
。
你可以在测试项目 03 DESCombine Test 的 CCombineFilesDLG::_initialize()
中找到执行此函数序列的地方。这些是新 DES 用户可能需要特别关注的重要函数。
如果你将此 C++ 版本与 C# 版本进行比较,你会发现存在一些差异,这反映了我的偏好:
- C# 版本创建一个专用线程(
DESCombine::EventWait()
)来轮询或查询事件,而 DES 在工作。相比之下,此 C++ 版本启用事件通知,使用消息处理程序,如 MSDN 文档中所述。 - 此 C++ 版本添加了许多辅助类(例如
InputFiles
、StreamInformation
和VideoInformation
)。 - 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 的人提供一个有价值的起点。