summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduard Hasenleithner <ehasenle@users.sourceforge.net>2001-08-07 16:00:10 +0000
committerEduard Hasenleithner <ehasenle@users.sourceforge.net>2001-08-07 16:00:10 +0000
commitac888501be071c7e3a2210d15fa04afe3220b5e7 (patch)
tree4fa7230a06b0eb76e9a3bf537d8885f3000b5687
parent27178f3a86648323c015dd67e97033b40e9d9e07 (diff)
downloadxine-lib-ac888501be071c7e3a2210d15fa04afe3220b5e7.tar.gz
xine-lib-ac888501be071c7e3a2210d15fa04afe3220b5e7.tar.bz2
Added new System Clock Reference providers architecture.
CVS patchset: 398 CVS date: 2001/08/07 16:00:10
-rw-r--r--src/xine-engine/metronom.c212
-rw-r--r--src/xine-engine/metronom.h32
2 files changed, 204 insertions, 40 deletions
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index d3ef4f40c..803f2abb4 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.16 2001/07/10 22:16:58 guenter Exp $
+ * $Id: metronom.c,v 1.17 2001/08/07 16:00:10 ehasenle Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -30,6 +30,8 @@
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
+#include <string.h>
+#include <errno.h>
#include "monitor.h"
#include "xine_internal.h"
@@ -43,85 +45,151 @@
#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
/*
* ****************************************
- * master clock feature
+ * primary SCR plugin:
+ * unix System Clock Reference
* ****************************************
*/
+typedef struct unixscr_s {
+ scr_plugin_t scr;
+ struct timeval start_time;
+ uint32_t start_pts;
+ uint32_t last_pts;
+ pthread_mutex_t lock;
+ float speed;
+} unixscr_t;
+
+static int unixscr_get_priority (scr_plugin_t *scr) {
+ return 5; /* low priority */
+}
-static void metronom_start_clock (metronom_t *this, uint32_t pts) {
+static void unixscr_set_speed (scr_plugin_t *scr, float ticks_ps) {
+ unixscr_t *self = (unixscr_t*) scr;
+ uint32_t now = scr->get_current(scr);
- pthread_mutex_lock (&this->lock);
+ pthread_mutex_lock (&self->lock);
+
+ gettimeofday(&self->start_time, NULL);
+ self->last_pts = self->start_pts = now;
+ self->speed = ticks_ps; /* ticks per second */
- gettimeofday(&this->start_time, NULL);
- this->last_pts = this->start_pts = pts;
- this->stopped = 0;
+ pthread_mutex_unlock (&self->lock);
+}
- pthread_mutex_unlock (&this->lock);
+static void unixscr_adjust (scr_plugin_t *scr, uint32_t vpts) {
+ unixscr_t *self = (unixscr_t*) scr;
+
+ int delta;
+ int32_t current_time = self->scr.get_current(&self->scr);
+ pthread_mutex_lock (&self->lock);
+
+ /* FIXME: this should be softer than a brute force warp... */
+ delta = vpts;
+ delta -= current_time;
+ self->start_pts += delta;
+ /* TODO: remove */
+ printf("adjusting start_pts to %d\n", self->start_pts);
+
+ pthread_mutex_unlock (&self->lock);
}
+static void unixscr_start (scr_plugin_t *scr, uint32_t start_vpts) {
+ unixscr_t *self = (unixscr_t*) scr;
-static uint32_t metronom_get_current_time (metronom_t *this) {
+ pthread_mutex_lock (&self->lock);
+
+ gettimeofday(&self->start_time, NULL);
+ self->last_pts = self->start_pts = start_vpts;
+ self->speed = REALTIME_PTS;
+
+ pthread_mutex_unlock (&self->lock);
+
+}
+
+static uint32_t unixscr_get_current (scr_plugin_t *scr) {
+ unixscr_t *self = (unixscr_t*) scr;
uint32_t pts;
struct timeval tv;
- pthread_mutex_lock (&this->lock);
+ pthread_mutex_lock (&self->lock);
gettimeofday(&tv, NULL);
- pts = (tv.tv_sec - this->start_time.tv_sec) * 90000;
- pts += (tv.tv_usec - this->start_time.tv_usec) / 10 * 9 / 10;
- pts += this->start_pts;
+ pts = (tv.tv_sec - self->start_time.tv_sec) * self->speed;
+ pts += (tv.tv_usec - self->start_time.tv_usec) * self->speed / 1e6;
+ pts += self->start_pts;
- if (this->stopped || (this->last_pts > pts)) {
+ if (self->last_pts > pts) {
/* printf("metronom: get_current_time(): timer STOPPED!\n"); */
- pts = this->last_pts;
+ pts = self->last_pts;
}
- pthread_mutex_unlock (&this->lock);
+ pthread_mutex_unlock (&self->lock);
return pts;
}
+static scr_plugin_t* unixscr_init () {
+ unixscr_t *self;
-static void metronom_stop_clock(metronom_t *this) {
+ self = malloc(sizeof(*self));
+ memset(self, 0, sizeof(*self));
+
+ self->scr.interface_version = 1;
+ self->scr.get_priority = unixscr_get_priority;
+ self->scr.set_speed = unixscr_set_speed;
+ self->scr.adjust = unixscr_adjust;
+ self->scr.start = unixscr_start;
+ self->scr.get_current = unixscr_get_current;
- uint32_t current_time = this->get_current_time(this);
+ pthread_mutex_init (&self->lock, NULL);
- pthread_mutex_lock (&this->lock);
+ return &self->scr;
+}
+
- this->stopped = 1;
- this->last_pts = current_time;
+/*
+ * ****************************************
+ * master clock feature
+ * ****************************************
+ */
- pthread_mutex_unlock (&this->lock);
+static void metronom_start_clock (metronom_t *this, uint32_t pts) {
+ scr_plugin_t** scr;
+ for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++)
+ if (*scr) (*scr)->start(*scr, pts);
}
-static void metronom_resume_clock(metronom_t *this) {
- this->start_clock(this, this->last_pts);
+static uint32_t metronom_get_current_time (metronom_t *this) {
+ return this->scr_master->get_current(this->scr_master);
}
+static void metronom_stop_clock(metronom_t *this) {
+ scr_plugin_t** scr;
+ for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++)
+ if (*scr) (*scr)->set_speed(*scr, 0.0);
+}
-static void metronom_adjust_clock(metronom_t *this, uint32_t desired_pts)
-{
- int delta;
- uint32_t current_time = this->get_current_time(this);
+static void metronom_resume_clock(metronom_t *this) {
+ scr_plugin_t** scr;
+ for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++)
+ if (*scr) (*scr)->set_speed(*scr, REALTIME_PTS);
+}
- pthread_mutex_lock (&this->lock);
- /* FIXME: this should be softer than a brute force warp... */
- delta = desired_pts;
- delta -= current_time;
- this->start_pts += delta;
- printf("adjusting start_pts to %d\n", this->start_pts);
- pthread_mutex_unlock (&this->lock);
+static void metronom_adjust_clock(metronom_t *this, uint32_t desired_pts)
+{
+ this->scr_master->adjust(this->scr_master, desired_pts);
}
/*
@@ -506,6 +574,68 @@ static int32_t metronom_get_av_offset (metronom_t *this) {
return this->av_offset;
}
+static scr_plugin_t* get_master_scr(metronom_t *this) {
+ int select = -1, maxprio = 0, i;
+
+ /* find the SCR provider with the highest priority */
+ for (i=0; i<MAX_SCR_PROVIDERS; i++) if (this->scr_list[i]) {
+ scr_plugin_t *scr = this->scr_list[i];
+
+ if (maxprio < scr->get_priority(scr)) {
+ select = i;
+ maxprio = scr->get_priority(scr);
+ }
+ }
+ if (select < 0) {
+ printf("panic: No scr provider found!\n");
+ return NULL;
+ }
+ return this->scr_list[select];
+}
+
+static int metronom_register_scr (metronom_t *this, scr_plugin_t *scr) {
+ int i;
+
+ if (scr->interface_version != 1) return -1;
+
+ for (i=0; i<MAX_SCR_PROVIDERS; i++)
+ if (this->scr_list[i] == NULL) break;
+ if (i >= MAX_SCR_PROVIDERS)
+ return -1; /* No free slot available */
+
+ scr->metronom = this;
+ this->scr_list[i] = scr;
+ this->scr_master = get_master_scr(this);
+ return 0;
+}
+
+static void metronom_unregister_scr (metronom_t *this, scr_plugin_t *scr) {
+ int i;
+
+ /* Never unregister scr_list[0]! */
+ for (i=1; i<MAX_SCR_PROVIDERS; i++)
+ if (this->scr_list[i] == scr) break;
+
+ if (i >= MAX_SCR_PROVIDERS)
+ return; /* Not found */
+
+ this->scr_list[i] = NULL;
+ this->scr_master = get_master_scr(this);
+}
+
+static int metronom_sync_loop (metronom_t *this) {
+ scr_plugin_t** scr;
+ uint32_t pts;
+
+ while (1) {
+ pts = this->scr_master->get_current(this->scr_master);
+
+ for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++)
+ if (*scr && *scr != this->scr_master) (*scr)->adjust(*scr, pts);
+
+ sleep(5); /* synchronise every 5 seconds */
+ }
+}
metronom_t * metronom_init (int have_audio) {
@@ -529,6 +659,16 @@ metronom_t * metronom_init (int have_audio) {
this->resume_clock = metronom_resume_clock;
this->get_current_time = metronom_get_current_time;
this->adjust_clock = metronom_adjust_clock;
+ this->register_scr = metronom_register_scr;
+ this->unregister_scr = metronom_unregister_scr;
+
+ this->scr_list = calloc(MAX_SCR_PROVIDERS, sizeof(void*));
+ this->register_scr(this, unixscr_init());
+
+ if (pthread_create(&this->sync_thread, NULL,
+ (void*(*)(void*)) metronom_sync_loop, this))
+ fprintf(stderr, "metronom: cannot create sync thread (%s)\n",
+ strerror(errno));
pthread_mutex_init (&this->lock, NULL);
pthread_cond_init (&this->video_started, NULL);
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h
index 1709a85c1..ef432c9ea 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.8 2001/07/18 21:38:17 f1rmb Exp $
+ * $Id: metronom.h,v 1.9 2001/08/07 16:00:10 ehasenle Exp $
*
* metronom: general pts => virtual calculation/assoc
*
@@ -40,6 +40,7 @@ extern "C" {
#include <pthread.h>
typedef struct metronom_s metronom_t ;
+typedef struct scr_plugin_s scr_plugin_t;
struct metronom_s {
@@ -155,6 +156,12 @@ struct metronom_s {
void (*adjust_clock) (metronom_t *this, uint32_t desired_pts);
/*
+ * (un)register a System Clock Reference provider at the metronom
+ */
+ int (*register_scr) (metronom_t *this, scr_plugin_t *scr);
+ void (*unregister_scr) (metronom_t *this, scr_plugin_t *scr);
+
+ /*
* metronom internal stuff
*/
@@ -180,9 +187,9 @@ struct metronom_s {
int32_t av_offset;
- struct timeval start_time;
- uint32_t start_pts, last_pts;
- int stopped ;
+ scr_plugin_t* scr_master;
+ scr_plugin_t** scr_list;
+ pthread_t sync_thread;
pthread_mutex_t lock;
@@ -200,6 +207,23 @@ struct metronom_s {
metronom_t *metronom_init (int have_audio);
+struct scr_plugin_s
+{
+ int interface_version;
+
+ int (*get_priority) (scr_plugin_t *this);
+
+ void (*set_speed) (scr_plugin_t *this, float pts_ps);
+
+ void (*adjust) (scr_plugin_t *this, uint32_t vpts);
+
+ void (*start) (scr_plugin_t *this, uint32_t start_vpts);
+
+ uint32_t (*get_current) (scr_plugin_t *this);
+
+ metronom_t *metronom;
+};
+
#ifdef __cplusplus
}
#endif