decoder: fix ff/fb for mpeg4&mpeg12&h265 format is abnormal. [1/2]
authoryanan.wang <yanan.wang@amlogic.com>
Thu, 19 Mar 2020 11:39:31 +0000 (19:39 +0800)
committerZhi Zhou <zhi.zhou@amlogic.com>
Wed, 8 Apr 2020 02:20:07 +0000 (18:20 -0800)
PD#SWPL-23122

Problem:
when ff/fb for mpeg4&mpeg12&h265 on trick mode is abnormal.

Solution:
add mpeg4&mpeg12&h265 TRICKMODE_I function.

Verify:
u212

Change-Id: If378a1d0d85f7212316d6c15ceff6becd0130071
Signed-off-by: yanan.wang <yanan.wang@amlogic.com>
drivers/frame_provider/decoder/avs2/vavs2.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

index 938312e225314aed4741e0c824aeba272aea3d8c..e459cd75564417ee48a6b5493536ecbf0ad62476 100644 (file)
@@ -6235,7 +6235,7 @@ static int vavs2_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
                (struct AVS2Decoder_s *)vdec->private;
        if (i_only_flag & 0x100)
                return 0;
-       if (trickmode == TRICKMODE_I)
+       if (trickmode == TRICKMODE_I || trickmode == TRICKMODE_I_HEVC)
                dec->i_only = 0x3;
        else if (trickmode == TRICKMODE_NONE)
                dec->i_only = 0x0;
index 9af3de72c07db6c175bfe6f4ebf1fd078868e742..f1a023f65d91d4c3257c195d878f8cfc7b30efc1 100644 (file)
@@ -537,6 +537,7 @@ void WRITE_VREG_DBG(unsigned adr, unsigned val)
 #undef WRITE_VREG
 #define WRITE_VREG WRITE_VREG_DBG
 #endif
+extern u32 trickmode_i;
 
 static DEFINE_MUTEX(vh265_mutex);
 
@@ -11088,6 +11089,32 @@ static void H265_DECODE_INIT(void)
 }
 #endif
 
+int vh265_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
+{
+    struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private;
+    hevc_print(hevc, 0,        "[%s %d] trickmode:%lu\n", __func__, __LINE__, trickmode);
+
+    if (trickmode == TRICKMODE_I) {
+               trickmode_i = 1;
+               i_only_flag = 0x1;
+    } else if (trickmode == TRICKMODE_NONE) {
+               trickmode_i = 0;
+               i_only_flag = 0x0;
+    } else if (trickmode == 0x02) {
+               trickmode_i = 0;
+               i_only_flag = 0x02;
+    } else if (trickmode == 0x03) {
+               trickmode_i = 1;
+               i_only_flag = 0x03;
+    } else if (trickmode == 0x07) {
+               trickmode_i = 1;
+               i_only_flag = 0x07;
+    }
+    //hevc_print(hevc, 0, "i_only_flag: %d trickmode_i:%d\n", i_only_flag, trickmode_i);
+
+    return 0;
+}
+
 static void config_decode_mode(struct hevc_state_s *hevc)
 {
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
@@ -12867,6 +12894,7 @@ static int amvdec_h265_probe(struct platform_device *pdev)
 #ifdef MULTI_INSTANCE_SUPPORT
        pdata->private = hevc;
        pdata->dec_status = vh265_dec_status;
+       pdata->set_trickmode = vh265_set_trickmode;
        pdata->set_isreset = vh265_set_isreset;
        is_reset = 0;
        if (vh265_init(pdata) < 0) {
@@ -13141,7 +13169,7 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
 
        pdata->private = hevc;
        pdata->dec_status = vh265_dec_status;
-       /* pdata->set_trickmode = set_trickmode; */
+       pdata->set_trickmode = vh265_set_trickmode;
        pdata->run_ready = run_ready;
        pdata->run = run;
        pdata->reset = reset;
index c52de4ba3d409dc3022e40476bae8db80d753944..71a45d019f3873411d1c961b847418ea695d8bec 100644 (file)
@@ -319,6 +319,7 @@ struct vdec_mpeg12_hw_s {
        struct vdec_info gvs;
        struct vframe_qos_s vframe_qos;
        unsigned int res_ch_flag;
+       u32 i_only;
 };
 static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
 static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
@@ -1525,6 +1526,7 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
        struct vdec_s *vdec = hw_to_vdec(hw);
        struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
        ulong nv_order = VIDTYPE_VIU_NV21;
+       bool pb_skip = false;
 
 #ifdef NV21
        type = nv_order;
@@ -1536,6 +1538,12 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
                        nv_order = VIDTYPE_VIU_NV12;
        }
 
+       pb_skip = (hw->pics[hw->refs[0]].offset ==
+               hw->pics[hw->refs[1]].offset);
+       if (hw->i_only) {
+               pb_skip = 1;
+       }
+
        user_data_ready_notify(hw, pic->pts, pic->pts_valid);
 
        if (hw->frame_prog & PICINFO_PROG) {
@@ -1616,7 +1624,7 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
                vf->type_original = vf->type;
 
                if ((error_skip(hw, pic->buffer_info, vf)) ||
-                       ((hw->first_i_frame_ready == 0) &&
+                       (((hw->first_i_frame_ready == 0) || pb_skip) &&
                        ((PICINFO_TYPE_MASK & pic->buffer_info) !=
                         PICINFO_TYPE_I))) {
                        hw->drop_frame_count++;
@@ -3150,6 +3158,23 @@ static void reset(struct vdec_s *vdec)
        pr_info("ammvdec_mpeg12: reset.\n");
 }
 
+static int vmpeg12_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
+{
+       struct vdec_mpeg12_hw_s *hw =
+       (struct vdec_mpeg12_hw_s *)vdec->private;
+       if (!hw)
+               return 0;
+
+       if (trickmode == TRICKMODE_I) {
+               hw->i_only = 0x3;
+               //trickmode_i = 1;
+       } else if (trickmode == TRICKMODE_NONE) {
+               hw->i_only = 0x0;
+               //trickmode_i = 0;
+       }
+       return 0;
+}
+
 static int ammvdec_mpeg12_probe(struct platform_device *pdev)
 {
        struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
@@ -3174,6 +3199,7 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
 
        pdata->private = hw;
        pdata->dec_status = vmmpeg12_dec_status;
+       pdata->set_trickmode = vmpeg12_set_trickmode;
        pdata->run_ready = run_ready;
        pdata->run = run;
        pdata->reset = reset;
index 6b904e0494a16034b9779f056f8e77df8f32471f..aa736132fdce9a21a95450705eef84162ad983d4 100644 (file)
@@ -307,6 +307,7 @@ struct vdec_mpeg4_hw_s {
        bool v4l_params_parsed;
        u32 buf_num;
        u32 dynamic_buf_num_margin;
+       u32 i_only;
 };
 static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw);
 static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw);
@@ -616,6 +617,7 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
        struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
        ulong nv_order = VIDTYPE_VIU_NV21;
        int index = pic->index;
+       bool pb_skip = false;
 
        /* swap uv */
        if (hw->is_used_v4l) {
@@ -624,6 +626,9 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
                        nv_order = VIDTYPE_VIU_NV12;
        }
 
+       if (hw->i_only)
+               pb_skip = 1;
+
        if (pic->pic_info & INTERLACE_FLAG) {
                if (kfifo_get(&hw->newframe_q, &vf) == 0) {
                        mmpeg4_debug_print(DECODE_ID(hw), 0,
@@ -662,7 +667,7 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
                        "field0: pts %d, pts64 %lld, w %d, h %d, dur %d\n",
                        vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration);
 
-               if ((hw->first_i_frame_ready == 0)
+               if (((hw->first_i_frame_ready == 0) || pb_skip)
                         && (pic->pic_type != I_PICTURE)) {
                        hw->drop_frame_count++;
                        hw->vfbuf_use[index]--;
@@ -713,8 +718,8 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
                mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
                        "filed1: pts %d, pts64 %lld, w %d, h %d, dur: %d\n",
                        vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration);
-               if ((hw->first_i_frame_ready == 0) &&
-                       (pic->pic_type != I_PICTURE)) {
+               if (((hw->first_i_frame_ready == 0) || pb_skip)
+                       && (pic->pic_type != I_PICTURE)) {
                        hw->drop_frame_count++;
                        hw->vfbuf_use[index]--;
                        kfifo_put(&hw->newframe_q,
@@ -778,8 +783,8 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
                        "prog: pts %d, pts64 %lld, w %d, h %d, dur %d\n",
                        vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration);
 
-               if ((hw->first_i_frame_ready == 0) &&
-                       (pic->pic_type != I_PICTURE)) {
+               if (((hw->first_i_frame_ready == 0) || pb_skip)
+                       && (pic->pic_type != I_PICTURE)) {
                        hw->drop_frame_count++;
                        hw->vfbuf_use[index]--;
                        kfifo_put(&hw->newframe_q,
@@ -2265,6 +2270,23 @@ static void reset(struct vdec_s *vdec)
        hw->ctx_valid = 0;
 }
 
+static int vmpeg4_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
+{
+       struct vdec_mpeg4_hw_s *hw =
+       (struct vdec_mpeg4_hw_s *)vdec->private;
+       if (!hw)
+               return 0;
+
+       if (trickmode == TRICKMODE_I) {
+               hw->i_only = 0x3;
+               trickmode_i = 1;
+       } else if (trickmode == TRICKMODE_NONE) {
+               hw->i_only = 0x0;
+               trickmode_i = 0;
+       }
+       return 0;
+}
+
 static int ammvdec_mpeg4_probe(struct platform_device *pdev)
 {
        struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
@@ -2289,6 +2311,7 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev)
        pdata->private = hw;
        pdata->dec_status = dec_status;
        /* pdata->set_trickmode = set_trickmode; */
+       pdata->set_trickmode = vmpeg4_set_trickmode;
        pdata->run_ready = run_ready;
        pdata->run = run;
        pdata->reset = reset;
index 206527fb3a44f6f159d0fa0c56f71e397112a3e2..623244f1e97c58966dc8f717aeb81f45d12773dd 100644 (file)
@@ -807,7 +807,6 @@ EXPORT_SYMBOL(vdec_status);
 int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
 {
        int r;
-
        if (vdec->set_trickmode) {
                r = vdec->set_trickmode(vdec, trickmode);
 
@@ -816,7 +815,6 @@ int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
                                trickmode);
                return r;
        }
-
        return -1;
 }
 EXPORT_SYMBOL(vdec_set_trickmode);