From 8e9fb3123465caf8757d5ae2a3f670901a7de5d1 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Sun, 24 Nov 2019 17:40:53 +0800 Subject: [PATCH] v4l: fixed some issues for v4l codec. [1/1] PD#SWPL-5313 Problem: Decoder V4L2 interface Phase3(AFBC&MMU Support) Solution: 1. fixed an issue of get/set parms abnormal. 2. fixed the issue of register vfm failed cause crash. 3. added post events for exception happend. 4. fixed profile_idc changes cause stuck. Verify: U212 Change-Id: I4519c91409d570e6fe8f9fedaad6c48628be85a0 Signed-off-by: Nanxin Qin --- drivers/amvdec_ports/aml_vcodec_adapt.c | 2 +- drivers/amvdec_ports/aml_vcodec_dec.c | 100 ++++++--- drivers/amvdec_ports/aml_vcodec_dec.h | 10 +- drivers/amvdec_ports/aml_vcodec_drv.h | 68 ++++-- drivers/amvdec_ports/aml_vcodec_vfm.c | 11 +- drivers/amvdec_ports/aml_vcodec_vfm.h | 1 + .../amvdec_ports/decoder/aml_h264_parser.c | 23 ++ drivers/amvdec_ports/decoder/vdec_h264_if.c | 148 ++++++++----- drivers/amvdec_ports/decoder/vdec_hevc_if.c | 143 +++++++----- drivers/amvdec_ports/decoder/vdec_mjpeg_if.c | 8 +- drivers/amvdec_ports/decoder/vdec_mpeg12_if.c | 8 +- drivers/amvdec_ports/decoder/vdec_mpeg4_if.c | 8 +- drivers/amvdec_ports/decoder/vdec_vp9_if.c | 207 ++++++++++-------- drivers/amvdec_ports/vdec_drv_if.h | 7 +- .../decoder/h264_multi/vmh264.c | 57 +++-- drivers/frame_provider/decoder/h265/vh265.c | 34 ++- .../decoder/mjpeg/vmjpeg_multi.c | 14 +- .../decoder/mpeg12/vmpeg12_multi.c | 14 +- .../decoder/mpeg4/vmpeg4_multi.c | 14 +- .../decoder/utils/vdec_v4l2_buffer_ops.c | 22 +- .../decoder/utils/vdec_v4l2_buffer_ops.h | 8 +- drivers/frame_provider/decoder/vp9/vvp9.c | 37 ++-- 22 files changed, 580 insertions(+), 364 deletions(-) diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c index a307a2b..7ac9ad5 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amvdec_ports/aml_vcodec_adapt.c @@ -695,7 +695,7 @@ int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, /* dump to file */ dump_write(buf, count); #endif - aml_v4l2_debug(4, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", + aml_v4l2_debug(3, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", ada_ctx->ctx->id, buf, count, ret, crc32_le(0, buf, count)); return ret; diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c index 7774522..f0a0d88 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amvdec_ports/aml_vcodec_dec.c @@ -203,16 +203,26 @@ static struct aml_q_data *aml_vdec_get_q_data(struct aml_vcodec_ctx *ctx, return &ctx->q_data[AML_Q_DATA_DST]; } -static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx) +void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes) { - static const struct v4l2_event ev_src_ch = { - .type = V4L2_EVENT_SOURCE_CHANGE, - .u.src_change.changes = - V4L2_EVENT_SRC_CH_RESOLUTION, - }; + struct v4l2_event event = {0}; - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); + switch (changes) { + case V4L2_EVENT_SRC_CH_RESOLUTION: + case V4L2_EVENT_SRC_CH_HDRINFO: + case V4L2_EVENT_REQUEST_RESET: + case V4L2_EVENT_REQUEST_EXIT: + event.type = V4L2_EVENT_SOURCE_CHANGE; + event.u.src_change.changes = changes; + break; + default: + pr_err("unsupport dispatch event %x\n", changes); + return; + } + + v4l2_event_queue_fh(&ctx->fh, &event); + aml_v4l2_debug(3, "[%d] %s() changes: %x", + ctx->id, __func__, changes); } static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx) @@ -484,6 +494,10 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f if (dstbuf->lastframe && ctx->q_data[AML_Q_DATA_SRC].resolution_changed) { + + /* make the run to stanby until new buffs to enque. */ + ctx->v4l_codec_dpb_ready = false; + /* * After all buffers containing decoded frames from * before the resolution change point ready to be @@ -492,7 +506,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f * type V4L2_EVENT_SRC_CH_RESOLUTION, also the upper * layer will get new information from cts->picinfo. */ - aml_vdec_queue_res_chg_event(ctx); + aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION); } ctx->decoded_frame_cnt++; @@ -518,6 +532,23 @@ static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffe return ret; } +static void aml_check_dpb_ready(struct aml_vcodec_ctx *ctx) +{ + if (!ctx->v4l_codec_dpb_ready) { + int buf_ready_num; + + /* is there enough dst bufs for decoding? */ + buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); + if ((ctx->dpb_size) && + ((buf_ready_num + ctx->buf_used_count) >= ctx->dpb_size)) + ctx->v4l_codec_dpb_ready = true; + aml_v4l2_debug(2, "[%d] %s() dpb: %d, ready: %d, used: %d, dpb is ready: %s", + ctx->id, __func__, ctx->dpb_size, + buf_ready_num, ctx->buf_used_count, + ctx->v4l_codec_dpb_ready ? "yes" : "no"); + } +} + static int is_vdec_ready(struct aml_vcodec_ctx *ctx) { struct aml_vcodec_dev *dev = ctx->dev; @@ -552,17 +583,8 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx) } mutex_unlock(&ctx->state_lock); - if (!ctx->v4l_codec_dpb_ready) { - int buf_ready_num; - - /* is there enough dst bufs for decoding? */ - buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); - if ((buf_ready_num + ctx->buf_used_count) >= ctx->dpb_size) - ctx->v4l_codec_dpb_ready = true; - aml_v4l2_debug(2, "[%d] %s() dpb: %d, ready: %d, used: %d", - ctx->id, __func__, ctx->dpb_size, - buf_ready_num, ctx->buf_used_count); - } + /* check dpb ready */ + //aml_check_dpb_ready(ctx); return 1; } @@ -653,7 +675,7 @@ static void aml_vdec_worker(struct work_struct *work) mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_ACTIVE) { ctx->state = AML_STATE_FLUSHING;// prepare flushing - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-END)", + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-LASTFRM)", ctx->id, __func__); } mutex_unlock(&ctx->state_lock); @@ -934,9 +956,16 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, V4L2_BUF_TYPE_VIDEO_CAPTURE); switch (cmd->cmd) { case V4L2_DEC_CMD_STOP: - - if (ctx->state != AML_STATE_ACTIVE) - return 0; + if (ctx->state != AML_STATE_ACTIVE) { + if (ctx->state >= AML_STATE_IDLE && + ctx->state <= AML_STATE_PROBE) { + ctx->state = AML_STATE_ABORT; + aml_vdec_dispatch_event(ctx, V4L2_EVENT_REQUEST_EXIT); + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + return -1; + } + } src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -1684,6 +1713,9 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) buf->queued_in_vb2 = true; buf->queued_in_v4l2 = true; buf->ready_to_display = false; + + /* check dpb ready */ + aml_check_dpb_ready(ctx); } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; @@ -1737,7 +1769,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) ctx->dpb_size = dpb; ctx->last_decoded_picinfo = ctx->picinfo; - aml_vdec_queue_res_chg_event(ctx); + aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION); mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_INIT) { @@ -2071,10 +2103,22 @@ static int vidioc_vdec_s_parm(struct file *file, void *fh, struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + struct aml_dec_params *in = + (struct aml_dec_params *) a->parm.raw_data; + struct aml_dec_params *dec = &ctx->config.parm.dec; + ctx->config.type = V4L2_CONFIG_PARM_DECODE; - ctx->config.length = sizeof(a->parm.raw_data); - memcpy(ctx->config.parm.data, a->parm.raw_data, - sizeof(a->parm.raw_data)); + + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + dec->cfg = in->cfg; + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + dec->ps = in->ps; + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + dec->hdr = in->hdr; + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + dec->cnt = in->cnt; + + dec->parms_status |= in->parms_status; } return 0; diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h index c465857..7ca3337 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.h +++ b/drivers/amvdec_ports/aml_vcodec_dec.h @@ -39,15 +39,6 @@ #define AML_V4L2_SET_DECMODE (V4L2_CID_USER_AMLOGIC_BASE + 0) -/* codec types of get/set parms. */ -#define V4L2_CONFIG_PARM_ENCODE (0) -#define V4L2_CONFIG_PARM_DECODE (1) - -/* types of decode parms. */ -#define V4L2_CONFIG_PARM_DECODE_COMMON (1 << 0) -#define V4L2_CONFIG_PARM_DECODE_PICINFO (1 << 1) -#define V4L2_CONFIG_PARM_DECODE_HDRINFO (1 << 2) - /* for video composer metafd private_data struct */ struct file_privdata { struct vframe_s vf; @@ -139,5 +130,6 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, void aml_thread_stop(struct aml_vcodec_ctx *ctx); void wait_vcodec_ending(struct aml_vcodec_ctx *ctx); void vdec_frame_buffer_release(void *data); +void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes); #endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h index 21a1ab2..fb1930e 100644 --- a/drivers/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amvdec_ports/aml_vcodec_drv.h @@ -38,6 +38,26 @@ #define AML_V4L2_BENCHMARK 0 #define WAIT_INTR_TIMEOUT_MS 1000 +/* codec types of get/set parms. */ +#define V4L2_CONFIG_PARM_ENCODE (0) +#define V4L2_CONFIG_PARM_DECODE (1) + +/* types of decode parms. */ +#define V4L2_CONFIG_PARM_DECODE_CFGINFO (1 << 0) +#define V4L2_CONFIG_PARM_DECODE_PSINFO (1 << 1) +#define V4L2_CONFIG_PARM_DECODE_HDRINFO (1 << 2) +#define V4L2_CONFIG_PARM_DECODE_CNTINFO (1 << 3) + +/* amlogic event define. */ +/* #define V4L2_EVENT_SRC_CH_RESOLUTION (1 << 0) */ +#define V4L2_EVENT_SRC_CH_HDRINFO (1 << 1) +#define V4L2_EVENT_SRC_CH_PSINFO (1 << 2) +#define V4L2_EVENT_SRC_CH_CNTINFO (1 << 3) + +/* exception handing */ +#define V4L2_EVENT_REQUEST_RESET (1 << 8) +#define V4L2_EVENT_REQUEST_EXIT (1 << 9) + /** * enum aml_hw_reg_idx - AML hw register base index */ @@ -234,14 +254,15 @@ struct vdec_pic_info { unsigned int c_bs_sz; unsigned int y_len_sz; unsigned int c_len_sz; + int profile_idc; }; -struct aml_vdec_pic_infos { - u32 visible_width; - u32 visible_height; - u32 coded_width; - u32 coded_height; - u32 dpb_size; +struct aml_vdec_cfg_infos { + u32 double_write_mode; + u32 init_width; + u32 init_height; + u32 ref_buf_margin; + u32 block_mode; }; struct aml_vdec_hdr_infos { @@ -265,16 +286,33 @@ struct aml_vdec_hdr_infos { struct vframe_master_display_colour_s color_parms; }; +struct aml_vdec_ps_infos { + u32 visible_width; + u32 visible_height; + u32 coded_width; + u32 coded_height; + u32 profile; + u32 mb_width; + u32 mb_height; + u32 dpb_size; + u32 ref_frames; + u32 reorder_frames; +}; + +struct aml_vdec_cnt_infos { + u32 bit_rate; + u32 frame_count; + u32 error_frame_count; + u32 drop_frame_count; + u32 total_data; +}; + struct aml_dec_params { - u32 dec_parms_status; - u32 es_need_header; - u32 double_write_mode; - u32 buffer_mode; - u32 buffer_width; - u32 buffer_height; - u32 buffer_margin; - struct aml_vdec_pic_infos pic; - struct aml_vdec_hdr_infos hdr; + u32 parms_status; + struct aml_vdec_cfg_infos cfg; + struct aml_vdec_ps_infos ps; + struct aml_vdec_hdr_infos hdr; + struct aml_vdec_cnt_infos cnt; }; struct v4l2_config_parm { diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.c b/drivers/amvdec_ports/aml_vcodec_vfm.c index e7b85fb..f5fdc7b 100644 --- a/drivers/amvdec_ports/aml_vcodec_vfm.c +++ b/drivers/amvdec_ports/aml_vcodec_vfm.c @@ -214,6 +214,8 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm) int vcodec_vfm_init(struct vcodec_vfm_s *vfm) { + int ret; + snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d", RECEIVER_NAME, vfm->ctx->id); snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d", @@ -222,13 +224,16 @@ int vcodec_vfm_init(struct vcodec_vfm_s *vfm) vfm->ada_ctx->recv_name = vfm->recv_name; vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm); - vf_reg_receiver(&vfm->vf_recv); + ret = vf_reg_receiver(&vfm->vf_recv); - return 0; + vfm->vfm_initialized = ret ? false : true; + + return ret; } void vcodec_vfm_release(struct vcodec_vfm_s *vfm) { - vf_unreg_receiver(&vfm->vf_recv); + if (vfm->vfm_initialized) + vf_unreg_receiver(&vfm->vf_recv); } diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.h b/drivers/amvdec_ports/aml_vcodec_vfm.h index 9aaf266..141e9a7 100644 --- a/drivers/amvdec_ports/aml_vcodec_vfm.h +++ b/drivers/amvdec_ports/aml_vcodec_vfm.h @@ -41,6 +41,7 @@ struct vcodec_vfm_s { char prov_name[VF_NAME_SIZE]; struct vframe_provider_s vf_prov; struct vframe_receiver_s vf_recv; + bool vfm_initialized; }; int vcodec_vfm_init(struct vcodec_vfm_s *vfm); diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.c b/drivers/amvdec_ports/decoder/aml_h264_parser.c index d5d1d91..8963afd 100644 --- a/drivers/amvdec_ports/decoder/aml_h264_parser.c +++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c @@ -495,6 +495,7 @@ static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *s goto out; } +#if 0 /* if the maximum delay is not stored in the SPS, derive it based on the level */ if (!sps->bitstream_restriction_flag && sps->ref_frame_count) { sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; @@ -507,6 +508,28 @@ static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *s } } } +#endif + + sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; + for (i = 0; i < ARRAY_SIZE(level_max_dpb_mbs); i++) { + if (level_max_dpb_mbs[i][0] == sps->level_idc) { + sps->num_reorder_frames = + MIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height), + sps->num_reorder_frames); + sps->num_reorder_frames += 1; + if (sps->max_dec_frame_buffering > sps->num_reorder_frames) + sps->num_reorder_frames = sps->max_dec_frame_buffering; + break; + } + } + + if ((sps->bitstream_restriction_flag) && + (sps->max_dec_frame_buffering < + sps->num_reorder_frames)) { + sps->num_reorder_frames = sps->max_dec_frame_buffering; + pr_info("set reorder_pic_num to %d\n", + sps->num_reorder_frames); + } if (!sps->sar.den) sps->sar.den = 1; diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c index 7bf4d5e..ea1d0f8 100644 --- a/drivers/amvdec_ports/decoder/vdec_h264_if.c +++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c @@ -261,29 +261,24 @@ static void vdec_parser_parms(struct vdec_h264_inst *inst) { struct aml_vcodec_ctx *ctx = inst->ctx; - if (!ctx->config.length) { - ctx->config.type = V4L2_CONFIG_PARM_DECODE; - ctx->config.parm.dec.double_write_mode = 16; - inst->parms = ctx->config.parm.dec; - - ctx->config.length = - vdec_config_default_parms(ctx->config.buf); - } else { + if (ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_CFGINFO) { u8 *pbuf = ctx->config.buf; - inst->parms = ctx->config.parm.dec; pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); pbuf += sprintf(pbuf, "mh264_double_write_mode:%d;", - inst->parms.double_write_mode); + ctx->config.parm.dec.cfg.double_write_mode); pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;", - inst->parms.buffer_margin); + ctx->config.parm.dec.cfg.ref_buf_margin); ctx->config.length = pbuf - ctx->config.buf; + } else { + ctx->config.parm.dec.cfg.double_write_mode = 16; + ctx->config.length = vdec_config_default_parms(ctx->config.buf); } - inst->vdec.config = ctx->config; - - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_COMMON; + inst->vdec.config = ctx->config; + inst->parms.cfg = ctx->config.parm.dec.cfg; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO; } static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) @@ -310,26 +305,30 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) /* init vfm */ inst->vfm.ctx = ctx; inst->vfm.ada_ctx = &inst->vdec; - vcodec_vfm_init(&inst->vfm); + ret = vcodec_vfm_init(&inst->vfm); + if (ret) { + pr_err("%s, init vfm failed.\n", __func__); + goto err; + } ret = video_decoder_init(&inst->vdec); if (ret) { aml_vcodec_err(inst, "vdec_h264 init err=%d", ret); - goto error_free_inst; + goto err; } /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_inst; + goto err; } /* alloc the header buffer to be used cache sps or spp etc.*/ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_vsi; + goto err; } init_completion(&inst->comp); @@ -342,11 +341,15 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) //dump_init(); return 0; - -error_free_vsi: - kfree(inst->vsi); -error_free_inst: - kfree(inst); +err: + if (inst) + vcodec_vfm_release(&inst->vfm); + if (inst && inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + if (inst && inst->vsi) + kfree(inst->vsi); + if (inst) + kfree(inst); *h_vdec = 0; return ret; @@ -446,8 +449,8 @@ static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_h264_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; - int dw = inst->parms.double_write_mode; - int margin = inst->parms.buffer_margin; + int dw = inst->parms.cfg.double_write_mode; + int margin = inst->parms.cfg.ref_buf_margin; u32 mb_w, mb_h, width, height; mb_w = sps->mb_width; @@ -474,20 +477,29 @@ static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps pic->coded_height = ALIGN(mb_h, 4) << 4; pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; + pic->profile_idc = sps->profile_idc; /* calc DPB size */ - dec->dpb_sz = sps->num_reorder_frames + 1 + margin; + dec->dpb_sz = sps->num_reorder_frames + margin; + + inst->parms.ps.visible_width = pic->visible_width; + inst->parms.ps.visible_height = pic->visible_height; + inst->parms.ps.coded_width = pic->coded_width; + inst->parms.ps.coded_height = pic->coded_height; + inst->parms.ps.profile = sps->profile_idc; + inst->parms.ps.mb_width = sps->mb_width; + inst->parms.ps.mb_height = sps->mb_height; + inst->parms.ps.ref_frames = sps->ref_frame_count; + inst->parms.ps.reorder_frames = sps->num_reorder_frames; + inst->parms.ps.dpb_size = dec->dpb_sz; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO; vdec_config_dw_mode(pic, dw); - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_PICINFO; - aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n", - inst->ctx->id,inst->parms.double_write_mode, - pic->coded_width, pic->coded_height, + inst->ctx->id, dw, pic->coded_width, pic->coded_height, pic->visible_width, pic->visible_height, - dec->dpb_sz - margin + 1, margin); + dec->dpb_sz - margin, margin); } static bool check_frame_combine(u8 *buf, u32 size, int *pos) @@ -778,10 +790,13 @@ static bool monitor_res_change(struct vdec_h264_inst *inst, u8 *buf, u32 size) if (type == NAL_H264_SPS) { ret = stream_parse(inst, p, len); - if (!ret && (inst->vsi->cur_pic.coded_width != + if (!ret && ((inst->vsi->cur_pic.coded_width != inst->vsi->pic.coded_width || inst->vsi->cur_pic.coded_height != - inst->vsi->pic.coded_height)) { + inst->vsi->pic.coded_height) || + (inst->vsi->pic.profile_idc != + inst->vsi->cur_pic.profile_idc))) { + pr_info("res change\n"); inst->vsi->cur_pic = inst->vsi->pic; return true; } @@ -834,9 +849,18 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, static void get_param_config_info(struct vdec_h264_inst *inst, struct aml_dec_params *parms) { - *parms = inst->parms; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + parms->cfg = inst->parms.cfg; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + parms->ps = inst->parms.ps; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + parms->hdr = inst->parms.hdr; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + parms->cnt = inst->parms.cnt; + + parms->parms_status |= inst->parms.parms_status; - aml_vcodec_debug(inst, "parms status: %u", parms->dec_parms_status); + aml_vcodec_debug(inst, "parms status: %u", parms->parms_status); } static int vdec_h264_get_param(unsigned long h_vdec, @@ -887,16 +911,16 @@ static void set_param_write_sync(struct vdec_h264_inst *inst) complete(&inst->comp); } -static void set_param_pic_info(struct vdec_h264_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_h264_inst *inst, + struct aml_vdec_ps_infos *ps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_h264_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; /* fill visible area size that be used for EGL. */ - pic->visible_width = info->visible_width; - pic->visible_height = info->visible_height; + pic->visible_width = ps->visible_width; + pic->visible_height = ps->visible_height; /* calc visible ares. */ rect->left = 0; @@ -905,33 +929,45 @@ static void set_param_pic_info(struct vdec_h264_inst *inst, rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = info->coded_width; - pic->coded_height = info->coded_height; + pic->coded_width = ps->coded_width; + pic->coded_height = ps->coded_height; pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; - dec->dpb_sz = info->dpb_size; + dec->dpb_sz = ps->dpb_size; - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_PICINFO; + inst->parms.ps = *ps; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_PSINFO; /*wake up*/ complete(&inst->comp); pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", - info->visible_width, info->visible_height, - info->coded_width, info->coded_height, - info->dpb_size); + ps->visible_width, ps->visible_height, + ps->coded_width, ps->coded_height, + dec->dpb_sz); } static void set_param_hdr_info(struct vdec_h264_inst *inst, struct aml_vdec_hdr_infos *hdr) { inst->parms.hdr = *hdr; - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_HDRINFO; + if (!(inst->parms.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO)) { + inst->parms.hdr = *hdr; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_HDRINFO; + aml_vdec_dispatch_event(inst->ctx, + V4L2_EVENT_SRC_CH_HDRINFO); + pr_info("H264 set HDR infos\n"); + } +} - //pr_info("H264 set HDR infos\n"); +static void set_param_post_event(struct vdec_h264_inst *inst, u32 *event) +{ + aml_vdec_dispatch_event(inst->ctx, *event); + pr_info("H264 post event: %d\n", *event); } static int vdec_h264_set_param(unsigned long h_vdec, @@ -950,13 +986,17 @@ static int vdec_h264_set_param(unsigned long h_vdec, set_param_write_sync(inst); break; - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; case SET_PARAM_HDR_INFO: set_param_hdr_info(inst, in); break; + + case SET_PARAM_POST_EVENT: + set_param_post_event(inst, in); + break; default: aml_vcodec_err(inst, "invalid set parameter type=%d", type); ret = -EINVAL; diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c index fb3fce7..1b06d77 100644 --- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c +++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c @@ -164,35 +164,27 @@ static void vdec_parser_parms(struct vdec_hevc_inst *inst) { struct aml_vcodec_ctx *ctx = inst->ctx; - if (!ctx->config.length) { - ctx->config.type = V4L2_CONFIG_PARM_DECODE; - ctx->config.parm.dec.double_write_mode = 16; - inst->parms = ctx->config.parm.dec; - - ctx->config.length = - vdec_config_default_parms(ctx->config.buf); - } else { + if (ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_CFGINFO) { u8 *pbuf = ctx->config.buf; - inst->parms = ctx->config.parm.dec; pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;", - inst->parms.buffer_margin); + ctx->config.parm.dec.cfg.ref_buf_margin); pbuf += sprintf(pbuf, "hevc_double_write_mode:%d;", - inst->parms.double_write_mode); - pbuf += sprintf(pbuf, "hevc_buf_width:%d;", - inst->parms.buffer_width); - pbuf += sprintf(pbuf, "hevc_buf_height:%d;", - inst->parms.buffer_height); - pbuf += sprintf(pbuf, "save_buffer_mode:%d;", - inst->parms.buffer_mode); + ctx->config.parm.dec.cfg.double_write_mode); + pbuf += sprintf(pbuf, "hevc_buf_width:4096;"); + pbuf += sprintf(pbuf, "hevc_buf_height:2304;"); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); ctx->config.length = pbuf - ctx->config.buf; + } else { + ctx->config.parm.dec.cfg.double_write_mode = 16; + ctx->config.length = vdec_config_default_parms(ctx->config.buf); } - inst->vdec.config = ctx->config; - - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_COMMON; + inst->vdec.config = ctx->config; + inst->parms.cfg = ctx->config.parm.dec.cfg; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO; } static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) @@ -222,26 +214,30 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) /* init vfm */ inst->vfm.ctx = ctx; inst->vfm.ada_ctx = &inst->vdec; - vcodec_vfm_init(&inst->vfm); + ret = vcodec_vfm_init(&inst->vfm); + if (ret) { + pr_err("%s, init vfm failed.\n", __func__); + goto err; + } ret = video_decoder_init(&inst->vdec); if (ret) { aml_vcodec_err(inst, "vdec_hevc init err=%d", ret); - goto error_free_inst; + goto err; } /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_hevc_vsi), GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_inst; + goto err; } /* alloc the header buffer to be used cache sps or spp etc.*/ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_vsi; + goto err; } init_completion(&inst->comp); @@ -254,11 +250,15 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) //dump_init(); return 0; - -error_free_vsi: - kfree(inst->vsi); -error_free_inst: - kfree(inst); +err: + if (inst) + vcodec_vfm_release(&inst->vfm); + if (inst && inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + if (inst && inst->vsi) + kfree(inst->vsi); + if (inst) + kfree(inst); *h_vdec = 0; return ret; @@ -297,9 +297,9 @@ static int refer_buffer_num(struct h265_SPS_t *sps) static int vdec_get_dw_mode(struct vdec_hevc_inst *inst, int dw_mode) { - u32 valid_dw_mode = inst->parms.double_write_mode; - int w = inst->parms.buffer_width; - int h = inst->parms.buffer_height; + u32 valid_dw_mode = inst->parms.cfg.double_write_mode; + int w = inst->parms.cfg.init_width; + int h = inst->parms.cfg.init_height; u32 dw = 0x1; /*1:1*/ switch (valid_dw_mode) { @@ -355,8 +355,8 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_hevc_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; - int dw = inst->parms.double_write_mode; - int margin = inst->parms.buffer_margin; + int dw = inst->parms.cfg.double_write_mode; + int margin = inst->parms.cfg.ref_buf_margin; /* fill visible area size that be used for EGL. */ pic->visible_width = sps->width - (sps->output_window.left_offset + @@ -380,14 +380,17 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - dec->dpb_sz = refer_buffer_num(sps) + margin; + dec->dpb_sz = refer_buffer_num(sps) + margin; - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_PICINFO; + inst->parms.ps.visible_width = pic->visible_width; + inst->parms.ps.visible_height = pic->visible_height; + inst->parms.ps.coded_width = pic->coded_width; + inst->parms.ps.coded_height = pic->coded_height; + inst->parms.ps.dpb_size = dec->dpb_sz; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO; pr_info("[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n", - inst->ctx->id, inst->parms.double_write_mode, - pic->coded_width, pic->coded_height, + inst->ctx->id, dw, pic->coded_width, pic->coded_height, pic->visible_width, pic->visible_height, dec->dpb_sz - margin, margin); } @@ -615,9 +618,18 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, static void get_param_config_info(struct vdec_hevc_inst *inst, struct aml_dec_params *parms) { - *parms = inst->parms; - - aml_vcodec_debug(inst, "parms status: %u", parms->dec_parms_status); + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + parms->cfg = inst->parms.cfg; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + parms->ps = inst->parms.ps; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + parms->hdr = inst->parms.hdr; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + parms->cnt = inst->parms.cnt; + + parms->parms_status |= inst->parms.parms_status; + + aml_vcodec_debug(inst, "parms status: %u", parms->parms_status); } static int vdec_hevc_get_param(unsigned long h_vdec, @@ -668,16 +680,16 @@ static void set_param_write_sync(struct vdec_hevc_inst *inst) complete(&inst->comp); } -static void set_param_pic_info(struct vdec_hevc_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_hevc_inst *inst, + struct aml_vdec_ps_infos *ps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_hevc_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; /* fill visible area size that be used for EGL. */ - pic->visible_width = info->visible_width; - pic->visible_height = info->visible_height; + pic->visible_width = ps->visible_width; + pic->visible_height = ps->visible_height; /* calc visible ares. */ rect->left = 0; @@ -686,15 +698,16 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst, rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = ALIGN(info->coded_width, 64); - pic->coded_height = ALIGN(info->coded_height, 64); + pic->coded_width = ALIGN(ps->coded_width, 64); + pic->coded_height = ALIGN(ps->coded_height, 64); pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; - dec->dpb_sz = info->dpb_size; + dec->dpb_sz = ps->dpb_size; - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_PICINFO; + inst->parms.ps = *ps; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_PSINFO; /*wake up*/ complete(&inst->comp); @@ -708,11 +721,21 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst, static void set_param_hdr_info(struct vdec_hevc_inst *inst, struct aml_vdec_hdr_infos *hdr) { - inst->parms.hdr = *hdr; - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_HDRINFO; + if (!(inst->parms.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO)) { + inst->parms.hdr = *hdr; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_HDRINFO; + aml_vdec_dispatch_event(inst->ctx, + V4L2_EVENT_SRC_CH_HDRINFO); + pr_info("H265 set HDR infos\n"); + } +} - //pr_info("H265 set HDR infos\n"); +static void set_param_post_event(struct vdec_hevc_inst *inst, u32 *event) +{ + aml_vdec_dispatch_event(inst->ctx, *event); + pr_info("H265 post event: %d\n", *event); } static int vdec_hevc_set_param(unsigned long h_vdec, @@ -731,13 +754,17 @@ static int vdec_hevc_set_param(unsigned long h_vdec, set_param_write_sync(inst); break; - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; case SET_PARAM_HDR_INFO: set_param_hdr_info(inst, in); break; + + case SET_PARAM_POST_EVENT: + set_param_post_event(inst, in); + break; default: aml_vcodec_err(inst, "invalid set parameter type=%d", type); ret = -EINVAL; diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c index 09bfd5e..0db4eca 100644 --- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c @@ -451,8 +451,8 @@ static int vdec_mjpeg_get_param(unsigned long h_vdec, return ret; } -static void set_param_pic_info(struct vdec_mjpeg_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_mjpeg_inst *inst, + struct aml_vdec_ps_infos *ps) { pr_info("---%s, %d\n", __func__, __LINE__); } @@ -469,8 +469,8 @@ static int vdec_mjpeg_set_param(unsigned long h_vdec, } switch (type) { - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; default: diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c index cf69aa9..5d5ca07 100644 --- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c @@ -443,8 +443,8 @@ static int vdec_mpeg12_get_param(unsigned long h_vdec, return ret; } -static void set_param_pic_info(struct vdec_mpeg12_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_mpeg12_inst *inst, + struct aml_vdec_ps_infos *ps) { pr_info("---%s, %d\n", __func__, __LINE__); } @@ -461,8 +461,8 @@ static int vdec_mpeg12_set_param(unsigned long h_vdec, } switch (type) { - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; default: diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c index a78c904..ab428af 100644 --- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c @@ -452,8 +452,8 @@ static int vdec_mpeg4_get_param(unsigned long h_vdec, return ret; } -static void set_param_pic_info(struct vdec_mpeg4_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_mpeg4_inst *inst, + struct aml_vdec_ps_infos *ps) { pr_info("---%s, %d\n", __func__, __LINE__); } @@ -470,8 +470,8 @@ static int vdec_mpeg4_set_param(unsigned long h_vdec, } switch (type) { - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; default: diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c index 6aa8bd8..54a6e17 100644 --- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c +++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c @@ -178,66 +178,64 @@ static void vdec_parser_parms(struct vdec_vp9_inst *inst) { struct aml_vcodec_ctx *ctx = inst->ctx; - if (!ctx->config.length) { - ctx->config.type = V4L2_CONFIG_PARM_DECODE; - ctx->config.parm.dec.double_write_mode = 16; - inst->parms = ctx->config.parm.dec; - - ctx->config.length = - vdec_config_default_parms(ctx->config.buf); - } else { + if (ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_CFGINFO) { u8 *pbuf = ctx->config.buf; - inst->parms = ctx->config.parm.dec; pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;", - inst->parms.buffer_margin); + ctx->config.parm.dec.cfg.ref_buf_margin); pbuf += sprintf(pbuf, "vp9_double_write_mode:%d;", - inst->parms.double_write_mode); + ctx->config.parm.dec.cfg.double_write_mode); pbuf += sprintf(pbuf, "vp9_buf_width:%d;", - inst->parms.buffer_width); + ctx->config.parm.dec.cfg.init_width); pbuf += sprintf(pbuf, "vp9_buf_height:%d;", - inst->parms.buffer_height); - pbuf += sprintf(pbuf, "save_buffer_mode:%d;", - inst->parms.buffer_mode); + ctx->config.parm.dec.cfg.init_height); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); pbuf += sprintf(pbuf, "no_head:0;"); - - if ((ctx->config.parm.dec.dec_parms_status & - V4L2_CONFIG_PARM_DECODE_HDRINFO) && - inst->parms.hdr.color_parms.present_flag) { - pbuf += sprintf(pbuf, "mG.x:%d;", - inst->parms.hdr.color_parms.primaries[0][0]); - pbuf += sprintf(pbuf, "mG.y:%d;", - inst->parms.hdr.color_parms.primaries[0][1]); - pbuf += sprintf(pbuf, "mB.x:%d;", - inst->parms.hdr.color_parms.primaries[1][0]); - pbuf += sprintf(pbuf, "mB.y:%d;", - inst->parms.hdr.color_parms.primaries[1][1]); - pbuf += sprintf(pbuf, "mR.x:%d;", - inst->parms.hdr.color_parms.primaries[2][0]); - pbuf += sprintf(pbuf, "mR.y:%d;", - inst->parms.hdr.color_parms.primaries[2][1]); - pbuf += sprintf(pbuf, "mW.x:%d;", - inst->parms.hdr.color_parms.white_point[0]); - pbuf += sprintf(pbuf, "mW.y:%d;", - inst->parms.hdr.color_parms.white_point[1]); - pbuf += sprintf(pbuf, "mMaxDL:%d;", - inst->parms.hdr.color_parms.luminance[0] / 1000); - pbuf += sprintf(pbuf, "mMinDL:%d;", - inst->parms.hdr.color_parms.luminance[1]); - pbuf += sprintf(pbuf, "mMaxCLL:%d;", - inst->parms.hdr.color_parms.content_light_level.max_content); - pbuf += sprintf(pbuf, "mMaxFALL:%d;", - inst->parms.hdr.color_parms.content_light_level.max_pic_average); - } - ctx->config.length = pbuf - ctx->config.buf; + } else { + ctx->config.parm.dec.cfg.double_write_mode = 16; + ctx->config.length = vdec_config_default_parms(ctx->config.buf); } - inst->vdec.config = ctx->config; + if ((ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO) && + inst->parms.hdr.color_parms.present_flag) { + u8 *pbuf = ctx->config.buf + ctx->config.length; + + pbuf += sprintf(pbuf, "mG.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[0][0]); + pbuf += sprintf(pbuf, "mG.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[0][1]); + pbuf += sprintf(pbuf, "mB.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[1][0]); + pbuf += sprintf(pbuf, "mB.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[1][1]); + pbuf += sprintf(pbuf, "mR.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[2][0]); + pbuf += sprintf(pbuf, "mR.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[2][1]); + pbuf += sprintf(pbuf, "mW.x:%d;", + ctx->config.parm.dec.hdr.color_parms.white_point[0]); + pbuf += sprintf(pbuf, "mW.y:%d;", + ctx->config.parm.dec.hdr.color_parms.white_point[1]); + pbuf += sprintf(pbuf, "mMaxDL:%d;", + ctx->config.parm.dec.hdr.color_parms.luminance[0] / 1000); + pbuf += sprintf(pbuf, "mMinDL:%d;", + ctx->config.parm.dec.hdr.color_parms.luminance[1]); + pbuf += sprintf(pbuf, "mMaxCLL:%d;", + ctx->config.parm.dec.hdr.color_parms.content_light_level.max_content); + pbuf += sprintf(pbuf, "mMaxFALL:%d;", + ctx->config.parm.dec.hdr.color_parms.content_light_level.max_pic_average); + ctx->config.length = pbuf - ctx->config.buf; + inst->parms.hdr = ctx->config.parm.dec.hdr; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_HDRINFO; + } - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_COMMON; + inst->vdec.config = ctx->config; + inst->parms.cfg = ctx->config.parm.dec.cfg; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO; } static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) @@ -267,20 +265,24 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) /* init vfm */ inst->vfm.ctx = ctx; inst->vfm.ada_ctx = &inst->vdec; - vcodec_vfm_init(&inst->vfm); + ret = vcodec_vfm_init(&inst->vfm); + if (ret) { + pr_err("%s, init vfm failed.\n", __func__); + goto err; + } /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_vp9_vsi), GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_inst; + goto err; } /* alloc the header buffer to be used cache sps or spp etc.*/ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_vsi; + goto err; } init_completion(&inst->comp); @@ -294,17 +296,21 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) ret = video_decoder_init(&inst->vdec); if (ret) { aml_vcodec_err(inst, "vdec_vp9 init err=%d", ret); - goto error_free_inst; + goto err; } //dump_init(); return 0; - -error_free_vsi: - kfree(inst->vsi); -error_free_inst: - kfree(inst); +err: + if (inst) + vcodec_vfm_release(&inst->vfm); + if (inst && inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + if (inst && inst->vsi) + kfree(inst->vsi); + if (inst) + kfree(inst); *h_vdec = 0; return ret; @@ -320,9 +326,9 @@ static int refer_buffer_num(int level_idc, int poc_cnt, static int vdec_get_dw_mode(struct vdec_vp9_inst *inst, int dw_mode) { - u32 valid_dw_mode = inst->parms.double_write_mode; - int w = inst->parms.buffer_width; - int h = inst->parms.buffer_height; + u32 valid_dw_mode = inst->parms.cfg.double_write_mode; + int w = inst->parms.cfg.init_width; + int h = inst->parms.cfg.init_height; u32 dw = 0x1; /*1:1*/ switch (valid_dw_mode) { @@ -379,8 +385,8 @@ static void fill_vdec_params(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_vp9_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; - int dw = inst->parms.double_write_mode; - int margin = inst->parms.buffer_margin; + int dw = inst->parms.cfg.double_write_mode; + int margin = inst->parms.cfg.ref_buf_margin; /* fill visible area size that be used for EGL. */ pic->visible_width = vdec_pic_scale(inst, vp9_ctx->render_width, dw); @@ -402,12 +408,15 @@ static void fill_vdec_params(struct vdec_vp9_inst *inst, /* calc DPB size */ dec->dpb_sz = 5 + margin;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_PICINFO; + inst->parms.ps.visible_width = pic->visible_width; + inst->parms.ps.visible_height = pic->visible_height; + inst->parms.ps.coded_width = pic->coded_width; + inst->parms.ps.coded_height = pic->coded_height; + inst->parms.ps.dpb_size = dec->dpb_sz; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO; aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n", - inst->ctx->id, inst->parms.double_write_mode, - pic->coded_width, pic->coded_height, + inst->ctx->id, dw, pic->coded_width, pic->coded_height, pic->visible_width, pic->visible_height, dec->dpb_sz - margin, margin); } @@ -719,9 +728,18 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, static void get_param_config_info(struct vdec_vp9_inst *inst, struct aml_dec_params *parms) { - *parms = inst->parms; - - aml_vcodec_debug(inst, "parms status: %u", parms->dec_parms_status); + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + parms->cfg = inst->parms.cfg; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + parms->ps = inst->parms.ps; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + parms->hdr = inst->parms.hdr; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + parms->cnt = inst->parms.cnt; + + parms->parms_status |= inst->parms.parms_status; + + aml_vcodec_debug(inst, "parms status: %u", parms->parms_status); } static int vdec_vp9_get_param(unsigned long h_vdec, @@ -772,16 +790,16 @@ static void set_param_write_sync(struct vdec_vp9_inst *inst) complete(&inst->comp); } -static void set_param_pic_info(struct vdec_vp9_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_vp9_inst *inst, + struct aml_vdec_ps_infos *ps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_vp9_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; /* fill visible area size that be used for EGL. */ - pic->visible_width = info->visible_width; - pic->visible_height = info->visible_height; + pic->visible_width = ps->visible_width; + pic->visible_height = ps->visible_height; /* calc visible ares. */ rect->left = 0; @@ -790,35 +808,46 @@ static void set_param_pic_info(struct vdec_vp9_inst *inst, rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = info->coded_width; - pic->coded_height = info->coded_height; + pic->coded_width = ps->coded_width; + pic->coded_height = ps->coded_height; pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - dec->dpb_sz = 5; + dec->dpb_sz = 5; - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_PICINFO; + inst->parms.ps = *ps; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_PSINFO; /*wake up*/ complete(&inst->comp); pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", - info->visible_width, info->visible_height, - info->coded_width, info->coded_height, - info->dpb_size); + ps->visible_width, ps->visible_height, + ps->coded_width, ps->coded_height, + ps->dpb_size); } static void set_param_hdr_info(struct vdec_vp9_inst *inst, struct aml_vdec_hdr_infos *hdr) { - inst->parms.hdr = *hdr; - inst->parms.dec_parms_status |= - V4L2_CONFIG_PARM_DECODE_HDRINFO; + if ((inst->parms.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO)) { + inst->parms.hdr = *hdr; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_HDRINFO; + aml_vdec_dispatch_event(inst->ctx, + V4L2_EVENT_SRC_CH_HDRINFO); + pr_info("VP9 set HDR infos\n"); + } +} - //pr_info("VP9 set HDR infos\n"); +static void set_param_post_event(struct vdec_vp9_inst *inst, u32 *event) +{ + aml_vdec_dispatch_event(inst->ctx, *event); + pr_info("VP9 post event: %d\n", *event); } static int vdec_vp9_set_param(unsigned long h_vdec, @@ -837,13 +866,17 @@ static int vdec_vp9_set_param(unsigned long h_vdec, set_param_write_sync(inst); break; - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; case SET_PARAM_HDR_INFO: set_param_hdr_info(inst, in); break; + + case SET_PARAM_POST_EVENT: + set_param_post_event(inst, in); + break; default: aml_vcodec_err(inst, "invalid set parameter type=%d", type); ret = -EINVAL; diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h index 8b029fe..d3ccef2 100644 --- a/drivers/amvdec_ports/vdec_drv_if.h +++ b/drivers/amvdec_ports/vdec_drv_if.h @@ -73,12 +73,13 @@ enum vdec_get_param_type { }; /* - * SET_PARAM_PIC_INFO : set picture info, data parsed from ucode. + * SET_PARAM_PS_INFO : set picture parms, data parsed from ucode. */ enum vdec_set_param_type { SET_PARAM_WRITE_FRAME_SYNC, - SET_PARAM_PIC_INFO, - SET_PARAM_HDR_INFO + SET_PARAM_PS_INFO, + SET_PARAM_HDR_INFO, + SET_PARAM_POST_EVENT }; /** diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index 29c3015..38321bb 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -2748,18 +2748,12 @@ int notify_v4l_eos(struct vdec_s *vdec) { struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - struct vframe_s *vf = NULL; + struct vframe_s *vf = &hw->vframe_dummy; + struct vdec_v4l2_buffer *fb = NULL; int index = INVALID_IDX; ulong expires; if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; - } - expires = jiffies + msecs_to_jiffies(2000); while (INVALID_IDX == (index = get_free_buf_idx(vdec))) { if (time_after(jiffies, expires)) @@ -2767,14 +2761,17 @@ int notify_v4l_eos(struct vdec_s *vdec) } if (index == INVALID_IDX) { - pr_err("[%d] EOS get free buff fail.\n", ctx->id); - return -1; + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) { + pr_err("[%d] EOS get free buff fail.\n", ctx->id); + return -1; + } } vf->type |= VIDTYPE_V4L_EOS; vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = hw->buffer_spec[index].cma_alloc_addr; vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb : + hw->buffer_spec[index].cma_alloc_addr; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); @@ -7836,15 +7833,15 @@ static void vh264_work_implement(struct vdec_h264_hw_s *hw, (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = hw->dpb.mDPB.size; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = hw->dpb.mDPB.size; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } } @@ -8204,20 +8201,20 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) get_used_buf_count(hw) >= run_ready_max_buf_num) ret = 0; - - if (hw->is_used_v4l) { - struct aml_vcodec_ctx *ctx = - (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - - if (ctx->param_sets_from_ucode && - !ctx->v4l_codec_ready && - hw->v4l_params_parsed) { - ret = 0; /*the params has parsed.*/ - } else if (!ctx->v4l_codec_dpb_ready) - ret = 0; - } } #endif + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !ctx->v4l_codec_ready && + hw->v4l_params_parsed) { + ret = 0; /*the params has parsed.*/ + } else if (!ctx->v4l_codec_dpb_ready) + ret = 0; + } + if (ret) not_run_ready[DECODE_ID(hw)] = 0; else diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c index 86055bf..9189564 100644 --- a/drivers/frame_provider/decoder/h265/vh265.c +++ b/drivers/frame_provider/decoder/h265/vh265.c @@ -8997,18 +8997,12 @@ static int notify_v4l_eos(struct vdec_s *vdec) { struct hevc_state_s *hw = (struct hevc_state_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - struct vframe_s *vf = NULL; + struct vframe_s *vf = &hw->vframe_dummy; + struct vdec_v4l2_buffer *fb = NULL; int index = INVALID_IDX; ulong expires; if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - hevc_print(hw, 0, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; - } - expires = jiffies + msecs_to_jiffies(2000); while (INVALID_IDX == (index = get_free_buf_idx(hw))) { if (time_after(jiffies, expires)) @@ -9016,15 +9010,17 @@ static int notify_v4l_eos(struct vdec_s *vdec) } if (index == INVALID_IDX) { - pr_err("[%d] EOS get free buff fail.\n", ctx->id); - return -1; + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) { + pr_err("[%d] EOS get free buff fail.\n", ctx->id); + return -1; + } } vf->type |= VIDTYPE_V4L_EOS; vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = hw->m_BUF[index].v4l_ref_buf_addr; vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; - + vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb : + hw->m_BUF[index].v4l_ref_buf_addr; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -10042,18 +10038,18 @@ force_output: (struct aml_vcodec_ctx *)(hevc->v4l2_ctx); if (ctx->param_sets_from_ucode && !hevc->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; hevc->frame_width = hevc->param.p.pic_width_in_luma_samples; hevc->frame_height = hevc->param.p.pic_height_in_luma_samples; - info.visible_width = hevc->frame_width; - info.visible_height = hevc->frame_height; - info.coded_width = ALIGN(hevc->frame_width, 32); - info.coded_height = ALIGN(hevc->frame_height, 32); - info.dpb_size = get_work_pic_num(hevc); + ps.visible_width = hevc->frame_width; + ps.visible_height = hevc->frame_height; + ps.coded_width = ALIGN(hevc->frame_width, 32); + ps.coded_height = ALIGN(hevc->frame_height, 32); + ps.dpb_size = get_work_pic_num(hevc); hevc->v4l_params_parsed = true; /*notice the v4l2 codec.*/ - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } } diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c index 5ebb6be..1ac107f 100644 --- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c +++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c @@ -292,15 +292,15 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = MAX_BMMU_BUFFER_NUM - 1; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } if (!ctx->v4l_codec_ready) diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c index 7033fa6..6095f68 100644 --- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c +++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c @@ -1627,15 +1627,15 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = MAX_BMMU_BUFFER_NUM - 1; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } if (!ctx->v4l_codec_ready) diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c index 50b10c6..e552855 100644 --- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -950,15 +950,15 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = MAX_BMMU_BUFFER_NUM - 1; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } if (!ctx->v4l_codec_ready) diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c index f712696..19be624 100644 --- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c +++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c @@ -15,8 +15,8 @@ int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx, } EXPORT_SYMBOL(vdec_v4l_get_buffer); -int vdec_v4l_set_pic_infos(struct aml_vcodec_ctx *ctx, - struct aml_vdec_pic_infos *info) +int vdec_v4l_set_ps_infos(struct aml_vcodec_ctx *ctx, + struct aml_vdec_ps_infos *ps) { int ret = 0; @@ -24,11 +24,11 @@ int vdec_v4l_set_pic_infos(struct aml_vcodec_ctx *ctx, return -EIO; ret = ctx->dec_if->set_param(ctx->drv_handle, - SET_PARAM_PIC_INFO, info); + SET_PARAM_PS_INFO, ps); return ret; } -EXPORT_SYMBOL(vdec_v4l_set_pic_infos); +EXPORT_SYMBOL(vdec_v4l_set_ps_infos); int vdec_v4l_set_hdr_infos(struct aml_vcodec_ctx *ctx, struct aml_vdec_hdr_infos *hdr) @@ -45,6 +45,20 @@ int vdec_v4l_set_hdr_infos(struct aml_vcodec_ctx *ctx, } EXPORT_SYMBOL(vdec_v4l_set_hdr_infos); +int vdec_v4l_post_evet(struct aml_vcodec_ctx *ctx, u32 event) +{ + int ret = 0; + + if (ctx->drv_handle == 0) + return -EIO; + + ret = ctx->dec_if->set_param(ctx->drv_handle, + SET_PARAM_POST_EVENT, &event); + + return ret; +} +EXPORT_SYMBOL(vdec_v4l_post_evet); + int vdec_v4l_write_frame_sync(struct aml_vcodec_ctx *ctx) { int ret = 0; diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h index b26cf51..13f3543 100644 --- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h +++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h @@ -8,9 +8,9 @@ int vdec_v4l_get_buffer( struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out); -int vdec_v4l_set_pic_infos( +int vdec_v4l_set_ps_infos( struct aml_vcodec_ctx *ctx, - struct aml_vdec_pic_infos *info); + struct aml_vdec_ps_infos *ps); int vdec_v4l_set_hdr_infos( struct aml_vcodec_ctx *ctx, @@ -19,4 +19,8 @@ int vdec_v4l_set_hdr_infos( int vdec_v4l_write_frame_sync( struct aml_vcodec_ctx *ctx); +int vdec_v4l_post_evet( + struct aml_vcodec_ctx *ctx, + u32 event); + #endif diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c index a59ee93..3cafea2 100644 --- a/drivers/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/frame_provider/decoder/vp9/vvp9.c @@ -1189,6 +1189,7 @@ struct VP9Decoder_s { struct vframe_qos_s vframe_qos; u32 mem_map_mode; u32 dynamic_buf_num_margin; + struct vframe_s vframe_dummy; }; static int vp9_print(struct VP9Decoder_s *pbi, @@ -6816,6 +6817,9 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg) struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; uint8_t index = vf->index & 0xff; + if (vf == (&pbi->vframe_dummy)) + return; + kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf); pbi->vf_put_count++; if (index < pbi->used_buf_num) { @@ -7256,18 +7260,12 @@ static int notify_v4l_eos(struct vdec_s *vdec) { struct VP9Decoder_s *hw = (struct VP9Decoder_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - struct vframe_s *vf = NULL; + struct vframe_s *vf = &hw->vframe_dummy; + struct vdec_v4l2_buffer *fb = NULL; int index = INVALID_IDX; ulong expires; if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - vp9_print(hw, 0, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; - } - expires = jiffies + msecs_to_jiffies(2000); while (INVALID_IDX == (index = get_free_fb(hw))) { if (time_after(jiffies, expires)) @@ -7275,14 +7273,17 @@ static int notify_v4l_eos(struct vdec_s *vdec) } if (index == INVALID_IDX) { - pr_err("[%d] EOS get free buff fail.\n", ctx->id); - return -1; + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) { + pr_err("[%d] EOS get free buff fail.\n", ctx->id); + return -1; + } } vf->type |= VIDTYPE_V4L_EOS; vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = hw->m_BUF[index].v4l_ref_buf_addr; vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb : + hw->m_BUF[index].v4l_ref_buf_addr; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); vf_notify_receiver(vdec->vf_provider_name, @@ -8297,15 +8298,15 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) pbi->frame_width = vp9_param.p.width; pbi->frame_height = vp9_param.p.height; if (ctx->param_sets_from_ucode && !pbi->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = pbi->frame_width; - info.visible_height = pbi->frame_height; - info.coded_width = ALIGN(pbi->frame_width, 32); - info.coded_height = ALIGN(pbi->frame_height, 32); - info.dpb_size = pbi->used_buf_num; + ps.visible_width = pbi->frame_width; + ps.visible_height = pbi->frame_height; + ps.coded_width = ALIGN(pbi->frame_width, 32); + ps.coded_height = ALIGN(pbi->frame_height, 32); + ps.dpb_size = pbi->used_buf_num; pbi->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } } -- 2.20.1