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@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
enable_save_file(bool enable)41 void enable_save_file (bool enable) {
42 _save_file = enable;
43 }
set_interval(uint32_t inteval)44 void set_interval (uint32_t inteval) {
45 _interval = inteval;
46 }
set_frame_save(uint32_t frame_save)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
FrameSaver(bool save,uint32_t interval,uint32_t count)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
~FrameSaver()76 FrameSaver::~FrameSaver ()
77 {
78 close_file ();
79 }
80
81 void
save_frame(XCamVideoBuffer * buffer)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
open_file()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
close_file()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
SampleHandler(const char * name)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
~SampleHandler()187 SampleHandler::~SampleHandler ()
188 {
189 if (_name)
190 xcam_free (_name);
191 }
192
193 XCamReturn
init(uint32_t width,uint32_t height,double framerate)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
deinit()205 SampleHandler::deinit ()
206 {
207 XCamReturn ret = XCAM_RETURN_NO_ERROR;
208 return ret;
209 }
210
211 bool
set_results_callback(AnalyzerCallback * callback)212 SampleHandler::set_results_callback (AnalyzerCallback *callback)
213 {
214 XCAM_ASSERT (!_callback);
215 _callback = callback;
216 return true;
217 }
218
219 XCamReturn
update_params(const XCamSmartAnalysisParam * params)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
analyze(XCamVideoBuffer * buffer)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 ();
get_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
XCamSmartAnalyerContext()293 XCamSmartAnalyerContext::XCamSmartAnalyerContext ()
294 {
295 setup_handler ();
296 }
297
~XCamSmartAnalyerContext()298 XCamSmartAnalyerContext::~XCamSmartAnalyerContext ()
299 {
300 _handler->deinit ();
301 }
302
303 bool
setup_handler()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
x3a_calculation_done(XAnalyzer * analyzer,X3aResultList & results)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
get_results(X3aResultList & results)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
xcam_create_context(XCamSmartAnalysisContext ** context,uint32_t * async_mode,XcamPostResultsFunc post_func)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
xcam_destroy_context(XCamSmartAnalysisContext * context)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
xcam_update_params(XCamSmartAnalysisContext * context,const XCamSmartAnalysisParam * params)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
xcam_get_results(XCamSmartAnalysisContext * context,XCam3aResultHead * results[],uint32_t * res_count)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
xcam_analyze(XCamSmartAnalysisContext * context,XCamVideoBuffer * buffer,XCam3aResultHead * results[],uint32_t * res_count)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
xcam_free_results(XCamSmartAnalysisContext * context,XCam3aResultHead * results[],uint32_t res_count)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