//----------------------------------------------------------------------------- int main( int argc, char* argv[] ) //----------------------------------------------------------------------------- { DeviceManager devMgr; cout << "This sample is meant for mvBlueLYNX-M7 devices only. Other devices might be installed" << endl << "but won't be recognized by the application." << endl << endl; int exposureTime_us = 20000; int frameRate_Hz = 5; int width = -1; int height = -1; int interPacketDelay = 25; // scan command line if( argc > 1 ) { for( int i = 1; i < argc; i++ ) { string param( argv[i] ), key, value; string::size_type keyEnd = param.find_first_of( "=" ); if( ( keyEnd == string::npos ) || ( keyEnd == param.length() - 1 ) ) { cout << "Invalid command line parameter: '" << param << "' (ignored)." << endl; } else { key = param.substr( 0, keyEnd ); value = param.substr( keyEnd + 1 ); if( ( key == "exposureTime" ) || ( key == "et" ) ) { exposureTime_us = static_cast<int>( atoi( value.c_str() ) ); } else if( ( key == "frameRate" ) || ( key == "fr" ) ) { frameRate_Hz = static_cast<int>( atoi( value.c_str() ) ); } else if( ( key == "width" ) || ( key == "w" ) ) { width = static_cast<int>( atoi( value.c_str() ) ); } else if( ( key == "height" ) || ( key == "h" ) ) { height = static_cast<int>( atoi( value.c_str() ) ); } else if( key == "scpd" ) { interPacketDelay = static_cast<int>( atoi( value.c_str() ) ); } else { cout << "Invalid command line parameter: '" << param << "' (ignored)." << endl; } } } } else { cout << "No command line parameters specified. Available parameters:" << endl << " 'frameRate' or 'fr' to specify the frame rate(frames per second per sensor head) of the resulting data stream" << endl << " 'exposureTime' or 'et' to specifiy the exposure time per frame in us" << endl << " 'width' or 'w' to specifiy the width of the AOI" << endl << " 'height' or 'h' to specifiy the height of the AOI" << endl << endl << "USAGE EXAMPLE:" << endl << " SynchronousCaptureMultipleInputs et=5000 frameRate=5" << endl << endl; } Device* pDev = getDeviceFromUserInput( devMgr, isDeviceSupportedBySample ); if( !pDev ) { cout << "Unable to continue!"; cout << "Press [ENTER] to end the application" << endl; cin.get(); return 0; } try { cout << "Please note, that this sample (depending on the selected frame rate and resolution) might require a lot" << endl << "of network bandwidth, thus to achieve optimal results, it's crucial to have" << endl << " - a good, reliable network controller (we recommed the Intel PRO/1000 series)" << endl << " - the latest driver for the network controller installed" << endl << " - jumbo frames enabled and the receive and transmit buffer for the network controller set to max. values" << endl << " - the InterfaceMTU on the mvBlueLYNX-M7 set to its maximum value" << endl << endl << "In case of 'rrFrameIncomplete' errors the reason is most certainly to be found in one of" << "the requirments listed above not being met." << endl; cout << "Will try to synchronize sensor heads(" << frameRate_Hz << " fps per head with " << exposureTime_us << "us exposure time per frame) now" << endl << "During this operation the device will be initialised. This might take some time..." << endl; Connector connector( pDev ); CameraSettingsBlueCOUGAR cs( pDev ); try { if( width != -1 ) { cs.aoiWidth.write( width ); } if( height != -1 ) { cs.aoiHeight.write( height ); } } catch( const ImpactAcquireException& e ) { cout << "Failed to set up AOI: " << e.getErrorString() << "(" << e.getErrorCodeAsString() << ")" << endl; } const int SENSOR_HEAD_COUNT = connector.videoChannel.read( plMaxValue ) + 1; setupHRTC( pDev, frameRate_Hz, exposureTime_us, SENSOR_HEAD_COUNT ); // initialise display windows // IMPORTANT: It's NOT save to create multiple display windows in multiple threads!!! ThreadParameter threadParam( pDev, SENSOR_HEAD_COUNT ); DeviceComponentLocator locator( pDev, dltSystemSettings ); PropertyI64 gevStreamChannelSelector; locator.bindComponent( gevStreamChannelSelector, "GevStreamChannelSelector" ); PropertyI64 gevSCPD; locator.bindComponent( gevSCPD, "GevSCPD" ); for( int i = 0; i < SENSOR_HEAD_COUNT; i++ ) { gevStreamChannelSelector.write( i ); gevSCPD.write( interPacketDelay ); MyWindow* p = createWindow( cs.aoiWidth.read(), cs.aoiHeight.read() ); p->show(); p->callback( windowCallback ); threadParam.displayData.push_back( new DisplayInfo( p ) ); } // start the execution of the 'live' thread. cout << "Close any of the display windows to end the application" << endl; liveLoop( &threadParam ); vector<DisplayInfo*>::size_type displayCount = threadParam.displayData.size(); for( vector<DisplayInfo*>::size_type i = 0; i < displayCount; i++ ) { delete threadParam.displayData[i]->pDisp; delete threadParam.displayData[i]; threadParam.displayData[i] = 0; } } catch( const ImpactAcquireException& e ) { // this e.g. might happen if the same device is already opened in another process... cout << "An error occurred while configuring device " << pDev->serial.read() << "(error code: " << e.getErrorCodeAsString() << "). Press [ENTER] to end the application..." << endl; cin.get(); } return 0; }
//----------------------------------------------------------------------------- unsigned int liveLoop( Device* pDev, bool boStoreFrames, const string& settingName, int iWidth, int iHeight, bool boSingleShotMode ) //----------------------------------------------------------------------------- { cout << " == " << __FUNCTION__ << " - establish access to the statistic properties...." << endl; // establish access to the statistic properties Statistics statistics( pDev ); cout << " == " << __FUNCTION__ << " - create an interface to the device found...." << endl; // create an interface to the device found FunctionInterface fi( pDev ); if( !settingName.empty() ) { cout << "Trying to load setting " << settingName << "..." << endl; int result = fi.loadSetting( settingName ); if( result != DMR_NO_ERROR ) { cout << "loadSetting( \"" << settingName << "\" ); call failed: " << ImpactAcquireException::getErrorCodeAsString( result ) << endl; } } // depending on the device and its sensor, we set an appropriate output format for displaying mvIMPACT::acquire::ImageDestination id( pDev ); if( !std::string( "mvBlueFOX" ).compare( pDev->family.readS() ) ) { mvIMPACT::acquire::InfoBlueFOX ibf( pDev ); if( !std::string( "BayerMosaic" ).compare( ibf.sensorColorMode.readS() ) ) { id.pixelFormat.writeS( "BGR888Packed" ); } } else if( !std::string( "mvBlueCOUGAR" ).compare( pDev->family.readS() ) ) { mvIMPACT::acquire::GenICam::ImageFormatControl ifc( pDev ); if( s_boGreySensor ) { ifc.pixelFormat.writeS( "Mono8" ); } else { GenICamDeviceSetColorPixelFormat( pDev ); id.pixelFormat.writeS( "BGR888Packed" ); } } else if( !std::string( "mvBlueLYNX" ).compare( pDev->family.readS() ) ) { mvIMPACT::acquire::GenICam::ImageFormatControl ifc( pDev ); if( s_boGreySensor ) { ifc.pixelFormat.writeS( "Mono8" ); } else { GenICamDeviceSetColorPixelFormat( pDev ); id.pixelFormat.writeS( "BGR888Packed" ); } } // Pre-fill the capture queue with ALL buffers currently available. In case the acquisition engine is operated // manually, buffers can only be queued when they have been queued before the acquisition engine is started as well. // Even though there can be more than 1, for this sample we will work with the default capture queue int requestResult = DMR_NO_ERROR; int requestCount = 0; if( boSingleShotMode ) { fi.imageRequestSingle(); ++requestCount; } else { while( ( requestResult = fi.imageRequestSingle() ) == DMR_NO_ERROR ) { ++requestCount; } } if( requestResult != DEV_NO_FREE_REQUEST_AVAILABLE ) { cout << "Last result: " << requestResult << "(" << ImpactAcquireException::getErrorCodeAsString( requestResult ) << "), "; } cout << requestCount << " buffers requested"; SystemSettings ss( pDev ); if( ss.requestCount.hasMaxValue() ) { cout << ", max request count: " << ss.requestCount.getMaxValue(); } cout << endl; cout << "Press <<ENTER>> to end the application!!" << endl; MyWindow* pWindow = createWindow( iWidth, iHeight ); pWindow->show(); pWindow->callback( windowCallback ); manuallyStartAcquisitionIfNeeded( pDev, fi ); // run thread loop const Request* pRequest = 0; const unsigned int timeout_ms = 8000; // USB 1.1 on an embedded system needs a large timeout for the first image int requestNr = -1; bool boLoopRunning = true; unsigned int cnt = 0; while( boLoopRunning ) { // wait for results from the default capture queue requestNr = fi.imageRequestWaitFor( timeout_ms ); if( fi.isRequestNrValid( requestNr ) ) { pRequest = fi.getRequest( requestNr ); if( pRequest->isOK() ) { ++cnt; // here we can display some statistical information every 20th image if( cnt % 20 == 0 ) { ostringstream out; out << pDev->serial.read() << ": " << statistics.framesPerSecond.name() << ": " << statistics.framesPerSecond.readS(); pWindow->setOverlayString( out.str() ); cout << cnt << ": Info from " << pDev->serial.read() << ": " << statistics.framesPerSecond.name() << ": " << statistics.framesPerSecond.readS() << ", " << statistics.errorCount.name() << ": " << statistics.errorCount.readS() << ", " << statistics.captureTime_s.name() << ": " << statistics.captureTime_s.readS() << " Image count: " << cnt << " (dimensions: " << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << ", format: " << pRequest->imagePixelFormat.readS(); if( pRequest->imageBayerMosaicParity.read() != bmpUndefined ) { cout << ", " << pRequest->imageBayerMosaicParity.name() << ": " << pRequest->imageBayerMosaicParity.readS(); } cout << ")" << endl; } // here we can store an image every 100th frame if( boStoreFrames && ( cnt % 100 == 0 ) ) { ostringstream oss; oss << "Image" << cnt << "." << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << "." << pRequest->imagePixelFormat.readS(); if( pRequest->imageBayerMosaicParity.read() != bmpUndefined ) { oss << "(BayerPattern=" << pRequest->imageBayerMosaicParity.readS() << ")"; } oss << ".raw"; FILE* fp = fopen( oss.str().c_str(), "wb" ); if( fp ) { unsigned char* pImageData = ( unsigned char* ) pRequest->imageData.read(); for( int h = 0; h < pRequest->imageHeight.read(); h++ ) { // write one line fwrite( pImageData, pRequest->imageWidth.read(), pRequest->imageBytesPerPixel.read(), fp ); // respect image line pitch pImageData += pRequest->imageLinePitch.read(); } fclose( fp ); } } // everything went well. Display the result pWindow->NewRequest( pRequest ); pWindow->redraw(); Fl::check(); } else { cout << "*** Error: A request has been returned with the following result: " << pRequest->requestResult << endl; } // this image has been displayed thus the buffer is no longer needed... fi.imageRequestUnlock( requestNr ); // send a new image request into the capture queue fi.imageRequestSingle(); if( boSingleShotMode ) { manuallyStartAcquisitionIfNeeded( pDev, fi ); } } else { cout << "*** Error: Result of waiting for a finished request: " << requestNr << "(" << ImpactAcquireException::getErrorCodeAsString( requestNr ) << "). Timeout value too small?" << endl; } boLoopRunning = waitForInput( 0, STDOUT_FILENO ) == 0 ? true : false; // break by STDIN // Exit when window was cloesd if( s_boTerminated ) { break; } } if( !boSingleShotMode ) { manuallyStopAcquisitionIfNeeded( pDev, fi ); } cout << " == " << __FUNCTION__ << " - free resources...." << endl; // free resources fi.imageRequestReset( 0, 0 ); return 0; }