From 61344c1970fc87448f563213e081fb28fce14758 Mon Sep 17 00:00:00 2001 From: Amit Shekhar Date: Tue, 16 Jul 2019 11:33:44 -0700 Subject: [PATCH] msm: vidc: Check image encode capabilities For heic/hevc image session, check respective capabilities to allow or reject. Change-Id: I4e565e6614a7863f75ecd4719480b850e1af43ae Signed-off-by: Amit Shekhar --- msm/vidc/msm_venc.c | 144 +++++++++++++++++++---------------- msm/vidc/msm_vidc.c | 12 --- msm/vidc/msm_vidc_clocks.c | 3 +- msm/vidc/msm_vidc_common.c | 99 +++++++++++++----------- msm/vidc/msm_vidc_common.h | 8 ++ msm/vidc/msm_vidc_internal.h | 3 - msm/vidc/msm_vidc_platform.c | 6 ++ msm/vidc/vidc_hfi_api.h | 4 + 8 files changed, 150 insertions(+), 129 deletions(-) diff --git a/msm/vidc/msm_venc.c b/msm/vidc/msm_venc.c index 0eb3b1671076..9359d2f20ae8 100644 --- a/msm/vidc/msm_venc.c +++ b/msm/vidc/msm_venc.c @@ -1506,12 +1506,6 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) "%s: set bitrate mode failed\n", __func__); break; } - case V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY: - inst->frame_quality = ctrl->val; - break; - case V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE: - inst->grid_enable = ctrl->val; - break; case V4L2_CID_MPEG_VIDEO_BITRATE: inst->clk_data.bitrate = ctrl->val; if (inst->state == MSM_VIDC_START_DONE) { @@ -1774,6 +1768,8 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) __func__); } break; + case V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY: + case V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE: case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER: case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE: case V4L2_CID_ROTATE: @@ -2800,12 +2796,74 @@ int msm_venc_set_qp_range(struct msm_vidc_inst *inst) return rc; } -int msm_venc_set_frame_quality(struct msm_vidc_inst *inst) +static void set_all_intra_preconditions(struct msm_vidc_inst *inst) +{ + struct v4l2_ctrl *ctrl = NULL, *ctrl_t = NULL; + + /* Disable multi slice */ + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE); + if (ctrl->val) { + dprintk(VIDC_HIGH, "Disable multi slice for all intra\n"); + ctrl->val = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + } + + /* Disable LTR */ + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT); + if (ctrl->val) { + dprintk(VIDC_HIGH, "Disable LTR for all intra\n"); + ctrl->val = 0; + } + + /* Disable Layer encoding */ + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER); + ctrl_t = get_ctrl(inst, + V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); + if (ctrl->val || ctrl_t->val) { + dprintk(VIDC_HIGH, "Disable layer encoding for all intra\n"); + ctrl->val = 0; + ctrl_t->val = 0; + } + + /* Disable IR */ + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM); + ctrl_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB); + if (ctrl->val || ctrl_t->val) { + dprintk(VIDC_HIGH, "Disable IR for all intra\n"); + ctrl->val = 0; + ctrl_t->val = 0; + } + + return; +} + +static void set_heif_preconditions(struct msm_vidc_inst *inst) +{ + struct v4l2_ctrl *ctrl = NULL; + + /* Reset PFrames */ + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE); + if (ctrl->val) { + dprintk(VIDC_HIGH, "Reset P-frame count for HEIF\n"); + ctrl->val = 0; + } + + /* Reset BFrames */ + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES); + if (ctrl->val) { + dprintk(VIDC_HIGH, "Reset B-frame count for HEIF\n"); + ctrl->val = 0; + } + + return; +} + +int msm_venc_set_image_properties(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct v4l2_ctrl *ctrl; struct hfi_heic_frame_quality frame_quality; + struct hfi_heic_grid_enable grid_enable; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); @@ -2819,31 +2877,13 @@ int msm_venc_set_frame_quality(struct msm_vidc_inst *inst) ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY); frame_quality.frame_quality = ctrl->val; - dprintk(VIDC_HIGH, "%s: %d\n", __func__, frame_quality.frame_quality); + dprintk(VIDC_HIGH, "%s: frame quality: %d\n", __func__, + frame_quality.frame_quality); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY, &frame_quality, sizeof(frame_quality)); if (rc) - dprintk(VIDC_ERR, "%s: set property failed\n", __func__); - - return rc; -} - -int msm_venc_set_grid(struct msm_vidc_inst *inst) -{ - int rc = 0; - struct hfi_device *hdev; - struct v4l2_ctrl *ctrl; - struct hfi_heic_grid_enable grid_enable; - - if (!inst || !inst->core) { - dprintk(VIDC_ERR, "%s: invalid params\n", __func__); - return -EINVAL; - } - hdev = inst->core->device; - - if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) - return 0; + dprintk(VIDC_ERR, "%s: set frame quality failed\n", __func__); ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE); @@ -2853,12 +2893,16 @@ int msm_venc_set_grid(struct msm_vidc_inst *inst) else grid_enable.grid_enable = true; - dprintk(VIDC_HIGH, "%s: %d\n", __func__, grid_enable.grid_enable); + dprintk(VIDC_HIGH, "%s: grid enable: %d\n", __func__, + grid_enable.grid_enable); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_CONFIG_HEIC_GRID_ENABLE, &grid_enable, sizeof(grid_enable)); if (rc) - dprintk(VIDC_ERR, "%s: set property failed\n", __func__); + dprintk(VIDC_ERR, "%s: set grid enable failed\n", __func__); + + set_all_intra_preconditions(inst); + set_heif_preconditions(inst); return rc; } @@ -4020,7 +4064,7 @@ int msm_venc_set_lossless(struct msm_vidc_inst *inst) int handle_all_intra_restrictions(struct msm_vidc_inst *inst) { - struct v4l2_ctrl *ctrl, *ctrl_t; + struct v4l2_ctrl *ctrl = NULL; u32 n_fps, fps_max; struct msm_vidc_capability *capability; struct v4l2_format *f; @@ -4071,38 +4115,7 @@ int handle_all_intra_restrictions(struct msm_vidc_inst *inst) return -ENOTSUPP; } - /* Disable multi slice */ - ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE); - if (ctrl->val) { - dprintk(VIDC_HIGH, "Disable multi slice for all intra\n"); - ctrl->val = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; - } - - /* Disable LTR */ - ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT); - if (ctrl->val) { - dprintk(VIDC_HIGH, "Disable LTR for all intra\n"); - ctrl->val = 0; - } - - /* Disable Layer encoding */ - ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER); - ctrl_t = get_ctrl(inst, - V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER); - if (ctrl->val || ctrl_t->val) { - dprintk(VIDC_HIGH, "Disable layer encoding for all intra\n"); - ctrl->val = 0; - ctrl_t->val = 0; - } - - /* Disable IR */ - ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM); - ctrl_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB); - if (ctrl->val || ctrl_t->val) { - dprintk(VIDC_HIGH, "Disable IR for all intra\n"); - ctrl->val = 0; - ctrl_t->val = 0; - } + set_all_intra_preconditions(inst); return 0; } @@ -4162,10 +4175,7 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst) rc = msm_venc_set_qp_range(inst); if (rc) goto exit; - rc = msm_venc_set_frame_quality(inst); - if (rc) - goto exit; - rc = msm_venc_set_grid(inst); + rc = msm_venc_set_image_properties(inst); if (rc) goto exit; rc = msm_venc_set_au_delimiter_mode(inst); diff --git a/msm/vidc/msm_vidc.c b/msm/vidc/msm_vidc.c index 99105eb9fc5f..088894140e43 100644 --- a/msm/vidc/msm_vidc.c +++ b/msm/vidc/msm_vidc.c @@ -826,15 +826,6 @@ static inline int start_streaming(struct msm_vidc_inst *inst) is_secondary_output_mode(inst)) b.buffer_type = HFI_BUFFER_OUTPUT2; - /* HEIC HW/FWK tiling encode is supported only for CQ RC mode */ - if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) { - if (!heic_encode_session_supported(inst)) { - dprintk(VIDC_ERR, - "HEIC Encode session not supported\n"); - return -ENOTSUPP; - } - } - /* Check if current session is under HW capability */ rc = msm_vidc_check_session_supported(inst); if (rc) { @@ -1440,9 +1431,6 @@ static int try_get_ctrl_for_instance(struct msm_vidc_inst *inst, V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, inst->profile); break; - case V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE: - ctrl->val = inst->grid_enable; - break; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: ctrl->val = msm_comm_hfi_to_v4l2( V4L2_CID_MPEG_VIDEO_H264_LEVEL, diff --git a/msm/vidc/msm_vidc_clocks.c b/msm/vidc/msm_vidc_clocks.c index ab6b96871e55..5b7a9688d102 100644 --- a/msm/vidc/msm_vidc_clocks.c +++ b/msm/vidc/msm_vidc_clocks.c @@ -1069,8 +1069,7 @@ int msm_dcvs_try_enable(struct msm_vidc_inst *inst) inst->flags & VIDC_THUMBNAIL || inst->clk_data.low_latency_mode || inst->batch.enable || - inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ || - inst->grid_enable) { + inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) { dprintk(VIDC_HIGH, "DCVS disabled: %pK\n", inst); inst->clk_data.dcvs_mode = false; return false; diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index 307852e4327f..b9374abe24f6 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -2387,48 +2387,6 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst, return 0; } -bool heic_encode_session_supported(struct msm_vidc_inst *inst) -{ - u32 slice_mode; - u32 idr_period = IDR_PERIOD; - u32 n_bframes; - u32 n_pframes; - struct v4l2_format *f; - - slice_mode = msm_comm_g_ctrl_for_id(inst, - V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE); - n_bframes = msm_comm_g_ctrl_for_id(inst, - V4L2_CID_MPEG_VIDEO_B_FRAMES); - n_pframes = msm_comm_g_ctrl_for_id(inst, - V4L2_CID_MPEG_VIDEO_GOP_SIZE); - - /* - * HEIC Encode is supported for Constant Quality RC mode only. - * All configurations below except grid_enable are required for any - * HEIC session including FWK tiled HEIC encode. - * grid_enable flag along with dimension check enables HW tiling. - */ - f = &inst->fmts[OUTPUT_PORT].v4l2_fmt; - if (inst->session_type == MSM_VIDC_ENCODER && - get_hal_codec(f->fmt.pix_mp.pixelformat) == - HAL_VIDEO_CODEC_HEVC && - inst->frame_quality >= MIN_FRAME_QUALITY && - inst->frame_quality <= MAX_FRAME_QUALITY && - slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE && - idr_period == 1 && - n_bframes == 0 && - n_pframes == 0) { - if (inst->grid_enable > 0) { - if (f->fmt.pix_mp.width < HEIC_GRID_DIMENSION || - f->fmt.pix_mp.height < HEIC_GRID_DIMENSION) - return false; - } - return true; - } else { - return false; - } -} - static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr) { struct eos_buf *temp, *next; @@ -5585,6 +5543,9 @@ static int msm_vidc_check_mbpf_supported(struct msm_vidc_inst *inst) /* ignore thumbnail session */ if (is_thumbnail_session(temp)) continue; + /* ignore HEIF sessions */ + if (is_image_session(temp)) + continue; mbpf += NUM_MBS_PER_FRAME( temp->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.height, temp->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.width); @@ -5629,10 +5590,15 @@ int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst) u32 x_min, x_max, y_min, y_max; u32 input_height, input_width, output_height, output_width; struct v4l2_format *f; + struct v4l2_ctrl *ctrl = NULL; - if (inst->grid_enable > 0) { - dprintk(VIDC_HIGH, "Skip scaling check for HEIC\n"); - return 0; + /* Grid get_ctrl allowed for encode session only */ + if (is_image_session(inst)) { + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE); + if (ctrl->val > 0) { + dprintk(VIDC_HIGH, "Skip scaling check for HEIC\n"); + return 0; + } } f = &inst->fmts[INPUT_PORT].v4l2_fmt; @@ -5719,6 +5685,7 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst) u32 width_min, width_max, height_min, height_max; u32 mbpf_max; struct v4l2_format *f; + struct v4l2_ctrl *ctrl = NULL; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s: Invalid parameter\n", __func__); @@ -5774,6 +5741,48 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst) input_height = f->fmt.pix_mp.height; input_width = f->fmt.pix_mp.width; + if (is_image_session(inst)) { + if (is_secure_session(inst)) { + dprintk(VIDC_ERR, + "Secure image encode isn't supported!\n"); + return -ENOTSUPP; + } + + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE); + if (ctrl->val > 0) { + if (inst->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.pixelformat != + V4L2_PIX_FMT_NV12 && + inst->fmts[INPUT_PORT].v4l2_fmt.fmt.pix_mp.pixelformat != + V4L2_PIX_FMT_NV12_512) + return -ENOTSUPP; + + width_min = + capability->cap[CAP_HEIC_IMAGE_FRAME_WIDTH].min; + width_max = + capability->cap[CAP_HEIC_IMAGE_FRAME_WIDTH].max; + height_min = + capability->cap[CAP_HEIC_IMAGE_FRAME_HEIGHT].min; + height_max = + capability->cap[CAP_HEIC_IMAGE_FRAME_HEIGHT].max; + mbpf_max = capability->cap[CAP_MBS_PER_FRAME].max; + + input_height = ALIGN(input_height, 512); + input_width = ALIGN(input_width, 512); + output_height = input_height; + output_width = input_width; + } else { + width_min = + capability->cap[CAP_HEVC_IMAGE_FRAME_WIDTH].min; + width_max = + capability->cap[CAP_HEVC_IMAGE_FRAME_WIDTH].max; + height_min = + capability->cap[CAP_HEVC_IMAGE_FRAME_HEIGHT].min; + height_max = + capability->cap[CAP_HEVC_IMAGE_FRAME_HEIGHT].max; + mbpf_max = capability->cap[CAP_MBS_PER_FRAME].max; + } + } + if (inst->session_type == MSM_VIDC_ENCODER && (input_width % 2 != 0 || input_height % 2 != 0 || output_width % 2 != 0 || output_height % 2 != 0)) { diff --git a/msm/vidc/msm_vidc_common.h b/msm/vidc/msm_vidc_common.h index a91208c1ed42..29b2348563e0 100644 --- a/msm/vidc/msm_vidc_common.h +++ b/msm/vidc/msm_vidc_common.h @@ -84,6 +84,14 @@ static inline u32 get_v4l2_codec(struct msm_vidc_inst *inst) return f->fmt.pix_mp.pixelformat; } +static inline bool is_image_session(struct msm_vidc_inst *inst) +{ + /* Grid may or may not be enabled for an image encode session */ + return inst->session_type == MSM_VIDC_ENCODER && + get_v4l2_codec(inst) == V4L2_PIX_FMT_HEVC && + inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ; +} + static inline bool is_realtime_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_REALTIME); diff --git a/msm/vidc/msm_vidc_internal.h b/msm/vidc/msm_vidc_internal.h index 668eec7531a8..b0d9610849c7 100644 --- a/msm/vidc/msm_vidc_internal.h +++ b/msm/vidc/msm_vidc_internal.h @@ -520,8 +520,6 @@ struct msm_vidc_inst { u32 colour_space; u32 profile; u32 level; - u32 grid_enable; - u32 frame_quality; u32 rc_type; u32 hybrid_hp; u32 layer_bitrate; @@ -560,7 +558,6 @@ void handle_cmd_response(enum hal_command_response cmd, void *data); int msm_vidc_trigger_ssr(struct msm_vidc_core *core, enum hal_ssr_trigger_type type); int msm_vidc_noc_error_info(struct msm_vidc_core *core); -bool heic_encode_session_supported(struct msm_vidc_inst *inst); int msm_vidc_check_session_supported(struct msm_vidc_inst *inst); int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst); void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type); diff --git a/msm/vidc/msm_vidc_platform.c b/msm/vidc/msm_vidc_platform.c index 316950a01e80..4dd91f205b5e 100644 --- a/msm/vidc/msm_vidc_platform.c +++ b/msm/vidc/msm_vidc_platform.c @@ -359,6 +359,12 @@ static struct msm_vidc_codec_capability kona_capabilities[] = { /* All intra encoding usecase specific */ {CAP_ALLINTRA_MAX_FPS, ENC, H264|HEVC, 1, 240, 1, 30}, + + /* Image specific */ + {CAP_HEVC_IMAGE_FRAME_WIDTH, ENC, HEVC, 128, 512, 1, 512}, + {CAP_HEVC_IMAGE_FRAME_HEIGHT, ENC, HEVC, 128, 512, 1, 512}, + {CAP_HEIC_IMAGE_FRAME_WIDTH, ENC, HEVC, 512, 8192, 1, 8192}, + {CAP_HEIC_IMAGE_FRAME_HEIGHT, ENC, HEVC, 512, 8192, 1, 8192}, }; /* diff --git a/msm/vidc/vidc_hfi_api.h b/msm/vidc/vidc_hfi_api.h index 950439c026ee..ba21bbdeecc0 100644 --- a/msm/vidc/vidc_hfi_api.h +++ b/msm/vidc/vidc_hfi_api.h @@ -284,6 +284,10 @@ enum hal_capability { CAP_LOSSLESS_FRAME_HEIGHT, CAP_LOSSLESS_MBS_PER_FRAME, CAP_ALLINTRA_MAX_FPS, + CAP_HEVC_IMAGE_FRAME_WIDTH, + CAP_HEVC_IMAGE_FRAME_HEIGHT, + CAP_HEIC_IMAGE_FRAME_WIDTH, + CAP_HEIC_IMAGE_FRAME_HEIGHT, CAP_MAX, };