| /* |
| * drivers/amlogic/media/frame_sync/tsync_pcr.c |
| * |
| * Copyright (C) 2017 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/types.h> |
| #include <linux/kernel.h> |
| #include <linux/timer.h> |
| |
| #include <linux/amlogic/media/frame_sync/tsync.h> |
| #include <linux/platform_device.h> |
| #include <linux/amlogic/media/frame_sync/timestamp.h> |
| #include <linux/amlogic/media/frame_sync/ptsserv.h> |
| |
| #include <linux/amlogic/media/frame_sync/tsync_pcr.h> |
| #include <linux/amlogic/cpu_version.h> |
| |
| #ifdef CONFIG_AM_PCRSYNC_LOG |
| #define AMLOG |
| #define LOG_LEVEL_ERROR 0 |
| #define LOG_LEVEL_ATTENTION 1 |
| #define LOG_LEVEL_INFO 2 |
| #define LOG_LEVEL_VAR amlog_level_tsync_pcr |
| #define LOG_MASK_VAR amlog_mask_tsync_pcr |
| #endif |
| #include <linux/amlogic/media/utils/amlog.h> |
| MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0, LOG_DEFAULT_LEVEL_DESC, |
| LOG_DEFAULT_MASK_DESC); |
| |
| enum play_mode_e { |
| PLAY_MODE_NORMAL = 0, |
| PLAY_MODE_SLOW, |
| PLAY_MODE_SPEED, |
| PLAY_MODE_FORCE_SLOW, |
| PLAY_MODE_FORCE_SPEED, |
| }; |
| |
| enum pcr_init_priority_e { |
| INIT_PRIORITY_PCR = 0, |
| INIT_PRIORITY_AUDIO = 1, |
| INIT_PRIORITY_VIDEO = 2, |
| }; |
| |
| #define PCR_DISCONTINUE 0x01 |
| #define VIDEO_DISCONTINUE 0x02 |
| #define AUDIO_DISCONTINUE 0x10 |
| |
| #define CHECK_INTERVAL (HZ * 5) |
| |
| #define START_AUDIO_LEVEL 256 |
| #define START_VIDEO_LEVEL 2048 |
| #define PAUSE_AUDIO_LEVEL 32 |
| #define PAUSE_VIDEO_LEVEL 2560 |
| #define UP_RESAMPLE_AUDIO_LEVEL 128 |
| #define UP_RESAMPLE_VIDEO_LEVEL 1024 |
| #define DOWN_RESAMPLE_CACHE_TIME (90000*2) |
| #define NO_DATA_CHECK_TIME 4000 |
| |
| /* |
| *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 3 */ |
| #define FORCE_RECOVERY_SPAN 20 |
| #define PAUSE_CHECK_TIME 2700 |
| #define PAUSE_RESUME_TIME 18000 |
| |
| /* modify it by dolby av sync 20160126 */ |
| static u32 tsync_pcr_recovery_span = 3; /* 10 */ |
| |
| |
| |
| /* the delay from ts demuxer to the amvideo */ |
| #define DEFAULT_VSTREAM_DELAY 18000 |
| |
| #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) |
| |
| /* local system inited check type */ |
| #define TSYNC_PCR_INITCHECK_PCR 0x0001 |
| #define TSYNC_PCR_INITCHECK_VPTS 0x0002 |
| #define TSYNC_PCR_INITCHECK_APTS 0x0004 |
| #define TSYNC_PCR_INITCHECK_RECORD 0x0008 |
| #define TSYNC_PCR_INITCHECK_END 0x0010 |
| |
| #define MIN_GAP (90000*3) /* 3s */ |
| #define MAX_GAP (90000*3) /* 4s */ |
| #define MAX_AV_DIFF (90000 * 5) |
| |
| /* av sync monitor threshold */ |
| #define MAX_SYNC_VGAP_TIME 90000 |
| #define MIN_SYNC_VCHACH_TIME 45000 |
| |
| #define MAX_SYNC_AGAP_TIME 45000 |
| #define MIN_SYNC_ACHACH_TIME 27000 |
| |
| #define PLAY_MODE_THRESHOLD 500 /*ms*/ |
| #define PLAY_PCR_INVALID_THRESHOLD (10 * 90000) |
| |
| /* ------------------------------------------------------------------ */ |
| /* The const */ |
| |
| static u32 tsync_pcr_discontinue_threshold = (TIME_UNIT90K * 1.5); |
| static u32 tsync_pcr_ref_latency = (TIME_UNIT90K * 0.3); |
| |
| /* use for pcr valid mode */ |
| static u32 tsync_pcr_max_cache_time = TIME_UNIT90K * 2.4; |
| static u32 tsync_pcr_up_cache_time = TIME_UNIT90K * 2.2; |
| /* modify it by dolby av sync */ |
| static u32 tsync_pcr_down_cache_time = TIME_UNIT90K * 0.8; /* 0.6 */ |
| static u32 tsync_pcr_min_cache_time = TIME_UNIT90K * 0.4; /* 0.2 */ |
| |
| static u32 tsync_pcr_max_delay_time = TIME_UNIT90K * 3; |
| static u32 tsync_pcr_up_delay_time = TIME_UNIT90K * 2; |
| static u32 tsync_pcr_down_delay_time = TIME_UNIT90K * 1.5; |
| static u32 tsync_pcr_min_delay_time = TIME_UNIT90K * 0.8; |
| |
| static u32 tsync_apts_adj_value = 150000; /* add it by dolby av sync */ |
| static u32 tsync_pcr_adj_value = 27000; /* 300ms */ |
| |
| static u32 tsync_pcr_first_video_frame_pts; |
| static u32 tsync_pcr_first_audio_frame_pts; |
| |
| /* reset control flag */ |
| static u8 tsync_pcr_reset_flag; |
| static int tsync_pcr_asynccheck_cnt; |
| static int tsync_pcr_vsynccheck_cnt; |
| |
| static int init_check_first_systemtime; |
| static u32 init_check_first_demuxpcr; |
| |
| /* ------------------------------------------------------------------ */ |
| /* The variate */ |
| |
| static struct timer_list tsync_pcr_check_timer; |
| |
| static u32 tsync_pcr_tsdemux_startpcr; |
| |
| static int tsync_pcr_vpause_flag; |
| static int tsync_pcr_apause_flag; |
| static int tsync_pcr_vstart_flag; |
| static int tsync_pcr_astart_flag; |
| static u8 tsync_pcr_inited_flag; |
| static u8 tsync_pcr_inited_mode = INIT_PRIORITY_PCR; |
| static u32 tsync_pcr_freerun_mode; |
| |
| static int tsync_pcr_latency_value; |
| |
| static int64_t tsync_pcr_stream_delta; |
| |
| /* the really ts demuxer pcr, haven't delay */ |
| static u32 tsync_pcr_last_tsdemuxpcr; |
| static u32 tsync_pcr_discontinue_local_point; |
| static u32 tsync_pcr_discontinue_waited; |
| /* the time waited the v-discontinue to happen */ |
| static u8 tsync_pcr_tsdemuxpcr_discontinue; |
| /* the boolean value */ |
| static u32 tsync_pcr_discontinue_point; |
| |
| static int abuf_level; |
| static int abuf_size; |
| static int vbuf_level; |
| static int vbuf_size; |
| static int play_mode = PLAY_MODE_NORMAL; |
| static u8 tsync_pcr_started; |
| static int tsync_pcr_read_cnt; |
| static u8 tsync_pcr_usepcr; |
| /* static int tsync_pcr_debug_pcrscr = 100; */ |
| static u64 first_time_record; |
| static u8 wait_pcr_count; |
| |
| static int abuf_fatal_error; |
| static int vbuf_fatal_error; |
| |
| static u32 tsync_pcr_first_jiffes; |
| static u32 tsync_pcr_first_systime; |
| |
| static u32 tsync_pcr_jiffes_diff; |
| static u32 tysnc_pcr_systime_diff; |
| static u32 tsync_last_play_mode; |
| |
| static u32 tsync_use_demux_pcr = 1; |
| |
| static u32 tsync_pcr_last_jiffes; |
| static int tsync_demux_pcr_valid = 1; |
| static u32 tsync_last_pcr_get; |
| static u32 tsync_demux_pcr_time_interval; |
| static u32 tsync_system_time_interval; |
| static u32 tsync_enable_demuxpcr_check; |
| static u32 tsync_enable_bufferlevel_tune; |
| |
| static u32 tsync_pcr_debug; |
| static u32 tsync_demux_last_pcr; |
| static u32 tsync_demux_pcr_discontinue_count; |
| static u32 tsync_demux_pcr_continue_count; |
| |
| static int tsync_vpts_adjust; |
| static u32 tsync_disable_demux_pcr; |
| static u32 tsync_audio_mode; |
| static u32 tsync_audio_state; |
| static u32 tsync_video_state; |
| static int tsync_audio_underrun; |
| static int tsync_audio_underrun_maxgap = 40; |
| static int tsync_audio_discontinue; |
| static int tsync_video_discontinue; |
| static int tsync_audio_continue_count; |
| static u32 tsync_video_continue_count; |
| static u32 last_discontinue_checkin_apts; |
| static u32 last_discontinue_checkin_vpts; |
| static u32 last_pcr_checkin_apts; |
| static u32 last_pcr_checkin_vpts; |
| static u32 last_pcr_checkin_apts_count; |
| static u32 last_pcr_checkin_vpts_count; |
| static DEFINE_SPINLOCK(tsync_pcr_lock); |
| static bool video_pid_valid; |
| static bool video_jumped; |
| static bool audio_jumped; |
| |
| module_param(tsync_pcr_max_cache_time, uint, 0664); |
| MODULE_PARM_DESC(tsync_pcr_max_cache_time, "\n tsync pcr max cache time\n"); |
| |
| module_param(tsync_pcr_up_cache_time, uint, 0664); |
| MODULE_PARM_DESC(tsync_pcr_up_cache_time, "\n tsync pcr up cache time\n"); |
| |
| module_param(tsync_pcr_down_cache_time, uint, 0664); |
| MODULE_PARM_DESC(tsync_pcr_down_cache_time, "\n tsync pcr down cache time\n"); |
| |
| module_param(tsync_pcr_min_cache_time, uint, 0664); |
| MODULE_PARM_DESC(tsync_pcr_min_cache_time, "\n tsync pcr min cache time\n"); |
| struct stream_buf_s { |
| s32 flag; |
| u32 type; |
| unsigned long buf_start; |
| struct page *buf_pages; |
| int buf_page_num; |
| u32 buf_size; |
| u32 default_buf_size; |
| u32 canusebuf_size; |
| u32 first_tstamp; |
| const ulong reg_base; |
| wait_queue_head_t wq; |
| struct timer_list timer; |
| u32 wcnt; |
| u32 buf_wp; |
| u32 buf_rp; |
| u32 max_buffer_delay_ms; |
| u64 last_write_jiffies64; |
| void *write_thread; |
| int for_4k; |
| bool is_secure; |
| } /*stream_buf_t*/; |
| |
| int get_stream_buffer_level(int type) |
| { |
| struct stream_buf_s *pbuf = NULL; |
| u32 buf_level = 0; |
| |
| if (type == 0) { |
| /* video */ |
| tsync_get_buf_by_type(PTS_TYPE_VIDEO, pbuf); |
| if (pbuf && tsync_get_stbuf_level(pbuf, &buf_level) |
| && pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/) |
| return buf_level; |
| } else { |
| /* audio */ |
| tsync_get_buf_by_type(PTS_TYPE_AUDIO, pbuf); |
| if (pbuf && tsync_get_stbuf_level(pbuf, &buf_level) && |
| pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/) |
| return stbuf_level_cb(pbuf); |
| } |
| |
| return 0; |
| } |
| EXPORT_SYMBOL(get_stream_buffer_level); |
| |
| int get_stream_buffer_size(int type) |
| { |
| struct stream_buf_s *pbuf = NULL; |
| u32 buf_size = 0; |
| if (type == 0) { |
| /* video */ |
| tsync_get_buf_by_type(PTS_TYPE_VIDEO, pbuf); |
| if (pbuf && tsync_get_stbuf_size(pbuf, &buf_size) && |
| pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/) |
| return buf_size; |
| } else { |
| /* audio */ |
| tsync_get_buf_by_type(PTS_TYPE_AUDIO, pbuf); |
| if (pbuf && tsync_get_stbuf_size(pbuf, &buf_size) && |
| pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/) |
| return buf_size; |
| } |
| |
| return 0; |
| } |
| EXPORT_SYMBOL(get_stream_buffer_size); |
| |
| int get_min_cache_delay(void) |
| { |
| /*int video_cache_time = calculation_vcached_delayed();*/ |
| /*int audio_cache_time = calculation_acached_delayed();*/ |
| int audio_cache_time = 90 * calculation_stream_delayed_ms( |
| PTS_TYPE_AUDIO, NULL, NULL); |
| int video_cache_time = 90 * calculation_stream_delayed_ms( |
| PTS_TYPE_VIDEO, NULL, NULL); |
| if (video_cache_time > 0 && audio_cache_time > 0) |
| return min(video_cache_time, audio_cache_time); |
| else if (video_cache_time > 0) |
| return video_cache_time; |
| else if (audio_cache_time > 0) |
| return audio_cache_time; |
| else |
| return 0; |
| } |
| EXPORT_SYMBOL(get_min_cache_delay); |
| |
| u32 tsync_pcr_vstream_delayed(void) |
| { |
| int cur_delay = calculation_vcached_delayed(); |
| |
| if (cur_delay == -1) |
| return DEFAULT_VSTREAM_DELAY; |
| |
| return cur_delay; |
| } |
| EXPORT_SYMBOL(tsync_pcr_vstream_delayed); |
| |
| u32 tsync_pcr_get_min_checkinpts(void) |
| { |
| u32 last_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| u32 last_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); |
| |
| if (last_checkin_vpts > 0 && last_checkin_apts > 0) |
| return min(last_checkin_vpts, last_checkin_apts); |
| else if (last_checkin_apts > 0) |
| return last_checkin_apts; |
| else if (last_checkin_vpts > 0) |
| return last_checkin_vpts; |
| else |
| return 0; |
| } |
| EXPORT_SYMBOL(tsync_pcr_get_min_checkinpts); |
| |
| |
| |
| |
| static void tsync_set_pcr_mode(int mode, u32 param) |
| { |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("tsync_use_demux_pcr: %d to %d, param=0x%x\n", |
| tsync_use_demux_pcr, mode, param); |
| } |
| if (mode == 0) { |
| tsync_use_demux_pcr = 0; |
| timestamp_pcrscr_set(param); |
| timestamp_pcrscr_enable(1); |
| timestamp_vpts_set(param); |
| } else if (mode == 1) { |
| tsync_use_demux_pcr = 1; |
| timestamp_pcrscr_enable(0); |
| } |
| } |
| |
| void tsync_set_av_state(u8 type, int state) |
| { |
| if (type == 0) { |
| tsync_video_state = state; |
| return; |
| } else if (type == 1) { |
| tsync_audio_state = state; |
| if ((tsync_pcr_debug & 0x01) && state == AUDIO_STOP) |
| pr_info("audio stopped!\n"); |
| } |
| } |
| EXPORT_SYMBOL(tsync_set_av_state); |
| |
| static u32 tsync_calcpcr_by_audio(u32 first_apts, uint64_t audio_cache_pts) |
| { |
| u32 ref_pcr = 0; |
| int diff = 0; |
| |
| if (audio_cache_pts >= tsync_pcr_ref_latency) { |
| ref_pcr = first_apts + audio_cache_pts - tsync_pcr_ref_latency; |
| pr_info("use cache audio pts calc:0x%x\n", ref_pcr); |
| } else { |
| diff = tsync_pcr_ref_latency - audio_cache_pts; |
| pr_info("audio need cache diff = %d\n", diff); |
| if (first_apts > diff) |
| ref_pcr = first_apts - diff; |
| else |
| ref_pcr = 0; |
| } |
| |
| return ref_pcr; |
| } |
| |
| static u32 tsync_calcpcr_by_video(u32 first_vpts, uint64_t video_cache_pts) |
| { |
| u32 ref_pcr = 0; |
| int diff = 0; |
| |
| if (video_cache_pts >= tsync_pcr_ref_latency) { |
| ref_pcr = first_vpts; |
| } else { |
| diff = tsync_pcr_ref_latency - video_cache_pts; |
| pr_info("video need cache diff = %d\n", diff); |
| if (first_vpts > diff) |
| ref_pcr = first_vpts - diff; |
| else |
| ref_pcr = 0; |
| } |
| return ref_pcr; |
| } |
| |
| u32 tsync_pcr_get_ref_pcr(void) |
| { |
| u32 first_vpts = 0, first_apts = 0; |
| u32 first_checkin_vpts = 0; |
| u32 first_checkin_apts = 0; |
| u32 cur_checkin_apts = 0, cur_checkin_vpts = 0; |
| u32 ref_pcr = 0; |
| u32 min_checkinpts = 0; |
| int av_diff = 0; |
| uint64_t audio_cache_pts = 0; |
| uint64_t video_cache_pts = 0; |
| uint64_t pts_cache_tmp = 0; |
| int audio_cache_ms = 0; |
| int video_cache_ms = 0; |
| |
| first_apts = timestamp_firstapts_get(); |
| first_vpts = timestamp_firstvpts_get(); |
| first_checkin_apts = timestamp_checkin_firstapts_get(); |
| first_checkin_vpts = timestamp_checkin_firstvpts_get(); |
| |
| if (!first_apts) |
| first_apts = first_checkin_apts; |
| if (!first_vpts) |
| first_vpts = first_checkin_vpts; |
| /*Use the first output vpts to calc buffer cache and init pcr*/ |
| if (tsync_pcr_vstart_flag == 1) { |
| first_vpts = tsync_pcr_first_video_frame_pts; |
| pr_info("Video Start, first vpts:0x%x\n", first_vpts); |
| } |
| cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| cur_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); |
| if (cur_checkin_vpts != 0xffffffff) |
| video_cache_pts = cur_checkin_vpts - first_vpts; |
| if (cur_checkin_apts != 0xffffffff) |
| audio_cache_pts = cur_checkin_apts - first_apts; |
| if ((first_apts == 0) && (cur_checkin_apts == 0xffffffff)) |
| audio_cache_pts = 0; |
| if ((first_vpts == 0) && (cur_checkin_vpts == 0xffffffff)) |
| video_cache_pts = 0; |
| |
| pts_cache_tmp = audio_cache_pts; |
| #ifdef CONFIG_64BIT |
| audio_cache_ms = audio_cache_pts / 90; |
| video_cache_ms = video_cache_pts / 90; |
| #else |
| audio_cache_ms = do_div(pts_cache_tmp, 90); |
| pts_cache_tmp = video_cache_pts; |
| video_cache_ms = do_div(pts_cache_tmp, 90); |
| #endif |
| av_diff = first_apts - first_vpts; |
| pr_info("get_ref_pcr:apts(%x,%x,%x,cache:%dms),vpts(%x,%x,%x,cache:%dms)\n", |
| first_checkin_apts, timestamp_firstapts_get(), cur_checkin_apts, |
| audio_cache_ms, first_checkin_vpts, timestamp_firstvpts_get(), |
| cur_checkin_vpts, video_cache_ms); |
| pr_info("first_apts=%x, first_vpts=%x,av_diff=%d\n", |
| first_apts, first_vpts, av_diff); |
| |
| if ((first_apts != 0 && first_apts < first_vpts && |
| (first_vpts - first_apts <= MAX_AV_DIFF) && |
| (audio_cache_pts < first_vpts - first_apts |
| + tsync_pcr_ref_latency)) || |
| (first_vpts == 0 && cur_checkin_vpts == 0xffffffff)) { |
| ref_pcr = tsync_calcpcr_by_audio(first_apts, |
| audio_cache_pts); |
| pr_info("calc pcr by audio ref_pcr=0x%x\n", ref_pcr); |
| } else if ((first_vpts != 0 && first_apts >= first_vpts) || |
| (first_apts == 0 && cur_checkin_apts == 0xffffffff)) { |
| ref_pcr = tsync_calcpcr_by_video(first_vpts, |
| video_cache_pts); |
| pr_info("calc pcr by video ref_pcr=0x%x\n", ref_pcr); |
| } else { |
| if (first_apts == 0 && first_vpts == 0) { |
| min_checkinpts = tsync_pcr_get_min_checkinpts(); |
| ref_pcr = min_checkinpts - tsync_pcr_ref_latency; |
| pr_info("calc ref_pcr by min_checkin:0x%x, pcr:0x%x\n", |
| min_checkinpts, ref_pcr); |
| } else if ((first_vpts > 0) && |
| (first_apts == 0 && |
| cur_checkin_apts != 0xffffffff) && |
| (first_vpts > cur_checkin_apts) && |
| ((first_vpts - cur_checkin_apts) <= MAX_AV_DIFF) && |
| (audio_cache_pts < first_vpts - cur_checkin_apts + |
| tsync_pcr_ref_latency)) { |
| ref_pcr = tsync_calcpcr_by_audio(cur_checkin_apts, |
| audio_cache_pts); |
| pr_info("cal pcr by checkin_apts:0x%x,ref_pcr:0x%x\n", |
| cur_checkin_apts, ref_pcr); |
| } else { |
| if (first_vpts == 0 && cur_checkin_vpts != 0xffffffff) { |
| ref_pcr = cur_checkin_vpts - |
| tsync_pcr_ref_latency; |
| pr_info("use cur_checin vpts to calc\n"); |
| } else |
| ref_pcr = tsync_calcpcr_by_video(first_vpts, |
| video_cache_pts); |
| pr_info("default cal pcr by vpts, pcr:0x%x\n", ref_pcr); |
| } |
| } |
| pr_info("return ref_pcr = 0x%x\n", ref_pcr); |
| return ref_pcr; |
| } |
| |
| |
| void tsync_pcr_pcrscr_set(void) |
| { |
| u32 first_pcr = 0, first_vpts = 0, first_apts = 0; |
| u32 cur_checkin_apts = 0, cur_checkin_vpts = 0, min_checkinpts = 0; |
| u32 cur_pcr = 0, ref_pcr = 0; |
| u32 tmp_pcr = 0; |
| u8 complete_init_flag = |
| TSYNC_PCR_INITCHECK_PCR | TSYNC_PCR_INITCHECK_VPTS | |
| TSYNC_PCR_INITCHECK_APTS; |
| |
| if (tsync_pcr_inited_flag & complete_init_flag) { |
| return; |
| } |
| |
| tsync_get_first_demux_pcr(&first_pcr); |
| first_apts = timestamp_firstapts_get(); |
| first_vpts = timestamp_firstvpts_get(); |
| if (!first_apts) |
| first_apts = timestamp_checkin_firstapts_get(); |
| if (!first_vpts) |
| first_vpts = timestamp_checkin_firstvpts_get(); |
| cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| cur_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); |
| min_checkinpts = tsync_pcr_get_min_checkinpts(); |
| |
| tsync_get_demux_pcr(&cur_pcr); |
| abuf_level = get_stream_buffer_level(1); |
| vbuf_level = get_stream_buffer_level(0); |
| |
| if (tsync_get_video_pid_valid() && |
| tsync_get_audio_pid_valid()) { |
| if (cur_checkin_apts == 0xffffffff) { |
| pr_debug("tsync_pcr_pcrscr_set not checkin_apts\n "); |
| } |
| } else { |
| if (tsync_pcr_debug&0x01) |
| pr_info("now and the cur_checkin_apts is %x\n ", |
| cur_checkin_apts); |
| } |
| if ((!cur_checkin_vpts || cur_checkin_vpts == 0xffffffff) && |
| first_vpts) |
| cur_checkin_vpts = first_vpts; |
| if ((!cur_checkin_apts || cur_checkin_apts == 0xffffffff) && |
| first_apts) |
| cur_checkin_apts = first_apts; |
| if (tsync_pcr_debug & 0x01) { |
| pr_info("check first_pcr=%x,first_apts=%x,first_vpts %x\n", |
| first_pcr, first_apts, first_vpts); |
| pr_info("cur_pcr=%x,checkin_apts=%x,checkin_vpts=%x\n", |
| cur_pcr, cur_checkin_apts, cur_checkin_vpts); |
| pr_info("gap_pa=%d,gap_pv=%d,gap_av=%d\n", |
| (int)(cur_pcr - cur_checkin_apts) / 90, |
| (int)(cur_pcr - cur_checkin_vpts) / 90, |
| (int)(cur_checkin_apts - cur_checkin_vpts) / 90); |
| pr_info("alevel=%d vlevel=%d mode=%d min_checkinpts=0x%x\n", |
| abuf_level, vbuf_level, tsync_use_demux_pcr, |
| min_checkinpts); |
| } |
| /* check the valid of the pcr */ |
| if (cur_pcr && cur_checkin_vpts && cur_checkin_apts && |
| cur_checkin_vpts != 0xffffffff && |
| cur_checkin_apts != 0xffffffff && |
| !(tsync_pcr_inited_flag & complete_init_flag)) { |
| u32 gap_pa, gap_pv, gap_av; |
| gap_pa = abs(cur_pcr - cur_checkin_apts); |
| gap_av = abs(cur_checkin_apts - cur_checkin_vpts); |
| gap_pv = abs(cur_pcr - cur_checkin_vpts); |
| if ((gap_pa > MAX_GAP) && (gap_pv > MAX_GAP)) { |
| if (gap_av > MAX_GAP) |
| ref_pcr = cur_checkin_vpts; |
| else |
| ref_pcr = min_checkinpts - |
| tsync_pcr_ref_latency; |
| tsync_set_pcr_mode(0, ref_pcr); |
| tsync_pcr_inited_mode = |
| INIT_PRIORITY_VIDEO; |
| tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_VPTS; |
| pr_info("tsync_set:pcrsrc %x,vpts %x, mode %d\n", |
| timestamp_pcrscr_get(), timestamp_vpts_get(), |
| tsync_use_demux_pcr); |
| return; |
| } |
| } |
| /* decide use which para to init */ |
| if (cur_pcr && !(tsync_pcr_inited_flag & complete_init_flag) |
| && (min_checkinpts != 0)) { |
| tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_PCR; |
| if ((abs(cur_pcr - cur_checkin_vpts) > |
| PLAY_PCR_INVALID_THRESHOLD) && |
| cur_checkin_vpts != 0xffffffff) { |
| if (first_vpts != 0) { |
| pr_info("use first_vpts:0x%x init\n", |
| first_vpts); |
| ref_pcr = first_vpts - tsync_pcr_ref_latency; |
| } else |
| ref_pcr = cur_checkin_vpts - |
| tsync_pcr_ref_latency; |
| tsync_set_pcr_mode(0, ref_pcr); |
| tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; |
| } else if (((cur_pcr > min_checkinpts) && |
| (cur_pcr - min_checkinpts) > 500 * 90) || |
| tsync_disable_demux_pcr == 1) { |
| if (abs(cur_checkin_apts - cur_checkin_vpts) |
| > MAX_GAP) { |
| if (first_vpts != 0) { |
| pr_info("use first_vpts calc pcr\n"); |
| ref_pcr = first_vpts - |
| tsync_pcr_ref_latency; |
| } else |
| ref_pcr = cur_checkin_vpts - |
| tsync_pcr_ref_latency; |
| } else |
| ref_pcr = min_checkinpts; |
| tsync_set_pcr_mode(0, ref_pcr); |
| tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; |
| } else { |
| tsync_set_pcr_mode(1, ref_pcr); |
| tsync_pcr_inited_mode = INIT_PRIORITY_PCR; |
| } |
| pr_info("1-tsync_set:pcrsrc %x,vpts %x,mode:%d\n", |
| timestamp_pcrscr_get(), timestamp_firstvpts_get(), |
| tsync_use_demux_pcr); |
| tsync_get_demux_pcr(&init_check_first_demuxpcr); |
| return; |
| } |
| |
| if (first_apts && !(tsync_pcr_inited_flag & complete_init_flag) |
| && (min_checkinpts != 0)) { |
| tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_APTS; |
| if (tsync_pcr_debug&0x02) |
| pr_info("cur_pcr=%x first_apts=%x\n", |
| cur_pcr, first_apts); |
| if (cur_pcr && abs(cur_pcr - first_apts) |
| > PLAY_PCR_INVALID_THRESHOLD) { |
| ref_pcr = first_apts; |
| tsync_use_demux_pcr = 0; |
| if (tsync_pcr_debug&0x01) { |
| pr_info("check init.first_pcr=0x%x, first_apts=0x%x, ", |
| first_pcr, first_apts); |
| pr_info("first_vpts=0x%x, cur_pcr = 0x%x, checkin_vpts=0x%x, ", |
| first_vpts, cur_pcr, cur_checkin_vpts); |
| pr_info("checkin_apts=0x%x alevel=%d vlevel=%d\n", |
| cur_checkin_apts, abuf_level, vbuf_level); |
| pr_info("[%d]init by apts. pcr=%x usepcr=%d\n", |
| __LINE__, ref_pcr, tsync_pcr_usepcr); |
| } |
| } else if (cur_pcr) { |
| tsync_use_demux_pcr = 1; |
| tsync_pcr_inited_mode = INIT_PRIORITY_PCR; |
| ref_pcr = timestamp_pcrscr_get(); |
| if ((tsync_pcr_debug & 0x01) && |
| tsync_get_demux_pcr(&tmp_pcr)) { |
| pr_info("use the pcr from stream , the cur demux pcr is %x\n", |
| tmp_pcr); |
| pr_info("the timestamp pcr is %x\n", |
| timestamp_pcrscr_get()); |
| pr_info("the timestamp video pts is %x\n", |
| timestamp_firstvpts_get()); |
| } |
| } |
| ref_pcr = tsync_pcr_get_ref_pcr(); |
| pr_info("check apts, get min checkin ref_pcr = 0x%x", ref_pcr); |
| tsync_set_pcr_mode(0, ref_pcr); |
| tsync_pcr_inited_mode = INIT_PRIORITY_AUDIO; |
| init_check_first_systemtime = ref_pcr; |
| tsync_get_demux_pcr(&init_check_first_demuxpcr); |
| } |
| |
| if (first_vpts && !(tsync_pcr_inited_flag & complete_init_flag) |
| && (min_checkinpts != 0)) { |
| tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_VPTS; |
| if (tsync_pcr_debug&0x02) |
| pr_info("cur_pcr=%x first_vpts=%x\n", |
| cur_pcr, first_vpts); |
| if (cur_pcr && abs(cur_pcr - first_vpts) |
| > PLAY_PCR_INVALID_THRESHOLD) { |
| if (min_checkinpts == 0xffffffff) |
| ref_pcr = first_vpts > 90*300 ? |
| first_vpts - 90*300 : 0; |
| else |
| ref_pcr = min_checkinpts; |
| tsync_use_demux_pcr = 0; |
| if (tsync_pcr_debug&0x01) { |
| pr_info("check init.first_pcr=0x%x, first_apts=0x%x, ", |
| first_pcr, first_apts); |
| pr_info("first_vpts=0x%x, cur_pcr = 0x%x, checkin_vpts=0x%x, ", |
| first_vpts, cur_pcr, cur_checkin_vpts); |
| pr_info("checkin_apts=0x%x alevel=%d vlevel=%d\n", |
| cur_checkin_apts, abuf_level, vbuf_level); |
| pr_info("[%d]init by pcr. pcr=%x usepcr=%d\n", |
| __LINE__, ref_pcr, tsync_pcr_usepcr); |
| } |
| } else if (cur_pcr) { |
| ref_pcr = timestamp_pcrscr_get(); |
| tsync_use_demux_pcr = 1; |
| if ((tsync_pcr_debug & 0x01) && |
| tsync_get_demux_pcr(&tmp_pcr)) { |
| pr_info("use the pcr from stream , the cur demux pcr is %x\n", |
| tmp_pcr); |
| pr_info("the timestamp pcr is %x\n", |
| timestamp_pcrscr_get()); |
| pr_info("the timestamp video pts is %x\n", |
| timestamp_firstvpts_get()); |
| } |
| } |
| ref_pcr = tsync_pcr_get_ref_pcr(); |
| pr_info("check vpts, get min checkin ref_pcr = 0x%x", ref_pcr); |
| tsync_set_pcr_mode(0, ref_pcr); |
| tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; |
| } |
| } |
| |
| static int speed_check_count; |
| static int normal_count; |
| static u8 tsync_process_checkspeed(void) |
| { |
| u32 demuxpcr_diff = 0; |
| u32 jiffies_diff = 0; |
| u32 cur_jiffiestime = 0; |
| u32 cur_demuxpcr = 0; |
| u32 checkin_apts = 0; |
| u32 checkin_vpts = 0; |
| u32 checkout_vpts = 0; |
| u32 checkout_apts = 0; |
| |
| if (tsync_pcr_first_jiffes == 0) |
| return tsync_last_play_mode; |
| |
| cur_jiffiestime = jiffies_to_msecs(jiffies); |
| tsync_get_demux_pcr(&cur_demuxpcr); |
| |
| if (timestamp_pcrscr_enable_state() == 0) |
| return PLAY_MODE_NORMAL; |
| |
| jiffies_diff = cur_jiffiestime - tsync_pcr_first_jiffes; |
| demuxpcr_diff = cur_demuxpcr - init_check_first_demuxpcr; |
| demuxpcr_diff = demuxpcr_diff / 90; |
| |
| if (demuxpcr_diff > jiffies_diff) { |
| u32 diff_delta = demuxpcr_diff - jiffies_diff; |
| |
| if (diff_delta > PLAY_MODE_THRESHOLD) { |
| tsync_last_play_mode = PLAY_MODE_SPEED; |
| if (tsync_pcr_debug&0x01) { |
| pr_info("pcr_diff %x ", demuxpcr_diff); |
| pr_info("jiffies_diff %x ", jiffies_diff); |
| pr_info("normal_count %d\n", normal_count); |
| } |
| } else { |
| tsync_last_play_mode = PLAY_MODE_NORMAL; |
| } |
| |
| } else if (demuxpcr_diff < jiffies_diff) { |
| u32 diff_delta = jiffies_diff - demuxpcr_diff; |
| |
| if (diff_delta > PLAY_MODE_THRESHOLD) { |
| tsync_last_play_mode = PLAY_MODE_SLOW; |
| if (tsync_pcr_debug&0x01) { |
| pr_info("pcr_diff %x ", demuxpcr_diff); |
| pr_info("jiffies_diff %x ", jiffies_diff); |
| pr_info("normal_count %d\n", normal_count); |
| } |
| |
| } else { |
| tsync_last_play_mode = PLAY_MODE_NORMAL; |
| } |
| |
| } else { |
| tsync_last_play_mode = PLAY_MODE_NORMAL; |
| } |
| |
| { |
| checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); |
| checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| checkout_vpts = timestamp_vpts_get(); |
| checkout_apts = timestamp_apts_get(); |
| |
| if (checkin_apts > checkout_apts) { |
| if ((checkin_apts - checkout_apts) > |
| (PLAY_MODE_THRESHOLD * 90)) { |
| tsync_last_play_mode = PLAY_MODE_SPEED; |
| if (tsync_pcr_debug&0x01) |
| pr_info(" audio cache time %d normal_count %d\n", |
| (checkin_apts - checkout_apts), |
| normal_count); |
| } else { |
| tsync_last_play_mode = PLAY_MODE_NORMAL; |
| } |
| } |
| |
| if (checkin_vpts > checkout_vpts) { |
| if ((checkin_vpts - checkout_vpts) > |
| (PLAY_MODE_THRESHOLD * 90)) { |
| tsync_last_play_mode = PLAY_MODE_SPEED; |
| if (tsync_pcr_debug&0x01) |
| pr_info(" video cached time %d normal_count %d\n", |
| (checkin_vpts - checkout_vpts), |
| normal_count); |
| } else { |
| tsync_last_play_mode = PLAY_MODE_NORMAL; |
| } |
| } |
| |
| } |
| if (tsync_last_play_mode == PLAY_MODE_NORMAL) |
| normal_count++; |
| |
| return tsync_last_play_mode; |
| } |
| |
| static void tsync_process_demux_pcr_valid(u32 jiffis_diff) |
| { |
| u32 ratio = 100; |
| |
| if (tsync_use_demux_pcr == 0 || tsync_demux_pcr_valid == 0) |
| return; |
| |
| if (tsync_system_time_interval > 1000) { |
| ratio = tsync_demux_pcr_time_interval * 100 |
| / tsync_system_time_interval; |
| pr_info("demux interval: %u, %u, ratio:%d.", |
| tsync_demux_pcr_time_interval, |
| tsync_system_time_interval, ratio); |
| tsync_demux_pcr_time_interval = 0; |
| tsync_system_time_interval = 0; |
| } |
| |
| if (ratio > 150 && ratio < 400) { |
| tsync_use_demux_pcr = 0; |
| tsync_demux_pcr_valid = 0; |
| timestamp_pcrscr_set(tsync_last_pcr_get + |
| jiffis_diff * 90); |
| timestamp_pcrscr_enable(1); |
| pr_info("demux pcr not valid, use system time,pcr=0x%x, tsync_last_pcr_get=%x\n", |
| timestamp_pcrscr_get(), tsync_last_pcr_get); |
| } |
| } |
| |
| static void tsync_adjust_system_clock(void) |
| { |
| abuf_level = get_stream_buffer_level(1); |
| abuf_size = get_stream_buffer_size(1); |
| vbuf_level = get_stream_buffer_level(0); |
| vbuf_size = get_stream_buffer_size(0); |
| |
| pr_info("adjust vlevel=%x,vsize=%x\n", |
| vbuf_level, vbuf_size); |
| pr_info("adjust alevel=%x asize=%x play_mode=%d\n", |
| abuf_level, abuf_size, play_mode); |
| |
| if (((vbuf_level * 3 > vbuf_size * 2 && vbuf_size > 0) |
| || (abuf_level * 3 > abuf_size * 2 && abuf_size > 0)) |
| && play_mode != PLAY_MODE_FORCE_SPEED) { |
| pr_info("adjust case 1.\n"); |
| play_mode = PLAY_MODE_FORCE_SPEED; |
| } else if ((vbuf_level * 5 > vbuf_size * 4 && vbuf_size > 0) |
| || (abuf_level * 5 > abuf_size * 4 && abuf_size > 0)) { |
| u32 new_pcr = 0; |
| |
| play_mode = PLAY_MODE_FORCE_SPEED; |
| new_pcr = timestamp_pcrscr_get() + 72000; /* 90000*0.8 */ |
| timestamp_pcrscr_set(new_pcr); |
| pr_info("adjust case 2.\n"); |
| } |
| |
| if (play_mode == PLAY_MODE_FORCE_SLOW) { |
| if ((vbuf_level * 50 > vbuf_size |
| && abuf_level * 50 > abuf_size |
| && vbuf_size > 0 && abuf_size > 0) |
| || (vbuf_level * 20 > vbuf_size && vbuf_size > 0) |
| || (abuf_level * 20 > abuf_size && abuf_size > 0)) { |
| play_mode = PLAY_MODE_NORMAL; |
| pr_info("adjust case 3.\n"); |
| } |
| } else if (play_mode == PLAY_MODE_FORCE_SPEED) { |
| if ((vbuf_size > 0 && vbuf_level * 4 < vbuf_size |
| && abuf_size > 0 && abuf_level * 4 < abuf_size) |
| || (vbuf_size > 0 && vbuf_level * 4 < vbuf_size |
| && abuf_level == 0) || (abuf_size > 0 |
| && abuf_level * 4 < abuf_size |
| && vbuf_level == 0)) { |
| play_mode = PLAY_MODE_NORMAL; |
| pr_info("adjust case 4.\n"); |
| } |
| } |
| |
| if ((play_mode != PLAY_MODE_FORCE_SLOW) |
| && (play_mode != PLAY_MODE_FORCE_SPEED)) { |
| int min_cache_time = get_min_cache_delay(); |
| |
| pr_info("adjust cache:%d.", min_cache_time); |
| if (min_cache_time > tsync_pcr_max_delay_time) { |
| if (play_mode != PLAY_MODE_SPEED) { |
| play_mode = PLAY_MODE_SPEED; |
| pr_info("adjust case 5."); |
| } |
| } else if (min_cache_time < tsync_pcr_min_delay_time |
| && min_cache_time > 0) { |
| if (play_mode != PLAY_MODE_SLOW) { |
| play_mode = PLAY_MODE_SLOW; |
| pr_info("adjust case 6."); |
| } |
| } else { |
| if (tsync_pcr_down_delay_time <= min_cache_time |
| && min_cache_time <= tsync_pcr_up_delay_time |
| && play_mode != PLAY_MODE_NORMAL) { |
| play_mode = PLAY_MODE_NORMAL; |
| pr_info("adjust case 7."); |
| } |
| } |
| } |
| |
| pr_info("adjust play_mode:%d,tsync_pcr_vpause_flag:%d.", |
| play_mode, tsync_pcr_vpause_flag); |
| |
| if (!tsync_pcr_vpause_flag) { |
| if (play_mode == PLAY_MODE_SLOW) { |
| timestamp_pcrscr_set(timestamp_pcrscr_get() - |
| tsync_pcr_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() + |
| tsync_pcr_recovery_span); |
| } else if (play_mode == PLAY_MODE_FORCE_SPEED) { |
| timestamp_pcrscr_set(timestamp_pcrscr_get() + |
| FORCE_RECOVERY_SPAN); |
| } |
| } |
| } |
| |
| static void tsync_process_discontinue(void) |
| { |
| u32 cur_vpts = timestamp_vpts_get(); |
| u32 cur_tsdemuxpcr = 0; |
| u32 ref_pcr = 0, tsdemux_pcr_diff, tsdemux_pcr_diff_ms; |
| u32 cur_pcr_jiffes = 0; |
| u32 pcr_jeffes_diff_ms = 0; |
| |
| u32 cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| |
| if (tsync_get_demux_pcr(&tsync_demux_last_pcr) && |
| (tsync_demux_last_pcr == 0 || |
| tsync_demux_last_pcr == 0xffffffff)) { |
| tsync_last_pcr_get = timestamp_pcrscr_get(); |
| tsync_pcr_last_jiffes = jiffies_to_msecs(jiffies); |
| } |
| if (tsync_get_demux_pcr(&cur_tsdemuxpcr)) |
| cur_pcr_jiffes = jiffies_to_msecs(jiffies); |
| else |
| return; |
| |
| tsdemux_pcr_diff = abs(cur_tsdemuxpcr - tsync_demux_last_pcr); |
| tsdemux_pcr_diff_ms = tsdemux_pcr_diff / 90; |
| pcr_jeffes_diff_ms = cur_pcr_jiffes - tsync_pcr_last_jiffes; |
| tsync_demux_pcr_time_interval += tsdemux_pcr_diff_ms; |
| tsync_system_time_interval += pcr_jeffes_diff_ms; |
| |
| if (cur_tsdemuxpcr == 0xffffffff || cur_tsdemuxpcr == 0 |
| || pcr_jeffes_diff_ms == 0) |
| return; |
| |
| if (tsync_enable_demuxpcr_check) |
| tsync_process_demux_pcr_valid(pcr_jeffes_diff_ms); |
| |
| tsync_pcr_last_jiffes = jiffies_to_msecs(jiffies); |
| tsync_last_pcr_get = timestamp_pcrscr_get(); |
| |
| if (tsync_pcr_inited_mode != INIT_PRIORITY_PCR) { |
| if ((tsync_pcr_tsdemuxpcr_discontinue & VIDEO_DISCONTINUE) |
| == VIDEO_DISCONTINUE) { |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("inited_mode=%d, cur_checkin_vpts %x\n", |
| tsync_pcr_inited_mode, |
| cur_checkin_vpts); |
| } |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| } |
| return; |
| } |
| //tsdemux_pcr_diff = abs(cur_tsdemuxpcr - tsync_demux_last_pcr); |
| if (tsync_demux_last_pcr != 0 && cur_tsdemuxpcr != 0 |
| && tsdemux_pcr_diff > tsync_pcr_discontinue_threshold) { |
| tsync_demux_pcr_discontinue_count++; |
| tsync_demux_pcr_continue_count = 0; |
| tsync_demux_last_pcr = cur_tsdemuxpcr; |
| } else { |
| tsync_demux_pcr_discontinue_count = 0; |
| tsync_demux_last_pcr = cur_tsdemuxpcr; |
| tsync_demux_pcr_continue_count++; |
| if (tsync_pcr_demux_pcr_used() == 0 && |
| abs(cur_tsdemuxpcr - cur_vpts) < |
| tsync_vpts_discontinuity_margin() && |
| tsync_demux_pcr_continue_count > 10 && |
| abs(cur_checkin_vpts - cur_vpts) < |
| tsync_vpts_discontinuity_margin() && |
| tsync_demux_pcr_valid) { |
| tsync_set_pcr_mode(1, cur_vpts); |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("discontinue,resume checkvpts %x,curvpts %x\n", |
| cur_checkin_vpts, cur_vpts); |
| } |
| return; |
| } |
| } |
| if (tsync_demux_pcr_discontinue_count > 100) { |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("PCR_DISCONTINUE, reset!,checkvpts %x,curvpts %x\n", |
| cur_checkin_vpts, cur_vpts); |
| } |
| tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; |
| cur_checkin_vpts -= tsync_pcr_ref_latency; |
| tsync_set_pcr_mode(0, cur_checkin_vpts); |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("pcr_dis_count=%d, cur_checkin_vpts %x\n", |
| tsync_demux_pcr_discontinue_count, |
| cur_checkin_vpts); |
| } |
| return; |
| } |
| if ((tsync_pcr_tsdemuxpcr_discontinue & |
| (VIDEO_DISCONTINUE | PCR_DISCONTINUE)) == |
| VIDEO_DISCONTINUE) { |
| if (abs(cur_checkin_vpts - cur_vpts) > |
| tsync_vpts_discontinuity_margin()) { |
| pr_info("v_dis cur_checkin_vpts=0x%x, cur_vpts=0x%x\n", |
| cur_checkin_vpts, cur_vpts); |
| tsync_set_pcr_mode(0, cur_vpts); |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| } else if (!tsync_check_vpts_discontinuity(cur_vpts) && |
| tsync_pcr_demux_pcr_used() == 0 && |
| tsync_demux_pcr_valid) { |
| tsync_set_pcr_mode(1, cur_vpts); |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| } else if (tsync_pcr_demux_pcr_used() == 0 && |
| tsync_video_continue_count > 100) { |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| tsync_set_pcr_mode(1, cur_checkin_vpts); |
| } else { |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| return; |
| } |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("VIDEO_DISCONTINUE checkvpts %x,curvpts %x\n", |
| cur_checkin_vpts, cur_vpts); |
| } |
| } else if ((tsync_pcr_tsdemuxpcr_discontinue & |
| (VIDEO_DISCONTINUE|PCR_DISCONTINUE)) == |
| PCR_DISCONTINUE) { |
| if (tsync_use_demux_pcr == 1) { |
| ref_pcr -= tsync_pcr_ref_latency; |
| timestamp_pcrscr_set(ref_pcr); |
| timestamp_pcrscr_enable(1); |
| tsync_use_demux_pcr = 0; |
| } |
| } else if ((tsync_pcr_tsdemuxpcr_discontinue & |
| (VIDEO_DISCONTINUE|PCR_DISCONTINUE)) == |
| (VIDEO_DISCONTINUE|PCR_DISCONTINUE)) { |
| tsync_use_demux_pcr = 1; |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| } |
| } |
| |
| static void tsync_audio_underrun_check(u32 last_pcr_checkin_apts, |
| u32 checkin_apts) |
| { |
| if (last_pcr_checkin_apts == checkin_apts) { |
| if (tsync_pcr_demux_pcr_used() == 1) |
| tsync_audio_underrun_maxgap = 40; |
| last_pcr_checkin_apts_count++; |
| if (last_pcr_checkin_apts_count > tsync_audio_underrun_maxgap) { |
| tsync_audio_underrun = 1; |
| if (tsync_pcr_debug & 0x03) |
| pr_info("audio underrun\n"); |
| } |
| } else { |
| last_pcr_checkin_apts_count = 0; |
| tsync_audio_underrun = 0; |
| } |
| } |
| |
| void tsync_pcr_check_checinpts(void) |
| { |
| u32 checkin_vpts = 0; |
| u32 checkin_apts = 0; |
| int max_gap; |
| u32 cur_vpts = 0; |
| u32 cur_apts = 0; |
| int clear_audio_discontinue = 0; |
| |
| if (tsync_pcr_astart_flag == 1) { |
| checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); |
| if ((checkin_apts != 0xffffffff) && |
| (last_pcr_checkin_apts != 0) && |
| (last_pcr_checkin_apts != 0xffffffff)) { |
| if (abs(last_pcr_checkin_apts - checkin_apts) |
| > AV_DISCONTINUE_THREDHOLD_MIN) { |
| tsync_pcr_tsdemuxpcr_discontinue |= |
| AUDIO_DISCONTINUE; |
| tsync_audio_discontinue = 1; |
| last_discontinue_checkin_apts = 0; |
| tsync_audio_continue_count = 0; |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("a_discontinue,last %x,cur %x\n", |
| last_pcr_checkin_apts, |
| checkin_apts); |
| } |
| } |
| if (tsync_get_new_arch() && |
| tsync_get_demux_pcrscr_valid()) |
| tsync_audio_underrun_check( |
| last_pcr_checkin_apts, |
| checkin_apts); |
| if (tsync_audio_discontinue == 1 && |
| checkin_apts != 0xffffffff && |
| last_discontinue_checkin_apts == 0 && |
| checkin_apts > last_pcr_checkin_apts && |
| ((checkin_apts - last_pcr_checkin_apts) |
| < 500 * 90)) { |
| last_discontinue_checkin_apts = |
| last_pcr_checkin_apts; |
| tsync_audio_continue_count = 1; |
| if (tsync_pcr_debug & 0x03) |
| pr_info("a_last:%x, cur:%x\n", |
| last_pcr_checkin_apts, |
| checkin_apts); |
| } |
| last_pcr_checkin_apts = checkin_apts; |
| |
| if (tsync_audio_continue_count) |
| tsync_audio_continue_count++; |
| if (tsync_audio_discontinue && video_pid_valid) { |
| cur_vpts = timestamp_vpts_get(); |
| cur_apts = timestamp_apts_get(); |
| if (!video_jumped && |
| last_discontinue_checkin_apts && |
| abs(cur_vpts - |
| last_discontinue_checkin_apts) < |
| 5000 * 90) { |
| video_jumped = true; |
| pr_info("v_continue:cur_vpts=%x\n", |
| cur_vpts); |
| } |
| if (!audio_jumped && |
| last_discontinue_checkin_apts && |
| abs(cur_apts - |
| last_discontinue_checkin_apts) < |
| 5000 * 90) { |
| audio_jumped = true; |
| pr_info("a_continue:cur_apts=%x\n", |
| cur_apts); |
| } |
| |
| if (video_jumped && audio_jumped) { |
| pr_info("cur_vpts=%x,cur_apts=%x\n", |
| cur_vpts, cur_apts); |
| clear_audio_discontinue = 1; |
| } else if (tsync_audio_continue_count > 500) { |
| pr_info("a_continue timeout,clear\n"); |
| clear_audio_discontinue = 1; |
| } |
| } |
| if (((!video_pid_valid && |
| tsync_audio_continue_count > 50) || |
| (video_pid_valid && clear_audio_discontinue)) && |
| tsync_audio_discontinue && |
| last_discontinue_checkin_apts) { |
| tsync_audio_discontinue = 0; |
| video_jumped = false; |
| audio_jumped = false; |
| if (tsync_pcr_debug & 0x03) |
| pr_info("a_continued,resumed\n"); |
| } |
| } else { |
| last_pcr_checkin_apts = checkin_apts; |
| } |
| } |
| |
| if (tsync_pcr_vstart_flag == 1) { |
| checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| if ((checkin_vpts != 0xffffffff) && |
| (last_pcr_checkin_vpts != 0) && |
| (last_pcr_checkin_vpts != 0xffffffff)) { |
| if (abs(last_pcr_checkin_vpts - checkin_vpts) |
| > 2 * 90000) { |
| tsync_pcr_tsdemuxpcr_discontinue |= |
| VIDEO_DISCONTINUE; |
| tsync_video_discontinue = 1; |
| last_discontinue_checkin_vpts = 0; |
| tsync_video_continue_count = 0; |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("v_discontinue,last %x,cur %x\n", |
| last_pcr_checkin_vpts, |
| checkin_vpts); |
| } |
| } |
| if (last_pcr_checkin_vpts == checkin_vpts) { |
| if (tsync_pcr_demux_pcr_used() == 1) |
| max_gap = 100; |
| else |
| max_gap = 300; |
| last_pcr_checkin_vpts_count++; |
| if (last_pcr_checkin_vpts_count > max_gap) { |
| tsync_pcr_tsdemuxpcr_discontinue |= |
| VIDEO_DISCONTINUE; |
| tsync_video_discontinue = 1; |
| last_discontinue_checkin_vpts = 0; |
| tsync_video_continue_count = 0; |
| if (tsync_pcr_debug & 0x03) |
| pr_info("v_discontinue,count\n"); |
| } |
| } else { |
| if (tsync_video_discontinue == 1 && |
| checkin_vpts != 0xffffffff && |
| last_discontinue_checkin_vpts == 0 && |
| checkin_vpts > last_pcr_checkin_vpts && |
| (abs(checkin_vpts |
| - last_pcr_checkin_vpts) |
| < 500 * 90)) { |
| last_discontinue_checkin_vpts = |
| last_pcr_checkin_vpts; |
| tsync_video_continue_count = 1; |
| } |
| last_pcr_checkin_vpts = checkin_vpts; |
| last_pcr_checkin_vpts_count = 0; |
| } |
| if (tsync_video_continue_count) { |
| tsync_video_continue_count++; |
| } |
| if (tsync_video_continue_count > 15 && |
| tsync_video_discontinue && |
| last_discontinue_checkin_vpts) { |
| tsync_video_discontinue = 0; |
| if (tsync_pcr_debug & 0x03) |
| pr_info("v_continued,resumed\n"); |
| } |
| } else { |
| last_pcr_checkin_vpts = checkin_vpts; |
| } |
| } |
| } |
| EXPORT_SYMBOL(tsync_pcr_pcrscr_set); |
| |
| void tsync_pcr_avevent_locked(enum avevent_e event, u32 param) |
| { |
| ulong flags; |
| u32 first_apts; |
| u32 cur_checkin_vpts, cur_checkin_apts; |
| u32 ref_pcr; |
| u32 cur_pcr; |
| u8 complete_init_flag = |
| TSYNC_PCR_INITCHECK_PCR | TSYNC_PCR_INITCHECK_VPTS | |
| TSYNC_PCR_INITCHECK_APTS; |
| spin_lock_irqsave(&tsync_pcr_lock, flags); |
| |
| switch (event) { |
| case VIDEO_START: |
| first_apts = timestamp_firstapts_get(); |
| cur_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); |
| if (tsync_pcr_vstart_flag == 0) { |
| /* play_mode=PLAY_MODE_NORMAL; */ |
| tsync_pcr_first_video_frame_pts = param; |
| pr_info("VIDEO_START! param=%x cur_pcr=%x\n", param, |
| timestamp_pcrscr_get()); |
| } |
| if (!timestamp_firstvpts_get() && param) |
| timestamp_firstvpts_set(param); |
| tsync_set_av_state(0, 2); |
| /*tsync_pcr_inited_mode = INIT_MODE_VIDEO;*/ |
| tsync_pcr_vstart_flag = 1; |
| |
| if (first_apts == 0 && |
| cur_checkin_apts == 0xffffffff && |
| tsync_get_audio_pid_valid()) { |
| } else { |
| tsync_get_demux_pcr(&cur_pcr); |
| cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| if (cur_checkin_vpts != 0xffffffff && |
| (abs(cur_pcr - cur_checkin_vpts) > |
| PLAY_PCR_INVALID_THRESHOLD) && |
| (tsync_pcr_inited_flag & complete_init_flag) && |
| tsync_get_new_arch()) |
| tsync_set_pcr_mode(0, cur_checkin_vpts); |
| else |
| tsync_pcr_pcrscr_set(); |
| } |
| break; |
| |
| case VIDEO_STOP: |
| timestamp_pcrscr_enable(0); |
| pr_info("VIDEO_STOP: reset pts !\n"); |
| timestamp_firstvpts_set(0); |
| timestamp_firstapts_set(0); |
| timestamp_checkin_firstvpts_set(0); |
| timestamp_checkin_firstapts_set(0); |
| timestamp_vpts_set(0); |
| timestamp_vpts_set_u64(0); |
| /* tsync_pcr_debug_pcrscr=100; */ |
| tsync_set_av_state(0, 3); |
| tsync_pcr_vpause_flag = 0; |
| tsync_pcr_vstart_flag = 0; |
| tsync_pcr_inited_flag = 0; |
| wait_pcr_count = 0; |
| |
| pr_info("wait_pcr_count = 0\n"); |
| tsync_pcr_tsdemuxpcr_discontinue = 0; |
| tsync_pcr_discontinue_point = 0; |
| tsync_pcr_discontinue_local_point = 0; |
| tsync_pcr_discontinue_waited = 0; |
| tsync_pcr_first_video_frame_pts = 0; |
| video_pid_valid = false; |
| video_jumped = false; |
| tsync_pcr_tsdemux_startpcr = 0; |
| play_mode = PLAY_MODE_NORMAL; |
| first_time_record = div64_u64((u64)jiffies * TIME_UNIT90K, HZ); |
| pr_info("update time record\n"); |
| tsync_reset(); |
| pr_info("video stop!\n"); |
| break; |
| |
| case VIDEO_TSTAMP_DISCONTINUITY:{ |
| unsigned int systime; |
| unsigned int demux_pcr; |
| |
| cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| if (tsync_pcr_debug & 0x03) |
| pr_info("VIDEO_TSTAMP_DISCONTINUITY param:0x%x,in:%x\n", |
| param, cur_checkin_vpts); |
| if (tsync_pcr_inited_mode != INIT_PRIORITY_PCR) { |
| if (cur_checkin_vpts > param && |
| (cur_checkin_vpts - param < 90000)) { |
| ref_pcr = param - tsync_pcr_ref_latency; |
| timestamp_pcrscr_set(ref_pcr); |
| } else |
| timestamp_pcrscr_set(param); |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("vdiscontinue param %x,pcrsrc %x\n", |
| param, timestamp_pcrscr_get()); |
| } |
| } else if (tsync_get_demux_pcrscr_valid() && |
| tsync_check_vpts_discontinuity(param)) { |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("vdiscontinue %d,param %x,pcrsrc %x\n", |
| tsync_use_demux_pcr, param, |
| timestamp_pcrscr_get()); |
| } |
| if (tsync_pcr_demux_pcr_used() == 1) { |
| systime = timestamp_pcrscr_get() + |
| timestamp_get_pcrlatency(); |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("used sys=0x%x, param=0x%x\n", |
| systime, param); |
| } |
| if (systime + 900000 < param) |
| tsync_set_pcr_mode(0, param); |
| else |
| timestamp_pcrscr_set(param); |
| } else { |
| systime = timestamp_pcrscr_get(); |
| tsync_get_demux_pcr(&demux_pcr); |
| if (tsync_pcr_debug & 0x03) { |
| pr_info("sys=%x, param=%x, pcr=%x\n", |
| systime, param, demux_pcr); |
| } |
| if ((demux_pcr + 900000 > param) && |
| tsync_demux_pcr_valid) |
| tsync_set_pcr_mode(1, param); |
| else |
| timestamp_pcrscr_set(param); |
| } |
| } |
| timestamp_vpts_set(param); |
| break; |
| } |
| case AUDIO_TSTAMP_DISCONTINUITY:{ |
| tsync_pcr_tsdemuxpcr_discontinue |= AUDIO_DISCONTINUE; |
| timestamp_apts_set(param); |
| param = timestamp_pcrscr_get(); |
| timestamp_apts_set(param); |
| } |
| break; |
| |
| case AUDIO_PRE_START: |
| timestamp_apts_start(0); |
| tsync_pcr_astart_flag = 0; |
| pr_info("audio prestart!\n"); |
| break; |
| |
| case AUDIO_START: |
| tsync_set_av_state(1, AUDIO_START); |
| timestamp_apts_set(param); |
| timestamp_firstapts_set(param); |
| timestamp_apts_enable(1); |
| timestamp_apts_start(1); |
| tsync_pcr_first_audio_frame_pts = param; |
| tsync_pcr_astart_flag = 1; |
| tsync_pcr_apause_flag = 0; |
| pr_info("AUDIO_START!timestamp_apts_set =%x. cur_pcr %x\n", |
| param, timestamp_pcrscr_get()); |
| break; |
| |
| case AUDIO_RESUME: |
| timestamp_apts_enable(1); |
| tsync_pcr_apause_flag = 0; |
| pr_info("audio resume!\n"); |
| break; |
| |
| case AUDIO_STOP: |
| tsync_set_av_state(1, AUDIO_STOP); |
| timestamp_apts_enable(0); |
| timestamp_apts_set(-1); |
| timestamp_firstapts_set(0); |
| timestamp_checkin_firstvpts_set(0); |
| timestamp_checkin_firstapts_set(0); |
| timestamp_apts_start(0); |
| audio_jumped = false; |
| tsync_pcr_astart_flag = 0; |
| tsync_pcr_apause_flag = 0; |
| tsync_pcr_first_audio_frame_pts = 0; |
| pr_info("AUDIO_STOP!\n"); |
| break; |
| |
| case AUDIO_PAUSE: |
| timestamp_apts_enable(0); |
| tsync_pcr_apause_flag = 1; |
| pr_info("audio pause!\n"); |
| break; |
| |
| case VIDEO_PAUSE: |
| if (param == 1) { |
| timestamp_pcrscr_enable(0); |
| tsync_pcr_vpause_flag = 1; |
| pr_info("video pause!\n"); |
| } else { |
| timestamp_pcrscr_enable(1); |
| tsync_pcr_vpause_flag = 0; |
| pr_info("video resume\n"); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| switch (event) { |
| case VIDEO_START: |
| case AUDIO_START: |
| case AUDIO_RESUME: |
| /*amvdev_resume();*//*DEBUG_TMP*/ |
| break; |
| case VIDEO_STOP: |
| case AUDIO_STOP: |
| case AUDIO_PAUSE: |
| /*amvdev_pause();*//*DEBUG_TMP*/ |
| break; |
| case VIDEO_PAUSE: |
| /*if (tsync_pcr_vpause_flag)*/ |
| /*amvdev_pause();*//*DEBUG_TMP*/ |
| /*else*/ |
| /*amvdev_resume();*//*DEBUG_TMP*/ |
| break; |
| default: |
| break; |
| } |
| |
| spin_unlock_irqrestore(&tsync_pcr_lock, flags); |
| } |
| EXPORT_SYMBOL(tsync_pcr_avevent_locked); |
| |
| /* timer to check the system with the referrence time in ts stream. */ |
| static unsigned long tsync_pcr_check(void) |
| { |
| u32 tsdemux_pcr = 0; |
| u32 tsdemux_pcr_diff = 0; |
| int need_recovery = 1; |
| unsigned long res = 1; |
| int64_t last_checkin_vpts = 0; |
| int64_t last_checkin_apts = 0; |
| int64_t last_cur_pcr = 0; |
| int64_t last_checkin_minpts = 0; |
| u32 cur_apts = 0; |
| u32 cur_vpts = 0; |
| u32 tmp_pcr = 0; |
| video_pid_valid = false; |
| |
| if (tsync_get_mode() != TSYNC_MODE_PCRMASTER |
| || tsync_pcr_freerun_mode == 1) |
| return res; |
| |
| if (tsync_pcr_first_jiffes != 0) { |
| tsync_pcr_jiffes_diff = jiffies_to_msecs(jiffies) |
| - tsync_pcr_first_jiffes; |
| if (tsync_get_demux_pcr(&tmp_pcr)) |
| tysnc_pcr_systime_diff = |
| tmp_pcr - tsync_pcr_first_systime; |
| } |
| |
| video_pid_valid = tsync_get_video_pid_valid(); |
| |
| tsync_pcr_check_checinpts(); |
| tsync_get_demux_pcr(&tsdemux_pcr); |
| last_checkin_vpts = (u32)get_last_checkin_pts(PTS_TYPE_VIDEO); |
| last_checkin_apts = (u32)get_last_checkin_pts(PTS_TYPE_AUDIO); |
| |
| 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 >= TSYNC_PCR_INITCHECK_PCR) { |
| u32 video_delayed = 0; |
| tsync_pcr_tsdemuxpcr_discontinue |= PCR_DISCONTINUE; |
| 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; |
| if (tsync_pcr_debug&0x02) { |
| pr_info("[tsync_pcr_check] refpcr_discontinue.\n"); |
| pr_info("tsdemux_pcr_diff=%x, last refpcr=%x,\n", |
| tsdemux_pcr_diff, |
| tsync_pcr_last_tsdemuxpcr); |
| pr_info("repcr=%x,waited=%x\n", |
| tsdemux_pcr, |
| tsync_pcr_discontinue_waited); |
| pr_info("last checkin vpts:%d\n", |
| (u32)get_last_checkin_pts(PTS_TYPE_VIDEO)); |
| pr_info("last checkin apts:%d\n", |
| (u32)get_last_checkin_pts(PTS_TYPE_AUDIO)); |
| } |
| tsync_pcr_discontinue_local_point = |
| timestamp_pcrscr_get(); |
| tsync_pcr_discontinue_point = |
| tsdemux_pcr - tsync_pcr_ref_latency; |
| need_recovery = 0; |
| } else if (tsync_pcr_tsdemuxpcr_discontinue & PCR_DISCONTINUE) { |
| /* to pause the pcr check */ |
| if ((abs |
| (timestamp_pcrscr_get() |
| - tsync_pcr_discontinue_local_point)) |
| > tsync_pcr_discontinue_waited){ |
| if (tsync_pcr_debug & 0x02) { |
| u32 temp = 0; |
| |
| temp = |
| tsync_pcr_discontinue_local_point; |
| pr_info( |
| "[tsync_pcr_check] audio or video"); |
| pr_info( |
| "discontinue didn't happen, waited=%x\n", |
| tsync_pcr_discontinue_waited); |
| pr_info( |
| " timestamp_pcrscr_get() =%x\n", |
| timestamp_pcrscr_get()); |
| pr_info( |
| "tsync_pcr_discontinue_local_point =%x\n", |
| temp); |
| } |
| /* 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; |
| } |
| if ((!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_VPTS)) |
| && (!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_PCR)) |
| && (!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_APTS))) { |
| u64 cur_system_time = |
| div64_u64((u64)jiffies * TIME_UNIT90K, HZ); |
| if ((cur_system_time - first_time_record) < |
| tsync_pcr_latency_value |
| && video_pid_valid) { |
| if (tsync_pcr_vstart_flag == 1 && |
| tsync_get_audio_pid_valid() && |
| last_checkin_apts != 0xffffffff) { |
| tsync_pcr_pcrscr_set(); |
| } |
| } else { |
| if (video_pid_valid) |
| tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; |
| else |
| tsync_pcr_inited_mode = INIT_PRIORITY_AUDIO; |
| tsync_pcr_pcrscr_set(); |
| } |
| return res; |
| } |
| |
| abuf_level = get_stream_buffer_level(1); |
| abuf_size = get_stream_buffer_size(1); |
| vbuf_level = get_stream_buffer_level(0); |
| vbuf_size = get_stream_buffer_size(0); |
| |
| /* |
| ********************************************************** |
| * On S905/S905X Platform, when we play avs video file on dtv |
| *which contian long cabac some time it will cause amstream |
| *video buffer enter an error status. vbuf_level will over vbuf_size, |
| *this will cause a lot of print in this function. And that will |
| *prevent reset ts monitor work thread from getting cpu control |
| *and to reset ts module. So we add the following code to avoid |
| *this case. |
| * |
| * Rong.Zhang@amlogic.com 2016-08-10 |
| ********************************************************** |
| */ |
| if (abuf_level > abuf_size) { |
| if (!abuf_fatal_error) { |
| abuf_fatal_error = 1; |
| } |
| return res; |
| } |
| |
| if (vbuf_level > vbuf_size) { |
| if (!vbuf_fatal_error) { |
| vbuf_fatal_error = 1; |
| } |
| return res; |
| } |
| |
| last_cur_pcr = timestamp_pcrscr_get(); |
| last_checkin_minpts = tsync_pcr_get_min_checkinpts(); |
| cur_apts = timestamp_apts_get(); |
| cur_vpts = timestamp_vpts_get(); |
| |
| tsync_process_discontinue(); |
| if (tsync_use_demux_pcr || tsync_demux_pcr_valid) |
| play_mode = tsync_process_checkspeed(); |
| else if (tsync_enable_bufferlevel_tune) |
| tsync_adjust_system_clock(); |
| |
| return res; |
| } |
| |
| static void tsync_pcr_check_timer_func(unsigned long arg) |
| { |
| ulong flags; |
| |
| spin_lock_irqsave(&tsync_pcr_lock, flags); |
| tsync_pcr_check(); |
| spin_unlock_irqrestore(&tsync_pcr_lock, flags); |
| |
| tsync_pcr_check_timer.expires = |
| (unsigned long)(jiffies + TEN_MS_INTERVAL); |
| |
| add_timer(&tsync_pcr_check_timer); |
| } |
| |
| static void tsync_pcr_param_reset(void) |
| { |
| 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; |
| wait_pcr_count = 0; |
| tsync_pcr_reset_flag = 0; |
| tsync_pcr_asynccheck_cnt = 0; |
| tsync_pcr_vsynccheck_cnt = 0; |
| tsync_pcr_last_tsdemuxpcr = 0; |
| tsync_pcr_discontinue_local_point = 0; |
| tsync_pcr_discontinue_point = 0; |
| /* the time waited the v-discontinue to happen */ |
| tsync_pcr_discontinue_waited = 0; |
| 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; |
| tsync_reset(); |
| /*tsync_pcr_inited_mode = INIT_MODE_VIDEO; */ |
| tsync_pcr_stream_delta = 0; |
| |
| last_pcr_checkin_apts = 0; |
| last_pcr_checkin_vpts = 0; |
| last_pcr_checkin_apts_count = 0; |
| last_pcr_checkin_vpts_count = 0; |
| tsync_last_play_mode = PLAY_MODE_NORMAL; |
| tsync_pcr_first_jiffes = 0; |
| tsync_pcr_first_systime = 0; |
| speed_check_count = 0; |
| tsync_audio_discontinue = 0; |
| tsync_audio_continue_count = 0; |
| tsync_video_continue_count = 0; |
| last_discontinue_checkin_apts = 0; |
| tsync_vpts_adjust = 0; |
| last_discontinue_checkin_vpts = 0; |
| tsync_video_discontinue = 0; |
| video_pid_valid = false; |
| video_jumped = false; |
| audio_jumped = false; |
| } |
| |
| int tsync_pcr_set_apts(unsigned int pts) |
| { |
| timestamp_apts_set(pts); |
| /* pr_info("[tsync_pcr_set_apts]set apts=%x",pts); */ |
| return 0; |
| } |
| EXPORT_SYMBOL(tsync_pcr_set_apts); |
| |
| int tsync_get_vpts_adjust(void) |
| { |
| return tsync_vpts_adjust * 90; |
| } |
| EXPORT_SYMBOL(tsync_get_vpts_adjust); |
| |
| int tsync_pcr_start(void) |
| { |
| if (tsync_pcr_started) |
| return 0; |
| |
| timestamp_pcrscr_enable(0); |
| timestamp_pcrscr_set(0); |
| |
| tsync_pcr_param_reset(); |
| if (tsync_get_mode() == TSYNC_MODE_PCRMASTER) { |
| pr_info("[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 = (unsigned long)jiffies; |
| |
| first_time_record = div64_u64((u64)jiffies * TIME_UNIT90K, HZ); |
| tsync_pcr_started = 1; |
| if ((tsync_get_demux_pcrscr_valid() == 0) || |
| tsync_disable_demux_pcr == 1) { |
| tsync_use_demux_pcr = 0; |
| tsync_pcr_inited_mode = INIT_PRIORITY_AUDIO; |
| } else { |
| tsync_use_demux_pcr = 1; |
| tsync_pcr_inited_mode = INIT_PRIORITY_PCR; |
| } |
| tsync_pcr_read_cnt = 0; |
| add_timer(&tsync_pcr_check_timer); |
| pr_info("start:inited_mode=%d,tsync_use_demux_pcr=%d.\n", |
| tsync_pcr_inited_mode, tsync_use_demux_pcr); |
| } |
| abuf_fatal_error = 0; |
| vbuf_fatal_error = 0; |
| tsync_demux_last_pcr = 0; |
| tsync_demux_pcr_discontinue_count = 0; |
| tsync_demux_pcr_continue_count = 0; |
| tsync_audio_state = 1; |
| tsync_video_state = 1; |
| tsync_demux_pcr_valid = 1; |
| tsync_demux_pcr_time_interval = 0; |
| tsync_system_time_interval = 0; |
| return 0; |
| } |
| EXPORT_SYMBOL(tsync_pcr_start); |
| |
| int tsync_pcr_demux_pcr_used(void) |
| { |
| return tsync_use_demux_pcr; |
| } |
| EXPORT_SYMBOL(tsync_pcr_demux_pcr_used); |
| |
| void tsync_pcr_stop(void) |
| { |
| if (tsync_pcr_started == 1) { |
| del_timer_sync(&tsync_pcr_check_timer); |
| pr_info("[tsync_pcr_stop]PCRMASTER stop success.\n"); |
| } |
| tsync_pcr_freerun_mode = 0; |
| tsync_pcr_started = 0; |
| tsync_audio_state = 0; |
| tsync_video_state = 0; |
| video_jumped = false; |
| audio_jumped = false; |
| timestamp_checkin_firstvpts_set(0); |
| timestamp_checkin_firstapts_set(0); |
| timestamp_vpts_set(0); |
| timestamp_vpts_set_u64(0); |
| timestamp_pcrscr_set(0); |
| tsync_reset(); |
| tsync_demux_pcr_valid = 1; |
| } |
| EXPORT_SYMBOL(tsync_pcr_stop); |
| |
| /* ------------------------------------------------------------------------ */ |
| /* define of tsync pcr class node */ |
| |
| static ssize_t show_play_mode(struct class *class, |
| struct class_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%d\n", play_mode); |
| } |
| |
| static ssize_t pcr_diff_show(struct class *class, |
| struct class_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%d %d %d %s\n", tsync_pcr_jiffes_diff * 90, |
| tysnc_pcr_systime_diff, |
| tsync_pcr_jiffes_diff - tysnc_pcr_systime_diff / 90, |
| "ms"); |
| } |
| |
| static ssize_t show_tsync_pcr_dispoint(struct class *class, |
| struct class_attribute *attr, char *buf) |
| { |
| pr_info("[%s:%d] tsync_pcr_discontinue_point:%x, HZ:%x,\n", |
| __func__, __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 int pts; |
| ssize_t r; |
| |
| /*r = sscanf(buf, "0x%x", &pts);*/ |
| r = kstrtoint(buf, 0, &pts); |
| |
| if (r != 0) |
| return -EINVAL; |
| |
| tsync_pcr_discontinue_point = pts; |
| pr_info("[%s:%d] tsync_pcr_discontinue_point:%x,\n", __func__, |
| __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 int type; |
| ssize_t r; |
| |
| /*r = sscanf(buf, "%d", &type);*/ |
| r = kstrtoint(buf, 0, &type); |
| |
| if (r != 0) |
| return -EINVAL; |
| |
| if (type == RESAMPLE_DOWN_FORCE_PCR_SLOW) { |
| play_mode = PLAY_MODE_SLOW; |
| pr_info("[%s:%d] Audio to FORCE_PCR_SLOW\n", __func__, |
| __LINE__); |
| } |
| return size; |
| } |
| |
| static ssize_t tsync_pcr_mode_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_use_demux_pcr); |
| } |
| |
| static ssize_t tsync_audio_mode_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_audio_mode); |
| } |
| |
| static ssize_t tsync_audio_state_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_audio_state); |
| } |
| |
| static ssize_t tsync_video_state_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_video_state); |
| } |
| |
| static ssize_t tsync_audio_mode_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_audio_mode); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| |
| static ssize_t tsync_latencytime_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_pcr_latency_value); |
| } |
| |
| static ssize_t tsync_latencytime_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_pcr_latency_value); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| |
| static ssize_t tsync_disable_pcr_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_disable_demux_pcr); |
| } |
| |
| static ssize_t tsync_disable_pcr_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_disable_demux_pcr); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| |
| static ssize_t tsync_vpts_adjust_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_vpts_adjust); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| |
| static ssize_t tsync_vpts_adjust_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_vpts_adjust); |
| } |
| |
| static ssize_t tsync_audio_level_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| u32 audio_level; |
| |
| audio_level = tsync_audio_discontinue & 0xff; |
| return sprintf(buf, "%d\n", audio_level); |
| } |
| |
| static ssize_t tsync_audio_underrun_maxgap_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_audio_underrun_maxgap); |
| } |
| |
| static ssize_t tsync_audio_underrun_maxgap_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_audio_underrun_maxgap); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| |
| static ssize_t tsync_audio_underrun_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_audio_underrun); |
| } |
| |
| static ssize_t tsync_video_discontinue_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| u32 vdiscontinue; |
| |
| vdiscontinue = tsync_video_discontinue & 0xff; |
| return sprintf(buf, "%d\n", vdiscontinue); |
| } |
| |
| |
| static ssize_t tsync_pcr_apts_diff_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| u32 t1, apts_diff; |
| |
| t1 = timestamp_get_pts_latency(1); |
| apts_diff = t1 & 0xffff; |
| return sprintf(buf, "%d\n", apts_diff); |
| } |
| |
| static ssize_t tsync_last_checkin_apts_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "0x%x\n", last_discontinue_checkin_apts); |
| } |
| |
| static ssize_t show_reset_flag(struct class *class, |
| struct class_attribute *attr, char *buf) |
| { |
| ssize_t size = 0; |
| |
| size = sprintf(buf, "%d\n", tsync_pcr_reset_flag); |
| tsync_pcr_reset_flag = 0; |
| return size; |
| } |
| |
| static ssize_t show_apause_flag(struct class *class, |
| struct class_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_pcr_apause_flag); |
| } |
| |
| static ssize_t tsync_pcr_recovery_span_show(struct class *cla, |
| struct class_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_pcr_recovery_span); |
| } |
| |
| static ssize_t tsync_pcr_recovery_span_store(struct class *cla, |
| struct class_attribute *attr, const char *buf, size_t count) |
| { |
| size_t r; |
| |
| /*r = sscanf(buf, "%d", &tsync_pcr_recovery_span);*/ |
| r = kstrtoint(buf, 0, &tsync_pcr_recovery_span); |
| |
| pr_info("%s(%d)\n", __func__, tsync_pcr_recovery_span); |
| |
| if (r != 0) |
| return -EINVAL; |
| |
| return count; |
| } |
| |
| /* add it for dolby av sync 20160126 */ |
| static ssize_t tsync_apts_adj_value_show(struct class *cla, |
| struct class_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_apts_adj_value); |
| } |
| |
| static ssize_t tsync_apts_adj_value_store(struct class *cla, |
| struct class_attribute *attr, const char *buf, size_t count) |
| { |
| size_t r; |
| |
| /*r = sscanf(buf, "%d", &tsync_apts_adj_value);*/ |
| r = kstrtoint(buf, 0, &tsync_apts_adj_value); |
| |
| pr_info("%s(%d)\n", __func__, tsync_apts_adj_value); |
| |
| if (r != 0) |
| return -EINVAL; |
| |
| return count; |
| } |
| |
| static ssize_t tsync_pcr_adj_value_show(struct class *cla, |
| struct class_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_pcr_adj_value); |
| } |
| |
| static ssize_t tsync_pcr_adj_value_store(struct class *cla, |
| struct class_attribute *attr, const char *buf, size_t count) |
| { |
| size_t r; |
| |
| /*r = sscanf(buf, "%d", &tsync_pcr_adj_value);*/ |
| r = kstrtoint(buf, 0, &tsync_pcr_adj_value); |
| |
| pr_info("%s(%d)\n", __func__, tsync_pcr_adj_value); |
| |
| if (r != 0) |
| return -EINVAL; |
| |
| return count; |
| } |
| |
| static ssize_t tsync_pcr_discontinue_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "0x%x\n", tsync_pcr_tsdemuxpcr_discontinue); |
| } |
| |
| static ssize_t tsync_pcr_debug_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| /*r = sscanf(buf, "%d", &tsync_pcr_debug);*/ |
| r = kstrtoint(buf, 0, &tsync_pcr_debug); |
| pr_info("%s(%d)\n", __func__, tsync_pcr_debug); |
| if (r != 0) |
| return -EINVAL; |
| |
| return count; |
| } |
| |
| static ssize_t tsync_pcr_debug_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_pcr_debug); |
| } |
| |
| static ssize_t show_vstream_cache(struct class *class, |
| struct class_attribute *attr, char *buf) |
| { |
| unsigned int cur_vpts = timestamp_vpts_get(); |
| unsigned int last_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); |
| unsigned int diff = 0; |
| |
| if (last_checkin_vpts > cur_vpts) |
| diff = last_checkin_vpts - cur_vpts; |
| else |
| diff = cur_vpts - last_checkin_vpts; |
| return sprintf(buf, "%d\n", diff); |
| } |
| |
| static ssize_t show_astream_cache(struct class *class, |
| struct class_attribute *attr, char *buf) |
| { |
| unsigned int cur_apts = timestamp_apts_get(); |
| unsigned int last_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); |
| unsigned int diff = 0; |
| |
| if (last_checkin_apts > cur_apts) |
| diff = last_checkin_apts - cur_apts; |
| else |
| diff = cur_apts - last_checkin_apts; |
| |
| return sprintf(buf, "%d\n", diff); |
| } |
| |
| static ssize_t tsync_enable_demuxpcr_check_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_enable_demuxpcr_check); |
| } |
| |
| static ssize_t tsync_enable_demuxpcr_check_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_enable_demuxpcr_check); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| |
| static ssize_t tsync_enable_bufferlevel_tune_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_enable_bufferlevel_tune); |
| } |
| |
| static ssize_t tsync_enable_bufferlevel_tune_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_enable_bufferlevel_tune); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| |
| static ssize_t tsync_pcr_inited_flag_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_pcr_inited_flag); |
| } |
| |
| static ssize_t tsync_pcr_ref_latency_show(struct class *cla, |
| struct class_attribute *attr, |
| char *buf) |
| { |
| return sprintf(buf, "%d\n", tsync_pcr_ref_latency); |
| } |
| |
| static ssize_t tsync_pcr_ref_latency_store(struct class *cla, |
| struct class_attribute *attr, |
| const char *buf, size_t count) |
| { |
| size_t r; |
| |
| r = kstrtoint(buf, 0, &tsync_pcr_ref_latency); |
| if (r != 0) |
| return -EINVAL; |
| return count; |
| } |
| /* ----------------------------------------------------------------------- */ |
| /* define of tsync pcr module */ |
| |
| static struct class_attribute tsync_pcr_class_attrs[] = { |
| __ATTR(play_mode, 0664, show_play_mode, NULL), |
| __ATTR(tsync_pcr_discontinue_point, 0644, |
| show_tsync_pcr_dispoint, store_tsync_pcr_dispoint), |
| __ATTR(audio_resample_type, 0644, NULL, |
| store_tsync_pcr_audio_resample_type), |
| __ATTR(tsync_pcr_mode, 0644, |
| tsync_pcr_mode_show, NULL), |
| __ATTR(tsync_audio_mode, 0644, |
| tsync_audio_mode_show, tsync_audio_mode_store), |
| __ATTR(tsync_audio_state, 0644, |
| tsync_audio_state_show, NULL), |
| __ATTR(tsync_video_state, 0644, |
| tsync_video_state_show, NULL), |
| __ATTR(tsync_disable_demux_pcr, 0644, |
| tsync_disable_pcr_show, tsync_disable_pcr_store), |
| |
| __ATTR(tsync_vpts_adjust, 0644, |
| tsync_vpts_adjust_show, tsync_vpts_adjust_store), |
| |
| __ATTR(tsync_audio_level, 0644, |
| tsync_audio_level_show, NULL), |
| __ATTR(tsync_vdiscontinue, 0644, |
| tsync_video_discontinue_show, NULL), |
| __ATTR(tsync_pcr_apts_diff, 0644, |
| tsync_pcr_apts_diff_show, NULL), |
| __ATTR(tsync_last_discontinue_checkin_apts, 0644, |
| tsync_last_checkin_apts_show, NULL), |
| __ATTR(tsync_pcr_reset_flag, 0664, |
| show_reset_flag, NULL), |
| __ATTR(tsync_pcr_apause_flag, 0664, |
| show_apause_flag, NULL), |
| __ATTR(tsync_pcr_recovery_span, 0644, |
| tsync_pcr_recovery_span_show, tsync_pcr_recovery_span_store), |
| __ATTR(tsync_apts_adj_value, 0644, |
| tsync_apts_adj_value_show, tsync_apts_adj_value_store), |
| __ATTR(tsync_pcr_adj_value, 0644, |
| tsync_pcr_adj_value_show, tsync_pcr_adj_value_store), |
| __ATTR(tsync_pcr_debug, 0644, |
| tsync_pcr_debug_show, tsync_pcr_debug_store), |
| __ATTR_RO(tsync_pcr_discontinue), |
| __ATTR_RO(pcr_diff), |
| __ATTR(tsync_vstream_cache, 0644, |
| show_vstream_cache, NULL), |
| __ATTR(tsync_astream_cache, 0644, |
| show_astream_cache, NULL), |
| __ATTR(tsync_enable_demuxpcr_check, 0644, |
| tsync_enable_demuxpcr_check_show, tsync_enable_demuxpcr_check_store), |
| __ATTR(tsync_enable_bufferlevel_tune, 0644, |
| tsync_enable_bufferlevel_tune_show, |
| tsync_enable_bufferlevel_tune_store), |
| __ATTR(tsync_pcr_inited_flag, 0644, |
| tsync_pcr_inited_flag_show, NULL), |
| __ATTR(tsync_pcr_ref_latency, 0644, |
| tsync_pcr_ref_latency_show, tsync_pcr_ref_latency_store), |
| __ATTR(tsync_pcr_latency_value, 0644, |
| tsync_latencytime_show, tsync_latencytime_store), |
| __ATTR(tsync_audio_underrun, 0644, |
| tsync_audio_underrun_show, NULL), |
| __ATTR(tsync_audio_underrun_maxgap, 0644, |
| tsync_audio_underrun_maxgap_show, tsync_audio_underrun_maxgap_store), |
| __ATTR_NULL}; |
| |
| static struct class tsync_pcr_class = { |
| .name = "tsync_pcr", |
| .class_attrs = tsync_pcr_class_attrs, |
| }; |
| |
| int tsync_pcr_init(void) |
| { |
| int r; |
| |
| r = class_register(&tsync_pcr_class); |
| |
| if (r) { |
| pr_info("[tsync_pcr_init]tsync_pcr_class create fail.\n"); |
| return r; |
| } |
| |
| /* init audio pts to -1, others to 0 */ |
| timestamp_apts_set(-1); |
| timestamp_vpts_set(0); |
| timestamp_vpts_set_u64(0); |
| timestamp_pcrscr_set(0); |
| wait_pcr_count = 0; |
| tsync_pcr_debug = 0; |
| tsync_audio_mode = 0; |
| tsync_disable_demux_pcr = 0; |
| tsync_pcr_latency_value = 540000; |
| pr_info("[tsync_pcr_init]init success.\n"); |
| return 0; |
| } |
| EXPORT_SYMBOL(tsync_pcr_init); |
| |
| void tsync_pcr_exit(void) |
| { |
| class_unregister(&tsync_pcr_class); |
| pr_info("[tsync_pcr_exit]exit success.\n"); |
| } |
| EXPORT_SYMBOL(tsync_pcr_exit); |
| |
| |
| module_init(tsync_pcr_init); |
| module_exit(tsync_pcr_exit); |
| |
| MODULE_DESCRIPTION |
| ("AMLOGIC time sync management driver of referrence by pcrscr"); |
| MODULE_LICENSE("GPL"); |
| MODULE_AUTHOR("le yang <le.yang@amlogic.com>"); |
| |