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