media_modules: CB1 Fix high bitrate stream stuck issue [1/1]
PD#SWPL-195155
Problem:
Some high resolution and bitrate stream will stuck due to
the limit of the DDR bandwidth
Solution:
When the average decoding time of the last 16 frames is
too long, set HIGH_BANDWIDTH mode to VPP
depends on CL:
499380
Verify:
T5M
Change-Id: I421c525931fd6b8b4c4ea9a49ec78cda75fb8e52
Signed-off-by: zhentao.guo <zhentao.guo@amlogic.com>
diff --git a/drivers/frame_provider/decoder/utils/vdec_profile.c b/drivers/frame_provider/decoder/utils/vdec_profile.c
index 81ebf0f..d1680ee 100644
--- a/drivers/frame_provider/decoder/utils/vdec_profile.c
+++ b/drivers/frame_provider/decoder/utils/vdec_profile.c
@@ -40,7 +40,8 @@
static bool rec_wrapped;
static uint dec_time_stat_flag;
uint dec_time_stat_reset;
-
+static u32 fps60_high_bandwidth_ms = 13;
+static u32 fps30_high_bandwidth_ms = 33;
struct dentry *root, *event;
@@ -216,35 +217,39 @@
else
vdec->back_run2cb_time = time_avg;
}
- if (time_avg >= rate_time_avg_threshold_hi && *print_flag == 0) {
- *print_flag = 0x1;
- }
- if (*print_flag == 0x2) {
- *freeze_time_sum += time;
- (*freeze_time_cnt)++;
- freeze_avg = div_u64(*freeze_time_sum, *freeze_time_cnt);
- }
- if (freeze_avg < rate_time_avg_threshold_lo && (*print_flag == 0x2))
- *print_flag = 0x4;
- if (*print_flag == 0x1) {
- pr_info("------------------------%s_start------------------------\n",
- (event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb");
- pr_info("%s frame cnt %d %s overtime start \n", back_core_flag ? "back_core" : "front_core", frame_cnt - (rate_time_avg_cnt-1),
- (event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb");
- *print_flag = 0x2;
- } else if (*print_flag == 0x2) {
- pr_info("%s %s_time_avg_16 is %llu us \n", back_core_flag ? "back_core" : "front_core",
- (event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb", time_avg);
- } else if (*print_flag == 0x4) {
- pr_info("%s frame cnt %d overtime end, freeze avg %s time is %llu us freeze cnt %d\n",
+ if ((vdec_get_debug() & VDEC_DBG_ENABLE_HW_TIME_DEBUG) ||
+ (vdec_get_debug() & VDEC_DBG_ENABLE_TIME_DEBUG)) {
+ if (time_avg >= rate_time_avg_threshold_hi && *print_flag == 0) {
+ *print_flag = 0x1;
+ }
+ if (*print_flag == 0x2) {
+ *freeze_time_sum += time;
+ (*freeze_time_cnt)++;
+ freeze_avg = div_u64(*freeze_time_sum, *freeze_time_cnt);
+ }
+ if (freeze_avg < rate_time_avg_threshold_lo && (*print_flag == 0x2))
+ *print_flag = 0x4;
+
+ if (*print_flag == 0x1) {
+ pr_info("------------------------%s_start------------------------\n",
+ (event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb");
+ pr_info("%s frame cnt %d %s overtime start \n", back_core_flag ? "back_core" : "front_core", frame_cnt - (rate_time_avg_cnt-1),
+ (event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb");
+ *print_flag = 0x2;
+ } else if (*print_flag == 0x2) {
+ pr_info("%s %s_time_avg_16 is %llu us \n", back_core_flag ? "back_core" : "front_core",
+ (event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb", time_avg);
+ } else if (*print_flag == 0x4) {
+ pr_info("%s frame cnt %d overtime end, freeze avg %s time is %llu us freeze cnt %d\n",
back_core_flag ? "back_core" : "front_core", frame_cnt, (event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb", freeze_avg,
*freeze_time_cnt + (rate_time_avg_cnt - 1));
- pr_info("----------------------------%s_end---------------------------\n",
+ pr_info("----------------------------%s_end---------------------------\n",
(event == VDEC_PROFILE_DECODER_PIC_END) ? "hw" : "run2cb");
- *print_flag = 0;
- *freeze_time_sum = 0;
- *freeze_time_cnt = 0;
+ *print_flag = 0;
+ *freeze_time_sum = 0;
+ *freeze_time_cnt = 0;
+ }
}
}
}
@@ -283,8 +288,7 @@
pr_info("vdec_profile front hw time : %llu\n", time_stat->multi_us_sum);
ATRACE_COUNTER(vdec->decode_hw_front_time_name, time_stat->multi_us_sum);
ATRACE_COUNTER(vdec->decode_hw_front_spend_time_avg, div_u64(time_stat->hw_time_stat.time_total_us, time_stat->hw_cnt));
- if (vdec_get_debug() & VDEC_DBG_ENABLE_HW_TIME_DEBUG)
- vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, time_stat->multi_us_sum);
+ vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, time_stat->multi_us_sum);
time_stat->multi_us_sum = 0;
time_stat->multi_slice_cnt = 0;
} else {
@@ -293,8 +297,7 @@
pr_info("vdec_profile back hw time : %llu\n", timestamp - time_stat->hw_lasttimestamp);
ATRACE_COUNTER(vdec->decode_hw_back_time_name, timestamp - time_stat->hw_lasttimestamp);
ATRACE_COUNTER(vdec->decode_hw_back_spend_time_avg, div_u64(time_stat->hw_time_stat.time_total_us, time_stat->hw_cnt));
- if (vdec_get_debug() & VDEC_DBG_ENABLE_HW_TIME_DEBUG)
- vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, timestamp - time_stat->hw_lasttimestamp);
+ vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, timestamp - time_stat->hw_lasttimestamp);
}
}
@@ -332,8 +335,7 @@
pr_info("vdec_profile front run2cb time : %llu\n", run2cb_time);
ATRACE_COUNTER(vdec->dec_spend_time, run2cb_time);
ATRACE_COUNTER(vdec->dec_spend_time_ave, div_u64(time_stat->run2cb_time_stat.time_total_us, time_stat->cb_cnt));
- if (vdec_get_debug() & VDEC_DBG_ENABLE_TIME_DEBUG)
- vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, run2cb_time);
+ vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, run2cb_time);
time_stat->hidden_frame_us_sum = 0;
}
time_stat->unhidden_frame = 0;
@@ -342,8 +344,7 @@
pr_info("vdec_profile back run2cb time : %llu\n", timestamp - time_stat->run_lasttimestamp);
ATRACE_COUNTER(vdec->dec_back_spend_time, timestamp - time_stat->run_lasttimestamp);
ATRACE_COUNTER(vdec->dec_back_spend_time_ave, div_u64(time_stat->run2cb_time_stat.time_total_us, time_stat->cb_cnt));
- if (vdec_get_debug() & VDEC_DBG_ENABLE_TIME_DEBUG)
- vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, timestamp - time_stat->run_lasttimestamp);
+ vdec_profile_time_summary(vdec, event, time_stat, back_core_flag, timestamp - time_stat->run_lasttimestamp);
}
} else if (event == VDEC_PROFILE_DECODED_FRAME) {
time_stat->decoded_frame_cnt++;
@@ -484,6 +485,27 @@
mutex_unlock(&vdec_profile_mutex);
}
+int vdec_profile_set_high_bandwidth_mode(struct vdec_s *vdec, u32 w, u32 h,
+ u32 duration)
+{
+ int ret = 0;
+
+ if ((vdec->front_run2cb_time > fps60_high_bandwidth_ms * 1000UL)
+ && duration > 1500 && duration < 2000
+ && w > 1920 && h > 1080) {
+ if (vdec_get_debug() & VDEC_DBG_ENABLE_PRINT_TIME_DEBUG)
+ pr_info("set VFRAME_FLAG_HIGH_BANDWIDTH \n");
+ ret = true;
+ } else if ((vdec->front_run2cb_time > fps30_high_bandwidth_ms * 1000UL)
+ && w > 1920 && h > 1080) {
+ if (vdec_get_debug() & VDEC_DBG_ENABLE_PRINT_TIME_DEBUG)
+ pr_info("set VFRAME_FLAG_HIGH_BANDWIDTH \n");
+ ret = true;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(vdec_profile_set_high_bandwidth_mode);
+
static const char *event_str(int event)
{
if (event < VDEC_PROFILE_MAX_EVENT)
@@ -764,6 +786,9 @@
module_param(dec_time_stat_reset, uint, 0664);
+module_param(fps30_high_bandwidth_ms, uint, 0664);
+
+module_param(fps60_high_bandwidth_ms, uint, 0664);
/*module_init(vdec_profile_init_debugfs);*/
diff --git a/drivers/frame_provider/decoder/utils/vdec_profile.h b/drivers/frame_provider/decoder/utils/vdec_profile.h
index 61e9b37..f44afff 100644
--- a/drivers/frame_provider/decoder/utils/vdec_profile.h
+++ b/drivers/frame_provider/decoder/utils/vdec_profile.h
@@ -43,6 +43,8 @@
extern void vdec_profile(struct vdec_s *vdec, int event, int mask);
extern void vdec_profile_more(struct vdec_s *vdec, int event, int para1, int para2, int mask);
extern void vdec_profile_flush(struct vdec_s *vdec);
+extern int vdec_profile_set_high_bandwidth_mode(struct vdec_s *vdec, u32 w, u32 h,
+ u32 duration);
int vdec_profile_init_debugfs(void);
void vdec_profile_exit_debugfs(void);
diff --git a/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
index 0523999..bcba18d 100644
--- a/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
@@ -195,6 +195,7 @@
static unsigned int decode_timeout_val = 100;
static unsigned int errordata_timeout_val = 50;
static unsigned int get_data_timeout_val = 2000;
+static u32 high_bandwidth_dynamic_enabled = 0;
/* H264_DATA_REQUEST does not work, disable it,
decode has error for data in none continuous address
@@ -1022,6 +1023,7 @@
u32 status_report_count; //for multi frames in once run isr status count
u32 multi_frame_in_run; //multi frames in once run flag
enum FenceModeBufStatus fence_mode_buf_status;
+ bool time_bandwidth_flag;
};
#define TIMEOUT_INIT 0
@@ -4017,6 +4019,17 @@
}
atomic_add(1, &hw->vf_pre_count);
+
+ if (high_bandwidth_dynamic_enabled) {
+ dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,"vf duration = %d\n", vf->duration);
+ if (hw->high_bandwidth_flag ||
+ vdec_profile_set_high_bandwidth_mode(hw_to_vdec(hw),
+ hw->frame_width, hw->frame_height, vf->duration)) {
+ hw->high_bandwidth_flag = 1;
+ vf->type_ext |= VIDTYPE_EXT_HIGH_BANDWIDTH;
+ }
+ }
+
vdec_vframe_ready(hw_to_vdec(hw), vf);
if (!frame->show_frame) {
@@ -12808,6 +12821,7 @@
ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_START);
vmh264_reset_udr_mgr(hw);
+
if (vh264_hw_ctx_restore(hw) < 0) {
vdec_schedule_work(&hw->work);
return;
@@ -13970,6 +13984,9 @@
module_param(one_packet_multi_frames_multi_run, uint, 0664);
MODULE_PARM_DESC(one_packet_multi_frames_multi_run, "\n one_packet_multi_frames_multi_run\n");
+module_param(high_bandwidth_dynamic_enabled, uint, 0664);
+MODULE_PARM_DESC(high_bandwidth_dynamic_enabled, "\n amvdec_h264 high_bandwidth_dynamic_enabled\n");
+
module_param(save_buffer, uint, 0664);
MODULE_PARM_DESC(save_buffer, "\n save_buffer\n");
diff --git a/drivers/frame_provider/decoder_v4l/h265/vh265.c b/drivers/frame_provider/decoder_v4l/h265/vh265.c
index 117aa14..e116842 100644
--- a/drivers/frame_provider/decoder_v4l/h265/vh265.c
+++ b/drivers/frame_provider/decoder_v4l/h265/vh265.c
@@ -326,6 +326,7 @@
static u32 dbg_cmd;
static u32 dump_nal;
static u32 dbg_skip_decode_index;
+static u32 high_bandwidth_dynamic_enabled = 0;
/*
* bit 0~3, for HEVCD_IPP_AXIIF_CONFIG endian config
* bit 8~23, for HEVC_SAO_CTRL1 endian config
@@ -2034,6 +2035,7 @@
struct mmu_copy mmu_copy_array[BUF_FBC_NUM_MAX];
bool check_suffix_data;
enum FenceModeBufStatus fence_mode_buf_status;
+ bool time_bandwidth_flag;
} /*hevc_stru_t */;
struct hevc_RPS_s {
@@ -10851,6 +10853,17 @@
tmp4x.double_write_mode = pic->double_write_mode;
vdec_fill_vdec_frame(vdec, &hevc->vframe_qos, &tmp4x, vf, pic->hw_decode_time);
vdec->vdec_fps_detec(vdec->id);
+
+ if (high_bandwidth_dynamic_enabled) {
+ hevc_print(hevc, H265_DEBUG_OUT_PTS, "vf->duration %d\n", vf->duration);
+ if (hevc->time_bandwidth_flag ||
+ vdec_profile_set_high_bandwidth_mode(vdec,
+ pic->width, pic->height, vf->duration)) {
+ hevc->time_bandwidth_flag = 1;
+ vf->type_ext |= VIDTYPE_EXT_HIGH_BANDWIDTH;
+ }
+ }
+
hevc_print(hevc, H265_DEBUG_BUFMGR,
"%s(type %d index 0x%x poc %d/%d) pts(%d,%d,%llu) dur %d\n",
__func__, vf->type, vf->index,
@@ -15420,7 +15433,6 @@
hevc->shift_byte_count_lo;
}
#endif
-
done_end:
mutex_lock(&hevc->chunks_mutex);
vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk);
@@ -17509,8 +17521,12 @@
module_param(detect_stuck_buffer_margin, uint, 0664);
MODULE_PARM_DESC(detect_stuck_buffer_margin, "\n detect_stuck_buffer_margin\n");
+module_param(high_bandwidth_dynamic_enabled, uint, 0664);
+MODULE_PARM_DESC(high_bandwidth_dynamic_enabled, "\n amvdec_h265 high_bandwidth_dynamic_enabled\n");
+
module_param(frmbase_multi_slice, uint, 0664);
MODULE_PARM_DESC(frmbase_multi_slice, "\n amvdec_h265 frmbase_multi_slice\n");
+
module_param(efficiency_mode, uint, 0664);
MODULE_PARM_DESC(efficiency_mode, "\n efficiency_mode\n");
diff --git a/drivers/frame_provider/decoder_v4l/vav1/vav1.c b/drivers/frame_provider/decoder_v4l/vav1/vav1.c
index b038f93..303a74f 100644
--- a/drivers/frame_provider/decoder_v4l/vav1/vav1.c
+++ b/drivers/frame_provider/decoder_v4l/vav1/vav1.c
@@ -880,6 +880,8 @@
u32 av1_dec_info[3];
bool enable_ucode_swap;
u32 max_spatial_id;
+
+ bool time_bandwidth_flag;
};
static void av1_dump_state(struct vdec_s *vdec);
@@ -2065,6 +2067,8 @@
static u32 scalable_enable = 1;
+static u32 high_bandwidth_dynamic_enabled = 0;
+
/*
*bit 0, 1: only display I picture;
*bit 1, 1: only decode I picture;
@@ -7069,6 +7073,17 @@
tmp4x.bit_depth_chroma = bit_depth_chroma;
tmp4x.double_write_mode = pic_config->double_write_mode;
vdec_fill_vdec_frame(hw_to_vdec(hw), &hw->vframe_qos, &tmp4x, vf, pic_config->hw_decode_time);
+
+ if (high_bandwidth_dynamic_enabled) {
+ av1_print(hw, PRINT_FLAG_VDEC_STATUS, "vf->duration: %d\n", vf->duration);
+ if (hw->time_bandwidth_flag ||
+ vdec_profile_set_high_bandwidth_mode(hw_to_vdec(hw),
+ pic_config->y_crop_width, pic_config->y_crop_height, vf->duration)) {
+ vf->type_ext |= VIDTYPE_EXT_HIGH_BANDWIDTH;
+ hw->time_bandwidth_flag = 1;
+ }
+ }
+
v4l_av1_update_frame_info(hw, vf, pic_config);
if (without_display_mode == 0) {
@@ -9845,6 +9860,7 @@
}
if (!hw->frame_decoded)
vdec_profile(hw_to_vdec(hw), VDEC_PROFILE_DECODER_START, CORE_MASK_HEVC);
+
ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
return IRQ_HANDLED;
}
@@ -10861,6 +10877,7 @@
hw->start_shift_bytes
);
vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
+
if (hw->dec_status == AOM_AV1_DEC_PIC_END)
vdec_code_rate(vdec, READ_VREG(HEVC_SHIFT_BYTE_COUNT) - hw->start_shift_bytes);
} else if (hw->dec_result == DEC_RESULT_AGAIN) {
@@ -12752,6 +12769,9 @@
module_param(efficiency_mode, uint, 0664);
MODULE_PARM_DESC(efficiency_mode, "\n efficiency_mode\n");
+module_param(high_bandwidth_dynamic_enabled, uint, 0664);
+MODULE_PARM_DESC(high_bandwidth_dynamic_enabled, "\n amvdec_av1 high_bandwidth_dynamic_enabled\n");
+
module_init(amvdec_av1_driver_init_module);
module_exit(amvdec_av1_driver_remove_module);
diff --git a/drivers/frame_provider/decoder_v4l/vp9/vvp9.c b/drivers/frame_provider/decoder_v4l/vp9/vvp9.c
index 5b5359c..77ad3d6 100644
--- a/drivers/frame_provider/decoder_v4l/vp9/vvp9.c
+++ b/drivers/frame_provider/decoder_v4l/vp9/vvp9.c
@@ -1290,6 +1290,7 @@
u32 data_size_bak;
u32 data_offset_bak;
u32 consume_byte_bak;
+ bool time_bandwidth_flag;
};
static int vp9_debug(struct VP9Decoder_s *pbi,
@@ -3159,6 +3160,7 @@
/* buffer_mode_dbg: debug only*/
static u32 buffer_mode_dbg = 0xffff0000;
/**/
+static u32 high_bandwidth_dynamic_enabled = 0;
/*
*bit 0, 1: only display I picture;
@@ -8148,6 +8150,16 @@
v4l2_ctx->fbc_transcode_and_set_vf(v4l2_ctx,
aml_buf, vf);
+ if (high_bandwidth_dynamic_enabled) {
+ vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, "vf->duration %d\n", vf->duration);
+ if (pbi->time_bandwidth_flag ||
+ vdec_profile_set_high_bandwidth_mode(pvdec,
+ pic_config->y_crop_width, pic_config->y_crop_height, vf->duration)) {
+ pbi->time_bandwidth_flag = 1;
+ vf->type_ext |= VIDTYPE_EXT_HIGH_BANDWIDTH;
+ }
+ }
+
if (without_display_mode == 0) {
if (v4l2_ctx->is_stream_off && ((!v4l2_ctx->avbcd_work_mode) ||
(v4l2_ctx->avbcd_work_mode && atomic_read(&pbi->vf_pre_count) > 1))) {
@@ -10823,6 +10835,7 @@
vdec_vframe_dirty(hw_to_vdec(pbi), pbi->chunk);
if (pbi->dec_status == HEVC_DECPIC_DATA_DONE)
vdec_code_rate(vdec, READ_VREG(HEVC_SHIFT_BYTE_COUNT) - pbi->start_shift_bytes);
+
} else if (pbi->dec_result == DEC_RESULT_AGAIN) {
/*
stream base: stream buf empty or timeout
@@ -12725,6 +12738,9 @@
module_param(efficiency_mode, uint, 0664);
MODULE_PARM_DESC(efficiency_mode, "\n efficiency_mode\n");
+module_param(high_bandwidth_dynamic_enabled, uint, 0664);
+MODULE_PARM_DESC(high_bandwidth_dynamic_enabled, "\n amvdec_vp9 high_bandwidth_dynamic_enabled\n");
+
module_init(amvdec_vp9_driver_init_module);
module_exit(amvdec_vp9_driver_remove_module);