I`m begining to DirectShow programing and I need help. I have this fuction:
void main(){
INICIALIZE();
while (true){
gb.GrabBitmap(Bitmap, BitmapSize)
Procesing(Bitmap);
}
}
I need to access to each frame capture for my hardware and procesing it with my software. But the capture is very slow. I try the next code but only capture the first frame and I don’t know how can I do
If I don't separete tha INICIALIZATE() function and I include this function in the "while" of the "main" the application work but very slow.
// Global Variables
CComPtr< ISampleGrabber > pGrabber;
CComPtr< IBaseFilter > pSource;
CComPtr< IGraphBuilder > pGraph;
HRESULT hr;
VIDEOINFOHEADER * vih;
AM_MEDIA_TYPE mt;
CMediaType GrabType;
CComPtr< IPin > pSourcePin;
CComPtr< IPin > pGrabPin;
CComPtr <IPin> pGrabOutPin;
CComPtr<IBaseFilter>pGrabberBase;
/**************************************************************************************/
//Inicializate the Sample Grabber, device and the grahp
void INICIALIZE(){
USES_CONVERSION;
// Create the sample grabber
pGrabber.CoCreateInstance( CLSID_SampleGrabber );
pGrabber.QueryInterface(&pGrabberBase);
// Get whatever capture device exists
GetDefaultCapDevice(&pSource);
// Tell the grabber to grab 24-bit video. Must do this
GrabType.SetType( &MEDIATYPE_Video );
GrabType.SetSubtype( &MEDIASUBTYPE_RGB24 );
hr = pGrabber->SetMediaType( &GrabType );
// Get the output pin and the input pin
pSourcePin = GetOutPin( pSource, 0 );
pGrabPin = GetInPin( pGrabberBase, 0 );
// Create the graph
//
pGraph.CoCreateInstance( CLSID_FilterGraph );
if( !pGraph ) { return 0; }
// Put them in the graph
//
pGraph->AddFilter( pSource, L"Source" );
pGraph->AddFilter( pGrabberBase, L"Grabber" );
// ... and connect them
//
hr = pGraph->Connect( pSourcePin, pGrabPin );
if( FAILED( hr ) ) { return 0; }
// Ask for the connection media type so we know its size
pGrabber->GetConnectedMediaType( &mt );
vih = (VIDEOINFOHEADER*) mt.pbFormat;
CB.Width = vih->bmiHeader.biWidth;
CB.Height = vih->bmiHeader.biHeight;
FreeMediaType( mt );
// Write the bitmap format
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;
// Render the grabber output pin (to a video renderer)
GrabOutPin = GetOutPin( pGrabberBase, 0 );
hr = pGraph->Render( pGrabOutPin );
// Don't buffer the samples as they pass through
pGrabber->SetBufferSamples( FALSE );
// Only grab one at a time, stop stream after
// grabbing one sample
pGrabber->SetOneShot( TRUE );
// Set the callback, so we can grab the one sample
pGrabber->SetCallback( &CB, 1 );
}
/***************************************************************************************************/
//I want execute this fuction and access to a frame different each time
int CGrabBitmap::GrabBitmap(PBITMAPINFO *Bitmap, ULONG *BitmapSize)
{
CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = pGraph;
if (pWindow) { hr = pWindow->put_AutoShow(OAFALSE); }
// activate the threads
CComQIPtr< IMediaControl, &IID_IMediaControl > pControl( pGraph );
hr = pControl->Run( );
// wait for the graph to settle
CComQIPtr< IMediaEvent, &IID_IMediaEvent > pEvent( pGraph );
long EvCode = 0;
hr = pEvent->WaitForCompletion( INFINITE, &EvCode );
// callback got the sample
CHAR *BitmapData = NULL;
cbInfo.biSize = CalcBitmapInfoSize(cbInfo.bih);
ULONG Size = cbInfo.biSize + cbInfo.lBufferSize;
*BitmapSize = Size;
if(Bitmap) // If we have a valid address from caller
{
*Bitmap = (BITMAPINFO *) new BYTE[Size];
if(*Bitmap)
{
(**Bitmap).bmiHeader = cbInfo.bih;
BitmapData = (CHAR *)(*Bitmap) + cbInfo.biSize;//DATOS DE LA IMAGEN
//for(int i=0;i<100000;i++) cbInfo.pBuffer
=0;
memcpy(BitmapData, cbInfo.pBuffer, cbInfo.lBufferSize);
}
}
return cbInfo.lBufferSize;
}