IDS Peak comfortSDK, genericSDK, IPL, and AFL developer manuals are external documents. Please contact us if you need them.
As soon as the image acquisition has been started, the camera sends image data that can be received via the "WaitForFinishedBuffer()"/"peak_Acquisition_WaitForFrame()" function. In the simplest case you can call this function in the main program. However, such a call blocks the main program.
If successful, the function returns an image buffer from the buffer pool or throws a timeout exception if no image was received within the requested time period (here 5000 ms).
comfortC
|
peak_frame_handle hFrame;
peak_status status = PEAK_STATUS_SUCCESS;
status = peak_Acquisition_WaitForFrame(hCam, 5000, &hFrame);
if (PEAK_STATUS_TIMEOUT == status) { /* Error handling ... */ }
if (PEAK_ERROR(status)) { /* Error handling ... */ }
|
genericC++
|
try
{
const auto buffer = m_dataStream->WaitForFinishedBuffer(5000);
// process buffer ...
// Queue buffer so that it can be used again
m_dataStream->QueueBuffer(buffer);
}
catch (const peak::core::TimeoutException& e)
{
// ...
}
catch (const std::exception& e)
{
// ...
}
|
In order not to block the main program, you should move this part to a separate thread that continuously waits for new images from the camera. There are different concepts for multi-threading in the various programming languages.
For a Qt widget-based application, the procedure could be as follows: A worker class is defined and an object is created with a function that is executed in a separate thread.
Defining the worker class
genericC++
|
class AcquisitionWorker : public QObject
{
Q_OBJECT
public:
AcquisitionWorker(QObject* parent = nullptr);
bool SetDataStream(std::shared_ptr<peak::core::DataStream> dataStream);
void Start();
private:
std::shared_ptr<peak::core::DataStream> m_dataStream;
std::shared_ptr<peak::core::NodeMap> m_nodemapRemoteDevice;
bool m_running = false;
};
|
Implementing the worker class
genericC++
|
AcquisitionWorker::AcquisitionWorker(QObject* parent) : QObject(parent)
{
m_running = false;
}
bool AcquisitionWorker::SetDataStream(std::shared_ptr<peak::core::DataStream> dataStream)
{
m_dataStream = dataStream;
try
{
m_nodemapRemoteDevice = m_dataStream->ParentDevice()->RemoteDevice()->NodeMaps().at(0);
return true;
}
catch (const std::exception& e)
{
// ...
}
return false;
}
void AcquisitionWorker::Start()
{
m_running = true;
while (m_running)
{
try
{
// Get buffer from device's DataStream. Wait 5000 ms. The buffer is automatically locked until it is queued again.
const auto buffer = m_dataStream->WaitForFinishedBuffer(5000);
// Process buffer ...
// Queue buffer so that it can be used again
m_dataStream->QueueBuffer(buffer);
}
catch (const std::exception& e)
{
// ...
}
}
}
|
Creating and starting the worker thread in main program
genericC++
|
void mainProgram()
{
// ...
// Create worker thread
AcquisitionWorker* m_acquisitionWorker = new AcquisitionWorker();
QThread m_acquisitionThread;
if (!m_acquisitionWorker->SetDataStream(m_dataStream))
{
// error
}
// Move the worker to a new thread
m_acquisitionWorker->moveToThread(&m_acquisitionThread);
// Call Start() slot of the worker when QThread starts
connect(&m_acquisitionThread, SIGNAL(started()), m_acquisitionWorker, SLOT(Start()));
// Start QThread
m_acquisitionThread.start();
}
|
After the thread start, call the worker thread's “Start()” function. This function continuously waits for images from the camera until the variable "m_running" is set to "false". Afterwards, the while loop terminates and finally also the thread.
The buffer returned by the "WaitForFinishedBuffer()" function is automatically locked by IDS peak and cannot be overwritten until you return the buffer into the buffer pool by "QueueBuffer()". The processing of the image memory is done between these two calls (see Converting images).