diff --git a/msm/vidc/msm_venc.c b/msm/vidc/msm_venc.c index 7abbad7e76be..0eb3b1671076 100644 --- a/msm/vidc/msm_venc.c +++ b/msm/vidc/msm_venc.c @@ -1477,6 +1477,12 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_GOP_SIZE: if (inst->state == MSM_VIDC_START_DONE) { + if (inst->all_intra) { + dprintk(VIDC_HIGH, + "%s: ignore dynamic gop size for all intra\n", + __func__); + break; + } rc = msm_venc_set_intra_period(inst); if (rc) dprintk(VIDC_ERR, @@ -1869,12 +1875,27 @@ int msm_venc_set_frame_rate(struct msm_vidc_inst *inst) int rc = 0; struct hfi_device *hdev; struct hfi_frame_rate frame_rate; + struct msm_vidc_capability *capability; + u32 fps_max; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } hdev = inst->core->device; + capability = &inst->capability; + + /* Check frame rate */ + if (inst->all_intra) + fps_max = capability->cap[CAP_ALLINTRA_MAX_FPS].max; + else + fps_max = capability->cap[CAP_FRAMERATE].max; + + if (inst->clk_data.frame_rate >> 16 > fps_max) { + dprintk(VIDC_ERR, "%s: Unsupported frame rate\n", + __func__); + return -ENOTSUPP; + } frame_rate.buffer_type = HFI_BUFFER_OUTPUT; frame_rate.frame_rate = inst->clk_data.frame_rate; @@ -2289,6 +2310,14 @@ int msm_venc_set_intra_period(struct msm_vidc_inst *inst) ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES); intra_period.bframes = ctrl->val; + if (inst->state == MSM_VIDC_START_DONE && + !intra_period.pframes && !intra_period.bframes) { + dprintk(VIDC_HIGH, + "%s: Switch from IPPP to All Intra is not allowed\n", + __func__); + return rc; + } + dprintk(VIDC_HIGH, "%s: %d %d\n", __func__, intra_period.pframes, intra_period.bframes); rc = call_hfi_op(hdev, session_set_property, inst->session, @@ -3989,10 +4018,102 @@ int msm_venc_set_lossless(struct msm_vidc_inst *inst) return rc; } +int handle_all_intra_restrictions(struct msm_vidc_inst *inst) +{ + struct v4l2_ctrl *ctrl, *ctrl_t; + u32 n_fps, fps_max; + struct msm_vidc_capability *capability; + struct v4l2_format *f; + enum hal_video_codec codec; + struct hfi_intra_period intra_period; + + if (!inst || !inst->core) { + dprintk(VIDC_ERR, "%s: invalid params\n", __func__); + return -EINVAL; + } + + if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) + return 0; + + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE); + intra_period.pframes = ctrl->val; + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES); + intra_period.bframes = ctrl->val; + + if (!intra_period.pframes && !intra_period.bframes) + inst->all_intra = true; + else + return 0; + + dprintk(VIDC_HIGH, "All Intra(IDRs) Encoding\n"); + /* check codec and profile */ + f = &inst->fmts[OUTPUT_PORT].v4l2_fmt; + codec = get_hal_codec(f->fmt.pix_mp.pixelformat); + if (codec != HAL_VIDEO_CODEC_HEVC && codec != HAL_VIDEO_CODEC_H264) { + dprintk(VIDC_ERR, "Unsupported codec for all intra\n"); + return -ENOTSUPP; + } + if (codec == HAL_VIDEO_CODEC_HEVC && + inst->profile == HFI_HEVC_PROFILE_MAIN10) { + dprintk(VIDC_ERR, "Unsupported HEVC profile for all intra\n"); + return -ENOTSUPP; + } + + /* check supported bit rate mode and frame rate */ + capability = &inst->capability; + n_fps = inst->clk_data.frame_rate >> 16; + fps_max = capability->cap[CAP_ALLINTRA_MAX_FPS].max; + if ((inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && + inst->rc_type != RATE_CONTROL_OFF && + inst->rc_type != RATE_CONTROL_LOSSLESS) || + n_fps > fps_max) { + dprintk(VIDC_ERR, "Unsupported bitrate mode or frame rate\n"); + 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; + } + + return 0; +} + int msm_venc_set_properties(struct msm_vidc_inst *inst) { int rc = 0; + rc = handle_all_intra_restrictions(inst); + if (rc) + goto exit; rc = msm_venc_set_frame_size(inst); if (rc) goto exit; diff --git a/msm/vidc/msm_venc.h b/msm/vidc/msm_venc.h index dd17266814f6..455bc70805b6 100644 --- a/msm/vidc/msm_venc.h +++ b/msm/vidc/msm_venc.h @@ -39,4 +39,5 @@ int msm_venc_set_hp_layer(struct msm_vidc_inst *inst); int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst); int msm_venc_set_lossless(struct msm_vidc_inst *inst); int msm_venc_set_blur_resolution(struct msm_vidc_inst *inst); +int handle_all_intra_restrictions(struct msm_vidc_inst *inst); #endif diff --git a/msm/vidc/msm_vidc.c b/msm/vidc/msm_vidc.c index 39935643c43a..99105eb9fc5f 100644 --- a/msm/vidc/msm_vidc.c +++ b/msm/vidc/msm_vidc.c @@ -1105,6 +1105,7 @@ static inline int stop_streaming(struct msm_vidc_inst *inst) dprintk(VIDC_ERR, "%s: failed to unprepare preprocess\n", __func__); + inst->all_intra = false; } msm_clock_data_reset(inst); @@ -1551,6 +1552,7 @@ void *msm_vidc_open(int core_id, int session_type) inst->smem_ops = &msm_vidc_smem_ops; inst->rc_type = RATE_CONTROL_OFF; inst->dpb_extra_binfo = NULL; + inst->all_intra = false; for (i = SESSION_MSG_INDEX(SESSION_MSG_START); i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) { diff --git a/msm/vidc/msm_vidc_clocks.c b/msm/vidc/msm_vidc_clocks.c index cab3cbd62487..d1f3bec83b44 100644 --- a/msm/vidc/msm_vidc_clocks.c +++ b/msm/vidc/msm_vidc_clocks.c @@ -1518,7 +1518,7 @@ int msm_vidc_decide_work_mode_iris2(struct msm_vidc_inst *inst) pdata.video_work_mode = HFI_WORKMODE_1; latency.enable = true; } - if (inst->rc_type == RATE_CONTROL_LOSSLESS) { + if (inst->rc_type == RATE_CONTROL_LOSSLESS || inst->all_intra) { pdata.video_work_mode = HFI_WORKMODE_2; latency.enable = false; } @@ -1738,6 +1738,7 @@ int msm_vidc_decide_core_and_power_mode_iris2(struct msm_vidc_inst *inst) if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ || inst->rc_type == RATE_CONTROL_LOSSLESS || + inst->all_intra || (mbpf <= max_hq_mbpf && mbps <= max_hq_mbps)) enable = false; diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index 0ced7f4cfb48..95b5d4870694 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -1571,6 +1571,9 @@ static void handle_session_init_done(enum hal_command_response cmd, void *data) &inst->capability.cap[CAP_LOSSLESS_FRAME_HEIGHT]); print_cap("lossless_mbs_per_frame", &inst->capability.cap[CAP_LOSSLESS_MBS_PER_FRAME]); + /* All intra encoding usecase specific */ + print_cap("all_intra_frame_rate", + &inst->capability.cap[CAP_ALLINTRA_MAX_FPS]); msm_vidc_comm_update_ctrl_limits(inst); diff --git a/msm/vidc/msm_vidc_internal.h b/msm/vidc/msm_vidc_internal.h index fec213496dff..668eec7531a8 100644 --- a/msm/vidc/msm_vidc_internal.h +++ b/msm/vidc/msm_vidc_internal.h @@ -533,6 +533,7 @@ struct msm_vidc_inst { struct delayed_work batch_work; struct msm_vidc_inst_smem_ops *smem_ops; int (*buffer_size_calculators)(struct msm_vidc_inst *inst); + bool all_intra; }; extern struct msm_vidc_drv *vidc_driver; diff --git a/msm/vidc/msm_vidc_platform.c b/msm/vidc/msm_vidc_platform.c index d9c4804f8faf..5964efac5aaf 100644 --- a/msm/vidc/msm_vidc_platform.c +++ b/msm/vidc/msm_vidc_platform.c @@ -356,6 +356,9 @@ static struct msm_vidc_codec_capability kona_capabilities[] = { {CAP_LOSSLESS_FRAME_HEIGHT, ENC, H264|HEVC, 128, 4096, 1, 1080}, /* (4096 * 2304) / 256 */ {CAP_LOSSLESS_MBS_PER_FRAME, ENC, H264|HEVC, 64, 36864, 1, 36864}, + + /* All intra encoding usecase specific */ + {CAP_ALLINTRA_MAX_FPS, ENC, H264|HEVC, 1, 240, 1, 30}, }; /* diff --git a/msm/vidc/vidc_hfi_api.h b/msm/vidc/vidc_hfi_api.h index 48097a046509..950439c026ee 100644 --- a/msm/vidc/vidc_hfi_api.h +++ b/msm/vidc/vidc_hfi_api.h @@ -283,6 +283,7 @@ enum hal_capability { CAP_LOSSLESS_FRAME_WIDTH, CAP_LOSSLESS_FRAME_HEIGHT, CAP_LOSSLESS_MBS_PER_FRAME, + CAP_ALLINTRA_MAX_FPS, CAP_MAX, };