最新日志

发表于:2008-5-15 13:14:27
标签:无标签

0

MIT课程下载方法

MIT课程下载方法

希望有兴趣的朋友喜欢

2008515星期四

1.打开MIT开放式课程主页

http://ocw.mit.edu/OcwWeb/web/home/home/index.htm

看到如下页面

 

2.Get started with OCW 中点击 Audio/Video Courses 可以进入Audio/Video Courses页面

 

3.在页面中列出的课程中选择你要学习的课程

 

为了给大家示范,我在这里选择 Electrical Engineering and Computer Science 里的课程Circuits and Electronics,本人比较喜欢。

 

 

 

 

4.点击  Circuits and Electronics  进入本课程页面

 

 

查看课程介绍,了解课程内容,可以看到关于教师,课时,时间安排,水平等信息

如果大家的英语水平不是很方便的话,可以去参照OOPS或是CORE翻译的课程,那样有助于大家学习,不过更希望大家好好利用机会学习一下英语啊

    美国人做事还是很让人佩服的,相比国内的一些精品课程,多少有点滥竽充数的感觉,

MIT致敬!!!

 

 

 

 

 

 

5.点击  lecture notes and videos  进入课程学习或是下载页面

 

注意:

1.       我们在这里下载的MIT课程都是.rm格式的视频,需要大家用可以播放此格式的播放器,推荐用Real Player 播放软件;

2.       如果大家想用ipod 来学习MIT课程,建议你去iTunesU去下载,那里有很多大学的开放式课程,具体方法我就不啰嗦了,很方便的;

3.       如果你可以忍受画面质量不是很好的情况的话,可以用下载工具去视频分享类网站下载,也很方便,直接观看也不错的,那个就不介绍了。

 

 

 

 

 

6.如果下载的话,建议选择RM-220K

RM-220K处右键选择迅雷下载,出现如下的下载页面

下载完成后,我们发现这只是非常小的文件,并不是我们需要的.rm格式的视频文件,这是为什么呢?好好研究一下,

7.打开那个文件所在的文件夹。

 

8. 用记事本打开下载得到的文件,得到下面的内容

 

rtsp://a30.v78701.c7870.g.vr.akamaistream.net/ondemand/7/30/7870/v0001/mitstorage.download.akamai.com/7870/6/6.002/f03/videolectures/mit-6.002-lec-mit-10250-04sep2003-0000-220k.rm

--stop--

pnm://a30.v78701.c7870.g.vr.akamaistream.net/ondemand/7/30/7870/v0001/mitstorage.download.akamai.com/7870/6/6.002/f03/videolectures/mit-6.002-lec-mit-10250-04sep2003-0000-220k.rm

9. 修改链接地址,得到真正的下载链接地址

若需要下载视频文件到自己的电脑中观看,可以将上面的红色字体部分的连接添加到

http://ocw.mit.edu/ans7870之后得到新的链接地址

http://ocw.mit.edu/ans7870/6/6.002/f03/videolectures/mit-6.002-lec-mit-10250-04sep2003-0000-220k.rm

10. 下载需要的视频文件

复制上面的链接地址到迅雷里下载,就OK了,下载截图如下:

  

同样的作法可以适用于大多数(但并非全部)的麻省理工学院开放式课程里的音视频课程。你只需要找到链接网址,把前半部的地址例如
http://mfile.akamai.com/7870/rm/mitstorage.download.akamai.com/7870
改为
http://ocw.mit.edu/ans7870
即可。

点击此处查看原文 >>

系统分类: 资源共享   |    用户分类:    |    来源: 原创

评论(0) | 阅读(31)
发表于:2008-4-12 16:08:28
标签:无标签

0

基于VFW的视频应用程序开发(zz)

基于VFW的视频应用程序开发
  

当前,在Windows 平台下开发视频应用程序一般采用两种方式:一种是基于视频采集卡所附带的二次软件开发包SDK(Software development kit)进行。这种方式的优点是应用方便,容易上手,缺点是对硬件的依赖性较强,灵活性差,且功能参差不齐,不能充分满足各种视频应用程序的开发需要;

另一种方式是基于VFW(Video for Windows)进行的。VFW 是Microsoft公司为开发Windows平台下的视频应用程序提供的软件工具包,提供了一系列应用程序编程接口(API),用户可以通过它们很方便地实现视频捕获[1]、视频编辑及视频播放等通用功能,还可利用回调函数开发更复杂的视频应用程序。它的特点是播放视频时不需要专用的硬件设备,而且应用灵活,可以满足视频应用程序开发的需要。Windows操作系统自身就携带了VFW,系统安装时,会自动安装VFW的相关组件。VC++自4.0以来就支持VFW,大大简化了视频应用程序的开发。目前,PC机上多媒体应用程序的视频部分,大都是利用VFW API开发的。

1  VFW 的体系结构

VFW以消息驱动方式对视频设备进行存取,可以很方便地控制设备数据流的工作过程。目前,大多数的视频采集卡驱动程序都支持VFW接口,它主要包括多个动态连接库,通过这些组件间的协调合作,来完成视频的捕获、视频压缩及播放功能。VFW体系结构如图1所示。

1)VICAP.DLL:主要实现视频捕获功能,包含了用于视频捕获的函数,为音像交错AVI (Audio video interleaved)格式文件和视频、音频设备程序提供一个高级接口。

2)MSVIDEO.DLL:能够将视频捕获窗口与获驱动设备连接起来,支持ICM视频编码服务。

3)MCIAVI.DRV:包含MCI(Media control interface)命令解释器,实现回放功能。

4)AVIFILE.DLL:提供对AVI文件的读写操作等文件管理功能。

5)ICM ( Installable compression manager ):即压缩管理器,提供对存储在AVI文件中视频图像数据的压缩、解压缩服务。

6)ACM ( Audio Compression Manager ):即音频压缩管理器,提供实时音频压缩及解压缩功能。

 2  视频捕获

视频数据的实时采集,主要通过AVICAP模块中的消息、宏函数、结构以及回调函数来完成。视频捕获的一般过程如下:

2.1 建立捕获窗口

利用AVICAP 组件函数 capCreateCaptureWindow() 建立视频捕获窗口,它是所有捕获工作及设置的基础,其主要功能包括:① 动态地同视频和音频输入器连接或断开;② 设置视频捕获速率;③ 提供视频源、视频格式以及是否采用视频压缩的对话框;④ 设置视频采集的显示模式为Overlay或为Preview; ⑤ 实时获取每一帧视频数据;⑥ 将一视频流和音频流捕获并保存到一个AVI文件中; ⑦ 捕获某一帧数字视频数据,并将单帧图像以DIB格式保存;⑧ 指定捕获数据的文件名,并能将捕获的内容拷贝到另一文件。

2.2 登记回调函数[2]

登记回调函数用来实现用户的一些特殊需要。在以一些实时监控系统或视频会议系统中,需要将数据流在写入磁盘以前就必须加以处理,达到实时功效。应用程序可用捕获窗来登记回调函数,以便及时处理以下情况:捕获窗状态改变、出错、使用视频或音频缓存、放弃控制权等,相应的回调函数分别为 capStatusCallback(), capErrorCallback(), capVideoStreamCallback(), capWaveStreamCallback(),capYieldCallback()。

2.3 获取捕获窗口的缺省设置

通过宏capCaptureGetSetup(hWndCap,&m_Parms,sizeof(m_Parms))来完成。

2.4 设置捕获窗口的相关参数

通过宏capCaptureSetSetup(hWndCap,&m_Parms,sizeof(m_Parms))来完成。

2.5 连接捕获窗口与视频捕获卡

通过宏capDriveConnect(hWndCap,0)来完成。

2.6 获取采集设备的功能和状态

通过宏capDriverGetCaps(hWndCap,&m_CapDrvCap,sizeof(CAPDRIVERCAPS))来获取

视频设备的能力,通过宏capGetStatus(hWndCap,&m_CapStatus,sizeof(m_CapStatus))

来获取视频设备的状态。

2.7 设置捕获窗口显示模式

视频显示有Overlay(叠加)和Preview(预览)两种模式。在叠加模式下,捕获视频数据布展系统资源,显示速度快,视频采集格式为YUV格式,可通过capOverlay(hWndCap,TRUE)来设置;预览模式下要占用系统资源,视频由系统调用GDI函数在捕获窗显示,显示速度慢,它支持RGB视频格式。

2.8 捕获图像到缓存或文件并作相应处理

若要对采集数据进行实时处理,则应利用回调机制,由capSetCallbackOnFrame(hWndCap, FrameCall-

backProc)完成单帧视频采集;由capSetCallbackOnVideoStream(hWndCap, VideoCallbackProc)完成视频流采集。如果要保存采集数据,则可调用capCaptureSequence(hWnd);要指定文件名,可调用capFileSetCap-

ture(hwnd, Filename)。

2.9 终止视频捕获 断开与视频采集设备的连接

调用capCatureStop(hWndCap)停止采集,调用capDriverDisconnect(hWndCap), 断开视频窗口与捕获驱动程序的连接。

3  视频编辑和播放

利用VFW,不仅可以实现视频流的实时采集,还提供了编辑和播放功能,主要通过AVIFILE、ICM、ACM、MCIWnd 等组件之间的协作来完成。

       1) AVIFileInit();//初始化;

2) AVIFileOpen(); //打开一个AVI文件并获文件的句柄;

3) AVIFileInfo(); //获取文件的相关信息,如图像的Width和Height等;

4) AVIFileGetStream(); //建立一个指向需要访问的数据流的指针;

5) AVIStreamInfo(); //获取存储数据流信息的AVISTREAMINFO结构;

6) AVIStreamRead(); //读取数据流中的原始数据, 对AVI文件进行所需的编辑处理;

7) AVIStreamRelease(); //释放指向视频流的指针;

8) AVIFileRelease();AVIFileExit(); //释放AVI文件。

若数据是压缩过的,则用AVIStreamGetFrameOpen(),AVIStreamGetFrame()和AVIStreamGetFrameClose()来操作,可以完成对视频流的逐帧分解。

3.2  视频播放

对于实现视频流的播放,VFW提供了MCIWnd窗口类[4],主要用于创建视频播放区,控制并修改MCI窗口当前加载媒体的属性。一个由函数、消息和宏组成的库与MCIWnd相关联,通过它们可以进行AVI文件操作,很方便地使应用程序完成视频播放功能。

1)MCIWndCreate(); //注册MCIWnd窗口类,创建MCIWnd窗口,并指定窗口风格;

2)AVIFileInit(); //初始化;

3) AVIFileOpen(); //打开AVI文件;

4) AVIFileGetStream(); //获得视频流;

5)运用相关函数进行各种播放任务:MCIWndPlay()正向播放AVI文件内容,MCIWndPlayReverse()反向播放,MCIWndResume() 恢复播放,MCIWndPlayPause()暂停播放,MCIWndStop()停止播放等等。

6) AVIStreamRelease(); //释放视频流;

7)AVIFileRease();AVIFileExit(); //断开与AVI文件的连接,释放视频源。

由以上步骤可以看出,视频播放是视频编辑其中的一种操作。

4  结束语

随着社会的发展,人们对多媒体技术的需求也越来越高,已经不满足单一的通信功能,要求影像与声音的同步服务,如可视电话、视频会议、各种实时监控系统、报警系统等,而数字视频技术则是多媒体技术的核心之一。微软推出的数字视频处理软件开发包Video for Windows,将开发者从硬件的底层束缚中解放出来,大大简化了数字视频捕获这一原本很复杂的工作,利用它可以很方便的将模拟视频信号数字化,并支持进一步处理和播放,为开发实时视频应用程序开辟了道路。

参考文献:

[1] 周长发. VC++多媒体编程技术与实例[M]. 北京:电子工业出版社, 1999.

[2] 张星明. 视频图像捕获及运动检测技术的实现[J]. 计算机工程, 2002, 28(8):130-132.

[3] 肖永隆,王  理. 利用VFW库函数快速分解AVI数据流[J]. 信息工程大学学报, 2001, 2(3):39-42.

[4] 喻其炳. 多媒体信息处理在Windows中的应用[J]. 重庆工商大学学报, 2003, 20(1):64-66.

点击此处查看原文 >>

系统分类: 软件开发   |    用户分类: 无分类    |    来源: 无分类

评论(0) | 阅读(159)
发表于:2008-3-25 9:58:08
标签:无标签

0

[转]视频捕捉全教程(vc+vfw)

目 录

一. 视频捕获快速入门

二.基本的捕获设置

          1.设置捕获速度:

          2.设置终止捕获

          3.捕获的时间限制

三.关于捕获窗口

          1.创建一个AVICAP捕获窗口

          2.将一个捕获窗口连接至捕获设备

          3. 父窗口与子窗口的交互

          4.捕获窗口的状态

四.视频捕获驱动和音频驱动

          1.视频捕获驱动的性能:

          2.视频对话框:

          3.PREVIEW 和 OVERLAY模式:

          4.视频格式

          5.视频捕获设置

          6.声频格式

五.使用视频捕获

        1.创建捕获窗口(CREATING A CAPTURE WINDOW)

        2.连接到捕获驱动(CONNECTING TO A CAPTURE DRIVER)

        3.列举所有已安装的捕获驱动(ENUMERATING INSTALLED CAPTURE DRIVERS)

        4.得到捕获驱动的性能(OBTAINING THE CAPABILITIES OF A CAPTURE DRIVER)

        5.得到捕获窗口的状态(OBTAINING THE STATUS OF A CAPTURE WINDOW)

        6.显示对话框设置视频特征(DISPLAYING DIALOG BOXES TO SET VIDEO CHARACTERISTICS)

        7.得到和设置视频格式(OBTAINING AND SETTING THE VIDEO FORMAT)

        8. 预览视频(PREVIEWING VIDEO)

        9.将视频设置为OVERLAY模式(ENABLING VIDEO OVERLAY)

        10.命名捕获文件(NAMING THE CAPTURE FILE)

        11.格式化声频捕获(FORMATTING AUDIO CAPTURE)

        12.改变视频捕获设置(CHANGING A VIDEO CAPTURE SETTING)

        13.捕获数据(CAPTURING DATA)

        14.增加一个信息块(ADDING AN INFORMATION CHUNK)

        15.在程序中加入一个回调函数(ADDING CALLBACK FUNCTIONS TO AN APPLICATION)

        16.创建一个状态回调函数(CREATING A STATUS CALLBACK FUNCTION)

        17.创建一个错误回调函数( CREATING AN ERROR CALLBACK FUNCTION)

        18.创建一个框架回调函数(CREATING A FRAME CALLBACK FUNCTION)

六.将四个标准对话框改成函数调用形式

         AUDIOFORMAT对话框

         VIDEOFORMAT对话框

         VIDEOSOURCE对话框

         VIDEO COMPRESSION对话框  

前 言

         视频捕获是指由专用的视频采集卡捕获声频和视频信息,然后将其进行数据化处理,再经过软件的压缩进行处理,这时就可对这些数据进行保存、回放、传输等各种操作。

         Windows专门提供了Video for Windows来对视频处理进行支持,提供的接口可以被大多数的视频采集卡支持,并有多种视频压缩驱动供选择(当然视频压缩可以自己开发),采集卡支持摄像头,TV等多种输入。


一. 视频捕获快速入门

          视频捕捉将一个视频流和音频流数字化, 然后存储在硬盘或其他存储介质上.

          一个AVICap视窗口句柄描述了声频与视频流的细节, 这样就使你的应用程序从AVI文件格式, 声频视频缓冲管理, 低层声频视频驱动访问等等解脱出来, AVICap为应用程序提供了一个灵活的介面, 你可以仅仅使用如下几行代码就可以将视频捕捉加入你的程序:

hWndC = capCreateCaptureWindow ( "My Own Capture Window",

WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID);

SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0 /* wIndex */, 0L);

SendMessage (hWndC, WM_CAP_SEQUENCE, 0, 0L);

           一个宏其实也是使用SendMessage, 只不过提供给程序一个更易读的代码而已, 下面的这些示例就是使用宏的方法将视频捕捉加入程序:

hWndC = capCreateCaptureWindow ( "My Own Capture Window",

WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID);

capDriverConnect (hWndC, 0);

capCaptureSequence (hWndC);


          当你创建了一个AVICap类的捕捉窗口并将它连接到一个视频驱动时, 此捕捉窗口即可以开始捕捉数据, 你的程序可以简单的发送WM_CAP_SEQUENCE消息(或者使用capCaptureSequence宏)来开始捕捉.

          如果是缺省的设置, WM_CAP_SEQUENCE会开始捕捉视频音频流到CAPTURE.AVI文件中, 直到下面的某一事件发生为止:

用户按下了ESC键或者一个鼠标键

你的应用程序终止或异常中断捕捉操作

磁盘已满


              在一个应用程序里, 你可以发送WM_CAP_STOP消息来终止捕捉数据(或者使用capCaptureStop宏), 你也可以发送WM_CAP_ABORT消息(或者使用capCaptureAbort宏)来终止.


二.基本的捕获设置

          基本的捕获设置包括:设置捕获速度(每秒捕获多少帧),是否同时捕获声频,捕获缓冲,允许最大丢失多少帧,是否使用DOS内存,以及用键盘的哪个键或鼠标的哪个键来终止捕获等等。这些基本的设置都可以使用CAPTUREPARAMS结构来描述,你可以使用capCaptureGetSetup宏来得到当前的设置,然后改变此结构的成员变量,再使用capCaptureSetSetup宏设置新的设置。

例如:

1.设置捕获速度:

           捕捉速度是指捕捉任务每秒钟捕获的帧数, 你可以发送WM_CAP_GET_SEQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)来得到当前的捕捉速度, 当前的捕捉速度保存在CAPTUREPARAMS结构的dwRequestMicroSecPerFrame成员变量中, 你可以通过设置此变量来改变当前设置, 单位是每毫秒连续的帧数, 你可以发送WM_CAP_SET_SEQUENCE_SETUP消息(或者使用capCaptureSetSetup宏), dwRequestMicroSecPerFrame的值是66667, 相当于每秒15帧.


2.设置终止捕获

           你可以允许用户按下某键或某组合键或者鼠标的左右键来终止一个捕获任务, 如果是实时的捕获, 则捕获的文件将会被丢弃; 如果是单步捕获, 在终止之前所捕获的内容将会被保存.

          你可以通过发送WM_CAP_GETQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)来得到当前的设置, 当前的按键设置保存在CAPTUREPARAMS的vKeyAbort成员中, 当前的鼠标设置保存在fAbortLeftMouse和fAbortRightMouse成员中. 你可以设置新的按键或按键组合, 或者鼠标左右键, 当你修改的CAPTUREPARAMS后,应该发送WM_CAP_SET_SEQUENCE_SETUP消息来进行更新(或者使用capCaptureSetSetup宏). 缺省的按键是VK_ESCAPE. 你必须在指定按键之前使用RegisterHotKey函数, 鼠标缺省的值是fAbortLeftMouse和fAbortRightMouse都为TRUE.


3.捕获的时间限制

           CAPTUREPARAMS结构中的fLimitEnabled指示是否有时间限度, wTimeLimit指示最大的持续时间, 单位为秒.

          得到fLimitEnabled和wTimeLimit的值可以发送WM_CAP_GET_SEQUENCE_SETUP消息(或使用capCatureGetSetup宏), 当设置了这些成员变量后, 应该发送消息WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)来更新CAPTUREPARAMS结构.


三.关于捕获窗口

        在捕获之前必须创建一个捕获窗口(capture window),在发送消息或使用宏的过程中都需要使用此窗口。

1.创建一个AVICap捕获窗口

        你可以使用capCreateCaptureWindow函数来创建一个AVICap捕获窗口, 此函数将会返回一个句柄, 此句柄以后在发送消息时要用.

        你可以在一个程序里创建一个或多个捕获窗口, 然后给每一个窗口连接不同的捕获设置.


2.将一个捕获窗口连接至捕获设备

           你可以动态的在一个捕获窗口与一个捕获设备之前连接或断接, 你可以发送WM_CAP_DRIVER_CONNECT消息来使一个捕获窗口与一个捕获设备连接或关联. 当连接上以后, 你就可以通过捕获窗口向捕获设备发送各种消息.

        如果你的系统里装有多个捕获设备, 你可以在发送WM_CAP_DRIVER_CONNECT消息时用wParam参数指定使用哪一个, 此参数是登记在SYSTEM.INI文件的[drivers]一节里的列表中的某一项, 0为第一个.

          你可以使用capGetDriverDescription函数来得到已安装的捕获设备的名称及版本, 这样你的程序就可以列举所有已安装的捕获设备和驱动, 这样用户就可以选择其中的一个来与你的捕获窗口连接.

         你可以发送WM_CAP_DRIVER_GET_NAME消息(或capDriverGetName宏)来得到连接到捕获窗口的捕获设备的名称, 得到版本发送WM_CAP_DRIVER_GET_VERSION消息(或capDriverGetVersion宏)

         你可以发送WM_CAP_DRIVER_DISCONNECT消息(或capDriverDisconnect宏)来断接.


3. 父窗口与子窗口的交互

           一些象WM_PALETTECHANGED和WM_QUERYNEWPALETTE的系统级消息只能发送到顶级窗口或OVERLAPPED窗口, 如果一个捕获窗口是子窗口,就必须通过父窗口转送.

         同样的, 如果父窗口的尺寸改变了, 它就需要通知捕获窗口, 相反地, 如果捕获窗口的尺寸改变了, 捕获窗口就需要发送消息给父窗口, 一个简单的方法就是始终保持捕获窗口的尺寸与视频流的尺寸一致, 并随时将尺寸的改变通知父窗口.


4.捕获窗口的状态

          你可以发送WM_CAP_GET_STATUS消息(或capGetStatus宏)来得到当前捕获窗口的状态, 得到的是一个CAPSTATUS结构的拷贝, 它包含图片的尺寸, 卷轴的当前位置, overlay和preview是否已设置.

        因为CAPSTATUS信息是动态的, 你的程序应该只要捕获的视频流的尺寸或格式可能发生了改变就应该进行刷新(例如: 显示了捕获设备的视频格式以后).

        改变捕获窗口的尺寸并不影响实际的捕获的视频流的尺寸, 视频捕获设备的格式对话框捕获频流的尺寸.


四.视频捕获驱动和音频驱动

1.视频捕获驱动的性能:

          你可以通过发送WM_CAP_DRIVER_GET_CAPS消息(或者capDriverGetCaps宏)来得到当前连接的视频驱动的硬件性能. 得到的信息保存在CAPDRIVERCAPS结构中.


2.视频对话框:

          每一个视频驱动能够提供四个对话框来控制视频捕获和数字化处理, 定义压缩品质等, 这些对话框都定义在视频捕获驱动中.

          Video Source对话框用于控制选择视频来源, 此对话框列举了此视频捕获卡连接的所有视频源(典型的例如:SVHS和合成输入), 并提供了改变色调, 对比度, 饱和度. 如果视频驱动支持此对话框, 你就可以显示并更新它, 使用WM_CAP_DLG_VIDEOSOURCE消息(或capDlgVideoSource宏).

           Video Format对话框定义视频帧的尺寸以及精度, 视频捕获卡的压缩设置. 如果卡支持的话, 可以发送消息WM_CAP_DLG_VIDEOFORMAT消息或(capDlgVideoFormat宏).

           Video Display对话框控制在视频捕获期间在显示器上的显示, 此控制不会影响视频数字数据, 但是他们可能会影响数字信号的表现形式, 例如: 如果捕获设备支持overlay, 可能允许改变色调和饱和度, 关键色彩 或者overlay队列. 如果卡支持, 你可以发送WM_CAP_DLG_VIDEODISPLAY消息(或者使用capDlgVideoDisplay宏).

           Video Compression对话框控制压缩品质, 如果卡支持, 发送消息WM_CAP_DLG_VIDEOCOMPRESSION(或capDlgVideoCompression宏).


3.Preview 和 Overlay模式:

                 一个视频捕获驱动对进入的视频流有两种工作模式: Preview模式和overlay模式, 如果一个捕获驱动能够执行两种方法, 用户可以在其中选择一种.

               Preview模式把从捕获硬件传来的数据送入系统内存并使用图形设备介面(GDI)将数字化帧显示在捕获窗口内. 应用程序可以在父窗口失去焦点时减缓显示速度, 当重新又得到焦点后加快显示速度, 此种模式要占用大量CPU时间.

有三种消息控制Preview操作:

WM_CAP_SET_PREIVEW消息(capPreview宏)允许或禁止preview模式

WM_CAP_SET_PREVIEWRATE(capPreviewRate宏)当帧在preview模式显示时设置速度.

WM_CAP_SET_SCALE(capPreviewScale宏)允许或禁止preview视频的缩放比例.

          当preview和scaling同时使用, 捕获的视频帧将会根据捕获窗口的尺寸自动缩放, 允许preview模式会自动关闭overlay模式.

                      overlay模式是一个硬件函数它将数据送入捕获缓冲区中因而不占用CPU资源. 你可以发送消息WM_CAP_SET_OVERLAY(或capOverlay宏)给捕获窗口来启用或终止overlay模式, 允许overlay模式会自动禁止preview模式.

               你同时也可以在preview模式或overlay模式里发送WM_CAP_SET_SCROLL消息(或capSetScrollPos宏)来设置视频帧的客户区卷轴位置.


4.视频格式

            你可以通过发送WM_CAP_GET_VIDEOFORMAT消息(或capGetVideoFormat和capGetVideoFormatSize宏)来得到视频格式的结构或结构的尺寸. 你可以通过发送CAP_SET_VIDEOFORMAT消息(或capSetVideoFormat宏)来设置视频格式.


5.视频捕获设置

           CAPTUREPARMS结构包含了对视频捕获流的控制参数, 你可以完成以下这些任务:

指定帧数

指定分配多少视频缓冲

允许或禁止声频捕获

指定捕获的时间间隔

指定在捕获的过程中是否使用MCI设置(VCR或者videodisc)

指定终止流的键盘或鼠标

specify the type of video averaging applied during capture.


得到:WM_CAP_GET_SEQUENCE_SETUP消息(或capCaptureGetSetup宏)

设置:WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)


6.声频格式

               你可以通过发送WM_CAP_GET_AUDIOFORMAT消息(或capGetAudioFormat宏和capGetAudioFormatSize宏)来得到当前捕获音频数据的格式或尺寸格式。缺省的声频格式是:单声道、8位、11kHz PCM。 当你使用WM_CAP_GET_AUDIOFORMAT时,总是使用WAVEFORMATEX结构。

             设置发送消息WM_CAP_SET_AUDIOFORMAT消息(或capSetAudioFormat宏),可以传送WAVEFORMAT,WAVEFORMATEX,PCMWAVEFORMAT结构指针。

五.使用视频捕获

1.创建捕获窗口(Creating a Capture Window)

hWndC = capCreateCaptureWindow (

(LPSTR) "My Capture Window", // window name if pop-up

WS_CHILD | WS_VISIBLE, // window style

0, 0, 160, 120, // window position and dimensions

(HWND) hwndParent,

(int) nID /* child ID */);


2.连接到捕获驱动(Connecting to a Capture Driver)

           下面的例子是将MSVIDEO驱动连接到句柄为hWndC的捕获窗口, 然后调用capDriverDisconnect宏来断接.

fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L);

//

// Or, use the macro to connect to the MSVIDEO driver:

// fOK = capDriverConnect(hWndC, 0);

//

// Place code to set up and capture video here.

//

capDriverDisconnect (hWndC);


3.列举所有已安装的捕获驱动(Enumerating Installed Capture Drivers)

           下面的例子使用capGetDriverDescription函数得到已安装的捕获驱动的名称及版本:

char szDeviceName[80];

char szDeviceVersion[80];


for (wIndex = 0; wIndex < 10; wIndex++)

{

if (capGetDriverDescription (wIndex, szDeviceName,

sizeof (szDeviceName), szDeviceVersion,

sizeof (szDeviceVersion))

{

// Append name to list of installed capture drivers

// and then let the user select a driver to use.

}

}


4.得到捕获驱动的性能(Obtaining the Capabilities of a Capture Driver)

              发送WM_CAP_DRIVER_GET_CAPS消息可以得到捕获驱动的性能,并保存入一个CAPDRIVERCAPS结构.每当程序连接一个新的捕获驱动到一个捕获窗口时, 就应该更新CAPDRIVERCAPS结构. 下面的程序举例说明了如何使用capDriverGetCaps宏来得到捕获驱动的性能:


CAPDRIVERCAPS CapDrvCaps;

SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS,

sizeof (CAPDRIVERCAPS), (LONG) (LPVOID) &CapDrvCaps);

// Or, use the macro to retrieve the driver capabilities.

// capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


5.得到捕获窗口的状态(Obtaining the Status of a Capture Window)

                 下面的例子使用SetWindowPos函数使捕获窗口与进来的视频流尺寸保持一致, 视频流的基本信息是使用capGetStatus宏得到的, 保存在CAPSTATUS结构中.


CAPSTATUS CapStatus;

capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

SetWindowPos(hWndC, NULL, 0, 0, CapStatus.uiImageWidth,

CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);


6.显示对话框设置视频特征(Displaying Dialog Boxes to Set Video Characteristics)

              每个视频捕获卡一般能提供三个不同的对话框用于控制视频捕获及数字化处理. 下面的例子说明如何显示这些对话框, 在显示这些对话框之前,使用了capDriverGetCaps宏来检查CAPDRIVERCAPS结构, 以检测该卡是否有显示这些对话框:


CAPDRIVERCAPS CapDrvCaps;

capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


// Video source dialog box.

if (CapDriverCaps.fHasDlgVideoSource)

capDlgVideoSource(hWndC);


// Video format dialog box.

if (CapDriverCaps.fHasDlgVideoFormat)

{

capDlgVideoFormat(hWndC);

// Are there new image dimensions?

capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

// If so, notify the parent of a size change.

}


// Video display dialog box.

if (CapDriverCaps.fHasDlgVideoDisplay)

capDlgVideoDisplay(hWndC);


7.得到和设置视频格式(Obtaining and Setting the Video Format)

                   BITMAPINFO结构的长度既适应于标准的也适应于压缩的数据格式, 所有程序必须总是询问此结构的尺寸以便在得到当前的视频格式之前分配内存. 下面的例子就是使用capGetVideoFormatSize宏来得到缓冲区尺寸并调用capGetVideoFormat宏来得到当前的视频格式.


LPBITMAPINFO lpbi;

DWORD dwSize;

dwSize = capGetVideoFormatSize(hWndC);

lpbi = GlobalAllocPtr (GHND, dwSize);

capGetVideoFormat(hWndC, lpbi, dwSize);


// Access the video format and then free the allocated memory.


              程序可以使用capSetVideoFormat宏(或WM_CAP_SET_VIDEOFORMAT消息)发送一个BITMAPINFO头结构给捕获窗口, 因为视频格式是设备细节, 你的程序应该检查返回值以便确定此格式是否已被接受.


8. 预览视频(Previewing Video)

             下面的例子使用capPreviewRate宏来设置每66毫秒显示一帧, 并使用capPreview宏将它放置在捕获窗口里.


capPreviewRate(hWndC, 66); // rate, in milliseconds

capPreview(hWndC, TRUE); // starts preview

// Preview

capPreview(hWnd, FALSE); // disables preview


9.将视频设置为overlay模式(Enabling Video Overlay)

            下面的例子: capDriverGetCaps宏确定此捕获卡是否有overlay功能, 如果有就使用宏来设置它


CAPDRIVERCAPS CapDrvCaps;

capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


if (CapDrvCaps.fHasOverlay)

capOverlay(hWndC, TRUE);


10.命名捕获文件(Naming the Capture File)

             下面的例子: 使用capFileSetCaptureFile宏来指定预备文件名为:MYCAP.AVI, capFileAlloc宏预先指定它的大小为5M.


char szCaptureFile[] = "MYCAP.AVI";

capFileSetCaptureFile( hWndC, szCaptureFile);

capFileAlloc( hWndC, (1024L * 1024L * 5));


11.格式化声频捕获(Formatting Audio Capture)

             下面的例子使用capSetAudioFormat来设置声频格式为:11kHz, PCM 8位, 立体声


WAVEFORMATEX wfex;

wfex.wFormatTag = WAVE_FORMAT_PCM;

wfex.nChannels = 2; // Use stereo

wfex.nSamplesPerSec = 11025;

wfex.nAvgBytesPerSec = 22050;

wfex.nBlockAlign = 2;

wfex.wBitsPerSample = 8;

wfex.cbSize = 0;


capSetAudioFormat(hWndC, &wfex, sizeof(WAVEFORMATEX));


12.改变视频捕获设置(Changing a Video Capture Setting)

               下面的例子使用capCaptureGetSetup和capCaptureSetSetup宏得将捕获帧数从缺省的15帧改成每秒10帧.


CAPTUREPARMS CaptureParms;

float FramesPerSec = 10.0;


capCaptureGetSetup(hWndC, &CaptureParms, sizeof(CAPTUREPARMS));


CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 /FramesPerSec);

capCaptureSetSetup(hWndC, &CaptureParms, sizeof (CAPTUREPARMS));


13.捕获数据(Capturing Data)

                下面的例子使用capCaptureSequence宏来开始捕获视频并使用capFileSaveAs宏来将捕获的数据拷贝至NEWFILE.AVI文件中.


char szNewName[] = "NEWFILE.AVI";

// Set up the capture operation.

capCaptureSequence(hWndC);

// Capture.

capFileSaveAs(hWndC, szNewName);


14.增加一个信息块(Adding an Information Chunk)

               如果你需要在你的程序捕获的声频和视频数据中加入你的其他信息, 你可以创建一个信息块并将它们插入捕获文件中, 信息块可以包含一些典型的信息, 例如:版权信息,视频来源, 外部定位信息等. 下面的例子使用capFileSetInfoChunk宏来插入一个信息块, 里面包含了一个SMPTE的时间代码.


// This example assumes the application controls

// the video source for preroll and postroll.

CAPINFOCHUNK cic;

// .

// .

// .

cic.fccInfoID = infotypeSMPTE_TIME;

cic.lpData = "00:20:30:12";

cic.cbData = strlen (cic.lpData) + 1;

capFileSetInfoChunk (hwndC, &cic);


15.在程序中加入一个回调函数(Adding Callback Functions to an Application)

               一个程序可以为捕获窗口登记一个回调函数以便在以下的这些情况下通知程序.


状态改变

错误发生

视频框架和声频缓冲区变得可用

程序应用在捕获视频流的过程中接收


           下面的例子创建一个捕获窗口并登记状态,错误,视频流和框架回调函数在消息处理对列中, 也包括了一个终止回调函数的说明.


case WM_CREATE:

{

char achDeviceName[80]

char achDeviceVersion[100]

char achBuffer[100]

WORD wDriverCount = 0

WORD wIndex

WORD wError

HMENU hMenu


// Create a capture window using the capCreateCaptureWindow macro.

ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",

WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0);


// Register the error callback function using the

// capSetCallbackOnError macro.

capSetCallbackOnError(ghWndCap, fpErrorCallback);


// Register the status callback function using the

// capSetCallbackOnStatus macro.

capSetCallbackOnStatus(ghWndCap, fpStatusCallback);


// Register the video-stream callback function using the

// capSetCallbackOnVideoStream macro.

capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback);


// Register the frame callback function using the

// capSetCallbackOnFrame macro.

capSetCallbackOnFrame(ghWndCap, fpFrameCallback);


// Connect to a capture driver


break;

}

case WM_CLOSE:

{

// Use the capSetCallbackOnFrame macro to

// disable the frame callback. Similar calls exist for the other

// callback functions.


capSetCallbackOnFrame(hWndC, NULL);


break;

}


16.创建一个状态回调函数(Creating a Status Callback Function)

            下面的例子是创建一个简单的状态回调函数,登记此回调函数使用capSetCallbackOnStatus宏.


// StatusCallbackProc: status callback function

// hWnd: capture window handle

// nID: status code for the current status

// lpStatusText: status text string for the current status

//

LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID,

LPSTR lpStatusText)

{

if (!ghWndMain)

return FALSE;


if (nID == 0) { // Clear old status messages.

SetWindowText(ghWndMain, (LPSTR) gachAppName);

return (LRESULT) TRUE;

}

// Show the status ID and status text...

wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);


SetWindowText(ghWndMain, (LPSTR)gachBuffer);

return (LRESULT) TRUE;

}


17.创建一个错误回调函数( Creating an Error Callback Function)

             下面的例子是创建一个简单的错误回调函数,登记此回调函数使用capsetCallbackOnError宏:


// ErrorCallbackProc: error callback function

// hWnd: capture window handle

// nErrID: error code for the encountered error

// lpErrorText: error text string for the encountered error

//

LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID,

LPSTR lpErrorText)

{

if (!ghWndMain)

return FALSE;


if (nErrID == 0) // Starting a new major function.

return TRUE; // Clear out old errors.


// Show the error identifier and text.

wsprintf(gachBuffer, "Error# %d", nErrID);


MessageBox(hWnd, lpErrorText, gachBuffer,

MB_OK | MB_ICONEXCLAMATION);


return (LRESULT) TRUE;

}


18.创建一个框架回调函数(Creating a Frame Callback Function)

              登记此回调函数使用capSetCallbackOnFrame宏:


// FrameCallbackProc: frame callback function

// hWnd: capture window handle

// lpVHdr: pointer to struct containing captured

// frame information

//

LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)

{

if (!ghWndMain)

return FALSE;


wsprintf(gachBuffer, "Preview frame# %ld ", gdwFrameNum++);

SetWindowText(ghWndMain, (LPSTR)gachBuffer);

return (LRESULT) TRUE

}


 

六.将四个标准对话框改成函数调用形式

              系统提供了四个标准的对话框:AudioFormat, VideoFormat, VideoSource, Video Compression,但有时程序希望通过函数控制它们,而不是使用系统提供的那个单一的对话框,此时就应该使用函数调用的方法:


AudioFormat对话框

            可以通过使用capSetAudioFormat来实现,此时要使用WAVEFORMATEX结构。

例如:改成PCM格式,立体声,16声道,12.05kHz,则:

WAVEFORMATEX audioFormat;

// 确定宽度

acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,&dwSize);

dwSize = max (dwSize, capGetAudioFormatSize (m_hwCapCapturing));

// 设置参数

audioFormat.wFormatTag = WAVE_FORMAT_PCM;

audioFormat.nChannels = 2;

audioFormat.nSamplesPerSec = 120500;

audioFormat.wBitsPerSample =16;

audioFormat.nBlockAlign = nBitsPerSample * nChannels / 8;

audioFormat.nAvgBytesPerSec =

audioFormat.nBlockAlign * nSamplesPerSec;

// 更新

capSetAudioFormat(ghCapWnd,&audioFormat,dwSize);

VideoFormat对话框

                  可以通过使用capSetVideoFormat来实现,此时要使用BITMAPINFOHEADER结构。

例如:设置图片大小为RGB24位岁,大小为230X160

BITMAPINFOHEADER bi;

DWORD dwSize,dw;

bi.biSize = sizeof(BITMAPINFOHEADER);

bi.biWidth = 320; // 起作用

bi.biHeight = 160; // 起作用

bi.biPlanes = 1;

bi.biBitCount = 24;

bi.biCompression = BI_RGB;

bi.biSizeImage = 0;

bi.biXPelsPerMeter = 176;

bi.biYPelsPerMeter = 144;

bi.biClrUsed = 0;

bi.biClrImportant = 0;

dwSize = bi.biSize + ((bi.biBitCount > 8 || bi.biClrUsed) ? (bi.biClrUsed * sizeof(PALETTEENTRY)) : (2 ^ bi.biBitCount * sizeof(PALETTEENTRY)));

dw = capSetVideoFormat(m_hwCapCapturing, &bi, dwSize);

VideoSource对话框

                没有找到现成的方法,但视频捕获卡提供的CD里面有一个动态链接库可以实现。

Video Compression对话框

             可以通过使用ICOpen,ICInfo等函数联合起来,得到当前系统里面的视频压缩驱动的列表,并可选择其一,MSDN里面有一个程序示范了此用户,程序名叫:ICWalk。

点击此处查看原文 >>

系统分类: 软件开发   |    用户分类: 无分类    |    来源: 无分类

评论(0) | 阅读(380)
发表于:2008-3-25 9:54:14
标签:无标签

0

MFC DLL向导(二)

使用DLL的一个比较严重的问题就是编译器之间的兼容性问题。不同的编译器对c++函数在二进制级别的实现方式是不同的。所以对基于C++的DLL,如果编译器不同就有很麻烦的。如果创建的是MFC扩展DLL,就不会存在问题,因为它只能被动态连接到MFC的客户应用程序。这里不是本文讨论的重点。

一、重新编译问题
我们先来看一个在实际中可能遇到的问题:
    比如现在建立好了一个DLL导出了CMyClass类,客户也能正常使用这个DLL,假设CMyClass对象的大小为30字节。如果我们需要修改DLL中的CMyClass类,让它有相同的函数和成员变量,但是给增加了一个私有的成员变量int类型,现在CMyClass对象的大小就是34字节了。当直接把这个新的DLL给客户使用替换掉原来30字节大小的DLL,客户应用程序期望的是30字节大小的对象,而现在却变成了一个34字节大小的对象,糟糕,客户程序出错了。
    类似的问题,如果不是导出CMyClass类,而在导出的函数中使用了CMyClass,改变对象的大小仍然会有问题的。这个时候修改这个问题的唯一办法就是替换客户程序中的CMyClass的头文件,全部重新编译整个应用程序,让客户程序使用大小为34字节的对象。
    这就是一个严重的问题,有的时候如果没有客户程序的源代码,那么我们就不能使用这个新的DLL了。

二、解决方法  
 为了能避免重新编译客户程序,这里介绍两个方法:(1)使用接口类。(2)使用创建和销毁类的静态函数。
1、使用接口类
   接口类的也就是创建第二个类,它作为要导出类的接口,所以在导出类改变时,也不需要重新编译客户程序,因为接口类没有发生变化。
   假设导出的CMyClass类有两个函数FunctionA FunctionB。现在创建一个接口类CMyInterface,下面就是在DLL中的CMyInterface类的头文件的代码:
# include "MyClass.h"
class _declspec(dllexport) CMyInterface
{
     CMyClass *pmyclass;
     CMyInterface();
     ~CMyInterface();
  public:
     int FunctionA(int);
     int FunctionB(int);
};
而在客户程序中的头文件稍不同,不需要INCLUDE语句,因为客户程序没有它的拷贝。相反,使用一个CMyClass的向前声明,即使没有头文件也能编译:
class _declspec(dllexport) CMyInterface
{
     class CMyClass;//向前声明
     CMyClass *pmyclass;
     CMyInterface();
     ~CMyInterface();
  public:
     int FunctionA(int);
     int FunctionB(int);
};
在DLL中的CMyInterface的实现如下:
CMyInterface::CMyInterface()
{
      pmyclass = new CMyClass();
}
CMyInterface::~CMyInterface()
{
     delete pmyclass;
}
int CMyInterface::FunctionA()
{
     return pmyclass->FunctionA();
}
int CMyInterface::FunctionB()
{
     return pmyclass->FunctionB();   
}
.....
对导出类CMyClass的每个成员函数,CMyInterface类都提供自己的对应的函数。客户程序与CMyClass没有联系,这样任意改CMyClass也不会有问题,因为CMyInterface类的大小没有发生变化。即使为了能访问CMyClass中的新增变量而给CMyInterface类加了函数也不会有问题的。
   但是这种方法也存在明显的问题,对导出类的每个函数和成员变量都要对应实现,有的时候这个接口类会很庞大。同时增加了客户程序调用所需要的时间。增加了程序的开销。

2、使用静态函数
   还可以使用静态函数来创建和销毁类对象。创建一个导出类的时候,增加两个静态的公有函数CreateMe()/DestroyMe(),头文件如下:
class _declspec(dllexport) CMyClass
{
     CMyClass();
     ~CMyClass();
  public:
     static CMyClass *CreateMe();
     static void DestroyMe(CMyClass *ptr);
};
实现函数就是:
CMyClass * CMyClass::CMyClass()
{
      return new CMyClass;
}
void CMyClass::DestroyMe(CMyClass *ptr)
{
      delete ptr;
}
然后象其他类一样导出CMyClass类,这个时候在客户程序中使用这个类的方法稍有不同了。如若想创建一个CMyClass对象,就应该是:
CMyClass x;
CMyClass *ptr = CMyClass::CreateMe();
在使用完后删除:
CMyClass::DestroyMe(ptr);

点击此处查看原文 >>

系统分类: 软件开发   |    用户分类: 无分类    |    来源: 无分类

评论(0) | 阅读(158)
发表于:2008-3-25 9:52:55
标签:无标签

1

MFC DLL向导(一)

虽然能用DLL实现的东西都可以用COM来实现,但DLL的优点确实不少,它更容易创建。本文将讨论如何利用MFC来创建不同类型的DLL,以及如何使用他们。

一、DLL的不同类型
    使用MFC可以生成两种类型的DLL:MFC扩展DLL和常规DLL。常规DLL有可以分为动态连接和静态连接。Visual C++还可以生成WIN32 DLL,但不是这里讨论的主要对象。
1、MFC扩展DLL
   每个DLL都有某种类型的接口:变量、指针、函数、客户程序访问的类。它们的作用是让客户程序使用DLL,MFC扩展DLL可以有C++的接口。也就是它可以导出C++类给客户端。导出的函数可以使用C++/MFC数据类型做参数或返回值,导出一个类时客户端能创建类对象或者派生这个类。同时,在DLL中也可以使用DLL和MFC。
   Visual C++使用的MFC类库也是保存在一个DLL中,MFC扩展DLL动态连接到MFC代码库的DLL,客户程序也必须要动态连接到MFC代码库的DLL。(这里谈到的两个DLL,一个是我们自己编写的DLL,一个装MFC类库的DLL)现在MFC代码库的DLL也存在多个版本,客户程序和扩展DLL都必须使用相同版本的MFC代码DLL。所以为了让MFC扩展DLL能很好的工作,扩展DLL和客户程序都必须动态连接到MFC代码库DLL。而这个DLL必须在客户程序运行的计算机上。
2、常规DLL
   使用MFC扩展DLL的一个问题就是DLL仅能和MFC客户程序一起工作,如果需要一个使用更广泛的DLL,最好采用常规DLL,因为它不受MFC的某些限制。常规DLL也有缺点:它不能和客户程序发送指针或MFC派生类和对象的引用。一句话就是常规DLL和客户程序的接口不能使用MFC,但在DLL和客户程序的内部还是可以使用MFC。
   当在常规DLL的内部使用MFC代码库的DLL时,可以是动态连接/静态连接。如果是动态连接,也就是常规DLL需要的MFC代码没有构建到DLL中,这种情况有点和扩展DLL类似,在DLL运行的计算机上必须要MFC代码库的DLL。如果是静态连接,常规DLL里面已经包含了需要的MFC代码,这样DLL的体积将比较大,但它可以在没有MFC代码库DLL的计算机上正常运行。

二、建立DLL
    利用Visual C++提供的向导功能可以很容易建立一个不完成任何实质任务的DLL,这里就不多讲了,主要的任务是如何给DLL添加功能,以及在客户程序中利用这个DLL
1、导出类
   用向导建立好框架后,就可以添加需要导出类的.cpp .h文件到DLL中来,或者用向导创建C++ Herder File/C++ Source File。为了能导出这个类,在类声明的时候要加“_declspec(dllexport)”,如:
class _declspec(dllexport) CMyClass
{
     ...//声明
}
如果创建的MFC扩展DLL,可以使用宏:AFX_EXT_CLASS:
class AFX_EXT_CLASS CMyClass
{
     ...//声明
}
这样导出类的方法是最简单的,也可以采用.def文件导出,这里暂不详谈。
2、导出变量、常量、对象
   很多时候不需要导出一个类,可以让DLL导出一个变量、常量、对象,导出它们只需要进行简单的声明:_declspec(dllexport) int MyInt;
  _declspec(dllexport) extern const COLORREF MyColor="RGB"(0,0,0);
  _declspec(dllexport) CRect rect(10,10,20,20);
要导出一个常量时必须使用关键字extern,否则会发生连接错误。
注意:如果客户程序识别这个类而且有自己的头文件,则只能导出一个类对象。如果在DLL中创建一个类,客户程序不使用头文件就无法识别这个类。
  当导出一个对象或者变量时,载入DLL的每个客户程序都有一个自己的拷贝。也就是如果两个程序使用的是同一个DLL,一个应用程序所做的修改不会影响另一个应用程序。
  我们在导出的时候只能导出DLL中的全局变量或对象,而不能导出局部的变量和对象,因为它们过了作用域也就不存在了,那样DLL就不能正常工作。如:
MyFunction()
{
      _declspec(dllexport) int MyInt;
      _declspec(dllexport) CMyClass object;
}
3、导出函数
导出函数和导出变量/对象类似,只要把_declspec(dllexport)加到函数原型开始的位置:
_declspec(dllexport) int MyFunction(int);
如果是常规DLL,它将和C写的程序使用,声明方式如下:
extern "c" _declspec(dllexport) int MyFunction(int);
实现:
extern "c" _declspec(dllexport) int MyFunction(int x)
{
     ...//操作
}
如果创建的是动态连接到MFC代码库DLL的常规DLL,则必须插入AFX_MANAGE_STATE作为导出函数的首行,因此定义如下:
extern "c" _declspec(dllexport) int MyFunction(int x)
{
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     ...//操作
}
有时候为了安全起见,在每个常规DLL里都加上,也不会有任何问题,只是在静态连接的时候这个宏无效而已。这是导出函数的方法,记住只有MFC扩展DLL才能让参数和返回值使用MFC的数据类型。
4、导出指针
导出指针的方式如下:
_declspec(dllexport) int *pint;
_declspec(dllexport) CMyClass object = new CMyClass;
如果声明的时候同时初始化了指针,就需要找到合适的地方类释放指针。在扩展DLL中有个函数DllMain()。(注意函数名中的两个l要是小写字母),可以在这个函数中处理指针:
# include "MyClass.h"
_declspec(dllexport) CMyClass *pobject = new CMyClass;
DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)
{
    if(dwReason == DLL_PROCESS_ATTACH)
    {
        .....//
    }
    else if(dwReason == DLL_PROCESS_DETACH)
    {
        delete pobject;
    }
}
常规DLL有一个从CWinApp派生的类对象处理DLL的开和关,可以使用类向导添加InitInstance/ExitInstance函数。
int CMyDllApp::ExitInstance()
{
    delete pobject;
    return CWinApp::ExitInstance();
}

三、在客户程序中使用DLL
    编译一个DLL时将创建两个文件.dll文件和.lib文件。首先将这两个文件复制到客户程序项目的文件夹里,这里需要注意DLL和客户程序的版本问题,尽量使用相同的版本,都使用RELEASE或者都是DEBUG版本。
   接着就需要在客户程序中设置LIB文件,打开Project Settings--->Link--->Object/library Modules中输入LIB的文件名和路径。如:Debug/SampleDll.lib。除了DLL和LIB文件外,客户程序需要针对导出类、函数、对象和变量的头文件,现在进行导入添加的关键字就是:_declspec(dllimport),如:
_declspec(dllimport) int MyFunction(int);
_declspec(dllimport) int MyInt;
_declspec(dllimport) CMyClass object;
extern "C" _declspec(dllimport) int MyFunction(int);
在有的时候为了导入类,要把相应类的头文件添加到客户程序中,不同的是要修改类声明的标志:
class _declspec(dllimport) CMyClass,如果创建的是扩展DLL,两个位置都是:
class AFX_EXT_CLASS CMyClass。

点击此处查看原文 >>

系统分类: 软件开发   |    用户分类: 无分类    |    来源: 无分类

评论(0) | 阅读(190)
发表于:2008-3-25 9:50:20
标签:无标签

0

基于VFW的视频应用程序开发

关  键  字: 视频捕获;SDK;VFW;AVI;MCI

当前,在Windows 平台下开发视频应用程序一般采用两种方式:一种是基于视频采集卡所附带的二次软件开发包SDK(Software development kit)进行。这种方式的优点是应用方便,容易上手,缺点是对硬件的依赖性较强,灵活性差,且功能参差不齐,不能充分满足各种视频应用程序的开发需要;

另一种方式是基于VFW(Video for Windows)进行的。VFW 是Microsoft公司为开发Windows平台下的视频应用程序提供的软件工具包,提供了一系列应用程序编程接口(API),用户可以通过它们很方便地实现视频捕获、视频编辑及视频播放等通用功能,还可利用回调函数开发更复杂的视频应用程序。它的特点是播放视频时不需要专用的硬件设备,而且应用灵活,可以满足视频应用程序开发的需要。Windows操作系统自身就携带了VFW,系统安装时,会自动安装VFW的相关组件。VC++自4.0以来就支持VFW,大大简化了视频应用程序的开发。目前,PC机上多媒体应用程序的视频部分,大都是利用VFW API开发的。

1  VFW 的体系结构

VFW以消息驱动方式对视频设备进行存取,可以很方便地控制设备数据流的工作过程。目前,大多数的视频采集卡驱动程序都支持VFW接口,它主要包括多个动态连接库,通过这些组件间的协调合作,来完成视频的捕获、视频压缩及播放功能。VFW体系结构如图1所示。

1)VICAP.DLL:主要实现视频捕获功能,包含了用于视频捕获的函数,为音像交错AVI (Audio video interleaved)格式文件和视频、音频设备程序提供一个高级接口。

2)MSVIDEO.DLL:能够将视频捕获窗口与获驱动设备连接起来,支持ICM视频编码服务。

3)MCIAVI.DRV:包含MCI(Media control interface)命令解释器,实现回放功能。

4)AVIFILE.DLL:提供对AVI文件的读写操作等文件管理功能。

5)ICM ( Installable compression manager ):即压缩管理器,提供对存储在AVI文件中视频图像数据的压缩、解压缩服务。

       6)ACM ( Audio Compression Manager ):即音频压缩管理器,提供实时音频压缩及解压缩功能。

Capture Application

Playback Application

Edit Application

AVICAP.DLL

 AVICAP

MSVIDEO.DLL

MCIWnd

ACM

MCIAVI.DRV

MCI Command

Interpreter

MSVIDEO.DLL

Video in     ICM

Channel

AVIFILE.DLL

File / Stream

Handler

MSVIDEO.DLL

Drawdib  ICM 

Capture Application

Playback Application

Edit Application

AVICAP.DLL

 AVICAP

MSVIDEO.DLL

MCIWnd

ACM

MCIAVI.DRV

MCI Command

Interpreter

MSVIDEO.DLL

Video in     ICM

Channel

AVIFILE.DLL

File / Stream

Handler

MSVIDEO.DLL

Drawdib  ICM