File: dummy_source.hpp

package info (click to toggle)
opencv 4.6.0%2Bdfsg-12
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 276,172 kB
  • sloc: cpp: 1,079,020; xml: 682,526; python: 43,885; lisp: 30,943; java: 25,642; ansic: 7,968; javascript: 5,956; objc: 2,039; sh: 1,017; cs: 601; perl: 494; makefile: 179
file content (102 lines) | stat: -rw-r--r-- 3,298 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#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 Ptr = std::shared_ptr<DummySource>;
    DummySource(const double       latency,
                const OutputDescr& output,
                const bool         drop_frames);
    bool pull(cv::gapi::wip::Data& data) override;
    cv::GMetaArg descr_of() const override;

private:
    double  m_latency;
    cv::Mat m_mat;
    bool    m_drop_frames;
    double  m_next_tick_ts = -1;
    int64_t m_curr_seq_id  = 0;
};

DummySource::DummySource(const double       latency,
                         const OutputDescr& output,
                         const bool         drop_frames)
    : m_latency(latency), m_drop_frames(drop_frames) {
    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<milliseconds>() + m_latency;
    }

    int64_t curr_ts = utils::timestamp<milliseconds>();
    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.
         */
        utils::sleep(m_next_tick_ts - curr_ts);
    } else {
        /*
         *                                       curr_ts
         *                         +1         +2    |
         *    |----------|----------|----------|----*-----|------->
         *               ^                     ^
         *         m_next_tick_ts ------------->
         *
         *
         *  NB: Shift m_next_tick_ts to the nearest tick before curr_ts and
         *  update current seq_id correspondingly.
         *
         *  if drop_frames is enabled, wait for the next tick, otherwise
         *  return last written frame (+2 at the picture above) immediately.
         */
        int64_t num_frames =
            static_cast<int64_t>((curr_ts - m_next_tick_ts) / m_latency);
        m_curr_seq_id  += num_frames;
        m_next_tick_ts += num_frames * m_latency;
        if (m_drop_frames) {
            m_next_tick_ts += m_latency;
            ++m_curr_seq_id;
            utils::sleep(m_next_tick_ts - curr_ts);
        }
    }

    // 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<milliseconds>();
    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