Impact Acquire SDK C++
GenICamSmartFrameRecallUsage.legacy.cpp

The GenICamSmartFrameRecallUsage.legacy program is a legacy version of the GenICamSmartFrameRecallUsage.cpp example.

Note
This is a legacy version of GenICamSmartFrameRecallUsage.cpp only needed when working on a system with a non C++11 capable compiler (e.g. Visual Studio smaller than version 2013 or gcc smaller than version 4.8. However please note that Impact Acquire these days is built using gcc 5.5.0 thus using an older compiler for building applications will most likely not result in working binaries!). For a detailed description please have a look on the modern version of this example. Even though the used C++ code is slightly different the general idea of the example is the same!
Source code
//
// @description: Example applications for Impact Acquire
// @copyright: Copyright (C) 2012 - 2023 Balluff GmbH
// @authors: APIs and drivers development team at Balluff GmbH
// @initial date: 2012-03-05
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,i
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#ifdef _MSC_VER // is Microsoft compiler?
# if _MSC_VER < 1300 // is 'old' VC 6 compiler?
# pragma warning( disable : 4786 ) // 'identifier was truncated to '255' characters in the debug information'
# endif // #if _MSC_VER < 1300
#endif // #ifdef _MSC_VER
#include <algorithm>
#include <ctime>
#include <functional>
#include <iostream>
#include <apps/Common/exampleHelper.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam_CustomCommands.h>
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# include <windows.h>
# include <process.h>
# include <mvDisplay/Include/mvIMPACT_acquire_display.h>
#else
# include <stdio.h>
# include <unistd.h>
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
using namespace std;
using namespace mvIMPACT::acquire;
static bool s_boTerminated = false;
//=============================================================================
//================= Data type definitions =====================================
//=============================================================================
//-----------------------------------------------------------------------------
struct ThreadParameter
//-----------------------------------------------------------------------------
{
Device* pDev;
int width; // the width of the ROI to request for transmission
int height; // the height of the ROI to request for transmission
int requestRate; // the rate at which full resolution frames shall be requested. A 'requestRate' of 2 will request every 2nd image from the stream again in full resolution
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
ImageDisplayWindow displayWindowStream;
// As the display might want to repaint the image we must keep it until the next one has been assigned to the display
Request* pLastRequestForStream;
ImageDisplayWindow displayWindowExplicitRequestedByHost;
// As the display might want to repaint the image we must keep it until the next one has been assigned to the display
Request* pLastRequestExplicitlyRequested;
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
explicit ThreadParameter( Device* p, int w, int h, int rr ) : pDev( p ), ccg( pDev ), width( w ), height( h ), requestRate( rr )
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
// initialise display window
// IMPORTANT: It's NOT safe to create multiple display windows in multiple threads!!!
, displayWindowStream( "mvIMPACT_acquire sample, Device " + pDev->serial.read() + "(live stream)" )
, pLastRequestForStream( 0 )
, displayWindowExplicitRequestedByHost( "mvIMPACT_acquire sample, Device " + pDev->serial.read() + "(explicit requests by the host)" )
, pLastRequestExplicitlyRequested( 0 )
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
{}
};
//=============================================================================
//================= function declarations =====================================
//=============================================================================
static void configureDevice( Device* pDev, int64_type skipRatio, int64_type thumbnailScaling, double framesPerSecond );
static bool isDeviceSupportedBySample( const Device* const pDev );
static unsigned int DMR_CALL liveThread( void* pData );
static void reportProblemAndExit( Device* pDev, const string& prologue, const string& epilogue = "" );
static void unlockAndRequestNext( FunctionInterface& fi, Request* pRequest );
//=============================================================================
//================= implementation ============================================
//=============================================================================
//-----------------------------------------------------------------------------
// Check if all features needed by this application are actually available
// and set up these features in a way that the 'smart frame recall' can be used.
// If a crucial feature is missing/not available this function will terminate
// with an error message.
void configureDevice( Device* pDev, int64_type skipRatio, int64_type thumbnailScaling, double framesPerSecond )
//-----------------------------------------------------------------------------
{
//switch to Bayer pixel format if this is a color camera
if( ( dc.mvDeviceSensorColorMode.isValid() ) && ( dc.mvDeviceSensorColorMode.readS() == "BayerMosaic" ) )
{
if( ifc.pixelColorFilter.isValid() )
{
const string parity = ifc.pixelColorFilter.readS();
if( parity == "BayerBG" )
{
ifc.pixelFormat.writeS( "BayerBG8" );
}
else if( parity == "BayerGB" )
{
ifc.pixelFormat.writeS( "BayerGB8" );
}
else if( parity == "BayerRG" )
{
ifc.pixelFormat.writeS( "BayerRG8" );
}
else if( parity == "BayerGR" )
{
ifc.pixelFormat.writeS( "BayerGR8" );
}
else
{
cout << "Undefined BayerMosaicParity! Terminating..." << endl;
exit( 42 );
}
}
else
{
cout << "Cannot determine BayerMosaicParity! Terminating..." << endl;
exit( 42 );
}
}
// Configure the device to use max. decimation in both directions in order to achieve minimum bandwidth
// for the preview stream. A real world application could use this frame e.g. to do some blob analysis
// on the reduced data saving both transmission bandwidth and processing time. Whenever anything of
// interest is detected an application could then request the same image with full resolution or even
// just a ROI of the image in full resolution.
if( ifc.decimationHorizontal.isValid() )
{
ifc.decimationHorizontal.write( thumbnailScaling != 0 ? thumbnailScaling : ifc.decimationHorizontal.getMaxValue() );
displayPropertyData( ifc.decimationHorizontal );
}
if( ifc.decimationVertical.isValid() )
{
ifc.decimationVertical.write( thumbnailScaling != 0 ? thumbnailScaling : ifc.decimationVertical.getMaxValue() );
displayPropertyData( ifc.decimationVertical );
}
// Enable the chunk mode and switch on the 'mvCustomIdentifier' chunk that can be used to easily distinguish frames
// belonging to the normal stream from the ones explicitly requested by the host application.
if( !cdc.chunkModeActive.isValid() )
{
reportProblemAndExit( pDev, "Chunk data is NOT supported" );
}
cdc.chunkModeActive.write( bTrue );
if( !supportsEnumStringValue( cdc.chunkSelector, "mvCustomIdentifier" ) )
{
reportProblemAndExit( pDev, "'mvCustomIdentifier' chunk is NOT supported", " Can't distinguish requested frames from streamed ones..." );
}
// The image data itself of course is needed in any case!
cdc.chunkSelector.writeS( "Image" );
cdc.chunkEnable.write( bTrue );
cdc.chunkSelector.writeS( "mvCustomIdentifier" );
cdc.chunkEnable.write( bTrue );
//Make sure the image width is a multiple of 8. This is needed in order to successfully enable
//SmartFrameRecall
const int modulo = ifc.width.read() % 8;
if( modulo != 0 )
{
ifc.width.write( ifc.width.read() - modulo );
}
// Enable the smart frame recall feature itself. This will configure the devices internal memory
// to store each frame that gets transmitted to the host in full resolution. These images (or ROIs of these images)
// can be requested by an application when needed. However once the internal memory is full
// the oldest frame will be removed from the memory whenever a new one becomes ready.
if( !ac.mvSmartFrameRecallEnable.isValid() )
{
reportProblemAndExit( pDev, "The 'Smart Frame Recall' feature is NOT supported" );
}
if( framesPerSecond != -1 )
{
if( ac.mvAcquisitionFrameRateLimitMode.isValid() )
{
ac.mvAcquisitionFrameRateLimitMode.writeS( "mvDeviceMaxSensorThroughput" );
}
if( ac.exposureTime.isValid() )
{
if( 1000000 / ac.exposureTime.read() < framesPerSecond )
{
ac.exposureTime.write( 1000000 / ( framesPerSecond * 1.1 ) );
cout << "ExposureTime changed to " << ac.exposureTime.read() << endl;
}
}
if( ac.acquisitionFrameRate.isValid() )
{
ac.acquisitionFrameRateEnable.write( bTrue );
ac.acquisitionFrameRate.write( framesPerSecond );
}
}
// Since firmware version 2.30 you can specify a drop rate so the device
// will throw away <skipRatio> frames between two images of reduced resolution.
// That way you will further reduce the needed bandwidth.
// When issuing requests for AOIs all images can be used - the ones you
// got no thumbnail for have to be guessed (timestamp-wise).
if ( ac.mvSmartFrameRecallFrameSkipRatio.isValid() )
{
ac.mvSmartFrameRecallFrameSkipRatio.write( skipRatio );
// in order to request the frames you cannot see, the Lookup Accuracy can
// be adjusted - for our free-running-example this is done in an easy way
// => if you skip 5 frames between two frames, you know the timestamps of
// we accept the timestamps even if they are 3*5=15 us away from the real one...
// => please ensure that the achievable accuracy of your setup (trigger etc.)
// shows up in this parameter ...
ac.mvSmartFrameRecallTimestampLookupAccuracy.write( ( skipRatio != 0 ) ? skipRatio * 3 : 1 );
}
else
{
cout << "===================================================" << endl;
cout << " mvSmartFrameRecallFrameSkipRatio not available " << endl;
cout << "===================================================" << endl;
}
ac.mvSmartFrameRecallEnable.write( bTrue );
// after switching on the smart frame recall certain properties (e.g. everything related
// to binning and decimation) will become read-only!
cout << "Required PreviewFPS = " << ac.mvResultingFrameRate.read() << endl;
}
//-----------------------------------------------------------------------------
void displayCommandLineOptions( void )
//-----------------------------------------------------------------------------
{
cout << "Available parameters:" << endl
<< " 'serial' or 's' to specify the serial number of the device to use" << endl
<< " 'skip' or 'sk' to specify a skip ratio for the stream of thumbnail images. A skip ratio of 3 will only transfer every third thumbnail image. However the skipped images can be requested using the smart frame recall mechanism as well." << endl
<< " 'width' or 'w' to specify the width of the ROI that will be requested for transmission" << endl
<< " 'height' or 'h' to specify the height of the ROI that will be requested for transmission" << endl
<< " 'requestRate' or 'rr' to specify the request rate(default: 3, will request every third image)" << endl
<< " 'thumbnailScaling' or 'tns' to specify the scaling factor of the thumbnail image ( 2,4,8,16 )" << endl
<< " 'framesPerSecond' or 'fps' to specify the required frame rate." << endl
<< "When either width or height is specified the parameter and the corresponding offset will no longer change randomly!"
<< endl
<< "USAGE EXAMPLE:" << endl
<< " GenICamSmartFrameRecallUsage width=100 rr=2 skip=4" << endl << endl;
}
//-----------------------------------------------------------------------------
// This function will allow to select devices that support the GenICam interface
// layout(these are devices, that claim to be compliant with the GenICam standard)
// and that are bound to drivers that support the user controlled start and stop
// of the internal acquisition engine. Other devices will not be listed for
// selection as the code of the example relies on these features in the code.
bool isDeviceSupportedBySample( const Device* const pDev )
//-----------------------------------------------------------------------------
{
if( !pDev->interfaceLayout.isValid() &&
{
return false;
}
vector<TDeviceInterfaceLayout> availableInterfaceLayouts;
pDev->interfaceLayout.getTranslationDictValues( availableInterfaceLayouts );
return find( availableInterfaceLayouts.begin(), availableInterfaceLayouts.end(), dilGenICam ) != availableInterfaceLayouts.end();
}
//-----------------------------------------------------------------------------
unsigned int DMR_CALL liveThread( void* pData )
//-----------------------------------------------------------------------------
{
ThreadParameter* pThreadParameter = reinterpret_cast<ThreadParameter*>( pData );
// establish access to the statistic properties
Statistics statistics( pThreadParameter->pDev );
// create an interface to the device found
FunctionInterface fi( pThreadParameter->pDev );
// Send all requests to the capture queue. There can be more than 1 queue for some devices, but for this sample
// we will work with the default capture queue. If a device supports more than one capture or result
// queue, this will be stated in the manual. If nothing is mentioned about it, the device supports one
// queue only. This loop will send all requests currently available to the driver. To modify the number of requests
// use the property mvIMPACT::acquire::SystemSettings::requestCount at runtime (note that some devices will
// only allow to modify this parameter while NOT streaming data!) or the property
// mvIMPACT::acquire::Device::defaultRequestCount BEFORE opening the device.
while( ( result = static_cast<TDMR_ERROR>( fi.imageRequestSingle() ) ) == DMR_NO_ERROR ) {};
if( result != DEV_NO_FREE_REQUEST_AVAILABLE )
{
cout << "'FunctionInterface.imageRequestSingle' returned with an unexpected result: " << result
<< "(" << ImpactAcquireException::getErrorCodeAsString( result ) << ")" << endl;
}
manuallyStartAcquisitionIfNeeded( pThreadParameter->pDev, fi );
// run thread loop
unsigned int previewCnt = 0;
unsigned int recallCnt = 0;
const unsigned int timeout_ms = 500;
int64_type skipRatio = 0;
int64_type lastReceivedTimestamp = -1;
int64_type lastStatisticImageTimestamp = -1;
GenICam::AcquisitionControl ac( pThreadParameter->pDev );
if ( ac.mvSmartFrameRecallFrameSkipRatio.isValid() )
{
skipRatio = ac.mvSmartFrameRecallFrameSkipRatio.read();
}
srand( static_cast<unsigned int>( time( 0 ) ) );
while( !s_boTerminated )
{
// wait for results from the default capture queue
const int requestNr = fi.imageRequestWaitFor( timeout_ms );
if( fi.isRequestNrValid( requestNr ) )
{
Request* pRequest = fi.getRequest( requestNr );
if( pRequest->isOK() )
{
// within this scope we have a valid buffer of data that can be an image or any other chunk of data.
if( previewCnt == 0 )
{
// make sure 'previewCnt' is never 0 not even when the variable overflows
previewCnt = 1;
lastStatisticImageTimestamp = pRequest->infoTimeStamp_us.read();
}
const int64_type chunkmvCustomIdentifier = pRequest->chunkmvCustomIdentifier.read();
if( chunkmvCustomIdentifier == 0 )
{
// we only want to count the preview images
++previewCnt;
// here we can display some statistical information every 100th preview image
const unsigned int printStatisticEveryNthPreviewFrame = 100;
if( previewCnt % printStatisticEveryNthPreviewFrame == 0 )
{
cout << "Info from " << pThreadParameter->pDev->serial.read()
<< " PreviewCnt: " << previewCnt
<< " PreviewFPS: " << printStatisticEveryNthPreviewFrame * 1000000 / ( pRequest->infoTimeStamp_us.read() - lastStatisticImageTimestamp ) << " Hz"
<< ", " << "Recalls: " << recallCnt
<< ", " << statistics.errorCount.name() << ": " << statistics.errorCount.readS() << endl;
recallCnt = 0;
lastStatisticImageTimestamp = pRequest->infoTimeStamp_us.read();
}
}
// Depending on the 'chunkmvCustomIdentifier' an application can easily distinguish between frames belonging to the
// default 'reduced' stream or if these images have been explicitly requested by the application. A typical application
// would
// - perform a quick analysis of the reduced image to check if this image is needed in full resolution. If so it would request this
// image or a ROI of this image from the device
// - perform the actual analysis the application has been developed for on the images that have been requested based on the previous
// reduced analysis
// This can reduce the bandwidth consumed by an application dramatically!
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
ImageDisplay& display = ( chunkmvCustomIdentifier == 0 ) ? pThreadParameter->displayWindowStream.GetImageDisplay() : pThreadParameter->displayWindowExplicitRequestedByHost.GetImageDisplay();
display.SetImage( pRequest );
display.Update();
Request** ppRequest = ( chunkmvCustomIdentifier == 0 ) ? &pThreadParameter->pLastRequestForStream : &pThreadParameter->pLastRequestExplicitlyRequested;
swap( *ppRequest, pRequest );
#else
cout << "Image captured(" << ( ( chunkmvCustomIdentifier == 0 ) ? string( "default stream" ) : string( "as requested by the application" ) ) << "): " << pRequest->imageOffsetX.read() << "x" << pRequest->imageOffsetY.read()
<< "@" << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << endl;
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
// if 'chunkmvCustomIdentifier' is NOT 0 this was an image requested by the host application! Do not use this to trigger another transmission request!
// if 'chunkmvCustomIdentifier' is 0 trigger transmission requests with the desired request rate
if( ( previewCnt % pThreadParameter->requestRate == 0 ) && ( chunkmvCustomIdentifier == 0 ) )
{
// here depending on the user supplied input parameters we either roll the dice or we use user supplied values for the ROI
// of the image transmission request.
int w = pThreadParameter->width;
int x = 0;
if( w == 0 )
{
// there is no user supplied 'width' so generate a random one
w = rand() % pRequest->imageWidth.read();
if( w == 0 )
{
w = 1;
}
x = rand() % ( pRequest->imageWidth.read() - w );
}
int h = pThreadParameter->height;
int y = 0;
if( h == 0 )
{
// there is no user supplied 'height' so generate a random one
h = rand() % pRequest->imageHeight.read();
if( h == 0 )
{
h = 1;
}
y = rand() % ( pRequest->imageHeight.read() - h );
}
// 'previewCnt' will be used as the custom identifier. To distinguish between normal stream an requested transmissions one could also simply set this value to '1'.
// When dealing with high frame rates one should consider to request the retransmission of frames from a separate thread in order not to block the acquisition
// loop while communicating with the device. Also when multiple AOIs shall be requested from a single image these requests should be sent to the device in a
// single command if possible by using one of the overloads of 'queueTransmissionRequest' instead of 'requestTransmission'. Please note that there are versions
// NOT using the pointer to the request object but the timestamp of the request. So once the timestamp has been extracted the request can be unlock even
// if a retransmission command is constructed afterwards. When using multiple threads be sure to lock all resources appropriately. The more complex C# example
// 'SmartFrameRecall' makes use of the recommendations made here thus can be used by those looking for additional information.
const int64_type actualTimestamp = pRequest->infoTimeStamp_us.read();
cout << "Requesting the full resolution transmission of the image with timestamp " << pRequest->infoTimeStamp_us.read() << " and a user defined identifier of '" << previewCnt
<< "'. ROI: " << x << "x" << y << "@" << w << "x" << h << " did ";
int requestTransmissionResult = pThreadParameter->ccg.requestTransmission( pRequest, x, y, w, h, rtmFullResolution, previewCnt );
if( requestTransmissionResult == DMR_NO_ERROR )
{
cout << "succeed!" << endl;
}
else
{
cout << "fail(error code: " << requestTransmissionResult << "(" << ImpactAcquireException::getErrorCodeAsString( requestTransmissionResult ) << "))!" << endl;
}
recallCnt++;
// For further reduction of preview bandwidth you can use 'mvSmartFrameRecallFrameSkipRatio' to skip frames.
// All full resolution images are still stored in the camera's frame buffer. In this case you have to calculate the timestamp of the requested image.
if( ( skipRatio > 0 ) && ( lastReceivedTimestamp != -1 ) )
{
int64_type hiddenTimestamp = actualTimestamp;
const int64_type timespan = actualTimestamp - lastReceivedTimestamp;
const int64_type frame2frame = timespan / ( skipRatio + 1 );
for ( int i = 0; i < skipRatio; i++ )
{
hiddenTimestamp -= frame2frame;
w = rand() % pRequest->imageWidth.read();
w = ( w == 0 ) ? 1 : w;
x = rand() % ( pRequest->imageWidth.read() - w );
h = rand() % pRequest->imageHeight.read();
h = ( h == 0 ) ? 1 : h;
y = rand() % ( pRequest->imageHeight.read() - h );
cout << "Requesting the full resolution transmission of the image with timestamp " << hiddenTimestamp << " (hidden frame). ROI: " << x << "x" << y << "@" << w << "x" << h << " did ";
// here another overload of the requestTransmission function is used (giving the timestamp explicitly)
requestTransmissionResult = pThreadParameter->ccg.requestTransmission( hiddenTimestamp, x, y, w, h, rtmFullResolution, previewCnt );
if( requestTransmissionResult == DMR_NO_ERROR )
{
cout << "succeed!" << endl;
}
else
{
cout << "fail(error code: " << requestTransmissionResult << "(" << ImpactAcquireException::getErrorCodeAsString( requestTransmissionResult ) << "))!" << endl;
}
}
}
lastReceivedTimestamp = actualTimestamp;
}
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
unlockAndRequestNext( fi, pRequest );
}
else
{
// If the error code is -2119(DEV_WAIT_FOR_REQUEST_FAILED), the documentation will provide
// additional information under TDMR_ERROR in the interface reference
cout << "imageRequestWaitFor failed (" << requestNr << ", " << ImpactAcquireException::getErrorCodeAsString( requestNr ) << ")"
<< ", timeout value too small?" << endl;
}
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__APPLE__)
s_boTerminated = waitForInput( 0, STDOUT_FILENO ) == 0 ? false : true; // break by STDIN
#endif // #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__APPLE__)
}
manuallyStopAcquisitionIfNeeded( pThreadParameter->pDev, fi );
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
// stop the display from showing freed memory
pThreadParameter->displayWindowExplicitRequestedByHost.GetImageDisplay().RemoveImage();
pThreadParameter->displayWindowStream.GetImageDisplay().RemoveImage();
// free the last potentially locked requests
if( pThreadParameter->pLastRequestExplicitlyRequested )
{
pThreadParameter->pLastRequestExplicitlyRequested->unlock();
}
if( pThreadParameter->pLastRequestForStream )
{
pThreadParameter->pLastRequestForStream->unlock();
}
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
// In this sample all the next lines are redundant as the device driver will be
// closed now, but in a real world application a thread like this might be started
// several times an then it becomes crucial to clean up correctly.
// clear all queues
fi.imageRequestReset( 0, 0 );
return 0;
}
//-----------------------------------------------------------------------------
// When a crucial feature needed for this example application is not available
// this function will get called. It reports an error and then terminates the
// application.
void reportProblemAndExit( Device* pDev, const string& prologue, const string& epilogue /* = "" */ )
//-----------------------------------------------------------------------------
{
cout << prologue << " by device " << pDev->serial.read() << "(" << pDev->product.read() << ", Firmware version: " << pDev->firmwareVersion.readS() << ")." << epilogue << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
exit( 42 );
}
//-----------------------------------------------------------------------------
// Unlock the current request and send a new image request down to the driver
void unlockAndRequestNext( FunctionInterface& fi, Request* pRequest )
//-----------------------------------------------------------------------------
{
if( pRequest )
{
pRequest->unlock();
// send a new image request into the capture queue
}
}
//-----------------------------------------------------------------------------
int main( int argc, char* argv[] )
//-----------------------------------------------------------------------------
{
int width = 0;
int height = 0;
int requestRate = 3;
int64_type skipRatio = 0;
int thumbnailScaling = 0;
double framesPerSecond = -1;
string serial;
bool boInvalidCommandLineParameterDetected = false;
// scan command line
if( argc > 1 )
{
for( int i = 1; i < argc; i++ )
{
string param( argv[i] );
string::size_type keyEnd = param.find_first_of( "=" );
if( ( keyEnd == string::npos ) || ( keyEnd == param.length() - 1 ) )
{
cout << "Invalid command line parameter: '" << param << "' (ignored)." << endl;
boInvalidCommandLineParameterDetected = true;
}
else
{
const string key = param.substr( 0, keyEnd );
const string value = param.substr( keyEnd + 1 );
if( ( key == "serial" ) || ( key == "s" ) )
{
serial = value.c_str();
}
else if ( ( key == "skip" ) || ( key == "sk" ) )
{
skipRatio = static_cast<int>( atoi( value.c_str() ) );
}
else if( ( key == "requestRate" ) || ( key == "rr" ) )
{
requestRate = 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 == "thumbnailScaling" ) || ( key == "tns" ) )
{
thumbnailScaling = static_cast<int>( atoi( value.c_str() ) );
}
else if( ( key == "FramesPerSecond" ) || ( key == "fps" ) )
{
framesPerSecond = atof( value.c_str() );
}
else
{
cout << "Invalid command line parameter: '" << param << "' (ignored)." << endl;
boInvalidCommandLineParameterDetected = true;
}
}
}
if( boInvalidCommandLineParameterDetected )
{
displayCommandLineOptions();
}
}
else
{
cout << "No command line parameters specified." << endl;
displayCommandLineOptions();
}
DeviceManager devMgr;
Device* pDev = 0;
if( !serial.empty() )
{
pDev = devMgr.getDeviceBySerial( serial );
if( pDev && pDev->interfaceLayout.isValid() )
{
// if this device offers the 'GenICam' interface switch it on, as this will
// allow are better control over GenICam compliant devices
conditionalSetProperty( pDev->interfaceLayout, dilGenICam, true );
}
cout << ", interface layout: " << pDev->interfaceLayout.readS();
}
if( !pDev )
{
pDev = getDeviceFromUserInput( devMgr, isDeviceSupportedBySample );
}
if( !pDev )
{
cout << "Could not obtain a valid pointer to a device. Unable to continue!";
cout << "Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
try
{
cout << "Initialising the device. This might take some time..." << endl << endl;
pDev->interfaceLayout.write( dilGenICam ); // This is also done 'silently' by the 'getDeviceFromUserInput' function but your application needs to do this as well so state this here clearly!
pDev->open();
// load the default settings
usc.userSetSelector.writeS( "Default" );
usc.userSetLoad.call();
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while opening device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
try
{
configureDevice( pDev, skipRatio, thumbnailScaling, framesPerSecond );
// start the execution of the 'live' thread.
cout << "Press [ENTER] to end the application" << endl;
ThreadParameter threadParam( pDev, width, height, requestRate );
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
unsigned int dwThreadID;
HANDLE hThread = ( HANDLE )_beginthreadex( 0, 0, liveThread, ( LPVOID )( &threadParam ), 0, &dwThreadID );
cin.get();
s_boTerminated = true;
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
#else
liveThread( &threadParam );
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while setting up device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
return 0;
}
bool isValid(void) const
Checks if the internal component referenced by this object is still valid.
Definition mvIMPACT_acquire.h:1721
Grants access to devices that can be operated by this software interface.
Definition mvIMPACT_acquire.h:7159
Device * getDeviceBySerial(const std::string &serial="", unsigned int devNr=0, char wildcard=' *') const
Tries to locate a device via the serial number.
Definition mvIMPACT_acquire.h:7512
This class and its functions represent an actual device detected by this interface in the current sys...
Definition mvIMPACT_acquire.h:6118
PropertyI firmwareVersion
An integer property (read-only) containing the firmware version of this device.
Definition mvIMPACT_acquire.h:6609
PropertyS product
A string property (read-only) containing the product name of this device.
Definition mvIMPACT_acquire.h:6536
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition mvIMPACT_acquire.h:6550
void open(void)
Opens a device.
Definition mvIMPACT_acquire.h:6419
PropertyIDeviceInterfaceLayout interfaceLayout
An enumerated integer property which can be used to define which interface layout shall be used when ...
Definition mvIMPACT_acquire.h:6643
PropertyIAcquisitionStartStopBehaviour acquisitionStartStopBehaviour
An enumerated integer property defining the start/stop behaviour during acquisition of this driver in...
Definition mvIMPACT_acquire.h:6788
ZYX read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:4907
ZYX read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:4300
const EnumPropertyI & getTranslationDictValues(std::vector< ZYX > &sequence) const
This function queries a list of valid values for this property.
Definition mvIMPACT_acquire.h:4266
const EnumPropertyI & write(ZYX value, int index=0) const
Writes one value to the property.
Definition mvIMPACT_acquire.h:4426
The function interface to devices supported by this interface.
Definition mvIMPACT_acquire.h:10746
int imageRequestSingle(ImageRequestControl *pImageRequestControl=0, int *pRequestUsed=0) const
Sends an image request to the mvIMPACT::acquire::Device driver.
Definition mvIMPACT_acquire.h:11491
Category for the acquisition and trigger control features.
Definition mvIMPACT_acquire_GenICam.h:2108
Category that contains the Chunk Data control features.
Definition mvIMPACT_acquire_GenICam.h:11816
Contains convenience functions to control features understood by a devices custom command interpreter...
Definition mvIMPACT_acquire_GenICam_CustomCommands.h:439
Category for device information and control.
Definition mvIMPACT_acquire_GenICam.h:82
Category for Image Format Control features.
Definition mvIMPACT_acquire_GenICam.h:1132
Category that contains the User Set control features.
Definition mvIMPACT_acquire_GenICam.h:9625
A base class for exceptions generated by Impact Acquire.
Definition mvIMPACT_acquire.h:256
std::string getErrorCodeAsString(void) const
Returns a string representation of the error associated with the exception.
Definition mvIMPACT_acquire.h:288
std::string read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:5323
std::string readS(int index=0, const std::string &format="") const
Reads data from this property as a string.
Definition mvIMPACT_acquire.h:3340
Contains information about a captured buffer.
Definition mvIMPACT_acquire.h:8628
PropertyI imageHeight
An integer property (read-only) containing the height of the image in pixels.
Definition mvIMPACT_acquire.h:10319
bool isOK(void) const
Convenience function to check if a request has been processed successfully.
Definition mvIMPACT_acquire.h:9462
PropertyIRequestResult requestResult
An enumerated integer property (read-only) defining the result of this request.
Definition mvIMPACT_acquire.h:9768
PropertyI imageWidth
An integer property (read-only) containing the width of the image in pixels.
Definition mvIMPACT_acquire.h:10308
int unlock(void)
Unlocks the request for the driver again.
Definition mvIMPACT_acquire.h:9602
PropertyI64 infoTimeStamp_us
A 64 bit integer property (read-only) containing a timestamp to define the exact time this image has ...
Definition mvIMPACT_acquire.h:9901
PropertyI64 chunkmvCustomIdentifier
A 64 bit integer property (read-only) containing the previously configured user defined identifier at...
Definition mvIMPACT_acquire.h:10102
Contains basic statistical information.
Definition mvIMPACT_acquire.h:14497
A class that can be used to display images in a window.
Definition mvIMPACT_acquire_display.h:587
A class that can be used for displaying images within existing windows or GUI elements that can provi...
Definition mvIMPACT_acquire_display.h:176
void SetImage(const void *pData, int width, int height, int bitsPerPixel, int pitch)
Sets the next image to display.
Definition mvIMPACT_acquire_display.h:296
void Update(void) const
Immediately redraws the current image.
Definition mvIMPACT_acquire_display.h:385
TDMR_ERROR
Errors reported by the device manager.
Definition mvDriverBaseEnums.h:2601
@ DMR_NO_ERROR
The function call was executed successfully.
Definition mvDriverBaseEnums.h:2603
This namespace contains classes and functions that can be used to display images.
This namespace contains classes and functions belonging to the image acquisition module of this SDK.
Definition mvCommonDataTypes.h:34