dummy_source.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #ifndef OPENCV_GAPI_PIPELINE_MODELING_TOOL_DUMMY_SOURCE_HPP
  2. #define OPENCV_GAPI_PIPELINE_MODELING_TOOL_DUMMY_SOURCE_HPP
  3. #include <thread>
  4. #include <memory>
  5. #include <chrono>
  6. #include <opencv2/gapi.hpp>
  7. #include <opencv2/gapi/streaming/cap.hpp> // cv::gapi::wip::IStreamSource
  8. #include "utils.hpp"
  9. class DummySource final: public cv::gapi::wip::IStreamSource {
  10. public:
  11. using WaitStrategy = std::function<void(std::chrono::microseconds)>;
  12. using Ptr = std::shared_ptr<DummySource>;
  13. using ts_t = std::chrono::microseconds;
  14. template <typename DurationT>
  15. DummySource(const DurationT latency,
  16. const OutputDescr& output,
  17. const bool drop_frames,
  18. WaitStrategy&& wait);
  19. bool pull(cv::gapi::wip::Data& data) override;
  20. cv::GMetaArg descr_of() const override;
  21. private:
  22. int64_t m_latency;
  23. cv::Mat m_mat;
  24. bool m_drop_frames;
  25. int64_t m_next_tick_ts = -1;
  26. int64_t m_curr_seq_id = 0;
  27. WaitStrategy m_wait;
  28. };
  29. template <typename DurationT>
  30. DummySource::DummySource(const DurationT latency,
  31. const OutputDescr& output,
  32. const bool drop_frames,
  33. WaitStrategy&& wait)
  34. : m_latency(std::chrono::duration_cast<ts_t>(latency).count()),
  35. m_drop_frames(drop_frames),
  36. m_wait(std::move(wait)) {
  37. utils::createNDMat(m_mat, output.dims, output.precision);
  38. utils::generateRandom(m_mat);
  39. }
  40. bool DummySource::pull(cv::gapi::wip::Data& data) {
  41. using namespace std::chrono;
  42. using namespace cv::gapi::streaming;
  43. // NB: Wait m_latency before return the first frame.
  44. if (m_next_tick_ts == -1) {
  45. m_next_tick_ts = utils::timestamp<ts_t>() + m_latency;
  46. }
  47. int64_t curr_ts = utils::timestamp<ts_t>();
  48. if (curr_ts < m_next_tick_ts) {
  49. /*
  50. * curr_ts
  51. * |
  52. * ------|----*-----|------->
  53. * ^
  54. * m_next_tick_ts
  55. *
  56. *
  57. * NB: New frame will be produced at the m_next_tick_ts point.
  58. */
  59. m_wait(ts_t{m_next_tick_ts - curr_ts});
  60. } else if (m_latency != 0) {
  61. /*
  62. * curr_ts
  63. * +1 +2 |
  64. * |----------|----------|----------|----*-----|------->
  65. * ^ ^
  66. * m_next_tick_ts ------------->
  67. *
  68. */
  69. // NB: Count how many frames have been produced since last pull (m_next_tick_ts).
  70. int64_t num_frames =
  71. static_cast<int64_t>((curr_ts - m_next_tick_ts) / m_latency);
  72. // NB: Shift m_next_tick_ts to the nearest tick before curr_ts.
  73. m_next_tick_ts += num_frames * m_latency;
  74. // NB: if drop_frames is enabled, update current seq_id and wait for the next tick, otherwise
  75. // return last written frame (+2 at the picture above) immediately.
  76. if (m_drop_frames) {
  77. // NB: Shift tick to the next frame.
  78. m_next_tick_ts += m_latency;
  79. // NB: Wait for the next frame.
  80. m_wait(ts_t{m_next_tick_ts - curr_ts});
  81. // NB: Drop already produced frames + update seq_id for the current.
  82. m_curr_seq_id += num_frames + 1;
  83. }
  84. }
  85. // NB: Just increase reference counter not to release mat memory
  86. // after assigning it to the data.
  87. cv::Mat mat = m_mat;
  88. data.meta[meta_tag::timestamp] = utils::timestamp<ts_t>();
  89. data.meta[meta_tag::seq_id] = m_curr_seq_id++;
  90. data = mat;
  91. m_next_tick_ts += m_latency;
  92. return true;
  93. }
  94. cv::GMetaArg DummySource::descr_of() const {
  95. return cv::GMetaArg{cv::descr_of(m_mat)};
  96. }
  97. #endif // OPENCV_GAPI_PIPELINE_MODELING_TOOL_DUMMY_SOURCE_HPP