summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2001-08-25 07:12:16 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2001-08-25 07:12:16 +0000
commitf3265672dc2071d68740903a6b562e9d988f6343 (patch)
tree6977dfc982230238363ced4cc637299e836082e6 /src
parent1129dc86b5e2e39167f20a9db3cc13caedbb5df8 (diff)
downloadxine-lib-f3265672dc2071d68740903a6b562e9d988f6343.tar.gz
xine-lib-f3265672dc2071d68740903a6b562e9d988f6343.tar.bz2
fixed seeking (back to the old method), implementing true pause function, introducing trick playback (slow motion and fast forward)
CVS patchset: 482 CVS date: 2001/08/25 07:12:16
Diffstat (limited to 'src')
-rw-r--r--src/xine-engine/audio_decoder.c10
-rw-r--r--src/xine-engine/metronom.c133
-rw-r--r--src/xine-engine/metronom.h28
-rw-r--r--src/xine-engine/xine.c189
-rw-r--r--src/xine-engine/xine_internal.h31
5 files changed, 217 insertions, 174 deletions
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index 07d64114b..ca701d0ad 100644
--- a/src/xine-engine/audio_decoder.c
+++ b/src/xine-engine/audio_decoder.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: audio_decoder.c,v 1.28 2001/08/15 11:35:47 f1rmb Exp $
+ * $Id: audio_decoder.c,v 1.29 2001/08/25 07:12:16 guenter Exp $
*
*
* functions that implement audio decoding
@@ -116,6 +116,14 @@ void *audio_decoder_loop (void *this_gen) {
break;
default:
+
+ while (this->audio_mute==2) {
+ usleep (50000);
+ }
+
+ if (this->audio_mute)
+ break;
+
if ( (buf->type & 0xFF000000) == BUF_AUDIO_BASE ) {
/* printf ("audio_decoder: got an audio buffer, type %08x\n", buf->type); */
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index 40e1c59aa..694646bf3 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.18 2001/08/14 08:21:41 ehasenle Exp $
+ * $Id: metronom.c,v 1.19 2001/08/25 07:12:16 guenter Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -56,101 +56,93 @@
*/
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;
+ scr_plugin_t scr;
+
+ struct timeval cur_time;
+ uint32_t cur_pts;
+ double speed_factor;
+
+ pthread_mutex_t lock;
+
} unixscr_t;
static int unixscr_get_priority (scr_plugin_t *scr) {
return 5; /* low priority */
}
-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);
+static int unixscr_set_speed (scr_plugin_t *scr, int speed) {
+ unixscr_t *this = (unixscr_t*) scr;
- pthread_mutex_lock (&self->lock);
-
- gettimeofday(&self->start_time, NULL);
- self->last_pts = self->start_pts = now;
- self->speed = ticks_ps; /* ticks per second */
+ pthread_mutex_lock (&this->lock);
+
+ this->speed_factor = (double) speed * 90000.0 / 4.0;
+
+ pthread_mutex_unlock (&this->lock);
- pthread_mutex_unlock (&self->lock);
+ return speed;
}
static void unixscr_adjust (scr_plugin_t *scr, uint32_t vpts) {
- unixscr_t *self = (unixscr_t*) scr;
+ unixscr_t *this = (unixscr_t*) scr;
- int delta;
- int32_t current_time = self->scr.get_current(&self->scr);
-
- pthread_mutex_lock (&self->lock);
+ pthread_mutex_lock (&this->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);
+ this->cur_pts = vpts;
+ gettimeofday(&this->cur_time, NULL);
- pthread_mutex_unlock (&self->lock);
+ pthread_mutex_unlock (&this->lock);
}
static void unixscr_start (scr_plugin_t *scr, uint32_t start_vpts) {
- unixscr_t *self = (unixscr_t*) scr;
-
- pthread_mutex_lock (&self->lock);
+ unixscr_t *this = (unixscr_t*) scr;
- gettimeofday(&self->start_time, NULL);
- self->last_pts = self->start_pts = start_vpts;
- self->speed = REALTIME_PTS;
+ pthread_mutex_lock (&this->lock);
- pthread_mutex_unlock (&self->lock);
+ gettimeofday(&this->cur_time, NULL);
+ this->cur_pts = start_vpts;
+ pthread_mutex_unlock (&this->lock);
}
static uint32_t unixscr_get_current (scr_plugin_t *scr) {
- unixscr_t *self = (unixscr_t*) scr;
+ unixscr_t *this = (unixscr_t*) scr;
+ struct timeval tv;
uint32_t pts;
- struct timeval tv;
-
- pthread_mutex_lock (&self->lock);
+
+ pthread_mutex_lock (&this->lock);
gettimeofday(&tv, NULL);
- 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 (self->last_pts > pts) {
- /* printf("metronom: get_current_time(): timer STOPPED!\n"); */
- pts = self->last_pts;
- }
- pthread_mutex_unlock (&self->lock);
+ this->cur_pts += (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor;
+ this->cur_pts += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6;
+
+ pts = this->cur_pts;
+ memcpy (&this->cur_time, &tv, sizeof (tv));
+
+ pthread_mutex_unlock (&this->lock);
return pts;
}
static scr_plugin_t* unixscr_init () {
- unixscr_t *self;
+ unixscr_t *this;
- self = malloc(sizeof(*self));
- memset(self, 0, sizeof(*self));
+ this = malloc(sizeof(*this));
+ memset(this, 0, sizeof(*this));
- 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;
+ this->scr.interface_version = 2;
+ this->scr.get_priority = unixscr_get_priority;
+ this->scr.set_speed = unixscr_set_speed;
+ this->scr.adjust = unixscr_adjust;
+ this->scr.start = unixscr_start;
+ this->scr.get_current = unixscr_get_current;
- pthread_mutex_init (&self->lock, NULL);
+ unixscr_set_speed (&this->scr, SPEED_NORMAL);
+
+ pthread_mutex_init (&this->lock, NULL);
- return &self->scr;
+ return &this->scr;
}
@@ -176,22 +168,34 @@ static uint32_t metronom_get_current_time (metronom_t *this) {
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);
+ if (*scr) (*scr)->set_speed(*scr, SPEED_PAUSE);
}
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);
+ if (*scr) (*scr)->set_speed(*scr, SPEED_NORMAL);
}
-static void metronom_adjust_clock(metronom_t *this, uint32_t desired_pts)
-{
+static void metronom_adjust_clock(metronom_t *this, uint32_t desired_pts) {
this->scr_master->adjust(this->scr_master, desired_pts);
}
+static int metronom_set_speed (metronom_t *this, int speed) {
+
+ scr_plugin_t **scr;
+ int true_speed;
+
+ true_speed = this->scr_master->set_speed (this->scr_master, speed);
+
+ for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++)
+ if (*scr) (*scr)->set_speed(*scr, true_speed);
+
+ return true_speed;
+}
+
/*
* virtual pts calculation
*/
@@ -603,7 +607,7 @@ static scr_plugin_t* get_master_scr(metronom_t *this) {
static int metronom_register_scr (metronom_t *this, scr_plugin_t *scr) {
int i;
- if (scr->interface_version != 1) return -1;
+ if (scr->interface_version != 2) return -1;
for (i=0; i<MAX_SCR_PROVIDERS; i++)
if (this->scr_list[i] == NULL) break;
@@ -668,6 +672,7 @@ metronom_t * metronom_init (int have_audio) {
this->adjust_clock = metronom_adjust_clock;
this->register_scr = metronom_register_scr;
this->unregister_scr = metronom_unregister_scr;
+ this->set_speed = metronom_set_speed;
this->scr_list = calloc(MAX_SCR_PROVIDERS, sizeof(void*));
this->register_scr(this, unixscr_init());
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h
index ef432c9ea..368bed25e 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.9 2001/08/07 16:00:10 ehasenle Exp $
+ * $Id: metronom.h,v 1.10 2001/08/25 07:12:16 guenter Exp $
*
* metronom: general pts => virtual calculation/assoc
*
@@ -121,13 +121,12 @@ struct metronom_s {
int32_t (*get_av_offset) (metronom_t *this);
/*
- * ****************************************
- * master clock functions
- * ****************************************
+ * system clock reference (SCR) functions
*/
/*
* start metronom clock (no clock reset)
+ * at given pts
*/
void (*start_clock) (metronom_t *this, uint32_t pts);
@@ -155,6 +154,14 @@ struct metronom_s {
*/
void (*adjust_clock) (metronom_t *this, uint32_t desired_pts);
+
+ /*
+ * set clock speed
+ * for constants see xine_internal.h
+ */
+
+ int (*set_speed) (metronom_t *this, int speed);
+
/*
* (un)register a System Clock Reference provider at the metronom
*/
@@ -207,13 +214,24 @@ struct metronom_s {
metronom_t *metronom_init (int have_audio);
+/*
+ * SCR plugins
+ */
+
struct scr_plugin_s
{
int interface_version;
int (*get_priority) (scr_plugin_t *this);
- void (*set_speed) (scr_plugin_t *this, float pts_ps);
+ /*
+ * set/get clock speed
+ *
+ * for speed constants see xine_internal.h
+ * returns actual speed
+ */
+
+ int (*set_speed) (scr_plugin_t *this, int speed);
void (*adjust) (scr_plugin_t *this, uint32_t vpts);
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 1e7b0a275..3760af606 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.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: xine.c,v 1.47 2001/08/24 10:02:05 guenter Exp $
+ * $Id: xine.c,v 1.48 2001/08/25 07:12:16 guenter Exp $
*
* top-level xine functions
*
@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <string.h>
#include <pthread.h>
#if defined (__linux__)
#include <endian.h>
@@ -74,46 +75,27 @@ void xine_stop (xine_t *this) {
pthread_mutex_unlock (&this->xine_lock);
return;
}
-
- if(this->status == XINE_PAUSE) {
-
- printf ("xine_stop: stopping demuxer\n");
-
- if(this->cur_demuxer_plugin) {
- this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin);
- }
-
- if(this->cur_input_plugin) {
- this->cur_input_plugin->stop(this->cur_input_plugin);
- }
- goto pause_done;
+ this->status = XINE_STOP;
+ printf ("xine_stop: stopping demuxer\n");
+
+ if(this->cur_demuxer_plugin) {
+ this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin);
+ this->cur_demuxer_plugin = NULL;
}
- else {
-
- printf ("xine_stop: closing demuxer\n");
-
- if(this->cur_demuxer_plugin) {
- this->cur_demuxer_plugin->close (this->cur_demuxer_plugin);
- this->cur_demuxer_plugin = NULL;
- }
-
- printf ("xine_stop: closing input\n");
-
- if(this->cur_input_plugin) {
- this->cur_input_plugin->close(this->cur_input_plugin);
- /*
- * If we set it to NULL, xine_eject() will not work after
- * a xine_stop() call.
- *
- * this->cur_input_plugin = NULL;
- */
- }
+
+ printf ("xine_stop: closing input\n");
+
+ if(this->cur_input_plugin) {
+ this->cur_input_plugin->close(this->cur_input_plugin);
+ /*
+ * If we set it to NULL, xine_eject() will not work after
+ * a xine_stop() call.
+ *
+ * this->cur_input_plugin = NULL;
+ */
}
-
- this->status = XINE_STOP;
- pause_done:
printf ("xine_stop: done\n");
pthread_mutex_unlock (&this->xine_lock);
@@ -270,52 +252,25 @@ void xine_play (xine_t *this, char *MRL, int spos) {
pthread_mutex_lock (&this->xine_lock);
- switch (this->status) {
- case XINE_PAUSE:
+ if (this->status != XINE_STOP) {
+
+ this->metronom->set_speed (this->metronom, SPEED_NORMAL);
+ this->audio_mute = 0;
+
pthread_mutex_unlock (&this->xine_lock);
- xine_pause(this);
return;
- break;
+ }
- case XINE_STOP:
- xine_play_internal (this, MRL, spos, (off_t) 0);
- break;
+ xine_play_internal (this, MRL, spos, (off_t) 0);
- default:
- printf ("xine_play: error, xine is not paused/stopped\n");
- }
pthread_mutex_unlock (&this->xine_lock);
}
-void xine_seek (xine_t *this, char *MRL, int spos) {
-
- pthread_mutex_lock (&this->xine_lock);
+void xine_seek (xine_t *this, char *mrl, int pos) {
- printf ("xine_seek\n");
-
- switch (this->status) {
- case XINE_PLAY:
- case XINE_STOP:
- case XINE_PAUSE:
- this->status = XINE_SEEK;
-
- if(this->cur_demuxer_plugin) {
- this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin);
- }
-
- if(this->cur_input_plugin) {
- this->cur_input_plugin->stop(this->cur_input_plugin);
- }
-
- this->status = XINE_STOP;
- xine_play_internal (this, MRL, spos, (off_t)0);
- break;
-
- default:
- printf ("xine_play: error, unhandled status %d\n", this->status);
- }
+ xine_stop (this);
+ xine_play (this, mrl, pos);
- pthread_mutex_unlock (&this->xine_lock);
}
int xine_eject (xine_t *this) {
@@ -385,30 +340,25 @@ void xine_pause (xine_t *this) {
printf ("xine_pause\n");
- if (this->status == XINE_PAUSE) {
+ if (this->status != XINE_PLAY) {
+ printf ("xine: error, pause called when not in playback mode\n");
- xprintf (VERBOSE, "xine play %s from %Ld\n",
- this->cur_mrl, this->cur_input_pos);
+ return;
+ }
- this->status = XINE_STOP;
- xine_play_internal (this, this->cur_mrl, 0, this->cur_input_pos);
- /* this->mnPausePos = 0; */
- } else if (this->status == XINE_PLAY) {
+ if (this->paused) {
- pthread_mutex_unlock (&this->xine_lock);
+ this->metronom->set_speed (this->metronom, SPEED_NORMAL);
+ this->audio_mute = 0;
+ this->paused = 0;
- printf ("pausing at %Ld\n", this->cur_input_pos);
+ } else {
- /*
- * xine_stop() will not change the status is
- * previous status is XINE_PAUSE.
- */
- this->status = XINE_PAUSE;
+ this->metronom->set_speed (this->metronom, SPEED_PAUSE);
+ this->paused = 1;
+ this->audio_mute = 2;
- xine_stop (this);
-
- pthread_mutex_lock (&this->xine_lock);
}
pthread_mutex_unlock (&this->xine_lock);
@@ -441,6 +391,11 @@ static void event_handler(xine_t *xine, event_t *event, void *data) {
}
}
break;
+ case XINE_SPU_EVENT:
+ if (xine->cur_spu_decoder_plugin)
+ xine->cur_spu_decoder_plugin->event(xine->cur_spu_decoder_plugin,
+ (spu_event_t*) event);
+ break;
}
}
@@ -468,11 +423,6 @@ xine_t *xine_init (vo_driver_t *vo,
profiler_set_label (2, "video output ");
/*
- * init event listeners
- */
- this->num_event_listeners = 0; /* Initially there are none */
-
- /*
* init lock
*/
@@ -507,14 +457,17 @@ xine_t *xine_init (vo_driver_t *vo,
this->video_out = vo_new_instance (vo, this->metronom);
video_decoder_init (this);
- if(ao) {
+ if(ao)
this->audio_out = ao_new_instance (ao, this->metronom, config);
-// this->audio_out = ao;
-// this->audio_out->connect (this->audio_out, this->metronom);
- }
+
audio_decoder_init (this);
printf("xine_init returning\n");
+ /*
+ * init event listeners
+ */
+ this->num_event_listeners = 0; /* Initially there are none */
+
if((xine_register_event_listener(this, event_handler)) < 1) {
fprintf(stderr, "xine_register_event_listener() failed.\n");
}
@@ -622,3 +575,39 @@ int xine_check_version(int major, int minor, int sub) {
return 0;
}
+
+/*
+ * manually adjust a/v sync
+ */
+
+void xine_set_av_offset (xine_t *this, int offset_pts) {
+ this->metronom->set_av_offset (this->metronom, offset_pts);
+}
+
+int xine_get_av_offset (xine_t *this) {
+ return this->metronom->get_av_offset (this->metronom);
+}
+
+/*
+ * trick play
+ */
+
+void xine_set_speed (xine_t *this, int speed) {
+
+ pthread_mutex_lock (&this->xine_lock);
+
+ printf ("xine_set_speed %d\n", speed);
+
+ this->metronom->set_speed (this->metronom, speed);
+
+ this->audio_mute = speed != SPEED_NORMAL;
+ this->paused = speed == SPEED_PAUSE;
+ this->speed = speed;
+
+ pthread_mutex_unlock (&this->xine_lock);
+}
+
+
+int xine_get_speed (xine_t *this) {
+ return this->speed;
+}
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 39ede9b61..d8727e172 100644
--- a/src/xine-engine/xine_internal.h
+++ b/src/xine-engine/xine_internal.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: xine_internal.h,v 1.40 2001/08/23 21:40:05 guenter Exp $
+ * $Id: xine_internal.h,v 1.41 2001/08/25 07:12:16 guenter Exp $
*
*/
@@ -119,9 +119,7 @@ typedef void (*gui_stream_end_cb_t)(int nStatus);
#define XINE_STOP 0
#define XINE_PLAY 1
-#define XINE_PAUSE 2
-#define XINE_SEEK 3
-#define XINE_QUIT 4
+#define XINE_QUIT 2
typedef struct xine_s xine_t;
@@ -145,6 +143,7 @@ struct xine_s {
int demux_strategy;
int status;
+ int speed;
off_t cur_input_pos;
char cur_mrl[1024];
@@ -166,6 +165,7 @@ struct xine_s {
video_decoder_t *video_decoder_plugins[DECODER_PLUGIN_MAX];
video_decoder_t *cur_video_decoder_plugin;
int video_finished;
+ int paused;
ao_instance_t *audio_out;
fifo_buffer_t *audio_fifo;
@@ -176,6 +176,7 @@ struct xine_s {
uint32_t audio_track_map[50];
int audio_track_map_entries;
int audio_finished;
+ int audio_mute;
gui_stream_end_cb_t stream_end_cb;
gui_get_next_mrl_cb_t get_next_mrl_cb;
@@ -233,6 +234,28 @@ void xine_seek (xine_t *this, char *MRL, int pos);
*/
void xine_pause (xine_t *this);
+/*
+ * set/get playback speed
+ *
+ * constants see below
+ */
+
+void xine_set_speed (xine_t *this, int speed);
+int xine_get_speed (xine_t *this);
+
+#define SPEED_PAUSE 0
+#define SPEED_SLOW_4 1
+#define SPEED_SLOW_2 2
+#define SPEED_NORMAL 4
+#define SPEED_FAST_2 8
+#define SPEED_FAST_4 16
+
+/*
+ * manually adjust a/v sync
+ */
+
+void xine_set_av_offset (xine_t *this, int offset_pts);
+int xine_get_av_offset (xine_t *this);
/*
* stop playing