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