Click here to Skip to main content
15,867,851 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi,
I need a program which reads an image from a USB webcam every second (or even faster, if that's possible) and write it to harddisk as JPEG.

My only problem is, that my program is too slow. Getting the picture from the webcam needs about 3 seconds... (Render() and WaitForCompletion() are the slow functions)

Here is a part of the source code I use (in a loop):
C++
CComPtr< ISampleGrabber > pGrabber;
 CComPtr< IBaseFilter >    pSource;
 CComPtr< IGraphBuilder >  pGraph;
 CComPtr< IVideoWindow >   pVideoWindow;

 pGrabber.CoCreateInstance( CLSID_SampleGrabber );

 CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabberBase( pGrabber );

 GetDefaultCapDevice(&pSource);

 pGraph.CoCreateInstance( CLSID_FilterGraph );
 pGraph->AddFilter( pSource, L"Source" );
 pGraph->AddFilter( pGrabberBase, L"Grabber" );

 AM_MEDIA_TYPE am_media_type;
 ZeroMemory(&am_media_type, sizeof(am_media_type));
 am_media_type.bFixedSizeSamples = TRUE;
 am_media_type.lSampleSize = 1;
 am_media_type.majortype = MEDIATYPE_Video;
 am_media_type.subtype = MEDIASUBTYPE_RGB24;
 am_media_type.formattype = FORMAT_VideoInfo;

 pGrabber->SetMediaType( &am_media_type );

CComPtr< IPin > pSourcePin;
 CComPtr< IPin > pGrabPin;
 pSourcePin = GetOutPin( pSource, 0 );
 pGrabPin   = GetInPin( pGrabberBase, 0 );
 pGraph->Connect( pSourcePin, pGrabPin );
AM_MEDIA_TYPE mt;
 pGrabber->GetConnectedMediaType( &mt );

 VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
 CB.Width  = vih->bmiHeader.biWidth;
 CB.Height = vih->bmiHeader.biHeight;
 _FreeMediaType( mt );

 memset( &(cbInfo.bih), 0, sizeof( cbInfo.bih ) );
 cbInfo.bih.biSize = sizeof( cbInfo.bih );
 cbInfo.bih.biWidth = CB.Width;
 cbInfo.bih.biHeight = CB.Height;
 cbInfo.bih.biPlanes = 1;
 cbInfo.bih.biBitCount = 24;

 CComPtr <IPin> pGrabOutPin = GetOutPin( pGrabberBase, 0 );
 pGraph->Render( pGrabOutPin ); /*************** ~ 2 sec *******************/
 pGrabber->SetBufferSamples( FALSE );
 pGrabber->SetOneShot( TRUE );
 pGrabber->SetCallback( &CB, 1 );

 CComQIPtr< IMediaControl, &IID_IMediaControl > pControl( pGraph );
 pControl->Run( );

 CComQIPtr< IMediaEvent, &IID_IMediaEvent > pEvent( pGraph );
 long EvCode = 0;
 pEvent->WaitForCompletion( INFINITE, &EvCode ); /******************** ~ 1 s ***********************/

 CHAR *BitmapData = NULL;
 cbInfo.biSize = CalcBitmapInfoSize(cbInfo.bih);
 ULONG Size = cbInfo.biSize + cbInfo.lBufferSize;
 *BitmapSize = Size;
 if(Bitmap)
 {
     *Bitmap = (BITMAPINFO *) new BYTE[Size];
     if(*Bitmap)
     {
         (**Bitmap).bmiHeader = cbInfo.bih;
         BitmapData = (CHAR *)(*Bitmap) + cbInfo.biSize;
         memcpy(BitmapData, cbInfo.pBuffer, cbInfo.lBufferSize);
     }
 }



What do I need to do, if I want at least 1 webcam image per second?
I already tried setting SetOneShot() to false, but then the whole program doesn't work anymore...
And what does SetBufferSamples() do?

Thanks in advance for your help!
Posted
Updated 7-Nov-10 12:16pm
v2

 
Share this answer
 
I don't understand how this can help me with my problem with SampleGrabber...
All I ask is how I can grab multiple frames in a row with SampleGrabber. Setting the SetOneShot() to false and then what else do I have to do?
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900