vdec: CF1 VDEC ErrorCodes Report [1/1]

PD#SWPL-167458

Problem:
VDEC ErrorCodes Report

Solution:
Added INPUT_UNDERRUN , OUTPUT_UNDERRUN,
OUTPUT_BUFFFER_NOT_READY, BAD_INPUT,
PROFILLE_LEVEL_NOT_SUPPORTED message reporting.

Verify:
S4

Change-Id: Ifd8523e81349ecf8eed424588a3c1ddf6c900684
Signed-off-by: xing.xu <xing.xu@amlogic.com>
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c
index 1f24dab..8736380 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.c
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -828,3 +828,22 @@
 
 	return;
 }
+
+int vdec_get_decoder_buffer_status(struct aml_vdec_adapt *ada_ctx)
+{
+	struct vdec_s *vdec = ada_ctx->vdec;
+	struct aml_vcodec_ctx *ctx = ada_ctx->ctx;
+	int buffer_status = 0;
+
+	if (!ctx->v4l_codec_dpb_ready)
+		buffer_status |= DEC_STATUS_OUTPUT_BUFFFER_NOT_READY;
+
+	if ((ctx->vpp_is_need ? ctx->picinfo.vpp_margin : ctx->picinfo.dpb_margin) <
+		(CTX_BUF_TOTAL(ctx) + ctx->out_buff_cnt - ctx->in_buff_cnt))
+		buffer_status |= DEC_STATUS_OUTPUT_UNDERRUN;
+
+	if (!vdec->input.have_frame_num)
+		buffer_status |= DEC_STATUS_INPUT_UNDERRUN;
+
+	return buffer_status;
+}
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h
index 2bed397..8e0cff4 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.h
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -48,6 +48,12 @@
 	char *frm_name;
 };
 
+enum DEC_STATUS {
+	DEC_STATUS_INPUT_UNDERRUN = 1,
+	DEC_STATUS_OUTPUT_UNDERRUN = 2,
+	DEC_STATUS_OUTPUT_BUFFFER_NOT_READY = 4,
+};
+
 int video_decoder_init(struct aml_vdec_adapt *ada_ctx);
 
 int video_decoder_release(struct aml_vdec_adapt *ada_ctx);
@@ -102,5 +108,7 @@
 
 void vdec_thread_wakeup(struct aml_vdec_adapt *ada_ctx);
 
+int vdec_get_decoder_buffer_status(struct aml_vdec_adapt *ada_ctx);
+
 #endif /* VDEC_ADAPT_H */
 
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c
index a3f1164..c31a02e 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -437,6 +437,7 @@
 {
 	struct v4l2_event event = {0};
 	const char *event_str = event_to_string(changes);
+	int events = 0;
 
 	switch (changes) {
 	case V4L2_EVENT_SRC_CH_RESOLUTION:
@@ -451,12 +452,26 @@
 		break;
 	case V4L2_EVENT_SEND_ERROR:
 		event.type = V4L2_EVENT_PRIVATE_EXT_SEND_ERROR;
+
+#ifdef CONFIG_AMLOGIC_MEDIA_PROXY
+		if (ctx->decoder_status_info.error_type & (1 << 24)) {
+			events = MEDIA_ERRORCODES_VDEC_F_NO_MEMORY;
+		} else if (ctx->decoder_status_info.error_type & (1 << 25)) {
+			events = MEDIA_ERRORCODES_VDEC_E_PROFILELEVEL_NOT_SUPPORTED;
+		}
+
+		aml_vdec_notify_msg_to_mediaproxy(ctx, MEDIA_VIDEO_ERROR_EVENT, NULL, events);
+#endif
 		break;
 	case V4L2_EVENT_REPORT_ERROR_FRAME:
 		event.type = V4L2_EVENT_PRIVATE_EXT_REPORT_ERROR_FRAME;
 		memcpy(event.u.data, &ctx->current_timestamp, sizeof(u64));
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "report error frame timestamp: %llu\n",
 			ctx->current_timestamp);
+#ifdef CONFIG_AMLOGIC_MEDIA_PROXY
+		events = MEDIA_ERRORCODES_VDEC_M_BAD_INPUT;
+		aml_vdec_notify_msg_to_mediaproxy(ctx, MEDIA_VIDEO_ERROR_EVENT, NULL, events);
+#endif
 		break;
 	case V4L2_EVENT_REPORT_DEC_INFO:
 		event.type = V4L2_EVENT_PRIVATE_EXT_REPORT_DECINFO;
@@ -961,27 +976,32 @@
 
 #ifdef CONFIG_AMLOGIC_MEDIA_PROXY
 void aml_vdec_notify_msg_to_mediaproxy(struct aml_vcodec_ctx *ctx,
-	int type, struct vframe_s *vf)
+	int type, struct vframe_s *vf, int event)
 {
 	struct aml_video_user_data msg;
 
 	memset(&msg, 0, sizeof(struct aml_video_user_data));
 
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
-		"%s bitstreamid: %llu instid: %u frame_index: %u time: %llu\n",
-		__func__, div64_u64(vf->timestamp, 1000000000),
-		vf->decoder_instid, vf->frame_index,
-		ktime_get_real_ns());
-
-	msg.data.frame_info.bitstreamid = div64_u64(vf->timestamp, 1000000000);
-	msg.data.frame_info.decoder_instid = vf->decoder_instid;
-	msg.data.frame_info.frame_index = vf->frame_index;
-	msg.data.frame_info.time = ktime_get_real_ns();
-	msg.data.frame_info.drop = 0;
-
-	if (type == MEDIA_VIDEO_METRICS_FRAME_DECODED_INFO)
+	if (type == MEDIA_VIDEO_METRICS_FRAME_DECODED_INFO) {
 		msg.message_type = MEDIA_VIDEO_METRICS_FRAME_DECODED_INFO;
 
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"%s bitstreamid: %llu instid: %u frame_index: %u time: %llu\n",
+			__func__, div64_u64(vf->timestamp, 1000000000),
+			vf->decoder_instid, vf->frame_index,
+			ktime_get_real_ns());
+
+		msg.data.frame_info.bitstreamid = div64_u64(vf->timestamp, 1000000000);
+		msg.data.frame_info.decoder_instid = vf->decoder_instid;
+		msg.data.frame_info.frame_index = vf->frame_index;
+		msg.data.frame_info.time = ktime_get_real_ns();
+		msg.data.frame_info.drop = 0;
+
+	} else if (type == MEDIA_VIDEO_ERROR_EVENT) {
+		msg.message_type = MEDIA_VIDEO_ERROR_EVENT;
+		msg.data.error_info.error_event = MEDIA_ERRORCODES_VDEC_M_BAD_INPUT;
+	}
+
 	notify_msg_to_mediaproxy(ctx->k_producer_session, 1, &msg);
 }
 #endif
@@ -1039,7 +1059,7 @@
 	vb2_buf->timestamp = vf->timestamp;
 	dstbuf->vb.flags |= vf->frame_type;
 #ifdef CONFIG_AMLOGIC_MEDIA_PROXY
-	aml_vdec_notify_msg_to_mediaproxy(ctx, MEDIA_VIDEO_METRICS_FRAME_DECODED_INFO, vf);
+	aml_vdec_notify_msg_to_mediaproxy(ctx, MEDIA_VIDEO_METRICS_FRAME_DECODED_INFO, vf, 0);
 #endif
 
 	if ((ctx->picinfo.field == V4L2_FIELD_INTERLACED) && (!ctx->vpp_is_need)) {
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h
index a215f80..62478d3 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.h
+++ b/drivers/amvdec_ports/aml_vcodec_dec.h
@@ -26,6 +26,7 @@
 #include <media/videobuf2-v4l2.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/media_proxy/AmlVideoUserdata.h>
+#include <linux/amlogic/media/media_proxy/AmlMediaErrorCodes.h>
 //#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
 #include "aml_vcodec_util.h"
 #include "aml_task_chain.h"
@@ -265,7 +266,7 @@
 
 #ifdef CONFIG_AMLOGIC_MEDIA_PROXY
 void aml_vdec_notify_msg_to_mediaproxy(struct aml_vcodec_ctx *ctx, int type,
-	struct vframe_s *vf);
+	struct vframe_s *vf, int event);
 #endif
 
 #endif /* _AML_VCODEC_DEC_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_infoserver.c b/drivers/amvdec_ports/aml_vcodec_dec_infoserver.c
index 8e63990..c83fdfd 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec_infoserver.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec_infoserver.c
@@ -23,6 +23,8 @@
 #include "aml_vcodec_adapt.h"
 #include "./decoder/utils.h"
 #include "../frame_provider/decoder/utils/vdec.h"
+#include "aml_vcodec_adapt.h"
+#include "vdec_drv_if.h"
 
 #ifndef MAX
 #define MAX(a, b) ({ \
@@ -407,6 +409,11 @@
 static int vcodec_get_data_stream(struct aml_vcodec_ctx *ctx,
 	struct vdec_common_s *data)
 {
+	int status = 0;
+
+	vdec_if_get_param(ctx, GET_PARAM_DECODER_STATUS, &status);
+	ctx->dec_intf.dec_stream.decode_status = status;
+
 	memcpy(&data->u.stream_info, &ctx->dec_intf.dec_stream,
 		sizeof(struct dec_stream_info_s));
 	data->u.stream_info.info_type = AML_STREAM_TYPE;
diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h
index d4d66cd..9e0301f 100644
--- a/drivers/amvdec_ports/aml_vcodec_drv.h
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -186,6 +186,7 @@
 	enum E_ASPECT_RATIO eu_aspect_ratio;  /* aspect ratio (4:3 or 16:9) */
 	struct aspect_ratio_size ratio_size;   /* sar width/height, dar width/height */
 	__u32 frame_dur;
+	__u32 decode_status;
 	char reserved[60];
 };
 
diff --git a/drivers/amvdec_ports/decoder/vdec_av1_if.c b/drivers/amvdec_ports/decoder/vdec_av1_if.c
index 4facd47..4abbd7f 100644
--- a/drivers/amvdec_ports/decoder/vdec_av1_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_av1_if.c
@@ -1132,6 +1132,7 @@
 {
 	int ret = 0;
 	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
 
 	if (!inst) {
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
@@ -1178,6 +1179,13 @@
 		get_param_comp_buf_info(inst, out);
 		break;
 
+	case GET_PARAM_DECODER_STATUS:
+	{
+		int *mode = out;
+		*mode = vdec_get_decoder_buffer_status(vdec);
+		break;
+	}
+
 	default:
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"invalid get parameter type=%d\n", type);
diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c
index c64cffa..3129ef2 100644
--- a/drivers/amvdec_ports/decoder/vdec_h264_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c
@@ -959,6 +959,7 @@
 {
 	int ret = 0;
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
 
 	if (!inst) {
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
@@ -1004,6 +1005,14 @@
 		*mode = vdec_get_dec_mode(w, h, m);
 		break;
 	}
+	case GET_PARAM_DECODER_STATUS:
+	{
+		int *mode = out;
+
+		*mode = vdec_get_decoder_buffer_status(vdec);
+
+		break;
+	}
 
 	default:
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
index d2a9503..4f0379a 100644
--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -558,6 +558,7 @@
 {
 	int ret = 0;
 	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
 
 	if (!inst) {
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
@@ -603,6 +604,12 @@
 	case GET_PARAM_CFG_INFO:
 		get_cfg_info(inst, out);
 		break;
+	case GET_PARAM_DECODER_STATUS:
+	{
+		int *mode = out;
+		*mode = vdec_get_decoder_buffer_status(vdec);
+		break;
+	}
 
 	default:
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
index 0f30899..9d18e20 100644
--- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
@@ -779,6 +779,7 @@
 {
 	int ret = 0;
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
 
 	if (!inst) {
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
@@ -821,6 +822,13 @@
 		get_param_comp_buf_info(inst, out);
 		break;
 
+	case GET_PARAM_DECODER_STATUS:
+	{
+		int *mode = out;
+		*mode = vdec_get_decoder_buffer_status(vdec);
+		break;
+	}
+
 	default:
 		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"invalid get parameter type=%d\n", type);
diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h
index ea08aa9..c7acb10 100644
--- a/drivers/amvdec_ports/vdec_drv_if.h
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -84,7 +84,8 @@
 	GET_PARAM_COMP_BUF_INFO,
 	GET_PARAM_CFG_INFO,
 	GET_PARAM_TW_MODE,
-	GET_PARAM_TIME_STAMP
+	GET_PARAM_TIME_STAMP,
+	GET_PARAM_DECODER_STATUS
 };
 
 /*
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
index 7241a9b..212d0d3 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
@@ -23,7 +23,6 @@
 #include <linux/printk.h>
 #include <linux/version.h>
 
-
 int vdec_v4l_get_pic_info(struct aml_vcodec_ctx *ctx,
 	struct vdec_pic_info *pic)
 {
@@ -268,7 +267,6 @@
 }
 EXPORT_SYMBOL(vdec_v4l_get_tw_mode);
 
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
 void v4l2_m2m_job_pause(struct v4l2_m2m_dev *m2m_dev,
 			struct v4l2_m2m_ctx *m2m_ctx)
diff --git a/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
index c5b5b0b..7652a8d 100644
--- a/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
@@ -1217,9 +1217,10 @@
 		return RES_RET_ABNORMAL;
 
 	base_csd_valid = is_base_csd_valid(hw, param4);
-	if (!base_csd_valid)
+	if (!base_csd_valid) {
+		vdec_v4l_post_error_event(hw->v4l2_ctx, DECODER_EMERGENCY_UNSUPPORT);
 		return RES_RET_ABNORMAL;
-
+	}
 	curr_info.frame_width = mb_width << 4;
 	curr_info.frame_height = mb_height << 4;
 	over_size = is_oversize(curr_info.frame_width, curr_info.frame_height);
@@ -3500,6 +3501,7 @@
 		if (frame->data_flag & ERROR_FLAG ||
 			frame->data_flag & NODISP_FLAG) {
 			vf->frame_type |= V4L2_BUF_FLAG_ERROR;
+			vdec_v4l_post_error_frame_event(hw->v4l2_ctx);
 		}
 
 		if ((hw->crop_bottom != 0) || (hw->crop_right != 0) ||
diff --git a/drivers/frame_provider/decoder_v4l/h265/vh265.c b/drivers/frame_provider/decoder_v4l/h265/vh265.c
index 669c584..9cc6c92 100644
--- a/drivers/frame_provider/decoder_v4l/h265/vh265.c
+++ b/drivers/frame_provider/decoder_v4l/h265/vh265.c
@@ -10013,6 +10013,7 @@
 
 		if ((pic->error_mark) && (hevc->PB_skip_mode != 0)) {
 			vf->frame_type |= V4L2_BUF_FLAG_ERROR;
+			vdec_v4l_post_error_frame_event(hevc->v4l2_ctx);
 		}
 
 		vf->v4l_mem_handle = hevc->m_BUF[pic->index].v4l_ref_buf_addr;
@@ -13629,9 +13630,8 @@
 	else
 		ret = 0;
 
-	if (ret < 0) {
+	if (ret < 0)
 		vdec_v4l_post_error_event(ctx, DECODER_EMERGENCY_NO_MEM);
-	}
 
 	return ret;
 }
@@ -15468,7 +15468,6 @@
 	vh265_work_implement(hevc, vdec, 1);
 }
 
-
 static int vh265_hw_ctx_restore(struct hevc_state_s *hevc)
 {
 	/* new to do ... */
diff --git a/drivers/frame_provider/decoder_v4l/h265_fb/vh265_fb_v4l.c b/drivers/frame_provider/decoder_v4l/h265_fb/vh265_fb_v4l.c
index 98c3ee9..b9f5187 100644
--- a/drivers/frame_provider/decoder_v4l/h265_fb/vh265_fb_v4l.c
+++ b/drivers/frame_provider/decoder_v4l/h265_fb/vh265_fb_v4l.c
@@ -18708,6 +18708,7 @@
 
 	if (init_mmu_buffers(hevc, 1) < 0) {
 		hevc_print(hevc, 0, "\n 265 mmu init failed!\n");
+		vdec_v4l_post_error_event(ctx, DECODER_EMERGENCY_NO_MEM);
 		mutex_unlock(&vh265_mutex);
 		if (hevc)
 			vfree((void *)hevc);
@@ -18720,6 +18721,7 @@
 			DRIVER_NAME, &hevc->buf_start);
 	if (ret < 0) {
 		uninit_mmu_buffers(hevc);
+		vdec_v4l_post_error_event(ctx, DECODER_EMERGENCY_NO_MEM);
 		/* devm_kfree(&pdev->dev, (void *)hevc); */
 		if (hevc)
 			vfree((void *)hevc);
diff --git a/drivers/frame_provider/decoder_v4l/vav1_fb/vav1_fb_v4l.c b/drivers/frame_provider/decoder_v4l/vav1_fb/vav1_fb_v4l.c
index 2d6d496..5349307 100644
--- a/drivers/frame_provider/decoder_v4l/vav1_fb/vav1_fb_v4l.c
+++ b/drivers/frame_provider/decoder_v4l/vav1_fb/vav1_fb_v4l.c
@@ -13003,6 +13003,7 @@
 			hw->cma_alloc_count * PAGE_SIZE, DRIVER_NAME,
 			&hw->cma_alloc_addr);
 	if (ret < 0) {
+		vdec_v4l_post_error_event(ctx, DECODER_EMERGENCY_NO_MEM);
 		pdata->dec_status = NULL;
 		ret = -ENOMEM;
 		goto multi_probe_failed2;