mpeg12: fix frame mode interlace data insufficient. [1/1]
authorshihong.zheng <shihong.zheng@amlogic.com>
Tue, 11 Aug 2020 04:28:36 +0000 (12:28 +0800)
committerGan Zhang <gan.zhang@amlogic.com>
Mon, 17 Aug 2020 05:45:27 +0000 (13:45 +0800)
PD#SWPL-30096

Problem:
decode timeout repeatly when use android raw extractor.
cts failed. interlace mpeg12 two slices in two packets.

Solution:
add data request status send more chunk for decode when
data insufficient.

ucode gerrit id: 120436
ucode commit id: 713286
ucode change id: I517c3

Verify:
ah212

Change-Id: Ieeb93c93290ab8b6fcf31b30ea63dddcf01cf47b
Signed-off-by: shihong.zheng <shihong.zheng@amlogic.com>
drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
firmware/video_ucode.bin

index 8a0bb194fdbee99cba969585a18196db481cbaed..ef45eb8d3ec545aef8d414f2256a1c8e53539d13 100644 (file)
@@ -160,6 +160,18 @@ enum {
        FRAME_REPEAT_BOT,
        FRAME_REPEAT_NONE
 };
+
+/*Send by AV_SCRATCH_9*/
+#define MPEG12_PIC_DONE     1
+#define MPEG12_DATA_EMPTY   2
+#define MPEG12_SEQ_END      3
+#define MPEG12_DATA_REQUEST 4
+
+/*Send by AV_SCRATCH_G*/
+#define MPEG12_V4L2_INFO_NOTIFY 1
+/*Send by AV_SCRATCH_J*/
+#define MPEG12_USERDATA_DONE 0x8000
+
 #define DEC_RESULT_NONE     0
 #define DEC_RESULT_DONE     1
 #define DEC_RESULT_AGAIN    2
@@ -173,15 +185,6 @@ enum {
 #define DECODE_ID(hw) (hw_to_vdec(hw)->id)
 #define DECODE_STOP_POS         AV_SCRATCH_K
 
-static struct vframe_s *vmpeg_vf_peek(void *);
-static struct vframe_s *vmpeg_vf_get(void *);
-static void vmpeg_vf_put(struct vframe_s *, void *);
-static int vmpeg_vf_states(struct vframe_states *states, void *);
-static int vmpeg_event_cb(int type, void *data, void *private_data);
-static int notify_v4l_eos(struct vdec_s *vdec);
-
-
-
 struct mmpeg2_userdata_record_t {
        struct userdata_meta_info_t meta_info;
        u32 rec_start;
@@ -334,6 +337,13 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
 static void reset_process_time(struct vdec_mpeg12_hw_s *hw);
 static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw);
 static void flush_output(struct vdec_mpeg12_hw_s *hw);
+static struct vframe_s *vmpeg_vf_peek(void *);
+static struct vframe_s *vmpeg_vf_get(void *);
+static void vmpeg_vf_put(struct vframe_s *, void *);
+static int vmpeg_vf_states(struct vframe_states *states, void *);
+static int vmpeg_event_cb(int type, void *data, void *private_data);
+static int notify_v4l_eos(struct vdec_s *vdec);
+static void start_process_time_set(struct vdec_mpeg12_hw_s *hw);
 
 static int debug_enable;
 /*static struct work_struct userdata_push_work;*/
@@ -505,7 +515,6 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
        return 0;
 }
 
-
 static unsigned int vmpeg12_get_buf_num(struct vdec_mpeg12_hw_s *hw)
 {
        unsigned int buf_num = DECODE_BUFFER_NUM_DEF;
@@ -1294,7 +1303,8 @@ static void vmmpeg2_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
 
        if (hw) {
                mutex_lock(&hw->userdata_mutex);
-               pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n",
+               pr_info("%s: bInit: %d, ri: %d, wi: %d\n",
+                       __func__,
                        bInit,
                        hw->userdata_info.read_index,
                        hw->userdata_info.write_index);
@@ -1860,24 +1870,38 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
        }
 
        reg = READ_VREG(AV_SCRATCH_J);
-       if (reg & (1<<16)) {
+       if (reg & (1 << 16)) {
                vdec_schedule_work(&hw->userdata_push_work);
                return IRQ_HANDLED;
        }
 
        reg = READ_VREG(MREG_BUFFEROUT);
-       if (reg == 2) {
+       if (reg == MPEG12_DATA_REQUEST) {
+               debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
+                       "%s: data request, bcnt=%x\n",
+                       __func__, READ_VREG(VIFF_BIT_CNT));
+               if (vdec_frame_based(vdec)) {
+                       reset_process_time(hw);
+                       hw->dec_result = DEC_RESULT_GET_DATA;
+                       vdec_schedule_work(&hw->work);
+               }
+       } else if (reg == MPEG12_DATA_EMPTY) {
                /*timeout when decoding next frame*/
                debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL,
-                       "mmpeg12: lack data, lvl=%x ctrl=%x bcnt=%x\n",
+                       "%s: Insufficient data, lvl=%x ctrl=%x bcnt=%x\n",
+                       __func__,
                        READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                        READ_VREG(VLD_MEM_VIFIFO_CONTROL),
                        READ_VREG(VIFF_BIT_CNT));
-
                if (vdec_frame_based(vdec)) {
-                       /* vmpeg12_save_hw_context(hw); */
-                       reset_process_time(hw);
-                       hw->dec_result = DEC_RESULT_DONE;
+                       u32 bitcnt = READ_VREG(VIFF_BIT_CNT);
+                       if (bitcnt < 32) {
+                               reset_process_time(hw);
+                               hw->dec_result = DEC_RESULT_GET_DATA;
+                       } else {
+                               userdata_pushed_drop(hw);
+                               hw->dec_result = DEC_RESULT_DONE;
+                       }
                        vdec_schedule_work(&hw->work);
                } else {
                        hw->dec_result = DEC_RESULT_AGAIN;
@@ -1886,7 +1910,7 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
                        reset_process_time(hw);
                }
                return IRQ_HANDLED;
-       } else {
+       } else {  /* MPEG12_PIC_DONE, MPEG12_SEQ_END */
                reset_process_time(hw);
 
                info = READ_VREG(MREG_PIC_INFO);
@@ -2135,6 +2159,8 @@ static int notify_v4l_eos(struct vdec_s *vdec)
 static void vmpeg12_work_implement(struct vdec_mpeg12_hw_s *hw,
        struct vdec_s *vdec, int from)
 {
+       int r;
+
        if (hw->dec_result != DEC_RESULT_DONE)
                debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
                        "%s, result=%d, status=%d\n", __func__,
@@ -2173,6 +2199,39 @@ static void vmpeg12_work_implement(struct vdec_mpeg12_hw_s *hw,
                vdec_vframe_dirty(vdec, hw->chunk);
                hw->chunk = NULL;
                vdec_clean_input(vdec);
+
+               r = vdec_prepare_input(vdec, &hw->chunk);
+               if (r < 0) {
+                       hw->input_empty++;
+                       reset_process_time(hw);
+                       hw->dec_result = DEC_RESULT_GET_DATA;
+                       debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+                               "%s: Insufficient data, get data retry\n", __func__);
+                       vdec_schedule_work(&hw->work);
+                       return;
+               }
+               hw->input_empty = 0;
+               if (vdec_frame_based(vdec) && (hw->chunk != NULL)) {
+                       r = hw->chunk->size +
+                               (hw->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+                       WRITE_VREG(VIFF_BIT_CNT, r * 8);
+                       if (vdec->mvfrm)
+                               vdec->mvfrm->frame_size += hw->chunk->size;
+               }
+               debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+                       "%s: %x %x %x size %d, bitcnt %d\n",
+                       __func__,
+                       READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+                       READ_VREG(VLD_MEM_VIFIFO_WP),
+                       READ_VREG(VLD_MEM_VIFIFO_RP),
+                       r, READ_VREG(VIFF_BIT_CNT));
+               vdec_enable_input(vdec);
+               hw->dec_result = DEC_RESULT_NONE;
+               hw->last_vld_level = 0;
+               start_process_time_set(hw);
+               hw->init_flag = 1;
+               mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+               WRITE_VREG(MREG_BUFFEROUT, 0);
                return;
        } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) {
                debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
@@ -2612,7 +2671,8 @@ static void reset_process_time(struct vdec_mpeg12_hw_s *hw)
                        max_process_time[DECODE_ID(hw)] = process_time;
        }
 }
-static void start_process_time(struct vdec_mpeg12_hw_s *hw)
+
+static void start_process_time_set(struct vdec_mpeg12_hw_s *hw)
 {
        if ((hw->refs[1] != -1) && (hw->refs[0] == -1))
                hw->decode_timeout_count = 1;
@@ -2620,6 +2680,7 @@ static void start_process_time(struct vdec_mpeg12_hw_s *hw)
                hw->decode_timeout_count = 10;
        hw->start_process_time = jiffies;
 }
+
 static void timeout_process(struct vdec_mpeg12_hw_s *hw)
 {
        struct vdec_s *vdec = hw_to_vdec(hw);
@@ -2690,7 +2751,7 @@ static void check_timer_func(unsigned long arg)
 
 static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
 {
-       u32 index, i;
+       u32 index = -1, i;
        struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
 
        index = find_free_buffer(hw);
@@ -3068,6 +3129,15 @@ void (*callback)(struct vdec_s *, void *),
                return;
        }
 
+       hw->input_empty = 0;
+       if ((vdec_frame_based(vdec)) &&
+               (hw->chunk != NULL)) {
+               size = hw->chunk->size +
+                       (hw->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+               WRITE_VREG(VIFF_BIT_CNT, size * 8);
+               if (vdec->mvfrm)
+                       vdec->mvfrm->frame_size = hw->chunk->size;
+       }
        if (vdec_frame_based(vdec) && !vdec_secure(vdec)) {
                /* HW needs padding (NAL start) for frame ending */
                char* tail = (char *)hw->chunk->block->start_virt;
@@ -3080,7 +3150,7 @@ void (*callback)(struct vdec_s *, void *),
                codec_mm_dma_flush(tail, 4, DMA_TO_DEVICE);
        }
 
-       if (vdec_frame_based(vdec) && debug_enable) {
+       if (vdec_frame_based(vdec) && debug_enable && !vdec_secure(vdec)) {
                u8 *data = NULL;
                if (hw->chunk)
                        debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
@@ -3107,42 +3177,32 @@ void (*callback)(struct vdec_s *, void *),
                if (debug_enable & PRINT_FRAMEBASE_DATA
                        ) {
                        int jj;
-
+                       debug_print(DECODE_ID(hw), PRINT_FRAMEBASE_DATA,
+                               "frame data:\n");
                        for (jj = 0; jj < size; jj++) {
                                if ((jj & 0xf) == 0)
-                                       debug_print(DECODE_ID(hw),
-                                       PRINT_FRAMEBASE_DATA,
-                                               "%06x:", jj);
-                               debug_print(DECODE_ID(hw),
-                               PRINT_FRAMEBASE_DATA,
-                                       "%02x ", data[jj]);
+                                       pr_info("%06x:", jj);
+                               pr_info("%02x ", data[jj]);
                                if (((jj + 1) & 0xf) == 0)
-                                       debug_print(DECODE_ID(hw),
-                                       PRINT_FRAMEBASE_DATA,
-                                               "\n");
+                                       pr_info("\n");
                        }
+                       pr_info("\n");
                }
 
                if (!hw->chunk->block->is_mapped)
                        codec_mm_unmap_phyaddr(data);
-       } else
+       } else {
                debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
-                       "%s: %x %x %x %x %x size 0x%x\n",
+                       "%s: %x %x %x %x %x size 0x%x, bitcnt %d\n",
                        __func__,
                        READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                        READ_VREG(VLD_MEM_VIFIFO_WP),
                        READ_VREG(VLD_MEM_VIFIFO_RP),
                        STBUF_READ(&vdec->vbuf, get_rp),
                        STBUF_READ(&vdec->vbuf, get_wp),
-                       size);
-
-       if (vdec->mvfrm && hw->chunk)
-               vdec->mvfrm->frame_size = hw->chunk->size;
-
-       hw->input_empty = 0;
-       vdec_enable_input(vdec);
+                       size, READ_VREG(VIFF_BIT_CNT));
+       }
 
-       hw->dec_result = DEC_RESULT_NONE;
        if (vdec->mc_loaded) {
        /*firmware have load before,
          and not changes to another.
@@ -3161,6 +3221,7 @@ void (*callback)(struct vdec_s *, void *),
                vdec->mc_loaded = 1;
                vdec->mc_type = VFORMAT_MPEG12;
        }
+
        if (vmpeg12_hw_ctx_restore(hw) < 0) {
                hw->dec_result = DEC_RESULT_ERROR;
                debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
@@ -3169,9 +3230,11 @@ void (*callback)(struct vdec_s *, void *),
                return;
        }
        /*wmb();*/
+       hw->dec_result = DEC_RESULT_NONE;
        hw->stat |= STAT_MC_LOAD;
+       vdec_enable_input(vdec);
        hw->last_vld_level = 0;
-       start_process_time(hw);
+       start_process_time_set(hw);
        if (vdec->mvfrm)
                vdec->mvfrm->hw_decode_start = local_clock();
        amvdec_start();
index a36e3d7dc55adedf8af9c731f94a620b3fb694cb..2499e5ee9a25f8040e085d40b5a346222cf2ee15 100644 (file)
Binary files a/firmware/video_ucode.bin and b/firmware/video_ucode.bin differ