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