Skip to content

Commit fa12144

Browse files
committed
Add CalcMask class for threading
1 parent 6649453 commit fa12144

File tree

1 file changed

+97
-6
lines changed

1 file changed

+97
-6
lines changed

app/deepseg.cc

Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,99 @@ static bool is_number(const std::string &s) {
145145
return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
146146
}
147147

148+
class CalcMask final {
149+
protected:
150+
enum class thread_state { INIT, RUNNING, DONE };
151+
volatile thread_state state;
152+
void *maskctx;
153+
// buffers
154+
cv::Mat mask1;
155+
cv::Mat mask2;
156+
cv::Mat *mask_current;
157+
cv::Mat *mask_out;
158+
cv::Mat frame1;
159+
cv::Mat frame2;
160+
cv::Mat *frame_current;
161+
cv::Mat *frame_next;
162+
// All mutexes need to come before the thread
163+
std::mutex lock_frame;
164+
std::mutex lock_mask;
165+
std::condition_variable condition_new_frame;
166+
bool new_frame;
167+
bool new_mask;
168+
169+
std::thread thread; // Must be after state and all relevant mutexes, because of initialization order)
170+
171+
void run() {
172+
cv::Mat *raw_tmp;
173+
174+
while(thread_state::INIT == this->state)
175+
usleep(1000); // Wait for constructor to complete initialization
176+
177+
while(thread_state::RUNNING == this->state) {
178+
/* actual handling */
179+
{
180+
std::unique_lock<std::mutex> hold(lock_frame);
181+
while (!new_frame) {
182+
condition_new_frame.wait(hold);
183+
}
184+
185+
// change frame buffer pointer
186+
new_frame = false;
187+
raw_tmp = frame_next;
188+
frame_next = frame_current;
189+
frame_current = raw_tmp;
190+
}
191+
if(!bs_maskgen_process(maskctx, *frame_current, *mask_current)) {
192+
fprintf(stderr, "failed to process video frame\n");
193+
exit(1);
194+
}
195+
{
196+
std::unique_lock<std::mutex> hold(lock_mask);
197+
raw_tmp = mask_out;
198+
mask_out = mask_current;
199+
mask_current = raw_tmp;
200+
new_mask = true;
201+
}
202+
}
203+
}
204+
205+
public:
206+
CalcMask(void *maskctx) :
207+
state{thread_state::INIT},
208+
thread{&CalcMask::run, this} {
209+
// Do all other initialization …
210+
this->maskctx = maskctx;
211+
frame_next = &frame1;
212+
frame_current = &frame2;
213+
mask_current = &mask1;
214+
mask_out = &mask2;
215+
new_frame = false;
216+
new_mask = false;
217+
state = thread_state::RUNNING;
218+
}
219+
220+
~CalcMask() {
221+
state = thread_state::DONE;
222+
thread.join();
223+
}
224+
225+
void set_input_frame(cv::Mat &frame) {
226+
std::lock_guard<std::mutex> hold(lock_frame);
227+
*frame_next = frame.clone();
228+
new_frame = true;
229+
condition_new_frame.notify_all();
230+
}
231+
232+
void get_output_mask(cv::Mat &out) {
233+
if (new_mask) {
234+
std::lock_guard<std::mutex> hold(lock_mask);
235+
out = mask_out->clone();
236+
new_mask = false;
237+
}
238+
}
239+
};
240+
148241
int main(int argc, char* argv[]) {
149242

150243
printf("deepseg version %s\n", _STR(DEEPSEG_VERSION));
@@ -334,8 +427,9 @@ int main(int argc, char* argv[]) {
334427
if (!maskctx)
335428
exit(1);
336429

337-
cv::Mat mask;
430+
cv::Mat mask(height, width, CV_8U);
338431
cv::Mat raw;
432+
CalcMask ai(maskctx);
339433
ti.lastns = timestamp();
340434
printf("Startup: %ldns\n", diffnanosecs(ti.lastns,ti.bootns));
341435

@@ -349,6 +443,7 @@ int main(int argc, char* argv[]) {
349443
cap.grab();
350444
// copy new frame to buffer
351445
cap.retrieve(raw);
446+
ai.set_input_frame(raw);
352447

353448
ti.copyns=timestamp();
354449
if (raw.rows == 0 || raw.cols == 0) continue; // sanity check
@@ -360,11 +455,7 @@ int main(int argc, char* argv[]) {
360455

361456
if (filterActive) {
362457
// do background detection magic
363-
cv::Mat mask;
364-
if(!bs_maskgen_process(maskctx, raw, mask)) {
365-
fprintf(stderr, "failed to process video frame\n");
366-
exit(1);
367-
}
458+
ai.get_output_mask(mask);
368459

369460
// alpha blend background over foreground using mask
370461
raw = alpha_blend(bg, raw, mask);

0 commit comments

Comments
 (0)