vpp: add vframe src_fmt struct and function [1/1]
authorBrian Zhu <brian.zhu@amlogic.com>
Fri, 27 Dec 2019 18:24:22 +0000 (02:24 +0800)
committerBrian Zhu <brian.zhu@amlogic.com>
Mon, 30 Dec 2019 16:26:23 +0000 (00:26 +0800)
PD#SWPL-17729

Problem:
In new video pipeline, vfm map is changed. So vpp
can not get aux data from decode directly. It cause
the format of dv or hdr10+ content is incorrect.

Solution:
Add src_fmt struct in vframe, and whole src_fmt interface.
Let front-end updates src_fmt directly. Then vpp, dv or
hdr10+ module can get the sei data from it.

Verify:
Verifed on AC214

Change-Id: I96b7f84fa72c51ceec9e3ec28288ea0e7a726139
Signed-off-by: Brian Zhu <brian.zhu@amlogic.com>
drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c
drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c
drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c
drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h
drivers/amlogic/media/video_sink/video.c
drivers/amlogic/media/video_sink/video_receiver.c
include/linux/amlogic/media/vfm/vframe.h

index b31da72799d27d7cf3092931d128d858ac244088..4087634dc1ee05ce0c141c350133cb06ba4d2df1 100644 (file)
@@ -3990,7 +3990,7 @@ static int dvel_receiver_event_fun(int type, void *data, void *arg)
                setting_update_count = 0;
                crc_count = 0;
                crc_bypass_count = 0;
-               dolby_vision_el_disable = 0;
+               dolby_vision_el_disable = false;
                return -1;
        } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) {
                return RECEIVER_ACTIVE;
@@ -4007,7 +4007,7 @@ static int dvel_receiver_event_fun(int type, void *data, void *arg)
                setting_update_count = 0;
                crc_count = 0;
                crc_bypass_count = 0;
-               dolby_vision_el_disable = 0;
+               dolby_vision_el_disable = false;
        }
        return 0;
 }
@@ -4710,10 +4710,18 @@ bool is_dovi_frame(struct vframe_s *vf)
        char *p;
        unsigned int size = 0;
        unsigned int type = 0;
+       enum vframe_signal_fmt_e fmt;
 
        if (!vf)
                return false;
 
+       fmt = get_vframe_src_fmt(vf);
+       if (fmt == VFRAME_SIGNAL_FMT_DOVI)
+               return true;
+
+       if (fmt != VFRAME_SIGNAL_FMT_INVALID)
+               return false;
+
        req.vf = vf;
        req.bot_flag = 0;
        req.aux_buf = NULL;
@@ -4731,9 +4739,10 @@ bool is_dovi_frame(struct vframe_s *vf)
                else
                        return 0;
        } else if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) {
-               vf_notify_provider_by_name(dv_provider,
-                                          VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
-                                          (void *)&req);
+               vf_notify_provider_by_name(
+                       dv_provider,
+                       VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
+                       (void *)&req);
                if (req.dv_enhance_exist)
                        return true;
                if (!req.aux_buf || !req.aux_size)
@@ -4760,6 +4769,17 @@ EXPORT_SYMBOL(is_dovi_frame);
 bool is_dovi_dual_layer_frame(struct vframe_s *vf)
 {
        struct provider_aux_req_s req;
+       enum vframe_signal_fmt_e fmt;
+
+       if (!vf)
+               return false;
+
+       fmt = get_vframe_src_fmt(vf);
+       /* valid src_fmt = DOVI or invalid src_fmt will check dual layer */
+       /* otherwise, it certainly is a non-dv vframe */
+       if ((fmt != VFRAME_SIGNAL_FMT_DOVI) &&
+           (fmt != VFRAME_SIGNAL_FMT_INVALID))
+               return false;
 
        req.vf = vf;
        req.bot_flag = 0;
@@ -6103,16 +6123,39 @@ int dolby_vision_parse_metadata(
                        dolby_vision_vf_add(vf, NULL);
                }
        } else if (vf && (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS)) {
-               /* check source format */
+               enum vframe_signal_fmt_e fmt;
+
                input_mode = INPUT_MODE_OTT;
+
                req.vf = vf;
                req.bot_flag = 0;
                req.aux_buf = NULL;
                req.aux_size = 0;
                req.dv_enhance_exist = 0;
-               vf_notify_provider_by_name(dv_provider,
-                                          VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
-                                          (void *)&req);
+
+               /* check source format */
+               fmt = get_vframe_src_fmt(vf);
+               if ((fmt == VFRAME_SIGNAL_FMT_DOVI) ||
+                   (fmt == VFRAME_SIGNAL_FMT_INVALID)) {
+                       u32 sei_size = 0;
+                       char *sei;
+
+                       vf_notify_provider_by_name(
+                               dv_provider,
+                               VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
+                               (void *)&req);
+                       /* use aux date first, if invaild, use sei_ptr */
+                       if ((!req.aux_buf || !req.aux_size) &&
+                           (fmt == VFRAME_SIGNAL_FMT_DOVI)) {
+                               sei = (char *)get_sei_from_src_fmt(
+                                       vf, &sei_size);
+                               if (sei && sei_size) {
+                                       req.aux_buf = sei;
+                                       req.aux_size = sei_size;
+                               }
+                       }
+               }
+
                if (debug_dolby & 1 && req.aux_buf && req.aux_size)
                        pr_dolby_dbg("dvbldec get aux data %p %x\n",
                                req.aux_buf, req.aux_size);
@@ -6313,7 +6356,7 @@ int dolby_vision_parse_metadata(
                        (el_flag && !mel_flag &&
                        ((dolby_vision_flags & FLAG_CERTIFICAION) == 0))) {
                        el_flag = 0;
-                       dolby_vision_el_disable = 1;
+                       dolby_vision_el_disable = true;
                }
                if (src_format != FORMAT_DOVI) {
                        el_flag = 0;
@@ -6920,7 +6963,6 @@ EXPORT_SYMBOL(dolby_vision_parse_metadata);
 /* 3: found match el     */
 int dolby_vision_wait_metadata(struct vframe_s *vf)
 {
-       struct provider_aux_req_s req;
        struct vframe_s *el_vf;
        int ret = 0;
        unsigned int mode = dolby_vision_mode;
@@ -6946,20 +6988,7 @@ int dolby_vision_wait_metadata(struct vframe_s *vf)
                        return 1;
        }
 
-       if (vf) {
-               req.vf = vf;
-               req.bot_flag = 0;
-               req.aux_buf = NULL;
-               req.aux_size = 0;
-               req.dv_enhance_exist = 0;
-
-               if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS)
-                       vf_notify_provider_by_name(
-                               dv_provider,
-                               VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
-                               (void *)&req);
-       }
-       if (vf && req.dv_enhance_exist) {
+       if (is_dovi_dual_layer_frame(vf)) {
                el_vf = dvel_vf_peek();
                while (el_vf) {
                        if (debug_dolby & 2)
index 81a43811d34e7a00f18b34e09b57f6ad77277945..7a88e1abadebddadc37b1ccc61ef49fab163dc4a 100644 (file)
@@ -672,14 +672,22 @@ void hdr10_plus_parser_metadata(struct vframe_s *vf)
                req.aux_size = 0;
                req.dv_enhance_exist = 0;
                req.low_latency = 0;
-
-               vf_notify_provider_by_name("vdec.h265.00",
+               if (get_vframe_src_fmt(vf) ==
+                   VFRAME_SIGNAL_FMT_HDR10PLUS) {
+                       size = 0;
+                       req.aux_buf = (char *)get_sei_from_src_fmt(vf, &size);
+                       req.aux_size = size;
+               } else {
+                       vf_notify_provider_by_name(
+                               "vdec.h265.00",
                                VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
                                (void *)&req);
-               if (!req.aux_buf)
-                       vf_notify_provider_by_name("decoder",
+                       if (!req.aux_buf)
+                               vf_notify_provider_by_name(
+                               "decoder",
                                VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
                                (void *)&req);
+               }
                if (req.aux_buf && req.aux_size) {
                        p = req.aux_buf;
                        while (p < req.aux_buf
index c5abbe572570141c181fd1cb5f2162af93fd2e08..f49e9603cfa2d22be960dfcc0378c8d8684412ee 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/file.h>
 #include <linux/amlogic/media/canvas/canvas_mgr.h>
 #include <linux/amlogic/media/vfm/amlogic_fbc_hook_v1.h>
+#include "../../common/vfm/vfm.h"
 
 #define V4LVIDEO_MODULE_NAME "v4lvideo"
 
@@ -42,6 +43,9 @@
 #define V4LVIDEO_DEVICE_NAME   "v4lvideo"
 #define DUR2PTS(x) ((x) - ((x) >> 4))
 
+static atomic_t global_set_cnt = ATOMIC_INIT(0);
+static u32 alloc_sei = 1;
+
 #define V4L2_CID_USER_AMLOGIC_V4LVIDEO_BASE  (V4L2_CID_USER_BASE + 0x1100)
 
 static unsigned int video_nr_base = 30;
@@ -802,6 +806,78 @@ struct vframe_s *v4lvideo_get_vf(int fd)
        return vf;
 }
 
+static s32 v4lvideo_release_sei_data(struct vframe_s *vf)
+{
+       void *p;
+       s32 ret = -2;
+       u32 size = 0;
+
+       if (!vf)
+               return ret;
+
+       p = get_sei_from_src_fmt(vf, &size);
+       if (p) {
+               vfree(p);
+               atomic_dec(&global_set_cnt);
+       }
+       ret = clear_vframe_src_fmt(vf);
+       return ret;
+}
+
+static s32 v4lvideo_import_sei_data(
+       struct vframe_s *vf,
+       struct vframe_s *dup_vf,
+       char *provider)
+{
+       struct provider_aux_req_s req;
+       s32 ret = -2;
+       char *p;
+
+       if (!vf || !dup_vf || !provider || !alloc_sei)
+               return ret;
+
+       req.vf = vf;
+       req.bot_flag = 0;
+       req.aux_buf = NULL;
+       req.aux_size = 0;
+       req.dv_enhance_exist = 0;
+       vf_notify_provider_by_name(
+               provider,
+               VFRAME_EVENT_RECEIVER_GET_AUX_DATA,
+               (void *)&req);
+
+       if (req.aux_buf && req.aux_size) {
+               p = vmalloc(req.aux_size);
+               if (p) {
+                       memcpy(p, req.aux_buf, req.aux_size);
+                       ret = update_vframe_src_fmt(
+                               dup_vf, (void *)p, (u32)req.aux_size,
+                               req.dv_enhance_exist ? true : false);
+                       if (!ret) {
+                               /* FIXME: work around for sei/el out of sync */
+                               if ((dup_vf->src_fmt.fmt ==
+                                    VFRAME_SIGNAL_FMT_SDR) &&
+                                   !strcmp(provider, "dvbldec"))
+                                       dup_vf->src_fmt.fmt =
+                                               VFRAME_SIGNAL_FMT_DOVI;
+                               atomic_inc(&global_set_cnt);
+                       } else {
+                               vfree(p);
+                       }
+               } else {
+                       ret = update_vframe_src_fmt(
+                               dup_vf, NULL, 0, false);
+               }
+       } else {
+               ret = update_vframe_src_fmt(dup_vf, NULL, 0, false);
+       }
+       if (alloc_sei & 2)
+               pr_info("import sei: provider:%s, vf:%p, dup_vf:%p, req.aux_buf:%p, req.aux_size:%d, req.dv_enhance_exist:%d, vf->src_fmt.fmt:%d\n",
+                       provider, vf, dup_vf,
+                       req.aux_buf, req.aux_size,
+                       req.dv_enhance_exist, dup_vf->src_fmt.fmt);
+       return ret;
+}
 /* ------------------------------------------------------------------
  * DMA and thread functions
  * ------------------------------------------------------------------
@@ -818,6 +894,8 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 
        dprintk(dev, 2, "%s\n", __func__);
 
+       dev->provider_name = NULL;
+
        dprintk(dev, 2, "returning from %s\n", __func__);
 
        return 0;
@@ -1052,6 +1130,8 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
                dprintk(dev, 1,
                        "vidioc_qbuf: vf is NULL, at the start of playback\n");
        }
+
+       v4lvideo_release_sei_data(&file_private_data->vf);
        init_file_private_data(file_private_data);
        fput(file_vf);
 
@@ -1070,6 +1150,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
        struct file_private_data *file_private_data = NULL;
        u64 pts_us64 = 0;
        u64 pts_tmp;
+       char *provider_name = NULL;
 
        mutex_lock(&dev->mutex_input);
        buf = v4l2q_peek(&dev->input_queue);
@@ -1088,6 +1169,21 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
        vf = vf_get(dev->vf_receiver_name);
        if (!vf)
                return -EAGAIN;
+
+       if (!dev->provider_name) {
+               provider_name = vf_get_provider_name(
+                       dev->vf_receiver_name);
+               while (provider_name) {
+                       if (!vf_get_provider_name(provider_name))
+                               break;
+                       provider_name =
+                               vf_get_provider_name(provider_name);
+               }
+               dev->provider_name = provider_name;
+               pr_info("v4lvideo: provider name: %s\n",
+                       dev->provider_name ? dev->provider_name : "NULL");
+       }
+
        get_count++;
        vf->omx_index = dev->frame_num;
        dev->am_parm.signal_type = vf->signal_type;
@@ -1111,6 +1207,10 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
        }
        file_private_data->vf = *vf;
        file_private_data->vf_p = vf;
+       v4lvideo_import_sei_data(
+               vf, &file_private_data->vf,
+               dev->provider_name);
+
        //pr_err("dqbuf: file_private_data=%p, vf=%p\n", file_private_data, vf);
        v4l2q_push(&dev->display_queue, file_private_data);
        fput(file_vf);
@@ -1347,6 +1447,7 @@ static int v4lvideo_file_release(struct inode *inode, struct file *file)
        if (file_private_data) {
                if (file_private_data->is_keep)
                        vf_free(file_private_data);
+               v4lvideo_release_sei_data(&file_private_data->vf);
                memset(file_private_data, 0, sizeof(struct file_private_data));
                kfree((u8 *)file_private_data);
                file->private_data = NULL;
@@ -1364,7 +1465,7 @@ static const struct file_operations v4lvideo_file_fops = {
 int v4lvideo_alloc_fd(int *fd)
 {
        struct file *file = NULL;
-       struct file_private_data *private_date = NULL;
+       struct file_private_data *private_data = NULL;
        int file_fd = get_unused_fd_flags(O_CLOEXEC);
 
        if (file_fd < 0) {
@@ -1372,19 +1473,19 @@ int v4lvideo_alloc_fd(int *fd)
                return -ENODEV;
        }
 
-       private_date = kzalloc(sizeof(*private_date), GFP_KERNEL);
-       if (!private_date) {
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
                put_unused_fd(file_fd);
                pr_err("v4lvideo_alloc_fd: private_date fail\n");
                return -ENOMEM;
        }
-       init_file_private_data(private_date);
+       init_file_private_data(private_data);
 
        file = anon_inode_getfile("v4lvideo_file",
                                  &v4lvideo_file_fops,
-                                 private_date, 0);
+                                 private_data, 0);
        if (IS_ERR(file)) {
-               kfree((u8 *)private_date);
+               kfree((u8 *)private_data);
                put_unused_fd(file_fd);
                pr_err("v4lvideo_alloc_fd: anon_inode_getfile fail\n");
                return -ENODEV;
@@ -1394,12 +1495,75 @@ int v4lvideo_alloc_fd(int *fd)
        return 0;
 }
 
-static struct class_attribute ion_video_class_attrs[] = {
+static ssize_t sei_cnt_show(
+       struct class *class, struct class_attribute *attr, char *buf)
+{
+       ssize_t r;
+       int cnt;
+
+       cnt = atomic_read(&global_set_cnt);
+       r = sprintf(buf, "allocated sei buffer cnt: %d\n", cnt);
+       return r;
+}
+
+static ssize_t sei_cnt_store(
+       struct class *class,
+       struct class_attribute *attr,
+       const char *buf, size_t count)
+{
+       ssize_t r;
+       int val;
+
+       r = kstrtoint(buf, 0, &val);
+       if (r < 0)
+               return -EINVAL;
+
+       pr_info("set sei_cnt val:%d\n", val);
+       atomic_set(&global_set_cnt, val);
+       return count;
+}
+
+static ssize_t alloc_sei_show(
+       struct class *class, struct class_attribute *attr, char *buf)
+{
+       return sprintf(buf, "alloc sei: %d\n", alloc_sei);
+}
+
+static ssize_t alloc_sei_store(
+       struct class *class,
+       struct class_attribute *attr,
+       const char *buf, size_t count)
+{
+       ssize_t r;
+       int val;
+
+       r = kstrtoint(buf, 0, &val);
+       if (r < 0)
+               return -EINVAL;
+
+       if (val > 0)
+               alloc_sei = val;
+       else
+               alloc_sei = 0;
+       pr_info("set alloc_sei val:%d\n", alloc_sei);
+       return count;
+}
+
+static struct class_attribute v4lvideo_class_attrs[] = {
+       __ATTR(sei_cnt,
+              0664,
+              sei_cnt_show,
+              sei_cnt_store),
+       __ATTR(alloc_sei,
+              0664,
+              alloc_sei_show,
+              alloc_sei_store),
+       __ATTR_NULL
 };
 
 static struct class v4lvideo_class = {
        .name = "v4lvideo",
-       .class_attrs = ion_video_class_attrs,
+       .class_attrs = v4lvideo_class_attrs,
 };
 
 static int v4lvideo_open(struct inode *inode, struct file *file)
index b5c0540d7ce29a77bcf7b7a06fd286a0745a5c5f..95b9bc0598c71b382f6ca83e3ecfed79d417875a 100644 (file)
@@ -223,6 +223,7 @@ struct v4lvideo_dev {
        struct v4l2_buffer v4lvideo_input[V4LVIDEO_POOL_SIZE];
        struct v4l2_amlogic_parm am_parm;
        u8 first_frame;
+       char *provider_name;
 };
 
 enum vframe_source_type {
index 2bcd92bbbc91e070f0ba4d925c24f0ec3c11fda7..b0023ce8f5fb7debee80d17cba82e2ea055e8bd9 100644 (file)
@@ -1351,6 +1351,7 @@ u32 last_el_status;
 bool has_enhanced_layer(struct vframe_s *vf)
 {
        struct provider_aux_req_s req;
+       enum vframe_signal_fmt_e fmt;
 
        if (is_dolby_vision_el_disable() &&
            !for_dolby_vision_certification())
@@ -1358,11 +1359,20 @@ bool has_enhanced_layer(struct vframe_s *vf)
 
        if (!vf)
                return 0;
+
        if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS)
                return 0;
+
        if (!is_dolby_vision_on())
                return 0;
 
+       fmt = get_vframe_src_fmt(vf);
+       /* valid src_fmt = DOVI or invalid src_fmt will check dual layer */
+       /* otherwise, it certainly is a non-dv vframe */
+       if ((fmt != VFRAME_SIGNAL_FMT_DOVI) &&
+           (fmt != VFRAME_SIGNAL_FMT_INVALID))
+               return 0;
+
        req.vf = vf;
        req.bot_flag = 0;
        req.aux_buf = NULL;
@@ -5347,11 +5357,14 @@ static int  get_display_info(void *data)
        return 0;
 }
 
-static struct vframe_s *get_dispbuf(void)
+static struct vframe_s *get_dispbuf(u8 layer_id)
 {
        struct vframe_s *dispbuf = NULL;
 
-       switch (glayer_info[0].display_path_id) {
+       if (layer_id >= MAX_VD_LAYERS)
+               return NULL;
+
+       switch (glayer_info[layer_id].display_path_id) {
        case VFM_PATH_DEF:
        case VFM_PATH_AMVIDEO:
                if (cur_dispbuf)
@@ -5644,6 +5657,134 @@ void pause_video(unsigned char pause_flag)
        atomic_set(&video_pause_flag, pause_flag ? 1 : 0);
 }
 EXPORT_SYMBOL(pause_video);
+
+/*********************************************************
+ * Vframe src fmt API
+ *********************************************************/
+#define signal_color_primaries ((vf->signal_type >> 16) & 0xff)
+#define signal_transfer_characteristic ((vf->signal_type >> 8) & 0xff)
+
+#define DV_SEI 0x01000000
+#define HDR10P 0x02000000
+
+static int check_media_sei(char *sei, u32 sei_size, u32 sei_type)
+{
+       int ret = 0;
+       char *p;
+       u32 type = 0, size;
+
+       if (!sei || (sei_size <= 8))
+               return ret;
+
+       p = sei;
+       while (p < sei + sei_size - 8) {
+               size = *p++;
+               size = (size << 8) | *p++;
+               size = (size << 8) | *p++;
+               size = (size << 8) | *p++;
+               type = *p++;
+               type = (type << 8) | *p++;
+               type = (type << 8) | *p++;
+               type = (type << 8) | *p++;
+
+               if (type == sei_type) {
+                       ret = 1;
+                       break;
+               }
+               p += size;
+       }
+       return ret;
+}
+
+s32 update_vframe_src_fmt(
+       struct vframe_s *vf, void *sei,
+       u32 size, bool dual_layer)
+{
+       if (!vf)
+               return -1;
+
+       vf->src_fmt.sei_magic_code = SEI_MAGIC_CODE;
+       vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_INVALID;
+       vf->src_fmt.sei_ptr = sei;
+       vf->src_fmt.sei_size = size;
+       vf->src_fmt.dual_layer = false;
+       if (((signal_transfer_characteristic == 14) ||
+            (signal_transfer_characteristic == 18)) &&
+           (signal_color_primaries == 9)) {
+               vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HLG;
+       } else if ((signal_transfer_characteristic == 0x30) &&
+                    ((signal_color_primaries == 9) ||
+                     (signal_color_primaries == 2))) {
+               if (check_media_sei(sei, size, HDR10P))
+                       vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10PLUS;
+               else /* TODO: if need switch to HDR10 */
+                       vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10;
+       } else if ((signal_transfer_characteristic == 16) &&
+                    ((signal_color_primaries == 9) ||
+                     (signal_color_primaries == 2))) {
+               vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_HDR10;
+       } else if (vf->type & VIDTYPE_MVC) {
+               vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_MVC;
+       }
+       if (sei && size &&
+           (vf->src_fmt.fmt == VFRAME_SIGNAL_FMT_INVALID)) {
+               if (dual_layer || check_media_sei(sei, size, DV_SEI)) {
+                       vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_DOVI;
+                       vf->src_fmt.dual_layer = dual_layer;
+               }
+       }
+       if (vf->src_fmt.fmt == VFRAME_SIGNAL_FMT_INVALID)
+               vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_SDR;
+       return 0;
+}
+EXPORT_SYMBOL(update_vframe_src_fmt);
+
+void *get_sei_from_src_fmt(struct vframe_s *vf, u32 *sei_size)
+{
+       if (!vf || !sei_size)
+               return NULL;
+
+       /* invaild src fmt case */
+       if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE)
+               return NULL;
+
+       *sei_size = vf->src_fmt.sei_size;
+       return vf->src_fmt.sei_ptr;
+}
+EXPORT_SYMBOL(get_sei_from_src_fmt);
+
+enum vframe_signal_fmt_e get_vframe_src_fmt(
+       struct vframe_s *vf)
+{
+       if (!vf)
+               return VFRAME_SIGNAL_FMT_INVALID;
+
+       /* invaild src fmt case */
+       if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE)
+               return VFRAME_SIGNAL_FMT_INVALID;
+
+       return vf->src_fmt.fmt;
+}
+EXPORT_SYMBOL(get_vframe_src_fmt);
+
+s32 clear_vframe_src_fmt(struct vframe_s *vf)
+{
+       if (!vf)
+               return -1;
+
+       /* invaild src fmt case */
+       if (vf->src_fmt.sei_magic_code != SEI_MAGIC_CODE)
+               return -1;
+
+       vf->src_fmt.sei_magic_code = 0;
+       vf->src_fmt.fmt = VFRAME_SIGNAL_FMT_INVALID;
+       vf->src_fmt.sei_ptr = NULL;
+       vf->src_fmt.sei_size = 0;
+       vf->src_fmt.dual_layer = false;
+       return 0;
+}
+EXPORT_SYMBOL(clear_vframe_src_fmt);
+
 /*********************************************************
  * Utilities
  *********************************************************/
@@ -6336,7 +6477,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
                                if (mvc_flag)
                                        process_3d_type |= MODE_3D_MVC;
                                vd_layer[0].property_changed = true;
-                               dispbuf = get_dispbuf();
+                               dispbuf = get_dispbuf(0);
                                if ((process_3d_type & MODE_3D_FA) &&
                                    dispbuf &&
                                    !dispbuf->trans_fmt)
@@ -7838,7 +7979,7 @@ static ssize_t threedim_mode_store(struct class *cla,
                        process_3d_type |= MODE_3D_MVC;
                vd_layer[0].property_changed = true;
 
-               dispbuf = get_dispbuf();
+               dispbuf = get_dispbuf(0);
                if ((process_3d_type & MODE_3D_FA) &&
                    dispbuf && !dispbuf->trans_fmt)
                        /*notify di 3d mode is frame alternative mode,1*/
@@ -7876,7 +8017,7 @@ static ssize_t frame_addr_show(struct class *cla, struct class_attribute *attr,
        struct vframe_s *dispbuf = NULL;
        unsigned int canvas0Addr;
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
        if (dispbuf) {
                canvas0Addr = get_layer_display_canvas(0);
                canvas_read(canvas0Addr & 0xff, &canvas);
@@ -7951,7 +8092,7 @@ static ssize_t frame_canvas_width_show(struct class *cla,
        u32 width[3];
        unsigned int canvas0Addr;
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
        if (dispbuf) {
                canvas0Addr = get_layer_display_canvas(0);
                canvas_read(canvas0Addr & 0xff, &canvas);
@@ -7976,7 +8117,7 @@ static ssize_t frame_canvas_height_show(struct class *cla,
        u32 height[3];
        unsigned int canvas0Addr;
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
        if (dispbuf) {
                canvas0Addr = get_layer_display_canvas(0);
                canvas_read(canvas0Addr & 0xff, &canvas);
@@ -7999,7 +8140,7 @@ static ssize_t frame_width_show(struct class *cla,
 {
        struct vframe_s *dispbuf = NULL;
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
 
        if ((hold_video == 1) &&
            ((glayer_info[0].display_path_id ==
@@ -8029,7 +8170,7 @@ static ssize_t frame_height_show(struct class *cla,
             VFM_PATH_DEF)))
                return sprintf(buf, "%d\n", cur_height);
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
        if (dispbuf) {
                if (dispbuf->type & VIDTYPE_COMPRESS)
                        return sprintf(buf, "%d\n", dispbuf->compHeight);
@@ -8045,7 +8186,7 @@ static ssize_t frame_format_show(struct class *cla,
        struct vframe_s *dispbuf = NULL;
        ssize_t ret = 0;
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
        if (dispbuf) {
                if ((dispbuf->type & VIDTYPE_TYPEMASK) ==
                    VIDTYPE_INTERLACE_TOP)
@@ -8070,7 +8211,7 @@ static ssize_t frame_aspect_ratio_show(struct class *cla,
 {
        struct vframe_s *dispbuf = NULL;
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
        if (dispbuf) {
                u32 ar = (dispbuf->ratio_control &
                        DISP_RATIO_ASPECT_RATIO_MASK) >>
@@ -8548,7 +8689,7 @@ static ssize_t pic_mode_info_show(struct class *cla,
        int ret = 0;
        struct vframe_s *dispbuf = NULL;
 
-       dispbuf = get_dispbuf();
+       dispbuf = get_dispbuf(0);
        if (dispbuf) {
                u32 adapted_mode = (dispbuf->ratio_control
                        & DISP_RATIO_ADAPTED_PICMODE) ? 1 : 0;
@@ -8578,6 +8719,51 @@ static ssize_t pic_mode_info_show(struct class *cla,
        return sprintf(buf, "NA\n");
 }
 
+static ssize_t src_fmt_show(
+       struct class *cla, struct class_attribute *attr, char *buf)
+{
+       int ret = 0;
+       struct vframe_s *dispbuf = NULL;
+       enum vframe_signal_fmt_e fmt;
+       void *sei_ptr;
+       u32 sei_size = 0;
+       static const char * const fmt_str[] = {
+               "SDR", "HDR10", "HDR10+", "HDR Prime", "HLG",
+               "Dolby Vison", "Dolby Vison Low latency", "MVC"
+       };
+
+       dispbuf = get_dispbuf(0);
+       ret += sprintf(buf + ret, "vd1 dispbuf: %p\n", dispbuf);
+       if (dispbuf) {
+               fmt = get_vframe_src_fmt(dispbuf);
+               if (fmt != VFRAME_SIGNAL_FMT_INVALID) {
+                       sei_ptr = get_sei_from_src_fmt(dispbuf, &sei_size);
+                       ret += sprintf(buf + ret, "fmt = %s\n",
+                               fmt_str[fmt]);
+                       ret += sprintf(buf + ret, "sei: %p, size: %d\n",
+                               sei_ptr, sei_size);
+               } else {
+                       ret += sprintf(buf + ret, "src_fmt is invaild\n");
+               }
+       }
+       dispbuf = get_dispbuf(1);
+       ret += sprintf(buf + ret, "vd2 dispbuf: %p\n", dispbuf);
+       if (dispbuf) {
+               fmt = get_vframe_src_fmt(dispbuf);
+               if (fmt != VFRAME_SIGNAL_FMT_INVALID) {
+                       sei_size = 0;
+                       sei_ptr = get_sei_from_src_fmt(dispbuf, &sei_size);
+                       ret += sprintf(buf + ret, "fmt=0x%s\n",
+                               fmt_str[fmt]);
+                       ret += sprintf(buf + ret, "sei: %p, size: %d\n",
+                               sei_ptr, sei_size);
+               } else {
+                       ret += sprintf(buf + ret, "src_fmt is invaild\n");
+               }
+       }
+       return ret;
+}
+
 static ssize_t video_inuse_show(struct class *class,
                        struct class_attribute *attr, char *buf)
 {
@@ -9516,6 +9702,7 @@ static struct class_attribute amvideo_class_attrs[] = {
        __ATTR_RO(vframe_ready_cnt),
        __ATTR_RO(video_layer1_state),
        __ATTR_RO(pic_mode_info),
+       __ATTR_RO(src_fmt),
        __ATTR(axis_pip,
               0664,
               videopip_axis_show,
index 1018772a9ab08de7dedf21434c4b653ffd8a0571..25db04de52b4c00ada0e69ae7f560f8c0c219487 100644 (file)
@@ -333,6 +333,7 @@ static struct vframe_s *recv_common_dequeue_frame(
        struct vframe_s *vf = NULL;
        struct vframe_s *toggle_vf = NULL;
        s32 drop_count = -1;
+       enum vframe_signal_fmt_e fmt;
 
        if (!ins) {
                pr_err("recv_common_dequeue_frame error, empty ins\n");
@@ -352,7 +353,11 @@ static struct vframe_s *recv_common_dequeue_frame(
                        dolby_vision_check_hdr10plus(vf);
                        dolby_vision_check_hlg(vf);
                }
-               if (vf_peek("dvel")) {
+
+               fmt = get_vframe_src_fmt(vf);
+               if (((fmt == VFRAME_SIGNAL_FMT_DOVI) ||
+                    (fmt == VFRAME_SIGNAL_FMT_INVALID)) &&
+                   vf_peek("dvel")) {
                        req.vf = NULL;
                        req.bot_flag = 0;
                        req.aux_buf = NULL;
index eaf398f0cd66720d2b8d77655c83942e3a5c0f4f..99e8dafa7815dae3d7b112bc63faa64a9316e0eb 100644 (file)
@@ -281,6 +281,29 @@ enum vframe_disp_mode_e {
        VFRAME_DISP_MODE_OK,
 };
 
+enum vframe_signal_fmt_e {
+       VFRAME_SIGNAL_FMT_INVALID = -1,
+       VFRAME_SIGNAL_FMT_SDR = 0,
+       VFRAME_SIGNAL_FMT_HDR10 = 1,
+       VFRAME_SIGNAL_FMT_HDR10PLUS = 2,
+       VFRAME_SIGNAL_FMT_HDR10PRIME = 3,
+       VFRAME_SIGNAL_FMT_HLG = 4,
+       VFRAME_SIGNAL_FMT_DOVI = 5,
+       VFRAME_SIGNAL_FMT_DOVI_LL = 6,
+       VFRAME_SIGNAL_FMT_MVC = 7
+};
+
+#define SEI_MAGIC_CODE 0x53656920 /* SEI */
+
+/* signal format and sei data */
+struct vframe_src_fmt_s {
+       enum vframe_signal_fmt_e fmt;
+       u32 sei_magic_code;
+       void *sei_ptr;
+       u32 sei_size;
+       bool dual_layer;
+};
+
 enum pic_mode_provider_e {
        PIC_MODE_PROVIDER_DB = 0,
        PIC_MODE_PROVIDER_WSS,
@@ -461,6 +484,9 @@ struct vframe_s {
        bool rendered;
 
        struct codec_mm_box_s mm_box;
+
+       /* signal format and sei data */
+       struct vframe_src_fmt_s src_fmt;
 } /*vframe_t */;
 
 #if 0
@@ -471,4 +497,12 @@ int get_curren_frame_para(int *top, int *left, int *bottom, int *right);
 u8 is_vpp_postblend(void);
 
 void pause_video(unsigned char pause_flag);
+
+s32 update_vframe_src_fmt(
+       struct vframe_s *vf, void *sei,
+       u32 size, bool dual_layer);
+void *get_sei_from_src_fmt(struct vframe_s *vf, u32 *sei_size);
+enum vframe_signal_fmt_e get_vframe_src_fmt(struct vframe_s *vf);
+s32 clear_vframe_src_fmt(struct vframe_s *vf);
+
 #endif /* VFRAME_H */