vdec: add struct for getting multi-vdec information modules part [1/4]
authorapollo.ling <apollo.ling@amlogic.com>
Sun, 29 Sep 2019 06:57:18 +0000 (14:57 +0800)
committerHui Zhang <hui.zhang@amlogic.com>
Mon, 20 Jan 2020 10:50:35 +0000 (02:50 -0800)
PD#SWPL-1449

Problem:
need to implement a way to get multi-vdec information

Solution:
add new data struct to dynamically record each VDEC's information

Verify:
u212

Change-Id: I03cf0ff013e64b865dbd83cce85ff7abc43b15a4
Signed-off-by: apollo.ling <apollo.ling@amlogic.com>
14 files changed:
drivers/frame_provider/decoder/avs2/avs2_global.h
drivers/frame_provider/decoder/avs2/vavs2.c
drivers/frame_provider/decoder/avs_multi/avs_multi.c
drivers/frame_provider/decoder/h264/vh264.c
drivers/frame_provider/decoder/h264_multi/h264_dpb.c
drivers/frame_provider/decoder/h264_multi/h264_dpb.h
drivers/frame_provider/decoder/h264_multi/vmh264.c
drivers/frame_provider/decoder/h265/vh265.c
drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
drivers/frame_provider/decoder/utils/vdec.c
drivers/frame_provider/decoder/utils/vdec.h
drivers/frame_provider/decoder/vp9/vvp9.c
drivers/stream_input/amports/amstream.c

index e6c28cfddb6b9a95b6e8e17a1971dd6827850c73..3e7fcb842cbb3226d3cf4c17cce16ba6fd7ec108 100644 (file)
@@ -811,6 +811,9 @@ struct avs2_frame_s {
        int max_mv;
        int min_mv;
        int avg_mv;
+
+       u32 hw_decode_time;
+       u32 frame_size; // For frame base mode
 };
 
 
index f90fee6345c5dd8a3286ea027b40c1cb49d5538d..4b88db3929f1a4e6b76866ec24a3312ba843e72c 100644 (file)
@@ -4258,7 +4258,10 @@ static void fill_frame_info(struct AVS2Decoder_s *dec,
 /*
 #define SHOW_QOS_INFO
 */
-       vframe_qos->size = framesize;
+       if (input_frame_based(hw_to_vdec(dec)))
+               vframe_qos->size = pic->frame_size;
+       else
+               vframe_qos->size = framesize;
        vframe_qos->pts = pts;
 #ifdef SHOW_QOS_INFO
        avs2_print(dec, 0, "slice:%d\n", pic->slice_type);
@@ -4297,8 +4300,6 @@ static void fill_frame_info(struct AVS2Decoder_s *dec,
 
        vframe_qos->num++;
 
-       if (dec->frameinfo_enable)
-               vdec_fill_frame_info(vframe_qos, 1);
 }
 
 static void set_vframe(struct AVS2Decoder_s *dec,
@@ -4306,7 +4307,7 @@ static void set_vframe(struct AVS2Decoder_s *dec,
 {
        unsigned long flags;
        int stream_offset;
-       unsigned int frame_size;
+       unsigned int frame_size = 0;
        int pts_discontinue;
        stream_offset = pic->stream_offset;
        avs2_print(dec, AVS2_DBG_BUFMGR,
@@ -4534,6 +4535,22 @@ static void set_vframe(struct AVS2Decoder_s *dec,
        dec->vf_pre_count++;
 }
 
+static inline void dec_update_gvs(struct AVS2Decoder_s *dec)
+{
+       if (dec->gvs->frame_height != dec->frame_height) {
+               dec->gvs->frame_width = dec->frame_width;
+               dec->gvs->frame_height = dec->frame_height;
+       }
+       if (dec->gvs->frame_dur != dec->frame_dur) {
+               dec->gvs->frame_dur = dec->frame_dur;
+               if (dec->frame_dur != 0)
+                       dec->gvs->frame_rate = 96000 / dec->frame_dur;
+               else
+                       dec->gvs->frame_rate = -1;
+       }
+       dec->gvs->status = dec->stat | dec->fatal_error;
+}
+
 
 static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec)
 {
@@ -4541,6 +4558,7 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec)
        struct vframe_s *vf = NULL;
        /*unsigned short slice_type;*/
        struct avs2_frame_s *pic;
+       struct vdec_s *pvdec = hw_to_vdec(dec);
        while (1) {
                pic = get_disp_pic(dec);
                if (pic == NULL)
@@ -4575,17 +4593,20 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec)
                }
 
                if (vf) {
+                       int stream_offset = pic->stream_offset;
                        set_vframe(dec, vf, pic, 0);
-                       decoder_do_frame_check(hw_to_vdec(dec), vf);
+                       decoder_do_frame_check(pvdec, vf);
                        kfifo_put(&dec->display_q, (const struct vframe_s *)vf);
                        ATRACE_COUNTER(MODULE_NAME, vf->pts);
 
-       #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+                       dec_update_gvs(dec);
                        /*count info*/
-                       gvs->frame_dur = dec->frame_dur;
-                       vdec_count_info(gvs, 0, stream_offset);
-       #endif
-                       hw_to_vdec(dec)->vdec_fps_detec(hw_to_vdec(dec)->id);
+                       vdec_count_info(dec->gvs, 0, stream_offset);
+                       dec->gvs->bit_rate = bit_depth_luma;
+                       dec->gvs->frame_data = bit_depth_chroma;
+                       dec->gvs->samp_cnt = get_double_write_mode(dec);
+                       vdec_fill_vdec_frame(pvdec, &dec->vframe_qos, dec->gvs, vf, pic->hw_decode_time);
+                       pvdec->vdec_fps_detec(pvdec->id);
                        if (without_display_mode == 0) {
                                vf_notify_receiver(dec->provider_name,
                                VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
@@ -4774,12 +4795,18 @@ we can call this function to get qos info*/
 static void get_picture_qos_info(struct AVS2Decoder_s *dec)
 {
        struct avs2_frame_s *picture = dec->avs2_dec.hc.cur_pic;
+       struct vdec_s *vdec = hw_to_vdec(dec);
        if (!picture) {
                avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
                        "%s decode picture is none exist\n");
 
                return;
        }
+       if (vdec->mvfrm) {
+               picture->frame_size = vdec->mvfrm->frame_size;
+               picture->hw_decode_time =
+               local_clock() - vdec->mvfrm->hw_decode_start;
+       }
 
 /*
 #define DEBUG_QOS
@@ -6111,19 +6138,17 @@ int vavs2_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
        vstatus->error_count = 0;
        vstatus->status = dec->stat | dec->fatal_error;
        vstatus->frame_dur = dec->frame_dur;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
-       vstatus->bit_rate = gvs->bit_rate;
-       vstatus->frame_data = gvs->frame_data;
-       vstatus->total_data = gvs->total_data;
-       vstatus->frame_count = gvs->frame_count;
-       vstatus->error_frame_count = gvs->error_frame_count;
-       vstatus->drop_frame_count = gvs->drop_frame_count;
-       vstatus->total_data = gvs->total_data;
-       vstatus->samp_cnt = gvs->samp_cnt;
-       vstatus->offset = gvs->offset;
+       vstatus->bit_rate = dec->gvs->bit_rate;
+       vstatus->frame_data = dec->gvs->frame_data;
+       vstatus->total_data = dec->gvs->total_data;
+       vstatus->frame_count = dec->gvs->frame_count;
+       vstatus->error_frame_count = dec->gvs->error_frame_count;
+       vstatus->drop_frame_count = dec->gvs->drop_frame_count;
+       vstatus->total_data = dec->gvs->total_data;
+       vstatus->samp_cnt = dec->gvs->samp_cnt;
+       vstatus->offset = dec->gvs->offset;
        snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
                "%s", DRIVER_NAME);
-#endif
        return 0;
 }
 
@@ -6292,6 +6317,8 @@ static s32 vavs2_init(struct vdec_s *vdec)
        if (vavs2_local_init(dec) < 0)
                return -EBUSY;
 
+       vdec_set_vframe_comm(vdec, DRIVER_NAME);
+
        fw = vmalloc(sizeof(struct firmware_s) + fw_size);
        if (IS_ERR_OR_NULL(fw))
                return -ENOMEM;
@@ -7055,6 +7082,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
                r = dec->chunk->size +
                        (dec->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+               if (vdec->mvfrm)
+                       vdec->mvfrm->frame_size = dec->chunk->size;
        }
 
        WRITE_VREG(HEVC_DECODE_SIZE, r);
@@ -7072,6 +7101,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
        mod_timer(&dec->timer, jiffies);
        dec->stat |= STAT_TIMER_ARM;
        dec->stat |= STAT_ISR_REG;
+       if (vdec->mvfrm)
+               vdec->mvfrm->hw_decode_start = local_clock();
        amhevc_start();
        dec->stat |= STAT_VDEC_RUN;
 }
index ada05c5f48373801efa0aecccc60905de23e14b3..f717244ea0b6194e7364a44a05cbb4e987d900f8 100644 (file)
@@ -906,6 +906,27 @@ static u8 UserDataHandler(struct vdec_avs_hw_s *hw)
 }
 #endif
 
+
+static inline void avs_update_gvs(struct vdec_avs_hw_s *hw)
+{
+       if (hw->gvs->frame_height != hw->frame_height) {
+               hw->gvs->frame_width = hw->frame_width;
+               hw->gvs->frame_height = hw->frame_height;
+       }
+       if (hw->gvs->frame_dur != hw->frame_dur) {
+               hw->gvs->frame_dur = hw->frame_dur;
+               if (hw->frame_dur != 0)
+                       hw->gvs->frame_rate = 96000 / hw->frame_dur;
+               else
+                       hw->gvs->frame_rate = -1;
+       }
+
+       hw->gvs->status = hw->stat;
+       hw->gvs->error_count = READ_VREG(AV_SCRATCH_C);
+       hw->gvs->drop_frame_count = hw->drop_frame_count;
+
+}
+
 #ifdef HANDLE_AVS_IRQ
 static irqreturn_t vavs_isr(int irq, void *dev_id)
 #else
@@ -913,7 +934,7 @@ static void vavs_isr(void)
 #endif
 {
        u32 reg;
-       struct vframe_s *vf;
+       struct vframe_s *vf = NULL;
        u32 dur;
        u32 repeat_count;
        u32 picture_type;
@@ -1369,8 +1390,9 @@ static void vavs_isr(void)
                }
 
                /*count info*/
-               hw->gvs->frame_dur = hw->frame_dur;
                vdec_count_info(hw->gvs, 0, offset);
+               avs_update_gvs(hw);
+               vdec_fill_vdec_frame(hw_to_vdec(hw), NULL, hw->gvs, vf, 0);
 
                /* pr_info("PicType = %d, PTS = 0x%x\n",
                 *   picture_type, vf->pts);
@@ -3930,6 +3952,8 @@ static void vmavs_dump_state(struct vdec_s *vdec)
 
        vdec_set_prepare_level(pdata, start_decode_buf_level);
 
+       vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
        if (pdata->parallel_dec == 1)
                vdec_core_request(pdata, CORE_MASK_VDEC_1);
        else {
index a6acc0328628605585f6c48fac447973701b1172..dc774b9e75421c42257dba01019a5c9370ef0eea 100644 (file)
@@ -2570,6 +2570,36 @@ static inline bool vh264_isr_parser(struct vframe_s *vf,
        }
        return true;
 }
+
+static inline void h264_update_gvs(void)
+{
+       u32 ratio_control;
+       u32 ar;
+
+       if (gvs->frame_height != frame_height) {
+               gvs->frame_width = frame_width;
+               gvs->frame_height = frame_height;
+       }
+       if (gvs->frame_dur != frame_dur) {
+               gvs->frame_dur = frame_dur;
+               if (frame_dur != 0)
+                       gvs->frame_rate = 96000 / frame_dur;
+               else
+                       gvs->frame_rate = -1;
+       }
+       gvs->error_count = READ_VREG(AV_SCRATCH_D);
+       gvs->status = stat;
+       if (fatal_error_reset)
+               gvs->status |= fatal_error_flag;
+       ar = min_t(u32,
+                       h264_ar,
+                       DISP_RATIO_ASPECT_RATIO_MAX);
+       ratio_control =
+               ar << DISP_RATIO_ASPECT_RATIO_BIT;
+       gvs->ratio_control = ratio_control;
+}
+
+
 #ifdef HANDLE_H264_IRQ
 static irqreturn_t vh264_isr(int irq, void *dev_id)
 #else
@@ -2875,7 +2905,7 @@ static void vh264_isr(void)
                        frame_count++;
 
                        s_vframe_qos.num = frame_count;
-                       vdec_fill_frame_info(&s_vframe_qos, 1);
+                       //vdec_fill_frame_info(&s_vframe_qos, 1);
 
                        /* on second IDR frame,check the diff between pts
                         *  compute from duration and pts from lookup ,
@@ -3011,8 +3041,9 @@ static void vh264_isr(void)
                         */
 
                        /*count info*/
-                       gvs->frame_dur = frame_dur;
+                       h264_update_gvs();
                        vdec_count_info(gvs, error, b_offset);
+                       vdec_fill_vdec_frame(vdec_h264, &s_vframe_qos, gvs, vf, 0);
 
                        if ((pts_valid) && (check_pts_discontinue)
                                        && (!error)) {
@@ -4325,6 +4356,7 @@ static int amvdec_h264_probe(struct platform_device *pdev)
        atomic_set(&vh264_active, 1);
 
        mutex_unlock(&vh264_mutex);
+       vdec_set_vframe_comm(pdata, DRIVER_NAME);
 
        return 0;
 }
index a408b0ec547cb7a4467932b553b6c2d61dc4c701..314b240b3659e84fd00c220ce3f6bd0ed387ca80 100644 (file)
@@ -1612,6 +1612,7 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
                                  struct StorablePicture *p,
                                  unsigned char data_flag)
 {
+       struct vdec_frames_s *mvfrm = p_H264_Dpb->vdec->mvfrm;
        struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
        /* InputParameters *p_Inp = p_Vid->p_Inp;
         *   dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
@@ -1761,6 +1762,10 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
        //fs->pts64 = p->pts64;
        }
        fs->timestamp = p->timestamp;
+       if (mvfrm) {
+               fs->frame_size2 = mvfrm->frame_size;
+               fs->hw_decode_time = mvfrm->hw_decode_time;
+       }
 }
 
 void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb,
index e9a74894a1e7c3db5141ca8fbabe3cce0b8fcd84..5c7645f3109f0388fd1de8b5d14b871bc4a0deba 100644 (file)
@@ -809,6 +809,8 @@ struct FrameStore {
        int min_mv;
        int avg_mv;
        int dpb_frame_count;
+       u32 hw_decode_time;
+       u32 frame_size2; // For recording the chunk->size in frame mode
 };
 
 
index 0426bd966d09ed788a493441534a7c1aa8d448d3..4dd8bf1e073636c132f835cb2d9467e16a8c61ec 100644 (file)
@@ -2538,6 +2538,7 @@ static int check_force_interlace(struct vdec_h264_hw_s *hw,
 static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame)
 {
        struct vframe_qos_s *vframe_qos = &hw->vframe_qos;
+
        if (frame->slice_type == I_SLICE)
                vframe_qos->type = 1;
        else if (frame->slice_type == P_SLICE)
@@ -2545,7 +2546,10 @@ static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame)
        else if (frame->slice_type == B_SLICE)
                vframe_qos->type = 3;
 
-       vframe_qos->size = frame->frame_size;
+       if (input_frame_based(hw_to_vdec(hw)))
+               vframe_qos->size = frame->frame_size2;
+       else
+               vframe_qos->size = frame->frame_size;
        vframe_qos->pts = frame->pts64;
 
        vframe_qos->max_mv = frame->max_mv;
@@ -2578,8 +2582,6 @@ static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame)
                vframe_qos->min_skip);
 */
        vframe_qos->num++;
-       if (hw->frameinfo_enable)
-               vdec_fill_frame_info(vframe_qos, 1);
 }
 
 static int is_iframe(struct FrameStore *frame) {
@@ -2866,8 +2868,16 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
                        vf->duration = vf->duration/2;
                }
 
-               if (i == 0)
-                       decoder_do_frame_check(hw_to_vdec(hw), vf);
+               if (i == 0) {
+                       struct vdec_s *pvdec;
+                       struct vdec_info vs;
+
+                       pvdec = hw_to_vdec(hw);
+                       memset(&vs, 0, sizeof(struct vdec_info));
+                       pvdec->dec_status(pvdec, &vs);
+                       decoder_do_frame_check(pvdec, vf);
+                       vdec_fill_vdec_frame(pvdec, &hw->vframe_qos, &vs, vf, frame->hw_decode_time);
+               }
 
                /*vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT);*/
                vf->sar_width = hw->width_aspect_ratio;
@@ -5514,6 +5524,10 @@ static int vh264_pic_done_proc(struct vdec_s *vdec)
        struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
        int ret;
 
+       if (vdec->mvfrm)
+               vdec->mvfrm->hw_decode_time =
+               local_clock() - vdec->mvfrm->hw_decode_start;
+
        if (input_frame_based(vdec) &&
                        (!(hw->i_only & 0x2)) &&
                        frmbase_cont_bitlevel != 0 &&
@@ -6818,8 +6832,10 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
 
        vstatus->frame_width = hw->frame_width;
        vstatus->frame_height = hw->frame_height;
-       if (hw->frame_dur != 0)
+       if (hw->frame_dur != 0) {
+               vstatus->frame_dur = hw->frame_dur;
                vstatus->frame_rate = 96000 / hw->frame_dur;
+       }
        else
                vstatus->frame_rate = -1;
        vstatus->error_count = 0;
@@ -8724,6 +8740,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                WRITE_VREG(H264_DECODE_INFO, (1<<13));
                WRITE_VREG(H264_DECODE_SIZE, decode_size);
                WRITE_VREG(VIFF_BIT_CNT, decode_size * 8);
+               if (vdec->mvfrm)
+                       vdec->mvfrm->frame_size = hw->chunk->size;
        } else {
                if (size <= 0)
                        size = 0x7fffffff; /*error happen*/
@@ -8757,6 +8775,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                else
                        CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
        }
+       if (vdec->mvfrm)
+               vdec->mvfrm->hw_decode_start = local_clock();
        amvdec_start();
        if (hw->mmu_enable /*&& !hw->frame_busy && !hw->frame_done*/) {
                WRITE_VREG(HEVC_ASSIST_SCRATCH_0, 0x0);
@@ -9338,6 +9358,7 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
                                | CORE_MASK_COMBINE);
 
        atomic_set(&hw->vh264_active, 1);
+       vdec_set_vframe_comm(pdata, DRIVER_NAME);
 
        return 0;
 }
index eeb893e3ba3c181e6a4d2b5e14aeb6dfc6ac2fa9..07214370e5ac556889acf0d06e9b999fe017974b 100644 (file)
@@ -537,7 +537,7 @@ static DEFINE_MUTEX(vh265_mutex);
 
 static DEFINE_MUTEX(vh265_log_mutex);
 
-static struct vdec_info *gvs;
+//static struct vdec_info *gvs;
 
 static u32 without_display_mode;
 
@@ -1403,6 +1403,8 @@ struct PIC_s {
        int min_mv;
        int avg_mv;
 
+       u32 hw_decode_time;
+       u32 frame_size; // For frame base mode
        bool vframe_bound;
 } /*PIC_t */;
 
@@ -1736,6 +1738,7 @@ struct hevc_state_s {
        void *v4l2_ctx;
        bool v4l_params_parsed;
        u32 mem_map_mode;
+       struct vdec_info *gvs;
 } /*hevc_stru_t */;
 
 #ifdef AGAIN_HAS_THRESHOLD
@@ -6066,6 +6069,8 @@ static inline void hevc_pre_pic(struct hevc_state_s *hevc,
 
                pic = get_pic_by_POC(hevc, decoded_poc);
                if (pic && (pic->POC != INVALID_POC)) {
+                       struct vdec_s *vdec = hw_to_vdec(hevc);
+
                        /*PB skip control */
                        if (pic->error_mark == 0
                                        && hevc->PB_skip_mode == 1) {
@@ -6114,6 +6119,10 @@ static inline void hevc_pre_pic(struct hevc_state_s *hevc,
                        pic->output_mark = 1;
                        pic->recon_mark = 1;
                        pic->dis_mark = 1;
+                       if (vdec->mvfrm) {
+                               pic->frame_size = vdec->mvfrm->frame_size;
+                               pic->hw_decode_time = (u32)vdec->mvfrm->hw_decode_time;
+                       }
                }
                do {
                        pic_display = output_pic(hevc, 0);
@@ -7299,11 +7308,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc,
 
                        if (hevc->cur_pic->error_mark
                                && ((hevc->ignore_bufmgr_error & 0x1) == 0)) {
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
                                /*count info*/
-                               vdec_count_info(gvs, hevc->cur_pic->error_mark,
+                               vdec_count_info(hevc->gvs, hevc->cur_pic->error_mark,
                                        hevc->cur_pic->stream_offset);
-#endif
                        }
 
                        if (is_skip_decoding(hevc,
@@ -7331,11 +7338,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc,
                        hevc_print(hevc, 0,
                        "Discard this picture index %d\n",
                                        hevc->cur_pic->index);
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
                /*count info*/
-               vdec_count_info(gvs, hevc->cur_pic->error_mark,
+               vdec_count_info(hevc->gvs, hevc->cur_pic->error_mark,
                        hevc->cur_pic->stream_offset);
-#endif
                return 2;
        }
 #ifdef MCRCC_ENABLE
@@ -7471,8 +7476,10 @@ static void hevc_local_uninit(struct hevc_state_s *hevc)
                hevc->frame_mmu_map_addr = NULL;
        }
 
-       kfree(gvs);
-       gvs = NULL;
+       //pr_err("[%s line %d] hevc->gvs=0x%p operation\n",__func__, __LINE__, hevc->gvs);
+       if (hevc->gvs)
+               kfree(hevc->gvs);
+       hevc->gvs = NULL;
 }
 
 static int hevc_local_init(struct hevc_state_s *hevc)
@@ -8517,7 +8524,10 @@ static void fill_frame_info(struct hevc_state_s *hevc,
 /*
 #define SHOW_QOS_INFO
 */
-       vframe_qos->size = framesize;
+       if (input_frame_based(hw_to_vdec(hevc)))
+               vframe_qos->size = pic->frame_size;
+       else
+               vframe_qos->size = framesize;
        vframe_qos->pts = pts;
 #ifdef SHOW_QOS_INFO
        hevc_print(hevc, 0, "slice:%d, poc:%d\n", pic->slice_type, pic->POC);
@@ -8556,19 +8566,33 @@ static void fill_frame_info(struct hevc_state_s *hevc,
 
        vframe_qos->num++;
 
-       if (hevc->frameinfo_enable)
-               vdec_fill_frame_info(vframe_qos, 1);
+}
+
+static inline void hevc_update_gvs(struct hevc_state_s *hevc)
+{
+       if (hevc->gvs->frame_height != hevc->frame_height) {
+               hevc->gvs->frame_width = hevc->frame_width;
+               hevc->gvs->frame_height = hevc->frame_height;
+       }
+       if (hevc->gvs->frame_dur != hevc->frame_dur) {
+               hevc->gvs->frame_dur = hevc->frame_dur;
+               if (hevc->frame_dur != 0)
+                       hevc->gvs->frame_rate = 96000 / hevc->frame_dur;
+               else
+                       hevc->gvs->frame_rate = -1;
+       }
+       hevc->gvs->status = hevc->stat | hevc->fatal_error;
+       if (hevc->gvs->ratio_control != hevc->ratio_control)
+               hevc->gvs->ratio_control = hevc->ratio_control;
 }
 
 static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
 {
-#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
        struct vdec_s *vdec = hw_to_vdec(hevc);
-#endif
        struct vframe_s *vf = NULL;
        int stream_offset = pic->stream_offset;
        unsigned short slice_type = pic->slice_type;
-       u32 frame_size;
+       u32 frame_size = 0;
 
        if (force_disp_pic_index & 0x100) {
                /*recycle directly*/
@@ -8598,7 +8622,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                }
 
 #ifdef MULTI_INSTANCE_SUPPORT
-               if (vdec_frame_based(hw_to_vdec(hevc))) {
+               if (vdec_frame_based(vdec)) {
                        vf->pts = pic->pts;
                        vf->pts_us64 = pic->pts64;
                        vf->timestamp = pic->timestamp;
@@ -8905,7 +8929,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                                | VIDTYPE_VIU_NV21;
                        }
                        hevc->vf_pre_count++;
-                       decoder_do_frame_check(hw_to_vdec(hevc), vf);
+                       decoder_do_frame_check(vdec, vf);
                        kfifo_put(&hevc->display_q,
                        (const struct vframe_s *)vf);
                        ATRACE_COUNTER(MODULE_NAME, vf->pts);
@@ -8954,7 +8978,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                                | VIDTYPE_VIU_NV21;
                        }
                        hevc->vf_pre_count++;
-                       decoder_do_frame_check(hw_to_vdec(hevc), vf);
+                       decoder_do_frame_check(vdec, vf);
                        kfifo_put(&hevc->display_q,
                        (const struct vframe_s *)vf);
                        ATRACE_COUNTER(MODULE_NAME, vf->pts);
@@ -8980,7 +9004,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                        process_pending_vframe(hevc,
                        pic, (pic->pic_struct == 9));
 
-                       decoder_do_frame_check(hw_to_vdec(hevc), vf);
+                       decoder_do_frame_check(vdec, vf);
                        /* process current vf */
                        kfifo_put(&hevc->pending_q,
                        (const struct vframe_s *)vf);
@@ -9029,7 +9053,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                                VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD;
                                vf->index = (pic->index << 8) | 0xff;
                        }
-                       decoder_do_frame_check(hw_to_vdec(hevc), vf);
+                       decoder_do_frame_check(vdec, vf);
                        kfifo_put(&hevc->pending_q,
                        (const struct vframe_s *)vf);
                        if (hevc->vf_pre_count == 0)
@@ -9074,7 +9098,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                                break;
                        }
                        hevc->vf_pre_count++;
-                       decoder_do_frame_check(hw_to_vdec(hevc), vf);
+                       decoder_do_frame_check(vdec, vf);
                        kfifo_put(&hevc->display_q,
                        (const struct vframe_s *)vf);
                        ATRACE_COUNTER(MODULE_NAME, vf->pts);
@@ -9083,7 +9107,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                vf->type_original = vf->type;
                pic->vf_ref = 1;
                hevc->vf_pre_count++;
-               decoder_do_frame_check(hw_to_vdec(hevc), vf);
+               decoder_do_frame_check(vdec, vf);
                kfifo_put(&hevc->display_q, (const struct vframe_s *)vf);
                ATRACE_COUNTER(MODULE_NAME, vf->pts);
 
@@ -9096,11 +9120,14 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
                                vf->pts, vf->pts_us64,
                                vf->duration);
 #endif
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
                /*count info*/
-               vdec_count_info(gvs, 0, stream_offset);
-#endif
-               hw_to_vdec(hevc)->vdec_fps_detec(hw_to_vdec(hevc)->id);
+               vdec_count_info(hevc->gvs, 0, stream_offset);
+               hevc_update_gvs(hevc);
+               hevc->gvs->bit_rate = hevc->bit_depth_luma;
+               hevc->gvs->frame_data = hevc->bit_depth_chroma;
+               hevc->gvs->samp_cnt = get_double_write_mode(hevc);
+               vdec_fill_vdec_frame(vdec, &hevc->vframe_qos, hevc->gvs, vf, pic->hw_decode_time);
+               vdec->vdec_fps_detec(vdec->id);
                if (without_display_mode == 0) {
                        vf_notify_receiver(hevc->provider_name,
                                VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
@@ -9662,6 +9689,10 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data)
                        struct PIC_s *pic;
                        struct PIC_s *pic_display;
                        int decoded_poc;
+
+                       if (vdec->mvfrm)
+                               vdec->mvfrm->hw_decode_time =
+                               local_clock() - vdec->mvfrm->hw_decode_start;
 #ifdef DETREFILL_ENABLE
                        if (hevc->is_swap &&
                                get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) {
@@ -9757,6 +9788,12 @@ pic_done:
 
                                        pic->output_mark = 1;
                                        pic->recon_mark = 1;
+                                       if (vdec->mvfrm) {
+                                               pic->frame_size =
+                                                       vdec->mvfrm->frame_size;
+                                               pic->hw_decode_time =
+                                               (u32)vdec->mvfrm->hw_decode_time;
+                                       }
                                }
                                check_pic_decoded_error(hevc,
                                        READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff);
@@ -10236,9 +10273,7 @@ force_output:
                                                &hevc->notify_work);
 
                                hevc->get_frame_dur = true;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
-                               gvs->frame_dur = hevc->frame_dur;
-#endif
+                               //hevc->gvs->frame_dur = hevc->frame_dur;
                        }
 
                        if (hevc->video_signal_type !=
@@ -10379,9 +10414,7 @@ force_output:
 #endif
        } else {
                /* skip, search next start code */
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
-               gvs->drop_frame_count++;
-#endif
+               hevc->gvs->drop_frame_count++;
                WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2));
                        hevc->skip_flag = 1;
                WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE);
@@ -10832,23 +10865,21 @@ int vh265_dec_status(struct vdec_info *vstatus)
                vstatus->frame_rate = -1;
        vstatus->error_count = 0;
        vstatus->status = hevc->stat | hevc->fatal_error;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
-       vstatus->bit_rate = gvs->bit_rate;
+       vstatus->bit_rate = hevc->gvs->bit_rate;
        vstatus->frame_dur = hevc->frame_dur;
-       if (gvs) {
-               vstatus->bit_rate = gvs->bit_rate;
-               vstatus->frame_data = gvs->frame_data;
-               vstatus->total_data = gvs->total_data;
-               vstatus->frame_count = gvs->frame_count;
-               vstatus->error_frame_count = gvs->error_frame_count;
-               vstatus->drop_frame_count = gvs->drop_frame_count;
-               vstatus->total_data = gvs->total_data;
-               vstatus->samp_cnt = gvs->samp_cnt;
-               vstatus->offset = gvs->offset;
+       if (hevc->gvs) {
+               vstatus->bit_rate = hevc->gvs->bit_rate;
+               vstatus->frame_data = hevc->gvs->frame_data;
+               vstatus->total_data = hevc->gvs->total_data;
+               vstatus->frame_count = hevc->gvs->frame_count;
+               vstatus->error_frame_count = hevc->gvs->error_frame_count;
+               vstatus->drop_frame_count = hevc->gvs->drop_frame_count;
+               vstatus->samp_cnt = hevc->gvs->samp_cnt;
+               vstatus->offset = hevc->gvs->offset;
        }
+
        snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
                "%s", DRIVER_NAME);
-#endif
        vstatus->ratio_control = hevc->ratio_control;
        return 0;
 }
@@ -10859,13 +10890,15 @@ int vh265_set_isreset(struct vdec_s *vdec, int isreset)
        return 0;
 }
 
-static int vh265_vdec_info_init(void)
+static int vh265_vdec_info_init(struct hevc_state_s  *hevc)
 {
-       gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
-       if (NULL == gvs) {
+       hevc->gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
+       //pr_err("[%s line %d] hevc->gvs=0x%p operation\n",__func__, __LINE__, hevc->gvs);
+       if (NULL == hevc->gvs) {
                pr_info("the struct of vdec status malloc failed.\n");
                return -ENOMEM;
        }
+       vdec_set_vframe_comm(hw_to_vdec(hevc), DRIVER_NAME);
        return 0;
 }
 
@@ -11050,9 +11083,7 @@ static int vh265_local_init(struct hevc_state_s *hevc)
        hevc->frame_dur =
                (hevc->vh265_amstream_dec_info.rate ==
                 0) ? 3600 : hevc->vh265_amstream_dec_info.rate;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
-       gvs->frame_dur = hevc->frame_dur;
-#endif
+       //hevc->gvs->frame_dur = hevc->frame_dur;
        if (hevc->frame_width && hevc->frame_height)
                hevc->frame_ar = hevc->frame_height * 0x100 / hevc->frame_width;
 
@@ -11427,8 +11458,10 @@ static int vh265_stop(struct hevc_state_s *hevc)
        uninit_mmu_buffers(hevc);
        amhevc_disable();
 
-       kfree(gvs);
-       gvs = NULL;
+       //pr_err("[%s line %d] hevc->gvs=0x%p operation\n",__func__, __LINE__, hevc->gvs);
+       if (hevc->gvs)
+               kfree(hevc->gvs);
+       hevc->gvs = NULL;
 
        return 0;
 }
@@ -12435,6 +12468,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                r = hevc->chunk->size +
                        (hevc->chunk->offset & (VDEC_FIFO_ALIGN - 1));
                hevc->decode_size = r;
+               if (vdec->mvfrm)
+                       vdec->mvfrm->frame_size = hevc->chunk->size;
        }
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
        else {
@@ -12456,6 +12491,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
        mod_timer(&hevc->timer, jiffies);
        hevc->stat |= STAT_TIMER_ARM;
        hevc->stat |= STAT_ISR_REG;
+       if (vdec->mvfrm)
+               vdec->mvfrm->hw_decode_start = local_clock();
        amhevc_start();
        hevc->stat |= STAT_VDEC_RUN;
 }
@@ -12646,7 +12683,7 @@ static int amvdec_h265_probe(struct platform_device *pdev)
                workaround_enable &= ~3;
 #endif
        hevc->cma_dev = pdata->cma_dev;
-       vh265_vdec_info_init();
+       vh265_vdec_info_init(hevc);
 
 #ifdef MULTI_INSTANCE_SUPPORT
        pdata->private = hevc;
@@ -12901,6 +12938,7 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
        int config_val;
 #endif
+       //pr_err("[%s pid=%d tgid=%d] \n",__func__, current->pid, current->tgid);
        if (pdata == NULL) {
                pr_info("\nammvdec_h265 memory resource undefined.\n");
                return -EFAULT;
@@ -13101,6 +13139,7 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
                hevc->double_write_mode);
 
        hevc->cma_dev = pdata->cma_dev;
+       vh265_vdec_info_init(hevc);
 
        if (vh265_init(pdata) < 0) {
                hevc_print(hevc, 0,
@@ -13138,6 +13177,7 @@ static int ammvdec_h265_remove(struct platform_device *pdev)
        if (hevc == NULL)
                return 0;
 
+       //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 64e81c7e23b74c4fdc764dd1e0b83ca4bfce2ce2..389812269aefa46915e52e2a656a474cba2883a1 100644 (file)
@@ -203,6 +203,8 @@ struct pic_info_t {
        u64 pts64;
        bool pts_valid;
        ulong v4l_ref_buf_addr;
+       u32 hw_decode_time;
+       u32 frame_size; // For frame base mode
 };
 
 struct vdec_mpeg12_hw_s {
@@ -307,11 +309,12 @@ struct vdec_mpeg12_hw_s {
        bool v4l_params_parsed;
        u32 buf_num;
        u32 dynamic_buf_num_margin;
+       struct vdec_info gvs;
+       struct vframe_qos_s vframe_qos;
 };
 static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
 static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
 static void reset_process_time(struct vdec_mpeg12_hw_s *hw);
-static struct vdec_info gvs;
 static int debug_enable;
 /*static struct work_struct userdata_push_work;*/
 #undef pr_info
@@ -512,6 +515,99 @@ static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec)
        return hw->buf_num;
 }
 
+/* +[SE][BUG-145343][huanghang] fixed:mpeg2 frame qos info notify */
+static void fill_frame_info(struct vdec_mpeg12_hw_s *hw, u32 slice_type,
+                                                       int frame_size, u32 pts)
+{
+       unsigned char a[3];
+       unsigned char i, j, t;
+       unsigned long  data;
+       struct vframe_qos_s *vframe_qos = &hw->vframe_qos;
+
+       vframe_qos->type = ((slice_type & PICINFO_TYPE_MASK) ==
+                                               PICINFO_TYPE_I) ? 1 :
+                                               ((slice_type &
+                                               PICINFO_TYPE_MASK) ==
+                                               PICINFO_TYPE_P) ? 2 : 3;
+       vframe_qos->size = frame_size;
+       vframe_qos->pts = pts;
+
+       get_random_bytes(&data, sizeof(unsigned long));
+       if (vframe_qos->type == 1)
+               data = 0;
+       a[0] = data & 0xff;
+       a[1] = (data >> 8) & 0xff;
+       a[2] = (data >> 16) & 0xff;
+
+       for (i = 0; i < 3; i++) {
+               for (j = i+1; j < 3; j++) {
+                       if (a[j] < a[i]) {
+                               t = a[j];
+                               a[j] = a[i];
+                               a[i] = t;
+                       } else if (a[j] == a[i]) {
+                               a[i]++;
+                               t = a[j];
+                               a[j] = a[i];
+                               a[i] = t;
+                       }
+               }
+       }
+       vframe_qos->max_mv = a[2];
+       vframe_qos->avg_mv = a[1];
+       vframe_qos->min_mv = a[0];
+
+       get_random_bytes(&data, sizeof(unsigned long));
+       a[0] = data & 0x1f;
+       a[1] = (data >> 8) & 0x3f;
+       a[2] = (data >> 16) & 0x7f;
+
+       for (i = 0; i < 3; i++) {
+               for (j = i+1; j < 3; j++) {
+                       if (a[j] < a[i]) {
+                               t = a[j];
+                               a[j] = a[i];
+                               a[i] = t;
+                       } else if (a[j] == a[i]) {
+                               a[i]++;
+                               t = a[j];
+                               a[j] = a[i];
+                               a[i] = t;
+                       }
+               }
+       }
+       vframe_qos->max_qp = a[2];
+       vframe_qos->avg_qp = a[1];
+       vframe_qos->min_qp = a[0];
+
+       get_random_bytes(&data, sizeof(unsigned long));
+       a[0] = data & 0x1f;
+       a[1] = (data >> 8) & 0x3f;
+       a[2] = (data >> 16) & 0x7f;
+
+       for (i = 0; i < 3; i++) {
+               for (j = i + 1; j < 3; j++) {
+                       if (a[j] < a[i]) {
+                               t = a[j];
+                               a[j] = a[i];
+                               a[i] = t;
+                       } else if (a[j] == a[i]) {
+                               a[i]++;
+                               t = a[j];
+                               a[j] = a[i];
+                               a[i] = t;
+                       }
+               }
+       }
+       vframe_qos->max_skip = a[2];
+       vframe_qos->avg_skip = a[1];
+       vframe_qos->min_skip = a[0];
+
+       vframe_qos->num++;
+
+       return;
+}
+
 static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf)
 {
        u32 ar_bits;
@@ -1351,6 +1447,28 @@ void userdata_pushed_drop(struct vdec_mpeg12_hw_s *hw)
 }
 
 
+static inline void hw_update_gvs(struct vdec_mpeg12_hw_s *hw)
+{
+       if (hw->gvs.frame_height != hw->frame_height) {
+               hw->gvs.frame_width = hw->frame_width;
+               hw->gvs.frame_height = hw->frame_height;
+       }
+       if (hw->gvs.frame_dur != hw->frame_dur) {
+               hw->gvs.frame_dur = hw->frame_dur;
+               if (hw->frame_dur != 0)
+                       hw->gvs.frame_rate = 96000 / hw->frame_dur;
+               else
+                       hw->gvs.frame_rate = -1;
+       }
+       if (hw->gvs.ratio_control != hw->ratio_control)
+               hw->gvs.ratio_control = hw->ratio_control;
+
+       hw->gvs.status = hw->stat;
+       hw->gvs.error_count = READ_VREG(AV_SCRATCH_C);
+       hw->gvs.drop_frame_count = hw->drop_frame_count;
+
+}
+
 static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
        struct pic_info_t *pic)
 {
@@ -1460,8 +1578,14 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
                                __func__, hw->disp_num, GET_SLICE_TYPE(info), i,
                                vf->pts, vf->pts_us64, vf->duration, vf->type);
                        hw->disp_num++;
-                       if (i == 0)
-                               decoder_do_frame_check(hw_to_vdec(hw), vf);
+                       if (i == 0) {
+                               struct vdec_s *vdec = hw_to_vdec(hw);
+
+                               decoder_do_frame_check(vdec, vf);
+                               hw_update_gvs(hw);
+                               vdec_fill_vdec_frame(vdec, &hw->vframe_qos,
+                                       &hw->gvs, vf, pic->hw_decode_time);
+                       }
                        vdec->vdec_fps_detec(vdec->id);
                        vf->mem_handle =
                                decoder_bmmu_box_get_mem_handle(
@@ -1555,7 +1679,7 @@ static bool is_ref_error(struct vdec_mpeg12_hw_s *hw)
 
 static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
 {
-       u32 reg, index, info, seqinfo, offset, pts, frame_size, tmp;
+       u32 reg, index, info, seqinfo, offset, pts, frame_size=0, tmp;
        u64 pts_us64 = 0;
        struct pic_info_t *new_pic, *disp_pic;
        struct vdec_mpeg12_hw_s *hw =
@@ -1624,6 +1748,11 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
                hw->dec_num++;
                hw->dec_result = DEC_RESULT_DONE;
                new_pic = &hw->pics[index];
+               if (vdec->mvfrm) {
+                       new_pic->frame_size = vdec->mvfrm->frame_size;
+                       new_pic->hw_decode_time =
+                       local_clock() - vdec->mvfrm->hw_decode_start;
+               }
                tmp = READ_VREG(MREG_PIC_WIDTH);
                if ((tmp > 1920) || (tmp == 0)) {
                        new_pic->width = 1920;
@@ -1734,6 +1863,11 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
                if (disp_pic->pts_valid)
                        hw->lastpts64 = disp_pic->pts64;
 
+               if (input_frame_based(hw_to_vdec(hw)))
+                       frame_size = new_pic->frame_size;
+
+               fill_frame_info(hw, info, frame_size, new_pic->pts);
+
                if ((hw->first_i_frame_ready == 0) &&
                        ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) &&
                        ((info & PICINFO_ERROR) == 0))
@@ -1760,7 +1894,7 @@ static irqreturn_t vmpeg12_isr(struct vdec_s *vdec, int irq)
        info = READ_VREG(MREG_PIC_INFO);
        offset = READ_VREG(MREG_FRAME_OFFSET);
 
-       vdec_count_info(&gvs, info & PICINFO_ERROR, offset);
+       vdec_count_info(&hw->gvs, info & PICINFO_ERROR, offset);
 
        WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
 
@@ -2047,16 +2181,16 @@ static int vmmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
                vstatus->frame_rate = -1;
        vstatus->error_count = READ_VREG(AV_SCRATCH_C);
        vstatus->status = hw->stat;
-       vstatus->bit_rate = gvs.bit_rate;
+       vstatus->bit_rate = hw->gvs.bit_rate;
        vstatus->frame_dur = hw->frame_dur;
-       vstatus->frame_data = gvs.frame_data;
-       vstatus->total_data = gvs.total_data;
-       vstatus->frame_count = gvs.frame_count;
-       vstatus->error_frame_count = gvs.error_frame_count;
+       vstatus->frame_data = hw->gvs.frame_data;
+       vstatus->total_data = hw->gvs.total_data;
+       vstatus->frame_count = hw->gvs.frame_count;
+       vstatus->error_frame_count = hw->gvs.error_frame_count;
        vstatus->drop_frame_count = hw->drop_frame_count;
-       vstatus->total_data = gvs.total_data;
-       vstatus->samp_cnt = gvs.samp_cnt;
-       vstatus->offset = gvs.offset;
+       vstatus->total_data = hw->gvs.total_data;
+       vstatus->samp_cnt = hw->gvs.samp_cnt;
+       vstatus->offset = hw->gvs.offset;
        vstatus->ratio_control = hw->ratio_control;
        snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
                        "%s", DRIVER_NAME);
@@ -2752,6 +2886,8 @@ void (*callback)(struct vdec_s *, void *),
                        READ_PARSER_REG(PARSER_VIDEO_WP),
                        size);
 
+       if (vdec->mvfrm && hw->chunk)
+               vdec->mvfrm->frame_size = hw->chunk->size;
 
        hw->input_empty = 0;
        vdec_enable_input(vdec);
@@ -2786,6 +2922,8 @@ void (*callback)(struct vdec_s *, void *),
        hw->stat |= STAT_MC_LOAD;
        hw->last_vld_level = 0;
        start_process_time(hw);
+       if (vdec->mvfrm)
+               vdec->mvfrm->hw_decode_start = local_clock();
        amvdec_start();
        hw->stat |= STAT_VDEC_RUN;
        hw->init_flag = 1;
@@ -2891,6 +3029,8 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
        }
        vdec_set_prepare_level(pdata, start_decode_buf_level);
 
+       vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
        if (pdata->parallel_dec == 1)
                vdec_core_request(pdata, CORE_MASK_VDEC_1);
        else {
@@ -2979,7 +3119,6 @@ static int ammvdec_mpeg12_remove(struct platform_device *pdev)
                hw = NULL;
        }
        pr_info("ammvdec_mpeg12 removed.\n");
-       memset(&gvs, 0x0, sizeof(gvs));
 
        return 0;
 }
index c098a5ecf95af876ce0254bcbf18ff36a8105529..92cea0e482cd08fcd084891915c482bccd94da59 100644 (file)
@@ -200,6 +200,8 @@ struct pic_info_t {
        u32 duration;
        u32 repeat_cnt;
        ulong v4l_ref_buf_addr;
+       u32 hw_decode_time;
+       u32 frame_size; // For frame base mode;
 };
 
 struct vdec_mpeg4_hw_s {
@@ -774,6 +776,8 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
                        kfifo_put(&hw->newframe_q,
                                (const struct vframe_s *)vf);
                } else {
+                       struct vdec_info vinfo;
+
                        vf->mem_handle =
                                decoder_bmmu_box_get_mem_handle(
                                        hw->mm_blk_handle, index);
@@ -784,6 +788,9 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
                        decoder_do_frame_check(vdec, vf);
                        hw->frame_num++;
 
+                       vdec->dec_status(vdec, &vinfo);
+                       vdec_fill_vdec_frame(vdec, NULL,
+                               &vinfo, vf, pic->hw_decode_time);
                        if (without_display_mode == 0) {
                                vf_notify_receiver(vdec->vf_provider_name,
                                        VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
@@ -949,6 +956,11 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
                }
                hw->dec_result = DEC_RESULT_DONE;
                dec_pic = &hw->pic[index];
+               if (vdec->mvfrm) {
+                       dec_pic->frame_size = vdec->mvfrm->frame_size;
+                       dec_pic->hw_decode_time =
+                       local_clock() - vdec->mvfrm->hw_decode_start;
+               }
                dec_pic->pts_valid = false;
                dec_pic->pts = 0;
                dec_pic->pts64 = 0;
@@ -2205,6 +2217,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                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;
        }
        hw->input_empty = 0;
        hw->last_vld_level = 0;
@@ -2213,6 +2227,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
        /* wmb before ISR is handled */
        wmb();
 
+       if (vdec->mvfrm)
+               vdec->mvfrm->hw_decode_start = local_clock();
        amvdec_start();
        hw->stat |= STAT_VDEC_RUN;
        hw->init_flag = 1;
@@ -2348,6 +2364,8 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev)
        }
        vdec_set_prepare_level(pdata, start_decode_buf_level);
 
+       vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
        if (pdata->parallel_dec == 1)
                vdec_core_request(pdata, CORE_MASK_VDEC_1);
        else {
index 644797ad99df5027081cfdc10e60d9b70ff6be17..07e039ba2cb85b9868e153d46ffcb85a6f653f60 100644 (file)
@@ -121,10 +121,8 @@ static int max_di_instance = 2;
 
 //static int path_debug = 0;
 
-static struct vframe_qos_s *frame_info_buf_in = NULL;
-static struct vframe_qos_s *frame_info_buf_out = NULL;
-static int frame_qos_wr = 0;
-static int frame_qos_rd = 0;
+static int enable_mvdec_info = 1;
+
 int decode_underflow = 0;
 
 #define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
@@ -1060,6 +1058,12 @@ struct vdec_s *vdec_create(struct stream_port_s *port,
                        master->slave = vdec;
                        master->sched = 1;
                }
+               if (enable_mvdec_info) {
+                       vdec->mvfrm = (struct vdec_frames_s *)
+                               vzalloc(sizeof(struct vdec_frames_s));
+                       if (!vdec->mvfrm)
+                               pr_err("vzalloc: vdec_frames_s failed\n");
+               }
        }
 
        pr_debug("vdec_create instance %p, total %d\n", vdec,
@@ -2049,6 +2053,8 @@ int vdec_destroy(struct vdec_s *vdec)
        vdec_profile_flush(vdec);
 #endif
        ida_simple_remove(&vdec_core->ida, vdec->id);
+       if (vdec->mvfrm)
+               vfree(vdec->mvfrm);
        vfree(vdec);
 
        atomic_dec(&vdec_core->vdec_nr);
@@ -2068,6 +2074,7 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
        const char *dev_name;
        int id = PLATFORM_DEVID_AUTO;/*if have used my self*/
 
+       //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
        dev_name = get_dev_name(vdec_single(vdec), vdec->format);
 
        if (dev_name == NULL)
@@ -2364,25 +2371,6 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
                vdec->sys_info->height);
        /* vdec is now ready to be active */
        vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED);
-       if (p->use_vfm_path) {
-               frame_info_buf_in = (struct vframe_qos_s *)
-                       kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL);
-               if (!frame_info_buf_in)
-                       pr_err("kmalloc: frame_info_buf_in failed\n");
-               else
-                       memset(frame_info_buf_in, 0,
-                                       QOS_FRAME_NUM*sizeof(struct vframe_qos_s));
-
-               frame_info_buf_out = (struct vframe_qos_s *)
-                       kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL);
-               if (!frame_info_buf_out)
-                       pr_err("kmalloc: frame_info_buf_out failed\n");
-               else
-                       memset(frame_info_buf_out, 0,
-                                       QOS_FRAME_NUM*sizeof(struct vframe_qos_s));
-               frame_qos_wr = 0;
-               frame_qos_rd = 0;
-       }
        return 0;
 
 error:
@@ -2445,14 +2433,6 @@ void vdec_release(struct vdec_s *vdec)
        platform_device_unregister(vdec->dev);
        pr_debug("vdec_release instance %p, total %d\n", vdec,
                atomic_read(&vdec_core->vdec_nr));
-       if (vdec->use_vfm_path) {
-               kfree(frame_info_buf_in);
-               frame_info_buf_in = NULL;
-               kfree(frame_info_buf_out);
-               frame_info_buf_out = NULL;
-               frame_qos_wr = 0;
-               frame_qos_rd = 0;
-       }
        vdec_destroy(vdec);
 
        mutex_lock(&vdec_mutex);
@@ -2750,7 +2730,7 @@ static irqreturn_t vdec_thread_isr(int irq, void *dev_id)
                vdec->tfn_ns = local_clock();
                isr2tfn = vdec->tfn_ns - vdec->isr_ns;
                if (isr2tfn > 10000000)
-                       pr_err("!!!!!!! %s vdec_isr to %s took %uns !!!\n",
+                       pr_err("!!!!!!! %s vdec_isr to %s took %u ns !!!\n",
                                vdec->vf_provider_name, __func__, isr2tfn);
        }
        if (c->dev_threaded_isr) {
@@ -4225,6 +4205,28 @@ static ssize_t clock_level_show(struct class *class,
        return ret;
 }
 
+static ssize_t enable_mvdec_info_show(struct class *cla,
+                                 struct class_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", enable_mvdec_info);
+}
+
+static ssize_t enable_mvdec_info_store(struct class *cla,
+                                  struct class_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       int r;
+       int val;
+
+       r = kstrtoint(buf, 0, &val);
+       if (r < 0)
+               return -EINVAL;
+       enable_mvdec_info = val;
+
+       return count;
+}
+
+
 static ssize_t store_poweron_clock_level(struct class *class,
                struct class_attribute *attr,
                const char *buf, size_t size)
@@ -4273,6 +4275,7 @@ static ssize_t show_keep_vdec_mem(struct class *class,
        return sprintf(buf, "%d\n", keep_vdec_mem);
 }
 
+
 #ifdef VDEC_DEBUG_SUPPORT
 static ssize_t store_debug(struct class *class,
                struct class_attribute *attr,
@@ -4878,6 +4881,8 @@ static struct class_attribute vdec_class_attrs[] = {
        __ATTR_RO(amrisc_regs),
        __ATTR_RO(dump_trace),
        __ATTR_RO(clock_level),
+       __ATTR(enable_mvdec_info, S_IRUGO | S_IWUSR | S_IWGRP,
+       enable_mvdec_info_show, enable_mvdec_info_store),
        __ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP,
        show_poweron_clock_level, store_poweron_clock_level),
        __ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP,
@@ -5105,104 +5110,109 @@ static int __init vdec_mem_setup(struct reserved_mem *rmem)
        return 0;
 }
 
-void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug)
+
+void vdec_set_vframe_comm(struct vdec_s *vdec, char *n)
 {
-       if (frame_info_buf_in == NULL) {
-               pr_info("error,frame_info_buf_in is null\n");
-               return;
-       }
-       if (frame_info_buf_out == NULL) {
-               pr_info("error,frame_info_buf_out is null\n");
-               return;
-       }
-       if (frame_qos_wr >= QOS_FRAME_NUM)
-               frame_qos_wr = 0;
+       struct vdec_frames_s *mvfrm = vdec->mvfrm;
 
-       if (frame_qos_wr >= QOS_FRAME_NUM ||
-                       frame_qos_wr < 0) {
-               pr_info("error,index :%d is error\n", frame_qos_wr);
+       if (!mvfrm)
                return;
-       }
-       if (frameinfo_flag == DISABLE_FRAME_INFO)
+
+       mvfrm->comm.vdec_id = vdec->id;
+
+       snprintf(mvfrm->comm.vdec_name, sizeof(mvfrm->comm.vdec_name)-1,
+               "%s", n);
+       mvfrm->comm.vdec_type = vdec->type;
+}
+EXPORT_SYMBOL(vdec_set_vframe_comm);
+
+void vdec_fill_vdec_frame(struct vdec_s *vdec, struct vframe_qos_s *vframe_qos,
+                               struct vdec_info *vinfo,struct vframe_s *vf,
+                               u32 hw_dec_time)
+{
+       u32 i;
+       struct vframe_counter_s *fifo_buf;
+       struct vdec_frames_s *mvfrm = vdec->mvfrm;
+
+       if (!mvfrm)
                return;
+       fifo_buf = mvfrm->fifo_buf;
+
+       /* assume fps==60,mv->wr max value can support system running 828 days,
+        this is enough for us */
+       i = mvfrm->wr & (NUM_FRAME_VDEC-1); //find the slot num in fifo_buf
+       mvfrm->fifo_buf[i].decode_time_cost = hw_dec_time;
+       if (vframe_qos)
+               memcpy(&fifo_buf[i].qos, vframe_qos, sizeof(struct vframe_qos_s));
+       if (vinfo) {
+               memcpy(&fifo_buf[i].frame_width, &vinfo->frame_width,
+                       ((char*)&vinfo->reserved[0] - (char*)&vinfo->frame_width));
+       }
+       if (vf) {
+               fifo_buf[i].vf_type = vf->type;
+               fifo_buf[i].signal_type = vf->signal_type;
+               fifo_buf[i].pts = vf->pts;
+               fifo_buf[i].pts_us64 = vf->pts_us64;
+       }
+       mvfrm->wr++;
+}
+EXPORT_SYMBOL(vdec_fill_vdec_frame);
+
+/* In this function,if we use copy_to_user, we may encounter sleep,
+which may block the vdec_fill_vdec_frame,this is not acceptable.
+So, we should use a tmp buffer(passed by caller) to get the content */
+u32  vdec_get_frame_vdec(struct vdec_s *vdec,  struct vframe_counter_s *tmpbuf)
+{
+       u32 toread = 0;
+       u32 slot_rd;
+       struct vframe_counter_s *fifo_buf = NULL;
+       struct vdec_frames_s *mvfrm = NULL;
 
-       if (frameinfo_flag == PRINT_FRAME_INFO) {
-               pr_info("num %d size %d pts %d\n",
-                               vframe_qos->num,
-                               vframe_qos->size,
-                               vframe_qos->pts);
-               pr_info("mv min_mv %d avg_mv %d max_mv %d\n",
-                               vframe_qos->min_mv,
-                               vframe_qos->avg_mv,
-                               vframe_qos->max_mv);
-               pr_info("qp min_qp %d avg_qp %d max_qp %d\n",
-                               vframe_qos->min_qp,
-                               vframe_qos->avg_qp,
-                               vframe_qos->max_qp);
-               pr_info("skip min_skip %d avg_skip %d max_skip %d\n",
-                               vframe_qos->min_skip,
-                               vframe_qos->avg_skip,
-                               vframe_qos->max_skip);
-       }
-       memcpy(&frame_info_buf_in[frame_qos_wr++],
-                       vframe_qos, sizeof(struct vframe_qos_s));
-       if (frame_qos_wr >= QOS_FRAME_NUM)
-               frame_qos_wr = 0;
-
-       /*pr_info("frame_qos_wr:%d\n", frame_qos_wr);*/
-
-}
-EXPORT_SYMBOL(vdec_fill_frame_info);
-
-struct vframe_qos_s *vdec_get_qos_info(void)
-{
-       int write_count = 0;
-       int qos_wr = frame_qos_wr;
-
-       if (frame_info_buf_in == NULL) {
-               pr_info("error,frame_info_buf_in is null\n");
-               return NULL;
-       }
-       if (frame_info_buf_out == NULL) {
-               pr_info("error,frame_info_buf_out is null\n");
-               return NULL;
+       /*
+       switch (version) {
+       case version_1:
+               f1();
+       case version_2:
+               f2();
+       default:
+               break;
        }
+       */
+
+       if (!vdec)
+               return 0;
+       mvfrm = vdec->mvfrm;
+       if (!mvfrm)
+               return 0;
 
+       fifo_buf = &mvfrm->fifo_buf[0];
 
-       memset(frame_info_buf_out, 0,
-                       QOS_FRAME_NUM*sizeof(struct vframe_qos_s));
-       if (frame_qos_rd > qos_wr) {
-               write_count = QOS_FRAME_NUM - frame_qos_rd;
-               if (write_count > 0 && write_count <= QOS_FRAME_NUM) {
-                       memcpy(frame_info_buf_out, &frame_info_buf_in[0],
-                               write_count*sizeof(struct vframe_qos_s));
-                       if ((write_count + qos_wr) <= QOS_FRAME_NUM)
-                               memcpy(&frame_info_buf_out[write_count], frame_info_buf_in,
-                                       qos_wr*sizeof(struct vframe_qos_s));
-                       else
-                               pr_info("get_qos_info:%d,out of range\n", __LINE__);
-               } else
-                       pr_info("get_qos_info:%d,out of range\n", __LINE__);
-       } else if (frame_qos_rd < qos_wr) {
-               write_count =  qos_wr - frame_qos_rd;
-               if (write_count > 0 && write_count < QOS_FRAME_NUM)
-                       memcpy(frame_info_buf_out, &frame_info_buf_in[frame_qos_rd],
-                               (write_count)*sizeof(struct vframe_qos_s));
-               else
-                       pr_info("get_qos_info:%d, out of range\n", __LINE__);
+       toread = mvfrm->wr - mvfrm->rd;
+       if (toread) {
+               if (toread >= NUM_FRAME_VDEC - QOS_FRAME_NUM) {
+                       /* round the fifo_buf length happens, give QOS_FRAME_NUM for buffer */
+                       mvfrm->rd = mvfrm->wr - (NUM_FRAME_VDEC - QOS_FRAME_NUM);
+               }
+
+               if (toread >= QOS_FRAME_NUM) {
+                       toread = QOS_FRAME_NUM; //by default, we use this num
+               }
+
+               slot_rd = mvfrm->rd &( NUM_FRAME_VDEC-1); //In this case it equals to x%y
+               if (slot_rd + toread <= NUM_FRAME_VDEC) {
+                       memcpy(tmpbuf, &fifo_buf[slot_rd], toread*sizeof(struct vframe_counter_s));
+               } else {
+                       u32 exeed;
+                       exeed = slot_rd + toread - NUM_FRAME_VDEC;
+                       memcpy(tmpbuf, &fifo_buf[slot_rd], (NUM_FRAME_VDEC - slot_rd)*sizeof(struct vframe_counter_s));
+                       memcpy(&tmpbuf[NUM_FRAME_VDEC-slot_rd], &fifo_buf[0], exeed*sizeof(struct vframe_counter_s));
+               }
+
+               mvfrm->rd += toread;
        }
-       /*
-          pr_info("cnt:%d,size:%d,num:%d,rd:%d,wr:%d\n",
-          wirte_count,
-          frame_info_buf_out[0].size,
-          frame_info_buf_out[0].num,
-          frame_qos_rd,qos_wr);
-       */
-       frame_qos_rd = qos_wr;
-       return frame_info_buf_out;
+       return toread;
 }
-EXPORT_SYMBOL(vdec_get_qos_info);
-
+EXPORT_SYMBOL(vdec_get_frame_vdec);
 
 RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup);
 /*
index 92a22447b5d6444b72613fb805f80ab3de9255d7..06b565db1b98561476e7c55ee076a9057ba97095 100644 (file)
@@ -121,7 +121,13 @@ extern void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size);
 unsigned int get_vdec_clk_config_settings(void);
 void update_vdec_clk_config_settings(unsigned int config);
 //unsigned int get_mmu_mode(void);//DEBUG_TMP
-extern void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug);
+//extern void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug);
+extern void vdec_fill_vdec_frame(struct vdec_s *vdec,
+                               struct vframe_qos_s *vframe_qos,
+                               struct vdec_info *vinfo,
+                               struct vframe_s *vf, u32 hw_dec_time);
+extern void vdec_set_vframe_comm(struct vdec_s *vdec, char *n);
+
 
 struct vdec_s;
 enum vformat_t;
@@ -265,6 +271,7 @@ struct vdec_s {
        int parallel_dec;
        volatile u64 isr_ns;
        volatile u64 tfn_ns;
+       struct vdec_frames_s *mvfrm;
 };
 
 /* common decoder vframe provider name to use default vfm path */
@@ -448,7 +455,7 @@ int vdec_get_status(struct vdec_s *vdec);
 
 void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp);
 
-extern struct vframe_qos_s *vdec_get_qos_info(void);
+extern u32  vdec_get_frame_vdec(struct vdec_s *vdec,  struct vframe_counter_s *tmpbuf);
 
 int vdec_get_frame_num(struct vdec_s *vdec);
 
index 1089c7520b03f464071793e4dabc3b217ef93186..bd1e51ae155edd834e0a9093f9763a973a404b4d 100644 (file)
@@ -582,6 +582,8 @@ struct PIC_BUFFER_CONFIG_s {
        int min_mv;
        int avg_mv;
 
+       u32 hw_decode_time;
+       u32 frame_size2; // For frame base mode
        bool vframe_bound;
 } PIC_BUFFER_CONFIG;
 
@@ -7007,16 +7009,33 @@ static void update_vf_memhandle(struct VP9Decoder_s *pbi,
        }
 }
 
+static inline void pbi_update_gvs(struct VP9Decoder_s *pbi)
+{
+       if (pbi->gvs->frame_height != frame_height) {
+               pbi->gvs->frame_width = frame_width;
+               pbi->gvs->frame_height = frame_height;
+       }
+       if (pbi->gvs->frame_dur != pbi->frame_dur) {
+               pbi->gvs->frame_dur = pbi->frame_dur;
+               if (pbi->frame_dur != 0)
+                       pbi->gvs->frame_rate = 96000 / pbi->frame_dur;
+               else
+                       pbi->gvs->frame_rate = -1;
+       }
+       pbi->gvs->status = pbi->stat | pbi->fatal_error;
+}
+
 static int prepare_display_buf(struct VP9Decoder_s *pbi,
                                struct PIC_BUFFER_CONFIG_s *pic_config)
 {
        struct vframe_s *vf = NULL;
+       struct vdec_s *pvdec = hw_to_vdec(pbi);
        int stream_offset = pic_config->stream_offset;
        unsigned short slice_type = pic_config->slice_type;
        u32 pts_valid = 0, pts_us64_valid = 0;
        u32 pts_save;
        u64 pts_us64_save;
-       u32 frame_size;
+       u32 frame_size = 0;
 
        if (debug & VP9_DEBUG_BUFMGR)
                pr_info("%s index = %d\r\n", __func__, pic_config->index);
@@ -7042,7 +7061,7 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
                }
 
 #ifdef MULTI_INSTANCE_SUPPORT
-               if (vdec_frame_based(hw_to_vdec(pbi))) {
+               if (vdec_frame_based(pvdec)) {
                        vf->pts = pic_config->pts;
                        vf->pts_us64 = pic_config->pts64;
                        vf->timestamp = pic_config->timestamp;
@@ -7260,16 +7279,19 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
                && (debug & VP9_DEBUG_NO_TRIGGER_FRAME) == 0
                && (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX))) {
                        inc_vf_ref(pbi, pic_config->index);
-                       decoder_do_frame_check(hw_to_vdec(pbi), vf);
+                       decoder_do_frame_check(pvdec, vf);
                        kfifo_put(&pbi->display_q, (const struct vframe_s *)vf);
                        ATRACE_COUNTER(MODULE_NAME, vf->pts);
                        pbi->vf_pre_count++;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+                       pbi_update_gvs(pbi);
                        /*count info*/
-                       gvs->frame_dur = pbi->frame_dur;
-                       vdec_count_info(gvs, 0, stream_offset);
-#endif
-                       hw_to_vdec(pbi)->vdec_fps_detec(hw_to_vdec(pbi)->id);
+                       vdec_count_info(pbi->gvs, 0, stream_offset);
+                       pbi->gvs->bit_rate = bit_depth_luma;
+                       pbi->gvs->frame_data = bit_depth_chroma;
+                       pbi->gvs->samp_cnt = get_double_write_mode(pbi);
+                       vdec_fill_vdec_frame(pvdec, &pbi->vframe_qos, pbi->gvs,
+                               vf, pic_config->hw_decode_time);
+                       pvdec->vdec_fps_detec(pvdec->id);
                        if (without_display_mode == 0) {
                                vf_notify_receiver(pbi->provider_name,
                                                VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
@@ -7665,7 +7687,10 @@ static void fill_frame_info(struct VP9Decoder_s *pbi,
 /*
 #define SHOW_QOS_INFO
 */
-       vframe_qos->size = framesize;
+       if (input_frame_based(hw_to_vdec(pbi)))
+               vframe_qos->size = frame->frame_size2;
+       else
+               vframe_qos->size = framesize;
        vframe_qos->pts = pts;
 #ifdef SHOW_QOS_INFO
        vp9_print(pbi, 0, "slice:%d\n", frame->slice_type);
@@ -7698,9 +7723,6 @@ static void fill_frame_info(struct VP9Decoder_s *pbi,
                        vframe_qos->min_skip);
 #endif
        vframe_qos->num++;
-
-       if (pbi->frameinfo_enable)
-               vdec_fill_frame_info(vframe_qos, 1);
 }
 
 /* only when we decoded one field or one frame,
@@ -7708,9 +7730,15 @@ we can call this function to get qos info*/
 static void get_picture_qos_info(struct VP9Decoder_s *pbi)
 {
        struct PIC_BUFFER_CONFIG_s *frame = &pbi->cur_buf->buf;
+       struct vdec_s *vdec = hw_to_vdec(pbi);
 
        if (!frame)
                return;
+       if (vdec->mvfrm) {
+               frame->frame_size2 = vdec->mvfrm->frame_size;
+               frame->hw_decode_time =
+               local_clock() - vdec->mvfrm->hw_decode_start;
+       }
 
        if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) {
                unsigned char a[3];
@@ -8755,19 +8783,17 @@ int vvp9_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
        vstatus->error_count = 0;
        vstatus->status = vp9->stat | vp9->fatal_error;
        vstatus->frame_dur = vp9->frame_dur;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
-       vstatus->bit_rate = gvs->bit_rate;
-       vstatus->frame_data = gvs->frame_data;
-       vstatus->total_data = gvs->total_data;
-       vstatus->frame_count = gvs->frame_count;
-       vstatus->error_frame_count = gvs->error_frame_count;
-       vstatus->drop_frame_count = gvs->drop_frame_count;
-       vstatus->total_data = gvs->total_data;
-       vstatus->samp_cnt = gvs->samp_cnt;
-       vstatus->offset = gvs->offset;
+       vstatus->bit_rate = vp9->gvs->bit_rate;
+       vstatus->frame_data = vp9->gvs->frame_data;
+       vstatus->total_data = vp9->gvs->total_data;
+       vstatus->frame_count = vp9->gvs->frame_count;
+       vstatus->error_frame_count = vp9->gvs->error_frame_count;
+       vstatus->drop_frame_count = vp9->gvs->drop_frame_count;
+       vstatus->total_data = vp9->gvs->total_data;
+       vstatus->samp_cnt = vp9->gvs->samp_cnt;
+       vstatus->offset = vp9->gvs->offset;
        snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
                "%s", DRIVER_NAME);
-#endif
        return 0;
 }
 
@@ -8935,6 +8961,7 @@ static int vvp9_local_init(struct VP9Decoder_s *pbi)
                pr_info("the struct of vdec status malloc failed.\n");
                return -1;
        }
+       vdec_set_vframe_comm(hw_to_vdec(pbi), DRIVER_NAME);
 #ifdef DEBUG_PTS
        pbi->pts_missed = 0;
        pbi->pts_hit = 0;
@@ -9965,6 +9992,8 @@ static void run_front(struct vdec_s *vdec)
                WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
                size = pbi->chunk->size +
                        (pbi->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+               if (vdec->mvfrm)
+                       vdec->mvfrm->frame_size = pbi->chunk->size;
        }
        WRITE_VREG(HEVC_DECODE_SIZE, size);
        WRITE_VREG(HEVC_DECODE_COUNT, pbi->slice_idx);
@@ -10130,6 +10159,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                PRINT_FLAG_VDEC_DETAIL, "%s mask %lx\r\n",
                __func__, mask);
 
+       if (vdec->mvfrm)
+               vdec->mvfrm->hw_decode_start = local_clock();
        run_count[pbi->index]++;
        pbi->vdec_cb_arg = arg;
        pbi->vdec_cb = callback;
index bc46356e00a3072f0172950d2f133ef2212cbd50..70367da861b09040e78312651f2f932344c20bac 100644 (file)
@@ -1611,6 +1611,8 @@ static int amstream_open(struct inode *inode, struct file *file)
        if (iminor(inode) >= amstream_port_num)
                return -ENODEV;
 
+       //pr_err("%s, port name %s\n", __func__, port->name);
+       //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
        mutex_lock(&amstream_mutex);
 
        if (port->type & PORT_TYPE_VIDEO) {
@@ -2606,17 +2608,71 @@ static long amstream_do_ioctl_new(struct port_priv_s *priv,
                        r = -EINVAL;
                break;
        case AMSTREAM_IOC_GET_QOSINFO:
+       case AMSTREAM_IOC_GET_MVDECINFO:
                {
-                       struct av_param_qosinfo_t  __user *uarg = (void *)arg;
-                       struct vframe_qos_s *qos_info = vdec_get_qos_info();
-                       if (this->type & PORT_TYPE_VIDEO) {
-                               if (qos_info != NULL && copy_to_user((void *)uarg->vframe_qos,
-                                                       qos_info,
-                                                       QOS_FRAME_NUM*sizeof(struct vframe_qos_s))) {
-                                       r = -EFAULT;
+                       u32 slots = 0;
+                       u32 struct_size = 0;
+                       int vdec_id = 0;
+                       struct vdec_s *vdec = NULL;
+                       struct vframe_counter_s tmpbuf[QOS_FRAME_NUM] = {0};
+                       struct av_param_mvdec_t  __user *uarg = (void *)arg;
+
+                       if (AMSTREAM_IOC_GET_MVDECINFO == cmd) {
+                               if (get_user(vdec_id, &uarg->vdec_id) < 0
+                                  || get_user(struct_size, &uarg->struct_size) < 0) {
+                                               r = -EFAULT;
+                                               break;
+                                       }
+                               if (struct_size != sizeof(struct av_param_mvdec_t)) {
+                                       pr_err("pass in size %u != expected size %u\n",
+                                               struct_size, sizeof(struct av_param_mvdec_t));
+                                       pr_err("App using old structue,we will support it.\n");
+                                       //Here will add the compatibility for old structure when
+                                       //current struecture be substituded by newer structure.
+                                       //msleep(1000); let app handle it.
                                        break;
                                }
                        }
+                       vdec = vdec_get_vdec_by_id(vdec_id);
+                       if (!vdec) {
+                               r = 0;
+                               break;
+                       }
+
+                       slots = vdec_get_frame_vdec(vdec, tmpbuf);
+                       if (AMSTREAM_IOC_GET_MVDECINFO == cmd)
+                               put_user(slots, &uarg->slots);
+                       if (slots) {
+                               if (AMSTREAM_IOC_GET_MVDECINFO == cmd) {
+                                       if (copy_to_user((void *)&uarg->comm,
+                                                               &vdec->mvfrm->comm,
+                                                               sizeof(struct vframe_comm_s))) {
+                                               r = -EFAULT;
+                                               break;
+                                       }
+                                       if (copy_to_user((void *)&uarg->minfo[0],
+                                                               tmpbuf,
+                                                               slots*sizeof(struct vframe_counter_s))) {
+                                               r = -EFAULT;
+                                               kfree(tmpbuf);
+                                               break;
+                                       }
+                               }else { //For compatibility, only copy the qos
+                                       struct av_param_qosinfo_t  __user *uarg = (void *)arg;
+                                       int i;
+                                       for (i=0; i<slots; i++)
+                                               if (copy_to_user((void *)&uarg->vframe_qos[i],
+                                                                       &tmpbuf[i].qos,
+                                                                       sizeof(struct vframe_qos_s))) {
+                                                       r = -EFAULT;
+                                                       break;
+                                               }
+                               }
+                       } else {
+                               /*Vdec didn't produce item,wait for 10 ms to avoid user application
+                             infinitely calling*/
+                               //msleep(10); let user app handle it.
+                       }
                }
                break;
        default:
@@ -3420,6 +3476,7 @@ static long amstream_do_ioctl(struct port_priv_s *priv,
        case AMSTREAM_IOC_SET_PTR:
        case AMSTREAM_IOC_SYSINFO:
        case AMSTREAM_IOC_GET_QOSINFO:
+       case AMSTREAM_IOC_GET_MVDECINFO:
                r = amstream_do_ioctl_new(priv, cmd, arg);
                break;
        default: