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 <qiweil@codeaurora.org>
Signed-off-by: Chinmay Sawarkar <chinmays@codeaurora.org>
This commit is contained in:
Qiwei Liu 2019-07-25 23:49:12 +08:00 • committed by Chinmay Sawarkar
commit 15f3510a38
11 changed files with 134 additions and 14 deletions

View file

@ -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);

View file

@ -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 +=

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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:

View file

@ -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;

View file

@ -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[] = {

View file

@ -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;

View file

@ -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;