diff --git a/mpp/codec/enc/h264/h264e_pps.c b/mpp/codec/enc/h264/h264e_pps.c index 492e08f5..8702b0fd 100644 --- a/mpp/codec/enc/h264/h264e_pps.c +++ b/mpp/codec/enc/h264/h264e_pps.c @@ -22,25 +22,34 @@ #include "h264e_debug.h" #include "h264e_pps.h" -static void write_scaling_list(MppWriteCtx *bit, RK_S32 mode) -{ - switch (mode) { - case 0 : { - // flat scaling matrix - /* scaling_list_present_flag */ - mpp_writer_put_bits(bit, 0, 1); - } break; - case 1 : { - /* scaling_list_present_flag */ - mpp_writer_put_bits(bit, 1, 1); - /* delta_scale */ - mpp_writer_put_se(bit, -8); - } break; - default : { - mpp_err_f("unsupport scaling list mode %d\n", mode); - } break; - } -} +static const uint8_t zigzag[64] = { + 0, 8, 1, 2, 9, 16, 24, 17, 10, 3, 4, 11, 18, 25, 32, 40, + 33, 26, 19, 12, 5, 6, 13, 20, 27, 34, 41, 48, 56, 49, 42, 35, + 28, 21, 14, 7, 15, 22, 29, 36, 43, 50, 57, 58, 51, 44, 37, 30, + 23, 31, 38, 45, 52, 59, 60, 53, 46, 39, 47, 54, 61, 62, 55, 63 +}; + +static const uint8_t intra_scl[64] = { + 10, 11, 14, 16, 17, 19, 21, 23, + 11, 12, 16, 17, 19, 21, 23, 25, + 14, 16, 17, 19, 21, 23, 25, 27, + 16, 17, 19, 21, 23, 25, 27, 28, + 17, 19, 21, 23, 25, 27, 28, 29, + 19, 21, 23, 25, 27, 28, 29, 30, + 21, 23, 25, 27, 28, 29, 30, 31, + 23, 25, 27, 28, 29, 30, 31, 32, +}; + +static const uint8_t inter_scl[64] = { + 12, 13, 15, 16, 17, 19, 20, 21, + 13, 14, 16, 17, 19, 20, 21, 22, + 15, 16, 17, 19, 20, 21, 22, 23, + 16, 17, 19, 20, 21, 22, 23, 25, + 17, 19, 20, 21, 22, 23, 25, 27, + 19, 20, 21, 22, 23, 25, 27, 28, + 20, 21, 22, 23, 25, 27, 28, 29, + 21, 22, 23, 25, 27, 28, 29, 30, +}; MPP_RET h264e_pps_update(H264ePps *pps, MppEncCfgSet *cfg) { @@ -165,16 +174,39 @@ RK_S32 h264e_pps_to_packet(H264ePps *pps, MppPacket packet, RK_S32 *offset, RK_S /* transform_8x8_mode_flag */ mpp_writer_put_bits(bit, pps->transform_8x8_mode, 1); - /* pic_scaling_matrix_present_flag */ - mpp_writer_put_bits(bit, pps->pic_scaling_matrix_present, 1); - if (pps->pic_scaling_matrix_present) { - /* Only support default scaling list */ - /* pic_scaling_list_present_flag[i] */ - RK_S32 count = pps->transform_8x8_mode ? 8 : 6; - RK_S32 i; + /* TODO: scaling_list_mode */ + mpp_writer_put_bits(bit, pps->pic_scaling_matrix_present != 0, 1); + if (pps->pic_scaling_matrix_present) + mpp_writer_put_bits(bit, 0, 6); - for (i = 0; i < count; i++) - write_scaling_list(bit, pps->use_default_scaling_matrix[i]); + if (1 == pps->pic_scaling_matrix_present) + mpp_writer_put_bits(bit, 0, 2); /* default scaling list */ + else if (2 == pps->pic_scaling_matrix_present) { + /* user defined scaling list */ + if (pps->transform_8x8_mode) { + RK_S32 run = 0; + RK_S32 len2 = 64; + RK_S32 j = 0; + + mpp_writer_put_bits(bit, 1, 1); + for (run = len2; run > 1; run --) + if (intra_scl[zigzag[run - 1]] != intra_scl[zigzag[run - 2]]) + break; + for (j = 0; j < run; j ++) + mpp_writer_put_se(bit, (int8_t)(intra_scl[zigzag[j]] - (j > 0 ? intra_scl[zigzag[j - 1]] : 8))); + if (run < len2) + mpp_writer_put_se(bit, (int8_t) - intra_scl[zigzag[run]]); + + mpp_writer_put_bits(bit, 1, 1); + for (run = len2; run > 1; run --) + if (inter_scl[zigzag[run - 1]] != inter_scl[zigzag[run - 2]]) + break; + for (j = 0; j < run; j ++) + mpp_writer_put_se(bit, (int8_t)(inter_scl[zigzag[j]] - (j > 0 ? inter_scl[zigzag[j - 1]] : 8))); + if (run < len2) + mpp_writer_put_se(bit, (int8_t) - inter_scl[zigzag[run]]); + } else + mpp_writer_put_bits(bit, 0, 2); } /* second_chroma_qp_index_offset */ diff --git a/mpp/codec/enc/h264/h264e_pps.h b/mpp/codec/enc/h264/h264e_pps.h index c9e3fd52..04b20897 100644 --- a/mpp/codec/enc/h264/h264e_pps.h +++ b/mpp/codec/enc/h264/h264e_pps.h @@ -52,7 +52,7 @@ typedef struct H264ePps_t { RK_S32 transform_8x8_mode; // Only support flat and default scaling list - RK_S32 pic_scaling_matrix_present; + RK_S32 pic_scaling_matrix_present; //TODO: replaced with scaling_list_mode RK_S32 use_default_scaling_matrix[H264_SCALING_MATRIX_TYPE_BUTT]; } H264ePps; diff --git a/mpp/codec/enc/h265/h265e_header_gen.c b/mpp/codec/enc/h265/h265e_header_gen.c index d386b843..9d05f248 100644 --- a/mpp/codec/enc/h265/h265e_header_gen.c +++ b/mpp/codec/enc/h265/h265e_header_gen.c @@ -494,12 +494,11 @@ static MPP_RET h265e_sps_write(H265eSps *sps, H265eStream *s) h265e_stream_write_ue_with_log(s, sps->m_quadtreeTUMaxDepthInter - 1, "max_transform_hierarchy_depth_inter"); h265e_stream_write_ue_with_log(s, sps->m_quadtreeTUMaxDepthIntra - 1, "max_transform_hierarchy_depth_intra"); h265e_stream_write1_with_log(s, sps->m_scalingListEnabledFlag ? 1 : 0, "scaling_list_enabled_flag"); - if (sps->m_scalingListEnabledFlag) { - h265e_stream_write1_with_log(s, sps->m_scalingListPresentFlag ? 1 : 0, "sps_scaling_list_data_present_flag"); - if (sps->m_scalingListPresentFlag) { - mpp_log("to do m_scalingListPresentFlag"); - ;//codeScalingList(m_slice->getScalingList()); //todo only support default - } + if (sps->m_scalingListEnabledFlag == 1) + h265e_stream_write1_with_log(s, 0, "sps_scaling_list_data_present_flag"); + else if (sps->m_scalingListEnabledFlag == 2) { + //TODO: + mpp_err_f("m_scalingListEnabledFlag == 2 not supported yet\n"); } h265e_stream_write1_with_log(s, sps->m_useAMP ? 1 : 0, "amp_enabled_flag"); h265e_stream_write1_with_log(s, sps->m_bUseSAO ? 1 : 0, "sample_adaptive_offset_enabled_flag"); diff --git a/mpp/codec/enc/h265/h265e_slice.h b/mpp/codec/enc/h265/h265e_slice.h index 3a5bf336..f8eb98c7 100644 --- a/mpp/codec/enc/h265/h265e_slice.h +++ b/mpp/codec/enc/h265/h265e_slice.h @@ -275,7 +275,7 @@ typedef struct H265eSps_e { RK_U32 m_bTemporalIdNestingFlag; // temporal_id_nesting_flag - RK_U32 m_scalingListEnabledFlag; + RK_U32 m_scalingListEnabledFlag; //TODO: replaced with scaling_list_mode RK_U32 m_scalingListPresentFlag; RK_U32 m_maxDecPicBuffering[MAX_SUB_LAYERS]; diff --git a/mpp/hal/rkenc/common/vepu510_common.h b/mpp/hal/rkenc/common/vepu510_common.h index e5f8319f..330abe19 100644 --- a/mpp/hal/rkenc/common/vepu510_common.h +++ b/mpp/hal/rkenc/common/vepu510_common.h @@ -905,6 +905,44 @@ typedef struct Vepu510RcRoi_t { Vepu510RoiCfg roi_cfg; } Vepu510RcRoi; +/* class: scaling list */ +/* 0x00002200 reg2176- 0x00002584 reg2401*/ +typedef struct Vepu510SclCfg_t { + /* 0x2200 - 0x221F, valid for h.264/h.h265, jpeg no use */ + RK_U32 tu8_intra_y[16]; + RK_U32 tu8_intra_u[16]; /* tu8_inter_y[16] for h.264 */ + + /* 0x2220 - 0x2584, valid for h.265 only */ + RK_U32 tu8_intra_v[16]; + RK_U32 tu8_inter_y[16]; + RK_U32 tu8_inter_u[16]; + RK_U32 tu8_inter_v[16]; + RK_U32 tu16_intra_y_ac[16]; + RK_U32 tu16_intra_u_ac[16]; + RK_U32 tu16_intra_v_ac[16]; + RK_U32 tu16_inter_y_ac[16]; + RK_U32 tu16_inter_u_ac[16]; + RK_U32 tu16_inter_v_ac[16]; + RK_U32 tu32_intra_y_ac[16]; + RK_U32 tu32_inter_y_ac[16]; + + /* 0x2580 */ + struct { + RK_U32 tu16_intra_y_dc : 8; + RK_U32 tu16_intra_u_dc : 8; + RK_U32 tu16_intra_v_dc : 8; + RK_U32 tu16_inter_y_dc : 8; + } tu_dc0; + + /* 0x2584 */ + struct { + RK_U32 tu16_inter_u_dc : 8; + RK_U32 tu16_inter_v_dc : 8; + RK_U32 tu32_intra_y_dc : 8; + RK_U32 tu32_inter_y_dc : 8; + } tu_dc1; +} Vepu510SclCfg; + /* class: st */ /* 0x00004000 reg4096 - 0x0000424c reg4243*/ typedef struct Vepu510Status_t { diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c index d239d5c4..d3e9d752 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c @@ -31,6 +31,29 @@ #define MAX_TASK_CNT 2 #define VEPU540C_MAX_ROI_NUM 8 +/* Custom Quant Matrices: Joint Video Team */ +static RK_U8 vepu510_h264_cqm_jvt8i[64] = { + 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static RK_U8 vepu510_h264_cqm_jvt8p[64] = { + 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 +}; + typedef struct Vepu510RoiH264BsCfg_t { RK_U64 force_inter : 42; RK_U64 mode_mask : 9; @@ -2106,6 +2129,31 @@ static void setup_vepu510_anti_smear(HalH264eVepu510Ctx *ctx) hal_h264e_dbg_func("leave\n"); } +static void setup_vepu510_scaling_list(HalH264eVepu510Ctx *ctx) +{ + HalVepu510RegSet *regs = ctx->regs_set; + Vepu510SclCfg *s = ®s->reg_scl; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U8 idx; + + hal_h264e_dbg_func("enter\n"); + + /* intra4x4 and inter4x4 is not supported on VEPU500. + * valid range: 0x2200 ~ 0x221F + */ + if (ctx->pps->pic_scaling_matrix_present == 1) { + for (idx = 0; idx < 64; idx++) { + p[idx] = vepu510_h264_cqm_jvt8i[63 - idx]; /* intra8x8 */ + p[idx + 64] = vepu510_h264_cqm_jvt8p[63 - idx]; /* inter8x8 */ + } + } else if (ctx->pps->pic_scaling_matrix_present == 2) { + //TODO: Update scaling list for (scaling_list_mode == 2) + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h264e_dbg_func("leave\n"); +} + static MPP_RET hal_h264e_vepu510_gen_regs(void *hal, HalEncTask *task) { HalH264eVepu510Ctx *ctx = (HalH264eVepu510Ctx *)hal; @@ -2139,6 +2187,7 @@ static MPP_RET hal_h264e_vepu510_gen_regs(void *hal, HalEncTask *task) setup_vepu510_anti_ringing(ctx); setup_vepu510_anti_flicker(ctx); setup_vepu510_anti_smear(ctx); + setup_vepu510_scaling_list(ctx); setup_vepu510_rc_base(regs, ctx, rc_task); setup_vepu510_io_buf(regs, ctx->offsets, task); diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510_reg.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_reg.h index 9b11af98..e40e294f 100644 --- a/mpp/hal/rkenc/h264e/hal_h264e_vepu510_reg.h +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_reg.h @@ -625,10 +625,6 @@ typedef struct H264eVepu510SqiCfg_t { } rdo_atf_resi_thd; } H264eVepu510Sqi; -typedef struct Vepu510SclCfg_t { - RK_U32 q_scal_list_0_225[226]; -} Vepu510SclCfg; - /* class: mmu */ /* 0x0000f000 reg15360 - 0x0000f024 reg15369 */ typedef struct HalVepu510Reg_t { diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c index 5775b7b9..c806dc99 100644 --- a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c @@ -248,6 +248,28 @@ static RK_U32 rdo_lambda_table_P[60] = { 0x01120000, 0x01600000, 0x01c00000, 0x02240000, }; +static RK_U8 vepu510_h265_cqm_intra8[64] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115 +}; + +static RK_U8 vepu510_h265_cqm_inter8[64] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91 +}; + static void setup_ext_line_bufs(H265eV510HalContext *ctx) { RK_S32 i; @@ -1855,6 +1877,60 @@ static void setup_vepu510_split(H265eV510RegSet *regs, MppEncCfgSet *enc_cfg, RK hal_h265e_dbg_func("leave\n"); } +static void vepu510_h265_set_scaling_list(H265eV510HalContext *ctx) +{ + Vepu510H265eFrmCfg *frm_cfg = ctx->frm; + H265eV510RegSet *regs = frm_cfg->regs_set; + Vepu510SclCfg *s = ®s->reg_scl; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U32 scl_lst_sel = regs->reg_frm.rdo_cfg.scl_lst_sel; + RK_U8 idx; + + hal_h265e_dbg_func("enter\n"); + + if (scl_lst_sel == 1) { + for (idx = 0; idx < 64; idx++) { + /* TU8 intra Y/U/V */ + p[idx + 64 * 0] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 1] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 2] = vepu510_h265_cqm_intra8[63 - idx]; + + /* TU8 inter Y/U/V */ + p[idx + 64 * 3] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 4] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 5] = vepu510_h265_cqm_inter8[63 - idx]; + + /* TU16 intra Y/U/V AC */ + p[idx + 64 * 6] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 7] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 8] = vepu510_h265_cqm_intra8[63 - idx]; + + /* TU16 inter Y/U/V AC */ + p[idx + 64 * 9] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 10] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 11] = vepu510_h265_cqm_inter8[63 - idx]; + + /* TU32 intra/inter Y AC */ + p[idx + 64 * 12] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 13] = vepu510_h265_cqm_inter8[63 - idx]; + } + + s->tu_dc0.tu16_intra_y_dc = 16; + s->tu_dc0.tu16_intra_u_dc = 16; + s->tu_dc0.tu16_intra_v_dc = 16; + s->tu_dc0.tu16_inter_y_dc = 16; + s->tu_dc1.tu16_inter_u_dc = 16; + s->tu_dc1.tu16_inter_v_dc = 16; + s->tu_dc1.tu32_intra_y_dc = 16; + s->tu_dc1.tu32_inter_y_dc = 16; + } else if (scl_lst_sel == 2) { + //TODO: Update scaling list for (scaling_list_mode == 2) + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h265e_dbg_func("leave\n"); +} + MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) { H265eV510HalContext *ctx = (H265eV510HalContext *)hal; @@ -1980,6 +2056,7 @@ MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) reg_frm->synt_nal.nal_unit_type = syn->sp.temporal_id ? NAL_TSA_R : i_nal_type; } + vepu510_h265_set_scaling_list(ctx); vepu510_h265_set_hw_address(ctx, reg_frm, task); vepu510_h265_set_pp_regs(regs, fmt, &ctx->cfg->prep); vepu510_h265_set_rc_regs(ctx, regs, task); @@ -2113,6 +2190,16 @@ MPP_RET hal_h265e_v510_start(void *hal, HalEncTask *enc_task) return ret; } + cfg.reg = &hw_regs->reg_scl; + cfg.size = sizeof(hw_regs->reg_scl); + cfg.offset = VEPU510_SCL_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->reg_cfg); if (ret) { mpp_err_f("set register offsets failed %d\n", ret); diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_reg.h index 2500acd7..d658b3af 100644 --- a/mpp/hal/rkenc/h265e/hal_h265e_vepu510_reg.h +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_reg.h @@ -810,6 +810,7 @@ typedef struct H265eV510RegSet_t { Vepu510RcRoi reg_rc_roi; H265eVepu510Param reg_param; H265eVepu510Sqi reg_sqi; + Vepu510SclCfg reg_scl; Vepu510Dbg reg_dbg; } H265eV510RegSet;