diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index 8a3d2692ef..99d178bb87 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -752,7 +752,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L1_BR, ENC, HEVC, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -761,7 +762,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L2_BR, ENC, HEVC, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -770,7 +772,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L3_BR, ENC, HEVC, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -779,7 +782,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L4_BR, ENC, HEVC, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -788,7 +792,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L5_BR, ENC, HEVC, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -797,7 +802,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L0_BR, ENC, H264, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -806,7 +812,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L1_BR, ENC, H264, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -815,7 +822,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L2_BR, ENC, H264, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -824,7 +832,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L3_BR, ENC, H264, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -833,7 +842,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L4_BR, ENC, H264, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -842,7 +852,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {L5_BR, ENC, H264, 1, MAX_BITRATE, 1, DEFAULT_BITRATE, @@ -851,7 +862,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - msm_vidc_adjust_bitrate, msm_vidc_set_bitrate}, + msm_vidc_adjust_dynamic_layer_bitrate, + msm_vidc_set_dynamic_layer_bitrate}, {ENTROPY_MODE, ENC, H264, V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index fba78b166c..b92216695b 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -14,6 +14,7 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst); int msm_vidc_ctrl_deinit(struct msm_vidc_inst *inst); int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl); int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_dynamic_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_bitrate_mode(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_profile(void *instance, struct v4l2_ctrl *ctrl); @@ -27,7 +28,6 @@ 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); -int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_peak_bitrate(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl); @@ -60,6 +60,8 @@ int msm_vidc_set_gop_size(void *instance, enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_bitrate(void *instance, enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_dynamic_layer_bitrate(void *instance, + enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_u32(void *instance, enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_u32_enum(void *instance, diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 6f26819883..33935209c9 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -1416,15 +1416,54 @@ exit: return 0; } -int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl) +static bool msm_vidc_check_all_layer_bitrate_set(struct msm_vidc_inst *inst) +{ + bool layer_bitrate_set = true; + u32 cap_id = 0, i, enh_layer_count; + u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; + + enh_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value; + + for (i = 0; i <= enh_layer_count; i++) { + if (i >= ARRAY_SIZE(layer_br_caps)) + break; + cap_id = layer_br_caps[i]; + if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) { + layer_bitrate_set = false; + break; + } + } + + return layer_bitrate_set; +} + +static u32 msm_vidc_get_cumulative_bitrate(struct msm_vidc_inst *inst) { int i; - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; + u32 cap_id = 0; + u32 cumulative_br = 0; + s32 enh_layer_count; + u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; + + enh_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value; + + for (i = 0; i <= enh_layer_count; i++) { + if (i >= ARRAY_SIZE(layer_br_caps)) + break; + cap_id = layer_br_caps[i]; + cumulative_br += inst->capabilities->cap[cap_id].value; + } + + return cumulative_br; +} + +int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl) +{ + int i, rc = 0; struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1, enh_layer_count = -1; - u32 cap_id = 0, cumulative_bitrate = 0; - bool layer_bitrate_set = false; + struct msm_vidc_inst_capability *capability; + s32 adjusted_value, max_bitrate, enh_layer_count; + u32 cumulative_bitrate = 0, cap_id = 0, cap_value = 0; u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; if (!inst || !inst->capabilities) { @@ -1433,72 +1472,150 @@ int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl) } capability = inst->capabilities; - adjusted_value = ctrl ? ctrl->val : - capability->cap[BIT_RATE].value; - /* ignore layer bitrate when total bitrate is set */ - if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) - goto exit; + if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { + /* + * For static case, ctrl is null. + * For dynamic case, only BIT_RATE cap uses this adjust function. + * Hence, no need to check for ctrl id to be BIT_RATE control, and not + * any of layer bitrate controls. + */ + adjusted_value = ctrl ? ctrl->val : capability->cap[BIT_RATE].value; + msm_vidc_update_cap_value(inst, BIT_RATE, adjusted_value, __func__); + + return 0; + } + + if (inst->vb2q[OUTPUT_PORT].streaming) + return 0; if (msm_vidc_get_parent_value(inst, BIT_RATE, ENH_LAYER_COUNT, &enh_layer_count, __func__)) return -EINVAL; - if (msm_vidc_get_parent_value(inst, BIT_RATE, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; + max_bitrate = inst->capabilities->cap[BIT_RATE].max; /* * ENH_LAYER_COUNT cap max is positive only if - * layer encoding is enabled for static setting + * layer encoding is enabled during streamon. */ if (capability->cap[ENH_LAYER_COUNT].max) { - layer_bitrate_set = true; - for (i = 0; i <= enh_layer_count; i++) { - if (i >= ARRAY_SIZE(layer_br_caps)) - break; - cap_id = layer_br_caps[i]; - if (!(capability->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) { - layer_bitrate_set = false; - break; - } - cumulative_bitrate += capability->cap[cap_id].value; + if (!msm_vidc_check_all_layer_bitrate_set(inst)) { + i_vpr_h(inst, + "%s: client did not set all layer bitrates\n", + __func__); + return 0; } - /* layer bitrate supported only for CBR rc */ - if (layer_bitrate_set && - (rc_type == HFI_RC_CBR_CFR || rc_type == HFI_RC_CBR_VFR)) { - if (cumulative_bitrate > capability->cap[BIT_RATE].max) - cumulative_bitrate = - capability->cap[BIT_RATE].max; - adjusted_value = cumulative_bitrate; - i_vpr_h(inst, - "%s: update BIT_RATE with cumulative bitrate\n", - __func__); - } - } else { - for (i = 0; i < sizeof(layer_br_caps) / sizeof(u32); i++) { - if (i >= ARRAY_SIZE(layer_br_caps)) - break; - cap_id = layer_br_caps[i]; - /* - * layer bitrate cannot be set - * when layer encoding is disabled - */ - if (capability->cap[cap_id].flags & - CAP_FLAG_CLIENT_SET) { - i_vpr_e(inst, - "%s: invalid layer bitrate set\n", - __func__); - return -EINVAL; + cumulative_bitrate = msm_vidc_get_cumulative_bitrate(inst); + + /* cap layer bitrates to max supported bitrate */ + if (cumulative_bitrate > max_bitrate) { + u32 decrement_in_value = 0; + u32 decrement_in_percent = ((cumulative_bitrate - max_bitrate) * 100) / + max_bitrate; + + cumulative_bitrate = 0; + for (i = 0; i <= enh_layer_count; i++) { + if (i >= ARRAY_SIZE(layer_br_caps)) + break; + cap_id = layer_br_caps[i]; + cap_value = inst->capabilities->cap[cap_id].value; + + decrement_in_value = (cap_value * + decrement_in_percent) / 100; + cumulative_bitrate += (cap_value - decrement_in_value); + + /* + * cap value for the L*_BR is changed. Hence, update cap, + * and add to FW_LIST to set new values to firmware. + */ + msm_vidc_update_cap_value(inst, cap_id, + (cap_value - decrement_in_value), __func__); } } + + i_vpr_h(inst, + "%s: update BIT_RATE with cumulative bitrate\n", + __func__); + msm_vidc_update_cap_value(inst, BIT_RATE, + cumulative_bitrate, __func__); } -exit: + return rc; +} + +int msm_vidc_adjust_dynamic_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + u32 cumulative_bitrate = 0; + u32 client_set_cap_id = INST_CAP_NONE; + u32 old_br = 0, new_br = 0, exceeded_br = 0; + s32 max_bitrate; + + if (!inst || !inst->capabilities || !ctrl) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + /* ignore layer bitrate when total bitrate is set */ + if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) + return 0; + + if (!inst->vb2q[OUTPUT_PORT].streaming) + return 0; + + /* + * ENH_LAYER_COUNT cap max is positive only if + * layer encoding is enabled during streamon. + */ + if (!capability->cap[ENH_LAYER_COUNT].max) { + i_vpr_e(inst, "%s: layers not enabled\n", __func__); + return -EINVAL; + } + + if (!msm_vidc_check_all_layer_bitrate_set(inst)) { + i_vpr_h(inst, + "%s: client did not set all layer bitrates\n", + __func__); + return 0; + } + + client_set_cap_id = msm_vidc_get_cap_id(inst, ctrl->id); + if (client_set_cap_id == INST_CAP_NONE) { + i_vpr_e(inst, "%s: could not find cap_id for ctrl %s\n", + __func__, ctrl->name); + return -EINVAL; + } + + cumulative_bitrate = msm_vidc_get_cumulative_bitrate(inst); + max_bitrate = inst->capabilities->cap[BIT_RATE].max; + old_br = capability->cap[client_set_cap_id].value; + new_br = ctrl->val; + + /* + * new bitrate is not supposed to cause cumulative bitrate to + * exceed max supported bitrate + */ + + if ((cumulative_bitrate - old_br + new_br) > max_bitrate) { + /* adjust new bitrate */ + exceeded_br = (cumulative_bitrate - old_br + new_br) - max_bitrate; + new_br = ctrl->val - exceeded_br; + } + msm_vidc_update_cap_value(inst, client_set_cap_id, new_br, __func__); + + /* adjust totol bitrate cap */ + i_vpr_h(inst, + "%s: update BIT_RATE with cumulative bitrate\n", + __func__); msm_vidc_update_cap_value(inst, BIT_RATE, - adjusted_value, __func__); - return 0; + msm_vidc_get_cumulative_bitrate(inst), __func__); + + return rc; } int msm_vidc_adjust_peak_bitrate(void *instance, struct v4l2_ctrl *ctrl) @@ -2409,7 +2526,6 @@ int msm_vidc_set_bitrate(void *instance, u32 hfi_value = 0; s32 rc_type = -1, enh_layer_count = -1; u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; - bool layer_bitrate_set = false; if (!inst || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); @@ -2420,44 +2536,50 @@ int msm_vidc_set_bitrate(void *instance, if (inst->capabilities->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) goto set_total_bitrate; - if (msm_vidc_get_parent_value(inst, BIT_RATE, - ENH_LAYER_COUNT, &enh_layer_count, __func__)) - return -EINVAL; + /* + * During runtime, if BIT_RATE cap CLIENT_SET flag is not set, + * then this function will be called due to change in ENH_LAYER_COUNT. + * In this case, client did not change bitrate, hence, no need to set + * to fw. + */ + if (inst->vb2q[OUTPUT_PORT].streaming) + return 0; if (msm_vidc_get_parent_value(inst, BIT_RATE, BITRATE_MODE, &rc_type, __func__)) return -EINVAL; - if (inst->capabilities->cap[ENH_LAYER_COUNT].max && - (rc_type == HFI_RC_CBR_CFR || - rc_type == HFI_RC_CBR_VFR)) { - layer_bitrate_set = true; + if (rc_type != HFI_RC_CBR_CFR && rc_type != HFI_RC_CBR_VFR) { + i_vpr_h(inst, "%s: set total bitrate for non CBR rc type\n", + __func__); + goto set_total_bitrate; + } + + if (msm_vidc_get_parent_value(inst, BIT_RATE, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + /* + * ENH_LAYER_COUNT cap max is positive only if + * layer encoding is enabled during streamon. + */ + if (inst->capabilities->cap[ENH_LAYER_COUNT].max) { + if (!msm_vidc_check_all_layer_bitrate_set(inst)) + goto set_total_bitrate; + + /* set Layer Bitrate */ for (i = 0; i <= enh_layer_count; i++) { if (i >= ARRAY_SIZE(layer_br_caps)) break; cap_id = layer_br_caps[i]; - if (!(inst->capabilities->cap[cap_id].flags & - CAP_FLAG_CLIENT_SET)) { - layer_bitrate_set = false; - break; - } - } - - if (layer_bitrate_set) { - /* set Layer Bitrate */ - for (i = 0; i <= enh_layer_count; i++) { - if (i >= ARRAY_SIZE(layer_br_caps)) - break; - cap_id = layer_br_caps[i]; - hfi_value = inst->capabilities->cap[cap_id].value; - rc = msm_vidc_packetize_control(inst, cap_id, - HFI_PAYLOAD_U32, &hfi_value, - sizeof(u32), __func__); - if (rc) - return rc; - } - goto exit; + hfi_value = inst->capabilities->cap[cap_id].value; + rc = msm_vidc_packetize_control(inst, cap_id, + HFI_PAYLOAD_U32, &hfi_value, + sizeof(u32), __func__); + if (rc) + return rc; } + goto exit; } set_total_bitrate: @@ -2470,6 +2592,67 @@ exit: return rc; } +int msm_vidc_set_dynamic_layer_bitrate(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + u32 hfi_value = 0; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!inst->vb2q[OUTPUT_PORT].streaming) + return 0; + + /* set Total Bitrate */ + if (inst->capabilities->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { + i_vpr_h(inst, + "%s: Total bitrate is set, ignore layer bitrate\n", + __func__); + return 0; + } + + /* + * ENH_LAYER_COUNT cap max is positive only if + * layer encoding is enabled during streamon. + */ + if (!inst->capabilities->cap[ENH_LAYER_COUNT].max || + !msm_vidc_check_all_layer_bitrate_set(inst)) { + i_vpr_h(inst, + "%s: invalid layer bitrate, ignore setting to fw\n", + __func__); + return 0; + } + + if (inst->hfi_rc_type == HFI_RC_CBR_CFR || + rc_type == HFI_RC_CBR_VFR) { + /* set layer bitrate for the client set layer */ + hfi_value = inst->capabilities->cap[cap_id].value; + rc = msm_vidc_packetize_control(inst, cap_id, + HFI_PAYLOAD_U32, &hfi_value, + sizeof(u32), __func__); + if (rc) + return rc; + } else { + /* + * All layer bitartes set for unsupported rc type. + * Hence accept layer bitrates, but set total bitrate prop + * with cumulative bitrate. + */ + hfi_value = inst->capabilities->cap[BIT_RATE].value; + rc = msm_vidc_packetize_control(inst, BIT_RATE, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + } + + return rc; +} + int msm_vidc_set_session_priority(void *instance, enum msm_vidc_inst_capability_type cap_id) {