(1)创建Sample Grabber,并将之加入到Filter Graph中。 //Create the Sample Grabber IBaseFilter*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 depth HDC hdc=GetDC(NULL); int iBitDepth=GetDeviceCaps(hdc, BITSPIXEL); ReleaseDC(NULL,hdc); //Set the media type mt.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);
(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 size long 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 block VIDEOINFOHEADER*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 GDI SetDIBitsToDevice( 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);