CVB++ 15.0
decl_stream.hpp
1#pragma once
2
3#include <chrono>
4#include <exception>
5#include <limits>
6#include <memory>
7
8#include "../../_cexports/c_driver.h"
9
10#include "../../global.hpp"
11#include "../../exception.hpp"
12
13#include "../driver.hpp"
14#include "../stream_base.hpp"
15
16#include "../../utilities/system_info.hpp"
17
18namespace Cvb
19{
20
21 CVB_BEGIN_INLINE_NS
22
23 namespace Driver
24 {
25
27
32 class Stream : public StreamBase
33 {
34 public:
36 {
37 return acquisitionEngine_->AcquisitionInterface();
38 }
39
41
46 {
47 if (acquisitionEngine_ && acquisitionInterface == acquisitionEngine_->AcquisitionInterface())
48 return;
49
50 switch (acquisitionInterface)
51 {
53 acquisitionEngine_ = std::make_unique<Grab2>(*Parent());
54 break;
55
57 acquisitionEngine_ = std::make_unique<Grab>(*Parent());
58 break;
59
60 default:
61 throw std::runtime_error("no suitable acquisition interface implemented");
62 break;
63 }
64 }
65
66 void Start() override
67 {
68 acquisitionEngine_->Start();
69 }
70
71 void Stop() override
72 {
73 if (!acquisitionEngine_->TryStop())
74 throw std::runtime_error("failed to stop acquisition");
75 }
76
77 bool TryStop() noexcept override
78 {
79 return acquisitionEngine_->TryStop();
80 }
81
82 void Abort() override
83 {
84 if (!acquisitionEngine_->TryAbort())
85 throw std::runtime_error("failed to abort acquisition");
86 }
87
88 bool TryAbort() noexcept override
89 {
90 return acquisitionEngine_->TryAbort();
91 }
92
94
102 bool IsRunning() const noexcept
103 {
104 return acquisitionEngine_->IsRunning();
105 }
106
107 bool IsIndexed() const noexcept override
108 {
109 return false;
110 }
111
113
118 double Statistics(StreamInfo query) const
119 {
120 return statistics_->Query(query);
121 }
122
124
129 template <class T>
130 T Statistics(StreamInfo query) const
131 {
132 return static_cast<T>(Statistics(query));
133 }
134
136
140 virtual RingBufferPtr RingBuffer() const noexcept
141 {
142 return RingBufferPtr();
143 }
144
146
152 template <class T, class Rep, class Period>
154 {
155 static_assert(std::is_base_of<StreamImage, T>::value, "CVB: StreamImage must be a base of T");
156 auto baseImage = WaitFor(timeSpan, waitStatus);
157 if (!baseImage)
158 return std::shared_ptr<T>();
159
160 auto image = std::dynamic_pointer_cast<T>(baseImage);
161 if (!image)
162 throw std::runtime_error("stream image cannot be cast");
163
164 return image;
165 }
166
168
174 template <class Rep, class Period>
176
178
183 template <class T, class Rep, class Period>
185 {
186 static_assert(std::is_base_of<StreamImage, T>::value, "CVB: StreamImage must be a base of T");
187 WaitResult<T> waitResult;
188 auto baseImage = WaitFor(timeSpan, waitResult.Status);
189 if (!baseImage)
190 return waitResult;
191
192 auto image = std::dynamic_pointer_cast<T>(baseImage);
193 if (!image)
194 throw std::runtime_error("stream image cannot be cast");
195
196 waitResult.Image = image;
197 return waitResult;
198 }
199
201
206 template <class Rep, class Period>
211
213
218 template <class T>
220 {
221 static_assert(std::is_base_of<StreamImage, T>::value, "CVB: StreamImage must be a base of T");
222 auto baseImage = Wait(waitStatus);
223 if (!baseImage)
224 return std::unique_ptr<T>();
225 auto image = std::dynamic_pointer_cast<T>(baseImage);
226 if (!image)
227 throw std::runtime_error("stream image cannot be cast");
228
229 return image;
230 }
231
233
239 {
240#ifdef max
241# undef max
242#endif
243 while (true)
244 {
246 if (waitStatus == WaitStatus::Timeout)
247 continue;
248 return std::move(image);
249 }
250 }
251
253
257 template <class T>
259 {
260 static_assert(std::is_base_of<StreamImage, T>::value, "CVB: StreamImage must be a base of T");
261 WaitResult<T> waitResult;
262 auto baseImage = Wait(waitResult.Status);
263 if (!baseImage)
264 return waitResult;
265 auto image = std::dynamic_pointer_cast<T>(baseImage);
266 if (!image)
267 throw std::runtime_error("stream image cannot be cast");
268
269 waitResult.Image = image;
270 return waitResult;
271 }
272
274
279 {
280#ifdef max
281# undef max
282#endif
283 while (true)
284 {
286 if (waitResult.Status == WaitStatus::Timeout)
287 continue;
288 return waitResult;
289 }
290 }
291
293
299 template <class T, class Rep, class Period>
301 {
302 static_assert(std::is_base_of<StreamImage, T>::value, "CVB: StreamImage must be a base of T");
303 auto baseImage = GetTimedSnapshot(timeSpan, waitStatus);
304 if (!baseImage)
305 return std::unique_ptr<T>();
306 auto image = std::dynamic_pointer_cast<T>(baseImage);
307 if (!image)
308 throw std::runtime_error("stream image cannot be cast");
309
310 return image;
311 }
312
314
320 template <class Rep, class Period>
322
324
329 template <class T, class Rep, class Period>
331 {
332 static_assert(std::is_base_of<StreamImage, T>::value, "CVB: StreamImage must be a base of T");
333 WaitResult<T> waitResult;
334 auto baseImage = GetTimedSnapshot(timeSpan, waitResult.Status);
335 if (!baseImage)
336 return waitResult;
337 auto image = std::dynamic_pointer_cast<T>(baseImage);
338 if (!image)
339 throw std::runtime_error("stream image cannot be cast");
340
341 waitResult.Image = image;
342 return waitResult;
343 }
344
346
351 template <class Rep, class Period>
356
358
364 {
365#ifdef max
366# undef max
367#endif
368 while (true)
369 {
370 auto image =
372 if (waitStatus == WaitStatus::Timeout)
373 continue;
374 return std::move(image);
375 }
376 }
377
379
384 {
385#ifdef max
386# undef max
387#endif
388 while (true)
389 {
391 if (waitResult.Status == WaitStatus::Timeout)
392 continue;
393 return waitResult;
394 }
395 }
396
397 protected:
398 explicit Stream(const DevicePtr &device);
399
400 virtual StreamImagePtr MakeStreamImage() = 0;
401
402 virtual StreamImagePtr MakeSnapshotImage() = 0;
403
404 private:
405 class AcquisitionEngine
406 {
407 public:
408 static Cvb::Driver::AcquisitionInterface GetBestAcquisitionInterface(const Device &device);
409
410 explicit AcquisitionEngine(const Device &device)
411 : device_(device)
412 , lastTimeout_(static_cast<uint32_t>(Utilities::SystemInfo::DefaultTimeout().count()))
413 {
414 }
415
416 AcquisitionEngine(const AcquisitionEngine &other) = delete;
417 AcquisitionEngine &operator=(const AcquisitionEngine &other) = delete;
418 AcquisitionEngine(AcquisitionEngine &&other) = delete;
419 AcquisitionEngine &operator=(AcquisitionEngine &&other) = delete;
420
421 virtual ~AcquisitionEngine() = default;
422
423 template <class Rep, class Period>
424 void WaitFor(const std::chrono::duration<Rep, Period> &timeSpan, WaitStatus &waitResult)
425 {
426#ifdef max
427# undef max
428#endif
429 auto msTimeSpan = std::chrono::duration_cast<std::chrono::milliseconds>(timeSpan).count();
430 if (msTimeSpan > static_cast<std::chrono::milliseconds::rep>(std::numeric_limits<std::uint32_t>::max()))
431 throw std::overflow_error("wait timeout must fit to unsigned 32 bit integer in ms");
432 auto result = TryWaitFor(static_cast<uint32_t>(msTimeSpan));
433 if (result < 0)
434 {
435 switch (result)
436 {
438 waitResult = WaitStatus::Timeout;
439 return;
440
442 waitResult = WaitStatus::Abort;
443 return;
444
445 default:
446 std::rethrow_exception(CvbException::FromCvbResult(result, "WaitFor failed"));
447 }
448 }
449 waitResult = WaitStatus::Ok;
450 }
451
452 template <class Rep, class Period>
453 void GetTimedSnapshot(const std::chrono::duration<Rep, Period> &timeSpan, WaitStatus &waitResult)
454 {
455#ifdef max
456# undef max
457#endif
458 auto msTimeSpan = std::chrono::duration_cast<std::chrono::milliseconds>(timeSpan).count();
459 if (msTimeSpan > static_cast<std::chrono::milliseconds::rep>(std::numeric_limits<std::uint32_t>::max()))
460 throw std::overflow_error("wait timeout must fit to unsigned 32 bit integer in ms");
461 auto result = TryGetTimedSnapshot(static_cast<uint32_t>(msTimeSpan));
462 if (result < 0)
463 {
464 switch (result)
465 {
467 waitResult = WaitStatus::Timeout;
468 return;
469
471 waitResult = WaitStatus::Abort;
472 return;
473
474 default:
475 std::rethrow_exception(CvbException::FromCvbResult(result, "WaitFor failed"));
476 }
477 }
478 waitResult = WaitStatus::Ok;
479 }
480
481 void SetTimeout(uint32_t msTimeSpan);
482
483 virtual void Start() = 0;
484
485 virtual bool TryStop() noexcept = 0;
486
487 virtual bool TryAbort() noexcept = 0;
488
489 virtual bool IsRunning() const noexcept = 0;
490
491 virtual Cvb::Driver::AcquisitionInterface AcquisitionInterface() const noexcept = 0;
492
493 virtual int TryWaitFor(uint32_t msTineSpan) = 0;
494
495 virtual int TryGetTimedSnapshot(uint32_t msTineSpan) = 0;
496
497 protected:
498 void *Handle() const noexcept;
499
500 private:
501 const Device &device_;
502
503 uint32_t lastTimeout_;
504 };
505
506 class Grab : public AcquisitionEngine
507 {
508 public:
509 explicit Grab(const Device &device);
510
511 void Start() override
512 {
513 if (isRunning_)
514 std::rethrow_exception(CvbException::FromCvbResult(ErrorCodes::CVB_BUSY, "acquisition already running"));
515 isRunning_ = true;
516 }
517
518 bool TryStop() noexcept override
519 {
520 isRunning_ = false;
521 return true;
522 }
523
524 bool TryAbort() noexcept override
525 {
526 return TryStop();
527 }
528
529 bool IsRunning() const noexcept override
530 {
531 return isRunning_;
532 }
533
534 Cvb::Driver::AcquisitionInterface AcquisitionInterface() const noexcept override
535 {
537 }
538
539 int TryWaitFor(uint32_t msTineSpan) override;
540
541 int TryGetTimedSnapshot(uint32_t msTineSpan) override;
542
543 private:
544 bool isRunning_;
545 };
546
547 class Grab2 : public AcquisitionEngine
548 {
549 public:
550 explicit Grab2(const Device &device);
551
552 void Start() override;
553
554 bool TryStop() noexcept override;
555
556 bool TryAbort() noexcept override;
557
558 bool IsRunning() const noexcept override;
559
560 Cvb::Driver::AcquisitionInterface AcquisitionInterface() const noexcept override
561 {
563 }
564
565 int TryWaitFor(uint32_t msTineSpan) override;
566
567 int TryGetTimedSnapshot(uint32_t msTineSpan) override;
568 };
569
570 class StreamStats
571 {
572 public:
573 static std::unique_ptr<StreamStats> CreateGrab2(const Device &device)
574 {
575 return std::make_unique<Grab2Stats>(device);
576 }
577
578 static std::unique_ptr<StreamStats> CreateNo(const Device &device)
579 {
580 return std::make_unique<NoStats>(device);
581 }
582
583 explicit StreamStats(const Device &device)
584 : device_(device)
585 {
586 }
587
588 StreamStats(const StreamStats &other) = delete;
589 StreamStats &operator=(const StreamStats &other) = delete;
590 StreamStats(StreamStats &&other) = delete;
591 StreamStats &operator=(StreamStats &&other) = delete;
592 virtual ~StreamStats() = default;
593
594 double Query(StreamInfo query) const
595 {
597 if (!TryGetValue(query, value))
598 throw std::runtime_error("statistics query not supported");
599 return value;
600 }
601
602 protected:
603 virtual bool TryGetValue(StreamInfo query, double &value) const noexcept = 0;
604
605 void *Handle() const noexcept;
606
607 private:
608 const Device &device_;
609 };
610
611 class Grab2Stats : public StreamStats
612 {
613 public:
614 explicit Grab2Stats(const Device &device)
615 : StreamStats(device)
616 {
617 }
618
619 protected:
620 bool TryGetValue(StreamInfo query, double &value) const noexcept override;
621 };
622
623 class NoStats : public StreamStats
624 {
625 public:
626 explicit NoStats(const Device &device)
627 : StreamStats(device)
628 {
629 }
630
631 protected:
632 bool TryGetValue(StreamInfo, double &) const noexcept override
633 {
634 return false;
635 }
636 };
637
638 std::unique_ptr<AcquisitionEngine> acquisitionEngine_;
639
640 std::unique_ptr<StreamStats> statistics_;
641 };
642
643 } // namespace Driver
644
645 using Driver::Stream;
646
647 CVB_END_INLINE_NS
648
649} // namespace Cvb
Generic CVB physical device.
Definition decl_device.hpp:39
DevicePtr Parent() const noexcept
Gets the parent device of this stream.
Definition stream_base.hpp:42
std::shared_ptr< T > WaitFor(const std::chrono::duration< Rep, Period > &timeSpan, WaitStatus &waitStatus)
Waits for the given time span for the next acquired image.
Definition decl_stream.hpp:153
void Abort() override
Stops the acquisition of images immediately.
Definition decl_stream.hpp:82
double Statistics(StreamInfo query) const
Gets statistics value if supported.
Definition decl_stream.hpp:118
StreamImagePtr GetSnapshot(WaitStatus &waitStatus)
Acquires a single image and returns it.
Definition decl_stream.hpp:363
WaitResult< T > Wait()
Waits for ever for the next acquired image and returns it.
Definition decl_stream.hpp:258
void Start() override
Starts the acquisition.
Definition decl_stream.hpp:66
Cvb::Driver::AcquisitionInterface AcquisitionInterface() const noexcept override
Gets the interface of this implementation.
Definition decl_stream.hpp:35
bool IsRunning() const noexcept
Gets whether the acquisition is currently active.
Definition decl_stream.hpp:102
std::shared_ptr< T > GetTimedSnapshot(const std::chrono::duration< Rep, Period > &timeSpan, WaitStatus &waitStatus)
Acquires a single image for a given time span and returns it.
Definition decl_stream.hpp:300
T Statistics(StreamInfo query) const
Gets statistics value if supported.
Definition decl_stream.hpp:130
WaitResult< StreamImage > Wait()
Waits for ever for the next acquired image and returns it.
Definition decl_stream.hpp:278
void Stop() override
Stops the acquisition.
Definition decl_stream.hpp:71
bool IsIndexed() const noexcept override
Gets whether this stream is an indexed stream.
Definition decl_stream.hpp:107
bool TryAbort() noexcept override
Stops the acquisition of images immediately.
Definition decl_stream.hpp:88
WaitResult< StreamImage > WaitFor(const std::chrono::duration< Rep, Period > &timeSpan)
Waits for the given time span for the next acquired image.
Definition decl_stream.hpp:207
WaitResult< StreamImage > GetSnapshot()
Acquires a single image and returns it.
Definition decl_stream.hpp:383
std::shared_ptr< T > Wait(WaitStatus &waitStatus)
Waits forever for the next acquired image and returns it.
Definition decl_stream.hpp:219
WaitResult< T > WaitFor(const std::chrono::duration< Rep, Period > &timeSpan)
Waits for the given time span for the next acquired image.
Definition decl_stream.hpp:184
void SetAcquisitionInterface(Cvb::Driver::AcquisitionInterface acquisitionInterface)
Sets the interface of this implementation.
Definition decl_stream.hpp:45
virtual RingBufferPtr RingBuffer() const noexcept
Gets the ring buffer interface object if present.
Definition decl_stream.hpp:140
WaitResult< StreamImage > GetTimedSnapshot(const std::chrono::duration< Rep, Period > &timeSpan)
Acquires a single image for a given time span and returns it.
Definition decl_stream.hpp:352
bool TryStop() noexcept override
Stops the acquisition.
Definition decl_stream.hpp:77
StreamImagePtr Wait(WaitStatus &waitStatus)
Waits for ever for the next acquired image and returns it.
Definition decl_stream.hpp:238
WaitResult< T > GetTimedSnapshot(const std::chrono::duration< Rep, Period > &timeSpan)
Acquires a single image for a given time span and returns it.
Definition decl_stream.hpp:330
T duration_cast(T... args)
T max(T... args)
T move(T... args)
Namespace for driver or device related operations.
Definition decl_composite.hpp:27
@ Stream
Definition driver.hpp:432
std::shared_ptr< StreamImage > StreamImagePtr
Convenience shared pointer for StreamImage.
Definition driver.hpp:84
StreamInfo
Queryable stream information.
Definition driver.hpp:453
std::shared_ptr< RingBuffer > RingBufferPtr
Convenience shared pointer for RingBuffer.
Definition driver.hpp:36
AcquisitionInterface
Known acquisition CVB interfaces.
Definition driver.hpp:437
@ Grab2
Ring buffer / queue based acquisition.
Definition driver.hpp:441
@ Grabber
Basic grabber interface for single image acquisition.
Definition driver.hpp:439
const int CVB_BUSY
Hardware busy.
Definition exception.hpp:57
const int CVB_GRABABORTED
Failure because grab was aborted.
Definition exception.hpp:61
const int CVB_TIMEOUT
Timeout in function.
Definition exception.hpp:29
Namespace for helpers and utilities, which are not directly related to image processing.
Definition version.hpp:16
Root namespace for the Image Manager interface.
Definition c_bayer_to_rgb.h:17
WaitStatus
Status after waiting for an image to be returned.
Definition global.hpp:396
@ Abort
The acquisition has been stopped asynchronously, there is no image buffer.
Definition global.hpp:402
@ Ok
Everything is fine, a new image arrived.
Definition global.hpp:398
@ Timeout
A timeout occurred, no image buffer has been returned.
Definition global.hpp:400
std::shared_ptr< Device > DevicePtr
Convenience shared pointer for Device.
Definition global.hpp:98
T dynamic_pointer_cast(T... args)
T quiet_NaN(T... args)
T rethrow_exception(T... args)
A combined result returned after waiting for a image.
Definition driver.hpp:393
WaitStatus Status
The status.
Definition driver.hpp:395
std::shared_ptr< T > Image
The returned image by wait if applicable cast to the provided type.
Definition driver.hpp:397