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 
38 #include "gentl_wrapper.h"
39 #include "exception.h"
40 #include "cport.h"
41 
42 #include <iostream>
43 #include <algorithm>
44 
45 #ifdef _WIN32
46 #undef min
47 #undef max
48 #endif
49 
50 namespace rcg
51 {
52 
53 Stream::Stream(const std::shared_ptr<Device> &_parent,
54  const std::shared_ptr<const GenTLWrapper> &_gentl, const char *_id) :
55  buffer(_gentl, this)
56 {
57  parent=_parent;
58  gentl=_gentl;
59  id=_id;
60 
61  n_open=0;
62  stream=0;
63  event=0;
64  bn=0;
65 }
66 
68 {
69  try
70  {
71  stopStreaming();
72 
73  if (stream != 0)
74  {
75  gentl->DSClose(stream);
76  }
77  }
78  catch (...) // do not throw exceptions in destructor
79  { }
80 }
81 
82 std::shared_ptr<Device> Stream::getParent() const
83 {
84  return parent;
85 }
86 
87 const std::string &Stream::getID() const
88 {
89  return id;
90 }
91 
93 {
94  std::lock_guard<std::recursive_mutex> lock(mtx);
95 
96  if (n_open == 0)
97  {
98  if (parent->getHandle() != 0)
99  {
100  if (gentl->DevOpenDataStream(parent->getHandle(), id.c_str(), &stream) !=
102  {
103  throw GenTLException("Stream::open()", gentl);
104  }
105  }
106  else
107  {
108  throw GenTLException("Stream::open(): Device must be opened before open before opening a stream");
109  }
110  }
111 
112  n_open++;
113 }
114 
116 {
117  std::lock_guard<std::recursive_mutex> lock(mtx);
118 
119  if (n_open > 0)
120  {
121  n_open--;
122  }
123 
124  if (n_open == 0)
125  {
126  stopStreaming();
127  gentl->DSClose(stream);
128  stream=0;
129 
130  nodemap=0;
131  cport=0;
132  }
133 }
134 
136 {
137  std::lock_guard<std::recursive_mutex> lock(mtx);
138 
139  buffer.setHandle(0);
140 
141  if (stream == 0)
142  {
143  throw GenTLException("Stream::startStreaming(): Stream is not open");
144  }
145 
146  // stop streaming if it is currently running
147 
148  if (bn > 0)
149  {
150  stopStreaming();
151  }
152 
153  // determine maximum buffer size from transport layer or remote device
154 
155  size_t size=0;
156  if (getDefinesPayloadsize())
157  {
158  size=getPayloadSize();
159  }
160  else
161  {
162  std::shared_ptr<GenApi::CNodeMapRef> nmap=parent->getRemoteNodeMap();
163  GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(nmap->_GetNode("PayloadSize"));
164 
165  if (GenApi::IsReadable(p))
166  {
167  size=static_cast<size_t>(p->GetValue());
168  }
169  }
170 
171  // announce and queue the minimum number of buffers
172 
173  bool err=false;
174 
175  bn=std::max(static_cast<size_t>(8), getBufAnnounceMin());
176  for (size_t i=0; i<bn; i++)
177  {
179 
180  if (gentl->DSAllocAndAnnounceBuffer(stream, size, 0, &p) != GenTL::GC_ERR_SUCCESS)
181  {
182  err=true;
183  break;
184  }
185 
186  if (!err && gentl->DSQueueBuffer(stream, p) != GenTL::GC_ERR_SUCCESS)
187  {
188  err=true;
189  break;
190  }
191  }
192 
193  // register event
194 
195  if (!err && gentl->GCRegisterEvent(stream, GenTL::EVENT_NEW_BUFFER, &event) !=
197  {
198  err=true;
199  }
200 
201  // start streaming
202 
203  uint64_t n=GENTL_INFINITE;
204 
205  if (na > 0)
206  {
207  n=static_cast<uint64_t>(na);
208  }
209 
210  if (!err && gentl->DSStartAcquisition(stream, GenTL::ACQ_START_FLAGS_DEFAULT, n) !=
212  {
213  gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
214  err=true;
215  }
216 
217  if (!err)
218  {
219  GenApi::CCommandPtr start=parent->getRemoteNodeMap()->_GetNode("AcquisitionStart");
220  start->Execute();
221  }
222 
223  // revoke buffers in case of an error, before throwing an event
224 
225  if (err)
226  {
227  gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
228 
230  while (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
231  {
232  gentl->DSRevokeBuffer(stream, p, 0, 0);
233  }
234 
235  throw GenTLException("Stream::startStreaming()", gentl);
236  }
237 }
238 
240 {
241  std::lock_guard<std::recursive_mutex> lock(mtx);
242 
243  if (bn > 0)
244  {
245  buffer.setHandle(0);
246 
247  // do not throw exceptions as this method is also called in destructor
248 
249  GenApi::CCommandPtr stop=parent->getRemoteNodeMap()->_GetNode("AcquisitionStop");
250  stop->Execute();
251 
252  gentl->DSStopAcquisition(stream, GenTL::ACQ_STOP_FLAGS_DEFAULT);
253  gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
254  gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
255 
256  // free all buffers
257 
259  while (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
260  {
261  gentl->DSRevokeBuffer(stream, p, 0, 0);
262  }
263 
264  event=0;
265  bn=0;
266  }
267 }
268 
269 const Buffer *Stream::grab(int64_t _timeout)
270 {
271  std::lock_guard<std::recursive_mutex> lock(mtx);
272 
273  uint64_t timeout=GENTL_INFINITE;
274  if (_timeout >= 0)
275  {
276  timeout=static_cast<uint64_t>(_timeout);
277  }
278 
279  // check that streaming had been started
280 
281  if (bn == 0 && event == 0)
282  {
283  throw GenTLException("Streaming::grab(): Streaming not started");
284  }
285 
286  // enqueue previously delivered buffer if any
287 
288  if (buffer.getHandle() != 0)
289  {
290  if (gentl->DSQueueBuffer(stream, buffer.getHandle()) != GenTL::GC_ERR_SUCCESS)
291  {
292  buffer.setHandle(0);
293  throw GenTLException("Stream::grab()", gentl);
294  }
295 
296  buffer.setHandle(0);
297  }
298 
299  // wait for event
300 
302  size_t size=sizeof(GenTL::EVENT_NEW_BUFFER_DATA);
303  memset(&data, 0, size);
304 
305  GenTL::GC_ERROR err=gentl->EventGetData(event, &data, &size, timeout);
306 
307  // return 0 in case of abort and timeout and throw exception in case of
308  // another error
309 
310  if (err == GenTL::GC_ERR_ABORT || err == GenTL::GC_ERR_TIMEOUT)
311  {
312  return 0;
313  }
314  else if (err != GenTL::GC_ERR_SUCCESS)
315  {
316  throw GenTLException("Stream::grab()", gentl);
317  }
318 
319  // return buffer
320 
321  buffer.setHandle(data.BufferHandle);
322 
323  return &buffer;
324 }
325 
326 namespace
327 {
328 
329 template<class T> inline T getStreamValue(const std::shared_ptr<const GenTLWrapper> &gentl,
330  void *stream, GenTL::STREAM_INFO_CMD cmd)
331 {
332  T ret=0;
333 
335  size_t size=sizeof(T);
336 
337  if (stream != 0)
338  {
339  gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
340  }
341 
342  return ret;
343 }
344 
345 inline bool getStreamBool(const std::shared_ptr<const GenTLWrapper> &gentl,
346  void *stream, GenTL::STREAM_INFO_CMD cmd)
347 {
348  bool8_t ret=0;
349 
351  size_t size=sizeof(ret);
352 
353  if (stream != 0)
354  {
355  gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
356  }
357 
358  return ret != 0;
359 }
360 
361 }
362 
364 {
365  std::lock_guard<std::recursive_mutex> lock(mtx);
366  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_DELIVERED);
367 }
368 
370 {
371  std::lock_guard<std::recursive_mutex> lock(mtx);
372  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_UNDERRUN);
373 }
374 
376 {
377  std::lock_guard<std::recursive_mutex> lock(mtx);
378  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_ANNOUNCED);
379 }
380 
382 {
383  std::lock_guard<std::recursive_mutex> lock(mtx);
384  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_QUEUED);
385 }
386 
388 {
389  std::lock_guard<std::recursive_mutex> lock(mtx);
390  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_AWAIT_DELIVERY);
391 }
392 
394 {
395  std::lock_guard<std::recursive_mutex> lock(mtx);
396  return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_STARTED);
397 }
398 
400 {
401  std::lock_guard<std::recursive_mutex> lock(mtx);
402  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_PAYLOAD_SIZE);
403 }
404 
406 {
407  std::lock_guard<std::recursive_mutex> lock(mtx);
408  return getStreamBool(gentl, stream, GenTL::STREAM_INFO_IS_GRABBING);
409 }
410 
412 {
413  std::lock_guard<std::recursive_mutex> lock(mtx);
414  return getStreamBool(gentl, stream, GenTL::STREAM_INFO_DEFINES_PAYLOADSIZE);
415 }
416 
417 std::string Stream::getTLType()
418 {
419  std::lock_guard<std::recursive_mutex> lock(mtx);
420  std::string ret;
421 
423  char tmp[1024]="";
424  size_t size=sizeof(tmp);
425 
426  if (stream != 0)
427  {
428  if (gentl->DSGetInfo(stream, GenTL::STREAM_INFO_TLTYPE, &type, &ret, &size) ==
430  {
431  if (type == GenTL::INFO_DATATYPE_STRING)
432  {
433  ret=tmp;
434  }
435  }
436  }
437 
438  return ret;
439 }
440 
442 {
443  std::lock_guard<std::recursive_mutex> lock(mtx);
444  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_CHUNKS_MAX);
445 }
446 
448 {
449  std::lock_guard<std::recursive_mutex> lock(mtx);
450  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ANNOUNCE_MIN);
451 }
452 
454 {
455  std::lock_guard<std::recursive_mutex> lock(mtx);
456  return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ALIGNMENT);
457 }
458 
459 std::shared_ptr<GenApi::CNodeMapRef> Stream::getNodeMap()
460 {
461  std::lock_guard<std::recursive_mutex> lock(mtx);
462  if (stream != 0 && !nodemap)
463  {
464  cport=std::shared_ptr<CPort>(new CPort(gentl, &stream));
466  }
467 
468  return nodemap;
469 }
470 
471 void *Stream::getHandle() const
472 {
473  return stream;
474 }
475 
476 }
uint64_t getNumDelivered()
Returns some information about the stream.
Definition: stream.cc:363
const Buffer * grab(int64_t timeout=-1)
Wait for the next image or data and return it in a buffer object.
Definition: stream.cc:269
int n_open
Definition: stream.h:288
std::shared_ptr< GenApi::CNodeMapRef > nodemap
Definition: stream.h:294
size_t bn
Definition: stream.h:291
size_t getNumAwaitDelivery()
Returns some information about the stream.
Definition: stream.cc:387
This is the port definition that connects GenAPI to GenTL.
Definition: cport.h:52
std::recursive_mutex mtx
Definition: stream.h:286
void * BUFFER_HANDLE
Definition: GenTL_v1_5.h:227
std::string getTLType()
Returns some information about the stream.
Definition: stream.cc:417
void * getHandle() const
Get internal stream handle.
Definition: buffer.cc:531
__int64 int64_t
Definition: config-win32.h:21
struct S_EVENT_NEW_BUFFER EVENT_NEW_BUFFER_DATA
Buffer buffer
Definition: stream.h:280
std::string id
Definition: stream.h:284
size_t getNumAnnounced()
Returns some information about the stream.
Definition: stream.cc:375
std::shared_ptr< Device > getParent() const
Returns the pointer to the parent device object.
Definition: stream.cc:82
void stopStreaming()
Stops streaming.
Definition: stream.cc:239
const std::string & getID() const
Get the internal ID of this stream.
Definition: stream.cc:87
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:393
interface GENAPI_DECL_ABSTRACT IInteger
Interface for integer properties.
Definition: IInteger.h:61
std::shared_ptr< const GenTLWrapper > gentl
Definition: stream.h:283
int32_t GC_ERROR
Definition: GenTL_v1_5.h:181
void * stream
Definition: stream.h:289
void startStreaming(int na=-1)
Allocates buffers and registers internal events if necessary and starts streaming.
Definition: stream.cc:135
size_t getNumChunksMax()
Returns some information about the stream.
Definition: stream.cc:441
size_t getNumQueued()
Returns some information about the stream.
Definition: stream.cc:381
bool getDefinesPayloadsize()
Returns some information about the stream.
Definition: stream.cc:411
The buffer class encapsulates a Genicam buffer that is provided by a stream.
Definition: buffer.h:115
size_t getPayloadSize()
Returns some information about the stream.
Definition: stream.cc:399
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:53
std::shared_ptr< CPort > cport
Definition: stream.h:293
uint8_t bool8_t
Definition: GenTL_v1_5.h:105
bool getIsGrabbing()
Returns some information about the stream.
Definition: stream.cc:405
void * getHandle() const
Get internal stream handle.
Definition: stream.cc:471
std::shared_ptr< Device > parent
Definition: stream.h:282
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:459
void * event
Definition: stream.h:290
Definition: buffer.cc:42
void open()
Opens the stream for working with it.
Definition: stream.cc:92
void setHandle(void *handle)
Set the buffer handle that this object should manage.
Definition: buffer.cc:130
void close()
Closes the stream.
Definition: stream.cc:115
#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:369
size_t getBufAnnounceMin()
Returns some information about the stream.
Definition: stream.cc:447
size_t getBufAlignment()
Returns some information about the stream.
Definition: stream.cc:453


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Thu Jun 6 2019 19:10:54