From ae26c44f67afb5bf64f50a84361e16f78cbac5ba Mon Sep 17 00:00:00 2001 From: "shihong.zheng" Date: Mon, 3 Aug 2020 13:33:45 +0800 Subject: [PATCH] vmh264: fix dec reset during v4l2 playing. [1/1] PD#SWPL-29734 Problem: fix h264 dec reset. h264 decode driver use cap_pool.out to check buffer num, but it increase both decoder and vpp get frame buffer. Solution: add new count var for dec. mapping a new seq index for decoder buffer. Verify: u212 Change-Id: I9f1b30abbbaf5aeba8f281b4e2613fd3a610e0b3 Signed-off-by: shihong.zheng --- drivers/amvdec_ports/aml_vcodec_dec.c | 18 ++--- drivers/amvdec_ports/aml_vcodec_dec.h | 1 + drivers/amvdec_ports/aml_vcodec_drv.h | 1 + .../decoder/h264_multi/vmh264.c | 80 +++++++++++++++---- 4 files changed, 72 insertions(+), 28 deletions(-) diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c index 1216ada..b0c2721 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amvdec_ports/aml_vcodec_dec.c @@ -409,20 +409,19 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_ dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb); + pfb = &dst_buf_info->frame_buffer; + pfb->buf_idx = dst_buf->index; + pfb->num_planes = dst_buf->num_planes; + pfb->status = FB_ST_NORMAL; if (dst_buf->num_planes == 1) { - pfb = &dst_buf_info->frame_buffer; pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr); pfb->m.mem[0].size = ctx->picinfo.y_len_sz + ctx->picinfo.c_len_sz; pfb->m.mem[0].offset = ctx->picinfo.y_len_sz; - pfb->num_planes = dst_buf->num_planes; - pfb->status = FB_ST_NORMAL; - v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR, "idx: %u, 1 plane, y:(0x%lx, %d)\n", dst_buf->index, pfb->m.mem[0].addr, pfb->m.mem[0].size); } else if (dst_buf->num_planes == 2) { - pfb = &dst_buf_info->frame_buffer; pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr); pfb->m.mem[0].size = ctx->picinfo.y_len_sz; @@ -432,15 +431,11 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_ pfb->m.mem[1].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[1].dma_addr); pfb->m.mem[1].size = ctx->picinfo.c_len_sz; pfb->m.mem[1].offset = ctx->picinfo.c_len_sz >> 1; - pfb->num_planes = dst_buf->num_planes; - pfb->status = FB_ST_NORMAL; - v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR, "idx: %u, 2 planes, y:(0x%lx, %d), c:(0x%lx, %d)\n", dst_buf->index, pfb->m.mem[0].addr, pfb->m.mem[0].size, pfb->m.mem[1].addr, pfb->m.mem[1].size); } else { - pfb = &dst_buf_info->frame_buffer; pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr); pfb->m.mem[0].size = ctx->picinfo.y_len_sz; @@ -455,8 +450,6 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_ pfb->m.mem[2].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[3].dma_addr); pfb->m.mem[2].size = ctx->picinfo.c_len_sz >> 1; pfb->m.mem[2].offset = 0; - pfb->num_planes = dst_buf->num_planes; - pfb->status = FB_ST_NORMAL; v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR, "idx: %u, 3 planes, y:(0x%lx, %d), u:(0x%lx, %d), v:(0x%lx, %d)\n", @@ -473,6 +466,7 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_ info = container_of(pfb, struct aml_video_dec_buf, frame_buffer); + ctx->cap_pool.dec++; ctx->cap_pool.seq[ctx->cap_pool.out++] = (V4L_CAP_BUFF_IN_DEC << 16 | dst_buf->index); v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); @@ -2380,6 +2374,8 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) ctx->buf_used_count = 0; ctx->cap_pool.in = 0; ctx->cap_pool.out = 0; + ctx->cap_pool.dec = 0; + ctx->cap_pool.vpp = 0; } static void m2mops_vdec_device_run(void *priv) diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h index 3406e9f..3653ff0 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.h +++ b/drivers/amvdec_ports/aml_vcodec_dec.h @@ -58,6 +58,7 @@ struct vdec_v4l2_buffer { } m; ulong vf_handle; u32 status; + u32 buf_idx; }; diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h index 1bc6211..a828b42 100644 --- a/drivers/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amvdec_ports/aml_vcodec_drv.h @@ -358,6 +358,7 @@ struct v4l_buff_pool { */ u32 seq[V4L_CAP_BUFF_MAX]; u32 in, out; + u32 dec, vpp; }; enum aml_thread_type { diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index 948b436..84c5f16 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -896,6 +896,7 @@ struct vdec_h264_hw_s { int sidebind_channel_id; u32 low_latency_mode; int ip_field_error_count; + int buffer_wrap[BUFSPEC_POOL_SIZE]; }; static u32 again_threshold; @@ -1688,6 +1689,7 @@ static void buf_spec_init(struct vdec_h264_hw_s *hw, bool buffer_reset_flag) for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { hw->buffer_spec[i].used = -1; hw->buffer_spec[i].canvas_pos = -1; + hw->buffer_wrap[i] = -1; } } @@ -1909,8 +1911,9 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) bs->cma_alloc_addr = (unsigned long)fb; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), cma alloc addr: 0x%x\n", - ctx->id, __func__, bs->cma_alloc_addr); + "[%d] %s(), cma alloc addr: 0x%x, out %d dec %d\n", + ctx->id, __func__, bs->cma_alloc_addr, + ctx->cap_pool.out, ctx->cap_pool.dec); if (fb->num_planes == 1) { y_addr = fb->m.mem[0].addr; @@ -2121,34 +2124,68 @@ static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) 7); } + +static int v4l_get_free_buffer_spec(struct vdec_h264_hw_s *hw) +{ + int i; + + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + if (hw->buffer_spec[i].cma_alloc_addr == 0) + return i; + } + + return -1; +} + +static int v4l_find_buffer_spec_idx(struct vdec_h264_hw_s *hw, unsigned int v4l_indx) +{ + int i; + + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + if (hw->buffer_wrap[i] == v4l_indx) + return i; + } + return -1; +} + 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; + int i, rt, idx = INVALID_IDX; ulong flags; + u32 state, index; 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); + state = (pool->seq[i] >> 16); + 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; + rt = v4l_find_buffer_spec_idx(hw, index); + if (rt >= 0) { + pic = &hw->buffer_spec[rt]; + if ((pic->vf_ref == 0) && + (pic->used == 0) && + pic->cma_alloc_addr) { + idx = rt; + } } 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; + rt = v4l_get_free_buffer_spec(hw); + if (rt >= 0) { + pic = &hw->buffer_spec[rt]; + if (!alloc_one_buf_spec_from_queue(hw, rt)) { + struct vdec_v4l2_buffer *fb; + config_decode_canvas(hw, rt); + fb = (struct vdec_v4l2_buffer *)pic->cma_alloc_addr; + hw->buffer_wrap[rt] = fb->buf_idx; + idx = rt; + } } break; default: @@ -2165,6 +2202,10 @@ static int v4l_get_free_buf_idx(struct vdec_s *vdec) if (idx < 0) { dpb_print(DECODE_ID(hw), 0, "%s fail\n", __func__); + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + dpb_print(DECODE_ID(hw), 0, "%s, %d\n", + __func__, hw->buffer_wrap[i]); + } vmh264_dump_state(vdec); } @@ -2195,6 +2236,7 @@ int get_free_buf_idx(struct vdec_s *vdec) hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; index = i; + hw->buffer_wrap[i] = index; break; } } @@ -2210,6 +2252,7 @@ int get_free_buf_idx(struct vdec_s *vdec) hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; index = i; + hw->buffer_wrap[i] = index; break; } } @@ -2476,7 +2519,7 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) } } - if (v4l->cap_pool.out < hw->dpb.mDPB.size && + if (v4l->cap_pool.dec < hw->dpb.mDPB.size && v4l2_m2m_num_dst_bufs_ready(v4l->m2m_ctx) >= run_ready_min_buf_num) return 1; @@ -2573,7 +2616,9 @@ static int check_force_interlace(struct vdec_h264_hw_s *hw, && (hw->frame_dur == 3840)) { bForceInterlace = 1; } - + if (hw->is_used_v4l && (bForceInterlace == 0)) { + bForceInterlace = (frame->frame->mb_aff_frame_flag)?1:0; + } return bForceInterlace; } @@ -6795,9 +6840,10 @@ static void dump_bufspec(struct vdec_h264_hw_s *hw, if (hw->buffer_spec[i].used == -1) continue; dpb_print(DECODE_ID(hw), 0, - "bufspec (%d): used %d adr 0x%x canvas(%d) vf_ref(%d) ", + "bufspec (%d): used %d adr 0x%x(%lx) canvas(%d) vf_ref(%d) ", i, hw->buffer_spec[i].used, hw->buffer_spec[i].buf_adr, + hw->buffer_spec[i].cma_alloc_addr, hw->buffer_spec[i].canvas_pos, hw->buffer_spec[i].vf_ref ); -- 2.20.1