summaryrefslogtreecommitdiff
authorNanxin Qin <nanxin.qin@amlogic.com>2019-12-18 14:17:33 (GMT)
committer Nanxin Qin <nanxin.qin@amlogic.com>2019-12-26 12:21:42 (GMT)
commit02515e2a0524217240c0cdede672d6b80618867e (patch)
tree6af6b75c4fd5c3c6cc12215e2a6c825f369b3650
parent59f773014c928cfd25844e00b89de15f03d82572 (diff)
downloadmedia_modules-02515e2a0524217240c0cdede672d6b80618867e.zip
media_modules-02515e2a0524217240c0cdede672d6b80618867e.tar.gz
media_modules-02515e2a0524217240c0cdede672d6b80618867e.tar.bz2
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 <nanxin.qin@amlogic.com>
Diffstat
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c226
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c7
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c4
3 files changed, 155 insertions, 82 deletions
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);