DShow中实现抓图的几种方法.doc_第1页
DShow中实现抓图的几种方法.doc_第2页
DShow中实现抓图的几种方法.doc_第3页
DShow中实现抓图的几种方法.doc_第4页
DShow中实现抓图的几种方法.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

DShow中实现抓图的几种方法1加入Sample Grabber Filter当我们加入Sample Grabber Filter的时候,我们可以直接调用其接口(interface)ISampleGrabber。该接口可以获取经过该Filter的单独的Media Samples。详情请参见DXSDK。 1.1 派生出自己的Sample Grabber从ISampleGrabberCB中派生出自己的类,然后实现其虚函数,详情请参见SDK中的示例程序(DXSDK ROOTSamplesC+DirectShowEditingGrabBitmaps)。 1.2 直接调用Sample Grabber Filter的接口如果我们在播放的过程中动态的加入Filter的话,操作和效率都不乐观。所以我采用下面的方法: 该方法传递的是时间,不是在播放的时候动态加入Filter然后截图,而是另外打开源文件进行操作。 A)。申明以下接口: A)。申明以下接口: #001 IGraphBuilder *pGraph = NULL; /for graph builder #002 IMediaControl *pControl = NULL; /media control #003 IMediaSeeking *pSeeking = NULL; /media seeking #004 IMediaEventEx *pEvent = NULL; /media envent #005 IBaseFilter *pNullFilter =NULL;/for holding the Sample grabber FilterB)。初始化接口: #001 JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, #002 IID_IGraphBuilder, (void *)&pGraph); #003 #004 JIF(CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC, #005 IID_IBaseFilter, (void *)&pNullFilter); #006 JIF(pGraph-QueryInterface(IID_IMediaControl,(void *)&pControl); #007 JIF(pGraph-QueryInterface(IID_IMediaSeeking, (void *)&pSeeking); #008 JIF(pGraph-QueryInterface(IID_IMediaEvent, (void *)&pEvent); C)。创建Sample Grabber #001 / Create the Sample Grabber. #002 IBaseFilter *pGrabberF = NULL; #003 JIF(CoCreateInstance(CLSID_SampleGrabber,NULL, CLSCTX_INPROC_SERVER, #004 IID_IBaseFilter, (void*)&pGrabberF); #005 #006 JIF(pGraph-AddFilter(pGrabberF, LSample Grabber); #007 JIF(pGraph-AddFilter(pNullFilter, LNull Render Filter); #008 #009 ISampleGrabber *pGrabber; #010 JIF(pGrabberF-QueryInterface(IID_ISampleGrabber, (void*)&pGrabber); 设置Sample Grabber的媒体格式:调用SetMediaType,该函数接受一个AM_MEDIA_TYPE的结构,主要是设置该结构中的majortype,和subtype域。 D)。添加Source Filter: #001 IBaseFilter *pSrc; #002 JIF(pGraph-AddSourceFilter(T2W(m_szFile), LSource, &pSrc); E)。连接Grabber 和 NullRender两个Filter: #001 IPin *pOutPin; #002 hr = GetPin(pGrabberF, PINDIR_OUTPUT, &pOutPin); #003 #004 IPin *pInPin; #005 hr = GetPin(pNullFilter, PINDIR_INPUT, &pInPin); #006 #007 pGraph-Connect(pOutPin, pInPin); F)。取得当前所连接媒体的类型 #001 AM_MEDIA_TYPE mt; #002 hr = pGrabber-GetConnectedMediaType(&mt); #003 / Examine the format block. #004 VIDEOINFOHEADER *pVih; #005 if (mt.formattype = FORMAT_VideoInfo) & #006 (mt.cbFormat = sizeof(VIDEOINFOHEADER) & #007 (mt.pbFormat != NULL) ) #008 #009 pVih = (VIDEOINFOHEADER*)mt.pbFormat; #010 #011 else #012 #013 / Wrong format. Free the format block and return an error. #014 FreeMediaType(mt); #015 return VFW_E_INVALIDMEDIATYPE; #016 #017 #018 / Do buffer the samples as they pass through #019 / #020 hr = pGrabber-SetBufferSamples(TRUE); #021 #022 / Only grab one at a time, stop stream after #023 / grabbing one sample #024 / #025 hr = pGrabber-SetOneShot( TRUE ); G)。Seeking文件,使其到达要截图的时间帧 #001 pSeeking-SetPositions(pCurrentPos, #002 AM_SEEKING_AbsolutePositioning, #003 NULL, AM_SEEKING_NoPositioning ); #004 #005 pControl-Run(); #006 #007 long EvCode = 0; #008 #009 hr = pEvent-WaitForCompletion( INFINITE, &EvCode ); H)。取得当前的buffer数据 #001 / Find the required buffer size. #002 long cbBuffer = 0; #003 hr = pGrabber-GetCurrentBuffer(&cbBuffer, NULL); #004 LONGLONG currentPos; #005 pSeeking-GetCurrentPosition(¤tPos); #006 BYTE *pBuffer = new BYTEcbBuffer; #007 if (!pBuffer) #008 #009 / Out of memory. Return an error code. #010 Msg(Out of Memory); #011 #012 hr = pGrabber-GetCurrentBuffer(&cbBuffer, (long*)pBuffer); I)。写入文件 #001 / Create a file to hold the bitmap #002 HANDLE hf = CreateFile(szFilename, GENERIC_WRITE, FILE_SHARE_READ, #003 NULL, CREATE_ALWAYS, NULL, NULL ); #004 #005 if( hf = INVALID_HANDLE_VALUE ) #006 #007 / Failed to create file #008 return 0; #009 #010 #011 / Write out the file header #012 / #013 BITMAPFILEHEADER bfh; #014 memset( &bfh, 0, sizeof( bfh ) ); #015 bfh.bfType = MB; #016 bfh.bfSize = sizeof( bfh ) + cbBuffer + sizeof( BITMAPINFOHEADER ); #017 bfh.bfOffBits = sizeof(BITMAPINFOHEADER)+sizeof( BITMAPFILEHEADER ); #018 #019 DWORD Written = 0; #020 WriteFile( hf, &bfh, sizeof( bfh ), &Written, NULL ); #021 #022 / Write the bitmap format #023 / #024 BITMAPINFOHEADER bih; #025 memset( &bih, 0, sizeof( bih ) ); #026 bih.biSize = sizeof( bih ); #027 bih.biWidth = pVih-bmiHeader.biWidth; #028 bih.biHeight = pVih-bmiHeader.biHeight; #029 bih.biPlanes = pVih-bmiHeader.biPlanes; #030 bih.biBitCount = pVih-bmiHeader.biBitCount; #031 #032 Written = 0; #033 #034 WriteFile( hf, &bih, sizeof( bih ), &Written, NULL ); #035 #036 / Write the bitmap bits #037 / #038 Written = 0; #039 WriteFile( hf, pBuffer, cbBuffer, &Written, NULL ); #040 FreeMediaType(mt); #041 CloseHandle(hf); J)。释放资源 #001 pControl-Stop();#002 SAFE_RELEASE(pControl); #003 SAFE_RELEASE(pSeeking); #004 SAFE_RELEASE(pEvent); #005 SAFE_RELEASE(pSrc); #006 SAFE_RELEASE(pNullFilter); #007 SAFE_RELEASE(pGrabber); #008 SAFE_RELEASE(pGrabberF); #009 SAFE_RELEASE(pGraph); K)。其实我们可以不用NullRender,而是用IVideoWindow接口来实现。如果是那样的话,首先申明IVideoWindow *pVideo = NULL;将pVideo加入到Filter Graph中 #001 JIF(pGraph-QueryInterface(IID_IVideoWindow,(void*)&pVideo); #002 hr = pGraph-Render(pOutPin); #003 if (pVideo) #004 #005 hr = pVideo-put_AutoShow(OAFALSE); #006 通过IBasicVideo:GetCurrentImage接口对于该接口,Video Renderer和Video Mixing Renderer(VMR)有不同的实现。 A)。Video Renderer 如果该Renderer使用了DDraw加速的话,该调用会失败。在调用该接口的时候,必须首先暂停Renderer(可以通过IMediaControl:Pause()暂停,如果不能确信该操作是否成功,应该调用IMediaControl:GetState()判断状态)。 B)。Video Mixing Renderer 对于VMR,该方法都会成功(不管是否运用了DDraw加速,也不管是否是暂停状态),此时对于它所有的状态(running, stopped, or paused)都适用。 函数Grabber代码如下(调用该函数的时候应该先将媒体文件暂停,原因上面已经说了): #001 bool Grabber(IBasicVideo mBasicVideo, TCHAR *szFilename) #002 #003 if (mBasicVideo) #004 #005 long bitmapSize = 0; #006 if(SUCCEEDED(mBasicVideo-GetCurrentImage(&bitmapSize, 0) #007 #008 /if语句里面的操作时取得buffer的size。 #009 /当我们在布确定image buffer的大小的情况下,我们给 #010 /GetCurrentImage的第二个参数传递0或者NULL,取得buffer的 #011 /大小供以后使用。 #012 bool pass = false; #013 unsigned char * buffer = new unsigned charbitmapSize; #014 if(SUCCEEDED(mBasicVideo-GetCurrentImage(&bitmapSize,(long*)buffer) #015 #016 /此时已经用到刚才所取得的大小(分配空间) #017 BITMAPFILEHEADERhdr; /Bitmap的头信息 #018 LPBITMAPINFOHEADERlpbi; / Bitmap的文件信息(包括数据) #019 #020 lpbi = (LPBITMAPINFOHEADER)buffer; #021 #022 int nColors = 1 biBitCount; #023 if (nColors 256) #024 nColors = 0; #025 #026 hdr.bfType= (WORD) (M biSize #031 CFile bitmapFile(outFile, CFile:modeReadWrite | CFile:modeCreate | CFile:typeBinary); #032 bitmapFile.Write(&hdr, sizeof(BITMAPFILEHEADER); #033 bitmapFile.Write(buffer, bitmapSize); #034 bitmapFile.Close(); #035 pass = true; #036 #037 delete buffer; /数据用过之后记得要释放空间 #038 return true; #039 #040 #041 #042 return false; #043 IMediaDet接口IMediaDet接口可以取得媒体文件的信息。SDK里面的示例代码(没有写入文件): #001 long size; #002 /取得图像帧的大小,给GetBitmapBits的第三个参数传递0 or NULL #003 hr = pDet-GetBitmapBits(0, &size, 0, width, height); #004 if(SUCCEEDED(hr) #005 #006 char *pBuffer = new charsize; #007 if(!pBuffer) #008 #009 return E_OUTOFMEMORY; #010 #011 #012 try #013 #014 hr = pDet-GetbitmapsBits(0, 0, pBuffer, width, height); #015 #016 catch(.) #017 #018 delete pBuffer; #019 throw; #020 #021 #022 if(SUCCEEDED(hr) #023

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论