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 (at) intel.com> 19 * Zong Wei <wei.zong (at) intel.com> 20 * Jia Meng <jia.meng (at) intel.com> 21 */ 22 23 #include "xcam_analyzer.h" 24 #include "x3a_stats_pool.h" 25 26 namespace XCam { 27 28 AnalyzerThread::AnalyzerThread (XAnalyzer *analyzer) 29 : Thread ("AnalyzerThread") 30 , _analyzer (analyzer) 31 {} 32 33 AnalyzerThread::~AnalyzerThread () 34 { 35 _stats_queue.clear (); 36 } 37 38 bool 39 AnalyzerThread::push_stats (const SmartPtr<VideoBuffer> &buffer) 40 { 41 _stats_queue.push (buffer); 42 return true; 43 } 44 45 bool 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 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 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 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 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 124 XAnalyzer::~XAnalyzer() 125 { 126 if (_name) 127 xcam_free (_name); 128 } 129 130 bool 131 XAnalyzer::set_results_callback (AnalyzerCallback *callback) 132 { 133 XCAM_ASSERT (!_callback); 134 _callback = callback; 135 return true; 136 } 137 138 XCamReturn 139 XAnalyzer::prepare_handlers () 140 { 141 return create_handlers (); 142 } 143 144 XCamReturn 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 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 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 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 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 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 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 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 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