amvideo2: add keep last frame [1/1]
authorrenjiang.han <renjiang.han@amlogic.com>
Tue, 12 Mar 2019 12:11:59 +0000 (20:11 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 20 Mar 2019 08:05:06 +0000 (00:05 -0800)
PD#OTT-2452

Problem:
Black screen in the middle of the cut.

Solution:
add keep last frame.

Verify:
on U212

Change-Id: Ib24f066e0682c7427024a74d9bf8cc9b8a310d62
Signed-off-by: renjiang.han <renjiang.han@amlogic.com>
drivers/amlogic/media/video_sink/video.c
drivers/amlogic/media/video_sink/video_keeper.c
drivers/amlogic/media/video_sink/video_priv.h
include/linux/amlogic/media/utils/amstream.h
include/linux/amlogic/media/video_sink/video.h
include/linux/amlogic/media/video_sink/video_keeper.h

index 79a0a96..15844da 100644 (file)
@@ -207,7 +207,7 @@ static struct vpp_frame_par_s *curpip_frame_par, *nextpip_frame_par;
 static struct vpp_frame_par_s pip_frame_parms[2];
 static struct vframe_s *cur_pipbuf;
 static struct vframe_s local_pip;
-static int _videopip_set_disable(u32 val);
+//int _videopip_set_disable(u32 val);
 #endif
 
 static struct device *amvideo_dev;
@@ -952,6 +952,7 @@ static u32 blackout;
 static u32 blackout = 1;
 #endif
 static u32 force_blackout;
+static u32 blackout_pip;
 
 /* disable video */
 
@@ -983,6 +984,12 @@ u32 get_video_enabled(void)
 {
        return video_enabled;
 }
+
+u32 get_videopip_enabled(void)
+{
+       return video2_enabled;
+}
+
 /* show first frame*/
 static bool show_first_frame_nosync;
 bool show_first_picture;
@@ -1154,7 +1161,12 @@ void safe_disble_videolayer(void)
 #endif
 }
 
-
+#ifdef VIDEO_PIP
+void safe_disble_videolayer2(void)
+{
+       DisableVideoLayer2();
+}
+#endif
 /*********************************************************/
 #ifdef VIDEO_PIP
 static inline struct vframe_s *pip_vf_peek(void)
@@ -3184,6 +3196,8 @@ static void pip_toggle_frame(struct vframe_s *vf)
        cur_pipbuf = vf;
        if (first_picture)
                pip_frame_ready_to_set = 1;
+       if (cur_pipbuf != &local_pip)
+               video_pip_keeper_new_frame_notify();
 }
 
 static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
@@ -8455,6 +8469,7 @@ static int video_receiver_event_fun(int type, void *data, void *private_data)
 static void pip_vf_unreg_provider(void)
 {
        ulong flags;
+       int keeped = 0;
 
        /* atomic_set(&video_unreg_flag, 1); */
        while (atomic_read(&video_inirq_flag) > 0)
@@ -8473,11 +8488,25 @@ static void pip_vf_unreg_provider(void)
        pip_frame_count = 0;
        spin_unlock_irqrestore(&lock, flags);
 
-       disable_videopip = VIDEO_DISABLE_FORNEXT;
-       DisableVideoLayer2();
+       if (blackout_pip | force_blackout) {
+               safe_disble_videolayer2();
+               try_free_keep_videopip(1);
+       }
+
+       if (cur_pipbuf)
+               keeped = vf_keep_pip_current_locked(cur_pipbuf, NULL);
+
+       if (keeped < 0) {/*keep failed.*/
+               pr_info("videopip keep failed, disable video now!\n");
+               safe_disble_videolayer2();
+               try_free_keep_videopip(1);
+       }
+
+       /*disable_videopip = VIDEO_DISABLE_FORNEXT;*/
+       /*DisableVideoLayer2();*/
 }
 
-static void pip_vf_light_unreg_provider(void)
+static void pip_vf_light_unreg_provider(int need_keep_frame)
 {
        ulong flags;
 
@@ -8492,6 +8521,11 @@ static void pip_vf_light_unreg_provider(void)
                cur_pipbuf = &local_pip;
        }
        spin_unlock_irqrestore(&lock, flags);
+       if (need_keep_frame) {
+               if (cur_pipbuf) {
+                       vf_keep_pip_current_locked(cur_pipbuf, NULL);
+               }
+       }
 }
 
 static int pip_receiver_event_fun(
@@ -8500,11 +8534,11 @@ static int pip_receiver_event_fun(
        if (type == VFRAME_EVENT_PROVIDER_UNREG)
                pip_vf_unreg_provider();
        else if (type == VFRAME_EVENT_PROVIDER_RESET)
-               pip_vf_light_unreg_provider();
+               pip_vf_light_unreg_provider(1);
        else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG)
-               pip_vf_light_unreg_provider();
+               pip_vf_light_unreg_provider(0);
        else if (type == VFRAME_EVENT_PROVIDER_REG)
-               pip_vf_light_unreg_provider();
+               pip_vf_light_unreg_provider(0);
        return 0;
 }
 #endif
@@ -8529,6 +8563,19 @@ u32 set_blackout_policy(int policy)
 }
 EXPORT_SYMBOL(set_blackout_policy);
 
+u32 get_blackout_pip_policy(void)
+{
+       return blackout_pip | force_blackout;
+}
+EXPORT_SYMBOL(get_blackout_pip_policy);
+
+u32 set_blackout_pip_policy(int policy)
+{
+       blackout_pip = policy;
+       return 0;
+}
+EXPORT_SYMBOL(set_blackout_pip_policy);
+
 u8 is_vpp_postblend(void)
 {
        if (READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) & VPP_VD1_POSTBLEND)
@@ -9021,27 +9068,28 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
                break;
 
        case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE:
+               put_user(disable_videopip, (u32 __user *)argp);
+               break;
        case AMSTREAM_IOC_GET_VIDEO_DISABLE:
-               if (layer->layer_id == 0)
-                       put_user(disable_video, (u32 __user *)argp);
-#ifdef VIDEO_PIP
-               else if (layer->layer_id == 1)
-                       put_user(disable_videopip, (u32 __user *)argp);
-#endif
+               put_user(disable_video, (u32 __user *)argp);
                break;
 
        case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE:
+               {
+                       u32 val;
+
+                       if (copy_from_user(&val, argp, sizeof(u32)) == 0)
+                               ret = _videopip_set_disable(val);
+                       else
+                               ret = -EFAULT;
+               }
+               break;
        case AMSTREAM_IOC_SET_VIDEO_DISABLE:
                {
                        u32 val;
 
                        if (copy_from_user(&val, argp, sizeof(u32)) == 0) {
-                               if (layer->layer_id == 0)
-                                       ret = _video_set_disable(val);
-#ifdef VIDEO_PIP
-                               else if (layer->layer_id == 1)
-                                       ret = _videopip_set_disable(val);
-#endif
+                               ret = _video_set_disable(val);
                        } else
                                ret = -EFAULT;
                }
@@ -9168,6 +9216,24 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
                }
                break;
 
+       case AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY:
+               if (copy_to_user(argp, &blackout_pip, sizeof(u32)) != 0)
+                       ret = -EFAULT;
+               break;
+
+       case AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY:{
+                       u32 mode;
+
+                       if (copy_from_user(&mode, argp, sizeof(u32)) == 0) {
+                               if (mode > 2)
+                                       ret = -EINVAL;
+                               else
+                                       blackout_pip = mode;
+                       } else
+                               ret = -EFAULT;
+               }
+               break;
+
        case AMSTREAM_IOC_CLEAR_VBUF:{
                        unsigned long flags;
                        while (atomic_read(&video_inirq_flag) > 0 ||
@@ -9184,6 +9250,19 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
                        safe_disble_videolayer();
                break;
 
+       case AMSTREAM_IOC_CLEAR_PIP_VBUF:{
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&lock, flags);
+                       cur_pipbuf = NULL;
+                       spin_unlock_irqrestore(&lock, flags);
+               }
+               break;
+
+       case AMSTREAM_IOC_CLEAR_VIDEOPIP:
+               safe_disble_videolayer2();
+               break;
+
        case AMSTREAM_IOC_SET_FREERUN_MODE:
                if (arg > FREERUN_DUR)
                        ret = -EFAULT;
@@ -9460,6 +9539,8 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg)
        case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT:
        case AMSTREAM_IOC_CLEAR_VBUF:
        case AMSTREAM_IOC_CLEAR_VIDEO:
+       case AMSTREAM_IOC_CLEAR_PIP_VBUF:
+       case AMSTREAM_IOC_CLEAR_VIDEOPIP:
        case AMSTREAM_IOC_SET_FREERUN_MODE:
        case AMSTREAM_IOC_DISABLE_SLOW_SYNC:
        case AMSTREAM_IOC_SET_3D_TYPE:
@@ -11389,7 +11470,7 @@ static ssize_t video_zorder_store(
 }
 
 #ifdef VIDEO_PIP
-static int _videopip_set_disable(u32 val)
+int _videopip_set_disable(u32 val)
 {
        if (val > VIDEO_DISABLE_FORNEXT)
                return -EINVAL;
@@ -11402,6 +11483,7 @@ static int _videopip_set_disable(u32 val)
                if ((disable_videopip == VIDEO_DISABLE_FORNEXT)
                        && cur_pipbuf && (cur_pipbuf != &local_pip))
                        pip_property_changed = 1;
+               try_free_keep_videopip(0);
        } else {
                if (cur_pipbuf && (cur_pipbuf != &local_pip))
                        EnableVideoLayer2();
@@ -11410,6 +11492,26 @@ static int _videopip_set_disable(u32 val)
        return 0;
 }
 
+static ssize_t videopip_blackout_policy_show(struct class *cla,
+                                         struct class_attribute *attr,
+                                         char *buf)
+{
+       return sprintf(buf, "%d\n", blackout_pip);
+}
+
+static ssize_t videopip_blackout_policy_store(struct class *cla,
+                                          struct class_attribute *attr,
+                                          const char *buf, size_t count)
+{
+       int r;
+
+       r = kstrtoint(buf, 0, &blackout_pip);
+       if (r < 0)
+               return -EINVAL;
+
+       return count;
+}
+
 static ssize_t videopip_axis_show(
        struct class *cla,
        struct class_attribute *attr,
@@ -11759,6 +11861,10 @@ static struct class_attribute amvideo_class_attrs[] = {
               0664,
               video_blackout_policy_show,
               video_blackout_policy_store),
+       __ATTR(blackout_pip_policy,
+                       0664,
+                       videopip_blackout_policy_show,
+                       videopip_blackout_policy_store),
        __ATTR(video_seek_flag,
               0664,
               video_seek_flag_show,
index ad8b02b..1c85320 100644 (file)
@@ -64,10 +64,15 @@ static DEFINE_MUTEX(video_keeper_mutex);
 
 static unsigned long keep_y_addr, keep_u_addr, keep_v_addr;
 static int keep_video_on;
+static int keep_video_pip_on;
 static int keep_id;
 static int keep_head_id;
+static int keep_pip_id;
+static int keep_pip_head_id;
 static int keep_el_id;
 static int keep_el_head_id;
+static int keep_pip_el_id;
+static int keep_pip_el_head_id;
 
 #define Y_BUFFER_SIZE   0x400000       /* for 1920*1088 */
 #define U_BUFFER_SIZE   0x100000       /* compatible with NV21 */
@@ -722,6 +727,28 @@ void try_free_keep_video(int flags)
 EXPORT_SYMBOL(try_free_keep_video);
 #endif
 
+void try_free_keep_videopip(int flags)
+{
+       int free_scatter_keeper = flags & 0x1;
+
+       if (keep_video_pip_on || free_scatter_keeper) {
+               /*pr_info("disbled keep video before free keep buffer.\n");*/
+               keep_video_pip_on = 0;
+               if (!get_videopip_enabled()) {
+                       /*if not disable video,changed to 2 for */
+                       pr_info("disbled videopip for next before free keep buffer!\n");
+                       _videopip_set_disable(VIDEO_DISABLE_FORNEXT);
+               } else if (get_videopip_enabled()) {
+                       safe_disble_videolayer2();
+               }
+       }
+       mutex_lock(&video_keeper_mutex);
+       video_pip_keeper_new_frame_notify();
+       free_alloced_keep_buffer();
+       mutex_unlock(&video_keeper_mutex);
+}
+EXPORT_SYMBOL(try_free_keep_videopip);
+
 static void video_keeper_update_keeper_mem(
        void *mem_handle, int type,
        int *id)
@@ -747,7 +774,6 @@ static int video_keeper_frame_keep_locked(
        struct vframe_s *cur_dispbuf_el)
 {
        int type = MEM_TYPE_CODEC_MM;
-
        if (cur_dispbuf->type & VIDTYPE_SCATTER)
                type = MEM_TYPE_CODEC_MM_SCATTER;
        video_keeper_update_keeper_mem(
@@ -775,6 +801,41 @@ static int video_keeper_frame_keep_locked(
        return (keep_id + keep_head_id) > 0;
 }
 
+static int video_pip_keeper_frame_keep_locked(
+       struct vframe_s *cur_dispbuf,
+       struct vframe_s *cur_dispbuf_el)
+{
+       int type = MEM_TYPE_CODEC_MM;
+
+       if (cur_dispbuf) {
+               if (cur_dispbuf->type & VIDTYPE_SCATTER)
+                       type = MEM_TYPE_CODEC_MM_SCATTER;
+               video_keeper_update_keeper_mem(
+                       cur_dispbuf->mem_handle,
+                       type,
+                       &keep_pip_id);
+               video_keeper_update_keeper_mem(
+                       cur_dispbuf->mem_head_handle,
+                       MEM_TYPE_CODEC_MM,
+                       &keep_pip_head_id);
+       }
+       if (cur_dispbuf_el) {
+               if (cur_dispbuf_el->type & VIDTYPE_SCATTER)
+                       type = MEM_TYPE_CODEC_MM_SCATTER;
+               else
+                       type = MEM_TYPE_CODEC_MM;
+               video_keeper_update_keeper_mem(
+                       cur_dispbuf_el->mem_handle,
+                       type,
+                       &keep_pip_el_id);
+               video_keeper_update_keeper_mem(
+                       cur_dispbuf_el->mem_head_handle,
+                       MEM_TYPE_CODEC_MM,
+                       &keep_pip_el_head_id);
+       }
+       return (keep_pip_id + keep_pip_head_id) > 0;
+}
+
 /*
  * call in irq.
  *don't used mutex
@@ -795,6 +856,7 @@ void video_keeper_new_frame_notify(void)
                codec_mm_keeper_unmask_keeper(keep_head_id, 120);
                keep_head_id = -1;
        }
+
        if (keep_el_id > 0) {
                /*wait 80 ms for vsync post.*/
                codec_mm_keeper_unmask_keeper(keep_el_id, 120);
@@ -808,6 +870,36 @@ void video_keeper_new_frame_notify(void)
        return;
 }
 
+void video_pip_keeper_new_frame_notify(void)
+{
+       if (keep_video_pip_on) {
+               pr_info("new frame show, pip free keeper\n");
+               keep_video_pip_on = 0;
+       }
+       if (keep_pip_id > 0) {
+               /*wait 80 ms for vsync post.*/
+               codec_mm_keeper_unmask_keeper(keep_pip_id, 120);
+               keep_pip_id = -1;
+       }
+       if (keep_pip_head_id > 0) {
+               /*wait 80 ms for vsync post.*/
+               codec_mm_keeper_unmask_keeper(keep_pip_head_id, 120);
+               keep_pip_head_id = -1;
+       }
+       if (keep_pip_el_id > 0) {
+               /*wait 80 ms for vsync post.*/
+               codec_mm_keeper_unmask_keeper(keep_pip_el_id, 120);
+               keep_pip_el_id = -1;
+       }
+       if (keep_pip_el_head_id > 0) {
+               /*wait 80 ms for vsync post.*/
+               codec_mm_keeper_unmask_keeper(keep_pip_el_head_id, 120);
+               keep_pip_el_head_id = -1;
+       }
+
+}
+
+
 static unsigned int vf_keep_current_locked(
        struct vframe_s *cur_dispbuf,
        struct vframe_s *cur_dispbuf_el)
@@ -1043,6 +1135,51 @@ static unsigned int vf_keep_current_locked(
        return 1;
 
 }
+
+unsigned int vf_keep_pip_current_locked(
+       struct vframe_s *cur_dispbuf,
+       struct vframe_s *cur_dispbuf_el)
+{
+       //u32 cur_index;
+       //u32 y_index, u_index, v_index;
+       //struct canvas_s cs0, cs1, cs2, cd;
+       int ret;
+
+       if (!cur_dispbuf) {
+               pr_info("keep pip exit without cur_dispbuf\n");
+               return 0;
+       }
+
+       if (get_video_debug_flags() &
+               DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) {
+               pr_info("flag: keep pip exit is skip current\n");
+               return 0;
+       }
+
+#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE
+       ext_frame_capture_poll(1); /*pull  if have capture end frame */
+#endif
+
+       if (get_blackout_pip_policy()) {
+               pr_info("policy: keep exit is skip current\n");
+               return 0;
+       }
+
+       ret = video_pip_keeper_frame_keep_locked(
+               cur_dispbuf,
+               cur_dispbuf_el);
+
+       if (ret) {
+               /*keeped ok with codec keeper!*/
+               pr_info("keep pip buffer on!\n");
+               keep_video_pip_on = 1;
+               return 1;
+       }
+
+       keep_video_pip_on = 0;
+       return 0;
+}
+
 unsigned int vf_keep_current(
        struct vframe_s *cur_dispbuf,
        struct vframe_s *cur_dispbuf2)
index f540771..34e19ee 100644 (file)
@@ -135,6 +135,7 @@ struct blend_setting_s {
 };
 
 void safe_disble_videolayer(void);
+void safe_disble_videolayer2(void);
 void update_cur_dispbuf(void *buf);
 
 /*for video related files only.*/
@@ -145,7 +146,9 @@ struct vframe_s *get_cur_dispbuf(void);
 
 int get_video_debug_flags(void);
 int _video_set_disable(u32 val);
+int _videopip_set_disable(u32 val);
 u32 get_video_enabled(void);
+u32 get_videopip_enabled(void);
 struct device *get_video_device(void);
 
 #ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE
index 3366382..e79e5b2 100644 (file)
@@ -90,6 +90,9 @@
 #define AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT  _IOR((_A_M), 0x21, int)
 #define AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT  _IOW((_A_M), 0x22, int)
 #define AMSTREAM_IOC_GET_VIDEO_LAYER1_ON  _IOR((_A_M), 0x23, int)
+/*video pip IOCTL command list*/
+#define AMSTREAM_IOC_CLEAR_VIDEOPIP _IOW((_A_M), 0x24, int)
+#define AMSTREAM_IOC_CLEAR_PIP_VBUF _IO((_A_M), 0x25)
 
 #define AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT  _IOR((_A_M), 0x2b, int)
 #define AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT  _IOW((_A_M), 0x2c, int)
  * 0x5c, struct userdata_buf_state_t)
  */
 
-
 #define AMSTREAM_IOC_VF_STATUS  _IOR((_A_M), 0x60, int)
+
+#define AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY   _IOR((_A_M), 0x62, int)
+#define AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY   _IOW((_A_M), 0x63, int)
+
 #define AMSTREAM_IOC_CLEAR_VBUF _IO((_A_M), 0x80)
 
 #define AMSTREAM_IOC_APTS_LOOKUP    _IOR((_A_M), 0x81, int)
index 04cb35b..6004ec2 100644 (file)
@@ -241,6 +241,8 @@ static inline int amvideo_notifier_call_chain(unsigned long val, void *v)
 int query_video_status(int type, int *value);
 u32 set_blackout_policy(int policy);
 u32 get_blackout_policy(void);
+u32 set_blackout_pip_policy(int policy);
+u32 get_blackout_pip_policy(void);
 void set_video_angle(u32 s_value);
 u32 get_video_angle(void);
 extern unsigned int DI_POST_REG_RD(unsigned int addr);
index 1594690..8794407 100644 (file)
 #include <linux/amlogic/media/vfm/vframe.h>
 
 void video_keeper_new_frame_notify(void);
+void video_pip_keeper_new_frame_notify(void);
 void try_free_keep_video(int flags);
+void try_free_keep_videopip(int flags);
 
 int __init video_keeper_init(void);
 void __exit video_keeper_exit(void);
 unsigned int vf_keep_current(
        struct vframe_s *cur_dispbuf,
        struct vframe_s *cur_dispbuf2);
+unsigned int vf_keep_pip_current_locked(
+       struct vframe_s *cur_dispbuf,
+       struct vframe_s *cur_dispbuf_el);
 
 #endif