stream.cc
Go to the documentation of this file.
00001 /*
00002  * This file is part of the rc_genicam_api package.
00003  *
00004  * Copyright (c) 2017 Roboception GmbH
00005  * All rights reserved
00006  *
00007  * Author: Heiko Hirschmueller
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions are met:
00011  *
00012  * 1. Redistributions of source code must retain the above copyright notice,
00013  * this list of conditions and the following disclaimer.
00014  *
00015  * 2. Redistributions in binary form must reproduce the above copyright notice,
00016  * this list of conditions and the following disclaimer in the documentation
00017  * and/or other materials provided with the distribution.
00018  *
00019  * 3. Neither the name of the copyright holder nor the names of its contributors
00020  * may be used to endorse or promote products derived from this software without
00021  * specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  * POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 #include "stream.h"
00037 
00038 #include "gentl_wrapper.h"
00039 #include "exception.h"
00040 #include "cport.h"
00041 
00042 #include <iostream>
00043 
00044 namespace rcg
00045 {
00046 
00047 Stream::Stream(const std::shared_ptr<Device> &_parent,
00048                const std::shared_ptr<const GenTLWrapper> &_gentl, const char *_id) :
00049                buffer(_gentl, this)
00050 {
00051   parent=_parent;
00052   gentl=_gentl;
00053   id=_id;
00054 
00055   n_open=0;
00056   stream=0;
00057   event=0;
00058   bn=0;
00059 }
00060 
00061 Stream::~Stream()
00062 {
00063   try
00064   {
00065     stopStreaming();
00066 
00067     if (stream != 0)
00068     {
00069       gentl->DSClose(stream);
00070     }
00071   }
00072   catch (...) // do not throw exceptions in destructor
00073   { }
00074 }
00075 
00076 std::shared_ptr<Device> Stream::getParent() const
00077 {
00078   return parent;
00079 }
00080 
00081 const std::string &Stream::getID() const
00082 {
00083   return id;
00084 }
00085 
00086 void Stream::open()
00087 {
00088   if (n_open == 0)
00089   {
00090     if (parent->getHandle() != 0)
00091     {
00092       if (gentl->DevOpenDataStream(parent->getHandle(), id.c_str(), &stream) !=
00093           GenTL::GC_ERR_SUCCESS)
00094       {
00095         throw GenTLException("Stream::open()", gentl);
00096       }
00097     }
00098     else
00099     {
00100       throw GenTLException("Stream::open(): Device must be opened before open before opening a stream");
00101     }
00102   }
00103 
00104   n_open++;
00105 }
00106 
00107 void Stream::close()
00108 {
00109   if (n_open > 0)
00110   {
00111     n_open--;
00112   }
00113 
00114   if (n_open == 0)
00115   {
00116     stopStreaming();
00117     gentl->DSClose(stream);
00118     stream=0;
00119 
00120     nodemap=0;
00121     cport=0;
00122   }
00123 }
00124 
00125 void Stream::startStreaming(int na)
00126 {
00127   buffer.setHandle(0);
00128 
00129   if (stream == 0)
00130   {
00131     throw GenTLException("Stream::startStreaming(): Stream is not open");
00132   }
00133 
00134   // stop streaming if it is currently running
00135 
00136   if (bn > 0)
00137   {
00138     stopStreaming();
00139   }
00140 
00141   // determine maximum buffer size from transport layer or remote device
00142 
00143   size_t size=0;
00144   if (getDefinesPayloadsize())
00145   {
00146     size=getPayloadSize();
00147   }
00148   else
00149   {
00150     std::shared_ptr<GenApi::CNodeMapRef> nodemap=parent->getRemoteNodeMap();
00151     GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(nodemap->_GetNode("PayloadSize"));
00152 
00153     if (GenApi::IsReadable(p))
00154     {
00155       size=p->GetValue();
00156     }
00157   }
00158 
00159   // announce and queue the minimum number of buffers
00160 
00161   bool err=false;
00162 
00163   bn=std::max(static_cast<size_t>(8), getBufAnnounceMin());
00164   for (size_t i=0; i<bn; i++)
00165   {
00166     GenTL::BUFFER_HANDLE p=0;
00167 
00168     if (gentl->DSAllocAndAnnounceBuffer(stream, size, 0, &p) != GenTL::GC_ERR_SUCCESS)
00169     {
00170       err=true;
00171       break;
00172     }
00173 
00174     if (!err && gentl->DSQueueBuffer(stream, p) != GenTL::GC_ERR_SUCCESS)
00175     {
00176       err=true;
00177       break;
00178     }
00179   }
00180 
00181   // register event
00182 
00183   if (!err && gentl->GCRegisterEvent(stream, GenTL::EVENT_NEW_BUFFER, &event) !=
00184       GenTL::GC_ERR_SUCCESS)
00185   {
00186     err=true;
00187   }
00188 
00189   // start streaming
00190 
00191   uint64_t n=GENTL_INFINITE;
00192 
00193   if (na > 0)
00194   {
00195     n=static_cast<uint64_t>(na);
00196   }
00197 
00198   if (!err && gentl->DSStartAcquisition(stream, GenTL::ACQ_START_FLAGS_DEFAULT, n) !=
00199       GenTL::GC_ERR_SUCCESS)
00200   {
00201     gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
00202     err=true;
00203   }
00204 
00205   if (!err)
00206   {
00207     GenApi::CCommandPtr start=parent->getRemoteNodeMap()->_GetNode("AcquisitionStart");
00208     start->Execute();
00209   }
00210 
00211   // revoke buffers in case of an error, before throwing an event
00212 
00213   if (err)
00214   {
00215     gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
00216 
00217     GenTL::BUFFER_HANDLE p=0;
00218     while (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
00219     {
00220       gentl->DSRevokeBuffer(stream, p, 0, 0);
00221     }
00222 
00223     throw GenTLException("Stream::startStreaming()", gentl);
00224   }
00225 }
00226 
00227 void Stream::stopStreaming()
00228 {
00229   if (bn > 0)
00230   {
00231     buffer.setHandle(0);
00232 
00233     // do not throw exceptions as this method is also called in destructor
00234 
00235     GenApi::CCommandPtr stop=parent->getRemoteNodeMap()->_GetNode("AcquisitionStop");
00236     stop->Execute();
00237 
00238     gentl->DSStopAcquisition(stream, GenTL::ACQ_STOP_FLAGS_DEFAULT);
00239     gentl->GCUnregisterEvent(stream, GenTL::EVENT_NEW_BUFFER);
00240     gentl->DSFlushQueue(stream, GenTL::ACQ_QUEUE_ALL_DISCARD);
00241 
00242     // free all buffers
00243 
00244     GenTL::BUFFER_HANDLE p=0;
00245     while (gentl->DSGetBufferID(stream, 0, &p) == GenTL::GC_ERR_SUCCESS)
00246     {
00247       gentl->DSRevokeBuffer(stream, p, 0, 0);
00248     }
00249 
00250     event=0;
00251     bn=0;
00252   }
00253 }
00254 
00255 const Buffer *Stream::grab(int64_t _timeout)
00256 {
00257   uint64_t timeout=GENTL_INFINITE;
00258   if (_timeout >= 0)
00259   {
00260     timeout=_timeout;
00261   }
00262 
00263   // check that streaming had been started
00264 
00265   if (bn == 0 && event == 0)
00266   {
00267     throw GenTLException("Streaming::grab(): Streaming not started");
00268   }
00269 
00270   // enqueue previously delivered buffer if any
00271 
00272   if (buffer.getHandle() != 0)
00273   {
00274     if (gentl->DSQueueBuffer(stream, buffer.getHandle()) != GenTL::GC_ERR_SUCCESS)
00275     {
00276       buffer.setHandle(0);
00277       throw GenTLException("Stream::grab()", gentl);
00278     }
00279 
00280     buffer.setHandle(0);
00281   }
00282 
00283   // wait for event
00284 
00285   GenTL::EVENT_NEW_BUFFER_DATA data;
00286   size_t size=sizeof(GenTL::EVENT_NEW_BUFFER_DATA);
00287   memset(&data, 0, size);
00288 
00289   GenTL::GC_ERROR err=gentl->EventGetData(event, &data, &size, timeout);
00290 
00291   // return 0 in case of abort and timeout and throw exception in case of
00292   // another error
00293 
00294   if (err == GenTL::GC_ERR_ABORT || err == GenTL::GC_ERR_TIMEOUT)
00295   {
00296     return 0;
00297   }
00298   else if (err != GenTL::GC_ERR_SUCCESS)
00299   {
00300     throw GenTLException("Stream::grab()", gentl);
00301   }
00302 
00303   // return buffer
00304 
00305   buffer.setHandle(data.BufferHandle);
00306 
00307   return &buffer;
00308 }
00309 
00310 namespace
00311 {
00312 
00313 template<class T> inline T getStreamValue(const std::shared_ptr<const GenTLWrapper> &gentl,
00314                                           void *stream, GenTL::STREAM_INFO_CMD cmd)
00315 {
00316   T ret=0;
00317 
00318   GenTL::INFO_DATATYPE type;
00319   size_t size=sizeof(T);
00320 
00321   if (stream != 0)
00322   {
00323     gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
00324   }
00325 
00326   return ret;
00327 }
00328 
00329 inline bool getStreamBool(const std::shared_ptr<const GenTLWrapper> &gentl,
00330                           void *stream, GenTL::STREAM_INFO_CMD cmd)
00331 {
00332   bool8_t ret=0;
00333 
00334   GenTL::INFO_DATATYPE type;
00335   size_t size=sizeof(ret);
00336 
00337   if (stream != 0)
00338   {
00339     gentl->DSGetInfo(stream, cmd, &type, &ret, &size);
00340   }
00341 
00342   return ret != 0;
00343 }
00344 
00345 }
00346 
00347 uint64_t Stream::getNumDelivered() const
00348 {
00349   return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_DELIVERED);
00350 }
00351 
00352 uint64_t Stream::getNumUnderrun() const
00353 {
00354   return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_UNDERRUN);
00355 }
00356 
00357 size_t Stream::getNumAnnounced() const
00358 {
00359   return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_ANNOUNCED);
00360 }
00361 
00362 size_t Stream::getNumQueued() const
00363 {
00364   return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_QUEUED);
00365 }
00366 
00367 size_t Stream::getNumAwaitDelivery() const
00368 {
00369   return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_AWAIT_DELIVERY);
00370 }
00371 
00372 uint64_t Stream::getNumStarted() const
00373 {
00374   return getStreamValue<uint64_t>(gentl, stream, GenTL::STREAM_INFO_NUM_STARTED);
00375 }
00376 
00377 size_t Stream::getPayloadSize() const
00378 {
00379   return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_PAYLOAD_SIZE);
00380 }
00381 
00382 bool Stream::getIsGrabbing() const
00383 {
00384   return getStreamBool(gentl, stream, GenTL::STREAM_INFO_IS_GRABBING);
00385 }
00386 
00387 bool Stream::getDefinesPayloadsize() const
00388 {
00389   return getStreamBool(gentl, stream, GenTL::STREAM_INFO_DEFINES_PAYLOADSIZE);
00390 }
00391 
00392 std::string Stream::getTLType() const
00393 {
00394   std::string ret;
00395 
00396   GenTL::INFO_DATATYPE type;
00397   char tmp[1024]="";
00398   size_t size=sizeof(tmp);
00399 
00400   if (stream != 0)
00401   {
00402     if (gentl->DSGetInfo(stream, GenTL::STREAM_INFO_TLTYPE, &type, &ret, &size) ==
00403         GenTL::GC_ERR_SUCCESS)
00404     {
00405       if (type == GenTL::INFO_DATATYPE_STRING)
00406       {
00407         ret=tmp;
00408       }
00409     }
00410   }
00411 
00412   return ret;
00413 }
00414 
00415 size_t Stream::getNumChunksMax() const
00416 {
00417   return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_NUM_CHUNKS_MAX);
00418 }
00419 
00420 size_t Stream::getBufAnnounceMin() const
00421 {
00422   return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ANNOUNCE_MIN);
00423 }
00424 
00425 size_t Stream::getBufAlignment() const
00426 {
00427   return getStreamValue<size_t>(gentl, stream, GenTL::STREAM_INFO_BUF_ALIGNMENT);
00428 }
00429 
00430 std::shared_ptr<GenApi::CNodeMapRef> Stream::getNodeMap()
00431 {
00432   if (stream != 0 && !nodemap)
00433   {
00434     cport=std::shared_ptr<CPort>(new CPort(gentl, &stream));
00435     nodemap=allocNodeMap(gentl, stream, cport.get());
00436   }
00437 
00438   return nodemap;
00439 }
00440 
00441 void *Stream::getHandle() const
00442 {
00443   return stream;
00444 }
00445 
00446 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:06