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 
125  if (n_open == 0)
126  {
127  stopStreaming();
128  gentl->DSClose(stream);
129  stream=0;
130 
131  buffer.setNodemap(0, "");
132 
133  nodemap=0;
134  cport=0;
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 
155 {
156  std::lock_guard<std::recursive_mutex> lock(mtx);
157 
158  buffer.setHandle(0);
159 
160  if (stream == 0)
161  {
162  throw GenTLException("Stream::startStreaming(): Stream is not open");
163  }
164 
165  // stop streaming if it is currently running
166 
167  if (bn > 0)
168  {
169  stopStreaming();
170  }
171 
172  // lock parameters before streaming starts
173 
174  std::shared_ptr<GenApi::CNodeMapRef> nmap=parent->getRemoteNodeMap();
175  GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("TLParamsLocked"));
176 
177  if (GenApi::IsWritable(p))
178  {
179  p->SetValue(1);
180  }
181 
182  // determine maximum buffer size from transport layer or remote device
183 
184  size_t size=0;
185  if (getDefinesPayloadsize())
186  {
187  size=getPayloadSize();
188  }
189  else
190  {
191  std::shared_ptr<GenApi::CNodeMapRef> nmap=parent->getRemoteNodeMap();
192  GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("PayloadSize"));
193 
194  if (GenApi::IsReadable(p))
195  {
196  size=static_cast<size_t>(p->GetValue());
197  }
198  }
199 
200  // announce and queue the minimum number of buffers
201 
202  bool err=false;
203 
204  bn=std::max(static_cast<size_t>(8), getBufAnnounceMin());
205  for (size_t i=0; i<bn; i++)
206  {
208 
209  if (gentl->DSAllocAndAnnounceBuffer(stream, size, 0, &p) != GenTL::GC_ERR_SUCCESS)
210  {
211  err=true;
212  break;
213  }
214 
215  if (!err && gentl->DSQueueBuffer(stream, p) != GenTL::GC_ERR_SUCCESS)
216  {
217  err=true;
218  break;
219  }
220  }
221 
222  // register event
223 
224  if (!err && gentl->GCRegisterEvent(stream, GenTL::EVENT_NEW_BUFFER, &event) !=
226  {
227  err=true;
228  }
229 
230  // start streaming
231 
232  uint64_t n=GENTL_INFINITE;
233 
234  if (na > 0)
235  {
236  n=static_cast<uint64_t>(na);
237  }
238 
239  if (!err && gentl->DSStartAcquisition(stream, GenTL::ACQ_START_FLAGS_DEFAULT, n) !=
241  {
242  gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
243  err=true;
244  }
245 
246  if (!err)
247  {
248  GenApi::CCommandPtr start=parent->getRemoteNodeMap()->_GetNode("AcquisitionStart");
249  start->Execute();
250  }
251 
252  // revoke buffers in case of an error, before throwing an event
253 
254  if (err)
255  {
256  gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
257 
259  while (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
260  {
261  gentl->DSRevokeBuffer(stream, p, 0, 0);
262  }
263 
264  // unlock parameters
265 
266  std::shared_ptr<GenApi::CNodeMapRef> nmap=parent->getRemoteNodeMap();
267  GenApi::IInteger *pi=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("TLParamsLocked"));
268 
269  if (GenApi::IsWritable(pi))
270  {
271  pi->SetValue(0);
272  }
273 
274  throw GenTLException("Stream::startStreaming()", gentl);
275  }
276 }
277 
279 {
280  std::lock_guard<std::recursive_mutex> lock(mtx);
281 
282  if (bn > 0)
283  {
284  buffer.setHandle(0);
285 
286  // do not throw exceptions as this method is also called in destructor
287 
288  GenApi::CCommandPtr stop=parent->getRemoteNodeMap()->_GetNode("AcquisitionStop");
289  stop->Execute();
290 
291  gentl->DSStopAcquisition(stream, GenTL::ACQ_STOP_FLAGS_DEFAULT);
292  gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
293  gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
294 
295  // free all buffers
296 
297  for (size_t i=0; i<bn; i++)
298  {
300  if (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
301  {
302  gentl->DSRevokeBuffer(stream, p, 0, 0);
303  }
304  }
305 
306  event=0;
307  bn=0;
308 
309  // unlock parameters
310 
311  std::shared_ptr<GenApi::CNodeMapRef> nmap=parent->getRemoteNodeMap();
312  GenApi::IInteger *pi=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("TLParamsLocked"));
313 
314  if (GenApi::IsWritable(pi))
315  {
316  pi->SetValue(0);
317  }
318  }
319 }
320 
321 const Buffer *Stream::grab(int64_t _timeout)
322 {
323  std::lock_guard<std::recursive_mutex> lock(mtx);
324 
325  uint64_t timeout=GENTL_INFINITE;
326  if (_timeout >= 0)
327  {
328  timeout=static_cast<uint64_t>(_timeout);
329  }
330 
331  // check that streaming had been started
332 
333  if (bn == 0 && event == 0)
334  {
335  throw GenTLException("Streaming::grab(): Streaming not started");
336  }
337 
338  // enqueue previously delivered buffer if any
339 
340  if (buffer.getHandle() != 0)
341  {
342  if (gentl->DSQueueBuffer(stream, buffer.getHandle()) != GenTL::GC_ERR_SUCCESS)
343  {
344  buffer.setHandle(0);
345  throw GenTLException("Stream::grab()", gentl);
346  }
347 
348  buffer.setHandle(0);
349  }
350 
351  // wait for event
352 
354  size_t size=sizeof(GenTL::EVENT_NEW_BUFFER_DATA);
355  memset(&data, 0, size);
356 
357  GenTL::GC_ERROR err=gentl->EventGetData(event, &data, &size, timeout);
358 
359  // return 0 in case of abort and timeout and throw exception in case of
360  // another error
361 
362  if (err == GenTL::GC_ERR_ABORT || err == GenTL::GC_ERR_TIMEOUT)
363  {
364  return 0;
365  }
366  else if (err != GenTL::GC_ERR_SUCCESS)
367  {
368  throw GenTLException("Stream::grab()", gentl);
369  }
370 
371  // return buffer
372 
373  buffer.setHandle(data.BufferHandle);
374 
375  return &buffer;
376 }
377 
378 namespace
379 {
380 
381 template<class T> inline T getStreamValue(const std::shared_ptr<const GenTLWrapper> &gentl,
382  void *stream, GenTL::STREAM_INFO_CMD cmd)
383 {
384  T ret=0;
385 
387  size_t size=sizeof(T);
388 
389  if (stream != 0)
390  {
391  gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
392  }
393 
394  return ret;
395 }
396 
397 inline bool getStreamBool(const std::shared_ptr<const GenTLWrapper> &gentl,
398  void *stream, GenTL::STREAM_INFO_CMD cmd)
399 {
400  bool8_t ret=0;
401 
403  size_t size=sizeof(ret);
404 
405  if (stream != 0)
406  {
407  gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
408  }
409 
410  return ret != 0;
411 }
412 
413 }
414 
416 {
417  std::lock_guard<std::recursive_mutex> lock(mtx);
418  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_DELIVERED);
419 }
420 
422 {
423  std::lock_guard<std::recursive_mutex> lock(mtx);
424  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_UNDERRUN);
425 }
426 
428 {
429  std::lock_guard<std::recursive_mutex> lock(mtx);
430  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_ANNOUNCED);
431 }
432 
434 {
435  std::lock_guard<std::recursive_mutex> lock(mtx);
436  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_QUEUED);
437 }
438 
440 {
441  std::lock_guard<std::recursive_mutex> lock(mtx);
442  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_AWAIT_DELIVERY);
443 }
444 
446 {
447  std::lock_guard<std::recursive_mutex> lock(mtx);
448  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_STARTED);
449 }
450 
452 {
453  std::lock_guard<std::recursive_mutex> lock(mtx);
454  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_PAYLOAD_SIZE);
455 }
456 
458 {
459  std::lock_guard<std::recursive_mutex> lock(mtx);
460  return getStreamBool(gentl, stream, GenTL::STREAM_INFO_IS_GRABBING);
461 }
462 
464 {
465  std::lock_guard<std::recursive_mutex> lock(mtx);
466  return getStreamBool(gentl, stream, GenTL::STREAM_INFO_DEFINES_PAYLOADSIZE);
467 }
468 
469 std::string Stream::getTLType()
470 {
471  std::lock_guard<std::recursive_mutex> lock(mtx);
472  std::string ret;
473 
475  char tmp[1024]="";
476  size_t size=sizeof(tmp);
477 
478  if (stream != 0)
479  {
480  if (gentl->DSGetInfo(stream, GenTL::STREAM_INFO_TLTYPE, &type, tmp, &size) ==
482  {
483  if (type == GenTL::INFO_DATATYPE_STRING)
484  {
485  ret=tmp;
486  }
487  }
488  }
489 
490  return ret;
491 }
492 
494 {
495  std::lock_guard<std::recursive_mutex> lock(mtx);
496  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_CHUNKS_MAX);
497 }
498 
500 {
501  std::lock_guard<std::recursive_mutex> lock(mtx);
502  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ANNOUNCE_MIN);
503 }
504 
506 {
507  std::lock_guard<std::recursive_mutex> lock(mtx);
508  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ALIGNMENT);
509 }
510 
511 std::shared_ptr<GenApi::CNodeMapRef> Stream::getNodeMap()
512 {
513  std::lock_guard<std::recursive_mutex> lock(mtx);
514  if (stream != 0 && !nodemap)
515  {
516  cport=std::shared_ptr<CPort>(new CPort(gentl, &stream));
518  }
519 
520  return nodemap;
521 }
522 
523 void *Stream::getHandle() const
524 {
525  return stream;
526 }
527 
528 }
uint64_t getNumDelivered()
Returns some information about the stream.
Definition: stream.cc:415
const Buffer * grab(int64_t timeout=-1)
Wait for the next image or data and return it in a buffer object.
Definition: stream.cc:321
int n_open
Definition: stream.h:299
std::shared_ptr< GenApi::CNodeMapRef > nodemap
Definition: stream.h:305
size_t bn
Definition: stream.h:302
GENICAM_INTERFACE IInteger
Interface for integer properties.
Definition: IFloat.h:114
size_t getNumAwaitDelivery()
Returns some information about the stream.
Definition: stream.cc:439
This is the port definition that connects GenAPI to GenTL.
Definition: cport.h:52
std::recursive_mutex mtx
Definition: stream.h:297
void * BUFFER_HANDLE
Definition: GenTL_v1_5.h:227
std::string getTLType()
Returns some information about the stream.
Definition: stream.cc:469
void * getHandle() const
Get internal stream handle.
Definition: buffer.cc:638
__int64 int64_t
Definition: config-win32.h:21
struct S_EVENT_NEW_BUFFER EVENT_NEW_BUFFER_DATA
Buffer buffer
Definition: stream.h:291
std::string id
Definition: stream.h:295
size_t getNumAnnounced()
Returns some information about the stream.
Definition: stream.cc:427
std::shared_ptr< Device > getParent() const
Returns the pointer to the parent device object.
Definition: stream.cc:83
void stopStreaming()
Stops streaming.
Definition: stream.cc:278
const std::string & getID() const
Get the internal ID of this stream.
Definition: stream.cc:88
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
int32_t STREAM_INFO_CMD
Definition: GenTL_v1_5.h:395
uint64_t getNumStarted()
Returns some information about the stream.
Definition: stream.cc:445
std::shared_ptr< const GenTLWrapper > gentl
Definition: stream.h:294
int32_t GC_ERROR
Definition: GenTL_v1_5.h:181
void * stream
Definition: stream.h:300
void startStreaming(int na=-1)
Allocates buffers and registers internal events if necessary and starts streaming.
Definition: stream.cc:154
size_t getNumChunksMax()
Returns some information about the stream.
Definition: stream.cc:493
size_t getNumQueued()
Returns some information about the stream.
Definition: stream.cc:433
bool getDefinesPayloadsize()
Returns some information about the stream.
Definition: stream.cc:463
The buffer class encapsulates a Genicam buffer that is provided by a stream.
Definition: buffer.h:118
size_t getPayloadSize()
Returns some information about the stream.
Definition: stream.cc:451
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
std::shared_ptr< CPort > cport
Definition: stream.h:304
uint8_t bool8_t
Definition: GenTL_v1_5.h:105
bool getIsGrabbing()
Returns some information about the stream.
Definition: stream.cc:457
void * getHandle() const
Get internal stream handle.
Definition: stream.cc:523
void setNodemap(const std::shared_ptr< GenApi::CNodeMapRef > nodemap, const std::string &tltype)
Set the device nodemap.
Definition: buffer.cc:143
std::shared_ptr< Device > parent
Definition: stream.h:293
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:133
std::shared_ptr< GenApi::CNodeMapRef > getNodeMap()
Returns the node map of this object.
Definition: stream.cc:511
void * event
Definition: stream.h:301
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:168
void close()
Closes the stream.
Definition: stream.cc:116
#define GENTL_INFINITE
Definition: GenTL_v1_5.h:235
int32_t INFO_DATATYPE
Definition: GenTL_v1_5.h:258
uint64_t getNumUnderrun()
Returns some information about the stream.
Definition: stream.cc:421
size_t getBufAnnounceMin()
Returns some information about the stream.
Definition: stream.cc:499
size_t getBufAlignment()
Returns some information about the stream.
Definition: stream.cc:505


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Wed Mar 17 2021 02:48:41