media: add aux data crc in h264 and h265 stream. [1/1]
authorGan Zhang <gan.zhang@amlogic.com>
Fri, 26 Jun 2020 08:04:58 +0000 (16:04 +0800)
committergan.zhang <gan.zhang@amlogic.com>
Fri, 25 Sep 2020 02:15:12 +0000 (10:15 +0800)
PD#SWPL-25416

Problem:
no aux data crc info.

Solution:
add aux data crc in h264 and h265 stream.

Verify:
AC214

Change-Id: Ie9675b154cc45c144d4d11bb4afe7f859cc75aed
Signed-off-by: Gan Zhang <gan.zhang@amlogic.com>
drivers/frame_provider/decoder/h264_multi/vmh264.c
drivers/frame_provider/decoder/h265/vh265.c
drivers/frame_provider/decoder/utils/frame_check.c
drivers/frame_provider/decoder/utils/frame_check.h
drivers/frame_provider/decoder/utils/vdec.h

index d455516276fb6281887f387c046cc074784788fb..17318c7839c5688507e4f3ec091830b1d127d2de 100644 (file)
@@ -3071,6 +3071,10 @@ static int post_video_frame(struct vdec_s *vdec, struct FrameStore *frame)
                ATRACE_COUNTER(MODULE_NAME, vf->pts);
                hw->vf_pre_count++;
                vdec->vdec_fps_detec(vdec->id);
+#ifdef AUX_DATA_CRC
+               decoder_do_aux_data_check(vdec, hw->buffer_spec[buffer_index].aux_data_buf,
+                       hw->buffer_spec[buffer_index].aux_data_size);
+#endif
                if (without_display_mode == 0) {
                        vf_notify_receiver(vdec->vf_provider_name,
                                VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
@@ -10098,6 +10102,10 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
                        USER_DATA_SIZE);
 #endif
 
+#ifdef AUX_DATA_CRC
+       vdec_aux_data_check_init(pdata);
+#endif
+
        vdec_set_prepare_level(pdata, start_decode_buf_level);
        if (pdata->parallel_dec == 1) {
                if (hw->mmu_enable == 0)
@@ -10195,6 +10203,10 @@ static int ammvdec_h264_remove(struct platform_device *pdev)
 #endif
        /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */
 
+#ifdef AUX_DATA_CRC
+       vdec_aux_data_check_exit(vdec);
+#endif
+
        atomic_set(&hw->vh264_active, 0);
        if (vdec->parallel_dec == 1) {
                if (hw->mmu_enable == 0)
index eeb1eecbff70a4f34f1358f806f0c32eb1bc5f6b..f58f0c3dada426eff4184903a9cdb07f94cab818 100644 (file)
@@ -9492,6 +9492,10 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                        get_pic_poc(hevc, (vf->index >> 8) & 0xff),
                        vf->pts, vf->pts_us64,
                        vf->duration);
+#ifdef AUX_DATA_CRC
+               decoder_do_aux_data_check(vdec, hevc->m_PIC[vf->index & 0xff]->aux_data_buf,
+                       hevc->m_PIC[vf->index & 0xff]->aux_data_size);
+#endif
 
                /*if (pic->vf_ref == hevc->vf_pre_count) {*/
                if (hevc->kpi_first_i_decoded == 0) {
@@ -13853,6 +13857,10 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+#ifdef AUX_DATA_CRC
+       vdec_aux_data_check_init(pdata);
+#endif
+
        vdec_set_prepare_level(pdata, start_decode_buf_level);
 
        /*set the max clk for smooth playing...*/
@@ -13878,6 +13886,10 @@ static int ammvdec_h265_remove(struct platform_device *pdev)
                return 0;
        vdec = hw_to_vdec(hevc);
 
+#ifdef AUX_DATA_CRC
+       vdec_aux_data_check_exit(vdec);
+#endif
+
        //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
        if (get_dbg_flag(hevc))
                hevc_print(hevc, 0, "%s\r\n", __func__);
index 5cdac0eae575d869722bced38e426bf7e6b96d8d..f2f55d676730a6f9efa4b40c01804a377c950921 100644 (file)
 #define FC_TST_DEBUG   0x80
 #define FC_ERR_CRC_BLOCK_MODE  0x10
 #define FC_CHECK_CRC_LOOP_MODE 0x20
+#define AD_CHECK_CRC_LOOP_MODE 0x40
 
 #define YUV_MASK       0x01
 #define CRC_MASK       0x02
+#define AUX_MASK       0x04
+
 
 #define MAX_YUV_SIZE (4096 * 2304)
 #define YUV_DEF_SIZE (MAX_YUV_SIZE * 3 / 2)
@@ -76,10 +79,12 @@ static unsigned int size_yuv_buf = (YUV_DEF_SIZE * YUV_DEF_NUM);
 #define CRC_PATH  "/data/tmp/"
 #define YUV_PATH  "/data/tmp/"
 static char comp_crc[128] = "name";
+static char aux_comp_crc[128] = "aux";
 
 static struct vdec_s *single_mode_vdec = NULL;
 
 static unsigned int yuv_enable, check_enable;
+static unsigned int aux_enable;
 static unsigned int yuv_start[MAX_INSTANCE_MUN];
 static unsigned int yuv_num[MAX_INSTANCE_MUN];
 
@@ -128,12 +133,29 @@ static inline void set_disable(struct pic_check_mgr_t *p, int mask)
        p->enable &= (~mask);
 }
 
+static inline void aux_set_enable(struct aux_data_check_mgr_t *p, int mask)
+{
+       p->enable |= mask;
+}
+
+static inline void aux_set_disable(struct aux_data_check_mgr_t *p, int mask)
+{
+       p->enable &= (~mask);
+}
+
+
 static inline void check_schedule(struct pic_check_mgr_t *mgr)
 {
        if (atomic_read(&mgr->work_inited))
                vdec_schedule_work(&mgr->frame_check_work);
 }
 
+static inline void aux_data_check_schedule(struct aux_data_check_mgr_t *mgr)
+{
+       if (atomic_read(&mgr->work_inited))
+               vdec_schedule_work(&mgr->aux_data_check_work);
+}
+
 static bool is_oversize(int w, int h)
 {
        if (w <= 0 || h <= 0)
@@ -288,6 +310,44 @@ static char *fget_crc_str(char *buf,
        return buf;
 }
 
+static char *fget_aux_data_crc_str(char *buf,
+       unsigned int size, struct aux_data_check_t *fc)
+{
+       unsigned int c = 0, sz, ret, index, crc;
+       mm_segment_t old_fs;
+       char *cs;
+
+       if (!fc->compare_fp)
+               return NULL;
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       do {
+               cs = buf;
+               sz = size;
+               while (--sz && (c = vfs_read(fc->compare_fp,
+                       cs, 1, &fc->compare_pos) != 0)) {
+                       if (*cs++ == '\n')
+                               break;
+               }
+               *cs = '\0';
+               if ((c == 0) && (cs == buf)) {
+                       set_fs(old_fs);
+                       return NULL;
+               }
+               ret = sscanf(buf, "%08u: %8x", &index, &crc);
+               dbg_print(FC_CRC_DEBUG, "%s, index = %d, cmp = %d\n",
+                       __func__, index, fc->cmp_crc_cnt);
+       }while(ret != 2 || index != fc->cmp_crc_cnt);
+
+       set_fs(old_fs);
+       fc->cmp_crc_cnt++;
+
+       return buf;
+}
+
+
 static struct file* file_open(int mode, const char *str, ...)
 {
        char file[256] = {0};
@@ -396,6 +456,42 @@ static int write_crc_work(struct pic_check_mgr_t *mgr)
        return 0;
 }
 
+
+static int write_aux_data_crc_work(struct aux_data_check_mgr_t *mgr)
+{
+       unsigned int wr_size;
+       char *crc_buf, crc_tmp[64*30];
+       mm_segment_t old_fs;
+       struct aux_data_check_t *check = &mgr->aux_data_check;
+
+       if (mgr->enable & AUX_MASK) {
+               wr_size = 0;
+               while (kfifo_get(&check->wr_chk_q, &crc_buf) != 0) {
+                       wr_size += sprintf(&crc_tmp[wr_size], "%s", crc_buf);
+                       if (check->compare_fp != NULL) {
+                               if (!fget_aux_data_crc_str(crc_buf, SIZE_CRC, check)) {
+                                       dbg_print(0, "%s, can't get more compare crc\n", __func__);
+                                       filp_close(check->compare_fp, current->files);
+                                       check->compare_fp = NULL;
+                               }
+                       }
+                       kfifo_put(&check->new_chk_q, crc_buf);
+               }
+               if (check->check_fp && (wr_size != 0)) {
+                       old_fs = get_fs();
+                       set_fs(KERNEL_DS);
+                       if (wr_size != vfs_write(check->check_fp,
+                               crc_tmp, wr_size, &check->check_pos)) {
+                               dbg_print(FC_ERROR, "failed to check_dump_filp\n");
+                       }
+                       set_fs(old_fs);
+               }
+       }
+       return 0;
+}
+
+
+
 static void do_check_work(struct work_struct *work)
 {
        struct pic_check_mgr_t *mgr = container_of(work,
@@ -406,6 +502,15 @@ static void do_check_work(struct work_struct *work)
        write_crc_work(mgr);
 }
 
+static void do_aux_data_check_work(struct work_struct *work)
+{
+       struct aux_data_check_mgr_t *mgr = container_of(work,
+               struct aux_data_check_mgr_t, aux_data_check_work);
+
+       write_aux_data_crc_work(mgr);
+}
+
+
 static int memcpy_phy_to_virt(char *to_virt,
        ulong phy_from, unsigned int size)
 {
@@ -659,6 +764,55 @@ static int crc_store(struct pic_check_mgr_t *mgr, struct vframe_s *vf,
        return ret;
 }
 
+static int aux_data_crc_store(struct aux_data_check_mgr_t *mgr,int crc)
+{
+       int ret = 0;
+       char *crc_addr = NULL;
+       int comp_frame = 0, comp_crc;
+       struct aux_data_check_t *check = &mgr->aux_data_check;
+
+       if (kfifo_get(&check->new_chk_q, &crc_addr) == 0) {
+               dbg_print(0, "%08d: %08x\n",
+                       mgr->frame_cnt, crc);
+               if (check->check_fp) {
+                       dbg_print(0, "crc32 dropped\n");
+               } else {
+                       dbg_print(0, "no opened file to write crc32\n");
+               }
+               return -1;
+       }
+       if (check->cmp_crc_cnt > mgr->frame_cnt) {
+               sscanf(crc_addr, "%08u: %8x",
+                       &comp_frame, &comp_crc);
+
+               dbg_print(0, "%08d: %08x <--> %08d: %08x\n",
+                       mgr->frame_cnt, crc,
+                       comp_frame, comp_crc);
+               if (comp_frame == mgr->frame_cnt) {
+                       if (comp_crc != crc) {
+                                       dbg_print(0, "\n\nError: %08d: %08x != %08x \n\n",
+                                               mgr->frame_cnt, crc, comp_crc);
+                       }
+               } else {
+                       dbg_print(0, "frame num error: frame_cnt(%d) frame_comp(%d)\n",
+                               mgr->frame_cnt, comp_frame);
+               }
+       } else {
+               dbg_print(0, "%08d: %08x\n", mgr->frame_cnt, crc);
+       }
+
+       if ((check->check_fp) && (crc_addr != NULL)) {
+               ret = snprintf(crc_addr, SIZE_CRC,
+                       "%08d: %08x\n", mgr->frame_cnt, crc);
+
+               kfifo_put(&check->wr_chk_q, crc_addr);
+               if ((mgr->frame_cnt & 0xf) == 0)
+                       aux_data_check_schedule(mgr);
+       }
+       return ret;
+}
+
+
 
 static int crc32_vmap_le(unsigned int *crc32,
        ulong phyaddr, unsigned int size)
@@ -818,6 +972,20 @@ static int do_check_yuv16(struct pic_check_mgr_t *mgr,
        return 0;
 }
 
+static int do_check_aux_data_crc(struct aux_data_check_mgr_t *mgr,
+       char *aux_buf, int size)
+{
+       unsigned int crc = 0;
+
+       crc = crc32_le(0, aux_buf, size);
+
+       //pr_info("%s:crc = %08x\n",crc);
+       aux_data_crc_store(mgr,crc);
+
+       return 0;
+}
+
+
 static int fbc_check_prepare(struct pic_check_t *check,
        int resize, int y_size)
 {
@@ -1018,6 +1186,29 @@ int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf)
 }
 EXPORT_SYMBOL(decoder_do_frame_check);
 
+int decoder_do_aux_data_check(struct vdec_s *vdec, char *aux_buffer, int size)
+{
+       struct aux_data_check_mgr_t *mgr = NULL;
+       int ret = 0;
+
+       if (vdec == NULL) {
+               return 0;
+       } else {
+               mgr = &vdec->adc;
+       }
+
+       if ((mgr == NULL) || (mgr->enable == 0))
+               return 0;
+
+       if (mgr->enable & AUX_MASK)
+               ret = do_check_aux_data_crc(mgr,aux_buffer,size);
+
+       mgr->frame_cnt++;
+
+       return ret;
+}
+EXPORT_SYMBOL(decoder_do_aux_data_check);
+
 static int dump_buf_alloc(struct pic_dump_t *dump)
 {
        if ((dump->buf_addr != NULL) &&
@@ -1132,6 +1323,63 @@ int frame_check_init(struct pic_check_mgr_t *mgr, int id)
        return 0;
 }
 
+
+int aux_data_check_init(struct aux_data_check_mgr_t *mgr, int id)
+{
+       int i;
+       struct aux_data_check_t *check = &mgr->aux_data_check;
+
+       mgr->frame_cnt = 0;
+       mgr->id = id;
+
+       check->check_pos = 0;
+       check->compare_pos = 0;
+
+       if (!atomic_read(&mgr->work_inited)) {
+               INIT_WORK(&mgr->aux_data_check_work, do_aux_data_check_work);
+               atomic_set(&mgr->work_inited, 1);
+       }
+
+       /* try to open compare meta crc32 file */
+       str_strip(aux_comp_crc);
+       check->compare_fp = file_open(O_RDONLY,
+               "%s%s", CRC_PATH, aux_comp_crc);
+
+       /* create meta crc log file */
+       check->check_fp = file_open(O_CREAT| O_WRONLY | O_TRUNC,
+               "%s%s-%d-%d.crc", CRC_PATH, aux_comp_crc, id, mgr->file_cnt);
+
+       INIT_KFIFO(check->new_chk_q);
+       INIT_KFIFO(check->wr_chk_q);
+       check->check_addr = vmalloc(SIZE_CRC * SIZE_CHECK_Q);
+       if (check->check_addr == NULL) {
+               dbg_print(FC_ERROR, "vmalloc qbuf fail\n");
+       } else {
+               void *qaddr = NULL, *rdret = NULL;
+               check->cmp_crc_cnt = 0;
+               for (i = 0; i < SIZE_CHECK_Q; i++) {
+                       qaddr = check->check_addr + i * SIZE_CRC;
+                       rdret = fget_aux_data_crc_str(qaddr,
+                               SIZE_CRC, check);
+                       if (rdret == NULL) {
+                               if (i < 3)
+                                       dbg_print(0, "can't get compare crc string\n");
+                               if (check->compare_fp) {
+                                       filp_close(check->compare_fp, current->files);
+                                       check->compare_fp = NULL;
+                               }
+                       }
+
+                       kfifo_put(&check->new_chk_q, qaddr);
+               }
+       }
+       aux_set_enable(mgr, AUX_MASK);
+       dbg_print(0, "%s end\n", __func__);
+
+       return 0;
+}
+
+
 void frame_check_exit(struct pic_check_mgr_t *mgr)
 {
        int i;
@@ -1190,6 +1438,40 @@ void frame_check_exit(struct pic_check_mgr_t *mgr)
        }
 }
 
+void aux_data_check_exit(struct aux_data_check_mgr_t *mgr)
+{
+       //struct pic_dump_t *dump = &mgr->pic_dump;
+       struct aux_data_check_t *check = &mgr->aux_data_check;
+
+       if (mgr->enable != 0) {
+               if (atomic_read(&mgr->work_inited)) {
+                       cancel_work_sync(&mgr->aux_data_check_work);
+                       atomic_set(&mgr->work_inited, 0);
+               }
+
+               write_aux_data_crc_work(mgr);
+
+               if (check->check_addr) {
+                       vfree(check->check_addr);
+                       check->check_addr = NULL;
+               }
+
+               if (check->check_fp) {
+                       filp_close(check->check_fp, current->files);
+                       check->check_fp = NULL;
+               }
+               if (check->compare_fp) {
+                       filp_close(check->compare_fp, current->files);
+                       check->compare_fp = NULL;
+               }
+
+               mgr->file_cnt++;
+               aux_set_disable(mgr, AUX_MASK);
+               dbg_print(0, "%s end\n", __func__);
+       }
+}
+
+
 
 int vdec_frame_check_init(struct vdec_s *vdec)
 {
@@ -1296,6 +1578,43 @@ int print_decoder_info(struct vdec_s *vdec)
        return 0;
 }
 
+int vdec_aux_data_check_init(struct vdec_s *vdec)
+{
+       int ret = 0, id = 0;
+
+       if (vdec == NULL)
+               return 0;
+
+       if ((vdec->is_reset) &&
+               (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXL))
+               return 0;
+
+       if (!aux_enable)
+               return 0;
+
+       id = vdec->id;
+
+       if (aux_enable & (0x01 << id)) {
+               aux_data_check_init(&vdec->adc, id);
+               /*repeat check one video meta crc32, not clear enable*/
+               if ((fc_debug & AD_CHECK_CRC_LOOP_MODE) == 0)
+                       aux_enable &= ~(0x01 << id);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(vdec_aux_data_check_init);
+
+
+void vdec_aux_data_check_exit(struct vdec_s *vdec)
+{
+       if (vdec == NULL)
+               return;
+       aux_data_check_exit(&vdec->adc);
+}
+EXPORT_SYMBOL(vdec_aux_data_check_exit);
+
+
 void vdec_frame_check_exit(struct vdec_s *vdec)
 {
        if (vdec == NULL)
@@ -1411,9 +1730,16 @@ ssize_t frame_check_show(struct class *class,
 module_param_string(comp_crc, comp_crc, 128, 0664);
 MODULE_PARM_DESC(comp_crc, "\n crc_filename\n");
 
+module_param_string(aux_comp_crc, aux_comp_crc, 128, 0664);
+MODULE_PARM_DESC(aux_comp_crc, "\n aux crc_filename\n");
+
+
 module_param(fc_debug, uint, 0664);
 MODULE_PARM_DESC(fc_debug, "\n frame check debug\n");
 
+module_param(aux_enable, uint, 0664);
+MODULE_PARM_DESC(aux_enable, "\n aux data check debug\n");
+
 module_param(size_yuv_buf, uint, 0664);
 MODULE_PARM_DESC(size_yuv_buf, "\n size_yuv_buf\n");
 
index 9d6a1d7f51e1da68606f40fbf36326f5bf41c4e2..e98337764565235a03f8877a92a7b9e7d7954644 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/kfifo.h>
 
 #define FRAME_CHECK
+#define AUX_DATA_CRC
+
 
 #define YUV_MAX_DUMP_NUM  60
 
@@ -58,6 +60,20 @@ struct pic_check_t{
        DECLARE_KFIFO(wr_chk_q, char *, SIZE_CHECK_Q);
 };
 
+struct aux_data_check_t{
+       struct file *check_fp;
+       loff_t check_pos;
+
+       struct file *compare_fp;
+       loff_t compare_pos;
+       unsigned int cmp_crc_cnt;
+       void *check_addr;
+
+       DECLARE_KFIFO(new_chk_q, char *, SIZE_CHECK_Q);
+       DECLARE_KFIFO(wr_chk_q, char *, SIZE_CHECK_Q);
+};
+
+
 struct pic_check_mgr_t{
        int id;
        int enable;
@@ -94,11 +110,29 @@ struct pic_check_mgr_t{
        u32 height;
 };
 
+struct aux_data_check_mgr_t{
+       int id;
+       int enable;
+       unsigned int frame_cnt;
+       /* pic info */
+       int aux_size;
+       char *aux_addr;
+
+       int file_cnt;
+       atomic_t work_inited;
+       struct work_struct aux_data_check_work;
+
+       struct aux_data_check_t aux_data_check;
+};
+
+
 int dump_yuv_trig(struct pic_check_mgr_t *mgr,
        int id, int start, int num);
 
 int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf);
 
+int decoder_do_aux_data_check(struct vdec_s *vdec, char *aux_buffer, int size);
+
 int frame_check_init(struct pic_check_mgr_t *mgr, int id);
 
 void frame_check_exit(struct pic_check_mgr_t *mgr);
@@ -120,5 +154,9 @@ ssize_t dump_yuv_store(struct class *class,
 void vdec_frame_check_exit(struct vdec_s *vdec);
 int vdec_frame_check_init(struct vdec_s *vdec);
 
+void vdec_aux_data_check_exit(struct vdec_s *vdec);
+int vdec_aux_data_check_init(struct vdec_s *vdec);
+
+
 #endif /* __FRAME_CHECK_H__ */
 
index 0a98c746213093abe1aad3d1c1c8834a71a6a25f..bf1b4111d51ceda33cd6875541345ae2dac7f74f 100644 (file)
@@ -274,6 +274,9 @@ struct vdec_s {
        int parallel_dec;
        struct vdec_frames_s *mvfrm;
        struct vdec_sync sync;
+
+       /*aux data check*/
+       struct aux_data_check_mgr_t adc;
 };
 
 /* common decoder vframe provider name to use default vfm path */