xref: /rockchip-linux_mpp/utils/mpp_enc_roi_utils.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2021 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 #define MODULE_TAG "enc_roi_utils"
18 
19 #include <string.h>
20 
21 #include "rk_type.h"
22 
23 #include "mpp_env.h"
24 #include "mpp_mem.h"
25 #include "mpp_soc.h"
26 #include "mpp_common.h"
27 #include "mpp_debug.h"
28 
29 #include "mpp_enc_roi_utils.h"
30 
31 #define VEPU541_MAX_ROI_NUM     8
32 #define CU_BASE_CFG_BYTE        64
33 #define CU_QP_CFG_BYTE          192
34 
35 typedef enum RoiType_e {
36     ROI_TYPE_AUTO       = -2,
37     ROI_TYPE_NONE       = -1,
38     ROI_TYPE_0          = 0,    /* vepu roi, not support yet */
39     ROI_TYPE_1          = 1,    /* rv1109/rk3566/rk3568 roi */
40     ROI_TYPE_2          = 2,    /* rk3588 roi */
41 
42     /* legacy  */
43     ROI_TYPE_LEGACY     = 0x10, /* legacy region config way */
44     ROI_TYPE_BUTT,
45 } RoiType;
46 
47 typedef struct Vepu541RoiCfg_t {
48     /*
49      * Force_intra
50      * 1 - The corresponding 16x16cu is forced to be intra
51      * 0 - Not force to intra
52      */
53     RK_U16 force_intra  : 1;
54     RK_U16 reserved     : 3;
55     /*
56      * Qp area index
57      * The choosed qp area index.
58      */
59     RK_U16 qp_area_idx  : 3;
60     /*
61      * Area qp limit function enable flag
62      * Force to be true in vepu541
63      */
64     RK_U16 qp_area_en   : 1;
65     /*
66      * Qp_adj
67      * Qp_adj
68      * in absolute qp mode qp_adj is the final qp used by encoder
69      * in relative qp mode qp_adj is a adjustment to final qp
70      */
71     RK_S16 qp_adj       : 7;
72     /*
73      * Qp_adj_mode
74      * Qp adjustment mode
75      * 1 - absolute qp mode:
76      *     the 16x16 MB qp is set to the qp_adj value
77      * 0 - relative qp mode
78      *     the 16x16 MB qp is adjusted by qp_adj value
79      */
80     RK_U16 qp_adj_mode  : 1;
81 } Vepu541RoiCfg;
82 
83 typedef struct Vepu580RoiH264BsCfg_t {
84     RK_U64 force_inter   : 42;
85     RK_U64 mode_mask     : 9;
86     RK_U64 reserved      : 10;
87     RK_U64 force_intra   : 1;
88     RK_U64 qp_adj_en     : 1;
89     RK_U64 amv_en        : 1;
90 } Vepu580RoiH264BsCfg;
91 
92 typedef struct Vepu580RoiH265BsCfg_t {
93     RK_U8 amv_en        : 1;
94     RK_U8 qp_adj        : 1;
95     RK_U8 force_split   : 1;
96     RK_U8 force_intra   : 2;
97     RK_U8 force_inter   : 2;
98 } Vepu580RoiH265BsCfg;
99 
100 typedef struct Vepu580RoiQpCfg_t {
101     RK_U16 reserved     : 4;
102     /*
103      * Qp area index
104      * The choosed qp area index.
105      */
106     RK_U16 qp_area_idx  : 4;
107     /*
108      * Qp_adj
109      * Qp_adj
110      * in absolute qp mode qp_adj is the final qp used by encoder
111      * in relative qp mode qp_adj is a adjustment to final qp
112      */
113     RK_S16 qp_adj       : 7;
114     /*
115      * Qp_adj_mode
116      * Qp adjustment mode
117      * 1 - absolute qp mode:
118      *     the 16x16 MB qp is set to the qp_adj value
119      * 0 - relative qp mode
120      *     the 16x16 MB qp is adjusted by qp_adj value
121      */
122     RK_U16 qp_adj_mode  : 1;
123 } Vepu580RoiQpCfg;
124 
125 typedef struct MppEncRoiImpl_t {
126     /* common parameters */
127     RK_S32              w;
128     RK_S32              h;
129     MppCodingType       type;
130 
131     /* region config set */
132     RoiRegionCfg        *regions;
133     RK_S32              max_count;
134     RK_S32              count;
135 
136     /*
137      * roi_type is for the different encoder roi config
138      *
139      * 0 - rv1109/rk3566/rk3568 roi
140      * 1 - rk3588 roi
141      *
142      * others - legacy roi config
143      */
144     RoiType             roi_type;
145 
146     /* For roi type legacy config */
147     MppEncROICfg        legacy_roi_cfg;
148     MppEncROIRegion     *legacy_roi_region;
149 
150     /* For roi type 1&2 config */
151     MppBufferGroup      roi_grp;
152     MppEncROICfg2       roi_cfg;
153 
154     /* buffer address and size of MppBuffer in MppEncROICfg2 */
155     void                *dst_base;
156     void                *dst_qp;
157     void                *dst_amv;
158     void                *dst_mv;
159     RK_U32              base_cfg_size;
160     RK_U32              qp_cfg_size;
161     RK_U32              amv_cfg_size;
162     RK_U32              mv_cfg_size;
163 
164     RK_U8               *cu_map;
165     RK_U32              cu_size;
166 
167     /* tmp buffer for convert vepu54x roi cfg to vepu58x roi cfg */
168     Vepu541RoiCfg       *tmp;
169 } MppEncRoiImpl;
170 
171 static RK_U32 raster2scan8[64] = {
172     0,  1,  4,  5,  16, 17, 20, 21,
173     2,  3,  6,  7,  18, 19, 22, 23,
174     8,  9,  12, 13, 24, 25, 28, 29,
175     10, 11, 14, 15, 26, 27, 30, 31,
176     32, 33, 36, 37, 48, 49, 52, 53,
177     34, 35, 38, 39, 50, 51, 54, 55,
178     40, 41, 44, 45, 56, 57, 60, 61,
179     42, 43, 46, 47, 58, 59, 62, 63
180 };
181 
182 static RK_U32 raster2zscan16[16] = {
183     0,  1,  4,  5,
184     2,  3,  6,  7,
185     8,  9,  12, 13,
186     10, 11, 14, 15
187 };
188 
vepu54x_h265_set_roi(void * dst_buf,void * src_buf,RK_S32 w,RK_S32 h)189 static MPP_RET vepu54x_h265_set_roi(void *dst_buf, void *src_buf, RK_S32 w, RK_S32 h)
190 {
191     Vepu541RoiCfg *src = (Vepu541RoiCfg *)src_buf;
192     Vepu541RoiCfg *dst = (Vepu541RoiCfg *)dst_buf;
193     RK_S32 mb_w = MPP_ALIGN(w, 64) / 64;
194     RK_S32 mb_h = MPP_ALIGN(h, 64) / 64;
195     RK_S32 ctu_line = mb_w;
196     RK_S32 j;
197 
198     for (j = 0; j < mb_h; j++) {
199         RK_S32 i;
200 
201         for (i = 0; i < mb_w; i++) {
202             RK_S32 ctu_addr = j * ctu_line + i;
203             RK_S32 cu16_num_line = ctu_line * 4;
204             RK_S32 cu16cnt;
205 
206             for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
207                 RK_S32 cu16_addr_in_frame;
208                 RK_S32 cu16_x = cu16cnt % 4;
209                 RK_S32 cu16_y = cu16cnt / 4;
210 
211                 cu16_x += i * 4;
212                 cu16_y += j * 4;
213                 cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
214 
215                 dst[ctu_addr * 16 + cu16cnt] = src[cu16_addr_in_frame];
216             }
217         }
218     }
219 
220     return MPP_OK;
221 }
222 
gen_vepu54x_roi(MppEncRoiImpl * ctx,Vepu541RoiCfg * dst)223 static MPP_RET gen_vepu54x_roi(MppEncRoiImpl *ctx, Vepu541RoiCfg *dst)
224 {
225     RoiRegionCfg *region = ctx->regions;
226     RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
227     RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
228     RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
229     RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
230     Vepu541RoiCfg cfg;
231     MPP_RET ret = MPP_NOK;
232     RK_S32 i;
233 
234     memset(ctx->cu_map, 0, ctx->cu_size);
235 
236     cfg.force_intra = 0;
237     cfg.reserved    = 0;
238     cfg.qp_area_idx = 0;
239     cfg.qp_area_en  = 1;
240     cfg.qp_adj      = 0;
241     cfg.qp_adj_mode = 0;
242 
243     /* step 1. reset all the config */
244     for (i = 0; i < stride_h * stride_v; i++)
245         memcpy(dst + i, &cfg, sizeof(cfg));
246 
247     if (ctx->w <= 0 || ctx->h <= 0) {
248         mpp_err_f("invalid size [%d:%d]\n", ctx->w, ctx->h);
249         goto DONE;
250     }
251 
252     /* check region config */
253     ret = MPP_OK;
254     for (i = 0; i < ctx->count; i++, region++) {
255         if (region->x + region->w > ctx->w || region->y + region->h > ctx->h)
256             ret = MPP_NOK;
257 
258         if (region->force_intra > 1 || region->qp_mode > 1)
259             ret = MPP_NOK;
260 
261         if ((region->qp_mode && region->qp_val > 51) ||
262             (!region->qp_mode && (region->qp_val > 51 || region->qp_val < -51)))
263             ret = MPP_NOK;
264 
265         if (ret) {
266             mpp_err_f("region %d invalid param:\n", i);
267             mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n",
268                       region->x, region->y, region->w, region->h, ctx->w, ctx->h);
269             mpp_err_f("force intra %d qp mode %d val %d\n",
270                       region->force_intra, region->qp_mode, region->qp_val);
271             goto DONE;
272         }
273     }
274 
275     region = ctx->regions;
276     /* step 2. setup region for top to bottom */
277     for (i = 0; i < ctx->count; i++, region++) {
278         Vepu541RoiCfg *p = dst;
279         RK_U8 *map = ctx->cu_map;
280         RK_S32 roi_width  = (region->w + 15) / 16;
281         RK_S32 roi_height = (region->h + 15) / 16;
282         RK_S32 pos_x_init = (region->x + 15) / 16;
283         RK_S32 pos_y_init = (region->y + 15) / 16;
284         RK_S32 pos_x_end  = pos_x_init + roi_width;
285         RK_S32 pos_y_end  = pos_y_init + roi_height;
286         RK_S32 x, y;
287 
288         mpp_assert(pos_x_init >= 0 && pos_x_init < mb_w);
289         mpp_assert(pos_x_end  >= 0 && pos_x_end <= mb_w);
290         mpp_assert(pos_y_init >= 0 && pos_y_init < mb_h);
291         mpp_assert(pos_y_end  >= 0 && pos_y_end <= mb_h);
292 
293         cfg.force_intra = region->force_intra;
294         cfg.reserved    = 0;
295         cfg.qp_area_idx = 0;
296         // NOTE: When roi is enabled the qp_area_en should be one.
297         cfg.qp_area_en  = 1; // region->area_map_en;
298         cfg.qp_adj      = region->qp_val;
299         cfg.qp_adj_mode = region->qp_mode;
300 
301         p += pos_y_init * stride_h + pos_x_init;
302         map += pos_y_init * stride_h + pos_x_init;
303         for (y = 0; y < roi_height; y++) {
304             for (x = 0; x < roi_width; x++) {
305                 memcpy(p + x, &cfg, sizeof(cfg));
306                 if (ctx->type == MPP_VIDEO_CodingAVC) {
307                     *(map + x) = 1;
308                 }
309 
310             }
311             p += stride_h;
312             map += stride_h;
313         }
314 
315         if (ctx->type == MPP_VIDEO_CodingHEVC) {
316             map = ctx->cu_map;
317             RK_U32 stride_cu64_h = stride_h * 16 / 64;
318 
319             roi_width  = (region->w + 64) / 64;
320             roi_height = (region->h + 64) / 64;
321 
322             if (region->x < 64) {
323                 pos_x_init = 0;
324                 roi_width += 2;
325             } else if (region->x % 64) {
326                 pos_x_init = (region->x - 64) / 64;
327                 roi_width += 2;
328             } else
329                 pos_x_init = region->x / 64;
330 
331             if (region->y < 64) {
332                 pos_y_init = 0;
333                 roi_height += 2;
334             } else if (region->y % 64) {
335                 pos_y_init = (region->y - 64) / 64;
336                 roi_height += 2;
337             } else
338                 pos_y_init = region->y / 64;
339 
340             map += pos_y_init * stride_cu64_h + pos_x_init;
341             for (y = 0; y < roi_height; y++) {
342                 for (x = 0; x < roi_width; x++) {
343                     *(map + x) = 1;
344                 }
345                 map += stride_cu64_h;
346             }
347         }
348     }
349 
350 DONE:
351     return ret;
352 }
353 
354 
set_roi_pos_val(RK_U32 * buf,RK_U32 pos,RK_U32 value)355 static MPP_RET set_roi_pos_val(RK_U32 *buf, RK_U32 pos, RK_U32 value)
356 {
357     RK_U32 index = pos / 32;
358     RK_U32 bits  = pos % 32;
359 
360     buf[index] = buf[index] | (value << bits);
361     return MPP_OK;
362 }
363 
364 #define set_roi_qpadj(buf, index, val) \
365     do { \
366         RK_U32 offset = 425 + index; \
367         set_roi_pos_val(buf, offset, val); \
368     } while(0)
369 
370 #define set_roi_force_split(buf, index, val) \
371     do { \
372         RK_U32 offset = 340 + index; \
373         set_roi_pos_val(buf, offset, val); \
374     } while(0)
375 
376 #define set_roi_force_intra(buf, index, val) \
377     do { \
378         RK_U32 offset = 170 + index * 2; \
379         set_roi_pos_val(buf, offset, val); \
380     } while(0)
381 
382 #define set_roi_force_inter(buf, index, val) \
383     do { \
384         RK_U32 offset = index * 2; \
385         set_roi_pos_val(buf, offset, val); \
386     } while(0)
387 
set_roi_cu8_base_cfg(RK_U32 * buf,RK_U32 index,Vepu580RoiH265BsCfg val)388 static void set_roi_cu8_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
389 {
390     set_roi_qpadj(buf, index, val.qp_adj);
391     set_roi_force_split(buf, index, val.force_split);
392     set_roi_force_intra(buf, index, val.force_intra);
393     set_roi_force_inter(buf, index, val.force_inter);
394 }
395 
set_roi_cu16_base_cfg(RK_U32 * buf,RK_U32 index,Vepu580RoiH265BsCfg val)396 static void set_roi_cu16_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
397 {
398     index += 64;
399     set_roi_qpadj(buf, index, val.qp_adj);
400     set_roi_force_split(buf, index, val.force_split);
401     set_roi_force_intra(buf, index, val.force_intra);
402     set_roi_force_inter(buf, index, val.force_inter);
403 }
404 
set_roi_cu32_base_cfg(RK_U32 * buf,RK_U32 index,Vepu580RoiH265BsCfg val)405 static void set_roi_cu32_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
406 {
407     index += 80;
408     set_roi_qpadj(buf, index, val.qp_adj);
409     set_roi_force_split(buf, index, val.force_split);
410     set_roi_force_intra(buf, index, val.force_intra);
411     set_roi_force_inter(buf, index, val.force_inter);
412 }
413 
set_roi_cu64_base_cfg(RK_U32 * buf,Vepu580RoiH265BsCfg val)414 static void set_roi_cu64_base_cfg(RK_U32 *buf, Vepu580RoiH265BsCfg val)
415 {
416     set_roi_qpadj(buf, 84, val.qp_adj);
417     set_roi_force_split(buf, 84, val.force_split);
418     set_roi_force_intra(buf, 84, val.force_intra);
419     set_roi_force_inter(buf, 84, val.force_inter);
420 }
421 
set_roi_qp_cfg(void * buf,RK_U32 index,Vepu541RoiCfg * cfg)422 static void set_roi_qp_cfg(void *buf, RK_U32 index, Vepu541RoiCfg *cfg)
423 {
424     Vepu580RoiQpCfg *qp_cfg_base = (Vepu580RoiQpCfg *)buf;
425     Vepu580RoiQpCfg *qp_cfg = &qp_cfg_base[index];
426 
427     qp_cfg->qp_adj = cfg->qp_adj;
428     qp_cfg->qp_adj_mode = cfg->qp_adj_mode;
429     qp_cfg->qp_area_idx = cfg->qp_area_idx;
430 }
431 
432 #define set_roi_cu8_qp_cfg(buf, index, cfg) \
433     do { \
434         RK_U32 offset = index; \
435         set_roi_qp_cfg(buf, offset, cfg); \
436     } while(0)
437 
438 #define set_roi_cu16_qp_cfg(buf, index, cfg) \
439     do { \
440         RK_U32 offset = 64 + index; \
441         set_roi_qp_cfg(buf, offset, cfg); \
442     } while(0)
443 
444 #define set_roi_cu32_qp_cfg(buf, index, cfg) \
445     do { \
446         RK_U32 offset = 80 + index; \
447         set_roi_qp_cfg(buf, offset, cfg); \
448     } while(0)
449 
450 #define set_roi_cu64_qp_cfg(buf, cfg) \
451     do { \
452         RK_U32 offset = 84; \
453         set_roi_qp_cfg(buf, offset, cfg); \
454     } while(0)
455 
set_roi_amv(RK_U32 * buf,Vepu580RoiH265BsCfg val)456 void set_roi_amv(RK_U32 *buf, Vepu580RoiH265BsCfg val)
457 {
458     set_roi_pos_val(buf, 511, val.amv_en);
459 }
460 
gen_vepu580_roi_h264(MppEncRoiImpl * ctx)461 static MPP_RET gen_vepu580_roi_h264(MppEncRoiImpl *ctx)
462 {
463     RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
464     RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
465     RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
466     RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
467     RK_S32 roi_buf_size = stride_h * stride_v * 8;
468     RK_S32 roi_qp_size = stride_h * stride_v * 2;
469 
470     Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
471     Vepu580RoiQpCfg *dst_qp = ctx->dst_qp;
472     Vepu580RoiH264BsCfg *dst_base = ctx->dst_base;
473     RK_S32 j, k;
474 
475     if (!src || !dst_qp || !dst_base)
476         return MPP_NOK;
477 
478     memset(dst_base, 0, roi_buf_size);
479     memset(dst_qp, 0, roi_qp_size);
480 
481     for (j = 0; j < mb_h; j++) {
482         for (k = 0; k < stride_h; k++) {
483             if (ctx->cu_map[j * stride_h + k]) {
484                 Vepu541RoiCfg *cu_cfg = &src[j * stride_h + k];
485                 Vepu580RoiQpCfg *qp_cfg = &dst_qp[j * stride_h + k];
486                 Vepu580RoiH264BsCfg *base_cfg = &dst_base[j * stride_h + k];
487 
488                 qp_cfg->qp_adj = cu_cfg->qp_adj;
489                 qp_cfg->qp_adj_mode = cu_cfg->qp_adj_mode;
490                 qp_cfg->qp_area_idx = cu_cfg->qp_area_idx;
491                 base_cfg->force_intra = cu_cfg->force_intra;
492                 base_cfg->qp_adj_en = !!cu_cfg->qp_adj;
493 #if 0
494                 if (j < 8 && k < 8) {
495                     RK_U64 *tmp = (RK_U64 *)base_cfg;
496                     RK_U16 *qp = (RK_U16 *)qp_cfg;
497 
498                     mpp_log("force_intra %d, qp_adj_en %d qp_adj %d, qp_adj_mode %d",
499                             base_cfg->force_intra, base_cfg->qp_adj_en, qp_cfg->qp_adj, qp_cfg->qp_adj_mode);
500                     mpp_log("val low %8x hight %8x", *tmp & 0xffffffff, ((*tmp >> 32) & 0xffffffff));
501 
502                     mpp_log("qp cfg %4x", *qp);
503                 }
504 #endif
505             }
506         }
507     }
508 
509     return MPP_OK;
510 }
511 
set_roi_cu16_split_cu8(RK_U32 * buf,RK_U32 cu16index,Vepu580RoiH265BsCfg val)512 void set_roi_cu16_split_cu8(RK_U32 *buf, RK_U32 cu16index, Vepu580RoiH265BsCfg val)
513 {
514     RK_S32 cu16_x = cu16index % 4;
515     RK_S32 cu16_y = cu16index / 4;
516     RK_U32 cu8cnt;
517 
518     // mpp_log("cu16index = %d, force intra = %d, cu16_y= %d", cu16index, val.force_intra, cu16_y);
519     for (cu8cnt = 0; cu8cnt < 4; cu8cnt++) {
520         RK_U32 zindex = 0;
521         RK_U32 cu8_x = cu8cnt % 2;
522         RK_U32 cu8_y = cu8cnt / 2;
523         RK_U32 cu8raster_index = (cu16_y * 2 + cu8_y) * 8 + cu16_x * 2 + cu8_x;
524 
525         //  mpp_log("cu8raster_index = %d", cu8raster_index);
526         zindex = raster2scan8[cu8raster_index];
527         //  mpp_log("cu8raster_index = %d zindex = %d x %d, y %d, cu8_x %d cu8_y %d",
528         //          cu8raster_index,zindex, x, y, cu8_x, cu8_y);
529         set_roi_cu8_base_cfg(buf, zindex, val);
530     }
531 }
532 
gen_vepu580_roi_h265(MppEncRoiImpl * ctx)533 static MPP_RET gen_vepu580_roi_h265(MppEncRoiImpl *ctx)
534 {
535     RK_S32 ctu_w = MPP_ALIGN(ctx->w, 64) / 64;
536     RK_S32 ctu_h = MPP_ALIGN(ctx->h, 64) / 64;
537     RK_S32 roi_buf_size = ctu_w * ctu_h * 64;
538     RK_S32 roi_qp_size =  ctu_w * ctu_h * 256;
539     RK_S32 ctu_line = ctu_w;
540 
541     Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
542     void *dst_qp = ctx->dst_qp;
543     RK_U32 *dst_base = ctx->dst_base;
544     RK_S32 i, j, k, cu16cnt;
545 
546     if (!src || !dst_qp || !dst_base)
547         return MPP_NOK;
548 
549     // mpp_log("roi_qp_size = %d, roi_buf_size %d", roi_qp_size, roi_buf_size);
550     memset(dst_qp, 0, roi_qp_size);
551     memset(dst_base, 0, roi_buf_size);
552 
553     for (j = 0; j < ctu_h; j++) {
554         for (k = 0; k < ctu_w; k++) {
555             RK_S32 cu16_num_line = ctu_line * 4;
556             RK_U32 adjust_cnt = 0;
557 
558             if (ctx->cu_map[j * ctu_w + k]) {
559                 for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
560                     RK_S32 cu16_x;
561                     RK_S32 cu16_y;
562                     RK_S32 cu16_addr_in_frame;
563                     RK_U32 zindex = 0;
564                     Vepu541RoiCfg *cu16_cfg = NULL;
565                     Vepu580RoiH265BsCfg val;
566 
567                     memset(&val, 0, sizeof(val));
568                     cu16_x = cu16cnt & 3;
569                     cu16_y = cu16cnt / 4;
570                     cu16_x += k * 4;
571                     cu16_y += j * 4;
572                     cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
573                     cu16_cfg = &src[cu16_addr_in_frame];
574                     zindex = raster2zscan16[cu16cnt];
575 
576                     val.force_intra = cu16_cfg->force_intra;
577                     val.qp_adj = !!cu16_cfg->qp_adj;
578                     if (val.force_intra || val.qp_adj) {
579                         adjust_cnt++;
580                     }
581 
582                     set_roi_cu16_split_cu8(dst_base, cu16cnt, val);
583                     set_roi_cu16_base_cfg(dst_base, zindex, val);
584                     set_roi_cu16_qp_cfg(dst_qp, zindex, cu16_cfg);
585                     /*
586                      * if all cu16 adjust c64 and cu32 must adjust
587                      * or we will force split to cu 16
588                      */
589                     if (adjust_cnt == 16 && cu16cnt == 15) {
590                         // cu64
591                         set_roi_cu64_base_cfg(dst_base, val);
592                         set_roi_cu64_qp_cfg(dst_qp, cu16_cfg);
593                         // cu32
594                         for (i = 0; i < 4; i++) {
595                             set_roi_cu32_base_cfg(dst_base, i, val);
596                             set_roi_cu32_qp_cfg(dst_qp, i, cu16_cfg);
597                         }
598 
599                         for (i = 0; i < 64; i ++) {
600                             set_roi_cu8_base_cfg(dst_base, i, val);
601                             set_roi_qp_cfg(dst_qp, i, cu16_cfg);
602                         }
603                     } else if (cu16cnt == 15 && adjust_cnt > 0) {
604                         val.force_split = 1;
605                         set_roi_force_split(dst_base, 84, val.force_split);
606                         for (i = 0; i < 4; i++) {
607                             set_roi_force_split(dst_base, 80 + i, val.force_split);
608                         }
609                         for (i = 0; i < 16; i++) {
610                             set_roi_force_split(dst_base, 64 + i, val.force_split);
611                         }
612                     }
613                 }
614             }
615 #if 0
616             if (j < 3 && (k < 3 )) {
617                 mpp_log("j %d, k %d need_update = %d", j, k, need_update);
618                 RK_U16 *qp_val = (RK_U16 *)dst_qp;
619                 for (i = 0; i < CU_BASE_CFG_BYTE / 4; i++) {
620                     mpp_log("cfg[%d] = %08x", i, dst_base[i]);
621                 }
622                 for (i = 0; i < CU_QP_CFG_BYTE / 2; i++) {
623                     mpp_log("qp[%d] = %04x", i, qp_val[i]);
624                 }
625             }
626 #endif
627             dst_base += CU_BASE_CFG_BYTE / 4;
628             dst_qp += CU_QP_CFG_BYTE;
629         }
630     }
631     return MPP_OK;
632 }
633 
mpp_enc_roi_init(MppEncRoiCtx * ctx,RK_U32 w,RK_U32 h,MppCodingType type,RK_S32 count)634 MPP_RET mpp_enc_roi_init(MppEncRoiCtx *ctx, RK_U32 w, RK_U32 h, MppCodingType type, RK_S32 count)
635 {
636     RockchipSocType soc_type = mpp_get_soc_type();
637     RoiType roi_type = ROI_TYPE_AUTO;
638     MppEncRoiImpl *impl = NULL;
639     MPP_RET ret = MPP_NOK;
640 
641     switch (soc_type) {
642     case ROCKCHIP_SOC_RV1109 :
643     case ROCKCHIP_SOC_RV1126 :
644     case ROCKCHIP_SOC_RK3566 :
645     case ROCKCHIP_SOC_RK3568 : {
646         roi_type = ROI_TYPE_1;
647     } break;
648     case ROCKCHIP_SOC_RK3588 : {
649         roi_type = ROI_TYPE_2;
650     } break;
651     default : {
652         roi_type = ROI_TYPE_LEGACY;
653         mpp_log("soc %s run with legacy roi config\n", mpp_get_soc_name());
654     } break;
655     }
656 
657     mpp_env_get_u32("roi_type", (RK_U32 *)&roi_type, roi_type);
658 
659     impl = mpp_calloc(MppEncRoiImpl, 1);
660     if (!impl) {
661         mpp_log("can't create roi context\n");
662         goto done;
663     }
664 
665     impl->w = w;
666     impl->h = h;
667     impl->type = type;
668     impl->roi_type = roi_type;
669     impl->max_count = count;
670     impl->regions = mpp_calloc(RoiRegionCfg, count);
671 
672     switch (roi_type) {
673     case ROI_TYPE_1 : {
674         RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
675         RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
676         RK_U32 ctu_w = MPP_ALIGN(impl->w, 64) / 64;
677         RK_U32 ctu_h  = MPP_ALIGN(impl->w, 64) / 64;
678         RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
679         RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
680 
681         mpp_log("set to vepu54x roi generation\n");
682 
683         impl->base_cfg_size = stride_h * stride_v * sizeof(Vepu541RoiCfg);
684         mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
685 
686         mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
687         if (!impl->roi_cfg.base_cfg_buf) {
688             goto done;
689         }
690         impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
691 
692         /* create tmp buffer for hevc */
693         if (type == MPP_VIDEO_CodingHEVC) {
694             impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
695             impl->cu_map  = mpp_calloc(RK_U8, ctu_w * ctu_h);
696             impl->cu_size = ctu_w * ctu_h;
697             if (!impl->tmp || !impl->cu_map)
698                 goto done;
699         } else {
700             impl->cu_map   = mpp_calloc(RK_U8, mb_w * mb_h);
701             impl->cu_size  = mb_w * mb_h;
702             if (!impl->cu_map)
703                 goto done;
704         }
705 
706         ret = MPP_OK;
707     } break;
708     case ROI_TYPE_2 : {
709         if (type == MPP_VIDEO_CodingHEVC) {
710             RK_U32 ctu_w = MPP_ALIGN(w, 64) / 64;
711             RK_U32 ctu_h  = MPP_ALIGN(h, 64) / 64;
712 
713             impl->base_cfg_size = ctu_w * ctu_h * 64;
714             impl->qp_cfg_size   = ctu_w * ctu_h * 256;
715             impl->amv_cfg_size  = ctu_w * ctu_h * 512;
716             impl->mv_cfg_size   = ctu_w * ctu_h * 4;
717             impl->cu_map        = mpp_calloc(RK_U8, ctu_w * ctu_h);
718             impl->cu_size       = ctu_w * ctu_h;
719         } else {
720             RK_U32 mb_w = MPP_ALIGN(w, 64) / 16;
721             RK_U32 mb_h = MPP_ALIGN(h, 64) / 16;
722 
723             impl->base_cfg_size = mb_w * mb_h * 8;
724             impl->qp_cfg_size   = mb_w * mb_h * 2;
725             impl->amv_cfg_size  = mb_w * mb_h / 4;
726             impl->mv_cfg_size   = mb_w * mb_h * 96 / 4;
727             impl->cu_map        = mpp_calloc(RK_U8, mb_w * mb_h);
728             impl->cu_size       = mb_w * mb_h;
729         }
730 
731         mpp_log("set to vepu58x roi generation\n");
732 
733         impl->roi_cfg.roi_qp_en = 1;
734         mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
735         mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
736         if (!impl->roi_cfg.base_cfg_buf) {
737             goto done;
738         }
739         impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
740         mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.qp_cfg_buf, impl->qp_cfg_size);
741         if (!impl->roi_cfg.qp_cfg_buf) {
742             goto done;
743         }
744         impl->dst_qp = mpp_buffer_get_ptr(impl->roi_cfg.qp_cfg_buf);
745         mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.amv_cfg_buf, impl->amv_cfg_size);
746         if (!impl->roi_cfg.amv_cfg_buf) {
747             goto done;
748         }
749         impl->dst_amv = mpp_buffer_get_ptr(impl->roi_cfg.amv_cfg_buf);
750         mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.mv_cfg_buf, impl->mv_cfg_size);
751         if (!impl->roi_cfg.mv_cfg_buf) {
752             goto done;
753         }
754         impl->dst_mv = mpp_buffer_get_ptr(impl->roi_cfg.mv_cfg_buf);
755 
756         {
757             // create tmp buffer for vepu54x H.264 config first
758             RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
759             RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
760             RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
761             RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
762 
763             impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
764             if (!impl->tmp)
765                 goto done;
766         }
767         ret = MPP_OK;
768     } break;
769     case ROI_TYPE_LEGACY : {
770         impl->legacy_roi_region = mpp_calloc(MppEncROIRegion, count);
771 
772         mpp_assert(impl->legacy_roi_region);
773         impl->legacy_roi_cfg.regions = impl->legacy_roi_region;
774         ret = MPP_OK;
775     } break;
776     default : {
777     } break;
778     }
779 
780 done:
781     if (ret) {
782         if (impl) {
783             mpp_enc_roi_deinit(impl);
784             impl = NULL;
785         }
786     }
787 
788     *ctx = impl;
789     return ret;
790 }
791 
mpp_enc_roi_deinit(MppEncRoiCtx ctx)792 MPP_RET mpp_enc_roi_deinit(MppEncRoiCtx ctx)
793 {
794     MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
795 
796     if (!impl)
797         return MPP_OK;
798 
799     if (impl->roi_cfg.base_cfg_buf) {
800         mpp_buffer_put(impl->roi_cfg.base_cfg_buf);
801         impl->roi_cfg.base_cfg_buf = NULL;
802     }
803 
804     if (impl->roi_cfg.qp_cfg_buf) {
805         mpp_buffer_put(impl->roi_cfg.qp_cfg_buf);
806         impl->roi_cfg.qp_cfg_buf = NULL;
807     }
808     if (impl->roi_cfg.amv_cfg_buf) {
809         mpp_buffer_put(impl->roi_cfg.amv_cfg_buf);
810         impl->roi_cfg.amv_cfg_buf = NULL;
811     }
812     if (impl->roi_cfg.mv_cfg_buf) {
813         mpp_buffer_put(impl->roi_cfg.mv_cfg_buf);
814         impl->roi_cfg.mv_cfg_buf = NULL;
815     }
816 
817     if (impl->roi_grp) {
818         mpp_buffer_group_put(impl->roi_grp);
819         impl->roi_grp = NULL;
820     }
821     MPP_FREE(impl->cu_map);
822     MPP_FREE(impl->legacy_roi_region);
823     MPP_FREE(impl->regions);
824     MPP_FREE(impl->tmp);
825 
826     MPP_FREE(impl);
827     return MPP_OK;
828 }
829 
mpp_enc_roi_add_region(MppEncRoiCtx ctx,RoiRegionCfg * region)830 MPP_RET mpp_enc_roi_add_region(MppEncRoiCtx ctx, RoiRegionCfg *region)
831 {
832     MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
833 
834     if (impl->count >= impl->max_count) {
835         mpp_err("can not add more region with max %d\n", impl->max_count);
836         return MPP_NOK;
837     }
838 
839     memcpy(impl->regions + impl->count, region, sizeof(*impl->regions));
840     impl->count++;
841 
842     return MPP_OK;
843 }
844 
mpp_enc_roi_setup_meta(MppEncRoiCtx ctx,MppMeta meta)845 MPP_RET mpp_enc_roi_setup_meta(MppEncRoiCtx ctx, MppMeta meta)
846 {
847     MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
848 
849     switch (impl->roi_type) {
850     case ROI_TYPE_1 : {
851         switch (impl->type) {
852         case MPP_VIDEO_CodingAVC : {
853             gen_vepu54x_roi(impl, impl->dst_base);
854         } break;
855         case MPP_VIDEO_CodingHEVC : {
856             gen_vepu54x_roi(impl, impl->tmp);
857             vepu54x_h265_set_roi(impl->dst_base, impl->tmp, impl->w, impl->h);
858         } break;
859         default : {
860         } break;
861         }
862 
863         mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
864         mpp_buffer_sync_ro_end(impl->roi_cfg.base_cfg_buf);
865     } break;
866     case ROI_TYPE_2 : {
867         gen_vepu54x_roi(impl, impl->tmp);
868 
869         switch (impl->type) {
870         case MPP_VIDEO_CodingAVC : {
871             gen_vepu580_roi_h264(impl);
872         } break;
873         case MPP_VIDEO_CodingHEVC : {
874             gen_vepu580_roi_h265(impl);
875         } break;
876         default : {
877         } break;
878         }
879 
880         mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
881         mpp_buffer_sync_ro_end(impl->roi_cfg.base_cfg_buf);
882         mpp_buffer_sync_ro_end(impl->roi_cfg.qp_cfg_buf);
883     } break;
884     case ROI_TYPE_LEGACY : {
885         MppEncROIRegion *region = impl->legacy_roi_region;
886         MppEncROICfg *roi_cfg = &impl->legacy_roi_cfg;
887         RoiRegionCfg *regions = impl->regions;
888         RK_S32 i;
889 
890         for (i = 0; i < impl->count; i++) {
891             region[i].x = regions[i].x;
892             region[i].y = regions[i].y;
893             region[i].w = regions[i].w;
894             region[i].h = regions[i].h;
895 
896             region[i].intra = regions[i].force_intra;
897             region[i].abs_qp_en = regions[i].qp_mode;
898             region[i].quality = regions[i].qp_val;
899             region[i].area_map_en = 1;
900             region[i].qp_area_idx = 0;
901         }
902 
903         roi_cfg->number = impl->count;
904         roi_cfg->regions = region;
905 
906         mpp_meta_set_ptr(meta, KEY_ROI_DATA, (void*)roi_cfg);
907     } break;
908     default : {
909     } break;
910     }
911 
912     impl->count = 0;
913 
914     return MPP_OK;
915 }
916