admin管理员组

文章数量:1531272

2024年7月19日发(作者:)

题 目 在线视频播放系统的设计与实现

学生姓名 崔媛媛 学号 **********

所在学院 物理与电信工程学院

专业班级 电子1202

指导教师 李菊叶

完成地点 物电学院计算机信息处理分室

2016 年 6 月 5 日

陕西理工学院毕业设计

毕业论文﹙设计﹚任务书

院(系) 物电学院 专业班级 电子信息工程 学生姓名 崔媛媛

一、毕业论文﹙设计﹚题目 在线视频播放系统的设计与实现

二、毕业论文﹙设计﹚工作自 2016 年 3 月 10 日 起至 2016 年 6 月 20 日止

三、毕业论文﹙设计﹚进行地点: 物电学院计算机信息处理分室

四、毕业论文﹙设计﹚的内容要求:

随着网络的普及,在线播放器也日益普及起来。本设计要求学生利用Visual C++为开发工具,

使用DirectShow SDK技术开发一个功能齐全的视频播放器,要求能够对硬盘或存储设备上的多媒体

文件进行播放,及在回放或显示过程中,用户可以控制回放的动作和显示特性等相关功能。

五、 毕业论文﹙设计﹚应收集资料及参考文献:

[1]徐孝凯,张纪勇.C++面向对象程序设计:VC++6.0运行环境[M].天津大学出版社2009.

[2]汪晓平,钟军.VC++网络通信协议分析与应用实现[M].北京:人民邮电出版社,2003.

[3]王艳平,张越.Windows网络与通信程序设计[M].北京:人民邮电出版社,2006.

[4] Andrew au.计算机网络(第四版)[M].北京:清华大学出版社,2004.

[5]谢希仁.计算机网络(第五版)[M].北京:电子工业出版社,2012.

[6]朱桂英.张元亮 Visual C++网络编程开发与实践[M].清华大学出版社.2013.

六、 毕业论文﹙设计﹚的进度安排:

3月2日——3月29日:查阅资料,完成初步设计方案和开题报告。

4月1日——4月26日:根据视频播放系统的工作原理,给出设计方案,及软件流程图。

4月29日——5月24:并在软件环境下进行运行调试,进一步完善系统功能,整理资料;

5月27日——6月7日:撰写、修改毕业设计论文。

6月10日——6月15日:打印论文准备并完成答辩。

指导教师签名 系(教研室)主任签名

专业负责人签名 批准日期

陕西理工学院毕业设计

在线视频播放系统的实现与设计

崔媛媛

(陕西理工学院物理与电信工程学院电子信息工程专业,2012级2班,陕西 汉中 723000)

指导教师:李菊叶

[

摘要

]

本设计在Visual C++环境下,利用MFC程序设计方法。并利用DirectShow的播放器核心技术,重点实

现了播放、暂停、停止 、声音控制、进度控制、抓取视频帧、播放模式控制、全屏等功能。通过对系统的需求分析、

设计、实现,完成了多媒体播放器系统,各项功能使用正常,并给出了实现关键代码。DirectShow是基于COM组件,

它是二进制级别的(不受限于编程语言和操作系统),具有很好的兼容性和移植性。

[关键字]

Visual C++;MFC;DirectShow;播放器

陕西理工学院毕业设计

The design and implement of online video broadcast

system

Cui Yuanyuan

(Grade12,Class02,Major electronics and information engineering,School of Physics and

Telecommunication Engineering,Shaanxi University of Technology,Hanzhong 723000,Shaanxi)

Tutor:Li Juye

Abstract:

This design uses MFC program design methods Under Visual C++ environment. At the same time,uses

DirectShow player core technology. Focus to achieve the play, pause, stop, sound control, schedule control, grab video

frames, playback mode control, full screen and other h the system requirements analysis, design,

implementation, completed a media player system, various functions normal use, and gives the realization key

Show is based on the COM component, it is a binary level (not limited to programming languages and operating

systems), has good compatibility and portability.

Keywords:

Visual C++ ;MFC;DirectShow;Player

陕西理工学院毕业设计

目录

1.引言 ................................................................................................... 1

1.1背景 ................................................................................................... 1

1.2 研究目的 .......................................................................................... 1

1.3 开发环境及语言 .............................................................................. 1

1.3.1 VC++2010平台 ....................................................................... 1

1.3.2 MFC概述 ................................................................................ 1

2. DirectShow介绍 .............................................................................. 3

2.1 DirectShow系统 ............................................................................... 3

2.2 DirectShow技术 ............................................................................... 3

2.2.1 过滤器 ..................................................................................... 3

2.2.2 COM组件 ................................................................................ 4

2.2.3针脚Pin ................................................................................... 4

2.2.4 Filter Graph .............................................................................. 5

2.2.5 Filter Graph Manager ............................................................... 5

2.2.6 Filter Graph中的数据流动 ..................................................... 5

2.3 Directshow事件交互 ....................................................................... 5

2.4 基于DirectShow的应用程序开发................................................. 7

2.5播放媒体文件 ................................................................................... 7

3.多媒体播放器的设计 ....................................................................... 9

3.1系统功能设计 ................................................................................... 9

3.1.1媒体文件添加 .......................................................................... 9

i

陕西理工学院毕业设计

3.1.2媒体文件存储和显示 .............................................................. 9

3.1.3媒体文件播放及控制 .............................................................. 9

3.2系统结构设计 ................................................................................... 9

3.3 播放器滤波器链表结构设计 .......................................................... 9

3.4播放视频文件的流程 ....................................................................... 9

3.5 Directshow智能连接 ..................................................................... 10

3.5.1智能连接概述 ........................................................................ 10

3.5.2智能连接的实现 .................................................................... 10

4.视频播放器的开发 ......................................................................... 12

4.1开发环境的配置 ............................................................................. 12

4.2.基于对话框的MFC应用程序 ................................................... 13

4.3 编辑对话框界面 ............................................................................ 13

4.4.视频窗口控制 ................................................................................. 14

4.5封装CDXGraph ............................................................................. 14

4.6.创建Filter Graph ............................................................................ 15

4.7创建播放主题 ................................................................................. 15

4.7.1 打开按钮响应函数 ............................................................... 15

4.7.2渲染 ........................................................................................ 15

4.7.3播放按钮响应函数 ................................................................ 16

4.7.4静音控制 ................................................................................ 17

4.7.5全屏 ........................................................................................ 17

4.7.6暂停、停止 ............................................................................ 18

ii

陕西理工学院毕业设计

4.7.7抓图按钮响应函数 ................................................................ 19

4.7.8退出按钮响应函数 ................................................................ 20

4.7.9进度条的实现 ........................................................................ 20

5.播放控制 ......................................................................................... 21

5.1视频窗口中的右击快捷菜单 ......................................................... 21

5.2相应菜单子项 ................................................................................. 22

5.3速率控制 ......................................................................................... 23

6.程序测试 ......................................................................................... 24

6.1 多媒体播放器的主题界面 ............................................................ 24

6.2程序功能实现 ................................................................................. 24

6.3 测试结论 ........................................................................................ 24

结束语 ................................................................................................ 25

致谢..................................................................................................... 26

参考文献 ............................................................................................ 27

附录A ................................................................................................. 28

附录B ................................................................................................. 34

iii

陕西理工学院毕业设计

1.引言

随着社会的发展,信息技术越来越发达,在线视频播放器在未来社会应用也会越来越普遍。

Microsoft的Windows操作系统作为全球最主流、最常用的操作系统,掌握在它上面的多媒体开发技

术显得越来越需要,相对于其他多媒体开发技术,掌握它本身提供的DirectX多媒体开发包显得更

为适合。

DirectShow是微软提供的多媒体开发包DirectX中的一部分,它是建立在DirectDraw和

DirectSound基础之上。 Microsoft给DirectShow程序员提供了一套开发多媒体标准的、统一的、高

效的API接口,这些接口使得多媒体数据的回放变得简单,剥离了应用程序和硬件底层的差异性。

而DirectShow是基于COM组件的开发包,COM是基于二进制代码级的协议(与编程语言无关的协

议),对使用DirectShow开发的软件以后的移植和兼容问题提供了良好的解决方案。 DirectShow

使用智能连接开发多媒体应用程序,大大简化了开发人员工作量,同时开发人员亦可开发自定义的

滤波器。使得基于DirectShow的应用程序可以充分满足不同用户的需求。在未来几年中,DirectShow

技术的发展前景将是非常广阔的。

1.1背景

当今信息技术越来越发达,社会越来越信息化、智能化,多媒体在未来社会应用越来越广泛。

Microsoft的Windows操作系统作为全球最主流、最常用的操作系统,掌握在它上面的多媒体开发

技术显得越来越需要,相对于其他多媒体开发技术,掌握它本身提供的DirectX多媒体开发包显得

更为适合。

1.2 研究目的

DirectShow是微软提供的多媒体开发包DirectX中的一部分,它是建立在DirectDraw和

DirectSound基础之上。 Microsoft给DirectShow程序员提供了一套开发多媒体标准的、统一的、高

效的API接口,这些接口使得多媒体数据的回放变得简单,剥离了应用程序和硬件底层的差异性。

而DirectShow是基于COM组件的开发包,COM是基于二进制代码级的协议(与编程语言无关的协

议),对使用DirectShow开发的软件以后的移植和兼容问题提供了良好的解决方案。 DirectShow

使用智能连接开发多媒体应用程序,大大简化了开发人员工作量,同时开发人员亦可开发自定义的

滤波器。使得基于DirectShow的应用程序可以充分满足不同用户的需求。在未来几年中DirectShow

技术的发展前景将是非常广阔的。

1.3 开发环境及语言

本文中视频播放系统使用C++语言及Directshow SDK技术,使用visual c++ 2010软件在

directshow的开发环境下进行视频播放器的开发。

1.3.1 VC++2010平台

Microsoft Visual C++,(简称Visual C++、MSVC、VC++或VC)C++语言开发工具,一个集成

的开发环境,能够提供编辑C语言,C++以及C++/CLI系列编程语言。VC++整合便利的除错工具,

尤其是整合Windows API、三维的动画DirectX API,Microsoft .NET框架

[1]

Microsoft Visual C++是微软公司推行开发的Win32环境程序、面向对象且可视化的集成化可编

程系统。其主要优点如下:

(1)程序框架能够自动生成

(2)便于灵活类管理

(3)代码编写与界面的设计可集成相互操作

(4)可开发各种程序

(5)支持各个数据库的接口、OLE2、WinSock网络和3D控制界面

1.3.2 MFC概述

MFC(Microsoft Foundation Classes)是微软公司所提供的类型库(class libraries),以C++类的

方式封装了Windows的API,且含有应用程序的框架,来减少程序开发者的工作量。

MFC中的关键技术:

(1)MFC程序的初始化过程

1

页 共48页

陕西理工学院毕业设计

建立一个MFC窗口:从CWinApp派生应用程序类,然后建立应用程序对象(theApp)。

(2)动态创建

运行的时候创建指定的类的对象。比如视对象、框架的窗口对象等等,比如文档对象需由文档

模版类对象进行动态的创建。

(3)串行化

尽管程序中有着各种数据,串行化机制也如流水般按照顺序储存置于单一文件里,并且也能按

照顺序取出,成为不同对象的数据。

(4)消息映射和传递

MFC把SDK编程中对消息的产生、传递、到过程函数中响应的过程封装起来,形成消息映射

宏、消息映射表和消息响应函数体系,更加直观和便于操作

[2]

2

页 共48页

陕西理工学院毕业设计

2. DirectShow介绍

2.1 DirectShow系统

DirectShow是新一代基于COM的流媒体处理的开发包,是微软公司在ActiveMovie和Video for

Windows的基础上推出的,与DirectX开发包共同发布。Directshow为多媒体的回放和捕捉提供了有

力强大的支持。应用DirectShow,能方便地在支持WDM采集卡中捕获数据,且后期进行一些相应

处理乃至储存到文件里。这样在多媒体的数据库管理系统里多媒体的数据存取就会更加方便。

它的架构如图1所示。图中央即是DirectShow系统,虚线下面是Ring 0特权级硬件设备,虚线

上面是Ring 3特权级的应用层。DirectShow系统处于应用层。它用Filter Graph模型来管理整体数据

流的处理。参与数据的处理的各功能模块称做Filter;各个Filter在Filter Graph中按相应顺序连成一

条“流水线”协调工作

[3]

应用程序

命令

事件

Directshow

文件系统

Filter Graph

ACM/VCM

编解码器

Source

因特网

Filters

Transform

Filters

Rendering

Filters

文件系统

DirectSound

内核流架构

显卡

VFW

采集设备

WDM采集

MPEG2硬

件解码器

声卡

DirectDraw

图2.1 DirectShow架构

2.2 DirectShow技术

2.2.1 过滤器

过滤器是DirectShow 的基本组成单元。DirectShow把数字媒体的处理(播放、捕获和格式转换)

划分为一些独立的步骤,过滤器就是完成一个或多个步骤的COM 对象。DirectShow提供了一组标

准的过滤器供应用程序使用,程序开发者也可以创建自定义的过滤器来扩充Directshow的功能,但

必须是以COM形式建立的

[4]

按照功能来分,Filter大致分为3类:Source Filter、Transform Filter和Rendering Filter。

所有能生成流的DS filter都可以认为是Source filter。这个流可以源自硬盘上的文件,也可以是

实时设备,如话筒,摄像头,或是DC。如果这个流是源自磁盘,那么它可以是预先记录的WAV, AVI

或是Windows Media文件。相应的,如果源是一个实时设备,那么它可以是Window兼容的所有外

设。DS是紧密绑定在WDM上,所有的安装后的多媒体设备的WDM驱动都自动可作为DS的源filter。

因此,例如,安装了驱动的摄像头可以立即成为DS的源filter。将实时设备转换成DS流的源filter

又可以称作捕捉源filter。第12章详细描述了源filter的设计实现。

Transform Filter是DS着墨最多的工作。转换filter从其它filter(可能是源filter)接收一个输入

流,对流执行某些操作后,将流传输给下一个filter。几乎所有能相像得到的对音视频流的操作都可

以在转换filter中实现。一个转换filter可以解析流的数据,编码它(可能将WAV数据转换成MP3格

3

页 共48页

陕西理工学院毕业设计

式)或解码它,或对一个视频序列添加一个文字层。DS包含有大量的转换filter,如编码或解码各种

各样的音视频格式。 转换filter同样还可以给流创建一个多通管道,意思是一个输入流可以复制到

一个或多个输出pin上。而有些转换filter可以将多个输入流混合成一个流。渲染filter将DS流转换

成某种形式的输出。如基本的渲染filter可以将流写到文件。而其它的渲染filter可以将音频流发送

到扬声器,或将视频流发送到桌面上的窗口。DirectShow中的Direct反映的是:使用DirectDraw和

DirectSound的渲染filter支持将它的流高效传输给显卡和声卡的技术。这个能力意味着DS的渲染

filter能进行快速且无关用户-内核模式的传输。(对于OS来说,这个处理意味着将数据从用户层传输

到内核层)。

一个filter graph可以有多个渲染filter。如使用一个多通管道将一路视频流送到一个渲染filter

以生成文件,另一路则将它送到另一个渲染filter以用于显示。从而可以实现监视视频的同时写文件。

简单来说,Source Filter主要负责获取数据,数据源可以是文件、因特网计算机里的采集卡(WDM

驱动的或VFW驱动的)数字摄像机等,然后将数据往下传输;Transform Filter主要负责数据的格式

转换,例如数据流分离、合成,解码、编码等,然后将数据继续往下传输;Rendering Filter主要负

责数据的最终去向——将数据送给显卡、声卡进行多媒体的演示,或者输出到文件进行存储。

2.2.2 COM组件

Directshow是基于COM的流媒体处理的开发包。COM是一种跨应用和语言共享的二

进制代码的方法,它是一个开放的组件标准,具有很强的扩展与扩充能力

[5]

。优点如下:

(1)可以方便的将应用系统扩展至网络环境;

(2)可以将系统中的组件用新的代替掉,以方便随时进行系统的升级和定制;

(3)可以在多个应用系统中多次利用同一个组件;

(4)COM组件与语言和平台无关。

2.2.3针脚Pin

过滤器能和一个或者多个过滤器相连,连接接口是COM形式,叫引脚。过滤器用引脚在各过

滤器之间传输各种数据。每个引脚都是从IPin这个COM对象派生出来的。每个引脚都是过滤器私

有的对象,过滤器能动态地创建引脚、销毁引脚、自由地控制引脚的生存时间。引脚可分为两种类

型:输出引脚和输入引脚。相连的两个引脚须是不同类型的,即输入引脚只能和输出引脚相连,并

且连接方向常是由输出引脚指向输入引脚的。Filter一般由一个或多个Pin组成,Filter之间通过Pin

相互连接,构成一条顺序的链路。Filter的分类亦可根据Filter包含的输入Pin或者输出Pin的数量

进行。

过滤器间的连接,实质上就是连接双方的媒体类型媒体协商的过程。连接大致的过程为:若调

用连接函数的时候已指定完整的媒体类型,那么用此媒体类型进行连接,是否成功都要结束连接进

程;如不完全指定或没有指定媒体的类型,就进行下面的枚举过程:枚举欲连接的输入引脚上的所

有的媒体类型,逐一使用此媒体类型和输出引脚进行连接(如连接函数提供不完全媒体类型,就要

先把每个枚举出的媒体类型和它进行匹配检查),若输出引脚也接受此媒体类型,那么引脚间的连

接就成功了;如果输出引脚对全部输入引脚上所枚举的媒体类型均不支持,那么就枚举输出引脚上

的全部媒体类型,且逐一利用这些媒体类型和输入引脚来进行连接,如果输入引脚接受其中的一种

媒体类型,那么引脚间的连接就成功了;如果对输出引脚上的全部媒体类型输入引脚均不支持,则

这两个引脚间的连接过程宣告失败。

如图2所示,仅含有输出Pin,没有输入Pin的Filter为Source Filter;既有输入Pin又有输出Pin

的Filter为Transform Filter;仅有输入Pin,没有输出Pin的Filter为Rendering Filter。

4

页 共48页

陕西理工学院毕业设计

源过滤器

输出引脚

输入引脚

转换过滤器

输出引脚

输入引脚

图2.2 Filter通过Pin连接

提交过滤器

2.2.4 Filter Graph

在DirectShow中,一个播放程序必需实例化一个或多个过滤器,并把它们连接起来。这样数据

才能从一个过滤器到达另一个,经过它们的处理,直到表现过滤器。所有这些过滤器和它们之间的

连接被称为过滤器图(Filter Graph)。

2.2.5 Filter Graph Manager

Filter Graph Manager 过滤器链表管理器为DirectShow结构的核心,是在过滤器链表中管理各过

滤器的COM对象。主要有以下的功能:

1> 协调Filter之间的状态改变: Graph中的Filter的状态改变应该一致,因此,应用程序并将状

态改变的命令直接发给Filter,而是将相应的状态改变的命令发送给Filter graph Manager,由manager

将命令分发给Graph中每一个Filter。

2> 建立参考时钟: Graph中的Filter均采用同一个时钟——参考时钟(reference clock),来确保

所有数据流的同步,音频帧或视频帧应被提交的时间(presentation time)是利用参考时钟确定的。

Filter graph Manager 应该选择一个可参考的时钟,可选择声卡上的时钟,亦可选系统时钟。

3> 将Graph的消息返回于应用程序:Graph管理器用事件机制把Graph中发生的事件通知给应

用程序,此机制和Windows 的消息循环机制类似。

4> 提供方法构建Filter Graph :Graph 管理器给应用程序提供将Filter 添加进Graph的方法,

断开Filter连接的方法,连接Filter的方法。

但是,Graph管理器没有提供如何将数据从一个Filter发送到另一个Filter的方法,这个工作是

由Filter在内部通过Pin来独立完成的。

2.2.6 Filter Graph中的数据流动

当用户要创建自定义的过滤器时,需了解媒体数据是如何在过滤器图表中传输的。为了在过滤

器图标中传送媒体数据,Directshow过滤器需支持传输协议。连接的过滤器须支持相同的传输相同

传输协议,否则不能交换媒体数据。

绝大多数的Directshow过滤器会把媒体的数据保存于主存储器里,且通过Pin把数据提交给其

他的过滤器,这种传输被称作局部的存储器传输。但并不是所有的过滤器均用局部的存储器传输,

例如有的过滤器用硬件传送媒体的数据,而引脚只是来提交所控制的信息。

Directshow给局部的存储器传输定义了两种机制,分别是推模式和拉模式:

在推模式里,将源过滤器生成数据提交给下级过滤器。下级过滤器被动地接受数据,完成数据

处理之后再传送给下级过滤器。

在拉模式里,源过滤器和分析过滤器相连。分析过滤器向源过滤器请求数据之后,源过滤器则

传送数据来响应请求。

2.3 Directshow事件交互

DirectShow应该有一种机制,能够让应用程序与Filter Graph Manager之间实现交互控制。

常见事件有:

EC_COMPLETE,表示Filter Graph中所有的数据都已经回放完毕;

EC_ERRORABORT,表示Filter Graph运行时出错;

5

页 共48页

陕西理工学院毕业设计

EC_DEVICE_LOST,表示热插拔设备脱离系统;

EC_REPAINT,表示视频窗口要求重画当前图像帧。

事件处理机制:Filter Graph Manager上有3种接口和事件的通知有关,即

IMediaEventSink,IMediaEvent和IMediaEventEx.

IMediaEventSink:用在Filter内部,其接口方法Notify用于向Filter Graph Manager发送事件的通知;

IMediaEvent:应用程序就利用它的接口方法处理Filter Graph Manager发出来的事件;

IMediaEventEx:IMediaEvent接口扩展,支持当Filter Graph Manager 发出事件时,用窗口消息的方

式来通知应用程序。

事件处理大致的过程如下:

一.Filter Graph中的Filter发出事件后,接收者是Filter Graph Manager;

二.Filter Graph Manager对一些特殊事件拥有默认处理的方法。接到事件之后,或按照默认的方法进行

直接处理,或放至事件队列,等候上层应用程序的处理;

三.应用程序获知Filter Graph Manager有事件发出后,则可使用IMediaEventEx接口方法到事件队列里

读取事件,之后依据事件的类型作相应的处理.

那么,应用程序是怎么知道Filter Graph Manager的事件队列里有事件在等待处理?

有两种办法:一种是Filter Graph Manager通过发送指定的窗口消息来通知应用程序,另一种通过事

件来同步对象。

一种:

//自定义一个消息,然后调用IMediaEventEx::SetNotifyWindow将其设置给Filter Graph Manager

#define WM_GRAPHNOTIFY (WM_APP+100)

IMediaEventEx *pEvent=NULL;

hr=pGraph->QueryInterface(IID_IMediaEventEx,(void**)&pEvent);

hr=pEvent->SetNotifyWindow((DAHWND)m_hwnd,WM_GRAPHNOTIFY,0);

//定义消息映射

ON_MESSAGE(WM_GRAPHNOTIFY,OnGraphNotify)

//在消息响应函数中获取Filter Graph的事件通知,并作出相应处理,

void CNotifyWnd::OnGraphNotify(WPARAM inWParam,LPARAM inLParam)

{

if(pEvent)

{

LONG eventCode=0,eventParam1=0,eventParam2=0;

while(SUCCEEDED(pEvent->GetEvent(&eventCode,&eventParam1,eventParam2);

switch(eventCode)

{

case EC_COMPLETE:

break;

case EC_USERABORT:

break;

case EC_ERRORABORT:

break;

default:

break;

}

}

}

第二种在Filter Graph Manager在内部创建了一个事件同步对象,它在事件队列中有尚未处理的事件

6

页 共48页

陕西理工学院毕业设计

时,状态标记为有效,而当应用程序不断调用接口方法取空事件状态复位。我们可以通过

IMediaEvent::GetEventHandle来得到这个事件同步对象的句柄。

HANDLE hEvent;

long evCode,param1,param2;

BOOLEAN bDone=FALSE;

HRESULT hr=S_OK;

hr=pEvent->GetEventHandle((OAEVENT*)&hEvent);

while(!bDone)

{

if(WAIT_OBJECT_0==WaitForSingleObject(hEvent,100))

{

while(hr=pEvent->GetEvent(&evCode,¶m1,¶m2,0),SUCCEEDED(hr))

{

printf("Event code:%#04xn Params:%d,%dn",evCode,param1,param2);

hr=pEvent->FreeEventParams(evCode,param1,param2);

bDone=(EC_COMPLETE==evCode);

}

}

}

2.4 基于DirectShow的应用程序开发

基于DirectShow的应用程序开发一般过程如图所示:

应用程序 应用程序 应用程序

方法调用

事件

滤波图标管理器 滤波图标管理器

滤波图标管理器

图2.3 基于DirectShow的应用程序开发过程

第一阶段,创建一个Filter Graph Manager组件。

第二阶段,根据实际的应用,创建一条完整的Filter链路。

第三阶段,调用Filter Graph Manager上(或直接在某个Filter上)的各个接口方法进行控制,

并且完成Filter Graph Manager与应用程序的事件交互。

2.5播放媒体文件

DirectShow提供了大量的Filter用以支持最基本的应用。根据实际需要,也可以定制一个自己的

Filter。它的最基本应用为回放媒体文件。如下图是一个AVI文件的回放链路。

7

页 共48页

陕西理工学院毕业设计

文件源

AVI splitter

AVI 解压处理

硬盘

视频输出

显卡

默认的音频装置

声卡

图2.4 本地AVI格式文件回放的链路

其中,箭头的方向即是数据的方向。Filter Source属于Source Filters,它用来管理硬盘里指定播放的

文件,并依据AVI Splitter要求提供相应数据。AVI Splitter与AVI解压处理属于Transform Filters,

其中,AVI Splitter负责向Filter Source索取数据,并将取得的音频和视频进行分离,然后分别从各

自的输出pin输出:AVI 解压处理负责视频的解码。Video Renderer和默认的音频装置负责同步播放

声音

[6]

8

页 共48页

陕西理工学院毕业设计

3.多媒体播放器的设计

3.1系统功能设计

3.1.1媒体文件添加

系统的输入数据来源于用户打开读取媒体文件,包含打开单个媒体文件和文件夹两个选择。

3.1.2媒体文件存储和显示

系统得到输入数据后,对它们进行存储和显示,为后续播放、控制操作奠定基础。

3.1.3媒体文件播放及控制

已知媒体文件存储信息的基础上,执行源滤波器->分解滤波器->音/视频解码滤波器->音/视频播

放滤波器->数据输出(音视频设备)流程以及对整个过程的控制。

3.2系统结构设计

此软件的整体结构设计如下图所示:

视频播放器

播放

暂停

停止

图3.1 系统整体结构

3.3 播放器滤波器链表结构设计

视频解码转换滤波器

视频播放滤波器

音频解码转换滤波器

图3.2播放器的滤波器链表结构

音频播放滤波器

3.4播放视频文件的流程

9

页 共48页

陕西理工学院毕业设计

CoCreateInstance(…,pGraph)

pGraph->QueryInterface(…,pMediaControl)

CoInitialize()

pGraph->QueryInterface(…,pMediaEvent)

pGraph->RenderFile("")

pMediaControl->Run()

pMediaEvent->WaitForCompletion()

CoUninitialize()

图3.3 播放视频文件的流程

流程图中关键函数的作用如下所示。

CoInitialize():初始化COM运行环境;

CoCreateInstance(…,pGraph) :用指定的类标识符创建一个Com对象。在该播放器中类标识符

为“CLSID_FilterGraph”,用于创建IGraphBuilder。

pGraph->QueryInterface(…,pMediaControl):通过QueryInterface()查询某个组件是否支持某个特

定的接口。在这里查询IMediaControl接口。

pGraph->QueryInterface(…,pMediaEvent) :同上。在这里查询IMediaEvent接口。

pGraph->RenderFile(""):为指定的文件智能的构建一个Filter Graph。

pMediaControl->Run() :开始运行Filter Graph中所有的Filter。

pMediaEvent->WaitForCompletion() :等待Filter Graph处理完所有数据。

CoUninitialize():释放CoInitialize()初始化的COM运行环境

[7]

3.5 Directshow智能连接

3.5.1智能连接概述

智能连接是滤波器链表管理器用以构建滤波器链表的机制,它包含了一系列选择滤波器和将其

添加到链表中去的算法。本软件即采用此方法构建供数据流传输的滤波器链表。

3.5.2智能连接的实现

智能连接的基本方法为试连接,它首先用内存中的Filter试连接,若不成功,则对当前的Filter

Graph中还没有完全连接的Filter进行试连接。如果不行,再从系统Filter里选取匹配的、最合适的

Filter进行试连,直到连接成功。若找不到合适的Filter,则失败返回。

10

页 共48页

陕西理工学院毕业设计

所以只要Filter Graph中有不同类型的、可接受同一媒体类型的Filter,则采用智能连接,每个

Filter都可连在正确的位置。为什么在智能连接中不同类型的Filter会连在各自的位置上呢?因为这

些Filter能接受的媒体类型不同。

从源Filter出来的数据流只带有编码格式信息,其他信息都是未知的,所以音视频解码Filter和

处理Filter都不能用,只能使用分离Filter匹配这种媒体类型,所以只会试连接分离Filter。而从分

离Filter出来的数据分为音、视频两路,每路的数据流都加上了音频或者视频的信息,但没有标明这

是何种音频或视频的信息,所以可以被音视频解码器Filter接受,但不能被音视频处理Filter接受。

而从音视频解码Filter出来的数据流带上了具体格式的音视频媒体类型的信息,所以能被音视频处理

Filter接受,最后发送到提交过滤器

[8]

11

页 共48页

陕西理工学院毕业设计

4.视频播放器的开发

4.1开发环境的配置

选择Microsoft DirectX 9.0 SDK (Summer 2004)和Microsoft Visual C++ 6.0作为Directshow播放

器的开发平台。

(1)下载静态库并复制到C:Program FilesMicrosoft DirectX 9.0 SDK (Summer

2004)Lib路径下。

(2) 使用_stdcall函数调用协议和多线程c语言的运行时库,即在VC菜单里选择

Project|Settings|C/C++,在弹出对话框中Category中选择Code generation,再在Calling convention中

选择_stdcal l,Use run-time library选择Debug Multithreaded Dll。

(3)配置必要链接库的文件,即在Visual C++的菜单里选择Project|Settings|Link,在弹出对话

框中Category中选择General,再在Object/library modules输入 。

(4)确认Direct SDK的include目录和lib目录都已经加入到VC的系统编译环境,选择

Tools|Options|directions,选择include files目录,加入如下路径:

(a)属性页

12

页 共48页

陕西理工学院毕业设计

(b)可执行目录配置

图4.1 VC中路径配置

4.2.基于对话框的MFC应用程序

使用VC的项目向导生成一个基于对话框的MFC应用程序,项目名称为MediaPlayer,并在

CMediaPlayerApp中添加COM库初始化、反初始化代码:

BOOL CMediaPlayerApp::InitInstance()

{

CoInitialize(NULL);//COM库初始化

CSimplePlayerDlg dlg;

m_pMainWnd = &dlg;

int nResponse = l();

……

}

int CSimplePlayerApp::ExitInstance()

{

CoUninitialize();//COM库反初始化

return CWinApp::ExitInstance();

}

4.3 编辑对话框界面

在资源编辑器中编辑主对话框界面,如下图:

13

页 共48页

陕西理工学院毕业设计

图4.2 播放器界面设计

4.4.视频窗口控制

定义一个视频窗口的控制对象:CStatic mVideoWindow ; 在主对话框的初始化函数

OnInitDialog中增加修改视频窗口的函数Style(0,WS_CLIPCHILDREN);并添

加WM_ERASEBKGND消息响应

[9]

。代码如下:

BOOL CMediaPlayerDlg::OnEraseBkgnd(CDC* pDC)

{

//为视频窗口擦除背景,否则当被其他窗口遮蔽后会变成默认的灰色

CRect rc;

dowRect(&rc);//获得窗口的矩形边界

ScreenToClient(&rc);

pDC->ExcludeClipRect(&rc);//排除被视频窗口覆盖的裁剪区域

return CDialog::OnEraseBkgnd(pDC);//擦除对话框剩下的区域

}

4.5封装CDXGraph

DirectShow是基于COM组件的开发包,所以此在应用程序的最开始应该初始化COM库环境。

实现为:在应用程序对象MediaPlayerApp的InitInstance函数中调用AfxOleInit()或者

CoInitialize(NULL)函数。

Directshow SDK是一个库函数,在使用时需要遵循先创建、再使用、后销毁的原则。媒体的播

放和图像显示等功能都是由SDK来完成的。为了系统开发方便,通常把与SDK有关的开发函数封

装在CDXGraph中去。这样应用程序可以使用其中的成员函数和变量来完成媒体的播放与显示。该

类中包含了回放媒体时所需要的几乎所有的动作和控制方法,也包括Filter Graph Manager的创建及

其各种控制接口等,在主对话框类中,定义一个CDXGraph的指针:CDXGraph*mFilterGraph;

14

页 共48页

陕西理工学院毕业设计

4.6.创建Filter Graph

在此需要首先创建滤波器链表管理器,然后在该链表下查询、使用各个接口。根据用户选择的

源文件,创建相应的回放Filter Graph,代码如下:

void CMediaPlayerDlg::DestroyGraph(void)

{

if (mFilterGraph)

{

mFilterGraph->Stop();// 停止滤器图表

mFilterGraph->SetNotifyWindow(NULL);//窗口消息处理

delete mFilterGraph;

mFilterGraph = NULL;

}

}

void CMediaPlayerDlg::CreateGraph(void)

{

DestroyGraph();//确保mFilterGraph为空

mFilterGraph = new CDXGraph();//新建Filter Graph

if (mFilterGraph->Create())//创建Filter Graph Manager

{

mFilterGraph->RenderFile(mSourceFile); // 获取源数据

mFilterGraph->SetDisplayWindow(eHwnd());//设置显示窗口

mFilterGraph->SetNotifyWindow(this->GetSafeHwnd());//窗口消息处理

mFilterGraph->Pause();//显示第一帧

}

4.7创建播放主题

4.7.1 打开按钮响应函数

单击播放器界面中的“打开”按钮后,即可打开要播放的媒体文件,此处需要添加一个鼠标单

击事件响应。代码如下:

void CMediaPlayerDlg::OnButtonOpen()

{

CString strFilter = "AVI File (*.avi)|*.avi|";//打开文件类型提示

strFilter += "MPEG File (*.mpg;*.mpeg)|*.mpg;*.mpeg|";

strFilter += "Wave File (*.wav)|*.wav|";

strFilter += "All Files (*.*)|*.*|";

CfileDialog dlgOpen(TRUE, NULL, NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,

strFilter, this); //打开文件对话框

if (IDOK == l())

{

mSourceFile = hName();

CreateGraph();//创建相应的回放Filter Graph

}

}

4.7.2渲染

渲染媒体文件,把显示图像窗口和Directshow SDK的视频窗口接口进行捆绑。因为所有对

Directshow SDK的控制是在封装类CDXGraph中实现的,所以首先要创建一个CDXGraph对象; 然

15

页 共48页

陕西理工学院毕业设计

后创建滤波器链表管理器,并把读取的文件的路径名改为宽字符形式。渲染媒体文件,自动剖析媒

体格式,构建滤波器列表。如果渲染成功,则设置图像显示窗口并注册消息通知窗口;最后显示第

一帧图像后,马上暂停。具体代码如下:

void CMediaPlayerDlg::CreateGraph()

{

DestroyGraph(); //销毁滤波器链表图

m_pFilterGraph = new CDXGraph(); //创建CDXGraph对象

if (m_pFilterGraph->Create()) //创建滤波器链表管理器

{

//if (!m_pFilterGraph->RenderFile(ch))//渲染媒体文件,构建滤波器链表括

TCHAR *ch1 = m_fer(m_gth());

if (!m_pFilterGraph->RenderFile(ch1))//渲染媒体文件?构建滤波器链,

{

MessageBox(_T("无法渲染此媒体文件!请确认是否安装相关解码器插件!n 或者此媒体文件已

损坏!"),_T( ("系统提示"),MB_ICONWARNING);

return;

}

m_eBuffer();

//设置图像显示窗口

m_pFilterGraph->SetDisplayWindow(m_eHwnd());

//设置窗口消息通知

m_pFilterGraph->SetNotifyWindow(this->GetSafeHwnd());

//显示第一帧图像

m_pFilterGraph->Pause();

}

}

4.7.3播放按钮响应函数

单击“播放”按钮后开始播放选择的媒体文件,同时在标题栏中显示播放速度和媒体文件名。

具体代码如下:

void CMediaPlayerDlg::OnButtonPlay()

{

if (mFilterGraph)

{

mFilterGraph->Run();//运行图表

if (mSliderTimer == 0)

{

mSliderTimer = SetTimer(SLIDER_TIMER, 100, NULL);//设置计时器

}

}

}

为了获取媒体播放的信息和各种事件。需要向窗口发送通知,具体步骤如下。

向对话框类中添加自定义的消息处理函数OnGrsphNotify:

afx_msg LRESULT OnGraphNotify(WPARAM inWParam, LPARAM inLParam);

向对话框消息映射部分添加消息映射宏:

16

页 共48页

陕西理工学院毕业设计

ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)

消息处理函数OnGraphNotify的具体实现代码如下:

LRESULT CMediaPlayerDlg::OnGraphNotify(WPARAM inWParam, LPARAM inLParam)

{

IMediaEventEx *pEvent = NULL;

if ((m_pFilterGraph!=NULL) && (pEvent = m_pFilterGraph->GetEventHandle()))

{

LONG eventCode = 0;

LONG eventParam1 = 0;

LONG eventParam2 = 0;

while (SUCCEEDED(pEvent->GetEvent(&eventCode, &eventParam1, &eventParam2, 0)))

{

pEvent->FreeEventParams(eventCode, eventParam1, eventParam2);

switch (eventCode)

{

case EC_COMPLETE:

OnBnClickedButtonPause();

m_pFilterGraph->SetCurrentPosition(0);

break;

case EC_USERABORT:

case EC_ERRORABORT:

OnBnClickedButtonStop();

break;

default:

break;

}

}

}

return 0;

}

4.7.4静音控制

有时用户在播放音频/视频中需要关掉声音,除了可以调节音量大小外,还可以使用静音操作更

为快捷。 原理为调用滤波器链表管理器的基本声音接口的设置声音函数,其实现如下:

m_pBasicAudio->put_Volume(-10000);

恢复声音:

long lVolume = (m_nVolume - 100) * 100;

m_pBasicAudio->put_Volume(lVolume);

在DirectShow中,声音的最大值表示为0,最小值表示为-10000。

4.7.5全屏

在播放视频文件时,经常需要将播放画面放大以至全屏,视觉效果和体验更好。在此软件中也

做了该操作,原理为调用滤波器链表管理器的视频窗口接口的全屏函数,其实现如下:

m_pVideoWindow->put_FullScreenMode(inEnabled?OATRUE:OAFALSE)

其中参数inEnabled为确定全屏或者退出全屏模式,针对此操作,捕获了Esc按钮消息亦可响应。

此软件在实际操作中,能够正常使视频画面全屏显示并能退出全屏模式

[10]

具体代码如下:

17

页 共48页

陕西理工学院毕业设计

void CMediaPlayerDlg::OnMenuFullscreen()

{

//(pMsg->put_WindowStyle(WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_THI

CKFRAME);

// TODO: 在此添加命令处理程序代码

static int flag=0;

if (m_pFilterGraph != NULL)

{

if (!flag){

m_pFilterGraph->SetFullScreen(TRUE);

flag = 1;

}else{

m_pFilterGraph->SetFullScreen(FALSE);

flag = 0;

}

}

}

4.7.6暂停、停止

用户在播放媒体文件过程中,想暂停或者停止播放,则可以点击相应菜单选项、图标或者按钮

即可。原理跟播放操作类似,即调用滤波器链表管理器控制接口中的暂停/停止函数,其实现如下:

m_pMediaControl->Pause();

m_pMediaControl->Stop();

其中,点击暂停后,点击一下播放按钮即可恢复播放状态,点击停止后则需点击播放按钮两下。

暂停按钮响应函数

void CMediaPlayerDlg::OnButtonPause()

{

if (mFilterGraph)

{

mFilterGraph->Pause();//暂停图表

if (mSliderTimer == 0)

{

mSliderTimer = SetTimer(SLIDER_TIMER, 100, NULL); //开始计时

}

}

}

停止按钮响应函数

void CMediaPlayerDlg::OnButtonStop()

{

if (mFilterGraph)

{

mFilterGraph->SetCurrentPosition(0);//设置当前位置

mFilterGraph->Stop();//停止图表

if (mSliderTimer)

{

KillTimer(mSliderTimer);//停止计时器

mSliderTimer = 0;

18

页 共48页

陕西理工学院毕业设计

}

}

}

4.7.7抓图按钮响应函数

用户在播放视频文件中,有时根据实际需要想要把某帧画面截取下来存放到指定目录以供使用。

此软件亦实现了此功能,在此默认的是把截取的图片放到跟应用程序的可执行文件的同一目录下且

保存为bmp格式的图片。原理是调用滤波器链表管理器的基本视频接口中的抓取当前帧函数,其实

现如下

[11]

void CMediaPlayerDlg::OnBnClickedButtonGrasp()

{

static int c = 0;

TCHAR szFilename[MAX_PATH];

DWORD dwPathLen = 0;

if((dwPathLen = ::GetModuleFileName(::AfxGetInstanceHandle(),szFilename, MAX_PATH ))== 0)

{

return;

}

for( int i=dwPathLen-1; i>=0; i--)

{

if(('' == szFilename[i]) || ('/' == szFilename[i]))

{

break;

} else {

szFilename[i] = '0';

}

}

CString str;

(_T("%s"),szFilename);

CString strTemp;

(_T("%d"),c);

str += strTemp + _T(".bmp");

c++;

TCHAR *p=fer(gth());

eBuffer();

if (m_pFilterGraph != NULL)

{

if (m_pFilterGraph->SnapshotBitmap(p))

{

}else

MessageBox(_T("抓图失败"));

}

19

页 共48页

陕西理工学院毕业设计

抓图列表如下:

图4.3 抓图列表

4.7.8退出按钮响应函数

void CMediaPlayerDlg::OnMenuExit()

{

OnBnClickedButtonStop();

CDialog::OnOK();

}

4.7.9进度条的实现

(1)为进度条控件添加控制类:CsliderCtrl mSliderGraph;

(2)在主对话框的初始化函数OnInitDialog中,初始化进度控件:

ge(0,100); (0);

(3)实现进度即时显示。用一个定时器,不断调用ImediaSeeking::GetCurrentPosition接口方法来

获得当前播放的时间点,之后依据媒体文件总时间的长度,计算出进度百分比,再转化成进度控件

当前的位置值,调用CsliderCtrl::SetPos函数设置

[12]

。定时消息处理如下:

void CMediaPlayerDlg::OnTimer(UINT nIDEvent)

{

if (nIDEvent == mSliderTimer && mFilterGraph)

{

double pos = 0, duration = 1.;

mFilterGraph->GetCurrentPosition(&pos); //获得当前播放的时间点

mFilterGraph->GetDuration(&duration); //获得文件播放总时间

int newPos = int(pos * 1000 / duration);//进度条新位置

if (() != newPos)

{

(newPos); //设置进度条新位置

}

}

CDialog::OnTimer(nIDEvent);

20

页 共48页

陕西理工学院毕业设计

5.播放控制

5.1视频窗口中的右击快捷菜单

在播放视频时,鼠标右击后弹出如图所示的菜单命令,通过这些菜单命令可以对当前的播放的

视频进行控制。

图5.1 快捷菜单

具体代码实现如下

[13]

BOOL CMediaPlayerDlg::PreTranslateMessage(MSG* pMsg)

{

// CG: The following block was added by the ToolTips component.

{

// Let the ToolTip process this message.

m_vent(pMsg);

}

if (pMsg->message == WM_KEYDOWN)

{

if (pMsg->wParam == VK_RETURN || VK_ESCAPE)

{

//RestoreFromFullScreen();

if (m_pFilterGraph != NULL)

{

if (m_pFilterGraph->GetFullScreen())

{

m_pFilterGraph->SetFullScreen(FALSE);

}

}

return TRUE;

21

页 共48页

陕西理工学院毕业设计

}

}else if (WM_RBUTTONDOWN == pMsg->message)

{

CPoint point;

//HMENU hmenu;

CMenu hmenu;

HMENU hmenuTrackPopup;

nu(IDR_MENU_MAIN);

GetCursorPos(&point);

hmenuTrackPopup = GetSubMenu(hmenu, 0);

TrackPopupMenu(hmenuTrackPopup, TPM_LEFTALIGN | TPM_LEFTBUTTON, point.x, point.y, 0,

this->m_hWnd, NULL);

DestroyMenu(hmenu);

}

return CDialog::PreTranslateMessage(pMsg);

}

5.2相应菜单子项

在右击后,里面有一个“OpenFile”菜单,此菜单下可以设置子菜单项。右击此菜单后,在弹

出的菜单命令中选择“添加事件处理程序命令”后,将弹出“事件处理程序向导”对话框,如图所

示。

22

页 共48页

陕西理工学院毕业设计

图5.2“事件处理程序向导”对话框

选择消息类型“COMMAND”,在类列表中选择“CMediaPlayerDlg”选项,然后单击“添加编

辑”按钮,此时会产生并补充后的代码如下

[14]

void CMediaPlayerDlg::OnMenuOpenfile()

{

// TODO: 在此添加命令处理程序代码

OnBnClickedButtonOpen();

}

5.3速率控制

用户在播放音视频过程中,有时需要快进或者慢放,这里跟拖动进度条实现快进不同,这里是

使整个播放过程速度均匀保持快进或者慢放。 此软件中设置了三种播放速率,1/2正常速率、正常

速率和2倍正常速率。原理为调用滤波器链表管理器媒体定位接口的设置速率函数,其实现如下:

m_pMediaSeeking->SetRate(inRate);

参数inRate为相对于正常速率的比例,此处可以为1/2、1和2。同时在播放器的顶端标题处会

显示当前媒体文件的播放速率,显得直观、易见

[15]

其他相关菜单子项同“OpenFile”菜单一样,逐一添加代码。

23

页 共48页

陕西理工学院毕业设计

6.程序测试

6.1 多媒体播放器的主题界面

播放主界面如图所示:

图6.1 播放器主界面

6.2程序功能实现

1> 能够播放AVI、MPEG、WAV格式的视频文件。

2> 能通过播放、暂停、停止按钮对视频的播放进行相应的控制。

3> 视频播放过程中能通过进度条显示播放进度。

4>能够实现全屏并退出全屏。

5>能够控制播放速率。

6> 正常执行抓取视频图像帧功能,将抓取的图像帧存放到指定目录(默认为当前应用程序可执

行文件目录)

6.3 测试结论

对此软件的测试记录结果表明系统所有的设计功能基本实现,达到预期目标。

24

页 共48页

陕西理工学院毕业设计

结束语

随着这篇毕业论文的收笔,我的毕业设计也接近尾声了。在最近的四个月中,我一直为此忙碌

着,学习、生活基本都是以它为中心。搜集材料,确定方案,不停修改,整理资料,综合等等,时

间过得简单而又紧凑。这四个月里,我经历了许多,得到了许多,也失去了很多,在这个过程中我

走过许多弯路,但也经历了太多太多的喜悦。我得到的并不只是书本上的知识,更是一个人工作研

究的态度,心境,经验——一个大学本科生对待自己的专业,对待自己的工作应该抱着一种态度;一

个人对待专业知识上的困难,应该怎样解决;一个人应该怎样面对成功与失败;一个人应该怎样和周围

的人交流等等——对于我来说,这些都是无价的。在这4个月中我的努力,仅仅为了将自己的想法

一点点地在现实世界中实现,虽然我回避了一些困难,虽然有些问题到现在还未得到很好的解决,

虽然我四个月的成就在行家眼里看来有些幼稚,但是我自己的努力都值得,这些已经令我感到欣慰

了。

另外也在一些不足之处,因为时间和能力的因素,此软件有很多可改进的地方,比如播放界面

可以做得更漂亮、软件功能可以更齐全、可以加入网络连接使软件融入Internet、可以加入视频捕获

等功能。以后有机会我一定深入这方面的研究。这个过程不但是一个学习更给了我的工作实践中很

大的帮助,更让我鼓足勇气,在自己专业这条道路上走得更远、更好。

25

页 共48页

陕西理工学院毕业设计

致谢

感谢我的指导老师李老师,感谢她即使是周末的休息时间,也耐心的帮我解决问题;感谢她对

我毕设的指导与帮助。

感谢我的室友们,从遥远的家来到这个陌生的城市里,是你们和我共同维系着彼此之间姐妹般

的感情,维系着寝室那份家的融洽。四年了,仿佛就在昨天。四年里,我们有太多欢声与笑语,一

起上课,一起吃饭,一起玩闹。即使也有拌嘴有吵闹,也会很快和好。在做毕设的这段日子里,我

们一起探讨并解决问题。我们在一起的日子,岂能容易忘记。

感谢我的爸爸妈妈,你们对我的爱我无以回报,你们永远健康快乐是我最大的心愿。

在论文即将完成之际,我的心情无法平静,从开始进入课题到论文的顺利完成,有多少可敬的师长、

同学、朋友给了我无言的帮助,在这里请接受我诚挚的谢意。

26

页 共 48 页

陕西理工学院毕业设计

参考文献

[1]徐孝凯,张纪勇.C++面向对象程序设计:VC++6.0运行环境[M].天津大学出版社,2009.13-14.

[2]侯俊杰.深入浅出MFC[M].湖北:华中科技大学出版社,2013.11-12.

[3]朱桂英,张元亮 .Visual C++网络编程开发与实践[M].清华大学出版社,2013.89-118.

[4]李桂兰,马旭东.Windows CE中的Directshow Filter开发[J]. 2008年3期.3-4.

[5]李冰山.COM组件技术及其应用[M].大连理工大学,2000.8-10

[4]庞然.基于Directx的音视频播放器软件设计[M].北京工业大学,2006.9-12

[5] 戴雯惠.基于VC++与DirectShow技术的媒体播放器的设计与实现[M].甘肃纵横科技.2010.6-17

[6]方淑燕.基于流媒体技术的视频点播系统[M].天津大学,2007.9-16

[7]吴联芳.基于DirectshowShow的音视频流媒体播放系统设计及加密技术研究[M].浙江大,2008.15-20.

[8]袁红亮.基于DirectShow的流媒体实时传输的研究与实现[M].大连理工大学,2009.12-20

[9]Fan Zhang、Bo Show Based Internet Video on Demand System[M]. Institute of Advanced Control and

Intelligent Information Processing Henan University.2000.23-35.

[10]Collins R.A system for video surveillance and monitoring: VSAM final report[M]. Carnegie Mellon University:

Technical Report CMU, 2000,45-69.

[11] B. Bose, E. Grimson. Improving Object Classification in Far-Field Video In: Proc. CVPR (2), 2004. 181–188

[12]汪晓平,钟军.VC++网络通信协议分析与应用实现[M].北京:人民邮电出版社,2003.5-18.

[13]薛勇.DirectShow技术在视频转码中的应用研究.电脑编程技巧与维护[J]. 2009年22期.22-24.

[14] Andrew au.计算机网络(第四版)[M].北京:清华大学出版社,2004.23-43.

[15]王艳平,张越.Windows网络与通信程序设计[M].北京:人民邮电出版社,2006.12-30.

27

页 共 48页

陕西理工学院毕业设计

附录A

外文文献

Visual C++ MFC concise course

MFC introductory remarks

Visual C++ not merely is a compiler. It is a comprehensive application procedure development

environment,you fully use C++ which has object-oriented characteristic to develop the specialized

Windows application procedure. In order to fully use these characteristics, you must understand the C++

programming you want grasped C++, you must grasp the Microsoft basic kind of storehouse

(MFC) level structure. This level structure contained user contact surface in the Windows API,and enabled

you very easily to establish the Windows application procedure by the object-oriented way. This kind of

level structure is suitable to all editions Windows and each other is compatible. You use the code which

MFC establishes are definitely may transplant.

If you want establish a Windows application procedure, how should start?

The good beginning is from designning user contact surface. First, you must decide what kind of user

can use this procedure and according to needs to establish the corresponding user contact surface object.

The Windows user contact surface has some standards to control, like the button, the menu, roll the strip

and tabulates and so on, this is be familiared with Windows users. You must remember, as a programmer

you mustt choose a group as the programmer to control and to decide how to arranges them to the screen.

Traditionaly, you need to make the schematic diagram of the user contact surface on the paper, until you

satified with various elements. This is possible to some small project, as well as some big project at early

time prototype stages.

The next step, is must realize the code. When for any Windows platform establishment application

procedure, the programmers all have two kind of choices: C or C++. Uses C, the programmer is in the

Windows application procedure contact surface (API) in the level compiles the code. This contact surface is

composed by several hundred C function, these functions reference manual all have the introduction in

Windows in the API. Regarding Windows NT, API is called "Win32 API", distinguishes to it uses in

Windows 3.1 16 API.

Microsoft has also provided the C++ storehouse, it is located above any Windows API, can make

programmer's work to be easier. It is the Microsoft basic kind of storehouse (MFC), this storehouse main

merit is the high efficiency. It reduce massive codes which established in Windows procedure.

Simultaneously it has also provided all general C++ programming merit. MFC can be transplant, for

example, the code which 3.1 compiles in Windows may very easily transplant to Windows NT or Windows

95. Therefore, MFC is worth the development Windows application

procedure method very much which recommends.

When you uses MFC, you compile the code is uses to establish the essential user contact surface to

control and to custom-made its outward appearance. Simultaneously you also must compile the codes

which use to respond the users’ operation. For example, if the user single-clicks a button, you should have

the code to respond. This is the event actuate code, it constituted all applications procedure. Once the

application procedure correct response all permissions control, its duty has also completed.

You may see, use MFC to establish Windows programming are a quite easy process. Visual C++

application procedure development procedure environment specially suits to uses MFC (also to have other

development environments to use MFC), therefore studies MFC and Visual C++ together can strengthen

your development procedure ability.

Windows supports several kind of types application procedure windows. A typical application

procedure should move in "the frame window" center. A frame window is an entire function main window,

the user may change its size, be smallist, be maximum and so on. Windows also supports two kind of types

28

页 共 48页

陕西理工学院毕业设计

of dialog boxes: Pattern and non- pattern dialog box. The pattern dialog box once appears on the screen,

other parts of the application procedure will respond only when it withdraws. The non- pattern dialog box

appears on the screen, other parts of the application procedure will respond, it like fluctuates on the screen.

The simplest Windows application procedure is uses the single documents contact surface (SDI), only

one frame window. The Windows clock and watch, the PIF editor, the memorandum and so on are all

examples of the SDI application procedure. Windows also provided multi- documents contact surface form,

it might uses in more complex application procedure. The MDI system permission user check many

documents in the same application procedure. For example, a text editor may allow the user open many text

documents at same time. When uses MDI, the application procedure has a main window, has some sub-

windows in the host window, in each stature window respectively contains its respective documents. In the

MDI frame, the main window has a main menu, it effective to the peakest window in the host frame. Each

sub- window all can flod or unflod into a chart sign, the MDI host window also can be aa chart sign. The

MDI contact surface possibly can give you second tabletop feeling, it give us very big help for the window

management and the deletion chaotic window.

Each procedure you established may use its own control, menu structure as well as the dialog box. To

choose a good application procedure contact surface is decided how to chooses and organizes these contact

surface objects. Visual C++ resources editor may enable you eestablishment and has custom-made these

contact surface objects.

Establishment project and translation code

In order to translates the code in Visual C++, you must have to establish a project. In order to the such

small procedure to establishes a project it must make a fuss over a trifling matter, but in any actual

procedure, the project concept is extremely useful. A project mainly preserving the following three kind of

different types information:

It may remember all source programs code document which establishes the executive routine. In this

simple example, document is the only source document, but in a large-scale application

procedure, in order to be advantageous for the management and the maintenance, you may be able to have

many different sources documents. The project can maintain these different documents tabulating, and

necessity translates them when you establish the next executive routine.

It can remember uses the compiler and the coupling option in view of yours application procedure. For

example, it can remember which storehouse connected in the executive routine, whether you translated in

advance document and so on.

It can remember the project type which establishes: A control bench application procedure, or window

application procedure and so on.

If you already understand the project document, then could be very easy to understand the project

document function as the machine. Now, we establish a simple project, and translates with it.

Therefore, first in the menu chooses "New" from "File" the option. In "Projects" in the label,

single-clicks "Win32 Application".Inputs an appropriate way name in "Location" territory or single-clicks

"Browse" button to "hello" in "Project name"as the project name. This time you can see

"hello" also can appear in "Location" territory. Single-clicks "OK" the button. Visual C++ can newly

establish HELLO contents, and put all projects document , , and

into this contents. If you withdraw, later again rewill open this project, then might choose

.

Now, in the screen’s left side, appearing three labels. InfoView label still in, also newly appeared

ClassView and the FileView label. The ClassView label can list all your procedures, the FileView label give

document tabulating in the project.

Now it allowed to input routine code. Chooses "New" in "File" meno to establish an editor window. In

29

页 共 48页

陕西理工学院毕业设计

appears in dialog box, choose "Files" label and "Text File". Above then can appear Visual C++ intelligent

editor, you may use it to input the procedure code. When input code, you can discover the editor can

automatically turn the different type texts into different colors. If you want

easily tochange its color or the close color function, you can choose “Options"in "Tools" menu, then

chooes "Format" label and "Source Windows" option to revise.

After inputs the code, choose "Save" option in"File"menu to preserves. In Visual C++ new

establishment ontents, saves it to document.

Now chooses "Add To Project" option in"Project"menu,and chooses "" . You can see a dialog

box for you to chooses the documents which you want to appent.

In the screen left side, single-clicks the FileView label, and double-clicks HELLO chart sign. You can

see document. Single-clicks ClassView label, and double-clicks the folder chart sign, you can

see all kinds in procedure. Any time you can use FileView to delete the project document, you only

single-click this document, then click delete key on keyboard.

This time you must tell the project to use MFC storehouse. If you neglected this step, the project in

connection time can make a mistake, but mistake information will not give you any help. Choose

"Settings"in"Project" menu. In appears dialog box chooses "General" label. In "Microsoft Foundation

Classes" Combined frame, choose "Use MFC in a Shared DLL". Then close dialog box.

We have already established the project document, and has adjusted the establishment, you now were

allowed to translate the HELLO. CPP procedure. In "Build" menu, you can discover three different

translations options:

Compile (Only when includes window in active way)

Build

Rebuild All

The first option only translates the source document and forms their goal document. This option

cannot complete the connection task, therefore it only useful to fast translates some source documents to

inspect right or wrong. The second option translation source documents since last time revised, and connect

to make the execution file. The third option must retranslate and the connection all sources document.

We may choose "Build " to translate and the connection code. Visual C++ can establish

"Debug" new sub-directory, and puts in this contents. This sub-directory documents can all

reproduce, therefore you may wilfully delete them.

If you discovered the translation mistakes, double-clicks the error message in the output window. By

now the editor could bring you to the position which made a mistake. Inspects your code whether has the

question, if has, revises it. If you see the massive connections mistake, then is possible make a wrong

project type which assigns in the establishment project dialog box. You may delet the sub-directory of the

project,then establishes it again according to the above step.

In order to carry out this procedure, you may select "Execute " option in"Build" menu.

You may see your first MFC procedure -- appeared "hello world" window. This window itself has: The title

block, the size zoom area, are biggest and smallest button and so on. In the window,has "hello world".

Please note, this procedure is complete. You may move the window, Shrink or Grow the window,

Minimized it and so on. You only used the very few codes to complete a complete Window application

procedure. This is the merit of MFC using. MFC will process all detail questions.

Visual C++ MFC 简明教程

一、MFC导论

Visual C++ 不仅仅是一个编译器,而且是一个全面的应用程序开发环境,你可以充分利用具有

面向对象特性的 C++ 来开发出专业级的 Windows 应用程序。为了能充分利用这些特性,你必须理

解 C++ 程序设计语言。为了掌握C++,你就必须掌握 Microsoft 基本类库(MFC)的层次结构。

30

页 共 48页

陕西理工学院毕业设计

该层次结构包含了 Windows API 中的用户界面部分,并使你能够很容易的以面向对象的方式建立

Windows 应用程序。这种层次结构适用于所有版本的 Windows 并彼此兼容。你用 MFC 所建立的

代码是完全可移植的。

如果你要建立一个 Windows 应用程序,应该如何下手?

好的开端是从设计用户界面开始。首先,你要决定什么样的用户能使用该程序并根据需要来设

置相应的用户界面对象。Windows 用户界面有一些标准的控制,如按钮、菜单、滚动条和列表等,

这对那些 Windows 用户已经是很熟悉了。要记住的是,作为程序员必须选择一组控制并决定如何

把其安排到屏幕上。传统上,你需要在纸上做一下用户界面的草图,直到对各元素感到满意为止。

这对于一些比较小的项目,以及一些大项目的早期原型阶段是可行的。

下一步,是要实现代码。为任何 Windows 平台建立应用程序时,程序员都有两种选择:

C 或 C++。使用 C,程序员是在 Windows 应用程序界面(API)的水平上编写代码。该界面

是由几百个 C 函数所组成,这些函数在Windows API 参考手册中都有介绍。对于Windows NT,

API 被称为“Win32 API”,以区别于其用于Windows 3.1的16位 API。

Microsoft 也提供了 C++ 库,其位于任何 Windows API 之上,能够使程序员的工作更容易。

其就是Microsoft基本类库(MFC),该库的主要优点是效率高。其减少了大量在建立 Windows 程

序时必须编写的代码。同时还提供了所有一般 C++ 编程的优点。MFC 是可移植的,例如,在

Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。因此,MFC 很值

得推荐的开发Windows 应用程序的方法。

当你使用 MFC 时,你编写的代码是用来建立必要的用户界面控制并定制其外观。同时你还要

编写用来响应用户操作这些控制的代码。例如,如果用户单击一个按钮时,你应该有代码来响应。

这就是事件驱动代码,其构成了所有应用程序。一旦应用程序正确的响应了所有允许的控制,其任

务也就完成了。

你可以看出,使用 MFC 进行 Windows 编程时是一件比较容易的过程。Visual C++ 应用程序

开发程序环境特别适合于使用 MFC(也有别的开发环境使用MFC),所以一起学习 MFC 和 Visual

C++ 能够增强你的开发程序的能力。

Windows支持几种类型的应用程序窗口。一个典型的应用程序应该活动在称为“框架窗口”中。

一个框架窗口是一个全功能的主窗口,用户可以改变尺寸、最小化、最大化等。Windows也支持两

种类型的对话框:模式和无模式对话框。模式对话框一旦出现在屏幕上,只有当其退出时,屏幕上

该应用程序的其余部分才能响应。无模式对话框出现在屏幕上时,程序的其余部分也可以做出响应,

其就好像浮动在上面一样。

最简单的 Windows 应用程序是使用单文档界面(SDI),只有一个框架窗口。Windows 的钟

表、PIF 编辑器、记事本等都是 SDI 应用程序的例子。Windows 也提供了一种称为多文档界面的

组织形式,其可用于更复杂的应用程序。MDI 系统允许用户在同一应用程序中同时可以查看多个文

档。例如,一个文本编辑器可以允许用户同时打开多个文本文件。使用 MDI 时,应用程序有一个

主窗口,在主窗口中有一些子窗口,每个子窗口中各自包含有各自的文档。在MDI框架中,主窗口

有一个主菜单,其对主框架中最顶端窗口有效。各子窗口都可以缩成图标或展开,MDI主窗口也可

以变成桌面上的一个图标。MDI界面可能会给你一种第二桌面的感觉,其对窗口的管理和删除混乱

的窗口有很大的帮助。

你所建立的每一个应用程序都会使用其自己的一套控制、菜单结构以及对话框。应用程序界面

的好坏取决于你如何选择和组织这些界面对象。Visual C++ 中的资源编辑器可以使你能容易的建立

和定制这些界面对象。

二、建立项目和编译代码

为了在 Visual C++ 中编译代码,你必须要建立一个项目。为了这么小的程序来建立一个项目可

能有点小题大做,但是,在任何实际的程序中,项目的概念是非常有用的。一个项目主要保存着下

面三种不同类型的信息:

可以记住建立一个可执行程序所需要的所有源程序代码文件。在这个简单的例子中,文件

31

页 共 48页

陕西理工学院毕业设计

是唯一的源文件,但是在一个大型的应用程序中,为了便于管理和维护,你可以会有

许多个不同的源文件。项目会维护这些不同文件的列表,并当你要建立下一个新的可执行程序时,

在必要时进行编译,其会记住针对你的应用程序所使用的编译器和连接器选项。例如,其会记住把

哪个库连接到了执行程序中,你是否预编译了头文件等等。其会记住你想要建立的项目类型:一个

控制台应用程序,或一个窗口应用程序等等。

如果你已经对项目文件有所了解,则会很容易明白作为机器产生的项目文件的作用。现在,我

们来建立一个简单的项目,并用其来编译 。

为此,首先从“File”菜单中选择“New”选项。在“Projects”标签中,单击“Win32 Application”。

在“Location”域中输入一个合适的路径名或单击“Browse”按钮来选择一个。在“Project name”

中输入“hello”作为项目名称。这时候你会看到“hello”也会出现在“Location”域中。单击“OK”

按钮。Visual C++ 会建立一个新的称为HELLO的目录,并把所有的项目文件 、

、 和 都放到该目录中。如果你退出以后再重新打开该项目,

则可选择 。

现在,在屏幕的左边,出现了三个标签。InfoView标签仍然在,又新出现了ClassView和FileView

标签。ClassView标签会把你程序中所有的类都列出来,FileView标签给出了项目中文件的列表。

现在可以输入程序的代码了。在“File”菜单中选择“New”选项来建立一个编辑窗口。在出现

的对话框中,选择“Files”标签和“Text File”。则会出现 Visual C++ 的智能编辑器,你可以用其

来输入上面的程序代码。输入代码时,你会发现编辑器会自动把不同类型的文本变成不同的颜色,

如果你要改变其颜色或关闭颜色功能,可选择“Tools”菜单中“Options”选项,然后选择“Format”

标签和“Source Windows”选项就可以修改。

输入完代码后,选择“File”菜单中的“Save”选项来保存。在 Visual C++ 新建立的目录中,

把其存成 文件。

现在选择在“Project”菜单中选择“Add To Project”选项,再选“”。你会看到一个对话

框供你选择要添加的文件。

在屏幕的左边,单击FileView标签,并双击标有 HELLO 的图标。你会看到名为

的文件。单击ClassView标签,并双击文件夹图标,你会看到程序中所有的类。任何时候你都可以

使用FileView来删除项目的文件,你只要单击该文件,然后按键盘上的 delete 键。

此时你必须告诉项目要使用MFC库。如果你忽略了这一步,则项目在连接时会出错,而出错信

息对你毫无帮助。选择“Project”菜单的“Settings”。在出现的对话框中选择“General”标签。在

“Microsoft Foundation Classes”组合框中,选择“Use MFC in a Shared DLL”。然后关闭对话框。

我们已经建立了项目文件,并调整了设置,你现在可以准备编译 程序了。在“Build”

菜单中,你会发现有三个不同的编译选项:

Compile (只有当含有 的窗口处于激活状态时才可)

Build

Rebuild All

第一个选项只是编译源文件并形成目标文件。该选项不能完成连接任务,所以其只对快速编译

一些源文件以检查错误有用。第二个选项编译自上次编译后所修改的所有源文件,并连接形成可执

行文件。第三个选项要重新编译和连接所有的源文件。

我们可以选择“Build ”来编译和连接代码。Visual C++ 会建立一个名为“Debug”

的新子目录,并把 放在该目录中。该子目录的文件都是可以再产生的,所以你可以对

其任意删除。

如果你发现了编译错误,双击输出窗口中的错误信息。这时编辑器会把你带到出错的位

置处。检查你的代码是否有问题,如果有,就修改之。如果你看到大量的连接错误,则可能你

在建立项目对话框中所指定的项目类型不对。你可以把该项目所在的子目录删除,然后再重新按上

面的步骤来建立。

为了执行该程序,你可选则“Build”菜单中的“Execute ”选项。你就可以看到你

32

页 共 48页

陕西理工学院毕业设计

的第一个MFC程序了---出现一个带有“hello world”的窗口。该窗口本身带有:标题栏、尺寸缩放

区、最大和最小按钮等等。在窗口上,有一个标有“hello world”。请注意,该程序是完整的。你可

以移动窗口、缩放窗口、最小化等。你只使用了很少的代码就完成了一个完整的Window 应用程序。

这就是使用MFC的优点。所有的细节问题都有MFC来处理。

33

页 共 48页

陕西理工学院毕业设计

附录B

其余代码:

//

//

//

#include "stdafx.h"

#include

#include "CDXGraph.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

CDXGraph::CDXGraph()

{

pGraph = NULL;

pMediaControl = NULL;

pMediaEvent = NULL;

pBasicVideo = NULL;

pBasicAudio = NULL;

pVideoWindow = NULL;

pMediaSeeking = NULL;

mObjectTableEntry = 0;

}

CDXGraph::~CDXGraph()

{

Release();

}

bool CDXGraph::Create(void)

{

if (!pGraph)

{

if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph,

CLSCTX_INPROC_SERVER,

IID_IGraphBuilder, (void **)&pGraph)))

{

AddToObjectTable();

return QueryInterfaces();

}

34

页 共 48页

NULL,

陕西理工学院毕业设计

pGraph = 0;

}

return false;

}

bool CDXGraph::QueryInterfaces(void)

{

if (pGraph)

{

HRESULT hr = NOERROR;

hr |= pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);

hr |= pGraph->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEvent);

hr |= pGraph->QueryInterface(IID_IBasicVideo, (void **)&pBasicVideo);

hr |= pGraph->QueryInterface(IID_IBasicAudio, (void **)&pBasicAudio);

hr |= pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVideoWindow);

hr |= pGraph->QueryInterface(IID_IMediaSeeking, (void **)&pMediaSeeking);

if (pMediaSeeking)

{

pMediaSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);

}

return SUCCEEDED(hr);

}

return false;

}

void CDXGraph::Release(void)

{

if (pMediaSeeking)

{

pMediaSeeking->Release();

pMediaSeeking = NULL;

}

if (pMediaControl)

{

pMediaControl->Release();

pMediaControl = NULL;

}

if (pMediaEvent)

{

pMediaEvent->Release();

pMediaEvent = NULL;

}

if (pBasicVideo)

{

pBasicVideo->Release();

pBasicVideo = NULL;

35

页 共 48页

陕西理工学院毕业设计

}

if (pBasicAudio)

{

pBasicAudio->Release();

pBasicAudio = NULL;

}

if (pVideoWindow)

{

pVideoWindow->put_Visible(OAFALSE);

pVideoWindow->put_MessageDrain((OAHWND)NULL);

pVideoWindow->put_Owner(OAHWND(0));

pVideoWindow->Release();

pVideoWindow = NULL;

}

RemoveFromObjectTable();

if (pGraph)

{

pGraph->Release();

pGraph = NULL;

}

}

bool CDXGraph::Attach(IGraphBuilder * inGraphBuilder)

{

Release();

if (inGraphBuilder)

{

inGraphBuilder->AddRef();

pGraph = inGraphBuilder;

AddToObjectTable();

return QueryInterfaces();

}

return true;

}

//IGraphBuilder * CDXGraph::GetGraph(void)

//{

// return pGraph;

//}

IMediaEventEx * CDXGraph::GetEventHandle(void)

{

return pMediaEvent;

}

36

页 共 48页

陕西理工学院毕业设计

// Connect filter from the upstream output pin to the downstream input pin

bool CDXGraph::ConnectFilters(IPin * inOutputPin, IPin * inInputPin,

const AM_MEDIA_TYPE * inMediaType)

{

if (pGraph && inOutputPin && inInputPin)

{

HRESULT hr = pGraph->ConnectDirect(inOutputPin, inInputPin, inMediaType);

return SUCCEEDED(hr) ? true : false;

}

return false;

}

void CDXGraph::DisconnectFilters(IPin * inOutputPin)

{

if (pGraph && inOutputPin)

{

HRESULT hr = pGraph->Disconnect(inOutputPin);

}

}

//输入显示窗口的句柄:inWindow

bool CDXGraph::SetDisplayWindow(HWND inWindow)

{

if (pVideoWindow)

{

// 首先隐藏视频窗口

pVideoWindow->put_Visible(OAFALSE);

pVideoWindow->put_Owner((OAHWND)inWindow);

//获取输入窗口的显示区域

RECT windowRect;

::GetClientRect(inWindow, &windowRect);

pVideoWindow->put_Left(0);

pVideoWindow->put_Top(0);

pVideoWindow->put_Width( - );

pVideoWindow->put_Height( - );

pVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_T

HICKFRAME);

pVideoWindow->put_MessageDrain((OAHWND) inWindow);

// 回复视频窗口

if (inWindow != NULL)

{

pVideoWindow->put_Visible(OATRUE);

}

37

页 共 48页

陕西理工学院毕业设计

else

{

pVideoWindow->put_Visible(OAFALSE);

}

return true;

}

return false;

}

bool CDXGraph::ResizeVideoWindow(long inLeft, long inTop, long inWidth, long inHeight)

{

if (pVideoWindow)

{

long lVisible = OATRUE;

pVideoWindow->get_Visible(&lVisible);

// Hide the video window first

pVideoWindow->put_Visible(OAFALSE);

pVideoWindow->put_Left(inLeft);

pVideoWindow->put_Top(inTop);

pVideoWindow->put_Width(inWidth);

pVideoWindow->put_Height(inHeight);

// Restore the video window

pVideoWindow->put_Visible(lVisible);

return true;

}

return false;

}

bool CDXGraph::SetNotifyWindow(HWND inWindow)

{

if (pMediaEvent)

{

pMediaEvent->SetNotifyWindow((OAHWND)inWindow, WM_GRAPHNOTIFY, 0);

return true;

}

return false;

}

void CDXGraph::HandleEvent(WPARAM inWParam, LPARAM inLParam)

{

if (pMediaEvent)

{

LONG eventCode = 0, eventParam1 = 0, eventParam2 = 0;

while (SUCCEEDED(pMediaEvent->GetEvent(&eventCode, &eventParam1,

38

页 共 48页

陕西理工学院毕业设计

&eventParam2, 0)))

{

pMediaEvent->FreeEventParams(eventCode, eventParam1, eventParam2);

switch (eventCode)

{

case EC_COMPLETE:

break;

case EC_USERABORT:

case EC_ERRORABORT:

break;

default:

break;

}

}

}

}

bool CDXGraph::Run(void)

{

if (pGraph && pMediaControl)

{

if (!IsRunning())

{

if (SUCCEEDED(pMediaControl->Run()))

{

return true;

}

}

else

{

return true;

}

}

return false;

}

bool CDXGraph::Stop(void)

{

if (pGraph && pMediaControl)

{

if (!IsStopped())

{

if (SUCCEEDED(pMediaControl->Stop()))

{

39

页 共 48页

陕西理工学院毕业设计

return true;

}

}

else

{

return true;

}

}

return false;

}

bool CDXGraph::Pause(void)

{

if (pGraph && pMediaControl)

{

if (!IsPaused())

{

if (SUCCEEDED(pMediaControl->Pause()))

{

return true;

}

}

else

{

return true;

}

}

return false;

}

bool CDXGraph::IsRunning(void)

{

if (pGraph && pMediaControl)

{

OAFilterState state = State_Stopped;

if (SUCCEEDED(pMediaControl->GetState(10, &state)))

{

return state == State_Running;

}

}

return false;

}

bool CDXGraph::IsStopped(void)

{

if (pGraph && pMediaControl)

40

页 共 48页

陕西理工学院毕业设计

{

OAFilterState state = State_Stopped;

if (SUCCEEDED(pMediaControl->GetState(10, &state)))

{

return state == State_Stopped;

}

}

return false;

}

bool CDXGraph::IsPaused(void)

{

if (pGraph && pMediaControl)

{

OAFilterState state = State_Stopped;

if (SUCCEEDED(pMediaControl->GetState(10, &state)))

{

return state == State_Paused;

}

}

return false;

}

bool CDXGraph::SetFullScreen(BOOL inEnabled)

{

if (pVideoWindow)

{

HRESULT hr = pVideoWindow->put_FullScreenMode(inEnabled

OAFALSE);

return SUCCEEDED(hr);

}

return false;

}

bool CDXGraph::GetFullScreen(void)

{

if (pVideoWindow)

{

long fullScreenMode = OAFALSE;

pVideoWindow->get_FullScreenMode(&fullScreenMode);

return (fullScreenMode == OATRUE);

}

return false;

}

// IMediaSeeking features

41

页 共 48页

? OATRUE :

陕西理工学院毕业设计

bool CDXGraph::GetCurrentPosition(double * outPosition)

{

if (pMediaSeeking)

{

__int64 position = 0;

if (SUCCEEDED(pMediaSeeking->GetCurrentPosition(&position)))

{

*outPosition = ((double)position) / 10000000.;

return true;

}

}

return false;

}

bool CDXGraph::GetStopPosition(double * outPosition)

{

if (pMediaSeeking)

{

__int64 position = 0;

if (SUCCEEDED(pMediaSeeking->GetStopPosition(&position)))

{

*outPosition = ((double)position) / 10000000.;

return true;

}

}

return false;

}

bool CDXGraph::SetCurrentPosition(double inPosition)

{

if (pMediaSeeking)

{

__int64 one = 10000000;

__int64 position = (__int64)(one * inPosition);

HRESULT hr = pMediaSeeking->SetPositions(&position,

AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame,

0, AM_SEEKING_NoPositioning);

return SUCCEEDED(hr);

}

return false;

}

bool CDXGraph::SetStartStopPosition(double inStart, double inStop)

{

if (pMediaSeeking)

{

42

页 共 48页

陕西理工学院毕业设计

__int64 one = 10000000;

__int64 startPos = (__int64)(one * inStart);

__int64 stopPos = (__int64)(one * inStop);

HRESULT hr = pMediaSeeking->SetPositions(&startPos,

AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame,

&stopPos, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame);

return SUCCEEDED(hr);

}

return false;

}

bool CDXGraph::GetDuration(double * outDuration)

{

if (pMediaSeeking)

{

__int64 length = 0;

if (SUCCEEDED(pMediaSeeking->GetDuration(&length)))

{

*outDuration = ((double)length) / 10000000.;

return true;

}

}

return false;

}

bool CDXGraph::SetPlaybackRate(double inRate)

{

if (pMediaSeeking)

{

if (SUCCEEDED(pMediaSeeking->SetRate(inRate)))

{

return true;

}

}

return false;

}

// Attention: range from -10000 to 0, and 0 is FULL_VOLUME.

bool CDXGraph::SetAudioVolume(long inVolume)

{

if (pBasicAudio)

{

HRESULT hr = pBasicAudio->put_Volume(inVolume);

return SUCCEEDED(hr);

}

return false;

43

页 共 48页

陕西理工学院毕业设计

}

long CDXGraph::GetAudioVolume(void)

{

long volume = 0;

if (pBasicAudio)

{

pBasicAudio->get_Volume(&volume);

}

return volume;

}

void CDXGraph::ChangeAudioVolume(int nVolume)

{

ASSERT(nVolume >= 0 && nVolume <= 100);

m_nVolume = nVolume;

if (!pBasicAudio)

return;

long lVolume = (nVolume - 100) * 100;

pBasicAudio->put_Volume(lVolume);

}

void CDXGraph::Mute()

{

if (!pBasicAudio)

return;

pBasicAudio->put_Volume(-10000);

}

void CDXGraph::UnMute()

{

if (!pBasicAudio)

return;

long lVolume = (m_nVolume - 100) * 100;

pBasicAudio->put_Volume(lVolume);

}

// Attention: range from -10000(left) to 10000(right), and 0 is both.

bool CDXGraph::SetAudioBalance(long inBalance)

{

if (pBasicAudio)

44

页 共 48页

陕西理工学院毕业设计

{

HRESULT hr = pBasicAudio->put_Balance(inBalance);

return SUCCEEDED(hr);

}

return false;

}

long CDXGraph::GetAudioBalance(void)

{

long balance = 0;

if (pBasicAudio)

{

pBasicAudio->get_Balance(&balance);

}

return balance;

}

bool CDXGraph::RenderFile(TCHAR * inFile)

{

if (pGraph)

{

//WCHAR szFilePath[MAX_PATH];

//MultiByteToWideChar(CP_ACP, 0, inFile, -1, szFilePath, MAX_PATH);

//if (SUCCEEDED(pGraph->RenderFile(szFilePath, NULL)))

if (SUCCEEDED(pGraph->RenderFile(inFile, NULL)))

{

return true;

}

}

return false;

}

bool CDXGraph::SnapshotBitmap(TCHAR *outFile)//const char * outFile)

{

if (pBasicVideo)

{

long bitmapSize = 0;

if (SUCCEEDED(pBasicVideo->GetCurrentImage(&bitmapSize, 0)))

{

bool pass = false;

unsigned char * buffer = new unsigned char[bitmapSize];

if (SUCCEEDED(pBasicVideo->GetCurrentImage(&bitmapSize, (long *)buffer)))

{

BITMAPFILEHEADER hdr;

LPBITMAPINFOHEADER lpbi;

45

页 共 48页

陕西理工学院毕业设计

+

lpbi = (LPBITMAPINFOHEADER)buffer;

int nColors = 0;

if (lpbi->biBitCount < 8)

{

nColors = 1 << lpbi->biBitCount;

}

rved1

rved2

its

= ((WORD) ('M' << 8) | 'B'); //always is "BM"

= bitmapSize + sizeof( hdr );

= 0;

= 0;

= (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize

nColors * sizeof(RGBQUAD));

CFile bitmapFile((outFile), CFile::modeReadWrite | CFile::modeCreate |

CFile::typeBinary);

(&hdr, sizeof(BITMAPFILEHEADER));

(buffer, bitmapSize);

();

pass = true;

}

delete [] buffer;

return pass;

}

}

return false;

}

//////////////////////// For GraphEdit Dubug purpose /////////////////////////////

void CDXGraph::AddToObjectTable(void)

{

IMoniker * pMoniker = 0;

IRunningObjectTable * objectTable = 0;

if (SUCCEEDED(GetRunningObjectTable(0, &objectTable)))

{

WCHAR wsz[256];

swprintf(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)pGraph,

GetCurrentProcessId());

HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);

if (SUCCEEDED(hr))

{

hr = objectTable->Register(0, pGraph, pMoniker, &mObjectTableEntry);

46

页 共 48页

陕西理工学院毕业设计

pMoniker->Release();

}

objectTable->Release();

}

}

void CDXGraph::RemoveFromObjectTable(void)

{

IRunningObjectTable * objectTable = 0;

if (SUCCEEDED(GetRunningObjectTable(0, &objectTable)))

{

objectTable->Revoke(mObjectTableEntry);

objectTable->Release();

mObjectTableEntry = 0;

}

}

void CMediaPlayerDlg::OnMenuNormalrate()

{

// TODO: 在此添加命令处理程序代码

if (m_pFilterGraph)

{

m_pFilterGraph->SetPlaybackRate(1.0);

SetWindowText(_T("1倍速播放 ") + m_mediaFileName);

}

}

void CMediaPlayerDlg::OnMenuDoublerate()

{

// TODO: 在此添加命令处理程序代码

if (m_pFilterGraph)

{

m_pFilterGraph->SetPlaybackRate(2.0);

SetWindowText(_T("2倍速播放 ") + m_mediaFileName);

}

}

void CMediaPlayerDlg::OnMenuFullscreen()

{

//(pMsg->put_WindowStyle(WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_THI

CKFRAME);

// TODO: 在此添加命令处理程序代码

static int flag=0;

if (m_pFilterGraph != NULL)

{

if (!flag){

m_pFilterGraph->SetFullScreen(TRUE);

47

页 共 48页

陕西理工学院毕业设计

flag = 1;

}else{

m_pFilterGraph->SetFullScreen(FALSE);

flag = 0;

}

}

}

void CMediaPlayerDlg::OnMenuAlwaysontop()

{

// TODO: 在此添加命令处理程序代码

static int flag=0;

if (!flag)

{

::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);

flag = 1;

}

else

{

::SetWindowPos(m_hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE

|SWP_NOMOVE);

flag = 0;

}

}

48

页 共 48页

本文标签: 播放应用程序数据视频连接