1 /*
2 * xcam_analyzer.cpp - libxcam analyzer
3 *
4 * Copyright (c) 2014-2015 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 * Zong Wei <wei.zong@intel.com>
20 * Jia Meng <jia.meng@intel.com>
21 */
22
23 #include "xcam_analyzer.h"
24 #include "x3a_stats_pool.h"
25
26 namespace XCam {
27
AnalyzerThread(XAnalyzer * analyzer)28 AnalyzerThread::AnalyzerThread (XAnalyzer *analyzer)
29 : Thread ("AnalyzerThread")
30 , _analyzer (analyzer)
31 {}
32
~AnalyzerThread()33 AnalyzerThread::~AnalyzerThread ()
34 {
35 _stats_queue.clear ();
36 }
37
38 bool
push_stats(const SmartPtr<VideoBuffer> & buffer)39 AnalyzerThread::push_stats (const SmartPtr<VideoBuffer> &buffer)
40 {
41 _stats_queue.push (buffer);
42 return true;
43 }
44
45 bool
started()46 AnalyzerThread::started ()
47 {
48 XCamReturn ret = XCAM_RETURN_NO_ERROR;
49
50 XCAM_ASSERT (_analyzer);
51 ret = _analyzer->configure ();
52 if (ret != XCAM_RETURN_NO_ERROR) {
53 _analyzer->notify_calculation_failed (NULL, 0, "configure 3a failed");
54 XCAM_LOG_WARNING ("analyzer(%s) configure 3a failed", XCAM_STR(_analyzer->get_name()));
55 return false;
56 }
57
58 return true;
59 }
60
61 bool
loop()62 AnalyzerThread::loop ()
63 {
64 const static int32_t timeout = -1;
65 SmartPtr<VideoBuffer> latest_stats;
66 SmartPtr<VideoBuffer> stats = _stats_queue.pop (timeout);
67 if (!stats.ptr()) {
68 XCAM_LOG_DEBUG ("analyzer thread got empty stats, stop thread");
69 return false;
70 }
71 //while ((latest_stats = _stats_queue.pop (0)).ptr ()) {
72 // stats = latest_stats;
73 // XCAM_LOG_WARNING ("lost 3a stats since 3a analyzer too slow");
74 //}
75
76 XCamReturn ret = _analyzer->analyze (stats);
77 if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS)
78 return true;
79
80 XCAM_LOG_DEBUG ("analyzer(%s) failed to analyze 3a stats", XCAM_STR(_analyzer->get_name()));
81 return false;
82 }
83
84 void
x3a_calculation_done(XAnalyzer * analyzer,X3aResultList & results)85 AnalyzerCallback::x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results)
86 {
87 XCAM_UNUSED (analyzer);
88
89 for (X3aResultList::iterator i_res = results.begin();
90 i_res != results.end(); ++i_res) {
91 SmartPtr<X3aResult> res = *i_res;
92 if (res.ptr() == NULL) continue;
93 XCAM_LOG_DEBUG (
94 "calculated 3a result(type:0x%x, timestamp:" XCAM_TIMESTAMP_FORMAT ")",
95 res->get_type (), XCAM_TIMESTAMP_ARGS (res->get_timestamp ()));
96 }
97 }
98
99 void
x3a_calculation_failed(XAnalyzer * analyzer,int64_t timestamp,const char * msg)100 AnalyzerCallback::x3a_calculation_failed (XAnalyzer *analyzer, int64_t timestamp, const char *msg)
101 {
102 XCAM_UNUSED (analyzer);
103
104 XCAM_LOG_WARNING (
105 "Calculate 3a result failed, ts(" XCAM_TIMESTAMP_FORMAT "), msg:%s",
106 XCAM_TIMESTAMP_ARGS (timestamp), XCAM_STR (msg));
107 }
108
XAnalyzer(const char * name)109 XAnalyzer::XAnalyzer (const char *name)
110 : _name (NULL)
111 , _sync (false)
112 , _started (false)
113 , _width (0)
114 , _height (0)
115 , _framerate (30.0)
116 , _callback (NULL)
117 {
118 if (name)
119 _name = strndup (name, XCAM_MAX_STR_SIZE);
120
121 _analyzer_thread = new AnalyzerThread (this);
122 }
123
~XAnalyzer()124 XAnalyzer::~XAnalyzer()
125 {
126 if (_name)
127 xcam_free (_name);
128 }
129
130 bool
set_results_callback(AnalyzerCallback * callback)131 XAnalyzer::set_results_callback (AnalyzerCallback *callback)
132 {
133 XCAM_ASSERT (!_callback);
134 _callback = callback;
135 return true;
136 }
137
138 XCamReturn
prepare_handlers()139 XAnalyzer::prepare_handlers ()
140 {
141 return create_handlers ();
142 }
143
144 XCamReturn
init(uint32_t width,uint32_t height,double framerate)145 XAnalyzer::init (uint32_t width, uint32_t height, double framerate)
146 {
147 XCAM_LOG_DEBUG ("Analyzer(%s) init.", XCAM_STR(get_name()));
148 XCamReturn ret = XCAM_RETURN_NO_ERROR;
149
150 XCAM_ASSERT (!_width && !_height);
151 _width = width;
152 _height = height;
153 _framerate = framerate;
154
155 ret = internal_init (width, height, _framerate);
156 if (ret != XCAM_RETURN_NO_ERROR) {
157 XCAM_LOG_WARNING ("analyzer init failed");
158 deinit ();
159 return ret;
160 }
161
162 XCAM_LOG_INFO (
163 "Analyzer(%s) initialized(w:%d, h:%d).",
164 XCAM_STR(get_name()), _width, _height);
165 return XCAM_RETURN_NO_ERROR;
166 }
167
168 XCamReturn
deinit()169 XAnalyzer::deinit ()
170 {
171 internal_deinit ();
172
173 release_handlers ();
174
175 _width = 0;
176 _height = 0;
177
178 XCAM_LOG_INFO ("Analyzer(%s) deinited.", XCAM_STR(get_name()));
179 return XCAM_RETURN_NO_ERROR;
180 }
181
182 XCamReturn
set_sync_mode(bool sync)183 XAnalyzer::set_sync_mode (bool sync)
184 {
185 if (_started) {
186 XCAM_LOG_ERROR ("can't set_sync_mode after analyzer started");
187 return XCAM_RETURN_ERROR_PARAM;
188 }
189 _sync = sync;
190 return XCAM_RETURN_NO_ERROR;
191 }
192
193 XCamReturn
start()194 XAnalyzer::start ()
195 {
196 if (_sync) {
197 XCamReturn ret = configure ();
198 if (ret != XCAM_RETURN_NO_ERROR) {
199 XCAM_LOG_ERROR ("analyzer failed to start in sync mode");
200 stop ();
201 return ret;
202 }
203 } else {
204 if (_analyzer_thread->start () == false) {
205 XCAM_LOG_WARNING ("analyzer thread start failed");
206 stop ();
207 return XCAM_RETURN_ERROR_THREAD;
208 }
209 }
210
211 _started = true;
212 XCAM_LOG_INFO ("Analyzer(%s) started in %s mode.", XCAM_STR(get_name()),
213 _sync ? "sync" : "async");
214 return XCAM_RETURN_NO_ERROR;
215 }
216
217 XCamReturn
stop()218 XAnalyzer::stop ()
219 {
220 if (!_sync) {
221 _analyzer_thread->triger_stop ();
222 _analyzer_thread->stop ();
223 }
224
225 _started = false;
226 XCAM_LOG_INFO ("Analyzer(%s) stopped.", XCAM_STR(get_name()));
227 return XCAM_RETURN_NO_ERROR;
228 }
229
230 XCamReturn
push_buffer(const SmartPtr<VideoBuffer> & buffer)231 XAnalyzer::push_buffer (const SmartPtr<VideoBuffer> &buffer)
232 {
233 XCamReturn ret = XCAM_RETURN_NO_ERROR;
234
235 if (get_sync_mode ()) {
236 ret = analyze (buffer);
237 }
238 else {
239 if (!_analyzer_thread->is_running())
240 return XCAM_RETURN_ERROR_THREAD;
241
242 if (!_analyzer_thread->push_stats (buffer))
243 return XCAM_RETURN_ERROR_THREAD;
244 }
245
246 return ret;
247 }
248
249 void
set_results_timestamp(X3aResultList & results,int64_t timestamp)250 XAnalyzer::set_results_timestamp (X3aResultList &results, int64_t timestamp)
251 {
252 if (results.empty ())
253 return;
254
255 X3aResultList::iterator i_results = results.begin ();
256 for (; i_results != results.end (); ++i_results)
257 {
258 (*i_results)->set_timestamp(timestamp);
259 }
260 }
261
262 void
notify_calculation_failed(AnalyzerHandler * handler,int64_t timestamp,const char * msg)263 XAnalyzer::notify_calculation_failed (AnalyzerHandler *handler, int64_t timestamp, const char *msg)
264 {
265 XCAM_UNUSED (handler);
266
267 if (_callback)
268 _callback->x3a_calculation_failed (this, timestamp, msg);
269 XCAM_LOG_DEBUG (
270 "calculation failed on ts:" XCAM_TIMESTAMP_FORMAT ", reason:%s",
271 XCAM_TIMESTAMP_ARGS (timestamp), XCAM_STR (msg));
272 }
273
274 void
notify_calculation_done(X3aResultList & results)275 XAnalyzer::notify_calculation_done (X3aResultList &results)
276 {
277 XCAM_ASSERT (!results.empty ());
278 if (_callback)
279 _callback->x3a_calculation_done (this, results);
280 }
281
282 };
283