11
11
#include < thread>
12
12
#include < mutex>
13
13
14
- std::mutex batch_lock; // batch frames filling will be locked
15
-
16
14
namespace custom {
17
15
class BatchProducer {
18
16
public:
19
- BatchProducer (const int batch_size, const float batch_fps)
20
- : batch_fps(batch_fps) {
17
+ BatchProducer (const int batch_size, const float batch_fps, const std::shared_ptr< bool >& drop_batch )
18
+ : batch_fps(batch_fps), drop_batch(drop_batch) {
21
19
/* * Create batch memory space for batch_size + 2 size
22
20
* first additional element is fast image
23
21
* second additional Mat is sacriface of memory for data about first element
24
22
**/
25
23
batch = std::vector<cv::Mat>(batch_size + 1 + 1 ); // 16(8) 15FPS-batch imgaes + one fast image + batch description
26
- batch[batch_size + 1 ].create (cv::Size{1 , 2 }, CV_8U); // 1x2 Mat for first element position and is_filled batch state
24
+ batch[batch_size + 1 ].create (cv::Size{ 1 , 2 }, CV_8U); // 1x2 Mat for first element position and is_filled batch state
27
25
auto ptr = batch[batch.size () - 1 ].ptr <uint8_t >();
28
26
ptr[1 ] = 0 ; // set is_filled to NO
29
27
}
30
28
std::vector<cv::Mat> getBatch () {
31
- return batch;
29
+ batch_lock.lock ();
30
+ std::vector<cv::Mat> temp_batch = batch;
31
+ batch_lock.unlock ();
32
+ return temp_batch;
32
33
}
33
34
34
35
void fillFastFrame (const cv::Mat& frame) {
35
- /* * Copy fast frame from VideoCapture to batch memory as 17th (9) image **/
36
- batch[batch.size () - 2 ] = frame. clone ( ); // 16th (from 0)
36
+ /* * Copy fast frame from VideoCapture to batch memory as 17th (9) image **/
37
+ frame. copyTo ( batch[batch.size () - 2 ]); // 16th (from 0)
37
38
}
38
39
39
40
void fillBatch (const cv::Mat& frame, std::chrono::steady_clock::time_point time) {
41
+ if (*drop_batch > 0 ) {
42
+ DropBatchInfo ();
43
+ }
40
44
/* * Place of new frame in batch **/
41
45
const int step = updateStep (batch.size () - 2 );
42
- batch_lock.lock ();
43
46
/* * Adding of new image to batch. **/
44
- batch[step] = frame. clone ( );
47
+ frame. copyTo ( batch[step]);
45
48
/* * Putting of info about batch to additional element **/
46
49
auto ptr = batch[batch.size () - 1 ].ptr <uint8_t >();
47
50
ptr[0 ] = first_el; // position of start of batch in cyclic buffer
48
- batch_lock.unlock ();
49
51
const auto cur_step = std::chrono::steady_clock::now () - time;
50
52
const auto gap = std::chrono::duration_cast<std::chrono::milliseconds>(cur_step);
51
53
const auto time_step = std::chrono::milliseconds (int (1000 .f / batch_fps)); // 1/15 sec
@@ -55,46 +57,59 @@ class BatchProducer {
55
57
}
56
58
private:
57
59
float batch_fps = 0 ; // constant FPS for batch
60
+ const std::shared_ptr<bool >& drop_batch;
58
61
std::vector<cv::Mat> batch; // pack of images for graph
59
62
size_t first_el = 0 ; // place of first image in batch
60
63
size_t images_in_batch_count = 0 ; // number of images in batch
61
64
bool is_filled = false ; // is batch filled
65
+ std::mutex batch_lock; // batch frames filling will be locked
62
66
63
67
int updateStep (const size_t batch_size) {
64
68
if (images_in_batch_count < batch_size) {
65
69
/* * case when batch isn't filled **/
66
70
return images_in_batch_count++;
67
- } else {
71
+ }
72
+ else {
68
73
if (!is_filled) {
69
- batch_lock.lock ();
70
74
auto ptr = batch[batch.size () - 1 ].ptr <uint8_t >();
71
75
ptr[1 ] = 1 ;
72
- batch_lock.unlock ();
73
76
is_filled = true ;
74
77
}
75
78
/* * Cyclic buffer if filled. Counting of step for next image **/
76
79
first_el = (first_el + 1 ) % batch_size;
77
80
return first_el;
78
81
}
79
82
}
83
+
84
+ void DropBatchInfo () {
85
+ /* * Drop batch information.
86
+ * Processing will continue when the batch will be filled
87
+ * Data of the batch will be overwritten */
88
+ auto ptr = batch[batch.size () - 1 ].ptr <uint8_t >();
89
+ ptr[0 ] = 0 ; // first position
90
+ ptr[1 ] = 0 ; // batch if filled
91
+ first_el = 0 ;
92
+ images_in_batch_count = 0 ;
93
+ is_filled = false ;
94
+ }
80
95
};
81
96
82
97
void runBatchFill (const cv::Mat& frame,
83
- BatchProducer& producer,
84
- std::chrono::steady_clock::time_point& time) {
85
- while (!frame.empty ()) {
98
+ BatchProducer& producer,
99
+ std::chrono::steady_clock::time_point& time) {
100
+ while (!frame.empty ()) {
86
101
producer.fillBatch (frame, time);
87
102
}
88
103
}
89
104
90
- class CustomCapSource : public cv ::gapi::wip::IStreamSource
91
- {
105
+ class CustomCapSource : public cv ::gapi::wip::IStreamSource {
92
106
public:
93
107
explicit CustomCapSource (const std::shared_ptr<ImagesCapture>& cap,
94
108
const cv::Size& frame_size,
95
109
const int batch_size,
96
- const float batch_fps)
97
- : cap(cap), producer(batch_size, batch_fps), source_fps(cap->fps ()) {
110
+ const float batch_fps,
111
+ const std::shared_ptr<bool >& drop_batch)
112
+ : cap(cap), producer(batch_size, batch_fps, drop_batch), source_fps(cap->fps ()) {
98
113
if (source_fps <= 0 .) {
99
114
source_fps = 30 .;
100
115
wait_gap = true ;
@@ -106,19 +121,21 @@ class CustomCapSource : public cv::gapi::wip::IStreamSource
106
121
GAPI_Assert (false && " Batch must contain more than one image" );
107
122
}
108
123
109
- fast_frame.create (frame_size, CV_8UC3);
110
-
111
124
/* * Reading of frame with ImagesCapture class **/
112
125
read_time = std::chrono::steady_clock::now ();
113
- fast_frame = cap->read ();
126
+ cv::Mat fast_frame = cap->read ();
114
127
if (!fast_frame.data ) {
115
128
GAPI_Assert (false && " Couldn't grab the frame" );
116
129
}
117
130
131
+ producer.fillFastFrame (fast_frame);
132
+ fast_frame.copyTo (thread_frame);
118
133
/* * Batch filling with constant time step **/
134
+ std::thread fill_bath_thr (runBatchFill,
135
+ std::cref (thread_frame),
136
+ std::ref (producer),
137
+ std::ref (read_time));
119
138
fill_bath_thr.detach ();
120
-
121
- producer.fillFastFrame (fast_frame);
122
139
first_batch = producer.getBatch ();
123
140
}
124
141
@@ -129,14 +146,11 @@ class CustomCapSource : public cv::gapi::wip::IStreamSource
129
146
bool wait_gap = false ; // waiting for fast frame reading (stop main thread when got a non-positive FPS value)
130
147
bool first_pulled = false ; // is first already pulled
131
148
std::vector<cv::Mat> first_batch; // batch from constructor
132
- cv::Mat fast_frame; // frame from cv::VideoCapture
149
+ cv::Mat thread_frame; // frame for batch constant filling
150
+ std::mutex thread_frame_lock;
133
151
std::chrono::steady_clock::time_point read_time; // timepoint from cv::read()
134
- std::thread fill_bath_thr = std::thread(runBatchFill,
135
- std::ref (fast_frame),
136
- std::ref(producer),
137
- std::ref(read_time));
138
152
139
- virtual bool pull (cv::gapi::wip::Data & data) override {
153
+ virtual bool pull (cv::gapi::wip::Data& data) override {
140
154
/* * Is first already pulled **/
141
155
if (!first_pulled) {
142
156
GAPI_Assert (!first_batch.empty ());
@@ -148,11 +162,16 @@ class CustomCapSource : public cv::gapi::wip::IStreamSource
148
162
149
163
/* * Frame reading with ImagesCapture class **/
150
164
read_time = std::chrono::steady_clock::now ();
151
- fast_frame = cap->read ();
165
+ cv::Mat fast_frame = cap->read ();
166
+
152
167
if (!fast_frame.data ) {
153
168
return false ;
154
169
}
155
170
171
+ thread_frame_lock.lock ();
172
+ fast_frame.copyTo (thread_frame);
173
+ thread_frame_lock.unlock ();
174
+
156
175
/* * Put fast frame to the batch **/
157
176
producer.fillFastFrame (fast_frame);
158
177
if (wait_gap) {
@@ -175,5 +194,4 @@ class CustomCapSource : public cv::gapi::wip::IStreamSource
175
194
return cv::GMetaArg{ cv::empty_array_desc () };
176
195
}
177
196
};
178
-
179
197
} // namespace custom
0 commit comments