mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.8 KiB
112 lines
3.8 KiB
#ifndef OPENCV_GAPI_PIPELINE_MODELING_TOOL_DUMMY_SOURCE_HPP |
|
#define OPENCV_GAPI_PIPELINE_MODELING_TOOL_DUMMY_SOURCE_HPP |
|
|
|
#include <thread> |
|
#include <memory> |
|
#include <chrono> |
|
|
|
#include <opencv2/gapi.hpp> |
|
#include <opencv2/gapi/streaming/cap.hpp> // cv::gapi::wip::IStreamSource |
|
|
|
#include "utils.hpp" |
|
|
|
class DummySource final: public cv::gapi::wip::IStreamSource { |
|
public: |
|
using WaitStrategy = std::function<void(std::chrono::microseconds)>; |
|
using Ptr = std::shared_ptr<DummySource>; |
|
using ts_t = std::chrono::microseconds; |
|
|
|
template <typename DurationT> |
|
DummySource(const DurationT latency, |
|
const OutputDescr& output, |
|
const bool drop_frames, |
|
WaitStrategy&& wait); |
|
|
|
bool pull(cv::gapi::wip::Data& data) override; |
|
cv::GMetaArg descr_of() const override; |
|
|
|
private: |
|
int64_t m_latency; |
|
cv::Mat m_mat; |
|
bool m_drop_frames; |
|
int64_t m_next_tick_ts = -1; |
|
int64_t m_curr_seq_id = 0; |
|
WaitStrategy m_wait; |
|
}; |
|
|
|
template <typename DurationT> |
|
DummySource::DummySource(const DurationT latency, |
|
const OutputDescr& output, |
|
const bool drop_frames, |
|
WaitStrategy&& wait) |
|
: m_latency(std::chrono::duration_cast<ts_t>(latency).count()), |
|
m_drop_frames(drop_frames), |
|
m_wait(std::move(wait)) { |
|
utils::createNDMat(m_mat, output.dims, output.precision); |
|
utils::generateRandom(m_mat); |
|
} |
|
|
|
bool DummySource::pull(cv::gapi::wip::Data& data) { |
|
using namespace std::chrono; |
|
using namespace cv::gapi::streaming; |
|
|
|
// NB: Wait m_latency before return the first frame. |
|
if (m_next_tick_ts == -1) { |
|
m_next_tick_ts = utils::timestamp<ts_t>() + m_latency; |
|
} |
|
|
|
int64_t curr_ts = utils::timestamp<ts_t>(); |
|
if (curr_ts < m_next_tick_ts) { |
|
/* |
|
* curr_ts |
|
* | |
|
* ------|----*-----|-------> |
|
* ^ |
|
* m_next_tick_ts |
|
* |
|
* |
|
* NB: New frame will be produced at the m_next_tick_ts point. |
|
*/ |
|
m_wait(ts_t{m_next_tick_ts - curr_ts}); |
|
} else if (m_latency != 0) { |
|
/* |
|
* curr_ts |
|
* +1 +2 | |
|
* |----------|----------|----------|----*-----|-------> |
|
* ^ ^ |
|
* m_next_tick_ts -------------> |
|
* |
|
*/ |
|
|
|
// NB: Count how many frames have been produced since last pull (m_next_tick_ts). |
|
int64_t num_frames = |
|
static_cast<int64_t>((curr_ts - m_next_tick_ts) / m_latency); |
|
// NB: Shift m_next_tick_ts to the nearest tick before curr_ts. |
|
m_next_tick_ts += num_frames * m_latency; |
|
// NB: if drop_frames is enabled, update current seq_id and wait for the next tick, otherwise |
|
// return last written frame (+2 at the picture above) immediately. |
|
if (m_drop_frames) { |
|
// NB: Shift tick to the next frame. |
|
m_next_tick_ts += m_latency; |
|
// NB: Wait for the next frame. |
|
m_wait(ts_t{m_next_tick_ts - curr_ts}); |
|
// NB: Drop already produced frames + update seq_id for the current. |
|
m_curr_seq_id += num_frames + 1; |
|
} |
|
} |
|
// NB: Just increase reference counter not to release mat memory |
|
// after assigning it to the data. |
|
cv::Mat mat = m_mat; |
|
data.meta[meta_tag::timestamp] = utils::timestamp<ts_t>(); |
|
data.meta[meta_tag::seq_id] = m_curr_seq_id++; |
|
data = mat; |
|
m_next_tick_ts += m_latency; |
|
|
|
return true; |
|
} |
|
|
|
cv::GMetaArg DummySource::descr_of() const { |
|
return cv::GMetaArg{cv::descr_of(m_mat)}; |
|
} |
|
|
|
#endif // OPENCV_GAPI_PIPELINE_MODELING_TOOL_DUMMY_SOURCE_HPP
|
|
|