fbdf337d91b0615f1120afdd0e89b0089847db39
[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 EnginePtr Engine::create()
18 {
19     LOG_DEBUG(TAG, "create");
20     std::lock_guard<std::mutex> lock(g_mutex);
21     if (g_instance.lock()){
22         LOG_ERROR(TAG, "already exists");
23         return EnginePtr();
24     }
25     EnginePtr instance (new Engine());
26     g_instance = instance;
27     return instance;
28 }
29
30 Engine::Engine()
31 {
32     //detector = std::make_shared<Detector>();
33     detector = DetectorPtr(new 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 void Engine::setVideoSrc(VideoSrcType type, const std::string& url)
51 {
52     reader = VideoReaderFactory::createVideoReader(type, url);
53 }
54
55 void Engine::run()
56 {
57     LOG_DEBUG(TAG, "run");
58     cv::Mat frame;
59     Detection detections[128];
60     while (reader->read(frame)){
61         LOG_DEBUG(TAG, "Size: " << frame.cols  <<  "x" << frame.rows);
62         int total = detector->detect(frame, detections);
63         multiTracker->update(total, detections, frame);
64     }
65 }
66
67 void Engine::start()
68 {
69     LOG_DEBUG(TAG, "start");
70     multiTracker = std::make_shared<MultiTracker>(g_instance);
71     if (!reader){
72         LOG_ERROR(TAG, "reader is null. exit");
73         return;
74     }
75     std::thread t(&Engine::run, this);
76     t.join();
77 }
78
79 void Engine::addObserver(EngineObserver *observer)
80 {
81     LOG_DEBUG(TAG, "addObserver");
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     LOG_DEBUG(TAG, "onPersonOut");
122     PersonsInfoPtr pp = std::make_shared<std::vector<Person>>(p);
123     eventThread.enqueue(new PersonOutEventWorkItem(this->observer_list, pp));
124 }
125
126 void Engine::onPersonsIn(const std::vector<Person>& p)
127 {
128     LOG_DEBUG(TAG, "onPersonIn");
129     PersonsInfoPtr pp = std::make_shared<std::vector<Person>>(p);
130     eventThread.enqueue(new PersonInEventWorkItem(this->observer_list, pp));
131 }