1、DirectShow 实 务 精 选 陆其明 编 著北京科海电子出版社内 容 提 要本 书 是 “DirectShow 专 业 著 作 ”丛 书 的 第 二 本 , 侧 重 介 绍 了 DirectShow 技 术在当前主要的几个领域中的应用,包括音视频采集、视频聊天、视频点播、 视频叠加、媒体播放等。在介绍各种应用的同时,辅助以大量详尽的实例源代 码。 这 些实例 , 不仅 具有很 强的实用 价值 和指导意 义, 更让读者 理论 联系实践 , 使学习 DirectShow 技 术 变 得 轻 松 自 如 。本 书 结 构 合 理 , 内 容 丰 富 新 颖 、 条 理 清 晰 , 适 合 广
2、 大 的 流 媒 体 应 用 开 发 人 员 、 系 统 设 计 人 员 、 以 及 对 Windows 平 台 上 多 媒 体 处 理 感 兴 趣 的 编 程 爱 好 者 学 习 和 参 考 。图 书 在 版 编 目 ( CIP) 数 据DirectShow 实务精选/陆其明编著.北京: 科学出版社,2004.7ISBN 7-03-013654-3I. D II. 陆 III. 多 媒 体 软 件 工 具 , Direct ShowIV. TP311.56中国版本图书馆 CIP 数据核字(2004 )第 054879 号责任编辑:洪英 / 责任校对:科海 责任印刷:科海 / 封面设计:谭洁红
3、 出版北 京 东 黄 城 根 北 街 16 号邮 政 编 码 : 100717http:/北京市耀华印刷有限公司印刷 科学出版社发行 各地新华书店经销*2004 年 7 月 第 一 版 开本:16 开2004 年 7 月 第 一 次 印 刷 印张:30印数:14 000 字数:730 千字定 价 : 59.00 元(1CD) (如有印装质量问题,我社负责调换)前 言 笔 者 的 前 一 本 拙 作 DirectShow开 发 指 南 ( 清 华 大 学 出 版 社 , 2003年 ) 自 问 世 以 来 , 颇受业内人士的关注。有褒扬的、有批评的,更多的则是对笔者提出了新的建议。首先, 笔者要
4、衷心地感谢这些热心的朋友,正是这些热心读者的关心和支持,使笔者深受鼓舞, 才决定要再编写一本书。DirectShow 开发指南 比较详尽地介绍了Direct Show系统框架, 以及DirectShow 技术 应用的方方面面。但是,有些读者仍然反馈道:“书的内容讲得细致入微,我都看懂了。 但在实际工作中,碰到问题后还是不知道从何处下手解决”,“看了这本书,基本上学会 了怎么开发Filte r, 但是在 应用程序中使用自己开发的Filte r时 , 碰到了很多 问题 ”, “这 本 书 比 较 偏 重 于 Filter的 开 发 , 能 不 能 再 写 一 本 书 , 专 门 介 绍 Direc
5、tShow技 术 的 实 际 应 用 呢?”看到这些读者的反馈后,笔者心里十分感激,笔者首先要对他们说的是:实践出真 知,要勇于实践。学习一门新技术,贵在理论联系实践。只有把从书本上学到的东西放到 实践中去检验,才能加深对已学知识的理解。反复实践,善于在实践中思考、总结,对于 提 高 自 身 的 技 术 水 平 , 以 及 分 析 问 题 、 解 决 问 题 的 能 力 是 至 关 重 要 的 。 之 后 , 笔 者 也 对 DirectShow开 发 指 南 一 书 的 内 容 进 行 了 一 番 反 思 : 在 这 方 面 , 笔 者 是 不 是 也 有 做 得 不 够的地方呢?或许,一些
6、读者已经学会了如何制砖,但是,他们还不知道如何使用这些砖 头来造房子。考虑许久之后,笔者决定编写本书(专门介绍如何造房子,造各式各样的房 子)。本 着 “实 用 第 一 ”的 原 则 , 笔 者 开 始 写 作 本 书 。 为 了 避 免 与 前 一 本 书 在 内 容 上 的 重 叠 , 本 书 侧 重 介 绍 了 DirectShow技 术 在 当 前 主 要 的 几 个 领 域 中 的 应 用 , 包 括 音 视 频 采 集 、 视 频 聊天、视频点播、视频叠加、媒体播放等。在介绍各种应用的同时,辅助以大量详尽的实 例源代码。这些实例,都是经过笔者精心设计的,不仅具有很强的实用价值和指导
7、意义, 更 能 促 使 读 者 理 论 联 系 实 践 , 真 正 地 提 高 对 DirectShow技 术 的 实 际 应 用 能 力 。 读 完 本 书 之 后 , 读 者 如 果 能 够 从 容 面 对 当 前 市 面 上 绝 大 部 分 的 DirectShow相 关 的 应 用 开 发 , 那 么 , 这 本书的价值也就得到了体现。本书是集体智慧的结晶。衷心感谢出版社的夏非彼老师、编辑李才应等人,如果没有 这些朋友的帮助,就不会有这本书的问世。本书在写作过程中,得到了敏递软件(上海) 有限公司的总经理祝开景博士的关心和支持,还有金邦飞、卞劲松、马涛、季劲松等人的 帮助,衷心感谢他们
8、:“你们是我碰到过的最好的同事!”本书的封面照旧由我的爱人谭 洁红设计,书中各章的插图也出自于她的创意。正是她出色的工作,使本书增色不少!由 于时间短,任务重,再加之笔者的水平有限,书中的错误以及疏漏之处在所难免,望各位专家、同行批评指正。注:本书的配套光盘提供了书中各章节涉及的所有实例源代码。这些实例均 在 Windows 2000操 作 系 统 、 DirectX SDK 9.0、 VC 6.0开 发 环 境 下 编 译 、 测 试 通过。声明:本书提供的实例源代码仅限于学习参考,若用于商业用途,本人不对 源代码的安全性和稳定性、以及因此可能导致的任何损失负责。请读者自行 斟酌。陆其明20
9、04年 6月 于 上 海目 录 第 1章 DirectShow系 统 11.1 系统概述 11.2 使 用 GraphEdit.31.3 最后的话 6第 2章 音 视 频 采 集 92.1 功能介绍 92.2 通用采集 132.2.1 采 集 设 备 枚 举 132.2.2 采 集 设 备 创 建 252.2.3 开 始 视 频 预 览 292.2.4 使 用 高 效 的 VMR .452.2.5 选 择 输 入 端 子 552.2.6 采 集 参 数 设 置 642.2.7 支 持 数 码 摄 像 机 762.2.8 支 持 热 插 拔 822.2.9 支 持 即 时 抓 图 932.2.1
10、0 采 集 到 AVI文 件 .1142.2.11 视 频 的 压 缩 方 案 1182.3 电视接收 1212.3.1 预 备 工 作 1212.3.2 电 视 选 台 1242.3.3 支 持 VBI1252.4 程序导读 1302.4.1 一 种 不 错 的 设 计 模 式 1302.4.2 程 序 结 构 1372.4.3 流 程 概 要 141第 3章 网 络 应 用 .1443.1 网 络 编 程 基 础 .1443.1.1 TCP传 输 .1453.1.2 UDP传输 .1663.1.3 IP组 播 技 术 .1762 目 录3.2 视频聊天 1853.2.1 功 能 介 绍 1
11、853.2.2 实 现 原 理 1873.2.3 采 集 设 备 自 检 1903.2.4 角 色 控 制 实 现 2043.2.5 开 发 网 络 发 送 Filter2233.2.6 开 发 网 络 接 收 Filter2303.2.7 程 序 导 读 2403.3 视频点播 2443.3.1 功 能 介 绍 2443.3.2 实 现 原 理 2473.3.3 开 发 网 络 接 收 Filter2503.3.4 支 持 MPEG1、 MP3 .2613.3.5 支 持 MPEG2 .2683.3.6 支 持 AVI .2703.3.7 程 序 导 读 275第 4章 视 频 叠 加 .3
12、114.1 视频抠像 3114.1.1 抠 像 原 理 3114.1.2 抠 像 算 法 实 现 3124.1.3 MMX算法优化 .3184.1.4 开 发 抠 像 Filter3214.1.5 模 拟 实 时 源 3394.1.6 应 用 演 示 3484.2 字符叠加 3504.2.1 开 发 字 符 叠 加 Filter3504.2.2 与 媒 体 播 放 集 成 353第 5章 SDK源 码 赏 析 3615.1 DSNetwork例子 .3615.1.1 程 序 结 构 分 析 3615.1.2 模 拟 MPEG2-TS源 .3725.1.3 应 用 演 示 3805.2 VMR-
13、9典 型 应 用 .3855.2.1 位 图 叠 加 例 子 BitmapMix3855.2.2 字 符 叠 加 例 子 Ticker3965.2.3 流 混 合 例 子 Blender405目 录 3附录A DirectShow常 见 问 题 解 答 .411A.1 一般性问题 .411A.2 编程问题 .413附录B PID扩 展 插 件 开 发 .420B.1 PID应 用 原 理 420B.2 PID插 件 开 发 421B.3 PID插 件 的 使 用 429附录C DES扩 展 Source( 实 现 字 符 叠 加 ) 432C.1 自动化基础 .433C.2 字符叠加基础 .4
14、33C.3 Source Filter的 开 发 .436C.4 Source Filter的 调 试 .448C.5 DES应 用 举 例 .449附录D 让 Windows Media Player播 放 自 定 义 格 式 文 件 452D.1 播放媒体文件的Filter Graph构 建 过 程 452D.2 两种解决方案 .454D.3 自定义格式文件的生成 .455D.4 Source Filter的 开 发 .457D.5 体 验 QQ文 件 的 播 放 471DirectShow 系统1.1 系 统 概 述很 多 人 都 听 说 过 DirectX, 而 且 知 道 它 神 通
15、 广 大 , 因 为 很 多 软 件 ( 特 别 是 一 些 游 戏 ) 都 钦点了它 要求系统安装DirectX xx以上版本。那么,DirectX iJ底是什么呢?它有哪些 特殊的本领呢?其实, DirectX是微软公司开发的一套基于 Windows平台的 编程接口 (A PI) ; 它能出色地完成高速的实时动画渲染、交互式音乐和环境音效、高效多媒体数据处理等一 般 API很 难 完 成 的 任 务 。从 Windows 95开 始 , 几 乎 每 一 代 Windows操 作 系 统 都 集 成 了 一 定 版 本 的 DirectX运 行 时 库 ( Runtime Library)
16、, 它 们 的 版 本 对 应 关 系 如 表 1.1所 示 。表 1.1 Windows操 作 系 统 与 DirectX的 版 本 对 应操作系统版本 DirectX版 本Windows 95 2.0Windows NT 4.0 3.0aWindows 98 5.0Windows 2000 6.0Windows Me 7.0Windows XP 8.1事实上,DirectX己经成为Windows家族操作系统中不可或缺的核心组件之一。这些组DirectShow实 务 精 选 2文 件 系 统Source Filters内 核 流 架 构WDM采 集 设 备件 可 以 不 断 地 升 级 iJ
17、最 新 版 本 , 但 一 般 不 可 以 卸 载 。 目 前 , DirectX的 最 新 版 本 是 9.0, 它 的 安 装 程 序 可 iJ微 软 公 司 的 官 方 网 站 http:/ 免 费 下 载 ( 本 书 的 配 套光盘也提供)。DirectX的 家 族 成 员 很 多 , 而 且 各 有 各 的 本 领 , 如 DirectDraw和 Direct3D负 责 二 维 图 形 图 像 / 三 维 动 画 加 速 、 DirectMusic 和 DirectSound 负 责 交 互 式 音 乐 / 环 境 音 效 处 理 等 。DirectShow是 DirectX大家族中
18、的一位成员, DirectShow为W indows平台上处理各种格式的媒 体文件播放、音视频采集等高性能要求的多媒体应用提供了完整的解决方案。DirectShow是一个开放性的应用框架,也是一套基于COM的编程接口。DirectShow 的 系统功能如图1.1所示。可以看iJ,图中最大的一块即是DirectShow系统,它的基本工作原 理就是“流水线”:将单元组件 Filter 串联在一起,交由 Filter Graph Manager统 一 控制。 系统的输入可以是本地文件系统、 硬件插卡、 因特网等 , 系统的输出可以是声卡 (声 音再现)、显卡(视频内容显示)、本地文件系统,当然也可以
19、最终将数据向网络发送。应 用 程 序命 令 事 件DirectShow因 特 网Filter Graph ManagerTransform FiltersRendering FiltersACM/VCM编 解 码 器文 件 系 统Ring 3(用户级) Ring 0(特权级)DirectSound DirectDrawVFW采 集 设 备 MPEG2硬件 解 码 器 声卡 显 卡图 1.1 DirectShow 系统功能事 实 上 , 计 算 机 应 用 领 域 中 的 很 多 模 块 都 可 以 和 DirectShow系 统 交 互 。 也 就 是 说 , DirectShow的 应用范畴
20、很广 。 单纯从本地系统来说, DirectShow可 以实现不同格式的媒体文 件的解码播放或格式之间的相互转换,可以从本地机器中的采集设备采集音视频数据并保 存 为 文 件 , 可 以 接 收 、 观 看 模 拟 电 视 等 。 而 从 网 络 应 用 的 角 度 来 说 , DirectShow更 可 用 于 视 频 点 播 、 视 频 会 议 、 视 频 监 控 等 领 域 。 其 实 , 从 广 义 上 来 说 , DirectShow系 统 适 合 于 一 切流式数据的处理,这些数据可以是音频、视频这样的多媒体数据,但又不局限于多媒体 数据。更 多 的 感 性 认 识 DirectS
21、how可 以 借 助 于 GraphEdit 一个随DirectX SDK一 起 发 布 的 小 型 工 具 软 件 ( 即 SDK目 录 中 的 BinDXUtilsgraphedt.exe) 。 下 面 , 就 来 介 绍 这 个 工 具 软 件 的使用。第 1 章 DirectShow系 统31.2 使 用 GraphEditGraphEdit可 以 算 是 一 个 简 单 的 DirectShow应 用 程 序 。 它 有 标 准 的 Windows用 户 界 面 , 如 图 1.2所 示 。图 1.2 GraphEdit 程序界面使用G raphEdit可以查看iJ 系统中所有 (正
22、常) 安装的Filter 。 执行 菜单命令G raph | Insert Filters, 将 弹 出 一 个 如 图 1.3所 示 的 对 话 框 。图 1.3 使用 GraphEdit 查 看 系 统 中 的 Filter提 示 : Filter的 注 册 信 息 通 常 包 括 两 部 分 COM服 务 器 信 息 和 Filter描 述 信 息 。 前 者 是 必 需 的 , 它 表 明 了 Filter是 一 个 COM组 件 ; 后 者 不 是 必 需 的 , 不 注 册也不会妨碍到 Filter功能的实现 。 GraphEdit查看不到没有注 册 Filter描述信息 的 Fi
23、lter。DirectShow实 务 精 选 4图 1.3中 有 很 多 Filter目 录 , 其 中 最 主 要 的 是 DirectShow Filters( 图 1.3中 高 亮 显 示 ) , 因 为绝大部分的Filte r都注 册在这个目录下。 其他的目录, 如 Audio Capture Sources包含的是音 频采集设备, Audio Compressors包含 的是音频各种格式的编码Filter , Video Capture Sources 包 含 的 是 视 频 采 集 设 备 , Video Compressors包 含 的 是 视 频 各 种 格 式 的 编 码 F
24、ilter, WDM Streaming Capture Devices包 含 的 是 本 地 机 器 中 所 有 的 采 集 设 备 ( 包 括 音 频 采 集 设 备 和 视 频 采 集 设 备 ) , WDM Streaming Crossbar Devices包 含 的 是 视 频 采 集 设 备 前 端 的 路 由 装 置 ( 用 于选择视频输入端子) , WDM Streaming TV Tuner Devices包含 的是模拟电视接收设备等等。提示: 通常在开发 DirectShow应用程序时, 注册在 DirectShow Filters目录下的 Filter可 以 通 过 指
25、 定 其 CLSID、 调 用 API函 数 CoCreateInstance来 创 建 , 而 注 册 在 其 他 目 录 ( 如 Audio Capture Sources、 Audio Compressors、 Video Capture Sources、 Video Compressors等 ) 下 的 Filter需 要 通 过 系 统 枚 举 来 创 建 。使用G raphEdit, 还可以播 放媒体文件。 构建指定文件播放用的Filter Grap h至 少有以下4种方法:(1) 执行菜 单命令File | Render Media File, 在随后 弹出的对话框中选择一个媒体
26、文件。( 2) 在 文 件 浏 览 器 中 直 接 将 要 播 放 的 媒 体 文 件 拖 iJGraphEdit中 。( 3) 执 行 菜 单 命 令 Graph | Insert Filters, 在 DirectShow Filters目 录 下 找 iJFile Source(A sync.) , 双击鼠标将其插入 , 在随后弹出的对话框中选择一个媒体文件, 然后再在Source Filter的 输 出 Pin上 右 击 鼠 标 , 从 弹 出 的 快 捷 菜 单 中 选 择 Render Pin命 令 。( 4) 与 方 法 ( 3) 类 似 , 预 先 插 入 所 有 需 要 的
27、Filter;连 接 时 , 在 上 一 级 Filter的 输 出 Pin 上按住鼠标左键不放, 拖动鼠标 iJ下一级Filter 的 输入Pin 上后 释放鼠标 ;这样依次连接所有 必 要 的 Pin即 可 ( 连 接 的 顺 序 一 般 总 是 从 左 iJ右 , 即 从 Source Filter连 iJRenderer Filter) 。构建的Filter Graph如 图 1.4所 示 。图 1.4 典型的文件播放 Filter Graph当Filter Grap h构建完成后 就可以进行播放了。 执行菜单命令 Graph | Play、 Pause或Sto p, 或者直接使用工具
28、条上的播放控制按钮。使 用 GraphEdit, 还 可 以 帮 助 我 们 调 试 自 己 开 发 的 Filter或 者 DirectShow应 用 程 序 。 在 Filter的开 发 项目上, 设置V C项目D EBUG时的执行 程序为gra phedt.exe。 当G raphEdit运行后 , 插 入 我 们 的 Filter, 构 建 特 定 的 Filter Graph, 然 后 运 行 Filter Graph就 可 以 跟 踪 Filter的 实 际 执 行流程了。而在开发DirectShow应用程序时,最通常的做法也是先在GraphEdit 中搭建特定第 1 章 Dire
29、ctShow系 统5的Filter G raph进 行 测 试 。 效 果 满 意 了 , 然 后 再 以 GraphEdit中 的 Filter连 接 图 为 模 板 , 在 应 用 程序中用程序代码来构建。在 应 用 程 序 中 构 建 的 Filter Graph不 像 在 GraphEdit中 构 建 的 那 么 直 观 。 要 是 在 应 用 程 序 中 构 建 的 Filter Graph能 用 GraphEdit显 示 出 来 就 好 了 ! 幸 运 的 是 , GraphEdit提 供 了 这 样 的 功 能,方法是:执行菜单命令File | Connect to Remote
30、 Graph, 随 后 将 弹 出 如 图 1.5所 示 的 对 话 框,选中一个Filter Graph的 注 册 条 目 后 单 击 OK按 钮 即 可 。图 1.5 GraphEdit 的远程连接功能需要注意的是, GraphEdit的这个远程连接功能仅在Wind ows 2000和W indows XP操作系 统下能用,而且还有一个前提是,应用程序必须把它创建的Filter Graph进 行 注 册 , 如 通 过 调 用 AddToRot函 数 实 现 :/ 在应用程序成功创建了一个 Filter Graph之后调用 AddToRot进行注册/ pUnkGraph: Filter G
31、raph Manager对象指针/ pdwRegister:成功注册后返回的一个 IDHRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)IMoniker * pMoniker; IRunningObjectTable *pROT;if (FAILED(GetRunningObjectTable(0, WCHAR wsz256;wsprintfW(wsz, L“pid %08x IFilterGraph = %08x “, GetCurrentProcessId(), (DWORD_PTR)pUnkGraph);HRESULT hr
32、 = CreateItemMoniker(L“!“, wsz, if (SUCCEEDED(hr)hr = pROT-Register(ROTFLAGS_REGISTRATIONKEEPSALIVE,pUnkGraph, pMoniker, pdwRegister); pMoniker-Release();pROT-Release(); return hr;/ 在销毁 Filter Graph Manager对象之前,调用 RemoveFromRot进行反注册DirectShow实 务 精 选 6/ pdwRegister为成功调用 AddToRot函数后返回的 ID void RemoveF
33、romRot(DWORD pdwRegister)IRunningObjectTable *pROT;if (SUCCEEDED(GetRunningObjectTable(0, pROT-Release();应用程序中的整个操作过程如下:IGraphBuilder *pGraph; DWORD dwRegister;/ 创建 Filter Graph ManagerCoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void *)/ 仅在 Debug时注册 Filter Gra
34、ph#ifdef _DEBUGhr = AddToRot(pGraph, #endif/ 应用程序进行其他操作(省略)/ / 对 Filter Graph进行反注册#ifdef _DEBUG RemoveFromRot(dwRegister);#endif/ 销毁 Filter Graph Manager对象 pGraph-Release();提 示 : 掌 握 GraphEdit更 多 的 使 用 方 法 , 请 读 者 参 考 它 的 帮 助 文 档 ( 即 SDK目 录 中 的 BinDXUtilsGraphEdit.chm) 。1.3 最 后 的 话开 发 DirectShow应 用
35、程 序 , 应 该 选 择 哪 种 编 程 语 言 ? 笔 者 推 荐 使 用 VC。 因 为 DirectX SDK最初就 是为V C开发者设计的。 要想深入理解DirectShow 架构 , 没有一定的V C编程基础 也是不行的。 那是不是说, VB、 DELPHI等其他语言的开发者就不能使用 DirectShow了呢 ? 非 也 ! DirectShow应 用 程 序 其 实 就 是 一 种 COM客 户 程 序 , 开 发 语 言 只 要 支 持 COM组 件 的 使 用 就 能 使 用 DirectShow。提示: 对于 VB、 DELPHI等其他语言的开发者来说 , 除了直接使用
36、DirectShow SDK外 , 还 可 以 有 另 外 一 种 方 法 : 使 用 VC对 DirectShow做 一 层 封 装 , 生 成 一第 1 章 DirectShow系 统7个 DLL, 应 用 程 序 上 直 接 调 用 这 个 DLL, 间 接 使 用 DirectShow提 供 的 功 能 服 务。既然说iJ了编程语言, 下面就顺便介绍一下笔者的编程风格。 因为从第2章开始, 读者 将接触iJ大量笔者编写的演示程序。预先了解一下笔者的编程风格,对于理解这些程序将 会很有帮助。笔者喜欢面向对象的程序设计风格,因此会写很多类。类有很多好处,如封装性、继 承性、多态性,更接近于
37、人的自然思维等。类的提取很大程度上取决于对专业应用领域的 了解,以及个人的程序设计经验。类的功能定义应该是很明确的,如这个类主要做什么, 哪些属性是私有的、哪些是保护的(通常情况下不要定义公有属性),哪些接口要对外暴 露、哪些应该隐藏等。很多事物,规模(数量)大了就会凸现一个管理的问题,类也是这 样 。 笔 者 一 般 在 一 个 文 件 中 只 定 义 一 个 类 , 而 且 文 件 的 名 字 跟 类 的 名 字 一 致 ( VC默 认 情 况 下, 文件名会把类的前缀C 去掉 ) 。 例如 现在有一个Filter Gra ph Manager的封装类C DXGraph, 它的实现文件就是
38、C DXGraph.cpp和C DXGraph.h。 而且, 笔者喜欢把同一个类的 .cpp文件 和.h 文 件 放 在 一 起 ( VC默 认 情 况 下 是 分 开 的 , .cpp文 件 放 在 Source Files目 录 下 , .h文 件 放 在 Header Files目 录 下 ) 。 根 据 类 完 成 的 功 能 , 在 VC的 工 作 区 ( Workspace) 建 立 不 同 的 目 录 , 以分别对这些类进行管理。这么做对于一个稍大的项目来说尤为重要。不要一时之间编写 了很多类,回过头来想要查找某个类时却要费九牛二虎之力。如此就麻烦了!笔者喜欢界面、控制逻辑、数据
39、分离的三层结构的程序设计方法。在笔者提供的演示 实例中 , 很多都是基于 MFC对话框类型的程序 , 界面类就是标准的对话框类 CDialog的派生 类。一般在界面类中会定义几个自定义类的实例,这些自定义类,典型的情况下,有一个 是数据封装类,一个是逻辑控制类。这些类的作用是:界面类表达一种用户操作逻辑;数 据 封 装 类 集 中 管 理 各 种 参 数 ;逻 辑 控 制 类 具 体 实 现 业 务 应 用 逻 辑 , 类 名 一 般 类 似 于 CXXXController、CXXXManager 、CXXXAdministrator等。这种界面、控制逻辑、数据分 离的三层结构,不仅使程序框
40、架清晰、容易被人理解,而且具有良好的移植性和扩展性。 笔者不喜欢在代码中写很多注释,除非特别需要(如一些核心算法、异常情况等)。 如果一定要给一段代码写上大段的注释后才能让人理解,笔者首先会怀疑这段代码的合理 性。笔者认为,通过合适的函数命名以及参数、变量的命名,足以让程序具有很好的可读 性 。 在 类 中 定 义 成 员 变 量 , 变 量 名 中 一 般 不 带 下 划 线 ( 太 麻 烦 了 ) , 如 定 义 一 个 long型 变 量 , VC推 荐 的 是 long m_Length, 而 笔 者 更 喜 欢 写 成 long mLength。 对 于 一 些 临 时 变 量 ,
41、笔者一般不会把变量的类型写iJ变量名中去, 如定义int nFileSize, 笔者更喜欢写成int fileSize。 因 为 如 果 以 后 想 改 变 变 量 的 类 型 为 long, 就 没 有 必 要 同 时 改 变 变 量 名 。 ( 如 果 像 原 先 定 义 的int nFileSize, 变 量 类 型 改 成 long之 后 , 为 了 一 致 起 见 , 变 量 名 应 该 相 应 改 成 lFileSize;另 外,程序中所有用iJ该变量的地方都要一一改正。太麻烦!)变量名要取得有实际意义, 如果由几个单词组成,第一个单词全部小写,后面的单词仅第一个字母大写。对于函数
42、的 参 数 , 参 数 名 也 不 带 类 型 信 息 , 而 是 用 前 缀 in表 示 输 入 参 数 , out表 示 输 出 参 数 , io表 示 输 入 并 有 输 出 的 参 数 。 例 如 函 数 BOOL Transform(BYTE * inData, long * ioLength, long * outError),inData是输入参数,指向输入数据的内存,ioLength在函数调用时赋值为输入数 据 的 长 度 , 函 数 返 回 时 被 赋 值 为 实 际 完 成 转 换 的 数 据 长 度 , outError为 输 出 参 数 , 用 于 指 示DirectS
43、how实 务 精 选 8函数调用过程中发生的错误码。 笔 者 的 编 程 风 格 大 致 就 是 这 样 , 希 望 读 者 能 够 理 解 。 重 新 回 iJDirectShow话 题 上 来 。开 发 DirectShow应 用 程 序 需 要 了 解 一 些 COM知 识 , 主 要 是 组 件 的 “使 用 ”问 题 。 而 开 发 DirectShow Filter则 需 要 更 多 的 COM知 识 , 主 要 是 组 件 的 “实 现 ”问 题 。 在 这 里 , 笔 者 最 后 还 要 强 调 一 下 VC开 发 环 境 的 配 置 。 这 一 步 是 很 重 要 的 , 因
44、 为 如 果 开 发 环 境 没 有 配 置 好 , 很 容 易 出 现 一 些 低 级 错 误 。 ( 假 设 DirectX SDK安 装 在 C:DXSDK目 录 下 。 )1. 编 译 基 类 源 代 码 , 至 少 生 成 两 个 静 态 库 文 件 打 开 C:DXSDKSamplesC+ DirectShowBaseClassesbaseclasses.dsw,Debug 版本生成 strmbasd.lib,Release 版本 生 成 strmbase.lib。2. 配置V C的 编译环境: Include目录和L ib目录。 执行 VC的菜单命令Too ls | Option
45、s, 在 随 后 弹 出 的 对 话 框 中 单 击 Directories标 签 , 在 Show directories for下 拉 列 表 中 选 择 Include files, 然 后 配 置 如 下 : ( 注 意 , 务 必 将 DirectX SDK的 目 录 放 在 标 准 的 VC目 录之前。)C:DXSDKInclude C:DXSDKSAMPLESC+DIRECTSHOWBASECLASSES C:DXSDKSAMPLESC+COMMONINCLUDEC:Program FilesMicrosoft Visual StudioVC98INCLUDE C:Program
46、 FilesMicrosoft Visual StudioVC98MFCINCLUDE C:Program FilesMicrosoft Visual StudioVC98ATLINCLUDE再在Show directories for下 拉 列 表 中 选 择 Library files, 配 置 如 下 :C:DXSDKLib C:DXSDKSAMPLESC+DIRECTSHOWBASECLASSESDEBUG C:DXSDKSAMPLESC+DIRECTSHOWBASECLASSESRELEASE C:PROGRAM FILESMICROSOFT SDKLIBC:Program File
47、sMicrosoft Visual StudioVC98LIB C:Program FilesMicrosoft Visual StudioVC98MFCLIB3. 配置DirectShow应用程序开发项目需要连接的库文件。执行 VC的菜单命令Project | Settings, 在 随后弹出的对话框中单击L ink标签, 在O bject/library modules文本框中, Debug版 本 输 入 strmbasd.lib Winmm.lib, Release版 本 输 入 strmbase.lib Winmm.lib。4. 如果安装的DirectX SDK的版本是9.0以前的,请
48、确认在编译应用程序的Debug 版本 之 前 己 经 定 义 了 DEBUG宏 。 执 行 VC的 菜 单 命 令 Project | Settings, 在 随 后 弹 出 的 对 话 框 中 单 击 C/C+ 标 签 , 在 Category 下 拉 列 表 中 选 择 Preprocessor , 然 后 确 认 Preprocessor definitions文 本 框 中 有 DEBUG( 如 果 没 有 就 加 上 ) 。另外,应用程序在调用任何COM库函数之前,务必调用CoInitialize或CoInitializeEx进 行 COM库 的 初 始 化 ( 一 般 只 需 在
49、程 序 启 动 时 调 用 一 次 ) ;在 结 束 所 有 COM操 作 之 后 , 调 用 CoUninitialize进行反初始化(一般在程序退出之前调用一次)。当程序中有多个线程都要 使 用 COM库 函 数 时 , 每 个 线 程 都 要 进 行 初 始 化 和 反 初 始 化 。 总 之 , 要 保 证 CoUninitialize和 CoInitialize( 或 CoInitializeEx) 调 用 的 一 一 配 对 。第 1 章 DirectShow系 统9音视频采集2.1 功 能 介 绍音视频采集是DirectSho w最基本的应用之一。 据一份网上调查表明, DirectShow开发者 中 的 60%都 在 做 音 视 频 采 集 相 关 的 应 用 。 所 谓 采 集 , 通