From 15f3510a38ecef126e8fa81094887198350aeeb5 Mon Sep 17 00:00:00 2001 From: Qiwei Liu Date: Thu, 25 Jul 2019 23:49:12 +0800 Subject: [PATCH] msm: vidc: Add window based bitrate check in decoder In decoder, window based bitrate check will help identify usecases where, input bitrate exceeds hw capabilities. CRs-Fixed: 2497423 Change-Id: Ic68bd66584ed84382ba03777d39775d08278a8a0 Signed-off-by: Qiwei Liu Signed-off-by: Chinmay Sawarkar --- msm/vidc/hfi_common.c | 2 +- msm/vidc/hfi_response_handler.c | 14 +++-- msm/vidc/msm_vidc.c | 7 ++- msm/vidc/msm_vidc_clocks.c | 3 +- msm/vidc/msm_vidc_common.c | 100 ++++++++++++++++++++++++++++++-- msm/vidc/msm_vidc_common.h | 6 ++ msm/vidc/msm_vidc_debug.h | 1 + msm/vidc/msm_vidc_internal.h | 8 +++ msm/vidc/msm_vidc_platform.c | 4 ++ msm/vidc/msm_vidc_res_parse.c | 2 + msm/vidc/msm_vidc_resources.h | 1 + 11 files changed, 134 insertions(+), 14 deletions(-) diff --git a/msm/vidc/hfi_common.c b/msm/vidc/hfi_common.c index b9548a914f6c..5b6beb3fe538 100644 --- a/msm/vidc/hfi_common.c +++ b/msm/vidc/hfi_common.c @@ -2387,7 +2387,7 @@ static int venus_hfi_session_init(void *device, void *session_id, s->device = dev; s->codec = codec_type; s->domain = session_type; - dprintk(VIDC_HIGH, + dprintk(VIDC_HIGH|VIDC_PERF, "%s: inst %pK, session %pK, codec 0x%x, domain 0x%x\n", __func__, session_id, s, s->codec, s->domain); diff --git a/msm/vidc/hfi_response_handler.c b/msm/vidc/hfi_response_handler.c index b6bef94a5e11..63c25b35d5ea 100644 --- a/msm/vidc/hfi_response_handler.c +++ b/msm/vidc/hfi_response_handler.c @@ -158,7 +158,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, (struct hfi_frame_size *) data_ptr; event_notify.width = frame_sz->width; event_notify.height = frame_sz->height; - dprintk(VIDC_HIGH, "height: %d width: %d\n", + dprintk(VIDC_HIGH|VIDC_PERF, + "height: %d width: %d\n", frame_sz->height, frame_sz->width); data_ptr += sizeof(struct hfi_frame_size); @@ -173,7 +174,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, (struct hfi_profile_level *) data_ptr; event_notify.profile = profile_level->profile; event_notify.level = profile_level->level; - dprintk(VIDC_HIGH, "profile: %d level: %d\n", + dprintk(VIDC_HIGH|VIDC_PERF, + "profile: %d level: %d\n", profile_level->profile, profile_level->level); data_ptr += @@ -209,7 +211,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, MSM_VIDC_BIT_DEPTH_10; else event_notify.bit_depth = luma_bit_depth; - dprintk(VIDC_HIGH, + dprintk(VIDC_HIGH|VIDC_PERF, "bitdepth(%d), luma_bit_depth(%d), chroma_bit_depth(%d)\n", event_notify.bit_depth, luma_bit_depth, chroma_bit_depth); @@ -224,7 +226,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, pic_struct = (struct hfi_pic_struct *) data_ptr; event_notify.pic_struct = pic_struct->progressive_only; - dprintk(VIDC_HIGH, + dprintk(VIDC_HIGH|VIDC_PERF, "Progressive only flag: %d\n", pic_struct->progressive_only); data_ptr += @@ -253,7 +255,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, data_ptr = data_ptr + sizeof(u32); entropy_mode = *(u32 *)data_ptr; event_notify.entropy_mode = entropy_mode; - dprintk(VIDC_HIGH, + dprintk(VIDC_HIGH|VIDC_PERF, "Entropy Mode: 0x%x\n", entropy_mode); data_ptr += sizeof(u32); @@ -269,7 +271,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, data_ptr; event_notify.capture_buf_count = buf_req->buffer_count_min; - dprintk(VIDC_HIGH, + dprintk(VIDC_HIGH|VIDC_PERF, "Capture Count : 0x%x\n", event_notify.capture_buf_count); data_ptr += diff --git a/msm/vidc/msm_vidc.c b/msm/vidc/msm_vidc.c index 088894140e43..343d6c83db4c 100644 --- a/msm/vidc/msm_vidc.c +++ b/msm/vidc/msm_vidc.c @@ -920,7 +920,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) */ if (inst->batch.enable) inst->batch.enable = is_batching_allowed(inst); - dprintk(VIDC_HIGH, "%s: batching %s for inst %pK (%#x)\n", + dprintk(VIDC_HIGH|VIDC_PERF, "%s: batching %s for inst %pK (%#x)\n", __func__, inst->batch.enable ? "enabled" : "disabled", inst, hash32_ptr(inst->session)); @@ -1524,6 +1524,7 @@ void *msm_vidc_open(int core_id, int session_type) INIT_MSM_VIDC_LIST(&inst->eosbufs); INIT_MSM_VIDC_LIST(&inst->etb_data); INIT_MSM_VIDC_LIST(&inst->fbd_data); + INIT_MSM_VIDC_LIST(&inst->window_data); INIT_DELAYED_WORK(&inst->batch_work, msm_vidc_batch_handler); kref_init(&inst->kref); @@ -1638,6 +1639,7 @@ fail_bufq_capture: DEINIT_MSM_VIDC_LIST(&inst->input_crs); DEINIT_MSM_VIDC_LIST(&inst->etb_data); DEINIT_MSM_VIDC_LIST(&inst->fbd_data); + DEINIT_MSM_VIDC_LIST(&inst->window_data); kfree(inst); inst = NULL; @@ -1709,6 +1711,8 @@ static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst) dprintk(VIDC_ERR, "Failed to release mark_data buffers\n"); + msm_comm_release_window_data(inst); + msm_comm_release_eos_buffers(inst); if (msm_comm_release_dpb_only_buffers(inst, true)) @@ -1769,6 +1773,7 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst) DEINIT_MSM_VIDC_LIST(&inst->input_crs); DEINIT_MSM_VIDC_LIST(&inst->etb_data); DEINIT_MSM_VIDC_LIST(&inst->fbd_data); + DEINIT_MSM_VIDC_LIST(&inst->window_data); mutex_destroy(&inst->sync_lock); mutex_destroy(&inst->bufq[OUTPUT_PORT].lock); diff --git a/msm/vidc/msm_vidc_clocks.c b/msm/vidc/msm_vidc_clocks.c index 5b7a9688d102..062116a1e039 100644 --- a/msm/vidc/msm_vidc_clocks.c +++ b/msm/vidc/msm_vidc_clocks.c @@ -1780,7 +1780,7 @@ void msm_print_core_status(struct msm_vidc_core *core, u32 core_id) out_f = &inst->fmts[OUTPUT_PORT].v4l2_fmt; inp_f = &inst->fmts[INPUT_PORT].v4l2_fmt; dprintk(VIDC_PERF, - "inst %pK (%4ux%4u) to (%4ux%4u) %3u %s %s %s %s %lu\n", + "inst %pK (%4ux%4u) to (%4ux%4u) %3u %s %s %u %s %s %lu\n", inst, inp_f->fmt.pix_mp.width, inp_f->fmt.pix_mp.height, @@ -1790,6 +1790,7 @@ void msm_print_core_status(struct msm_vidc_core *core, u32 core_id) inst->session_type == MSM_VIDC_ENCODER ? "ENC" : "DEC", inst->clk_data.work_mode == HFI_WORKMODE_1 ? "WORK_MODE_1" : "WORK_MODE_2", + inst->clk_data.work_route, inst->flags & VIDC_LOW_POWER ? "LP" : "HQ", inst->flags & VIDC_REALTIME ? "RealTime" : "NonRTime", inst->clk_data.min_freq); diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index b9374abe24f6..56e56f1aff26 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -1729,6 +1729,7 @@ static void handle_event_change(enum hal_command_response cmd, void *data) inst->profile = event_notify->profile; inst->level = event_notify->level; + inst->entropy_mode = event_notify->entropy_mode; inst->prop.crop_info.left = event_notify->crop_data.left; inst->prop.crop_info.top = @@ -1795,7 +1796,7 @@ static void handle_event_change(enum hal_command_response cmd, void *data) /* decide batching as configuration changed */ if (inst->batch.enable) inst->batch.enable = is_batching_allowed(inst); - dprintk(VIDC_HIGH, "%s: %x : batching %s\n", + dprintk(VIDC_HIGH|VIDC_PERF, "%s: %x : batching %s\n", __func__, hash32_ptr(inst->session), inst->batch.enable ? "enabled" : "disabled"); @@ -2095,6 +2096,9 @@ static void handle_session_flush(enum hal_command_response cmd, void *data) goto exit; } + if (flush_type == HAL_FLUSH_ALL) + msm_comm_release_window_data(inst); + dprintk(VIDC_HIGH, "Notify flush complete, flush_type: %x\n", flush_type); v4l2_event_queue_fh(&inst->event_handler, &flush_event); @@ -4306,6 +4310,10 @@ static int msm_comm_qbuf_to_hfi(struct msm_vidc_inst *inst, mbuf->flags |= MSM_VIDC_FLAG_QUEUED; msm_vidc_debugfs_update(inst, e); + if (mbuf->vvb.vb2_buf.type == INPUT_MPLANE && + is_decode_session(inst)) + rc = msm_comm_check_window_bitrate(inst, &frame_data); + err_bad_input: return rc; } @@ -4450,7 +4458,7 @@ static int msm_comm_qbuf_in_rbr(struct msm_vidc_inst *inst, if (rc) dprintk(VIDC_ERR, "%s: scale clocks failed\n", __func__); - print_vidc_buffer(VIDC_HIGH, "qbuf in rbr", inst, mbuf); + print_vidc_buffer(VIDC_HIGH|VIDC_PERF, "qbuf in rbr", inst, mbuf); rc = msm_comm_qbuf_to_hfi(inst, mbuf); if (rc) dprintk(VIDC_ERR, "%s: Failed qbuf to hfi: %d\n", __func__, rc); @@ -4487,7 +4495,7 @@ int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf) if (rc) dprintk(VIDC_ERR, "%s: scale clocks failed\n", __func__); - print_vidc_buffer(VIDC_HIGH, "qbuf", inst, mbuf); + print_vidc_buffer(VIDC_HIGH|VIDC_PERF, "qbuf", inst, mbuf); ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME); if (ctrl->val) rc = msm_comm_qbuf_superframe_to_hfi(inst, mbuf); @@ -4572,7 +4580,7 @@ int msm_comm_qbufs_batch(struct msm_vidc_inst *inst, if (buf->flags & MSM_VIDC_FLAG_RBR_PENDING) goto loop_end; - print_vidc_buffer(VIDC_HIGH, "batch-qbuf", inst, buf); + print_vidc_buffer(VIDC_HIGH|VIDC_PERF, "batch-qbuf", inst, buf); rc = msm_comm_qbuf_to_hfi(inst, buf); if (rc) { dprintk(VIDC_ERR, "%s: Failed batch qbuf to hfi: %d\n", @@ -4614,7 +4622,8 @@ int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst, if (inst->state != MSM_VIDC_START_DONE) { mbuf->flags |= MSM_VIDC_FLAG_DEFERRED; - print_vidc_buffer(VIDC_HIGH, "qbuf deferred", inst, mbuf); + print_vidc_buffer(VIDC_HIGH|VIDC_PERF, + "qbuf deferred", inst, mbuf); return 0; } @@ -6170,6 +6179,10 @@ void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst, { if (!(tag & msm_vidc_debug) || !inst || !vb2) return; + if ((tag & VIDC_PERF) && + !(tag & VIDC_HIGH) && + (inst->session_type != MSM_VIDC_DECODER)) + return; if (vb2->num_planes == 1) dprintk(tag, @@ -7195,3 +7208,80 @@ bool msm_comm_check_for_inst_overload(struct msm_vidc_core *core) } return overload; } + +int msm_comm_check_window_bitrate(struct msm_vidc_inst *inst, + struct vidc_frame_data *frame_data) +{ + struct msm_vidc_window_data *pdata, *next; + u32 bitrate, max_br, window_size; + int buf_cnt = 1, fps, window_start; + + if (!inst || !inst->core || !frame_data) { + dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__); + return -EINVAL; + } + + if (!inst->core->resources.avsync_window_size) + return 0; + + fps = inst->clk_data.frame_rate >> 16; + max_br = MAX_BITRATE_DECODER_CAVLC; + if (inst->entropy_mode == HFI_H264_ENTROPY_CABAC) + max_br = inst->clk_data.work_mode == HFI_WORKMODE_2 ? + MAX_BITRATE_DECODER_2STAGE_CABAC : + MAX_BITRATE_DECODER_1STAGE_CABAC; + window_size = inst->core->resources.avsync_window_size * fps; + window_size = DIV_ROUND_UP(window_size, 1000); + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dprintk(VIDC_ERR, "%s: malloc failure.\n", __func__); + return -ENOMEM; + } + + bitrate = pdata->frame_size = frame_data->filled_len; + window_start = pdata->etb_count = inst->count.etb; + + mutex_lock(&inst->window_data.lock); + list_add(&pdata->list, &inst->window_data.list); + list_for_each_entry_safe_continue(pdata, next, + &inst->window_data.list, list) { + if (buf_cnt < window_size) { + bitrate += pdata->frame_size; + window_start = pdata->etb_count; + buf_cnt++; + } else { + list_del(&pdata->list); + kfree(pdata); + } + } + mutex_unlock(&inst->window_data.lock); + + bitrate = DIV_ROUND_UP(((u64)bitrate * 8 * fps), window_size); + if (bitrate > max_br) { + dprintk(VIDC_PERF, + "Unsupported bitrate %u max %u, window size %u [%u,%u]", + bitrate, max_br, window_size, + window_start, inst->count.etb); + } + + return 0; +} + +void msm_comm_release_window_data(struct msm_vidc_inst *inst) +{ + struct msm_vidc_window_data *pdata, *next; + + if (!inst) { + dprintk(VIDC_ERR, "%s: invalid params %pK\n", + __func__, inst); + return; + } + + mutex_lock(&inst->window_data.lock); + list_for_each_entry_safe(pdata, next, &inst->window_data.list, list) { + list_del(&pdata->list); + kfree(pdata); + } + mutex_unlock(&inst->window_data.lock); +} diff --git a/msm/vidc/msm_vidc_common.h b/msm/vidc/msm_vidc_common.h index 29b2348563e0..f9c4b4a910b5 100644 --- a/msm/vidc/msm_vidc_common.h +++ b/msm/vidc/msm_vidc_common.h @@ -18,6 +18,9 @@ #define CBR_MB_LIMIT (((1280+15)/16)*((720+15)/16)*30) #define CBR_VFR_MB_LIMIT (((640+15)/16)*((480+15)/16)*30) #define V4L2_CID_MPEG_VIDEO_UNKNOWN (V4L2_CID_MPEG_MSM_VIDC_BASE + 0xFFF) +#define MAX_BITRATE_DECODER_CAVLC 220000000 +#define MAX_BITRATE_DECODER_2STAGE_CABAC 200000000 +#define MAX_BITRATE_DECODER_1STAGE_CABAC 70000000 struct vb2_buf_entry { struct list_head list; @@ -307,4 +310,7 @@ int msm_comm_set_extradata(struct msm_vidc_inst *inst, uint32_t extradata_id, uint32_t value); bool msm_comm_check_for_inst_overload(struct msm_vidc_core *core); void msm_vidc_batch_handler(struct work_struct *work); +int msm_comm_check_window_bitrate(struct msm_vidc_inst *inst, + struct vidc_frame_data *frame_data); +void msm_comm_release_window_data(struct msm_vidc_inst *inst); #endif diff --git a/msm/vidc/msm_vidc_debug.h b/msm/vidc/msm_vidc_debug.h index 976bc2056258..a28151c2c430 100644 --- a/msm/vidc/msm_vidc_debug.h +++ b/msm/vidc/msm_vidc_debug.h @@ -137,6 +137,7 @@ static inline char *get_debug_level_str(int level) switch (level) { case VIDC_ERR: return "err"; + case VIDC_HIGH|VIDC_PERF: case VIDC_HIGH: return "high"; case VIDC_LOW: diff --git a/msm/vidc/msm_vidc_internal.h b/msm/vidc/msm_vidc_internal.h index b0d9610849c7..d36af351b747 100644 --- a/msm/vidc/msm_vidc_internal.h +++ b/msm/vidc/msm_vidc_internal.h @@ -206,6 +206,12 @@ struct msm_vidc_buf_data { u32 filled_length; }; +struct msm_vidc_window_data { + struct list_head list; + u32 frame_size; + u32 etb_count; +}; + struct msm_vidc_common_data { char key[128]; int value; @@ -493,6 +499,7 @@ struct msm_vidc_inst { struct msm_vidc_list cvpbufs; struct msm_vidc_list etb_data; struct msm_vidc_list fbd_data; + struct msm_vidc_list window_data; struct buffer_requirements buff_req; struct vidc_frame_data superframe_data[VIDC_SUPERFRAME_MAX]; struct v4l2_ctrl_handler ctrl_handler; @@ -520,6 +527,7 @@ struct msm_vidc_inst { u32 colour_space; u32 profile; u32 level; + u32 entropy_mode; u32 rc_type; u32 hybrid_hp; u32 layer_bitrate; diff --git a/msm/vidc/msm_vidc_platform.c b/msm/vidc/msm_vidc_platform.c index 4dd91f205b5e..a1ea7062e77e 100644 --- a/msm/vidc/msm_vidc_platform.c +++ b/msm/vidc/msm_vidc_platform.c @@ -627,6 +627,10 @@ static struct msm_vidc_common_data kona_common_data[] = { .key = "qcom,fw-vpp-cycles", .value = 44156, }, + { + .key = "qcom,avsync-window-size", + .value = 40, + }, }; static struct msm_vidc_common_data sm6150_common_data[] = { diff --git a/msm/vidc/msm_vidc_res_parse.c b/msm/vidc/msm_vidc_res_parse.c index d2d66bb60291..067637053422 100644 --- a/msm/vidc/msm_vidc_res_parse.c +++ b/msm/vidc/msm_vidc_res_parse.c @@ -835,6 +835,8 @@ int read_platform_resources_from_drv_data( "qcom,fw-cycles"); res->fw_vpp_cycles = find_key_value(platform_data, "qcom,fw-vpp-cycles"); + res->avsync_window_size = find_key_value(platform_data, + "qcom,avsync-window-size"); res->csc_coeff_data = &platform_data->csc_data; diff --git a/msm/vidc/msm_vidc_resources.h b/msm/vidc/msm_vidc_resources.h index 76b5b8d206bd..7c5619de22dc 100644 --- a/msm/vidc/msm_vidc_resources.h +++ b/msm/vidc/msm_vidc_resources.h @@ -208,6 +208,7 @@ struct msm_vidc_platform_resources { uint32_t vpu_ver; uint32_t fw_cycles; uint32_t fw_vpp_cycles; + uint32_t avsync_window_size; struct msm_vidc_ubwc_config_data *ubwc_config; uint32_t clk_freq_threshold; struct cx_ipeak_client *cx_ipeak_context;