diff --git a/drivers/amlogic/amports/amstream.c b/drivers/amlogic/amports/amstream.c index 740775d367b7..b9eda5aa638c 100755 --- a/drivers/amlogic/amports/amstream.c +++ b/drivers/amlogic/amports/amstream.c @@ -66,6 +66,7 @@ #include "amvideocap_priv.h" #include "amports_priv.h" #include "amports_config.h" +#include "tsync_pcr.h" #include @@ -665,24 +666,25 @@ static int amstream_port_init(stream_port_t *port) } } - if (port->type & PORT_TYPE_MPTS) { - if (HAS_HEVC_VDEC) { - r = tsdemux_init((port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, - (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, - port->pcrid, - (port->vformat == VFORMAT_HEVC)); - } else { - r = tsdemux_init((port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, - (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, - (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, - port->pcrid, 0); - } - + if (port->type & PORT_TYPE_MPTS) { + if (HAS_HEVC_VDEC) { + r = tsdemux_init((port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, + (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, + (port->pcr_inited == 1) ? port->pcrid : 0xffff, + (port->vformat == VFORMAT_HEVC)); + }else{ + r = tsdemux_init((port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, + (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff, + (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff, + (port->pcr_inited == 1) ? port->pcrid : 0xffff, 0); + } + if (r < 0) { printk("tsdemux_init failed\n"); goto error4; } + tsync_pcr_start(); } if (port->type & PORT_TYPE_MPPS) { r = psparser_init((port->flag & PORT_FLAG_VID) ? port->vid : 0xffff, @@ -736,6 +738,7 @@ static int amstream_port_release(stream_port_t *port) } if (port->type & PORT_TYPE_MPTS) { + tsync_pcr_stop(); tsdemux_release(); } @@ -756,6 +759,7 @@ static int amstream_port_release(stream_port_t *port) sub_port_release(port, psbuf); } + port->pcr_inited=0; port->flag = 0; return 0; } @@ -1142,6 +1146,7 @@ static int amstream_open(struct inode *inode, struct file *file) file->private_data = this; this->flag = PORT_FLAG_IN_USE; + this->pcr_inited = 0; #ifdef DATA_DEBUG debug_filp = filp_open(DEBUG_FILE_NAME, O_WRONLY, 0); if (IS_ERR(debug_filp)) { @@ -1334,6 +1339,7 @@ static long amstream_ioctl(struct file *file, case AMSTREAM_IOC_PCRID: this->pcrid= (u32)arg; + this->pcr_inited = 1; printk("set pcrid = 0x%x \n", this->pcrid); break; @@ -1742,6 +1748,9 @@ static long amstream_ioctl(struct file *file, printk("Get audio pts from user space fault! \n"); return -EFAULT; } + if(tsync_get_mode()==TSYNC_MODE_PCRMASTER) + tsync_pcr_set_apts(pts); + else tsync_set_apts(pts); break; } @@ -1811,6 +1820,7 @@ static ssize_t ports_show(struct class *class, struct class_attribute *attr, cha pbuf += sprintf(pbuf, "\tVid:%d\n", (p->flag & PORT_FLAG_VID) ? p->vid : -1); pbuf += sprintf(pbuf, "\tAid:%d\n", (p->flag & PORT_FLAG_AID) ? p->aid : -1); pbuf += sprintf(pbuf, "\tSid:%d\n", (p->flag & PORT_FLAG_SID) ? p->sid : -1); + pbuf += sprintf(pbuf, "\tPCRid:%d\n", (p->pcr_inited == 1) ? p->pcrid : -1); pbuf += sprintf(pbuf, "\tachannel:%d\n", p->achanl); pbuf += sprintf(pbuf, "\tasamprate:%d\n", p->asamprate); pbuf += sprintf(pbuf, "\tadatawidth:%d\n\n", p->adatawidth); diff --git a/drivers/amlogic/amports/ptsserv.c b/drivers/amlogic/amports/ptsserv.c index 041a5b97bc7b..eb8e6782f0fe 100755 --- a/drivers/amlogic/amports/ptsserv.c +++ b/drivers/amlogic/amports/ptsserv.c @@ -280,6 +280,27 @@ int calculation_vcached_delayed(void) } EXPORT_SYMBOL(calculation_vcached_delayed); +// return the 1/90000 unit time +int calculation_acached_delayed(void){ + pts_table_t *pTable; + u32 delay=0; + + pTable = &pts_table[PTS_TYPE_AUDIO]; + + delay = pTable->last_checkin_pts-pTable->last_checkout_pts; + if (0last_avg_bitrate>0){ + int diff = pTable->last_checkin_offset-pTable->last_checkout_offset; + delay=diff*90000/(1+pTable->last_avg_bitrate/8); + + return delay; + } + + return -1; +} +EXPORT_SYMBOL(calculation_acached_delayed); int calculation_stream_ext_delayed_ms(u8 type) { pts_table_t *pTable; @@ -548,7 +569,7 @@ int pts_lookup(u8 type, u32 *val, u32 pts_margin) } EXPORT_SYMBOL(pts_lookup); -static int pts_lookup_offset_inline( +static int _pts_lookup_offset_inline( u8 type, u32 offset, u32 *val, u32 pts_margin, u64 *uS64) { ulong flags; @@ -771,6 +792,24 @@ static int pts_lookup_offset_inline( return -1; } +static int pts_lookup_offset_inline( + u8 type, u32 offset, u32 *val, u32 pts_margin, u64 *uS64){ + int res = _pts_lookup_offset_inline(type,offset,val,pts_margin,uS64); + + if(timestamp_firstvpts_get()==0&&res==0&&(*val)!=0&&type==PTS_TYPE_VIDEO){ + timestamp_firstvpts_set(*val); + } +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 + else if(timestamp_firstvpts_get()==0&&res==0&&(*val)!=0&&type==PTS_TYPE_HEVC){ + timestamp_firstvpts_set(*val); + } +#endif + else if(timestamp_firstapts_get()==0&&res==0&&(*val)!=0&&type==PTS_TYPE_AUDIO){ + timestamp_firstapts_set(*val); + } + + return res; +} int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin){ u64 pts_us; return pts_lookup_offset_inline(type,offset,val,pts_margin,&pts_us); @@ -929,6 +968,7 @@ int pts_start(u8 type) - pTable->buf_start; WRITE_MPEG_REG(VIDEO_PTS, 0); timestamp_pcrscr_set(0);//video always need the pcrscr,Clear it to use later + timestamp_firstvpts_set(0); pTable->first_checkin_pts = -1; pTable->first_lookup_ok = 0; pTable->first_lookup_is_fail = 0; @@ -948,6 +988,7 @@ int pts_start(u8 type) WRITE_MPEG_REG(VIDEO_PTS, 0); timestamp_pcrscr_set(0);//video always need the pcrscr,Clear it to use later + timestamp_firstvpts_set(0); pTable->first_checkin_pts = -1; pTable->first_lookup_ok = 0; pTable->first_lookup_is_fail = 0; @@ -959,6 +1000,7 @@ int pts_start(u8 type) //BUG_ON(pTable->buf_size <= 0x10000); WRITE_MPEG_REG(AUDIO_PTS, 0); + timestamp_firstapts_set(0); pTable->first_checkin_pts = -1; pTable->first_lookup_ok = 0; pTable->first_lookup_is_fail = 0; diff --git a/drivers/amlogic/amports/streambuf.h b/drivers/amlogic/amports/streambuf.h index 663f2f4ce3ef..f57a132d20e0 100755 --- a/drivers/amlogic/amports/streambuf.h +++ b/drivers/amlogic/amports/streambuf.h @@ -67,6 +67,7 @@ typedef struct stream_port_s { /* ports control */ s32 type; s32 flag; + s32 pcr_inited; /* decoder info */ s32 vformat; diff --git a/drivers/amlogic/amports/timestamp.c b/drivers/amlogic/amports/timestamp.c index 1b9e871d8798..da2f1090322b 100755 --- a/drivers/amlogic/amports/timestamp.c +++ b/drivers/amlogic/amports/timestamp.c @@ -1,5 +1,5 @@ #include - +#include #include unsigned int timestamp_enable_resample_flag = 0; EXPORT_SYMBOL(timestamp_enable_resample_flag); @@ -72,7 +72,7 @@ void timestamp_apts_inc(s32 inc) #ifdef MODIFY_TIMESTAMP_INC_WITH_PLL inc = inc*timestamp_inc_factor/PLL_FACTOR; #endif - if(0){//timestamp_enable_resample_flag){ + if(tsync_get_mode()!=TSYNC_MODE_PCRMASTER){//timestamp_enable_resample_flag){ if(timestamp_resample_type_flag==0){ //0-->no resample processing }else if(timestamp_resample_type_flag==1){//1-->down resample processing @@ -100,6 +100,7 @@ EXPORT_SYMBOL(timestamp_apts_inc); void timestamp_apts_enable(u32 enable) { audio_pts_up = enable; + printk("timestamp_apts_enable enable:%x, \n", enable); } EXPORT_SYMBOL(timestamp_apts_enable); @@ -135,6 +136,7 @@ EXPORT_SYMBOL(timestamp_pcrscr_set); void timestamp_firstvpts_set(u32 pts) { first_vpts = pts; + printk("video first pts = %x\n", first_vpts); } EXPORT_SYMBOL(timestamp_firstvpts_set); @@ -148,6 +150,7 @@ EXPORT_SYMBOL(timestamp_firstvpts_get); void timestamp_firstapts_set(u32 pts) { first_apts = pts; + printk("audio first pts = %x\n", first_apts); } EXPORT_SYMBOL(timestamp_firstapts_set); @@ -164,7 +167,7 @@ void timestamp_pcrscr_inc(s32 inc) #ifdef MODIFY_TIMESTAMP_INC_WITH_PLL inc = inc*timestamp_inc_factor/PLL_FACTOR; #endif - if(0){//timestamp_enable_resample_flag){ + if(tsync_get_mode()!=TSYNC_MODE_PCRMASTER){//timestamp_enable_resample_flag){ if(timestamp_resample_type_flag==0){ //0-->no resample processing }else if(timestamp_resample_type_flag==1){//1-->down resample processing diff --git a/drivers/amlogic/amports/tsdemux.c b/drivers/amlogic/amports/tsdemux.c index 713c7deae06d..c0339df74117 100755 --- a/drivers/amlogic/amports/tsdemux.c +++ b/drivers/amlogic/amports/tsdemux.c @@ -52,7 +52,8 @@ const static char tsdemux_irq_id[] = "tsdemux-irq-id"; static DECLARE_WAIT_QUEUE_HEAD(wq); static u32 fetch_done; static u32 discontinued_counter; -static int pcrscr_valid=0; +static u32 first_pcr = 0; +static u8 pcrscr_valid=0; static int demux_skipbyte; @@ -620,6 +621,7 @@ s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc) } #endif + if (pcrid < 0x1FFF){ /* set paramater to fetch pcr */ pcr_num=0; if(pcrid == vid) @@ -644,7 +646,9 @@ s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc) WRITE_MPEG_REG(ASSIGN_PID_NUMBER, pcr_num); printk("[tsdemux_init] To use device 1,pcr_num=%d \n",pcr_num); } + first_pcr = 0; pcrscr_valid=1; + } return 0; @@ -669,6 +673,7 @@ err1: void tsdemux_release(void) { pcrscr_valid=0; + first_pcr=0; WRITE_MPEG_REG(PARSER_INT_ENABLE, 0); WRITE_MPEG_REG(PARSER_VIDEO_HOLE, 0); @@ -911,18 +916,27 @@ void tsdemux_set_demux(int dev) u32 tsdemux_pcrscr_get(void) { + u32 pcr; if(READ_MPEG_REG(TS_HIU_CTL_2) & 0x40){ - return READ_MPEG_REG(PCR_DEMUX_2); + + pcr = READ_MPEG_REG(PCR_DEMUX_2); } else if(READ_MPEG_REG(TS_HIU_CTL_3) & 0x40){ - return READ_MPEG_REG(PCR_DEMUX_3); + pcr = READ_MPEG_REG(PCR_DEMUX_3); } else{ - return READ_MPEG_REG(PCR_DEMUX); + pcr = READ_MPEG_REG(PCR_DEMUX); } + if(first_pcr == 0) + first_pcr = pcr; + return pcr; } -int tsdemux_pcrscr_valid(void) + u32 tsdemux_first_pcrscr_get(void) + { + return first_pcr; + } +u8 tsdemux_pcrscr_valid(void) { return pcrscr_valid; } diff --git a/drivers/amlogic/amports/tsdemux.h b/drivers/amlogic/amports/tsdemux.h index 025325aac787..9571a7a203b8 100755 --- a/drivers/amlogic/amports/tsdemux.h +++ b/drivers/amlogic/amports/tsdemux.h @@ -81,7 +81,8 @@ extern ssize_t tsdemux_write(struct file *file, const char __user *buf, size_t count); extern u32 tsdemux_pcrscr_get(void); -extern int tsdemux_pcrscr_valid(void); +extern u8 tsdemux_pcrscr_valid(void); +extern u32 tsdemux_first_pcrscr_get(void); int tsdemux_class_register(void); void tsdemux_class_unregister(void); diff --git a/drivers/amlogic/amports/tsync.c b/drivers/amlogic/amports/tsync.c index 103b219e05df..f8d15e2bf307 100755 --- a/drivers/amlogic/amports/tsync.c +++ b/drivers/amlogic/amports/tsync.c @@ -976,6 +976,12 @@ void tsync_pcr_recover(void) EXPORT_SYMBOL(tsync_pcr_recover); +int tsync_get_mode(void) +{ + return tsync_mode; +} +EXPORT_SYMBOL(tsync_get_mode); + int tsync_get_debug_pts_checkin(void) { return debug_pts_checkin; diff --git a/drivers/amlogic/amports/tsync_pcr.c b/drivers/amlogic/amports/tsync_pcr.c index f1394403c9e3..e0160d434cd9 100644 --- a/drivers/amlogic/amports/tsync_pcr.c +++ b/drivers/amlogic/amports/tsync_pcr.c @@ -1,16 +1,20 @@ #include +#include #include +#include + #include #include #include #include + #include "tsync_pcr.h" #include "amvdec.h" #include "tsdemux.h" #include "streambuf.h" #include "amports_priv.h" -//#define CONFIG_AM_PCRSYNC_LOG +#define CONFIG_AM_PCRSYNC_LOG #ifdef CONFIG_AM_PCRSYNC_LOG #define AMLOG @@ -34,9 +38,9 @@ typedef enum { #define CHECK_INTERVAL (HZ * 5) #define START_AUDIO_LEVEL 256 -#define START_VIDEO_LEVEL 2048 +#define START_VIDEO_LEVEL 20480 #define PAUSE_AUDIO_LEVEL 16 -#define PAUSE_VIDEO_LEVEL 512 +#define PAUSE_VIDEO_LEVEL 256 #define UP_RESAMPLE_AUDIO_LEVEL 128 #define UP_RESAMPLE_VIDEO_LEVEL 1024 #define DOWN_RESAMPLE_CACHE_TIME 90000*2 @@ -45,17 +49,43 @@ typedef enum { /* the diff of system time and referrence lock, which use the threshold to adjust the system time */ #define OPEN_RECOVERY_THRESHOLD 18000 #define CLOSE_RECOVERY_THRESHOLD 300 -#define RECOVERY_SPAN 10 +#define RECOVERY_SPAN 5 #define FORCE_RECOVERY_SPAN 20 /* the delay from ts demuxer to the amvideo */ #define DEFAULT_VSTREAM_DELAY 18000 -static struct timer_list tsync_pcr_check_timer; +#define RESAMPLE_TYPE_NONE 0 +#define RESAMPLE_TYPE_DOWN 1 +#define RESAMPLE_TYPE_UP 2 +#define RESAMPLE_DOWN_FORCE_PCR_SLOW 3 + +#define MS_INTERVAL (HZ/1000) +#define TEN_MS_INTERVAL (HZ/100) + +// ------------------------------------------------------------------ +// The const static u32 tsync_pcr_discontinue_threshold = (TIME_UNIT90K * 1.5); +static u32 tsync_pcr_ref_latency = 30000; //TIME_UNIT90K/3 -static u32 tsync_pcr_ref_cache_time = TIME_UNIT90K; +// use for pcr valid mode +static u32 tsync_pcr_max_cache_time = TIME_UNIT90K*2; //TIME_UNIT90K*2; +static u32 tsync_pcr_up_cache_time = TIME_UNIT90K*1.5; //TIME_UNIT90K*1.5; +static u32 tsync_pcr_down_cache_time = TIME_UNIT90K*1.2; //TIME_UNIT90K*1.2; +static u32 tsync_pcr_min_cache_time = TIME_UNIT90K*0.8; //TIME_UNIT90K*0.8; + + +// use for pcr invalid mode +static u32 tsync_pcr_max_delay_time = TIME_UNIT90K*3; //TIME_UNIT90K*3; +static u32 tsync_pcr_up_delay_time = TIME_UNIT90K*2; //TIME_UNIT90K*2; +static u32 tsync_pcr_down_delay_time = TIME_UNIT90K*1.5; //TIME_UNIT90K*1.5; +static u32 tsync_pcr_min_delay_time = TIME_UNIT90K*1; //TIME_UNIT90K*0.8; + +// ------------------------------------------------------------------ +// The variate + +static struct timer_list tsync_pcr_check_timer; static u32 tsync_pcr_system_startpcr=0; static u32 tsync_pcr_tsdemux_startpcr=0; @@ -63,19 +93,24 @@ static u32 tsync_pcr_tsdemux_startpcr=0; static int tsync_pcr_vpause_flag = 0; static int tsync_pcr_apause_flag = 0; static int tsync_pcr_vstart_flag = 0; +static int tsync_pcr_astart_flag = 0; static int tsync_pcr_inited_flag = 0; // the really ts demuxer pcr, haven't delay static u32 tsync_pcr_last_tsdemuxpcr = 0; -static u32 tsync_pcr_discontinue_point = 0; +static u32 tsync_pcr_discontinue_local_point = 0; static u32 tsync_pcr_discontinue_waited = 0; // the time waited the v-discontinue to happen -static int tsync_pcr_tsdemuxpcr_discontinue = 0; // the boolean value +static u8 tsync_pcr_tsdemuxpcr_discontinue = 0; // the boolean value +static u32 tsync_pcr_discontinue_point = 0; static int abuf_level=0; static int abuf_size=0; static int vbuf_level=0; static int vbuf_size=0; static int play_mode=PLAY_MODE_NORMAL; +static u8 tsync_pcr_started=0; +static int tsync_pcr_read_cnt=0; +static u8 tsync_pcr_usepcr=1; //static int tsync_pcr_debug_pcrscr = 100; extern int get_vsync_pts_inc_mode(void); @@ -91,13 +126,13 @@ u32 tsync_pcr_vstream_delayed(void) void tsync_pcr_avevent_locked(avevent_t event, u32 param) { - switch (event) { case VIDEO_START: if (tsync_pcr_vstart_flag == 0) { - timestamp_firstvpts_set(param); + //play_mode=PLAY_MODE_NORMAL; + printk("video start! init system time param=%x cur_pcr=%x\n",param,timestamp_pcrscr_get()); } - +/* if(tsync_pcr_vstart_flag == 0 && tsync_pcr_inited_flag == 0){ u32 ref_pcr=param - VIDEO_HOLD_THRESHOLD; // to wait 3 second u32 tsdemux_pcr = tsdemux_pcrscr_get(); @@ -110,14 +145,13 @@ void tsync_pcr_avevent_locked(avevent_t event, u32 param) if (!tsync_pcr_vpause_flag) { timestamp_pcrscr_enable(1); } - } + }*/ tsync_pcr_vstart_flag=1; break; case VIDEO_STOP: timestamp_pcrscr_enable(0); timestamp_vpts_set(0); - timestamp_firstvpts_set(0); //tsync_pcr_debug_pcrscr=100; tsync_pcr_vpause_flag=0; @@ -126,50 +160,55 @@ void tsync_pcr_avevent_locked(avevent_t event, u32 param) tsync_pcr_tsdemuxpcr_discontinue=0; tsync_pcr_discontinue_point=0; + tsync_pcr_discontinue_local_point=0; tsync_pcr_discontinue_waited=0; tsync_pcr_tsdemux_startpcr = 0; tsync_pcr_system_startpcr = 0; + play_mode=PLAY_MODE_NORMAL; printk("video stop! \n"); break; case VIDEO_TSTAMP_DISCONTINUITY: { - unsigned oldpts=timestamp_vpts_get(); - if((abs(param-oldpts)>AV_DISCONTINUE_THREDHOLD_MIN) && (!get_vsync_pts_inc_mode())){ - u32 tsdemux_pcr = tsdemux_pcrscr_get(); - u32 ref_pcr = param; - printk("[tsync_pcr_avevent_locked] video discontinue happen.param=%x,discontinue=%d\n",param,tsync_pcr_tsdemuxpcr_discontinue); + //unsigned oldpts=timestamp_vpts_get(); + u32 tsdemux_pcr = tsdemux_pcrscr_get(); + //if((abs(param-oldpts)>AV_DISCONTINUE_THREDHOLD_MIN) && (!get_vsync_pts_inc_mode())){ + if(!get_vsync_pts_inc_mode()){ + u32 ref_pcr = param-tsync_pcr_ref_latency*2; //if(ref_pcr == 0) // ref_pcr=tsdemux_pcr-tsync_pcr_vstream_delayed(); + timestamp_pcrscr_set(ref_pcr); tsync_pcr_tsdemux_startpcr = tsdemux_pcr; tsync_pcr_system_startpcr = ref_pcr; - printk("reset ref pcr=%x , ts demuxer pcr=%x \n",tsync_pcr_system_startpcr, tsync_pcr_tsdemux_startpcr); + //play_mode=PLAY_MODE_FORCE_SLOW; + printk("[tsync_pcr_avevent_locked] video discontinue happen and slow play.ref_pcr=%x,param=%x,discontinue=%d\n",ref_pcr,param,tsync_pcr_tsdemuxpcr_discontinue); /* to resume the pcr check*/ tsync_pcr_tsdemuxpcr_discontinue=0; tsync_pcr_discontinue_point=0; + tsync_pcr_discontinue_local_point=0; tsync_pcr_discontinue_waited=0; } + //} timestamp_vpts_set(param); break; } case AUDIO_PRE_START: timestamp_apts_start(0); + tsync_pcr_astart_flag=0; printk("audio prestart! \n"); break; - case AUDIO_START: - if(timestamp_apts_started()==0) - timestamp_firstapts_set(param); - + case AUDIO_START: timestamp_apts_set(param); timestamp_apts_enable(1); timestamp_apts_start(1); - + + tsync_pcr_astart_flag=1; tsync_pcr_apause_flag=0; printk("audio start!timestamp_apts_set =%x. \n",param); break; @@ -184,7 +223,7 @@ void tsync_pcr_avevent_locked(avevent_t event, u32 param) timestamp_apts_enable(0); timestamp_apts_set(-1); timestamp_apts_start(0); - timestamp_firstapts_set(0); + tsync_pcr_astart_flag=0; tsync_pcr_apause_flag=0; printk("audio stop! \n"); break; @@ -236,36 +275,48 @@ void tsync_pcr_avevent_locked(avevent_t event, u32 param) // timer to check the system with the referrence time in ts stream. static unsigned long tsync_pcr_check(void) { - u32 tsdemux_pcr=tsdemux_pcrscr_get(); + u32 tsdemux_pcr=0; u32 tsdemux_pcr_diff=0; int need_recovery=1; - unsigned long res=jiffies; - - /* check the value valid */ - if(tsync_pcr_last_tsdemuxpcr ==0 && tsdemux_pcr ==0) - return res; - - // To monitor the pcr discontinue - tsdemux_pcr_diff=abs(tsdemux_pcr - tsync_pcr_last_tsdemuxpcr); - if(tsdemux_pcr_diff > tsync_pcr_discontinue_threshold && tsync_pcr_tsdemuxpcr_discontinue==0 && tsync_pcr_inited_flag==1){ - tsync_pcr_tsdemuxpcr_discontinue=1; - tsync_pcr_discontinue_waited=tsync_pcr_vstream_delayed()+TIME_UNIT90K; - printk("[tsync_pcr_check] refpcr_discontinue. tsdemux_pcr_diff=%x, last refpcr=%x, repcr=%x\n",tsdemux_pcr_diff,tsync_pcr_last_tsdemuxpcr,tsdemux_pcr); - tsync_pcr_discontinue_point=timestamp_pcrscr_get(); - need_recovery=0; + unsigned long res=1; + if(tsync_get_mode() != TSYNC_MODE_PCRMASTER){ + return res; } - else if(tsync_pcr_tsdemuxpcr_discontinue == 1){ - // to pause the pcr check - if(abs(timestamp_pcrscr_get()-tsync_pcr_discontinue_point)>tsync_pcr_discontinue_waited){ - // the v-discontinue did'n happen - tsync_pcr_tsdemuxpcr_discontinue=0; - tsync_pcr_discontinue_point=0; - tsync_pcr_discontinue_waited=0; - printk("[tsync_pcr_check] video discontinue didn't happen, waited=%lx\n",abs(tsdemux_pcr-tsync_pcr_discontinue_point)); + + tsdemux_pcr=tsdemux_pcrscr_get(); + if(tsync_pcr_usepcr==1){ + // To monitor the pcr discontinue + tsdemux_pcr_diff=abs(tsdemux_pcr - tsync_pcr_last_tsdemuxpcr); + if(tsync_pcr_last_tsdemuxpcr!=0&&tsdemux_pcr!=0&&tsdemux_pcr_diff > tsync_pcr_discontinue_threshold && tsync_pcr_inited_flag==1){ + u32 video_delayed=0; + tsync_pcr_tsdemuxpcr_discontinue=1; + video_delayed = tsync_pcr_vstream_delayed(); + if(TIME_UNIT90K*2<=video_delayed&&video_delayed<=TIME_UNIT90K*4) + tsync_pcr_discontinue_waited=video_delayed+TIME_UNIT90K; + else if(TIME_UNIT90K*2>video_delayed) + tsync_pcr_discontinue_waited=TIME_UNIT90K*3; + else + tsync_pcr_discontinue_waited=TIME_UNIT90K*5; + + printk("[tsync_pcr_check] refpcr_discontinue. tsdemux_pcr_diff=%x, last refpcr=%x, repcr=%x,waited=%x\n",tsdemux_pcr_diff,tsync_pcr_last_tsdemuxpcr,tsdemux_pcr,tsync_pcr_discontinue_waited); + tsync_pcr_discontinue_local_point=timestamp_pcrscr_get(); + tsync_pcr_discontinue_point=tsdemux_pcr-tsync_pcr_ref_latency; + need_recovery=0; } - need_recovery=0; + else if(tsync_pcr_tsdemuxpcr_discontinue == 1){ + // to pause the pcr check + if(abs(timestamp_pcrscr_get()-tsync_pcr_discontinue_local_point)>tsync_pcr_discontinue_waited){ + printk("[tsync_pcr_check] video discontinue didn't happen, waited=%x\n",tsync_pcr_discontinue_waited); + // the v-discontinue did'n happen + tsync_pcr_tsdemuxpcr_discontinue=0; + tsync_pcr_discontinue_point=0; + tsync_pcr_discontinue_local_point=0; + tsync_pcr_discontinue_waited=0; + } + need_recovery=0; + } + tsync_pcr_last_tsdemuxpcr=tsdemux_pcr; } - tsync_pcr_last_tsdemuxpcr=tsdemux_pcr; abuf_level= stbuf_level(get_buf_by_type(BUF_TYPE_AUDIO)); abuf_size= stbuf_size(get_buf_by_type(BUF_TYPE_AUDIO)); @@ -273,68 +324,117 @@ static unsigned long tsync_pcr_check(void) vbuf_size= stbuf_size(get_buf_by_type(BUF_TYPE_VIDEO)); if(tsync_pcr_inited_flag == 0){ // check the video and audio stream buffer, to check to start - if((timestamp_apts_started() == 1 && tsync_pcr_vstart_flag)){ - u32 ref_pcr =0; - //if(timestamp_firstvpts_get() <= timestamp_firstapts_get() || timestamp_firstapts_get() == 0){ - ref_pcr=timestamp_firstvpts_get(); - printk("[tsync_pcr_check]Inited use video pts. ref_pcr=%x tsdemux time=%x \n",ref_pcr,tsdemux_pcr); - //} - //else{ - // ref_pcr=timestamp_firstapts_get(); - // printk("[tsync_pcr_check]Inited use audio pts. ref_pcr=%x tsdemux time=%x \n",ref_pcr,tsdemux_pcr); - //} - - timestamp_pcrscr_set(ref_pcr); - tsync_pcr_tsdemux_startpcr = tsdemux_pcr; - tsync_pcr_system_startpcr = ref_pcr; - tsync_pcr_inited_flag = 1; - play_mode=PLAY_MODE_FORCE_SLOW; - printk("[tsync_pcr_check] init and slow play.abuf_level=%x vbuf_level=%x \n", abuf_level,vbuf_level); - - if (!tsync_pcr_vpause_flag) { - timestamp_pcrscr_enable(1); - } + u32 first_pcr =tsdemux_first_pcrscr_get(); + u32 first_vpts = timestamp_firstvpts_get(); + u32 first_apts = timestamp_firstapts_get(); + u32 ref_pcr=0; + u8 ref_pcr_valid=0; + + if(tsync_pcr_usepcr==1){ + if(first_pcr != 0){ + // pcr is valid, use + ref_pcr = first_pcr - tsync_pcr_ref_latency; + ref_pcr_valid=1; + printk("[tsync_pcr_check]Inited use pcr mode.ref_pcr=%x first_pcr=%x first_vpts=%x first_apts=%x \n",ref_pcr,first_pcr,first_vpts,first_apts); + }else{ + if(first_vpts!=0||first_apts!=0){ + tsync_pcr_usepcr=0; + printk("[tsync_pcr_check]can't read valid pcr, use other mode. read_cnt=%d \n",tsync_pcr_read_cnt); + } + tsync_pcr_read_cnt++; + } } + else{ + // pcr is invalid, use vmaster or amaster mode + if(tsync_pcr_astart_flag==1&&tsync_pcr_vstart_flag==1&&first_vpts!=0&&first_apts!=0&&vbuf_level>=START_VIDEO_LEVEL){ + if(first_vpts <= first_apts){ + //play_mode=PLAY_MODE_FORCE_SLOW; + ref_pcr = first_vpts; + printk("[tsync_pcr_check]Inited use video pts and slow play.ref_pcr=%x first_pcr=%x first_vpts=%x first_apts=%x \n",ref_pcr,first_pcr,first_vpts,first_apts); + } + else{ + //play_mode=PLAY_MODE_FORCE_SLOW; + ref_pcr=first_apts; + printk("[tsync_pcr_check]Inited use audio pts and slow play.ref_pcr=%x first_pcr=%x first_vpts=%x first_apts=%x \n",ref_pcr,first_pcr,first_vpts,first_apts); + } + ref_pcr_valid=1; + } + else if(tsync_pcr_astart_flag==0&&tsync_pcr_vstart_flag==1&&first_vpts!=0&&(vbuf_level*20)>vbuf_size&&abuf_level==0){ + int vdelayed=calculation_vcached_delayed(); + if(tsync_pcr_max_cache_timeabuf_size&&vbuf_level==0){ + int adelayed=calculation_acached_delayed(); + if(tsync_pcr_max_cache_time vbuf_size * 4 || abuf_level * 5 > abuf_size * 4) && play_mode != PLAY_MODE_FORCE_SPEED){ - printk("[tsync_pcr_check]Buffer will overflow and speed play. vlevel=%x vsize=%x alevel=%x asize=%x play_mode=%d\n", - vbuf_level,vbuf_size,abuf_level,abuf_size, play_mode); // the video stream buffer will happen overflow - play_mode=PLAY_MODE_FORCE_SPEED; + u32 new_pcr=0; + play_mode=PLAY_MODE_FORCE_SPEED; + new_pcr=timestamp_pcrscr_get()+72000; // 90000*0.8 + timestamp_pcrscr_set(new_pcr); + printk("[tsync_pcr_check]Buffer will overflow and speed play. new_pcr=%x vlevel=%x vsize=%x alevel=%x asize=%x play_mode=%d\n", + new_pcr,vbuf_level,vbuf_size,abuf_level,abuf_size, play_mode); } - + + if(play_mode == PLAY_MODE_FORCE_SLOW){ - if((vbuf_level * 50 > vbuf_size && abuf_level * 50 > abuf_size)|| - vbuf_level * 10 > vbuf_size || - abuf_level * 10 > abuf_size){ + /*if((vbuf_level * 50 > vbuf_size && abuf_level * 50 > abuf_size)|| + vbuf_level * 20 > vbuf_size || + abuf_level * 20 > abuf_size){*/ + if(vbuf_level * 20 > vbuf_size){ play_mode=PLAY_MODE_NORMAL; printk("[tsync_pcr_check]Buffer to vlevel=%x vsize=%x alevel=%x asize=%x. slow to normal play\n", vbuf_level,vbuf_size,abuf_level,abuf_size); } } else if(play_mode == PLAY_MODE_FORCE_SPEED){ - if((vbuf_level * 3 < vbuf_size && abuf_level * 3 < abuf_size) || - vbuf_level * 10 < vbuf_size || - abuf_level * 10 < abuf_size){ + if((vbuf_level * 4 < vbuf_size && abuf_level * 4 < abuf_size) || + (vbuf_level * 4 < vbuf_size && abuf_level == 0)|| + (abuf_level * 4 < abuf_size && vbuf_level == 0)){ play_mode=PLAY_MODE_NORMAL; tsync_pcr_tsdemux_startpcr = tsdemux_pcr; tsync_pcr_system_startpcr = timestamp_pcrscr_get(); @@ -349,35 +449,75 @@ static unsigned long tsync_pcr_check(void) tsync_pcr_debug_pcrscr=0; } */ + //if(need_recovery==1 || play_mode == PLAY_MODE_FORCE_SLOW || play_mode == PLAY_MODE_FORCE_SPEED){ /* To check the system time with ts demuxer pcr */ - if(play_mode != PLAY_MODE_FORCE_SLOW && play_mode != PLAY_MODE_FORCE_SPEED){ - u32 ref_pcr=tsdemux_pcr-tsync_pcr_ref_cache_time; - u32 cur_pcr=timestamp_pcrscr_get(); - u32 diff=abs(ref_pcr - cur_pcr); - if(diff > OPEN_RECOVERY_THRESHOLD && cur_pcr OPEN_RECOVERY_THRESHOLD && cur_pcr>ref_pcr && play_mode!=PLAY_MODE_SLOW && need_recovery){ + if((play_mode != PLAY_MODE_FORCE_SLOW) && (play_mode != PLAY_MODE_FORCE_SPEED) && (tsync_pcr_usepcr==1)){ + // use the pcr to adjust + //u32 ref_pcr=tsdemux_pcr-calculation_vcached_delayed(); + int64_t ref_pcr=(int64_t)tsdemux_pcr- (int64_t)tsync_pcr_ref_latency; + int64_t cur_pcr=(int64_t)timestamp_pcrscr_get(); + int64_t diff=abs(ref_pcr - cur_pcr); + + //if(diff > OPEN_RECOVERY_THRESHOLD && cur_pcr (tsync_pcr_max_cache_time)) && (play_mode!=PLAY_MODE_SPEED) && need_recovery){ + play_mode=PLAY_MODE_SPEED; + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] diff=%lld to speed play \n",diff); + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] ref_pcr=%lld to speed play \n",ref_pcr); + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] cur_pcr=%lld to speed play \n",cur_pcr); + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] tsync_pcr_max_cache_time=%d to speed play \n",tsync_pcr_max_cache_time); + } + //else if(diff > OPEN_RECOVERY_THRESHOLD && cur_pcr>ref_pcr && play_mode!=PLAY_MODE_SLOW && need_recovery){ + else if((ref_pcr - cur_pcr) < (tsync_pcr_min_cache_time) && (play_mode!=PLAY_MODE_SLOW) && need_recovery){ play_mode=PLAY_MODE_SLOW; - amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] diff=%x to show play \n",diff); - } - else if(diff < CLOSE_RECOVERY_THRESHOLD && play_mode!=PLAY_MODE_NORMAL){ - play_mode=PLAY_MODE_NORMAL; - amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] diff=%x to nomal play \n",diff); - } + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] diff=%lld to slow play \n",diff); + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] ref_pcr=%lld to slow play \n",ref_pcr); + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] cur_pcr=%lld to slow play \n",cur_pcr); + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] tsync_pcr_max_cache_time=%d to slow play \n",tsync_pcr_max_cache_time); + } + //else if(diff < CLOSE_RECOVERY_THRESHOLD && play_mode!=PLAY_MODE_NORMAL){ + else if((!need_recovery||((tsync_pcr_down_cache_time tsync_pcr_max_delay_time){ + if(play_mode!=PLAY_MODE_SPEED){ + play_mode= PLAY_MODE_SPEED; + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] video_delay_time=%d to speed play \n",video_cache_time); + } + } + else if( video_cache_time < tsync_pcr_min_delay_time && video_cache_time>=0 ){ + if(play_mode!=PLAY_MODE_SLOW){ + play_mode=PLAY_MODE_SLOW; + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] video_delay_time=%d to show play \n",video_cache_time); + } + } + else{ + if(tsync_pcr_down_delay_time<=video_cache_time&&video_cache_time<=tsync_pcr_up_delay_time&&play_mode!=PLAY_MODE_NORMAL){ + play_mode=PLAY_MODE_NORMAL; + amlog_level(LOG_LEVEL_INFO, "[tsync_pcr_check] video_delay_time=%d to nomal play \n", video_cache_time); + } + } + } + + if(need_recovery&&!tsync_pcr_vpause_flag){ + if(play_mode == PLAY_MODE_SLOW) + timestamp_pcrscr_set(timestamp_pcrscr_get()-RECOVERY_SPAN); + else if( play_mode == PLAY_MODE_FORCE_SLOW) + timestamp_pcrscr_set(timestamp_pcrscr_get()-FORCE_RECOVERY_SPAN); + else if(play_mode == PLAY_MODE_SPEED) + timestamp_pcrscr_set(timestamp_pcrscr_get()+RECOVERY_SPAN); + else if( play_mode == PLAY_MODE_FORCE_SPEED) + timestamp_pcrscr_set(timestamp_pcrscr_get()+FORCE_RECOVERY_SPAN); } - - if(play_mode == PLAY_MODE_SLOW) - timestamp_pcrscr_set(timestamp_pcrscr_get()-RECOVERY_SPAN); - else if( play_mode == PLAY_MODE_FORCE_SLOW) - timestamp_pcrscr_set(timestamp_pcrscr_get()-FORCE_RECOVERY_SPAN); - else if(play_mode == PLAY_MODE_SPEED) - timestamp_pcrscr_set(timestamp_pcrscr_get()+RECOVERY_SPAN); - else if( play_mode == PLAY_MODE_FORCE_SPEED) - timestamp_pcrscr_set(timestamp_pcrscr_get()+FORCE_RECOVERY_SPAN); //} return res; @@ -385,17 +525,73 @@ static unsigned long tsync_pcr_check(void) static void tsync_pcr_check_timer_func(unsigned long arg) { - if(tsdemux_pcrscr_valid() == 1){ - tsync_pcr_check_timer.expires = tsync_pcr_check(); - } - else{ - tsync_pcr_last_tsdemuxpcr=0; - tsync_pcr_check_timer.expires = jiffies; - } + tsync_pcr_check(); + tsync_pcr_check_timer.expires = jiffies+TEN_MS_INTERVAL; add_timer(&tsync_pcr_check_timer); } +static void tsync_pcr_param_reset(void){ + tsync_pcr_system_startpcr=0; + tsync_pcr_tsdemux_startpcr=0; + + tsync_pcr_vpause_flag = 0; + tsync_pcr_apause_flag = 0; + tsync_pcr_vstart_flag = 0; + tsync_pcr_astart_flag = 0; + tsync_pcr_inited_flag = 0; + + tsync_pcr_last_tsdemuxpcr = 0; + tsync_pcr_discontinue_local_point=0; + tsync_pcr_discontinue_point = 0; + tsync_pcr_discontinue_waited = 0; // the time waited the v-discontinue to happen + tsync_pcr_tsdemuxpcr_discontinue = 0; // the boolean value + + abuf_level=0; + abuf_size=0; + vbuf_level=0; + vbuf_size=0; + play_mode=PLAY_MODE_NORMAL; + tsync_pcr_started=0; +} +int tsync_pcr_set_apts(unsigned pts) +{ + timestamp_apts_set(pts); + //printk("[tsync_pcr_set_apts]set apts=%x",pts); + return 0; +} +int tsync_pcr_start(void) +{ + tsync_pcr_param_reset(); + + if(tsync_get_mode() == TSYNC_MODE_PCRMASTER){ + printk("[tsync_pcr_start]PCRMASTER started success. \n"); + init_timer(&tsync_pcr_check_timer); + + tsync_pcr_check_timer.function = tsync_pcr_check_timer_func; + tsync_pcr_check_timer.expires = jiffies; + + tsync_pcr_started=1; + tsync_pcr_usepcr=tsdemux_pcrscr_valid(); + tsync_pcr_read_cnt=0; + printk("[tsync_pcr_start]usepcr=%d\n",tsync_pcr_usepcr); + add_timer(&tsync_pcr_check_timer); + } + return 0; +} + +void tsync_pcr_stop(void) +{ + if(tsync_pcr_started==1){ + del_timer_sync(&tsync_pcr_check_timer); + printk("[tsync_pcr_start]PCRMASTER stop success. \n"); + } + tsync_pcr_started=0; +} + +// -------------------------------------------------------------------------------- +// define of tsync pcr class node + static ssize_t show_play_mode(struct class *class, struct class_attribute *attr, char *buf) @@ -403,12 +599,59 @@ static ssize_t show_play_mode(struct class *class, return sprintf(buf, "%d\n", play_mode); } +static ssize_t show_tsync_pcr_dispoint(struct class *class, + struct class_attribute *attr, + char *buf) +{ +printk("[%s:%d] tsync_pcr_discontinue_point:%x, HZ:%x, \n", __FUNCTION__, __LINE__, tsync_pcr_discontinue_point, HZ); + return sprintf(buf, "0x%x\n", tsync_pcr_discontinue_point); +} +static ssize_t store_tsync_pcr_dispoint(struct class *class, + struct class_attribute *attr, + const char *buf, + size_t size) +{ + unsigned pts; + ssize_t r; + + r = sscanf(buf, "0x%x", &pts); + if (r != 1) { + return -EINVAL; + } + + tsync_pcr_discontinue_point = pts; + printk("[%s:%d] tsync_pcr_discontinue_point:%x, \n", __FUNCTION__, __LINE__, tsync_pcr_discontinue_point); + + return size; +} + +static ssize_t store_tsync_pcr_audio_resample_type(struct class *class, + struct class_attribute *attr, + const char *buf, + size_t size) +{ + unsigned type; + ssize_t r; + + r = sscanf(buf, "%d", &type); + if (r != 1) { + return -EINVAL; + } + + if(type==RESAMPLE_DOWN_FORCE_PCR_SLOW){ + play_mode=PLAY_MODE_SLOW; + printk("[%s:%d] Audio to FORCE_PCR_SLOW\n", __FUNCTION__, __LINE__); + } + return size; +} // -------------------------------------------------------------------------------- // define of tsync pcr module static struct class_attribute tsync_pcr_class_attrs[] = { __ATTR(play_mode, S_IRUGO | S_IWUSR | S_IWGRP, show_play_mode, NULL), + __ATTR(tsync_pcr_discontinue_point, S_IRUGO | S_IWUSR, show_tsync_pcr_dispoint, store_tsync_pcr_dispoint), + __ATTR(audio_resample_type, S_IRUGO | S_IWUSR, NULL, store_tsync_pcr_audio_resample_type), __ATTR_NULL }; static struct class tsync_pcr_class = { @@ -432,21 +675,12 @@ static int __init tsync_pcr_init(void) timestamp_vpts_set(0); timestamp_pcrscr_set(0); - init_timer(&tsync_pcr_check_timer); - - tsync_pcr_check_timer.function = tsync_pcr_check_timer_func; - tsync_pcr_check_timer.expires = jiffies; - - add_timer(&tsync_pcr_check_timer); - printk("[tsync_pcr_init]init success. \n"); return (0); } static void __exit tsync_pcr_exit(void) { - del_timer_sync(&tsync_pcr_check_timer); - class_unregister(&tsync_pcr_class); printk("[tsync_pcr_exit]exit success. \n"); } diff --git a/drivers/amlogic/amports/tsync_pcr.h b/drivers/amlogic/amports/tsync_pcr.h index 1ee3015614b5..2a20609d568b 100644 --- a/drivers/amlogic/amports/tsync_pcr.h +++ b/drivers/amlogic/amports/tsync_pcr.h @@ -3,6 +3,11 @@ extern void tsync_pcr_avevent_locked(avevent_t event, u32 param); +extern int tsync_pcr_start(void); + +extern void tsync_pcr_stop(void); + +extern int tsync_pcr_set_apts(unsigned pts); #endif diff --git a/drivers/amlogic/amports/video.c b/drivers/amlogic/amports/video.c index 635bc2abcb88..079b2e04b8cb 100755 --- a/drivers/amlogic/amports/video.c +++ b/drivers/amlogic/amports/video.c @@ -591,6 +591,10 @@ static u32 force_blackout = 0; /* disable video */ static u32 disable_video = VIDEO_DISABLE_NONE; +/* show first frame*/ +static bool show_first_frame_nosync=true; +//static bool first_frame=false; + /* test screen*/ static u32 test_screen = 0; @@ -2214,6 +2218,8 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) vdin_v4l2_ops_t *vdin_ops = NULL; vdin_arg_t arg; #endif + bool show_nosync=false; + #ifdef CONFIG_AM_VIDEO_LOG int toggle_cnt; #endif @@ -2423,10 +2429,14 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) tsync_avevent_locked(VIDEO_START, (vf->pts) ? vf->pts : timestamp_vpts_get()); + #ifdef SLOW_SYNC_REPEAT frame_repeat_count = 0; #endif + if(show_first_frame_nosync) + show_nosync=true; + } else if ((cur_dispbuf == &vf_local) && (video_property_changed)) { if (!(blackout|force_blackout)) { if((READ_VCBUS_REG(DI_IF1_GEN_REG)&0x1)==0) @@ -2457,7 +2467,7 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) } while (vf) { - if (vpts_expire(cur_dispbuf, vf)) { + if (vpts_expire(cur_dispbuf, vf)||show_nosync) { amlog_mask(LOG_MASK_TIMESTAMP, "VIDEO_PTS = 0x%x, cur_dur=0x%x, next_pts=0x%x, scr = 0x%x\n", timestamp_vpts_get(), @@ -4873,6 +4883,30 @@ static ssize_t video_angle_store(struct class *cla, struct class_attribute *attr return strnlen(buf, count); } +static ssize_t show_first_frame_nosync_show(struct class *cla, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", show_first_frame_nosync?1:0); +} + +static ssize_t show_first_frame_nosync_store(struct class *cla, struct class_attribute *attr, const char *buf, + size_t count) +{ + size_t r; + int value; + + r = sscanf(buf, "%d", &value); + + if (r != 1) { + return -EINVAL; + } + + if(value==0) + show_first_frame_nosync=false; + else + show_first_frame_nosync=true; + + return count; +} static struct class_attribute amvideo_class_attrs[] = { __ATTR(axis, S_IRUGO | S_IWUSR | S_IWGRP, @@ -4973,6 +5007,10 @@ static struct class_attribute amvideo_class_attrs[] = { __ATTR(stereo_scaler, S_IRUGO|S_IWUSR,NULL, video_3d_scale_store), + __ATTR(show_first_frame_nosync, + S_IRUGO | S_IWUSR, + show_first_frame_nosync_show, + show_first_frame_nosync_store), __ATTR_RO(device_resolution), __ATTR_RO(frame_addr), __ATTR_RO(frame_canvas_width), diff --git a/drivers/amlogic/dvb_tv/aml_dmx.c b/drivers/amlogic/dvb_tv/aml_dmx.c index f4f1f3f5360f..dfa62a8760c6 100755 --- a/drivers/amlogic/dvb_tv/aml_dmx.c +++ b/drivers/amlogic/dvb_tv/aml_dmx.c @@ -1406,6 +1406,7 @@ static int dmx_enable(struct aml_dmx *dmx) (1<id, PES_STRONG_SYNC, 0x1234); DMX_WRITE_REG(dmx->id, DEMUX_ENDIAN, @@ -1483,6 +1484,9 @@ static u32 dmx_get_chan_target(struct aml_dmx *dmx, int cid) case DMX_PES_TELETEXT: type = SUB_PACKET; break; + case DMX_PES_PCR: + type=SCR_ONLY_PACKET; + break; default: type = OTHER_PES_PACKET; break; diff --git a/drivers/amlogic/dvb_tv/aml_dvb.c b/drivers/amlogic/dvb_tv/aml_dvb.c index 8495800bb80d..5ade62fd670d 100755 --- a/drivers/amlogic/dvb_tv/aml_dvb.c +++ b/drivers/amlogic/dvb_tv/aml_dvb.c @@ -556,8 +556,19 @@ static ssize_t tso_store_source(struct class *class,struct class_attribute *attr return size; } - - +/*Show PCR*/ +#define DEMUX_PCR_FUNC_DECL(i) \ +static ssize_t demux##i##_show_pcr(struct class *class, struct class_attribute *attr,char *buf)\ +{\ + int f = 0;\ + if(i == 0)\ + f = READ_MPEG_REG(PCR_DEMUX);\ + else if(i==1)\ + f = READ_MPEG_REG(PCR_DEMUX_2);\ + else if(i==2)\ + f = READ_MPEG_REG(PCR_DEMUX_3);\ + return sprintf(buf, "%08x\n", f);\ +} /*Show the STB input source*/ #define DEMUX_SOURCE_FUNC_DECL(i) \ @@ -736,6 +747,7 @@ static ssize_t dvr##i##_store_mode(struct class *class, struct class_attribute } #if DMX_DEV_COUNT>0 + DEMUX_PCR_FUNC_DECL(0) DEMUX_SOURCE_FUNC_DECL(0) DEMUX_FREE_FILTERS_FUNC_DECL(0) DEMUX_FILTER_USERS_FUNC_DECL(0) @@ -744,6 +756,7 @@ static ssize_t dvr##i##_store_mode(struct class *class, struct class_attribute DEMUX_CHANNEL_ACTIVITY_FUNC_DECL(0) #endif #if DMX_DEV_COUNT>1 + DEMUX_PCR_FUNC_DECL(1) DEMUX_SOURCE_FUNC_DECL(1) DEMUX_FREE_FILTERS_FUNC_DECL(1) DEMUX_FILTER_USERS_FUNC_DECL(1) @@ -752,6 +765,7 @@ static ssize_t dvr##i##_store_mode(struct class *class, struct class_attribute DEMUX_CHANNEL_ACTIVITY_FUNC_DECL(1) #endif #if DMX_DEV_COUNT>2 + DEMUX_PCR_FUNC_DECL(2) DEMUX_SOURCE_FUNC_DECL(2) DEMUX_FREE_FILTERS_FUNC_DECL(2) DEMUX_FILTER_USERS_FUNC_DECL(2) @@ -1044,6 +1058,8 @@ static struct class_attribute aml_stb_class_attrs[] = { __ATTR(source, S_IRUGO | S_IWUSR | S_IWGRP, stb_show_source, stb_store_source), __ATTR(dsc_source, S_IRUGO | S_IWUSR, dsc_show_source, dsc_store_source), __ATTR(tso_source, S_IRUGO | S_IWUSR, tso_show_source, tso_store_source), +#define DEMUX_SOURCE_ATTR_PCR(i)\ + __ATTR(demux##i##_pcr, S_IRUGO | S_IWUSR, demux##i##_show_pcr, NULL) #define DEMUX_SOURCE_ATTR_DECL(i)\ __ATTR(demux##i##_source, S_IRUGO | S_IWUSR | S_IWGRP, demux##i##_show_source, demux##i##_store_source) #define DEMUX_FREE_FILTERS_ATTR_DECL(i)\ @@ -1057,6 +1073,7 @@ static struct class_attribute aml_stb_class_attrs[] = { #define DEMUX_CHANNEL_ACTIVITY_ATTR_DECL(i)\ __ATTR(demux##i##_channel_activity, S_IRUGO | S_IWUSR, demux##i##_show_channel_activity, NULL) #if DMX_DEV_COUNT>0 + DEMUX_SOURCE_ATTR_PCR(0), DEMUX_SOURCE_ATTR_DECL(0), DEMUX_FREE_FILTERS_ATTR_DECL(0), DEMUX_FILTER_USERS_ATTR_DECL(0), @@ -1065,6 +1082,7 @@ static struct class_attribute aml_stb_class_attrs[] = { DEMUX_CHANNEL_ACTIVITY_ATTR_DECL(0), #endif #if DMX_DEV_COUNT>1 + DEMUX_SOURCE_ATTR_PCR(1), DEMUX_SOURCE_ATTR_DECL(1), DEMUX_FREE_FILTERS_ATTR_DECL(1), DEMUX_FILTER_USERS_ATTR_DECL(1), @@ -1073,6 +1091,7 @@ static struct class_attribute aml_stb_class_attrs[] = { DEMUX_CHANNEL_ACTIVITY_ATTR_DECL(1), #endif #if DMX_DEV_COUNT>2 + DEMUX_SOURCE_ATTR_PCR(2), DEMUX_SOURCE_ATTR_DECL(2), DEMUX_FREE_FILTERS_ATTR_DECL(2), DEMUX_FILTER_USERS_ATTR_DECL(2), diff --git a/include/linux/amlogic/amports/ptsserv.h b/include/linux/amlogic/amports/ptsserv.h index 14a060e44090..91eb9665c301 100755 --- a/include/linux/amlogic/amports/ptsserv.h +++ b/include/linux/amlogic/amports/ptsserv.h @@ -74,4 +74,5 @@ extern int calculation_stream_delayed_ms(u8 type,u32 *latestbirate,u32*avg_bitar extern int calculation_vcached_delayed(void); +extern int calculation_acached_delayed(void); #endif /* PTSSERV_H */ diff --git a/include/linux/amlogic/amports/tsync.h b/include/linux/amlogic/amports/tsync.h index 2e3376f5e2e1..9694938b0da9 100755 --- a/include/linux/amlogic/amports/tsync.h +++ b/include/linux/amlogic/amports/tsync.h @@ -65,6 +65,8 @@ extern void tsync_set_dec_reset(void); extern void tsync_set_enable(int enable); +extern int tsync_get_mode(void); + extern int tsync_get_sync_adiscont(void); extern int tsync_get_sync_vdiscont(void);