author | Nanxin Qin <nanxin.qin@amlogic.com> | 2020-04-05 04:34:04 (GMT) |
---|---|---|
committer | Nanxin Qin <nanxin.qin@amlogic.com> | 2020-08-03 08:25:07 (GMT) |
commit | 9b8c972a3daa492a462bb166aef3ae3928fa82d4 (patch) | |
tree | 5a0a3624b76708607dbe52f6f2b259647910eb1f | |
parent | 0f7b4bb4ec8d7083401fe6e97cf79db9c16efbfa (diff) | |
download | media_modules-9b8c972a3daa492a462bb166aef3ae3928fa82d4.zip media_modules-9b8c972a3daa492a462bb166aef3ae3928fa82d4.tar.gz media_modules-9b8c972a3daa492a462bb166aef3ae3928fa82d4.tar.bz2 |
v4l: supports playback of av1 with v4l codec. [1/1]
PD#SWPL-23548
Problem:
add a new format AV1 for v4l codec.
Solution:
supports playback of av1 with v4l codec.
Verify:
verified with android Q on sc2.
Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
Change-Id: Ic59e739dc75ed6f23f033115e918dd3ed5bbed89
-rw-r--r-- | drivers/amvdec_ports/Makefile | 1 | ||||
-rw-r--r-- | drivers/amvdec_ports/aml_vcodec_adapt.c | 8 | ||||
-rw-r--r-- | drivers/amvdec_ports/aml_vcodec_dec.c | 7 | ||||
-rw-r--r-- | drivers/amvdec_ports/aml_vcodec_dec_drv.c | 4 | ||||
-rw-r--r-- | drivers/amvdec_ports/decoder/vdec_av1_if.c | 1320 | ||||
-rw-r--r-- | drivers/amvdec_ports/vdec_drv_if.c | 4 | ||||
-rw-r--r-- | drivers/frame_provider/decoder/vav1/av1_bufmgr.c | 109 | ||||
-rw-r--r-- | drivers/frame_provider/decoder/vav1/av1_global.h | 10 | ||||
-rw-r--r-- | drivers/frame_provider/decoder/vav1/vav1.c | 1317 |
9 files changed, 2432 insertions, 348 deletions
diff --git a/drivers/amvdec_ports/Makefile b/drivers/amvdec_ports/Makefile index d5f2341..6395adf 100644 --- a/drivers/amvdec_ports/Makefile +++ b/drivers/amvdec_ports/Makefile @@ -11,6 +11,7 @@ amvdec_ports-objs += decoder/vdec_vp9_if.o amvdec_ports-objs += decoder/vdec_mpeg12_if.o amvdec_ports-objs += decoder/vdec_mpeg4_if.o amvdec_ports-objs += decoder/vdec_mjpeg_if.o +amvdec_ports-objs += decoder/vdec_av1_if.o ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER amvdec_ports-objs += decoder/aml_h264_parser.o amvdec_ports-objs += decoder/aml_hevc_parser.o diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c index 67a29bb..94f1f0e 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amvdec_ports/aml_vcodec_adapt.c @@ -682,8 +682,8 @@ int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, dump_write(buf, count); #endif v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT, - "write frames, vbuf: %p, size: %u, ret: %d, crc: %x\n", - buf, count, ret, crc32_le(0, buf, count)); + "write frames, vbuf: %p, size: %u, ret: %d, crc: %x, ts: %llu\n", + buf, count, ret, crc32_le(0, buf, count), timestamp); return ret; } @@ -706,8 +706,8 @@ int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx, } v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT, - "write frames, vbuf: %lx, size: %u, ret: %d\n", - addr, count, ret); + "write frames, vbuf: %lx, size: %u, ret: %d, ts: %llu\n", + addr, count, ret, timestamp); return ret; } diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c index b0c2721..99406bc 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amvdec_ports/aml_vcodec_dec.c @@ -97,6 +97,11 @@ static struct aml_video_fmt aml_video_formats[] = { .num_planes = 1, }, { + .fourcc = V4L2_PIX_FMT_AV1, + .type = AML_FMT_DEC, + .num_planes = 1, + }, + { .fourcc = V4L2_PIX_FMT_NV21, .type = AML_FMT_FRAME, .num_planes = 1, @@ -516,7 +521,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; v4l_dbg(ctx, V4L_DEBUG_CODEC_OUTPUT, - "FROM (%s %s) vf: %lx, ts: %llx, idx: %d, " + "FROM (%s %s) vf: %lx, ts: %llu, idx: %d, " "Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)\n", vf_get_provider(ctx->ada_ctx->recv_name)->name, ctx->ada_ctx->vfm_path != FRAME_BASE_PATH_V4L_VIDEO ? "OSD" : "VIDEO", diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c index 7758ca8..1a975c2 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c +++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c @@ -608,6 +608,10 @@ int vp9_need_prefix; EXPORT_SYMBOL(vp9_need_prefix); module_param(vp9_need_prefix, int, 0644); +int av1_need_prefix; +EXPORT_SYMBOL(av1_need_prefix); +module_param(av1_need_prefix, int, 0644); + bool multiplanar; EXPORT_SYMBOL(multiplanar); module_param(multiplanar, bool, 0644); diff --git a/drivers/amvdec_ports/decoder/vdec_av1_if.c b/drivers/amvdec_ports/decoder/vdec_av1_if.c new file mode 100644 index 0000000..ca5e6ae --- a/dev/null +++ b/drivers/amvdec_ports/decoder/vdec_av1_if.c @@ -0,0 +1,1320 @@ +/* +* Copyright (C) 2017 Amlogic, Inc. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <uapi/linux/swab.h> +#include "../vdec_drv_if.h" +#include "../aml_vcodec_util.h" +#include "../aml_vcodec_dec.h" +#include "../aml_vcodec_drv.h" +#include "../aml_vcodec_adapt.h" +#include "../vdec_drv_base.h" +#include "../aml_vcodec_vfm.h" +#include "../utils/common.h" + +#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2 +#include <trace/events/meson_atrace.h> + +#define PREFIX_SIZE (16) + +#define HEADER_BUFFER_SIZE (32 * 1024) +#define SYNC_CODE (0x498342) + +extern int av1_need_prefix; + +/** + * struct av1_fb - av1 decode frame buffer information + * @vdec_fb_va : virtual address of struct vdec_fb + * @y_fb_dma : dma address of Y frame buffer (luma) + * @c_fb_dma : dma address of C frame buffer (chroma) + * @poc : picture order count of frame buffer + * @reserved : for 8 bytes alignment + */ +struct av1_fb { + uint64_t vdec_fb_va; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + int32_t poc; + uint32_t reserved; +}; + +/** + * struct vdec_av1_dec_info - decode information + * @dpb_sz : decoding picture buffer size + * @resolution_changed : resoltion change happen + * @reserved : for 8 bytes alignment + * @bs_dma : Input bit-stream buffer dma address + * @y_fb_dma : Y frame buffer dma address + * @c_fb_dma : C frame buffer dma address + * @vdec_fb_va : VDEC frame buffer struct virtual address + */ +struct vdec_av1_dec_info { + uint32_t dpb_sz; + uint32_t resolution_changed; + uint32_t reserved; + uint64_t bs_dma; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + uint64_t vdec_fb_va; +}; + +/** + * struct vdec_av1_vsi - shared memory for decode information exchange + * between VPU and Host. + * The memory is allocated by VPU then mapping to Host + * in vpu_dec_init() and freed in vpu_dec_deinit() + * by VPU. + * AP-W/R : AP is writer/reader on this item + * VPU-W/R: VPU is write/reader on this item + * @hdr_buf : Header parsing buffer (AP-W, VPU-R) + * @list_free : free frame buffer ring list (AP-W/R, VPU-W) + * @list_disp : display frame buffer ring list (AP-R, VPU-W) + * @dec : decode information (AP-R, VPU-W) + * @pic : picture information (AP-R, VPU-W) + * @crop : crop information (AP-R, VPU-W) + */ +struct vdec_av1_vsi { + char *header_buf; + int sps_size; + int pps_size; + int sei_size; + int head_offset; + struct vdec_av1_dec_info dec; + struct vdec_pic_info pic; + struct vdec_pic_info cur_pic; + struct v4l2_rect crop; + bool is_combine; + int nalu_pos; +}; + +/** + * struct vdec_av1_inst - av1 decoder instance + * @num_nalu : how many nalus be decoded + * @ctx : point to aml_vcodec_ctx + * @vsi : VPU shared information + */ +struct vdec_av1_inst { + unsigned int num_nalu; + struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt vdec; + struct vdec_av1_vsi *vsi; + struct vcodec_vfm_s vfm; + struct aml_dec_params parms; + struct completion comp; +}; + +/*!\brief OBU types. */ +enum OBU_TYPE { + OBU_SEQUENCE_HEADER = 1, + OBU_TEMPORAL_DELIMITER = 2, + OBU_FRAME_HEADER = 3, + OBU_TILE_GROUP = 4, + OBU_METADATA = 5, + OBU_FRAME = 6, + OBU_REDUNDANT_FRAME_HEADER = 7, + OBU_TILE_LIST = 8, + OBU_PADDING = 15, +}; + +/*!\brief OBU metadata types. */ +enum OBU_METADATA_TYPE { + OBU_METADATA_TYPE_RESERVED_0 = 0, + OBU_METADATA_TYPE_HDR_CLL = 1, + OBU_METADATA_TYPE_HDR_MDCV = 2, + OBU_METADATA_TYPE_SCALABILITY = 3, + OBU_METADATA_TYPE_ITUT_T35 = 4, + OBU_METADATA_TYPE_TIMECODE = 5, +}; + +struct ObuHeader { + size_t size; // Size (1 or 2 bytes) of the OBU header (including the + // optional OBU extension header) in the bitstream. + enum OBU_TYPE type; + int has_size_field; + int has_extension; + // The following fields come from the OBU extension header and therefore are + // only used if has_extension is true. + int temporal_layer_id; + int spatial_layer_id; +}; + +static const size_t kMaximumLeb128Size = 8; +static const u8 kLeb128ByteMask = 0x7f; // Binary: 01111111 + +// Disallow values larger than 32-bits to ensure consistent behavior on 32 and +// 64 bit targets: value is typically used to determine buffer allocation size +// when decoded. +static const u64 kMaximumLeb128Value = ULONG_MAX; + +char obu_type_name[16][32] = { + "UNKNOWN", + "OBU_SEQUENCE_HEADER", + "OBU_TEMPORAL_DELIMITER", + "OBU_FRAME_HEADER", + "OBU_TILE_GROUP", + "OBU_METADATA", + "OBU_FRAME", + "OBU_REDUNDANT_FRAME_HEADER", + "OBU_TILE_LIST", + "UNKNOWN", + "UNKNOWN", + "UNKNOWN", + "UNKNOWN", + "UNKNOWN", + "UNKNOWN", + "OBU_PADDING" +}; + +char meta_type_name[6][32] = { + "OBU_METADATA_TYPE_RESERVED_0", + "OBU_METADATA_TYPE_HDR_CLL", + "OBU_METADATA_TYPE_HDR_MDCV", + "OBU_METADATA_TYPE_SCALABILITY", + "OBU_METADATA_TYPE_ITUT_T35", + "OBU_METADATA_TYPE_TIMECODE" +}; + +struct read_bit_buffer { + const u8 *bit_buffer; + const u8 *bit_buffer_end; + u32 bit_offset; +}; + +struct DataBuffer { + const u8 *data; + size_t size; +}; + +static int vdec_write_nalu(struct vdec_av1_inst *inst, + u8 *buf, u32 size, u64 ts); + +static void get_pic_info(struct vdec_av1_inst *inst, + struct vdec_pic_info *pic) +{ + *pic = inst->vsi->pic; + + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, + "pic(%d, %d), buf(%d, %d)\n", + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, + "Y(%d, %d), C(%d, %d)\n", + pic->y_bs_sz, pic->y_len_sz, + pic->c_bs_sz, pic->c_len_sz); +} + +static void get_crop_info(struct vdec_av1_inst *inst, struct v4l2_rect *cr) +{ + cr->left = inst->vsi->crop.left; + cr->top = inst->vsi->crop.top; + cr->width = inst->vsi->crop.width; + cr->height = inst->vsi->crop.height; + + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, + "l=%d, t=%d, w=%d, h=%d\n", + cr->left, cr->top, cr->width, cr->height); +} + +static void get_dpb_size(struct vdec_av1_inst *inst, unsigned int *dpb_sz) +{ + *dpb_sz = inst->vsi->dec.dpb_sz; + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz); +} + +static u32 vdec_config_default_parms(u8 *parm) +{ + u8 *pbuf = parm; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:11;"); + pbuf += sprintf(pbuf, "av1_double_write_mode:3;"); + pbuf += sprintf(pbuf, "av1_buf_width:1920;"); + pbuf += sprintf(pbuf, "av1_buf_height:1088;"); + pbuf += sprintf(pbuf, "av1_max_pic_w:8192;"); + pbuf += sprintf(pbuf, "av1_max_pic_h:4608;"); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); + pbuf += sprintf(pbuf, "no_head:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;"); + + return parm - pbuf; +} + +static void vdec_parser_parms(struct vdec_av1_inst *inst) +{ + struct aml_vcodec_ctx *ctx = inst->ctx; + + if (ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_CFGINFO) { + u8 *pbuf = ctx->config.buf; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;", + ctx->config.parm.dec.cfg.ref_buf_margin); + pbuf += sprintf(pbuf, "av1_double_write_mode:%d;", + ctx->config.parm.dec.cfg.double_write_mode); + pbuf += sprintf(pbuf, "av1_buf_width:%d;", + ctx->config.parm.dec.cfg.init_width); + pbuf += sprintf(pbuf, "av1_buf_height:%d;", + ctx->config.parm.dec.cfg.init_height); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); + pbuf += sprintf(pbuf, "no_head:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;", + ctx->config.parm.dec.cfg.canvas_mem_mode); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;", + ctx->config.parm.dec.cfg.canvas_mem_endian); + ctx->config.length = pbuf - ctx->config.buf; + } else { + ctx->config.parm.dec.cfg.double_write_mode = 16; + ctx->config.parm.dec.cfg.ref_buf_margin = 7; + ctx->config.length = vdec_config_default_parms(ctx->config.buf); + } + + if ((ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO) && + inst->parms.hdr.color_parms.present_flag) { + u8 *pbuf = ctx->config.buf + ctx->config.length; + + pbuf += sprintf(pbuf, "mG.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[0][0]); + pbuf += sprintf(pbuf, "mG.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[0][1]); + pbuf += sprintf(pbuf, "mB.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[1][0]); + pbuf += sprintf(pbuf, "mB.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[1][1]); + pbuf += sprintf(pbuf, "mR.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[2][0]); + pbuf += sprintf(pbuf, "mR.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[2][1]); + pbuf += sprintf(pbuf, "mW.x:%d;", + ctx->config.parm.dec.hdr.color_parms.white_point[0]); + pbuf += sprintf(pbuf, "mW.y:%d;", + ctx->config.parm.dec.hdr.color_parms.white_point[1]); + pbuf += sprintf(pbuf, "mMaxDL:%d;", + ctx->config.parm.dec.hdr.color_parms.luminance[0] / 1000); + pbuf += sprintf(pbuf, "mMinDL:%d;", + ctx->config.parm.dec.hdr.color_parms.luminance[1]); + pbuf += sprintf(pbuf, "mMaxCLL:%d;", + ctx->config.parm.dec.hdr.color_parms.content_light_level.max_content); + pbuf += sprintf(pbuf, "mMaxFALL:%d;", + ctx->config.parm.dec.hdr.color_parms.content_light_level.max_pic_average); + ctx->config.length = pbuf - ctx->config.buf; + inst->parms.hdr = ctx->config.parm.dec.hdr; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_HDRINFO; + } + + inst->vdec.config = ctx->config; + inst->parms.cfg = ctx->config.parm.dec.cfg; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO; +} + +static int vdec_av1_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) +{ + struct vdec_av1_inst *inst = NULL; + int ret = -1; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->vdec.video_type = VFORMAT_AV1; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + inst->ctx = ctx; + + vdec_parser_parms(inst); + + /* set play mode.*/ + if (ctx->is_drm_mode) + inst->vdec.port.flag |= PORT_FLAG_DRM; + + /* to eable av1 hw.*/ + inst->vdec.port.type = PORT_TYPE_HEVC; + + /* init vfm */ + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + ret = vcodec_vfm_init(&inst->vfm); + if (ret) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "init vfm failed.\n"); + goto err; + } + + /* probe info from the stream */ + inst->vsi = kzalloc(sizeof(struct vdec_av1_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto err; + } + + /* alloc the header buffer to be used cache sps or spp etc.*/ + inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); + if (!inst->vsi->header_buf) { + ret = -ENOMEM; + goto err; + } + + init_completion(&inst->comp); + + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, + "av1 Instance >> %lx\n", (ulong) inst); + + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; + + /* init decoder. */ + ret = video_decoder_init(&inst->vdec); + if (ret) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "vdec_av1 init err=%d\n", ret); + goto err; + } + + //dump_init(); + + return 0; +err: + if (inst) + vcodec_vfm_release(&inst->vfm); + if (inst && inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + if (inst && inst->vsi) + kfree(inst->vsi); + if (inst) + kfree(inst); + *h_vdec = 0; + + return ret; +} + +static int parse_stream_ucode(struct vdec_av1_inst *inst, + u8 *buf, u32 size, u64 timestamp) +{ + int ret = 0; + + ret = vdec_write_nalu(inst, buf, size, timestamp); + if (ret < 0) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "write data failed. size: %d, err: %d\n", size, ret); + return ret; + } + + /* wait ucode parse ending. */ + wait_for_completion_timeout(&inst->comp, + msecs_to_jiffies(1000)); + + return inst->vsi->dec.dpb_sz ? 0 : -1; +} + +static int parse_stream_ucode_dma(struct vdec_av1_inst *inst, + ulong buf, u32 size, u64 timestamp, u32 handle) +{ + int ret = 0; + struct aml_vdec_adapt *vdec = &inst->vdec; + + ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle); + if (ret < 0) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "write frame data failed. err: %d\n", ret); + return ret; + } + + /* wait ucode parse ending. */ + wait_for_completion_timeout(&inst->comp, + msecs_to_jiffies(1000)); + + return inst->vsi->dec.dpb_sz ? 0 : -1; +} + +static int parse_stream_cpu(struct vdec_av1_inst *inst, u8 *buf, u32 size) +{ + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "can not suppport parse stream by cpu.\n"); + + return -1; +} + +static int vdec_av1_probe(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out) +{ + struct vdec_av1_inst *inst = + (struct vdec_av1_inst *)h_vdec; + u8 *buf = (u8 *)bs->vaddr; + u32 size = bs->size; + int ret = 0; + + if (inst->ctx->is_drm_mode) { + if (bs->model == VB2_MEMORY_MMAP) { + struct aml_video_stream *s = + (struct aml_video_stream *) buf; + + if ((s->magic != AML_VIDEO_MAGIC) && + (s->type != V4L_STREAM_TYPE_MATEDATA)) + return -1; + + if (inst->ctx->param_sets_from_ucode) { + ret = parse_stream_ucode(inst, s->data, + s->len, bs->timestamp); + } else { + ret = parse_stream_cpu(inst, s->data, s->len); + } + } else if (bs->model == VB2_MEMORY_DMABUF || + bs->model == VB2_MEMORY_USERPTR) { + ret = parse_stream_ucode_dma(inst, bs->addr, size, + bs->timestamp, BUFF_IDX(bs, bs->index)); + } + } else { + if (inst->ctx->param_sets_from_ucode) { + ret = parse_stream_ucode(inst, buf, size, bs->timestamp); + } else { + ret = parse_stream_cpu(inst, buf, size); + } + } + + inst->vsi->cur_pic = inst->vsi->pic; + + return ret; +} + +static void vdec_av1_deinit(unsigned long h_vdec) +{ + ulong flags; + struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec; + struct aml_vcodec_ctx *ctx = inst->ctx; + + video_decoder_release(&inst->vdec); + + vcodec_vfm_release(&inst->vfm); + + //dump_deinit(); + + spin_lock_irqsave(&ctx->slock, flags); + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); + + ctx->drv_handle = 0; + spin_unlock_irqrestore(&ctx->slock, flags); +} + +static int vdec_av1_get_fb(struct vdec_av1_inst *inst, struct vdec_v4l2_buffer **out) +{ + return get_fb_from_queue(inst->ctx, out); +} + +static void vdec_av1_get_vf(struct vdec_av1_inst *inst, struct vdec_v4l2_buffer **out) +{ + struct vframe_s *vf = NULL; + struct vdec_v4l2_buffer *fb = NULL; + + vf = peek_video_frame(&inst->vfm); + if (!vf) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "there is no vframe.\n"); + *out = NULL; + return; + } + + vf = get_video_frame(&inst->vfm); + if (!vf) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "the vframe is avalid.\n"); + *out = NULL; + return; + } + + atomic_set(&vf->use_cnt, 1); + + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; + + *out = fb; +} + +// Returns 1 when OBU type is valid, and 0 otherwise. +static int valid_obu_type(int obu_type) +{ + int valid_type = 0; + + switch (obu_type) { + case OBU_SEQUENCE_HEADER: + case OBU_TEMPORAL_DELIMITER: + case OBU_FRAME_HEADER: + case OBU_TILE_GROUP: + case OBU_METADATA: + case OBU_FRAME: + case OBU_REDUNDANT_FRAME_HEADER: + case OBU_TILE_LIST: + case OBU_PADDING: + valid_type = 1; + break; + default: + break; + } + + return valid_type; +} + +size_t uleb_size_in_bytes(u64 value) +{ + size_t size = 0; + + do { + ++size; + } while ((value >>= 7) != 0); + + return size; +} + +int uleb_decode(const u8 *buffer, size_t available, + u64 *value, size_t *length) +{ + int i; + + if (buffer && value) { + *value = 0; + + for (i = 0; i < kMaximumLeb128Size && i < available; ++i) { + const u8 decoded_byte = *(buffer + i) & kLeb128ByteMask; + + *value |= ((u64)decoded_byte) << (i * 7); + if ((*(buffer + i) >> 7) == 0) { + if (length) { + *length = i + 1; + } + + // Fail on values larger than 32-bits to ensure consistent behavior on + // 32 and 64 bit targets: value is typically used to determine buffer + // allocation size. + if (*value > ULONG_MAX) + return -1; + + return 0; + } + } + } + + // If we get here, either the buffer/value pointers were invalid, + // or we ran over the available space + return -1; +} + +int uleb_encode(u64 value, size_t available, + u8 *coded_value, size_t *coded_size) +{ + int i; + const size_t leb_size = uleb_size_in_bytes(value); + + if (value > kMaximumLeb128Value || leb_size > kMaximumLeb128Size || + leb_size > available || !coded_value || !coded_size) { + return -1; + } + + for (i = 0; i < leb_size; ++i) { + u8 byte = value & 0x7f; + + value >>= 7; + if (value != 0) byte |= 0x80; // Signal that more bytes follow. + + *(coded_value + i) = byte; + } + + *coded_size = leb_size; + + return 0; +} + +static int rb_read_bit(struct read_bit_buffer *rb) +{ + const u32 off = rb->bit_offset; + const u32 p = off >> 3; + const int q = 7 - (int)(off & 0x7); + + if (rb->bit_buffer + p < rb->bit_buffer_end) { + const int bit = (rb->bit_buffer[p] >> q) & 1; + + rb->bit_offset = off + 1; + return bit; + } else { + return 0; + } +} + +static int rb_read_literal(struct read_bit_buffer *rb, int bits) +{ + int value = 0, bit; + + for (bit = bits - 1; bit >= 0; bit--) + value |= rb_read_bit(rb) << bit; + + return value; +} + +static int read_obu_size(const u8 *data, + size_t bytes_available, + size_t *const obu_size, + size_t *const length_field_size) +{ + u64 u_obu_size = 0; + + if (uleb_decode(data, bytes_available, &u_obu_size, length_field_size) != 0) { + return -1; + } + + if (u_obu_size > ULONG_MAX) + return -1; + + *obu_size = (size_t) u_obu_size; + + return 0; +} + +// Parses OBU header and stores values in 'header'. +static int read_obu_header(struct read_bit_buffer *rb, + int is_annexb, struct ObuHeader *header) +{ + const int bit_buffer_byte_length = + rb->bit_buffer_end - rb->bit_buffer; + + if (!rb || !header) + return -1; + + if (bit_buffer_byte_length < 1) + return -1; + + header->size = 1; + + if (rb_read_bit(rb) != 0) { + // Forbidden bit. Must not be set. + return -1; + } + + header->type = (enum OBU_TYPE) rb_read_literal(rb, 4); + if (!valid_obu_type(header->type)) + return -1; + + header->has_extension = rb_read_bit(rb); + header->has_size_field = rb_read_bit(rb); + + if (!header->has_size_field && !is_annexb) { + // section 5 obu streams must have obu_size field set. + return -1; + } + + if (rb_read_bit(rb) != 0) { + // obu_reserved_1bit must be set to 0. + return -1; + } + + if (header->has_extension) { + if (bit_buffer_byte_length == 1) + return -1; + + header->size += 1; + header->temporal_layer_id = rb_read_literal(rb, 3); + header->spatial_layer_id = rb_read_literal(rb, 2); + if (rb_read_literal(rb, 3) != 0) { + // extension_header_reserved_3bits must be set to 0. + return -1; + } + } + + return 0; +} + +int read_obu_header_and_size(const u8 *data, + size_t bytes_available, + int is_annexb, + struct ObuHeader *obu_header, + size_t *const payload_size, + size_t *const bytes_read) +{ + size_t length_field_size_obu = 0; + size_t length_field_size_payload = 0; + size_t obu_size = 0; + int status = 0; + struct read_bit_buffer rb = { data + length_field_size_obu, + data + bytes_available, 0}; + + if (is_annexb) { + // Size field comes before the OBU header, and includes the OBU header + status = read_obu_size(data, bytes_available, &obu_size, &length_field_size_obu); + if (status != 0) + return status; + } + + status = read_obu_header(&rb, is_annexb, obu_header); + if (status != 0) + return status; + + if (!obu_header->has_size_field) { + // Derive the payload size from the data we've already read + if (obu_size < obu_header->size) + return -1; + + *payload_size = obu_size - obu_header->size; + } else { + // Size field comes after the OBU header, and is just the payload size + status = read_obu_size(data + length_field_size_obu + obu_header->size, + bytes_available - length_field_size_obu - obu_header->size, + payload_size, &length_field_size_payload); + if (status != 0) + return status; + } + + *bytes_read = length_field_size_obu + obu_header->size + length_field_size_payload; + + return 0; +} + +int parser_frame(int is_annexb, u8 *data, const u8 *data_end, + u8 *dst_data, u32 *frame_len, u8 *meta_buf, u32 *meta_len) +{ + int frame_decoding_finished = 0; + u32 obu_size = 0; + int seen_frame_header = 0; + int next_start_tile = 0; + struct DataBuffer obu_size_hdr; + u8 header[20] = {0}; + u8 *p = NULL; + u32 rpu_size = 0; + struct ObuHeader obu_header; + + memset(&obu_header, 0, sizeof(obu_header)); + + // decode frame as a series of OBUs + while (!frame_decoding_finished) { + // struct read_bit_buffer rb; + size_t payload_size = 0; + size_t header_size = 0; + size_t bytes_read = 0; + const size_t bytes_available = data_end - data; + enum OBU_METADATA_TYPE meta_type; + int status; + u64 type; + u32 i; + + if (bytes_available == 0 && !seen_frame_header) { + break; + } + + status = read_obu_header_and_size(data, bytes_available, is_annexb, + &obu_header, &payload_size, &bytes_read); + if (status != 0) { + return -1; + } + + // Record obu size header information. + obu_size_hdr.data = data + obu_header.size; + obu_size_hdr.size = bytes_read - obu_header.size; + + // Note: read_obu_header_and_size() takes care of checking that this + // doesn't cause 'data' to advance past 'data_end'. + + if ((size_t)(data_end - data - bytes_read) < payload_size) { + return -1; + } + + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "obu %s len %zu+%zu\n", + obu_type_name[obu_header.type], + bytes_read, payload_size); + + if (!is_annexb) { + obu_size = bytes_read + payload_size + 4; + header_size = 20; + } else { + obu_size = bytes_read + payload_size; + header_size = 16; + } + + header[0] = ((obu_size + 4) >> 24) & 0xff; + header[1] = ((obu_size + 4) >> 16) & 0xff; + header[2] = ((obu_size + 4) >> 8) & 0xff; + header[3] = ((obu_size + 4) >> 0) & 0xff; + header[4] = header[0] ^ 0xff; + header[5] = header[1] ^ 0xff; + header[6] = header[2] ^ 0xff; + header[7] = header[3] ^ 0xff; + header[8] = 0; + header[9] = 0; + header[10] = 0; + header[11] = 1; + header[12] = 'A'; + header[13] = 'M'; + header[14] = 'L'; + header[15] = 'V'; + + // put new size to here as annexb + header[16] = (obu_size & 0xff) | 0x80; + header[17] = ((obu_size >> 7) & 0xff) | 0x80; + header[18] = ((obu_size >> 14) & 0xff) | 0x80; + header[19] = ((obu_size >> 21) & 0xff) | 0x00; + + memcpy(dst_data, header, header_size); + dst_data += header_size; + memcpy(dst_data, data, bytes_read + payload_size); + dst_data += (bytes_read + payload_size); + + data += bytes_read; + *frame_len += (header_size + bytes_read + payload_size); + + switch (obu_header.type) { + case OBU_TEMPORAL_DELIMITER: + seen_frame_header = 0; + next_start_tile = 0; + break; + case OBU_SEQUENCE_HEADER: + // The sequence header should not change in the middle of a frame. + if (seen_frame_header) { + return -1; + } + break; + case OBU_FRAME_HEADER: + if (data_end == data + payload_size) { + frame_decoding_finished = 1; + } else { + seen_frame_header = 1; + } + break; + case OBU_REDUNDANT_FRAME_HEADER: + case OBU_FRAME: + if (obu_header.type == OBU_REDUNDANT_FRAME_HEADER) { + if (!seen_frame_header) { + return -1; + } + } else { + // OBU_FRAME_HEADER or OBU_FRAME. + if (seen_frame_header) { + return -1; + } + } + if (obu_header.type == OBU_FRAME) { + if (data_end == data + payload_size) { + frame_decoding_finished = 1; + seen_frame_header = 0; + } + } + break; + case OBU_TILE_GROUP: + if (!seen_frame_header) { + return -1; + } + if (data + payload_size == data_end) + frame_decoding_finished = 1; + if (frame_decoding_finished) + seen_frame_header = 0; + break; + case OBU_METADATA: + uleb_decode(data, 8, &type, &bytes_read); + if (type < 6) + meta_type = type; + else + meta_type = 0; + p = data + bytes_read; + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, + "meta type %s %zu+%zu\n", + meta_type_name[type], + bytes_read, + payload_size - bytes_read); + + if (meta_type == OBU_METADATA_TYPE_ITUT_T35) { +#if 0 /* for dumping original obu payload */ + for (i = 0; i < payload_size - bytes_read; i++) { + pr_info("%02x ", p[i]); + if (i % 16 == 15) + pr_info("\n"); + } + if (i % 16 != 0) + pr_info("\n"); +#endif + if ((p[0] == 0xb5) /* country code */ + && ((p[1] == 0x00) && (p[2] == 0x3b)) /* terminal_provider_code */ + && ((p[3] == 0x00) && (p[4] == 0x00) && (p[5] == 0x08) && (p[6] == 0x00))) { /* terminal_provider_oriented_code */ + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, + "dolbyvison rpu\n"); + meta_buf[0] = meta_buf[1] = meta_buf[2] = 0; + meta_buf[3] = 0x01; + meta_buf[4] = 0x19; + + if (p[11] & 0x10) { + rpu_size = 0x100; + rpu_size |= (p[11] & 0x0f) << 4; + rpu_size |= (p[12] >> 4) & 0x0f; + if (p[12] & 0x08) { + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, + "meta rpu in obu exceed 512 bytes\n"); + break; + } + for (i = 0; i < rpu_size; i++) { + meta_buf[5 + i] = (p[12 + i] & 0x07) << 5; + meta_buf[5 + i] |= (p[13 + i] >> 3) & 0x1f; + } + rpu_size += 5; + } else { + rpu_size = (p[10] & 0x1f) << 3; + rpu_size |= (p[11] >> 5) & 0x07; + for (i = 0; i < rpu_size; i++) { + meta_buf[5 + i] = (p[11 + i] & 0x0f) << 4; + meta_buf[5 + i] |= (p[12 + i] >> 4) & 0x0f; + } + rpu_size += 5; + } + *meta_len = rpu_size; + } + } else if (meta_type == OBU_METADATA_TYPE_HDR_CLL) { + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "hdr10 cll:\n"); + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "max_cll = %x\n", (p[0] << 8) | p[1]); + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "max_fall = %x\n", (p[2] << 8) | p[3]); + } else if (meta_type == OBU_METADATA_TYPE_HDR_MDCV) { + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "hdr10 primaries[r,g,b] = \n"); + for (i = 0; i < 3; i++) { + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, " %x, %x\n", + (p[i * 4] << 8) | p[i * 4 + 1], + (p[i * 4 + 2] << 8) | p[i * 4 + 3]); + } + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, + "white point = %x, %x\n", (p[12] << 8) | p[13], (p[14] << 8) | p[15]); + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, + "maxl = %x\n", (p[16] << 24) | (p[17] << 16) | (p[18] << 8) | p[19]); + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, + "minl = %x\n", (p[20] << 24) | (p[21] << 16) | (p[22] << 8) | p[23]); + } + break; + case OBU_TILE_LIST: + break; + case OBU_PADDING: + break; + default: + // Skip unrecognized OBUs + break; + } + + data += payload_size; + } + + return 0; +} + +static int vdec_write_nalu(struct vdec_av1_inst *inst, + u8 *buf, u32 size, u64 ts) +{ + int ret = 0; + struct aml_vdec_adapt *vdec = &inst->vdec; + u8 *data = NULL; + u32 length = 0; + bool need_prefix = av1_need_prefix; + + if (need_prefix) { + u8 meta_buffer[1024] = {0}; + u32 meta_size = 0; + u8 *src = buf; + + data = vzalloc(size + 0x1000); + if (!data) + return -ENOMEM; + + parser_frame(0, src, src + size, data, &length, meta_buffer, &meta_size); + + if (length) + ret = vdec_vframe_write(vdec, data, length, ts); + else + ret = -1; + + vfree(data); + } else { + ret = vdec_vframe_write(vdec, buf, size, ts); + } + + return ret; +} + +static bool monitor_res_change(struct vdec_av1_inst *inst, u8 *buf, u32 size) +{ + int ret = -1; + u8 *p = buf; + int len = size; + u32 synccode = av1_need_prefix ? + ((p[1] << 16) | (p[2] << 8) | p[3]) : + ((p[17] << 16) | (p[18] << 8) | p[19]); + + if (synccode == SYNC_CODE) { + ret = parse_stream_cpu(inst, p, len); + if (!ret && (inst->vsi->cur_pic.coded_width != + inst->vsi->pic.coded_width || + inst->vsi->cur_pic.coded_height != + inst->vsi->pic.coded_height)) { + inst->vsi->cur_pic = inst->vsi->pic; + return true; + } + } + + return false; +} + +static int vdec_av1_decode(unsigned long h_vdec, + struct aml_vcodec_mem *bs, bool *res_chg) +{ + struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec; + struct aml_vdec_adapt *vdec = &inst->vdec; + u8 *buf = (u8 *) bs->vaddr; + u32 size = bs->size; + int ret = -1; + + if (bs == NULL) + return -1; + + if (vdec_input_full(vdec)) { + ATRACE_COUNTER("vdec_input_full", 0); + return -EAGAIN; + } + + if (inst->ctx->is_drm_mode) { + if (bs->model == VB2_MEMORY_MMAP) { + struct aml_video_stream *s = + (struct aml_video_stream *) buf; + + if (s->magic != AML_VIDEO_MAGIC) + return -1; + + if (!inst->ctx->param_sets_from_ucode && + (s->type == V4L_STREAM_TYPE_MATEDATA)) { + if ((*res_chg = monitor_res_change(inst, + s->data, s->len))) + return 0; + } + + ret = vdec_vframe_write(vdec, + s->data, + s->len, + bs->timestamp); + } else if (bs->model == VB2_MEMORY_DMABUF || + bs->model == VB2_MEMORY_USERPTR) { + ret = vdec_vframe_write_with_dma(vdec, + bs->addr, size, bs->timestamp, + BUFF_IDX(bs, bs->index)); + } + } else { + /*checked whether the resolution changes.*/ + if ((!inst->ctx->param_sets_from_ucode) && + (*res_chg = monitor_res_change(inst, buf, size))) + return 0; + + ret = vdec_write_nalu(inst, buf, size, bs->timestamp); + } + ATRACE_COUNTER("v4l2_decode_write", ret); + + return ret; +} + + static void get_param_config_info(struct vdec_av1_inst *inst, + struct aml_dec_params *parms) + { + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + parms->cfg = inst->parms.cfg; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + parms->ps = inst->parms.ps; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + parms->hdr = inst->parms.hdr; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + parms->cnt = inst->parms.cnt; + + parms->parms_status |= inst->parms.parms_status; + + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, + "parms status: %u\n", parms->parms_status); + } + +static int vdec_av1_get_param(unsigned long h_vdec, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec; + + if (!inst) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "the av1 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case GET_PARAM_DISP_FRAME_BUFFER: + vdec_av1_get_vf(inst, out); + break; + + case GET_PARAM_FREE_FRAME_BUFFER: + ret = vdec_av1_get_fb(inst, out); + break; + + case GET_PARAM_PIC_INFO: + get_pic_info(inst, out); + break; + + case GET_PARAM_DPB_SIZE: + get_dpb_size(inst, out); + break; + + case GET_PARAM_CROP_INFO: + get_crop_info(inst, out); + break; + + case GET_PARAM_CONFIG_INFO: + get_param_config_info(inst, out); + break; + + default: + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "invalid get parameter type=%d\n", type); + ret = -EINVAL; + } + + return ret; +} + +static void set_param_write_sync(struct vdec_av1_inst *inst) +{ + complete(&inst->comp); +} + +static void set_param_ps_info(struct vdec_av1_inst *inst, + struct aml_vdec_ps_infos *ps) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_av1_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + + /* fill visible area size that be used for EGL. */ + pic->visible_width = ps->visible_width; + pic->visible_height = ps->visible_height; + + /* calc visible ares. */ + 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->coded_width = ps->coded_width; + pic->coded_height = ps->coded_height; + + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + /* calc DPB size */ + dec->dpb_sz = ps->dpb_size; + + inst->parms.ps = *ps; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_PSINFO; + + /*wake up*/ + complete(&inst->comp); + + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, + "Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", + ps->visible_width, ps->visible_height, + ps->coded_width, ps->coded_height, + ps->dpb_size); +} + +static void set_param_hdr_info(struct vdec_av1_inst *inst, + struct aml_vdec_hdr_infos *hdr) +{ + if ((inst->parms.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO)) { + inst->parms.hdr = *hdr; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_HDRINFO; + aml_vdec_dispatch_event(inst->ctx, + V4L2_EVENT_SRC_CH_HDRINFO); + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, + "av1 set HDR infos\n"); + } +} + +static void set_param_post_event(struct vdec_av1_inst *inst, u32 *event) +{ + aml_vdec_dispatch_event(inst->ctx, *event); + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, + "av1 post event: %d\n", *event); +} + +static int vdec_av1_set_param(unsigned long h_vdec, + enum vdec_set_param_type type, void *in) +{ + int ret = 0; + struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec; + + if (!inst) { + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "the av1 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case SET_PARAM_WRITE_FRAME_SYNC: + set_param_write_sync(inst); + break; + + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); + break; + + case SET_PARAM_HDR_INFO: + set_param_hdr_info(inst, in); + break; + + case SET_PARAM_POST_EVENT: + set_param_post_event(inst, in); + break; + default: + v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, + "invalid set parameter type=%d\n", type); + ret = -EINVAL; + } + + return ret; +} + +static struct vdec_common_if vdec_av1_if = { + .init = vdec_av1_init, + .probe = vdec_av1_probe, + .decode = vdec_av1_decode, + .get_param = vdec_av1_get_param, + .set_param = vdec_av1_set_param, + .deinit = vdec_av1_deinit, +}; + +struct vdec_common_if *get_av1_dec_comm_if(void); + +struct vdec_common_if *get_av1_dec_comm_if(void) +{ + return &vdec_av1_if; +} + diff --git a/drivers/amvdec_ports/vdec_drv_if.c b/drivers/amvdec_ports/vdec_drv_if.c index 3be48b9..ed9f053 100644 --- a/drivers/amvdec_ports/vdec_drv_if.c +++ b/drivers/amvdec_ports/vdec_drv_if.c @@ -31,6 +31,7 @@ const struct vdec_common_if *get_vp9_dec_comm_if(void); const struct vdec_common_if *get_mpeg12_dec_comm_if(void); const struct vdec_common_if *get_mpeg4_dec_comm_if(void); const struct vdec_common_if *get_mjpeg_dec_comm_if(void); +const struct vdec_common_if *get_av1_dec_comm_if(void); int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc) { @@ -57,6 +58,9 @@ int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc) case V4L2_PIX_FMT_MJPEG: ctx->dec_if = get_mjpeg_dec_comm_if(); break; + case V4L2_PIX_FMT_AV1: + ctx->dec_if = get_av1_dec_comm_if(); + break; default: return -EINVAL; } diff --git a/drivers/frame_provider/decoder/vav1/av1_bufmgr.c b/drivers/frame_provider/decoder/vav1/av1_bufmgr.c index abd14a1..583f646 100644 --- a/drivers/frame_provider/decoder/vav1/av1_bufmgr.c +++ b/drivers/frame_provider/decoder/vav1/av1_bufmgr.c @@ -424,45 +424,6 @@ void av1_setup_scale_factors_for_frame(struct scale_factors *sf, int other_w, } #endif - -static int get_free_fb(AV1_COMMON *cm) { - RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; - int i; - unsigned long flags; - lock_buffer_pool(cm->buffer_pool, flags); - for (i = 0; i < FRAME_BUFFERS; ++i) - if (frame_bufs[i].ref_count == 0 -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - && frame_bufs[i].buf.vf_ref == 0 -#endif - ) - break; - - if (i != FRAME_BUFFERS) { - if (frame_bufs[i].buf.use_external_reference_buffers) { - // If this frame buffer's y_buffer, u_buffer, and v_buffer point to the - // external reference buffers. Restore the buffer pointers to point to the - // internally allocated memory. - PIC_BUFFER_CONFIG *ybf = &frame_bufs[i].buf; - ybf->y_buffer = ybf->store_buf_adr[0]; - ybf->u_buffer = ybf->store_buf_adr[1]; - ybf->v_buffer = ybf->store_buf_adr[2]; - ybf->use_external_reference_buffers = 0; - } - - frame_bufs[i].ref_count = 1; - } else { - // We should never run out of free buffers. If this assertion fails, there - // is a reference leak. - assert(0 && "Ran out of free frame buffers. Likely a reference leak."); - // Reset i to be INVALID_IDX to indicate no free buffer found. - i = INVALID_IDX; - } - - unlock_buffer_pool(cm->buffer_pool, flags); - return i; -} - static RefCntBuffer *assign_cur_frame_new_fb(AV1_COMMON *const cm) { // Release the previously-used frame-buffer int new_fb_idx; @@ -472,7 +433,7 @@ static RefCntBuffer *assign_cur_frame_new_fb(AV1_COMMON *const cm) { } // Assign a new framebuffer - new_fb_idx = get_free_fb(cm); + new_fb_idx = get_free_frame_buffer(cm); if (new_fb_idx == INVALID_IDX) return NULL; cm->cur_frame = &cm->buffer_pool->frame_bufs[new_fb_idx]; @@ -502,9 +463,8 @@ static void assign_frame_buffer_p(RefCntBuffer **lhs_ptr, ++rhs_ptr->ref_count; } -AV1Decoder *av1_decoder_create(BufferPool *const pool) { +AV1Decoder *av1_decoder_create(BufferPool *const pool, AV1_COMMON *cm) { int i; - AV1_COMMON *cm; #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC AV1Decoder *pbi = (AV1Decoder *)malloc(sizeof(*pbi)); @@ -514,12 +474,11 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) { if (!pbi) return NULL; memset(pbi, 0, sizeof(*pbi)); - cm = &pbi->common; - // The jmp_buf is valid only for the duration of the function that calls // setjmp(). Therefore, this function must reset the 'setjmp' field to 0 // before it returns. + pbi->common = cm; cm->error.setjmp = 1; #ifdef ORI_CODE @@ -539,7 +498,7 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) { cm->current_frame.frame_number = 0; pbi->decoding_first_frame = 1; - pbi->common.buffer_pool = pool; + pbi->common->buffer_pool = pool; cm->seq_params.bit_depth = AOM_BITS_8; @@ -567,6 +526,29 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) { return pbi; } +static void reset_frame_buffers(AV1Decoder *const pbi); + +void av1_bufmgr_ctx_reset(AV1Decoder *pbi, BufferPool *const pool, AV1_COMMON *cm) +{ + if (!pbi || !pool || !cm) + return; + + reset_frame_buffers(pbi); + memset(pbi, 0, sizeof(*pbi)); + memset(cm, 0, sizeof(*cm)); + + cm->current_frame.frame_number = 0; + cm->seq_params.bit_depth = AOM_BITS_8; + cm->error.setjmp = 0; + + pbi->bufmgr_proc_count = 0; + pbi->need_resync = 1; + pbi->decoding_first_frame = 1; + pbi->num_output_frames = 0; + pbi->common = cm; + pbi->common->buffer_pool = pool; +} + int release_fb_cb(void *cb_priv, aom_codec_frame_buffer_t *fb) { #if 0 InternalFrameBuffer *const int_fb = (InternalFrameBuffer *)fb->priv; @@ -605,7 +587,7 @@ static void decrease_ref_count(AV1Decoder *pbi, RefCntBuffer *const buf, static void swap_frame_buffers(AV1Decoder *pbi, int frame_decoded) { int ref_index = 0, mask; - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; BufferPool *const pool = cm->buffer_pool; unsigned long flags; @@ -729,7 +711,7 @@ void av1_zero_unused_internal_frame_buffers(InternalFrameBufferList *list) { // Release the references to the frame buffers in cm->ref_frame_map and reset // all elements of cm->ref_frame_map to NULL. static void reset_ref_frame_map(AV1Decoder *const pbi) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; BufferPool *const pool = cm->buffer_pool; int i; @@ -744,7 +726,7 @@ static void reset_ref_frame_map(AV1Decoder *const pbi) { // Generate next_ref_frame_map. static void generate_next_ref_frame_map(AV1Decoder *const pbi) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; BufferPool *const pool = cm->buffer_pool; unsigned long flags; int ref_index = 0; @@ -790,7 +772,7 @@ static void update_ref_frame_id(AV1_COMMON *const cm, int frame_id) { static void show_existing_frame_reset(AV1Decoder *const pbi, int existing_frame_idx) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; int i; assert(cm->show_existing_frame); @@ -825,7 +807,7 @@ static void show_existing_frame_reset(AV1Decoder *const pbi, } static void reset_frame_buffers(AV1Decoder *const pbi) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; int i; unsigned long flags; @@ -1894,7 +1876,7 @@ static void setup_segmentation(AV1_COMMON *const cm, int av1_decode_frame_headers_and_setup(AV1Decoder *pbi, int trailing_bits_present, union param_u *params) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; /* read_uncompressed_header() */ @@ -2197,7 +2179,7 @@ int av1_decode_frame_headers_and_setup(AV1Decoder *pbi, int trailing_bits_presen } // If no corresponding buffer exists, allocate a new buffer with all // pixels set to neutral grey. - buf_idx = get_free_fb(cm); + buf_idx = get_free_frame_buffer(cm); if (buf_idx == INVALID_IDX) { aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR, "Unable to find free frame buffer"); @@ -2708,7 +2690,7 @@ static int is_valid_seq_level_idx(AV1_LEVEL seq_level_idx) { static uint32_t read_sequence_header_obu(AV1Decoder *pbi, union param_u *params) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; int i; int operating_point; // Verify rb has been configured to report errors. @@ -2887,7 +2869,7 @@ static uint32_t read_sequence_header_obu(AV1Decoder *pbi, int aom_decode_frame_from_obus(AV1Decoder *pbi, union param_u *params, int obu_type) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; ObuHeader obu_header; int frame_decoding_finished = 0; uint32_t frame_header_size = 0; @@ -2991,12 +2973,12 @@ int aom_decode_frame_from_obus(AV1Decoder *pbi, union param_u *params, int obu_t default: break; } - return frame_decoding_finished; + return frame_decoding_finished; } int get_buffer_index(AV1Decoder *pbi, RefCntBuffer *buffer) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; int i = -1; if (buffer) { @@ -3008,6 +2990,7 @@ int get_buffer_index(AV1Decoder *pbi, RefCntBuffer *buffer) } } } + return i; } @@ -3031,7 +3014,7 @@ void dump_buffer(RefCntBuffer *buf) void dump_ref_buffer_info(AV1Decoder *pbi, int i) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; pr_info("remapped_ref_idx %d, ref_frame_sign_bias %d, ref_frame_id %d, valid_for_referencing %d ref_frame_side %d ref_frame_map idx %d, next_ref_frame_map idx %d", cm->remapped_ref_idx[i], cm->ref_frame_sign_bias[i], @@ -3045,7 +3028,7 @@ void dump_ref_buffer_info(AV1Decoder *pbi, int i) void dump_mv_refs(AV1Decoder *pbi) { int i, j; - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; for (i = 0; i < cm->mv_ref_id_index; i++) { pr_info("%d: ref_id %d cal_tpl_mvs %d mv_ref_offset: ", i, cm->mv_ref_id[i], cm->mv_cal_tpl_mvs[i]); @@ -3058,7 +3041,7 @@ void dump_mv_refs(AV1Decoder *pbi) void dump_ref_spec_bufs(AV1Decoder *pbi) { int i; - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; for (i = 0; i < INTER_REFS_PER_FRAME; ++i) { PIC_BUFFER_CONFIG *pic_config = av1_get_ref_frame_spec_buf(cm, LAST_FRAME + i); if (pic_config == NULL) continue; @@ -3083,7 +3066,7 @@ void dump_ref_spec_bufs(AV1Decoder *pbi) void dump_scale_factors(AV1Decoder *pbi) { int i; - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) { struct scale_factors *const sf = get_ref_scale_factors(cm, i); @@ -3101,7 +3084,7 @@ void dump_scale_factors(AV1Decoder *pbi) void dump_buffer_status(AV1Decoder *pbi) { int i; - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; BufferPool *const pool = cm->buffer_pool; unsigned long flags; @@ -3230,7 +3213,7 @@ void dump_params(AV1Decoder *pbi, union param_u *params) int av1_bufmgr_process(AV1Decoder *pbi, union param_u *params, unsigned char new_compressed_data, int obu_type) { - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; int j; // Release any pending output frames from the previous decoder_decode call. // We need to do this even if the decoder is being flushed or the input @@ -3347,7 +3330,7 @@ struct scale_factors *av1_get_ref_scale_factors( void av1_set_next_ref_frame_map(AV1Decoder *pbi) { int ref_index = 0; int mask; - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; int check_on_show_existing_frame; av1_print2(AV1_DEBUG_BUFMGR_DETAIL, "%s, %d, mask 0x%x, show_existing_frame %d, reset_decoder_state %d\n", __func__, pbi->camera_frame_header_ready, diff --git a/drivers/frame_provider/decoder/vav1/av1_global.h b/drivers/frame_provider/decoder/vav1/av1_global.h index 4583a7c..75af688 100644 --- a/drivers/frame_provider/decoder/vav1/av1_global.h +++ b/drivers/frame_provider/decoder/vav1/av1_global.h @@ -1322,6 +1322,8 @@ typedef struct PIC_BUFFER_CONFIG_s { int min_mv; int avg_mv; #endif + bool vframe_bound; + u64 timestamp; } PIC_BUFFER_CONFIG; /* @@ -2023,7 +2025,7 @@ typedef struct AV1Decoder { //DECLARE_ALIGNED(32, MACROBLOCKD, mb); //DECLARE_ALIGNED(32, AV1_COMMON, common); - AV1_COMMON common; + AV1_COMMON *common; #ifdef ORI_CODE AVxWorker lf_worker; @@ -2264,7 +2266,7 @@ void av1_release_buf(AV1Decoder *pbi, RefCntBuffer *const buf); int av1_bufmgr_postproc(AV1Decoder *pbi, unsigned char frame_decoded); -AV1Decoder *av1_decoder_create(BufferPool *const pool); +AV1Decoder *av1_decoder_create(BufferPool *const pool, AV1_COMMON *cm); unsigned char av1_frame_is_inter(const AV1_COMMON *const cm); @@ -2273,6 +2275,10 @@ RefCntBuffer *av1_get_primary_ref_frame_buf( void av1_raw_write_image(AV1Decoder *pbi, PIC_BUFFER_CONFIG *sd); +int get_free_frame_buffer(struct AV1_Common_s *cm); + +void av1_bufmgr_ctx_reset(AV1Decoder *pbi, BufferPool *const pool, AV1_COMMON *cm); + #if 1 #define lock_buffer_pool(pool, flags) \ spin_lock_irqsave(&pool->lock, flags) diff --git a/drivers/frame_provider/decoder/vav1/vav1.c b/drivers/frame_provider/decoder/vav1/vav1.c index 56867f2..cd2e598 100644 --- a/drivers/frame_provider/decoder/vav1/vav1.c +++ b/drivers/frame_provider/decoder/vav1/vav1.c @@ -42,6 +42,7 @@ #include <linux/amlogic/media/codec_mm/codec_mm.h> #include "../utils/decoder_mmu_box.h" #include "../utils/decoder_bmmu_box.h" +#include <linux/crc32.h> #define MEM_NAME "codec_av1" /* #include <mach/am_regs.h> */ @@ -65,7 +66,9 @@ #ifdef SUPPORT_V4L2 #include "../utils/vdec_v4l2_buffer_ops.h" +#include <media/v4l2-mem2mem.h> #endif +#include "../../../amvdec_ports/utils/common.h" #define AML #include "aom_av1_define.h" @@ -313,7 +316,7 @@ static void vav1_prot_init(struct AV1HW_s *hw, u32 mask); static int vav1_local_init(struct AV1HW_s *hw); static void vav1_put_timer_func(unsigned long arg); static void dump_data(struct AV1HW_s *hw, int size); -static unsigned char get_data_check_sum +static unsigned int get_data_check_sum (struct AV1HW_s *hw, int size); static void dump_pic_list(struct AV1HW_s *hw); static int vav1_mmu_map_alloc(struct AV1HW_s *hw); @@ -382,6 +385,11 @@ struct BUF_s { unsigned int free_start_adr; ulong v4l_ref_buf_addr; + ulong header_addr; + u32 header_size; + u32 luma_size; + ulong chroma_addr; + u32 chroma_size; } /*BUF_t */; struct MVBUF_s { @@ -446,7 +454,6 @@ static u32 udebug_pause_val; static u32 udebug_pause_decode_idx; - #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION static u32 dv_toggle_prov_name; #endif @@ -697,9 +704,12 @@ struct AV1HW_s { u8 first_pts_index; u32 frame_mode_pts_save[FRAME_BUFFERS]; u64 frame_mode_pts64_save[FRAME_BUFFERS]; + u64 frame_mode_timestamp_save[FRAME_BUFFERS]; + u64 timestamp_duration; int last_pts; u64 last_pts_us64; + u64 last_timestamp; u64 shift_byte_count; u32 shift_byte_count_lo; @@ -777,6 +787,7 @@ struct AV1HW_s { bool pic_list_init_done2; bool is_used_v4l; void *v4l2_ctx; + bool v4l_params_parsed; int frameinfo_enable; struct vframe_qos_s vframe_qos; @@ -784,11 +795,15 @@ struct AV1HW_s { /* * malloc may not work in real chip, please allocate memory for the following structures */ - struct loop_filter_info_n_s *lfi; - struct loopfilter *lf; - struct segmentation_lf *seg_4lf; -#endif - + struct loop_filter_info_n_s *lfi; + struct loopfilter *lf; + struct segmentation_lf *seg_4lf; +#endif + u32 mem_map_mode; + u32 dynamic_buf_num_margin; + struct vframe_s vframe_dummy; + unsigned int res_ch_flag; + int buffer_wrap[FRAME_BUFFERS]; }; static void av1_dump_state(struct vdec_s *vdec); @@ -854,16 +869,8 @@ static int is_oversize(int w, int h) return false; } -static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) -{ - int ret = 0; - - ret = ctx->dec_if->get_param(ctx->drv_handle, - GET_PARAM_FREE_FRAME_BUFFER, out); - - return ret; -} - +static int v4l_alloc_and_config_pic(struct AV1HW_s *hw, + struct PIC_BUFFER_CONFIG_s *pic); static inline bool close_to(int a, int b, int m) { @@ -892,6 +899,15 @@ static int av1_print_cont(struct AV1HW_s *hw, static void trigger_schedule(struct AV1HW_s *hw) { + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !hw->v4l_params_parsed) + vdec_v4l_write_frame_sync(ctx); + } + if (hw->vdec_cb) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); } @@ -946,12 +962,46 @@ static u32 get_valid_double_write_mode(struct AV1HW_s *hw) return dw; } +static int v4l_parser_get_double_write_mode(struct AV1HW_s *hw) +{ + u32 valid_dw_mode = get_valid_double_write_mode(hw); + u32 dw; + int w, h; + + /* mask for supporting double write value bigger than 0x100 */ + if (valid_dw_mode & 0xffffff00) { + w = hw->frame_width; + h = hw->frame_height; + + dw = 0x1; /*1:1*/ + switch (valid_dw_mode) { + case 0x100: + if (w > 1920 && h > 1088) + dw = 0x4; /*1:2*/ + break; + case 0x200: + if (w > 1920 && h > 1088) + dw = 0x2; /*1:4*/ + break; + case 0x300: + if (w > 1280 && h > 720) + dw = 0x4; /*1:2*/ + break; + default: + break; + } + return dw; + } + + return valid_dw_mode; +} + static int get_double_write_mode(struct AV1HW_s *hw) { u32 valid_dw_mode = get_valid_double_write_mode(hw); u32 dw; int w, h; - struct AV1_Common_s *cm = &hw->pbi->common; + struct AV1_Common_s *cm = &hw->common; struct PIC_BUFFER_CONFIG_s *cur_pic_config; if (!cm->cur_frame) @@ -1024,6 +1074,30 @@ static int get_double_write_ratio(struct AV1HW_s *hw, return ratio; } +/* return page number */ +static int av1_mmu_page_num(struct AV1HW_s *hw, + int w, int h, int save_mode) +{ + int picture_size; + int cur_mmu_4k_number, max_frame_num; + + picture_size = compute_losless_comp_body_size(w, h, save_mode); + cur_mmu_4k_number = ((picture_size + (PAGE_SIZE - 1)) >> PAGE_SHIFT); + + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + max_frame_num = MAX_FRAME_8K_NUM; + else + max_frame_num = MAX_FRAME_4K_NUM; + + if (cur_mmu_4k_number > max_frame_num) { + pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", + cur_mmu_4k_number, w, h); + return -1; + } + + return cur_mmu_4k_number; +} + //#define MAX_4K_NUM 0x1200 int av1_alloc_mmu( struct AV1HW_s *hw, @@ -1035,38 +1109,35 @@ int av1_alloc_mmu( { int ret = 0; int bit_depth_10 = (bit_depth == AOM_BITS_10); - int picture_size; - int cur_mmu_4k_number, max_frame_num; + int cur_mmu_4k_number; + if (!hw->mmu_box) { pr_err("error no mmu box!\n"); return -1; } + if (hw->double_write_mode & 0x10) return 0; + if (bit_depth >= AOM_BITS_12) { hw->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW; pr_err("fatal_error, un support bit depth 12!\n\n"); return -1; } - picture_size = compute_losless_comp_body_size(pic_width, pic_height, - bit_depth_10); - cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); - - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) - max_frame_num = MAX_FRAME_8K_NUM; - else - max_frame_num = MAX_FRAME_4K_NUM; - if (cur_mmu_4k_number > max_frame_num) { - pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", - cur_mmu_4k_number, pic_width, pic_height); + cur_mmu_4k_number = av1_mmu_page_num(hw, + pic_width, + pic_height, + bit_depth_10); + if (cur_mmu_4k_number < 0) return -1; - } + ret = decoder_mmu_box_alloc_idx( hw->mmu_box, - cur_buf_idx, + hw->buffer_wrap[cur_buf_idx], cur_mmu_4k_number, mmu_index_adr); + return ret; } @@ -1113,7 +1184,7 @@ int av1_alloc_mmu_dw( } ret = decoder_mmu_box_alloc_idx( hw->mmu_box_dw, - cur_buf_idx, + hw->buffer_wrap[cur_buf_idx], cur_mmu_4k_number, mmu_index_adr); return ret; @@ -1278,7 +1349,7 @@ static void put_mv_buf(struct AV1HW_s *hw, } static void put_un_used_mv_bufs(struct AV1HW_s *hw) { - struct AV1_Common_s *const cm = &hw->pbi->common; + struct AV1_Common_s *const cm = &hw->common; struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; int i; for (i = 0; i < hw->used_buf_num; ++i) { @@ -1291,10 +1362,139 @@ static void put_un_used_mv_bufs(struct AV1HW_s *hw) } #endif +static void init_pic_list_hw(struct AV1HW_s *pbi); + +static int get_free_fb_idx(AV1_COMMON *cm) +{ + int i; + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; + + for (i = 0; i < FRAME_BUFFERS; ++i) { + if (frame_bufs[i].ref_count == 0 + && frame_bufs[i].buf.vf_ref == 0) + break; + } + + return i; +} + +static int v4l_get_free_fb(struct AV1HW_s *hw) +{ + struct AV1_Common_s *const cm = &hw->common; + struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + struct aml_vcodec_ctx * v4l = hw->v4l2_ctx; + struct v4l_buff_pool *pool = &v4l->cap_pool; + struct PIC_BUFFER_CONFIG_s *pic = NULL; + struct PIC_BUFFER_CONFIG_s *free_pic = NULL; + ulong flags; + int idx, i; + + lock_buffer_pool(cm->buffer_pool, flags); + + for (i = 0; i < pool->in; ++i) { + u32 state = (pool->seq[i] >> 16); + u32 index = (pool->seq[i] & 0xffff); + + switch (state) { + case V4L_CAP_BUFF_IN_DEC: + pic = &frame_bufs[i].buf; + if ((frame_bufs[i].ref_count == 0) && + (pic->vf_ref == 0) && + (pic->index != -1) && + pic->cma_alloc_addr) { + free_pic = pic; + } + break; + case V4L_CAP_BUFF_IN_M2M: + idx = get_free_fb_idx(cm); + pic = &frame_bufs[idx].buf; + pic->y_crop_width = hw->frame_width; + pic->y_crop_height = hw->frame_height; + hw->buffer_wrap[idx] = index; + if (!v4l_alloc_and_config_pic(hw, pic)) { + set_canvas(hw, pic); + init_pic_list_hw(hw); + free_pic = pic; + } + break; + default: + pr_err("v4l buffer state err %d.\n", state); + break; + } + + if (free_pic) { + if (frame_bufs[i].buf.use_external_reference_buffers) { + // If this frame buffer's y_buffer, u_buffer, and v_buffer point to the + // external reference buffers. Restore the buffer pointers to point to the + // internally allocated memory. + PIC_BUFFER_CONFIG *ybf = &frame_bufs[i].buf; + + ybf->y_buffer = ybf->store_buf_adr[0]; + ybf->u_buffer = ybf->store_buf_adr[1]; + ybf->v_buffer = ybf->store_buf_adr[2]; + ybf->use_external_reference_buffers = 0; + } + + frame_bufs[i].ref_count = 1; + break; + } + } + + unlock_buffer_pool(cm->buffer_pool, flags); + + return free_pic ? free_pic->index : INVALID_IDX; +} + +static int get_free_fb(AV1_COMMON *cm) { + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; + unsigned long flags; + int i; + + lock_buffer_pool(cm->buffer_pool, flags); + for (i = 0; i < FRAME_BUFFERS; ++i) { + if (frame_bufs[i].ref_count == 0 +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + && frame_bufs[i].buf.vf_ref == 0 +#endif + ) + break; + } + + if (i != FRAME_BUFFERS) { + if (frame_bufs[i].buf.use_external_reference_buffers) { + // If this frame buffer's y_buffer, u_buffer, and v_buffer point to the + // external reference buffers. Restore the buffer pointers to point to the + // internally allocated memory. + PIC_BUFFER_CONFIG *ybf = &frame_bufs[i].buf; + ybf->y_buffer = ybf->store_buf_adr[0]; + ybf->u_buffer = ybf->store_buf_adr[1]; + ybf->v_buffer = ybf->store_buf_adr[2]; + ybf->use_external_reference_buffers = 0; + } + + frame_bufs[i].ref_count = 1; + } else { + // We should never run out of free buffers. If this assertion fails, there + // is a reference leak. + //assert(0 && "Ran out of free frame buffers. Likely a reference leak."); + // Reset i to be INVALID_IDX to indicate no free buffer found. + i = INVALID_IDX; + } + + unlock_buffer_pool(cm->buffer_pool, flags); + return i; +} + +int get_free_frame_buffer(struct AV1_Common_s *cm) +{ + struct AV1HW_s *hw = container_of(cm, struct AV1HW_s, common); + + return hw->is_used_v4l ? v4l_get_free_fb(hw) : get_free_fb(cm); +} static int get_free_buf_count(struct AV1HW_s *hw) { - struct AV1_Common_s *const cm = &hw->pbi->common; + struct AV1_Common_s *const cm = &hw->common; struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; int i; int free_buf_count = 0; @@ -1309,7 +1509,7 @@ static int get_free_buf_count(struct AV1HW_s *hw) int aom_bufmgr_init(struct AV1HW_s *hw, struct BuffInfo_s *buf_spec_i, struct buff_s *mc_buf_i) { - struct AV1_Common_s *cm = &hw->pbi->common; + struct AV1_Common_s *cm = &hw->common; if (debug) pr_info("%s %d %p\n", __func__, __LINE__, hw->pbi); hw->frame_count = 0; @@ -1351,6 +1551,7 @@ int aom_bufmgr_init(struct AV1HW_s *hw, struct BuffInfo_s *buf_spec_i, hw->last_pts = 0; hw->last_pts_us64 = 0; + hw->last_timestamp = 0; hw->shift_byte_count = 0; hw->shift_byte_count_lo = 0; hw->shift_byte_count_hi = 0; @@ -2309,13 +2510,64 @@ static void init_buff_spec(struct AV1HW_s *hw, } } +static bool v4l_is_there_vframe_bound(struct AV1HW_s *hw) +{ + int i; + struct AV1_Common_s *const cm = &hw->common; + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + + for (i = 0; i < hw->used_buf_num; ++i) { + if (frame_bufs[i].buf.vframe_bound) + return true; + } + return false; +} + +static void v4l_mmu_buffer_release(struct AV1HW_s *hw) +{ + struct AV1_Common_s *const cm = &hw->common; + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + int i; + + /* release workspace */ + if (hw->bmmu_box) + decoder_bmmu_box_free_idx(hw->bmmu_box, + WORK_SPACE_BUF_ID); + /* + * it's only when vframe get back to driver, right now we can be sure + * that vframe and fd are related. if the playback exits, the capture + * requires the upper app to release when the fd is closed, and others + * buffers drivers are released by driver. + */ + for (i = 0; i < hw->used_buf_num; ++i) { + if (!frame_bufs[i].buf.vframe_bound) { + if (hw->bmmu_box) + decoder_bmmu_box_free_idx(hw->bmmu_box, + HEADER_BUFFER_IDX(hw->buffer_wrap[i])); + if (hw->mmu_box) + decoder_mmu_box_free_idx(hw->mmu_box, hw->buffer_wrap[i]); + + av1_print(hw, PRINT_FLAG_V4L_DETAIL, + "%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n", + __func__, i, hw->bmmu_box, hw->mmu_box); + } + } +} static void uninit_mmu_buffers(struct AV1HW_s *hw) { #ifndef MV_USE_FIXED_BUF dealloc_mv_bufs(hw); #endif + if (hw->is_used_v4l && + v4l_is_there_vframe_bound(hw)) { + if (get_double_write_mode(hw) != 0x10) { + v4l_mmu_buffer_release(hw); + return; + } + } + if (hw->mmu_box) decoder_mmu_box_free(hw->mmu_box); hw->mmu_box = NULL; @@ -2330,6 +2582,132 @@ static void uninit_mmu_buffers(struct AV1HW_s *hw) hw->bmmu_box = NULL; } +static int calc_luc_quantity(int lcu_size, u32 w, u32 h) +{ + int pic_width_64 = (w + 63) & (~0x3f); + int pic_height_32 = (h + 31) & (~0x1f); + int pic_width_lcu = (pic_width_64 % lcu_size) ? + pic_width_64 / lcu_size + 1 : pic_width_64 / lcu_size; + int pic_height_lcu = (pic_height_32 % lcu_size) ? + pic_height_32 / lcu_size + 1 : pic_height_32 / lcu_size; + + return pic_width_lcu * pic_height_lcu; +} + +static int v4l_alloc_and_config_pic(struct AV1HW_s *hw, + struct PIC_BUFFER_CONFIG_s *pic) +{ + int ret = -1; + int i = pic->index; + int dw_mode = get_double_write_mode_init(hw); + int lcu_total = calc_luc_quantity(hw->current_lcu_size, + hw->frame_width, hw->frame_height); +#ifdef MV_USE_FIXED_BUF + u32 mpred_mv_end = hw->work_space_buf->mpred_mv.buf_start + + hw->work_space_buf->mpred_mv.buf_size; +#ifdef USE_DYNAMIC_MV_BUFFER + int32_t MV_MEM_UNIT = (lcu_size == 128) ? (19*4*16) : (19*16); + int32_t mv_buffer_size = (lcu_total*MV_MEM_UNIT); +#else + int32_t mv_buffer_size = MAX_ONE_MV_BUFFER_SIZE; +#endif +#endif + struct vdec_v4l2_buffer *fb = NULL; + + if (i < 0) + return ret; + + ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); + if (ret < 0) { + av1_print(hw, 0, "[%d] AV1 get buffer fail.\n", + ((struct aml_vcodec_ctx *) (hw->v4l2_ctx))->id); + return ret; + } + + if (hw->mmu_enable) { + hw->m_BUF[i].header_addr = decoder_bmmu_box_get_phy_addr( + hw->bmmu_box, HEADER_BUFFER_IDX(hw->buffer_wrap[i])); + if (debug & AV1_DEBUG_BUFMGR_MORE) { + pr_info("MMU header_adr %d: %ld\n", + i, hw->m_BUF[i].header_addr); + } + } + +#ifdef MV_USE_FIXED_BUF + if ((hw->work_space_buf->mpred_mv.buf_start + + ((i + 1) * mv_buffer_size)) + <= mpred_mv_end) { +#endif + hw->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; + pic->cma_alloc_addr = fb->m.mem[0].addr; + if (fb->num_planes == 1) { + hw->m_BUF[i].start_adr = fb->m.mem[0].addr; + hw->m_BUF[i].luma_size = fb->m.mem[0].offset; + hw->m_BUF[i].size = fb->m.mem[0].size; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + pic->dw_y_adr = hw->m_BUF[i].start_adr; + pic->dw_u_v_adr = pic->dw_y_adr + hw->m_BUF[i].luma_size; + } else if (fb->num_planes == 2) { + hw->m_BUF[i].start_adr = fb->m.mem[0].addr; + hw->m_BUF[i].size = fb->m.mem[0].size; + hw->m_BUF[i].chroma_addr = fb->m.mem[1].addr; + hw->m_BUF[i].chroma_size = fb->m.mem[1].size; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + fb->m.mem[1].bytes_used = fb->m.mem[1].size; + pic->dw_y_adr = hw->m_BUF[i].start_adr; + pic->dw_u_v_adr = hw->m_BUF[i].chroma_addr; + } + + /* config frame buffer */ + if (hw->mmu_enable) + pic->header_adr = hw->m_BUF[i].header_addr; + + pic->BUF_index = i; + pic->lcu_total = lcu_total; + pic->mc_canvas_y = pic->index; + pic->mc_canvas_u_v = pic->index; + + if (dw_mode & 0x10) { + pic->mc_canvas_y = (pic->index << 1); + pic->mc_canvas_u_v = (pic->index << 1) + 1; + } + +#ifdef MV_USE_FIXED_BUF + pic->mpred_mv_wr_start_addr = + hw->work_space_buf->mpred_mv.buf_start + + (pic->index * mv_buffer_size); +#endif + +#ifdef DUMP_FILMGRAIN + if (pic->index == fg_dump_index) { + pic->fgs_table_adr = hw->fg_phy_addr; + pr_info("set buffer %d film grain table 0x%x\n", + pic->index, pic->fgs_table_adr); + } else +#endif + pic->fgs_table_adr = + hw->work_space_buf->fgs_table.buf_start + + (pic->index * FGS_TABLE_SIZE); + + if (debug) { + + pr_info("%s index %d BUF_index %d ", + __func__, pic->index, + pic->BUF_index); + pr_info("comp_body_size %x comp_buf_size %x ", + pic->comp_body_size, + pic->buf_size); + pr_info("mpred_mv_wr_start_adr %d\n", + pic->mpred_mv_wr_start_addr); + pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n", + pic->dw_y_adr, + pic->dw_u_v_adr); + } +#ifdef MV_USE_FIXED_BUF + } +#endif + return ret; +} static int config_pic(struct AV1HW_s *hw, struct PIC_BUFFER_CONFIG_s *pic_config) @@ -2375,7 +2753,6 @@ static int config_pic(struct AV1HW_s *hw, int mc_buffer_size_u_v = 0; int mc_buffer_size_u_v_h = 0; int dw_mode = get_double_write_mode_init(hw); - struct vdec_v4l2_buffer *fb = NULL; hw->lcu_total = lcu_total; @@ -2426,26 +2803,26 @@ static int config_pic(struct AV1HW_s *hw, /*!USE_SPEC_BUF_FOR_MMU_HEAD*/ if (hw->mmu_enable) { pic_config->header_adr = decoder_bmmu_box_get_phy_addr( - hw->bmmu_box, HEADER_BUFFER_IDX(pic_config->index)); + hw->bmmu_box, HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index])); #ifdef AOM_AV1_MMU_DW if (hw->dw_mmu_enable) { pic_config->header_dw_adr = decoder_bmmu_box_get_phy_addr( - hw->bmmu_box, DW_HEADER_BUFFER_IDX(pic_config->index)); + hw->bmmu_box, DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index])); } if (debug & AV1_DEBUG_BUFMGR_MORE) { pr_info("MMU dw header_adr (%d, %d) %d: %d\n", hw->dw_mmu_enable, - DW_HEADER_BUFFER_IDX(pic_config->index), - pic_config->index, + DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index]), + hw->buffer_wrap[pic_config->index], pic_config->header_dw_adr); } #endif if (debug & AV1_DEBUG_BUFMGR_MORE) { pr_info("MMU header_adr %d: %d\n", - pic_config->index, pic_config->header_adr); + hw->buffer_wrap[pic_config->index], pic_config->header_adr); } } #endif @@ -2458,39 +2835,17 @@ static int config_pic(struct AV1HW_s *hw, ) { #endif if (buf_size > 0) { - if (hw->is_used_v4l) { -#ifdef SUPPORT_V4L2 - ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); -#endif - if (ret) { - av1_print(hw, PRINT_FLAG_ERROR, - "[%d] get fb fail.\n", - ((struct aml_vcodec_ctx *) - (hw->v4l2_ctx))->id); - return ret; - } - - hw->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; -#ifdef SUPPORT_V4L2 - pic_config->cma_alloc_addr = fb->m.mem[0].addr; -#endif - av1_print(hw, PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l ref buf addr: 0x%x\n", - ((struct aml_vcodec_ctx *) - (hw->v4l2_ctx))->id, __func__, fb); - } else { - ret = decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, - VF_BUFFER_IDX(i), - buf_size, DRIVER_NAME, - &pic_config->cma_alloc_addr); - if (ret < 0) { - pr_info( - "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n", - VF_BUFFER_IDX(i), - buf_size - ); - return ret; - } + ret = decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, + VF_BUFFER_IDX(hw->buffer_wrap[i]), + buf_size, DRIVER_NAME, + &pic_config->cma_alloc_addr); + if (ret < 0) { + pr_info( + "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n", + VF_BUFFER_IDX(hw->buffer_wrap[i]), + buf_size + ); + return ret; } if (pic_config->cma_alloc_addr) @@ -2498,7 +2853,7 @@ static int config_pic(struct AV1HW_s *hw, else { pr_info( "decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n", - VF_BUFFER_IDX(i), + VF_BUFFER_IDX(hw->buffer_wrap[i]), buf_size ); return -1; @@ -2603,7 +2958,7 @@ static int vaom_dw_frame_mmu_map_size(struct AV1HW_s *hw) static void init_pic_list(struct AV1HW_s *hw) { int i; - struct AV1_Common_s *cm = &hw->pbi->common; + struct AV1_Common_s *cm = &hw->common; struct PIC_BUFFER_CONFIG_s *pic_config; struct vdec_s *vdec = hw_to_vdec(hw); @@ -2650,20 +3005,24 @@ static void init_pic_list(struct AV1HW_s *hw) pic_config->y_canvas_index = -1; pic_config->uv_canvas_index = -1; } - if (config_pic(hw, pic_config) < 0) { - if (debug) - av1_print(hw, 0, "Config_pic %d fail\n", - pic_config->index); - pic_config->index = -1; - break; - } pic_config->y_crop_width = hw->init_pic_w; pic_config->y_crop_height = hw->init_pic_h; pic_config->double_write_mode = get_double_write_mode(hw); + hw->buffer_wrap[i] = i; + + if (!hw->is_used_v4l) { + if (config_pic(hw, pic_config) < 0) { + if (debug) + av1_print(hw, 0, "Config_pic %d fail\n", + pic_config->index); + pic_config->index = -1; + break; + } - if (pic_config->double_write_mode && - (pic_config->double_write_mode & 0x20) == 0) { - set_canvas(hw, pic_config); + if (pic_config->double_write_mode && + (pic_config->double_write_mode & 0x20) == 0) { + set_canvas(hw, pic_config); + } } } for (; i < hw->used_buf_num; i++) { @@ -2671,6 +3030,7 @@ static void init_pic_list(struct AV1HW_s *hw) pic_config->index = -1; pic_config->BUF_index = -1; pic_config->mv_buf_index = -1; + hw->buffer_wrap[i] = i; if (vdec->parallel_dec == 1) { pic_config->y_canvas_index = -1; pic_config->uv_canvas_index = -1; @@ -2684,7 +3044,7 @@ static void init_pic_list(struct AV1HW_s *hw) static void init_pic_list_hw(struct AV1HW_s *hw) { int i; - struct AV1_Common_s *cm = &hw->pbi->common; + struct AV1_Common_s *cm = &hw->common; struct PIC_BUFFER_CONFIG_s *pic_config; /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, @@ -2739,7 +3099,7 @@ static void init_pic_list_hw(struct AV1HW_s *hw) static void dump_pic_list(struct AV1HW_s *hw) { - struct AV1_Common_s *const cm = &hw->pbi->common; + struct AV1_Common_s *const cm = &hw->common; struct PIC_BUFFER_CONFIG_s *pic_config; int i; for (i = 0; i < FRAME_BUFFERS; i++) { @@ -2786,27 +3146,14 @@ void av1_release_buf(AV1Decoder *pbi, RefCntBuffer *const buf) void av1_release_bufs(struct AV1HW_s *hw) { - /*struct AV1HW_s *hw = (struct AV1HW_s *)(pbi->private_data);*/ - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; int i; - if (!hw->mmu_enable) - return; for (i = 0; i < FRAME_BUFFERS; ++i) { if (frame_bufs[i].buf.vf_ref == 0 && frame_bufs[i].ref_count == 0 && frame_bufs[i].buf.index >= 0) { - //release_buffer_4k(&av1_mmumgr_m, i); - decoder_mmu_box_free_idx(hw->mmu_box, i); -#ifdef AOM_AV1_MMU_DW - //release_buffer_4k(&av1_mmumgr_dw, i); - if (hw->dw_mmu_enable) - decoder_mmu_box_free_idx(hw->mmu_box_dw, i); -#endif - av1_print(hw, AOM_DEBUG_HW_MORE, "%s, index %d\n", - __func__, i); - if (frame_bufs[i].buf.aux_data_buf) release_aux_data(hw, &frame_bufs[i].buf); } @@ -2815,8 +3162,8 @@ void av1_release_bufs(struct AV1HW_s *hw) static int config_pic_size(struct AV1HW_s *hw, unsigned short bit_depth) { - uint32_t data32; - struct AV1_Common_s *cm = &hw->pbi->common; + uint32_t data32; + struct AV1_Common_s *cm = &hw->common; struct PIC_BUFFER_CONFIG_s *cur_pic_config = &cm->cur_frame->buf; int losless_comp_header_size, losless_comp_body_size; #ifdef AOM_AV1_MMU_DW @@ -2918,7 +3265,7 @@ static int config_pic_size(struct AV1HW_s *hw, unsigned short bit_depth) static int config_mc_buffer(struct AV1HW_s *hw, unsigned short bit_depth, unsigned char inter_flag) { int32_t i; - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; PIC_BUFFER_CONFIG* cur_pic_config = &cm->cur_frame->buf; uint8_t scale_enable = 0; @@ -3061,7 +3408,7 @@ static void clear_mpred_hw(struct AV1HW_s *hw) static void config_mpred_hw(struct AV1HW_s *hw, unsigned char inter_flag) { - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; PIC_BUFFER_CONFIG *cur_pic_config = &cm->cur_frame->buf; //PIC_BUFFER_CONFIG *last_frame_pic_config = NULL; int i, j, pos, reg_i; @@ -3302,7 +3649,7 @@ static void config_mpred_hw(struct AV1HW_s *hw, unsigned char inter_flag) cm->current_frame.frame_type, cm->cur_frame->frame_type, cm->allow_ref_frame_mvs); - if (av1_frame_is_inter(&hw->pbi->common)) { + if (av1_frame_is_inter(&hw->common)) { if (cm->allow_ref_frame_mvs) { data32 |= (1 << 11); /*read enable*/ } @@ -3330,7 +3677,7 @@ static void config_sao_hw(struct AV1HW_s *hw, union param_u *params) !!!!!!!!!!!!!!!!!!!!!!!!!TODO .... !!!!!!!!!!! mem_map_mode, endian, get_double_write_mode */ - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; PIC_BUFFER_CONFIG* pic_config = &cm->cur_frame->buf; uint32_t data32; int32_t lcu_size = @@ -3339,6 +3686,8 @@ static void config_sao_hw(struct AV1HW_s *hw, union param_u *params) pic_config->lcu_total*lcu_size*lcu_size/2; int32_t mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff)>>16; //64k alignment + struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx; + av1_print(hw, AOM_DEBUG_HW_MORE, "[test.c] #### config_sao_hw ####, lcu_size %d\n", lcu_size); av1_print(hw, AOM_DEBUG_HW_MORE, @@ -3507,6 +3856,27 @@ static void config_sao_hw(struct AV1HW_s *hw, union param_u *params) WRITE_VREG(HEVC_DBLK_CFGB, data); } + /* swap uv */ + if (hw->is_used_v4l) { + if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) || + (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) + data32 &= ~(1 << 8); /* NV21 */ + else + data32 |= (1 << 8); /* NV12 */ + } + + /* + * [31:24] ar_fifo1_axi_thred + * [23:16] ar_fifo0_axi_thred + * [15:14] axi_linealign, 0-16bytes, 1-32bytes, 2-64bytes + * [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 + * [11:08] axi_lendian_C + * [07:04] axi_lendian_Y + * [3] reserved + * [2] clk_forceon + * [1] dw_disable:disable double write output + * [0] cm_disable:disable compress output + */ WRITE_VREG(HEVC_SAO_CTRL1, data32); if (get_double_write_mode(hw) & 0x10) { @@ -3539,6 +3909,25 @@ static void config_sao_hw(struct AV1HW_s *hw, union param_u *params) data32 &= (~0xF); data32 |= 0xf; /* valid only when double write only */ /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ + + /* swap uv */ + if (hw->is_used_v4l) { + if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) || + (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) + data32 |= (1 << 12); /* NV21 */ + else + data32 &= ~(1 << 12); /* NV12 */ + } + + /* + * [3:0] little_endian + * [5:4] address_format 00:linear 01:32x32 10:64x32 + * [7:6] reserved + * [9:8] Linear_LineAlignment 00:16byte 01:32byte 10:64byte + * [11:10] reserved + * [12] CbCr_byte_swap + * [31:13] reserved + */ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); #endif @@ -4070,7 +4459,7 @@ static int init_dblk_struc(struct AV1HW_s *hw) static void config_dblk_hw(struct AV1HW_s *hw) { AV1Decoder *pbi = hw->pbi; - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; loop_filter_info_n *lfi = hw->lfi; struct loopfilter *lf = hw->lf; struct segmentation_lf *seg_4lf = hw->seg_4lf; @@ -4251,7 +4640,7 @@ static void config_dblk_hw(struct AV1HW_s *hw) av1_print(hw, AOM_DEBUG_HW_MORE, "[test.c] av1_upscale_frame_init (run before every frame decoding start)\n"); av1_upscale_frame_init(pbi, - &pbi->common, &hw->aom_param); + pbi->common, &hw->aom_param); #endif // #ifdef AOM_AV1_UPSCALE_INIT //BuffInfo_t* buf_spec = pbi->work_space_buf; @@ -5026,6 +5415,7 @@ static int av1_local_init(struct AV1HW_s *hw) return -1; } #endif + hw->mv_buf_margin = mv_buf_margin; if (IS_4K_SIZE(hw->init_pic_w, hw->init_pic_h)) { hw->used_buf_num = MAX_BUF_NUM_LESS + dynamic_buf_num_margin; @@ -5035,6 +5425,9 @@ static int av1_local_init(struct AV1HW_s *hw) else hw->used_buf_num = max_buf_num + dynamic_buf_num_margin; + if (hw->is_used_v4l) + hw->used_buf_num = 9 + hw->dynamic_buf_num_margin; + if (hw->used_buf_num > MAX_BUF_NUM) hw->used_buf_num = MAX_BUF_NUM; if (hw->used_buf_num > FRAME_BUFFERS) @@ -5157,10 +5550,10 @@ static void set_canvas(struct AV1HW_s *hw, canvas_config_ex(pic_config->y_canvas_index, pic_config->dw_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hw->is_used_v4l ? 0 : 7); canvas_config_ex(pic_config->uv_canvas_index, pic_config->dw_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hw->is_used_v4l ? 0 : 7); #ifdef MULTI_INSTANCE_SUPPORT pic_config->canvas_config[0].phy_addr = @@ -5171,7 +5564,7 @@ static void set_canvas(struct AV1HW_s *hw, canvas_h; pic_config->canvas_config[0].block_mode = blkmode; - pic_config->canvas_config[0].endian = 7; + pic_config->canvas_config[0].endian = hw->is_used_v4l ? 0 : 7; pic_config->canvas_config[1].phy_addr = pic_config->dw_u_v_adr; @@ -5181,7 +5574,7 @@ static void set_canvas(struct AV1HW_s *hw, canvas_h; pic_config->canvas_config[1].block_mode = blkmode; - pic_config->canvas_config[1].endian = 7; + pic_config->canvas_config[1].endian = hw->is_used_v4l ? 0 : 7; #endif } } @@ -5199,6 +5592,16 @@ static void set_frame_info(struct AV1HW_s *hw, struct vframe_s *vf) ar = min_t(u32, hw->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + if (hw->is_used_v4l && hw->vf_dp.present_flag) { + struct aml_vdec_hdr_infos hdr; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + memset(&hdr, 0, sizeof(hdr)); + hdr.signal_type = vf->signal_type; + hdr.color_parms = hw->vf_dp; + vdec_v4l_set_hdr_infos(ctx, &hdr); + } } static int vav1_vf_states(struct vframe_states *states, void *op_arg) @@ -5247,21 +5650,23 @@ static struct vframe_s *vav1_vf_get(void *op_arg) if (kfifo_get(&hw->display_q, &vf)) { struct vframe_s *next_vf; uint8_t index = vf->index & 0xff; - if (index < hw->used_buf_num) { + if (index < hw->used_buf_num || + (vf->type & VIDTYPE_V4L_EOS)) { hw->vf_get_count++; if (debug & AOM_DEBUG_VFRAME) { - struct BufferPool_s *pool = hw->pbi->common.buffer_pool; + struct BufferPool_s *pool = hw->common.buffer_pool; struct PIC_BUFFER_CONFIG_s *pic = &pool->frame_bufs[index].buf; unsigned long flags; - lock_buffer_pool(hw->pbi->common.buffer_pool, flags); - av1_print(hw, AOM_DEBUG_VFRAME, "%s index 0x%x type 0x%x w/h %d/%d, aux size %d, pts %d, %lld\n", + lock_buffer_pool(hw->common.buffer_pool, flags); + av1_print(hw, AOM_DEBUG_VFRAME, "%s index 0x%x type 0x%x w/h %d/%d, aux size %d, pts %d, %lld, ts: %llu\n", __func__, vf->index, vf->type, vf->width, vf->height, pic->aux_data_size, vf->pts, - vf->pts_us64); - unlock_buffer_pool(hw->pbi->common.buffer_pool, flags); + vf->pts_us64, + vf->timestamp); + unlock_buffer_pool(hw->common.buffer_pool, flags); } if (kfifo_peek(&hw->display_q, &next_vf)) { @@ -5273,14 +5678,14 @@ static struct vframe_s *vav1_vf_get(void *op_arg) if (index == fg_dump_index) { unsigned long flags; int ii; - lock_buffer_pool(hw->pbi->common.buffer_pool, flags); + lock_buffer_pool(hw->common.buffer_pool, flags); pr_info("FGS_TABLE for buffer %d:\n", index); for (ii = 0; ii < FGS_TABLE_SIZE; ii++) { pr_info("%02x ", hw->fg_ptr[ii]); if (((ii+ 1) & 0xf) == 0) pr_info("\n"); } - unlock_buffer_pool(hw->pbi->common.buffer_pool, flags); + unlock_buffer_pool(hw->common.buffer_pool, flags); } #endif @@ -5302,30 +5707,35 @@ static void vav1_vf_put(struct vframe_s *vf, void *op_arg) kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); hw->vf_put_count++; if (debug & AOM_DEBUG_VFRAME) { - lock_buffer_pool(hw->pbi->common.buffer_pool, flags); - av1_print(hw, AOM_DEBUG_VFRAME, "%s index 0x%x type 0x%x w/h %d/%d, pts %d, %lld\n", + lock_buffer_pool(hw->common.buffer_pool, flags); + av1_print(hw, AOM_DEBUG_VFRAME, "%s index 0x%x type 0x%x w/h %d/%d, pts %d, %lld, ts: %llu\n", __func__, vf->index, vf->type, vf->width, vf->height, vf->pts, - vf->pts_us64); - unlock_buffer_pool(hw->pbi->common.buffer_pool, flags); + vf->pts_us64, + vf->timestamp); + unlock_buffer_pool(hw->common.buffer_pool, flags); } if (index < hw->used_buf_num) { - struct AV1_Common_s *cm = &hw->pbi->common; + struct AV1_Common_s *cm = &hw->common; struct BufferPool_s *pool = cm->buffer_pool; - lock_buffer_pool(hw->pbi->common.buffer_pool, flags); + lock_buffer_pool(hw->common.buffer_pool, flags); if ((debug & AV1_DEBUG_IGNORE_VF_REF) == 0) { if (pool->frame_bufs[index].buf.vf_ref > 0) pool->frame_bufs[index].buf.vf_ref--; } + + if (hw->is_used_v4l) + pool->frame_bufs[index].buf.vframe_bound = true; + if (hw->wait_buf) WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); hw->last_put_idx = index; hw->new_frame_displayed++; - unlock_buffer_pool(hw->pbi->common.buffer_pool, flags); + unlock_buffer_pool(hw->common.buffer_pool, flags); } } @@ -5334,7 +5744,7 @@ static int vav1_event_cb(int type, void *data, void *op_arg) { unsigned long flags; struct AV1HW_s *hw = (struct AV1HW_s *)op_arg; - struct AV1_Common_s *cm = &hw->pbi->common; + struct AV1_Common_s *cm = &hw->common; struct BufferPool_s *pool = cm->buffer_pool; if (type & VFRAME_EVENT_RECEIVER_RESET) { @@ -5359,7 +5769,7 @@ static int vav1_event_cb(int type, void *data, void *op_arg) (struct provider_aux_req_s *)data; unsigned char index; - lock_buffer_pool(hw->pbi->common.buffer_pool, flags); + lock_buffer_pool(hw->common.buffer_pool, flags); index = req->vf->index & 0xff; req->aux_buf = NULL; req->aux_size = 0; @@ -5387,7 +5797,7 @@ static int vav1_event_cb(int type, void *data, void *op_arg) req->dv_enhance_exist = 0; #endif } - unlock_buffer_pool(hw->pbi->common.buffer_pool, flags); + unlock_buffer_pool(hw->common.buffer_pool, flags); if (debug & AOM_DEBUG_AUX_DATA) av1_print(hw, 0, @@ -5410,7 +5820,7 @@ static int vav1_event_cb(int type, void *data, void *op_arg) void av1_inc_vf_ref(struct AV1HW_s *hw, int index) { - struct AV1_Common_s *cm = &hw->pbi->common; + struct AV1_Common_s *cm = &hw->common; if ((debug & AV1_DEBUG_IGNORE_VF_REF) == 0) { cm->buffer_pool->frame_bufs[index].buf.vf_ref++; @@ -5490,6 +5900,10 @@ static int frame_duration_adapt(struct AV1HW_s *hw, struct vframe_s *vf, u32 val static void update_vf_memhandle(struct AV1HW_s *hw, struct vframe_s *vf, struct PIC_BUFFER_CONFIG_s *pic) { + /* keeper not needed for v4l solution */ + if (hw->is_used_v4l) + return; + if (pic->index < 0) { vf->mem_handle = NULL; vf->mem_head_handle = NULL; @@ -5500,27 +5914,27 @@ static void update_vf_memhandle(struct AV1HW_s *hw, (debug & AOM_DEBUG_DW_DISP_MAIN) == 0) { vf->mem_handle = decoder_mmu_box_get_mem_handle( - hw->mmu_box_dw, pic->index); + hw->mmu_box_dw, hw->buffer_wrap[pic->index]); vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( hw->bmmu_box, - DW_HEADER_BUFFER_IDX(pic->BUF_index)); + DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index])); vf->mem_dw_handle = NULL; } else #endif { vf->mem_handle = decoder_mmu_box_get_mem_handle( - hw->mmu_box, pic->index); + hw->mmu_box, hw->buffer_wrap[pic->index]); vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( hw->bmmu_box, - HEADER_BUFFER_IDX(pic->BUF_index)); + HEADER_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index])); if (hw->double_write_mode == 3) vf->mem_dw_handle = decoder_bmmu_box_get_mem_handle( hw->bmmu_box, - VF_BUFFER_IDX(pic->BUF_index)); + VF_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index])); else vf->mem_dw_handle = NULL; } @@ -5530,7 +5944,7 @@ static void update_vf_memhandle(struct AV1HW_s *hw, } else { vf->mem_handle = decoder_bmmu_box_get_mem_handle( - hw->bmmu_box, VF_BUFFER_IDX(pic->BUF_index)); + hw->bmmu_box, VF_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index])); vf->mem_head_handle = NULL; vf->mem_dw_handle = NULL; /*vf->mem_head_handle = @@ -5545,9 +5959,11 @@ static int prepare_display_buf(struct AV1HW_s *hw, { struct vframe_s *vf = NULL; int stream_offset = pic_config->stream_offset; + struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx; + ulong nv_order = VIDTYPE_VIU_NV21; u32 pts_valid = 0, pts_us64_valid = 0; u32 frame_size; - int i, reclac_flag; + int i, reclac_flag = 0; av1_print(hw, AOM_DEBUG_VFRAME, "%s index = %d\r\n", __func__, pic_config->index); if (kfifo_get(&hw->newframe_q, &vf) == 0) { @@ -5555,6 +5971,13 @@ static int prepare_display_buf(struct AV1HW_s *hw, return -1; } + /* swap uv */ + if (hw->is_used_v4l) { + if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) || + (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M)) + nv_order = VIDTYPE_VIU_NV12; + } + if (pic_config->double_write_mode && (pic_config->double_write_mode & 0x20) == 0) set_canvas(hw, pic_config); @@ -5562,37 +5985,60 @@ static int prepare_display_buf(struct AV1HW_s *hw, display_frame_count[hw->index]++; if (vf) { if (!force_pts_unstable && (hw->av1_first_pts_ready)) { - if ((pic_config->pts == 0) || (pic_config->pts <= hw->last_pts)) { - for (i = (FRAME_BUFFERS - 1); i > 0; i--) { - if ((hw->last_pts == hw->frame_mode_pts_save[i]) || - (hw->last_pts_us64 == hw->frame_mode_pts64_save[i])) { - pic_config->pts = hw->frame_mode_pts_save[i - 1]; - pic_config->pts64 = hw->frame_mode_pts64_save[i - 1]; - break; + if (hw->is_used_v4l) { + if ((pic_config->timestamp == 0) || (pic_config->timestamp <= hw->last_timestamp)) { + for (i = (FRAME_BUFFERS - 1); i > 0; i--) { + if (hw->last_timestamp == hw->frame_mode_timestamp_save[i]) { + pic_config->timestamp = hw->frame_mode_timestamp_save[i - 1]; + break; + } + } + + if ((i == 0) || (pic_config->timestamp <= hw->last_timestamp)) { + av1_print(hw, AV1_DEBUG_OUT_PTS, + "no found timestamp %d, set 0. %d, %d\n", + i, pic_config->timestamp, hw->last_timestamp); + pic_config->timestamp = 0; } } - if ((i == 0) || (pic_config->pts <= hw->last_pts)) { - av1_print(hw, AV1_DEBUG_OUT_PTS, - "no found pts %d, set 0. %d, %d\n", - i, pic_config->pts, hw->last_pts); - pic_config->pts = 0; - pic_config->pts64 = 0; + } else { + if ((pic_config->pts == 0) || (pic_config->pts <= hw->last_pts)) { + for (i = (FRAME_BUFFERS - 1); i > 0; i--) { + if ((hw->last_pts == hw->frame_mode_pts_save[i]) || + (hw->last_pts_us64 == hw->frame_mode_pts64_save[i])) { + pic_config->pts = hw->frame_mode_pts_save[i - 1]; + pic_config->pts64 = hw->frame_mode_pts64_save[i - 1]; + break; + } + } + + if ((i == 0) || (pic_config->pts <= hw->last_pts)) { + av1_print(hw, AV1_DEBUG_OUT_PTS, + "no found pts %d, set 0. %d, %d\n", + i, pic_config->pts, hw->last_pts); + pic_config->pts = 0; + pic_config->pts64 = 0; + } } } } + if (hw->is_used_v4l) { vf->v4l_mem_handle = hw->m_BUF[pic_config->BUF_index].v4l_ref_buf_addr; - av1_print(hw, PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l mem handle: 0x%lx\n", - ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, - __func__, vf->v4l_mem_handle); + if (hw->mmu_enable) { + vf->mm_box.bmmu_box = hw->bmmu_box; + vf->mm_box.bmmu_idx = HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->BUF_index]); + vf->mm_box.mmu_box = hw->mmu_box; + vf->mm_box.mmu_idx = hw->buffer_wrap[pic_config->BUF_index]; + } } #ifdef MULTI_INSTANCE_SUPPORT if (vdec_frame_based(hw_to_vdec(hw))) { vf->pts = pic_config->pts; vf->pts_us64 = pic_config->pts64; + vf->timestamp = pic_config->timestamp; if (vf->pts != 0 || vf->pts_us64 != 0) { pts_valid = 1; pts_us64_valid = 1; @@ -5622,18 +6068,31 @@ static int prepare_display_buf(struct AV1HW_s *hw, } if (hw->av1_first_pts_ready) { - if (hw->frame_dur && ((vf->pts == 0) || (vf->pts_us64 == 0))) { - vf->pts = hw->last_pts + DUR2PTS(hw->frame_dur); - vf->pts_us64 = hw->last_pts_us64 + - (DUR2PTS(hw->frame_dur) * 100 / 9); - reclac_flag = 1; - } + if (hw->is_used_v4l) { + if (hw->frame_dur && (vf->timestamp == 0)) { + vf->timestamp = hw->last_timestamp + + hw->timestamp_duration; + } + + if (!close_to(vf->timestamp, (hw->last_timestamp + + hw->timestamp_duration), 100)) { + vf->timestamp = hw->last_timestamp + + hw->timestamp_duration; + } + } else { + if (hw->frame_dur && ((vf->pts == 0) || (vf->pts_us64 == 0))) { + vf->pts = hw->last_pts + DUR2PTS(hw->frame_dur); + vf->pts_us64 = hw->last_pts_us64 + + (DUR2PTS(hw->frame_dur) * 100 / 9); + reclac_flag = 1; + } - if (!close_to(vf->pts, (hw->last_pts + DUR2PTS(hw->frame_dur)), 100)) { - vf->pts = hw->last_pts + DUR2PTS(hw->frame_dur); - vf->pts_us64 = hw->last_pts_us64 + - (DUR2PTS(hw->frame_dur) * 100 / 9); - reclac_flag = 2; + if (!close_to(vf->pts, (hw->last_pts + DUR2PTS(hw->frame_dur)), 100)) { + vf->pts = hw->last_pts + DUR2PTS(hw->frame_dur); + vf->pts_us64 = hw->last_pts_us64 + + (DUR2PTS(hw->frame_dur) * 100 / 9); + reclac_flag = 2; + } } /* try find the closed pts in saved pts pool */ @@ -5655,18 +6114,21 @@ static int prepare_display_buf(struct AV1HW_s *hw, } } else { av1_print(hw, AV1_DEBUG_OUT_PTS, - "first pts %d change to save[%d] %d\n", + "first pts %d change to save[%d] %d, ts: %llu\n", vf->pts, hw->first_pts_index - 1, - hw->frame_mode_pts_save[hw->first_pts_index - 1]); + hw->frame_mode_pts_save[hw->first_pts_index - 1], + hw->frame_mode_timestamp_save[hw->first_pts_index - 1]); vf->pts = hw->frame_mode_pts_save[hw->first_pts_index - 1]; vf->pts_us64 = hw->frame_mode_pts64_save[hw->first_pts_index - 1]; + vf->timestamp = hw->frame_mode_timestamp_save[hw->first_pts_index - 1]; } hw->last_pts = vf->pts; hw->last_pts_us64 = vf->pts_us64; + hw->last_timestamp = vf->timestamp; hw->av1_first_pts_ready = true; av1_print(hw, AV1_DEBUG_OUT_PTS, - "av1 output slice type %d, dur %d, pts %d, pts64 %lld\n", - pic_config->slice_type, hw->frame_dur, vf->pts, vf->pts_us64); + "av1 output slice type %d, dur %d, pts %d, pts64 %lld, ts: %llu\n", + pic_config->slice_type, hw->frame_dur, vf->pts, vf->pts_us64, vf->timestamp); fill_frame_info(hw, pic_config, frame_size, vf->pts); @@ -5839,31 +6301,38 @@ static int notify_v4l_eos(struct vdec_s *vdec) { struct AV1HW_s *hw = (struct AV1HW_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; + struct vframe_s *vf = &hw->vframe_dummy; + struct vdec_v4l2_buffer *fb = NULL; + int index = INVALID_IDX; + ulong expires; if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - av1_print(hw, 0, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; + expires = jiffies + msecs_to_jiffies(2000); + while (INVALID_IDX == (index = v4l_get_free_fb(hw))) { + if (time_after(jiffies, expires) || + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) + break; } - if (v4l_get_fb(hw->v4l2_ctx, &fb)) { - pr_err("[%d] get fb fail.\n", ctx->id); - return -1; + if (index == INVALID_IDX) { + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) { + pr_err("[%d] EOS get free buff fail.\n", ctx->id); + return -1; + } } - vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = (unsigned long)fb; - vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->type |= VIDTYPE_V4L_EOS; + vf->timestamp = ULONG_MAX; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb : + hw->m_BUF[index].v4l_ref_buf_addr; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - av1_print(hw, AOM_DEBUG_HW_MORE, "[%d] AV1 EOS notify.\n", ctx->id); + av1_print(hw, PRINT_FLAG_V4L_DETAIL, + "[%d] AV1 EOS notify.\n", ctx->id); } return 0; @@ -5889,10 +6358,68 @@ static void get_rpm_param(union param_u *params) pr_info("leave %s\r\n", __func__); } +#ifdef CHANGE_REMOVED +static int recycle_mmu_buf_tail(struct AV1HW_s *hw, + bool check_dma) +{ + struct AV1_Common_s *const cm = &hw->common; + + hw->used_4k_num = + READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; + + av1_print(hw, 0, "pic index %d page_start %d\n", + cm->cur_fb_idx_mmu, hw->used_4k_num); + + if (check_dma) + hevc_mmu_dma_check(hw_to_vdec(hw)); + + decoder_mmu_box_free_idx_tail( + hw->mmu_box, + hw->buffer_wrap[cm->cur_fb_idx_mmu], + hw->used_4k_num); + + cm->cur_fb_idx_mmu = INVALID_IDX; + hw->used_4k_num = -1; + + return 0; +} +#endif + +#ifdef CHANGE_REMOVED +static void av1_recycle_mmu_buf_tail(struct AV1HW_s *hw) +{ + struct AV1_Common_s *const cm = &hw->common; + if (hw->double_write_mode & 0x10) + return; + + if (cm->cur_fb_idx_mmu != INVALID_IDX) { + recycle_mmu_buf_tail(hw, + ((hw->used_4k_num == -1) && + hw->m_ins_flag) ? 1 : 0); + } +} +#endif + +static void av1_recycle_mmu_buf(struct AV1HW_s *hw) +{ + struct AV1_Common_s *const cm = &hw->common; + + if (hw->is_used_v4l) + return; + + if (hw->double_write_mode & 0x10) + return; + if (cm->cur_fb_idx_mmu != INVALID_IDX) { + decoder_mmu_box_free_idx(hw->mmu_box, + hw->buffer_wrap[cm->cur_fb_idx_mmu]); + + cm->cur_fb_idx_mmu = INVALID_IDX; + hw->used_4k_num = -1; + } +} static void dec_again_process(struct AV1HW_s *hw) { -#ifdef CHANGE_REMOVED amhevc_stop(); hw->dec_result = DEC_RESULT_AGAIN; if (hw->process_state == @@ -5904,12 +6431,11 @@ static void dec_again_process(struct AV1HW_s *hw) } reset_process_time(hw); vdec_schedule_work(&hw->work); -#endif } static void read_film_grain_reg(struct AV1HW_s *hw) { - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; int i; if (cm->cur_frame == NULL) { av1_print(hw, AOM_DEBUG_HW_MORE, "%s, cur_frame not exist!!!\n", __func__); @@ -5926,7 +6452,7 @@ static void read_film_grain_reg(struct AV1HW_s *hw) static void config_film_grain_reg(struct AV1HW_s *hw, int film_grain_params_ref_idx) { - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; int i; unsigned char found = 0; RefCntBuffer *buf; @@ -5972,19 +6498,21 @@ static void config_film_grain_reg(struct AV1HW_s *hw, int film_grain_params_ref_ void config_next_ref_info_hw(struct AV1HW_s *hw) { int j; - AV1_COMMON *const cm = &hw->pbi->common; + AV1_COMMON *const cm = &hw->common; av1_set_next_ref_frame_map(hw->pbi); if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2) WRITE_VREG(HEVC_PARSER_MEM_WR_ADDR, 0x11a0); else WRITE_VREG(HEVC_PARSER_MEM_WR_ADDR, 0x1000); - for (j = 0; j < 12; j++) { - unsigned int info = - av1_get_next_used_ref_info(cm, j); - WRITE_VREG(HEVC_PARSER_MEM_RW_DATA, info); - av1_print(hw, AOM_DEBUG_HW_MORE, - "config next ref info %d 0x%x\n", j, info); + + for (j = 0; j < 12; j++) { + unsigned int info = + av1_get_next_used_ref_info(cm, j); + + WRITE_VREG(HEVC_PARSER_MEM_RW_DATA, info); + av1_print(hw, AOM_DEBUG_HW_MORE, + "config next ref info %d 0x%x\n", j, info); } } @@ -6288,7 +6816,7 @@ static void config_mcrcc_axi_hw_nearest_ref(struct AV1HW_s *hw) uint32_t refcanvas_array[2]; uint32_t orderhint_bits; unsigned char is_inter; - AV1_COMMON *cm = &hw->pbi->common; + AV1_COMMON *cm = &hw->common; PIC_BUFFER_CONFIG *curr_pic_config; int32_t curr_orderhint; int cindex0 = LAST_FRAME; @@ -6300,7 +6828,7 @@ static void config_mcrcc_axi_hw_nearest_ref(struct AV1HW_s *hw) WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); // reset mcrcc - is_inter = av1_frame_is_inter(&hw->pbi->common); //((pbi->common.frame_type != KEY_FRAME) && (!pbi->common.intra_only)) ? 1 : 0; + is_inter = av1_frame_is_inter(&hw->common); //((pbi->common.frame_type != KEY_FRAME) && (!pbi->common.intra_only)) ? 1 : 0; if ( !is_inter ) { // I-PIC //WRITE_VREG(HEVCD_MCRCC_CTL1, 0x1); // remove reset -- disables clock WRITE_VREG(HEVCD_MCRCC_CTL2, 0xffffffff); // Replace with current-frame canvas @@ -6395,7 +6923,8 @@ int av1_continue_decoding(struct AV1HW_s *hw, int obu_type) #if 1 //def CHANGE_DONE AV1Decoder *pbi = hw->pbi; - AV1_COMMON *const cm = &pbi->common; + AV1_COMMON *const cm = pbi->common; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); int i; av1_print(hw, AOM_DEBUG_HW_MORE, @@ -6423,6 +6952,9 @@ int av1_continue_decoding(struct AV1HW_s *hw, int obu_type) hw->has_keyframe = 1; on_no_keyframe_skiped = 0; + if (hw->is_used_v4l && ctx->param_sets_from_ucode) + hw->res_ch_flag = 0; + //pre_decode_idx = pbi->decode_idx; if (pbi->bufmgr_proc_count == 0 || hw->one_compressed_data_done) { @@ -6542,8 +7074,10 @@ int av1_continue_decoding(struct AV1HW_s *hw, int obu_type) __func__, hw->chunk->pts, hw->chunk->pts64); cur_pic_config->pts = hw->chunk->pts; cur_pic_config->pts64 = hw->chunk->pts64; + cur_pic_config->timestamp = hw->chunk->timestamp; hw->chunk->pts = 0; - hw->chunk->pts64 = 0; + hw->chunk->pts64 = 0; + hw->chunk->timestamp = 0; } #ifdef DUAL_DECODE #else @@ -6589,7 +7123,7 @@ int av1_continue_decoding(struct AV1HW_s *hw, int obu_type) } else { ret = 0; } - if (av1_frame_is_inter(&hw->pbi->common)) { + if (av1_frame_is_inter(&hw->common)) { //if ((pbi->common.frame_type != KEY_FRAME) && (!pbi->common.intra_only)) { #ifdef DUAL_DECODE #else @@ -6734,7 +7268,14 @@ int av1_continue_decoding(struct AV1HW_s *hw, int obu_type) if ((frame_bufs[i].ref_count == 0) && (frame_bufs[i].buf.vf_ref == 0) && (frame_bufs[i].buf.index != -1)) { - decoder_mmu_box_free_idx(hw->mmu_box, i); + if (pbi->is_used_v4l) { + struct internal_comp_buf *ibuf = + index_to_icomp_buf(pbi, i); + + decoder_mmu_box_free_idx(ibuf->mmu_box, i); + } else { + decoder_mmu_box_free_idx(pbi->mmu_box, i); + } } hw->last_put_idx = -1; } @@ -7244,7 +7785,7 @@ static int load_param(struct AV1HW_s *hw, union param_u *params, uint32_t dec_st params->p.enable_superres = (params->p.seq_flags >> 15) & 0x1; if (debug & AV1_DEBUG_BUFMGR_MORE) { - lock_buffer_pool(hw->pbi->common.buffer_pool, flags); + lock_buffer_pool(hw->common.buffer_pool, flags); pr_info("aom_param: (%d)\n", hw->pbi->decode_idx); //pbi->slice_idx++; for ( i = 0; i < (RPM_END-RPM_BEGIN); i++) { @@ -7252,7 +7793,7 @@ static int load_param(struct AV1HW_s *hw, union param_u *params, uint32_t dec_st if (((i + 1) & 0xf) == 0) pr_info("\n"); } - unlock_buffer_pool(hw->pbi->common.buffer_pool, flags); + unlock_buffer_pool(hw->common.buffer_pool, flags); } return head_type; } @@ -7265,12 +7806,61 @@ static int av1_postproc(struct AV1HW_s *hw) return av1_bufmgr_postproc(hw->pbi, hw->frame_decoded); } +static int vav1_get_ps_info(struct AV1HW_s *hw, struct aml_vdec_ps_infos *ps) +{ + int dw_mode = v4l_parser_get_double_write_mode(hw); + + ps->visible_width = hw->frame_width / get_double_write_ratio(hw, dw_mode); + ps->visible_height = hw->frame_height / get_double_write_ratio(hw, dw_mode); + ps->coded_width = ALIGN(hw->frame_width, 32) / get_double_write_ratio(hw, dw_mode); + ps->coded_height = ALIGN(hw->frame_height, 32) / get_double_write_ratio(hw, dw_mode); + ps->dpb_size = hw->used_buf_num; + + return 0; +} + + +static int v4l_res_change(struct AV1HW_s *hw) +{ + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + struct AV1_Common_s *const cm = &hw->common; + int ret = 0; + + if (ctx->param_sets_from_ucode && + hw->res_ch_flag == 0) { + struct aml_vdec_ps_infos ps; + + if ((cm->width != 0 && + cm->height != 0) && + (hw->frame_width != cm->width || + hw->frame_height != cm->height)) { + + av1_print(hw, 0, + "%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width, + cm->height, hw->frame_width, hw->frame_height); + + vav1_get_ps_info(hw, &ps); + vdec_v4l_set_ps_infos(ctx, &ps); + vdec_v4l_res_ch_event(ctx); + hw->v4l_params_parsed = false; + hw->res_ch_flag = 1; + hw->eos = 1; + //del_timer_sync(&pbi->timer); + notify_v4l_eos(hw_to_vdec(hw)); + ret = 1; + } + } + + return ret; +} + static irqreturn_t vav1_isr_thread_fn(int irq, void *data) { struct AV1HW_s *hw = (struct AV1HW_s *)data; unsigned int dec_status = hw->dec_status; int obu_type; - int ret; + int ret = 0; /*if (hw->wait_buf) * pr_info("set wait_buf to 0\r\n"); @@ -7294,7 +7884,7 @@ static irqreturn_t vav1_isr_thread_fn(int irq, void *data) hw->process_busy = 0; return IRQ_HANDLED; } else if (dec_status == AOM_AV1_DEC_PIC_END) { - struct AV1_Common_s *const cm = &hw->pbi->common; + struct AV1_Common_s *const cm = &hw->common; #if 1 u32 fg_reg0, fg_reg1, num_y_points, num_cb_points, num_cr_points; WRITE_VREG(HEVC_FGS_IDX, 0); @@ -7357,13 +7947,13 @@ static irqreturn_t vav1_isr_thread_fn(int irq, void *data) av1_print(hw, AOM_DEBUG_HW_MORE, "mmu free tail, index %d used_num 0x%x\n", cm->cur_frame->buf.index, used_4k_num); decoder_mmu_box_free_idx_tail(hw->mmu_box, - cm->cur_frame->buf.index, used_4k_num); + hw->buffer_wrap[cm->cur_frame->buf.index], used_4k_num); #ifdef AOM_AV1_MMU_DW if (hw->dw_mmu_enable) { used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS2) >> 16); decoder_mmu_box_free_idx_tail(hw->mmu_box_dw, - cm->cur_frame->buf.index, used_4k_num); + hw->buffer_wrap[cm->cur_frame->buf.index], used_4k_num); av1_print(hw, AOM_DEBUG_HW_MORE, "dw mmu free tail, index %d used_num 0x%x\n", cm->cur_frame->buf.index, used_4k_num); } @@ -7592,7 +8182,6 @@ static irqreturn_t vav1_isr_thread_fn(int irq, void *data) if (hw->m_ins_flag) reset_process_time(hw); - if (hw->process_state != PROC_STATE_SENDAGAIN ) { if (hw->one_compressed_data_done) { @@ -7604,7 +8193,36 @@ static irqreturn_t vav1_isr_thread_fn(int irq, void *data) } } - ret = av1_continue_decoding(hw, obu_type); + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + hw->frame_width = hw->common.seq_params.max_frame_width; + hw->frame_height = hw->common.seq_params.max_frame_height; + + if (!v4l_res_change(hw)) { + if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { + struct aml_vdec_ps_infos ps; + + pr_info("set ucode parse\n"); + vav1_get_ps_info(hw, &ps); + /*notice the v4l2 codec.*/ + vdec_v4l_set_ps_infos(ctx, &ps); + hw->v4l_params_parsed = true; + hw->postproc_done = 0; + hw->process_busy = 0; + dec_again_process(hw); + return IRQ_HANDLED; + } + } else { + hw->postproc_done = 0; + hw->process_busy = 0; + dec_again_process(hw); + return IRQ_HANDLED; + } + } + + av1_continue_decoding(hw, obu_type); hw->postproc_done = 0; hw->process_busy = 0; @@ -7626,7 +8244,7 @@ static irqreturn_t vav1_isr(int irq, void *data) int i; unsigned int dec_status; struct AV1HW_s *hw = (struct AV1HW_s *)data; - //struct AV1_Common_s *const cm = &hw->pbi->common; + //struct AV1_Common_s *const cm = &hw->common; uint debug_tag; WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); @@ -7773,11 +8391,14 @@ static void vav1_put_timer_func(unsigned long arg) if (hw->m_ins_flag) { if (hw_to_vdec(hw)->next_status == VDEC_STATUS_DISCONNECTED) { - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - pr_debug( - "vdec requested to be disconnected\n"); - return; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + if (!hw->is_used_v4l || ctx->is_stream_off) { + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + pr_debug("vdec requested to be disconnected\n"); + return; + } } } if (hw->init_flag == 0) { @@ -8141,6 +8762,9 @@ static int vav1_local_init(struct AV1HW_s *hw) INIT_KFIFO(hw->display_q); INIT_KFIFO(hw->newframe_q); + for (i = 0; i < FRAME_BUFFERS; i++) { + hw->buffer_wrap[i] = i; + } for (i = 0; i < VF_POOL_SIZE; i++) { const struct vframe_s *vf = &hw->vfpool[i]; @@ -8158,6 +8782,7 @@ static int vav1_local_init(struct AV1HW_s *hw) pr_info("set pts unstable\n"); } } + return ret; } @@ -8395,7 +9020,7 @@ static int amvdec_av1_mmu_init(struct AV1HW_s *hw) } hw->need_cache_size = buf_size * SZ_1M; hw->sc_start_time = get_jiffies_64(); - if (hw->mmu_enable && ((hw->double_write_mode & 0x10) == 0)) { + if (hw->mmu_enable) { int count = FRAME_BUFFERS; hw->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, hw->index /* * 2*/, count, @@ -8481,7 +9106,7 @@ static int amvdec_av1_probe(struct platform_device *pdev) return -ENOMEM; } - pbi = av1_decoder_create(&hw->av1_buffer_pool); //&aom_decoder; + pbi = av1_decoder_create(&hw->av1_buffer_pool, &hw->common); //&aom_decoder; hw->pbi = pbi; if (hw->pbi == NULL) { pr_info("\nammvdec_av1 device data allocation failed\n"); @@ -8489,7 +9114,7 @@ static int amvdec_av1_probe(struct platform_device *pdev) vfree(hw); return -ENOMEM; } - //hw->pbi->common.buffer_pool = &hw->av1_buffer_pool; //???? + //hw->common.buffer_pool = &hw->av1_buffer_pool; //???? hw->pbi->private_data = hw; hw->init_flag = 0; @@ -8617,9 +9242,9 @@ static int amvdec_av1_remove(struct platform_device *pdev) if (vdec->parallel_dec == 1) { for (i = 0; i < FRAME_BUFFERS; i++) { - vdec->free_canvas_ex(hw->pbi->common.buffer_pool-> + vdec->free_canvas_ex(hw->common.buffer_pool-> frame_bufs[i].buf.y_canvas_index, vdec->id); - vdec->free_canvas_ex(hw->pbi->common.buffer_pool-> + vdec->free_canvas_ex(hw->common.buffer_pool-> frame_bufs[i].buf.uv_canvas_index, vdec->id); } } @@ -8677,10 +9302,9 @@ static struct codec_profile_t amvdec_av1_profile = { static struct codec_profile_t amvdec_av1_profile_mult; -static unsigned char get_data_check_sum +static unsigned int get_data_check_sum (struct AV1HW_s *hw, int size) { - int jj; int sum = 0; u8 *data = NULL; @@ -8691,8 +9315,7 @@ static unsigned char get_data_check_sum data = ((u8 *)hw->chunk->block->start_virt) + hw->chunk->offset; - for (jj = 0; jj < size; jj++) - sum += data[jj]; + sum = crc32_le(0, data, size); if (!hw->chunk->block->is_mapped) codec_mm_unmap_phyaddr(data); @@ -8917,8 +9540,10 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (!hw->pic_list_init_done2 || hw->eos) return ret; + if (!hw->first_sc_checked && hw->mmu_enable) { int size = decoder_mmu_box_sc_check(hw->mmu_box, tvp); + hw->first_sc_checked = 1; av1_print(hw, 0, "av1 cached=%d need_size=%d speed= %d ms\n", size, (hw->need_cache_size >> PAGE_SHIFT), @@ -8937,7 +9562,31 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) ret = CORE_MASK_HEVC; else ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC; + } + + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode) { + if (hw->v4l_params_parsed) { + if ((ctx->cap_pool.in < hw->used_buf_num) && + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < + run_ready_min_buf_num) + ret = 0; + } else { + if ((hw->res_ch_flag == 1) && + ((ctx->state <= AML_STATE_INIT) || + (ctx->state >= AML_STATE_FLUSHING))) + ret = 0; + } + } else if (ctx->cap_pool.in < ctx->dpb_size) { + if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < + run_ready_min_buf_num) + ret = 0; } + } + if (ret) not_run_ready[hw->index] = 0; else @@ -8951,21 +9600,24 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) static void av1_frame_mode_pts_save(struct AV1HW_s *hw) { - unsigned int i, valid_pts_diff_cnt, pts_diff_sum; - unsigned int in_pts_diff, last_valid_pts_diff, calc_dur; + u64 i, valid_pts_diff_cnt, pts_diff_sum; + u64 in_pts_diff, last_valid_pts_diff, calc_dur; if ((hw->chunk == NULL) || (hw->frame_count && (hw->chunk->pts == 0)) || (hw->frame_mode_pts_save[0] == hw->chunk->pts)) return; av1_print(hw, AV1_DEBUG_OUT_PTS, - "run_front: pts %d, pts64 %lld\n", hw->chunk->pts, hw->chunk->pts64); + "run_front: pts %d, pts64 %lld, ts: %llu\n", + hw->chunk->pts, hw->chunk->pts64, hw->chunk->timestamp); for (i = (FRAME_BUFFERS - 1); i > 0; i--) { hw->frame_mode_pts_save[i] = hw->frame_mode_pts_save[i - 1]; hw->frame_mode_pts64_save[i] = hw->frame_mode_pts64_save[i - 1]; + hw->frame_mode_timestamp_save[i] = hw->frame_mode_timestamp_save[i - 1]; } hw->frame_mode_pts_save[0] = hw->chunk->pts; hw->frame_mode_pts64_save[0] = hw->chunk->pts64; + hw->frame_mode_timestamp_save[0] = hw->chunk->timestamp; if (hw->first_pts_index < ARRAY_SIZE(hw->frame_mode_pts_save)) hw->first_pts_index++; /* frame duration check, vdec_secure return for nts problem */ @@ -8973,13 +9625,23 @@ static void av1_frame_mode_pts_save(struct AV1HW_s *hw) return; valid_pts_diff_cnt = 0; pts_diff_sum = 0; + for (i = 0; i < FRAME_BUFFERS - 1; i++) { - if ((hw->frame_mode_pts_save[i] > hw->frame_mode_pts_save[i + 1]) && - (hw->frame_mode_pts_save[i + 1] != 0)) - in_pts_diff = hw->frame_mode_pts_save[i] - - hw->frame_mode_pts_save[i + 1]; - else - in_pts_diff = 0; + if (hw->is_used_v4l) { + if ((hw->frame_mode_timestamp_save[i] > hw->frame_mode_timestamp_save[i + 1]) && + (hw->frame_mode_timestamp_save[i + 1] != 0)) + in_pts_diff = hw->frame_mode_timestamp_save[i] + - hw->frame_mode_timestamp_save[i + 1]; + else + in_pts_diff = 0; + } else { + if ((hw->frame_mode_pts_save[i] > hw->frame_mode_pts_save[i + 1]) && + (hw->frame_mode_pts_save[i + 1] != 0)) + in_pts_diff = hw->frame_mode_pts_save[i] + - hw->frame_mode_pts_save[i + 1]; + else + in_pts_diff = 0; + } if (in_pts_diff < 100 || (valid_pts_diff_cnt && (!close_to(in_pts_diff, last_valid_pts_diff, 100)))) @@ -8991,10 +9653,12 @@ static void av1_frame_mode_pts_save(struct AV1HW_s *hw) pts_diff_sum += in_pts_diff; } + if (!valid_pts_diff_cnt) { av1_print(hw, 0, "checked no avaliable pts\n"); return; } + calc_dur = PTS2DUR(pts_diff_sum / valid_pts_diff_cnt); if ((!close_to(calc_dur, hw->frame_dur, 10)) && (calc_dur < 9601) && (calc_dur > 800)) { @@ -9005,6 +9669,11 @@ static void av1_frame_mode_pts_save(struct AV1HW_s *hw) if (hw->frame_count > FRAME_BUFFERS) hw->get_frame_dur = true; } + + if (hw->is_used_v4l) { + hw->timestamp_duration = + pts_diff_sum / valid_pts_diff_cnt; + } } static void run_front(struct vdec_s *vdec) @@ -9035,44 +9704,50 @@ static void run_front(struct vdec_s *vdec) av1_frame_mode_pts_save(hw); if (debug & PRINT_FLAG_VDEC_STATUS) { - /*int ii;*/ - av1_print(hw, 0, - "%s (%d): size 0x%x (0x%x 0x%x) sum 0x%x (%x %x %x %x %x) bytes 0x%x\n", - __func__, - hw->frame_count, size, - hw->chunk ? hw->chunk->size : 0, - hw->chunk ? hw->chunk->offset : 0, - hw->chunk ? ((vdec_frame_based(vdec) && - (debug & PRINT_FLAG_VDEC_STATUS)) ? - get_data_check_sum(hw, size) : 0) : 0, - READ_VREG(HEVC_STREAM_START_ADDR), - READ_VREG(HEVC_STREAM_END_ADDR), - READ_VREG(HEVC_STREAM_LEVEL), - READ_VREG(HEVC_STREAM_WR_PTR), - READ_VREG(HEVC_STREAM_RD_PTR), - hw->start_shift_bytes); -#if 0 if (vdec_frame_based(vdec) && hw->chunk) { u8 *data = NULL; if (!hw->chunk->block->is_mapped) data = codec_mm_vmap(hw->chunk->block->start + - hw->chunk->offset, 8); + hw->chunk->offset, size); else data = ((u8 *)hw->chunk->block->start_virt) + hw->chunk->offset; - av1_print_cont(hw, 0, "data adr %p:", - data); - for (ii = 0; ii < 8; ii++) - av1_print_cont(hw, 0, "%02x ", - data[ii]); + //print_hex_debug(data, size, size > 64 ? 64 : size); + av1_print(hw, 0, + "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", + __func__, size, get_data_check_sum(hw, size), + data[0], data[1], data[2], data[3], + data[4], data[5], data[size - 4], + data[size - 3], data[size - 2], + data[size - 1]); + av1_print(hw, 0, + "%s frm cnt (%d): chunk (0x%x 0x%x) (%x %x %x %x %x) bytes 0x%x\n", + __func__, hw->frame_count, hw->chunk->size, hw->chunk->offset, + READ_VREG(HEVC_STREAM_START_ADDR), + READ_VREG(HEVC_STREAM_END_ADDR), + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR), + hw->start_shift_bytes); if (!hw->chunk->block->is_mapped) codec_mm_unmap_phyaddr(data); + } else { + av1_print(hw, 0, + "%s (%d): size 0x%x (0x%x 0x%x) (%x %x %x %x %x) bytes 0x%x\n", + __func__, + hw->frame_count, size, + hw->chunk ? hw->chunk->size : 0, + hw->chunk ? hw->chunk->offset : 0, + READ_VREG(HEVC_STREAM_START_ADDR), + READ_VREG(HEVC_STREAM_END_ADDR), + READ_VREG(HEVC_STREAM_LEVEL), + READ_VREG(HEVC_STREAM_WR_PTR), + READ_VREG(HEVC_STREAM_RD_PTR), + hw->start_shift_bytes); } - av1_print_cont(hw, 0, "\r\n"); -#endif } if (vdec->mc_loaded) { /*firmware have load before, @@ -9160,15 +9835,71 @@ static void run(struct vdec_s *vdec, unsigned long mask, run_front(vdec); } -static void reset(struct vdec_s *vdec) +static void av1_decode_ctx_reset(struct AV1HW_s *hw) { + struct AV1_Common_s *const cm = &hw->common; + struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + int i; + + for (i = 0; i < FRAME_BUFFERS; ++i) { + frame_bufs[i].ref_count = 0; + frame_bufs[i].buf.vf_ref = 0; + frame_bufs[i].buf.decode_idx = 0; + frame_bufs[i].buf.cma_alloc_addr = 0; + frame_bufs[i].buf.index = i; + frame_bufs[i].buf.BUF_index = -1; + frame_bufs[i].buf.mv_buf_index = -1; + } + for (i = 0; i < MV_BUFFER_NUM; i++) { + if (hw->m_mv_BUF[i].start_adr) { + hw->m_mv_BUF[i].used_flag = 0; + } + } + + hw->one_compressed_data_done = 0; + hw->config_next_ref_info_flag = 0; + hw->init_flag = 0; + hw->first_sc_checked = 0; + hw->fatal_error = 0; + hw->show_frame_num = 0; + hw->postproc_done = 0; + hw->process_busy = 0; + hw->process_state = 0; + hw->frame_decoded = 0; + hw->eos = 0; +} + +static void reset(struct vdec_s *vdec) +{ struct AV1HW_s *hw = (struct AV1HW_s *)vdec->private; - av1_print(hw, - PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + cancel_work_sync(&hw->work); + cancel_work_sync(&hw->set_clk_work); + + if (hw->stat & STAT_VDEC_RUN) { + amhevc_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->timer); + hw->stat &= ~STAT_TIMER_ARM; + } + + reset_process_time(hw); + + av1_bufmgr_ctx_reset(hw->pbi, &hw->av1_buffer_pool, &hw->common); + hw->pbi->private_data = hw; + + av1_local_uninit(hw); + if (vav1_local_init(hw) < 0) + av1_print(hw, 0, "%s local_init failed \r\n", __func__); + av1_decode_ctx_reset(hw); + + av1_print(hw, PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); } static irqreturn_t av1_irq_cb(struct vdec_s *vdec, int irq) @@ -9189,7 +9920,7 @@ static void av1_dump_state(struct vdec_s *vdec) { struct AV1HW_s *hw = (struct AV1HW_s *)vdec->private; - struct AV1_Common_s *const cm = &hw->pbi->common; + struct AV1_Common_s *const cm = &hw->common; int i; av1_print(hw, 0, "====== %s\n", __func__); @@ -9367,13 +10098,14 @@ static int ammvdec_av1_probe(struct platform_device *pdev) return -ENOMEM; } - hw->pbi = av1_decoder_create(&hw->av1_buffer_pool); //&aom_decoder; + hw->pbi = av1_decoder_create(&hw->av1_buffer_pool, &hw->common); //&aom_decoder; if (hw->pbi == NULL) { av1_print(hw, 0, "\nammvdec_av1 device data allocation failed\n"); release_dblk_struct(hw); vfree(hw); return -ENOMEM; } + hw->pbi->private_data = hw; /* the ctx from v4l2 driver. */ hw->v4l2_ctx = pdata->private; @@ -9494,6 +10226,21 @@ static int ammvdec_av1_probe(struct platform_device *pdev) hw->max_pic_h = av1_buf_height; av1_print(hw, 0, "use buf resolution\n"); } + + if (get_config_int(pdata->config, + "parm_v4l_codec_enable", + &config_val) == 0) + hw->is_used_v4l = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_buffer_margin", + &config_val) == 0) + hw->dynamic_buf_num_margin = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_canvas_mem_mode", + &config_val) == 0) + hw->mem_map_mode = config_val; #endif if (get_config_int(pdata->config, "HDRStaticInfo", &vf_dp.present_flag) == 0 @@ -9548,23 +10295,38 @@ static int ammvdec_av1_probe(struct platform_device *pdev) hw->max_pic_h = 4608; hw->double_write_mode = double_write_mode; } + + if (!hw->is_used_v4l) { + hw->mem_map_mode = mem_map_mode; + } + if (is_oversize(hw->max_pic_w, hw->max_pic_h)) { pr_err("over size: %dx%d, probe failed\n", hw->max_pic_w, hw->max_pic_h); return -1; } - hw->mmu_enable = 1; + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL || + hw->double_write_mode == 0x10) + hw->mmu_enable = 0; + else + hw->mmu_enable = 1; + video_signal_type = hw->video_signal_type; - hw->is_used_v4l = (((unsigned long) - hw->vav1_amstream_dec_info.param & 0x80) >> 7); - if (hw->is_used_v4l) { - hw->double_write_mode = 0x10; - hw->mmu_enable = 0; - hw->max_pic_w = 1920; - hw->max_pic_h = 1080; + if (pdata->sys_info) { + hw->vav1_amstream_dec_info = *pdata->sys_info; + if ((unsigned long) hw->vav1_amstream_dec_info.param + & 0x08) { + hw->low_latency_flag = 1; + } else + hw->low_latency_flag = 0; + } else { + hw->vav1_amstream_dec_info.width = 0; + hw->vav1_amstream_dec_info.height = 0; + hw->vav1_amstream_dec_info.rate = 30; } + #ifdef AOM_AV1_MMU_DW hw->dw_mmu_enable = get_double_write_mode_init(hw) & 0x20 ? 1 : 0; @@ -9655,15 +10417,14 @@ static int ammvdec_av1_remove(struct platform_device *pdev) if (vdec->parallel_dec == 1) { for (i = 0; i < FRAME_BUFFERS; i++) { vdec->free_canvas_ex - (hw->pbi->common.buffer_pool->frame_bufs[i].buf.y_canvas_index, + (hw->common.buffer_pool->frame_bufs[i].buf.y_canvas_index, vdec->id); vdec->free_canvas_ex - (hw->pbi->common.buffer_pool->frame_bufs[i].buf.uv_canvas_index, + (hw->common.buffer_pool->frame_bufs[i].buf.uv_canvas_index, vdec->id); } } - #ifdef DEBUG_PTS pr_info("pts missed %ld, pts hit %ld, duration %d\n", hw->pts_missed, hw->pts_hit, hw->frame_dur); |