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