1 /* 2 * image_processor.h - 3a image processor 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 */ 20 21 #include "image_processor.h" 22 #include "xcam_thread.h" 23 24 namespace XCam { 25 26 void 27 ImageProcessCallback::process_buffer_done (ImageProcessor *processor, const SmartPtr<VideoBuffer> &buf) { 28 XCAM_UNUSED (processor); 29 XCAM_ASSERT (buf.ptr() && processor); 30 31 int64_t ts = buf->get_timestamp(); 32 XCAM_UNUSED (ts); 33 XCAM_LOG_DEBUG ( 34 "processor(%s) handled buffer(" XCAM_TIMESTAMP_FORMAT ") successfully", 35 XCAM_STR(processor->get_name()), 36 XCAM_TIMESTAMP_ARGS (ts)); 37 } 38 39 void 40 ImageProcessCallback::process_buffer_failed (ImageProcessor *processor, const SmartPtr<VideoBuffer> &buf) 41 { 42 XCAM_ASSERT (buf.ptr() && processor); 43 44 int64_t ts = buf->get_timestamp(); 45 XCAM_UNUSED (ts); 46 XCAM_LOG_WARNING ( 47 "processor(%s) handled buffer(" XCAM_TIMESTAMP_FORMAT ") failed", 48 XCAM_STR(processor->get_name()), 49 XCAM_TIMESTAMP_ARGS (ts)); 50 } 51 52 void 53 ImageProcessCallback::process_image_result_done (ImageProcessor *processor, const SmartPtr<X3aResult> &result) 54 { 55 XCAM_UNUSED (processor); 56 XCAM_ASSERT (result.ptr() && processor); 57 58 int64_t ts = result->get_timestamp(); 59 XCAM_UNUSED (ts); 60 61 XCAM_LOG_DEBUG ( 62 "processor(%s) processed result(type:%d, timestamp:" XCAM_TIMESTAMP_FORMAT ") done", 63 XCAM_STR(processor->get_name()), 64 (int)result->get_type(), 65 XCAM_TIMESTAMP_ARGS (ts)); 66 } 67 68 class ImageProcessorThread 69 : public Thread 70 { 71 public: 72 ImageProcessorThread (ImageProcessor *processor) 73 : Thread ("image_processor") 74 , _processor (processor) 75 {} 76 ~ImageProcessorThread () {} 77 78 virtual bool loop (); 79 80 private: 81 ImageProcessor *_processor; 82 }; 83 84 bool ImageProcessorThread::loop () 85 { 86 XCamReturn ret = _processor->buffer_process_loop (); 87 if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT) 88 return true; 89 return false; 90 } 91 92 class X3aResultsProcessThread 93 : public Thread 94 { 95 typedef SafeList<X3aResult> ResultQueue; 96 public: 97 X3aResultsProcessThread (ImageProcessor *processor) 98 : Thread ("x3a_results_process_thread") 99 , _processor (processor) 100 {} 101 ~X3aResultsProcessThread () {} 102 103 XCamReturn push_result (SmartPtr<X3aResult> &result) { 104 _queue.push (result); 105 return XCAM_RETURN_NO_ERROR; 106 } 107 108 void triger_stop () { 109 _queue.pause_pop (); 110 } 111 112 virtual bool loop (); 113 114 private: 115 ImageProcessor *_processor; 116 ResultQueue _queue; 117 }; 118 119 bool X3aResultsProcessThread::loop () 120 { 121 X3aResultList result_list; 122 SmartPtr<X3aResult> result; 123 124 result = _queue.pop (-1); 125 if (!result.ptr ()) 126 return false; 127 128 result_list.push_back (result); 129 while ((result = _queue.pop (0)).ptr ()) { 130 result_list.push_back (result); 131 } 132 133 XCamReturn ret = _processor->process_3a_results (result_list); 134 if (ret != XCAM_RETURN_NO_ERROR) { 135 XCAM_LOG_DEBUG ("processing 3a result failed"); 136 } 137 138 return true; 139 } 140 ImageProcessor::ImageProcessor (const char* name) 141 : _name (NULL) 142 , _callback (NULL) 143 { 144 if (name) 145 _name = strndup (name, XCAM_MAX_STR_SIZE); 146 147 _processor_thread = new ImageProcessorThread (this); 148 _results_thread = new X3aResultsProcessThread (this); 149 } 150 151 ImageProcessor::~ImageProcessor () 152 { 153 if (_name) 154 xcam_free (_name); 155 } 156 157 bool 158 ImageProcessor::set_callback (ImageProcessCallback *callback) 159 { 160 XCAM_ASSERT (!_callback); 161 _callback = callback; 162 return true; 163 } 164 165 XCamReturn 166 ImageProcessor::start() 167 { 168 XCamReturn ret = XCAM_RETURN_NO_ERROR; 169 if (!_results_thread->start ()) { 170 return XCAM_RETURN_ERROR_THREAD; 171 } 172 if (!_processor_thread->start ()) { 173 return XCAM_RETURN_ERROR_THREAD; 174 } 175 ret = emit_start (); 176 if (ret != XCAM_RETURN_NO_ERROR) { 177 XCAM_LOG_WARNING ("ImageProcessor(%s) emit start failed", XCAM_STR (_name)); 178 _video_buf_queue.pause_pop (); 179 _results_thread->triger_stop (); 180 _processor_thread->stop (); 181 _results_thread->stop (); 182 return ret; 183 } 184 XCAM_LOG_INFO ("ImageProcessor(%s) started", XCAM_STR (_name)); 185 return XCAM_RETURN_NO_ERROR; 186 } 187 188 XCamReturn 189 ImageProcessor::stop() 190 { 191 _video_buf_queue.pause_pop (); 192 _results_thread->triger_stop (); 193 194 emit_stop (); 195 196 _processor_thread->stop (); 197 _results_thread->stop (); 198 XCAM_LOG_DEBUG ("ImageProcessor(%s) stopped", XCAM_STR (_name)); 199 return XCAM_RETURN_NO_ERROR; 200 } 201 202 XCamReturn 203 ImageProcessor::push_buffer (SmartPtr<VideoBuffer> &buf) 204 { 205 if (_video_buf_queue.push (buf)) 206 return XCAM_RETURN_NO_ERROR; 207 208 XCAM_LOG_DEBUG ("processor push buffer failed"); 209 return XCAM_RETURN_ERROR_UNKNOWN; 210 } 211 212 XCamReturn 213 ImageProcessor::push_3a_results (X3aResultList &results) 214 { 215 XCAM_ASSERT (!results.empty ()); 216 XCamReturn ret = XCAM_RETURN_NO_ERROR; 217 for (X3aResultList::iterator i_res = results.begin(); 218 i_res != results.end(); ++i_res) { 219 SmartPtr<X3aResult> &res = *i_res; 220 221 ret = _results_thread->push_result (res); 222 if (ret != XCAM_RETURN_NO_ERROR) 223 break; 224 } 225 226 XCAM_FAIL_RETURN( 227 WARNING, 228 ret == XCAM_RETURN_NO_ERROR, 229 ret, 230 "processor(%s) push 3a results failed", XCAM_STR(get_name())); 231 return XCAM_RETURN_NO_ERROR; 232 } 233 234 XCamReturn 235 ImageProcessor::push_3a_result (SmartPtr<X3aResult> &result) 236 { 237 XCamReturn ret = _results_thread->push_result (result); 238 XCAM_FAIL_RETURN( 239 WARNING, 240 ret == XCAM_RETURN_NO_ERROR, 241 ret, 242 "processor(%s) push 3a result failed", XCAM_STR(get_name())); 243 return XCAM_RETURN_NO_ERROR; 244 } 245 246 XCamReturn 247 ImageProcessor::process_3a_results (X3aResultList &results) 248 { 249 X3aResultList valid_results; 250 XCamReturn ret = XCAM_RETURN_NO_ERROR; 251 252 filter_valid_results (results, valid_results); 253 if (valid_results.empty()) 254 return XCAM_RETURN_BYPASS; 255 256 ret = apply_3a_results (valid_results); 257 258 if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) { 259 XCAM_LOG_WARNING ("processor(%s) apply results failed", XCAM_STR(get_name())); 260 return ret; 261 } 262 263 if (_callback) { 264 for (X3aResultList::iterator i_res = valid_results.begin(); 265 i_res != valid_results.end(); ++i_res) { 266 SmartPtr<X3aResult> &res = *i_res; 267 _callback->process_image_result_done (this, res); 268 } 269 } 270 271 return ret; 272 } 273 274 XCamReturn 275 ImageProcessor::process_3a_result (SmartPtr<X3aResult> &result) 276 { 277 X3aResultList valid_results; 278 XCamReturn ret = XCAM_RETURN_NO_ERROR; 279 280 if (!can_process_result(result)) 281 return XCAM_RETURN_BYPASS; 282 283 ret = apply_3a_result (result); 284 285 if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) { 286 XCAM_LOG_WARNING ("processor(%s) apply result failed", XCAM_STR(get_name())); 287 return ret; 288 } 289 290 if (_callback) { 291 _callback->process_image_result_done (this, result); 292 } 293 294 return ret; 295 } 296 297 void 298 ImageProcessor::filter_valid_results (X3aResultList &input, X3aResultList &valid_results) 299 { 300 for (X3aResultList::iterator i_res = input.begin(); i_res != input.end(); ) { 301 SmartPtr<X3aResult> &res = *i_res; 302 if (can_process_result(res)) { 303 valid_results.push_back (res); 304 input.erase (i_res++); 305 } else 306 ++i_res; 307 } 308 } 309 310 void 311 ImageProcessor::notify_process_buffer_done (const SmartPtr<VideoBuffer> &buf) 312 { 313 if (_callback) 314 _callback->process_buffer_done (this, buf); 315 } 316 317 void 318 ImageProcessor::notify_process_buffer_failed (const SmartPtr<VideoBuffer> &buf) 319 { 320 if (_callback) 321 _callback->process_buffer_failed (this, buf); 322 } 323 324 XCamReturn 325 ImageProcessor::buffer_process_loop () 326 { 327 XCamReturn ret = XCAM_RETURN_NO_ERROR; 328 SmartPtr<VideoBuffer> new_buf; 329 SmartPtr<VideoBuffer> buf = _video_buf_queue.pop(); 330 331 if (!buf.ptr()) 332 return XCAM_RETURN_ERROR_MEM; 333 334 ret = this->process_buffer (buf, new_buf); 335 if (ret < XCAM_RETURN_NO_ERROR) { 336 XCAM_LOG_DEBUG ("processing buffer failed"); 337 notify_process_buffer_failed (buf); 338 return ret; 339 } 340 341 if (new_buf.ptr ()) 342 notify_process_buffer_done (new_buf); 343 344 return XCAM_RETURN_NO_ERROR; 345 } 346 347 XCamReturn 348 ImageProcessor::emit_start () 349 { 350 return XCAM_RETURN_NO_ERROR; 351 } 352 353 void 354 ImageProcessor::emit_stop () 355 { 356 } 357 358 }; 359