summaryrefslogtreecommitdiff
path: root/src/xine-engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine')
-rw-r--r--src/xine-engine/audio_decoder.c17
-rw-r--r--src/xine-engine/audio_out.c5
-rw-r--r--src/xine-engine/audio_out.h11
-rw-r--r--src/xine-engine/buffer.h15
-rw-r--r--src/xine-engine/buffer_types.c9
-rw-r--r--src/xine-engine/metronom.c523
-rw-r--r--src/xine-engine/metronom.h108
-rw-r--r--src/xine-engine/video_decoder.c23
-rw-r--r--src/xine-engine/video_out.c985
-rw-r--r--src/xine-engine/video_out.h98
-rw-r--r--src/xine-engine/video_overlay.h38
-rw-r--r--src/xine-engine/xine.c14
12 files changed, 771 insertions, 1075 deletions
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index fa6a3582b..169919f2b 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.57 2001/12/11 15:30:06 miguelfreitas Exp $
+ * $Id: audio_decoder.c,v 1.58 2002/02/09 07:13:24 guenter Exp $
*
*
* functions that implement audio decoding
@@ -81,14 +81,12 @@ void *audio_decoder_loop (void *this_gen) {
this->audio_finished = 0;
pthread_mutex_unlock (&this->finished_lock);
- this->metronom->audio_stream_start (this->metronom);
+ this->metronom->expect_audio_discontinuity (this->metronom);
break;
case BUF_CONTROL_END:
- this->metronom->audio_stream_end (this->metronom);
-
if (this->cur_audio_decoder_plugin) {
this->cur_audio_decoder_plugin->close (this->cur_audio_decoder_plugin);
this->cur_audio_decoder_plugin = NULL;
@@ -124,23 +122,12 @@ void *audio_decoder_loop (void *this_gen) {
running = 0;
break;
- case BUF_VIDEO_FILL:
- break;
-
case BUF_CONTROL_NOP:
break;
case BUF_CONTROL_DISCONTINUITY:
- printf ("audio_decoder: BUF_CONTROL_DISCONTINUITY is deprecated\n");
- break;
-
- case BUF_CONTROL_AVSYNC_RESET:
printf ("audio_decoder: discontinuity ahead\n");
- if (this->cur_audio_decoder_plugin) {
- this->cur_audio_decoder_plugin->reset (this->cur_audio_decoder_plugin);
- }
-
this->metronom->expect_audio_discontinuity (this->metronom);
break;
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index c1c099fe7..2eca26b8f 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.39 2001/12/24 12:36:19 miguelfreitas Exp $
+ * $Id: audio_out.c,v 1.40 2002/02/09 07:13:24 guenter Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -237,7 +237,6 @@ static void *ao_loop (void *this_gen) {
audio_buffer_t *buf;
int32_t gap;
int delay;
- uint8_t *data;
uint32_t cur_time;
int num_output_frames ;
int paused_wait;
@@ -474,7 +473,7 @@ static void ao_put_buffer (ao_instance_t *this, audio_buffer_t *buf) {
if ( buf->vpts<this->last_audio_vpts) {
/* reject buffer */
- printf ("audio_out: rejected buffer vpts=%d, last_audio_vpts=%d\n",
+ printf ("audio_out: rejected buffer vpts=%lld, last_audio_vpts=%lld\n",
buf->vpts, this->last_audio_vpts);
fifo_append (this->free_fifo, buf);
diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h
index ab219a648..23e987560 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.22 2001/11/27 00:00:35 jcdutton Exp $
+ * $Id: audio_out.h,v 1.23 2002/02/09 07:13:24 guenter Exp $
*/
#ifndef HAVE_AUDIO_OUT_H
#define HAVE_AUDIO_OUT_H
@@ -31,6 +31,9 @@ extern "C" {
#if defined(XINE_COMPILE)
#include "metronom.h"
#include "configfile.h"
+#else
+#include <xine/metronom.h>
+#include <xine/configfile.h>
#endif
@@ -133,8 +136,8 @@ struct audio_buffer_s {
int mem_size;
int num_frames;
- uint32_t vpts;
- uint32_t scr;
+ int64_t vpts;
+ int64_t scr;
uint32_t frame_header_count;
uint32_t first_access_unit;
};
@@ -191,7 +194,7 @@ struct ao_instance_s {
int32_t output_frame_rate, input_frame_rate;
double frame_rate_factor;
uint32_t num_channels;
- uint32_t last_audio_vpts;
+ int64_t last_audio_vpts;
int resample_conf;
int force_rate; /* force audio output rate to this value if non-zero */
int do_resample;
diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h
index f63327e23..685faf347 100644
--- a/src/xine-engine/buffer.h
+++ b/src/xine-engine/buffer.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: buffer.h,v 1.32 2002/01/15 17:30:51 miguelfreitas Exp $
+ * $Id: buffer.h,v 1.33 2002/02/09 07:13:24 guenter Exp $
*
*
* contents:
@@ -65,12 +65,10 @@ extern "C" {
#define BUF_CONTROL_START 0x01000000
#define BUF_CONTROL_END 0x01010000
#define BUF_CONTROL_QUIT 0x01020000
-#define BUF_CONTROL_DISCONTINUITY 0x01030000 /* deprecated */
+#define BUF_CONTROL_DISCONTINUITY 0x01030000 /* former AVSYNC_RESET */
#define BUF_CONTROL_NOP 0x01040000
#define BUF_CONTROL_AUDIO_CHANNEL 0x01050000
#define BUF_CONTROL_SPU_CHANNEL 0x01060000
-#define BUF_CONTROL_AVSYNC_RESET 0x01070000
-#define BUF_CONTROL_FLUSH 0x01080000
/* video buffer types: (please keep in sync with buffer_types.c) */
@@ -90,7 +88,6 @@ extern "C" {
#define BUF_VIDEO_ATIVCR2 0x020c0000
#define BUF_VIDEO_I263 0x020d0000
#define BUF_VIDEO_RV10 0x020e0000
-#define BUF_VIDEO_FILL 0x020f0000
#define BUF_VIDEO_RGB 0x02100000
#define BUF_VIDEO_YUY2 0x02110000
#define BUF_VIDEO_JPEG 0x02120000
@@ -142,13 +139,13 @@ struct buf_element_s {
buf_element_t *next;
unsigned char *mem;
- unsigned char *content; /* start of raw content in pMem (without header etc) */
+ unsigned char *content; /* start of raw content in pMem (without header etc) */
- int32_t size ; /* size of _content_ */
+ int32_t size ; /* size of _content_ */
int32_t max_size;
uint32_t type;
- uint32_t PTS; /* presentation time stamp, used for a/v sync */
- uint32_t SCR; /* system clock reference, used for discont. detection */
+ int64_t pts; /* presentation time stamp, used for a/v sync */
+ int64_t scr; /* system clock reference, used for discont. detection */
off_t input_pos; /* remember where this buf came from in the input source */
int input_time;/* time offset in seconds from beginning of stream */
uint32_t decoder_info[4]; /* additional decoder flags and other dec-spec. stuff */
diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c
index 994cacd97..f9b66892f 100644
--- a/src/xine-engine/buffer_types.c
+++ b/src/xine-engine/buffer_types.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: buffer_types.c,v 1.9 2002/01/15 17:30:51 miguelfreitas Exp $
+ * $Id: buffer_types.c,v 1.10 2002/02/09 07:13:24 guenter Exp $
*
*
* contents:
@@ -215,13 +215,6 @@ static video_db_t video_db[] = {
},
{
{
- 0
- },
- BUF_VIDEO_FILL,
- ""
-},
-{
- {
mmioFOURCC('r','a','w',' '),
0
},
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index f2d4e2875..8dd7d81f3 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.52 2002/01/28 17:28:39 miguelfreitas Exp $
+ * $Id: metronom.c,v 1.53 2002/02/09 07:13:24 guenter Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -37,41 +37,20 @@
#include "xine_internal.h"
#include "metronom.h"
#include "xineutils.h"
+#include "video_out.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_THRESHOLD 120000
-#define SCR_DISCONTINUITY 60000
-#define MAX_NUM_WRAP_DIFF 100
+#define MAX_NUM_WRAP_DIFF 10
#define MAX_SCR_PROVIDERS 10
#define PREBUFFER_PTS_OFFSET 30000
+#define VIDEO_DRIFT_TOLERANCE 45000
-#ifdef __GNUC__
-#define LOG_MSG_STDERR(xine, message, args...) { \
- xine_log((xine_t*)xine, XINE_LOG_METRONOM, message, ##args); \
- fprintf(stderr, message, ##args); \
- }
-#define LOG_MSG(xine, message, args...) { \
- xine_log((xine_t*)xine, XINE_LOG_METRONOM, message, ##args); \
- printf(message, ##args); \
- }
-#else
-#define LOG_MSG_STDERR(xine, ...) { \
- xine_log((xine_t*)xine, XINE_LOG_METRONOM, __VA_ARGS__); \
- fprintf(stderr, __VA_ARGS__); \
- }
-#define LOG_MSG(xine, ...) { \
- xine_log((xine_t*)xine, XINE_LOG_METRONOM, __VA_ARGS__); \
- printf(__VA_ARGS__); \
- }
-#endif
+#define METRONOM_REPORT
-/*
#define METRONOM_LOG
-*/
+
/*
* ****************************************
@@ -84,7 +63,7 @@ typedef struct unixscr_s {
scr_plugin_t scr;
struct timeval cur_time;
- uint32_t cur_pts;
+ int64_t cur_pts;
double speed_factor;
pthread_mutex_t lock;
@@ -99,7 +78,7 @@ static int unixscr_get_priority (scr_plugin_t *scr) {
static void unixscr_set_pivot (unixscr_t *this) {
struct timeval tv;
- uint32_t pts;
+ int64_t pts;
double pts_calc;
gettimeofday(&tv, NULL);
@@ -130,7 +109,7 @@ static int unixscr_set_speed (scr_plugin_t *scr, int speed) {
return speed;
}
-static void unixscr_adjust (scr_plugin_t *scr, uint32_t vpts) {
+static void unixscr_adjust (scr_plugin_t *scr, int64_t vpts) {
unixscr_t *this = (unixscr_t*) scr;
struct timeval tv;
@@ -144,7 +123,7 @@ static void unixscr_adjust (scr_plugin_t *scr, uint32_t vpts) {
pthread_mutex_unlock (&this->lock);
}
-static void unixscr_start (scr_plugin_t *scr, uint32_t start_vpts) {
+static void unixscr_start (scr_plugin_t *scr, int64_t start_vpts) {
unixscr_t *this = (unixscr_t*) scr;
pthread_mutex_lock (&this->lock);
@@ -155,11 +134,11 @@ static void unixscr_start (scr_plugin_t *scr, uint32_t start_vpts) {
pthread_mutex_unlock (&this->lock);
}
-static uint32_t unixscr_get_current (scr_plugin_t *scr) {
+static int64_t unixscr_get_current (scr_plugin_t *scr) {
unixscr_t *this = (unixscr_t*) scr;
struct timeval tv;
- uint32_t pts;
+ int64_t pts;
double pts_calc;
pthread_mutex_lock (&this->lock);
@@ -202,14 +181,17 @@ static scr_plugin_t* unixscr_init () {
*/
-static void metronom_start_clock (metronom_t *this, uint32_t pts) {
+static void metronom_start_clock (metronom_t *this, int64_t pts) {
scr_plugin_t** scr;
+
+ printf ("metronom: start_clock (at %lld)\n", pts);
+
for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++)
if (*scr) (*scr)->start(*scr, pts);
}
-static uint32_t metronom_get_current_time (metronom_t *this) {
+static int64_t metronom_get_current_time (metronom_t *this) {
return this->scr_master->get_current(this->scr_master);
}
@@ -228,7 +210,7 @@ static void metronom_resume_clock(metronom_t *this) {
-static void metronom_adjust_clock(metronom_t *this, uint32_t desired_pts) {
+static void metronom_adjust_clock(metronom_t *this, int64_t desired_pts) {
this->scr_master->adjust(this->scr_master, desired_pts);
}
@@ -245,179 +227,8 @@ static int metronom_set_speed (metronom_t *this, int speed) {
return true_speed;
}
-/*
- * virtual pts calculation
- */
-
-static void metronom_video_stream_start (metronom_t *this) {
-
- pthread_mutex_lock (&this->lock);
-
- LOG_MSG(this->xine, _("metronom: video stream start...\n"));
-
- if (this->video_stream_running) {
- LOG_MSG(this->xine, _("metronom: video stream start ignored\n"));
- pthread_mutex_unlock (&this->lock);
- return;
- }
-
- /*this->pts_per_frame = 3000; */
- this->avg_frame_duration = this->pts_per_frame;
-
- this->video_vpts = PREBUFFER_PTS_OFFSET;
-
- this->last_video_pts = 0;
- this->last_video_scr = 0;
- this->num_video_vpts_guessed = 0;
-
- /* video_wrap_offset will be updated with the first pts */
- /* 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) {
- LOG_MSG(this->xine, _("metronom: waiting for audio to start...\n"));
- pthread_cond_wait (&this->audio_started, &this->lock);
- }
- }
- pthread_cond_signal (&this->video_started);
-
- pthread_mutex_unlock (&this->lock);
-
- metronom_start_clock (this, 0);
-}
-
-
-static void metronom_video_stream_end (metronom_t *this) {
-
- pthread_mutex_lock (&this->lock);
-
- LOG_MSG(this->xine, _("metronom: video stream end\n"));
-
- if (!this->video_stream_running) {
- LOG_MSG(this->xine, _("metronom: video stream end ignored\n"));
- pthread_mutex_unlock (&this->lock);
- return;
- }
-
- this->video_stream_running = 0;
-
- if (this->have_audio) {
- /* while (this->audio_stream_running) { */
- if (this->audio_stream_running) {
- LOG_MSG(this->xine, _("metronom: waiting for audio to end...\n"));
- pthread_cond_wait (&this->audio_ended, &this->lock);
- }
- }
- pthread_cond_signal (&this->video_ended);
-
-
- pthread_mutex_unlock (&this->lock);
-}
-
-static void metronom_audio_stream_start (metronom_t *this) {
-
- pthread_mutex_lock (&this->lock);
-
- LOG_MSG(this->xine, _("metronom: audio stream start...\n"));
-
- if (this->audio_stream_running) {
- LOG_MSG(this->xine, _("metronom: audio stream start ignored\n"));
- pthread_mutex_unlock (&this->lock);
- return;
- }
-
- this->audio_vpts = PREBUFFER_PTS_OFFSET;
-
- this->audio_pts_delta = 0;
-
- this->num_audio_samples_guessed = 1;
- this->last_audio_pts = 0;
- this->last_audio_scr = 0;
-
- /* audio_wrap_offset will be updated with the first pts */
- /* 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) {
- LOG_MSG(this->xine, _("metronom: waiting for video to start...\n"));
- pthread_cond_wait (&this->video_started, &this->lock);
- }
-
- pthread_cond_signal (&this->audio_started);
-
- pthread_mutex_unlock (&this->lock);
-
- LOG_MSG(this->xine, _("metronom: audio stream start...done\n"));
-
- metronom_start_clock (this, 0);
-}
-
-static void metronom_audio_stream_end (metronom_t *this) {
-
- pthread_mutex_lock (&this->lock);
-
- LOG_MSG(this->xine, _("metronom: audio stream end\n"));
- if (!this->audio_stream_running) {
- LOG_MSG(this->xine, _("metronom: audio stream end ignored\n"));
- pthread_mutex_unlock (&this->lock);
- return;
- }
-
- this->audio_stream_running = 0;
-
- /* while (this->video_stream_running) { */
- if (this->video_stream_running) {
- LOG_MSG(this->xine, _("metronom: waiting for video to end...\n"));
- pthread_cond_wait (&this->video_ended, &this->lock);
- }
-
- pthread_cond_signal (&this->audio_ended);
- pthread_mutex_unlock (&this->lock);
-}
-
-static void metronom_set_video_rate (metronom_t *this, uint32_t pts_per_frame) {
- pthread_mutex_lock (&this->lock);
-
- printf ("metronom: set_video_rate %d\n", pts_per_frame);
-
- this->pts_per_frame = pts_per_frame;
-
- this->avg_frame_duration = this->pts_per_frame;
-
- pthread_mutex_unlock (&this->lock);
-}
-
-static uint32_t metronom_get_video_rate (metronom_t *this) {
- int ret;
-
- pthread_mutex_lock (&this->lock);
- ret = this->avg_frame_duration;
- pthread_mutex_unlock (&this->lock);
-
- /* this is due bad streams, but returning 0 will
- cause problems to video out timer setting. */
- if( ret < 100 )
- ret = 100;
- return ret;
-}
-
-static void metronom_set_audio_rate (metronom_t *this, uint32_t pts_per_smpls) {
+static void metronom_set_audio_rate (metronom_t *this, int64_t pts_per_smpls) {
pthread_mutex_lock (&this->lock);
this->pts_per_smpls = pts_per_smpls;
@@ -425,14 +236,14 @@ static void metronom_set_audio_rate (metronom_t *this, uint32_t pts_per_smpls) {
pthread_mutex_unlock (&this->lock);
#ifdef METRONOM_LOG
- printf ("metronom: %d pts per %d samples\n", pts_per_smpls, AUDIO_SAMPLE_NUM);
+ printf ("metronom: %lld pts per %d samples\n", pts_per_smpls, AUDIO_SAMPLE_NUM);
#endif
}
-static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts,
- uint32_t duration, uint32_t scr ) {
- uint32_t vpts;
+static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts,
+ int64_t duration, int64_t scr ) {
+ int64_t vpts;
pthread_mutex_lock (&this->lock);
@@ -452,9 +263,7 @@ static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts,
detected but this->video_wrap_offset not updated (would give
wrong values too).
*/
- if ( this->video_stream_starting ) {
- vpts = 0;
- } else if ( this->video_discontinuity ) {
+ if ( this->video_discontinuity ) {
/* we can safely use audio_wrap_offset if already updated */
if( !this->audio_discontinuity ) {
vpts = pts + this->audio_wrap_offset;
@@ -478,14 +287,14 @@ static void metronom_expect_video_discontinuity (metronom_t *this) {
this->video_discontinuity_count++;
pthread_cond_signal (&this->video_discontinuity_reached);
- LOG_MSG(this->xine, _("metronom: video discontinuity #%d\n"),
+ printf ("metronom: video discontinuity #%d\n",
this->video_discontinuity_count);
if( this->have_audio ) {
while ( this->audio_discontinuity_count <
this->video_discontinuity_count ) {
- LOG_MSG(this->xine, _("metronom: waiting for audio discontinuity #%d\n"),
+ printf ("metronom: waiting for audio discontinuity #%d\n",
this->video_discontinuity_count);
pthread_cond_wait (&this->audio_discontinuity_reached, &this->lock);
@@ -493,56 +302,53 @@ static void metronom_expect_video_discontinuity (metronom_t *this) {
if ( this->video_vpts < this->audio_vpts ) {
this->video_vpts = this->audio_vpts;
- LOG_MSG(this->xine, _("metronom: video vpts adjusted to %d\n"), this->video_vpts);
+ printf ("metronom: video vpts adjusted to %lld\n", this->video_vpts);
}
}
- /* this->num_video_vpts_guessed = 0; */
- /* this->last_video_pts = this->video_vpts - this->video_wrap_offset; */
- /*
- this->avg_frame_duration = this->pts_per_frame;
- */
- this->frames_since_start = 0;
-
pthread_mutex_unlock (&this->lock);
}
-static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts, uint32_t scr) {
+static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
- uint32_t vpts;
- int pts_discontinuity = 0;
+ int64_t vpts;
+ int64_t pts = img->pts;
+ int64_t duration = img->duration;
+ int pts_discontinuity = 0;
pthread_mutex_lock (&this->lock);
- if( (this->audio_discontinuity || this->audio_stream_starting) &&
- (this->video_discontinuity || this->video_stream_starting) ) {
-
- /* this is needed to take care of still frame with no audio
- were vpts are not updated.
- we can only do it here because audio and video decoder threads
- have just been synced */
- if ( this->video_vpts < metronom_get_current_time(this) ) {
- this->video_vpts = metronom_get_current_time(this) + PREBUFFER_PTS_OFFSET;
- this->audio_vpts = this->video_vpts;
- LOG_MSG(this->xine, _("metronom: audio/video vpts too old, adjusted to %d\n"),
- this->video_vpts);
- }
- }
-
/* check for pts discontinuities against the predicted pts value */
- if (pts && this->last_video_pts) {
- vpts = this->last_video_pts +
- (this->num_video_vpts_guessed+1) * this->avg_frame_duration;
- if( ( pts > vpts && (pts - vpts) > WRAP_THRESHOLD ) ||
- ( pts < vpts && (vpts - pts) > WRAP_THRESHOLD ) ) {
+ if (pts) {
+
+ int64_t diff, predicted_pts;
+
+ predicted_pts = this->last_video_pts + duration;
+
+ diff = pts - predicted_pts;
+
+#ifdef METRONOM_LOG
+ printf ("metronom: got video pts %lld, predicted %lld (= %lld + %lld) => diff %lld\n",
+ pts, predicted_pts, this->last_video_pts, duration, diff);
+#endif
+
+ if ( abs (diff) > WRAP_THRESHOLD ) {
+
pts_discontinuity = 1;
+#ifdef METRONOM_LOG
+ printf ("metronom: this is a video discontinuity\n");
+#endif
+
/*
- ignore discontinuities created by frame reordering around
- the REAL discontinuity. :)
- */
- if( !this->video_discontinuity && !this->video_stream_starting ) {
+ * ignore discontinuities created by frame reordering around
+ * the REAL discontinuity. :)
+ */
+ if( !this->video_discontinuity ) {
pts = 0;
+#ifdef METRONOM_LOG
+ printf ("metronom: not expecting a video discontinuity => ignored\n");
+#endif
}
}
}
@@ -552,33 +358,33 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts, uint32
* check if there was any pending SCR discontinuity (video_discontinuity
* is set from the decoder loop) together with pts discont.
*/
- if ( (this->video_discontinuity && pts_discontinuity) ||
- this->video_stream_starting ) {
+ if (this->video_discontinuity && pts_discontinuity) {
this->video_discontinuity = 0;
- this->video_stream_starting = 0;
this->wrap_diff_counter = 0;
- this->video_wrap_offset = this->video_vpts + this->avg_frame_duration - pts;
- /* + this->num_video_vpts_guessed * this->avg_frame_duration; */
+ this->video_wrap_offset = this->video_vpts - pts;
vpts = pts + this->video_wrap_offset;
- LOG_MSG(this->xine, _("metronom: video pts discontinuity/start, pts is %d, wrap_offset is %d, vpts is %d\n"),
+ printf ("metronom: video pts discontinuity/start, pts is %lld, wrap_offset is %lld, vpts is %lld\n",
pts, this->video_wrap_offset, vpts);
} else {
+ int64_t diff;
+
/*
* audio and video wrap are not allowed to differ for too long
*/
- if ( !this->audio_stream_starting && this->have_audio
+
+ if ( this->have_audio
&& (this->video_wrap_offset != this->audio_wrap_offset)
&& !this->video_discontinuity && !this->audio_discontinuity ) {
this->wrap_diff_counter++;
if (this->wrap_diff_counter > MAX_NUM_WRAP_DIFF) {
- LOG_MSG(this->xine, _("metronom: forcing video_wrap (%d) and audio wrap (%d)"),
+ printf ("metronom: forcing video_wrap (%lld) and audio wrap (%lld)",
this->video_wrap_offset, this->audio_wrap_offset);
if (this->video_wrap_offset > this->audio_wrap_offset)
@@ -586,103 +392,64 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts, uint32
else
this->video_wrap_offset = this->audio_wrap_offset;
- LOG_MSG(this->xine, _(" to %d\n"), this->video_wrap_offset);
+ printf (this->xine, " to %d\n", this->video_wrap_offset);
this->wrap_diff_counter = 0;
}
}
/*
- * calc overall average frame duration (according to pts values)
+ * compare predicted (this->video_vpts) and given (pts+wrap_offset)
+ * pts values - hopefully they will be the same
+ * if not, for small diffs try to interpolate
+ * for big diffs: jump
*/
- if (this->frames_since_start && this->last_video_pts) {
- int current_avg_delta;
-
- int weight_old = 9;
- int weight_new = 1;
-
- /*
- printf("foo: pts %d, last pts %d\n", pts, this->last_video_pts);
- */
-
- if (pts > this->last_video_pts) {
- current_avg_delta = (pts - this->last_video_pts) / (this->num_video_vpts_guessed + 1);
-
- /*
- printf("foo: current_avg_delta %d\n", current_avg_delta);
- */
-
- this->avg_frame_duration =
- (((this->avg_frame_duration * weight_old) + (current_avg_delta * weight_new)) /
- (weight_old + weight_new));
- } else {
- current_avg_delta = (this->last_video_pts - pts) / (this->num_video_vpts_guessed + 1);
-
- /*
- printf("foo: current_avg_delta - %d\n", current_avg_delta);
- */
- this->avg_frame_duration =
- (((this->avg_frame_duration * weight_old) - (current_avg_delta * weight_new)) /
- (weight_old + weight_new));
- }
- }
- }
+ vpts = pts + this->video_wrap_offset;
- this->last_video_pts = pts;
- }
+ diff = this->video_vpts - vpts;
- this->video_vpts += this->avg_frame_duration;
+#ifdef METRONOM_LOG
+ printf ("metronom: video diff is %lld (predicted %lld, given %lld)\n",
+ diff, this->video_vpts, vpts);
+#endif
- /*
- * smoothen possibly wrong pts as long as delta is small
- */
+ if (abs (diff) > VIDEO_DRIFT_TOLERANCE) {
- if (pts) {
- int drift;
- int delta = this->video_vpts - this->video_wrap_offset - pts;
+ this->video_vpts = vpts;
+ this->video_wrap_offset = vpts - pts;
#ifdef METRONOM_LOG
- printf("metronom: delta (vpts <-> pts+wrap_offset): %d\n", delta);
+ printf ("metronom: video jump, wrap offset is now %lld\n",
+ this->video_wrap_offset);
#endif
+
+ } else if (diff) {
- if (abs (delta) > 45000) {
-
- this->video_vpts = pts + this->video_wrap_offset;
-
- LOG_MSG(this->xine, _("metronom: delta too big, setting vpts to %d\n"),
- this->video_vpts);
+ this->video_vpts -= diff / 8; /* FIXME: better heuristics ? */
+ this->video_wrap_offset = vpts - pts;
-
- } else {
-
- if (this->num_video_vpts_guessed > 10)
- this->num_video_vpts_guessed = 10;
-
- drift = delta / 20 * (this->num_video_vpts_guessed + 1);
#ifdef METRONOM_LOG
- printf("metronom: compensation drift: %d\n", drift);
+ printf ("metronom: video drift, wrap offset is now %lld\n",
+ this->video_wrap_offset);
#endif
-
- this->video_vpts -= drift;
+ }
}
- this->num_video_vpts_guessed = 0;
+ this->last_video_pts = pts;
} else
- this->num_video_vpts_guessed++;
+ this->last_video_pts = this->video_vpts - this->video_wrap_offset;
- this->frames_since_start++;
+ img->vpts = this->video_vpts + this->av_offset;
#ifdef METRONOM_LOG
- printf ("metronom: video vpts for %10d : %10d (avg_frame_duration %d)\n",
- pts, this->video_vpts, this->avg_frame_duration);
+ printf ("metronom: video vpts for %10lld : %10lld\n",
+ pts, this->video_vpts);
#endif
- vpts = this->video_vpts + this->av_offset;
-
- pthread_mutex_unlock (&this->lock);
+ this->video_vpts += duration;
- return vpts;
+ pthread_mutex_unlock (&this->lock);
}
static void metronom_expect_audio_discontinuity (metronom_t *this) {
@@ -693,13 +460,13 @@ static void metronom_expect_audio_discontinuity (metronom_t *this) {
this->audio_discontinuity_count++;
pthread_cond_signal (&this->audio_discontinuity_reached);
- LOG_MSG(this->xine, _("metronom: audio discontinuity #%d\n"),
+ printf ("metronom: audio discontinuity #%d\n",
this->audio_discontinuity_count);
while ( this->audio_discontinuity_count >
this->video_discontinuity_count ) {
- LOG_MSG(this->xine, _("metronom: waiting for video_discontinuity #%d\n"),
+ printf ("metronom: waiting for video_discontinuity #%d\n",
this->audio_discontinuity_count);
pthread_cond_wait (&this->video_discontinuity_reached, &this->lock);
@@ -707,7 +474,7 @@ static void metronom_expect_audio_discontinuity (metronom_t *this) {
if ( this->audio_vpts < this->video_vpts ) {
this->audio_vpts = this->video_vpts;
- LOG_MSG(this->xine, _("metronom: audio vpts adjusted to %d\n"), this->audio_vpts);
+ printf ("metronom: audio vpts adjusted to %lld\n", this->audio_vpts);
}
/* this->num_audio_samples_guessed = 1; */
@@ -717,20 +484,20 @@ static void metronom_expect_audio_discontinuity (metronom_t *this) {
}
-static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts,
- uint32_t nsamples, uint32_t scr) {
+static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts,
+ int nsamples, int64_t scr) {
- uint32_t vpts;
+ int64_t vpts;
#ifdef METRONOM_LOG
- printf ("metronom: got %d samples, pts is %u, last_pts is %u, diff = %d\n",
+ printf ("metronom: got %d samples, pts is %lld, last_pts is %lld, diff = %lld\n",
nsamples, pts, this->last_audio_pts, pts - this->last_audio_pts);
#endif
pthread_mutex_lock (&this->lock);
- if( (this->audio_discontinuity || this->audio_stream_starting) &&
- (this->video_discontinuity || this->video_stream_starting) ) {
+#if 0
+ if (this->audio_discontinuity && this->video_discontinuity) {
/* this is needed to take care of still frame with no audio
were vpts are not updated.
@@ -739,32 +506,31 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts,
if ( this->audio_vpts < metronom_get_current_time(this) ) {
this->audio_vpts = metronom_get_current_time(this) + PREBUFFER_PTS_OFFSET;
this->video_vpts = this->audio_vpts;
- LOG_MSG(this->xine, _("metronom: audio/video vpts too old, adjusted to %d\n"),
+ printf ("metronom: audio/video vpts too old, adjusted to %lld\n",
this->audio_vpts);
}
}
-
- this->last_audio_scr = scr;
+#endif
if (pts) {
/*
* discontinuity ?
*/
- if ( this->audio_discontinuity || this->audio_stream_starting ) {
+ if ( this->audio_discontinuity ) {
this->audio_discontinuity = 0;
- this->audio_stream_starting = 0;
this->wrap_diff_counter = 0;
this->audio_wrap_offset = this->audio_vpts - 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 ;
+ */
vpts = pts + this->audio_wrap_offset;
- LOG_MSG(this->xine, _("metronom: audio pts discontinuity/start, pts is %d, wrap_offset is %d, vpts is %d\n"),
+ printf ("metronom: audio pts discontinuity/start, pts is %lld, wrap_offset is %lld, vpts is %lld\n",
pts, this->audio_wrap_offset, vpts);
@@ -781,7 +547,7 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts,
if (this->wrap_diff_counter > MAX_NUM_WRAP_DIFF) {
- LOG_MSG(this->xine, _("metronom: forcing video_wrap (%d) and audio wrap (%d)"),
+ printf ("metronom: forcing video_wrap (%lld) and audio wrap (%lld)",
this->video_wrap_offset, this->audio_wrap_offset);
if (this->video_wrap_offset > this->audio_wrap_offset)
@@ -789,7 +555,7 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts,
else
this->video_wrap_offset = this->audio_wrap_offset;
- LOG_MSG(this->xine, _("to %d\n"), this->video_wrap_offset);
+ printf ("to %lld\n", this->video_wrap_offset);
this->wrap_diff_counter = 0;
}
@@ -823,7 +589,7 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts,
this->num_audio_samples_guessed += nsamples;
#ifdef METRONOM_LOG
- printf ("metronom: audio vpts for %10d : %10d\n", pts, vpts);
+ printf ("metronom: audio vpts for %10lld : %10lld\n", pts, vpts);
#endif
pthread_mutex_unlock (&this->lock);
@@ -839,7 +605,7 @@ static void metronom_set_av_offset (metronom_t *this, int32_t pts) {
pthread_mutex_unlock (&this->lock);
- LOG_MSG(this->xine, _("metronom: av_offset=%d pts\n"), pts);
+ printf ("metronom: av_offset=%d pts\n", pts);
}
static int32_t metronom_get_av_offset (metronom_t *this) {
@@ -859,7 +625,7 @@ static scr_plugin_t* get_master_scr(metronom_t *this) {
}
}
if (select < 0) {
- LOG_MSG(this->xine, _("metronom: panic - no scr provider found!\n"));
+ printf ("metronom: panic - no scr provider found!\n");
return NULL;
}
return this->scr_list[select];
@@ -896,8 +662,9 @@ static void metronom_unregister_scr (metronom_t *this, scr_plugin_t *scr) {
}
static int metronom_sync_loop (metronom_t *this) {
+
scr_plugin_t** scr;
- uint32_t pts;
+ int64_t pts;
while (((xine_t*)this->xine)->status != XINE_QUIT) {
pts = this->scr_master->get_current(this->scr_master);
@@ -917,12 +684,6 @@ metronom_t * metronom_init (int have_audio, void *xine) {
int err;
this->xine = xine;
- this->audio_stream_start = metronom_audio_stream_start;
- this->audio_stream_end = metronom_audio_stream_end ;
- this->video_stream_start = metronom_video_stream_start;
- this->video_stream_end = metronom_video_stream_end ;
- this->set_video_rate = metronom_set_video_rate;
- this->get_video_rate = metronom_get_video_rate;
this->set_audio_rate = metronom_set_audio_rate;
this->got_video_frame = metronom_got_video_frame;
this->got_audio_samples = metronom_got_audio_samples;
@@ -945,20 +706,50 @@ metronom_t * metronom_init (int have_audio, void *xine) {
if ((err = pthread_create(&this->sync_thread, NULL,
(void*(*)(void*)) metronom_sync_loop, this)) != 0)
- LOG_MSG(this->xine, _("metronom: cannot create sync thread (%s)\n"),
+ 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;
- this->pts_per_frame = 3600;
+
+
+ /* initialize video stuff */
+
+ this->have_audio = have_audio;
+ this->video_vpts = PREBUFFER_PTS_OFFSET;
+
+ this->last_video_pts = 0;
+
+ this->video_wrap_offset = PREBUFFER_PTS_OFFSET;
+ this->wrap_diff_counter = 0;
+
+ this->video_discontinuity = 0;
+ this->video_discontinuity_count = 0;
+
+ /* initialize audio stuff */
+
+ this->audio_vpts = PREBUFFER_PTS_OFFSET;
+
+ this->audio_pts_delta = 0;
+
+ this->num_audio_samples_guessed = 1;
+ this->last_audio_pts = 0;
+
+ this->audio_wrap_offset = PREBUFFER_PTS_OFFSET;
+ this->wrap_diff_counter = 0;
+
+ this->audio_discontinuity = 0;
+ this->audio_discontinuity_count = 0;
return this;
}
+
+
+
+
+
+
+
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h
index 18dd2ca8e..1b6a841cc 100644
--- a/src/xine-engine/metronom.h
+++ b/src/xine-engine/metronom.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2001 the xine project
+ * Copyright (C) 2000-2002 the xine project
*
* This file is part of xine, a unix video player.
*
@@ -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.16 2001/12/27 14:30:30 f1rmb Exp $
+ * $Id: metronom.h,v 1.17 2002/02/09 07:13:24 guenter Exp $
*
* metronom: general pts => virtual calculation/assoc
*
@@ -50,6 +50,7 @@ extern "C" {
#include <inttypes.h>
#include <sys/time.h>
#include <pthread.h>
+#include "video_out.h"
typedef struct metronom_s metronom_t ;
typedef struct scr_plugin_s scr_plugin_t;
@@ -63,58 +64,26 @@ struct metronom_s {
void *xine;
/*
- * this is called to tell metronom to prepare for a new video stream
- * (video and audio decoder threads may be blocked at these functions
- * to synchronize starting and stopping)
- */
-
- void (*video_stream_start) (metronom_t *this);
- void (*video_stream_end) (metronom_t *this);
-
- /*
- * this is called to tell metronom to prepare for a new audio stream
- * (video and audio decoder threads may be blocked at these functions
- * to synchronize starting and stopping)
- */
-
- void (*audio_stream_start) (metronom_t *this);
- void (*audio_stream_end) (metronom_t *this);
-
- /*
- * called by video output driver to inform metronom about current framerate
- *
- * parameter pts_per_frame : frame display duration in 1/90000 sec
- */
- void (*set_video_rate) (metronom_t *this, uint32_t pts_per_frame);
-
- /*
- * return current video rate (including delta corrections)
- */
-
- uint32_t (*get_video_rate) (metronom_t *this);
-
- /*
* called by audio output driver to inform metronom about current audio
- * bitrate
+ * samplerate
*
* parameter pts_per_smpls : 1/90000 sec per 65536 samples
*/
- void (*set_audio_rate) (metronom_t *this, uint32_t pts_per_smpls);
+ void (*set_audio_rate) (metronom_t *this, int64_t pts_per_smpls);
/*
* called by video output driver for *every* frame
*
- * parameter pts: pts for frame if known, 0 otherwise
- * scr: system clock reference, may be 0 or == pts if unknown
+ * parameter frame containing pts, scr, ... information
*
- * return value: virtual pts for frame (interpolated if pts == 0)
+ * will set vpts field in frame
*
* this function will also update video_wrap_offset if a discontinuity
* is detected (read the comentaries below about discontinuities).
*
*/
- uint32_t (*got_video_frame) (metronom_t *this, uint32_t pts, uint32_t scr);
+ void (*got_video_frame) (metronom_t *this, vo_frame_t *frame);
/*
* called by audio output driver whenever audio samples are delivered to it
@@ -130,7 +99,8 @@ struct metronom_s {
*
*/
- uint32_t (*got_audio_samples) (metronom_t *this, uint32_t pts, uint32_t nsamples, uint32_t scr);
+ int64_t (*got_audio_samples) (metronom_t *this, int64_t pts,
+ int nsamples, int64_t scr);
/*
* called by SPU decoder whenever a packet is delivered to it
@@ -143,17 +113,17 @@ struct metronom_s {
* due to the lack of regularity on spu packets)
*/
- uint32_t (*got_spu_packet) (metronom_t *this, uint32_t pts, uint32_t duration,
- uint32_t scr);
+ int64_t (*got_spu_packet) (metronom_t *this, int64_t pts, int64_t duration,
+ int64_t scr);
/*
- * Tell metronom about discontinuities.
+ * tell metronom about discontinuities.
*
- * These functions are called due to a discontinuity detected at
+ * these functions are called due to a discontinuity detected at
* demux stage from SCR values. As SCR are not guarateed to happen with
* any regularity, we can not correct the xxx_wrap_offset right now.
*
- * We will instead prepare both audio and video to correct the
+ * we will instead prepare both audio and video to correct the
* discontinuity at the first new PTS value (got_video_frame or
* got_audio_samples). As we can predict with reasonably accuracy what
* the old PTS would have being the calculated wrap_offset should be
@@ -185,7 +155,7 @@ struct metronom_s {
* start metronom clock (no clock reset)
* at given pts
*/
- void (*start_clock) (metronom_t *this, uint32_t pts);
+ void (*start_clock) (metronom_t *this, int64_t pts);
/*
@@ -203,13 +173,13 @@ struct metronom_s {
/*
* get current clock value in vpts
*/
- uint32_t (*get_current_time) (metronom_t *this);
+ int64_t (*get_current_time) (metronom_t *this);
/*
* adjust master clock to external timer (e.g. audio hardware)
*/
- void (*adjust_clock) (metronom_t *this, uint32_t desired_pts);
+ void (*adjust_clock) (metronom_t *this, int64_t desired_pts);
/*
@@ -229,28 +199,24 @@ struct metronom_s {
* metronom internal stuff
*/
- uint32_t pts_per_frame;
- uint32_t pts_per_smpls;
+ int64_t pts_per_smpls;
- int32_t audio_pts_delta;
+ int64_t audio_pts_delta;
- uint32_t video_vpts;
- uint32_t spu_vpts;
- uint32_t audio_vpts;
+ int64_t video_vpts;
+ int64_t spu_vpts;
+ int64_t audio_vpts;
- int32_t video_wrap_offset;
- int32_t audio_wrap_offset;
+ int64_t video_wrap_offset;
+ int64_t audio_wrap_offset;
int wrap_diff_counter;
- uint32_t last_video_pts;
- uint32_t last_video_scr;
- int num_video_vpts_guessed;
+ int64_t last_video_pts;
- uint32_t last_audio_pts;
- uint32_t last_audio_scr;
+ int64_t last_audio_pts;
int num_audio_samples_guessed;
- int32_t av_offset;
+ int64_t av_offset;
scr_plugin_t* scr_master;
scr_plugin_t** scr_list;
@@ -259,29 +225,19 @@ struct metronom_s {
pthread_mutex_t lock;
int have_audio;
- int video_stream_starting;
- int video_stream_running;
- int audio_stream_starting;
- int audio_stream_running;
int video_discontinuity;
int video_discontinuity_count;
int audio_discontinuity;
int audio_discontinuity_count;
pthread_cond_t video_discontinuity_reached;
pthread_cond_t audio_discontinuity_reached;
- pthread_cond_t video_started;
- pthread_cond_t audio_started;
- pthread_cond_t video_ended;
- pthread_cond_t audio_ended;
- int frames_since_start;
- int avg_frame_duration;
};
metronom_t *metronom_init (int have_audio, void *xine);
/*
- * SCR plugins
+ * SCR (system clock reference) plugins
*/
struct scr_plugin_s
@@ -299,11 +255,11 @@ struct scr_plugin_s
int (*set_speed) (scr_plugin_t *this, int speed);
- void (*adjust) (scr_plugin_t *this, uint32_t vpts);
+ void (*adjust) (scr_plugin_t *this, int64_t vpts);
- void (*start) (scr_plugin_t *this, uint32_t start_vpts);
+ void (*start) (scr_plugin_t *this, int64_t start_vpts);
- uint32_t (*get_current) (scr_plugin_t *this);
+ int64_t (*get_current) (scr_plugin_t *this);
metronom_t *metronom;
};
diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c
index 6c0f1db43..d14467557 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.71 2002/01/25 00:35:46 f1rmb Exp $
+ * $Id: video_decoder.c,v 1.72 2002/02/09 07:13:24 guenter Exp $
*
*/
@@ -105,8 +105,8 @@ void *video_decoder_loop (void *this_gen) {
this->spu_finished = 0;
pthread_mutex_unlock (&this->finished_lock);
-
- this->metronom->video_stream_start (this->metronom);
+
+ this->metronom->expect_video_discontinuity (this->metronom);
break;
@@ -144,8 +144,6 @@ void *video_decoder_loop (void *this_gen) {
case BUF_CONTROL_END:
- this->metronom->video_stream_end (this->metronom);
-
if (this->cur_video_decoder_plugin) {
this->cur_video_decoder_plugin->close (this->cur_video_decoder_plugin);
this->cur_video_decoder_plugin = NULL;
@@ -184,15 +182,8 @@ void *video_decoder_loop (void *this_gen) {
break;
case BUF_CONTROL_DISCONTINUITY:
- printf ("video_decoder: BUF_CONTROL_DISCONTINUITY is deprecated\n");
- break;
-
- case BUF_CONTROL_AVSYNC_RESET:
printf ("video_decoder: discontinuity ahead\n");
- if (this->cur_video_decoder_plugin)
- this->cur_video_decoder_plugin->flush (this->cur_video_decoder_plugin);
-
this->video_in_discontinuity = 1;
this->metronom->expect_video_discontinuity (this->metronom);
@@ -200,14 +191,6 @@ void *video_decoder_loop (void *this_gen) {
this->video_in_discontinuity = 0;
break;
- case BUF_VIDEO_FILL:
- break;
-
- case BUF_CONTROL_FLUSH:
- if (this->cur_video_decoder_plugin)
- this->cur_video_decoder_plugin->flush (this->cur_video_decoder_plugin);
- break;
-
case BUF_CONTROL_AUDIO_CHANNEL:
{
xine_ui_event_t ui_event;
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 8f43d71ce..10a327045 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -17,8 +17,9 @@
* 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.70 2002/02/02 13:39:30 miguelfreitas Exp $
+ * $Id: video_out.c,v 1.71 2002/02/09 07:13:24 guenter Exp $
*
+ * frame allocation / queuing / scheduling / output functions
*/
#ifdef HAVE_CONFIG_H
@@ -34,6 +35,7 @@
#include <zlib.h>
#include "video_out.h"
+#include "metronom.h"
#include "xine_internal.h"
#include "xineutils.h"
@@ -57,12 +59,48 @@
}
#endif
-/*
+
#define VIDEO_OUT_LOG
-*/
#define NUM_FRAME_BUFFERS 15
+typedef struct {
+
+ vo_instance_t vo; /* public part */
+
+ vo_driver_t *driver;
+ metronom_t *metronom;
+ xine_t *xine;
+
+ img_buf_fifo_t *free_img_buf_queue;
+ img_buf_fifo_t *display_img_buf_queue;
+
+ vo_frame_t *last_frame;
+ vo_frame_t *img_backup;
+ int backup_is_logo;
+
+ int video_loop_running;
+ int video_opened;
+ pthread_t video_thread;
+
+ int num_frames_delivered;
+ int num_frames_skipped;
+ int num_frames_discarded;
+
+ /* pts value when decoder delivered last video frame */
+ int64_t last_delivery_pts;
+
+ int logo_w, logo_h;
+ uint8_t *logo_yuy2;
+
+ video_overlay_instance_t *overlay_source;
+ int overlay_enabled;
+} vos_t;
+
+/*
+ * frame queue (fifo) util functions
+ */
+
struct img_buf_fifo_s {
vo_frame_t *first;
vo_frame_t *last;
@@ -144,439 +182,521 @@ static vo_frame_t *vo_remove_from_img_buf_queue (img_buf_fifo_t *queue) {
return img;
}
-static void vo_set_timer (uint32_t video_step) {
- struct itimerval tval;
-
- tval.it_interval.tv_sec = 0;
- tval.it_interval.tv_usec = video_step*100000/90000;
- tval.it_value.tv_sec = 0;
- tval.it_value.tv_usec = video_step*100000/90000;
-
- if (setitimer(ITIMER_REAL, &tval, NULL)) {
- printf ("vo_set_timer: setitimer failed :");
- }
-}
+/*
+ * function called by video output driver
+ */
-void video_timer_handler (int hubba) {
-#if !HAVE_SIGACTION
- signal (SIGALRM, video_timer_handler);
-#endif
-}
+static void vo_frame_displayed (vo_frame_t *img) {
-/* send a buf to force video_decoder->flush */
-static void video_out_send_decoder_flush( fifo_buffer_t *video_fifo ) {
- buf_element_t *buf;
+ pthread_mutex_lock (&img->mutex);
- if( !video_fifo )
- return;
-
- buf = video_fifo->buffer_pool_alloc (video_fifo);
-
- buf->type = BUF_CONTROL_FLUSH ;
- buf->PTS = 0;
- buf->SCR = 0;
- buf->input_pos = 0;
- buf->input_time = 0;
+ img->driver_locked = 0;
- video_fifo->put (video_fifo, buf);
+ if (!img->decoder_locked) {
+ vos_t *this = (vos_t *) img->instance;
+ vo_append_to_img_buf_queue (this->free_img_buf_queue, img);
+ }
+ pthread_mutex_unlock (&img->mutex);
}
-static vo_frame_t *vo_get_frame (vo_instance_t *this,
+/*
+ *
+ * functions called by video decoder:
+ *
+ * get_frame => alloc frame for rendering
+ *
+ * frame_draw=> queue finished frame for display
+ *
+ * frame_free=> frame no longer used as reference frame by decoder
+ *
+ */
+
+static vo_frame_t *vo_get_frame (vo_instance_t *this_gen,
uint32_t width, uint32_t height,
- int ratio, int format, uint32_t duration,
+ int ratio, int format,
int flags) {
vo_frame_t *img;
+ vos_t *this = (vos_t *) this_gen;
- /*
- printf ("video_out : get_frame %d x %d from queue %d\n",
- width, height, this->free_img_buf_queue);
- fflush(stdout);
- */
-
- if (this->pts_per_frame != duration) {
- this->pts_per_frame = duration;
- this->pts_per_half_frame = duration / 2;
- this->metronom->set_video_rate (this->metronom, duration);
- }
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: get_frame (%d x %d)\n", width, height);
+#endif
img = vo_remove_from_img_buf_queue (this->free_img_buf_queue);
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: got a frame -> pthread_mutex_lock (&img->mutex)\n");
+#endif
+
pthread_mutex_lock (&img->mutex);
img->display_locked = 0;
img->decoder_locked = 1;
img->driver_locked = 0;
- img->width = width;
- img->height = height;
- img->ratio = ratio;
- img->format = format;
- img->duration = duration;
- img->drawn = 0;
+ img->width = width;
+ img->height = height;
+ img->ratio = ratio;
+ img->format = format;
/* let driver ensure this image has the right format */
- this->driver->update_frame_format (this->driver, img, width, height, ratio, format, flags);
+ this->driver->update_frame_format (this->driver, img, width, height,
+ ratio, format, flags);
pthread_mutex_unlock (&img->mutex);
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: get_frame (%d x %d) done\n", width, height);
+#endif
+
return img;
}
-static void *video_out_loop (void *this_gen) {
+static int vo_frame_draw (vo_frame_t *img) {
- uint32_t cur_pts;
- int diff, absdiff, pts=0;
- vo_frame_t *img, *img_backup;
- int backup_is_logo = 0;
- uint32_t video_step, video_step_new;
- vo_instance_t *this = (vo_instance_t *) this_gen;
- static int prof_video_out = -1;
- static int prof_spu_blend = -1;
- sigset_t vo_mask;
-
- int flush_sent = 0;
+ vos_t *this = (vos_t *) img->instance;
+ int64_t diff;
+ int64_t cur_vpts;
+ int64_t pic_vpts ;
+ int frames_to_skip;
- /* printf ("%d video_out start\n", getpid()); */
+ this->metronom->got_video_frame (this->metronom, img);
- if (prof_video_out == -1)
- prof_video_out = xine_profiler_allocate_slot ("video output");
- if (prof_spu_blend == -1)
- prof_spu_blend = xine_profiler_allocate_slot ("spu blend");
+ pic_vpts = img->vpts;
- img_backup = NULL;
- this->last_draw_vpts = 0;
-
- /*
- * set up timer signal
- */
-
- sigemptyset(&vo_mask);
- sigaddset(&vo_mask, SIGALRM);
- if (sigprocmask (SIG_UNBLOCK, &vo_mask, NULL)) {
- LOG_MSG(this->xine, _("video_out: sigprocmask failed.\n"));
- }
-#if HAVE_SIGACTION
- {
- struct sigaction sig_act;
- memset (&sig_act, 0, sizeof(sig_act));
- sig_act.sa_handler = video_timer_handler;
- sigaction (SIGALRM, &sig_act, NULL);
- }
-#else
- signal (SIGALRM, video_timer_handler);
-#endif
+ cur_vpts = this->metronom->get_current_time(this->metronom);
+ this->last_delivery_pts = cur_vpts;
- video_step = this->metronom->get_video_rate (this->metronom);
- vo_set_timer (video_step);
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: got image at master vpts %lld. vpts for picture is %lld (pts was %lld)\n",
+ cur_vpts, pic_vpts, pic_vpts);
+#endif
- /*
- * here it is - the big video output loop
- */
+ this->num_frames_delivered++;
- while ( this->video_loop_running ) {
+ diff = pic_vpts - cur_vpts;
+ frames_to_skip = ((-1 * diff) / img->duration + 3) * 2;
- /*
- * wait until it's time to display a frame
- */
-
- pause ();
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: delivery diff : %lld, current vpts is %lld\n",
+ diff, cur_vpts);
+#endif
- video_step_new = this->metronom->get_video_rate (this->metronom);
- if (video_step_new != video_step) {
- video_step = video_step_new;
-
- vo_set_timer (video_step);
- }
-
- /*
- * now, look at the frame queue and decide which frame to display
- * or generate still frames if no frames are available
- */
+ if (img->display_locked) {
+ printf ("video_out: ALERT! frame is already locked for displaying\n");
+ return frames_to_skip;
+ }
- xine_profiler_start_count (prof_video_out);
+ if (cur_vpts>0) {
- cur_pts = this->metronom->get_current_time (this->metronom);
+ if (diff<(-1 * img->duration) && img->drawn != 2 ) {
+ this->num_frames_discarded++;
#ifdef VIDEO_OUT_LOG
- printf ("video_out : video loop iteration at audio pts %d\n", cur_pts);
+ printf ("video_out: frame rejected, %d frames to skip\n", frames_to_skip);
#endif
-
- img = this->display_img_buf_queue->first;
- /* update timer for inactivity flush */
- if( img ) {
- this->last_draw_vpts = cur_pts;
- } else {
- /* start timer when decoder receives the first packet */
- if( !this->last_draw_vpts && this->decoder_started_flag )
- this->last_draw_vpts = cur_pts;
-
- if( this->last_draw_vpts && (cur_pts - this->last_draw_vpts) > (8 * this->pts_per_frame) ) {
-#ifdef VIDEO_OUT_LOG
- printf("video_out : sending decoder flush due to inactivity\n");
-#endif
- video_out_send_decoder_flush( this->xine->video_fifo );
- this->last_draw_vpts = cur_pts;
- flush_sent = 1;
- }
+ pthread_mutex_lock (&img->mutex);
+ img->display_locked = 0;
+ pthread_mutex_unlock (&img->mutex);
+
+ vo_frame_displayed (img);
+
+ this->last_frame = img;
+
+ return frames_to_skip;
+
}
-
-
+ } /* else: we are probably in precaching mode */
+
+ if (!img->bad_frame) {
/*
- * throw away expired frames
+ * put frame into FIFO-Buffer
*/
- diff = 1000000;
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: frame is ok => appending to display buffer\n");
+#endif
+
+ this->last_frame = img;
+
+ pthread_mutex_lock (&img->mutex);
+ img->display_locked = 1;
+ pthread_mutex_unlock (&img->mutex);
+
+ vo_append_to_img_buf_queue (this->display_img_buf_queue, img);
+
+ } else {
+ this->num_frames_skipped++;
+
+ pthread_mutex_lock (&img->mutex);
+ img->display_locked = 0;
+ pthread_mutex_unlock (&img->mutex);
+
+ vo_frame_displayed (img);
+ }
+
+ /*
+ * performance measurement
+ */
+
+ if (this->num_frames_delivered>199) {
+ LOG_MSG_STDERR(this->xine,
+ _("%d frames delivered, %d frames skipped, %d frames discarded\n"),
+ this->num_frames_delivered,
+ this->num_frames_skipped, this->num_frames_discarded);
+
+ this->num_frames_delivered = 0;
+ this->num_frames_discarded = 0;
+ this->num_frames_skipped = 0;
+ }
+
+ return frames_to_skip;
+}
+
+static void vo_frame_free (vo_frame_t *img) {
+
+ pthread_mutex_lock (&img->mutex);
+ img->decoder_locked = 0;
+
+ if (!img->display_locked && !img->driver_locked ) {
+ vos_t *this = (vos_t *) img->instance;
+ vo_append_to_img_buf_queue (this->free_img_buf_queue, img);
+ }
+
+ pthread_mutex_unlock (&img->mutex);
+}
+
+
+
+/*
+ *
+ * video out loop related functions
+ *
+ */
+
+static void expire_frames (vos_t *this, int64_t cur_vpts) {
+
+ int64_t pts;
+ int64_t diff;
+ vo_frame_t *img;
+
+ img = this->display_img_buf_queue->first;
+
+ /*
+ * throw away expired frames
+ */
+
+ diff = 1000000; /* always enter the while-loop */
- while (img && (diff >this->pts_per_half_frame)) {
- pts = img->PTS;
- diff = cur_pts - pts;
- absdiff = abs(diff);
+ while (img && (diff > img->duration)) {
+ pts = img->vpts;
+ diff = cur_vpts - pts;
- if (diff >this->pts_per_half_frame) {
- LOG_MSG(this->xine, _("video_out : throwing away image with pts %d because "
- "it's too old (diff : %d > %d).\n"),
- pts, diff, this->pts_per_half_frame);
+ if (diff > img->duration) {
+ LOG_MSG(this->xine,
+ _("video_out: throwing away image with pts %lld because "
+ "it's too old (diff : %lld).\n"), pts, diff);
- this->num_frames_discarded++;
+ this->num_frames_discarded++;
- img = vo_remove_from_img_buf_queue (this->display_img_buf_queue);
+ img = vo_remove_from_img_buf_queue (this->display_img_buf_queue);
- /*
- * last frame? back it up for
- * still frame creation
- */
+ /*
+ * last frame? back it up for
+ * still frame creation
+ */
- if (!this->display_img_buf_queue->first) {
+ if (!this->display_img_buf_queue->first) {
- if (img_backup) {
- pthread_mutex_lock (&img_backup->mutex);
+ if (this->img_backup) {
+ pthread_mutex_lock (&this->img_backup->mutex);
#ifdef VIDEO_OUT_LOG
- printf("video_out : overwriting frame backup\n");
+ printf("video_out: overwriting frame backup\n");
#endif
- img_backup->display_locked = 0;
- if (!img->decoder_locked)
- vo_append_to_img_buf_queue (this->free_img_buf_queue, img_backup);
-
- pthread_mutex_unlock (&img_backup->mutex);
- }
- printf("video_out : possible still frame (old)\n");
- flush_sent = 0;
-
- /* we must not clear display_locked from img_backup.
- without it decoder may try to free our backup. */
- img_backup = img;
- backup_is_logo = 0;
- } else {
- pthread_mutex_lock (&img->mutex);
-
- img->display_locked = 0;
+ this->img_backup->display_locked = 0;
if (!img->decoder_locked)
- vo_append_to_img_buf_queue (this->free_img_buf_queue, img);
-
- pthread_mutex_unlock (&img->mutex);
+ vo_append_to_img_buf_queue (this->free_img_buf_queue,
+ this->img_backup);
+
+ pthread_mutex_unlock (&this->img_backup->mutex);
}
-
- img = this->display_img_buf_queue->first;
+ printf("video_out: possible still frame (old)\n");
+
+ /* we must not clear display_locked from img_backup.
+ without it decoder may try to free our backup. */
+ this->img_backup = img;
+ this->backup_is_logo = 0;
+ } else {
+ pthread_mutex_lock (&img->mutex);
+
+ img->display_locked = 0;
+ if (!img->decoder_locked)
+ vo_append_to_img_buf_queue (this->free_img_buf_queue, img);
+
+ pthread_mutex_unlock (&img->mutex);
}
- }
+
+ img = this->display_img_buf_queue->first;
+ }
+ }
- /*
- * still frame detection:
- */
+}
+
+static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts) {
+
+ vo_frame_t *img;
+
+ img = this->display_img_buf_queue->first;
+
+ /*
+ * still frame detection:
+ */
- /* no frame? => still frame detection */
+ /* no frame? => still frame detection */
- if (!img) {
+ if (!img) {
#ifdef VIDEO_OUT_LOG
- printf ("video_out : no frame\n");
+ printf ("video_out: no frame\n");
#endif
- /*
- * display logo ?
- */
- if (!this->video_opened && (!img_backup || !backup_is_logo)) {
+ /*
+ * display logo ?
+ */
+ if (!this->video_opened && (!this->img_backup || !this->backup_is_logo)) {
- if (img_backup) {
- pthread_mutex_lock (&img_backup->mutex);
+ if (this->img_backup) {
+ pthread_mutex_lock (&this->img_backup->mutex);
#ifdef VIDEO_OUT_LOG
- printf("video_out : overwriting frame backup\n");
+ printf("video_out: overwriting frame backup\n");
#endif
- img_backup->display_locked = 0;
- if (!img_backup->decoder_locked)
- vo_append_to_img_buf_queue (this->free_img_buf_queue, img_backup);
+ this->img_backup->display_locked = 0;
+ if (!this->img_backup->decoder_locked)
+ vo_append_to_img_buf_queue (this->free_img_buf_queue,
+ this->img_backup);
- pthread_mutex_unlock (&img_backup->mutex);
- }
+ pthread_mutex_unlock (&this->img_backup->mutex);
+ }
- printf("video_out : copying logo image\n");
+ printf("video_out: copying logo image\n");
- img_backup = vo_get_frame (this, this->logo_w, this->logo_h,
- 42, IMGFMT_YUY2, 6000, VO_BOTH_FIELDS);
-
- img_backup->decoder_locked = 0;
- img_backup->display_locked = 1;
- img_backup->driver_locked = 0;
-
- xine_fast_memcpy(img_backup->base[0], this->logo_yuy2,
- this->logo_w*this->logo_h*2);
-
- /* this shouldn't be needed, duplicate_frame will call
- img->copy for us. [mf]
- if (img_backup->copy) {
- int height = this->logo_h;
- int stride = this->logo_w;
- uint8_t* src[3];
-
- src[0] = img_backup->base[0];
-
- while ((height -= 16) >= 0) {
- img_backup->copy(img_backup, src);
- src[0] += 32 * stride;
- }
- }
- */
-
- backup_is_logo = 1;
- }
+ this->img_backup = vo_get_frame (&this->vo, this->logo_w, this->logo_h,
+ 42, IMGFMT_YUY2, VO_BOTH_FIELDS);
+ this->img_backup->decoder_locked = 0;
+ this->img_backup->display_locked = 1;
+ this->img_backup->driver_locked = 0;
+ this->img_backup->duration = 10000;
- if (img_backup) {
+ xine_fast_memcpy(this->img_backup->base[0], this->logo_yuy2,
+ this->logo_w*this->logo_h*2);
- /*
- * wait until it's time to display this still frame
- */
- pts = this->metronom->get_current_time (this->metronom);
- do {
- xine_usec_sleep ( 10000 );
- cur_pts = this->metronom->get_current_time (this->metronom);
- /* using abs will avoid problems if metronom gets updated */
- diff = abs(cur_pts - pts);
-
- } while (diff < 2 * this->pts_per_frame) ;
+ this->backup_is_logo = 1;
+ }
- /* if some frame arrived dont generate still */
- if( this->display_img_buf_queue->first ) {
- xine_profiler_stop_count (prof_video_out);
- continue;
- }
+ if (this->img_backup) {
#ifdef VIDEO_OUT_LOG
- printf("video_out : generating still frame (cur_pts = %d) \n", cur_pts);
+ printf("video_out: generating still frame (cur_vpts = %lld) \n",
+ cur_vpts);
#endif
- /* keep playing still frames */
- img = this->duplicate_frame( this, img_backup );
- img->display_locked = 1;
+ /* keep playing still frames */
+ img = this->vo.duplicate_frame (&this->vo, this->img_backup );
+ img->display_locked = 1;
- img->PTS = cur_pts;
- diff = 0;
+ do {
+ this->metronom->got_video_frame(this->metronom, img);
+ } while (img->vpts < cur_vpts);
- } else {
+ return img;
+
+ } else {
#ifdef VIDEO_OUT_LOG
- printf ("video_out : no frame, but no backup frame\n");
+ printf ("video_out: no frame, but no backup frame\n");
#endif
- xine_profiler_stop_count (prof_video_out);
- continue;
- }
- } else {
+ return NULL;
+ }
+ } else {
- /*
- * time to display frame >img< ?
- */
+ int64_t diff;
+
+ diff = cur_vpts - img->vpts;
+
+ /*
+ * time to display frame "img" ?
+ */
#ifdef VIDEO_OUT_LOG
- printf ("video_out : diff %d\n", diff);
+ printf ("video_out: diff %lld\n", diff);
#endif
- if (diff<0) {
- xine_profiler_stop_count (prof_video_out);
- continue;
- }
+ if (diff < 0) {
+ return 0;
+ }
- if (img_backup) {
- pthread_mutex_lock (&img_backup->mutex);
- printf("video_out : freeing frame backup\n");
+ if (this->img_backup) {
+ pthread_mutex_lock (&this->img_backup->mutex);
+ printf("video_out: freeing frame backup\n");
- img_backup->display_locked = 0;
- if( !img_backup->decoder_locked )
- vo_append_to_img_buf_queue (this->free_img_buf_queue, img_backup);
- pthread_mutex_unlock (&img_backup->mutex);
- img_backup = NULL;
- }
+ this->img_backup->display_locked = 0;
+ if( !this->img_backup->decoder_locked )
+ vo_append_to_img_buf_queue (this->free_img_buf_queue,
+ this->img_backup);
+ pthread_mutex_unlock (&this->img_backup->mutex);
+ this->img_backup = NULL;
+ }
- /*
- * last frame? make backup for possible still image
- */
- if (img && !img->next &&
- (this->xine->video_fifo->size(this->xine->video_fifo) < 10 ||
- flush_sent || this->xine->video_in_discontinuity) ) {
+ /*
+ * last frame? make backup for possible still image
+ */
+ if (img && !img->next &&
+ (this->xine->video_fifo->size(this->xine->video_fifo) < 10
+ || this->xine->video_in_discontinuity) ) {
- printf("video_out : possible still frame (fifosize = %d, flushsent=%d)\n",
- this->xine->video_fifo->size(this->xine->video_fifo), flush_sent);
+ printf ("video_out: possible still frame (fifosize = %d)\n",
+ this->xine->video_fifo->size(this->xine->video_fifo));
- img_backup = this->duplicate_frame(this, img);
- backup_is_logo = 0;
- }
+ this->img_backup = this->vo.duplicate_frame (&this->vo, img);
+ this->backup_is_logo = 0;
+ }
- flush_sent = 0;
-
- /*
- * remove frame from display queue and show it
- */
+ /*
+ * remove frame from display queue and show it
+ */
- img = vo_remove_from_img_buf_queue (this->display_img_buf_queue);
+ img = vo_remove_from_img_buf_queue (this->display_img_buf_queue);
- if (!img) {
- xine_profiler_stop_count (prof_video_out);
- continue;
- }
- }
+ return img;
+ }
+}
+
+static void overlay_and_display_frame (vos_t *this,
+ vo_frame_t *img) {
+
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: displaying image with vpts = %lld\n",
+ img->vpts);
+#endif
+
+ pthread_mutex_lock (&img->mutex);
+ img->driver_locked = 1;
+
+#ifdef VIDEO_OUT_LOG
+ if (!img->display_locked)
+ printf ("video_out: ALERT! frame was not locked for display queue\n");
+#endif
+
+ img->display_locked = 0;
+ pthread_mutex_unlock (&img->mutex);
+
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: passing to video driver image with pts = %lld\n",
+ img->vpts);
+#endif
+
+ if (this->overlay_source) {
+ /* This is the only way for the overlay manager to get pts values
+ * for flushing its buffers. So don't remove it! */
+
+ this->overlay_source->multiple_overlay_blend (this->overlay_source,
+ img->vpts,
+ this->driver, img,
+ this->video_loop_running && this->overlay_enabled);
+ }
+
+ this->driver->display_frame (this->driver, img);
+}
+
+static void *video_out_loop (void *this_gen) {
+
+ int64_t vpts, diff;
+ vo_frame_t *img;
+ vos_t *this = (vos_t *) this_gen;
+ int64_t frame_duration, next_frame_pts;
+ int64_t usec_to_sleep;
+
+ /*
+ * here it is - the heart of xine (or rather: one of the hearts
+ * of xine) : the video output loop
+ */
+
+ frame_duration = 1500; /* default */
+ next_frame_pts = 0;
+
+#ifdef VIDEO_OUT_LOG
+ printf ("video_out: loop starting...\n");
+#endif
+
+ while ( this->video_loop_running ) {
/*
- * from this point on, img must be a valid frame for
- * overlay and output
+ * get current time and find frame to display
*/
+ vpts = this->metronom->get_current_time (this->metronom);
#ifdef VIDEO_OUT_LOG
- printf ("video_out : displaying image with pts = %d (diff=%d)\n", pts, diff);
+ printf ("video_out: loop iteration at %lld\n", vpts);
#endif
+ expire_frames (this, vpts);
+ img = get_next_frame (this, vpts);
- pthread_mutex_lock (&img->mutex);
- img->driver_locked = 1;
+ /*
+ * if we have found a frame, display it
+ */
+
+ if (img)
+ overlay_and_display_frame (this, img);
+
+ /*
+ * if we haven't heared from the decoder for some time
+ * flush it
+ */
+
+ diff = vpts - this->last_delivery_pts;
+ if (diff > 30000) {
+ if (this->xine->cur_video_decoder_plugin) {
+ this->xine->cur_video_decoder_plugin->flush(this->xine->cur_video_decoder_plugin);
#ifdef VIDEO_OUT_LOG
- if (!img->display_locked)
- printf ("video_out : ALERT! frame was not locked for display queue\n");
+ printf ("video_out: flushing current video decoder plugin\n");
#endif
- img->display_locked = 0;
- pthread_mutex_unlock (&img->mutex);
+ }
+ }
+
+ /*
+ * wait until it's time to display next frame
+ */
+
+ if (img)
+ frame_duration = img->duration;
+
+ next_frame_pts += frame_duration;
#ifdef VIDEO_OUT_LOG
- printf ("video_out : passing to video driver, image with pts = %d\n", pts);
+ printf ("video_out: next_frame_pts is %lld\n", next_frame_pts);
#endif
+
+ do {
+ vpts = this->metronom->get_current_time (this->metronom);
- if (this->overlay_source) {
- /* This is the only way for the overlay manager to get pts values
- * for flushing it's buffers. So don't remove it! */
- xine_profiler_start_count (prof_spu_blend);
+ usec_to_sleep = (next_frame_pts - vpts) * 100 / 9;
- this->overlay_source->multiple_overlay_blend (this->overlay_source, img->PTS,
- this->driver, img,
- this->video_loop_running && this->overlay_enabled);
- xine_profiler_stop_count (prof_spu_blend);
- }
-
- this->driver->display_frame (this->driver, img);
+ printf ("video_out: %lld usec to sleep at master vpts %lld\n",
+ usec_to_sleep, vpts);
+
+ if (usec_to_sleep>0)
+ xine_usec_sleep (usec_to_sleep);
- xine_profiler_stop_count (prof_video_out);
+ } while (usec_to_sleep > 0);
}
+
/*
* throw away undisplayed frames
*/
@@ -596,29 +716,32 @@ static void *video_out_loop (void *this_gen) {
img = this->display_img_buf_queue->first;
}
- if( img_backup ) {
- pthread_mutex_lock (&img_backup->mutex);
+ if (this->img_backup) {
+ pthread_mutex_lock (&this->img_backup->mutex);
- img_backup->display_locked = 0;
- if( !img_backup->decoder_locked )
- vo_append_to_img_buf_queue (this->free_img_buf_queue, img_backup);
+ this->img_backup->display_locked = 0;
+ if (!this->img_backup->decoder_locked)
+ vo_append_to_img_buf_queue (this->free_img_buf_queue, this->img_backup);
- pthread_mutex_unlock (&img_backup->mutex);
+ pthread_mutex_unlock (&this->img_backup->mutex);
}
pthread_exit(NULL);
}
-static uint32_t vo_get_capabilities (vo_instance_t *this) {
+static uint32_t vo_get_capabilities (vo_instance_t *this_gen) {
+ vos_t *this = (vos_t *) this_gen;
return this->driver->get_capabilities (this->driver);
}
-static vo_frame_t * vo_duplicate_frame( vo_instance_t *this, vo_frame_t *img ) {
+static vo_frame_t * vo_duplicate_frame( vo_instance_t *this_gen, vo_frame_t *img ) {
+
vo_frame_t *dupl;
- int image_size;
+ /* vos_t *this = (vos_t *) this_gen; */
+ int image_size;
- dupl = vo_get_frame( this, img->width, img->height, img->ratio,
- img->format, img->duration, VO_BOTH_FIELDS );
+ dupl = vo_get_frame (this_gen, img->width, img->height, img->ratio,
+ img->format, VO_BOTH_FIELDS );
pthread_mutex_lock (&dupl->mutex);
@@ -643,7 +766,10 @@ static vo_frame_t * vo_duplicate_frame( vo_instance_t *this, vo_frame_t *img ) {
}
dupl->bad_frame = 0;
- dupl->PTS = dupl->SCR = 0;
+ dupl->pts = 0;
+ dupl->vpts = 0;
+ dupl->scr = 0;
+ dupl->duration = img->duration;
/* Support copy; Dangerous, since some decoders may use a source that's
* not dupl->base. It's up to the copy implementation to check for NULL */
@@ -683,14 +809,18 @@ static vo_frame_t * vo_duplicate_frame( vo_instance_t *this, vo_frame_t *img ) {
return dupl;
}
-static void vo_open (vo_instance_t *this) {
+static void vo_open (vo_instance_t *this_gen) {
+
+ vos_t *this = (vos_t *) this_gen;
- this->decoder_started_flag = 0;
this->video_opened = 1;
+ this->last_delivery_pts = 0;
}
-static void vo_close (vo_instance_t *this) {
-
+static void vo_close (vo_instance_t *this_gen) {
+
+ vos_t *this = (vos_t *) this_gen;
+
/* this will make sure all hide events were processed */
if (this->overlay_source)
this->overlay_source->flush_events (this->overlay_source);
@@ -698,7 +828,8 @@ static void vo_close (vo_instance_t *this) {
this->video_opened = 0;
}
-static void vo_free_img_buffers (vo_instance_t *this) {
+static void vo_free_img_buffers (vo_instance_t *this_gen) {
+ vos_t *this = (vos_t *) this_gen;
vo_frame_t *img;
while (this->free_img_buf_queue->first) {
@@ -712,163 +843,45 @@ static void vo_free_img_buffers (vo_instance_t *this) {
}
}
-static void vo_exit (vo_instance_t *this) {
+static void vo_exit (vo_instance_t *this_gen) {
+
+ vos_t *this = (vos_t *) this_gen;
printf ("video_out: vo_exit...\n");
if (this->video_loop_running) {
void *p;
this->video_loop_running = 0;
- this->video_paused = 0;
pthread_join (this->video_thread, &p);
}
- vo_free_img_buffers (this);
+ vo_free_img_buffers (this_gen);
this->driver->exit (this->driver);
printf ("video_out: vo_exit... done\n");
}
-static void vo_frame_displayed (vo_frame_t *img) {
-
- pthread_mutex_lock (&img->mutex);
-
- img->driver_locked = 0;
-
- if (!img->decoder_locked) {
- vo_append_to_img_buf_queue (img->instance->free_img_buf_queue, img);
- }
-
- pthread_mutex_unlock (&img->mutex);
-}
-
-static void vo_frame_free (vo_frame_t *img) {
-
- pthread_mutex_lock (&img->mutex);
- img->decoder_locked = 0;
-
- if (!img->display_locked && !img->driver_locked ) {
- vo_append_to_img_buf_queue (img->instance->free_img_buf_queue, img);
- }
-
- pthread_mutex_unlock (&img->mutex);
-}
-
-static vo_frame_t *vo_get_last_frame (vo_instance_t *this) {
+static vo_frame_t *vo_get_last_frame (vo_instance_t *this_gen) {
+ vos_t *this = (vos_t *) this_gen;
return this->last_frame;
}
-static int vo_frame_draw (vo_frame_t *img) {
-
- vo_instance_t *this = img->instance;
- int32_t diff;
- uint32_t cur_vpts;
- uint32_t pic_vpts ;
- int frames_to_skip;
-
- pic_vpts = this->metronom->got_video_frame (this->metronom, img->PTS, img->SCR);
-
-#ifdef VIDEO_OUT_LOG
- printf ("video_out : got image %d. vpts for picture is %d (pts was %d)\n",
- img, pic_vpts, img->PTS);
-#endif
-
- img->PTS = pic_vpts;
- this->num_frames_delivered++;
-
- cur_vpts = this->metronom->get_current_time(this->metronom);
- this->last_draw_vpts = cur_vpts;
-
- diff = pic_vpts - cur_vpts;
- frames_to_skip = ((-1 * diff) / this->pts_per_frame + 3) * 2;
-
-#ifdef VIDEO_OUT_LOG
- printf ("video_out : delivery diff : %d\n",diff);
-#endif
-
- if (img->display_locked) {
- LOG_MSG(this->xine, _("video_out : ALERT! frame is already locked for displaying\n"));
- return frames_to_skip;
- }
-
- if (cur_vpts>0) {
-
- if (diff<(-1 * this->pts_per_half_frame) && img->drawn != 2 ) {
-
- this->num_frames_discarded++;
-#ifdef VIDEO_OUT_LOG
- printf ("video_out : frame rejected, %d frames to skip\n", frames_to_skip);
-#endif
-
- LOG_MSG(this->xine, _("video_out: rejected, %d frames to skip\n"), frames_to_skip);
-
- pthread_mutex_lock (&img->mutex);
- img->display_locked = 0;
- pthread_mutex_unlock (&img->mutex);
-
- vo_frame_displayed (img);
-
- this->last_frame = img;
-
- return frames_to_skip;
-
- }
- } /* else: we are probably in precaching mode */
-
- if (!img->bad_frame) {
- /*
- * put frame into FIFO-Buffer
- */
-
-#ifdef VIDEO_OUT_LOG
- printf ("video_out : frame is ok => appending to display buffer\n");
-#endif
-
- this->last_frame = img;
-
- pthread_mutex_lock (&img->mutex);
- img->display_locked = 1;
- pthread_mutex_unlock (&img->mutex);
-
- vo_append_to_img_buf_queue (this->display_img_buf_queue, img);
-
- } else {
- this->num_frames_skipped++;
-
- pthread_mutex_lock (&img->mutex);
- img->display_locked = 0;
- pthread_mutex_unlock (&img->mutex);
-
- vo_frame_displayed (img);
- }
-
- /*
- * performance measurement
- */
-
- if (this->num_frames_delivered>199) {
- LOG_MSG_STDERR(this->xine,
- _("%d frames delivered, %d frames skipped, %d frames discarded\n"),
- this->num_frames_delivered, this->num_frames_skipped, this->num_frames_discarded);
+/*
+ * overlay stuff
+ */
- this->num_frames_delivered = 0;
- this->num_frames_discarded = 0;
- this->num_frames_skipped = 0;
- }
-
- return frames_to_skip;
+static video_overlay_instance_t *vo_get_overlay_instance (vo_instance_t *this_gen) {
+ vos_t *this = (vos_t *) this_gen;
+ return this->overlay_source;
}
-static void vo_enable_overlay (vo_instance_t *this, int overlay_enabled) {
+static void vo_enable_overlay (vo_instance_t *this_gen, int overlay_enabled) {
+ vos_t *this = (vos_t *) this_gen;
this->overlay_enabled = overlay_enabled;
}
-static void vo_decoder_started (vo_instance_t *this) {
- this->decoder_started_flag = 1;
-}
-
static uint16_t gzread_i16(gzFile *fp) {
uint16_t ret;
ret = gzgetc(fp) << 8 ;
@@ -880,28 +893,28 @@ static uint16_t gzread_i16(gzFile *fp) {
vo_instance_t *vo_new_instance (vo_driver_t *driver, xine_t *xine) {
- vo_instance_t *this;
+ vos_t *this;
int i;
char pathname[LOGO_PATH_MAX];
pthread_attr_t pth_attrs;
int err;
gzFile *fp;
+ this = xine_xmalloc (sizeof (vos_t)) ;
- this = xine_xmalloc (sizeof (vo_instance_t)) ;
this->driver = driver;
this->xine = xine;
this->metronom = xine->metronom;
- this->open = vo_open;
- this->get_frame = vo_get_frame;
- this->duplicate_frame = vo_duplicate_frame;
- this->get_last_frame = vo_get_last_frame;
- this->close = vo_close;
- this->exit = vo_exit;
- this->get_capabilities = vo_get_capabilities;
- this->enable_ovl = vo_enable_overlay;
- this->decoder_started = vo_decoder_started;
+ this->vo.open = vo_open;
+ this->vo.get_frame = vo_get_frame;
+ this->vo.duplicate_frame = vo_duplicate_frame;
+ this->vo.get_last_frame = vo_get_last_frame;
+ this->vo.close = vo_close;
+ this->vo.exit = vo_exit;
+ this->vo.get_capabilities = vo_get_capabilities;
+ this->vo.enable_ovl = vo_enable_overlay;
+ this->vo.get_overlay_instance = vo_get_overlay_instance;
this->num_frames_delivered = 0;
this->num_frames_skipped = 0;
@@ -909,9 +922,9 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, xine_t *xine) {
this->free_img_buf_queue = vo_new_img_buf_queue ();
this->display_img_buf_queue = vo_new_img_buf_queue ();
this->video_loop_running = 0;
- this->video_paused = 0;
- this->pts_per_frame = 6000;
- this->pts_per_half_frame = 3000;
+
+ this->img_backup = NULL;
+ this->backup_is_logo = 0;
this->overlay_source = video_overlay_new_instance();
this->overlay_source->init (this->overlay_source);
@@ -922,7 +935,7 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, xine_t *xine) {
img = driver->alloc_frame (driver) ;
- img->instance = this;
+ img->instance = &this->vo;
img->free = vo_frame_free ;
img->displayed = vo_frame_displayed;
img->draw = vo_frame_draw;
@@ -961,7 +974,6 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, xine_t *xine) {
*/
this->video_loop_running = 1;
- this->decoder_started_flag = 0;
this->video_opened = 0;
pthread_attr_init(&pth_attrs);
@@ -976,10 +988,7 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, xine_t *xine) {
printf (_("video_out: sorry, this should not happen. please restart xine.\n"));
exit(1);
} else
- LOG_MSG(this->xine, _("video_out : thread created\n"));
+ LOG_MSG(this->xine, _("video_out: thread created\n"));
- return this;
+ return &this->vo;
}
-
-
-
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index 7738e8ad8..a75547236 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2001 the xine project
+ * Copyright (C) 2000-2002 the xine project
*
* This file is part of xine, a free video player.
*
@@ -17,11 +17,19 @@
* 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.39 2002/01/24 23:09:54 guenter Exp $
+ * $Id: video_out.h,v 1.40 2002/02/09 07:13:24 guenter Exp $
*
*
* xine version of video_out.h
*
+ * vo_frame : frame containing yuv data and timing info,
+ * transferred between video_decoder and video_output
+ *
+ * vo_driver : lowlevel, platform-specific video output code
+ *
+ * vo_instance : generic frame_handling code, uses
+ * a vo_driver for output
+ *
*/
#ifndef HAVE_VIDEO_OUT_H
@@ -38,6 +46,7 @@ extern "C" {
#include <inttypes.h>
#include <pthread.h>
+#if 0
#if defined(XINE_COMPILE)
#include "configfile.h"
#include "metronom.h"
@@ -47,6 +56,7 @@ extern "C" {
#include "xine/metronom.h"
#include "xine/buffer.h"
#endif
+#endif
#define VIDEO_OUT_PLUGIN_IFACE_VERSION 1
@@ -58,46 +68,50 @@ typedef struct img_buf_fifo_s img_buf_fifo_t;
typedef struct vo_overlay_s vo_overlay_t;
typedef struct video_overlay_instance_s video_overlay_instance_t;
typedef struct xine_s xine_t;
+typedef struct vo_private_s vo_private_t;
/* public part, video drivers may add private fields */
struct vo_frame_s {
struct vo_frame_s *next;
- uint32_t PTS;
- uint32_t pts_corrector; /* Repeat first field tricks */
- uint32_t SCR;
- int bad_frame; /* e.g. frame skipped or based on skipped frame */
- int drawn;
- uint8_t *base[3];
+ int64_t pts; /* presentation time stamp (1/90000 sec) */
+ int64_t vpts; /* virtual pts, generated by metronom */
+ int64_t pts_corrector; /* used for pepeat first field tricks */
+ int64_t scr; /* system clock reference (discont. detection) */
+ int bad_frame; /* e.g. frame skipped or based on skipped frame */
+ int duration; /* frame length in time, in 1/90000 sec */
+ /* yv12 (planar) base[0]: y, base[1]: u, base[2]: v */
+ /* yuy2 (interleaved) base[0]: yuyv..., base[1]: --, base[2]: -- */
+ uint8_t *base[3];
- /* additional information to be able to duplicate frames: */
+ /* info that can be used for interlaced output (e.g. tv-out) */
+ int top_field_first;
+ int repeat_first_field;
+
+ /* additional information to be able to duplicate frames: */
int width, height;
- int ratio, format;
- int duration;
- int aspect_ratio;
- int frame_rate_code;
- int progressive_sequence;
- int top_field_first;
- int repeat_first_field;
- int progressive_frame;
- int picture_coding_type;
- int bitrate;
+ int ratio; /* aspect ratio, codes see below */
+ int format; /* IMGFMT_YV12 or IMGFMT_RGB */
+
+ int drawn; /* used by decoder, frame has already been drawn */
int display_locked, decoder_locked, driver_locked;
pthread_mutex_t mutex; /* so the various locks will be serialized */
- vo_instance_t *instance;
+ /* "backward" references to where this frame originates from */
+ vo_instance_t *instance;
+ vo_driver_t *driver;
/*
* member functions
*/
- /* this frame is no longer used by decoder */
+ /* this frame is no longer used by the decoder */
void (*free) (vo_frame_t *vo_img);
- /* tell video driver to copy/convert a slice of this frame */
+ /* tell video driver to copy/convert a slice of this frame, may be NULL */
void (*copy) (vo_frame_t *vo_img, uint8_t **src);
/* tell video driver that the decoder starts a new field */
@@ -128,13 +142,11 @@ struct vo_instance_s {
* height == height of video to display.
* ratio == aspect ration information
* format == FOURCC descriptor of image format
- * duration == frame duration in 1/90000 sec
* flags == field/prediction flags
*/
vo_frame_t* (*get_frame) (vo_instance_t *this, uint32_t width,
uint32_t height, int ratio_code,
- int format, uint32_t duration,
- int flags);
+ int format, int flags);
vo_frame_t* (*get_last_frame) (vo_instance_t *this);
@@ -146,46 +158,18 @@ struct vo_instance_s {
/* overlay stuff */
void (*enable_ovl) (vo_instance_t *this, int ovl_enable);
- video_overlay_instance_t *overlay_source;
- int overlay_enabled;
- /* this is just a hint to video_out to detect single frame streams */
- void (*decoder_started) (vo_instance_t *this);
-
/* video driver is no longer used by decoder => close */
void (*close) (vo_instance_t *this);
/* called on xine exit */
void (*exit) (vo_instance_t *this);
- /* private stuff */
-
- vo_driver_t *driver;
- metronom_t *metronom;
- xine_t *xine;
-
- img_buf_fifo_t *free_img_buf_queue;
- img_buf_fifo_t *display_img_buf_queue;
-
- vo_frame_t *last_frame;
-
- int video_loop_running;
- int video_opened;
- int video_paused;
- pthread_t video_thread;
-
- int pts_per_half_frame;
- int pts_per_frame;
-
- int num_frames_delivered;
- int num_frames_skipped;
- int num_frames_discarded;
+ /* get overlay instance (overlay source) */
+ video_overlay_instance_t* (*get_overlay_instance) (vo_instance_t *this);
- int decoder_started_flag;
- uint32_t last_draw_vpts;
+ /* private stuff can be added here */
- int logo_w, logo_h;
- uint8_t *logo_yuy2;
} ;
/* constants for the get/set property functions */
@@ -225,7 +209,7 @@ struct vo_instance_s {
#define IMGFMT_YV12 0x32315659
#define IMGFMT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y')
-#define IMGFMT_RGB (('R'<<24)|('G'<<16)|('B'<<8))
+/*#define IMGFMT_RGB (('R'<<24)|('G'<<16)|('B'<<8)) unused */
/* possible ratios for the VO_PROP_ASPECT_RATIO call */
diff --git a/src/xine-engine/video_overlay.h b/src/xine-engine/video_overlay.h
index 5752642c9..08bf6e0a6 100644
--- a/src/xine-engine/video_overlay.h
+++ b/src/xine-engine/video_overlay.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_overlay.h,v 1.4 2002/01/05 19:09:55 jcdutton Exp $
+ * $Id: video_overlay.h,v 1.5 2002/02/09 07:13:24 guenter Exp $
*
*/
@@ -32,33 +32,33 @@
#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) { (_cb), (_cr), (_y) }
#endif
-#define MAX_OBJECTS 50
-#define MAX_EVENTS 50
-#define MAX_SHOWING 5
+#define MAX_OBJECTS 50
+#define MAX_EVENTS 50
+#define MAX_SHOWING 5
-#define EVENT_NULL 0
-#define EVENT_SHOW_SPU 1
-#define EVENT_HIDE_SPU 2
-#define EVENT_HIDE_MENU 3
-#define EVENT_MENU_SPU 4
-#define EVENT_MENU_BUTTON 5
-#define EVENT_DELETE_RESOURCE 6 /* Maybe release handle will do this */
-#define EVENT_SHOW_OSD 7 /* Not yet implemented */
-#define EVENT_FREE_HANDLE 8 /* Frees a handle, previous allocated via get_handle */
+#define EVENT_NULL 0
+#define EVENT_SHOW_SPU 1
+#define EVENT_HIDE_SPU 2
+#define EVENT_HIDE_MENU 3
+#define EVENT_MENU_SPU 4
+#define EVENT_MENU_BUTTON 5
+#define EVENT_DELETE_RESOURCE 6 /* Maybe release handle will do this */
+#define EVENT_SHOW_OSD 7 /* Not yet implemented */
+#define EVENT_FREE_HANDLE 8 /* Frees a handle, previous allocated via get_handle */
typedef struct video_overlay_object_s {
- int32_t handle; /* Used to match Show and Hide events. */
- uint32_t object_type; /* 0=Subtitle, 1=Menu */
- uint32_t pts; /* Needed for Menu button compares */
- vo_overlay_t *overlay; /* The image data. */
+ int32_t handle; /* Used to match Show and Hide events. */
+ uint32_t object_type; /* 0=Subtitle, 1=Menu */
+ uint32_t pts; /* Needed for Menu button compares */
+ vo_overlay_t *overlay; /* The image data. */
uint32_t palette_type; /* 1 Y'CrCB, 2 R'G'B' */
- uint32_t *palette; /* If NULL, no palette contained in this event. */
+ uint32_t *palette; /* If NULL, no palette contained in this event. */
} video_overlay_object_t;
/* This will hold all details of an event item, needed for event queue to function */
typedef struct video_overlay_event_s {
uint32_t event_type; /* Show SPU, Show OSD, Hide etc. */
- uint32_t vpts; /* Time when event will action. 0 means action now */
+ uint32_t vpts; /* Time when event will action. 0 means action now */
/* Once video_out blend_yuv etc. can take rle_elem_t with Colour, blend and length information.
* we can remove clut and blend from this structure.
* This will allow for many more colours for OSD.
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 5f8e9be8d..1329dde12 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.102 2002/02/01 09:59:08 f1rmb Exp $
+ * $Id: xine.c,v 1.103 2002/02/09 07:13:24 guenter Exp $
*
* top-level xine functions
*
@@ -159,7 +159,7 @@ void xine_stop_internal (xine_t *this) {
this->metronom->set_speed (this->metronom, SPEED_NORMAL);
this->speed = SPEED_NORMAL;
- this->video_out->video_paused = 0;
+
if( this->audio_out )
this->audio_out->audio_paused = 0;
@@ -298,11 +298,6 @@ int xine_play (xine_t *this, char *mrl,
this->cur_input_plugin->stop(this->cur_input_plugin);
}
- /* this will make output threads discard about everything
- (seeking should be faster!) */
- this->metronom->adjust_clock(this->metronom,
- this->metronom->get_current_time(this->metronom) + 30 * 90000 );
-
this->status = XINE_STOP;
}
@@ -373,7 +368,7 @@ int xine_play (xine_t *this, char *mrl,
strncpy (this->cur_mrl, mrl, 1024);
this->metronom->set_speed (this->metronom, SPEED_NORMAL);
- this->video_out->video_paused = 0;
+
if( this->audio_out )
this->audio_out->audio_paused = 0;
this->speed = SPEED_NORMAL;
@@ -504,7 +499,7 @@ xine_t *xine_init (vo_driver_t *vo,
this->video_out = vo_new_instance (vo, this);
video_decoder_init (this);
- this->osd_renderer = osd_renderer_init( this->video_out->overlay_source, config );
+ this->osd_renderer = osd_renderer_init (this->video_out->get_overlay_instance (this->video_out), config );
this->osd = this->osd_renderer->new_object (this->osd_renderer, 300, 100);
this->osd_renderer->set_font (this->osd, "cetus", 24);
@@ -704,7 +699,6 @@ void xine_set_speed (xine_t *this, int speed) {
this->metronom->set_speed (this->metronom, speed);
- this->video_out->video_paused = (speed == SPEED_PAUSE);
/* see coment on audio_out loop about audio_paused */
if( this->audio_out )
this->audio_out->audio_paused = (speed != SPEED_NORMAL) +