diff --git a/include/uapi/vidc/media/msm_vidc_utils.h b/include/uapi/vidc/media/msm_vidc_utils.h index 2e4f351c4927..a20d4816841a 100644 --- a/include/uapi/vidc/media/msm_vidc_utils.h +++ b/include/uapi/vidc/media/msm_vidc_utils.h @@ -252,6 +252,8 @@ enum v4l2_mpeg_vidc_video_bitrate_savings_type { (V4L2_CID_MPEG_MSM_VIDC_BASE + 132) #define V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_HINT \ (V4L2_CID_MPEG_MSM_VIDC_BASE + 133) +#define V4L2_CID_MPEG_VIDC_VDEC_HEIF_MODE \ + (V4L2_CID_MPEG_MSM_VIDC_BASE + 134) #define V4L2_CID_MPEG_VIDC_VIDEO_UNKNOWN \ (V4L2_CID_MPEG_MSM_VIDC_BASE + 0xFFF) diff --git a/msm/vidc/msm_vdec.c b/msm/vidc/msm_vdec.c index 685f56e6c17b..5a2b8a348978 100644 --- a/msm/vidc/msm_vdec.c +++ b/msm/vidc/msm_vdec.c @@ -434,6 +434,15 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = { .default_value = 0, .step = 1, }, + { + .id = V4L2_CID_MPEG_VIDC_VDEC_HEIF_MODE, + .name = "HEIF Decoder", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .minimum = V4L2_MPEG_MSM_VIDC_DISABLE, + .maximum = V4L2_MPEG_MSM_VIDC_ENABLE, + .default_value = V4L2_MPEG_MSM_VIDC_DISABLE, + .step = 1, + }, }; #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls) @@ -948,6 +957,15 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) break; case V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_HINT: break; + case V4L2_CID_MPEG_VIDC_VDEC_HEIF_MODE: + if(get_v4l2_codec(inst) != V4L2_PIX_FMT_HEVC) + break; + inst->flags &= ~VIDC_TURBO; + if (ctrl->val) + inst->flags |= VIDC_TURBO; + if (inst->state < MSM_VIDC_LOAD_RESOURCES) + msm_vidc_calculate_buffer_counts(inst); + break; default: s_vpr_e(inst->sid, "Unknown control %#x\n", ctrl->id); break; diff --git a/msm/vidc/msm_vidc.c b/msm/vidc/msm_vidc.c index 7f78071d585d..499abc4f5ad8 100644 --- a/msm/vidc/msm_vidc.c +++ b/msm/vidc/msm_vidc.c @@ -432,7 +432,8 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev, timestamp_us = (s64)((b->timestamp.tv_sec * 1000000) + b->timestamp.tv_usec); - if (is_decode_session(inst) && b->type == INPUT_MPLANE) { + if (is_decode_session(inst) && b->type == INPUT_MPLANE && + !is_heif_decoder(inst)) { if (inst->flush_timestamps) msm_comm_release_timestamps(inst); inst->flush_timestamps = false; @@ -513,7 +514,8 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b) } if (is_decode_session(inst) && b->type == OUTPUT_MPLANE && - !(b->flags & V4L2_BUF_FLAG_CODECCONFIG)) + !(b->flags & V4L2_BUF_FLAG_CODECCONFIG) && + !is_heif_decoder(inst)) msm_comm_fetch_ts_framerate(inst, b); return rc; diff --git a/msm/vidc/msm_vidc_buffer_calculations.c b/msm/vidc/msm_vidc_buffer_calculations.c index 03079a37ee35..4b1a2bd287d9 100644 --- a/msm/vidc/msm_vidc_buffer_calculations.c +++ b/msm/vidc/msm_vidc_buffer_calculations.c @@ -27,6 +27,10 @@ /* extra output buffers for encoder HEIF usecase */ #define HEIF_ENC_TOTAL_OUTPUT_BUFFERS 12 +/* extra buffer count for heif decoder */ +#define HEIF_DEC_TOTAL_INPUT_BUFFERS 12 +#define HEIF_DEC_EXTRA_OUTPUT_BUFFERS 8 + #define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_WIDTH 32 #define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_HEIGHT 8 #define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_WIDTH 16 @@ -789,6 +793,9 @@ static int msm_vidc_get_extra_input_buff_count(struct msm_vidc_inst *inst) core = inst->core; + if (is_heif_decoder(inst)) + return (HEIF_DEC_TOTAL_INPUT_BUFFERS - MIN_INPUT_BUFFERS); + /* * For thumbnail session, extra buffers are not required as * neither dcvs nor batching will be enabled. @@ -821,6 +828,9 @@ static int msm_vidc_get_extra_output_buff_count(struct msm_vidc_inst *inst) core = inst->core; + if (is_heif_decoder(inst)) + return HEIF_DEC_EXTRA_OUTPUT_BUFFERS; + /* * For a non-realtime session, extra buffers are not required. * For thumbnail session, extra buffers are not required as @@ -829,7 +839,7 @@ static int msm_vidc_get_extra_output_buff_count(struct msm_vidc_inst *inst) if (!is_realtime_session(inst) || is_thumbnail_session(inst)) return extra_output_count; - /* For HEIF, we are increasing buffer count */ + /* For HEIF encoder, we are increasing buffer count */ if (is_image_session(inst)) { extra_output_count = (HEIF_ENC_TOTAL_OUTPUT_BUFFERS - MIN_ENC_OUTPUT_BUFFERS); @@ -889,6 +899,11 @@ u32 msm_vidc_calculate_dec_input_frame_size(struct msm_vidc_inst *inst) base_res_mbs = inst->capability.cap[CAP_MBS_PER_FRAME].max; div_factor = 1; } + /* For HEIF image, use the actual resolution to calc buffer size */ + if (is_heif_decoder(inst)) { + base_res_mbs = num_mbs; + div_factor = 1; + } frame_size = base_res_mbs * MB_SIZE_IN_PIXEL * 3 / 2 / div_factor; diff --git a/msm/vidc/msm_vidc_clocks.c b/msm/vidc/msm_vidc_clocks.c index 0af709fe2d36..64b5f95408f9 100644 --- a/msm/vidc/msm_vidc_clocks.c +++ b/msm/vidc/msm_vidc_clocks.c @@ -1293,6 +1293,7 @@ int msm_vidc_set_bse_vpp_delay(struct msm_vidc_inst *inst) if (!inst->core->resources.has_vpp_delay || !is_decode_session(inst) || is_thumbnail_session(inst) || + is_heif_decoder(inst) || inst->clk_data.work_mode != HFI_WORKMODE_2) { s_vpr_hp(inst->sid, "%s: Skip bse-vpp\n", __func__); return 0; diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index 652334c646c4..0cab94351d95 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -2839,6 +2839,7 @@ bool is_batching_allowed(struct msm_vidc_inst *inst) is_decode_session(inst) && !is_thumbnail_session(inst) && is_realtime_session(inst) && + !is_heif_decoder(inst) && !inst->clk_data.low_latency_mode && (op_pixelformat == V4L2_PIX_FMT_NV12_UBWC || op_pixelformat == V4L2_PIX_FMT_NV12_TP10_UBWC) && diff --git a/msm/vidc/msm_vidc_common.h b/msm/vidc/msm_vidc_common.h index e46c5bbd9f62..24a04dd0a257 100644 --- a/msm/vidc/msm_vidc_common.h +++ b/msm/vidc/msm_vidc_common.h @@ -121,6 +121,17 @@ static inline bool is_grid_session(struct msm_vidc_inst *inst) return 0; } +static inline bool is_heif_decoder(struct msm_vidc_inst *inst) +{ + struct v4l2_ctrl *ctrl = NULL; + if (inst->session_type == MSM_VIDC_DECODER && + get_v4l2_codec(inst) == V4L2_PIX_FMT_HEVC) { + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VDEC_HEIF_MODE); + return (ctrl->val > 0); + } + return 0; +} + static inline bool is_video_session(struct msm_vidc_inst *inst) { return !is_grid_session(inst);