1 /*
2 * aiq_wrapper.cpp - aiq wrapper:
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: Wind Yuan <feng.yuan@intel.com>
19 */
20
21 #include <base/xcam_3a_description.h>
22 #include <xcam_std.h>
23 #include "x3a_analyzer_aiq.h"
24 #include "x3a_statistics_queue.h"
25 #include "aiq3a_utils.h"
26 #include "x3a_result_factory.h"
27 #include "x3a_analyze_tuner.h"
28
29 #define DEFAULT_AIQ_CPF_FILE "/etc/atomisp/imx185.cpf"
30
31
32 using namespace XCam;
33
34 #define AIQ_CONTEXT_CAST(context) ((XCam3AAiqContext*)(context))
35
36 class XCam3AAiqContext
37 : public AnalyzerCallback
38 {
39 public:
40 XCam3AAiqContext ();
41 ~XCam3AAiqContext ();
42 bool setup_analyzer (struct atomisp_sensor_mode_data &sensor_mode_data, const char *cpf);
43 void set_size (uint32_t width, uint32_t height);
44 bool setup_stats_pool (uint32_t bit_depth = 8);
is_stats_pool_ready() const45 bool is_stats_pool_ready () const {
46 return (_stats_pool.ptr () ? true : false);
47 }
get_analyzer()48 SmartPtr<X3aAnalyzeTuner> &get_analyzer () {
49 return _analyzer;
50 }
51
52 SmartPtr<X3aIspStatistics> get_stats_buffer ();
53 uint32_t get_results (X3aResultList &results);
54
55 // derive from AnalyzerCallback
56 virtual void x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results);
57 void update_brightness_result(XCamCommonParam *params);
58
59 private:
60 XCAM_DEAD_COPY (XCam3AAiqContext);
61
62 private:
63 // members
64 SmartPtr<X3aAnalyzeTuner> _analyzer;
65 SmartPtr<X3aStatisticsQueue> _stats_pool;
66 uint32_t _video_width;
67 uint32_t _video_height;
68
69 Mutex _result_mutex;
70 X3aResultList _results;
71 double _brightness_level;
72 };
73
XCam3AAiqContext()74 XCam3AAiqContext::XCam3AAiqContext ()
75 : _video_width (0)
76 , _video_height (0)
77 , _brightness_level(0)
78 {
79 }
80
~XCam3AAiqContext()81 XCam3AAiqContext::~XCam3AAiqContext ()
82 {
83 _analyzer->stop ();
84 _analyzer->deinit ();
85 }
86
87 bool
setup_analyzer(struct atomisp_sensor_mode_data & sensor_mode_data,const char * cpf)88 XCam3AAiqContext::setup_analyzer (struct atomisp_sensor_mode_data &sensor_mode_data, const char *cpf)
89 {
90 XCAM_ASSERT (!_analyzer.ptr ());
91 SmartPtr<X3aAnalyzer> aiq_analyzer = new X3aAnalyzerAiq (sensor_mode_data, cpf);
92 XCAM_ASSERT (aiq_analyzer.ptr ());
93
94 _analyzer = new X3aAnalyzeTuner ();
95 XCAM_ASSERT (_analyzer.ptr ());
96
97 _analyzer->set_analyzer (aiq_analyzer);
98 _analyzer->set_results_callback (this);
99 return true;
100 }
101
102 void
set_size(uint32_t width,uint32_t height)103 XCam3AAiqContext::set_size (uint32_t width, uint32_t height)
104 {
105 _video_width = width;
106 _video_height = height;
107 }
108
109 bool
setup_stats_pool(uint32_t bit_depth)110 XCam3AAiqContext::setup_stats_pool (uint32_t bit_depth)
111 {
112 VideoBufferInfo info;
113 info.init (XCAM_PIX_FMT_SGRBG16, _video_width, _video_height);
114
115 _stats_pool = new X3aStatisticsQueue;
116 XCAM_ASSERT (_stats_pool.ptr ());
117
118 _stats_pool->set_bit_depth (bit_depth);
119 XCAM_FAIL_RETURN (
120 WARNING,
121 _stats_pool->set_video_info (info),
122 false,
123 "3a stats set video info failed");
124
125
126 if (!_stats_pool->reserve (6)) {
127 XCAM_LOG_WARNING ("init_3a_stats_pool failed to reserve stats buffer.");
128 return false;
129 }
130
131 return true;
132 }
133
134 SmartPtr<X3aIspStatistics>
get_stats_buffer()135 XCam3AAiqContext::get_stats_buffer ()
136 {
137 SmartPtr<X3aIspStatistics> new_stats =
138 _stats_pool->get_buffer (_stats_pool).dynamic_cast_ptr<X3aIspStatistics> ();
139
140 XCAM_FAIL_RETURN (
141 WARNING,
142 new_stats.ptr (),
143 NULL,
144 "get isp stats buffer failed");
145
146 return new_stats;
147 }
148
149
150 void
x3a_calculation_done(XAnalyzer * analyzer,X3aResultList & results)151 XCam3AAiqContext::x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results)
152 {
153 XCAM_UNUSED (analyzer);
154 SmartLock locker (_result_mutex);
155 _results.insert (_results.end (), results.begin (), results.end ());
156 }
157
158 void
update_brightness_result(XCamCommonParam * params)159 XCam3AAiqContext::update_brightness_result(XCamCommonParam *params)
160 {
161 if( params->brightness == _brightness_level)
162 return;
163 _brightness_level = params->brightness;
164
165 XCam3aResultBrightness xcam3a_brightness_result;
166 xcam_mem_clear (xcam3a_brightness_result);
167 xcam3a_brightness_result.head.type = XCAM_3A_RESULT_BRIGHTNESS;
168 xcam3a_brightness_result.head.process_type = XCAM_IMAGE_PROCESS_ALWAYS;
169 xcam3a_brightness_result.head.version = XCAM_VERSION;
170 xcam3a_brightness_result.brightness_level = _brightness_level;
171
172 SmartPtr<X3aResult> brightness_result =
173 X3aResultFactory::instance ()->create_3a_result ((XCam3aResultHead*)&xcam3a_brightness_result);
174 _results.push_back(brightness_result);
175 }
176
177 uint32_t
get_results(X3aResultList & results)178 XCam3AAiqContext::get_results (X3aResultList &results)
179 {
180 uint32_t size = 0;
181
182 SmartLock locker (_result_mutex);
183
184 results.assign (_results.begin (), _results.end ());
185 size = _results.size ();
186 _results.clear ();
187
188 return size;
189 }
190
191 static SmartPtr<X3aAnalyzeTuner>
get_analyzer(XCam3AContext * context)192 get_analyzer (XCam3AContext *context)
193 {
194 XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context);
195 if (!aiq_context)
196 return NULL;
197
198 return aiq_context->get_analyzer ();
199 }
200
201 static XCamReturn
xcam_create_context(XCam3AContext ** context)202 xcam_create_context (XCam3AContext **context)
203 {
204 XCAM_ASSERT (context);
205 XCam3AAiqContext *aiq_context = new XCam3AAiqContext ();
206 *context = ((XCam3AContext*)(aiq_context));
207 return XCAM_RETURN_NO_ERROR;
208 }
209
210 static XCamReturn
xcam_destroy_context(XCam3AContext * context)211 xcam_destroy_context (XCam3AContext *context)
212 {
213 XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context);
214 delete aiq_context;
215 return XCAM_RETURN_NO_ERROR;
216 }
217
218 static XCamReturn
xcam_configure_3a(XCam3AContext * context,uint32_t width,uint32_t height,double framerate)219 xcam_configure_3a (XCam3AContext *context, uint32_t width, uint32_t height, double framerate)
220 {
221 XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context);
222 XCamReturn ret = XCAM_RETURN_NO_ERROR;
223 struct atomisp_sensor_mode_data sensor_mode_data;
224
225 switch ((int)framerate) {
226 case 30:
227 sensor_mode_data.coarse_integration_time_min = 1;
228 sensor_mode_data.coarse_integration_time_max_margin = 1;
229 sensor_mode_data.fine_integration_time_min = 0;
230 sensor_mode_data.fine_integration_time_max_margin = 0;
231 sensor_mode_data.fine_integration_time_def = 0;
232 sensor_mode_data.frame_length_lines = 1125;
233 sensor_mode_data.line_length_pck = 1100;
234 sensor_mode_data.read_mode = 0;
235 sensor_mode_data.vt_pix_clk_freq_mhz = 37125000;
236 sensor_mode_data.crop_horizontal_start = 0;
237 sensor_mode_data.crop_vertical_start = 0;
238 sensor_mode_data.crop_horizontal_end = 1920;
239 sensor_mode_data.crop_vertical_end = 1080;
240 sensor_mode_data.output_width = 1920;
241 sensor_mode_data.output_height = 1080;
242 sensor_mode_data.binning_factor_x = 1;
243 sensor_mode_data.binning_factor_y = 1;
244 break;
245 default:
246 sensor_mode_data.coarse_integration_time_min = 1;
247 sensor_mode_data.coarse_integration_time_max_margin = 1;
248 sensor_mode_data.fine_integration_time_min = 0;
249 sensor_mode_data.fine_integration_time_max_margin = 0;
250 sensor_mode_data.fine_integration_time_def = 0;
251 sensor_mode_data.frame_length_lines = 1125;
252 sensor_mode_data.line_length_pck = 1320;
253 sensor_mode_data.read_mode = 0;
254 sensor_mode_data.vt_pix_clk_freq_mhz = 37125000;
255 sensor_mode_data.crop_horizontal_start = 0;
256 sensor_mode_data.crop_vertical_start = 0;
257 sensor_mode_data.crop_horizontal_end = 1920;
258 sensor_mode_data.crop_vertical_end = 1080;
259 sensor_mode_data.output_width = 1920;
260 sensor_mode_data.output_height = 1080;
261 sensor_mode_data.binning_factor_x = 1;
262 sensor_mode_data.binning_factor_y = 1;
263 break;
264 }
265
266 XCAM_ASSERT (aiq_context);
267 const char *path_cpf = getenv ("AIQ_CPF_PATH");
268 XCAM_FAIL_RETURN (
269 WARNING,
270 aiq_context->setup_analyzer (sensor_mode_data, path_cpf == NULL ? DEFAULT_AIQ_CPF_FILE : path_cpf),
271 XCAM_RETURN_ERROR_UNKNOWN,
272 "setup aiq 3a analyzer failed");
273
274 SmartPtr<X3aAnalyzeTuner> analyzer = aiq_context->get_analyzer ();
275
276 ret = analyzer->prepare_handlers ();
277 XCAM_FAIL_RETURN (
278 WARNING,
279 ret == XCAM_RETURN_NO_ERROR,
280 ret,
281 "analyzer(aiq3alib) prepare handlers failed");
282
283 ret = analyzer->init (width, height, framerate);
284 XCAM_FAIL_RETURN (
285 WARNING,
286 ret == XCAM_RETURN_NO_ERROR,
287 ret,
288 "configure aiq 3a failed");
289
290 ret = analyzer->start ();
291 XCAM_FAIL_RETURN (
292 WARNING,
293 ret == XCAM_RETURN_NO_ERROR,
294 ret,
295 "start aiq 3a failed");
296
297 aiq_context->set_size (width, height);
298
299 return XCAM_RETURN_NO_ERROR;
300 }
301
302 static XCamReturn
xcam_set_3a_stats(XCam3AContext * context,XCam3AStats * stats,int64_t timestamp)303 xcam_set_3a_stats (XCam3AContext *context, XCam3AStats *stats, int64_t timestamp)
304 {
305 XCamReturn ret = XCAM_RETURN_NO_ERROR;
306 XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context);
307 XCAM_ASSERT (aiq_context);
308
309 SmartPtr<X3aAnalyzeTuner> analyzer = aiq_context->get_analyzer ();
310 XCAM_ASSERT (analyzer.ptr ());
311 XCAM_ASSERT (stats);
312
313 if (!aiq_context->is_stats_pool_ready ()) {
314 // init statistics queue
315 XCAM_FAIL_RETURN (
316 WARNING,
317 aiq_context->setup_stats_pool (stats->info.bit_depth),
318 XCAM_RETURN_ERROR_UNKNOWN,
319 "aiq configure 3a failed on stats pool setup");
320 }
321
322 // Convert stats to atomisp_3a_stats;
323 SmartPtr<X3aIspStatistics> isp_stats = aiq_context->get_stats_buffer ();
324 if (!isp_stats.ptr ()) {
325 XCAM_LOG_WARNING ("get stats bufffer failed or stopped");
326 return XCAM_RETURN_ERROR_MEM;
327 }
328
329 struct atomisp_3a_statistics *raw_stats = isp_stats->get_isp_stats ();
330 XCAM_ASSERT (raw_stats);
331
332 translate_3a_stats (stats, raw_stats);
333 isp_stats->set_timestamp (timestamp);
334
335 ret = analyzer->push_3a_stats (isp_stats);
336 if (ret != XCAM_RETURN_NO_ERROR) {
337 XCAM_LOG_WARNING ("set 3a stats failed");
338 }
339
340 return ret;
341 }
342
343 static XCamReturn
xcam_update_common_params(XCam3AContext * context,XCamCommonParam * params)344 xcam_update_common_params (XCam3AContext *context, XCamCommonParam *params)
345 {
346 if (params) {
347 SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context);
348 XCAM_ASSERT (analyzer.ptr ());
349
350 analyzer->update_common_parameters (*params);
351 }
352 #if 0
353 XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context);
354 aiq_context->update_brightness_result(params);
355 #endif
356 return XCAM_RETURN_NO_ERROR;
357 }
358
359 static XCamReturn
xcam_analyze_awb(XCam3AContext * context,XCamAwbParam * params)360 xcam_analyze_awb (XCam3AContext *context, XCamAwbParam *params)
361 {
362 if (params) {
363 SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context);
364 XCAM_ASSERT (analyzer.ptr ());
365
366 analyzer->update_awb_parameters (*params);
367 }
368 return XCAM_RETURN_NO_ERROR;
369 }
370
371 static XCamReturn
xcam_analyze_ae(XCam3AContext * context,XCamAeParam * params)372 xcam_analyze_ae (XCam3AContext *context, XCamAeParam *params)
373 {
374 if (params) {
375 SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context);
376 XCAM_ASSERT (analyzer.ptr ());
377
378 analyzer->update_ae_parameters (*params);
379 }
380 return XCAM_RETURN_NO_ERROR;
381 }
382
383 static XCamReturn
xcam_analyze_af(XCam3AContext * context,XCamAfParam * params)384 xcam_analyze_af (XCam3AContext *context, XCamAfParam *params)
385 {
386 if (params) {
387 SmartPtr<X3aAnalyzeTuner> analyzer = get_analyzer (context);
388 XCAM_ASSERT (analyzer.ptr ());
389
390 analyzer->update_af_parameters (*params);
391 }
392 return XCAM_RETURN_NO_ERROR;
393 }
394
395 static XCamReturn
xcam_combine_analyze_results(XCam3AContext * context,XCam3aResultHead * results[],uint32_t * res_count)396 xcam_combine_analyze_results (XCam3AContext *context, XCam3aResultHead *results[], uint32_t *res_count)
397 {
398 XCam3AAiqContext *aiq_context = AIQ_CONTEXT_CAST (context);
399 XCAM_ASSERT (aiq_context);
400 X3aResultList aiq_results;
401 uint32_t result_count = aiq_context->get_results (aiq_results);
402
403 if (!result_count) {
404 *res_count = 0;
405 XCAM_LOG_DEBUG ("aiq wrapper combine with no result out");
406 return XCAM_RETURN_NO_ERROR;
407 }
408
409 // mark as static
410 static XCam3aResultHead *res_array[XCAM_3A_MAX_RESULT_COUNT];
411 xcam_mem_clear (res_array);
412 XCAM_ASSERT (result_count < XCAM_3A_MAX_RESULT_COUNT);
413
414 // result_count may changed
415 result_count = translate_3a_results_to_xcam (aiq_results, res_array, XCAM_3A_MAX_RESULT_COUNT);
416
417 for (uint32_t i = 0; i < result_count; ++i) {
418 results[i] = res_array[i];
419 }
420 *res_count = result_count;
421 XCAM_ASSERT (result_count > 0);
422
423 return XCAM_RETURN_NO_ERROR;
424 }
425
426 static void
xcam_free_results(XCam3aResultHead * results[],uint32_t res_count)427 xcam_free_results (XCam3aResultHead *results[], uint32_t res_count)
428 {
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 XCam3ADescription xcam_3a_desciption = {
438 XCAM_VERSION,
439 sizeof (XCam3ADescription),
440 xcam_create_context,
441 xcam_destroy_context,
442 xcam_configure_3a,
443 xcam_set_3a_stats,
444 xcam_update_common_params,
445 xcam_analyze_awb,
446 xcam_analyze_ae,
447 xcam_analyze_af,
448 xcam_combine_analyze_results,
449 xcam_free_results
450 };
451
452 XCAM_END_DECLARE
453
454