From 5a2b2ee39930aae6ce4c991be25099ac94e42bc0 Mon Sep 17 00:00:00 2001 From: Akshata Sahukar Date: Mon, 12 Apr 2021 13:09:40 -0700 Subject: [PATCH] video: driver: Add support to adjust slice mode Add support to adjust slice mode. Change-Id: Id09e951b3085c55cc5bc6b15a2ce002645923435 Signed-off-by: Akshata Sahukar --- driver/platform/waipio/src/msm_vidc_waipio.c | 21 ++-- driver/vidc/inc/msm_vidc_control.h | 1 + driver/vidc/inc/msm_vidc_internal.h | 9 ++ driver/vidc/src/msm_venc.c | 21 +++- driver/vidc/src/msm_vidc_control.c | 110 ++++++++++++++++++- 5 files changed, 152 insertions(+), 10 deletions(-) diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index ba2253867c..1063978798 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -25,6 +25,11 @@ #define MAX_QP 51 #define DEFAULT_QP 20 #define MAX_CONSTANT_QUALITY 100 +#define MIN_SLICE_BYTE_SIZE 512 +#define MAX_SLICE_BYTE_SIZE \ + ((MAX_BITRATE) >> 3) +#define MAX_SLICE_MB_SIZE \ + (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) #define UBWC_CONFIG(mc, ml, hbb, bs1, bs2, bs3, bsp) \ { \ @@ -329,7 +334,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { {0}, {LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, I_FRAME_QP, ENH_LAYER_COUNT, BIT_RATE, CONTENT_ADAPTIVE_CODING, - BITRATE_BOOST, MIN_QUALITY, VBV_DELAY, PEAK_BITRATE}, + BITRATE_BOOST, MIN_QUALITY, VBV_DELAY, PEAK_BITRATE, + SLICE_MODE}, msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum}, {BITRATE_MODE, ENC, HEVC, @@ -347,7 +353,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CONSTANT_QUALITY, ENH_LAYER_COUNT, CONTENT_ADAPTIVE_CODING, BIT_RATE, BITRATE_BOOST, MIN_QUALITY, VBV_DELAY, - PEAK_BITRATE}, + PEAK_BITRATE, SLICE_MODE}, msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum}, {LOSSLESS, ENC, HEVC|HEIC, @@ -1027,18 +1033,19 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, 0, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, - {0}, {0}, - NULL, msm_vidc_set_slice_count}, + CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + {BITRATE_MODE}, {0}, + msm_vidc_adjust_slice_count, msm_vidc_set_slice_count}, {SLICE_MAX_BYTES, ENC, H264|HEVC|HEIC, - 1, INT_MAX, 1, INT_MAX, + MIN_SLICE_BYTE_SIZE, MAX_SLICE_BYTE_SIZE, + 1, MIN_SLICE_BYTE_SIZE, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, HFI_PROP_MULTI_SLICE_BYTES_COUNT, CAP_FLAG_OUTPUT_PORT}, {SLICE_MAX_MB, ENC, H264|HEVC|HEIC, - 1, INT_MAX, 1, INT_MAX, + 1, MAX_SLICE_MB_SIZE, 1, 1, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, HFI_PROP_MULTI_SLICE_MB_COUNT, CAP_FLAG_OUTPUT_PORT}, diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index 80859bc2c9..484d16e494 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -28,6 +28,7 @@ int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_ir_random(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl); diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 77d06f386c..14a11fb655 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -56,6 +56,15 @@ #define MAX_AVC_ENH_LAYER_HYBRID_HP 5 #define PERCENT_PEAK_BITRATE_INCREASED 10 #define INVALID_DEFAULT_MARK_OR_USE_LTR -1 +#define MAX_SLICES_PER_FRAME 10 +#define MAX_SLICES_FRAME_RATE 60 +#define MAX_MB_SLICE_WIDTH 4096 +#define MAX_MB_SLICE_HEIGHT 2160 +#define MAX_BYTES_SLICE_WIDTH 1920 +#define MAX_BYTES_SLICE_HEIGHT 1088 +#define MIN_HEVC_SLICE_WIDTH 384 +#define MIN_AVC_SLICE_WIDTH 192 +#define MIN_SLICE_HEIGHT 128 #define DCVS_WINDOW 16 /* Superframe can have maximum of 32 frames */ diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index 4ad5330cb1..a1e7b80b28 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -1245,6 +1245,7 @@ static int msm_venc_s_fmt_input(struct msm_vidc_inst *inst, struct v4l2_format * if (fmt->fmt.pix_mp.width != crop_width || fmt->fmt.pix_mp.height != crop_height) { + struct v4l2_format *output_fmt; /* reset crop dimensions with updated resolution */ inst->crop.top = inst->crop.left = 0; @@ -1256,9 +1257,17 @@ static int msm_venc_s_fmt_input(struct msm_vidc_inst *inst, struct v4l2_format * inst->compose.width = f->fmt.pix_mp.width; inst->compose.height = f->fmt.pix_mp.height; - rc = msm_venc_s_fmt_output(inst, &inst->fmts[OUTPUT_PORT]); + output_fmt = &inst->fmts[OUTPUT_PORT]; + rc = msm_venc_s_fmt_output(inst, output_fmt); if (rc) return rc; + + i_vpr_h(inst, + "%s: type %d: format %#x width %d height %d size %d\n", + __func__, output_fmt->type, output_fmt->fmt.pix_mp.pixelformat, + output_fmt->fmt.pix_mp.width, + output_fmt->fmt.pix_mp.height, + output_fmt->fmt.pix_mp.plane_fmt[0].sizeimage); } //rc = msm_vidc_check_session_supported(inst); @@ -1385,6 +1394,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) int msm_venc_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s) { int rc = 0; + struct v4l2_format *output_fmt; if (!inst || !s) { d_vpr_e("%s: invalid params\n", __func__); @@ -1431,9 +1441,16 @@ int msm_venc_s_selection(struct msm_vidc_inst* inst, struct v4l2_selection* s) if (inst->compose.height > inst->crop.height) inst->compose.height = inst->crop.height; /* update output format based on new crop dimensions */ - rc = msm_venc_s_fmt_output(inst, &inst->fmts[OUTPUT_PORT]); + output_fmt = &inst->fmts[OUTPUT_PORT]; + rc = msm_venc_s_fmt_output(inst, output_fmt); if (rc) return rc; + i_vpr_h(inst, + "%s: type %d: format %#x width %d height %d size %d\n", + __func__, output_fmt->type, output_fmt->fmt.pix_mp.pixelformat, + output_fmt->fmt.pix_mp.width, + output_fmt->fmt.pix_mp.height, + output_fmt->fmt.pix_mp.plane_fmt[0].sizeimage); break; case V4L2_SEL_TGT_COMPOSE_BOUNDS: case V4L2_SEL_TGT_COMPOSE_PADDED: diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 357b538639..576c72186b 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -1072,6 +1072,112 @@ int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl) return 0; } +int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + struct v4l2_format *output_fmt; + s32 adjusted_value, rc_type = -1, slice_mode; + u32 slice_val, mbpf = 0, mbps = 0, max_mbpf = 0, max_mbps = 0; + u32 update_cap, max_avg_slicesize, output_width, output_height; + u32 min_width, min_height, max_width, max_height, fps; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + slice_mode = ctrl ? ctrl->val : + capability->cap[SLICE_MODE].value; + + if (msm_vidc_get_parent_value(inst, SLICE_MODE, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) + return 0; + + fps = capability->cap[FRAME_RATE].value >> 16; + if (fps > MAX_SLICES_FRAME_RATE || + (rc_type != HFI_RC_OFF && + rc_type != HFI_RC_CBR_CFR && + rc_type != HFI_RC_CBR_VFR)) { + adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + update_cap = SLICE_MODE; + i_vpr_h(inst, + "%s: slice unsupported, fps: %u, rc_type: %#x\n", + __func__, fps, rc_type); + goto exit; + } + + output_fmt = &inst->fmts[OUTPUT_PORT]; + output_width = output_fmt->fmt.pix_mp.width; + output_height = output_fmt->fmt.pix_mp.height; + + max_width = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ? + MAX_MB_SLICE_WIDTH : MAX_BYTES_SLICE_WIDTH; + max_height = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ? + MAX_MB_SLICE_HEIGHT : MAX_BYTES_SLICE_HEIGHT; + min_width = (inst->codec == MSM_VIDC_HEVC) ? + MIN_HEVC_SLICE_WIDTH : MIN_AVC_SLICE_WIDTH; + min_height = MIN_SLICE_HEIGHT; + + /* + * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB: + * - width >= 384 and height >= 128 + * - width and height <= 4096 + * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES: + * - width >= 192 and height >= 128 + * - width and height <= 1920 + */ + if (output_width < min_width || output_height < min_height || + output_width > max_width || output_height > max_width) { + adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + update_cap = SLICE_MODE; + i_vpr_h(inst, + "%s: slice unsupported, codec: %#x wxh: [%dx%d]\n", + __func__, inst->codec, output_width, output_height); + goto exit; + } + + mbpf = NUM_MBS_PER_FRAME(output_height, output_width); + mbps = NUM_MBS_PER_SEC(output_height, output_width, fps); + max_mbpf = NUM_MBS_PER_FRAME(max_height, max_width); + max_mbps = NUM_MBS_PER_SEC(max_height, max_width, fps); + + if (mbpf > max_mbpf || mbps > max_mbps) { + adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + update_cap = SLICE_MODE; + i_vpr_h(inst, + "%s: Unsupported, mbpf[%u] > max[%u], mbps[%u] > max[%u]\n", + __func__, mbpf, max_mbpf, mbps, max_mbps); + goto exit; + } + + if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) { + update_cap = SLICE_MAX_MB; + slice_val = capability->cap[SLICE_MAX_MB].value; + slice_val = max(slice_val, mbpf / MAX_SLICES_PER_FRAME); + } else { + slice_val = capability->cap[SLICE_MAX_BYTES].value; + update_cap = SLICE_MAX_BYTES; + if (rc_type != HFI_RC_OFF) { + max_avg_slicesize = ((capability->cap[BIT_RATE].value / + fps) / 8) / + MAX_SLICES_PER_FRAME; + slice_val = max(slice_val, max_avg_slicesize); + } + } + adjusted_value = slice_val; + +exit: + msm_vidc_update_cap_value(inst, update_cap, + adjusted_value, __func__); + + return 0; +} + static int msm_vidc_adjust_static_layer_count_and_type(struct msm_vidc_inst *inst, s32 layer_count) { @@ -2033,7 +2139,9 @@ int msm_vidc_set_slice_count(void* instance, return 0; } if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) { - hfi_value = inst->capabilities->cap[SLICE_MAX_MB].value; + hfi_value = (inst->codec == MSM_VIDC_HEVC) ? + ((inst->capabilities->cap[SLICE_MAX_MB].value + 3) / 4) : + inst->capabilities->cap[SLICE_MAX_MB].value; set_cap_id = SLICE_MAX_MB; } else if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) { hfi_value = inst->capabilities->cap[SLICE_MAX_BYTES].value;