116 files changed, 25845 insertions, 36303 deletions
diff --git a/drivers/stream_input/amports/amstream.c b/drivers/stream_input/amports/amstream.c index 51fd4b7..95ea2ae 100644 --- a/drivers/stream_input/amports/amstream.c +++ b/drivers/stream_input/amports/amstream.c @@ -30,10 +30,12 @@ #include <linux/delay.h> #include <linux/kthread.h> +#include <linux/amlogic/media/video_sink/video.h> #include <linux/amlogic/media/utils/amstream.h> #include <linux/amlogic/media/utils/vformat.h> #include <linux/amlogic/media/utils/aformat.h> +#include <linux/amlogic/media/video_sink/video.h> #include <linux/amlogic/media/frame_sync/tsync.h> #include <linux/amlogic/media/frame_sync/ptsserv.h> #include <linux/amlogic/media/frame_sync/timestamp.h> @@ -120,9 +122,6 @@ static int def_vstreambuf_sizeM = (DEFAULT_VIDEO_BUFFER_SIZE >> 20); static int slow_input; - - - /* #define DATA_DEBUG */ static int use_bufferlevelx10000 = 10000; static int reset_canuse_buferlevel(int level); @@ -430,6 +429,13 @@ static struct stream_port_s ports[] = { .fops = &vbuf_fops, .vformat = VFORMAT_HEVC, }, + { + .name = "amstream_dves_av1", + .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC | PORT_TYPE_FRAME | + PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC, + .fops = &vframe_fops, + .vformat = VFORMAT_AV1, + }, #endif #endif }; @@ -634,6 +640,19 @@ static int video_port_init(struct port_priv_s *priv, return r; } + if (vdec_dual(vdec)) { + if (port->vformat == VFORMAT_AV1) /* av1 dv only single layer */ + return 0; + r = vdec_init(vdec->slave, + (priv->vdec->sys_info->height * + priv->vdec->sys_info->width) > 1920*1088); + if (r < 0) { + pr_err("video_port_init %d, vdec_init failed\n", + __LINE__); + video_port_release(priv, pbuf, 2); + return r; + } + } return 0; } @@ -770,6 +789,9 @@ static int audio_port_reset(struct stream_port_s *port, r = pts_start(PTS_TYPE_AUDIO); + //clear audio break flag after reset + //tsync_audio_break(0); + pr_info("audio_port_reset done\n"); mutex_unlock(&amstream_mutex); return r; @@ -882,6 +904,16 @@ static void amstream_user_buffer_init(void) pubuf->buf_rp = 0; } +#if 1 +/*DDD*/ +struct stream_buf_s *get_vbuf(void) +{ + return &bufs[BUF_TYPE_VIDEO]; +} + +EXPORT_SYMBOL(get_vbuf); +#endif + static int amstream_port_init(struct port_priv_s *priv) { int r = 0; @@ -931,6 +963,7 @@ static int amstream_port_init(struct port_priv_s *priv) if (has_hevc_vdec()) { if (port->vformat == VFORMAT_HEVC || port->vformat == VFORMAT_AVS2 || + port->vformat == VFORMAT_AV1 || port->vformat == VFORMAT_VP9) pvbuf = &bufs[BUF_TYPE_HEVC]; } @@ -961,6 +994,7 @@ static int amstream_port_init(struct port_priv_s *priv) (port->pcr_inited == 1) ? port->pcrid : 0xffff, (port->vformat == VFORMAT_HEVC) || (port->vformat == VFORMAT_AVS2) || + (port->vformat == VFORMAT_AV1) || (port->vformat == VFORMAT_VP9), vdec); } else { @@ -1041,6 +1075,7 @@ static int amstream_port_release(struct port_priv_s *priv) if (has_hevc_vdec()) { if (port->vformat == VFORMAT_HEVC || port->vformat == VFORMAT_AVS2 + || port->vformat == VFORMAT_AV1 || port->vformat == VFORMAT_VP9) pvbuf = &bufs[BUF_TYPE_HEVC]; } @@ -1197,6 +1232,7 @@ static ssize_t amstream_mpts_write(struct file *file, const char *buf, if (has_hevc_vdec()) { pvbuf = (port->vformat == VFORMAT_HEVC || port->vformat == VFORMAT_AVS2 || + port->vformat == VFORMAT_AV1 || port->vformat == VFORMAT_VP9) ? &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; } else @@ -1588,6 +1624,7 @@ static int amstream_open(struct inode *inode, struct file *file) struct stream_port_s *s; struct stream_port_s *port = &ports[iminor(inode)]; struct port_priv_s *priv; + VDEC_PRINT_FUN_LINENO(__func__, __LINE__); #ifdef G12A_BRINGUP_DEBUG if (vdec_get_debug_flags() & 0xff0000) { pr_info("%s force open port %d\n", @@ -1600,6 +1637,8 @@ static int amstream_open(struct inode *inode, struct file *file) if (iminor(inode) >= amstream_port_num) return -ENODEV; + //pr_err("%s, port name %s\n", __func__, port->name); + //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid); mutex_lock(&amstream_mutex); if (port->type & PORT_TYPE_VIDEO) { @@ -1788,6 +1827,7 @@ static int amstream_release(struct inode *inode, struct file *file) if ((port->vformat == VFORMAT_HEVC || port->vformat == VFORMAT_AVS2 + || port->vformat == VFORMAT_AV1 || port->vformat == VFORMAT_VP9)) { vdec_poweroff(VDEC_HEVC); } else { @@ -2084,7 +2124,7 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) this->flag |= PORT_FLAG_AID; if (port_get_inited(priv)) { - tsync_audio_break(1); + //tsync_audio_break(1); amstream_change_avid(this); } } else @@ -2335,6 +2375,7 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) buf = (this->vformat == VFORMAT_HEVC || this->vformat == VFORMAT_AVS2 || + this->vformat == VFORMAT_AV1 || this->vformat == VFORMAT_VP9) ? &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; @@ -2595,17 +2636,99 @@ static long amstream_do_ioctl_new(struct port_priv_s *priv, r = -EINVAL; break; case AMSTREAM_IOC_GET_QOSINFO: + case AMSTREAM_IOC_GET_MVDECINFO: { - struct av_param_qosinfo_t __user *uarg = (void *)arg; - struct vframe_qos_s *qos_info = vdec_get_qos_info(); - if (this->type & PORT_TYPE_VIDEO) { - if (qos_info != NULL && copy_to_user((void *)uarg->vframe_qos, - qos_info, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s))) { - r = -EFAULT; + u32 slots = 0; + u32 struct_size = 0; + int vdec_id = 0; + struct vdec_s *vdec = NULL; + struct vframe_counter_s tmpbuf[QOS_FRAME_NUM] = {0}; + struct av_param_mvdec_t __user *uarg = (void *)arg; + + if (AMSTREAM_IOC_GET_MVDECINFO == cmd) { + if (get_user(vdec_id, &uarg->vdec_id) < 0 + || get_user(struct_size, &uarg->struct_size) < 0) { + r = -EFAULT; + break; + } + if (struct_size != sizeof(struct av_param_mvdec_t)) { + pr_err("pass in size %u != expected size %u\n", + struct_size, (u32)sizeof(struct av_param_mvdec_t)); + pr_err("App using old structue,we will support it.\n"); + //Here will add the compatibility for old structure when + //current struecture be substituded by newer structure. + //msleep(1000); let app handle it. break; } } + vdec = vdec_get_vdec_by_id(vdec_id); + if (!vdec) { + r = 0; + break; + } + + slots = vdec_get_frame_vdec(vdec, tmpbuf); + if (AMSTREAM_IOC_GET_MVDECINFO == cmd) + put_user(slots, &uarg->slots); + if (slots) { + if (AMSTREAM_IOC_GET_MVDECINFO == cmd) { + if (copy_to_user((void *)&uarg->comm, + &vdec->mvfrm->comm, + sizeof(struct vframe_comm_s))) { + r = -EFAULT; + break; + } + if (copy_to_user((void *)&uarg->minfo[0], + tmpbuf, + slots*sizeof(struct vframe_counter_s))) { + r = -EFAULT; + kfree(tmpbuf); + break; + } + }else { //For compatibility, only copy the qos + struct av_param_qosinfo_t __user *uarg = (void *)arg; + int i; + for (i=0; i<slots; i++) + if (copy_to_user((void *)&uarg->vframe_qos[i], + &tmpbuf[i].qos, + sizeof(struct vframe_qos_s))) { + r = -EFAULT; + break; + } + } + } else { + /*Vdec didn't produce item,wait for 10 ms to avoid user application + infinitely calling*/ + //msleep(10); let user app handle it. + } + } + break; + case AMSTREAM_IOC_GET_AVINFO: + { + struct av_param_info_t __user *uarg = (void *)arg; + struct av_info_t av_info; + int delay; + u32 avgbps; + if (this->type & PORT_TYPE_VIDEO) { + av_info.first_pic_coming = get_first_pic_coming(); + av_info.current_fps = -1; + av_info.vpts = timestamp_vpts_get(); + av_info.vpts_err = tsync_get_vpts_error_num(); + av_info.apts = timestamp_apts_get(); + av_info.apts_err = tsync_get_apts_error_num(); + av_info.ts_error = get_discontinue_counter(); + av_info.first_vpts = timestamp_firstvpts_get(); + av_info.toggle_frame_count = get_toggle_frame_count(); + delay = calculation_stream_delayed_ms( + PTS_TYPE_VIDEO, NULL, &avgbps); + if (delay >= 0) + av_info.dec_video_bps = avgbps; + else + av_info.dec_video_bps = 0; + } + if (copy_to_user((void *)&uarg->av_info, (void *)&av_info, + sizeof(struct av_info_t))) + r = -EFAULT; } break; default: @@ -2706,7 +2829,7 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, this->flag |= PORT_FLAG_AID; if (port_get_inited(priv)) { - tsync_audio_break(1); + //tsync_audio_break(1); amstream_change_avid(this); } } else @@ -2739,6 +2862,7 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, buf = (this->vformat == VFORMAT_HEVC || this->vformat == VFORMAT_AVS2 || + this->vformat == VFORMAT_AV1 || this->vformat == VFORMAT_VP9) ? &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; @@ -3409,6 +3533,8 @@ static long amstream_do_ioctl(struct port_priv_s *priv, case AMSTREAM_IOC_SET_PTR: case AMSTREAM_IOC_SYSINFO: case AMSTREAM_IOC_GET_QOSINFO: + case AMSTREAM_IOC_GET_MVDECINFO: + case AMSTREAM_IOC_GET_AVINFO: r = amstream_do_ioctl_new(priv, cmd, arg); break; default: @@ -3951,6 +4077,117 @@ static ssize_t audio_path_store(struct class *class, return size; } +ssize_t dump_stream_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *p_buf = buf; + + p_buf += sprintf(p_buf, "\nmdkir -p /data/tmp -m 777;setenforce 0;\n\n"); + p_buf += sprintf(p_buf, "video:\n\t echo 0 > /sys/class/amstream/dump_stream;\n"); + p_buf += sprintf(p_buf, "hevc :\n\t echo 4 > /sys/class/amstream/dump_stream;\n"); + + return p_buf - buf; +} + +#define DUMP_STREAM_FILE "/data/tmp/dump_stream.h264" +ssize_t dump_stream_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + struct stream_buf_s *p_buf; + int ret = 0, id = 0; + unsigned int stride, remain, level, vmap_size; + int write_size; + void *stbuf_vaddr; + unsigned long offset; + struct file *fp; + mm_segment_t old_fs; + loff_t fpos; + + ret = sscanf(buf, "%d", &id); + if (ret < 0) { + pr_info("paser buf id fail, default id = 0\n"); + id = 0; + } + if (id != BUF_TYPE_VIDEO && id != BUF_TYPE_HEVC) { + pr_info("buf id out of range, max %d, id %d, set default id 0\n", BUF_MAX_NUM - 1, id); + id = 0; + } + p_buf = get_stream_buffer(id); + if (!p_buf) { + pr_info("get buf fail, id %d\n", id); + return size; + } + if ((!p_buf->buf_size) || (p_buf->is_secure) || (!(p_buf->flag & BUF_FLAG_IN_USE))) { + pr_info("buf size %d, is_secure %d, in_use %d, it can not dump\n", + p_buf->buf_size, p_buf->is_secure, (p_buf->flag & BUF_FLAG_IN_USE)); + return size; + } + + level = stbuf_level(p_buf); + if (!level || level > p_buf->buf_size) { + pr_info("stream buf level %d, buf size %d, error return\n", level, p_buf->buf_size); + return size; + } + + fp = filp_open(DUMP_STREAM_FILE, O_CREAT | O_RDWR, 0666); + if (IS_ERR(fp)) { + fp = NULL; + pr_info("create dump stream file failed\n"); + return size; + } + + offset = p_buf->buf_start; + remain = level; + stride = SZ_1M; + vmap_size = 0; + fpos = 0; + pr_info("create file success, it will dump from addr 0x%lx, size 0x%x\n", offset, remain); + while (remain > 0) { + if (remain > stride) + vmap_size = stride; + else { + stride = remain; + vmap_size = stride; + } + + stbuf_vaddr = codec_mm_vmap(offset, vmap_size); + if (stbuf_vaddr == NULL) { + stride >>= 1; + pr_info("vmap fail change vmap stide size 0x%x\n", stride); + continue; + } + codec_mm_dma_flush(stbuf_vaddr, vmap_size, DMA_FROM_DEVICE); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + write_size = vfs_write(fp, stbuf_vaddr, vmap_size, &fpos); + if (write_size < vmap_size) { + write_size += vfs_write(fp, stbuf_vaddr + write_size, vmap_size - write_size, &fpos); + pr_info("fail write retry, total %d, write %d\n", vmap_size, write_size); + if (write_size < vmap_size) { + pr_info("retry fail, interrupt dump stream, break\n"); + break; + } + } + set_fs(old_fs); + vfs_fsync(fp, 0); + pr_info("vmap_size 0x%x dump size 0x%x\n", vmap_size, write_size); + + offset += vmap_size; + remain -= vmap_size; + codec_mm_unmap_phyaddr(stbuf_vaddr); + } + + filp_close(fp, current->files); + pr_info("dump stream buf end\n"); + + return size; +} + + + + static struct class_attribute amstream_class_attrs[] = { __ATTR_RO(ports), __ATTR_RO(bufs), @@ -3962,6 +4199,8 @@ static struct class_attribute amstream_class_attrs[] = { store_maxdelay), __ATTR(reset_audio_port, S_IRUGO | S_IWUSR | S_IWGRP, NULL, audio_path_store), + __ATTR(dump_stream, S_IRUGO | S_IWUSR | S_IWGRP, + dump_stream_show, dump_stream_store), __ATTR_NULL }; |