From 683ef21d17b38798584b7700f3d52acdb33614ab Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Sat, 28 Jul 2018 01:04:53 +0800 Subject: [PATCH] amvdec_ports: optimize some codes of the v4l vcodec. PD#170885 1. support the h264 decoding with multi-instance. 2. the reference count of clk mux has't clean was fixed. 3. replace capture worker to thread process. 4. optimize the machine status of the vcodec. 5. remover some locks unnecessary to promote efficiency. 6. the picture infos used to vda that was fixed. Change-Id: I061ebdc088c8c7e14eab73032308715da5f4aafb Signed-off-by: Nanxin Qin --- .../amvdec_ports/aml_vcodec_adapt.c | 124 ++- .../amvdec_ports/aml_vcodec_adapt.h | 28 +- .../amvdec_ports/aml_vcodec_dec.c | 724 +++++++++++------- .../amvdec_ports/aml_vcodec_dec.h | 10 + .../amvdec_ports/aml_vcodec_dec_drv.c | 51 +- .../amvdec_ports/aml_vcodec_drv.h | 74 +- .../amvdec_ports/aml_vcodec_util.c | 12 +- .../amvdec_ports/aml_vcodec_util.h | 22 +- .../amvdec_ports/aml_vcodec_vfm.c | 45 +- .../amvdec_ports/aml_vcodec_vfm.h | 5 +- .../amvdec_ports/decoder/vdec_h264_if.c | 191 ++--- .../media_modules/amvdec_ports/vdec_drv_if.c | 14 +- .../media_modules/amvdec_ports/vdec_drv_if.h | 6 +- .../decoder/h264_multi/vmh264.c | 65 +- .../frame_provider/decoder/utils/vdec.c | 7 +- .../stream_input/amports/amstream.c | 18 +- 16 files changed, 792 insertions(+), 604 deletions(-) diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c index 8b67fb6b6ec2..2f8fc822d147 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c @@ -89,31 +89,17 @@ static struct stream_buf_s bufs[BUF_MAX_NUM] = { }, }; -struct vdec_adapt_config { - struct vdec_s *vdec; - struct stream_port_s port; - struct dec_sysinfo dec_prop; -}; - -struct vdec_adapt_config g_cfg; - static void set_cfg_info(struct aml_vdec_adapt *vdec) { unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); - g_cfg.port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_ES); - g_cfg.port.flag |= PORT_FLAG_VFORMAT; - g_cfg.dec_prop.format = VFORMAT_H264; - g_cfg.dec_prop.width = 1920; - g_cfg.dec_prop.height = 1080; - g_cfg.dec_prop.rate = 3200; - g_cfg.dec_prop.param = (void *)sync_mode; -} - -static void set_system_info(struct vdec_s *vdec) -{ - vdec->sys_info = &g_cfg.dec_prop; - vdec->sys_info_store = g_cfg.dec_prop; + vdec->port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_FRAME/* | PORT_TYPE_ES*/); + vdec->port.flag |= PORT_FLAG_VFORMAT; + vdec->dec_prop.format = vdec->format; + vdec->dec_prop.width = 1920; + vdec->dec_prop.height = 1080; + vdec->dec_prop.rate = 3200; + vdec->dec_prop.param = (void *)sync_mode; } static void set_vdec_mode(struct vdec_s *vdec) @@ -127,10 +113,8 @@ static void set_vdec_vfm(struct vdec_s *vdec) vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO; } -static int enable_hardware(void) +static int enable_hardware(struct stream_port_s *port) { - struct stream_port_s *port = &g_cfg.port; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) return -1; @@ -142,30 +126,22 @@ static int enable_hardware(void) amports_switch_gate("vdec", 1); if (has_hevc_vdec()) { - if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) { - amports_switch_gate("clk_hevc_mux", 1); + if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) vdec_poweron(VDEC_HEVC); - } - if ((port->type & PORT_TYPE_HEVC) == 0) { - amports_switch_gate("clk_vdec_mux", 1); + if ((port->type & PORT_TYPE_HEVC) == 0) vdec_poweron(VDEC_1); - } } else { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { - amports_switch_gate("clk_vdec_mux", 1); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) vdec_poweron(VDEC_1); - } } } return 0; } -static int disable_hardware(void) +static int disable_hardware(struct stream_port_s *port) { - struct stream_port_s *port = &g_cfg.port; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) return -1; @@ -316,9 +292,9 @@ static int audio_component_init(struct stream_port_s *port, static void video_component_release(struct stream_port_s *port, struct stream_buf_s *pbuf, int release_num) { - struct vdec_adapt_config *cfg - = container_of(port, struct vdec_adapt_config, port); - struct vdec_s *vdec = cfg->vdec; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; struct vdec_s *slave = NULL; bool is_multidec = !vdec_single(vdec); @@ -355,9 +331,9 @@ static int video_component_init(struct stream_port_s *port, struct stream_buf_s *pbuf) { int ret = -1; - struct vdec_adapt_config *cfg - = container_of(port, struct vdec_adapt_config, port); - struct vdec_s *vdec = cfg->vdec; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) { pr_err("vformat not set\n"); @@ -437,9 +413,9 @@ static int video_component_init(struct stream_port_s *port, static int vdec_ports_release(struct stream_port_s *port) { - struct vdec_adapt_config *cfg - = container_of(port, struct vdec_adapt_config, port); - struct vdec_s *vdec = cfg->vdec; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; @@ -492,7 +468,7 @@ static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt) struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - struct stream_port_s *port = &g_cfg.port; + struct stream_port_s *port = &vdec_adapt->port; struct vdec_s *vdec = NULL; /* create the vdec instance.*/ @@ -503,11 +479,13 @@ static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt) /* set v4l2 ctx */ vdec->private = vdec_adapt->ctx; - g_cfg.vdec = vdec; + vdec_adapt->vdec = vdec; + vdec->sys_info = &vdec_adapt->dec_prop; + vdec->sys_info_store = vdec_adapt->dec_prop; + vdec->vf_receiver_name = vdec_adapt->recv_name; /* set video format and sys info */ - vdec_set_format(vdec, g_cfg.dec_prop.format); //set by ioctl ??? - set_system_info(vdec); + vdec_set_format(vdec, vdec_adapt->dec_prop.format); set_vdec_mode(vdec); set_vdec_vfm(vdec); @@ -563,7 +541,7 @@ int video_decoder_init(struct aml_vdec_adapt *vdec) set_cfg_info(vdec); /* init hw and gate*/ - ret = enable_hardware(); + ret = enable_hardware(&vdec->port); if (ret < 0) { pr_info("enable hw fail.\n"); goto out; @@ -582,7 +560,7 @@ out: int video_decoder_release(struct aml_vdec_adapt *vdec) { int ret = -1; - struct stream_port_s *port = &g_cfg.port; + struct stream_port_s *port = &vdec->port; ret = vdec_ports_release(port); if (ret < 0) { @@ -591,7 +569,7 @@ int video_decoder_release(struct aml_vdec_adapt *vdec) } /* disable gates */ - ret = disable_hardware(); + ret = disable_hardware(port); if (ret < 0) { pr_info("disable hw fail.\n"); goto out; @@ -600,12 +578,13 @@ out: return ret; } -int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count) +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count) { int ret = -1; int try_cnt = 100; - struct stream_port_s *port = &g_cfg.port; - struct vdec_s *vdec = g_cfg.vdec; + struct stream_port_s *port = &ada_ctx->port; + struct vdec_s *vdec = ada_ctx->vdec; struct stream_buf_s *pbuf = NULL; if (has_hevc_vdec()) { @@ -622,9 +601,9 @@ int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count) do { if (vdec->port_flag & PORT_FLAG_DRM) - ret = drm_write(file, pbuf, buf, count); + ret = drm_write(ada_ctx->filp, pbuf, buf, count); else - ret = esparser_write(file, pbuf, buf, count); + ret = esparser_write(ada_ctx->filp, pbuf, buf, count); } while (ret == -EAGAIN && try_cnt--); if (slow_input) { @@ -641,9 +620,9 @@ int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count) return ret; } -int is_need_to_buf(void) +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; if (vdec->input.have_frame_num > 8) return 0; @@ -651,12 +630,12 @@ int is_need_to_buf(void) return 1; } -int vdec_vframe_write(struct file *file, const char *buf, - unsigned int count, unsigned long int timestamp) +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp) { int ret = -1; int try_cnt = 10; - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; /* set timestamp */ vdec_set_timestamp(vdec, timestamp); @@ -678,33 +657,36 @@ int vdec_vframe_write(struct file *file, const char *buf, /* dump to file */ dump_write(buf, count); #endif - aml_v4l2_debug(1, "vdec_vframe_write, vbuf: %p, size: %u, ret: %d, crc: %x\n", - buf, count, ret, crc32(0, buf, count)); + aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", + ada_ctx->ctx->id, buf, count, ret, crc32(0, buf, count)); return ret; } -void aml_decoder_flush(void) +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; if (vdec) vdec_set_eos(vdec, true); } -void aml_codec_reset(void) +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; + int ret = 0; if (vdec) { vdec_set_eos(vdec, false); - vdec_reset(vdec); + ret = vdec_reset(vdec); } + + return ret; } -bool is_decoder_ready(void) +bool is_input_ready(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; int state = VDEC_STATUS_UNINITIALIZED; if (vdec) { diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h index 9c0b05ba4ad7..e2601495b5e1 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h @@ -2,10 +2,12 @@ #define VDEC_ADAPT_H #include +#include +#include "../stream_input/parser/streambuf.h" #include "aml_vcodec_drv.h" struct aml_vdec_adapt { - enum vformat_e id; + enum vformat_e format; void *vsi; int32_t failure; uint32_t inst_addr; @@ -14,27 +16,31 @@ struct aml_vdec_adapt { struct platform_device *dev; wait_queue_head_t wq; struct file *filp; - //ipi_handler_t handler; + struct vdec_s *vdec; + struct stream_port_s port; + struct dec_sysinfo dec_prop; + char *recv_name; }; -int video_decoder_init(struct aml_vdec_adapt *vdec); +int video_decoder_init(struct aml_vdec_adapt *ada_ctx); -int video_decoder_release(struct aml_vdec_adapt *vdec); +int video_decoder_release(struct aml_vdec_adapt *ada_ctx); -int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count); +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count); -int vdec_vframe_write(struct file *file, const char *buf, - unsigned int count, unsigned long int pts); +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp); -int is_need_to_buf(void); +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); -void aml_decoder_flush(void); +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx); -void aml_codec_reset(void); +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx); extern void dump_write(const char __user *buf, size_t count); -bool is_decoder_ready(void); +bool is_input_ready(struct aml_vdec_adapt *ada_ctx); #endif /* VDEC_ADAPT_H */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c index e33ca62dfdcc..bc6fabcc2b28 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c @@ -106,15 +106,15 @@ static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx) V4L2_EVENT_SRC_CH_RESOLUTION, }; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); } static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx) { - aml_v4l2_debug(1, "%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - aml_decoder_flush(); + aml_decoder_flush(ctx->ada_ctx); } static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) @@ -125,34 +125,34 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->last_decoded_picinfo)) { - aml_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", + aml_v4l2_err("[%d] Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", ctx->id); return; } - if (ctx->last_decoded_picinfo.pic_w == 0 || - ctx->last_decoded_picinfo.pic_h == 0 || - ctx->last_decoded_picinfo.buf_w == 0 || - ctx->last_decoded_picinfo.buf_h == 0) { + if (ctx->last_decoded_picinfo.visible_width == 0 || + ctx->last_decoded_picinfo.visible_height == 0 || + ctx->last_decoded_picinfo.coded_width == 0 || + ctx->last_decoded_picinfo.coded_height == 0) { aml_v4l2_err("Cannot get correct pic info"); return; } - if ((ctx->last_decoded_picinfo.pic_w == ctx->picinfo.pic_w) || - (ctx->last_decoded_picinfo.pic_h == ctx->picinfo.pic_h)) + if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) || + (ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height)) return; aml_v4l2_debug(4, "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)", - ctx->id, ctx->last_decoded_picinfo.pic_w, - ctx->last_decoded_picinfo.pic_h, - ctx->picinfo.pic_w, ctx->picinfo.pic_h, - ctx->last_decoded_picinfo.buf_w, - ctx->last_decoded_picinfo.buf_h); + ctx->id, ctx->last_decoded_picinfo.visible_width, + ctx->last_decoded_picinfo.visible_height, + ctx->picinfo.visible_width, ctx->picinfo.visible_height, + ctx->last_decoded_picinfo.coded_width, + ctx->last_decoded_picinfo.coded_width); ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize); if (dpbsize == 0) - aml_v4l2_err("Incorrect dpb size, ret=%d", ret); + aml_v4l2_err("[%d] Incorrect dpb size, ret=%d", ctx->id, ret); ctx->dpb_size = dpbsize; } @@ -163,14 +163,20 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) struct vdec_fb *pfb; struct aml_video_dec_buf *dst_buf_info, *info; struct vb2_v4l2_buffer *dst_vb2_v4l2; + int try_cnt = 10; - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); - if (!dst_buf) { - pr_err("[%d] dst_buf is empty!!\n", ctx->id); + do { + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + if (dst_buf) + break; + aml_v4l2_debug(3, "[%d] waitting enough dst buffers.", ctx->id); + msleep(20); + } while (try_cnt--); + + if (!dst_buf) return -1; - } 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); @@ -179,23 +185,21 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) //pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->base_y.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_y.dma_addr)); - pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz; + pfb->base_y.size = ctx->picinfo.y_len_sz; //pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1); pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); pfb->base_c.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_c.dma_addr)); - pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz; - pfb->status = 0; + pfb->base_c.size = ctx->picinfo.c_len_sz; + pfb->status = FB_ST_NORMAL; - aml_v4l2_debug(4, - "id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx\n", - dst_buf->index, pfb, - pfb->base_y.va, &pfb->base_y.dma_addr, + aml_v4l2_debug(4, "[%d] id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx", + ctx->id, dst_buf->index, pfb, pfb->base_y.va, &pfb->base_y.dma_addr, &pfb->base_c.dma_addr, pfb->base_y.size, pfb->base_c.size); - mutex_lock(&ctx->lock); + //mutex_lock(&ctx->lock); dst_buf_info->used = true; - mutex_unlock(&ctx->lock); + //mutex_unlock(&ctx->lock); v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); @@ -211,10 +215,10 @@ int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) { struct aml_video_dec_buf *dstbuf; - pr_info("%s() [%d]\n", __FUNCTION__, __LINE__); + pr_info("[%d] %s() [%d]\n", ctx->id, __func__, __LINE__); if (in_fb == NULL) { - aml_v4l2_debug(4, " No free frame buffer"); + aml_v4l2_debug(4, "[%d] No free frame buffer", ctx->id); return -1; } @@ -228,7 +232,7 @@ int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) goto out; aml_v4l2_debug(4, - "[%d]status=%x queue id=%d to rdy_queue", + "[%d] status=%x queue id=%d to rdy_queue", ctx->id, in_fb->status, dstbuf->vb.vb2_buf.index); @@ -250,8 +254,6 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); - if (!dstbuf->used) - return; aml_v4l2_debug(4,"%s() [%d], base_y: %zu, idx: %u\n", __FUNCTION__, __LINE__, fb->base_y.size, dstbuf->vb.vb2_buf.index); @@ -259,40 +261,45 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) __FUNCTION__, __LINE__, fb->base_c.size, dstbuf->vb.vb2_buf.index); dstbuf->vb.vb2_buf.timestamp = vf->timestamp; - aml_v4l2_debug(4,"%s() [%d], timestamp: %llx\n", __FUNCTION__, __LINE__, - vf->timestamp); + aml_v4l2_debug(4, "[%d] %s() [%d], timestamp: %llx", + ctx->id, __func__, __LINE__, vf->timestamp); vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->base_y.bytes_used); vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->base_c.bytes_used); dstbuf->ready_to_display = true; - aml_v4l2_debug(4,"%s() [%d], [%d]status=%x queue id=%d to done_list %d\n", - __FUNCTION__, __LINE__, - ctx->id, fb->status, - dstbuf->vb.vb2_buf.index, + aml_v4l2_debug(4, "[%d]status=%x queue id=%d to done_list %d", + ctx->id, fb->status, dstbuf->vb.vb2_buf.index, dstbuf->queued_in_vb2); cnt = atomic_read(&dstbuf->vb.vb2_buf.vb2_queue->owned_by_drv_count); - aml_v4l2_debug(4,"%s() [%d], owned_by_drv_count: %d\n", __FUNCTION__, __LINE__, cnt); - aml_v4l2_debug(4,"%s() [%d], y_va: %p, vf_h: %lx\n", __FUNCTION__, __LINE__, - dstbuf->frame_buffer.base_y.va, dstbuf->frame_buffer.vf_handle); - - if (ctx->state == AML_STATE_FLUSH && - vf->flag == VFRAME_FLAG_EMPTY_FRAME_V4L) { - pr_info("recevie a empty frame after flush.\n"); + aml_v4l2_debug(4, "[%d] %s() [%d], owned_by_drv_count: %d", + ctx->id, __func__, __LINE__, cnt); + aml_v4l2_debug(4, "[%d] %s() [%d], y_va: %p, vf_h: %lx", + ctx->id, __func__, __LINE__, dstbuf->frame_buffer.base_y.va, + dstbuf->frame_buffer.vf_handle); + if (vf->flag == VFRAME_FLAG_EMPTY_FRAME_V4L) { dstbuf->lastframe = true; dstbuf->vb.flags = V4L2_BUF_FLAG_LAST; vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0); ctx->has_receive_eos = true; + pr_info("[%d] recevie a empty frame.\n", ctx->id); } - aml_v4l2_debug(1, "%s() [%d]\n", __FUNCTION__, __LINE__); - v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHING && + ctx->has_receive_eos) { + ctx->state = AML_STATE_FLUSHED; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHED)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + ctx->decoded_frame_cnt++; } @@ -300,56 +307,65 @@ static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) { int ret = -1; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); ret = vdec_if_get_param(ctx, GET_PARAM_DISP_FRAME_BUFFER, out); if (ret) { - aml_v4l2_err("[%d]Cannot get param : GET_PARAM_DISP_FRAME_BUFFER", ctx->id); + aml_v4l2_err("[%d] Cannot get param : GET_PARAM_DISP_FRAME_BUFFER", ctx->id); return -1; } if (!*out) { - aml_v4l2_debug(4, "No display frame buffer"); + aml_v4l2_debug(4, "[%d] No display frame buffer", ctx->id); return -1; } - //aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); - return ret; } -static void try_to_capture(struct aml_vcodec_ctx *ctx) +static int is_vdec_ready(struct aml_vcodec_ctx *ctx) { - int ret = -1; - int try_cnt = 100; - struct vdec_fb *fb = NULL; - struct aml_video_dec_buf *dstbuf; - int cnt = 0; + struct aml_vcodec_dev *dev = ctx->dev; - do { - ret = get_display_buffer(ctx, &fb); - if (ret) { - aml_v4l2_debug(4,"%s() [%d], the que have no disp buf,ret: %d\n", - __FUNCTION__, __LINE__, ret); - break; + if (!is_input_ready(ctx->ada_ctx)) { + pr_err("[%d] %s() the decoder intput has not ready.\n", + ctx->id, __func__); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + return 0; + } + + if (ctx->state == AML_STATE_PROBE) { + 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->dpb_size) { + aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.\n", + ctx->id, buf_ready_num); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + v4l2_m2m_try_schedule(ctx->m2m_ctx); + msleep(60); + return 0; } - dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); - dstbuf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;//need to change status - cnt = atomic_read(&dstbuf->vb.vb2_buf.vb2_queue->owned_by_drv_count); - aml_v4l2_debug(1, "%s() [%d], cnt: %d\n", __FUNCTION__, __LINE__, cnt); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_PROBE) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + } - if (cnt) - trans_vframe_to_user(ctx, fb); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_READY) { + ctx->state = AML_STATE_ACTIVE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); - //msleep(300); - //video_vf_put(fb);//recycle video buf - - /*ret = put_fb_to_queue(ctx, fb); - if (ret) - aml_v4l2_debug(4,"%s() [%d], put_fb_to_queue fail.\n", - __FUNCTION__, __LINE__);*/ - } while(try_cnt--); + return 1; } static void aml_vdec_worker(struct work_struct *work) @@ -364,20 +380,28 @@ static void aml_vdec_worker(struct work_struct *work) struct aml_video_dec_buf *src_buf_info; struct vb2_v4l2_buffer *src_vb2_v4l2; - aml_v4l2_debug(4,"entry [%d] [%s]\n", __LINE__, __FUNCTION__); + aml_v4l2_debug(4, "[%d] entry [%d] [%s]", ctx->id, __LINE__, __func__); - if ((ctx->state == AML_STATE_FLUSH || - ctx->state == AML_STATE_RESET) && - !is_decoder_ready()) { - pr_err("[%d] [%s] the decoder has no ready.\n", - __LINE__, __FUNCTION__); + aml_vdec_lock(ctx); + + if (ctx->state < AML_STATE_INIT || + ctx->state > AML_STATE_FLUSHED) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); + return; + } + + if (!is_vdec_ready(ctx)) { + pr_err("[%d] %s() the decoder has not ready.\n", + ctx->id, __func__); + aml_vdec_unlock(ctx); return; } src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); if (src_buf == NULL) { - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - aml_v4l2_debug(0, "[%d] src_buf empty!!", ctx->id); + pr_err("[%d] src_buf empty!\n", ctx->id); + aml_vdec_unlock(ctx); return; } @@ -386,10 +410,23 @@ static void aml_vdec_worker(struct work_struct *work) if (src_buf_info->lastframe) { //the empty data use to flushed the decoder. - aml_v4l2_debug(0, "Got empty flush input buffer."); + aml_v4l2_debug(3, "[%d] Got empty flush input buffer.", ctx->id); src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + + /* sets eos data for vdec input. */ + aml_vdec_flush_decoder(ctx); + + 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)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + aml_vdec_unlock(ctx); return; } @@ -402,6 +439,7 @@ static void aml_vdec_worker(struct work_struct *work) v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); aml_v4l2_err("[%d] id=%d src_addr is NULL!!", ctx->id, src_buf->index); + aml_vdec_unlock(ctx); return; } aml_v4l2_debug(4, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", @@ -410,10 +448,10 @@ static void aml_vdec_worker(struct work_struct *work) src_buf_info->used = true; //pr_err("%s() [%d], size: 0x%zx, crc: 0x%x\n", - //__FUNCTION__, __LINE__, buf.size, crc32(0, buf.va, buf.size)); + //__func__, __LINE__, buf.size, crc32(0, buf.va, buf.size)); /* pts = (time / 10e6) * (90k / fps) */ - aml_v4l2_debug(4,"[%d] [%s] timestamp: 0x%llx\n", __LINE__, __FUNCTION__, + aml_v4l2_debug(4, "[%d] %s() timestamp: 0x%llx", ctx->id , __func__, src_buf->timestamp); ret = vdec_if_decode(ctx, &buf, src_buf->timestamp, &res_chg); @@ -426,13 +464,14 @@ static void aml_vdec_worker(struct work_struct *work) v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); } else if (ret == -EAGAIN) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); return; } else { src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); if (ret == -EIO) { - mutex_lock(&ctx->lock); + //mutex_lock(&ctx->lock); src_buf_info->error = true; - mutex_unlock(&ctx->lock); + //mutex_unlock(&ctx->lock); } v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR); } @@ -457,55 +496,160 @@ static void aml_vdec_worker(struct work_struct *work) } v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); -} - -static void aml_vdec_worker_vf(struct work_struct *work) -{ - struct aml_vcodec_ctx *ctx = - container_of(work, struct aml_vcodec_ctx, decode_work_vf); - - aml_v4l2_debug(1, "[%d] [%s], state: %d \n", __LINE__, __FUNCTION__, ctx->state); - - if (ctx->state != AML_STATE_ABORT && - ctx->state != AML_STATE_FREE) - try_to_capture(ctx); + aml_vdec_unlock(ctx); } static void aml_reset_worker(struct work_struct *work) { struct aml_vcodec_ctx *ctx = container_of(work, struct aml_vcodec_ctx, reset_work); - int try_cnt = 10; - int buf_ready_num; - - aml_v4l2_debug(1, "[%d] [%s] \n", __LINE__, __FUNCTION__); + struct aml_video_dec_buf *buf = NULL; aml_vdec_lock(ctx); - do { - buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); - if (buf_ready_num < ctx->dpb_size) { - aml_v4l2_debug(4,"try to get more bufs, num: %d.\n", - buf_ready_num); - msleep(20); - } - } while (buf_ready_num < ctx->dpb_size && try_cnt--); - - if (buf_ready_num < ctx->dpb_size) { + if (ctx->state == AML_STATE_ABORT) { + pr_err("[%d] %s() the decoder will be exited.\n", + ctx->id, __func__); aml_vdec_unlock(ctx); - pr_err("the buf has not enough to be used in decoder.\n"); return; } - aml_codec_reset(); + /* fast enque capture buffers. */ + list_for_each_entry(buf, &ctx->capture_list, node) { + if (buf->que_in_m2m) + v4l2_m2m_buf_queue(ctx->m2m_ctx, &buf->vb); + } - ctx->state = AML_STATE_HEADER; + if (aml_codec_reset(ctx->ada_ctx)) { + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } - v4l2_m2m_try_schedule(ctx->m2m_ctx); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_RESET) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + + v4l2_m2m_try_schedule(ctx->m2m_ctx); + } + mutex_unlock(&ctx->state_lock); aml_vdec_unlock(ctx); } +void try_to_capture(struct aml_vcodec_ctx *ctx) +{ + int ret = 0; + struct vdec_fb *fb = NULL; + + ret = get_display_buffer(ctx, &fb); + if (ret) { + aml_v4l2_debug(4, "[%d] %s() [%d], the que have no disp buf,ret: %d", + ctx->id, __func__, __LINE__, ret); + return; + } + + trans_vframe_to_user(ctx, fb); +} +EXPORT_SYMBOL_GPL(try_to_capture); + +static int vdec_thread(void *data) +{ + struct aml_vdec_thread *thread = + (struct aml_vdec_thread *) data; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *) thread->priv; + + for (;;) { + aml_v4l2_debug(3, "[%d] %s() state: %d", ctx->id, + __func__, ctx->state); + + if (down_interruptible(&thread->sem)) + break; + + if (thread->stop) + break; + + thread->func(ctx); + } + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + + return 0; +} + +void aml_thread_notify(struct aml_vcodec_ctx *ctx, + enum aml_thread_type type) +{ + struct aml_vdec_thread *thread = NULL; + + list_for_each_entry(thread, &ctx->vdec_thread_list, node) { + if (thread->task == NULL) + continue; + + if (thread->type == type) + up(&thread->sem); + } +} +EXPORT_SYMBOL_GPL(aml_thread_notify); + +int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, + enum aml_thread_type type, const char *thread_name) +{ + struct aml_vdec_thread *thread; + int ret = 0; + + thread = kzalloc(sizeof(*thread), GFP_KERNEL); + if (thread == NULL) + return -ENOMEM; + + thread->type = type; + thread->func = func; + thread->priv = ctx; + sema_init(&thread->sem, 0); + + thread->task = kthread_run(vdec_thread, thread, "aml-%s", thread_name); + if (IS_ERR(thread->task)) { + ret = PTR_ERR(thread->task); + thread->task = NULL; + goto err; + } + + list_add(&thread->node, &ctx->vdec_thread_list); + + return 0; + +err: + kfree(thread); + + return ret; +} +EXPORT_SYMBOL_GPL(aml_thread_start); + +void aml_thread_stop(struct aml_vcodec_ctx *ctx) +{ + struct aml_vdec_thread *thread = NULL; + + while (!list_empty(&ctx->vdec_thread_list)) { + thread = list_entry(ctx->vdec_thread_list.next, + struct aml_vdec_thread, node); + list_del(&thread->node); + thread->stop = true; + up(&thread->sem); + kthread_stop(thread->task); + thread->task = NULL; + kfree(thread); + } +} +EXPORT_SYMBOL_GPL(aml_thread_stop); + static int vidioc_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { @@ -534,23 +678,25 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, if (ret) return ret; - aml_v4l2_debug(1, "[%d] [%s], cmd: %u\n", __LINE__, __FUNCTION__, cmd->cmd); + aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u", + ctx->id, __func__, __LINE__, cmd->cmd); dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); switch (cmd->cmd) { case V4L2_DEC_CMD_STOP: - if (ctx->state != AML_STATE_HEADER) + if (ctx->state != AML_STATE_ACTIVE) return 0; src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (!vb2_is_streaming(src_vq)) { - aml_v4l2_debug(0, "Output stream is off. No need to flush."); + pr_err("[%d] Output stream is off. No need to flush.\n", ctx->id); return 0; } + if (!vb2_is_streaming(dst_vq)) { - aml_v4l2_debug(0, "Capture stream is off. No need to flush."); + pr_err("[%d] Capture stream is off. No need to flush.\n", ctx->id); return 0; } @@ -558,14 +704,10 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention - /* flush dst */ - aml_vdec_flush_decoder(ctx); - - ctx->state = AML_STATE_FLUSH; break; case V4L2_DEC_CMD_START: - aml_v4l2_debug(4,"[%d] [%s] V4L2_DEC_CMD_START \n", __LINE__, __FUNCTION__); + aml_v4l2_debug(4, "[%d] CMD V4L2_DEC_CMD_START ", ctx->id); vb2_clear_last_buffer_dequeued(dst_vq);//pay attention break; @@ -589,12 +731,16 @@ static int vidioc_decoder_streamon(struct file *file, void *priv, q = v4l2_m2m_get_vq(fh->m2m_ctx, i); - if (ctx->state == AML_STATE_FLUSH) { + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHED) { if (!V4L2_TYPE_IS_OUTPUT(q->type)) { - queue_work(dev->reset_workqueue, &ctx->reset_work); ctx->state = AML_STATE_RESET; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", + ctx->id, __func__); + queue_work(dev->reset_workqueue, &ctx->reset_work); } } + mutex_unlock(&ctx->state_lock); return ret; } @@ -611,8 +757,15 @@ void aml_vdec_lock(struct aml_vcodec_ctx *ctx) void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx) { + aml_vdec_lock(ctx); + + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + vdec_if_deinit(ctx); - ctx->state = AML_STATE_FREE; + + aml_vdec_unlock(ctx); } void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) @@ -623,7 +776,6 @@ void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) ctx->fh.m2m_ctx = ctx->m2m_ctx; ctx->fh.ctrl_handler = &ctx->ctrl_hdl; INIT_WORK(&ctx->decode_work, aml_vdec_worker); - INIT_WORK(&ctx->decode_work_vf, aml_vdec_worker_vf); INIT_WORK(&ctx->reset_work, aml_reset_worker); ctx->colorspace = V4L2_COLORSPACE_REC709; ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; @@ -661,6 +813,10 @@ void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) q_data->bytesperline[0] = q_data->coded_width; q_data->sizeimage[1] = q_data->sizeimage[0] / 2; q_data->bytesperline[1] = q_data->coded_width; + + ctx->state = AML_STATE_IDLE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_IDLE)", + ctx->id, __func__); } static int vidioc_vdec_qbuf(struct file *file, void *priv, @@ -688,12 +844,6 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv, return -EIO; } - /*if (V4L2_TYPE_IS_OUTPUT(buf->type)) { - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); - wait_event_interruptible_timeout(ctx->wq, is_need_to_buf(), - msecs_to_jiffies(200)); - }*/ - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); } @@ -744,7 +894,7 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt) * Find next closer width align 64, heign align 64, size align * 64 rectangle * Note: This only get default value, the real HW needed value - * only available when ctx in AML_STATE_HEADER state + * only available when ctx in AML_STATE_PROBE state */ tmp_w = pix_fmt_mp->width; tmp_h = pix_fmt_mp->height; @@ -839,14 +989,14 @@ static int vidioc_vdec_g_selection(struct file *file, void *priv, case V4L2_SEL_TGT_COMPOSE_DEFAULT: s->r.left = 0; s->r.top = 0; - s->r.width = ctx->picinfo.pic_w; - s->r.height = ctx->picinfo.pic_h; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; break; case V4L2_SEL_TGT_COMPOSE_BOUNDS: s->r.left = 0; s->r.top = 0; - s->r.width = ctx->picinfo.buf_w; - s->r.height = ctx->picinfo.buf_h; + s->r.width = ctx->picinfo.coded_width; + s->r.height = ctx->picinfo.coded_height; break; case V4L2_SEL_TGT_COMPOSE: if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) { @@ -861,7 +1011,7 @@ static int vidioc_vdec_g_selection(struct file *file, void *priv, return -EINVAL; } - if (ctx->state < AML_STATE_HEADER) { + if (ctx->state < AML_STATE_PROBE) { /* set to default value if header info not ready yet*/ s->r.left = 0; s->r.top = 0; @@ -885,8 +1035,8 @@ static int vidioc_vdec_s_selection(struct file *file, void *priv, case V4L2_SEL_TGT_COMPOSE: s->r.left = 0; s->r.top = 0; - s->r.width = ctx->picinfo.pic_w; - s->r.height = ctx->picinfo.pic_h; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; break; default: return -EINVAL; @@ -904,7 +1054,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, int ret = 0; struct aml_video_fmt *fmt; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); q_data = aml_vdec_get_q_data(ctx, f->type); if (!q_data) @@ -913,12 +1063,12 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, pix_mp = &f->fmt.pix_mp; if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) { - aml_v4l2_err("out_q_ctx buffers already requested"); + aml_v4l2_err("[%d] out_q_ctx buffers already requested", ctx->id); } if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) { - aml_v4l2_err("cap_q_ctx buffers already requested"); + aml_v4l2_err("[%d] cap_q_ctx buffers already requested", ctx->id); } fmt = aml_vdec_find_format(f); @@ -941,8 +1091,8 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, q_data->coded_width = pix_mp->width; q_data->coded_height = pix_mp->height; - aml_v4l2_debug(4, "%s() [%d], w: %d, h: %d, size: %d\n", - __func__, __LINE__, pix_mp->width, pix_mp->height, + aml_v4l2_debug(4, "[%d] %s() [%d], w: %d, h: %d, size: %d", + ctx->id, __func__, __LINE__, pix_mp->width, pix_mp->height, pix_mp->plane_fmt[0].sizeimage); ctx->colorspace = f->fmt.pix_mp.colorspace; @@ -950,15 +1100,20 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, ctx->quantization = f->fmt.pix_mp.quantization; ctx->xfer_func = f->fmt.pix_mp.xfer_func; - if (ctx->state == AML_STATE_FREE) { + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_IDLE) { ret = vdec_if_init(ctx, q_data->fmt->fourcc); if (ret) { aml_v4l2_err("[%d]: vdec_if_init() fail ret=%d", ctx->id, ret); + mutex_unlock(&ctx->state_lock); return -EINVAL; } ctx->state = AML_STATE_INIT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_INIT)", + ctx->id, __func__); } + mutex_unlock(&ctx->state_lock); } return 0; @@ -981,14 +1136,14 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, fsize->stepwise = aml_vdec_framesizes[i].stepwise; if (!(ctx->dev->dec_capability & VCODEC_CAPABILITY_4K_DISABLED)) { - aml_v4l2_debug(4, "4K is enabled"); + aml_v4l2_debug(4, "[%d] 4K is enabled", ctx->id); fsize->stepwise.max_width = VCODEC_DEC_4K_CODED_WIDTH; fsize->stepwise.max_height = VCODEC_DEC_4K_CODED_HEIGHT; } - aml_v4l2_debug(4, "%x, %d %d %d %d %d %d", - ctx->dev->dec_capability, + aml_v4l2_debug(4, "[%d] %x, %d %d %d %d %d %d", + ctx->id, ctx->dev->dec_capability, fsize->stepwise.min_width, fsize->stepwise.max_width, fsize->stepwise.step_width, @@ -1049,7 +1204,7 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (!vq) { - aml_v4l2_err("no vb2 queue for type=%d", f->type); + aml_v4l2_err("[%d] no vb2 queue for type=%d", ctx->id, f->type); return -EINVAL; } @@ -1062,7 +1217,7 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, pix_mp->xfer_func = ctx->xfer_func; if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && - (ctx->state >= AML_STATE_HEADER)) { + (ctx->state >= AML_STATE_PROBE)) { /* Until STREAMOFF is called on the CAPTURE queue * (acknowledging the event), the driver operates as if * the resolution hasn't changed yet. @@ -1074,11 +1229,11 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, q_data->sizeimage[1] = ctx->picinfo.c_len_sz; /* it is used for alloc the EGL image buffer size. */ - q_data->coded_width = ctx->picinfo.pic_w; - q_data->coded_height = ctx->picinfo.pic_h; + q_data->coded_width = ctx->picinfo.coded_width; + q_data->coded_height = ctx->picinfo.coded_height; - q_data->bytesperline[0] = ctx->picinfo.buf_w; - q_data->bytesperline[1] = ctx->picinfo.buf_w; + q_data->bytesperline[0] = ctx->picinfo.coded_width; + q_data->bytesperline[1] = ctx->picinfo.coded_height; /* * Width and height are set to the dimensions @@ -1099,7 +1254,6 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; - } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { /* * This is run on OUTPUT @@ -1153,7 +1307,7 @@ static int vb2ops_vdec_queue_setup(struct vb2_queue *vq, q_data = aml_vdec_get_q_data(ctx, vq->type); if (q_data == NULL) { - aml_v4l2_err("vq->type=%d err\n", vq->type); + aml_v4l2_err("[%d] vq->type=%d err", ctx->id, vq->type); return -EINVAL; } @@ -1177,7 +1331,7 @@ static int vb2ops_vdec_queue_setup(struct vb2_queue *vq, } } - pr_info("[%d], type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n", + pr_info("[%d] type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n", ctx->id, vq->type, *nplanes, *nbuffers, sizes[0], sizes[1]); return 0; @@ -1196,8 +1350,8 @@ static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb) for (i = 0; i < q_data->fmt->num_planes; i++) { if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) { - aml_v4l2_err("data will not fit into plane %d (%lu < %d)", - i, vb2_plane_size(vb, i), + aml_v4l2_err("[%d] data will not fit into plane %d (%lu < %d)", + ctx->id, i, vb2_plane_size(vb, i), q_data->sizeimage[i]); } } @@ -1216,29 +1370,36 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) vb2_v4l2 = to_vb2_v4l2_buffer(vb); buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - aml_v4l2_debug(1, "%s(),[%d], vb: %p, type: %d, idx: %d, state: %d, used: %d\n", - __FUNCTION__, __LINE__, vb, vb->vb2_queue->type, + aml_v4l2_debug(3, "[%d] %s(), vb: %p, type: %d, idx: %d, state: %d, used: %d", + ctx->id, __func__, vb, vb->vb2_queue->type, vb->index, vb->state, buf->used); /* * check if this buffer is ready to be used after decode */ - if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + aml_v4l2_debug(3, "[%d] %s() [%d], y_va: %p, vf_h: %lx, state: %d", ctx->id, + __func__, __LINE__, buf->frame_buffer.base_y.va, + buf->frame_buffer.vf_handle, buf->frame_buffer.status); - aml_v4l2_debug(4, "%s() [%d], y_va: %p, vf_h: %lx\n", __FUNCTION__, __LINE__, - buf->frame_buffer.base_y.va, buf->frame_buffer.vf_handle); - - if (buf->used == false) { + if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) { + aml_v4l2_debug(3, "[%d] enque capture buf idx %d, %p\n", + ctx->id, vb->index, vb); v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); + buf->que_in_m2m = true; buf->queued_in_vb2 = true; buf->queued_in_v4l2 = true; buf->ready_to_display = false; - } else { + + /*save capture bufs to be used for resetting config.*/ + list_add(&buf->node, &ctx->capture_list); + } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; buf->ready_to_display = false; /* recycle vf */ - video_vf_put(&buf->frame_buffer); + video_vf_put(ctx->ada_ctx->recv_name, + &buf->frame_buffer, ctx->id); } return; } @@ -1255,7 +1416,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); if (buf->lastframe) { /* This shouldn't happen. Just in case. */ - aml_v4l2_err("Invalid flush buffer.\n"); + aml_v4l2_err("[%d] Invalid flush buffer.", ctx->id); v4l2_m2m_src_buf_remove(ctx->m2m_ctx); return; } @@ -1280,11 +1441,13 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) ctx->last_decoded_picinfo = ctx->picinfo; aml_vdec_queue_res_chg_event(ctx); - ctx->state = AML_STATE_HEADER; - - aml_v4l2_debug(1, "pic info, w: %u, h: %u, y_s: %u, c_s: %u, DPB: %u\n", - ctx->picinfo.pic_w, ctx->picinfo.pic_h, ctx->picinfo.y_len_sz, - ctx->picinfo.c_len_sz, ctx->dpb_size); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_INIT) { + ctx->state = AML_STATE_PROBE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); } static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) @@ -1294,39 +1457,43 @@ static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) struct aml_video_dec_buf *buf = NULL; bool buf_error; - //pr_err("entry [%d] [%s]\n", __LINE__, __FUNCTION__); - vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - mutex_lock(&ctx->lock); + //mutex_lock(&ctx->lock); if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { buf->queued_in_v4l2 = false; buf->queued_in_vb2 = false; } buf_error = buf->error; - mutex_unlock(&ctx->lock); + //mutex_unlock(&ctx->lock); if (buf_error) { - aml_v4l2_err("Unrecoverable error on buffer."); + aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id); ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); } } static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) { + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); struct aml_video_dec_buf *buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); unsigned int size, phy_addr = 0; + char *owner = __getname(); - aml_v4l2_debug(4, "(%d) id=%d", vb->vb2_queue->type, vb->index); + aml_v4l2_debug(4, "[%d] (%d) id=%d", + ctx->id, vb->vb2_queue->type, vb->index); if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { buf->used = false; buf->ready_to_display = false; buf->queued_in_v4l2 = false; + buf->frame_buffer.status = FB_ST_NORMAL; } else { buf->lastframe = false; } @@ -1335,31 +1502,42 @@ static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) if (V4L2_TYPE_IS_OUTPUT(vb->type)) { size = vb->planes[0].length; phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - buf->mem[0] = v4l_reqbufs_from_codec_mm("v4l-input", - phy_addr, size, vb->index); - aml_v4l2_debug(1, "IN alloc, addr: %x, size: %u, idx: %u\n", - phy_addr, size, vb->index); + snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] IN alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); } else { size = vb->planes[0].length; phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - buf->mem[0] = v4l_reqbufs_from_codec_mm("v4l-output", - phy_addr, size, vb->index); - aml_v4l2_debug(1, "OUT Y alloc, addr: %x, size: %u, idx: %u\n", + snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); size = vb->planes[1].length; phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1); - buf->mem[1] = v4l_reqbufs_from_codec_mm("v4l-output", - phy_addr, size, vb->index); - aml_v4l2_debug(1, "OUT C alloc, addr: %x, size: %u, idx: %u\n", - phy_addr, size, vb->index); + buf->mem[1] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT C alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); } + __putname(owner); + return 0; } static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) { + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); struct vb2_v4l2_buffer *vb2_v4l2 = NULL; struct aml_video_dec_buf *buf = NULL; int i; @@ -1371,23 +1549,23 @@ static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) return; if (V4L2_TYPE_IS_OUTPUT(q->bufs[i]->type)) { - v4l_freebufs_back_to_codec_mm("v4l-input", buf->mem[0]); - buf->mem[0] = NULL; + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); - aml_v4l2_debug(1, "IN clean, addr: %lx, size: %u, idx: %u\n", - buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + aml_v4l2_debug(3, "[%d] IN clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + buf->mem[0] = NULL; continue; } - v4l_freebufs_back_to_codec_mm("v4l-output", buf->mem[0]); - v4l_freebufs_back_to_codec_mm("v4l-output", buf->mem[1]); + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]); + + aml_v4l2_debug(3, "[%d] OUT Y clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + aml_v4l2_debug(3, "[%d] OUT C clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); buf->mem[0] = NULL; buf->mem[1] = NULL; - - aml_v4l2_debug(1, "OUT Y clean, addr: %lx, size: %u, idx: %u\n", - buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); - aml_v4l2_debug(1, "OUT C clean, addr: %lx, size: %u, idx: %u\n", - buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); } } @@ -1403,70 +1581,31 @@ static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count) static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) { - struct vb2_buffer *src_buf = NULL, *dst_buf = NULL; + struct aml_video_dec_buf *buf = NULL; + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); int i; - aml_v4l2_debug(1, "[%d] [%s], [%d] (%d) state=(%x) frame_cnt=%d\n", - __LINE__, __FUNCTION__, ctx->id, q->type, - ctx->state, ctx->decoded_frame_cnt); + aml_v4l2_debug(3, "[%d] (%d) state=(%x) frame_cnt=%d", + ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt); codec_mm_bufs_cnt_clean(q); - if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) { - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_video_dec_buf *buf_info = NULL; - int cnt; - - vb2_v4l2 = to_vb2_v4l2_buffer(src_buf); - buf_info = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - - cnt = atomic_read(&src_buf->vb2_queue->owned_by_drv_count); - aml_v4l2_debug(4,"%s() [%d], owned_by_drv_count: %d, lastframe: %d\n", - __FUNCTION__, __LINE__, cnt, buf_info->lastframe); - - if (!buf_info->lastframe) - v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_QUEUED); - } - + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + while (v4l2_m2m_src_buf_remove(ctx->m2m_ctx)); return; } - while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) { - int cnt; + while (v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)); - vb2_set_plane_payload(dst_buf, 0, 0); - vb2_set_plane_payload(dst_buf, 1, 0); - - cnt = atomic_read(&dst_buf->vb2_queue->owned_by_drv_count); - - aml_v4l2_debug(4,"%s() [%d], state: %d, cnt: %d\n", - __FUNCTION__, __LINE__, dst_buf->state, cnt); - - if (dst_buf->state == VB2_BUF_STATE_DONE || !cnt) { //discard vframe data - dst_buf->state = VB2_BUF_STATE_ACTIVE; - continue; - } - - dst_buf->state = VB2_BUF_STATE_ACTIVE;//need to change status - - v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf), VB2_BUF_STATE_QUEUED); - } - - /*capture*/ for (i = 0; i < q->num_buffers; ++i) { - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_video_dec_buf *buf_info = NULL; - - if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) - vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_QUEUED); - + if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { + q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED; + atomic_dec(&q->owned_by_drv_count); + } vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); - buf_info = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - - if (ctx->has_receive_eos) - buf_info->used = false; + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + buf->frame_buffer.status = FB_ST_FREE; } } @@ -1475,36 +1614,31 @@ static void m2mops_vdec_device_run(void *priv) struct aml_vcodec_ctx *ctx = priv; struct aml_vcodec_dev *dev = ctx->dev; - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); queue_work(dev->decode_workqueue, &ctx->decode_work); } void vdec_device_vf_run(struct aml_vcodec_ctx *ctx) { - struct aml_vcodec_dev *dev = ctx->dev; + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + if (ctx->state < AML_STATE_ACTIVE || + ctx->state > AML_STATE_FLUSHED) + return; - /*wake_up_interruptible(&ctx->wq);*/ - - queue_work(dev->decode_workqueue_vf, &ctx->decode_work_vf); + aml_thread_notify(ctx, AML_THREAD_CAPTURE); } static int m2mops_vdec_job_ready(void *m2m_priv) { struct aml_vcodec_ctx *ctx = m2m_priv; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s(), state: %d", ctx->id, + __func__, ctx->state); - if (ctx->state == AML_STATE_ABORT) - return 0; - - if ((ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w) || - (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h)) - return 0; - - if (ctx->state != AML_STATE_HEADER) + if (ctx->state < AML_STATE_PROBE || + ctx->state > AML_STATE_FLUSHED) return 0; return 1; @@ -1514,9 +1648,13 @@ static void m2mops_vdec_job_abort(void *priv) { struct aml_vcodec_ctx *ctx = priv; - aml_v4l2_debug(1, "%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + + wake_up(&ctx->m2m_ctx->finished); } static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) @@ -1524,14 +1662,14 @@ static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl); int ret = 0; - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(4, "%s() [%d]", __func__, __LINE__); switch (ctrl->id) { case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - if (ctx->state >= AML_STATE_HEADER) { + if (ctx->state >= AML_STATE_PROBE) { ctrl->val = ctx->dpb_size; } else { - aml_v4l2_debug(0, "Seqinfo not ready"); + pr_err("Seqinfo not ready.\n"); ctrl->val = 0; } break; @@ -1558,8 +1696,8 @@ int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx) ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; if (ctx->ctrl_hdl.error) { - aml_v4l2_err("Adding control failed %d", - ctx->ctrl_hdl.error); + aml_v4l2_err("[%d] Adding control failed %d", + ctx->id, ctx->ctrl_hdl.error); return ctx->ctrl_hdl.error; } @@ -1571,7 +1709,7 @@ static void m2mops_vdec_lock(void *m2m_priv) { struct aml_vcodec_ctx *ctx = m2m_priv; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); mutex_lock(&ctx->dev->dev_mutex); } @@ -1579,7 +1717,7 @@ static void m2mops_vdec_unlock(void *m2m_priv) { struct aml_vcodec_ctx *ctx = m2m_priv; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); mutex_unlock(&ctx->dev->dev_mutex); } @@ -1644,7 +1782,7 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, struct aml_vcodec_ctx *ctx = priv; int ret = 0; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; src_vq->io_modes = VB2_DMABUF | VB2_MMAP; @@ -1657,11 +1795,11 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, ret = vb2_queue_init(src_vq); if (ret) { - aml_v4l2_err("Failed to initialize videobuf2 queue(output)"); + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(output)", ctx->id); return ret; } dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; + dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); dst_vq->ops = &aml_vdec_vb2_ops; @@ -1672,7 +1810,7 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, ret = vb2_queue_init(dst_vq); if (ret) { vb2_queue_release(src_vq); - aml_v4l2_err("Failed to initialize videobuf2 queue(capture)"); + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(capture)", ctx->id); } return ret; diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h index ae9f1e9338fa..62ef2c91d467 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h @@ -49,8 +49,11 @@ struct aml_video_dec_buf { struct vdec_fb frame_buffer; struct codec_mm_s *mem[2]; + char mem_onwer[32]; + struct list_head node; bool used; bool ready_to_display; + bool que_in_m2m; bool queued_in_vb2; bool queued_in_v4l2; bool lastframe; @@ -77,4 +80,11 @@ int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx); void vdec_device_vf_run(struct aml_vcodec_ctx *ctx); +void try_to_capture(struct aml_vcodec_ctx *ctx); +void aml_thread_notify(struct aml_vcodec_ctx *ctx, + enum aml_thread_type type); +int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, + enum aml_thread_type type, const char *thread_name); +void aml_thread_stop(struct aml_vcodec_ctx *ctx); + #endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c index f931c602bb48..8a45a032d05b 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "aml_vcodec_drv.h" #include "aml_vcodec_dec.h" @@ -49,24 +50,26 @@ static int fops_vcodec_open(struct file *file) file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); INIT_LIST_HEAD(&ctx->list); + INIT_LIST_HEAD(&ctx->capture_list); + INIT_LIST_HEAD(&ctx->vdec_thread_list); dev->filp = file; ctx->dev = dev; init_waitqueue_head(&ctx->queue); + mutex_init(&ctx->state_lock); mutex_init(&ctx->lock); - sema_init(&ctx->sem, 1); init_waitqueue_head(&ctx->wq); ctx->type = AML_INST_DECODER; ret = aml_vcodec_dec_ctrls_setup(ctx); if (ret) { - aml_v4l2_err("Failed to setup mt vcodec controls\n"); + aml_v4l2_err("Failed to setup vcodec controls"); goto err_ctrls_setup; } ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx, &aml_vcodec_dec_queue_init); if (IS_ERR((__force void *)ctx->m2m_ctx)) { ret = PTR_ERR((__force void *)ctx->m2m_ctx); - aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)\n", ret); + aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", ret); goto err_m2m_ctx_init; } src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, @@ -75,6 +78,12 @@ static int fops_vcodec_open(struct file *file) ctx->empty_flush_buf->lastframe = true; aml_vcodec_dec_set_default_params(ctx); + ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap"); + if (ret) { + aml_v4l2_err("Failed to creat capture thread."); + goto err_creat_thread; + } + list_add(&ctx->list, &dev->ctx_list); mutex_unlock(&dev->dev_mutex); @@ -83,8 +92,8 @@ static int fops_vcodec_open(struct file *file) return ret; /* Deinit when failure occurred */ -//err_load_fw: - /*v4l2_m2m_ctx_release(ctx->m2m_ctx);*/ +err_creat_thread: + v4l2_m2m_ctx_release(ctx->m2m_ctx); err_m2m_ctx_init: v4l2_ctrl_handler_free(&ctx->ctrl_hdl); err_ctrls_setup: @@ -111,13 +120,15 @@ static int fops_vcodec_release(struct file *file) * Second, the decoder will be flushed and all the buffers will be * returned in stop_streaming. */ - v4l2_m2m_ctx_release(ctx->m2m_ctx); aml_vcodec_dec_release(ctx); + v4l2_m2m_ctx_release(ctx->m2m_ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); + aml_thread_stop(ctx); + list_del_init(&ctx->list); kfree(ctx->empty_flush_buf); kfree(ctx); @@ -156,7 +167,7 @@ static int aml_vcodec_probe(struct platform_device *pdev) ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) { - aml_v4l2_err("v4l2_device_register err=%d\n", ret); + aml_v4l2_err("v4l2_device_register err=%d", ret); goto err_res; } @@ -164,7 +175,7 @@ static int aml_vcodec_probe(struct platform_device *pdev) vfd_dec = video_device_alloc(); if (!vfd_dec) { - aml_v4l2_err("Failed to allocate video device\n"); + aml_v4l2_err("Failed to allocate video device"); ret = -ENOMEM; goto err_dec_alloc; } @@ -186,7 +197,7 @@ static int aml_vcodec_probe(struct platform_device *pdev) dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops); if (IS_ERR((__force void *)dev->m2m_dev_dec)) { - aml_v4l2_err("Failed to init mem2mem dec device\n"); + aml_v4l2_err("Failed to init mem2mem dec device"); ret = PTR_ERR((__force void *)dev->m2m_dev_dec); goto err_dec_mem_init; } @@ -195,28 +206,17 @@ static int aml_vcodec_probe(struct platform_device *pdev) alloc_ordered_workqueue(AML_VCODEC_DEC_NAME, WQ_MEM_RECLAIM | WQ_FREEZABLE); if (!dev->decode_workqueue) { - aml_v4l2_err("Failed to create decode workqueue\n"); + aml_v4l2_err("Failed to create decode workqueue"); ret = -EINVAL; goto err_event_workq; } - dev->decode_workqueue_vf = - alloc_ordered_workqueue("aml-vcodec-dec-vf", - WQ_MEM_RECLAIM | WQ_FREEZABLE); - if (!dev->decode_workqueue_vf) { - aml_v4l2_err("Failed to create decode workqueue\n"); - ret = -EINVAL; - destroy_workqueue(dev->decode_workqueue); - goto err_event_workq; - } - dev->reset_workqueue = alloc_ordered_workqueue("aml-vcodec-reset", WQ_MEM_RECLAIM | WQ_FREEZABLE); - if (!dev->decode_workqueue_vf) { - aml_v4l2_err("Failed to create decode workqueue\n"); + if (!dev->reset_workqueue) { + aml_v4l2_err("Failed to create decode workqueue"); ret = -EINVAL; - destroy_workqueue(dev->decode_workqueue_vf); destroy_workqueue(dev->decode_workqueue); goto err_event_workq; } @@ -235,7 +235,6 @@ static int aml_vcodec_probe(struct platform_device *pdev) err_dec_reg: destroy_workqueue(dev->reset_workqueue); - destroy_workqueue(dev->decode_workqueue_vf); destroy_workqueue(dev->decode_workqueue); err_event_workq: v4l2_m2m_release(dev->m2m_dev_dec); @@ -259,8 +258,8 @@ static int aml_vcodec_dec_remove(struct platform_device *pdev) { struct aml_vcodec_dev *dev = platform_get_drvdata(pdev); - flush_workqueue(dev->decode_workqueue_vf); - destroy_workqueue(dev->decode_workqueue_vf); + flush_workqueue(dev->reset_workqueue); + destroy_workqueue(dev->reset_workqueue); flush_workqueue(dev->decode_workqueue); destroy_workqueue(dev->decode_workqueue); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h index 4b9573091c84..4e00b233de17 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h @@ -12,7 +12,7 @@ #define AML_VCODEC_DRV_NAME "aml_vcodec_drv" #define AML_VCODEC_DEC_NAME "aml-vcodec-dec" #define AML_VCODEC_ENC_NAME "aml-vcodec-enc" -#define AML_PLATFORM_STR "platform:mt8173" +#define AML_PLATFORM_STR "platform:amlogic" #define AML_VCODEC_MAX_PLANES 3 #define AML_V4L2_BENCHMARK 0 @@ -52,20 +52,25 @@ enum aml_instance_type { /** * enum aml_instance_state - The state of an AML Vcodec instance. - * @AML_STATE_FREE - default state when instance is created - * @AML_STATE_INIT - vcodec instance is initialized - * @AML_STATE_HEADER - vdec had sps/pps header parsed or venc - * had sps/pps header encoded - * @AML_STATE_FLUSH - vdec is flushing. Only used by decoder - * @AML_STATE_ABORT - vcodec should be aborted + * @AML_STATE_IDLE - default state when instance is created + * @AML_STATE_INIT - vcodec instance is initialized + * @AML_STATE_PROBE - vdec/venc had sps/pps header parsed/encoded + * @AML_STATE_ACTIVE - vdec is ready for work. + * @AML_STATE_FLUSHING - vdec is flushing. Only used by decoder + * @AML_STATE_FLUSHED - decoder has transacted the last frame. + * @AML_STATE_RESET - decoder has be reset after flush. + * @AML_STATE_ABORT - vcodec should be aborted */ enum aml_instance_state { - AML_STATE_FREE = 0, - AML_STATE_INIT = 1, - AML_STATE_HEADER = 2, - AML_STATE_FLUSH = 3, - AML_STATE_ABORT = 4, - AML_STATE_RESET = 5, + AML_STATE_IDLE, + AML_STATE_INIT, + AML_STATE_PROBE, + AML_STATE_READY, + AML_STATE_ACTIVE, + AML_STATE_FLUSHING, + AML_STATE_FLUSHED, + AML_STATE_RESET, + AML_STATE_ABORT, }; /** @@ -186,10 +191,10 @@ struct aml_vcodec_pm { /** * struct vdec_pic_info - picture size information - * @pic_w: picture width - * @pic_h: picture height - * @buf_w: picture buffer width (64 aligned up from pic_w) - * @buf_h: picture buffer heiht (64 aligned up from pic_h) + * @visible_width: picture width + * @visible_height: picture height + * @coded_width: picture buffer width (64 aligned up from pic_w) + * @coded_height: picture buffer heiht (64 aligned up from pic_h) * @y_bs_sz: Y bitstream size * @c_bs_sz: CbCr bitstream size * @y_len_sz: additional size required to store decompress information for y @@ -200,16 +205,35 @@ struct aml_vcodec_pm { * buffer size will be aligned to 176x160. */ struct vdec_pic_info { - unsigned int pic_w; - unsigned int pic_h; - unsigned int buf_w; - unsigned int buf_h; + unsigned int visible_width; + unsigned int visible_height; + unsigned int coded_width; + unsigned int coded_height; unsigned int y_bs_sz; unsigned int c_bs_sz; unsigned int y_len_sz; unsigned int c_len_sz; }; +enum aml_thread_type { + AML_THREAD_OUTPUT, + AML_THREAD_CAPTURE, +}; + +typedef void (*aml_thread_func)(struct aml_vcodec_ctx *ctx); + +struct aml_vdec_thread { + struct list_head node; + spinlock_t lock; + struct semaphore sem; + struct task_struct *task; + enum aml_thread_type type; + void *priv; + int stop; + + aml_thread_func func; +}; + /** * struct aml_vcodec_ctx - Context (instance) private data. * @@ -256,8 +280,10 @@ struct aml_vcodec_ctx { struct v4l2_fh fh; struct v4l2_m2m_ctx *m2m_ctx; + struct aml_vdec_adapt *ada_ctx; struct aml_q_data q_data[2]; int id; + struct mutex state_lock; enum aml_instance_state state; enum aml_encode_param param_change; struct aml_enc_params enc_params; @@ -276,7 +302,6 @@ struct aml_vcodec_ctx { struct v4l2_ctrl_handler ctrl_hdl; struct work_struct decode_work; - struct work_struct decode_work_vf; struct work_struct encode_work; struct work_struct reset_work; struct vdec_pic_info last_decoded_picinfo; @@ -289,10 +314,10 @@ struct aml_vcodec_ctx { int decoded_frame_cnt; struct mutex lock; - struct semaphore sem; wait_queue_head_t wq; bool has_receive_eos; - + struct list_head capture_list; + struct list_head vdec_thread_list; }; /** @@ -352,7 +377,6 @@ struct aml_vcodec_dev { unsigned long id_counter; struct workqueue_struct *decode_workqueue; - struct workqueue_struct *decode_workqueue_vf; struct workqueue_struct *encode_workqueue; struct workqueue_struct *reset_workqueue; int int_cond; diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c index b30dd2b051ea..32733e35012f 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c @@ -45,10 +45,10 @@ int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, memset(mem->va, 0, size); - aml_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va); - aml_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id, + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, (unsigned long)mem->dma_addr); - aml_v4l2_debug(3, "[%d] size = 0x%lx", ctx->id, size); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); return 0; } @@ -67,10 +67,10 @@ void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, return; } - aml_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va); - aml_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id, + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, (unsigned long)mem->dma_addr); - aml_v4l2_debug(3, "[%d] size = 0x%lx", ctx->id, size); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); dma_free_coherent(dev, size, mem->va, mem->dma_addr); mem->va = NULL; diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h index 861c8e6a0286..ee9b5370116a 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h @@ -23,11 +23,10 @@ extern bool aml_vcodec_dbg; #if defined(DEBUG) -#define aml_v4l2_debug(level, fmt, args...) \ - do { \ - if (aml_v4l2_dbg_level >= level) \ - pr_info("[AML_V4L2] level=%d %s(),%d: " fmt "\n",\ - level, __func__, __LINE__, ##args); \ +#define aml_v4l2_debug(level, fmt, args...) \ + do { \ + if (aml_v4l2_dbg_level >= level) \ + pr_info(fmt "\n", ##args); \ } while (0) #define aml_v4l2_debug_enter() aml_v4l2_debug(3, "+") @@ -36,8 +35,8 @@ extern bool aml_vcodec_dbg; #define aml_vcodec_debug(h, fmt, args...) \ do { \ if (aml_vcodec_dbg) \ - pr_info("[AML_VCODEC][%d]: %s() " fmt "\n", \ - ((struct aml_vcodec_ctx *)h->ctx)->id, \ + pr_info("[%d]: %s() " fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, \ __func__, ##args); \ } while (0) @@ -56,13 +55,12 @@ extern bool aml_vcodec_dbg; #endif -#define aml_v4l2_err(fmt, args...) \ - pr_err("[AML_V4L2][ERROR] %s:%d: " fmt "\n", __func__, __LINE__, \ - ##args) +#define aml_v4l2_err(fmt, args...) \ + pr_err("[ERR]" fmt "\n", ##args) #define aml_vcodec_err(h, fmt, args...) \ - pr_err("[AML_VCODEC][ERROR][%d]: %s() " fmt "\n", \ - ((struct aml_vcodec_ctx *)h->ctx)->id, __func__, ##args) + pr_err("[ERR][%d]" fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, ##args) void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, unsigned int reg_idx); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c index 0ee4be4d3f75..307b18fc21da 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c @@ -1,6 +1,7 @@ #include "aml_vcodec_vfm.h" #include "aml_vcodec_vfq.h" #include "aml_vcodec_util.h" +#include "aml_vcodec_adapt.h" #include #define RECEIVER_NAME "v4l2-video" @@ -50,16 +51,16 @@ static int vdec_vf_states(struct vframe_states *states, void *op_arg) return 0; } -void video_vf_put(struct vdec_fb *fb) +void video_vf_put(char *receiver, struct vdec_fb *fb, int id) { - struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME); + struct vframe_provider_s *vfp = vf_get_provider(receiver); struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; - aml_v4l2_debug(4, "%s() [%d], vfp: %p, vf: %p, cnt: %d\n", - __FUNCTION__, __LINE__, vfp, vf, atomic_read(&vf->use_cnt)); + aml_v4l2_debug(2, "[%d] TO (%s) vf: %p, idx: %d", + id, vfp->name, vf, vf->index); if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) - vf_put(vf, RECEIVER_NAME); + vf_put(vf, receiver); } static const struct vframe_operations_s vf_provider = { @@ -76,26 +77,23 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) struct vframe_states states; struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data; - aml_v4l2_debug(4, "%s() [%d], type: %d, vfm: %p\n", - __FUNCTION__, __LINE__, type, vfm); + //aml_v4l2_debug(4, "[%d] type: %d, vfm: %p", vfm->ctx->id, type, vfm); switch (type) { case VFRAME_EVENT_PROVIDER_UNREG: { if (vf_get_receiver(vfm->prov_name)) { - aml_v4l2_debug(4, "%s() [%d] unreg %s provider.\n", - __FUNCTION__, __LINE__, vfm->prov_name); + aml_v4l2_debug(4, "[%d] unreg %s provider.", + vfm->ctx->id, vfm->prov_name); vf_unreg_provider(&vfm->vf_prov); } - vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]); - break; } case VFRAME_EVENT_PROVIDER_START: { if (vf_get_receiver(vfm->prov_name)) { - aml_v4l2_debug(4, "%s() [%d] reg %s provider.\n", - __FUNCTION__, __LINE__, vfm->prov_name); + aml_v4l2_debug(4, "[%d] reg %s provider.", + vfm->ctx->id, vfm->prov_name); vf_provider_init(&vfm->vf_prov, vfm->prov_name, &vf_provider, vfm); vf_reg_provider(&vfm->vf_prov); @@ -126,6 +124,11 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) if (!vfm->vf) ret = -1; + if (ret < 0) { + pr_err("[%d] receiver vf err.\n", vfm->ctx->id); + break; + } + vfq_push(&vfm->vf_que, vfm->vf); /*vf_notify_receiver(vfm->prov_name, @@ -133,14 +136,15 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) /* schedule capture work. */ vdec_device_vf_run(vfm->ctx); - aml_v4l2_debug(1, "%s() [%d] VFRAME_EVENT_PROVIDER_VFRAME_READY.\n", - __FUNCTION__, __LINE__); + aml_v4l2_debug(2, "[%d] FROM (%s) vf: %p, idx: %d", + vfm->ctx->id, vf_get_provider(vfm->recv_name)->name, + vfm->vf, vfm->vf->index); break; } default: - aml_v4l2_debug(4, "the vf event is %d .", type); + aml_v4l2_debug(4, "[%d] the vf event is %d", vfm->ctx->id, type); } return ret; @@ -162,8 +166,12 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm) int vcodec_vfm_init(struct vcodec_vfm_s *vfm) { - memcpy(vfm->recv_name, RECEIVER_NAME, sizeof(RECEIVER_NAME)); - memcpy(vfm->prov_name, PROVIDER_NAME, sizeof(PROVIDER_NAME)); + snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d", + RECEIVER_NAME, vfm->ctx->id); + snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d", + PROVIDER_NAME, vfm->ctx->id); + + 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); @@ -174,6 +182,5 @@ int vcodec_vfm_init(struct vcodec_vfm_s *vfm) void vcodec_vfm_release(struct vcodec_vfm_s *vfm) { vf_unreg_receiver(&vfm->vf_recv); - vf_unreg_provider(&vfm->vf_prov); } diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h index a47916c36aea..268e8eb07cc5 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h @@ -8,10 +8,11 @@ #include #define VF_NAME_SIZE (32) -#define POOL_SIZE (16) +#define POOL_SIZE (64) struct vcodec_vfm_s { struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt *ada_ctx; struct vfq_s vf_que; struct vframe_s *vf; struct vframe_s *pool[POOL_SIZE + 1]; @@ -32,6 +33,6 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm); int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb); int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb); -void video_vf_put(struct vdec_fb *fb); +void video_vf_put(char *receiver, struct vdec_fb *fb, int id); #endif /* __AML_VCODEC_VFM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c index fbda1f298715..2e414f2b2770 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c @@ -12,6 +12,7 @@ #include "../aml_vcodec_vfm.h" #include "h264_stream.h" #include "h264_parse.h" +#include /* h264 NALU type */ #define NAL_NON_IDR_SLICE 0x01 @@ -32,6 +33,8 @@ #define H264_MAX_FB_NUM 17 #define HDR_PARSING_BUF_SZ 1024 +#define HEADER_BUFFER_SIZE (32 * 1024) + /** * struct h264_fb - h264 decode frame buffer information * @vdec_fb_va : virtual address of struct vdec_fb @@ -104,6 +107,7 @@ struct vdec_h264_dec_info { */ struct vdec_h264_vsi { unsigned char hdr_buf[HDR_PARSING_BUF_SZ]; + char *header_buf; int sps_size; int pps_size; int sei_size; @@ -137,8 +141,6 @@ struct vdec_h264_inst { struct vcodec_vfm_s vfm; }; -static DEFINE_MUTEX(mutex); - #define DUMP_FILE_NAME "/data/dump/dump.tmp" static struct file *filp; static loff_t file_pos; @@ -177,13 +179,25 @@ void dump_deinit(void) } } +void swap_uv(void *uv, int size) +{ + int i; + __u16 *p = uv; + + size /= 2; + + for (i = 0; i < size; i++, p++) + *p = __swab16(*p); +} + static void get_pic_info(struct vdec_h264_inst *inst, struct vdec_pic_info *pic) { *pic = inst->vsi->pic; aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", - pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h); + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); } @@ -220,7 +234,7 @@ static int find_start_code(unsigned char *data, unsigned int data_sz) static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) { struct vdec_h264_inst *inst = NULL; - int err = -1; + int ret = -1; inst = kzalloc(sizeof(*inst), GFP_KERNEL); if (!inst) @@ -228,56 +242,60 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->ctx = ctx; - inst->vdec.id = VFORMAT_H264; + inst->vdec.format = VFORMAT_H264; inst->vdec.dev = ctx->dev->vpu_plat_dev; inst->vdec.filp = ctx->dev->filp; inst->vdec.ctx = ctx; inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; vcodec_vfm_init(&inst->vfm); - //inst->vpu.handler = vpu_dec_ipi_handler; - - err = video_decoder_init(&inst->vdec); - if (err) { - aml_vcodec_err(inst, "vdec_h264 init err=%d", err); - //goto error_free_inst; + ret = video_decoder_init(&inst->vdec); + if (ret) { + aml_vcodec_err(inst, "vdec_h264 init err=%d", ret); + goto error_free_inst; } - //inst->vsi = (struct vdec_h264_vsi *)inst->vpu.vsi; - - //probe info from the decoder hw debug_tmp + /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_inst; + } - //debug_tmp - inst->vsi->pic.pic_w = 1920; - inst->vsi->pic.pic_h = 1088; - inst->vsi->pic.buf_w = 1920; - inst->vsi->pic.buf_h = 1088; + /* 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; + } + + inst->vsi->pic.visible_width = 1920; + inst->vsi->pic.visible_height = 1080; + inst->vsi->pic.coded_width = 1920; + inst->vsi->pic.coded_height = 1088; inst->vsi->pic.y_bs_sz = 0; inst->vsi->pic.y_len_sz = (1920 * 1088); inst->vsi->pic.c_bs_sz = 0; inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); - //err = allocate_predication_buf(inst); - //if (err) - //goto error_deinit; - aml_vcodec_debug(inst, "H264 Instance >> %p", inst); + ctx->ada_ctx = &inst->vdec; *h_vdec = (unsigned long)inst; dump_init(); return 0; -//error_deinit: - //vpu_dec_deinit(&inst->vpu); - -//error_free_inst: - /*kfree(inst->vsi); +error_free_vsi: + kfree(inst->vsi); +error_free_inst: kfree(inst); - return err;*/ + *h_vdec = 0; + + return ret; } static int refer_buffer_num(int level_idc, int poc_cnt, @@ -352,11 +370,11 @@ static int refer_buffer_num(int level_idc, int poc_cnt, return size; } -static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi) +static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps) { - struct vdec_pic_info *pic = &vsi->pic; - struct vdec_h264_dec_info *dec = &vsi->dec; - struct v4l2_rect *rect = &vsi->crop; + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_h264_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; unsigned int mb_w, mb_h, width, height; unsigned int crop_unit_x = 0, crop_unit_y = 0; unsigned int poc_cnt = 0; @@ -388,21 +406,21 @@ static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi) height -= crop_unit_y * (sps->frame_crop_top_offset + sps->frame_crop_bottom_offset); - /* fill image size that be used for EGL. */ - pic->pic_w = width; - pic->pic_h = height; + /* fill visible area size that be used for EGL. */ + pic->visible_width = width; + pic->visible_height = height; /* calc visible ares. */ - rect->left = 0; - rect->top = 0; - rect->width = pic->pic_w; - rect->height = pic->pic_h; + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->buf_w = ALIGN(mb_w, 4) << 4; - pic->buf_h = ALIGN(mb_h, 4) << 4; - pic->y_len_sz = pic->buf_w * pic->buf_h; - pic->c_len_sz = pic->y_len_sz >> 1; + pic->coded_width = ALIGN(mb_w, 4) << 4; + 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; /* calc DPB size */ poc_cnt = sps->pic_order_cnt_type; @@ -411,8 +429,9 @@ static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi) dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); - pr_info("the stream infos, width: %d, height: %d, dpb: %d\n", - pic->pic_w, pic->pic_h, dec->dpb_sz); + pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", + inst->ctx->id, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, dec->dpb_sz); } static int vdec_h264_probe(unsigned long h_vdec, @@ -448,7 +467,7 @@ static int vdec_h264_probe(unsigned long h_vdec, h264_sps_parse(&s, sps); //h264_sps_info(sps); - fill_vdec_params(sps, inst->vsi); + fill_vdec_params(inst, sps); kfree(sps); @@ -459,7 +478,8 @@ static void vdec_h264_deinit(unsigned long h_vdec) { struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - mutex_lock(&mutex); + if (!inst) + return; aml_vcodec_debug_enter(inst); @@ -469,11 +489,13 @@ static void vdec_h264_deinit(unsigned long h_vdec) dump_deinit(); - kfree(inst->vsi); - kfree(inst); - inst = NULL; + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); - mutex_unlock(&mutex); + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); } static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out) @@ -486,27 +508,27 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) struct vframe_s *vf = NULL; struct vdec_fb *fb = NULL; - aml_vcodec_debug(inst, "%s() [%d], vfm: %p\n", - __FUNCTION__, __LINE__, &inst->vfm); + aml_vcodec_debug(inst, "%s() [%d], vfm: %p", + __func__, __LINE__, &inst->vfm); vf = peek_video_frame(&inst->vfm); if (!vf) { - aml_vcodec_debug(inst, "there is no vframe.\n"); + aml_vcodec_debug(inst, "there is no vframe."); *out = NULL; return; } vf = get_video_frame(&inst->vfm); if (!vf) { - aml_vcodec_debug(inst, "the vframe is avalid.\n"); + aml_vcodec_debug(inst, "the vframe is avalid."); *out = NULL; return; } atomic_set(&vf->use_cnt, 1); - aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx\n", - __FUNCTION__, __LINE__, vf, vf->v4l_mem_handle); + aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", + __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); fb = (struct vdec_fb *)vf->v4l_mem_handle; fb->vf_handle = (unsigned long)vf; @@ -514,14 +536,18 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) *out = fb; + //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); //dump_write(fb->base_y.va, fb->base_y.bytes_used); //dump_write(fb->base_c.va, fb->base_c.bytes_used); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu\n", - __FUNCTION__, __LINE__, fb->base_y.va, + /* convert yuv format. */ + //swap_uv(fb->base_c.va, fb->base_c.size); + + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %lu", + __func__, __LINE__, fb->base_y.va, (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu\n", - __FUNCTION__, __LINE__, fb->base_c.va, + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %lu", + __func__, __LINE__, fb->base_c.va, (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); } @@ -550,47 +576,46 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, nal_start = buf[nal_start_idx]; nal_type = NAL_TYPE(buf[nal_start_idx]); - aml_v4l2_debug(1, "NALU type: %d, size: %u\n", nal_type, buf_sz); + aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, buf_sz); if (nal_type == NAL_H264_SPS) { - if (buf_sz > HDR_PARSING_BUF_SZ) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { err = -EILSEQ; goto err_free_fb_out; } inst->vsi->sps_size = buf_sz; - memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz); + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); inst->vsi->head_offset += inst->vsi->sps_size; } else if (nal_type == NAL_H264_PPS) { //buf_sz -= nal_start_idx; - if (buf_sz > HDR_PARSING_BUF_SZ) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { err = -EILSEQ; goto err_free_fb_out; } inst->vsi->pps_size = buf_sz; - memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz); + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); inst->vsi->head_offset += inst->vsi->pps_size; } else if (nal_type == NAL_H264_SEI) { - if (buf_sz > HDR_PARSING_BUF_SZ) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { err = -EILSEQ; goto err_free_fb_out; } inst->vsi->sei_size = buf_sz; - memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz); + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); inst->vsi->head_offset += inst->vsi->sei_size; } else { char *write_buf = vmalloc(inst->vsi->head_offset + buf_sz); - memcpy(write_buf, inst->vsi->hdr_buf, inst->vsi->head_offset); + memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset); memcpy(write_buf + inst->vsi->head_offset, buf, buf_sz); - ret = vdec_vframe_write(vdec->filp, write_buf, + ret = vdec_vframe_write(vdec, write_buf, inst->vsi->head_offset + buf_sz, timestamp); - aml_vcodec_debug(inst, - "%s() [%d], buf: %p, buf size: %u, write to: %d\n", - __FUNCTION__, __LINE__, write_buf, - inst->vsi->head_offset + buf_sz, ret); + aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", + write_buf, inst->vsi->head_offset + buf_sz, ret); + memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE); inst->vsi->head_offset = 0; inst->vsi->sps_size = 0; inst->vsi->pps_size = 0; @@ -626,14 +651,12 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, //vpu_dec_end(vpu); } - - aml_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu, - nal_type); return ret; err_free_fb_out: //put_fb_to_free(inst, fb); - aml_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err); + aml_vcodec_err(inst, "NALU[%d] err=%d", inst->num_nalu, err); + return err; } @@ -643,17 +666,13 @@ static int vdec_h264_get_param(unsigned long h_vdec, int ret = 0; struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - mutex_lock(&mutex); - if (!inst) { - pr_err("the h264 inst of dec is void.\n"); - mutex_unlock(&mutex); + pr_err("the h264 inst of dec is void."); return -1; } switch (type) { case GET_PARAM_DISP_FRAME_BUFFER: - //vdec_h264_get_fb(inst, &inst->vsi->list_disp, true, out); vdec_h264_get_vf(inst, out); break; @@ -675,11 +694,9 @@ static int vdec_h264_get_param(unsigned long h_vdec, default: aml_vcodec_err(inst, "invalid get parameter type=%d", type); - return -EINVAL; + ret = -EINVAL; } - mutex_unlock(&mutex); - return ret; } diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c index d6ccb63331a3..2b05dc66084f 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c @@ -74,17 +74,17 @@ int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, if (ctx->drv_handle == 0) return -EIO; - aml_vdec_lock(ctx); + //aml_vdec_lock(ctx); aml_vcodec_set_curr_ctx(ctx->dev, ctx); //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp - enable_irq(ctx->dev->dec_irq); + //enable_irq(ctx->dev->dec_irq); ret = ctx->dec_if->decode(ctx->drv_handle, bs, timestamp, res_chg); //disable_irq(ctx->dev->dec_irq); //aml_vcodec_dec_clock_off(&ctx->dev->pm); aml_vcodec_set_curr_ctx(ctx->dev, NULL); - aml_vdec_unlock(ctx); + //aml_vdec_unlock(ctx); return ret; } @@ -97,9 +97,9 @@ int vdec_if_get_param(struct aml_vcodec_ctx *ctx, if (ctx->drv_handle == 0) return -EIO; - aml_vdec_lock(ctx); + //aml_vdec_lock(ctx); ret = ctx->dec_if->get_param(ctx->drv_handle, type, out); - aml_vdec_unlock(ctx); + //aml_vdec_unlock(ctx); return ret; } @@ -109,11 +109,11 @@ void vdec_if_deinit(struct aml_vcodec_ctx *ctx) if (ctx->drv_handle == 0) return; - aml_vdec_lock(ctx); + //aml_vdec_lock(ctx); //aml_vcodec_dec_clock_on(&ctx->dev->pm); ctx->dec_if->deinit(ctx->drv_handle); //aml_vcodec_dec_clock_off(&ctx->dev->pm); - aml_vdec_unlock(ctx); + //aml_vdec_unlock(ctx); ctx->drv_handle = 0; } diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h index 025e2cb5d29a..7e7f0e1cfb08 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h @@ -13,9 +13,9 @@ * @FB_ST_FREE : frame buffer is not used by decoder any more */ enum vdec_fb_status { - FB_ST_NORMAL = 0, - FB_ST_DISPLAY = (1 << 0), - FB_ST_FREE = (1 << 1) + FB_ST_NORMAL, + FB_ST_DISPLAY, + FB_ST_FREE }; /* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER, diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c index d77c19d61e97..5c918125d2a4 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c @@ -1609,16 +1609,13 @@ static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) { int ret = 0; + struct aml_vcodec_ctx *ctx = NULL; struct buffer_spec_s *bs = &hw->buffer_spec[idx]; struct canvas_config_s *y_canvas_cfg = NULL; struct canvas_config_s *c_canvas_cfg = NULL; struct vdec_fb *fb = NULL; unsigned int y_addr, c_addr; - int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], buf size: %d\n", __FUNCTION__, __LINE__, buf_size); - if (IS_ERR_OR_NULL(hw->v4l2_ctx)) { pr_err("the v4l context has err.\n"); return -1; @@ -1627,26 +1624,31 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) if (bs->cma_alloc_addr) return 0; + ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), buf size: %d\n", ctx->id, __func__, + (hw->mb_total << 8) + (hw->mb_total << 7)); + ret = v4l_get_fb(hw->v4l2_ctx, &fb); if (ret) { - pr_err("get fb fail.\n"); + pr_err("[%d] get fb fail.\n", ctx->id); return ret; } bs->cma_alloc_addr = (unsigned long)fb; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], cma alloc addr: 0x%x\n", - __FUNCTION__, __LINE__, bs->cma_alloc_addr); + "[%d] %s(), cma alloc addr: 0x%x\n", + ctx->id, __func__, bs->cma_alloc_addr); y_addr = virt_to_phys(fb->base_y.va); c_addr = virt_to_phys(fb->base_c.va); dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], y_addr: %x, va: %p\n", - __FUNCTION__, __LINE__, y_addr, fb->base_y.va); + "[%d] %s(), y_addr: %x, va: %p\n", + ctx->id, __func__, y_addr, fb->base_y.va); dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], c_addr: %x, va: %p\n", - __FUNCTION__, __LINE__, c_addr, fb->base_c.va); + "[%d] %s(), c_addr: %x, va: %p\n", + ctx->id, __func__, c_addr, fb->base_c.va); bs->y_addr = y_addr; bs->u_addr = c_addr; @@ -1661,7 +1663,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; fb->base_y.bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], y_w: %d, y_h: %d\n", __FUNCTION__, __LINE__, + "[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__, y_canvas_cfg->width,y_canvas_cfg->height); c_canvas_cfg->phy_addr = c_addr; @@ -1670,11 +1672,11 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; fb->base_c.bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], c_w: %d, c_h: %d\n", __FUNCTION__, __LINE__, + "[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__, c_canvas_cfg->width, c_canvas_cfg->height); dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s, alloc buf for bufspec%d\n", __FUNCTION__, idx); + "[%d] %s(), alloc buf for bufspec%d\n", ctx->id, __func__, idx); return ret; } @@ -2140,8 +2142,9 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) vf->v4l_mem_handle = hw->buffer_spec[buffer_index].cma_alloc_addr; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], v4l mem handle: 0x%x\n", - __FUNCTION__, __LINE__, vf->v4l_mem_handle); + "[%d] %s(), v4l mem handle: 0x%x\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, + __func__, vf->v4l_mem_handle); } if (hw->mmu_enable) { @@ -2258,6 +2261,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) 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 vdec_fb *fb = NULL; @@ -2270,7 +2274,7 @@ int notify_v4l_eos(struct vdec_s *vdec) } if (v4l_get_fb(hw->v4l2_ctx, &fb)) { - pr_err("get fb fail.\n"); + pr_err("[%d] get fb fail.\n", ctx->id); return -1; } @@ -2279,9 +2283,10 @@ int notify_v4l_eos(struct vdec_s *vdec) vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - pr_info("264 EOS notify \n"); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + pr_info("[%d] H264 EOS notify.\n", ctx->id); } return 0; @@ -3604,7 +3609,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, (unsigned int)((8 << chroma444) - 1)); } dpb_print(DECODE_ID(hw), 0, - "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d, ", + "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d,\n", frame_mbs_only_flag, crop_bottom, hw->frame_height); dpb_print(DECODE_ID(hw), 0, "mb_height %d,crop_right %d, frame_width %d, mb_width %d\n", @@ -3755,12 +3760,13 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, for (j = 1; j < buf_cnt; j++) { i = get_buf_spec_by_canvas_pos(hw, j); - if (hw->is_used_v4l && - alloc_one_buf_spec_from_queue + if (hw->is_used_v4l) { + if (alloc_one_buf_spec_from_queue (hw, i) < 0) { - if (j++ != buf_cnt) - ret = -1; - break; + if (j++ != buf_cnt) + ret = -1; + break; + } } else if (alloc_one_buf_spec(hw, i) < 0) break; @@ -3974,9 +3980,12 @@ static void vui_config(struct vdec_h264_hw_s *hw) static void bufmgr_recover(struct vdec_h264_hw_s *hw) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2); - if (error_proc_policy & 0x20) - hw->reset_bufmgr_flag = 1; + if (error_proc_policy & 0x20) { + if (!hw->is_used_v4l) + hw->reset_bufmgr_flag = 1; + } } void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb) @@ -5207,6 +5216,10 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); #endif + /* cbcr_merge_swap_en */ + if (hw->is_used_v4l) + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c index 3369043927b1..4838a6fa1796 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c @@ -1581,7 +1581,8 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) "vdec-map-%d", vdec->id); } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) { snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, "v4l2-video"); + "%s %s", vdec->vf_provider_name, + vdec->vf_receiver_name); snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); } @@ -2442,6 +2443,7 @@ void vdec_poweron(enum vdec_type_e core) * m8baby and m8m2 can dynamic adjust vdec clock, * power on with default clock level */ + amports_switch_gate("clk_vdec_mux", 1); vdec_clock_hi_enable(); /* power up vdec memories */ WRITE_VREG(DOS_MEM_PD_VDEC, 0); @@ -2519,6 +2521,9 @@ void vdec_poweron(enum vdec_type_e core) WRITE_VREG(DOS_SW_RESET3, 0xffffffff); WRITE_VREG(DOS_SW_RESET3, 0); /* enable hevc clock */ + amports_switch_gate("clk_hevc_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + amports_switch_gate("clk_hevcb_mux", 1); hevc_clock_hi_enable(); hevc_back_clock_hi_enable(); /* power up hevc memories */ diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream.c b/drivers/amlogic/media_modules/stream_input/amports/amstream.c index 730d24a005ef..a7927009c6d3 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/amstream.c +++ b/drivers/amlogic/media_modules/stream_input/amports/amstream.c @@ -612,10 +612,6 @@ static int video_port_init(struct port_priv_s *priv, pbuf->for_4k = 1; if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX && port->vformat == VFORMAT_H264) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); - vdec_poweron(VDEC_HEVC); } } else { @@ -1620,22 +1616,14 @@ static int amstream_open(struct inode *inode, struct file *file) if (has_hevc_vdec()) { if (port->type & - (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); + (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) vdec_poweron(VDEC_HEVC); - } - if ((port->type & PORT_TYPE_HEVC) == 0) { - amports_switch_gate("clk_vdec_mux", 1); + if ((port->type & PORT_TYPE_HEVC) == 0) vdec_poweron(VDEC_1); - } } else { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - amports_switch_gate("clk_vdec_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) vdec_poweron(VDEC_1); - } } }