xref: /rockchip-linux_mpp/mpp/vproc/iep2/iep2_osd.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2020 Rockchip Electronics Co. LTD
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 #include "iep2_gmv.h"
18 
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 
23 #include "mpp_common.h"
24 #include "mpp_buffer.h"
25 
26 #include "iep2_api.h"
27 
iep2_sort(uint32_t bin[],uint32_t map[],int size)28 void iep2_sort(uint32_t bin[], uint32_t map[], int size)
29 {
30     int i, m, n;
31     uint32_t *dat = malloc(size * sizeof(uint32_t));
32 
33     for (i = 0; i < size; ++i) {
34         map[i] = i;
35         dat[i] = bin[i];
36     }
37 
38     for (m = 0; m < size; ++m) {
39         int max = m;
40         uint32_t temp;
41         int p;
42 
43         for (n = m + 1; n < size; ++n)
44             if (dat[n] > dat[max])
45                 max = n;
46         // Put found minimum element in its place
47         temp = dat[m];
48         p = map[m];
49 
50         map[m] = map[max];
51         map[max] = p;
52         dat[m] = dat[max];
53         dat[max] = temp;
54     }
55 
56     free(dat);
57 }
58 
iep2_osd_check(int8_t * mv,int w,int sx,int ex,int sy,int ey,int * mvx)59 static int iep2_osd_check(int8_t *mv, int w, int sx, int ex, int sy, int ey,
60                           int *mvx)
61 {
62     /* (28 + 27) * 4 + 1 */
63     uint32_t hist[221];
64     uint32_t map[221];
65     int total = (ey - sy + 1) * (ex - sx + 1);
66     int non_zero = 0;
67     int domin = 0;
68     int i, j;
69 
70     memset(hist, 0, sizeof(hist));
71 
72     for (i = sy; i <= ey; ++i) {
73         for (j = sx; j <= ex; ++j) {
74             int8_t v = mv[i * w + j];
75             uint32_t idx = v + 28 * 4;
76 
77             if (idx >= MPP_ARRAY_ELEMS(hist)) {
78                 mpp_log("invalid mv at (%d, %d)\n", j, i);
79                 continue;
80             }
81             hist[idx]++;
82         }
83     }
84 
85     non_zero = total - hist[28 * 4];
86 
87     iep2_sort(hist, map, MPP_ARRAY_ELEMS(hist));
88 
89     domin = hist[map[0]];
90     if (map[0] + 1 < MPP_ARRAY_ELEMS(hist))
91         domin += hist[map[0] + 1];
92     if (map[0] >= 1)
93         domin += hist[map[0] - 1];
94 
95     iep_dbg_trace("total tiles in current osd: %d, non-zero %d\n",
96                   total, non_zero);
97 
98     if (domin * 4 < non_zero * 3) {
99         iep_dbg_trace("main mv %d count %d not dominant\n",
100                       map[0] - 28 * 4, domin);
101         return 0;
102     }
103 
104     *mvx = map[0] - 28 * 4;
105 
106     return 1;
107 }
108 
iep2_set_osd(struct iep2_api_ctx * ctx,struct mv_list * ls)109 void iep2_set_osd(struct iep2_api_ctx *ctx, struct mv_list *ls)
110 {
111     uint32_t i, j;
112     int idx = 0;
113 
114     int sx[8];
115     int ex[8];
116     int sy[8];
117     int ey[8];
118 
119     uint32_t osd_tile_cnt = 0;
120     int mvx;
121     int8_t *pmv = mpp_buffer_get_ptr(ctx->mv_buf);
122 
123     memset(ls, 0, sizeof(*ls));
124 
125     for (i = 0; i < ctx->output.dect_osd_cnt; ++i) {
126         sx[i] = ctx->output.x_sta[i];
127         ex[i] = ctx->output.x_end[i];
128         sy[i] = ctx->output.y_sta[i];
129         ey[i] = ctx->output.y_end[i];
130     }
131 
132     /* Hardware isn't supporting subtitle regions overlap. */
133     for (i = 0; i < ctx->output.dect_osd_cnt; ++i) {
134         for (j = i + 1; j < ctx->output.dect_osd_cnt; ++j) {
135             if (sy[j] == ey[i]) {
136                 if (ex[i] - sx[i] > ex[j] - sx[j]) {
137                     sy[j]++;
138                 } else {
139                     ey[i]--;
140                 }
141             } else {
142                 break;
143             }
144         }
145     }
146 
147     for (i = 0; i < ctx->output.dect_osd_cnt; ++i) {
148         if (!iep2_osd_check(pmv, ctx->params.tile_cols,
149                             sx[i], ex[i], sy[i], ey[i], &mvx))
150             continue;
151 
152         ctx->params.osd_x_sta[idx] = sx[i];
153         ctx->params.osd_x_end[idx] = ex[i];
154         ctx->params.osd_y_sta[idx] = sy[i];
155         ctx->params.osd_y_end[idx] = ey[i];
156 
157         osd_tile_cnt += (ex[i] - sx[i] + 1) * (ey[i] - sy[i] + 1);
158 
159         ls->mv[idx] = mvx;
160         ls->vld[idx] = 1;
161 
162         iep_dbg_trace("[%d] from [%d,%d][%d,%d] to [%d,%d][%d,%d] mv %d\n", i,
163                       sx[i], ex[i], sy[i], ey[i],
164                       ctx->params.osd_x_sta[idx], ctx->params.osd_x_end[idx],
165                       ctx->params.osd_y_sta[idx], ctx->params.osd_y_end[idx],
166                       ls->mv[idx]);
167         idx++;
168     }
169 
170     ctx->params.osd_area_num = idx;
171     ls->idx = idx;
172 
173     iep_dbg_trace("osd tile count %d comb %d\n",
174                   osd_tile_cnt, ctx->output.out_osd_comb_cnt);
175     if (osd_tile_cnt * 2 > ctx->output.out_osd_comb_cnt * 3) {
176         memset(ctx->params.comb_osd_vld, 0, sizeof(ctx->params.comb_osd_vld));
177     } else {
178         memset(ctx->params.comb_osd_vld, 1, sizeof(ctx->params.comb_osd_vld));
179     }
180 }
181 
182