From 911dc56174d5df8d005df92ee136510ddfa6c67f Mon Sep 17 00:00:00 2001 From: Amit Shekhar Date: Thu, 28 May 2020 10:14:58 -0700 Subject: [PATCH] msm: vidc: Add support for Hier-B Add support for Hier-B. Change-Id: I2bd6f1b6525224795500d8a260de3d78a78d2163 CRs-Fixed: 2637948 Signed-off-by: Amit Shekhar --- msm/vidc/msm_venc.c | 171 +++++++++++++++++++----- msm/vidc/msm_venc.h | 1 + msm/vidc/msm_vidc_buffer_calculations.c | 41 ++++-- msm/vidc/msm_vidc_common.h | 19 +++ msm/vidc/vidc_hfi_helper.h | 4 + 5 files changed, 193 insertions(+), 43 deletions(-) diff --git a/msm/vidc/msm_venc.c b/msm/vidc/msm_venc.c index c7f16dfe3c72..b703dbf04c1a 100644 --- a/msm/vidc/msm_venc.c +++ b/msm/vidc/msm_venc.c @@ -601,10 +601,11 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE, .name = "Set Hier coding type", .type = V4L2_CTRL_TYPE_MENU, - .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P, + .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B, .maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P, .default_value = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P, .menu_skip_mask = ~( + (1 << V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) | (1 << V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) ), .qmenu = NULL, @@ -2451,8 +2452,14 @@ int msm_venc_set_intra_period(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; - struct v4l2_ctrl *ctrl; + struct v4l2_ctrl *gop_size = NULL; + struct v4l2_ctrl *bframes = NULL; + struct v4l2_ctrl *max_layer = NULL; + struct v4l2_ctrl *frame_t = NULL; struct hfi_intra_period intra_period; + struct hfi_adaptive_p_b_intra_period adaptive_p_b_intra_period; + u32 codec; + bool adaptive_bframes = false; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); @@ -2460,38 +2467,78 @@ int msm_venc_set_intra_period(struct msm_vidc_inst *inst) } hdev = inst->core->device; - msm_venc_adjust_gop_size(inst); + frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE); + gop_size = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE); + max_layer = get_ctrl(inst, + V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); + codec = get_v4l2_codec(inst); - ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE); - intra_period.pframes = ctrl->val; + if (!max_layer->val && codec == V4L2_PIX_FMT_H264) { + intra_period.pframes = gop_size->val; + /* + * At this point we've already made decision on bframe. + * Control value gives updated bframe value. + */ + bframes = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES); + intra_period.bframes = bframes->val; + if (intra_period.bframes) + adaptive_bframes = true; + } - /* - * At this point we have already made decision on bframe - * Control value gives updated bframe value. - */ - ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES); - intra_period.bframes = ctrl->val; + if (max_layer->val > 1) { + if (frame_t->val == + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) { + if (codec == V4L2_PIX_FMT_HEVC) { + adaptive_p_b_intra_period.nframes = + gop_size->val; + adaptive_bframes = true; + } else { + d_vpr_e("%s: Hier-B supported for HEVC only\n", + __func__); + return -EINVAL; + } + } else if (frame_t->val == + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) { + msm_venc_adjust_gop_size(inst); + intra_period.pframes = gop_size->val; + intra_period.bframes = 0; + adaptive_bframes = false; + } + } if (inst->state == MSM_VIDC_START_DONE && - !intra_period.pframes && !intra_period.bframes) { + !intra_period.pframes && !intra_period.bframes) { s_vpr_h(inst->sid, "%s: Switch from IPPP to All Intra is not allowed\n", __func__); return rc; } - s_vpr_h(inst->sid, "%s: %d %d\n", __func__, intra_period.pframes, - intra_period.bframes); - rc = call_hfi_op(hdev, session_set_property, inst->session, - HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD, &intra_period, - sizeof(intra_period)); + if (frame_t->val == + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B && + codec == V4L2_PIX_FMT_HEVC) { + s_vpr_h(inst->sid, "%s: nframes: %d\n", + __func__, adaptive_p_b_intra_period.nframes); + rc = call_hfi_op(hdev, session_set_property, inst->session, + HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD, + &adaptive_p_b_intra_period, + sizeof(adaptive_p_b_intra_period)); + + } else { + s_vpr_h(inst->sid, "%s: pframes: %d bframes: %d\n", + __func__, intra_period.pframes, + intra_period.bframes); + rc = call_hfi_op(hdev, session_set_property, inst->session, + HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD, + &intra_period, sizeof(intra_period)); + } + if (rc) { s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } - if (intra_period.bframes) { - /* Enable adaptive bframes as nbframes!= 0 */ + if (adaptive_bframes) { rc = msm_venc_set_adaptive_bframes(inst); if (rc) { s_vpr_e(inst->sid, "%s: set property failed\n", @@ -2499,6 +2546,7 @@ int msm_venc_set_intra_period(struct msm_vidc_inst *inst) return rc; } } + return rc; } @@ -2764,14 +2812,14 @@ int msm_venc_set_layer_bitrate(struct msm_vidc_inst *inst) if (!max_layer->val || !layer->val) { s_vpr_h(inst->sid, - "%s: Hierp layer not set. Ignore layer bitrate\n", + "%s: Hier-P layer not set. Ignore layer bitrate\n", __func__); goto error; } if (max_layer->val < layer->val) { s_vpr_h(inst->sid, - "%s: Hierp layer greater than max isn't allowed\n", + "%s: Hier-P layer greater than max isn't allowed\n", __func__); goto error; } @@ -3611,7 +3659,7 @@ int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst) max_layer = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); if (max_layer->val <= 0) { - s_vpr_h(inst->sid, "%s: Layer id can only be set with Hierp\n", + s_vpr_h(inst->sid, "%s: Layer id can only be set with Hier-P\n", __func__); return 0; } @@ -3629,11 +3677,54 @@ int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst) return rc; } +int msm_venc_set_hb_max_layer(struct msm_vidc_inst *inst) +{ + int rc = 0; + struct hfi_device *hdev; + struct v4l2_ctrl *frame_t = NULL; + struct v4l2_ctrl *max_layer = NULL; + u32 hb_layer = 0; + u32 codec; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params %pK\n", __func__, inst); + return -EINVAL; + } + hdev = inst->core->device; + + codec = get_v4l2_codec(inst); + if (codec != V4L2_PIX_FMT_HEVC) + return 0; + + max_layer = get_ctrl(inst, + V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); + frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE); + if (max_layer->val < 2 || + frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) { + s_vpr_h(inst->sid, + "%s: Hier-B not requested for this session\n", + __func__); + return 0; + } + hb_layer = max_layer->val - 1; + + s_vpr_h(inst->sid, "%s: Hier-B max layer: %d\n", + __func__, hb_layer); + rc = call_hfi_op(hdev, session_set_property, inst->session, + HFI_PROPERTY_PARAM_VENC_HIER_B_MAX_NUM_ENH_LAYER, + &hb_layer, sizeof(hb_layer)); + if (rc) + s_vpr_e(inst->sid, "%s: set property failed\n", __func__); + + return rc; +} + int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; - struct v4l2_ctrl *ctrl; + struct v4l2_ctrl *frame_t = NULL; + struct v4l2_ctrl *max_layer = NULL; u32 hp_layer = 0; u32 codec; @@ -3647,12 +3738,20 @@ int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst) if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC) return 0; - ctrl = get_ctrl(inst, + max_layer = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); + frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE); + if (max_layer->val < 2 || + frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) { + s_vpr_h(inst->sid, + "%s: Hier-P not requested for this session\n", + __func__); + return 0; + } rc = msm_venc_enable_hybrid_hp(inst); if (rc) { - s_vpr_e(inst->sid, "%s: get hybrid hp decision failed\n", + s_vpr_e(inst->sid, "%s: get hybrid hier-P decision failed\n", __func__); return rc; } @@ -3661,17 +3760,17 @@ int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst) * We send enhancement layer count to FW, * hence, input 0/1 indicates absence of layer encoding. */ - if (ctrl->val) - hp_layer = ctrl->val - 1; + if (max_layer->val) + hp_layer = max_layer->val - 1; if (inst->hybrid_hp) { - s_vpr_h(inst->sid, "%s: Hybrid hierp layer: %d\n", + s_vpr_h(inst->sid, "%s: Hybrid hier-P layer: %d\n", __func__, hp_layer); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VENC_HIER_P_HYBRID_MODE, &hp_layer, sizeof(hp_layer)); } else { - s_vpr_h(inst->sid, "%s: Hierp max layer: %d\n", + s_vpr_h(inst->sid, "%s: Hier-P max layer: %d\n", __func__, hp_layer); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER, @@ -3686,6 +3785,7 @@ int msm_venc_set_hp_layer(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; + struct v4l2_ctrl *frame_t = NULL; struct v4l2_ctrl *ctrl = NULL; struct v4l2_ctrl *max_layer = NULL; u32 hp_layer = 0; @@ -3697,6 +3797,14 @@ int msm_venc_set_hp_layer(struct msm_vidc_inst *inst) } hdev = inst->core->device; + frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE); + if (frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) { + s_vpr_h(inst->sid, + "%s: Hier-P layer can be set for P type frame only\n", + __func__); + return 0; + } + codec = get_v4l2_codec(inst); if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC) return 0; @@ -3728,7 +3836,7 @@ int msm_venc_set_hp_layer(struct msm_vidc_inst *inst) if (ctrl->val) hp_layer = ctrl->val - 1; - s_vpr_h(inst->sid, "%s: Hierp enhancement layer: %d\n", + s_vpr_h(inst->sid, "%s: Hier-P enhancement layer: %d\n", __func__, hp_layer); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER, @@ -4735,6 +4843,9 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst) if (rc) goto exit; rc = msm_venc_set_ltr_mode(inst); + if (rc) + goto exit; + rc = msm_venc_set_hb_max_layer(inst); if (rc) goto exit; rc = msm_venc_set_hp_max_layer(inst); diff --git a/msm/vidc/msm_venc.h b/msm/vidc/msm_venc.h index bb5a651f3da9..4f5689fe50d1 100644 --- a/msm/vidc/msm_venc.h +++ b/msm/vidc/msm_venc.h @@ -35,6 +35,7 @@ int msm_venc_set_ltr_markframe(struct msm_vidc_inst *inst); int msm_venc_set_dyn_qp(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl); int msm_venc_set_request_keyframe(struct msm_vidc_inst *inst); int msm_venc_set_intra_refresh_mode(struct msm_vidc_inst *inst); +int msm_venc_set_hb_max_layer(struct msm_vidc_inst *inst); int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst); int msm_venc_set_hp_layer(struct msm_vidc_inst *inst); int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst); diff --git a/msm/vidc/msm_vidc_buffer_calculations.c b/msm/vidc/msm_vidc_buffer_calculations.c index d9ef661314db..63ed34ed17f8 100644 --- a/msm/vidc/msm_vidc_buffer_calculations.c +++ b/msm/vidc/msm_vidc_buffer_calculations.c @@ -465,10 +465,11 @@ int msm_vidc_get_decoder_internal_buffer_sizes(struct msm_vidc_inst *inst) int msm_vidc_get_num_ref_frames(struct msm_vidc_inst *inst) { int num_ref = 1; - int num_bframes = -1, ltr_count = -1, num_hp_layers; - struct v4l2_ctrl *bframe_ctrl; - struct v4l2_ctrl *ltr_ctrl; - struct v4l2_ctrl *layer_ctrl; + int num_bframes = -1, ltr_count = -1; + struct v4l2_ctrl *bframe_ctrl = NULL; + struct v4l2_ctrl *ltr_ctrl = NULL; + struct v4l2_ctrl *frame_t = NULL; + struct v4l2_ctrl *max_layer = NULL; u32 codec; bframe_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES); @@ -482,21 +483,27 @@ int msm_vidc_get_num_ref_frames(struct msm_vidc_inst *inst) if (ltr_count > 0) num_ref = num_ref + ltr_count; - layer_ctrl = get_ctrl(inst, + frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE); + max_layer = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); - num_hp_layers = layer_ctrl->val; - codec = get_v4l2_codec(inst); - if (num_hp_layers > 0) { + if (frame_t->val == V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P && + max_layer->val > 0) { + codec = get_v4l2_codec(inst); /* LTR and B - frame not supported with hybrid HP */ if (inst->hybrid_hp) - num_ref = (num_hp_layers - 1); + num_ref = (max_layer->val - 1); else if (codec == V4L2_PIX_FMT_HEVC) - num_ref = ((num_hp_layers + 1) / 2) + ltr_count; - else if ((codec == V4L2_PIX_FMT_H264) && (num_hp_layers <= 4)) - num_ref = ((1 << (num_hp_layers - 1)) - 1) + ltr_count; + num_ref = ((max_layer->val + 1) / 2) + ltr_count; + else if ((codec == V4L2_PIX_FMT_H264) && (max_layer->val <= 4)) + num_ref = ((1 << (max_layer->val - 1)) - 1) + ltr_count; else - num_ref = ((num_hp_layers + 1) / 2) + ltr_count; + num_ref = ((max_layer->val + 1) / 2) + ltr_count; } + + if (is_hier_b_session(inst)) { + num_ref = (1 << (max_layer->val - 1)) / 2 + 1; + } + return num_ref; } @@ -626,6 +633,7 @@ int msm_vidc_calculate_input_buffer_count(struct msm_vidc_inst *inst) { struct msm_vidc_format *fmt; int extra_buff_count = 0; + struct v4l2_ctrl *max_layer = NULL; if (!inst) { d_vpr_e("%s: invalid params\n", __func__); @@ -655,6 +663,13 @@ int msm_vidc_calculate_input_buffer_count(struct msm_vidc_inst *inst) extra_buff_count = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT); fmt->count_min = MIN_INPUT_BUFFERS; + + if (is_hier_b_session(inst)) { + max_layer = get_ctrl(inst, + V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); + fmt->count_min = (1 << (max_layer->val - 1)) + 2; + } + fmt->count_min_host = fmt->count_actual = fmt->count_min + extra_buff_count; diff --git a/msm/vidc/msm_vidc_common.h b/msm/vidc/msm_vidc_common.h index 806a8edb3dbd..98287b8570e7 100644 --- a/msm/vidc/msm_vidc_common.h +++ b/msm/vidc/msm_vidc_common.h @@ -190,6 +190,25 @@ static inline bool is_internal_buffer(enum hal_buffer type) return !!(buf_type & type); } +static inline bool is_hier_b_session(struct msm_vidc_inst *inst) +{ + struct v4l2_ctrl *max_layer = NULL; + struct v4l2_ctrl *frame_t = NULL; + + if (inst->session_type == MSM_VIDC_ENCODER) { + max_layer = get_ctrl(inst, + V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); + frame_t = get_ctrl(inst, + V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE); + if (get_v4l2_codec(inst) == V4L2_PIX_FMT_HEVC && + max_layer->val > 1 && + frame_t->val == + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) + return true; + } + return false; +} + static inline int msm_comm_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl) { diff --git a/msm/vidc/vidc_hfi_helper.h b/msm/vidc/vidc_hfi_helper.h index accdcdff8a16..65e1f0e486e3 100644 --- a/msm/vidc/vidc_hfi_helper.h +++ b/msm/vidc/vidc_hfi_helper.h @@ -541,6 +541,10 @@ struct hfi_intra_period { u32 bframes; }; +struct hfi_adaptive_p_b_intra_period { + u32 nframes; +}; + struct hfi_multi_stream { u32 buffer_type; u32 enable;