VS2010 C++学习(5):基于DirectShow的视频

预览录像程序

学习VC++编制的基于DirectShow视频捕获程序,主要练习基于DirectShow程序的应用。

一、           主要内容:

1.        基于DirectShow视频预览;

2.        基于DirectShow视频录像;

二、           设计实现:

(一)、安装DirectShow

首先我们安装DirectShow SDK,由于现在directShow没有和direcxtx一起发布,而是和windows
sdk 打包发布了,可以到官网下载最新的windows sdk
开发包。一个可用的下载地址为http://dl-sh-ctc-2.pchome.net/07/hh/DXSDK_Feb10.rar

然后安装好windows SDK。安装完DirectShow SDK的目录为C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow。

(二)、开发环境配置

开发环境的配置主要有两个工作要做:

一是在使用Directshow SDK开发自己的程序时需要的DirectShow的有关静态库的配置,

二是visual C++开发环境的配置。

1)      生成DirectShow SDK开发库

使用DirectShow SDK开发用户自己的程序需要几个静态链接库:quartz.lib、strmbasd.lib、STRMBASE.lib和strmiids.lib。中间两个lib需要用户自己编译生成,而其他两个微软已经提供。下表列出了使用DirectShow
SDK开发程序所有要使用的库。

库名

功能说明

Strmiids.lib

定义了DirectShow标准的输出类标识(CLSID)和接口标识(IID)

Strmbasd.lib

流媒体开发用到的库,Debug、Debug_Unicode版本

Strmbase.lib

流媒体开发用到的库,Release、Release_Unicode版本

Quartz.lib

定义了导出函数AMGetErrorText

Winmm.lib

使用Windows多媒体编程用到的库

2)      更改添加的include内容:

C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses;

C:\Program Files\Microsoft SDKs\Windows\v7.1\Include;

添加过程如下。选择“Ex005属性”→“选项” →“VC++目录” →“包含目录”,将上面的2个Include内容添加进去。

3)      更改添加lib路径

要添加的lib内容:

C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Debug;

C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib;

添加过程和Include内容相似,选择“Ex005属性”→“选项” →“VC++目录” →“库文件”选项。

4)      添加链接库支持

C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Debug;

C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib;

5)     
 小贴士

DirectShow中的例子,在编译的过程中经常会出现这样的错误:



Error 1 error C2061: syntax error : identifier 'CAMSchedule' c:/program files/microsoft sdks/windows/v6.0/samples/multimedia/directshow/baseclasses/refclock.h 80


     这主要是因为在不同SDK的目录里包含了多个 schedule.h file 和 refclock.h

因此需要在
“Ex005属性”→“选项” →“VC++目录” →“包含目录”中调整 include 的顺序,将samples/multimedia/directshow/baseclasses 放到其他的sdk之前即可

(三)、DirectShow视频采集方案

流媒体处理技术以其复杂性和技术性一直受到人们的关注。随着网络技术的不断发展,流媒体在网络上得到了广泛地应用。如何能够简单、有效地进行流媒体处理,已成为一个焦点问题。为此,Microsoft推出了DirectShow,DirectShow是Microsoft推出的基于Windows平台的流媒体处理开发包,它与DirectX一起发布。DirectShow对流媒体的捕捉、回放提供了强大的支持。

1)      DirectShow系统结构分析

DirectShow主要由过滤器(Filter Graph)图表构成。过滤图表中包含了各种Filter,这些Filter能够按一定顺序连接在一起,构成一条流水线。

从功能的角度划分,Filter
大体可以分为3类,

l  Source Filters;主要负责获取数据,可以是一个文件、一个采集卡、声卡或数码相机等。

l  Transform Filters;负责数据的转换、传输。例如各种码器、解码器等。

l  Rendering Filters。负责数据的最终去向,例如将数据传送到声卡、显卡或存储为文件。

在开发DirectShow应用程序时,通常需要设计一个过滤图表(Filter
Graph),向过滤图表中添加相应的过滤器,最后连接过滤器的引脚就完成了功能的设计。

例如,实现一个简单的视频预览功能,需要向过滤图表中添加一个视频捕捉源过滤器和一个Video Renderer过滤器,将视频捕捉源过滤器的输出引脚与Video Renderer过滤器的输入引脚相连就可以了。

而在程序中只需要按照设计过滤图表的捕捉添加过滤器并连接过滤器引脚就可以了。在连接过滤器引脚时需要注意:只能是输出过滤器引脚与输入过滤器引脚相连,两个输出过滤器或两个输入过滤器引脚是不能相连的。

2)      Filter图表设计

为了方便用户设计过滤图表,DirectX提供了一个Graph Edit工具。

位于 C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\graphedt.exe。

点击运行。演示如何使用Graph Edit工具设计过滤图表,过滤图表的功能是实现视频的预览功能。具体步骤如下:

(1)单击“Graph/Insert Filters”菜单项打开“添加过滤器”窗口,

选择一个视频捕捉源过滤器。选择“Video Renderer”最终去向过滤器,连接,如图1。

图2 宽屏haali视频分离器

单击工具栏中的“>”按钮运行过滤图表,将显示一个视频预览窗口。

3)      枚举系统设备

使用Graph Edit工具,用户可以非常方便地获得与某一系统设备相关的过滤器。但是,在程序中该如何获得这些过滤器呢?

用户可以采用枚举的方式列举系统中安装的设备。

以列举系统中的视频捕捉设备为例,

(1)    首先定义一个设备列举接口 ICreateDevEnum的一个指针;

(2)    调用CoCreateInstance方法创建ICreateDevEnum实例。

(3)    然后定义一个列举监视器 IEnumMoniker的一个指针;

(4)    调用ICreateDevEnum实例的CreateClassEnumerator方法创建
IEnumMoniker实例。

(5)    最后以循环的方式调用IEnumMoniker实例的Next方法遍历系统设备;

(6)    调用IEnumMoniker实例的 BindToObject方法将系统设备绑定到过滤器上。

在上面的描述中,ICreateDevEnum实例的CreateClassEnumerator方法的第一个参数确定枚举的系统设备。例如,第一个参数为CLSID_VideoInputDeviceCategory,表示将要枚举系统中的视频捕捉卡,为
CLSID_VideoCompressorCategory,表示枚举系统中的视频压缩器。

下面的代码演示了如何枚举系统中的视频捕捉卡。

//枚举视频设备;值= CLSID_VideoInputDeviceCategory

//    
音频设备的值= CLSID_ AudioInputDeviceCategory;

ICreateDevEnum *pDevEnum = NULL;

CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,

IID_ICreateDevEnum, (void **)&pDevEnum);

IEnumMoniker *pClassEnum = NULL;

pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClassEnum, 0);

ULONG cFetched;

while (pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK)

{

pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc);

pMoniker->Release();

break;

}

pClassEnum->Release();

而下面的代码则用于判断系统中是否安装了指定的视频压缩器。

ICreateDevEnum *pDevEnum = NULL;

CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,

IID_ICreateDevEnum, (void **)&pDevEnum);

IEnumMoniker *pClassEnum = NULL;

//列举视频压缩设备;值=CLSID_VideoCompressorCategory

pDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pClassEnum, 0);

while (pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK)

{

IPropertyBag* pProp= NULL;

pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pProp);

VARIANT varName;

varName.vt = VT_BSTR;

pProp->Read(L"FriendlyName", &varName,0);

CString str = varName.bstrVal;

if (str.Find("Microsoft Video 1",0)!= -1)

{

pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCompress);

pMoniker->Release();

break;

}

VariantClear(&varName);

}

pClassEnum->Release();

4)      查找Filter Pin过滤器引脚

每一个过滤器(Filter)至少应有一个引脚(Pin),或者是输入引脚或者是输出引脚。有些过滤器还拥有多个引脚,即又输入引脚又有输出引脚。但是过滤器的输入、输出引脚并不是对应的,有些过滤器可以有多个输入引脚,而只有一个输出引脚或者没有输出引脚。在程序中为了连接过滤器间的引脚,通常需要获得过滤器的各个引脚。

用户可以使用IEnumPins接口来枚举某一个过滤器的输入、输出引脚。过滤器 IBaseFilter提供了一个EnumPins方法用于生成一个IEnumPins接口实例,这样,通过调用IEnumPins的Next方法便可以访问各个引脚了。

下面的代码定义了一个FindPin函数,用于获得某个过滤器的输入或输出引脚。

//查找引脚

IPin* CKinescopeDlg::FindPin(IBaseFilter *pFilter, PIN_DIRECTION dir)

{

IEnumPins* pEnumPins;

IPin* pOutpin;

PIN_DIRECTION pDir;

pFilter->EnumPins(&pEnumPins);

while (pEnumPins->Next(1,&pOutpin,NULL)==S_OK)

{

pOutpin->QueryDirection(&pDir);

if (pDir==dir) {return pOutpin;}

}

return 0;

}

用户可以按下面的方式获得某个过滤器的输入、输出引脚。

IPin * pComOut,*pComIn ;

pComIn  = FindPin(pCompress,PINDIR_INPUT);

pComOut = FindPin(pCompress,PINDIR_OUTPUT);

5)      连接Filter Pin过滤器引脚

使用Graph Edit工具,用户可以利用鼠标非常方便地连接两个过滤器间的引脚。但是在程序中却没这么简单了。首先需要按照上面介绍的方法获得两个过滤器的输入、输出引脚,然后将第一个过滤器的输出引脚连接到第二个过滤器的输入引脚,其中,连接两个引脚需要调用IGraphBuilder接口的
ConnectDirect方法。

下面的代码演示了如何连接两个过滤器的引脚。

IPin * pComOut,*pComIn ;

pComIn  = FindPin(pCompress,PINDIR_INPUT);

pComOut = FindPin(pCompress,PINDIR_OUTPUT);

IPin* pOutpin = FindPin(pSrc,PINDIR_OUTPUT); //pSrc的输出引脚

HRESULT result ;

result = pGraph->ConnectDirect(pOutpin,pComIn,NULL);

VS2010 C++学习(5):基于DirectShow的视频预览录像程序的更多相关文章

  1. DirectShow 进行视频预览和录制

    这一篇讲怎么采集摄像头图像并预览,以及录制视频到本地. 程序实现流程 这里通过使用 CaptureGraphBuilder 来简化 Graph 的创建流程. 具体流程如下: 初始化 COM 库 创建各 ...

  2. 上传APP加入视频预览--精简点名

    上传APP加入视频预览--精简点名 在为精简点名APP制作视频预览时的坑: 1.视频预览不能太长.也不能太短15-30s就好.我录制的是18s 2.视频的帧数不能太大.也就是说你在录制视频的时候.要慢 ...

  3. 一款基于jQuery可放大预览的图片滑块插件

    今天给大家分享一款基于jQuery可放大预览的图片滑块插件.这款jQuery焦点图插件的特点是可以横向左右滑动图片,并且点击图片可以进行放大预览,唯一的缺陷是这款焦点图并不能循环切换,如果你有较好的J ...

  4. 关于云平台中OFFICE预览与视频预览的解决办法

    最近,随着firefox x64的升级,出现flash插件完全被禁止的现象,html5替换是大势所趋,原来我们在云平台中有多处使用flash的地方,比如OFFICE预览,视频播放,游戏等,现对于OFF ...

  5. 基于HTML5的可预览多图片Ajax上传

    一.关于图片上传什么什么的 在XHTML的时代,我们使用HTML file控件上传图片一次只能上传一张.要一次上传多图,做法是借助于flash.例如swfupload.js.可惜,使用复杂的点,比如f ...

  6. mvc实现上传视频预览

    上个项目中用到了上传视频,本来打算用百度的webuploader做的,但是webuploader可能有个毛病就是不能上传太大的东西. 于是乎,只能换个方法做了啊,看了半天最终决定用传统的uploade ...

  7. 基于jquery的相册预览gallery

    众多有图片的产品,都要加个图片预览功能.然后市面上就出现了各种各样的相册,下面也提供一个基于jquery的相册. 源码:https://github.com/lilyH/gallery 版本: v0. ...

  8. JS通过使用PDFJS实现基于文件流的预览功能

    需求: 使用JS实现PDF文件预览功能 备选方案: 使用ViewerJS,官网  http://viewerjs.org/ 使用PDFJS,官网  https://mozilla.github.io/ ...

  9. 基于Bootstrap 3可预览的HTML5文件上传插件

    前端常用资源地址: http://www.htmleaf.com/ http://www.htmleaf.com/html5/html5muban/201505091801.html 源代码地址 ht ...

随机推荐

  1. React-Native 之 Modal介绍与使用

    前言 遗漏的常用组件,刚发现官方有提供,这边也来介绍一下. 如本文有错或理解偏差欢迎联系我,会尽快改正更新! 如有什么问题,也可直接通过邮箱 277511806@qq.com 联系我. 本章涉及资源下 ...

  2. vue项目实现记住密码到cookie功能(附源码)

    实现功能: 1.记住密码勾选,点登陆时,将账号和密码保存到cookie,下次登陆自动显示到表单内 2.不勾选,点登陆时候则清空之前保存到cookie的值,下次登陆需要手动输入 大体思路就是通过存/取/ ...

  3. BZOJ 2073: [POI2004]PRZ [DP 状压]

    传送门 水题不解释 这道题的主要目的在于记录一个枚举子集的技巧 #include <iostream> #include <cstdio> #include <cstri ...

  4. 【模板小程序】求小于等于N范围内的质数

    //筛法求N以内的素数(普通法+优化),N>=2 #include <iostream> #include <cmath> #include <vector> ...

  5. python+opencv2相机位姿估计

    最近在做基于图像的室内定位方面的研究,于是使用到了百度最新的室内数据库Image-based Localization (IBL) .由于该数据库给出的数据是每幅图像和其对应相机的内外参数和光心投影方 ...

  6. PYTHON3 RE正则表达:

    The special characters are: "." Matches any character except a newline. "^" Matc ...

  7. PLEC-交流电机系统+笔记

    1.固有机械特性近似图 2.三相交流电机的控制系统 1)理论推导 第一次制动选择能耗制动,第二次制动选择倒拉制动. 2)模型搭建 3)模拟仿真 3.心得体会和笔记总结 制动方式的选择主要是根据各个制动 ...

  8. MacbookPro管理员问题

    更改用户名重启之后,发现用户名还是用户名,管理员权限降成了普通用户. 参考这个帖子改的用户名: https://zhidao.baidu.com/question/259845860.html 找回管 ...

  9. PHP基础点滴

    PHP基础点滴 双冒号::的用法: 双冒号操作符即作用域限定操作符Scope Resolution Operator可以访问静态.const和类中重写的属性与方法. 伪类型(pseudo-types) ...

  10. 大型互联网公司Java开发岗位面试题归类!

    ​一.Java基础 1. String类为什么是final的. 2. HashMap的源码,实现原理,底层结构. 3. 说说你知道的几个Java集合类:list.set.queue.map实现类咯.. ...