• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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