amvideo2: add keep last frame [1/1]

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>
This commit is contained in:
renjiang.han
2019-03-12 20:11:59 +08:00
committed by Luan Yuan
parent ddf73459b7
commit eead0b2e8a
6 changed files with 282 additions and 23 deletions

View File

@@ -206,7 +206,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;
@@ -950,6 +950,7 @@ static u32 blackout;
static u32 blackout = 1;
#endif
static u32 force_blackout;
static u32 blackout_pip;
/* disable video */
@@ -981,6 +982,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;
@@ -1152,7 +1159,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)
@@ -3132,6 +3144,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)
@@ -8297,6 +8311,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)
@@ -8315,11 +8330,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;
@@ -8334,6 +8363,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(
@@ -8342,11 +8376,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
@@ -8371,6 +8405,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)
@@ -8863,27 +8910,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;
}
@@ -9010,6 +9058,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 ||
@@ -9026,6 +9092,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;
@@ -9302,6 +9381,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:
@@ -11226,7 +11307,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;
@@ -11239,6 +11320,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();
@@ -11247,6 +11329,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,
@@ -11596,6 +11698,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,

View 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)

View 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

View 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)
@@ -156,8 +159,11 @@
* 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)

View 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);

View File

@@ -21,12 +21,17 @@
#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