From e17abd45c1fd6af33e8e5b76425e8078d9a0eb30 Mon Sep 17 00:00:00 2001 From: Darshana Patil Date: Mon, 23 Aug 2021 15:50:33 -0700 Subject: [PATCH] video: driver: limit max number of sessions based on resolution add checks to limit max number of sessions supported based on resolution. max number of 720P sessions: 16 max number of 1080P sessions: 8 max number of 4K sessions: 4 max number of 8K sessions: 2 Change-Id: I2a784a0d28ba050923bdc7f42a21ee9801d01d86 Signed-off-by: Darshana Patil --- driver/platform/waipio/src/msm_vidc_waipio.c | 4 + driver/vidc/inc/msm_vidc_driver.h | 2 + driver/vidc/inc/msm_vidc_internal.h | 4 + driver/vidc/src/msm_vidc_driver.c | 210 ++++++++++++++----- 4 files changed, 170 insertions(+), 50 deletions(-) diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index 70df147b1c..bf6b8e182e 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -53,6 +53,10 @@ static struct msm_platform_core_capability core_data_waipio[] = { {ENC_CODECS, H264|HEVC|HEIC}, {DEC_CODECS, H264|HEVC|VP9|HEIC}, {MAX_SESSION_COUNT, 16}, + {MAX_NUM_720P_SESSIONS, 16}, + {MAX_NUM_1080P_SESSIONS, 8}, + {MAX_NUM_4K_SESSIONS, 4}, + {MAX_NUM_8K_SESSIONS, 2}, {MAX_SECURE_SESSION_COUNT, 3}, {MAX_MBPF, 173056}, /* (8192x4320)/256 + (4096x2176)/256*/ {MAX_MBPS, 7833600}, /* max_load diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 9a6901bf59..b40e2b02a8 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -428,6 +428,8 @@ void msm_vidc_free_capabililty_list(struct msm_vidc_inst *inst, enum msm_vidc_ctrl_list_type list_type); bool res_is_greater_than(u32 width, u32 height, u32 ref_width, u32 ref_height); +bool res_is_greater_than_or_equal_to(u32 width, u32 height, + u32 ref_width, u32 ref_height); bool res_is_less_than(u32 width, u32 height, u32 ref_width, u32 ref_height); bool res_is_less_than_or_equal_to(u32 width, u32 height, diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 729abc62f6..b16e91fe5d 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -304,6 +304,10 @@ enum msm_vidc_core_capability_type { ENC_CODECS, DEC_CODECS, MAX_SESSION_COUNT, + MAX_NUM_720P_SESSIONS, + MAX_NUM_1080P_SESSIONS, + MAX_NUM_4K_SESSIONS, + MAX_NUM_8K_SESSIONS, MAX_SECURE_SESSION_COUNT, MAX_LOAD, MAX_MBPF, diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index ba5c6ab3ea..4ade7bee37 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -1104,6 +1104,20 @@ bool res_is_greater_than(u32 width, u32 height, return false; } +bool res_is_greater_than_or_equal_to(u32 width, u32 height, + u32 ref_width, u32 ref_height) +{ + u32 num_mbs = NUM_MBS_PER_FRAME(height, width); + u32 max_side = max(ref_width, ref_height); + + if (num_mbs >= NUM_MBS_PER_FRAME(ref_height, ref_width) || + width >= max_side || + height >= max_side) + return true; + else + return false; +} + bool res_is_less_than(u32 width, u32 height, u32 ref_width, u32 ref_height) { @@ -5334,13 +5348,12 @@ exit: return allow; } -int msm_vidc_check_session_supported(struct msm_vidc_inst *inst) +static int msm_vidc_check_resolution_supported(struct msm_vidc_inst *inst) { struct msm_vidc_inst_capability *capability; u32 width = 0, height = 0, min_width, min_height, max_width, max_height; - bool allow = false, is_interlaced = false; - int rc = 0; + bool is_interlaced = false; if (!inst || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); @@ -5348,24 +5361,6 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst) } capability = inst->capabilities; - if (is_image_session(inst) && is_secure_session(inst)) { - i_vpr_e(inst, "%s: secure image session not supported\n", __func__); - rc = -EINVAL; - goto exit; - } - - rc = msm_vidc_check_core_mbps(inst); - if (rc) - goto exit; - - rc = msm_vidc_check_core_mbpf(inst); - if (rc) - goto exit; - - rc = msm_vidc_check_inst_mbpf(inst); - if (rc) - goto exit; - if (is_decode_session(inst)) { width = inst->fmts[INPUT_PORT].fmt.pix_mp.width; height = inst->fmts[INPUT_PORT].fmt.pix_mp.height; @@ -5399,56 +5394,171 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst) i_vpr_e(inst, "%s: resolution is not even. wxh [%u x %u], compose [%u x %u]\n", __func__, width, height, inst->compose.width, inst->compose.height); - rc = -EINVAL; - goto exit; + return -EINVAL; } - /* check decoder input width and height is in supported range */ - if (is_decode_session(inst)) { + /* check if input width and height is in supported range */ + if (is_decode_session(inst) || is_encode_session(inst)) { if (!in_range(width, min_width, max_width) || !in_range(height, min_height, max_height)) { i_vpr_e(inst, "%s: unsupported input wxh [%u x %u], allowed range: [%u x %u] to [%u x %u]\n", __func__, width, height, min_width, min_height, max_width, max_height); - rc = -EINVAL; - goto exit; + return -EINVAL; } } - /* check encoder crop width and height is in supported range */ - if (is_encode_session(inst)) { - if (!in_range(width, min_width, max_width) || - !in_range(height, min_height, max_height)) { - i_vpr_e(inst, - "%s: unsupported wxh [%u x %u], allowed range: [%u x %u] to [%u x %u]\n", - __func__, width, height, min_width, - min_height, max_width, max_height); - rc = -EINVAL; - goto exit; - } - } - - /* check image capabilities */ - if (is_image_encode_session(inst)) { - allow = msm_vidc_allow_image_encode_session(inst); - if (!allow) { - rc = -EINVAL; - goto exit; - } - return 0; - } - /* check interlace supported resolution */ is_interlaced = capability->cap[CODED_FRAMES].value == CODED_FRAMES_INTERLACE; if (is_interlaced && (width > INTERLACE_WIDTH_MAX || height > INTERLACE_HEIGHT_MAX || NUM_MBS_PER_FRAME(width, height) > INTERLACE_MB_PER_FRAME_MAX)) { i_vpr_e(inst, "%s: unsupported interlace wxh [%u x %u], max [%u x %u]\n", __func__, width, height, INTERLACE_WIDTH_MAX, INTERLACE_HEIGHT_MAX); + return -EINVAL; + } + + return 0; +} + +static int msm_vidc_check_max_sessions(struct msm_vidc_inst *inst) +{ + u32 width = 0, height = 0; + u32 num_720p_sessions = 0, num_1080p_sessions = 0; + u32 num_4k_sessions = 0, num_8k_sessions = 0; + struct msm_vidc_inst *i; + struct msm_vidc_core *core; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + if (!core->capabilities) { + i_vpr_e(inst, "%s: invalid params\n", __func__); + return -EINVAL; + } + + core_lock(core, __func__); + list_for_each_entry(i, &core->instances, list) { + /* skip image sessions count */ + if (is_image_session(inst)) + continue; + + if (is_decode_session(i)) { + width = i->fmts[INPUT_PORT].fmt.pix_mp.width; + height = i->fmts[INPUT_PORT].fmt.pix_mp.height; + } else if (is_encode_session(i)) { + width = i->crop.width; + height = i->crop.height; + } + + /* + * one 8k session equals to 64 720p sessions in reality. + * So for one 8k session the number of 720p sessions will + * exceed max supported session count(16), hence one 8k session + * will be rejected as well. + * Therefore, treat one 8k session equal to two 4k sessions and + * one 4k session equal to two 1080p sessions and + * one 1080p session equal to two 720p sessions. This equation + * will make one 8k session equal to eight 720p sessions + * which looks good. + */ + if (res_is_greater_than(width, height, 4096, 2176)) { + num_8k_sessions += 1; + num_4k_sessions += 2; + num_1080p_sessions += 4; + num_720p_sessions += 8; + } else if (res_is_greater_than(width, height, 1920, 1088)) { + num_4k_sessions += 1; + num_1080p_sessions += 2; + num_720p_sessions += 4; + } else if (res_is_greater_than(width, height, 1280, 736)) { + num_1080p_sessions += 1; + num_720p_sessions += 2; + } else { + num_720p_sessions += 1; + } + } + core_unlock(core, __func__); + + if (num_8k_sessions > core->capabilities[MAX_NUM_8K_SESSIONS].value) { + i_vpr_e(inst, "%s: total 8k sessions %d, exceeded max limit %d\n", + __func__, num_8k_sessions, + core->capabilities[MAX_NUM_8K_SESSIONS].value); + return -ENOMEM; + } + + if (num_4k_sessions > core->capabilities[MAX_NUM_4K_SESSIONS].value) { + i_vpr_e(inst, "%s: total 4K sessions %d, exceeded max limit %d\n", + __func__, num_4k_sessions, + core->capabilities[MAX_NUM_4K_SESSIONS].value); + return -ENOMEM; + } + + if (num_1080p_sessions > core->capabilities[MAX_NUM_1080P_SESSIONS].value) { + i_vpr_e(inst, "%s: total 1080p sessions %d, exceeded max limit %d\n", + __func__, num_1080p_sessions, + core->capabilities[MAX_NUM_1080P_SESSIONS].value); + return -ENOMEM; + } + + if (num_720p_sessions > core->capabilities[MAX_NUM_720P_SESSIONS].value) { + i_vpr_e(inst, "%s: total sessions(<=720p) %d, exceeded max limit %d\n", + __func__, num_720p_sessions, + core->capabilities[MAX_NUM_720P_SESSIONS].value); + return -ENOMEM; + } + + return 0; +} + +int msm_vidc_check_session_supported(struct msm_vidc_inst *inst) +{ + bool allow = false; + int rc = 0; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (is_image_session(inst) && is_secure_session(inst)) { + i_vpr_e(inst, "%s: secure image session not supported\n", __func__); rc = -EINVAL; goto exit; } + rc = msm_vidc_check_core_mbps(inst); + if (rc) + goto exit; + + rc = msm_vidc_check_core_mbpf(inst); + if (rc) + goto exit; + + rc = msm_vidc_check_inst_mbpf(inst); + if (rc) + goto exit; + + rc = msm_vidc_check_resolution_supported(inst); + if (rc) + goto exit; + + /* check image capabilities */ + if (is_image_encode_session(inst)) { + allow = msm_vidc_allow_image_encode_session(inst); + if (!allow) { + rc = -EINVAL; + goto exit; + } + } + + rc = msm_vidc_check_max_sessions(inst); + if (rc) + goto exit; + exit: if (rc) { i_vpr_e(inst, "%s: current session not supported\n", __func__);