diff options
Diffstat (limited to 'src/xine-engine/metronom.c')
-rw-r--r-- | src/xine-engine/metronom.c | 232 |
1 files changed, 105 insertions, 127 deletions
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 6b3effcc6..e2ce2fda0 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: metronom.c,v 1.32 2001/10/24 22:23:10 guenter Exp $ + * $Id: metronom.c,v 1.33 2001/11/10 13:48:03 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -39,16 +39,16 @@ #include "metronom.h" #include "utils.h" -#define MAX_PTS_TOLERANCE 5000 -#define MAX_VIDEO_DELTA 1600 -#define MAX_AUDIO_DELTA 1600 -#define AUDIO_SAMPLE_NUM 32768 -#define WRAP_START_TIME 100000 -#define WRAP_TRESHOLD 30000 -#define MAX_NUM_WRAP_DIFF 100 -#define MAX_SCR_PROVIDERS 10 -#define REALTIME_PTS 90000.0 -#define PREBUFFER_PTS_OFFSET 30000 +#define MAX_PTS_TOLERANCE 5000 +#define MAX_VIDEO_DELTA 1600 +#define MAX_AUDIO_DELTA 1600 +#define AUDIO_SAMPLE_NUM 32768 +#define WRAP_START_TIME 100000 +#define WRAP_TRESHOLD 30000 +#define SCR_DISCONTINUITY 60000 +#define MAX_NUM_WRAP_DIFF 100 +#define MAX_SCR_PROVIDERS 10 +#define PREBUFFER_PTS_OFFSET 30000 /* #define METRONOM_LOG @@ -228,7 +228,7 @@ static int metronom_set_speed (metronom_t *this, int speed) { /* * virtual pts calculation -*/ + */ static void metronom_video_stream_start (metronom_t *this) { @@ -249,14 +249,18 @@ static void metronom_video_stream_start (metronom_t *this) { this->video_pts_delta = 0; this->last_video_pts = 0; + this->last_video_scr = 0; this->num_video_vpts_guessed = 1; - this->video_wrap_offset = 0; + this->video_wrap_offset = PREBUFFER_PTS_OFFSET; this->wrap_diff_counter = 0; this->video_stream_running = 1; this->video_stream_starting = 1; + this->video_discontinuity = 0; + this->video_discontinuity_count = 0; + if (this->have_audio) { /*while (!this->audio_stream_running) {*/ if (!this->audio_stream_running) { @@ -317,13 +321,17 @@ static void metronom_audio_stream_start (metronom_t *this) { this->num_audio_samples_guessed = 1; this->last_audio_pts = 0; + this->last_audio_scr = 0; - this->audio_wrap_offset = 0; + this->audio_wrap_offset = PREBUFFER_PTS_OFFSET; this->wrap_diff_counter = 0; this->audio_stream_running = 1; this->audio_stream_starting = 1; + this->audio_discontinuity = 0; + this->audio_discontinuity_count = 0; + /*while (!this->video_stream_running) { */ if (!this->video_stream_running) { printf ("metronom: waiting for video to start...\n"); @@ -385,7 +393,8 @@ static void metronom_set_audio_rate (metronom_t *this, uint32_t pts_per_smpls) { } -static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts,uint32_t duration) { +static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts, + uint32_t duration, uint32_t scr) { if (pts) { this->spu_vpts=pts; } else { @@ -402,21 +411,37 @@ static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts,uint32_t return pts + this->video_wrap_offset; } -static void metronom_expect_audio_discontinuity (metronom_t *this) { - - printf ("metronom: expecting audio discontinuity\n"); - - this->audio_discontinuity = 10; -} - static void metronom_expect_video_discontinuity (metronom_t *this) { - printf ("metronom: expecting video discontinuity\n"); + pthread_mutex_lock (&this->lock); + printf ("metronom: video discontinuity\n"); + this->video_discontinuity = 10; + + this->video_discontinuity_count++; + pthread_cond_signal (&this->video_discontinuity_reached); + + while ( this->audio_discontinuity_count < + this->video_discontinuity_count ) { + pthread_cond_wait (&this->audio_discontinuity_reached, &this->lock); + } + + if ( this->video_vpts < this->audio_vpts ) { + this->video_vpts = this->audio_vpts; + printf("metronom: video vpts adjusted to %d\n", this->video_vpts); + } + + this->num_video_vpts_guessed = 1; + this->last_video_pts = this->video_vpts - this->video_wrap_offset; + + printf ("metronom: video discontinuity => last_video_pts=%d, wrap_offset=%d, video_vpts=%d\n", + this->last_video_pts, this->video_wrap_offset, this->video_vpts); + + pthread_mutex_unlock (&this->lock); } -static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { +static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts, uint32_t scr) { uint32_t vpts; @@ -425,44 +450,27 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { if (pts) { /* - * first video pts ? + * first video pts ? */ - if (this->video_stream_starting) { + if (this->video_stream_starting) this->video_stream_starting = 0; - this->video_wrap_offset = this->video_vpts + this->pts_per_frame - pts; - assert (this->video_pts_delta == 0); - - if (this->audio_wrap_offset) { - if (this->audio_wrap_offset>this->video_wrap_offset) - this->video_wrap_offset = this->audio_wrap_offset; - else - this->audio_wrap_offset = this->video_wrap_offset; - } - - printf ("metronom: first video pts => offset = %d\n", this->video_wrap_offset); - - } - /* - * did a wrap-around occur? + * discontinuity ? */ - if ( ( (pts + WRAP_TRESHOLD) <this->last_video_pts) - && (this->video_discontinuity || (pts<WRAP_START_TIME)) ) { - + if ( this->video_discontinuity ) { + this->video_discontinuity = 0; this->video_wrap_offset += this->last_video_pts - pts - + this->num_video_vpts_guessed *(this->pts_per_frame + this->video_pts_delta); + + this->num_video_vpts_guessed + * (this->pts_per_frame + this->video_pts_delta); - printf ("metronom: video pts wraparound detected, wrap_offset = %d\n", - this->video_wrap_offset); - } + printf ("metronom: video pts discontinuity, pts is %d, last_pts is %d, wrap_offset = %d\n", + pts, this->last_video_pts, this->video_wrap_offset); - /* don't expect discontinuities forever */ - if (this->video_discontinuity) - this->video_discontinuity--; + } /* * audio and video wrap are not allowed to differ @@ -492,22 +500,6 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { vpts = pts + this->video_wrap_offset; /* - * jump into the future? - */ - if (this->video_discontinuity - && (vpts > (this->video_vpts + 10000))) { - - printf ("metronom: video jump into the future\n"); - - this->video_discontinuity = 0; - - this->video_wrap_offset += this->last_video_pts - pts - + this->num_video_vpts_guessed *(this->pts_per_frame + this->video_pts_delta); - - vpts = pts + this->video_wrap_offset; - } - - /* * calc delta to compensate wrong framerates */ @@ -540,24 +532,38 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { return vpts + this->av_offset; } -static void metronom_got_audio_still (metronom_t *this) { +static void metronom_expect_audio_discontinuity (metronom_t *this) { pthread_mutex_lock (&this->lock); - - this->audio_vpts += this->pts_per_frame + this->video_pts_delta; - this->audio_wrap_offset = this->video_wrap_offset; - this->last_audio_pts = this->audio_vpts - this->audio_wrap_offset; - this->audio_stream_starting = 0; - -#ifdef METRONOM_LOG - printf ("metronom: got audio still, vpts = %d, wrap = %d\n", - this->audio_vpts, this->audio_wrap_offset); -#endif + + printf ("metronom: audio discontinuity\n"); + + this->audio_discontinuity = 10; + this->audio_discontinuity_count++; + pthread_cond_signal (&this->audio_discontinuity_reached); + + while ( this->audio_discontinuity_count > + this->video_discontinuity_count ) { + pthread_cond_wait (&this->video_discontinuity_reached, &this->lock); + } + + if ( this->audio_vpts < this->video_vpts ) { + this->audio_vpts = this->video_vpts; + printf("metronom: audio vpts adjusted to %d\n", this->audio_vpts); + } + + this->num_audio_samples_guessed = 1; + this->last_audio_pts = this->audio_vpts - this->audio_wrap_offset; + + printf ("metronom: audio discontinuity => last_audio_pts=%d, wrap_offset=%d, audio_vpts=%d\n", + this->last_audio_pts, this->audio_wrap_offset, this->audio_vpts); pthread_mutex_unlock (&this->lock); } -static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint32_t nsamples) { + +static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, + uint32_t nsamples, uint32_t scr) { uint32_t vpts; @@ -566,53 +572,40 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint pthread_mutex_lock (&this->lock); + + this->last_audio_scr = scr; + if (pts) { /* * first audio pts ? */ - if (this->audio_stream_starting) { + if (this->audio_stream_starting) this->audio_stream_starting = 0; - this->audio_wrap_offset = this->audio_vpts + (nsamples * this->pts_per_smpls) / AUDIO_SAMPLE_NUM - pts; - assert (this->audio_pts_delta == 0); - - if (this->video_wrap_offset) { - if (this->audio_wrap_offset>this->video_wrap_offset) - this->video_wrap_offset = this->audio_wrap_offset; - else - this->audio_wrap_offset = this->video_wrap_offset; - } - - printf ("metronom: first audio pts => offset = %d\n", this->audio_wrap_offset); - } - /* - * did a wrap-around occur? + * discontinuity ? */ - if ( ( (pts + WRAP_TRESHOLD) < this->last_audio_pts ) - && (this->audio_discontinuity || (pts<WRAP_START_TIME)) ) { + + if ( this->audio_discontinuity ) { this->audio_discontinuity = 0; this->audio_wrap_offset += this->last_audio_pts - pts - + this->num_audio_samples_guessed *(this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM ; + + this->num_audio_samples_guessed + * (this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM ; - printf ("metronom: audio pts wraparound detected, wrap_offset = %d\n", - this->audio_wrap_offset); - } + printf ("metronom: audio pts discontinuity, pts is %d, last_pts is %d, wrap_offset = %d\n", + pts, this->last_audio_pts, this->audio_wrap_offset); - /* don't expect discontinuities forever */ - if (this->audio_discontinuity) - this->audio_discontinuity--; + } /* * audio and video wrap are not allowed to differ * for too long */ - if ( !this->video_stream_starting - && this->video_wrap_offset != this->audio_wrap_offset) { + if ( this->video_wrap_offset != this->audio_wrap_offset ) { this->wrap_diff_counter++; if (this->wrap_diff_counter > MAX_NUM_WRAP_DIFF) { @@ -634,22 +627,6 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint vpts = pts + this->audio_wrap_offset; /* - * jump into the future? - */ - if (this->audio_discontinuity - && (vpts > (this->audio_vpts + 10000))) { - - printf ("metronom: video jump into the future\n"); - - this->audio_discontinuity = 0; - - this->audio_wrap_offset += this->last_audio_pts - pts - + this->num_audio_samples_guessed *(this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM ; - - vpts = pts + this->audio_wrap_offset; - } - - /* * calc delta to compensate wrong samplerates */ @@ -710,7 +687,7 @@ static scr_plugin_t* get_master_scr(metronom_t *this) { } } if (select < 0) { - printf("panic: No scr provider found!\n"); + printf("metronom: panic - no scr provider found!\n"); return NULL; } return this->scr_list[select]; @@ -776,10 +753,10 @@ metronom_t * metronom_init (int have_audio) { this->got_video_frame = metronom_got_video_frame; this->got_audio_samples = metronom_got_audio_samples; this->got_spu_packet = metronom_got_spu_packet; + this->expect_audio_discontinuity = metronom_expect_audio_discontinuity; + this->expect_video_discontinuity = metronom_expect_video_discontinuity; this->set_av_offset = metronom_set_av_offset; this->get_av_offset = metronom_get_av_offset; - this->expect_video_discontinuity = metronom_expect_video_discontinuity; - this->expect_audio_discontinuity = metronom_expect_audio_discontinuity; this->start_clock = metronom_start_clock; this->stop_clock = metronom_stop_clock; this->resume_clock = metronom_resume_clock; @@ -788,21 +765,22 @@ metronom_t * metronom_init (int have_audio) { this->register_scr = metronom_register_scr; this->unregister_scr = metronom_unregister_scr; this->set_speed = metronom_set_speed; - this->got_audio_still = metronom_got_audio_still; this->scr_list = calloc(MAX_SCR_PROVIDERS, sizeof(void*)); this->register_scr(this, unixscr_init()); if ((err = pthread_create(&this->sync_thread, NULL, (void*(*)(void*)) metronom_sync_loop, this)) != 0) - fprintf(stderr, "metronom: cannot create sync thread (%s)\n", - strerror(err)); + printf("metronom: cannot create sync thread (%s)\n", + strerror(err)); pthread_mutex_init (&this->lock, NULL); pthread_cond_init (&this->video_started, NULL); pthread_cond_init (&this->audio_started, NULL); pthread_cond_init (&this->video_ended, NULL); pthread_cond_init (&this->audio_ended, NULL); + pthread_cond_init (&this->video_discontinuity_reached, NULL); + pthread_cond_init (&this->audio_discontinuity_reached, NULL); this->av_offset = 0; this->have_audio = have_audio; |