xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkisp_demo/demo/sample/sample_smartIr.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *  Copyright (c) 2019 Rockchip Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #include "sample_comm.h"
19 
20 #ifdef SAMPLE_SMART_IR
21 
22 #include <fcntl.h>
23 #include <linux/v4l2-subdev.h>
24 #include <linux/videodev2.h>
25 #include <sys/ioctl.h>
26 #include <unistd.h>
27 
28 #include "rk_smart_ir_api.h"
29 #include "uAPI2/rk_aiq_user_api2_ae.h"
30 #include "uAPI2/rk_aiq_user_api2_awb.h"
31 #include "uAPI2/rk_aiq_user_api2_sysctl.h"
32 
33 #define RK_SMART_IR_AUTO_IRLED true
34 
sample_smartIr_usage()35 static void sample_smartIr_usage()
36 {
37     printf("Usage : \n");
38     printf("  SmartIr API: \n");
39     printf("\t s) SmartIr:         Start SmartIr test.\n");
40     printf("\t e) SmartIr:         Exit SmartIr test.\n");
41     printf("\t c) SmartIr:         Ir wb calibration.\n");
42     printf("\n");
43     printf("\t h) SmartIr:         help.\n");
44     printf("\t q) SmartIr:         return to main sample screen.\n");
45 
46     printf("\n");
47     printf("\t please press the key: ");
48 
49     return;
50 }
51 
sample_print_smartIr_info(const void * arg)52 void sample_print_smartIr_info(const void* arg)
53 {
54     printf("enter SmartIr modult test!\n");
55 }
56 
57 typedef struct sample_smartIr_s {
58     pthread_t tid;
59     bool tquit;
60     const rk_aiq_sys_ctx_t* aiq_ctx;
61     bool started;
62     const char* ir_cut_v4ldev;
63     const char* ir_v4ldev;
64     rk_smart_ir_ctx_t* ir_ctx;
65     rk_smart_ir_params_t ir_configs;
66 } sample_smartIr_t;
67 
68 static sample_smartIr_t g_sample_smartIr_ctx;
69 
enableIrCutter(bool on)70 static void enableIrCutter(bool on)
71 {
72     sample_smartIr_t* smartIr_ctx = &g_sample_smartIr_ctx;
73 
74     struct v4l2_control control;
75 
76     control.id = V4L2_CID_BAND_STOP_FILTER;
77     if (on)
78         control.value = 3; // filter ir
79     else
80         control.value = 0; // ir in
81 
82     int _fd = open(smartIr_ctx->ir_cut_v4ldev, O_RDWR | O_CLOEXEC);
83     if (_fd != -1) {
84         if (ioctl(_fd, VIDIOC_S_CTRL, &control) < 0) {
85             printf("failed to set ircut value %d to device!\n", control.value);
86         }
87         close(_fd);
88     }
89 }
90 
switch_to_day()91 static void switch_to_day()
92 {
93     // ir-cutter on
94     enableIrCutter(true);
95     // ir off
96     // switch to isp day params
97 }
98 
switch_to_night()99 static void switch_to_night()
100 {
101     // switch to isp night params
102     // ir-cutter off
103     enableIrCutter(false);
104     // ir on
105 }
106 
load_ir_configs()107 static void load_ir_configs()
108 {
109     sample_smartIr_t* smartIr_ctx = &g_sample_smartIr_ctx;
110     rk_smart_ir_result_t ir_init_res;
111 
112     smartIr_ctx->ir_cut_v4ldev = NULL;
113     smartIr_ctx->ir_v4ldev = NULL;
114 
115     smartIr_ctx->ir_cut_v4ldev = "/dev/v4l-subdev3";
116     smartIr_ctx->ir_configs.d2n_envL_th = 0.04f;
117     smartIr_ctx->ir_configs.n2d_envL_th = 0.20f;
118     smartIr_ctx->ir_configs.rggain_base = 1.0f;
119     smartIr_ctx->ir_configs.bggain_base = 1.0f;
120     smartIr_ctx->ir_configs.awbgain_rad = 0.10f;
121     smartIr_ctx->ir_configs.awbgain_dis = 0.22f;
122     smartIr_ctx->ir_configs.switch_cnts_th = 100;
123     rk_smart_ir_config(smartIr_ctx->ir_ctx, &smartIr_ctx->ir_configs);
124     // set initial status to day
125     ir_init_res.status = RK_SMART_IR_STATUS_DAY;
126     rk_smart_ir_set_status(smartIr_ctx->ir_ctx, ir_init_res);
127     switch_to_day();
128 }
129 
switch_ir_thread(void * args)130 static void* switch_ir_thread(void* args)
131 {
132     sample_smartIr_t* smartIr_ctx = &g_sample_smartIr_ctx;
133     rk_smart_ir_result_t ir_res;
134     rk_aiq_isp_stats_t *stats_ref = NULL;
135     XCamReturn ret = XCAM_RETURN_NO_ERROR;
136 
137     rk_smart_ir_autoled_t auto_irled = { 0 };
138     int irled_cur_value = 100;
139     if (RK_SMART_IR_AUTO_IRLED) {
140         // TODO: set init irled pwm duty
141         auto_irled.is_smooth_convert = false;
142         auto_irled.auto_irled_val = irled_cur_value;
143         auto_irled.auto_irled_min = 10;
144         auto_irled.auto_irled_max = 100;
145     }
146 
147     while (!smartIr_ctx->tquit) {
148         ret = rk_aiq_uapi2_sysctl_get3AStatsBlk(smartIr_ctx->aiq_ctx, &stats_ref, -1);
149         if (ret == XCAM_RETURN_NO_ERROR && stats_ref != NULL) {
150             rk_smart_ir_runOnce(smartIr_ctx->ir_ctx, stats_ref, &ir_res);
151 
152             rk_aiq_uapi2_sysctl_release3AStatsRef(smartIr_ctx->aiq_ctx, stats_ref);
153 
154             if (RK_SMART_IR_AUTO_IRLED) {
155                 rk_smart_ir_auto_irled(smartIr_ctx->ir_ctx, &auto_irled);
156                 if (irled_cur_value != auto_irled.auto_irled_val) {
157                     irled_cur_value = auto_irled.auto_irled_val;
158                     // TODO: update irled pwm duty
159                 }
160             }
161 
162             if (ir_res.status == RK_SMART_IR_STATUS_DAY) {
163                 switch_to_day();
164             } else if (ir_res.status == RK_SMART_IR_STATUS_NIGHT) {
165                 switch_to_night();
166             } else {
167             }
168             printf("SAMPLE_SMART_IR: switch to %s\n", ir_res.status == RK_SMART_IR_STATUS_DAY ? "DAY" : "Night");
169         } else {
170             if (ret == XCAM_RETURN_NO_ERROR) {
171                 printf("aiq has stopped !\n");
172             } else if (ret == XCAM_RETURN_ERROR_TIMEOUT) {
173                 printf("aiq timeout!\n");
174             } else if (ret == XCAM_RETURN_ERROR_FAILED) {
175                 printf("aiq failed!\n");
176             }
177         }
178     }
179 
180     return NULL;
181 }
182 
sample_smartIr_start(const void * arg)183 static void sample_smartIr_start(const void* arg)
184 {
185     const rk_aiq_sys_ctx_t* ctx = (rk_aiq_sys_ctx_t*)(arg);
186     sample_smartIr_t* smartIr_ctx = &g_sample_smartIr_ctx;
187 
188     smartIr_ctx->ir_ctx = rk_smart_ir_init((rk_aiq_sys_ctx_t*)arg);
189     load_ir_configs();
190 
191     smartIr_ctx->tquit = false;
192     pthread_create(&smartIr_ctx->tid, NULL, switch_ir_thread, NULL);
193     smartIr_ctx->started = true;
194 }
195 
sample_smartIr_stop(const void * arg)196 static void sample_smartIr_stop(const void* arg)
197 {
198     const rk_aiq_sys_ctx_t* ctx = (rk_aiq_sys_ctx_t*)(arg);
199     sample_smartIr_t* smartIr_ctx = &g_sample_smartIr_ctx;
200 
201     if (smartIr_ctx->started) {
202         smartIr_ctx->tquit = true;
203         pthread_join(smartIr_ctx->tid, NULL);
204     }
205     smartIr_ctx->started = false;
206 
207     if (smartIr_ctx->ir_ctx) {
208         rk_smart_ir_deInit(smartIr_ctx->ir_ctx);
209         smartIr_ctx->ir_ctx = NULL;
210     }
211 }
212 
sample_smartIr_calib(const void * arg)213 static void sample_smartIr_calib(const void* arg)
214 {
215     const rk_aiq_sys_ctx_t* ctx = (rk_aiq_sys_ctx_t*)(arg);
216 
217     // 1. make sure no visible light
218     // 2. ircutter off, ir on
219     switch_to_night();
220     // 3. query wb info
221     rk_aiq_wb_querry_info_t wb_info;
222     float RGgain = 0.0f, BGgain = 0.0f;
223     int counts = 0;
224     rk_aiq_isp_stats_t *stats_ref = NULL;
225     printf("SmartIr Calib start ...... \n");
226     XCamReturn ret = XCAM_RETURN_NO_ERROR;
227     while (counts++ < 100) {
228         ret = rk_aiq_uapi2_sysctl_get3AStatsBlk(ctx, &stats_ref, -1);
229         if (ret == XCAM_RETURN_NO_ERROR && stats_ref != NULL) {
230             printf("stats frame id %d \n", stats_ref->frame_id);
231             if (stats_ref->awb_hw_ver == 4) { // isp32
232                 float Rvalue = 0, Gvalue = 0, Bvalue = 0, RGgain = 0, BGgain = 0;
233                 for (int i = 0; i < RK_AIQ_AWB_GRID_NUM_TOTAL; i++) {
234                     Rvalue = (float)stats_ref->awb_stats_v32.blockResult[i].Rvalue;
235                     Gvalue = (float)stats_ref->awb_stats_v32.blockResult[i].Gvalue;
236                     Bvalue = (float)stats_ref->awb_stats_v32.blockResult[i].Bvalue;
237                     RGgain = RGgain + Rvalue / Gvalue;
238                     BGgain = BGgain + Bvalue / Gvalue;
239                 }
240                 RGgain /= RK_AIQ_AWB_GRID_NUM_TOTAL;
241                 BGgain /= RK_AIQ_AWB_GRID_NUM_TOTAL;
242                 printf("origin rggain_base:%0.3f, bggain_base:%0.3f\n", RGgain, BGgain);
243             }
244             rk_aiq_uapi2_sysctl_release3AStatsRef(ctx, stats_ref);
245         } else {
246             if (ret == XCAM_RETURN_NO_ERROR) {
247                 printf("aiq has stopped !\n");
248             } else if (ret == XCAM_RETURN_ERROR_TIMEOUT) {
249                 printf("aiq timeout!\n");
250             } else if (ret == XCAM_RETURN_ERROR_FAILED) {
251                 printf("aiq failed!\n");
252             }
253         }
254     }
255     printf("SmartIr Calib Done ...... \n");
256 }
257 
sample_smartIr_module(const void * arg)258 XCamReturn sample_smartIr_module(const void* arg)
259 {
260     int key = -1;
261     CLEAR();
262 
263     const demo_context_t *demo_ctx = (demo_context_t *)arg;
264     const rk_aiq_sys_ctx_t* ctx;
265     if (demo_ctx->camGroup) {
266         ctx = (rk_aiq_sys_ctx_t*)(demo_ctx->camgroup_ctx);
267     } else {
268         ctx = (rk_aiq_sys_ctx_t*)(demo_ctx->aiq_ctx);
269     }
270 
271     if (ctx == NULL) {
272         ERR("%s, ctx is nullptr\n", __FUNCTION__);
273         return XCAM_RETURN_ERROR_PARAM;
274     }
275 
276     sample_smartIr_usage();
277 
278     g_sample_smartIr_ctx.tquit = false;
279     g_sample_smartIr_ctx.started = false;
280     g_sample_smartIr_ctx.aiq_ctx = ctx;
281     g_sample_smartIr_ctx.ir_ctx = NULL;
282 
283     do {
284         key = getchar();
285         while (key == '\n' || key == '\r')
286             key = getchar();
287         printf("\n");
288 
289         switch (key) {
290         case 'h':
291             CLEAR();
292             sample_smartIr_usage();
293             break;
294         case 'e':
295             sample_smartIr_stop(ctx);
296             break;
297         case 's':
298             sample_smartIr_start(ctx);
299             break;
300         case 'c':
301             sample_smartIr_calib(ctx);
302             break;
303         default:
304             break;
305         }
306     } while (key != 'q' && key != 'Q');
307 
308     sample_smartIr_stop(ctx);
309 
310     return XCAM_RETURN_NO_ERROR;
311 }
312 
313 #else
sample_print_smartIr_info(const void * arg)314 void sample_print_smartIr_info(const void* arg)
315 {
316     printf("enter SmartIr modult test!\n");
317 }
318 
sample_smartIr_module(const void * arg)319 XCamReturn sample_smartIr_module(const void* arg)
320 {
321     printf("Not enabled! Add option SAMPLE_SMART_IR in makefile \n");
322     return XCAM_RETURN_NO_ERROR;
323 }
324 #endif
325