blob: 7e0a961dea36b8861f2e023041d978c50d164bce [file] [log] [blame]
Googler9398cc32022-12-02 17:21:52 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include "vpp_pq.h"
7#include <linux/types.h>
8#include <linux/amlogic/media/amvecm/amvecm.h>
9
10/*BLUE_SCENE default 0*/
11/*GREEN_SCENE default 0*/
12/*SKIN_TONE_SCENE default 0*/
13/*PEAKING_SCENE default 100*/
14/*SATURATION_SCENE default 30*/
15/*DYNAMIC_CONTRAST_SCENE default 0*/
16/*NOISE_SCENE default 0*/
17
18/*
19 * vpp_pq
20 * 0 faceskin
21 * 1 bluesky
22 * 2 food
23 * 3 architecture
24 * 4 grass
25 * 5 nightscop
26 * 6 waterside
27 * 7 flowers
28 * 8 breads
29 * 9 fruits
30 * 10 meats
31 * 11 document
32 * 12 ocean
33 * 13 pattern
34 * 14 group
35 * 15 animals
36 * 16 iceskate
37 * 17 leaves
38 * 18 racetrack
39 * 19 fireworks
40 * 20 waterfall
41 * 21 beach
42 * 22 snows
43 * 23 sunset
44 * 24 default setting
45 */
46int vpp_pq_data[AI_SCENES_MAX][SCENES_VALUE] = {
47 {0, 0, 25, 15, 15, 0, 0, 0, 0, 0},/*faceskin*/
48 {30, 0, 0, 0, 10, 0, 0, 0, 0, 0},/*bluesky*/
49 {0, 0, 0, 15, 20, 0, 0, 0, 0, 0},/*foods*/
50 {0, 0, 0, 25, 0, 2, 0, 0, 0, 0},/*architecture*/
51 {0, 30, 0, 15, 10, 0, 0, 0, 0, 0},/*grass*/
52 {0, 0, 0, 0, 0, 3, 0, 0, 0, 0},/*nightscop*/
53 {0, 0, 0, 20, 0, 2, 0, 0, 0, 0},/*document*/
54 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
55 {0, 0, 0, 100, 70, 0, 0, 0, 0, 0},
56 {0, 0, 0, 100, 70, 0, 0, 0, 0, 0},
57 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
58 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
59 {0, 80, 0, 100, 30, 0, 0, 0, 0, 0},
60 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
61 {0, 80, 0, 100, 30, 0, 0, 0, 0, 0},
62 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
63 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
64 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
65 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
66 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
67 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
68 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
69 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
70 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0},
71 {0, 0, 0, 100, 30, 0, 0, 0, 0, 0}
72};
73
74static unsigned int det_stb_cnt = 30;
75
76static unsigned int det_unstb_cnt = 20;
77
78static unsigned int tolrnc_cnt = 6;
79
80static unsigned int timer_filter_en;
81
82/*aipq policy:
83 * 0 default policy from algorithm, owner gumin
84 * 1: use top 3 blend offset, with timer filter which can select as policy
85 */
86static unsigned int aipq_set_policy;
87
88static unsigned int color_th = 100;
89
90/*scene_prob[0]: scene, scene_prob[1]: prob*/
91int scene_prob[2] = {0, 0};
92struct ai_pq_hist_data aipq_hist_data = {
93 .pre_skin_pct = 0,
94 .pre_green_pct = 0,
95 .pre_blue_pct = 0,
96 .cur_skin_pct = 0,
97 .cur_green_pct = 0,
98 .cur_blue_pct = 0
99};
100
101enum iir_policy_e aipq_tiir_policy_proc(int (*prob)[2], int sc_chg,
102 int *pq_debug, int *kp_flag)
103{
104 static int stable_cnt, unstb_cnt;
105 static int pre_det_sc = -1, pre_det_sec = -1, pre_det_thd = -1;
106 enum iir_policy_e policy, ret_plcy;
107 int prob_sum_2 = 0, prob_sum_3 = 0;
108 static enum aipq_state_mach state_mach = AIPQ_IDLE;
109 int i;
110
111 for (i = 0; i < 3; i++) {
112 prob_sum_3 += prob[i][1];
113 if (i < 2)
114 prob_sum_2 += prob[i][1];
115 }
116
117 if ((pre_det_sc == prob[0][0] && prob[0][1] >= 5000) ||
118 (pre_det_sc == prob[0][0] && pre_det_sec == prob[1][0] &&
119 prob_sum_2 >= 7000) ||
120 (pre_det_sc == prob[0][0] && pre_det_sec == prob[1][0] &&
121 pre_det_thd == prob[2][0] && prob_sum_3 >= 8000)) {
122 policy = SC_DETECTED;
123 } else {
124 policy = SC_INVALID;
125 }
126
127 switch (state_mach) {
128 case AIPQ_IDLE:
129 if (policy == SC_DETECTED) {
130 stable_cnt++;
131 unstb_cnt = 0;
132 state_mach++;
133 }
134 /*set pre detected scene*/
135 pre_det_sc = prob[0][0];
136 pre_det_sec = prob[1][0];
137 pre_det_thd = prob[2][0];
138 ret_plcy = SC_INVALID;
139 break;
140 case AIPQ_DET_UNSTABLE:
141 if (policy == SC_DETECTED)
142 stable_cnt++;
143 else
144 unstb_cnt++;
145
146 det_stb_cnt = get_stb_cnt();
147 tolrnc_cnt = get_tolrnc_cnt();
148
149 if (unstb_cnt >= tolrnc_cnt) {
150 state_mach--;
151 unstb_cnt = 0;
152 stable_cnt = 0;
153 } else if (stable_cnt >= det_stb_cnt) {
154 state_mach++;
155 unstb_cnt = 0;
156 }
157 ret_plcy = SC_INVALID;
158 break;
159 case AIPQ_DET_STATBLE:
160 if (policy == SC_INVALID) {
161 unstb_cnt++;
162 *kp_flag = 1;
163 } else {
164 if (unstb_cnt > 0)
165 unstb_cnt--;
166 }
167
168 det_unstb_cnt = get_unstb_cnt();
169
170 if (unstb_cnt >= det_unstb_cnt) {
171 state_mach = AIPQ_IDLE;
172 stable_cnt = 0;
173 unstb_cnt = 0;
174 }
175 ret_plcy = SC_DETECTED;
176 break;
177 default:
178 ret_plcy = SC_INVALID;
179 break;
180 }
181
182 if (pq_debug[2] > 0x10)
183 pr_info("%s: cur policy = %d, stable_cnt = %d, unstable_cnt = %d, iir policy = %d\n",
184 __func__, policy, stable_cnt, unstb_cnt, ret_plcy);
185
186 return ret_plcy;
187}
188
189int aipq_scs_bld_proc(int (*cfg)[SCENES_VALUE], int (*prob)[2],
190 int *out, int *pq_debug)
191{
192 int i, j;
193 int a = 0;
194 int m;
195 int sc[3];
196 int sc_pr[3];
197 enum iir_policy_e policy;
198 static int pre_out[SCENES_VALUE];
199 int kp_flag = 0;
200
201 memset(out, 0, sizeof(int) * SCENES_VALUE);
202 timer_filter_en = get_timer_filter_en();
203
204 if (!timer_filter_en) {
205 /*prob 10000 as 1.0*/
206 if (prob[0][1] >= 8000) {
207 m = prob[0][0];
208 memcpy(out, cfg[m], sizeof(int) * SCENES_VALUE);
209 } else {
210 for (i = 0; i < 3; i++)
211 a += prob[i][1];
212
213 if (a >= 4500 && prob[0][1] >= 3000) {
214 for (i = 0; i < 3; i++) {
215 sc[i] = prob[i][0];
216 sc_pr[i] = prob[i][1] << 10;
217 sc_pr[i] = div64_s64(sc_pr[i], a);
218 }
219
220 for (i = 0; i < 3; i++) {
221 for (j = 0; j < SCENE_MAX; j++)
222 out[j] +=
223 (*(cfg + sc[i]))[j] * sc_pr[i] >> 10;
224 }
225 } else {
226 if (pq_debug[2] > 0x10)
227 pr_info("sum of top3 prob < 50 percent or top1 prob < 30 per\n");
228 }
229 }
230 return 0;
231 }
232
233 policy = aipq_tiir_policy_proc(prob, 0, pq_debug, &kp_flag);
234
235 switch (policy) {
236 case SC_DETECTED:
237 if (kp_flag) {
238 memcpy(out, pre_out, sizeof(int) * SCENES_VALUE);
239 if (pq_debug[2] > 0x10)
240 pr_info("same policy, keep setting\n");
241 break;
242 }
243 /*prob 10000 as 1.0*/
244 if (prob[0][1] >= 8000) {
245 m = prob[0][0];
246 memcpy(out, cfg[m], sizeof(int) * SCENES_VALUE);
247 } else {
248 for (i = 0; i < 3; i++)
249 a += prob[i][1];
250
251 for (i = 0; i < 3; i++) {
252 sc[i] = prob[i][0];
253 sc_pr[i] = prob[i][1] << 10;
254 sc_pr[i] = div64_s64(sc_pr[i], a);
255 }
256
257 for (i = 0; i < 3; i++) {
258 for (j = 0; j < SCENE_MAX; j++)
259 out[j] +=
260 (*(cfg + sc[i]))[j] * sc_pr[i] >> 10;
261 }
262 }
263
264 memcpy(pre_out, out, sizeof(int) * SCENES_VALUE);
265
266 if (pq_debug[2] > 0x10) {
267 pr_info("top1 prob = %d: bld value: %d, %d, %d, %d, %d, %d, %d\n",
268 prob[0][1], out[0], out[1], out[2], out[3],
269 out[4], out[5], out[6]);
270 }
271 break;
272 case SC_INVALID:
273 if (pq_debug[2] > 0x10)
274 pr_info("detected unstable: skip aipq seeting\n");
275 break;
276 default:
277 break;
278 }
279
280 return 0;
281}
282
283void aipq_scs_proc(struct vframe_s *vf,
284 int (*cfg)[SCENES_VALUE],
285 int (*prob)[2],
286 int *out,
287 int *pq_debug)
288{
289 static int pre_top_one = -1;
290 int top_one, top_one_prob;
291 int top_two, top_two_prob;
292 int top_three, top_three_prob;
293 /*select color: skin/ green/ blue, percent : 1000 as 1.0*/
294 static unsigned int pre_skin_pct;
295 static unsigned int pre_green_pct;
296 static unsigned int pre_blue_pct;
297 unsigned int cur_total_hist = 1, cur_skin_pct, cur_green_pct, cur_blue_pct;
298 u64 cur_skin_hist = 0, cur_green_hist = 0, cur_blue_hist = 0;
299 unsigned int diff_skin_pct, diff_green_pct, diff_blue_pct;
300 int i;
301 static int pre_hist[32];
302
303 memset(out, 0, sizeof(int) * SCENES_VALUE);
304
305 top_one = prob[0][0];
306 top_one_prob = prob[0][1];
307 top_two = prob[1][0];
308 top_two_prob = prob[1][1];
309 top_three = prob[2][0];
310 top_three_prob = prob[2][1];
311
312 for (i = 0; i < 3; i++)
313 cur_skin_hist += vf->prop.hist.vpp_hue_gamma[11 + i];
314 for (i = 0; i < 5; i++)
315 cur_green_hist += vf->prop.hist.vpp_hue_gamma[18 + i];
316 for (i = 0; i < 5; i++)
317 cur_blue_hist += vf->prop.hist.vpp_hue_gamma[27 + i];
318 for (i = 0; i < 32; i++)
319 cur_total_hist += vf->prop.hist.vpp_hue_gamma[i];
320
321 cur_skin_pct = div64_u64(cur_skin_hist * 1000, cur_total_hist);
322 cur_green_pct = div64_u64(cur_green_hist * 1000, cur_total_hist);
323 cur_blue_pct = div64_u64(cur_blue_hist * 1000, cur_total_hist);
324
325 aipq_hist_data.cur_skin_pct = cur_skin_pct;
326 aipq_hist_data.cur_blue_pct = cur_blue_pct;
327 aipq_hist_data.cur_green_pct = cur_green_pct;
328
329 diff_skin_pct = (cur_skin_pct > pre_skin_pct) ?
330 (cur_skin_pct - pre_skin_pct) :
331 (pre_skin_pct - cur_skin_pct);
332
333 diff_green_pct = (cur_green_pct > pre_green_pct) ?
334 (cur_green_pct - pre_green_pct) :
335 (pre_green_pct - cur_green_pct);
336
337 diff_blue_pct = (cur_blue_pct > pre_blue_pct) ?
338 (cur_blue_pct - pre_blue_pct) :
339 (pre_blue_pct - cur_blue_pct);
340
341 color_th = get_color_th();
342
343 if (pre_top_one == top_one) {
344 memcpy(out, cfg[pre_top_one], sizeof(int) * SCENES_VALUE);
345 scene_prob[0] = top_one;
346 scene_prob[1] = top_one_prob;
347 } else if (((pre_top_one == top_two) && (top_two_prob > 1000)) ||
348 ((pre_top_one == top_three) && (top_three_prob > 1000))) {
349 memcpy(out, cfg[pre_top_one], sizeof(int) * SCENES_VALUE);
350
351 if (pre_top_one == top_two) {
352 scene_prob[0] = top_two;
353 scene_prob[1] = top_two_prob;
354 } else {
355 scene_prob[0] = top_three;
356 scene_prob[1] = top_three_prob;
357 }
358 } else if ((diff_skin_pct + diff_green_pct + diff_blue_pct < color_th) &&
359 (pre_top_one >= 0)) {
360 memcpy(out, cfg[pre_top_one], sizeof(int) * SCENES_VALUE);
361 } else if ((top_one == 1) && (pre_top_one == 3) && (pre_blue_pct > 500) &&
362 (pre_blue_pct < cur_blue_pct)) {
363 memcpy(out, cfg[pre_top_one], sizeof(int) * SCENES_VALUE);
364 } else {
365 if (pq_debug[2] == 0x8) {
366 pr_info("pre_top_one = %d, top_one = %d, top_one_prob = %d, diff_skin_pct = %d, diff_green_pct = %d, diff_blue_pct = %d\n",
367 pre_top_one, top_one, top_one_prob,
368 diff_skin_pct, diff_green_pct, diff_blue_pct);
369 for (i = 0; i < 4; i++)
370 pr_info("pre: %d, %d, %d, %d, %d, %d, %d, %d\n",
371 pre_hist[i * 8],
372 pre_hist[i * 8 + 1],
373 pre_hist[i * 8 + 2],
374 pre_hist[i * 8 + 3],
375 pre_hist[i * 8 + 4],
376 pre_hist[i * 8 + 5],
377 pre_hist[i * 8 + 6],
378 pre_hist[i * 8 + 7]);
379 for (i = 0; i < 4; i++)
380 pr_info("cur: %d, %d, %d, %d, %d, %d, %d, %d\n",
381 vf->prop.hist.vpp_hue_gamma[i * 8],
382 vf->prop.hist.vpp_hue_gamma[i * 8 + 1],
383 vf->prop.hist.vpp_hue_gamma[i * 8 + 2],
384 vf->prop.hist.vpp_hue_gamma[i * 8 + 3],
385 vf->prop.hist.vpp_hue_gamma[i * 8 + 4],
386 vf->prop.hist.vpp_hue_gamma[i * 8 + 5],
387 vf->prop.hist.vpp_hue_gamma[i * 8 + 6],
388 vf->prop.hist.vpp_hue_gamma[i * 8 + 7]);
389 }
390 memcpy(out, cfg[top_one], sizeof(int) * SCENES_VALUE);
391 pre_top_one = top_one;
392
393 scene_prob[0] = top_one;
394 scene_prob[1] = top_one_prob;
395 }
396
397 for (i = 0; i < 32; i++)
398 pre_hist[i] = vf->prop.hist.vpp_hue_gamma[i];
399
400 if (pq_debug[2] > 0x10)
401 pr_info("pre_top_one = %d, diff_skin_pct = %d, diff_green_pct = %d, diff_blue_pct = %d\n",
402 pre_top_one, diff_skin_pct,
403 diff_green_pct, diff_blue_pct);
404
405 pre_skin_pct = cur_skin_pct;
406 pre_green_pct = cur_green_pct;
407 pre_blue_pct = cur_blue_pct;
408
409 aipq_hist_data.pre_skin_pct = pre_skin_pct;
410 aipq_hist_data.pre_green_pct = pre_green_pct;
411 aipq_hist_data.pre_blue_pct = pre_blue_pct;
412}
413
414void vf_pq_process(struct vframe_s *vf,
415 struct ai_scenes_pq *vpp_scenes,
416 int *pq_debug)
417{
418 int pq_value;
419 int value;
420 int i = 0;
421 int prob[3][2];
422 int bld_ofst[SCENES_VALUE];
423 static int en_flag;
424
425 if (vf->ai_pq_enable && !en_flag)
426 en_flag = 1;
427
428 if (!en_flag) {
429 if (pq_debug[2] == 0x1)
430 pr_info("vf->ai_pq_enable = %d\n", vf->ai_pq_enable);
431 return;
432 }
433
434 if (en_flag) {
435 if (!vf->ai_pq_enable) {
436 i = 0;
437 while (i < SCENE_MAX) {
438 detected_scenes[i].func(0, 0);
439 i++;
440 }
441 en_flag = 0;
442
443 scene_prob[0] = 0;
444 scene_prob[1] = 0;
445 if (pq_debug[2] == 0x1)
446 pr_info("disable nn detect\n");
447 }
448 }
449
450 pq_value = vf->nn_value[0].maxclass;
451
452 for (i = 0; i < 3; i++) {
453 prob[i][0] = vf->nn_value[i].maxclass;
454 prob[i][1] = vf->nn_value[i].maxprob;
455 if (pq_debug[2] > 0x10)
456 pr_info("classi top%d= %d: prob = %d\n",
457 i + 1, prob[i][0], prob[i][1]);
458 }
459
460 if (pq_debug[0] != -1)
461 pq_value = pq_debug[0];
462
463 if (vf->nn_value[0].maxprob == 0 && pq_debug[0] == -1)
464 return;
465
466 if (pq_debug[1])
467 pq_value = 23;
468
469 aipq_set_policy = get_aipq_set_policy();
470 if (aipq_set_policy)
471 aipq_scs_bld_proc(vpp_pq_data, prob, bld_ofst, pq_debug);
472 else
473 aipq_scs_proc(vf, vpp_pq_data, prob, bld_ofst, pq_debug);
474
475 if (pq_debug[2] == 0x1)
476 pr_info("top5:%d,%d; %d,%d; %d,%d; %d,%d; %d,%d;\n",
477 vf->nn_value[0].maxclass, vf->nn_value[0].maxprob,
478 vf->nn_value[1].maxclass, vf->nn_value[1].maxprob,
479 vf->nn_value[2].maxclass, vf->nn_value[2].maxprob,
480 vf->nn_value[3].maxclass, vf->nn_value[3].maxprob,
481 vf->nn_value[4].maxclass, vf->nn_value[4].maxprob);
482
483 i = 0;
484 while (i < SCENE_MAX) {
485 vpp_scenes[pq_value].pq_scenes = pq_value;
486 if (pq_debug[3]) {
487 detected_scenes[i].func(bld_ofst[i], 1);
488 } else {
489 value = vpp_scenes[pq_value].pq_values[i];
490 detected_scenes[i].func(value, 1);
491 }
492 i++;
493 }
494}
495