How to configure/use this feature can be seen in the following source code example.
#include <algorithm>
#include <ctime>
#include <functional>
#include <iostream>
#include <thread>
#include <apps/Common/exampleHelper.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam_CustomCommands.h>
#ifdef _WIN32
# include <mvDisplay/Include/mvIMPACT_acquire_display.h>
# define USE_DISPLAY
#else
# include <stdio.h>
# include <unistd.h>
#endif
using namespace std;
static bool s_boTerminated = false;
struct ThreadParameter
{
int width;
int height;
int requestRate;
#ifdef USE_DISPLAY
Request* pLastRequestExplicitlyRequested;
#endif
explicit ThreadParameter(
Device* p,
int w,
int h,
int rr ) : pDev( p ), ccg( pDev ), width( w ), height( h ), requestRate( rr )
#ifdef USE_DISPLAY
, 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
{}
ThreadParameter( const ThreadParameter& src ) = delete;
ThreadParameter& operator=( const ThreadParameter& rhs ) = delete;
};
static void configureDevice(
Device* pDev, int64_type skipRatio, int64_type thumbnailScaling,
double framesPerSecond );
static bool isDeviceSupportedBySample(
const Device*
const pDev );
static void liveThread( ThreadParameter* pThreadParameter );
static void reportProblemAndExit(
Device* pDev,
const string& prologue,
const string& epilogue =
"" );
void configureDevice(
Device* pDev, int64_type skipRatio, int64_type thumbnailScaling,
double framesPerSecond )
{
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 );
}
}
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 );
}
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..." );
}
cdc.chunkSelector.writeS( "Image" );
cdc.chunkEnable.write( bTrue );
cdc.chunkSelector.writeS( "mvCustomIdentifier" );
cdc.chunkEnable.write( bTrue );
const int modulo = ifc.width.read() % 8;
if( modulo != 0 )
{
ifc.width.write( ifc.width.read() - modulo );
}
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 );
}
}
if( ac.mvSmartFrameRecallFrameSkipRatio.isValid() )
{
ac.mvSmartFrameRecallFrameSkipRatio.write( skipRatio );
ac.mvSmartFrameRecallTimestampLookupAccuracy.write( ( skipRatio != 0 ) ? skipRatio * 3 : 1 );
}
else
{
cout << "===================================================" << endl;
cout << " mvSmartFrameRecallFrameSkipRatio not available " << endl;
cout << "===================================================" << endl;
}
ac.mvSmartFrameRecallEnable.write( bTrue );
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;
}
bool isDeviceSupportedBySample(
const Device*
const pDev )
{
{
return false;
}
vector<TDeviceInterfaceLayout> availableInterfaceLayouts;
return find( availableInterfaceLayouts.begin(), availableInterfaceLayouts.end(), dilGenICam ) != availableInterfaceLayouts.end();
}
void liveThread( ThreadParameter* pThreadParameter )
{
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 );
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};
if( ac.mvSmartFrameRecallFrameSkipRatio.isValid() )
{
skipRatio = ac.mvSmartFrameRecallFrameSkipRatio.read();
}
srand( static_cast<unsigned int>( time( 0 ) ) );
while( !s_boTerminated )
{
const int requestNr = fi.imageRequestWaitFor( timeout_ms );
if( fi.isRequestNrValid( requestNr ) )
{
Request* pRequest = fi.getRequest( requestNr );
{
if( previewCnt == 0 )
{
previewCnt = 1;
}
if( chunkmvCustomIdentifier == 0 )
{
++previewCnt;
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;
}
}
#ifdef USE_DISPLAY
ImageDisplay& display = ( chunkmvCustomIdentifier == 0 ) ? pThreadParameter->displayWindowStream.GetImageDisplay() : pThreadParameter->displayWindowExplicitRequestedByHost.GetImageDisplay();
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( ( previewCnt % pThreadParameter->requestRate == 0 ) && ( chunkmvCustomIdentifier == 0 ) )
{
int w = pThreadParameter->width;
int x = 0;
if( w == 0 )
{
if( w == 0 )
{
w = 1;
}
}
int h = pThreadParameter->height;
int y = 0;
if( h == 0 )
{
if( h == 0 )
{
h = 1;
}
}
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++;
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 = ( w == 0 ) ? 1 : w;
h = ( h == 0 ) ? 1 : h;
cout << "Requesting the full resolution transmission of the image with timestamp " << hiddenTimestamp << " (hidden frame). ROI: " << x << "x" << y << "@" << w << "x" << h << " did ";
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
{
}
unlockAndRequestNext( fi, pRequest );
}
}
manuallyStopAcquisitionIfNeeded( pThreadParameter->pDev, fi );
#ifdef USE_DISPLAY
pThreadParameter->displayWindowExplicitRequestedByHost.GetImageDisplay().RemoveImage();
pThreadParameter->displayWindowStream.GetImageDisplay().RemoveImage();
if( pThreadParameter->pLastRequestExplicitlyRequested != nullptr )
{
pThreadParameter->pLastRequestExplicitlyRequested->unlock();
}
if( pThreadParameter->pLastRequestForStream != nullptr )
{
pThreadParameter->pLastRequestForStream->unlock();
}
#endif
fi.imageRequestReset( 0, 0 );
}
void reportProblemAndExit(
Device* pDev,
const string& prologue,
const string& epilogue )
{
<< "Press [ENTER] to end the application..." << endl;
cin.get();
exit( 42 );
}
{
if( pRequest != nullptr )
{
}
}
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;
if( argc > 1 )
{
for( int i = 1; i < argc; i++ )
{
const string param( argv[i] );
const auto 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;
}
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();
}
if( !serial.empty() )
{
{
}
}
if( pDev == nullptr )
{
pDev = getDeviceFromUserInput( devMgr, isDeviceSupportedBySample );
}
if( pDev == nullptr )
{
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;
usc.userSetSelector.writeS( "Default" );
usc.userSetLoad.call();
}
{
cout <<
"An error occurred while opening device " << pDev->
serial.
read()
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
try
{
configureDevice( pDev, skipRatio, thumbnailScaling, framesPerSecond );
cout << "Press [ENTER] to end the application" << endl;
ThreadParameter threadParam( pDev, width, height, requestRate );
thread myThread( liveThread, &threadParam );
cin.get();
s_boTerminated = true;
myThread.join();
}
{
cout <<
"An error occurred while setting up device " << pDev->
serial.
read()
<< "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:7171
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:7524
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:6610
PropertyS product
A string property (read-only) containing the product name of this device.
Definition mvIMPACT_acquire.h:6537
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition mvIMPACT_acquire.h:6551
void open(void)
Opens a device.
Definition mvIMPACT_acquire.h:6420
PropertyIDeviceInterfaceLayout interfaceLayout
An enumerated integer property which can be used to define which interface layout shall be used when ...
Definition mvIMPACT_acquire.h:6644
PropertyIAcquisitionStartStopBehaviour acquisitionStartStopBehaviour
An enumerated integer property defining the start/stop behaviour during acquisition of this driver in...
Definition mvIMPACT_acquire.h:6800
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:10758
int imageRequestSingle(ImageRequestControl *pImageRequestControl=0, int *pRequestUsed=0) const
Sends an image request to the mvIMPACT::acquire::Device driver.
Definition mvIMPACT_acquire.h:11503
Category for the acquisition and trigger control features.
Definition mvIMPACT_acquire_GenICam.h:2115
Category that contains the Chunk Data control features.
Definition mvIMPACT_acquire_GenICam.h:11823
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 that contains the User Set control features.
Definition mvIMPACT_acquire_GenICam.h:9632
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:8640
PropertyI imageHeight
An integer property (read-only) containing the height of the image in pixels.
Definition mvIMPACT_acquire.h:10331
bool isOK(void) const
Convenience function to check if a request has been processed successfully.
Definition mvIMPACT_acquire.h:9474
PropertyIRequestResult requestResult
An enumerated integer property (read-only) defining the result of this request.
Definition mvIMPACT_acquire.h:9780
PropertyI imageWidth
An integer property (read-only) containing the width of the image in pixels.
Definition mvIMPACT_acquire.h:10320
int unlock(void)
Unlocks the request for the driver again.
Definition mvIMPACT_acquire.h:9614
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:9913
PropertyI64 chunkmvCustomIdentifier
A 64 bit integer property (read-only) containing the previously configured user defined identifier at...
Definition mvIMPACT_acquire.h:10114
Contains basic statistical information.
Definition mvIMPACT_acquire.h:14509
A class that can be used to display images in a window.
Definition mvIMPACT_acquire_display.h:606
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:316
void Update(void) const
Immediately redraws the current image.
Definition mvIMPACT_acquire_display.h:405
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