1 /* 2 * sample_smart_analysis.cpp - smart analysis sample code 3 * 4 * Copyright (c) 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: Zong Wei <wei.zong (at) intel.com> 19 */ 20 21 #include <base/xcam_smart_description.h> 22 #include <base/xcam_buffer.h> 23 #include <xcam_std.h> 24 #include "aiq3a_utils.h" 25 #include "x3a_result_factory.h" 26 #include "smart_analyzer.h" 27 28 using namespace XCam; 29 30 #define DEFAULT_SAVE_FRAME_NAME "frame_buffer" 31 #define XSMART_ANALYSIS_CONTEXT_CAST(context) ((XCamSmartAnalyerContext*)(context)) 32 33 class FrameSaver 34 { 35 public: 36 explicit FrameSaver (bool save, uint32_t interval, uint32_t count); 37 ~FrameSaver (); 38 39 void save_frame (XCamVideoBuffer *buffer); 40 41 void enable_save_file (bool enable) { 42 _save_file = enable; 43 } 44 void set_interval (uint32_t inteval) { 45 _interval = inteval; 46 } 47 void set_frame_save (uint32_t frame_save) { 48 _frame_save = frame_save; 49 } 50 51 private: 52 XCAM_DEAD_COPY (FrameSaver); 53 void open_file (); 54 void close_file (); 55 56 private: 57 FILE *_file; 58 bool _save_file; 59 uint32_t _interval; 60 uint32_t _frame_save; 61 uint32_t _frame_count; 62 uint32_t _skip_frame_count; 63 64 }; 65 66 FrameSaver::FrameSaver (bool save, uint32_t interval, uint32_t count) 67 : _file (NULL) 68 , _save_file (save) 69 , _interval (interval) 70 , _frame_save (count) 71 , _frame_count (0) 72 , _skip_frame_count (300) 73 { 74 } 75 76 FrameSaver::~FrameSaver () 77 { 78 close_file (); 79 } 80 81 void 82 FrameSaver::save_frame (XCamVideoBuffer *buffer) 83 { 84 if (NULL == buffer) { 85 return; 86 } 87 if (!_save_file) 88 return ; 89 90 if ((_frame_count++ % _interval) != 0) 91 return; 92 93 if (_frame_count < _skip_frame_count) 94 return; 95 96 if (_frame_count > (_frame_save * _interval + _skip_frame_count)) { 97 return; 98 } 99 100 open_file (); 101 102 if (!_file) { 103 XCAM_LOG_ERROR ("open file failed"); 104 return; 105 } 106 107 uint8_t *memory = xcam_video_buffer_map (buffer); 108 XCamVideoBufferPlanarInfo planar; 109 for (uint32_t index = 0; index < buffer->info.components; index++) { 110 xcam_video_buffer_get_planar_info (&buffer->info, &planar, index); 111 uint32_t line_bytes = planar.width * planar.pixel_bytes; 112 113 for (uint32_t i = 0; i < planar.height; i++) { 114 if (fwrite (memory + buffer->info.offsets [index] + i * buffer->info.strides [index], 115 1, line_bytes, _file) != line_bytes) { 116 XCAM_LOG_ERROR ("write file failed, size doesn't match"); 117 return; 118 } 119 } 120 } 121 xcam_video_buffer_unmap (buffer); 122 close_file (); 123 } 124 125 void 126 FrameSaver::open_file () 127 { 128 if ((_file) && (_frame_save == 0)) 129 return; 130 131 char file_name[512]; 132 if (_frame_save != 0) { 133 snprintf (file_name, sizeof(file_name), "%s%d%s", DEFAULT_SAVE_FRAME_NAME, _frame_count, ".yuv"); 134 } 135 136 _file = fopen(file_name, "wb"); 137 } 138 139 void 140 FrameSaver::close_file () 141 { 142 if (_file) 143 fclose (_file); 144 _file = NULL; 145 } 146 147 class SampleHandler 148 { 149 public: 150 explicit SampleHandler (const char *name = NULL); 151 virtual ~SampleHandler (); 152 153 XCamReturn init (uint32_t width, uint32_t height, double framerate); 154 XCamReturn deinit (); 155 bool set_results_callback (AnalyzerCallback *callback); 156 157 XCamReturn update_params (const XCamSmartAnalysisParam *params); 158 XCamReturn analyze (XCamVideoBuffer *buffer); 159 160 private: 161 XCAM_DEAD_COPY (SampleHandler); 162 163 private: 164 char *_name; 165 uint32_t _width; 166 uint32_t _height; 167 double _framerate; 168 AnalyzerCallback *_callback; 169 SmartPtr<FrameSaver> _frameSaver; 170 }; 171 172 SampleHandler::SampleHandler (const char *name) 173 : _name (NULL) 174 , _width (0) 175 , _height (0) 176 , _framerate (30.0) 177 , _callback (NULL) 178 { 179 if (name) 180 _name = strndup (name, XCAM_MAX_STR_SIZE); 181 182 if (!_frameSaver.ptr ()) { 183 _frameSaver = new FrameSaver (true, 2, 16); 184 } 185 } 186 187 SampleHandler::~SampleHandler () 188 { 189 if (_name) 190 xcam_free (_name); 191 } 192 193 XCamReturn 194 SampleHandler::init (uint32_t width, uint32_t height, double framerate) 195 { 196 XCamReturn ret = XCAM_RETURN_NO_ERROR; 197 _width = width; 198 _height = height; 199 _framerate = framerate; 200 201 return ret; 202 } 203 204 XCamReturn 205 SampleHandler::deinit () 206 { 207 XCamReturn ret = XCAM_RETURN_NO_ERROR; 208 return ret; 209 } 210 211 bool 212 SampleHandler::set_results_callback (AnalyzerCallback *callback) 213 { 214 XCAM_ASSERT (!_callback); 215 _callback = callback; 216 return true; 217 } 218 219 XCamReturn 220 SampleHandler::update_params (const XCamSmartAnalysisParam *params) 221 { 222 XCAM_UNUSED (params); 223 224 XCamReturn ret = XCAM_RETURN_NO_ERROR; 225 return ret; 226 } 227 228 XCamReturn 229 SampleHandler::analyze (XCamVideoBuffer *buffer) 230 { 231 XCAM_LOG_DEBUG ("Smart SampleHandler::analyze on ts:" XCAM_TIMESTAMP_FORMAT, XCAM_TIMESTAMP_ARGS (buffer->timestamp)); 232 if (NULL == buffer) { 233 return XCAM_RETURN_ERROR_PARAM; 234 } 235 XCamReturn ret = XCAM_RETURN_NO_ERROR; 236 237 XCAM_LOG_DEBUG ("format(0x%x), color_bits(%d)", buffer->info.format, buffer->info.color_bits); 238 XCAM_LOG_DEBUG ("size(%d), components(%d)", buffer->info.size, buffer->info.components); 239 XCAM_LOG_DEBUG ("width(%d), heitht(%d)", buffer->info.width, buffer->info.height); 240 XCAM_LOG_DEBUG ("aligned_width(%d), aligned_height(%d)", buffer->info.aligned_width, buffer->info.aligned_height); 241 242 _frameSaver->save_frame (buffer); 243 244 X3aResultList results; 245 XCam3aResultBrightness xcam3a_brightness_result; 246 xcam_mem_clear (xcam3a_brightness_result); 247 xcam3a_brightness_result.head.type = XCAM_3A_RESULT_BRIGHTNESS; 248 xcam3a_brightness_result.head.process_type = XCAM_IMAGE_PROCESS_ALWAYS; 249 xcam3a_brightness_result.head.version = XCAM_VERSION; 250 xcam3a_brightness_result.brightness_level = 9.9; 251 252 SmartPtr<X3aResult> brightness_result = 253 X3aResultFactory::instance ()->create_3a_result ((XCam3aResultHead*)&xcam3a_brightness_result); 254 results.push_back(brightness_result); 255 256 if (_callback) { 257 if (XCAM_RETURN_NO_ERROR == ret) { 258 _callback->x3a_calculation_done (NULL, results); 259 } else { 260 _callback->x3a_calculation_failed (NULL, buffer->timestamp, "pre 3a analyze failed"); 261 } 262 } 263 264 return ret; 265 } 266 267 class XCamSmartAnalyerContext 268 : public AnalyzerCallback 269 { 270 public: 271 XCamSmartAnalyerContext (); 272 ~XCamSmartAnalyerContext (); 273 bool setup_handler (); 274 SmartPtr<SampleHandler> &get_handler () { 275 return _handler; 276 } 277 278 uint32_t get_results (X3aResultList &results); 279 280 // derive from AnalyzerCallback 281 virtual void x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results); 282 283 private: 284 XCAM_DEAD_COPY (XCamSmartAnalyerContext); 285 286 private: 287 // members 288 SmartPtr<SampleHandler> _handler; 289 Mutex _result_mutex; 290 X3aResultList _results; 291 }; 292 293 XCamSmartAnalyerContext::XCamSmartAnalyerContext () 294 { 295 setup_handler (); 296 } 297 298 XCamSmartAnalyerContext::~XCamSmartAnalyerContext () 299 { 300 _handler->deinit (); 301 } 302 303 bool 304 XCamSmartAnalyerContext::setup_handler () 305 { 306 XCAM_ASSERT (!_handler.ptr ()); 307 _handler = new SampleHandler (); 308 XCAM_ASSERT (_handler.ptr ()); 309 _handler->set_results_callback (this); 310 return true; 311 } 312 313 void 314 XCamSmartAnalyerContext::x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results) 315 { 316 XCAM_UNUSED (analyzer); 317 SmartLock locker (_result_mutex); 318 _results.insert (_results.end (), results.begin (), results.end ()); 319 } 320 321 uint32_t 322 XCamSmartAnalyerContext::get_results (X3aResultList &results) 323 { 324 uint32_t size = 0; 325 SmartLock locker (_result_mutex); 326 327 results.assign (_results.begin (), _results.end ()); 328 size = _results.size (); 329 _results.clear (); 330 331 return size; 332 } 333 334 static XCamReturn 335 xcam_create_context (XCamSmartAnalysisContext **context, uint32_t *async_mode, XcamPostResultsFunc post_func) 336 { 337 XCAM_ASSERT (context); 338 XCAM_UNUSED (post_func); 339 XCamSmartAnalyerContext *analysis_context = new XCamSmartAnalyerContext (); 340 *context = ((XCamSmartAnalysisContext*)(analysis_context)); 341 *async_mode = false; 342 343 return XCAM_RETURN_NO_ERROR; 344 } 345 346 static XCamReturn 347 xcam_destroy_context (XCamSmartAnalysisContext *context) 348 { 349 XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context); 350 delete analysis_context; 351 return XCAM_RETURN_NO_ERROR; 352 } 353 354 static XCamReturn 355 xcam_update_params (XCamSmartAnalysisContext *context, const XCamSmartAnalysisParam *params) 356 { 357 XCamReturn ret = XCAM_RETURN_NO_ERROR; 358 XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context); 359 XCAM_ASSERT (analysis_context); 360 361 SmartPtr<SampleHandler> handler = analysis_context->get_handler (); 362 XCAM_ASSERT (handler.ptr ()); 363 XCAM_ASSERT (params); 364 365 ret = handler->update_params (params); 366 if (ret != XCAM_RETURN_NO_ERROR) { 367 XCAM_LOG_WARNING ("update params failed"); 368 } 369 370 return ret; 371 } 372 373 static XCamReturn 374 xcam_get_results (XCamSmartAnalysisContext *context, XCam3aResultHead *results[], uint32_t *res_count) 375 { 376 XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context); 377 XCAM_ASSERT (analysis_context); 378 X3aResultList analysis_results; 379 uint32_t result_count = analysis_context->get_results (analysis_results); 380 381 if (!result_count) { 382 *res_count = 0; 383 XCAM_LOG_DEBUG ("Smart Analysis return no result"); 384 return XCAM_RETURN_NO_ERROR; 385 } 386 387 // mark as static 388 static XCam3aResultHead *res_array[XCAM_3A_MAX_RESULT_COUNT]; 389 XCAM_ASSERT (result_count < XCAM_3A_MAX_RESULT_COUNT); 390 result_count = translate_3a_results_to_xcam (analysis_results, res_array, XCAM_3A_MAX_RESULT_COUNT); 391 392 for (uint32_t i = 0; i < result_count; ++i) { 393 results[i] = res_array[i]; 394 } 395 *res_count = result_count; 396 XCAM_ASSERT (result_count > 0); 397 398 return XCAM_RETURN_NO_ERROR; 399 } 400 401 402 static XCamReturn 403 xcam_analyze (XCamSmartAnalysisContext *context, XCamVideoBuffer *buffer, XCam3aResultHead *results[], uint32_t *res_count) 404 { 405 XCamReturn ret = XCAM_RETURN_NO_ERROR; 406 if (!buffer) { 407 return XCAM_RETURN_ERROR_PARAM; 408 } 409 410 XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context); 411 XCAM_ASSERT (analysis_context); 412 413 SmartPtr<SampleHandler> handler = analysis_context->get_handler (); 414 XCAM_ASSERT (handler.ptr ()); 415 416 ret = handler->analyze(buffer); 417 if (ret != XCAM_RETURN_NO_ERROR) { 418 XCAM_LOG_WARNING ("buffer analyze failed"); 419 } 420 421 xcam_get_results (context, results, res_count); 422 return ret; 423 } 424 425 static void 426 xcam_free_results (XCamSmartAnalysisContext *context, XCam3aResultHead *results[], uint32_t res_count) 427 { 428 XCAM_UNUSED (context); 429 for (uint32_t i = 0; i < res_count; ++i) { 430 if (results[i]) 431 free_3a_result (results[i]); 432 } 433 } 434 435 XCAM_BEGIN_DECLARE 436 437 XCamSmartAnalysisDescription xcam_smart_analysis_desciption = { 438 XCAM_VERSION, 439 sizeof (XCamSmartAnalysisDescription), 440 XCAM_SMART_PLUGIN_PRIORITY_DEFAULT, 441 "sample test", 442 xcam_create_context, 443 xcam_destroy_context, 444 xcam_update_params, 445 xcam_analyze, 446 xcam_free_results 447 }; 448 449 XCAM_END_DECLARE 450 451