From 1acefd6207b34b416eff0ccd7eb894d00b64ee9f Mon Sep 17 00:00:00 2001 From: "timkingh.huang" Date: Thu, 21 Dec 2017 11:47:27 +0800 Subject: [PATCH] [h264e]: add configuration of ROI Change-Id: Ieba60baedc8fabd248112636f5ea59a107775403 Signed-off-by: timkingh.huang --- inc/rk_mpi_cmd.h | 31 +++++++---- mpp/codec/mpp_enc.cpp | 4 ++ mpp/hal/common/h264/hal_h264e_com.h | 1 + mpp/hal/rkenc/h264e/hal_h264e_rkv.c | 26 +++++++++ mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.c | 65 +++++++++++++++++++++++ mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.h | 8 +-- test/mpi_enc_test.c | 28 ++++++++++ 7 files changed, 148 insertions(+), 15 deletions(-) diff --git a/inc/rk_mpi_cmd.h b/inc/rk_mpi_cmd.h index 3f2c8d71..5eaf6c60 100644 --- a/inc/rk_mpi_cmd.h +++ b/inc/rk_mpi_cmd.h @@ -120,6 +120,7 @@ typedef enum { MPP_ENC_GET_SEI_DATA, /* SEI: Supplement Enhancemant Information, parameter is MppPacket */ MPP_ENC_PRE_ALLOC_BUFF, /* allocate buffers before encoding */ MPP_ENC_SET_QP_RANGE, /* used for adjusting qp range, the parameter can be 1 or 2 */ + MPP_ENC_SET_ROI_CFG, /* set MppEncROICfg structure */ MPP_ENC_CMD_END, MPP_ISP_CMD_BASE = CMD_MODULE_CODEC | CMD_CTX_ID_ISP, @@ -455,22 +456,30 @@ typedef struct MppEncPrepCfg_t { MppEncPrepSharpenCfg sharpen; } MppEncPrepCfg; -/* - * Mpp ROI parameter - * Region configture define a rectangle as ROI +/** + * @brief Mpp ROI parameter + * Region configure define a rectangle as ROI + * @note x, y, w, h are calculated in pixels, which had better be 16-pixel aligned. + * These parameters MUST retain in memory when encoder is running. + * TODO: Only absolute qp is supported so far, relative qp should be supported + * in the future. Also, the ROI regions can be overlaid with each other, + * so overlay priority should be considered. */ typedef struct MppEncROIRegion_t { - RK_U16 x; - RK_U16 y; - RK_U16 w; - RK_U16 h; - RK_U16 intra; - RK_U16 quality; + RK_U16 x; /**< horizontal position of top left corner */ + RK_U16 y; /**< vertical position of top left corner */ + RK_U16 w; /**< width of ROI rectangle */ + RK_U16 h; /**< height of ROI rectangle */ + RK_U16 intra; /**< flag of forced intra macroblock */ + RK_U16 quality; /**< absolute qp of macroblock */ } MppEncROIRegion; +/** + * @brief MPP encoder's ROI configuration + */ typedef struct MppEncROICfg_t { - RK_U32 number; - MppEncROIRegion *regions; + RK_U32 number; /**< ROI rectangle number */ + MppEncROIRegion *regions;/**< ROI parameters */ } MppEncROICfg; /* diff --git a/mpp/codec/mpp_enc.cpp b/mpp/codec/mpp_enc.cpp index ab66df3a..5f2b539a 100644 --- a/mpp/codec/mpp_enc.cpp +++ b/mpp/codec/mpp_enc.cpp @@ -521,6 +521,10 @@ MPP_RET mpp_enc_control(MppEnc *enc, MpiCmd cmd, void *param) mpp_enc_dbg_ctrl("set osd data\n"); ret = mpp_hal_control(enc->hal, cmd, param); } break; + case MPP_ENC_SET_ROI_CFG : { + mpp_enc_dbg_ctrl("set roi data\n"); + ret = mpp_hal_control(enc->hal, cmd, param); + } break; case MPP_ENC_SET_SEI_CFG : { mpp_enc_dbg_ctrl("set sei\n"); ret = mpp_hal_control(enc->hal, cmd, param); diff --git a/mpp/hal/common/h264/hal_h264e_com.h b/mpp/hal/common/h264/hal_h264e_com.h index 8ce7c1c5..c861ce66 100644 --- a/mpp/hal/common/h264/hal_h264e_com.h +++ b/mpp/hal/common/h264/hal_h264e_com.h @@ -434,6 +434,7 @@ typedef struct H264eHalContext_t { H264eOsdPltType osd_plt_type; //-1:invalid, 0:user define, 1:default MppEncOSDData osd_data; + MppEncROICfg roi_data; MppEncSeiMode sei_mode; MppEncCfgSet *cfg; diff --git a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c index 0ae713a1..7da5b40f 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_rkv.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_rkv.c @@ -328,6 +328,7 @@ MPP_RET hal_h264e_rkv_init(void *hal, MppHalCfg *cfg) ctx->frame_cnt_send_ready = 0; ctx->num_frames_to_send = 1; ctx->osd_plt_type = H264E_OSD_PLT_TYPE_NONE; + ctx->hw_cfg.roi_en = 1; /* support multi-refs */ dpb_ctx = (H264eRkvDpbCtx *)ctx->dpb_ctx; @@ -704,6 +705,24 @@ h264e_rkv_set_osd_regs(H264eHalContext *ctx, H264eRkvRegSet *regs) return MPP_OK; } +static MPP_RET +h264e_rkv_set_roi_regs(H264eHalContext *ctx, H264eRkvRegSet *regs) +{ + MppEncROICfg *cfg = &ctx->roi_data; + h264e_hal_rkv_buffers *bufs = (h264e_hal_rkv_buffers *)ctx->buffers; + RK_U8 *roi_base; + + if(cfg->number && cfg->regions){ + regs->swreg10.roi_enc = 1; + regs->swreg29_ctuc_addr = mpp_buffer_get_fd(bufs->hw_roi_buf[0]); + + roi_base = (RK_U8 *)mpp_buffer_get_ptr(bufs->hw_roi_buf[0]); + rkv_config_roi_area(ctx, roi_base); + } + + return MPP_OK; +} + static MPP_RET h264e_rkv_set_pp_regs(H264eRkvRegSet *regs, H264eHwCfg *syn, MppEncPrepCfg *prep_cfg, MppBuffer hw_buf_w, MppBuffer hw_buf_r) @@ -1394,6 +1413,9 @@ MPP_RET hal_h264e_rkv_gen_regs(void *hal, HalTaskInfo *task) h264e_rkv_set_osd_regs(ctx, regs); + /* ROI configure */ + h264e_rkv_set_roi_regs(ctx, regs); + regs->swreg69.bs_lgth = 0x0; regs->swreg70.sse_l32 = 0x0; @@ -1848,6 +1870,10 @@ MPP_RET hal_h264e_rkv_control(void *hal, RK_S32 cmd_type, void *param) h264e_rkv_set_osd_data(ctx, param); break; } + case MPP_ENC_SET_ROI_CFG : { + h264e_rkv_set_roi_data(ctx, param); + break; + } case MPP_ENC_SET_SEI_CFG: { ctx->sei_mode = *((MppEncSeiMode *)param); break; diff --git a/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.c b/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.c index 7249c310..1f3e8214 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.c @@ -73,3 +73,68 @@ MPP_RET h264e_rkv_set_osd_data(H264eHalContext *ctx, void *param) h264e_hal_leave(); return MPP_OK; } + +MPP_RET h264e_rkv_set_roi_data(H264eHalContext *ctx, void *param) +{ + MppEncROICfg *src = (MppEncROICfg *)param; + MppEncROICfg *dst = &ctx->roi_data; + + h264e_hal_enter(); + + if (src->number && src->regions) { + dst->number = src->number; + dst->regions = src->regions; + } else { + memset(dst, 0, sizeof(*dst)); + } + + h264e_hal_leave(); + return MPP_OK; +} + +MPP_RET rkv_config_roi_area(H264eHalContext *ctx, RK_U8 *roi_base) +{ + h264e_hal_enter(); + RK_U32 ret = MPP_OK, idx = 0, num = 0; + RK_U32 init_pos_x, init_pos_y, roi_width, roi_height, mb_width, pos_y; + RkvRoiCfg cfg; + MppEncROIRegion *region; + RK_U8 *ptr = roi_base; + + if(ctx == NULL || roi_base == NULL){ + mpp_err("NULL pointer ctx %p roi_base %p\n", ctx, roi_base); + return MPP_NOK; + } + + region = ctx->roi_data.regions; + for(num = 0; num < ctx->roi_data.number; num++){ + init_pos_x = (region->x + 15) / 16; + init_pos_y = (region->y + 15) / 16; + roi_width = (region->w + 15) / 16; + roi_height = (region->h + 15) / 16; + mb_width = (ctx->hw_cfg.width + 15) / 16; + pos_y = init_pos_y; + + for (idx = 0; idx < roi_width * roi_height; idx++) { + if(idx % roi_width == 0) + pos_y = init_pos_y + idx / roi_width; + ptr = roi_base + (pos_y * mb_width + init_pos_x) + (idx % roi_width); + + if (region->quality) { + cfg.qp_y = region->quality; + cfg.set_qp_y_en = 1; + cfg.forbid_inter = region->intra; + } else { + cfg.set_qp_y_en = 0; + cfg.forbid_inter = 0; + } + + memcpy(ptr, &cfg, sizeof(RkvRoiCfg)); + } + + region++; + } + h264e_hal_leave(); + + return ret; +} diff --git a/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.h b/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.h index cce84ac6..d75388b4 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.h +++ b/mpp/hal/rkenc/h264e/hal_h264e_rkv_utils.h @@ -19,15 +19,15 @@ #include "hal_h264e_com.h" -// TODO: add ROI function -typedef struct h264e_hal_rkv_roi_cfg_t { +typedef struct{ RK_U8 qp_y : 6; RK_U8 set_qp_y_en : 1; RK_U8 forbid_inter : 1; -} h264e_hal_rkv_roi_cfg; +} RkvRoiCfg; MPP_RET h264e_rkv_set_osd_plt(H264eHalContext *ctx, void *param); MPP_RET h264e_rkv_set_osd_data(H264eHalContext *ctx, void *param); - +MPP_RET h264e_rkv_set_roi_data(H264eHalContext *ctx, void *param); +MPP_RET rkv_config_roi_area(H264eHalContext *ctx, RK_U8 *roi_base); #endif /* __HAL_H264E_RKV_UTILS_H__ */ diff --git a/test/mpi_enc_test.c b/test/mpi_enc_test.c index 718ad2bb..b0df6c00 100644 --- a/test/mpi_enc_test.c +++ b/test/mpi_enc_test.c @@ -38,6 +38,7 @@ #define MPI_ENC_TEST_SET_IDR_FRAME 0 #define MPI_ENC_TEST_SET_OSD 0 +#define MPI_ENC_TEST_SET_ROI 1 typedef struct { char file_input[MAX_FILE_NAME_LENGTH]; @@ -81,6 +82,7 @@ typedef struct { MppBuffer md_buf[MPI_ENC_IO_COUNT]; MppBuffer osd_idx_buf[MPI_ENC_IO_COUNT]; MppEncOSDPlt osd_plt; + MppEncROIRegion roi_region[3]; /* can be more regions */ MppEncSeiMode sei_mode; // paramter for resource malloc @@ -799,6 +801,32 @@ MPP_RET test_mpp_run(MpiEncTestData *p) } #endif +#if MPI_ENC_TEST_SET_ROI + MppEncROIRegion *region = p->roi_region; + MppEncROICfg roi_cfg; + + /* calculated in pixels */ + region->x = region->y = 64; + region->w = region->h = 128; /* 16-pixel aligned is better */ + region->intra = 0; /* flag of forced intra macroblock */ + region->quality = 20; /* qp of macroblock */ + + region++; + region->x = region->y = 256; + region->w = region->h = 128; /* 16-pixel aligned is better */ + region->intra = 1; /* flag of forced intra macroblock */ + region->quality = 25; /* qp of macroblock */ + + roi_cfg.number = 2; + roi_cfg.regions = p->roi_region; + + ret = mpi->control(ctx, MPP_ENC_SET_ROI_CFG, &roi_cfg); + if (MPP_OK != ret) { + mpp_err("mpi control enc set roi data failed\n"); + goto RET; + } +#endif + ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task); if (ret) { mpp_err("mpp task input enqueue failed\n");