summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/xine-engine/metronom.c103
-rw-r--r--src/xine-engine/metronom.h19
2 files changed, 115 insertions, 7 deletions
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index 5137095ff..911e4ca56 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.126 2003/11/15 20:43:11 mroi Exp $
+ * $Id: metronom.c,v 1.127 2003/11/16 12:15:21 mroi Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -265,6 +265,24 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) {
int64_t vpts;
pthread_mutex_lock (&this->lock);
+
+ if (this->master) {
+ metronom_t *master = this->master;
+
+ pthread_mutex_lock(&this->master->lock);
+ pthread_mutex_unlock(&this->lock);
+
+ this->vpts_offset = this->master->vpts_offset;
+ this->spu_offset = this->master->spu_offset;
+
+ /* no recursion, please */
+ this->master = NULL;
+ vpts = master->got_spu_packet(this, pts);
+ this->master = master;
+
+ pthread_mutex_unlock(&this->master->lock);
+ return vpts;
+ }
vpts = pts + this->vpts_offset + this->spu_offset;
@@ -283,6 +301,12 @@ static void metronom_handle_video_discontinuity (metronom_t *this, int type,
int64_t cur_time;
pthread_mutex_lock (&this->lock);
+
+ if (this->master) {
+ /* slaves are currently not allowed to set discontinuities */
+ pthread_mutex_unlock(&this->lock);
+ return;
+ }
this->video_discontinuity_count++;
pthread_cond_signal (&this->video_discontinuity_reached);
@@ -385,6 +409,24 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
pthread_mutex_lock (&this->lock);
+ if (this->master) {
+ metronom_t *master = this->master;
+
+ pthread_mutex_lock(&this->master->lock);
+ pthread_mutex_unlock(&this->lock);
+
+ this->vpts_offset = this->master->vpts_offset;
+ this->av_offset = this->master->av_offset;
+
+ /* no recursion, please */
+ this->master = NULL;
+ master->got_video_frame(this, img);
+ this->master = master;
+
+ pthread_mutex_unlock(&this->master->lock);
+ return;
+ }
+
lprintf("got_video_frame pts = %lld, duration = %d\n", pts, img->duration);
this->img_cpt++;
@@ -468,6 +510,12 @@ static void metronom_handle_audio_discontinuity (metronom_t *this, int type,
pthread_mutex_lock (&this->lock);
+ if (this->master) {
+ /* slaves are currently not allowed to set discontinuities */
+ pthread_mutex_unlock(&this->lock);
+ return;
+ }
+
this->audio_discontinuity_count++;
pthread_cond_signal (&this->audio_discontinuity_reached);
@@ -500,6 +548,23 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts,
lprintf("AUDIO pts from last= %lld\n", pts-this->last_audio_pts);
pthread_mutex_lock (&this->lock);
+
+ if (this->master) {
+ metronom_t *master = this->master;
+
+ pthread_mutex_lock(&this->master->lock);
+ pthread_mutex_unlock(&this->lock);
+
+ this->vpts_offset = this->master->vpts_offset;
+
+ /* no recursion, please */
+ this->master = NULL;
+ vpts = master->got_audio_samples(this, pts, nsamples);
+ this->master = master;
+
+ pthread_mutex_unlock(&this->master->lock);
+ return vpts;
+ }
if (pts && pts != this->last_audio_pts) {
vpts = pts + this->vpts_offset;
@@ -555,6 +620,13 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts,
static void metronom_set_option (metronom_t *this, int option, int64_t value) {
pthread_mutex_lock (&this->lock);
+
+ if (this->master) {
+ /* pass the option on to the master */
+ this->master->set_option(this->master, option, value);
+ pthread_mutex_unlock(&this->lock);
+ return;
+ }
switch (option) {
case METRONOM_AV_OFFSET:
@@ -603,6 +675,10 @@ static void metronom_clock_set_option (metronom_clock_t *this,
}
static int64_t metronom_get_option (metronom_t *this, int option) {
+
+ if (this->master)
+ return this->master->get_option(this->master, option);
+
switch (option) {
case METRONOM_AV_OFFSET:
return this->av_offset;
@@ -628,6 +704,26 @@ static int64_t metronom_clock_get_option (metronom_clock_t *this, int option) {
return 0;
}
+static void metronom_set_master(metronom_t *this, metronom_t *master) {
+ metronom_t *old_master = this->master;
+
+ pthread_mutex_lock(&this->lock);
+ /* someone might currently be copying values from the old master,
+ * so we need his lock too */
+ if (old_master) pthread_mutex_lock(&old_master->lock);
+
+ this->master = master;
+ if (!old_master) {
+ /* when being attached to the first master, do not drift into
+ * his vpts values but adopt at once */
+ this->force_video_jump = 1;
+ this->force_audio_jump = 1;
+ }
+
+ if (old_master) pthread_mutex_unlock(&old_master->lock);
+ pthread_mutex_unlock(&this->lock);
+}
+
static scr_plugin_t* get_master_scr(metronom_clock_t *this) {
int select = -1, maxprio = 0, i;
@@ -747,7 +843,6 @@ metronom_t * _x_metronom_init (int have_audio, xine_t *xine) {
metronom_t *this = xine_xmalloc (sizeof (metronom_t));
- this->xine = xine;
this->set_audio_rate = metronom_set_audio_rate;
this->got_video_frame = metronom_got_video_frame;
this->got_audio_samples = metronom_got_audio_samples;
@@ -756,8 +851,12 @@ metronom_t * _x_metronom_init (int have_audio, xine_t *xine) {
this->handle_video_discontinuity = metronom_handle_video_discontinuity;
this->set_option = metronom_set_option;
this->get_option = metronom_get_option;
+ this->set_master = metronom_set_master;
this->exit = metronom_exit;
+ this->xine = xine;
+ this->master = NULL;
+
pthread_mutex_init (&this->lock, NULL);
this->prebuffer = PREBUFFER_PTS_OFFSET;
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h
index 04304de20..1cf72eeb6 100644
--- a/src/xine-engine/metronom.h
+++ b/src/xine-engine/metronom.h
@@ -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.h,v 1.53 2003/11/15 20:43:11 mroi Exp $
+ * $Id: metronom.h,v 1.54 2003/11/16 12:15:21 mroi Exp $
*
* metronom: general pts => virtual calculation/assoc
*
@@ -166,16 +166,24 @@ struct metronom_s {
void (*set_option) (metronom_t *self, int option, int64_t value);
int64_t (*get_option) (metronom_t *self, int option);
- void (*exit) (metronom_t *self);
-
/*
- * pointer to current xine object.
+ * set a master metronom
+ * this is currently useful to sync independently generated streams
+ * (e.g. by post plugins) to the discontinuity domain of another
+ * metronom
*/
- xine_t *xine;
+ void (*set_master) (metronom_t *self, metronom_t *master);
+ void (*exit) (metronom_t *self);
+
+/*#ifdef XINE_ENGINE_INTERNAL*/
+#if 1
/*
* metronom internal stuff
*/
+ xine_t *xine;
+
+ metronom_t *master;
int64_t pts_per_smpls;
@@ -213,6 +221,7 @@ struct metronom_s {
int64_t last_video_pts;
int64_t last_audio_pts;
+#endif
};
/*