v4l: optimize the process of the resolution change. [1/1]
authorNanxin Qin <nanxin.qin@amlogic.com>
Thu, 22 Oct 2020 06:23:55 +0000 (14:23 +0800)
committerNanxin Qin <nanxin.qin@amlogic.com>
Thu, 29 Oct 2020 02:22:40 +0000 (19:22 -0700)
PD#SWPL-34992

Problem:
[RDK][Placto] H264 decoding error

Solution:
optimize the process of the resolution change.

Verify:
ab301

Change-Id: I1b70deb86e51169cc1d19f0ffb121d8053cc2957
Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
drivers/amvdec_ports/aml_vcodec_dec.c
drivers/amvdec_ports/aml_vcodec_drv.h
drivers/frame_provider/decoder/h264_multi/vmh264.c
drivers/frame_provider/decoder/h265/vh265.c
drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
drivers/frame_provider/decoder/vav1/vav1.c
drivers/frame_provider/decoder/vp9/vvp9.c

index b7c904605d8459d8f6492e4a0b0b616b1f752a07..29da0f1754e94434c38fb73ece35aafba461dd23 100644 (file)
@@ -1197,6 +1197,7 @@ static int vidioc_decoder_streamon(struct file *file, void *priv,
                        mutex_unlock(&ctx->state_lock);
 
                        ctx->is_stream_off = false;
+                       ctx->v4l_resolution_change = false;
                }
        } else
                ctx->is_out_stream_off = false;
@@ -2318,6 +2319,7 @@ static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
        struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q);
 
        ctx->has_receive_eos = false;
+
        v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
 
        v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
index f3ee0c5da958ec754d22f00d13e6e801d0fa5786..e9195dcff60f9ac26cd2555435e07c331e4ef40d 100644 (file)
@@ -408,6 +408,7 @@ struct aml_vdec_thread {
  * @param_change: indicate encode parameter type
  * @param_sets_from_ucode: if true indicate ps from ucode.
  * @v4l_codec_dpb_ready: queue buffer number greater than dpb.
+ # @v4l_resolution_change: indicate resolution change happend.
  * @comp: comp be used for sync picture information with decoder.
  * @config: used to set or get parms for application.
  * @picinfo: store picture info after header parsing.
@@ -453,6 +454,7 @@ struct aml_vcodec_ctx {
        int                             dpb_size;
        bool                            param_sets_from_ucode;
        bool                            v4l_codec_dpb_ready;
+       bool                            v4l_resolution_change;
        struct completion               comp;
        struct v4l2_config_parm         config;
        struct vdec_pic_info            picinfo;
index f441234098d985e3c14624d94e0ce554762b0c9d..4390ccc46f878a841e1d2c520c3584b7061d3d44 100644 (file)
@@ -906,7 +906,7 @@ struct vdec_h264_hw_s {
        unsigned int last_picture_slice_count;
        unsigned int first_pre_frame_num;
 #endif
-       unsigned int res_ch_flag;
+       u32 res_ch_flag;
        u32 b_frame_error_count;
        struct vdec_info gvs;
        u32 kpi_first_i_comming;
@@ -937,6 +937,7 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
                        u32 index);
 static void release_aux_data(struct vdec_h264_hw_s *hw,
        int buf_spec_num);
+static void clear_refer_bufs(struct vdec_h264_hw_s *hw);
 #ifdef ERROR_HANDLE_TEST
 static void h264_clear_dpb(struct vdec_h264_hw_s *hw);
 #endif
@@ -2534,6 +2535,11 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec)
        int allocated_count = 0;
 
        if (hw->is_used_v4l) {
+               struct h264_dpb_stru *dpb = &hw->dpb;
+
+               if (dpb->mDPB.used_size >= dpb->mDPB.size - 1)
+                       return 0;
+
                for (i = 0; i < hw->dpb.mDPB.size; i++) {
                        if (hw->buffer_spec[i].used == 0 &&
                                hw->buffer_spec[i].vf_ref == 0 &&
@@ -8734,6 +8740,7 @@ static int v4l_res_change(struct vdec_h264_hw_s *hw,
                        vdec_v4l_set_ps_infos(ctx, &ps);
                        vdec_v4l_res_ch_event(ctx);
                        hw->res_ch_flag = 1;
+                       ctx->v4l_resolution_change = 1;
                        amvdec_stop();
                        if (hw->mmu_enable)
                                amhevc_stop();
@@ -8793,11 +8800,12 @@ static void vh264_work_implement(struct vdec_h264_hw_s *hw,
                                        }
                                        hw->v4l_params_parsed = true;
                                        vdec_v4l_set_ps_infos(ctx, &ps);
+                                       clear_refer_bufs(hw);
+
                                        amvdec_stop();
                                        if (hw->mmu_enable)
                                                amhevc_stop();
-                               }
-                               else {
+                               } else {
                                        if (vh264_set_params(hw, param1,
                                        param2, param3, param4, false) < 0)
                                                dpb_print(DECODE_ID(hw), 0, "set parameters error\n");
@@ -9237,10 +9245,11 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                                        v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
                                        run_ready_min_buf_num)
                                        ret = 0;
+                               else if (ctx->v4l_codec_dpb_ready &&
+                                       !is_buffer_available(vdec))
+                                       ret = 0;
                        } else {
-                               if ((hw->res_ch_flag == 1) &&
-                                       ((ctx->state <= AML_STATE_INIT) ||
-                                       (ctx->state >= AML_STATE_FLUSHING)))
+                               if (ctx->v4l_resolution_change)
                                        ret = 0;
                        }
                } else if (!ctx->v4l_codec_dpb_ready) {
@@ -9527,10 +9536,17 @@ static void run(struct vdec_s *vdec, unsigned long mask,
 static void clear_refer_bufs(struct vdec_h264_hw_s *hw)
 {
        int i;
+       ulong flags;
 
-       mutex_lock(&vmh264_mutex);
-       dealloc_buf_specs(hw, 1);
-       mutex_unlock(&vmh264_mutex);
+       if (hw->is_used_v4l) {
+               spin_lock_irqsave(&hw->bufspec_lock, flags);
+               for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+                       hw->buffer_spec[i].used = -1;
+                       hw->buffer_spec[i].cma_alloc_addr = 0;
+                       hw->buffer_spec[i].buf_adr = 0;
+               }
+               spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+       }
 
        INIT_KFIFO(hw->display_q);
        INIT_KFIFO(hw->newframe_q);
@@ -9565,11 +9581,7 @@ static void reset(struct vdec_s *vdec)
        }
        hw->eos = 0;
        hw->decode_pic_count = 0;
-       hw->dec_result = DEC_RESULT_NONE;
-       /* v4l will reset on every res change */
-       hw->res_ch_flag = 0;
 
-       clear_refer_bufs(hw);
        reset_process_time(hw);
        h264_reset_bufmgr(vdec);
 
@@ -9744,10 +9756,12 @@ static void h264_reset_bufmgr(struct vdec_s *vdec)
        /*hw->decode_pic_count = 0;
        hw->seq_info2 = 0;*/
 
-       hw->cfg_param1 = READ_VREG(AV_SCRATCH_1);
-       hw->cfg_param2 = READ_VREG(AV_SCRATCH_2);
-       hw->cfg_param3 = READ_VREG(AV_SCRATCH_6);
-       hw->cfg_param4 = READ_VREG(AV_SCRATCH_B);
+       if (!hw->is_used_v4l) {
+               hw->cfg_param1 = READ_VREG(AV_SCRATCH_1);
+               hw->cfg_param2 = READ_VREG(AV_SCRATCH_2);
+               hw->cfg_param3 = READ_VREG(AV_SCRATCH_6);
+               hw->cfg_param4 = READ_VREG(AV_SCRATCH_B);
+       }
 
        if (vh264_set_params(hw,
                hw->cfg_param1,
index 132a3d0776b4f36e3bc724cf9231ba14cbf17089..257b779832582cf451616740f6ced66ef4d54f73 100644 (file)
@@ -1792,7 +1792,7 @@ struct hevc_state_s {
        u32 mem_map_mode;
        u32 performance_profile;
        struct vdec_info *gvs;
-       unsigned int res_ch_flag;
+       u32 res_ch_flag;
        bool ip_mode;
        u32 kpi_first_i_comming;
        u32 kpi_first_i_decoded;
@@ -10081,6 +10081,7 @@ static int v4l_res_change(struct hevc_state_s *hevc, union param_u *rpm_param)
                        vdec_v4l_res_ch_event(ctx);
                        hevc->v4l_params_parsed = false;
                        hevc->res_ch_flag = 1;
+                       ctx->v4l_resolution_change = 1;
                        hevc->eos = 1;
                        flush_output(hevc, NULL);
                        //del_timer_sync(&hevc->timer);
@@ -13187,9 +13188,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                                run_ready_min_buf_num)
                                        ret = 0;
                        } else {
-                               if ((hevc->res_ch_flag == 1) &&
-                               ((ctx->state <= AML_STATE_INIT) ||
-                               (ctx->state >= AML_STATE_FLUSHING)))
+                               if (ctx->v4l_resolution_change)
                                        ret = 0;
                        }
                } else if (!ctx->v4l_codec_dpb_ready) {
index ba4c9f5845ed0f173d902976d344d4546683d3f0..160ee6fd9fe93821d6c0b5f6ee9c2d8f668f3689 100644 (file)
@@ -227,7 +227,7 @@ struct vdec_mjpeg_hw_s {
        int dynamic_buf_num_margin;
        int sidebind_type;
        int sidebind_channel_id;
-       unsigned int res_ch_flag;
+       u32 res_ch_flag;
        u32 canvas_mode;
        u32 canvas_endian;
 };
@@ -319,6 +319,7 @@ static int v4l_res_change(struct vdec_mjpeg_hw_s *hw, int width, int height)
                        vdec_v4l_res_ch_event(ctx);
                        hw->v4l_params_parsed = false;
                        hw->res_ch_flag = 1;
+                       ctx->v4l_resolution_change = 1;
                        hw->eos = 1;
                        notify_v4l_eos(hw_to_vdec(hw));
 
@@ -1281,9 +1282,7 @@ static unsigned long run_ready(struct vdec_s *vdec,
                                        run_ready_min_buf_num)
                                        return 0;
                        } else {
-                               if ((hw->res_ch_flag == 1) &&
-                               ((ctx->state <= AML_STATE_INIT) ||
-                               (ctx->state >= AML_STATE_FLUSHING)))
+                               if (ctx->v4l_resolution_change)
                                        return 0;
                        }
                } else if (!ctx->v4l_codec_dpb_ready) {
index 59e096d96821ad86a43af46a1889a1ad0c065189..73925e9a4cfe1ec082d36fa8f2bb99c6b4d94750 100644 (file)
@@ -326,7 +326,7 @@ struct vdec_mpeg12_hw_s {
        u32 dynamic_buf_num_margin;
        struct vdec_info gvs;
        struct vframe_qos_s vframe_qos;
-       unsigned int res_ch_flag;
+       u32 res_ch_flag;
        u32 i_only;
        u32 kpi_first_i_comming;
        u32 kpi_first_i_decoded;
@@ -1818,6 +1818,7 @@ static int v4l_res_change(struct vdec_mpeg12_hw_s *hw, int width, int height)
                        vdec_v4l_res_ch_event(ctx);
                        hw->v4l_params_parsed = false;
                        hw->res_ch_flag = 1;
+                       ctx->v4l_resolution_change = 1;
                        hw->eos = 1;
                        flush_output(hw);
                        notify_v4l_eos(hw_to_vdec(hw));
@@ -3104,9 +3105,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                                if (!ctx->v4l_codec_dpb_ready)
                                        return 0;
                        } else {
-                               if ((hw->res_ch_flag == 1) &&
-                               ((ctx->state <= AML_STATE_INIT) ||
-                               (ctx->state >= AML_STATE_FLUSHING)))
+                               if (ctx->v4l_resolution_change)
                                        return 0;
                        }
                } else if (!ctx->v4l_codec_dpb_ready) {
index 1ef8ced58a3b940dbe25bf8df7ab6ae59e3d53e7..1d34412d0f78e0d8baf95be341f9adf62878b3dd 100644 (file)
@@ -318,7 +318,7 @@ struct vdec_mpeg4_hw_s {
        u32 i_only;
        int sidebind_type;
        int sidebind_channel_id;
-       unsigned int res_ch_flag;
+       u32 res_ch_flag;
        unsigned int i_decoded_frames;
        unsigned int i_lost_frames;
        unsigned int i_concealed_frames;
@@ -1015,6 +1015,7 @@ static int v4l_res_change(struct vdec_mpeg4_hw_s *hw, int width, int height)
                        vdec_v4l_res_ch_event(ctx);
                        hw->v4l_params_parsed = false;
                        hw->res_ch_flag = 1;
+                       ctx->v4l_resolution_change = 1;
                        hw->eos = 1;
                        flush_output(hw);
                        notify_v4l_eos(hw_to_vdec(hw));
@@ -2286,9 +2287,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                                        run_ready_min_buf_num)
                                        return 0;
                        } else {
-                               if ((hw->res_ch_flag == 1) &&
-                               ((ctx->state <= AML_STATE_INIT) ||
-                               (ctx->state >= AML_STATE_FLUSHING)))
+                               if (ctx->v4l_resolution_change)
                                        return 0;
                        }
                } else if (!ctx->v4l_codec_dpb_ready) {
index c9e4cbae0d4a7909b1662f11e8eccabae59783f5..853c2e2467621a2aef1a0a88af61d29b18b1099f 100644 (file)
@@ -803,7 +803,7 @@ struct AV1HW_s {
        u32 mem_map_mode;
        u32 dynamic_buf_num_margin;
        struct vframe_s vframe_dummy;
-       unsigned int res_ch_flag;
+       u32 res_ch_flag;
        int buffer_wrap[FRAME_BUFFERS];
 };
 static void av1_dump_state(struct vdec_s *vdec);
@@ -7850,6 +7850,7 @@ static int v4l_res_change(struct AV1HW_s *hw)
                        vdec_v4l_res_ch_event(ctx);
                        hw->v4l_params_parsed = false;
                        hw->res_ch_flag = 1;
+                       ctx->v4l_resolution_change = 1;
                        hw->eos = 1;
                        //del_timer_sync(&pbi->timer);
                        notify_v4l_eos(hw_to_vdec(hw));
@@ -9580,9 +9581,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                                run_ready_min_buf_num)
                                        ret = 0;
                        } else {
-                               if ((hw->res_ch_flag == 1) &&
-                               ((ctx->state <= AML_STATE_INIT) ||
-                               (ctx->state >= AML_STATE_FLUSHING)))
+                               if (ctx->v4l_resolution_change)
                                        ret = 0;
                        }
                } else if (ctx->cap_pool.in < ctx->dpb_size) {
index 92fb6054f10f67e150c8765f5d2402f90d72836e..0b81f1b2dab5e6fc11b379cbd12775553fe4730b 100644 (file)
@@ -1215,7 +1215,7 @@ struct VP9Decoder_s {
        u32 mem_map_mode;
        u32 dynamic_buf_num_margin;
        struct vframe_s vframe_dummy;
-       unsigned int res_ch_flag;
+       u32 res_ch_flag;
        /*struct VP9Decoder_s vp9_decoder;*/
        union param_u vp9_param;
        int sidebind_type;
@@ -7737,6 +7737,7 @@ int continue_decoding(struct VP9Decoder_s *pbi)
 
        if (pbi->is_used_v4l && ctx->param_sets_from_ucode)
                pbi->res_ch_flag = 0;
+
        bit_depth_luma = pbi->vp9_param.p.bit_depth;
        bit_depth_chroma = pbi->vp9_param.p.bit_depth;
 
@@ -8406,6 +8407,7 @@ static int v4l_res_change(struct VP9Decoder_s *pbi)
                        vdec_v4l_res_ch_event(ctx);
                        pbi->v4l_params_parsed = false;
                        pbi->res_ch_flag = 1;
+                       ctx->v4l_resolution_change = 1;
                        pbi->eos = 1;
                        vp9_bufmgr_postproc(pbi);
                        //del_timer_sync(&pbi->timer);
@@ -10208,9 +10210,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                                pbi->run_ready_min_buf_num)
                                        ret = 0;
                        } else {
-                               if ((pbi->res_ch_flag == 1) &&
-                               ((ctx->state <= AML_STATE_INIT) ||
-                               (ctx->state >= AML_STATE_FLUSHING)))
+                               if (ctx->v4l_resolution_change)
                                        ret = 0;
                        }
                } else if (ctx->cap_pool.in < ctx->dpb_size) {