From 02515e2a0524217240c0cdede672d6b80618867e Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Wed, 18 Dec 2019 14:17:33 +0000 Subject: decode: optimize local reset when decode error happened. [1/1] PD#SWPL-18664 Problem: optimize local reset when decode error happened. Solution: just clear dpb reference when decode error reset. Verify: u212 Change-Id: If8628625ce8ed0d95048ea900dbd972fcfa57ccf Signed-off-by: Nanxin Qin --- diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index 2b3e5c3..c2a0f38 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -850,7 +850,6 @@ struct vdec_h264_hw_s { bool ref_err_flush_dpb_flag; unsigned int first_i_policy; u32 reorder_dpb_size_margin; - bool wait_reset_done_flag; }; static u32 again_threshold; @@ -860,7 +859,7 @@ static void dump_bufspec(struct vdec_h264_hw_s *hw, const char *caller); static void h264_reconfig(struct vdec_h264_hw_s *hw); static void h264_reset_bufmgr(struct vdec_s *vdec); -static void vh264_local_init(struct vdec_h264_hw_s *hw); +static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset); static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw); static int vh264_stop(struct vdec_h264_hw_s *hw); static s32 vh264_init(struct vdec_h264_hw_s *hw); @@ -1608,10 +1607,36 @@ static void buf_spec_init(struct vdec_h264_hw_s *hw) int i; unsigned long flags; spin_lock_irqsave(&hw->bufspec_lock, flags); + + for (i = 0; i < VF_POOL_SIZE; i++) { + struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i]; + u32 ref_idx = BUFSPEC_INDEX(vf->index); + if ((vf->index != -1) && + (hw->buffer_spec[ref_idx].vf_ref == 0) && + (hw->buffer_spec[ref_idx].used != -1)) { + vf->index = -1; + } + } + + hw->cur_pool++; + if (hw->cur_pool >= VF_POOL_NUM) + hw->cur_pool = 0; + + for (i = 0; i < VF_POOL_SIZE; i++) { + struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i]; + u32 ref_idx = BUFSPEC_INDEX(vf->index); + if ((vf->index != -1) && + (hw->buffer_spec[ref_idx].vf_ref == 0) && + (hw->buffer_spec[ref_idx].used != -1)) { + vf->index = -1; + } + } + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { hw->buffer_spec[i].used = -1; hw->buffer_spec[i].canvas_pos = -1; } + if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) dump_bufspec(hw, __func__); @@ -2023,6 +2048,55 @@ static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) 7); } +static int v4l_get_free_buf_idx(struct vdec_s *vdec) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct aml_vcodec_ctx * v4l = hw->v4l2_ctx; + struct v4l_buff_pool *pool = &v4l->cap_pool; + struct buffer_spec_s *pic = NULL; + int i, idx = INVALID_IDX; + ulong flags; + + spin_lock_irqsave(&hw->bufspec_lock, flags); + for (i = 0; i < pool->in; ++i) { + u32 state = (pool->seq[i] >> 16); + u32 index = (pool->seq[i] & 0xffff); + + switch (state) { + case V4L_CAP_BUFF_IN_DEC: + pic = &hw->buffer_spec[i]; + if ((pic->vf_ref == 0) && + (pic->used == 0) && + pic->cma_alloc_addr) { + idx = i; + } + break; + case V4L_CAP_BUFF_IN_M2M: + pic = &hw->buffer_spec[index]; + if (!alloc_one_buf_spec_from_queue(hw, index)) { + config_decode_canvas(hw, index); + idx = index; + } + break; + default: + pr_err("v4l buffer state err %d.\n", state); + break; + } + + if (idx != INVALID_IDX) { + pic->used = 1; + break; + } + } + spin_unlock_irqrestore(&hw->bufspec_lock, flags); + + if (idx < 0) { + dpb_print(DECODE_ID(hw), 0, "%s fail\n", __func__); + vmh264_dump_state(vdec); + } + + return idx; +} int get_free_buf_idx(struct vdec_s *vdec) { @@ -2033,23 +2107,18 @@ int get_free_buf_idx(struct vdec_s *vdec) int buf_total = BUFSPEC_POOL_SIZE; if (hw->is_used_v4l) - buf_total = hw->dpb.mDPB.size; + return v4l_get_free_buf_idx(vdec); spin_lock_irqsave(&hw->bufspec_lock, flags); /*hw->start_search_pos = 0;*/ for (i = hw->start_search_pos; i < buf_total; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; - else { + else addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->is_used_v4l && !addr) { - if (!alloc_one_buf_spec_from_queue(hw, i)) { - config_decode_canvas(hw, i); - addr = hw->buffer_spec[i].cma_alloc_addr; - } - } - } - if (hw->buffer_spec[i].used == 0 && addr) { + + if (hw->buffer_spec[i].vf_ref == 0 && + hw->buffer_spec[i].used == 0 && addr) { hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; index = i; @@ -2060,16 +2129,11 @@ int get_free_buf_idx(struct vdec_s *vdec) for (i = 0; i < hw->start_search_pos; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; - else { + else addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->is_used_v4l && !addr) { - if (!alloc_one_buf_spec_from_queue(hw, i)) { - config_decode_canvas(hw, i); - addr = hw->buffer_spec[i].cma_alloc_addr; - } - } - } - if (hw->buffer_spec[i].used == 0 && addr) { + + if (hw->buffer_spec[i].vf_ref == 0 && + hw->buffer_spec[i].used == 0 && addr) { hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; index = i; @@ -2324,16 +2388,35 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) int i; unsigned long addr; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct aml_vcodec_ctx * v4l = hw->v4l2_ctx; int canvas_pos_min = BUFSPEC_POOL_SIZE; int index = -1; int ret = 0; int allocated_count = 0; + + if (hw->is_used_v4l) { + for (i = 0; i < hw->dpb.mDPB.size; i++) { + if (hw->buffer_spec[i].used == 0 && + hw->buffer_spec[i].vf_ref == 0 && + hw->buffer_spec[i].cma_alloc_addr) { + return 1; + } + } + + if (v4l2_m2m_num_dst_bufs_ready(v4l->m2m_ctx) + >= run_ready_min_buf_num) + return 1; + + return 0; + } + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; else addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->buffer_spec[i].used == 0) { + if (hw->buffer_spec[i].used == 0 && + hw->buffer_spec[i].vf_ref == 0) { if (addr) return 1; @@ -2350,13 +2433,12 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) dealloc_buf_specs(hw, 0); if (max_alloc_buf_count == 0 || allocated_count < max_alloc_buf_count) { - if (hw->is_used_v4l) - ret = 1; - else if (alloc_one_buf_spec(hw, index) >= 0) + if (alloc_one_buf_spec(hw, index) >= 0) ret = 1; } mutex_unlock(&vmh264_mutex); } + return ret; } @@ -2753,7 +2835,7 @@ int notify_v4l_eos(struct vdec_s *vdec) if (hw->is_used_v4l && hw->eos) { expires = jiffies + msecs_to_jiffies(2000); - while (INVALID_IDX == (index = get_free_buf_idx(vdec))) { + while (INVALID_IDX == (index = v4l_get_free_buf_idx(vdec))) { if (time_after(jiffies, expires)) break; } @@ -3783,6 +3865,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) { struct vdec_s *vdec = op_arg; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + unsigned long flags; int buf_spec_num; int frame_index; @@ -3807,6 +3890,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) } /*get_buf_spec_idx_by_canvas_config(hw, &vf->canvas0_config[0]);*/ + spin_lock_irqsave(&hw->bufspec_lock, flags); if (hw->buffer_spec[buf_spec_num].used == 2) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, @@ -3820,13 +3904,11 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) set_frame_output_flag(&hw->dpb, frame_index); } else { - unsigned long flags; dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s %p isolated vf, buf_spec_num %d used %d vf_ref %d\n", __func__, vf, buf_spec_num, hw->buffer_spec[buf_spec_num].used, hw->buffer_spec[buf_spec_num].vf_ref); - spin_lock_irqsave(&hw->bufspec_lock, flags); hw->buffer_spec[buf_spec_num].vf_ref--; if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) { if (hw->buffer_spec[buf_spec_num].used == 3) @@ -3834,12 +3916,12 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) else if (hw->buffer_spec[buf_spec_num].used == 5) hw->buffer_spec[buf_spec_num].used = 0; } - spin_unlock_irqrestore(&hw->bufspec_lock, flags); if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) dump_bufspec(hw, __func__); } + spin_unlock_irqrestore(&hw->bufspec_lock, flags); hw->vf_put_count++; kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); @@ -5100,6 +5182,8 @@ static bool is_buffer_available(struct vdec_s *vdec) if (hw->reset_bufmgr_flag == 1) buffer_available = 1; + else if (hw->is_used_v4l) + buffer_available = have_free_buf_spec(vdec); } return buffer_available; @@ -6355,7 +6439,7 @@ static void vmh264_dump_state(struct vdec_s *vdec) } dpb_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x wait_reset_done_flag %d\n", + "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x \n", __func__, kfifo_len(&hw->newframe_q), VF_POOL_SIZE, @@ -6368,8 +6452,7 @@ static void vmh264_dump_state(struct vdec_s *vdec) p_H264_Dpb->mDPB.init_done, p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size, is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB), - p_H264_Dpb->fast_output_enable, - hw->wait_reset_done_flag + p_H264_Dpb->fast_output_enable ); dump_dpb(&p_H264_Dpb->mDPB, 1); @@ -6752,7 +6835,7 @@ static int vmh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) } static unsigned char amvdec_enable_flag; -static void vh264_local_init(struct vdec_h264_hw_s *hw) +static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset) { int i; hw->init_flag = 0; @@ -6823,14 +6906,16 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) else if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x20) hw->send_error_frame_flag = 0; /*Don't display mark err frames*/ - INIT_KFIFO(hw->display_q); - INIT_KFIFO(hw->newframe_q); + if (!is_reset) { + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - hw->vfpool[hw->cur_pool][i].bufWidth = 1920; - kfifo_put(&hw->newframe_q, vf); + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); + hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ + hw->vfpool[hw->cur_pool][i].bufWidth = 1920; + kfifo_put(&hw->newframe_q, vf); + } } hw->duration_from_pts_done = 0; @@ -6868,7 +6953,7 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) hw->stat |= STAT_ISR_REG; mutex_init(&hw->chunks_mutex); - vh264_local_init(hw); + vh264_local_init(hw, false); INIT_WORK(&hw->work, vh264_work); INIT_WORK(&hw->notify_work, vh264_notify_work); INIT_WORK(&hw->timeout_work, vh264_timeout_work); @@ -8286,19 +8371,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, if (hw->reset_bufmgr_flag || ((error_proc_policy & 0x40) && p_H264_Dpb->buf_alloc_fail)) { - if (!hw->is_used_v4l) - h264_reset_bufmgr(vdec); - else { - struct aml_vcodec_ctx *ctx = - (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - pr_info("v4l2 buffer reset\n"); - hw->wait_reset_done_flag = 1; - hw->reset_bufmgr_flag = 0; - vdec_v4l_post_evet(ctx, V4L2_EVENT_REQUEST_RESET); - hw->dec_result = DEC_RESULT_NONE; - vdec_schedule_work(&hw->work); - return; - } + h264_reset_bufmgr(vdec); hw->reset_bufmgr_flag = 0; } @@ -8497,6 +8570,25 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->init_flag = 1; } +static void clear_refer_bufs(struct vdec_h264_hw_s *hw) +{ + int i; + + mutex_lock(&vmh264_mutex); + dealloc_buf_specs(hw, 1); + mutex_unlock(&vmh264_mutex); + + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); + hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ + hw->vfpool[hw->cur_pool][i].bufWidth = 1920; + kfifo_put(&hw->newframe_q, vf); + } +} + static void reset(struct vdec_s *vdec) { struct vdec_h264_hw_s *hw = @@ -8518,9 +8610,10 @@ static void reset(struct vdec_s *vdec) hw->eos = 0; hw->decode_pic_count = 0; hw->dec_result = DEC_RESULT_NONE; + + clear_refer_bufs(hw); reset_process_time(hw); h264_reset_bufmgr(vdec); - hw->wait_reset_done_flag = 0; dpb_print(DECODE_ID(hw), 0, "%s\n", __func__); } @@ -8597,7 +8690,6 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw) if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) dump_bufspec(hw, "after h264_reconfig"); - } #ifdef ERROR_HANDLE_TEST @@ -8620,7 +8712,6 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw) static void h264_reset_bufmgr(struct vdec_s *vdec) { - int i; ulong timeout; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; #if 0 @@ -8686,32 +8777,14 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) schedule(); } - for (i = 0; i < VF_POOL_SIZE; i++) - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - - hw->cur_pool++; - if (hw->cur_pool >= VF_POOL_NUM) - hw->cur_pool = 0; - - for (i = 0; i < VF_POOL_SIZE; i++) - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - - vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_RESET, NULL); buf_spec_init(hw); - vh264_local_init(hw); + vh264_local_init(hw, true); /*hw->decode_pic_count = 0; hw->seq_info2 = 0;*/ - if (hw->is_used_v4l) { - mutex_lock(&vmh264_mutex); - /* detach relationship with v4l buffs.*/ - dealloc_buf_specs(hw, 1); - mutex_unlock(&vmh264_mutex); - } - if (vh264_set_params(hw, hw->cfg_param1, hw->cfg_param2, @@ -8808,7 +8881,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev) hw->first_head_check_flag = 0; hw->new_iframe_flag = 0; hw->ref_err_flush_dpb_flag = 0; - hw->wait_reset_done_flag = 0; if (pdata->sys_info) hw->vh264_amstream_dec_info = *pdata->sys_info; diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c index 8c4a9ab..fe582a9 100644 --- a/drivers/frame_provider/decoder/h265/vh265.c +++ b/drivers/frame_provider/decoder/h265/vh265.c @@ -5554,6 +5554,7 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, && pic->output_ready == 0 && pic->width == hevc->pic_w && pic->height == hevc->pic_h + && pic->vf_ref == 0 ) { if (new_pic) { if (new_pic->POC != INVALID_POC) { @@ -5670,14 +5671,13 @@ static struct PIC_s *v4l_get_new_pic(struct hevc_state_s *hevc, union param_u *rpm_param) { int ret; - int used_buf_num = get_work_pic_num(hevc); struct aml_vcodec_ctx * v4l = hevc->v4l2_ctx; + struct v4l_buff_pool *pool = &v4l->cap_pool; struct PIC_s *new_pic = NULL; struct PIC_s *pic = NULL; int i; - for (i = 0; i < used_buf_num; ++i) { - struct v4l_buff_pool *pool = &v4l->cap_pool; + for (i = 0; i < pool->in; ++i) { u32 state = (pool->seq[i] >> 16); u32 index = (pool->seq[i] & 0xffff); @@ -5690,6 +5690,7 @@ static struct PIC_s *v4l_get_new_pic(struct hevc_state_s *hevc, (pic->output_ready == 0) && (pic->width == hevc->pic_w) && (pic->height == hevc->pic_h) && + (pic->vf_ref == 0) && pic->cma_alloc_addr) { new_pic = pic; } diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c index d227e15..a24a596 100644 --- a/drivers/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/frame_provider/decoder/vp9/vvp9.c @@ -2174,14 +2174,14 @@ static int v4l_get_free_fb(struct VP9Decoder_s *pbi) struct VP9_Common_s *const cm = &pbi->common; struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; struct aml_vcodec_ctx * v4l = pbi->v4l2_ctx; + struct v4l_buff_pool *pool = &v4l->cap_pool; struct PIC_BUFFER_CONFIG_s *pic = NULL; int i, idx = INVALID_IDX; ulong flags; lock_buffer_pool(cm->buffer_pool, flags); - for (i = 0; i < pbi->used_buf_num; ++i) { - struct v4l_buff_pool *pool = &v4l->cap_pool; + for (i = 0; i < pool->in; ++i) { u32 state = (pool->seq[i] >> 16); u32 index = (pool->seq[i] & 0xffff); -- cgit