stream.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_genicam_api package.
3  *
4  * Copyright (c) 2017 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Heiko Hirschmueller
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "stream.h"
37 #include "config.h"
38 
39 #include "gentl_wrapper.h"
40 #include "exception.h"
41 #include "cport.h"
42 
43 #include <iostream>
44 #include <algorithm>
45 
46 #ifdef _WIN32
47 #undef min
48 #undef max
49 #endif
50 
51 namespace rcg
52 {
53 
54 Stream::Stream(const std::shared_ptr<Device> &_parent,
55  const std::shared_ptr<const GenTLWrapper> &_gentl, const char *_id) :
56  buffer(_gentl, this)
57 {
58  parent=_parent;
59  gentl=_gentl;
60  id=_id;
61 
62  n_open=0;
63  stream=0;
64  event=0;
65  bn=0;
66 }
67 
69 {
70  try
71  {
72  stopStreaming();
73 
74  if (stream != 0)
75  {
76  gentl->DSClose(stream);
77  }
78  }
79  catch (...) // do not throw exceptions in destructor
80  { }
81 }
82 
83 std::shared_ptr<Device> Stream::getParent() const
84 {
85  return parent;
86 }
87 
88 const std::string &Stream::getID() const
89 {
90  return id;
91 }
92 
94 {
95  std::lock_guard<std::recursive_mutex> lock(mtx);
96 
97  if (n_open == 0)
98  {
99  if (parent->getHandle() != 0)
100  {
101  if (gentl->DevOpenDataStream(parent->getHandle(), id.c_str(), &stream) !=
103  {
104  throw GenTLException("Stream::open()", gentl);
105  }
106  }
107  else
108  {
109  throw GenTLException("Stream::open(): Device must be opened before open before opening a stream");
110  }
111  }
112 
113  n_open++;
114 }
115 
117 {
118  std::lock_guard<std::recursive_mutex> lock(mtx);
119 
120  if (n_open > 0)
121  {
122  n_open--;
123 
124  if (n_open == 0)
125  {
126  stopStreaming();
127  gentl->DSClose(stream);
128  stream=0;
129 
130  buffer.setNodemap(0, "");
131 
132  nodemap=0;
133  cport=0;
134  }
135  }
136 }
137 
138 void Stream::attachBuffers(bool enable)
139 {
140  if (enable)
141  {
142  if (parent->getHandle() != 0)
143  {
144  std::shared_ptr<GenApi::CNodeMapRef> rnodemap=parent->getRemoteNodeMap();
145  buffer.setNodemap(rnodemap, parent->getTLType());
146  }
147  }
148  else
149  {
150  buffer.setNodemap(0, "");
151  }
152 }
153 
154 void Stream::startStreaming(int nacquire)
155 {
156  startStreaming(nacquire, 4);
157 }
158 
159 void Stream::startStreaming(int nacquire, int min_buffers)
160 {
161  std::lock_guard<std::recursive_mutex> lock(mtx);
162 
163  buffer.setHandle(0);
164 
165  if (stream == 0)
166  {
167  throw GenTLException("Stream::startStreaming(): Stream is not open");
168  }
169 
170  // stop streaming if it is currently running
171 
172  if (bn > 0)
173  {
174  stopStreaming();
175  }
176 
177  // lock parameters before streaming starts
178 
179  std::shared_ptr<GenApi::CNodeMapRef> nmap=parent->getRemoteNodeMap();
180  GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("TLParamsLocked"));
181 
182  if (GenApi::IsWritable(p))
183  {
184  p->SetValue(1);
185  }
186 
187  // determine maximum buffer size from transport layer or remote device
188 
189  size_t size=0;
190  if (getDefinesPayloadsize())
191  {
192  size=getPayloadSize();
193  }
194  else
195  {
196  GenApi::IInteger *pp=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("PayloadSize"));
197 
198  if (GenApi::IsReadable(pp))
199  {
200  size=static_cast<size_t>(pp->GetValue());
201  }
202  }
203 
204  // announce and queue the minimum number of buffers
205 
206  bool err=false;
207 
208  bn=std::max(static_cast<size_t>(min_buffers), getBufAnnounceMin());
209  for (size_t i=0; i<bn; i++)
210  {
212 
213  if (gentl->DSAllocAndAnnounceBuffer(stream, size, 0, &pp) != GenTL::GC_ERR_SUCCESS)
214  {
215  err=true;
216  break;
217  }
218 
219  if (!err && gentl->DSQueueBuffer(stream, pp) != GenTL::GC_ERR_SUCCESS)
220  {
221  err=true;
222  break;
223  }
224  }
225 
226  // register event
227 
228  if (!err && gentl->GCRegisterEvent(stream, GenTL::EVENT_NEW_BUFFER, &event) !=
230  {
231  err=true;
232  }
233 
234  // start streaming
235 
236  uint64_t n=GENTL_INFINITE;
237 
238  if (nacquire > 0)
239  {
240  n=static_cast<uint64_t>(nacquire);
241  }
242 
243  if (!err && gentl->DSStartAcquisition(stream, GenTL::ACQ_START_FLAGS_DEFAULT, n) !=
245  {
246  gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
247  err=true;
248  }
249 
250  if (!err)
251  {
252  GenApi::CCommandPtr start=parent->getRemoteNodeMap()->_GetNode("AcquisitionStart");
253  start->Execute();
254  }
255 
256  // revoke buffers in case of an error, before throwing an event
257 
258  if (err)
259  {
260  gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
261 
263  while (gentl->DSGetBufferID(stream, 0, &pp) == GenTL::GC_ERR_SUCCESS)
264  {
265  gentl->DSRevokeBuffer(stream, pp, 0, 0);
266  }
267 
268  // unlock parameters
269 
270  GenApi::IInteger *pi=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("TLParamsLocked"));
271 
272  if (GenApi::IsWritable(pi))
273  {
274  pi->SetValue(0);
275  }
276 
277  throw GenTLException("Stream::startStreaming()", gentl);
278  }
279 }
280 
282 {
283  std::lock_guard<std::recursive_mutex> lock(mtx);
284 
285  if (bn > 0)
286  {
287  buffer.setHandle(0);
288 
289  // do not throw exceptions as this method is also called in destructor
290 
291  GenApi::CCommandPtr stop=parent->getRemoteNodeMap()->_GetNode("AcquisitionStop");
292  stop->Execute();
293 
294  gentl->DSStopAcquisition(stream, GenTL::ACQ_STOP_FLAGS_DEFAULT);
295  gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
296  gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
297 
298  // free all buffers
299 
300  for (size_t i=0; i<bn; i++)
301  {
303  if (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
304  {
305  gentl->DSRevokeBuffer(stream, p, 0, 0);
306  }
307  }
308 
309  event=0;
310  bn=0;
311 
312  // unlock parameters
313 
314  std::shared_ptr<GenApi::CNodeMapRef> nmap=parent->getRemoteNodeMap();
315  GenApi::IInteger *pi=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("TLParamsLocked"));
316 
317  if (GenApi::IsWritable(pi))
318  {
319  pi->SetValue(0);
320  }
321  }
322 }
323 
325 {
326  size_t ret=0;
327 
329  size_t size=sizeof(ret);
330 
331  if (bn > 0 && event != 0)
332  {
333  if (gentl->EventGetInfo(event, GenTL::EVENT_NUM_IN_QUEUE, &type, &ret, &size) != GenTL::GC_ERR_SUCCESS)
334  {
335  ret=0;
336  }
337  }
338 
339  return static_cast<int>(ret);
340 }
341 
342 const Buffer *Stream::grab(int64_t _timeout)
343 {
344  std::lock_guard<std::recursive_mutex> lock(mtx);
345 
346  uint64_t timeout=GENTL_INFINITE;
347  if (_timeout >= 0)
348  {
349  timeout=static_cast<uint64_t>(_timeout);
350  }
351 
352  // check that streaming had been started
353 
354  if (bn == 0 || event == 0)
355  {
356  throw GenTLException("Streaming::grab(): Streaming not started");
357  }
358 
359  // enqueue previously delivered buffer if any
360 
361  if (buffer.getHandle() != 0)
362  {
363  if (gentl->DSQueueBuffer(stream, buffer.getHandle()) != GenTL::GC_ERR_SUCCESS)
364  {
365  buffer.setHandle(0);
366  throw GenTLException("Stream::grab()", gentl);
367  }
368 
369  buffer.setHandle(0);
370  }
371 
372  // wait for event
373 
375  size_t size=sizeof(GenTL::EVENT_NEW_BUFFER_DATA);
376  memset(&data, 0, size);
377 
378  GenTL::GC_ERROR err=gentl->EventGetData(event, &data, &size, timeout);
379 
380  // return 0 in case of abort and timeout and throw exception in case of
381  // another error
382 
383  if (err == GenTL::GC_ERR_ABORT || err == GenTL::GC_ERR_TIMEOUT)
384  {
385  return 0;
386  }
387  else if (err != GenTL::GC_ERR_SUCCESS)
388  {
389  throw GenTLException("Stream::grab()", gentl);
390  }
391 
392  // return buffer
393 
394  buffer.setHandle(data.BufferHandle);
395 
396  return &buffer;
397 }
398 
399 namespace
400 {
401 
402 template<class T> inline T getStreamValue(const std::shared_ptr<const GenTLWrapper> &gentl,
403  void *stream, GenTL::STREAM_INFO_CMD cmd)
404 {
405  T ret=0;
406 
408  size_t size=sizeof(T);
409 
410  if (stream != 0)
411  {
412  gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
413  }
414 
415  return ret;
416 }
417 
418 inline bool getStreamBool(const std::shared_ptr<const GenTLWrapper> &gentl,
419  void *stream, GenTL::STREAM_INFO_CMD cmd)
420 {
421  bool8_t ret=0;
422 
424  size_t size=sizeof(ret);
425 
426  if (stream != 0)
427  {
428  gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
429  }
430 
431  return ret != 0;
432 }
433 
434 }
435 
437 {
438  std::lock_guard<std::recursive_mutex> lock(mtx);
439  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_DELIVERED);
440 }
441 
443 {
444  std::lock_guard<std::recursive_mutex> lock(mtx);
445  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_UNDERRUN);
446 }
447 
449 {
450  std::lock_guard<std::recursive_mutex> lock(mtx);
451  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_ANNOUNCED);
452 }
453 
455 {
456  std::lock_guard<std::recursive_mutex> lock(mtx);
457  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_QUEUED);
458 }
459 
461 {
462  std::lock_guard<std::recursive_mutex> lock(mtx);
463  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_AWAIT_DELIVERY);
464 }
465 
467 {
468  std::lock_guard<std::recursive_mutex> lock(mtx);
469  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_STARTED);
470 }
471 
473 {
474  std::lock_guard<std::recursive_mutex> lock(mtx);
475  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_PAYLOAD_SIZE);
476 }
477 
479 {
480  std::lock_guard<std::recursive_mutex> lock(mtx);
481  return getStreamBool(gentl, stream, GenTL::STREAM_INFO_IS_GRABBING);
482 }
483 
485 {
486  std::lock_guard<std::recursive_mutex> lock(mtx);
487  return getStreamBool(gentl, stream, GenTL::STREAM_INFO_DEFINES_PAYLOADSIZE);
488 }
489 
490 std::string Stream::getTLType()
491 {
492  std::lock_guard<std::recursive_mutex> lock(mtx);
493  std::string ret;
494 
496  char tmp[1024]="";
497  size_t size=sizeof(tmp);
498 
499  if (stream != 0)
500  {
501  if (gentl->DSGetInfo(stream, GenTL::STREAM_INFO_TLTYPE, &type, tmp, &size) ==
503  {
504  if (type == GenTL::INFO_DATATYPE_STRING)
505  {
506  ret=tmp;
507  }
508  }
509  }
510 
511  return ret;
512 }
513 
515 {
516  std::lock_guard<std::recursive_mutex> lock(mtx);
517  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_CHUNKS_MAX);
518 }
519 
521 {
522  std::lock_guard<std::recursive_mutex> lock(mtx);
523  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ANNOUNCE_MIN);
524 }
525 
527 {
528  std::lock_guard<std::recursive_mutex> lock(mtx);
529  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ALIGNMENT);
530 }
531 
532 std::shared_ptr<GenApi::CNodeMapRef> Stream::getNodeMap()
533 {
534  std::lock_guard<std::recursive_mutex> lock(mtx);
535  if (stream != 0 && !nodemap)
536  {
537  cport=std::shared_ptr<CPort>(new CPort(gentl, &stream));
539  }
540 
541  return nodemap;
542 }
543 
544 void *Stream::getHandle() const
545 {
546  return stream;
547 }
548 
549 }
struct S_EVENT_NEW_BUFFER EVENT_NEW_BUFFER_DATA
uint64_t getNumDelivered()
Returns some information about the stream.
Definition: stream.cc:436
const Buffer * grab(int64_t timeout=-1)
Wait for the next image or data and return it in a buffer object.
Definition: stream.cc:342
int n_open
Definition: stream.h:317
int32_t STREAM_INFO_CMD
Definition: GenTL_v1_6.h:399
std::shared_ptr< GenApi::CNodeMapRef > nodemap
Definition: stream.h:323
void * getHandle() const
Get internal stream handle.
Definition: buffer.cc:717
size_t bn
Definition: stream.h:320
GENICAM_INTERFACE IInteger
Interface for integer properties.
Definition: IFloat.h:114
size_t getNumAwaitDelivery()
Returns some information about the stream.
Definition: stream.cc:460
This is the port definition that connects GenAPI to GenTL.
Definition: cport.h:52
std::recursive_mutex mtx
Definition: stream.h:315
std::string getTLType()
Returns some information about the stream.
Definition: stream.cc:490
void startStreaming(int nacquire=-1)
Allocates four buffers, registers internal events and starts streaming of nacquire buffers...
Definition: stream.cc:154
__int64 int64_t
Definition: config-win32.h:21
Buffer buffer
Definition: stream.h:309
std::string id
Definition: stream.h:313
size_t getNumAnnounced()
Returns some information about the stream.
Definition: stream.cc:448
void stopStreaming()
Stops streaming.
Definition: stream.cc:281
void attachBuffers(bool enable)
Enabling or disabling attaching the grabbed buffer to the remote device nodemap.
Definition: stream.cc:138
bool IsReadable(EAccessMode AccessMode)
Tests if readable.
Definition: INode.h:178
uint64_t getNumStarted()
Returns some information about the stream.
Definition: stream.cc:466
std::shared_ptr< const GenTLWrapper > gentl
Definition: stream.h:312
void * stream
Definition: stream.h:318
void * getHandle() const
Get internal stream handle.
Definition: stream.cc:544
void * BUFFER_HANDLE
Definition: GenTL_v1_6.h:231
size_t getNumChunksMax()
Returns some information about the stream.
Definition: stream.cc:514
size_t getNumQueued()
Returns some information about the stream.
Definition: stream.cc:454
bool getDefinesPayloadsize()
Returns some information about the stream.
Definition: stream.cc:484
The buffer class encapsulates a Genicam buffer that is provided by a stream.
Definition: buffer.h:118
std::shared_ptr< Device > getParent() const
Returns the pointer to the parent device object.
Definition: stream.cc:83
size_t getPayloadSize()
Returns some information about the stream.
Definition: stream.cc:472
Encapsulates a GenApi pointer dealing with the dynamic_cast automatically.
Definition: Pointer.h:51
Stream(const std::shared_ptr< Device > &parent, const std::shared_ptr< const GenTLWrapper > &gentl, const char *id)
Constructs a stream class.
Definition: stream.cc:54
#define GENTL_INFINITE
Definition: GenTL_v1_6.h:238
std::shared_ptr< CPort > cport
Definition: stream.h:322
bool getIsGrabbing()
Returns some information about the stream.
Definition: stream.cc:478
void setNodemap(const std::shared_ptr< GenApi::CNodeMapRef > nodemap, const std::string &tltype)
Set the device nodemap.
Definition: buffer.cc:146
std::shared_ptr< Device > parent
Definition: stream.h:311
int32_t INFO_DATATYPE
Definition: GenTL_v1_6.h:261
std::shared_ptr< GenApi::CNodeMapRef > allocNodeMap(std::shared_ptr< const GenTLWrapper > gentl, void *port, CPort *cport, const char *xml)
Convenience function that returns a GenICam node map from the given port.
Definition: cport.cc:156
int32_t GC_ERROR
Definition: GenTL_v1_6.h:185
std::shared_ptr< GenApi::CNodeMapRef > getNodeMap()
Returns the node map of this object.
Definition: stream.cc:532
const std::string & getID() const
Get the internal ID of this stream.
Definition: stream.cc:88
void * event
Definition: stream.h:319
Definition: buffer.cc:47
bool IsWritable(EAccessMode AccessMode)
Tests if writable.
Definition: INode.h:196
void open()
Opens the stream for working with it.
Definition: stream.cc:93
void setHandle(void *handle)
Set the buffer handle that this object should manage.
Definition: buffer.cc:171
void close()
Closes the stream.
Definition: stream.cc:116
uint64_t getNumUnderrun()
Returns some information about the stream.
Definition: stream.cc:442
size_t getBufAnnounceMin()
Returns some information about the stream.
Definition: stream.cc:520
int getAvailableBufferCount()
Returns the number ob buffers that are currently available for grabbing.
Definition: stream.cc:324
size_t getBufAlignment()
Returns some information about the stream.
Definition: stream.cc:526
uint8_t bool8_t
Definition: GenTL_v1_6.h:108


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Sun Jun 18 2023 02:43:55