DirectShow获取一张图片
基于DirectShow视频及图片捕获软件的开发

我们知道目前很多工业相机的图像数据采集都是基于DirectShow的,常见的有映美精等。
DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。
DirectShow为多媒体流的捕捉和回放提供了强有力的支持。
运用DirectShow,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。
它广泛地支持各种媒体格式,包括Asf、Mpeg、Avi、Dv、Mp3、Wave等等,使得多媒体数据的回放变得轻而易举。
另外,DirectShow还集成了DirectX其它部分(比如DirectDraw、DirectSound)的技术,直接支持DVD的播放,视频的非线性编辑,以及与数字摄像机的数据交换。
更值得一提的是,DirectShow提供的是一种开放式的开发环境,我们可以根据自己的需要定制自己的组件。
笔者使用visual studio 2005 来开发了基于DirectShow的视频捕获软件,并用开发的软件对映美精相机进行了测试。
本软件不但可以实现对相机的视频捕获,而且还可以抓取图像帧。
软件运行时自动搜索所连接的相机,预览后可以对相机参数进行设置。
下面是软件的主界面。
预览视频后可以对视频格式和图像参数进行设置。
开始预览时,捕获的视频是黑白的,我们将颜色空间设置为UYVY即可捕获彩色视频。
下面是捕获的一帧图像,图像质量虽然没有映美精自带的软件效果好,但已经实现了所需各项基本功能,接下来的工作将会进一步提高软件性能。
另外我们还可以捕获视频,点击“捕获视频”按钮,输入要保持的文件名,注意要以.avi后缀结尾,点确定就开始捕获视频。
从我们开发的软件可以看到,映美精的相机能够很好的支持DirectShow的驱动,我们的软件对映美精相机的识别是如此的容易。
接下来我们将继续开发基于其它驱动的图像捕获软件,为最终实现在一个软件中识别各种相机而努力。
(MatLab、Labview)通过Directshow接口访问相机参数设置方法

(MatLab、Labview)通过Directshow接⼝访问相机参数设置⽅法DirectShow接⼝访问相机参数设置⽅法本⽂档适⽤于所有适⽤directshow接⼝访问相机的程序,例如MATLAB 和Labview的ImaqDx接⼝、Halcon的Directshow接⼝等。
MATLAB中,可以通过如下界⾯设置相机参数:Labview的NIMAX中可以通过如下界⾯设置相机参数:下⾯以Labview为例,介绍Labview中如何通过ImaqDx接⼝访问迈德威视⼯业相机。
⽬前,我们提供三种⽅式,在Labview中访问我们的相机:1.GigeVision接⼝。
仅我司GigE相机⽀持该⽅式访问。
2.直接基于SDK的DLL⽂件调⽤的⽅式。
该⽅式⽀持我们所有型号相机。
例程在安装⽬录的DEMO/LABVIEW/USEDLL⽂件夹中。
3.通过ImaqDx使⽤Directshow接⼝访问相机。
该⽅式⽀持我们所有型号相机。
Directshow接⼝是windows系统上的⾳视频标准接⼝,定义了⼀些预先约定好的协议,但是由于协议定义时间⽐较早,也没有为⼯业摄像头考虑参数接⼝,所以接⼝的参数配置上,没有像使⽤我们的SDK那样灵活。
我们针对此问题,做了⼀些特殊处理,扩展了Dircetshow接⼝中Camera Atrributes的“White Balance”属性,⽬前可以该⽅式进⾏如下操作:1.设置相机⼯作模式(连续采集、软触发、硬触发)⽅法:在Camera Atrributes中,设置“White Balance”属性的Value值●为0,则相机进⼊连续⼯作模式;●设置为1,则相机进⼊软触发⼯作模式;●设置为2则相机进⼊硬触发⼯作模式。
2.执⾏⼀次软触发⽅法:在Camera Atrributes中,设置“White Balance”属性的Value 值为3,则相机进⾏⼀次软触发,如果要多次软触发,则重复设置“White Balance”属性的Value值为3即可,每设置⼀次,进⾏⼀次软触发。
DirectShow视频采集方案

流媒体处理技术以其复杂性和技术性一直受到人们的关注。随着网络技术的不断发展,流媒体在网络上得到了广泛地应用。如何能够简单、有效地进行流媒体处理,已成为一个焦点问题。为此,Microsoft推出了DirectShow,DirectShow是Microsoft推出的基于Windows平台的流媒体处理开发包,它与DirectX一起发布。DirectShow对流媒体的捕捉、回放提供了强大的支持,使用它还可以在基于WDM驱动的采集卡上进行数据捕捉。本节将介绍有关DirectShow的相关知识。
while (pEnumPins->Next(1,&pOutpin,NULL)==S_OK)
{
pOutpin->QueryDirection(&pDir);
if (pDir==dir)
{
return pOutpin;
}
}
return 0;
}
用户可以按下面的方式获得某个过滤器的输入、输出引脚。
IPin * pComOut,*pComIn ;
在开发DirectShow应用程序时,通常需要设计一个过滤图表(Filter Graph),向过滤图表中添加相应的过滤器,最后连接过滤器的引脚就完成了功能的设计。例如,实现一个简单的视频预览功能,需要向过滤图表中添加一个视频捕捉源过滤器和一个Video Renderer过滤器,将视频捕捉源过滤器的输出引脚与Video Renderer过滤器的输入引脚相连就可以了。而在程序中只需要按照设计过滤图表的捕捉添加过滤器并连接过滤器引脚就可以了。在连接过滤器引脚时需要注意:只能是输出过滤器引脚与输入过滤器引脚相连,两个输出过滤器或两个输入过滤器引脚是不能相连的。
为了在程序中使用DirectShow,需要单独安装DirectX,当前DirectX的最新版本为9.0,即DirectX9.0,用户可以从Microsoft的官方网站上免费下载。在安装DirectX之后,程序中需要引用“dshow.h”头文件,并导入“Strmiids.lib”库文件和“quartz.lib”库文件才可以使用DirectShow。代码如下:
工业相机安装使用说明书

工业相机安装使用说明书文件版本:V1.2目录1产品简介 (3)2程序的安装 (4)3演示软件的使用方法 (8)3.1菜单栏 (9)3.2工具栏 (9)3.3视频预览区 (11)3.4状态栏 (12)4相机DirectShow接口的使用方法 (13)5相机TWAIN接口的使用方法 (17)在Photoshop中使用TWAIN接口捕获图像 (17)在Scope photo中使用TWAIN接口捕获图像 (19)在Image-Pro Plus中使用TWAIN接口捕获图像 (21)6相机Halcon接口的使用方法 (22)7相机Labview接口的使用方法 (27)8如何使用相机SDK进行二次开发 (29)1产品简介我公司工业相机有如下特点:1,统一的SDK接口。
我公司USB2.0、USB3.0、千兆网、1394接口的CCD、CMOS相机,都使用同一套SDK、演示平台,您无需关心不同型号、接口的相机带来的差异。
2,完美支持一台电脑接多个相机。
用户或者开发人员可以在配置界面中方便修改指定相机的名称,用来区分多相机,相机名称修改后,无论接在哪台电脑、无论是使用DSHOW、TWAIN、还是SDK接口,都会显示为您修改后的名字,您无需再为一台电脑接多个相机难以区分而烦恼。
3,相机支持4组参数保存与加载,同时,支持从文件中加载参数,方便量产。
支持多种不同的参数加载模式,可以按照相机的名称、唯一序列号、或者型号来进行加载,以满足您不同的使用场合需求。
4,提供丰富的图像处理接口,算法关键部分采用硬件加速功能,有效提升图像质量的同时降低CPU占用率。
5,支持多种第三方软件接口。
目前已经支持的接口有DirectShow、TWAIN、Halcon、Labview、OpenCV、OCX。
6,所有相机均支持时间戳功能,能够准确记录图像采集的时间点,录像文件能够准确还原拍摄时的时间。
7,提供中英文两个版本,可动态切换。
8,人性化的相机配置界面。
基于DirectShow视频及图片捕获软件的开发

基于DirectShow视频及图片捕获软件的开发我们知道目前很多工业相机的图像数据采集都是基于DirectShow的,常见的有映美精等。
DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。
DirectShow为多媒体流的捕捉和回放提供了强有力的支持。
运用DirectShow,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。
它广泛地支持各种媒体格式,包括Asf、Mpeg、Avi、Dv、Mp3、Wave等等,使得多媒体数据的回放变得轻而易举。
另外,DirectShow还集成了DirectX其它部分(比如DirectDraw、DirectSound)的技术,直接支持DVD的播放,视频的非线性编辑,以及与数字摄像机的数据交换。
更值得一提的是,DirectShow提供的是一种开放式的开发环境,我们可以根据自己的需要定制自己的组件。
笔者使用visual studio 2005 来开发了基于DirectShow的视频捕获软件,并用开发的软件对映美精相机进行了测试。
本软件不但可以实现对相机的视频捕获,而且还可以抓取图像帧。
软件运行时自动搜索所连接的相机,预览后可以对相机参数进行设置。
下面是软件的主界面。
预览视频后可以对视频格式和图像参数进行设置。
开始预览时,捕获的视频是黑白的,我们将颜色空间设置为UYVY即可捕获彩色视频。
下面是捕获的一帧图像,图像质量虽然没有映美精自带的软件效果好,但已经实现了所需各项基本功能,接下来的工作将会进一步提高软件性能。
另外我们还可以捕获视频,点击“捕获视频”按钮,输入要保持的文件名,注意要以.avi后缀结尾,点确定就开始捕获视频。
从我们开发的软件可以看到,映美精的相机能够很好的支持DirectShow的驱动,我们的软件对映美精相机的识别是如此的容易。
接下来我们将继续开发基于其它驱动的图像捕获软件,为最终实现在一个软件中识别各种相机而努力。
directshow教程(新整理)

Directshow教程0.11MSDN翻译系列作者:黄丁杰说明:如果有任何问题请联系din-je@。
是本人业余翻译的如果有错误请直接发到我邮箱我会立刻改正,directshow的其他文章我会在以后不断翻译出来。
如果觉得好请帮我作作宣传。
欢迎转载,但是禁止修改。
Directshow起步。
本章主要介绍diirectshow在编写程序时所需的基本概念。
在本章你可以总揽下directshow 技术。
你必须在总体上对本章的编程和媒体有所了解。
本章将介绍。
设置编译环境。
介绍directshow应用程序编程。
如何播放一个文件设置编译环境:你可以编译工程在命令行模式下或者在vs集成环境中头文件所有的directshow应用程序都使用下面的头文件。
Dshow。
H部分directshow接口需要附加的头文件。
这些文件会在接口的注意中给出。
所需的库文件directshow需要如下的库文件strmiidl。
Lib 该库包含CLSIDs和IIDs的接口。
所有的directshow都需要该库。
Quartz。
Lib 该库包含AMGetErrorText函数。
如果你没有调用该函数,该库没有用。
记住在你的编译环境中必须把directx SDK 的头文件库和连接库的目录作为vs优先搜索的路径。
这样可以保证编译的时候用的是最新版本的文件。
介绍directshow应用程序编程本章介绍编写一个directshow程序的基本技术和概念,读完本章你就可以写个你自己的directshow的应用程序了。
滤镜和图像滤镜directshow是由被称作滤镜的东西构成的。
滤镜是一个软件包用来执行对多媒体流的一些操作。
比如directshow的滤镜可以读出一个文件从视频捕捉设备获取视频流解码各种各样的多媒体格式,比如MPEG-1S视频。
传输视频和音频到屏幕和声卡。
滤镜几乎完成视频播放所需要的从输入到输出的所有功能。
比如一个MPEG-1的滤镜。
它可以输入MPEG码流然后输出图像帧用于后续显示在directshow程序中只要执行把滤镜连接在一起就可以了。
directshow中利用samplegrabber捕获摄像头每一帧图像并转为bmp文件

directshow中利用samplegrabber捕获摄像头每一帧图像并转为bmp文件关于怎样枚举设备、建立Filter Graph等问题,我就不多说了,说也说不清楚,因为我也是才接触DirectShow。
网上这类资料还是很多,百度知道的比我多多了。
这里主要介绍一下自己在学习了StillCap例子之后,实现利用SampleGrabber捕获摄像头每一帧图像的过程。
过程中遇到的印象深刻的问题会在下一篇博文中介绍。
废话不说了,开门见山吧。
大致思路与代码如下:1、从ISampleGrabber实例化一个sample grabber,充当一个Transform Filter[cpp] viewplaincopy?CComPtr<ISampleGrabber>m_pSampleGrabber;2、设置相关参数,将Grabber注册并且加入到m_pGB这个Filter Graph中[cpp] viewplaincopy?//////////////////////////////////////////////////////////////////////////Add SampleGrabber // create a sample grabber // hr =m_pSampleGrabber.CoCreateInstance( CLSID_SampleGrabber ); if( !m_pSampleGrabber ) { MessageBox(NULL, L"Could not create SampleGrabber (is qedit.dll registered?)", L"", MB_OK); return hr; } CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pSampleGrabber ); // force it to connect to video, 24 bit // CMediaType VideoType;VideoType.SetType( &MEDIATYPE_Video ); VideoType.SetSubtype( &MEDIASUBTYPE_RGB24 ); VideoType.SetFormatType(&FORMAT_VideoInfo); hr = m_pSampleGrabber->SetMediaType( &VideoType ); // shouldn't fail if (FAILED(hr)) { MessageBox(NULL, L"不能初始化SampleGrabber媒体类型。
(MatLab、Labview)通过Directshow接口访问相机参数设置方法

DirectShow接口访问相机参数设置方法本文档适用于所有适用directshow接口访问相机的程序,例如MATLAB 和Labview的ImaqDx接口、Halcon的Directshow接口等。
MATLAB中,可以通过如下界面设置相机参数:Labview的NIMAX中可以通过如下界面设置相机参数:下面以Labview为例,介绍Labview中如何通过ImaqDx接口访问迈德威视工业相机。
目前,我们提供三种方式,在Labview中访问我们的相机:1.GigeVision接口。
仅我司GigE相机支持该方式访问。
2.直接基于SDK的DLL文件调用的方式。
该方式支持我们所有型号相机。
例程在安装目录的DEMO/LABVIEW/USEDLL文件夹中。
3.通过ImaqDx使用Directshow接口访问相机。
该方式支持我们所有型号相机。
Directshow接口是windows系统上的音视频标准接口,定义了一些预先约定好的协议,但是由于协议定义时间比较早,也没有为工业摄像头考虑参数接口,所以接口的参数配置上,没有像使用我们的SDK那样灵活。
我们针对此问题,做了一些特殊处理,扩展了Dircetshow接口中Camera Atrributes的“White Balance”属性,目前可以该方式进行如下操作:1.设置相机工作模式(连续采集、软触发、硬触发)方法:在Camera Atrributes中,设置“White Balance”属性的Value值●为0,则相机进入连续工作模式;●设置为1,则相机进入软触发工作模式;●设置为2则相机进入硬触发工作模式。
2.执行一次软触发方法:在Camera Atrributes中,设置“White Balance”属性的Value 值为3,则相机进行一次软触发,如果要多次软触发,则重复设置“White Balance”属性的Value值为3即可,每设置一次,进行一次软触发。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
DirectShow:图片的抓取 zz在播放媒体文件的过程中,有一个很有用的功能,就是在当前播放的位置抓取图,实现这种图片抓取功能的方法很多,我们这里只介绍常用的两种。
第1种方法最简单,它使用1BasicVideo::GetCurrentImage接口方法,代码如下。
boolSnapshotBitmap(IBasicVideo*pBa8icVideo,ê? constchar*OutFile) if (pBasicVldeo){long bitmapSize=0;ê?//首先获得图像大小if(SUCCEEDED(pEasicVidee->GetcurrentImage(&bitmapSize,ê?0))){bool pass=false;ê?//分¤?配?图ª?像?帧?内¨²存ä?unsignedchar*buffer=newunsignedchar[bitmapSize];//获?取¨?图ª?像?帧?数ºy据Yif(SUCCEEDED(pBasicVideo->GetCurrentImage(&bitmapSize,(long*)buffer)) ){BITMAPFILEHEADER hdr;ê?LPBITMAPINFOHEADER ipbi;ê?ipbi=(LPBITMAPINFOHEADER)buffer;ê?int nColors=1<<ipbi->biBitCount;ê?if(nColors>256)//always is”¡ÀBM”¡Àhdr.bfType =((WORD)(‘?M’¡¥<<8)|’¡¥B’¡¥);ê?hdr.ê?bfSize =bitmapSize+sizeof(hdr);ê?hdr.ê?bfReservedl =0;hdr.ê?bfReserved2 =0;ê?hdr.ê?bfOffBits =(DWORD)(sizeof(BITMAPFILEHEADER)+lpbi->biSize+nColors*sizeof(RGBQUAD));CFilebitmapFile(outFile,ê?CFile:êo:êomodeReadWrite |CFile:êo:êomodeCreate | CFile:êo:êotypeBinary);ê?//写¡ä入¨?位?图ª?文?件t头ª¡¤bitmapFile.ê?Write{&hdr,ê?sizeof【?BITMApFILEHEADER));//写¡ä入¨?图ª?像?帧?数ºy据Y(包㨹括¤¡§BITMAPINFOHEADER信?息¡é)bitmapFile.ê?Write(buffer,ê?bitmapSize);ê?bitmapFile.ê?Close();ê?pas8=true;}delete[]burfer;ê?return Pass;}returnfalse ;值得注意的是,IBasieVideo接口应该从Filter Graph Manager上获得,但真正实现在Renderer Filter 上。
如果我们使用的是传统的Video Renderer,那么使用GetCurrentlmage 抓图将是不可靠的。
因为如果Video Renderer使用了DirectDraw加速,这个函数调用会失败;而且调用这个函数,Video Renderer必须处于暂停状态。
但如果我们使用的是VMR,则没有上述这些限制。
第2种方法比较复杂.它使用Sample Grabber Filter。
它其实是一个Trans-In-Place Filter,在SDK安装目录下的Samples\C++\DirectShow’Filters\Grabber提供了源代码。
实际上,Sample Grabber可以抓取任何类型的Sample。
但在这里,我们只介绍使用它抓取视频帧的方法。
步骤如下:(1)创建Sample Grabber,并将之加入到Filter Graph中。
//Create the Sample GrabberIBaseFilter*pGrabberF=NULL;hr=CoCreateInstanee(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,IID IBaseFilter, (void**)&pGrabberF);if(FAILED(hr)){//Return an error}hr=pGraph->AddFilter(pGrabberF,L"Sample Grabber");if(FAILED(hr){//Return an error}ISampleGrabber*pGrabber=NULL;pGrabberF->QueryInterface(IID_ISampleGrabber,(void**)&pGrabber);(2)给SampleGrabber设置Pin上连接用的媒体类型。
如果我们想抓取24位的RGB图片,如下设置媒体类型:AM_MEDIA_TYPE mt;ZeroMemorY(&mt,sizeof(AM_MEDIA_TYPE));mt.malOrtype=MEDIATYPE Video;mt.subtype=ME:DIASUBTYPE RGB24;hr=pGrabber->SetMediaType(&mt);也可以根据当前显示器的配置来设置Sample Grabber接受的RGB类型,代码如下://Find the current bit depthHDC hdc=GetDC(NULL);int iBitDepth=GetDeviceCaps(hdc, BITSPIXEL);ReleaseDC(NULL,hdc);//Set the media typemt.maJortype=MEDIATYPE Video;switch(iBitDepth){Case 8:mt.subtype=MEDIASUBTYPE RGB8 ;break;case 1 6:mt.subtype=MEDIASUBTYPE_RGB555;break;case 24:mt.subtype=MEDIASUBTYPE_RGB24;break;case 32:mt.subtype=MEDIASUBTYPE_RGB32;break;default:return E_FAIL;}hr=pGrabber->SetMediaType(&mt);(3)完成FilterGraph的构建。
因为Sample Grabber上已经设置了一个媒体类型,则其他Filter必须以这种媒才能与Sample Grabber相连。
我们可以使用DimctShow的“智能连接”机制,来个Fitler Graph的创建过程,代码如下。
IBaseFiiter*pSrc;hr=pGraph->AddSourceFilter(wszFileName, L"Source", &pSrc};if(FAILED(hr)){//Return an error code}hr=ConnectFiiters(pGraph,pSrc,pGrabberF);其中,ConnectFilters是我们在5.3节中介绍的自定义函数。
如果我们只是想抓图(不需要对视频预览),则Sample Grabber后面可以连接一个Null Renderer Filter(它的CLSID为CLSID NullRenderer)。
如果要Filter Graph中的数据流以最快的速度传送,则Filter Graph不要使用参考时钟(调用IMediaFitter::SetSyncSource,参数为NULL)。
(4)运行FilterGraph。
Sample Grabber可以有如下两种工作模式:缓冲模式将输入的Sample进行缓存后,再往下传送。
回调模式当有输入的Sample时,调用应用程序设置进来的回调函数。
因为回调模式会影响整个Filter Graph的效率,并且容易引起死锁,所以我们推荐使用缓冲模式。
另外,我们可以设置 ISampleGrabber::SetOneShot,使得Sample Grabber获取一个Sample以后,就让FilterGraph停止,代码如下://Set one-shot mode and buffering.hr=pGrabber->SetOneShot(TRUE);hr=pGrabber->SetBufferSamples(TRUE);pControl->Run();//Run the graph.pEvent->WaitForCompletion(INFINITE,&evCode),//Wait till it’s done.(5)获取抓到的Sample数据。
缓冲模式下,我们可以调用ISampleGrabber::GetCurrentBuffer来获取Sample数据,代码如下://Find the required buffer sizelong cbBuffer=0;hr=pGrabber->GetCurrentBuffer(&cbBuffer,NULL);char*pBuffer=new char[cbBuffer];if(!pBuffer)//Out of memory.Return an error code}hr=pGrabber->GetCurrentBuffer(&cbBuffer,(long*)pBuffer);我们也可以将获取的数据使用GDI函数显示出来,代码如下:AM_MEDIA_TYPE mt;hr=pGrabber->GetConnectedMediaType(&rot);if(FAILED(hr)){//Return err05 code}//Examine the format blockVIDEOINFOHEADER*pVih;if((mt.formattype==FORMAT_VideoInfo)&&(mt.cbFormat>=sizeof(VIDEOINFOHEADER))&&(mt.pbFormat!=NULL))pVih={vIDEOINFOHEADER*)mt·pbFormat;}else{//Wrong format.Free the format block and return an error‘FreeMedlaType(mt);return VFW_E_INVALIDMEDIATYPE;//youcan use the media type to access the BITMAPINFOHEAFRE information,//For example,the following code draws the bitmap using GDISetDIBitsToDevice(hdc,0,0,pVih->bmiHeader.biWidth,pVih->bmiHeader.biHeight,O, O,0,pVih->bmiHeader.biHeight,pBuffer,(BITMAPINFO*)&pVih->bmiHeader,DIB RGB COLORS),//Free the format block when you are done:FreeMediaType(mt);从摄像头流中捕捉一张图片zzAtomictry(天影))关键字:视频捕获拍照 ISampleGrabber函数说明HRESULT StartDisplay(HWND hwnd);HRESULT BuilderGraph()HRESULT SnapStill()BOOL SetFormat(ICaptureGraphBuilder2* pBuilder, IBaseFilter* pCap, long lWidth, long lHeight, unsigned short iColorBit, __int64 iRate )HRESULT StartDisplay(HWND hwnd){HRESULT hr = S_OK;hr = BuilderGraph();if(hr==S_FALSE) return S_FALSE;//Create Display WindowspSendWindow->put_Owner((OAHWND)hwnd);pSendWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);pSendWindow->SetWindowPosition(0,0,250,250); pSendWindow->put_Visible(OATRUE);hr = pGrabber->SetOneShot(FALSE);hr = pGrabber->SetBufferSamples(TRUE);//Begin displayhr=pSendControl->Run();Sleep(500);SnapStill();return S_OK;}HRESULT BuilderGraph(){HRESULT hr=S_OK;pSendGraph=NULL;pCaputerFilter=NULL;pCaputerBuilder=NULL;pSendWindow=NULL;pSendControl=NULL;pSendEvent=NULL;pGrabberSample = NULL;//1.Builder Filter Graphhr=CoCreateInstance((REFCLSID)CLSID_FilterGraph,NULL, CLSCTX_INPROC_SERVER,(REFIID)IID_IGraphBuilder,(void**)&pSendGraph);if(FAILED(hr)) return S_FALSE;//2.Builder Caputer Filterhr=CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2,(void**)&pCaputerBuilder);if(FAILED(hr)) return S_FALSE;//3.Builder SampleGrabber Filterhr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pGrabberSample);if(FAILED(hr)) return S_FALSE;hr=pCaputerBuilder->SetFiltergraph(pSendGraph);if(FAILED(hr))return S_FALSE;//Find Caputer Filterhr=FindCaputerDevice();if(FAILED(hr)) {SAFE_RELEASE(pCaputerBuilder);SAFE_RELEASE(pSendGraph);return S_FALSE;}hr =pSendGraph->AddFilter(pNetSend,NULL);hr =pSendGraph->AddFilter(pCaputerFilter,L"Caputer Filter");hr =pSendGraph->AddFilter(pCompressor,L"Compressor Filter");hr = pSendGraph->AddFilter(pGrabberSample, L"Sample Grabber");hr=pSendGraph->QueryInterface(IID_IMediaControl,(void**)&pSendControl );if(FAILED(hr)) return S_FALSE;hr=pSendGraph->QueryInterface(IID_IVideoWindow,(void**)&pSendWindow); if(FAILED(hr)) return S_FALSE;hr=pSendGraph->QueryInterface(IID_IMediaEvent,(void**)&pSendEvent);if(FAILED(hr)) return S_FALSE;hr=pGrabberSample->QueryInterface(IID_ISampleGrabber,(void**)&pGrabber);if(FAILED(hr)) return S_FALSE;// 修改分辨率SetFormat(pCaputerBuilder, pCaputerFilter, 640, 480, 24, 30);//Display local videohr=pCaputerBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,NULL,pCaputerF ilter,pGrabberSample,NULL);if(FAILED(hr)) return S_FALSE;return S_OK;}HRESULT SnapStill(){HRESULT hr;long cbBuffer = 0;hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);if(FAILED(hr)) return E_FAIL;char *pBuffer = new char[cbBuffer];if (!pBuffer) {// Deal Out of memory. Return an error code.}hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);if(FAILED(hr)) return E_FAIL;//生成BitmapAM_MEDIA_TYPE mt;hr = pGrabber->GetConnectedMediaType(&mt);if (FAILED(hr)) return E_FAIL;VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)mt.pbFormat;if(pVideoHeader==NULL) return E_FAIL;BITMAPINFO BitmapInfo;ZeroMemory(&BitmapInfo, sizeof(BitmapInfo));CopyMemory(&BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader),sizeof(BITMAPINFOHEADER));HBITMAP hBitmap;hBitmap = ::CreateDIBitmap(::GetDC(NULL), &(pVideoHeader->bmiHeader), CBM_INIT, pBuffer, &BitmapInfo, DIB_RGB_COLORS);if(hBitmap==NULL) return E_FAIL;CStringstrSaveFileName="";CFileDialogfiledlg(FALSE,_T("bmp"),_T(""),OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_ T("BMP(*.bmp)"));if(filedlg.DoModal()==IDOK){strSaveFileName=filedlg.GetPathName();SaveBitmapToFile(hBitmap,strSaveFileName.GetBuffer(0));}return hr;BOOL SetFormat(ICaptureGraphBuilder2* pBuilder, IBaseFilter* pCap, long lWidth, long lHeight, unsigned short iColorBit, __int64 iRate ){VIDEOINFOHEADER* phead;IAMStreamConfig* iconfig;HRESULT hr;hr = pBuilder ->FindInterface( &PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,pCap, IID_IAMStreamConfig, (void **)&iconfig );if ( hr != NOERROR ){hr = pBuilder ->FindInterface( &PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, pCap,IID_IAMStreamConfig, (void **)&iconfig);}if ( FAILED( hr ) )return FALSE;AM_MEDIA_TYPE* pmt;if ( iconfig ->GetFormat( &pmt ) != S_OK )return FALSE;if ( pmt ->formattype == FORMAT_VideoInfo){phead = ( VIDEOINFOHEADER* )pmt ->pbFormat;phead ->bmiHeader.biBitCount = iColorBit;phead ->bmiHeader.biWidth = lWidth;phead ->bmiHeader.biHeight = lHeight;phead ->bmiHeader.biSizeImage = lWidth * lHeight * iColorBit / 8; phead ->AvgTimePerFrame = iRate;if ( ( hr = iconfig ->SetFormat( pmt ) ) != S_OK )return FALSE;}iconfig -> Release();iconfig = NULL;FreeMediaType( *pmt );return TRUE;}从摄像头流中捕捉一张图片zz视频问题,从摄像头流中捕捉一张图片。