summaryrefslogtreecommitdiff
path: root/src/xine-engine/metronom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/metronom.c')
-rw-r--r--src/xine-engine/metronom.c232
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;