summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Roitzsch <mroi@users.sourceforge.net>2002-10-29 16:02:43 +0000
committerMichael Roitzsch <mroi@users.sourceforge.net>2002-10-29 16:02:43 +0000
commit4f15163a94c863e3e0cf8a65f3ad6f88946f7670 (patch)
tree34d456a17444c13b8b8c520c274ab11c483b0c3e /src
parent4d910814b52c53ac6af78f77e20ee5db7eab3211 (diff)
downloadxine-lib-4f15163a94c863e3e0cf8a65f3ad6f88946f7670.tar.gz
xine-lib-4f15163a94c863e3e0cf8a65f3ad6f88946f7670.tar.bz2
engine improvements
- output fifo flushing - more sophisticated discontinuity handling - seek improvement by waiting for at least one frame CVS patchset: 3089 CVS date: 2002/10/29 16:02:43
Diffstat (limited to 'src')
-rw-r--r--src/xine-engine/audio_decoder.c4
-rw-r--r--src/xine-engine/audio_out.c105
-rw-r--r--src/xine-engine/audio_out.h10
-rw-r--r--src/xine-engine/demux.c8
-rw-r--r--src/xine-engine/metronom.c173
-rw-r--r--src/xine-engine/metronom.h14
-rw-r--r--src/xine-engine/video_decoder.c10
-rw-r--r--src/xine-engine/video_out.c61
-rw-r--r--src/xine-engine/video_out.h5
-rw-r--r--src/xine-engine/xine.c30
-rw-r--r--src/xine-engine/xine_internal.h7
11 files changed, 295 insertions, 132 deletions
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index 32fb031e0..890298251 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.86 2002/10/18 04:04:10 miguelfreitas Exp $
+ * $Id: audio_decoder.c,v 1.87 2002/10/29 16:02:43 mroi Exp $
*
*
* functions that implement audio decoding
@@ -149,8 +149,6 @@ void *audio_decoder_loop (void *stream_gen) {
case BUF_CONTROL_RESET_DECODER:
if (stream->audio_decoder_plugin)
stream->audio_decoder_plugin->reset (stream->audio_decoder_plugin);
- if (stream->audio_out)
- stream->audio_out->control(stream->audio_out, AO_CTRL_FLUSH_BUFFERS);
break;
case BUF_CONTROL_DISCONTINUITY:
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index 0c7310557..a17f438c8 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -17,7 +17,7 @@
* along with self program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_out.c,v 1.74 2002/10/24 17:51:30 guenter Exp $
+ * $Id: audio_out.c,v 1.75 2002/10/29 16:02:45 mroi Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -136,11 +136,9 @@ static audio_fifo_t *fifo_new () {
return fifo;
}
-static void fifo_append (audio_fifo_t *fifo,
+static void fifo_append_int (audio_fifo_t *fifo,
audio_buffer_t *buf) {
- pthread_mutex_lock (&fifo->mutex);
-
buf->next = NULL;
if (!fifo->first) {
@@ -156,16 +154,19 @@ static void fifo_append (audio_fifo_t *fifo,
fifo->num_buffers++;
}
-
pthread_cond_signal (&fifo->not_empty);
- pthread_mutex_unlock (&fifo->mutex);
}
-static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) {
-
- audio_buffer_t *buf;
+static void fifo_append (audio_fifo_t *fifo,
+ audio_buffer_t *buf) {
pthread_mutex_lock (&fifo->mutex);
+ fifo_append_int (fifo, buf);
+ pthread_mutex_unlock (&fifo->mutex);
+}
+
+static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo) {
+ audio_buffer_t *buf;
while (!fifo->first) {
pthread_cond_wait (&fifo->not_empty, &fifo->mutex);
@@ -187,11 +188,21 @@ static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) {
}
+ return buf;
+}
+
+static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) {
+
+ audio_buffer_t *buf;
+
+ pthread_mutex_lock (&fifo->mutex);
+ buf = fifo_remove_int(fifo);
pthread_mutex_unlock (&fifo->mutex);
return buf;
}
+
void write_pause_burst(ao_instance_t *this, uint32_t num_frames)
{
int error = 0;
@@ -320,7 +331,7 @@ static void audio_filter_compress (ao_instance_t *this, int16_t *mem, int num_fr
this->compression_factor = this->compression_factor_max;
}
-#if LOG
+#ifdef LOG
printf ("audio_out: max=%d f_max=%f compression_factor=%f\n",
maxs, f_max, this->compression_factor);
#endif
@@ -471,11 +482,8 @@ static void *ao_loop (void *this_gen) {
int64_t gap;
int64_t delay;
int64_t cur_time;
- /* int num_output_frames ;*/
- /* int paused_wait; */
int64_t last_sync_time;
int bufs_since_sync;
- /* double acc_output_frames, output_frame_excess = 0; */
last_sync_time = bufs_since_sync = 0;
#ifdef LOG
@@ -490,12 +498,21 @@ static void *ao_loop (void *this_gen) {
while ((this->audio_loop_running) ||
(!this->audio_loop_running && this->out_fifo->first)) {
+
+ if (this->flush_audio_driver) {
+#ifdef LOG
+ printf ("audio_out: flush audio driver\n");
+#endif
+ this->control(this, AO_CTRL_FLUSH_BUFFERS);
+ this->flush_audio_driver = 0;
+ }
+
/* wait until user unpauses stream
audio_paused == 1 means we are playing at a different speed
them we must process buffers otherwise the entire engine will stop.
*/
- while ( this->audio_paused ) {
+ while ( this->audio_paused && this->audio_loop_running ) {
switch (this->audio_paused) {
case 1:
{
@@ -512,7 +529,7 @@ static void *ao_loop (void *this_gen) {
}
case 2:
{
- this->metronom->allow_full_ao_fill_gap = 1;
+ this->allow_full_ao_fill_gap = 1;
#ifdef LOG
printf ("audio_out:loop:pause: I feel sleepy.\n");
#endif
@@ -526,7 +543,7 @@ static void *ao_loop (void *this_gen) {
}
/* pthread_mutex_lock( &this->driver_lock ); What is this lock for ? */
delay = this->driver->delay(this->driver);
- while (delay <=0) {
+ while (delay <=0 && this->audio_loop_running) {
/* Get the audio card into RUNNING state. */
ao_fill_gap (this, 10000); /* FIXME, this PTS of 1000 should == period size */
delay = this->driver->delay(this->driver);
@@ -586,8 +603,9 @@ static void *ao_loop (void *this_gen) {
} else if ( abs(gap) < AO_MAX_GAP && abs(gap) > this->gap_tolerance &&
cur_time > (last_sync_time + SYNC_TIME_INVERVAL) &&
bufs_since_sync >= SYNC_BUF_INTERVAL ) {
-
+#ifdef LOG
printf ("audio_out: audio_loop: ADJ_VPTS\n");
+#endif
this->metronom->set_option(this->metronom, METRONOM_ADJ_VPTS_OFFSET,
-gap/SYNC_GAP_RATE );
last_sync_time = cur_time;
@@ -595,9 +613,9 @@ static void *ao_loop (void *this_gen) {
} else if ( gap > AO_MAX_GAP ) {
/* for big gaps output silence */
- if (this->metronom->allow_full_ao_fill_gap) {
+ if (this->allow_full_ao_fill_gap) {
ao_fill_gap (this, gap);
- this->metronom->allow_full_ao_fill_gap = 0;
+ this->allow_full_ao_fill_gap = 0;
} else {
ao_fill_gap (this, gap / 2);
}
@@ -955,6 +973,26 @@ static int ao_control (ao_instance_t *this, int cmd, ...) {
return rval;
}
+static void ao_flush (ao_instance_t *this) {
+ audio_buffer_t *buf;
+ int i, num_buffers;
+
+ pthread_mutex_lock (&this->out_fifo->mutex);
+ pthread_mutex_lock (&this->free_fifo->mutex);
+ num_buffers = this->out_fifo->num_buffers;
+ printf ("audio_out: flush fifo (%d buffers)\n", num_buffers);
+
+ for (i = 0; i < this->out_fifo->num_buffers; i++) {
+ buf = fifo_remove_int (this->out_fifo);
+ fifo_append_int (this->free_fifo, buf);
+ }
+
+ this->flush_audio_driver = 1;
+ this->allow_full_ao_fill_gap = 1;
+ pthread_mutex_unlock (&this->free_fifo->mutex);
+ pthread_mutex_unlock (&this->out_fifo->mutex);
+}
+
ao_instance_t *ao_new_instance (xine_ao_driver_t *driver,
xine_stream_t *stream) {
@@ -971,19 +1009,22 @@ ao_instance_t *ao_new_instance (xine_ao_driver_t *driver,
this->stream = stream;
pthread_mutex_init( &this->driver_lock, NULL );
- this->open = ao_open;
- this->get_buffer = ao_get_buffer;
- this->put_buffer = ao_put_buffer;
- this->close = ao_close;
- this->exit = ao_exit;
- this->get_capabilities = ao_get_capabilities;
- this->get_property = ao_get_property;
- this->set_property = ao_set_property;
- this->control = ao_control;
- this->audio_loop_running = 0;
- this->audio_paused = 0;
- this->zero_space = xine_xmalloc (ZERO_BUF_SIZE * 2 * 6);
- this->gap_tolerance = driver->get_gap_tolerance (this->driver);
+ this->open = ao_open;
+ this->get_buffer = ao_get_buffer;
+ this->put_buffer = ao_put_buffer;
+ this->close = ao_close;
+ this->exit = ao_exit;
+ this->get_capabilities = ao_get_capabilities;
+ this->get_property = ao_get_property;
+ this->set_property = ao_set_property;
+ this->control = ao_control;
+ this->flush = ao_flush;
+ this->audio_loop_running = 0;
+ this->audio_paused = 0;
+ this->flush_audio_driver = 0;
+ this->allow_full_ao_fill_gap = 0;
+ this->zero_space = xine_xmalloc (ZERO_BUF_SIZE * 2 * 6);
+ this->gap_tolerance = driver->get_gap_tolerance (this->driver);
this->resample_conf = config->register_enum (config, "audio.resample_mode", 0,
resample_modes,
diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h
index b22f1a7bc..5e1cedaa4 100644
--- a/src/xine-engine/audio_out.h
+++ b/src/xine-engine/audio_out.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: audio_out.h,v 1.39 2002/10/24 17:51:30 guenter Exp $
+ * $Id: audio_out.h,v 1.40 2002/10/29 16:02:47 mroi Exp $
*/
#ifndef HAVE_AUDIO_OUT_H
#define HAVE_AUDIO_OUT_H
@@ -201,7 +201,11 @@ struct ao_instance_s {
*/
int (*control) (ao_instance_t *this, int cmd, /* arg */ ...);
-
+ /*
+ * Flush audio_out fifo.
+ */
+ void (*flush) (ao_instance_t *this);
+
/* private stuff */
xine_ao_driver_t *driver;
@@ -232,6 +236,8 @@ struct ao_instance_s {
int16_t *zero_space;
int64_t passthrough_offset;
+ int flush_audio_driver;
+ int allow_full_ao_fill_gap;
int do_compress;
double compression_factor; /* current compression */
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c
index 7ccfaa8b4..ddbb9017f 100644
--- a/src/xine-engine/demux.c
+++ b/src/xine-engine/demux.c
@@ -56,6 +56,14 @@ void xine_demux_flush_engine (xine_stream_t *stream) {
buf->type = BUF_CONTROL_RESET_DECODER;
stream->audio_fifo->put (stream->audio_fifo, buf);
}
+
+ if (stream->video_out) {
+ stream->video_out->flush(stream->video_out);
+ }
+
+ if (stream->audio_out) {
+ stream->audio_out->flush(stream->audio_out);
+ }
stream->metronom->adjust_clock(stream->metronom,
stream->metronom->get_current_time(stream->metronom) + 30 * 90000 );
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index a779953f2..3635bdaa4 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.95 2002/10/28 07:53:52 tmattern Exp $
+ * $Id: metronom.c,v 1.96 2002/10/29 16:02:48 mroi Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -47,6 +47,7 @@
#define PREBUFFER_PTS_OFFSET 30000
#define VIDEO_DRIFT_TOLERANCE 45000
#define AUDIO_DRIFT_TOLERANCE 45000
+#define AV_DIFF_TOLERANCE 45000
/* redefine abs as macro to handle 64-bit diffs.
i guess llabs may not be available everywhere */
@@ -262,17 +263,17 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) {
int64_t vpts, video_vpts, vpts_old, vpts_new;
pthread_mutex_lock (&this->lock);
- vpts_old = pts + this->vpts_offset;
- vpts_new = pts + this->next_vpts_offset;
+ vpts_old = pts + this->old_vpts_offset;
+ vpts_new = pts + this->vpts_offset;
video_vpts = this->video_vpts;
if (pts >= 0 ) {
- if ( abs(vpts_old - video_vpts) > abs(vpts_new - video_vpts) ) {
- vpts = vpts_new;
- } else {
- vpts=vpts_old;
- }
- /* printf ("metronom: WARNING:got_spu_packet: vpts=%lld, old offset=%lld, new offset=%lld, video_vpts=%lld\n", vpts, vpts_old, vpts_new, video_vpts); */
+ if ( abs(vpts_old - video_vpts) > abs(vpts_new - video_vpts) ) {
+ vpts = vpts_new;
+ } else {
+ vpts = vpts_old;
+ }
+ /* printf ("metronom: WARNING:got_spu_packet: vpts=%lld, old offset=%lld, new offset=%lld, video_vpts=%lld\n", vpts, vpts_old, vpts_new, video_vpts); */
} else {
/* pts < 0 */
vpts = this->vpts_offset;
@@ -285,11 +286,12 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) {
static void metronom_handle_video_discontinuity (metronom_t *this, int type,
int64_t disc_off) {
+ int64_t diff;
pthread_mutex_lock (&this->lock);
#ifdef LOG
- printf ("metronom: av_diff=%ld\n", this->video_vpts - this->audio_vpts);
+ printf ("metronom: av_diff=%lld\n", this->video_vpts - this->audio_vpts);
#endif
this->video_discontinuity_count++;
@@ -307,55 +309,83 @@ static void metronom_handle_video_discontinuity (metronom_t *this, int type,
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 %lld\n", this->video_vpts);
- }
}
+ if ( this->audio_vpts < metronom_get_current_time(this) ) {
+ this->audio_vpts = PREBUFFER_PTS_OFFSET + metronom_get_current_time(this);
+ printf ("metronom: audio vpts adjusted with prebuffer to %lld\n", this->audio_vpts);
+ }
if ( this->video_vpts < metronom_get_current_time(this) ) {
this->video_vpts = PREBUFFER_PTS_OFFSET + metronom_get_current_time(this);
printf ("metronom: video vpts adjusted with prebuffer to %lld\n", this->video_vpts);
}
+
+ diff = this->video_vpts - this->audio_vpts;
+ if (abs(diff) > AV_DIFF_TOLERANCE) {
+ if (this->video_vpts > this->audio_vpts)
+ this->audio_vpts = this->video_vpts;
+ else
+ this->video_vpts = this->audio_vpts;
+ } else {
+ this->video_drift = diff;
+ this->video_drift_step = diff / 30;
+ }
- if (this->in_discontinuity)
- this->vpts_offset = this->next_vpts_offset;
-
+ this->old_vpts_offset = this->vpts_offset;
+
switch (type) {
case DISC_STREAMSTART:
#ifdef LOG
printf ("metronom: DISC_STREAMSTART\n");
#endif
- this->vpts_offset = this->video_vpts;
- this->in_discontinuity = 0;
- this->force_audio_jump = 0;
+ if (this->video_vpts > this->audio_vpts)
+ this->vpts_offset = this->audio_vpts = this->video_vpts;
+ else
+ this->vpts_offset = this->video_vpts = this->audio_vpts;
+ this->video_discontinuity_pts = disc_off;
+ this->audio_discontinuity_pts = disc_off;
+ this->in_video_discontinuity = 0;
+ this->in_audio_discontinuity = 0;
+ this->force_audio_jump = 1;
+ this->force_video_jump = 1;
+ this->video_drift = 0;
break;
case DISC_ABSOLUTE:
#ifdef LOG
printf ("metronom: DISC_ABSOLUTE\n");
#endif
- this->next_vpts_offset = this->video_vpts - disc_off;
- this->in_discontinuity = 30;
- this->force_audio_jump = 0;
+ this->vpts_offset = this->video_vpts - disc_off;
+ this->video_discontinuity_pts = disc_off;
+ this->audio_discontinuity_pts = disc_off;
+ this->in_video_discontinuity = 30;
+ this->in_audio_discontinuity = 30;
+ this->force_audio_jump = 0;
+ this->force_video_jump = 0;
break;
case DISC_RELATIVE:
#ifdef LOG
printf ("metronom: DISC_RELATIVE\n");
#endif
- this->next_vpts_offset = this->vpts_offset - disc_off;
- this->in_discontinuity = 30;
- this->force_audio_jump = 0;
+ this->vpts_offset = this->vpts_offset - disc_off;
+ this->video_discontinuity_pts = this->video_vpts - this->vpts_offset;
+ this->audio_discontinuity_pts = this->audio_vpts - this->vpts_offset;
+ this->in_video_discontinuity = 30;
+ this->in_audio_discontinuity = 30;
+ this->force_audio_jump = 0;
+ this->force_video_jump = 0;
break;
case DISC_STREAMSEEK:
#ifdef LOG
printf ("metronom: DISC_STREAMSEEK\n");
#endif
- this->vpts_offset = this->video_vpts - disc_off;
- this->next_vpts_offset = this->video_vpts - disc_off;
- this->in_discontinuity = 30;
- this->force_audio_jump = 1;
- this->allow_full_ao_fill_gap = 1;
+ this->vpts_offset = this->video_vpts - disc_off;
+ this->video_discontinuity_pts = disc_off;
+ this->audio_discontinuity_pts = disc_off;
+ this->in_video_discontinuity = 30;
+ this->in_audio_discontinuity = 30;
+ this->force_audio_jump = 1;
+ this->force_video_jump = 1;
+ this->video_drift = 0;
break;
}
@@ -378,13 +408,17 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
printf("metronom: got_video_frame pts = %lld\n", pts );
#endif
- if (this->in_discontinuity) {
- this->in_discontinuity--;
+ if (this->in_video_discontinuity) {
+ this->in_video_discontinuity--;
- if (!this->in_discontinuity)
- this->vpts_offset = this->next_vpts_offset;
- else
- pts = 0; /* ignore pts during discontinuities */
+ if (pts) {
+ diff = pts - this->video_discontinuity_pts;
+ if (abs(diff) < VIDEO_DRIFT_TOLERANCE) {
+ this->in_video_discontinuity = 0;
+ } else {
+ pts = 0; /* ignore pts during discontinuities */
+ }
+ }
}
this->img_cpt++;
@@ -424,10 +458,10 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
diff, this->video_vpts, vpts);
#endif
- if (abs (diff) > VIDEO_DRIFT_TOLERANCE) {
-
- this->video_vpts = vpts;
- this->video_drift = 0;
+ if ((abs (diff) > VIDEO_DRIFT_TOLERANCE) || (this->force_video_jump)) {
+ this->force_video_jump = 0;
+ this->video_vpts = vpts;
+ this->video_drift = 0;
printf ("metronom: video jump\n");
@@ -489,16 +523,6 @@ static void metronom_handle_audio_discontinuity (metronom_t *this, int type,
pthread_cond_wait (&this->video_discontinuity_reached, &this->lock);
}
- if ( this->audio_vpts < metronom_get_current_time(this) ) {
- this->audio_vpts = PREBUFFER_PTS_OFFSET + metronom_get_current_time(this);
- printf ("metronom: audio vpts adjusted with prebuffer to %lld\n", this->audio_vpts);
- }
-
- if ( this->audio_vpts < this->video_vpts ) {
- this->audio_vpts = this->video_vpts;
- printf ("metronom: audio vpts adjusted to %lld\n", this->audio_vpts);
- }
-
/* next_vpts_offset, in_discontinuity is handled in expect_video_discontinuity */
while ( this->audio_discontinuity_count >
this->discontinuity_handled_count ) {
@@ -527,17 +551,28 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts,
pthread_mutex_lock (&this->lock);
- if (this->in_discontinuity && !this->force_audio_jump)
- pts = 0; /* ignore pts during discontinuities */
+ if (this->in_audio_discontinuity) {
+ this->in_audio_discontinuity--;
+
+ if (pts) {
+ diff = pts - this->audio_discontinuity_pts;
+ if (abs(diff) < AUDIO_DRIFT_TOLERANCE) {
+ this->in_audio_discontinuity = 0;
+ } else {
+ pts = 0; /* ignore pts during discontinuities */
+ }
+ }
+ }
+
if (pts) {
vpts = pts + this->vpts_offset;
diff = this->audio_vpts - vpts;
/* compare predicted and given vpts */
- if( (abs(diff) > AUDIO_DRIFT_TOLERANCE) || this->force_audio_jump ) {
- this->audio_vpts = vpts;
- this->audio_drift_step = 0;
+ if((abs(diff) > AUDIO_DRIFT_TOLERANCE) || (this->force_audio_jump)) {
this->force_audio_jump = 0;
+ this->audio_vpts = vpts;
+ this->audio_drift_step = 0;
printf("metronom: audio jump\n");
}
else {
@@ -760,17 +795,17 @@ metronom_t * metronom_init (int have_audio, xine_stream_t *stream) {
printf ("metronom: cannot create sync thread (%s)\n",
strerror(err));
- this->av_offset = 0;
- this->in_discontinuity = 0;
- this->vpts_offset = 0;
- this->next_vpts_offset = 0;
+ this->av_offset = 0;
+ this->vpts_offset = 0;
+ this->old_vpts_offset = 0;
/* initialize video stuff */
- this->video_vpts = PREBUFFER_PTS_OFFSET;
- this->video_drift = 0;
- this->video_drift_step = 0;
- this->video_discontinuity_count = 0;
+ this->video_vpts = PREBUFFER_PTS_OFFSET;
+ this->video_drift = 0;
+ this->video_drift_step = 0;
+ this->video_discontinuity_count = 0;
+ this->in_video_discontinuity = 0;
this->discontinuity_handled_count = 0;
pthread_cond_init (&this->video_discontinuity_reached, NULL);
this->img_duration = 3000;
@@ -780,10 +815,10 @@ metronom_t * metronom_init (int have_audio, xine_stream_t *stream) {
/* initialize audio stuff */
- this->have_audio = have_audio;
- this->audio_vpts = PREBUFFER_PTS_OFFSET;
- this->audio_discontinuity_count = 0;
- this->allow_full_ao_fill_gap = 0;
+ this->have_audio = have_audio;
+ this->audio_vpts = PREBUFFER_PTS_OFFSET;
+ this->in_audio_discontinuity = 0;
+ this->audio_discontinuity_count = 0;
pthread_cond_init (&this->audio_discontinuity_reached, NULL);
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h
index 8baeece10..85d0c5eb6 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.38 2002/10/28 07:53:52 tmattern Exp $
+ * $Id: metronom.h,v 1.39 2002/10/29 16:02:49 mroi Exp $
*
* metronom: general pts => virtual calculation/assoc
*
@@ -217,9 +217,7 @@ struct metronom_s {
int64_t audio_vpts;
int64_t vpts_offset;
- int64_t next_vpts_offset;
-
- int in_discontinuity;
+ int64_t old_vpts_offset;
int64_t video_drift;
int64_t video_drift_step;
@@ -244,9 +242,15 @@ struct metronom_s {
pthread_cond_t audio_discontinuity_reached;
pthread_cond_t cancel;
- int allow_full_ao_fill_gap;
+ int force_video_jump;
int force_audio_jump;
+ int64_t video_discontinuity_pts;
+ int64_t audio_discontinuity_pts;
+
+ int in_video_discontinuity;
+ int in_audio_discontinuity;
+
int64_t img_duration;
int img_cpt;
int64_t last_video_pts;
diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c
index 90915ef3d..9b3eff3ba 100644
--- a/src/xine-engine/video_decoder.c
+++ b/src/xine-engine/video_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: video_decoder.c,v 1.105 2002/10/27 01:52:15 guenter Exp $
+ * $Id: video_decoder.c,v 1.106 2002/10/29 16:02:49 mroi Exp $
*
*/
@@ -206,6 +206,14 @@ void *video_decoder_loop (void *stream_gen) {
buf->decoder_flags & BUF_FLAG_END_STREAM);
}
+ /* Wake up xine_play if it's waiting for a frame */
+ pthread_mutex_lock (&stream->first_frame_lock);
+ if (stream->first_frame_flag) {
+ stream->first_frame_flag = 0;
+ pthread_cond_signal(&stream->first_frame_reached);
+ }
+ pthread_mutex_unlock (&stream->first_frame_lock);
+
break;
case BUF_CONTROL_QUIT:
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 8c10a1b1f..f89daa873 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.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: video_out.c,v 1.106 2002/10/16 22:54:48 guenter Exp $
+ * $Id: video_out.c,v 1.107 2002/10/29 16:02:50 mroi Exp $
*
* frame allocation / queuing / scheduling / output functions
*/
@@ -109,11 +109,9 @@ static img_buf_fifo_t *vo_new_img_buf_queue () {
return queue;
}
-static void vo_append_to_img_buf_queue (img_buf_fifo_t *queue,
+static void vo_append_to_img_buf_queue_int (img_buf_fifo_t *queue,
vo_frame_t *img) {
- pthread_mutex_lock (&queue->mutex);
-
/* img already enqueue? (serious leak) */
assert (img->next==NULL);
@@ -132,14 +130,18 @@ static void vo_append_to_img_buf_queue (img_buf_fifo_t *queue,
queue->num_buffers++;
pthread_cond_signal (&queue->not_empty);
+}
+
+static void vo_append_to_img_buf_queue (img_buf_fifo_t *queue,
+ vo_frame_t *img) {
+ pthread_mutex_lock (&queue->mutex);
+ vo_append_to_img_buf_queue_int (queue, img);
pthread_mutex_unlock (&queue->mutex);
}
-static vo_frame_t *vo_remove_from_img_buf_queue (img_buf_fifo_t *queue) {
+static vo_frame_t *vo_remove_from_img_buf_queue_int (img_buf_fifo_t *queue) {
vo_frame_t *img;
- pthread_mutex_lock (&queue->mutex);
-
while (!queue->first || queue->locked_for_read) {
pthread_cond_wait (&queue->not_empty, &queue->mutex);
}
@@ -158,6 +160,14 @@ static vo_frame_t *vo_remove_from_img_buf_queue (img_buf_fifo_t *queue) {
}
}
+ return img;
+}
+
+static vo_frame_t *vo_remove_from_img_buf_queue (img_buf_fifo_t *queue) {
+ vo_frame_t *img;
+
+ pthread_mutex_lock (&queue->mutex);
+ img = vo_remove_from_img_buf_queue_int(queue);
pthread_mutex_unlock (&queue->mutex);
return img;
@@ -279,6 +289,17 @@ static int vo_frame_draw (vo_frame_t *img) {
}
if (!img->bad_frame) {
+
+ /*
+ * Wake up xine_play if it's waiting for a frame
+ */
+ pthread_mutex_lock (&this->stream->first_frame_lock);
+ if (this->stream->first_frame_flag) {
+ this->stream->first_frame_flag = 0;
+ pthread_cond_signal(&this->stream->first_frame_reached);
+ }
+ pthread_mutex_unlock (&this->stream->first_frame_lock);
+
/*
* put frame into FIFO-Buffer
*/
@@ -703,7 +724,7 @@ static void *video_out_loop (void *this_gen) {
printf ("video_out: displaying frame (id=%d)\n", img->id);
#endif
overlay_and_display_frame (this, img, vpts);
- }
+ }
else
{
check_redraw_needed( this, vpts );
@@ -886,6 +907,29 @@ static void vo_enable_overlay (vo_instance_t *this_gen, int overlay_enabled) {
this->overlay_enabled = overlay_enabled;
}
+/*
+ * Flush video_out fifo
+ */
+static void vo_flush (vo_instance_t *this_gen) {
+ vos_t *this = (vos_t *) this_gen;
+ vo_frame_t *img;
+ int i, num_buffers;
+
+ pthread_mutex_lock (&this->display_img_buf_queue->mutex);
+ pthread_mutex_lock (&this->free_img_buf_queue->mutex);
+ num_buffers = this->display_img_buf_queue->num_buffers;
+
+ /* don't flush the last img, it improves seeking */
+ printf ("video_out: flush fifo (%d buffers)\n", num_buffers);
+ for (i = 1; i < num_buffers; i++) {
+ img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue);
+ vo_append_to_img_buf_queue_int (this->free_img_buf_queue, img);
+ }
+
+ pthread_mutex_unlock (&this->free_img_buf_queue->mutex);
+ pthread_mutex_unlock (&this->display_img_buf_queue->mutex);
+}
+
vo_instance_t *vo_new_instance (xine_vo_driver_t *driver,
xine_stream_t *stream) {
@@ -912,6 +956,7 @@ vo_instance_t *vo_new_instance (xine_vo_driver_t *driver,
this->vo.get_capabilities = vo_get_capabilities;
this->vo.enable_ovl = vo_enable_overlay;
this->vo.get_overlay_instance = vo_get_overlay_instance;
+ this->vo.flush = vo_flush;
this->num_frames_delivered = 0;
this->num_frames_skipped = 0;
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index 17d956868..275fcd0d0 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.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: video_out.h,v 1.68 2002/10/26 14:45:28 mroi Exp $
+ * $Id: video_out.h,v 1.69 2002/10/29 16:02:50 mroi Exp $
*
*
* xine version of video_out.h
@@ -150,6 +150,9 @@ struct vo_instance_s {
/* get overlay instance (overlay source) */
video_overlay_instance_t* (*get_overlay_instance) (vo_instance_t *this);
+ /* flush video_out fifo */
+ void (*flush) (vo_instance_t *this);
+
/* private stuff can be added here */
};
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 43ee01788..edda8b025 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.182 2002/10/29 03:31:38 guenter Exp $
+ * $Id: xine.c,v 1.183 2002/10/29 16:02:51 mroi Exp $
*
* top-level xine functions
*
@@ -113,7 +113,7 @@ static void xine_set_speed_internal (xine_stream_t *stream, int speed) {
* samples from the sound driver
*/
if (speed != XINE_SPEED_NORMAL && speed != XINE_SPEED_PAUSE)
- stream->audio_out->control(stream->audio_out, AO_CTRL_FLUSH_BUFFERS);
+ stream->audio_out->flush(stream->audio_out);
stream->audio_out->control(stream->audio_out,
speed == XINE_SPEED_PAUSE ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME);
@@ -187,10 +187,6 @@ static void xine_stop_internal (xine_stream_t *stream) {
printf ("xine_stop: demux stopped\n");
#endif
- /* remove buffered samples from the sound device driver */
- if (stream->audio_out)
- stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS);
-
#ifdef LOG
printf ("xine_stop: done\n");
#endif
@@ -318,6 +314,9 @@ xine_stream_t *xine_stream_new (xine_t *this,
pthread_mutex_init (&stream->osd_lock, NULL);
pthread_mutex_init (&stream->counter_lock, NULL);
pthread_cond_init (&stream->counter_changed, NULL);
+ pthread_mutex_init (&stream->first_frame_lock, NULL);
+ pthread_cond_init (&stream->first_frame_reached, NULL);
+
/*
* event queues
@@ -412,10 +411,6 @@ static int xine_open_internal (xine_stream_t *stream, const char *mrl) {
_("xine: couldn't find demux for >%s<\n"), mrl);
stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
- /* remove buffered samples from the sound device driver */
- if (stream->audio_out)
- stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS);
-
stream->status = XINE_STATUS_STOP;
return 0;
}
@@ -509,6 +504,17 @@ static int xine_play_internal (xine_stream_t *stream, int start_pos, int start_t
if (stream->speed != XINE_SPEED_NORMAL)
xine_set_speed_internal (stream, XINE_SPEED_NORMAL);
+ /* Wait until the first frame produced by the previous
+ * xine_play call is pushed into the video_out fifo
+ * see video_out.c
+ */
+ pthread_mutex_lock (&stream->first_frame_lock);
+ /* FIXME: howto detect if video frames will be produced */
+ if (stream->first_frame_flag && stream->video_decoder_plugin) {
+ pthread_cond_wait(&stream->first_frame_reached, &stream->first_frame_lock);
+ }
+ pthread_mutex_unlock (&stream->first_frame_lock);
+
/*
* start/seek demux
*/
@@ -544,6 +550,10 @@ static int xine_play_internal (xine_stream_t *stream, int start_pos, int start_t
stream->status = XINE_STATUS_PLAY;
}
+ pthread_mutex_lock (&stream->first_frame_lock);
+ stream->first_frame_flag = 1;
+ pthread_mutex_unlock (&stream->first_frame_lock);
+
printf ("xine: xine_play_internal ...done\n");
return 1;
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 0f7e8baec..1eb4b5fae 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.108 2002/10/28 03:24:44 miguelfreitas Exp $
+ * $Id: xine_internal.h,v 1.109 2002/10/29 16:02:54 mroi Exp $
*
*/
@@ -190,6 +190,11 @@ struct xine_stream_s {
int stream_info[XINE_STREAM_INFO_MAX];
char *meta_info [XINE_STREAM_INFO_MAX];
+ /* seeking slowdown */
+ int first_frame_flag;
+ pthread_mutex_t first_frame_lock;
+ pthread_cond_t first_frame_reached;
+
/* wait for headers sent / stream decoding finished */
pthread_mutex_t counter_lock;
pthread_cond_t counter_changed;