Add worker thread
[trackerpp.git] / src / Engine.cpp
1 #include <mutex>
2 #include <thread>
3 #include <condition_variable>
4 #include "Engine.h"
5 #include "Logger.h"
6 #include "PredictorWrapper.h"
7
8 using namespace suanzi;
9 using namespace std;
10
11 static const std::string TAG = "Engine";
12 static std::mutex g_mutex;
13 static EngineWPtr g_instance;
14
15 typedef std::shared_ptr<std::vector<Person>> PersonsInfoPtr;
16
17 // class Engine
18 EnginePtr Engine::create()
19 {
20     LOG_DEBUG(TAG, "create");
21     std::lock_guard<std::mutex> lock(g_mutex);
22     if (g_instance.lock()){
23         LOG_ERROR(TAG, "already exists");
24         return EnginePtr(); // nullptr
25     }
26     EnginePtr instance (new Engine());
27     g_instance = instance;
28     return instance;
29 }
30
31 Engine::Engine()
32 {
33     detector = std::make_shared<Detector>();
34 }
35
36 Engine::~Engine()
37 {    
38     destroy();
39 }
40
41 void Engine::destroy()
42 {
43     LOG_DEBUG(TAG, "destroy");
44     detector.reset();
45     multiTracker.reset();
46     reader.reset();
47     observer_list.clear();
48 }
49
50
51 void Engine::setVideoSrc(VideoSrcType type, const std::string& url)
52 {
53     reader = VideoReaderFactory::createVideoReader(type, url);
54 }
55
56 void Engine::run()
57 {
58     LOG_DEBUG(TAG, "run");
59     cv::Mat frame;
60     Detection detections[128];
61     while (reader->read(frame)){
62         LOG_DEBUG(TAG, "Size: " << frame.cols  <<  "x" << frame.rows);
63         int total = detector->detect(frame, detections);
64         multiTracker->update(total, detections, frame);
65     }
66 }
67
68 void Engine::start()
69 {
70     LOG_DEBUG(TAG, "start");
71     multiTracker = std::make_shared<MultiTracker>(g_instance);
72     if (!reader){
73         LOG_ERROR(TAG, "reader is null. exit");
74         return;
75     }
76     std::thread t(&Engine::run, this);
77     t.join();
78 }
79
80 void Engine::addObserver(EngineObserver *observer)
81 {
82     observer_list.insert(observer);
83 }
84
85
86 // WorkItem class for event thread
87 class PersonInEventWorkItem : public WorkItem
88 {
89 public:
90     PersonInEventWorkItem(std::set<EngineObserver*> obs, PersonsInfoPtr info) : obs(obs), info(info){
91     }
92     ~PersonInEventWorkItem(){}
93     void run (){
94         for (auto o : obs){
95             o->onPersonsIn(*(info.get()));
96         }
97     }
98 private:
99     std::set<EngineObserver*> obs;
100     PersonsInfoPtr info;
101 };
102
103 class PersonOutEventWorkItem : public WorkItem
104 {
105 public:
106     PersonOutEventWorkItem(std::set<EngineObserver*> obs, PersonsInfoPtr info) : obs(obs), info(info){
107     }
108     ~PersonOutEventWorkItem(){}
109     void run (){
110         for (auto o : obs){
111             o->onPersonsIn(*(info.get()));
112         }
113     }
114 private:
115     std::set<EngineObserver*> obs;
116     PersonsInfoPtr info;
117 };
118
119 void Engine::onPersonsOut(const std::vector<Person>& p)
120 {
121     PersonsInfoPtr pp = std::make_shared<std::vector<Person>>(p);
122     eventThread.enqueue(new PersonOutEventWorkItem(this->observer_list, pp));
123 }
124
125 void Engine::onPersonsIn(const std::vector<Person>& p)
126 {
127     PersonsInfoPtr pp = std::make_shared<std::vector<Person>>(p);
128     eventThread.enqueue(new PersonInEventWorkItem(this->observer_list, pp));
129 }
130
131 void Engine::onStatusChanged()
132 {
133     Person pm, p2;
134     std::vector<Person> ps;
135     ps.push_back(pm);
136     ps.push_back(p2);
137     onPersonsOut(ps);
138 }