PDA

View Full Version : MemBufferCollection and why last frame became first? BUG?



nikkadim
October 12, 2012, 15:52:04
I have pretty simple code that captured images in memory and than store as BMP-file.
But when I tried to capture electronic stopwatch I notice that always the last frame became first, could you please explain why?
PS: And I have the same with callback example.



int main(int argc, char* argv[])
{

std::clock_t start;
start = std::clock();
double duration;
double fps;



// Initialize the library.
DShowLib::InitLibrary();

Grabber grabber;
//grabber.setExternalTrigger( true);
DShowLib::Grabber::tVidCapDevListPtr pVidCapDevList = grabber.getAvailableVideoCaptureDevices();
if( pVidCapDevList == 0 || pVidCapDevList->empty() )
{
return -1; // No device available.
}

int choice = presentUserChoice( toStringArrayPtr( pVidCapDevList ) );
// Open the selected video capture device.
if( choice == -1 )
{
return -1;
}

grabber.openDev( pVidCapDevList->at( choice ) );
SetExposureAbsolute(&grabber, 0.05);

/*if( !setupDeviceFromFile( grabber ) )
{
return -1;
}*/


grabber.setExternalTrigger( false);
Grabber::tVidFmtListPtr pVidFmtList = grabber.getAvailableVideoFormats();

if( pVidFmtList == 0 ) // No video formats available?
{
std::cerr << "Error : " << grabber.getLastError().toString() << std::endl;
}
else
{
unsigned int counter = 0;
// List the available video formats.
for( Grabber::tVidFmtList::iterator it = pVidFmtList->begin();
it != pVidFmtList->end();
++it )
{
std::cout << "\t[" << counter++ << "] " << it->toString() << std::endl;
}
}

grabber.setVideoFormat(pVidFmtList->at( 22));
grabber.setFPS(52.0f);

grabber.setOverlayBitmapPathPosition( ePP_NONE );

// Set the image buffer format to eY800. eY800 means monochrome, 8 bits (1 byte) per pixel.
// Let the sink create a matching MemBufferCollection with 1 buffer.
tFrameHandlerSinkPtr pSink = FrameHandlerSink::create( eY800, 1 );

// We use snap mode.
pSink->setSnapMode( true );

// Set the sink.
grabber.setSinkType( pSink );

// Prepare the live mode, to get the output size if the sink.
if( !grabber.prepareLive( false ) )
{
std::cerr << "Could not render the VideoFormat into a eY800 sink.";
return -1;
}

// Retrieve the output type and dimension of the handler sink.
// The dimension of the sink could be different from the VideoFormat, when
// you use filters.
FrameTypeInfo info;
pSink->getOutputFrameType( info );

BYTE* pBuf[FRAMES_TO_CAPTURE];
// Allocate FRAMES_TO_CAPTURE image buffers of the above calculate buffer size.
for( int i = 0; i < FRAMES_TO_CAPTURE; ++i )
{
pBuf[i] = new BYTE[info.buffersize];
}

// Create a new MemBuffer collection that uses our own image buffers.
tMemBufferCollectionPtr pCollection = MemBufferCollection::create( info, FRAMES_TO_CAPTURE, pBuf );
if( pCollection == 0 || !pSink->setMemBufferCollection( pCollection ) )
{
std::cerr << "Could not set the new MemBufferCollection, because types do not match.";
return -1;
}

// Start live mode for fast snapping. The live video will not be displayed,
// because false is passed to startLive().
// SetExposureAbsolute(&grabber, 0.05);
//SetGainAbsolute(&grabber, 50 );
start = std::clock();
grabber.startLive( false );


// Snap images. The images are copied to the MemBufferCollection the
// application created above.
pSink->snapImages( FRAMES_TO_CAPTURE );
fps = grabber.getFPS();

// Stop the live video.
grabber.stopLive();
duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;
// Close the device.
grabber.closeDev();

// Save the five captured images in the MemBuffer collection to separate files.
pCollection->save( "file*.bmp" );

// Free the buffers in the MemBuffer collection.
for( int j = 0; j < FRAMES_TO_CAPTURE; ++j )
{
delete pBuf[j];
}
printf("Duration: myFPS=%f apiFPS=%f",FRAMES_TO_CAPTURE/duration, fps);
return 0;
}


Captured images from this example available here (http://nikkadim.com/MembufferCollection_bmp.zip) ~7 MB

Stefan Geissler
October 15, 2012, 11:45:47
Hi,

I think, this is an old inherited issue, because in old VB6 times, the index of an array started at 1, not a 0.

nikkadim
October 15, 2012, 20:45:08
Hi,

I think, this is an old inherited issue, because in old VB6 times, the index of an array started at 1, not a 0.

Ok, could you advice a workaround? Or only in new C++ SDK version?

Stefan Geissler
October 16, 2012, 09:52:18
Hi,

the image buffers have a timestamp. You may find the oldest image buffer, which is the first one filled. This is shown in this C# sample:
http://www.imagingcontrol.com/en_US/library/dotnet/iterating-an-image-sequence/

It is a little bit similar in C++. You use the getSampleDesc() method on the Membuffers:
http://www.imagingcontrol.com/en_US/support/documentation/class/meth_descIFrame_getSampleDesc.htm