PVCAM  3.9.x
Programmable Virtual Camera Access Method library
Live Image SMART Streaming

This sample application demonstrates how to run continuous acquisition in circular buffer mode and with SMART Streaming feature enabled.

Initialize PVCAM and open the first available camera. Please refer to the actual code sample in the SDK installation directory for more details about the common helper functions used in this documentation.

std::vector<CameraContext*> contexts;
if (!InitAndOpenOneCamera(contexts, cSingleCamIndex))
return APP_EXIT_ERROR;
CameraContext* ctx = contexts[cSingleCamIndex];

Check whether SMART Streaming feature has been detected during the camera initialization.

if (!ctx->isSmartStreaming)
{
printf("Camera %d does not support Smart Streaming\n", ctx->hcam);
CloseAllCamerasAndUninit(contexts);
return APP_EXIT_ERROR;
}

To use callbacks we need to create a callback function and register it with PVCAM. PVCAM will then call this function every time a frame arrives. This approach is used in most samples, thus a generic code block is shared across the code examples. For more information please refer to Frame Callback Handler section.

The following code snippet uploads the desired set of exposures to the camera. Please, see the UploadSmartStreamingExposures for details.

const uns32 smartStreamingValues[] = { 10, 20, 30, 40, 50, 60, 70, 80 };
const uns32 smartStreamingValueCount =
sizeof(smartStreamingValues) / sizeof(uns32);
if (!UploadSmartStreamingExposures(ctx, smartStreamingValues,
smartStreamingValueCount))
{
CloseAllCamerasAndUninit(contexts);
return APP_EXIT_ERROR;
}

Prepare the continuous acquisition with circular buffer mode. The pl_exp_setup_cont function returns the size of one frame in bytes (unlike the size of entire buffer as with the pl_exp_setup_seq function). Please, see more details in Acquisition Configuration section.

uns32 exposureBytes;
const uns32 exposureTime = 5; // milliseconds
const uns16 circBufferFrames = 20;
const int16 bufferMode = CIRC_OVERWRITE;
if (PV_OK != pl_exp_setup_cont(ctx->hcam, 1, &ctx->region, exposureMode,
exposureTime, &exposureBytes, bufferMode))
{
PrintErrorMessage(pl_error_code(), "pl_exp_setup_cont() error");
CloseAllCamerasAndUninit(contexts);
return APP_EXIT_ERROR;
}
Warning
If SMART Streaming mode is enabled, the exposure time entered here is ignored and the values from SMART array are used. However, the value entered here must not be 0.
Note
This example uses the extended trigger mode configuration and sets up the camera to use internal trigger with first-row expose out mode. However, legacy cameras do not support the extended modes and the list of supported expose out modes may differ as well. It is important to always discover the supported modes using the PARAM_EXPOSURE_MODE and PARAM_EXPOSE_OUT_MODE parameters when working with multiple camera models.

Now allocate the buffer memory. The application is in control of the circular buffer and should allocate memory of appropriate size.

const uns32 circBufferBytes = circBufferFrames * exposureBytes;
uns8* circBufferInMemory = new (std::nothrow) uns8[circBufferBytes];
if (!circBufferInMemory)
{
printf("Unable to allocate buffer for camera %d\n", ctx->hcam);
CloseAllCamerasAndUninit(contexts);
return APP_EXIT_ERROR;
}

Start the continuous acquisition. By passing the entire size of the buffer to pl_exp_start_cont, PVCAM can calculate the capacity of the circular buffer.

if (PV_OK != pl_exp_start_cont(ctx->hcam, circBufferInMemory, circBufferBytes))
{
PrintErrorMessage(pl_error_code(), "pl_exp_start_cont() error");
CloseAllCamerasAndUninit(contexts);
delete [] circBufferInMemory;
return APP_EXIT_ERROR;
}

Loop to acquire 16 frames. Since SMART Streaming array holds 8 different exposure times, these will be applied in a circular manner, thus after the first 8 exposures are completed, the next 8 exposures will start again with the initial exposure time of 10ms.

bool errorOccured = false;
uns32 framesAcquired = 0;
while (framesAcquired < 16)
{

Here we need to wait for a frame readout notification signaled by eofEvent in CameraContext which is raised in the callback handler we registered. If the frame does not arrive within 5 seconds or if user aborts the acquisition with ctrl+c keyboard shortcut, the main while loop is interrupted and the acquisition is aborted.

printf("Waiting for EOF event to occur on camera %d\n", ctx->hcam);
if (!WaitForEofEvent(ctx, 5000, errorOccurred))
break;

Next, use the address of the latest frame in the circular buffer stored in the callback handler:

printf("Frame #%u has been delivered from camera %d, exposure time = %ums\n",
framesAcquired + 1, ctx->hcam,
smartStreamingValues[framesAcquired % smartStreamingValueCount]);
ShowImage(ctx, ctx->eofFrame, exposureBytes);
framesAcquired++;
} // End of while cycle

Once we have acquired the desired number of frames, the acquisition should be stopped with pl_exp_abort. For more information about closing cameras and uninitializing PVCAM, please, refer to the Closing Camera and Uninitializing PVCAM section.

if (PV_OK != pl_exp_abort(ctx->hcam, CCS_HALT))
PrintErrorMessage(pl_error_code(), "pl_exp_abort() error");
delete [] circBufferInMemory;
CloseAllCamerasAndUninit(contexts);
if (errorOccured)
return APP_EXIT_ERROR;
return 0;