H264/MPEG2: CF2 v4l support the afd [1/1]

PD#SWPL-187841
PD#TV-115710

Problem:
h264/mpeg12 v4l need the afd.

Solution:
h264/mpeg12 v4l support the afd

Verify:
ohm

Change-Id: I5ca138baafe9ccef2640bbedc2a58195abcf225b
Signed-off-by: yuna.liu <yuna.liu@amlogic.com>
diff --git a/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.c b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.c
index 43a03d2..d2b4a62 100644
--- a/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.c
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.c
@@ -1293,6 +1293,7 @@
 	fs->frame->colocated_buf_index = fs->top_field->colocated_buf_index;
 	fs->frame->data_flag = fs->top_field->data_flag;
 	fs->frame->slice_type = fs->top_field->slice_type;
+	fs->frame->pic_struct = PIC_INVALID;
 	if (fs->bottom_field)
 		fs->frame->data_flag |= (fs->bottom_field->data_flag & 0xf0);
 
diff --git a/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.h b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.h
index 283975d..646247f 100644
--- a/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.h
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.h
@@ -42,6 +42,7 @@
 #define PRINT_FLAG_SEI_DETAIL         0x4000
 #define PRINT_FLAG_V4L_DETAIL         0x8000
 #define DISABLE_ERROR_HANDLE          0x10000
+#define PRINT_FLAG_UD_DETAIL          0x20000
 #define DEBUG_DUMP_STAT               0x80000
 #define DEBUG_TIMEOUT_DEC_STAT        0x800000
 #define DEBUG_CACHE_HIT_RATE          0x1000000
diff --git a/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
index c96fe9f..c5b5b0b 100644
--- a/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
@@ -529,6 +529,7 @@
 	dos_addr_t dw_u_v_adr;
 	int fs_idx;
 	int ctx_buf_idx;
+	struct userdata_param_t ud_param[2];
 };
 
 #define AUX_DATA_SIZE(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_size)
@@ -3319,6 +3320,8 @@
 	int bForceInterlace = 0;
 	int vf_count = 1;
 	int i;
+	int ud_index;
+	struct buffer_spec_s *pic = &hw->buffer_spec[buffer_index];
 	u32 slice_type = 0;
 	u32 offset = 0;
 	int dw_mode = get_double_write_mode(hw);
@@ -3736,6 +3739,38 @@
 			__func__, __LINE__,vs.i_decoded_frames,vs.p_decoded_frames,vs.b_decoded_frames);
 		}
 
+		ud_index = i;
+		if (frame->frame != NULL &&
+			(frame->frame->pic_struct == PIC_TOP_BOT ||
+			frame->frame->pic_struct == PIC_BOT_TOP||
+			frame->frame->pic_struct == PIC_TOP_BOT_TOP ||
+			frame->frame->pic_struct == PIC_BOT_TOP_BOT ||
+			frame->frame->pic_struct == PIC_DOUBLE_FRAME ||
+			frame->frame->pic_struct ==  PIC_TRIPLE_FRAME))
+			ud_index = 0;
+
+		vf->vf_ud_param.magic_code = UD_MAGIC_CODE;
+		vf->vf_ud_param.ud_param = pic->ud_param[ud_index];
+
+		if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_UD_DETAIL))
+		{
+			struct userdata_param_t ud_param = pic->ud_param[ud_index];
+			{
+				int j = 0;
+				u8 *pstart = (u8 *)ud_param.pbuf_addr;
+				PR_INIT(128);
+				dpb_print(DECODE_ID(hw), 0, "%s:userdata len %d. vdec %p video_id %d, ud_index %d\n",
+					__func__,ud_param.buf_len, vdec, ud_param.instance_id, ud_index);
+
+				for (j = 0; j < ud_param.buf_len; j++) {
+					PR_FILL("%02x ", pstart[j]);
+					if (((j + 1) & 0xf) == 0)
+						PR_INFO(DECODE_ID(hw));
+				}
+				PR_INFO(DECODE_ID(hw));
+			}
+		}
+
 		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
 			"%s: index %d poc %d frame_type %d dur %d type %x pts %d(0x%x), pts64 %lld(0x%x) ts %llu(0x%x)\n",
 			__func__, vf->index, frame->poc, vf->frame_type, vf->duration, vf->type, vf->pts, vf->pts,
@@ -10312,12 +10347,60 @@
 	int data_length;
 	struct mh264_userdata_record_t *p_userdata_rec;
 	struct vdec_s *vdec = hw_to_vdec(hw);
+	struct StorablePicture *p = p_H264_Dpb->mVideo.dec_picture;
+	u32 index;
 
 #ifdef MH264_USERDATA_ENABLE
 	struct userdata_meta_info_t meta_info;
 	memset(&meta_info, 0, sizeof(meta_info));
 #endif
 
+	if ((get_cur_slice_picture_struct(p_H264_Dpb) == FRAME)
+			|| (get_cur_slice_picture_struct(p_H264_Dpb) == TOP_FIELD))
+		index = 0;
+	else
+		index = 1;
+
+	if (p != NULL && p->buf_spec_num >= 0) {
+		struct buffer_spec_s *pic = &hw->buffer_spec[p->buf_spec_num];
+		struct userdata_param_t *ud_param = &(pic->ud_param[index]);
+		char *user_data_buf;
+		u32 size = pic->aux_data_size + index * SEI_ITU_DATA_SIZE;
+		user_data_buf = pic->aux_data_buf + size;
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_UD_DETAIL,
+				"%s: size %d/%d, index %d, sei_itu_data_len %d\n",
+				__func__, pic->aux_data_size, size, index, hw->sei_itu_data_len);
+
+		if ((size < SEI_BUF_SIZE) && (user_data_buf != NULL)) {
+			memset(user_data_buf, 0, SEI_ITU_DATA_SIZE);
+			if (hw->sei_itu_data_len < SEI_ITU_DATA_SIZE &&
+				(hw->sei_itu_data_len > 0)) {
+				memcpy(user_data_buf, hw->sei_itu_data_buf,
+					hw->sei_itu_data_len);
+				ud_param->buf_len = hw->sei_itu_data_len;
+			} else {
+				ud_param->buf_len = 0;
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_UD_DETAIL,
+					"set sei data len(%d) to 0\n", hw->sei_itu_data_len);
+			}
+		} else {
+			pic->ud_param[index].buf_len = 0;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_UD_DETAIL,
+					"set sei data len(%d) to 0, size(%d)\n", hw->sei_itu_data_len, size);
+		}
+		ud_param->pbuf_addr = user_data_buf;
+		ud_param->instance_id = vdec->afd_video_id;
+		ud_param->meta_info.duration = hw->frame_dur;
+		ud_param->meta_info.flags = (VFORMAT_H264 << 3);
+		ud_param->meta_info.poc_number =
+			p_H264_Dpb->mVideo.dec_picture->poc;
+		ud_param->meta_info.flags |=
+			p_H264_Dpb->mVideo.dec_picture->pic_struct << 12;
+		ud_param->meta_info.vpts = vpts;
+		ud_param->meta_info.vpts_valid = vpts_valid;
+	}
+
 	if (hw->sei_itu_data_len <= 0)
 		return;
 
diff --git a/drivers/frame_provider/decoder_v4l/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder_v4l/mpeg12/vmpeg12_multi.c
index 61b0e66..9356300 100644
--- a/drivers/frame_provider/decoder_v4l/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder_v4l/mpeg12/vmpeg12_multi.c
@@ -232,6 +232,10 @@
 	u64 timestamp;
 	u64 last_timestamp;
 	u32 poc;
+	char *user_data_buf;
+	struct userdata_param_t ud_param;
+	int user_data_size;
+	int ctx_buf_idx;
 };
 
 struct vdec_mpeg12_hw_s {
@@ -372,6 +376,10 @@
 	u32 chunk_offset;
 	u32 consume_byte;
 	int last_dur;
+	u8  parse_user_data_buf[CCBUF_SIZE];
+	u32 parse_user_data_size;
+	struct userdata_meta_info_t meta_info;
+	u32 vf_ucode_cc_last_wp;
 };
 static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
 static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
@@ -571,6 +579,9 @@
 		decbuf_start, decbuf_uv_start,
 		canvas_width, canvas_height);
 
+	ctx->aux_infos.bind_sei_buffer(ctx, &hw->pics[i].user_data_buf,
+			&hw->pics[i].user_data_size, &hw->pics[i].ctx_buf_idx);
+
 	aml_buf_get_ref(&ctx->bm, aml_buf);
 
 	hw->aml_buf = NULL;
@@ -1505,7 +1516,9 @@
 {
 	u32 reg;
 	u8 *pdata;
+	u8 *p_user_data;
 	u8 *psrc_data;
+	u8 *vf_psrc_data;
 	u8 head_info[8];
 	struct userdata_meta_info_t meta_info;
 	u32 wp;
@@ -1515,6 +1528,7 @@
 	u32 picture_type;
 	u32 temp;
 	u32 data_length;
+	u32 vf_data_length;
 	u32 data_start;
 	int i;
 	u32 offset;
@@ -1560,6 +1574,8 @@
 
 	if (cur_wp < hw->ucode_cc_last_wp)
 		hw->ucode_cc_last_wp = 0;
+	if (cur_wp < hw->vf_ucode_cc_last_wp)
+		hw->vf_ucode_cc_last_wp = 0;
 
 	offset = READ_VREG(AV_SCRATCH_I);
 
@@ -1586,10 +1602,11 @@
 	picture_type = (temp >> 10) & 0x7;
 
 	if (debug_enable & PRINT_FLAG_USERDATA_DETAIL)
-		pr_info("index:%d, wp:%d, ref:%d, type:%d, struct:0x%x, u_last_wp:0x%x\n",
+		pr_info("index:%d, wp:%d, ref:%d, type:%d, struct:0x%x, u_last_wp:0x%x, vf_last_wp:0x%x\n",
 			index, wp, reference,
 			picture_type, picture_struct,
-			hw->ucode_cc_last_wp);
+			hw->ucode_cc_last_wp,
+			hw->vf_ucode_cc_last_wp);
 
 	switch (picture_type) {
 	case 1:
@@ -1640,6 +1657,27 @@
 	if (psrc_data)
 		v4l_vmpeg2_fill_userdata(hw, psrc_data, data_length, meta_info.flags);
 
+	vf_data_length = cur_wp - hw->vf_ucode_cc_last_wp;
+	if (vf_data_length == 0) {
+		hw->vf_ucode_cc_last_wp = hw->ucode_cc_last_wp;
+		vf_data_length = cur_wp - hw->vf_ucode_cc_last_wp;
+	}
+
+	vf_psrc_data = (u8 *)hw->ccbuf_phyAddress_virt + hw->vf_ucode_cc_last_wp;
+	if (debug_enable & PRINT_FLAG_USERDATA_DETAIL)
+	{
+		int i = 0;
+		u8 *pstart = (u8 *)vf_psrc_data;
+		PR_INIT(128);
+		debug_print(DECODE_ID(hw), 0,"%s:data_length %d.\n", __func__, vf_data_length);
+		for (i = 0; i < vf_data_length; i++) {
+			PR_FILL("%02x ", pstart[i]);
+			if (((i + 1) & 0xf) == 0)
+				PR_INFO(DECODE_ID(hw));
+		}
+		PR_INFO(DECODE_ID(hw));
+	}
+
 	pdata = hw->userdata_info.data_buf + hw->userdata_info.last_wp;
 	for (i = 0; i < data_length && hw->ccbuf_phyAddress_virt != NULL && psrc_data; i++) {
 		*pdata++ = *psrc_data++;
@@ -1647,9 +1685,20 @@
 			pdata = hw->userdata_info.data_buf;
 	}
 
+	p_user_data = hw->parse_user_data_buf + hw->parse_user_data_size;
+	for (i = 0; i < vf_data_length && hw->ccbuf_phyAddress_virt != NULL && vf_psrc_data; i++) {
+		if (hw->parse_user_data_size < CCBUF_SIZE) {
+			*p_user_data++ = *vf_psrc_data++;
+			hw->parse_user_data_size++;
+		} else {
+			debug_print(DECODE_ID(hw), 0,"%s: user data is over %d.\n", __func__, vf_data_length);
+		}
+	}
+
 	pcur_ud_rec = hw->ud_record + hw->cur_ud_idx;
 
 	pcur_ud_rec->meta_info = meta_info;
+	hw->meta_info = meta_info;
 	pcur_ud_rec->rec_start = hw->userdata_info.last_wp;
 	pcur_ud_rec->rec_len = data_length;
 
@@ -1660,6 +1709,7 @@
 	hw->wait_for_udr_send = 1;
 
 	hw->ucode_cc_last_wp = cur_wp;
+	hw->vf_ucode_cc_last_wp = cur_wp;
 
 	if (debug_enable & PRINT_FLAG_USERDATA_DETAIL)
 		pr_info("cur_wp:%d, rec_start:%d, rec_len:%d, poc %d\n",
@@ -1704,6 +1754,8 @@
 	hw->ucode_cc_last_wp = hw->notify_ucode_cc_last_wp;
 	hw->cur_ud_idx = 0;
 	hw->wait_for_udr_send = 0;
+	hw->parse_user_data_size = 0;
+	memset(hw->parse_user_data_buf, 0, CCBUF_SIZE);
 }
 
 static void v4l_mpeg12_collect_stream_info(struct vdec_s *vdec,
@@ -1861,6 +1913,8 @@
 	}
 
 	user_data_ready_notify(hw, pic->pts, pic->pts_valid);
+	pic->ud_param.meta_info.vpts = pic->pts;
+	pic->ud_param.meta_info.vpts_valid = pic->pts_valid;
 
 	if (hw->frame_prog & PICINFO_PROG) {
 		field_num = 1;
@@ -2059,6 +2113,26 @@
 					&hw->gvs, vf, pic->hw_decode_time);
 				v4l_mpeg12_update_frame_info(hw, vf, pic);
 			}
+
+			vf->vf_ud_param.magic_code = UD_MAGIC_CODE;
+			vf->vf_ud_param.ud_param = pic->ud_param;
+
+			if (debug_enable & PRINT_FLAG_USERDATA_DETAIL)
+			{
+				struct userdata_param_t ud_param = pic->ud_param;
+				int i = 0;
+				u8 *pstart = (u8 *)ud_param.pbuf_addr;
+				PR_INIT(128);
+				debug_print(DECODE_ID(hw), 0,"%s:userdata len %d. vdec %p video_id %d\n",
+					__func__,ud_param.buf_len, vdec, ud_param.instance_id);
+				for (i = 0; i < ud_param.buf_len; i++) {
+					PR_FILL("%02x ", pstart[i]);
+					if (((i + 1) & 0xf) == 0)
+						PR_INFO(DECODE_ID(hw));
+				}
+				PR_INFO(DECODE_ID(hw));
+			}
+
 			vdec->vdec_fps_detec(vdec->id);
 			if (!vdec->is_v4l && !vdec->vbuf.use_ptsserv && vdec_stream_based(vdec)) {
 				/* offset for tsplayer pts lookup */
@@ -2357,6 +2431,47 @@
 	hw->cur_idx = INVALID_IDX;
 }
 
+static void copy_user_data_to_pic(struct vdec_mpeg12_hw_s *hw, struct pic_info_t *pic)
+{
+	struct vdec_s *vdec = hw_to_vdec(hw);
+
+
+	if (pic->user_data_buf != NULL) {
+		memset(pic->user_data_buf, 0, CCBUF_SIZE);
+		if (hw->parse_user_data_size < CCBUF_SIZE) {
+			memcpy(pic->user_data_buf, hw->parse_user_data_buf, hw->parse_user_data_size);
+			pic->ud_param.buf_len = hw->parse_user_data_size;
+		} else {
+			pic->ud_param.buf_len = 0;
+			debug_print(DECODE_ID(hw), 0,
+				"sei data len is over 5k\n", hw->parse_user_data_size);
+		}
+	} else {
+		pic->ud_param.buf_len = 0;
+	}
+	pic->ud_param.pbuf_addr = pic->user_data_buf;
+	pic->ud_param.meta_info = hw->meta_info;
+	pic->ud_param.instance_id = vdec->afd_video_id;
+	pic->ud_param.meta_info.poc_number = pic->poc;
+	pic->ud_param.meta_info.flags &= 0xFFFFFC7F; //bit7~bit9: ud frame type
+
+	if ((pic->buffer_info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I)
+		pic->ud_param.meta_info.flags |= (1<<7);
+	else if ((pic->buffer_info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)
+		pic->ud_param.meta_info.flags |= (2<<7);
+	else if ((pic->buffer_info & PICINFO_TYPE_MASK) == PICINFO_TYPE_B)
+		pic->ud_param.meta_info.flags |= (3<<7);
+	else
+		debug_print(DECODE_ID(hw), PRINT_FLAG_USERDATA_DETAIL, "pic type invalid\n");
+
+	debug_print(DECODE_ID(hw), PRINT_FLAG_USERDATA_DETAIL,
+			"%s: poc %d, flags 0x%x\n", __func__,
+			pic->ud_param.meta_info.poc_number, pic->ud_param.meta_info.flags);
+
+	hw->parse_user_data_size = 0;
+	memset(hw->parse_user_data_buf, 0, CCBUF_SIZE);
+}
+
 static irqreturn_t vmpeg12_isr_thread_handler(struct vdec_s *vdec, int irq)
 {
 	u32 reg, index, info, seqinfo, offset, frame_size=0, tmp_h, tmp_w;
@@ -2597,6 +2712,9 @@
 		new_pic->offset = offset;
 		new_pic->index = index;
 		new_pic->poc = READ_VREG(AV_SCRATCH_1) & 0x3ff;
+
+		copy_user_data_to_pic(hw, new_pic);
+
 		if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) ||
 			((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)) {
 			if (hw->chunk) {
@@ -4593,6 +4711,12 @@
 		hw->vmpeg12_amstream_dec_info.height,
 		hw->tvp_flag);
 
+	if (hw->v4l2_ctx != NULL) {
+		struct aml_vcodec_ctx *ctx = hw->v4l2_ctx;
+
+		ctx->aux_infos.alloc_buffer(ctx, SEI_TYPE);
+	}
+
 	if (vmpeg12_init(hw) < 0) {
 		pr_info("ammvdec_mpeg12 init failed.\n");
 		if (hw) {