|
@@ -1,903 +1,903 @@
|
|
|
-/*
|
|
|
- * Copyright 2021 Rockchip Electronics Co. LTD
|
|
|
- *
|
|
|
- * Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
- * you may not use this file except in compliance with the License.
|
|
|
- * You may obtain a copy of the License at
|
|
|
- *
|
|
|
- * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
- *
|
|
|
- * Unless required by applicable law or agreed to in writing, software
|
|
|
- * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
- * See the License for the specific language governing permissions and
|
|
|
- * limitations under the License.
|
|
|
- */
|
|
|
-
|
|
|
-#define MODULE_TAG "enc_roi_utils"
|
|
|
-
|
|
|
-#include <string.h>
|
|
|
-
|
|
|
-#include "rk_type.h"
|
|
|
-
|
|
|
-#include "mpp_env.h"
|
|
|
-#include "mpp_mem.h"
|
|
|
-#include "mpp_soc.h"
|
|
|
-#include "mpp_common.h"
|
|
|
-#include "mpp_debug.h"
|
|
|
-
|
|
|
-#include "mpp_enc_roi_utils.h"
|
|
|
-
|
|
|
-#define VEPU541_MAX_ROI_NUM 8
|
|
|
-#define CU_BASE_CFG_BYTE 64
|
|
|
-#define CU_QP_CFG_BYTE 192
|
|
|
-
|
|
|
-typedef enum RoiType_e {
|
|
|
- ROI_TYPE_AUTO = -2,
|
|
|
- ROI_TYPE_NONE = -1,
|
|
|
- ROI_TYPE_0 = 0, /* vepu roi, not support yet */
|
|
|
- ROI_TYPE_1 = 1, /* rv1109/rk3566/rk3568 roi */
|
|
|
- ROI_TYPE_2 = 2, /* rk3588 roi */
|
|
|
-
|
|
|
- /* legacy */
|
|
|
- ROI_TYPE_LEGACY = 0x10, /* legacy region config way */
|
|
|
- ROI_TYPE_BUTT,
|
|
|
-} RoiType;
|
|
|
-
|
|
|
-typedef struct Vepu541RoiCfg_t {
|
|
|
- /*
|
|
|
- * Force_intra
|
|
|
- * 1 - The corresponding 16x16cu is forced to be intra
|
|
|
- * 0 - Not force to intra
|
|
|
- */
|
|
|
- RK_U16 force_intra : 1;
|
|
|
- RK_U16 reserved : 3;
|
|
|
- /*
|
|
|
- * Qp area index
|
|
|
- * The choosed qp area index.
|
|
|
- */
|
|
|
- RK_U16 qp_area_idx : 3;
|
|
|
- /*
|
|
|
- * Area qp limit function enable flag
|
|
|
- * Force to be true in vepu541
|
|
|
- */
|
|
|
- RK_U16 qp_area_en : 1;
|
|
|
- /*
|
|
|
- * Qp_adj
|
|
|
- * Qp_adj
|
|
|
- * in absolute qp mode qp_adj is the final qp used by encoder
|
|
|
- * in relative qp mode qp_adj is a adjustment to final qp
|
|
|
- */
|
|
|
- RK_S16 qp_adj : 7;
|
|
|
- /*
|
|
|
- * Qp_adj_mode
|
|
|
- * Qp adjustment mode
|
|
|
- * 1 - absolute qp mode:
|
|
|
- * the 16x16 MB qp is set to the qp_adj value
|
|
|
- * 0 - relative qp mode
|
|
|
- * the 16x16 MB qp is adjusted by qp_adj value
|
|
|
- */
|
|
|
- RK_U16 qp_adj_mode : 1;
|
|
|
-} Vepu541RoiCfg;
|
|
|
-
|
|
|
-typedef struct Vepu580RoiH264BsCfg_t {
|
|
|
- RK_U64 force_inter : 42;
|
|
|
- RK_U64 mode_mask : 9;
|
|
|
- RK_U64 reserved : 10;
|
|
|
- RK_U64 force_intra : 1;
|
|
|
- RK_U64 qp_adj_en : 1;
|
|
|
- RK_U64 amv_en : 1;
|
|
|
-} Vepu580RoiH264BsCfg;
|
|
|
-
|
|
|
-typedef struct Vepu580RoiH265BsCfg_t {
|
|
|
- RK_U8 amv_en : 1;
|
|
|
- RK_U8 qp_adj : 1;
|
|
|
- RK_U8 force_split : 1;
|
|
|
- RK_U8 force_intra : 2;
|
|
|
- RK_U8 force_inter : 2;
|
|
|
-} Vepu580RoiH265BsCfg;
|
|
|
-
|
|
|
-typedef struct Vepu580RoiQpCfg_t {
|
|
|
- RK_U16 reserved : 4;
|
|
|
- /*
|
|
|
- * Qp area index
|
|
|
- * The choosed qp area index.
|
|
|
- */
|
|
|
- RK_U16 qp_area_idx : 4;
|
|
|
- /*
|
|
|
- * Qp_adj
|
|
|
- * Qp_adj
|
|
|
- * in absolute qp mode qp_adj is the final qp used by encoder
|
|
|
- * in relative qp mode qp_adj is a adjustment to final qp
|
|
|
- */
|
|
|
- RK_S16 qp_adj : 7;
|
|
|
- /*
|
|
|
- * Qp_adj_mode
|
|
|
- * Qp adjustment mode
|
|
|
- * 1 - absolute qp mode:
|
|
|
- * the 16x16 MB qp is set to the qp_adj value
|
|
|
- * 0 - relative qp mode
|
|
|
- * the 16x16 MB qp is adjusted by qp_adj value
|
|
|
- */
|
|
|
- RK_U16 qp_adj_mode : 1;
|
|
|
-} Vepu580RoiQpCfg;
|
|
|
-
|
|
|
-typedef struct MppEncRoiImpl_t {
|
|
|
- /* common parameters */
|
|
|
- RK_S32 w;
|
|
|
- RK_S32 h;
|
|
|
- MppCodingType type;
|
|
|
-
|
|
|
- /* region config set */
|
|
|
- RoiRegionCfg *regions;
|
|
|
- RK_S32 max_count;
|
|
|
- RK_S32 count;
|
|
|
-
|
|
|
- /*
|
|
|
- * roi_type is for the different encoder roi config
|
|
|
- *
|
|
|
- * 0 - rv1109/rk3566/rk3568 roi
|
|
|
- * 1 - rk3588 roi
|
|
|
- *
|
|
|
- * others - legacy roi config
|
|
|
- */
|
|
|
- RoiType roi_type;
|
|
|
-
|
|
|
- /* For roi type legacy config */
|
|
|
- MppEncROICfg legacy_roi_cfg;
|
|
|
- MppEncROIRegion *legacy_roi_region;
|
|
|
-
|
|
|
- /* For roi type 1&2 config */
|
|
|
- MppBufferGroup roi_grp;
|
|
|
- MppEncROICfg2 roi_cfg;
|
|
|
-
|
|
|
- /* buffer address and size of MppBuffer in MppEncROICfg2 */
|
|
|
- void *dst_base;
|
|
|
- void *dst_qp;
|
|
|
- void *dst_amv;
|
|
|
- void *dst_mv;
|
|
|
- RK_U32 base_cfg_size;
|
|
|
- RK_U32 qp_cfg_size;
|
|
|
- RK_U32 amv_cfg_size;
|
|
|
- RK_U32 mv_cfg_size;
|
|
|
-
|
|
|
- RK_U8 *cu_map;
|
|
|
- RK_U32 cu_size;
|
|
|
-
|
|
|
- /* tmp buffer for convert vepu54x roi cfg to vepu58x roi cfg */
|
|
|
- Vepu541RoiCfg *tmp;
|
|
|
-} MppEncRoiImpl;
|
|
|
-
|
|
|
-static RK_U32 raster2scan8[64] = {
|
|
|
- 0, 1, 4, 5, 16, 17, 20, 21,
|
|
|
- 2, 3, 6, 7, 18, 19, 22, 23,
|
|
|
- 8, 9, 12, 13, 24, 25, 28, 29,
|
|
|
- 10, 11, 14, 15, 26, 27, 30, 31,
|
|
|
- 32, 33, 36, 37, 48, 49, 52, 53,
|
|
|
- 34, 35, 38, 39, 50, 51, 54, 55,
|
|
|
- 40, 41, 44, 45, 56, 57, 60, 61,
|
|
|
- 42, 43, 46, 47, 58, 59, 62, 63
|
|
|
-};
|
|
|
-
|
|
|
-static RK_U32 raster2zscan16[16] = {
|
|
|
- 0, 1, 4, 5,
|
|
|
- 2, 3, 6, 7,
|
|
|
- 8, 9, 12, 13,
|
|
|
- 10, 11, 14, 15
|
|
|
-};
|
|
|
-
|
|
|
-static MPP_RET vepu54x_h265_set_roi(void *dst_buf, void *src_buf, RK_S32 w, RK_S32 h)
|
|
|
-{
|
|
|
- Vepu541RoiCfg *src = (Vepu541RoiCfg *)src_buf;
|
|
|
- Vepu541RoiCfg *dst = (Vepu541RoiCfg *)dst_buf;
|
|
|
- RK_S32 mb_w = MPP_ALIGN(w, 64) / 64;
|
|
|
- RK_S32 mb_h = MPP_ALIGN(h, 64) / 64;
|
|
|
- RK_S32 ctu_line = mb_w;
|
|
|
- RK_S32 j;
|
|
|
-
|
|
|
- for (j = 0; j < mb_h; j++) {
|
|
|
- RK_S32 i;
|
|
|
-
|
|
|
- for (i = 0; i < mb_w; i++) {
|
|
|
- RK_S32 ctu_addr = j * ctu_line + i;
|
|
|
- RK_S32 cu16_num_line = ctu_line * 4;
|
|
|
- RK_S32 cu16cnt;
|
|
|
-
|
|
|
- for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
|
|
|
- RK_S32 cu16_addr_in_frame;
|
|
|
- RK_S32 cu16_x = cu16cnt % 4;
|
|
|
- RK_S32 cu16_y = cu16cnt / 4;
|
|
|
-
|
|
|
- cu16_x += i * 4;
|
|
|
- cu16_y += j * 4;
|
|
|
- cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
|
|
|
-
|
|
|
- dst[ctu_addr * 16 + cu16cnt] = src[cu16_addr_in_frame];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return MPP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static MPP_RET gen_vepu54x_roi(MppEncRoiImpl *ctx, Vepu541RoiCfg *dst)
|
|
|
-{
|
|
|
- RoiRegionCfg *region = ctx->regions;
|
|
|
- RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
|
|
|
- RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
|
|
|
- RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
- RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
- Vepu541RoiCfg cfg;
|
|
|
- MPP_RET ret = MPP_NOK;
|
|
|
- RK_S32 i;
|
|
|
-
|
|
|
- memset(ctx->cu_map, 0, ctx->cu_size);
|
|
|
-
|
|
|
- cfg.force_intra = 0;
|
|
|
- cfg.reserved = 0;
|
|
|
- cfg.qp_area_idx = 0;
|
|
|
- cfg.qp_area_en = 1;
|
|
|
- cfg.qp_adj = 0;
|
|
|
- cfg.qp_adj_mode = 0;
|
|
|
-
|
|
|
- /* step 1. reset all the config */
|
|
|
- for (i = 0; i < stride_h * stride_v; i++)
|
|
|
- memcpy(dst + i, &cfg, sizeof(cfg));
|
|
|
-
|
|
|
- if (ctx->w <= 0 || ctx->h <= 0) {
|
|
|
- mpp_err_f("invalid size [%d:%d]\n", ctx->w, ctx->h);
|
|
|
- goto DONE;
|
|
|
- }
|
|
|
-
|
|
|
- /* check region config */
|
|
|
- ret = MPP_OK;
|
|
|
- for (i = 0; i < ctx->count; i++, region++) {
|
|
|
- if (region->x + region->w > ctx->w || region->y + region->h > ctx->h)
|
|
|
- ret = MPP_NOK;
|
|
|
-
|
|
|
- if (region->force_intra > 1 || region->qp_mode > 1)
|
|
|
- ret = MPP_NOK;
|
|
|
-
|
|
|
- if ((region->qp_mode && region->qp_val > 51) ||
|
|
|
- (!region->qp_mode && (region->qp_val > 51 || region->qp_val < -51)))
|
|
|
- ret = MPP_NOK;
|
|
|
-
|
|
|
- if (ret) {
|
|
|
- mpp_err_f("region %d invalid param:\n", i);
|
|
|
- mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n",
|
|
|
- region->x, region->y, region->w, region->h, ctx->w, ctx->h);
|
|
|
- mpp_err_f("force intra %d qp mode %d val %d\n",
|
|
|
- region->force_intra, region->qp_mode, region->qp_val);
|
|
|
- goto DONE;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- region = ctx->regions;
|
|
|
- /* step 2. setup region for top to bottom */
|
|
|
- for (i = 0; i < ctx->count; i++, region++) {
|
|
|
- Vepu541RoiCfg *p = dst;
|
|
|
- RK_U8 *map = ctx->cu_map;
|
|
|
- RK_S32 roi_width = (region->w + 15) / 16;
|
|
|
- RK_S32 roi_height = (region->h + 15) / 16;
|
|
|
- RK_S32 pos_x_init = (region->x + 15) / 16;
|
|
|
- RK_S32 pos_y_init = (region->y + 15) / 16;
|
|
|
- RK_S32 pos_x_end = pos_x_init + roi_width;
|
|
|
- RK_S32 pos_y_end = pos_y_init + roi_height;
|
|
|
- RK_S32 x, y;
|
|
|
-
|
|
|
- mpp_assert(pos_x_init >= 0 && pos_x_init < mb_w);
|
|
|
- mpp_assert(pos_x_end >= 0 && pos_x_end <= mb_w);
|
|
|
- mpp_assert(pos_y_init >= 0 && pos_y_init < mb_h);
|
|
|
- mpp_assert(pos_y_end >= 0 && pos_y_end <= mb_h);
|
|
|
-
|
|
|
- cfg.force_intra = region->force_intra;
|
|
|
- cfg.reserved = 0;
|
|
|
- cfg.qp_area_idx = 0;
|
|
|
- // NOTE: When roi is enabled the qp_area_en should be one.
|
|
|
- cfg.qp_area_en = 1; // region->area_map_en;
|
|
|
- cfg.qp_adj = region->qp_val;
|
|
|
- cfg.qp_adj_mode = region->qp_mode;
|
|
|
-
|
|
|
- p += pos_y_init * stride_h + pos_x_init;
|
|
|
- map += pos_y_init * stride_h + pos_x_init;
|
|
|
- for (y = 0; y < roi_height; y++) {
|
|
|
- for (x = 0; x < roi_width; x++) {
|
|
|
- memcpy(p + x, &cfg, sizeof(cfg));
|
|
|
- if (ctx->type == MPP_VIDEO_CodingAVC) {
|
|
|
- *(map + x) = 1;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- p += stride_h;
|
|
|
- map += stride_h;
|
|
|
- }
|
|
|
-
|
|
|
- if (ctx->type == MPP_VIDEO_CodingHEVC) {
|
|
|
- map = ctx->cu_map;
|
|
|
- RK_U32 stride_cu64_h = stride_h * 16 / 64;
|
|
|
-
|
|
|
- roi_width = (region->w + 64) / 64;
|
|
|
- roi_height = (region->h + 64) / 64;
|
|
|
-
|
|
|
- if (region->x < 64) {
|
|
|
- pos_x_init = 0;
|
|
|
- roi_width += 2;
|
|
|
- } else if (region->x % 64) {
|
|
|
- pos_x_init = (region->x - 64) / 64;
|
|
|
- roi_width += 2;
|
|
|
- } else
|
|
|
- pos_x_init = region->x / 64;
|
|
|
-
|
|
|
- if (region->y < 64) {
|
|
|
- pos_y_init = 0;
|
|
|
- roi_height += 2;
|
|
|
- } else if (region->y % 64) {
|
|
|
- pos_y_init = (region->y - 64) / 64;
|
|
|
- roi_height += 2;
|
|
|
- } else
|
|
|
- pos_y_init = region->y / 64;
|
|
|
-
|
|
|
- map += pos_y_init * stride_cu64_h + pos_x_init;
|
|
|
- for (y = 0; y < roi_height; y++) {
|
|
|
- for (x = 0; x < roi_width; x++) {
|
|
|
- *(map + x) = 1;
|
|
|
- }
|
|
|
- map += stride_cu64_h;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-DONE:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static MPP_RET set_roi_pos_val(RK_U32 *buf, RK_U32 pos, RK_U32 value)
|
|
|
-{
|
|
|
- RK_U32 index = pos / 32;
|
|
|
- RK_U32 bits = pos % 32;
|
|
|
-
|
|
|
- buf[index] = buf[index] | (value << bits);
|
|
|
- return MPP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-#define set_roi_qpadj(buf, index, val) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = 425 + index; \
|
|
|
- set_roi_pos_val(buf, offset, val); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-#define set_roi_force_split(buf, index, val) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = 340 + index; \
|
|
|
- set_roi_pos_val(buf, offset, val); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-#define set_roi_force_intra(buf, index, val) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = 170 + index * 2; \
|
|
|
- set_roi_pos_val(buf, offset, val); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-#define set_roi_force_inter(buf, index, val) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = index * 2; \
|
|
|
- set_roi_pos_val(buf, offset, val); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-static void set_roi_cu8_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
|
|
|
-{
|
|
|
- set_roi_qpadj(buf, index, val.qp_adj);
|
|
|
- set_roi_force_split(buf, index, val.force_split);
|
|
|
- set_roi_force_intra(buf, index, val.force_intra);
|
|
|
- set_roi_force_inter(buf, index, val.force_inter);
|
|
|
-}
|
|
|
-
|
|
|
-static void set_roi_cu16_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
|
|
|
-{
|
|
|
- index += 64;
|
|
|
- set_roi_qpadj(buf, index, val.qp_adj);
|
|
|
- set_roi_force_split(buf, index, val.force_split);
|
|
|
- set_roi_force_intra(buf, index, val.force_intra);
|
|
|
- set_roi_force_inter(buf, index, val.force_inter);
|
|
|
-}
|
|
|
-
|
|
|
-static void set_roi_cu32_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
|
|
|
-{
|
|
|
- index += 80;
|
|
|
- set_roi_qpadj(buf, index, val.qp_adj);
|
|
|
- set_roi_force_split(buf, index, val.force_split);
|
|
|
- set_roi_force_intra(buf, index, val.force_intra);
|
|
|
- set_roi_force_inter(buf, index, val.force_inter);
|
|
|
-}
|
|
|
-
|
|
|
-static void set_roi_cu64_base_cfg(RK_U32 *buf, Vepu580RoiH265BsCfg val)
|
|
|
-{
|
|
|
- set_roi_qpadj(buf, 84, val.qp_adj);
|
|
|
- set_roi_force_split(buf, 84, val.force_split);
|
|
|
- set_roi_force_intra(buf, 84, val.force_intra);
|
|
|
- set_roi_force_inter(buf, 84, val.force_inter);
|
|
|
-}
|
|
|
-
|
|
|
-static void set_roi_qp_cfg(void *buf, RK_U32 index, Vepu541RoiCfg *cfg)
|
|
|
-{
|
|
|
- Vepu580RoiQpCfg *qp_cfg_base = (Vepu580RoiQpCfg *)buf;
|
|
|
- Vepu580RoiQpCfg *qp_cfg = &qp_cfg_base[index];
|
|
|
-
|
|
|
- qp_cfg->qp_adj = cfg->qp_adj;
|
|
|
- qp_cfg->qp_adj_mode = cfg->qp_adj_mode;
|
|
|
- qp_cfg->qp_area_idx = cfg->qp_area_idx;
|
|
|
-}
|
|
|
-
|
|
|
-#define set_roi_cu8_qp_cfg(buf, index, cfg) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = index; \
|
|
|
- set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-#define set_roi_cu16_qp_cfg(buf, index, cfg) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = 64 + index; \
|
|
|
- set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-#define set_roi_cu32_qp_cfg(buf, index, cfg) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = 80 + index; \
|
|
|
- set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-#define set_roi_cu64_qp_cfg(buf, cfg) \
|
|
|
- do { \
|
|
|
- RK_U32 offset = 84; \
|
|
|
- set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
- } while(0)
|
|
|
-
|
|
|
-void set_roi_amv(RK_U32 *buf, Vepu580RoiH265BsCfg val)
|
|
|
-{
|
|
|
- set_roi_pos_val(buf, 511, val.amv_en);
|
|
|
-}
|
|
|
-
|
|
|
-static MPP_RET gen_vepu580_roi_h264(MppEncRoiImpl *ctx)
|
|
|
-{
|
|
|
- RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
|
|
|
- RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
|
|
|
- RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
- RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
- RK_S32 roi_buf_size = stride_h * stride_v * 8;
|
|
|
- RK_S32 roi_qp_size = stride_h * stride_v * 2;
|
|
|
-
|
|
|
- Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
|
|
|
- Vepu580RoiQpCfg *dst_qp = ctx->dst_qp;
|
|
|
- Vepu580RoiH264BsCfg *dst_base = ctx->dst_base;
|
|
|
- RK_S32 j, k;
|
|
|
-
|
|
|
- if (!src || !dst_qp || !dst_base)
|
|
|
- return MPP_NOK;
|
|
|
-
|
|
|
- memset(dst_base, 0, roi_buf_size);
|
|
|
- memset(dst_qp, 0, roi_qp_size);
|
|
|
-
|
|
|
- for (j = 0; j < mb_h; j++) {
|
|
|
- for (k = 0; k < stride_h; k++) {
|
|
|
- if (ctx->cu_map[j * stride_h + k]) {
|
|
|
- Vepu541RoiCfg *cu_cfg = &src[j * stride_h + k];
|
|
|
- Vepu580RoiQpCfg *qp_cfg = &dst_qp[j * stride_h + k];
|
|
|
- Vepu580RoiH264BsCfg *base_cfg = &dst_base[j * stride_h + k];
|
|
|
-
|
|
|
- qp_cfg->qp_adj = cu_cfg->qp_adj;
|
|
|
- qp_cfg->qp_adj_mode = cu_cfg->qp_adj_mode;
|
|
|
- qp_cfg->qp_area_idx = cu_cfg->qp_area_idx;
|
|
|
- base_cfg->force_intra = cu_cfg->force_intra;
|
|
|
- base_cfg->qp_adj_en = !!cu_cfg->qp_adj;
|
|
|
-#if 0
|
|
|
- if (j < 8 && k < 8) {
|
|
|
- RK_U64 *tmp = (RK_U64 *)base_cfg;
|
|
|
- RK_U16 *qp = (RK_U16 *)qp_cfg;
|
|
|
-
|
|
|
- mpp_log("force_intra %d, qp_adj_en %d qp_adj %d, qp_adj_mode %d",
|
|
|
- base_cfg->force_intra, base_cfg->qp_adj_en, qp_cfg->qp_adj, qp_cfg->qp_adj_mode);
|
|
|
- mpp_log("val low %8x hight %8x", *tmp & 0xffffffff, ((*tmp >> 32) & 0xffffffff));
|
|
|
-
|
|
|
- mpp_log("qp cfg %4x", *qp);
|
|
|
- }
|
|
|
-#endif
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return MPP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-void set_roi_cu16_split_cu8(RK_U32 *buf, RK_U32 cu16index, Vepu580RoiH265BsCfg val)
|
|
|
-{
|
|
|
- RK_S32 cu16_x = cu16index % 4;
|
|
|
- RK_S32 cu16_y = cu16index / 4;
|
|
|
- RK_U32 cu8cnt;
|
|
|
-
|
|
|
- // mpp_log("cu16index = %d, force intra = %d, cu16_y= %d", cu16index, val.force_intra, cu16_y);
|
|
|
- for (cu8cnt = 0; cu8cnt < 4; cu8cnt++) {
|
|
|
- RK_U32 zindex = 0;
|
|
|
- RK_U32 cu8_x = cu8cnt % 2;
|
|
|
- RK_U32 cu8_y = cu8cnt / 2;
|
|
|
- RK_U32 cu8raster_index = (cu16_y * 2 + cu8_y) * 8 + cu16_x * 2 + cu8_x;
|
|
|
-
|
|
|
- // mpp_log("cu8raster_index = %d", cu8raster_index);
|
|
|
- zindex = raster2scan8[cu8raster_index];
|
|
|
- // mpp_log("cu8raster_index = %d zindex = %d x %d, y %d, cu8_x %d cu8_y %d",
|
|
|
- // cu8raster_index,zindex, x, y, cu8_x, cu8_y);
|
|
|
- set_roi_cu8_base_cfg(buf, zindex, val);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static MPP_RET gen_vepu580_roi_h265(MppEncRoiImpl *ctx)
|
|
|
-{
|
|
|
- RK_S32 ctu_w = MPP_ALIGN(ctx->w, 64) / 64;
|
|
|
- RK_S32 ctu_h = MPP_ALIGN(ctx->h, 64) / 64;
|
|
|
- RK_S32 roi_buf_size = ctu_w * ctu_h * 64;
|
|
|
- RK_S32 roi_qp_size = ctu_w * ctu_h * 256;
|
|
|
- RK_S32 ctu_line = ctu_w;
|
|
|
-
|
|
|
- Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
|
|
|
- void *dst_qp = ctx->dst_qp;
|
|
|
- RK_U32 *dst_base = ctx->dst_base;
|
|
|
- RK_S32 i, j, k, cu16cnt;
|
|
|
-
|
|
|
- if (!src || !dst_qp || !dst_base)
|
|
|
- return MPP_NOK;
|
|
|
-
|
|
|
- // mpp_log("roi_qp_size = %d, roi_buf_size %d", roi_qp_size, roi_buf_size);
|
|
|
- memset(dst_qp, 0, roi_qp_size);
|
|
|
- memset(dst_base, 0, roi_buf_size);
|
|
|
-
|
|
|
- for (j = 0; j < ctu_h; j++) {
|
|
|
- for (k = 0; k < ctu_w; k++) {
|
|
|
- RK_S32 cu16_num_line = ctu_line * 4;
|
|
|
- RK_U32 adjust_cnt = 0;
|
|
|
-
|
|
|
- if (ctx->cu_map[j * ctu_w + k]) {
|
|
|
- for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
|
|
|
- RK_S32 cu16_x;
|
|
|
- RK_S32 cu16_y;
|
|
|
- RK_S32 cu16_addr_in_frame;
|
|
|
- RK_U32 zindex = 0;
|
|
|
- Vepu541RoiCfg *cu16_cfg = NULL;
|
|
|
- Vepu580RoiH265BsCfg val;
|
|
|
-
|
|
|
- memset(&val, 0, sizeof(val));
|
|
|
- cu16_x = cu16cnt & 3;
|
|
|
- cu16_y = cu16cnt / 4;
|
|
|
- cu16_x += k * 4;
|
|
|
- cu16_y += j * 4;
|
|
|
- cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
|
|
|
- cu16_cfg = &src[cu16_addr_in_frame];
|
|
|
- zindex = raster2zscan16[cu16cnt];
|
|
|
-
|
|
|
- val.force_intra = cu16_cfg->force_intra;
|
|
|
- val.qp_adj = !!cu16_cfg->qp_adj;
|
|
|
- if (val.force_intra || val.qp_adj) {
|
|
|
- adjust_cnt++;
|
|
|
- }
|
|
|
-
|
|
|
- set_roi_cu16_split_cu8(dst_base, cu16cnt, val);
|
|
|
- set_roi_cu16_base_cfg(dst_base, zindex, val);
|
|
|
- set_roi_cu16_qp_cfg(dst_qp, zindex, cu16_cfg);
|
|
|
- /*
|
|
|
- * if all cu16 adjust c64 and cu32 must adjust
|
|
|
- * or we will force split to cu 16
|
|
|
- */
|
|
|
- if (adjust_cnt == 16 && cu16cnt == 15) {
|
|
|
- // cu64
|
|
|
- set_roi_cu64_base_cfg(dst_base, val);
|
|
|
- set_roi_cu64_qp_cfg(dst_qp, cu16_cfg);
|
|
|
- // cu32
|
|
|
- for (i = 0; i < 4; i++) {
|
|
|
- set_roi_cu32_base_cfg(dst_base, i, val);
|
|
|
- set_roi_cu32_qp_cfg(dst_qp, i, cu16_cfg);
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < 64; i ++) {
|
|
|
- set_roi_cu8_base_cfg(dst_base, i, val);
|
|
|
- set_roi_qp_cfg(dst_qp, i, cu16_cfg);
|
|
|
- }
|
|
|
- } else if (cu16cnt == 15 && adjust_cnt > 0) {
|
|
|
- val.force_split = 1;
|
|
|
- set_roi_force_split(dst_base, 84, val.force_split);
|
|
|
- for (i = 0; i < 4; i++) {
|
|
|
- set_roi_force_split(dst_base, 80 + i, val.force_split);
|
|
|
- }
|
|
|
- for (i = 0; i < 16; i++) {
|
|
|
- set_roi_force_split(dst_base, 64 + i, val.force_split);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-#if 0
|
|
|
- if (j < 3 && (k < 3 )) {
|
|
|
- mpp_log("j %d, k %d need_update = %d", j, k, need_update);
|
|
|
- RK_U16 *qp_val = (RK_U16 *)dst_qp;
|
|
|
- for (i = 0; i < CU_BASE_CFG_BYTE / 4; i++) {
|
|
|
- mpp_log("cfg[%d] = %08x", i, dst_base[i]);
|
|
|
- }
|
|
|
- for (i = 0; i < CU_QP_CFG_BYTE / 2; i++) {
|
|
|
- mpp_log("qp[%d] = %04x", i, qp_val[i]);
|
|
|
- }
|
|
|
- }
|
|
|
-#endif
|
|
|
- dst_base += CU_BASE_CFG_BYTE / 4;
|
|
|
- dst_qp += CU_QP_CFG_BYTE;
|
|
|
- }
|
|
|
- }
|
|
|
- return MPP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-MPP_RET mpp_enc_roi_init(MppEncRoiCtx *ctx, RK_U32 w, RK_U32 h, MppCodingType type, RK_S32 count)
|
|
|
-{
|
|
|
- RockchipSocType soc_type = mpp_get_soc_type();
|
|
|
- RoiType roi_type = ROI_TYPE_AUTO;
|
|
|
- MppEncRoiImpl *impl = NULL;
|
|
|
- MPP_RET ret = MPP_NOK;
|
|
|
-
|
|
|
- switch (soc_type) {
|
|
|
- case ROCKCHIP_SOC_RV1109 :
|
|
|
- case ROCKCHIP_SOC_RV1126 :
|
|
|
- case ROCKCHIP_SOC_RK3566 :
|
|
|
- case ROCKCHIP_SOC_RK3568 : {
|
|
|
- roi_type = ROI_TYPE_1;
|
|
|
- } break;
|
|
|
- case ROCKCHIP_SOC_RK3588 : {
|
|
|
- roi_type = ROI_TYPE_2;
|
|
|
- } break;
|
|
|
- default : {
|
|
|
- roi_type = ROI_TYPE_LEGACY;
|
|
|
- mpp_log("soc %s run with legacy roi config\n", mpp_get_soc_name());
|
|
|
- } break;
|
|
|
- }
|
|
|
-
|
|
|
- mpp_env_get_u32("roi_type", (RK_U32 *)&roi_type, roi_type);
|
|
|
-
|
|
|
- impl = mpp_calloc(MppEncRoiImpl, 1);
|
|
|
- if (!impl) {
|
|
|
- mpp_log("can't create roi context\n");
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- impl->w = w;
|
|
|
- impl->h = h;
|
|
|
- impl->type = type;
|
|
|
- impl->roi_type = roi_type;
|
|
|
- impl->max_count = count;
|
|
|
- impl->regions = mpp_calloc(RoiRegionCfg, count);
|
|
|
-
|
|
|
- switch (roi_type) {
|
|
|
- case ROI_TYPE_1 : {
|
|
|
- RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
|
|
|
- RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
|
|
|
- RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
- RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
-
|
|
|
- mpp_log("set to vepu54x roi generation\n");
|
|
|
-
|
|
|
- impl->base_cfg_size = stride_h * stride_v * sizeof(Vepu541RoiCfg);
|
|
|
- mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION);
|
|
|
-
|
|
|
- mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
|
|
|
- if (!impl->roi_cfg.base_cfg_buf) {
|
|
|
- goto done;
|
|
|
- }
|
|
|
- impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
|
|
|
-
|
|
|
- /* create tmp buffer for hevc */
|
|
|
- if (type == MPP_VIDEO_CodingHEVC) {
|
|
|
- impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
|
|
|
- if (!impl->tmp)
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- ret = MPP_OK;
|
|
|
- } break;
|
|
|
- case ROI_TYPE_2 : {
|
|
|
- if (type == MPP_VIDEO_CodingHEVC) {
|
|
|
- RK_U32 ctu_w = MPP_ALIGN(w, 64) / 64;
|
|
|
- RK_U32 ctu_h = MPP_ALIGN(h, 64) / 64;
|
|
|
-
|
|
|
- impl->base_cfg_size = ctu_w * ctu_h * 64;
|
|
|
- impl->qp_cfg_size = ctu_w * ctu_h * 256;
|
|
|
- impl->amv_cfg_size = ctu_w * ctu_h * 512;
|
|
|
- impl->mv_cfg_size = ctu_w * ctu_h * 4;
|
|
|
- impl->cu_map = mpp_calloc(RK_U8, ctu_w * ctu_h);
|
|
|
- impl->cu_size = ctu_w * ctu_h;
|
|
|
- } else {
|
|
|
- RK_U32 mb_w = MPP_ALIGN(w, 64) / 16;
|
|
|
- RK_U32 mb_h = MPP_ALIGN(h, 64) / 16;
|
|
|
-
|
|
|
- impl->base_cfg_size = mb_w * mb_h * 8;
|
|
|
- impl->qp_cfg_size = mb_w * mb_h * 2;
|
|
|
- impl->amv_cfg_size = mb_w * mb_h / 4;
|
|
|
- impl->mv_cfg_size = mb_w * mb_h * 96 / 4;
|
|
|
- impl->cu_map = mpp_calloc(RK_U8, mb_w * mb_h);
|
|
|
- impl->cu_size = mb_w * mb_h;
|
|
|
- }
|
|
|
-
|
|
|
- mpp_log("set to vepu58x roi generation\n");
|
|
|
-
|
|
|
- impl->roi_cfg.roi_qp_en = 1;
|
|
|
- mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION);
|
|
|
- mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
|
|
|
- if (!impl->roi_cfg.base_cfg_buf) {
|
|
|
- goto done;
|
|
|
- }
|
|
|
- impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
|
|
|
- mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.qp_cfg_buf, impl->qp_cfg_size);
|
|
|
- if (!impl->roi_cfg.qp_cfg_buf) {
|
|
|
- goto done;
|
|
|
- }
|
|
|
- impl->dst_qp = mpp_buffer_get_ptr(impl->roi_cfg.qp_cfg_buf);
|
|
|
- mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.amv_cfg_buf, impl->amv_cfg_size);
|
|
|
- if (!impl->roi_cfg.amv_cfg_buf) {
|
|
|
- goto done;
|
|
|
- }
|
|
|
- impl->dst_amv = mpp_buffer_get_ptr(impl->roi_cfg.amv_cfg_buf);
|
|
|
- mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.mv_cfg_buf, impl->mv_cfg_size);
|
|
|
- if (!impl->roi_cfg.mv_cfg_buf) {
|
|
|
- goto done;
|
|
|
- }
|
|
|
- impl->dst_mv = mpp_buffer_get_ptr(impl->roi_cfg.mv_cfg_buf);
|
|
|
-
|
|
|
- {
|
|
|
- // create tmp buffer for vepu54x H.264 config first
|
|
|
- RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
|
|
|
- RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
|
|
|
- RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
- RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
-
|
|
|
- impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
|
|
|
- if (!impl->tmp)
|
|
|
- goto done;
|
|
|
- }
|
|
|
- ret = MPP_OK;
|
|
|
- } break;
|
|
|
- case ROI_TYPE_LEGACY : {
|
|
|
- impl->legacy_roi_region = mpp_calloc(MppEncROIRegion, count);
|
|
|
-
|
|
|
- mpp_assert(impl->legacy_roi_region);
|
|
|
- impl->legacy_roi_cfg.regions = impl->legacy_roi_region;
|
|
|
- ret = MPP_OK;
|
|
|
- } break;
|
|
|
- default : {
|
|
|
- } break;
|
|
|
- }
|
|
|
-
|
|
|
-done:
|
|
|
- if (ret) {
|
|
|
- if (impl) {
|
|
|
- mpp_enc_roi_deinit(impl);
|
|
|
- impl = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- *ctx = impl;
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-MPP_RET mpp_enc_roi_deinit(MppEncRoiCtx ctx)
|
|
|
-{
|
|
|
- MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
|
|
|
-
|
|
|
- if (!impl)
|
|
|
- return MPP_OK;
|
|
|
-
|
|
|
- if (impl->roi_cfg.base_cfg_buf) {
|
|
|
- mpp_buffer_put(impl->roi_cfg.base_cfg_buf);
|
|
|
- impl->roi_cfg.base_cfg_buf = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (impl->roi_cfg.qp_cfg_buf) {
|
|
|
- mpp_buffer_put(impl->roi_cfg.qp_cfg_buf);
|
|
|
- impl->roi_cfg.qp_cfg_buf = NULL;
|
|
|
- }
|
|
|
- if (impl->roi_cfg.amv_cfg_buf) {
|
|
|
- mpp_buffer_put(impl->roi_cfg.amv_cfg_buf);
|
|
|
- impl->roi_cfg.amv_cfg_buf = NULL;
|
|
|
- }
|
|
|
- if (impl->roi_cfg.mv_cfg_buf) {
|
|
|
- mpp_buffer_put(impl->roi_cfg.mv_cfg_buf);
|
|
|
- impl->roi_cfg.mv_cfg_buf = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (impl->roi_grp) {
|
|
|
- mpp_buffer_group_put(impl->roi_grp);
|
|
|
- impl->roi_grp = NULL;
|
|
|
- }
|
|
|
- MPP_FREE(impl->cu_map);
|
|
|
- MPP_FREE(impl->legacy_roi_region);
|
|
|
- MPP_FREE(impl->regions);
|
|
|
- MPP_FREE(impl->tmp);
|
|
|
-
|
|
|
- MPP_FREE(impl);
|
|
|
- return MPP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-MPP_RET mpp_enc_roi_add_region(MppEncRoiCtx ctx, RoiRegionCfg *region)
|
|
|
-{
|
|
|
- MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
|
|
|
-
|
|
|
- if (impl->count >= impl->max_count) {
|
|
|
- mpp_err("can not add more region with max %d\n", impl->max_count);
|
|
|
- return MPP_NOK;
|
|
|
- }
|
|
|
-
|
|
|
- memcpy(impl->regions + impl->count, region, sizeof(*impl->regions));
|
|
|
- impl->count++;
|
|
|
-
|
|
|
- return MPP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-MPP_RET mpp_enc_roi_setup_meta(MppEncRoiCtx ctx, MppMeta meta)
|
|
|
-{
|
|
|
- MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
|
|
|
-
|
|
|
- switch (impl->roi_type) {
|
|
|
- case ROI_TYPE_1 : {
|
|
|
- switch (impl->type) {
|
|
|
- case MPP_VIDEO_CodingAVC : {
|
|
|
- gen_vepu54x_roi(impl, impl->dst_base);
|
|
|
- } break;
|
|
|
- case MPP_VIDEO_CodingHEVC : {
|
|
|
- gen_vepu54x_roi(impl, impl->tmp);
|
|
|
- vepu54x_h265_set_roi(impl->dst_base, impl->tmp, impl->w, impl->h);
|
|
|
- } break;
|
|
|
- default : {
|
|
|
- } break;
|
|
|
- }
|
|
|
-
|
|
|
- mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
|
|
|
- } break;
|
|
|
- case ROI_TYPE_2 : {
|
|
|
- gen_vepu54x_roi(impl, impl->tmp);
|
|
|
-
|
|
|
- switch (impl->type) {
|
|
|
- case MPP_VIDEO_CodingAVC : {
|
|
|
- gen_vepu580_roi_h264(impl);
|
|
|
- } break;
|
|
|
- case MPP_VIDEO_CodingHEVC : {
|
|
|
- gen_vepu580_roi_h265(impl);
|
|
|
- } break;
|
|
|
- default : {
|
|
|
- } break;
|
|
|
- }
|
|
|
-
|
|
|
- mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
|
|
|
- } break;
|
|
|
- case ROI_TYPE_LEGACY : {
|
|
|
- MppEncROIRegion *region = impl->legacy_roi_region;
|
|
|
- MppEncROICfg *roi_cfg = &impl->legacy_roi_cfg;
|
|
|
- RoiRegionCfg *regions = impl->regions;
|
|
|
- RK_S32 i;
|
|
|
-
|
|
|
- for (i = 0; i < impl->count; i++) {
|
|
|
- region[i].x = regions[i].x;
|
|
|
- region[i].y = regions[i].y;
|
|
|
- region[i].w = regions[i].w;
|
|
|
- region[i].h = regions[i].h;
|
|
|
-
|
|
|
- region[i].intra = regions[i].force_intra;
|
|
|
- region[i].abs_qp_en = regions[i].qp_mode;
|
|
|
- region[i].quality = regions[i].qp_val;
|
|
|
- region[i].area_map_en = 1;
|
|
|
- region[i].qp_area_idx = 0;
|
|
|
- }
|
|
|
-
|
|
|
- roi_cfg->number = impl->count;
|
|
|
- roi_cfg->regions = region;
|
|
|
-
|
|
|
- mpp_meta_set_ptr(meta, KEY_ROI_DATA, (void*)roi_cfg);
|
|
|
- } break;
|
|
|
- default : {
|
|
|
- } break;
|
|
|
- }
|
|
|
-
|
|
|
- impl->count = 0;
|
|
|
-
|
|
|
- return MPP_OK;
|
|
|
-}
|
|
|
+/*
|
|
|
+ * Copyright 2021 Rockchip Electronics Co. LTD
|
|
|
+ *
|
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
+ * you may not use this file except in compliance with the License.
|
|
|
+ * You may obtain a copy of the License at
|
|
|
+ *
|
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+ *
|
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+ * See the License for the specific language governing permissions and
|
|
|
+ * limitations under the License.
|
|
|
+ */
|
|
|
+
|
|
|
+#define MODULE_TAG "enc_roi_utils"
|
|
|
+
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+#include "rk_type.h"
|
|
|
+
|
|
|
+#include "mpp_env.h"
|
|
|
+#include "mpp_mem.h"
|
|
|
+#include "mpp_soc.h"
|
|
|
+#include "mpp_common.h"
|
|
|
+#include "mpp_debug.h"
|
|
|
+
|
|
|
+#include "mpp_enc_roi_utils.h"
|
|
|
+
|
|
|
+#define VEPU541_MAX_ROI_NUM 8
|
|
|
+#define CU_BASE_CFG_BYTE 64
|
|
|
+#define CU_QP_CFG_BYTE 192
|
|
|
+
|
|
|
+typedef enum RoiType_e {
|
|
|
+ ROI_TYPE_AUTO = -2,
|
|
|
+ ROI_TYPE_NONE = -1,
|
|
|
+ ROI_TYPE_0 = 0, /* vepu roi, not support yet */
|
|
|
+ ROI_TYPE_1 = 1, /* rv1109/rk3566/rk3568 roi */
|
|
|
+ ROI_TYPE_2 = 2, /* rk3588 roi */
|
|
|
+
|
|
|
+ /* legacy */
|
|
|
+ ROI_TYPE_LEGACY = 0x10, /* legacy region config way */
|
|
|
+ ROI_TYPE_BUTT,
|
|
|
+} RoiType;
|
|
|
+
|
|
|
+typedef struct Vepu541RoiCfg_t {
|
|
|
+ /*
|
|
|
+ * Force_intra
|
|
|
+ * 1 - The corresponding 16x16cu is forced to be intra
|
|
|
+ * 0 - Not force to intra
|
|
|
+ */
|
|
|
+ RK_U16 force_intra : 1;
|
|
|
+ RK_U16 reserved : 3;
|
|
|
+ /*
|
|
|
+ * Qp area index
|
|
|
+ * The choosed qp area index.
|
|
|
+ */
|
|
|
+ RK_U16 qp_area_idx : 3;
|
|
|
+ /*
|
|
|
+ * Area qp limit function enable flag
|
|
|
+ * Force to be true in vepu541
|
|
|
+ */
|
|
|
+ RK_U16 qp_area_en : 1;
|
|
|
+ /*
|
|
|
+ * Qp_adj
|
|
|
+ * Qp_adj
|
|
|
+ * in absolute qp mode qp_adj is the final qp used by encoder
|
|
|
+ * in relative qp mode qp_adj is a adjustment to final qp
|
|
|
+ */
|
|
|
+ RK_S16 qp_adj : 7;
|
|
|
+ /*
|
|
|
+ * Qp_adj_mode
|
|
|
+ * Qp adjustment mode
|
|
|
+ * 1 - absolute qp mode:
|
|
|
+ * the 16x16 MB qp is set to the qp_adj value
|
|
|
+ * 0 - relative qp mode
|
|
|
+ * the 16x16 MB qp is adjusted by qp_adj value
|
|
|
+ */
|
|
|
+ RK_U16 qp_adj_mode : 1;
|
|
|
+} Vepu541RoiCfg;
|
|
|
+
|
|
|
+typedef struct Vepu580RoiH264BsCfg_t {
|
|
|
+ RK_U64 force_inter : 42;
|
|
|
+ RK_U64 mode_mask : 9;
|
|
|
+ RK_U64 reserved : 10;
|
|
|
+ RK_U64 force_intra : 1;
|
|
|
+ RK_U64 qp_adj_en : 1;
|
|
|
+ RK_U64 amv_en : 1;
|
|
|
+} Vepu580RoiH264BsCfg;
|
|
|
+
|
|
|
+typedef struct Vepu580RoiH265BsCfg_t {
|
|
|
+ RK_U8 amv_en : 1;
|
|
|
+ RK_U8 qp_adj : 1;
|
|
|
+ RK_U8 force_split : 1;
|
|
|
+ RK_U8 force_intra : 2;
|
|
|
+ RK_U8 force_inter : 2;
|
|
|
+} Vepu580RoiH265BsCfg;
|
|
|
+
|
|
|
+typedef struct Vepu580RoiQpCfg_t {
|
|
|
+ RK_U16 reserved : 4;
|
|
|
+ /*
|
|
|
+ * Qp area index
|
|
|
+ * The choosed qp area index.
|
|
|
+ */
|
|
|
+ RK_U16 qp_area_idx : 4;
|
|
|
+ /*
|
|
|
+ * Qp_adj
|
|
|
+ * Qp_adj
|
|
|
+ * in absolute qp mode qp_adj is the final qp used by encoder
|
|
|
+ * in relative qp mode qp_adj is a adjustment to final qp
|
|
|
+ */
|
|
|
+ RK_S16 qp_adj : 7;
|
|
|
+ /*
|
|
|
+ * Qp_adj_mode
|
|
|
+ * Qp adjustment mode
|
|
|
+ * 1 - absolute qp mode:
|
|
|
+ * the 16x16 MB qp is set to the qp_adj value
|
|
|
+ * 0 - relative qp mode
|
|
|
+ * the 16x16 MB qp is adjusted by qp_adj value
|
|
|
+ */
|
|
|
+ RK_U16 qp_adj_mode : 1;
|
|
|
+} Vepu580RoiQpCfg;
|
|
|
+
|
|
|
+typedef struct MppEncRoiImpl_t {
|
|
|
+ /* common parameters */
|
|
|
+ RK_S32 w;
|
|
|
+ RK_S32 h;
|
|
|
+ MppCodingType type;
|
|
|
+
|
|
|
+ /* region config set */
|
|
|
+ RoiRegionCfg *regions;
|
|
|
+ RK_S32 max_count;
|
|
|
+ RK_S32 count;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * roi_type is for the different encoder roi config
|
|
|
+ *
|
|
|
+ * 0 - rv1109/rk3566/rk3568 roi
|
|
|
+ * 1 - rk3588 roi
|
|
|
+ *
|
|
|
+ * others - legacy roi config
|
|
|
+ */
|
|
|
+ RoiType roi_type;
|
|
|
+
|
|
|
+ /* For roi type legacy config */
|
|
|
+ MppEncROICfg legacy_roi_cfg;
|
|
|
+ MppEncROIRegion *legacy_roi_region;
|
|
|
+
|
|
|
+ /* For roi type 1&2 config */
|
|
|
+ MppBufferGroup roi_grp;
|
|
|
+ MppEncROICfg2 roi_cfg;
|
|
|
+
|
|
|
+ /* buffer address and size of MppBuffer in MppEncROICfg2 */
|
|
|
+ void *dst_base;
|
|
|
+ void *dst_qp;
|
|
|
+ void *dst_amv;
|
|
|
+ void *dst_mv;
|
|
|
+ RK_U32 base_cfg_size;
|
|
|
+ RK_U32 qp_cfg_size;
|
|
|
+ RK_U32 amv_cfg_size;
|
|
|
+ RK_U32 mv_cfg_size;
|
|
|
+
|
|
|
+ RK_U8 *cu_map;
|
|
|
+ RK_U32 cu_size;
|
|
|
+
|
|
|
+ /* tmp buffer for convert vepu54x roi cfg to vepu58x roi cfg */
|
|
|
+ Vepu541RoiCfg *tmp;
|
|
|
+} MppEncRoiImpl;
|
|
|
+
|
|
|
+static RK_U32 raster2scan8[64] = {
|
|
|
+ 0, 1, 4, 5, 16, 17, 20, 21,
|
|
|
+ 2, 3, 6, 7, 18, 19, 22, 23,
|
|
|
+ 8, 9, 12, 13, 24, 25, 28, 29,
|
|
|
+ 10, 11, 14, 15, 26, 27, 30, 31,
|
|
|
+ 32, 33, 36, 37, 48, 49, 52, 53,
|
|
|
+ 34, 35, 38, 39, 50, 51, 54, 55,
|
|
|
+ 40, 41, 44, 45, 56, 57, 60, 61,
|
|
|
+ 42, 43, 46, 47, 58, 59, 62, 63
|
|
|
+};
|
|
|
+
|
|
|
+static RK_U32 raster2zscan16[16] = {
|
|
|
+ 0, 1, 4, 5,
|
|
|
+ 2, 3, 6, 7,
|
|
|
+ 8, 9, 12, 13,
|
|
|
+ 10, 11, 14, 15
|
|
|
+};
|
|
|
+
|
|
|
+static MPP_RET vepu54x_h265_set_roi(void *dst_buf, void *src_buf, RK_S32 w, RK_S32 h)
|
|
|
+{
|
|
|
+ Vepu541RoiCfg *src = (Vepu541RoiCfg *)src_buf;
|
|
|
+ Vepu541RoiCfg *dst = (Vepu541RoiCfg *)dst_buf;
|
|
|
+ RK_S32 mb_w = MPP_ALIGN(w, 64) / 64;
|
|
|
+ RK_S32 mb_h = MPP_ALIGN(h, 64) / 64;
|
|
|
+ RK_S32 ctu_line = mb_w;
|
|
|
+ RK_S32 j;
|
|
|
+
|
|
|
+ for (j = 0; j < mb_h; j++) {
|
|
|
+ RK_S32 i;
|
|
|
+
|
|
|
+ for (i = 0; i < mb_w; i++) {
|
|
|
+ RK_S32 ctu_addr = j * ctu_line + i;
|
|
|
+ RK_S32 cu16_num_line = ctu_line * 4;
|
|
|
+ RK_S32 cu16cnt;
|
|
|
+
|
|
|
+ for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
|
|
|
+ RK_S32 cu16_addr_in_frame;
|
|
|
+ RK_S32 cu16_x = cu16cnt % 4;
|
|
|
+ RK_S32 cu16_y = cu16cnt / 4;
|
|
|
+
|
|
|
+ cu16_x += i * 4;
|
|
|
+ cu16_y += j * 4;
|
|
|
+ cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
|
|
|
+
|
|
|
+ dst[ctu_addr * 16 + cu16cnt] = src[cu16_addr_in_frame];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return MPP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static MPP_RET gen_vepu54x_roi(MppEncRoiImpl *ctx, Vepu541RoiCfg *dst)
|
|
|
+{
|
|
|
+ RoiRegionCfg *region = ctx->regions;
|
|
|
+ RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
|
|
|
+ RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
|
|
|
+ RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
+ RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
+ Vepu541RoiCfg cfg;
|
|
|
+ MPP_RET ret = MPP_NOK;
|
|
|
+ RK_S32 i;
|
|
|
+
|
|
|
+ memset(ctx->cu_map, 0, ctx->cu_size);
|
|
|
+
|
|
|
+ cfg.force_intra = 0;
|
|
|
+ cfg.reserved = 0;
|
|
|
+ cfg.qp_area_idx = 0;
|
|
|
+ cfg.qp_area_en = 1;
|
|
|
+ cfg.qp_adj = 0;
|
|
|
+ cfg.qp_adj_mode = 0;
|
|
|
+
|
|
|
+ /* step 1. reset all the config */
|
|
|
+ for (i = 0; i < stride_h * stride_v; i++)
|
|
|
+ memcpy(dst + i, &cfg, sizeof(cfg));
|
|
|
+
|
|
|
+ if (ctx->w <= 0 || ctx->h <= 0) {
|
|
|
+ mpp_err_f("invalid size [%d:%d]\n", ctx->w, ctx->h);
|
|
|
+ goto DONE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* check region config */
|
|
|
+ ret = MPP_OK;
|
|
|
+ for (i = 0; i < ctx->count; i++, region++) {
|
|
|
+ if (region->x + region->w > ctx->w || region->y + region->h > ctx->h)
|
|
|
+ ret = MPP_NOK;
|
|
|
+
|
|
|
+ if (region->force_intra > 1 || region->qp_mode > 1)
|
|
|
+ ret = MPP_NOK;
|
|
|
+
|
|
|
+ if ((region->qp_mode && region->qp_val > 51) ||
|
|
|
+ (!region->qp_mode && (region->qp_val > 51 || region->qp_val < -51)))
|
|
|
+ ret = MPP_NOK;
|
|
|
+
|
|
|
+ if (ret) {
|
|
|
+ mpp_err_f("region %d invalid param:\n", i);
|
|
|
+ mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n",
|
|
|
+ region->x, region->y, region->w, region->h, ctx->w, ctx->h);
|
|
|
+ mpp_err_f("force intra %d qp mode %d val %d\n",
|
|
|
+ region->force_intra, region->qp_mode, region->qp_val);
|
|
|
+ goto DONE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ region = ctx->regions;
|
|
|
+ /* step 2. setup region for top to bottom */
|
|
|
+ for (i = 0; i < ctx->count; i++, region++) {
|
|
|
+ Vepu541RoiCfg *p = dst;
|
|
|
+ RK_U8 *map = ctx->cu_map;
|
|
|
+ RK_S32 roi_width = (region->w + 15) / 16;
|
|
|
+ RK_S32 roi_height = (region->h + 15) / 16;
|
|
|
+ RK_S32 pos_x_init = (region->x + 15) / 16;
|
|
|
+ RK_S32 pos_y_init = (region->y + 15) / 16;
|
|
|
+ RK_S32 pos_x_end = pos_x_init + roi_width;
|
|
|
+ RK_S32 pos_y_end = pos_y_init + roi_height;
|
|
|
+ RK_S32 x, y;
|
|
|
+
|
|
|
+ mpp_assert(pos_x_init >= 0 && pos_x_init < mb_w);
|
|
|
+ mpp_assert(pos_x_end >= 0 && pos_x_end <= mb_w);
|
|
|
+ mpp_assert(pos_y_init >= 0 && pos_y_init < mb_h);
|
|
|
+ mpp_assert(pos_y_end >= 0 && pos_y_end <= mb_h);
|
|
|
+
|
|
|
+ cfg.force_intra = region->force_intra;
|
|
|
+ cfg.reserved = 0;
|
|
|
+ cfg.qp_area_idx = 0;
|
|
|
+ // NOTE: When roi is enabled the qp_area_en should be one.
|
|
|
+ cfg.qp_area_en = 1; // region->area_map_en;
|
|
|
+ cfg.qp_adj = region->qp_val;
|
|
|
+ cfg.qp_adj_mode = region->qp_mode;
|
|
|
+
|
|
|
+ p += pos_y_init * stride_h + pos_x_init;
|
|
|
+ map += pos_y_init * stride_h + pos_x_init;
|
|
|
+ for (y = 0; y < roi_height; y++) {
|
|
|
+ for (x = 0; x < roi_width; x++) {
|
|
|
+ memcpy(p + x, &cfg, sizeof(cfg));
|
|
|
+ if (ctx->type == MPP_VIDEO_CodingAVC) {
|
|
|
+ *(map + x) = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ p += stride_h;
|
|
|
+ map += stride_h;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ctx->type == MPP_VIDEO_CodingHEVC) {
|
|
|
+ map = ctx->cu_map;
|
|
|
+ RK_U32 stride_cu64_h = stride_h * 16 / 64;
|
|
|
+
|
|
|
+ roi_width = (region->w + 64) / 64;
|
|
|
+ roi_height = (region->h + 64) / 64;
|
|
|
+
|
|
|
+ if (region->x < 64) {
|
|
|
+ pos_x_init = 0;
|
|
|
+ roi_width += 2;
|
|
|
+ } else if (region->x % 64) {
|
|
|
+ pos_x_init = (region->x - 64) / 64;
|
|
|
+ roi_width += 2;
|
|
|
+ } else
|
|
|
+ pos_x_init = region->x / 64;
|
|
|
+
|
|
|
+ if (region->y < 64) {
|
|
|
+ pos_y_init = 0;
|
|
|
+ roi_height += 2;
|
|
|
+ } else if (region->y % 64) {
|
|
|
+ pos_y_init = (region->y - 64) / 64;
|
|
|
+ roi_height += 2;
|
|
|
+ } else
|
|
|
+ pos_y_init = region->y / 64;
|
|
|
+
|
|
|
+ map += pos_y_init * stride_cu64_h + pos_x_init;
|
|
|
+ for (y = 0; y < roi_height; y++) {
|
|
|
+ for (x = 0; x < roi_width; x++) {
|
|
|
+ *(map + x) = 1;
|
|
|
+ }
|
|
|
+ map += stride_cu64_h;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+DONE:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static MPP_RET set_roi_pos_val(RK_U32 *buf, RK_U32 pos, RK_U32 value)
|
|
|
+{
|
|
|
+ RK_U32 index = pos / 32;
|
|
|
+ RK_U32 bits = pos % 32;
|
|
|
+
|
|
|
+ buf[index] = buf[index] | (value << bits);
|
|
|
+ return MPP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+#define set_roi_qpadj(buf, index, val) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = 425 + index; \
|
|
|
+ set_roi_pos_val(buf, offset, val); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+#define set_roi_force_split(buf, index, val) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = 340 + index; \
|
|
|
+ set_roi_pos_val(buf, offset, val); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+#define set_roi_force_intra(buf, index, val) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = 170 + index * 2; \
|
|
|
+ set_roi_pos_val(buf, offset, val); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+#define set_roi_force_inter(buf, index, val) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = index * 2; \
|
|
|
+ set_roi_pos_val(buf, offset, val); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+static void set_roi_cu8_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
|
|
|
+{
|
|
|
+ set_roi_qpadj(buf, index, val.qp_adj);
|
|
|
+ set_roi_force_split(buf, index, val.force_split);
|
|
|
+ set_roi_force_intra(buf, index, val.force_intra);
|
|
|
+ set_roi_force_inter(buf, index, val.force_inter);
|
|
|
+}
|
|
|
+
|
|
|
+static void set_roi_cu16_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
|
|
|
+{
|
|
|
+ index += 64;
|
|
|
+ set_roi_qpadj(buf, index, val.qp_adj);
|
|
|
+ set_roi_force_split(buf, index, val.force_split);
|
|
|
+ set_roi_force_intra(buf, index, val.force_intra);
|
|
|
+ set_roi_force_inter(buf, index, val.force_inter);
|
|
|
+}
|
|
|
+
|
|
|
+static void set_roi_cu32_base_cfg(RK_U32 *buf, RK_U32 index, Vepu580RoiH265BsCfg val)
|
|
|
+{
|
|
|
+ index += 80;
|
|
|
+ set_roi_qpadj(buf, index, val.qp_adj);
|
|
|
+ set_roi_force_split(buf, index, val.force_split);
|
|
|
+ set_roi_force_intra(buf, index, val.force_intra);
|
|
|
+ set_roi_force_inter(buf, index, val.force_inter);
|
|
|
+}
|
|
|
+
|
|
|
+static void set_roi_cu64_base_cfg(RK_U32 *buf, Vepu580RoiH265BsCfg val)
|
|
|
+{
|
|
|
+ set_roi_qpadj(buf, 84, val.qp_adj);
|
|
|
+ set_roi_force_split(buf, 84, val.force_split);
|
|
|
+ set_roi_force_intra(buf, 84, val.force_intra);
|
|
|
+ set_roi_force_inter(buf, 84, val.force_inter);
|
|
|
+}
|
|
|
+
|
|
|
+static void set_roi_qp_cfg(void *buf, RK_U32 index, Vepu541RoiCfg *cfg)
|
|
|
+{
|
|
|
+ Vepu580RoiQpCfg *qp_cfg_base = (Vepu580RoiQpCfg *)buf;
|
|
|
+ Vepu580RoiQpCfg *qp_cfg = &qp_cfg_base[index];
|
|
|
+
|
|
|
+ qp_cfg->qp_adj = cfg->qp_adj;
|
|
|
+ qp_cfg->qp_adj_mode = cfg->qp_adj_mode;
|
|
|
+ qp_cfg->qp_area_idx = cfg->qp_area_idx;
|
|
|
+}
|
|
|
+
|
|
|
+#define set_roi_cu8_qp_cfg(buf, index, cfg) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = index; \
|
|
|
+ set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+#define set_roi_cu16_qp_cfg(buf, index, cfg) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = 64 + index; \
|
|
|
+ set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+#define set_roi_cu32_qp_cfg(buf, index, cfg) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = 80 + index; \
|
|
|
+ set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+#define set_roi_cu64_qp_cfg(buf, cfg) \
|
|
|
+ do { \
|
|
|
+ RK_U32 offset = 84; \
|
|
|
+ set_roi_qp_cfg(buf, offset, cfg); \
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+void set_roi_amv(RK_U32 *buf, Vepu580RoiH265BsCfg val)
|
|
|
+{
|
|
|
+ set_roi_pos_val(buf, 511, val.amv_en);
|
|
|
+}
|
|
|
+
|
|
|
+static MPP_RET gen_vepu580_roi_h264(MppEncRoiImpl *ctx)
|
|
|
+{
|
|
|
+ RK_S32 mb_w = MPP_ALIGN(ctx->w, 16) / 16;
|
|
|
+ RK_S32 mb_h = MPP_ALIGN(ctx->h, 16) / 16;
|
|
|
+ RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
+ RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
+ RK_S32 roi_buf_size = stride_h * stride_v * 8;
|
|
|
+ RK_S32 roi_qp_size = stride_h * stride_v * 2;
|
|
|
+
|
|
|
+ Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
|
|
|
+ Vepu580RoiQpCfg *dst_qp = ctx->dst_qp;
|
|
|
+ Vepu580RoiH264BsCfg *dst_base = ctx->dst_base;
|
|
|
+ RK_S32 j, k;
|
|
|
+
|
|
|
+ if (!src || !dst_qp || !dst_base)
|
|
|
+ return MPP_NOK;
|
|
|
+
|
|
|
+ memset(dst_base, 0, roi_buf_size);
|
|
|
+ memset(dst_qp, 0, roi_qp_size);
|
|
|
+
|
|
|
+ for (j = 0; j < mb_h; j++) {
|
|
|
+ for (k = 0; k < stride_h; k++) {
|
|
|
+ if (ctx->cu_map[j * stride_h + k]) {
|
|
|
+ Vepu541RoiCfg *cu_cfg = &src[j * stride_h + k];
|
|
|
+ Vepu580RoiQpCfg *qp_cfg = &dst_qp[j * stride_h + k];
|
|
|
+ Vepu580RoiH264BsCfg *base_cfg = &dst_base[j * stride_h + k];
|
|
|
+
|
|
|
+ qp_cfg->qp_adj = cu_cfg->qp_adj;
|
|
|
+ qp_cfg->qp_adj_mode = cu_cfg->qp_adj_mode;
|
|
|
+ qp_cfg->qp_area_idx = cu_cfg->qp_area_idx;
|
|
|
+ base_cfg->force_intra = cu_cfg->force_intra;
|
|
|
+ base_cfg->qp_adj_en = !!cu_cfg->qp_adj;
|
|
|
+#if 0
|
|
|
+ if (j < 8 && k < 8) {
|
|
|
+ RK_U64 *tmp = (RK_U64 *)base_cfg;
|
|
|
+ RK_U16 *qp = (RK_U16 *)qp_cfg;
|
|
|
+
|
|
|
+ mpp_log("force_intra %d, qp_adj_en %d qp_adj %d, qp_adj_mode %d",
|
|
|
+ base_cfg->force_intra, base_cfg->qp_adj_en, qp_cfg->qp_adj, qp_cfg->qp_adj_mode);
|
|
|
+ mpp_log("val low %8x hight %8x", *tmp & 0xffffffff, ((*tmp >> 32) & 0xffffffff));
|
|
|
+
|
|
|
+ mpp_log("qp cfg %4x", *qp);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return MPP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+void set_roi_cu16_split_cu8(RK_U32 *buf, RK_U32 cu16index, Vepu580RoiH265BsCfg val)
|
|
|
+{
|
|
|
+ RK_S32 cu16_x = cu16index % 4;
|
|
|
+ RK_S32 cu16_y = cu16index / 4;
|
|
|
+ RK_U32 cu8cnt;
|
|
|
+
|
|
|
+ // mpp_log("cu16index = %d, force intra = %d, cu16_y= %d", cu16index, val.force_intra, cu16_y);
|
|
|
+ for (cu8cnt = 0; cu8cnt < 4; cu8cnt++) {
|
|
|
+ RK_U32 zindex = 0;
|
|
|
+ RK_U32 cu8_x = cu8cnt % 2;
|
|
|
+ RK_U32 cu8_y = cu8cnt / 2;
|
|
|
+ RK_U32 cu8raster_index = (cu16_y * 2 + cu8_y) * 8 + cu16_x * 2 + cu8_x;
|
|
|
+
|
|
|
+ // mpp_log("cu8raster_index = %d", cu8raster_index);
|
|
|
+ zindex = raster2scan8[cu8raster_index];
|
|
|
+ // mpp_log("cu8raster_index = %d zindex = %d x %d, y %d, cu8_x %d cu8_y %d",
|
|
|
+ // cu8raster_index,zindex, x, y, cu8_x, cu8_y);
|
|
|
+ set_roi_cu8_base_cfg(buf, zindex, val);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static MPP_RET gen_vepu580_roi_h265(MppEncRoiImpl *ctx)
|
|
|
+{
|
|
|
+ RK_S32 ctu_w = MPP_ALIGN(ctx->w, 64) / 64;
|
|
|
+ RK_S32 ctu_h = MPP_ALIGN(ctx->h, 64) / 64;
|
|
|
+ RK_S32 roi_buf_size = ctu_w * ctu_h * 64;
|
|
|
+ RK_S32 roi_qp_size = ctu_w * ctu_h * 256;
|
|
|
+ RK_S32 ctu_line = ctu_w;
|
|
|
+
|
|
|
+ Vepu541RoiCfg *src = (Vepu541RoiCfg *)ctx->tmp;
|
|
|
+ void *dst_qp = ctx->dst_qp;
|
|
|
+ RK_U32 *dst_base = ctx->dst_base;
|
|
|
+ RK_S32 i, j, k, cu16cnt;
|
|
|
+
|
|
|
+ if (!src || !dst_qp || !dst_base)
|
|
|
+ return MPP_NOK;
|
|
|
+
|
|
|
+ // mpp_log("roi_qp_size = %d, roi_buf_size %d", roi_qp_size, roi_buf_size);
|
|
|
+ memset(dst_qp, 0, roi_qp_size);
|
|
|
+ memset(dst_base, 0, roi_buf_size);
|
|
|
+
|
|
|
+ for (j = 0; j < ctu_h; j++) {
|
|
|
+ for (k = 0; k < ctu_w; k++) {
|
|
|
+ RK_S32 cu16_num_line = ctu_line * 4;
|
|
|
+ RK_U32 adjust_cnt = 0;
|
|
|
+
|
|
|
+ if (ctx->cu_map[j * ctu_w + k]) {
|
|
|
+ for (cu16cnt = 0; cu16cnt < 16; cu16cnt++) {
|
|
|
+ RK_S32 cu16_x;
|
|
|
+ RK_S32 cu16_y;
|
|
|
+ RK_S32 cu16_addr_in_frame;
|
|
|
+ RK_U32 zindex = 0;
|
|
|
+ Vepu541RoiCfg *cu16_cfg = NULL;
|
|
|
+ Vepu580RoiH265BsCfg val;
|
|
|
+
|
|
|
+ memset(&val, 0, sizeof(val));
|
|
|
+ cu16_x = cu16cnt & 3;
|
|
|
+ cu16_y = cu16cnt / 4;
|
|
|
+ cu16_x += k * 4;
|
|
|
+ cu16_y += j * 4;
|
|
|
+ cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line;
|
|
|
+ cu16_cfg = &src[cu16_addr_in_frame];
|
|
|
+ zindex = raster2zscan16[cu16cnt];
|
|
|
+
|
|
|
+ val.force_intra = cu16_cfg->force_intra;
|
|
|
+ val.qp_adj = !!cu16_cfg->qp_adj;
|
|
|
+ if (val.force_intra || val.qp_adj) {
|
|
|
+ adjust_cnt++;
|
|
|
+ }
|
|
|
+
|
|
|
+ set_roi_cu16_split_cu8(dst_base, cu16cnt, val);
|
|
|
+ set_roi_cu16_base_cfg(dst_base, zindex, val);
|
|
|
+ set_roi_cu16_qp_cfg(dst_qp, zindex, cu16_cfg);
|
|
|
+ /*
|
|
|
+ * if all cu16 adjust c64 and cu32 must adjust
|
|
|
+ * or we will force split to cu 16
|
|
|
+ */
|
|
|
+ if (adjust_cnt == 16 && cu16cnt == 15) {
|
|
|
+ // cu64
|
|
|
+ set_roi_cu64_base_cfg(dst_base, val);
|
|
|
+ set_roi_cu64_qp_cfg(dst_qp, cu16_cfg);
|
|
|
+ // cu32
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ set_roi_cu32_base_cfg(dst_base, i, val);
|
|
|
+ set_roi_cu32_qp_cfg(dst_qp, i, cu16_cfg);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < 64; i ++) {
|
|
|
+ set_roi_cu8_base_cfg(dst_base, i, val);
|
|
|
+ set_roi_qp_cfg(dst_qp, i, cu16_cfg);
|
|
|
+ }
|
|
|
+ } else if (cu16cnt == 15 && adjust_cnt > 0) {
|
|
|
+ val.force_split = 1;
|
|
|
+ set_roi_force_split(dst_base, 84, val.force_split);
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ set_roi_force_split(dst_base, 80 + i, val.force_split);
|
|
|
+ }
|
|
|
+ for (i = 0; i < 16; i++) {
|
|
|
+ set_roi_force_split(dst_base, 64 + i, val.force_split);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#if 0
|
|
|
+ if (j < 3 && (k < 3 )) {
|
|
|
+ mpp_log("j %d, k %d need_update = %d", j, k, need_update);
|
|
|
+ RK_U16 *qp_val = (RK_U16 *)dst_qp;
|
|
|
+ for (i = 0; i < CU_BASE_CFG_BYTE / 4; i++) {
|
|
|
+ mpp_log("cfg[%d] = %08x", i, dst_base[i]);
|
|
|
+ }
|
|
|
+ for (i = 0; i < CU_QP_CFG_BYTE / 2; i++) {
|
|
|
+ mpp_log("qp[%d] = %04x", i, qp_val[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ dst_base += CU_BASE_CFG_BYTE / 4;
|
|
|
+ dst_qp += CU_QP_CFG_BYTE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return MPP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+MPP_RET mpp_enc_roi_init(MppEncRoiCtx *ctx, RK_U32 w, RK_U32 h, MppCodingType type, RK_S32 count)
|
|
|
+{
|
|
|
+ RockchipSocType soc_type = mpp_get_soc_type();
|
|
|
+ RoiType roi_type = ROI_TYPE_AUTO;
|
|
|
+ MppEncRoiImpl *impl = NULL;
|
|
|
+ MPP_RET ret = MPP_NOK;
|
|
|
+
|
|
|
+ switch (soc_type) {
|
|
|
+ case ROCKCHIP_SOC_RV1109 :
|
|
|
+ case ROCKCHIP_SOC_RV1126 :
|
|
|
+ case ROCKCHIP_SOC_RK3566 :
|
|
|
+ case ROCKCHIP_SOC_RK3568 : {
|
|
|
+ roi_type = ROI_TYPE_1;
|
|
|
+ } break;
|
|
|
+ case ROCKCHIP_SOC_RK3588 : {
|
|
|
+ roi_type = ROI_TYPE_2;
|
|
|
+ } break;
|
|
|
+ default : {
|
|
|
+ roi_type = ROI_TYPE_LEGACY;
|
|
|
+ mpp_log("soc %s run with legacy roi config\n", mpp_get_soc_name());
|
|
|
+ } break;
|
|
|
+ }
|
|
|
+
|
|
|
+ mpp_env_get_u32("roi_type", (RK_U32 *)&roi_type, roi_type);
|
|
|
+
|
|
|
+ impl = mpp_calloc(MppEncRoiImpl, 1);
|
|
|
+ if (!impl) {
|
|
|
+ mpp_log("can't create roi context\n");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ impl->w = w;
|
|
|
+ impl->h = h;
|
|
|
+ impl->type = type;
|
|
|
+ impl->roi_type = roi_type;
|
|
|
+ impl->max_count = count;
|
|
|
+ impl->regions = mpp_calloc(RoiRegionCfg, count);
|
|
|
+
|
|
|
+ switch (roi_type) {
|
|
|
+ case ROI_TYPE_1 : {
|
|
|
+ RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
|
|
|
+ RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
|
|
|
+ RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
+ RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
+
|
|
|
+ mpp_log("set to vepu54x roi generation\n");
|
|
|
+
|
|
|
+ impl->base_cfg_size = stride_h * stride_v * sizeof(Vepu541RoiCfg);
|
|
|
+ mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION);
|
|
|
+
|
|
|
+ mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
|
|
|
+ if (!impl->roi_cfg.base_cfg_buf) {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
|
|
|
+
|
|
|
+ /* create tmp buffer for hevc */
|
|
|
+ if (type == MPP_VIDEO_CodingHEVC) {
|
|
|
+ impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
|
|
|
+ if (!impl->tmp)
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = MPP_OK;
|
|
|
+ } break;
|
|
|
+ case ROI_TYPE_2 : {
|
|
|
+ if (type == MPP_VIDEO_CodingHEVC) {
|
|
|
+ RK_U32 ctu_w = MPP_ALIGN(w, 64) / 64;
|
|
|
+ RK_U32 ctu_h = MPP_ALIGN(h, 64) / 64;
|
|
|
+
|
|
|
+ impl->base_cfg_size = ctu_w * ctu_h * 64;
|
|
|
+ impl->qp_cfg_size = ctu_w * ctu_h * 256;
|
|
|
+ impl->amv_cfg_size = ctu_w * ctu_h * 512;
|
|
|
+ impl->mv_cfg_size = ctu_w * ctu_h * 4;
|
|
|
+ impl->cu_map = mpp_calloc(RK_U8, ctu_w * ctu_h);
|
|
|
+ impl->cu_size = ctu_w * ctu_h;
|
|
|
+ } else {
|
|
|
+ RK_U32 mb_w = MPP_ALIGN(w, 64) / 16;
|
|
|
+ RK_U32 mb_h = MPP_ALIGN(h, 64) / 16;
|
|
|
+
|
|
|
+ impl->base_cfg_size = mb_w * mb_h * 8;
|
|
|
+ impl->qp_cfg_size = mb_w * mb_h * 2;
|
|
|
+ impl->amv_cfg_size = mb_w * mb_h / 4;
|
|
|
+ impl->mv_cfg_size = mb_w * mb_h * 96 / 4;
|
|
|
+ impl->cu_map = mpp_calloc(RK_U8, mb_w * mb_h);
|
|
|
+ impl->cu_size = mb_w * mb_h;
|
|
|
+ }
|
|
|
+
|
|
|
+ mpp_log("set to vepu58x roi generation\n");
|
|
|
+
|
|
|
+ impl->roi_cfg.roi_qp_en = 1;
|
|
|
+ mpp_buffer_group_get_internal(&impl->roi_grp, MPP_BUFFER_TYPE_ION);
|
|
|
+ mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.base_cfg_buf, impl->base_cfg_size);
|
|
|
+ if (!impl->roi_cfg.base_cfg_buf) {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ impl->dst_base = mpp_buffer_get_ptr(impl->roi_cfg.base_cfg_buf);
|
|
|
+ mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.qp_cfg_buf, impl->qp_cfg_size);
|
|
|
+ if (!impl->roi_cfg.qp_cfg_buf) {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ impl->dst_qp = mpp_buffer_get_ptr(impl->roi_cfg.qp_cfg_buf);
|
|
|
+ mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.amv_cfg_buf, impl->amv_cfg_size);
|
|
|
+ if (!impl->roi_cfg.amv_cfg_buf) {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ impl->dst_amv = mpp_buffer_get_ptr(impl->roi_cfg.amv_cfg_buf);
|
|
|
+ mpp_buffer_get(impl->roi_grp, &impl->roi_cfg.mv_cfg_buf, impl->mv_cfg_size);
|
|
|
+ if (!impl->roi_cfg.mv_cfg_buf) {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ impl->dst_mv = mpp_buffer_get_ptr(impl->roi_cfg.mv_cfg_buf);
|
|
|
+
|
|
|
+ {
|
|
|
+ // create tmp buffer for vepu54x H.264 config first
|
|
|
+ RK_S32 mb_w = MPP_ALIGN(impl->w, 16) / 16;
|
|
|
+ RK_S32 mb_h = MPP_ALIGN(impl->h, 16) / 16;
|
|
|
+ RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
|
|
|
+ RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
|
|
|
+
|
|
|
+ impl->tmp = mpp_malloc(Vepu541RoiCfg, stride_h * stride_v);
|
|
|
+ if (!impl->tmp)
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ ret = MPP_OK;
|
|
|
+ } break;
|
|
|
+ case ROI_TYPE_LEGACY : {
|
|
|
+ impl->legacy_roi_region = mpp_calloc(MppEncROIRegion, count);
|
|
|
+
|
|
|
+ mpp_assert(impl->legacy_roi_region);
|
|
|
+ impl->legacy_roi_cfg.regions = impl->legacy_roi_region;
|
|
|
+ ret = MPP_OK;
|
|
|
+ } break;
|
|
|
+ default : {
|
|
|
+ } break;
|
|
|
+ }
|
|
|
+
|
|
|
+done:
|
|
|
+ if (ret) {
|
|
|
+ if (impl) {
|
|
|
+ mpp_enc_roi_deinit(impl);
|
|
|
+ impl = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ *ctx = impl;
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+MPP_RET mpp_enc_roi_deinit(MppEncRoiCtx ctx)
|
|
|
+{
|
|
|
+ MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
|
|
|
+
|
|
|
+ if (!impl)
|
|
|
+ return MPP_OK;
|
|
|
+
|
|
|
+ if (impl->roi_cfg.base_cfg_buf) {
|
|
|
+ mpp_buffer_put(impl->roi_cfg.base_cfg_buf);
|
|
|
+ impl->roi_cfg.base_cfg_buf = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (impl->roi_cfg.qp_cfg_buf) {
|
|
|
+ mpp_buffer_put(impl->roi_cfg.qp_cfg_buf);
|
|
|
+ impl->roi_cfg.qp_cfg_buf = NULL;
|
|
|
+ }
|
|
|
+ if (impl->roi_cfg.amv_cfg_buf) {
|
|
|
+ mpp_buffer_put(impl->roi_cfg.amv_cfg_buf);
|
|
|
+ impl->roi_cfg.amv_cfg_buf = NULL;
|
|
|
+ }
|
|
|
+ if (impl->roi_cfg.mv_cfg_buf) {
|
|
|
+ mpp_buffer_put(impl->roi_cfg.mv_cfg_buf);
|
|
|
+ impl->roi_cfg.mv_cfg_buf = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (impl->roi_grp) {
|
|
|
+ mpp_buffer_group_put(impl->roi_grp);
|
|
|
+ impl->roi_grp = NULL;
|
|
|
+ }
|
|
|
+ MPP_FREE(impl->cu_map);
|
|
|
+ MPP_FREE(impl->legacy_roi_region);
|
|
|
+ MPP_FREE(impl->regions);
|
|
|
+ MPP_FREE(impl->tmp);
|
|
|
+
|
|
|
+ MPP_FREE(impl);
|
|
|
+ return MPP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+MPP_RET mpp_enc_roi_add_region(MppEncRoiCtx ctx, RoiRegionCfg *region)
|
|
|
+{
|
|
|
+ MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
|
|
|
+
|
|
|
+ if (impl->count >= impl->max_count) {
|
|
|
+ mpp_err("can not add more region with max %d\n", impl->max_count);
|
|
|
+ return MPP_NOK;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(impl->regions + impl->count, region, sizeof(*impl->regions));
|
|
|
+ impl->count++;
|
|
|
+
|
|
|
+ return MPP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+MPP_RET mpp_enc_roi_setup_meta(MppEncRoiCtx ctx, MppMeta meta)
|
|
|
+{
|
|
|
+ MppEncRoiImpl *impl = (MppEncRoiImpl *)ctx;
|
|
|
+
|
|
|
+ switch (impl->roi_type) {
|
|
|
+ case ROI_TYPE_1 : {
|
|
|
+ switch (impl->type) {
|
|
|
+ case MPP_VIDEO_CodingAVC : {
|
|
|
+ gen_vepu54x_roi(impl, impl->dst_base);
|
|
|
+ } break;
|
|
|
+ case MPP_VIDEO_CodingHEVC : {
|
|
|
+ gen_vepu54x_roi(impl, impl->tmp);
|
|
|
+ vepu54x_h265_set_roi(impl->dst_base, impl->tmp, impl->w, impl->h);
|
|
|
+ } break;
|
|
|
+ default : {
|
|
|
+ } break;
|
|
|
+ }
|
|
|
+
|
|
|
+ mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
|
|
|
+ } break;
|
|
|
+ case ROI_TYPE_2 : {
|
|
|
+ gen_vepu54x_roi(impl, impl->tmp);
|
|
|
+
|
|
|
+ switch (impl->type) {
|
|
|
+ case MPP_VIDEO_CodingAVC : {
|
|
|
+ gen_vepu580_roi_h264(impl);
|
|
|
+ } break;
|
|
|
+ case MPP_VIDEO_CodingHEVC : {
|
|
|
+ gen_vepu580_roi_h265(impl);
|
|
|
+ } break;
|
|
|
+ default : {
|
|
|
+ } break;
|
|
|
+ }
|
|
|
+
|
|
|
+ mpp_meta_set_ptr(meta, KEY_ROI_DATA2, (void*)&impl->roi_cfg);
|
|
|
+ } break;
|
|
|
+ case ROI_TYPE_LEGACY : {
|
|
|
+ MppEncROIRegion *region = impl->legacy_roi_region;
|
|
|
+ MppEncROICfg *roi_cfg = &impl->legacy_roi_cfg;
|
|
|
+ RoiRegionCfg *regions = impl->regions;
|
|
|
+ RK_S32 i;
|
|
|
+
|
|
|
+ for (i = 0; i < impl->count; i++) {
|
|
|
+ region[i].x = regions[i].x;
|
|
|
+ region[i].y = regions[i].y;
|
|
|
+ region[i].w = regions[i].w;
|
|
|
+ region[i].h = regions[i].h;
|
|
|
+
|
|
|
+ region[i].intra = regions[i].force_intra;
|
|
|
+ region[i].abs_qp_en = regions[i].qp_mode;
|
|
|
+ region[i].quality = regions[i].qp_val;
|
|
|
+ region[i].area_map_en = 1;
|
|
|
+ region[i].qp_area_idx = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ roi_cfg->number = impl->count;
|
|
|
+ roi_cfg->regions = region;
|
|
|
+
|
|
|
+ mpp_meta_set_ptr(meta, KEY_ROI_DATA, (void*)roi_cfg);
|
|
|
+ } break;
|
|
|
+ default : {
|
|
|
+ } break;
|
|
|
+ }
|
|
|
+
|
|
|
+ impl->count = 0;
|
|
|
+
|
|
|
+ return MPP_OK;
|
|
|
+}
|