diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-02-09 07:13:22 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-02-09 07:13:22 +0000 |
commit | 8700c75544d88f1479d5455b5b2788921d4dd5ee (patch) | |
tree | 7a80e2b00e4e7294c7d7ca1440c4d136ccf12998 | |
parent | 2f8fed75fc94e7afe89f7b60586f7cb55737efe1 (diff) | |
download | xine-lib-8700c75544d88f1479d5455b5b2788921d4dd5ee.tar.gz xine-lib-8700c75544d88f1479d5455b5b2788921d4dd5ee.tar.bz2 |
the long-awaited video_out changes, not completely debuged (races)
- pts are 64 bit now
- scr and video_out-loop run all the time
- video_out cleanups
- metronom cleanups
- buffer type BUF_CONTROL_DISCONTINUITY is used internally now,
input plugins should no longer send this one
- support for individual frame durations
- using nano-/usleep instead of itimer (simpler code, maybe this will
help freebsd)
CVS patchset: 1487
CVS date: 2002/02/09 07:13:22
49 files changed, 1102 insertions, 1399 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index db4b15167..df72f0989 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = xine-utils xine-engine audio_out video_out dxr3 input libmpeg2 libspudec demuxers \ - liba52 libffmpeg liblpcm libw32dll libmad libdts libvfill \ + liba52 libffmpeg liblpcm libw32dll libmad libdts \ libvorbis libdivx4 libsputext libspucc debug: diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index 034f03126..4fef54fb8 100644 --- a/src/demuxers/demux_asf.c +++ b/src/demuxers/demux_asf.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: demux_asf.c,v 1.21 2002/02/03 23:26:08 guenter Exp $ + * $Id: demux_asf.c,v 1.22 2002/02/09 07:13:22 guenter Exp $ * * demultiplexer for asf streams * @@ -701,8 +701,8 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream, buf->input_pos = 0 ; buf->input_time = 0 ; } - buf->PTS = timestamp * 90; - buf->SCR = timestamp * 90; + buf->pts = timestamp * 90; + buf->scr = timestamp * 90; buf->type = stream->buf_type; buf->size = bufsize; timestamp = 0; @@ -774,9 +774,9 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream, buf->input_time = 0 ; } - buf->PTS = stream->timestamp * 90 + stream->ts_per_kbyte * + buf->pts = stream->timestamp * 90 + stream->ts_per_kbyte * (p-stream->buffer) / 1024; - buf->SCR = buf->PTS; + buf->scr = buf->pts; buf->type = stream->buf_type; buf->size = bufsize; diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index 257dcc88a..6bb2b1ae3 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.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: demux_avi.c,v 1.62 2002/01/24 22:55:51 guenter Exp $ + * $Id: demux_avi.c,v 1.63 2002/02/09 07:13:22 guenter Exp $ * * demultiplexer for avi streams * @@ -751,8 +751,8 @@ static int demux_avi_next (demux_avi_t *this) { /* read audio */ - buf->PTS = audio_pts; - buf->SCR = audio_pts; + buf->pts = audio_pts; + buf->scr = audio_pts; buf->size = AVI_read_audio (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]); if (buf->size<0) { @@ -778,8 +778,8 @@ static int demux_avi_next (demux_avi_t *this) { /* read video */ - buf->PTS = video_pts; - buf->SCR = video_pts; + buf->pts = video_pts; + buf->scr = video_pts; buf->size = AVI_read_video (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]); buf->type = this->avi->video_type; @@ -807,7 +807,7 @@ static int demux_avi_next (demux_avi_t *this) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_SPU_TEXT; - buf->PTS = video_pts; + buf->pts = video_pts; buf->decoder_info[0] = 1; buf->decoder_info[1] = this->avi->video_posf; @@ -923,7 +923,7 @@ static void demux_avi_start (demux_plugin_t *this_gen, LOG_MSG(this->xine, _("demux_avi: video format = %s, audio format = 0x%lx\n"), this->avi->compressor, this->avi->a_fmt); - LOG_MSG(this->xine, _("demux_avi: video frame size %d x %d\n"), + LOG_MSG(this->xine, _("demux_avi: video frame size %ld x %ld\n"), this->avi->width, this->avi->height); this->no_audio = 0; diff --git a/src/demuxers/demux_cda.c b/src/demuxers/demux_cda.c index a585a988b..d5fd46b0f 100644 --- a/src/demuxers/demux_cda.c +++ b/src/demuxers/demux_cda.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: demux_cda.c,v 1.6 2002/01/14 21:42:59 f1rmb Exp $ + * $Id: demux_cda.c,v 1.7 2002/02/09 07:13:22 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -93,11 +93,11 @@ static int demux_cda_next (demux_cda_t *this) { pos = this->input->get_current_pos(this->input); len = this->input->get_length(this->input); - buf->PTS = 0; - buf->SCR = 0; + buf->pts = 0; + buf->scr = 0; buf->input_pos = pos; buf->input_time = buf->input_pos / this->blocksize; - buf->type = BUF_VIDEO_FILL; /* Fake */ + buf->type = BUF_CONTROL_NOP; /* Fake */ this->video_fifo->put(this->video_fifo, buf); diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c index 44f000590..608c74fa0 100644 --- a/src/demuxers/demux_elem.c +++ b/src/demuxers/demux_elem.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: demux_elem.c,v 1.32 2002/01/02 18:16:07 jkeil Exp $ + * $Id: demux_elem.c,v 1.33 2002/02/09 07:13:22 guenter Exp $ * * demultiplexer for elementary mpeg streams * @@ -108,8 +108,8 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) { else buf->decoder_info[0] = 1; - buf->PTS = 0; - buf->SCR = 0; + buf->pts = 0; + buf->scr = 0; buf->input_pos = this->input->get_current_pos(this->input); buf->type = BUF_VIDEO_MPEG; diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 8df1d4fe1..ddfc39cfc 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.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: demux_mpeg.c,v 1.48 2002/01/02 18:16:07 jkeil Exp $ + * $Id: demux_mpeg.c,v 1.49 2002/02/09 07:13:22 guenter Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -185,8 +185,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) return ; } buf->type = BUF_AUDIO_A52 + track; - buf->PTS = pts; - buf->SCR = scr; + buf->pts = pts; + buf->scr = scr; if (this->preview_mode) buf->decoder_info[0] = 0; else @@ -235,8 +235,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) return ; } buf->type = BUF_AUDIO_MPEG + track; - buf->PTS = pts; - buf->SCR = scr; + buf->pts = pts; + buf->scr = scr; if (this->preview_mode) buf->decoder_info[0] = 0; else @@ -280,8 +280,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) return ; } buf->type = BUF_VIDEO_MPEG; - buf->PTS = pts; - buf->SCR = scr; + buf->pts = pts; + buf->scr = scr; if (this->preview_mode) buf->decoder_info[0] = 0; else @@ -392,8 +392,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) return ; } buf->type = BUF_AUDIO_MPEG + track ; - buf->PTS = pts; - buf->SCR = scr; + buf->pts = pts; + buf->scr = scr; if (this->preview_mode) buf->decoder_info[0] = 0; else @@ -415,8 +415,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) return ; } buf->type = BUF_VIDEO_MPEG; - buf->PTS = pts; - buf->SCR = scr; + buf->pts = pts; + buf->scr = scr; if (this->preview_mode) buf->decoder_info[0] = 0; else @@ -516,14 +516,14 @@ static uint32_t parse_pack(demux_mpeg_t *this) { buf_element_t *buf; buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_AVSYNC_RESET; - buf->SCR = scr; + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->scr = scr; this->video_fifo->put (this->video_fifo, buf); if (this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_CONTROL_AVSYNC_RESET; - buf->SCR = scr; + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->scr = scr; this->audio_fifo->put (this->audio_fifo, buf); } } diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index 0eb35d522..53f1a0b86 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.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: demux_mpeg_block.c,v 1.75 2002/02/01 13:01:57 f1rmb Exp $ + * $Id: demux_mpeg_block.c,v 1.76 2002/02/09 07:13:23 guenter Exp $ * * demultiplexer for mpeg 1/2 program streams * @@ -202,7 +202,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m scr |= (p[6] & 0xFF) << 7; scr |= (p[7] & 0xFE) >> 1; - buf->SCR = scr; + buf->scr = scr; /* mux_rate */ @@ -234,7 +234,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) ); */ - buf->SCR = scr; + buf->scr = scr; /* mux_rate */ @@ -294,14 +294,14 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m #endif buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_AVSYNC_RESET; - buf->SCR = scr; + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->scr = scr; this->video_fifo->put (this->video_fifo, buf); if (this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_CONTROL_AVSYNC_RESET; - buf->SCR = scr; + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->scr = scr; this->audio_fifo->put (this->audio_fifo, buf); } } @@ -315,7 +315,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf->content = p; buf->size = packet_len; buf->type = BUF_SPU_NAV; - buf->PTS = 0; /* NAV packets do not have PES values */ + buf->pts = 0; /* NAV packets do not have PES values */ buf->input_pos = this->input->get_current_pos(this->input); this->video_fifo->put (this->video_fifo, buf); return ; @@ -424,7 +424,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf->content = p+1; buf->size = packet_len-1; buf->type = BUF_SPU_PACKAGE + spu_id; - buf->PTS = PTS; + buf->pts = PTS; buf->input_pos = this->input->get_current_pos(this->input); this->video_fifo->put (this->video_fifo, buf); @@ -445,7 +445,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m } else { buf->type = BUF_AUDIO_A52 + track; } - buf->PTS = PTS; + buf->pts = PTS; buf->input_pos = this->input->get_current_pos(this->input); @@ -505,7 +505,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf->content = p+pcm_offset; buf->size = packet_len-pcm_offset; buf->type = BUF_AUDIO_LPCM_BE + track; - buf->PTS = PTS; + buf->pts = PTS; buf->input_pos = this->input->get_current_pos(this->input); @@ -522,7 +522,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf->content = p; buf->size = packet_len; buf->type = BUF_VIDEO_MPEG; - buf->PTS = PTS; + buf->pts = PTS; buf->input_pos = this->input->get_current_pos(this->input); @@ -538,7 +538,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf->content = p; buf->size = packet_len; buf->type = BUF_AUDIO_MPEG + track; - buf->PTS = PTS; + buf->pts = PTS; buf->input_pos = this->input->get_current_pos(this->input); diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 17e10c138..df01ac14d 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.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: demux_mpgaudio.c,v 1.33 2002/01/13 21:15:48 jcdutton Exp $ + * $Id: demux_mpgaudio.c,v 1.34 2002/02/09 07:13:23 guenter Exp $ * * demultiplexer for mpeg audio (i.e. mp3) streams * @@ -207,8 +207,8 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this) { } } - buf->PTS = 0; - buf->SCR = 0; + buf->pts = 0; + buf->scr = 0; buf->input_pos = this->input->get_current_pos(this->input); buf->input_time = buf->input_pos * this->stream_length / this->input->get_length(this->input); diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index b78f9cd63..c1382cbdb 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.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: demux_ogg.c,v 1.13 2002/01/02 18:16:07 jkeil Exp $ + * $Id: demux_ogg.c,v 1.14 2002/02/09 07:13:23 guenter Exp $ * * demultiplexer for ogg streams * @@ -184,8 +184,8 @@ static void demux_ogg_send_package (demux_ogg_t *this, int is_content) { } - buf->PTS = 0; /* FIXME */ - buf->SCR = 0; /* FIXME */ + buf->pts = 0; /* FIXME */ + buf->scr = 0; /* FIXME */ buf->size = op.bytes; buf->decoder_info[0] = is_content; diff --git a/src/demuxers/demux_pes.c b/src/demuxers/demux_pes.c index 26d36ecad..2a5305aee 100644 --- a/src/demuxers/demux_pes.c +++ b/src/demuxers/demux_pes.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: demux_pes.c,v 1.17 2002/01/02 18:16:07 jkeil Exp $ + * $Id: demux_pes.c,v 1.18 2002/02/09 07:13:23 guenter Exp $ * * demultiplexer for mpeg 2 PES (Packetized Elementary Streams) * reads streams of variable blocksizes @@ -183,8 +183,8 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { return ; } buf->type = BUF_AUDIO_A52 + track; - buf->PTS = pts; - buf->SCR = pts; /* FIMXE! */ + buf->pts = pts; + buf->scr = pts; /* FIMXE! */ if (this->preview_mode) buf->decoder_info[0] = 0; else @@ -229,8 +229,8 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { return ; } buf->type = BUF_AUDIO_MPEG + track; - buf->PTS = pts; - buf->SCR = pts; /* FIXME ! */ + buf->pts = pts; + buf->scr = pts; /* FIXME ! */ if (this->preview_mode) buf->decoder_info[0] = 0; else @@ -275,8 +275,8 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { return ; } buf->type = BUF_VIDEO_MPEG; - buf->PTS = pts; - buf->SCR = pts; /* FIXME! */ + buf->pts = pts; + buf->scr = pts; /* FIXME! */ if (this->preview_mode) buf->decoder_info[0] = 0; else diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index bfbda7a61..a739bfa59 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.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: demux_qt.c,v 1.19 2002/01/15 21:10:31 miguelfreitas Exp $ + * $Id: demux_qt.c,v 1.20 2002/02/09 07:13:23 guenter Exp $ * * demultiplexer for quicktime streams, based on: * @@ -4026,8 +4026,8 @@ static void *demux_qt_loop (void *this_gen) { /* int count; */ - buf->PTS = audio_pts; - buf->SCR = audio_pts; + buf->pts = audio_pts; + buf->scr = audio_pts; buf->type = this->audio_type; buf->decoder_info[0] = 1; buf->input_time = 0; @@ -4073,8 +4073,8 @@ static void *demux_qt_loop (void *this_gen) { buf->content = buf->mem; buf->size = copy_bytes; - buf->PTS = video_pts; - buf->SCR = video_pts; + buf->pts = video_pts; + buf->scr = video_pts; buf->type = this->video_type; buf->input_time = video_pts / 90000; buf->input_pos = this->input->get_current_pos(this->input); diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 54bcd6c8e..44e05147c 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.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: demux_ts.c,v 1.35 2002/01/13 21:15:48 jcdutton Exp $ + * $Id: demux_ts.c,v 1.36 2002/02/09 07:13:23 guenter Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -544,8 +544,8 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, buf->content = buf->mem; buf->size = m->size; buf->type = m->type; - buf->PTS = m->PTS; - buf->SCR = this->PCR; + buf->pts = m->PTS; + buf->scr = this->PCR; buf->decoder_info[0] = 1; m->fifo->put (m->fifo, buf); } @@ -556,8 +556,8 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, buf->content = buf->mem; buf->size = len; buf->type = m->type; - buf->PTS = 0; - buf->SCR = 0; + buf->pts = 0; + buf->scr = 0; buf->input_pos = this->input->get_current_pos(this->input); buf->decoder_info[0] = 1; m->fifo->put (m->fifo, buf); diff --git a/src/input/input_net.c b/src/input/input_net.c index 6b859ea6e..c89c25524 100644 --- a/src/input/input_net.c +++ b/src/input/input_net.c @@ -99,7 +99,6 @@ static int host_connect_attempt(struct in_addr ia, int port, xine_t *xine) { int s; struct sockaddr_in sin; - fd_set wfd; s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s==-1) { diff --git a/src/input/strict_scr.c b/src/input/strict_scr.c index ba045418e..a0c78f1f3 100644 --- a/src/input/strict_scr.c +++ b/src/input/strict_scr.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: strict_scr.c,v 1.1 2002/01/10 21:42:50 guenter Exp $ + * $Id: strict_scr.c,v 1.2 2002/02/09 07:13:23 guenter Exp $ * * scr plugin that may not allow others to adjust it (used for streaming) */ @@ -70,7 +70,7 @@ static int strictscr_set_speed (scr_plugin_t *scr, int speed) { return speed; } -static void strictscr_adjust (scr_plugin_t *scr, uint32_t vpts) { +static void strictscr_adjust (scr_plugin_t *scr, int64_t vpts) { strictscr_t *this = (strictscr_t*) scr; struct timeval tv; @@ -88,7 +88,7 @@ static void strictscr_adjust (scr_plugin_t *scr, uint32_t vpts) { } } -static void strictscr_start (scr_plugin_t *scr, uint32_t start_vpts) { +static void strictscr_start (scr_plugin_t *scr, int64_t start_vpts) { strictscr_t *this = (strictscr_t*) scr; pthread_mutex_lock (&this->lock); @@ -99,11 +99,11 @@ static void strictscr_start (scr_plugin_t *scr, uint32_t start_vpts) { pthread_mutex_unlock (&this->lock); } -static uint32_t strictscr_get_current (scr_plugin_t *scr) { +static int64_t strictscr_get_current (scr_plugin_t *scr) { strictscr_t *this = (strictscr_t*) scr; struct timeval tv; - uint32_t pts; + int64_t pts; double pts_calc; pthread_mutex_lock (&this->lock); @@ -139,4 +139,4 @@ strictscr_t* strictscr_init () { return this; } - + diff --git a/src/input/strict_scr.h b/src/input/strict_scr.h index 934060c4c..39d8bb8bf 100644 --- a/src/input/strict_scr.h +++ b/src/input/strict_scr.h @@ -29,7 +29,7 @@ typedef struct strictscr_s { scr_plugin_t scr; struct timeval cur_time; - uint32_t cur_pts; + int64_t cur_pts; double speed_factor; int adjustable; diff --git a/src/liba52/xine_decoder.c b/src/liba52/xine_decoder.c index 52910aada..0dbf203e3 100644 --- a/src/liba52/xine_decoder.c +++ b/src/liba52/xine_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: xine_decoder.c,v 1.16 2002/01/05 21:54:17 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.17 2002/02/09 07:13:23 guenter Exp $ * * stuff needed to turn liba52 into a xine decoder plugin */ @@ -50,8 +50,8 @@ int a52file; typedef struct a52dec_decoder_s { audio_decoder_t audio_decoder; - uint32_t pts; - uint32_t last_pts; + int64_t pts; + int64_t last_pts; uint8_t frame_buffer[3840]; uint8_t *frame_ptr; @@ -457,14 +457,14 @@ void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->last_pts = buf->PTS; */ - if (buf->PTS) - this->pts = buf->PTS; + if (buf->pts) + this->pts = buf->pts; while (current != end) { if ( (this->sync_todo == 0) && (this->frame_todo == 0) ) { - a52dec_decode_frame (this, this->pts, buf->SCR); + a52dec_decode_frame (this, this->pts, buf->scr); #ifdef DEBUG_A52 write (a52file, this->frame_buffer, this->frame_length); #endif diff --git a/src/libdivx4/xine_decoder.c b/src/libdivx4/xine_decoder.c index ce63350b6..0e41addfa 100644 --- a/src/libdivx4/xine_decoder.c +++ b/src/libdivx4/xine_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: xine_decoder.c,v 1.16 2002/01/05 21:54:17 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.17 2002/02/09 07:13:23 guenter Exp $ * * xine decoder plugin using divx4 * @@ -394,9 +394,11 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if (buf->decoder_info[0] == 2) { /* need to decode a frame */ /* allocate image (taken from ffmpeg plugin) */ img = this->video_out->get_frame (this->video_out, this->biWidth, - this->biHeight, XINE_ASPECT_RATIO_DONT_TOUCH, IMGFMT_YV12, - this->video_step, VO_BOTH_FIELDS); + this->biHeight, XINE_ASPECT_RATIO_DONT_TOUCH, + IMGFMT_YV12, + VO_BOTH_FIELDS); + img->duration = this->video_step; /* setup the decode frame parameters, as demonstrated by avifile. Old versions used DEC_YV12, but that was basically wrong and just happened to work with the Xv driver. Now DEC_USER is the only option. @@ -422,7 +424,7 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { } /* this again from ffmpeg plugin */ - img->PTS = buf->PTS; + img->pts = buf->pts; img->draw(img); img->free(img); diff --git a/src/libdts/xine_decoder.c b/src/libdts/xine_decoder.c index c8849ffbc..89b8cf1d2 100644 --- a/src/libdts/xine_decoder.c +++ b/src/libdts/xine_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: xine_decoder.c,v 1.13 2002/01/05 21:54:17 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.14 2002/02/09 07:13:23 guenter Exp $ * * 04-09-2001 DTS passtrough (C) Joachim Koenig * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton @@ -123,8 +123,8 @@ void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { /* printf("DTS first access unit=%u\n",audio_buffer->first_access_unit); */ if (n == first_access_unit) { - audio_buffer->vpts = buf->PTS; - audio_buffer->scr = buf->SCR; + audio_buffer->vpts = buf->pts; + audio_buffer->scr = buf->scr; } else { audio_buffer->vpts = 0; audio_buffer->scr = 0; diff --git a/src/libffmpeg/xine_decoder.c b/src/libffmpeg/xine_decoder.c index c239648d6..609a60ee7 100644 --- a/src/libffmpeg/xine_decoder.c +++ b/src/libffmpeg/xine_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: xine_decoder.c,v 1.25 2002/01/28 17:28:39 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.26 2002/02/09 07:13:23 guenter Exp $ * * xine decoder plugin using ffmpeg * @@ -249,10 +249,10 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { this->biHeight, 42, IMGFMT_YV12, - this->video_step, VO_BOTH_FIELDS); - img->PTS = buf->PTS; + img->pts = buf->pts; + img->duration = this->video_step; if (len<0 || this->skipframes) { if( !this->skipframes ) printf ("ffmpeg: error decompressing frame\n"); diff --git a/src/liblpcm/xine_decoder.c b/src/liblpcm/xine_decoder.c index a333695d2..dbff95cda 100644 --- a/src/liblpcm/xine_decoder.c +++ b/src/liblpcm/xine_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: xine_decoder.c,v 1.18 2002/01/05 21:54:17 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.19 2002/02/09 07:13:23 guenter Exp $ * * 31-8-2001 Added LPCM rate sensing. * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk @@ -129,8 +129,8 @@ void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { else memcpy (audio_buffer->mem, sample_buffer, buf->size); - audio_buffer->vpts = buf->PTS; - audio_buffer->scr = buf->SCR; + audio_buffer->vpts = buf->pts; + audio_buffer->scr = buf->scr; audio_buffer->num_frames = (((buf->size*8)/this->number_of_channels)/this->bits_per_sample); this->audio_out->put_buffer (this->audio_out, audio_buffer); diff --git a/src/libmad/xine_decoder.c b/src/libmad/xine_decoder.c index fb6cc03b8..854057761 100644 --- a/src/libmad/xine_decoder.c +++ b/src/libmad/xine_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: xine_decoder.c,v 1.12 2002/01/05 21:54:17 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.13 2002/02/09 07:13:23 guenter Exp $ * * stuff needed to turn libmad into a xine decoder plugin */ @@ -37,7 +37,7 @@ typedef struct mad_decoder_s { audio_decoder_t audio_decoder; - uint32_t pts; + int64_t pts; struct mad_synth synth; struct mad_stream stream; @@ -225,12 +225,12 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } audio_buffer->num_frames = pcm->length; - audio_buffer->vpts = buf->PTS; - audio_buffer->scr = buf->SCR; + audio_buffer->vpts = buf->pts; + audio_buffer->scr = buf->scr; this->audio_out->put_buffer (this->audio_out, audio_buffer); - buf->PTS = 0; + buf->pts = 0; } /* printf ("libmad: decode worked\n"); */ diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 2c2a25de2..999ef3079 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -22,10 +22,6 @@ * */ -/* -#define LOG_PAN_SCAN -*/ - #include "config.h" #include <stdio.h> @@ -40,6 +36,12 @@ #include "xine_internal.h" #include "events.h" +/* +#define LOG_PAN_SCAN +*/ + +#define LOG + #define BUFFER_SIZE (224 * 1024) mpeg2_config_t config; @@ -49,7 +51,7 @@ static void process_userdata(mpeg2dec_t *mpeg2dec, uint8_t *buffer); void mpeg2_init (mpeg2dec_t * mpeg2dec, vo_instance_t * output) { - static int do_init = 1; + static int do_init = 1; if (do_init) { do_init = 0; @@ -79,50 +81,54 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec, header_state_init (mpeg2dec->picture); } -static int get_frame_duration(mpeg2dec_t * mpeg2dec, vo_frame_t * frame) +static inline void get_frame_duration (mpeg2dec_t * mpeg2dec, vo_frame_t *frame) { - int duration; - switch (frame->frame_rate_code) { + switch (mpeg2dec->picture->frame_rate_code) { case 1: /* 23.976 fps */ - frame->duration = 3913; + frame->duration = 3913; + frame->pts_corrector = 0; break; case 2: /* 24 fps */ - frame->duration = 3750; + frame->duration = 3750; + frame->pts_corrector = 0; break; case 3: /* 25 fps */ - frame->duration = frame->repeat_first_field ? 5400 : 3600; + frame->duration = mpeg2dec->picture->repeat_first_field ? 5400 : 3600; + frame->pts_corrector = 0; break; case 4: /* 29.97 fps */ - if ((frame->repeat_first_field) || (mpeg2dec->last_repeat_first_field)) { - frame->duration = 3754; + if ((mpeg2dec->picture->repeat_first_field) || (mpeg2dec->last_repeat_first_field)) { + frame->duration = 3754; frame->pts_corrector = frame->repeat_first_field ? 375 : -375; } else { - frame->duration = 3003; + frame->duration = 3003; frame->pts_corrector = 0; } -// duration = 3754; -// duration = frame->repeat_first_field ? 4504 : 3003; break; case 5: /* 30 fps */ - frame->duration = 3000; + frame->duration = 3000; + frame->pts_corrector = 0; break; case 6: /* 50 fps */ - frame->duration = 1800; + frame->duration = 1800; + frame->pts_corrector = 0; break; case 7: /* 59.94 fps */ - frame->duration = 1525; + frame->duration = 1525; + frame->pts_corrector = 0; break; case 8: /* 60 fps */ - frame->duration = 1509; + frame->duration = 1509; + frame->pts_corrector = 0; break; default: /* printf ("invalid/unknown frame rate code : %d \n", frame->frame_rate_code); */ - duration = 3000; + frame->duration = 3000; + frame->pts_corrector = 0; } /* printf("mpeg2dec: rff=%u\n",frame->repeat_first_field); */ mpeg2dec->last_repeat_first_field = frame->repeat_first_field; - return 1; } static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, @@ -159,8 +165,6 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, if ( picture->current_frame && ((picture->picture_structure == FRAME_PICTURE) || (picture->second_field)) ) { - picture->current_frame->bad_frame |= mpeg2dec->drop_frame; - #if 0 printf ("type %s: %s\n", picture->picture_coding_type == I_TYPE ? "I" : @@ -168,10 +172,11 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->current_frame->bad_frame ? "BAD" : "good"); #endif if (picture->picture_coding_type == B_TYPE) { - if (picture->mpeg1) { - picture->current_frame->PTS = 0; - } - get_frame_duration(mpeg2dec, picture->current_frame); + + /* hack against wrong mpeg1 pts */ + if (picture->mpeg1) + picture->current_frame->pts = 0; + mpeg2dec->frames_to_drop = picture->current_frame->draw (picture->current_frame); picture->current_frame->free (picture->current_frame); picture->current_frame = NULL; @@ -225,7 +230,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, break; case I_TYPE: - /* + /* for the sake of dvd menus, never drop i-frames if (mpeg2dec->frames_to_drop>4) { mpeg2dec->drop_frame = 1; } @@ -249,7 +254,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, || (picture->frame_height != picture->coded_picture_height)) { xine_frame_change_event_t notify_event; - printf ("mpeg2dec: frame size has changed to from %d x %d to %d x %d\n", + printf ("libmpeg2: frame size has changed to from %d x %d to %d x %d\n", picture->frame_width, picture->frame_height, picture->coded_picture_width, picture->coded_picture_height); @@ -264,7 +269,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, if (picture->backward_reference_frame) picture->backward_reference_frame->free (picture->backward_reference_frame); - printf ("mpeg2dec: old frames freed.\n"); + printf ("libmpeg2: old frames freed.\n"); mpeg2dec->is_sequence_needed = 0; picture->forward_reference_frame = NULL; @@ -277,23 +282,23 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, case 0xb5: /* extension_start_code */ if (header_process_extension (picture, buffer)) { - fprintf (stderr, "bad extension\n"); - exit (1); + printf ("libmpeg2: bad extension\n"); + exit (1); } break; case 0xb7: /* sequence end code */ #ifdef LOG_PAN_SCAN - printf ("libmpeg2:SEQUENCE END CODE NOT HANDLED!\n"); + printf ("libmpeg2: sequence end code not handled\n"); #endif case 0xb8: /* group of pictures start code */ if (header_process_group_of_pictures (picture, buffer)) { - fprintf (stderr, "bad group of pictures\n"); - exit (1); + printf ("libmpeg2: bad group of pictures\n"); + exit (1); } default: if (code >= 0xb9) - fprintf (stderr, "stream not demultiplexed ?\n"); + printf ("libmpeg2: stream not demultiplexed ?\n"); if (code >= 0xb0) break; @@ -315,7 +320,6 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->coded_picture_height, picture->aspect_ratio_information, IMGFMT_YV12, - picture->frame_duration, picture->picture_structure); else { picture->current_frame = @@ -324,7 +328,6 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->coded_picture_height, picture->aspect_ratio_information, IMGFMT_YV12, - picture->frame_duration, (VO_PREDICTION_FLAG | picture->picture_structure)); if (picture->forward_reference_frame) picture->forward_reference_frame->free (picture->forward_reference_frame); @@ -333,19 +336,15 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->backward_reference_frame; picture->backward_reference_frame = picture->current_frame; } - picture->current_frame->bad_frame = 0; - picture->current_frame->drawn = 0; - picture->current_frame->PTS = mpeg2dec->pts; - picture->current_frame->SCR = mpeg2dec->scr; - picture->current_frame->aspect_ratio = picture->aspect_ratio_information; - picture->current_frame->frame_rate_code = picture->frame_rate_code; - picture->current_frame->top_field_first = picture->top_field_first; - picture->current_frame->progressive_sequence = picture->progressive_sequence; + picture->current_frame->bad_frame = 1; + picture->current_frame->drawn = 0; + picture->current_frame->pts = mpeg2dec->pts; + picture->current_frame->scr = mpeg2dec->scr; + picture->current_frame->top_field_first = picture->top_field_first; picture->current_frame->repeat_first_field = picture->repeat_first_field; - picture->current_frame->progressive_frame = picture->progressive_frame; - picture->current_frame->picture_coding_type = picture->picture_coding_type; - picture->current_frame->bitrate = picture->bitrate; - picture->current_frame->repeat_first_field = picture->repeat_first_field; + + get_frame_duration(mpeg2dec, picture->current_frame); + mpeg2dec->pts = 0; } } @@ -353,7 +352,8 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, if (!(mpeg2dec->drop_frame)) { /* printf ("slice_process\n"); */ - slice_process (picture, code, buffer); + if (slice_process (picture, code, buffer) == 1) + picture->current_frame->bad_frame = 0; #ifdef ARCH_X86 if (config.flags & MM_ACCEL_X86_MMX) @@ -362,7 +362,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, } } - /* printf ("parse_chunk %d completed\n", code); */ + /* printf ("libmpeg2: parse_chunk %d completed\n", code); */ return is_frame_done; } @@ -381,8 +381,8 @@ static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec, limit = end; /* - printf ("copy chunk current %08x\n", current ); - printf ("copy chunk end %08x\n", end); fflush(stdout); + printf ("libmpeg2: copy chunk current %08x\n", current ); + printf ("libmpeg2: copy chunk end %08x\n", end); fflush(stdout); */ while (1) { @@ -444,31 +444,32 @@ int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end, void mpeg2_flush (mpeg2dec_t * mpeg2dec) { - picture_t *picture = mpeg2dec->picture; + picture_t *picture = mpeg2dec->picture; - if (picture->backward_reference_frame && !picture->backward_reference_frame->drawn) { - vo_frame_t *img; - - printf ("libmpeg2: blasting out backward reference frame on flush\n"); - picture->backward_reference_frame->PTS = 0; - picture->backward_reference_frame->SCR = mpeg2dec->scr; - get_frame_duration(mpeg2dec, picture->backward_reference_frame); - picture->backward_reference_frame->bad_frame = 0; - picture->backward_reference_frame->drawn = 1; - picture->backward_reference_frame->displayed (picture->backward_reference_frame); - - /* output a copy instead of the frame used by decoder */ - img = picture->backward_reference_frame->instance->duplicate_frame( - picture->backward_reference_frame->instance, - picture->backward_reference_frame); - img->PTS = 0; - img->SCR = mpeg2dec->scr; - img->bad_frame = 0; - img->drawn = 2; - img->draw(img); - - img->free(img); - } + if (picture->backward_reference_frame && !picture->backward_reference_frame->drawn + && !picture->backward_reference_frame->bad_frame) { + + vo_frame_t *img; + + printf ("libmpeg2: blasting out backward reference frame on flush\n"); + + picture->backward_reference_frame->drawn = 1; + + /* output a copy instead of the frame used by decoder */ + img = picture->backward_reference_frame->instance->duplicate_frame(picture->backward_reference_frame->instance, + picture->backward_reference_frame); + img->pts = 0; + img->scr = 0; + img->bad_frame = 0; + img->drawn = 1; + + img->draw(img); + img->free(img); + + } else { + printf ("libmpeg2: flush called, but I have no frame to flush\n"); + + } } @@ -501,9 +502,8 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec) if (picture->throwaway_frame) { printf ("libmpeg2: blasting out throwaway frame on close\n"); - picture->throwaway_frame->PTS = 0; - picture->throwaway_frame->SCR = mpeg2dec->scr; - picture->throwaway_frame->bad_frame = 0; + picture->throwaway_frame->pts = 0; + picture->throwaway_frame->scr = 0; get_frame_duration(mpeg2dec, picture->throwaway_frame); picture->throwaway_frame->draw (picture->throwaway_frame); picture->throwaway_frame->free (picture->throwaway_frame); @@ -511,10 +511,9 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec) if (picture->backward_reference_frame) { printf ("libmpeg2: blasting out backward reference frame on close\n"); - picture->backward_reference_frame->PTS = 0; - picture->backward_reference_frame->SCR = mpeg2dec->scr; + picture->backward_reference_frame->pts = 0; + picture->backward_reference_frame->scr = mpeg2dec->scr; get_frame_duration(mpeg2dec, picture->backward_reference_frame); - picture->backward_reference_frame->bad_frame = 0; if( !picture->backward_reference_frame->drawn) picture->backward_reference_frame->draw (picture->backward_reference_frame); picture->backward_reference_frame->free (picture->backward_reference_frame); diff --git a/src/libmpeg2/header.c b/src/libmpeg2/header.c index e075f51e1..0a486f0f9 100644 --- a/src/libmpeg2/header.c +++ b/src/libmpeg2/header.c @@ -131,39 +131,7 @@ int header_process_sequence_header (picture_t * picture, uint8_t * buffer) /* this is not used by the decoder */ picture->aspect_ratio_information = buffer[3] >> 4; picture->frame_rate_code = buffer[3] & 15; - - switch (picture->frame_rate_code) { - case 1: /* 23.976 fps */ - picture->frame_duration = 3913; - break; - case 2: /* 24 fps */ - picture->frame_duration = 3750; - break; - case 3: /* 25 fps */ - picture->frame_duration = 3600; - break; - case 4: /* 29.97 fps */ - picture->frame_duration = 3003; - break; - case 5: /* 30 fps */ - picture->frame_duration = 3000; - break; - case 6: /* 50 fps */ - picture->frame_duration = 1800; - break; - case 7: /* 59.94 fps */ - picture->frame_duration = 1525; - break; - case 8: /* 60 fps */ - picture->frame_duration = 1509; - break; - default: - /* printf ("invalid/unknown frame rate code : %d \n", - picture->frame_rate_code); */ - picture->frame_duration = 3000; - } - - picture->bitrate = (buffer[4]<<10)|(buffer[5]<<2)|(buffer[6]>>6); + /* picture->bitrate = (buffer[4]<<10)|(buffer[5]<<2)|(buffer[6]>>6); */ if (buffer[7] & 2) { for (i = 0; i < 64; i++) @@ -194,6 +162,7 @@ int header_process_sequence_header (picture_t * picture, uint8_t * buffer) /* picture->alternate_scan = 0; */ picture->picture_structure = FRAME_PICTURE; /* picture->second_field = 0; */ + picture->last_mba = ((width * height) >> 8) - 1; return 0; } @@ -209,10 +178,14 @@ static int header_process_sequence_extension (picture_t * picture, /* this is not used by the decoder */ picture->progressive_sequence = (buffer[1] >> 3) & 1; + picture->low_delay = buffer[5] & 0x80; + if (picture->progressive_sequence) picture->coded_picture_height = (picture->coded_picture_height + 31) & ~31; + printf ("libmpeg2: low_delay : %d\n", picture->low_delay); + /* printf ("libmpeg2: sequence extension+5 : %08x (%d)\n", buffer[5], buffer[5] % 0x80); @@ -422,6 +395,8 @@ int header_process_group_of_pictures (picture_t * picture, uint8_t * buffer) { int header_process_picture_header (picture_t *picture, uint8_t * buffer) { picture->picture_coding_type = (buffer [1] >> 3) & 7; + picture->vbv_delay = ((buffer[1] << 13) | (buffer[2] << 5) | + (buffer[3] >> 3)) & 0xffff; /* forward_f_code and backward_f_code - used in mpeg1 only */ picture->f_motion.f_code[1] = (buffer[3] >> 2) & 1; @@ -437,3 +412,5 @@ int header_process_picture_header (picture_t *picture, uint8_t * buffer) return 0; } + + diff --git a/src/libmpeg2/mpeg2_internal.h b/src/libmpeg2/mpeg2_internal.h index fcb70368b..767be0093 100644 --- a/src/libmpeg2/mpeg2_internal.h +++ b/src/libmpeg2/mpeg2_internal.h @@ -91,6 +91,9 @@ typedef struct picture_s { /* what type of picture this is (I, P, B, D) */ int picture_coding_type; + + int vbv_delay; + int low_delay; /* picture coding extension stuff */ @@ -107,6 +110,8 @@ typedef struct picture_s { int q_scale_type; /* bool to use different vlc tables */ int intra_vlc_format; + /* last macroblock in the picture */ + int last_mba; /* used for DMV MC */ int top_field_first; @@ -132,11 +137,10 @@ typedef struct picture_s { /* this is a temporary interface, we will build a better one later. */ int aspect_ratio_information; int frame_rate_code; - int frame_duration; int progressive_sequence; int repeat_first_field; int progressive_frame; - int bitrate; + /*int bitrate; */ uint32_t frame_centre_horizontal_offset; uint32_t frame_centre_vertical_offset; uint32_t video_format; @@ -222,7 +226,7 @@ extern mc_functions_t mc_functions_altivec; extern mc_functions_t mc_functions_mlib; /* slice.c */ -void slice_process (picture_t *picture, uint8_t code, uint8_t * buffer); +int slice_process (picture_t *picture, uint8_t code, uint8_t * buffer); /* stats.c */ void stats_header (uint8_t code, uint8_t * buffer); diff --git a/src/libmpeg2/slice.c b/src/libmpeg2/slice.c index 4abdf8a4a..3cd547f24 100644 --- a/src/libmpeg2/slice.c +++ b/src/libmpeg2/slice.c @@ -968,7 +968,7 @@ do { \ NEEDBITS (bit_buf, bits, bit_ptr); \ continue; \ default: /* end of slice, or error */ \ - return; \ + return (mba >= picture->last_mba); \ } \ } \ DUMPBITS (bit_buf, bits, tab->len); \ @@ -1497,15 +1497,15 @@ do { \ dest[2] += 4 * stride; \ } while (0); \ if (! (picture->mpeg1)) \ - return; \ + return (mba >= picture->last_mba); \ picture->v_offset += 16; \ if (picture->v_offset >= picture->coded_picture_height) \ - return; \ + return 1; \ offset = 0; \ } \ } while (0) -void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) +int slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) { #define bit_buf (picture->bitstream_buf) #define bits (picture->bitstream_bits) @@ -1515,8 +1515,10 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) uint8_t * dest[3]; int offset; uint8_t ** forward_ref[2]; + int mba; stride = picture->coded_picture_width; + mba = (code-1) * (stride >> 4); offset = (code - 1) * stride * 4; picture->v_offset = (code - 1) * 16; @@ -1592,6 +1594,7 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) NEEDBITS (bit_buf, bits, bit_ptr); GET_MACROBLOCK_ADDRESS_INCREMENT (offset); + mba += offset; offset <<= 4; while (1) { @@ -1744,6 +1747,7 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) picture->dc_dct_pred[2] = 1 << (picture->intra_dc_precision+7); } + mba++; offset += 16; CHECK_DISPLAY; @@ -1764,6 +1768,7 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) else MOTION (motion_fi_zero, MACROBLOCK_MOTION_FORWARD); + mba++; offset += 16; CHECK_DISPLAY; } while (--mba_inc); @@ -1776,6 +1781,7 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) else MOTION (motion_fi_reuse, macroblock_modes); + mba++; offset += 16; CHECK_DISPLAY; } while (--mba_inc); @@ -1785,4 +1791,7 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) #undef bit_buf #undef bits #undef bit_ptr + + return (mba >= picture->last_mba); + } diff --git a/src/libmpeg2/xine_decoder.c b/src/libmpeg2/xine_decoder.c index 2f6a338bb..da5415253 100644 --- a/src/libmpeg2/xine_decoder.c +++ b/src/libmpeg2/xine_decoder.c @@ -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: xine_decoder.c,v 1.20 2002/01/05 21:54:17 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.21 2002/02/09 07:13:23 guenter Exp $ * * stuff needed to turn libmpeg2 into a xine decoder plugin */ @@ -36,69 +36,74 @@ #include "buffer.h" #include "xine_internal.h" +#define LOG + typedef struct mpeg2dec_decoder_s { video_decoder_t video_decoder; mpeg2dec_t mpeg2; vo_instance_t *video_out; - /*int mpeg_file;*/ /* debugging purposes only */ + pthread_mutex_t lock; /* mutex for async flush */ } mpeg2dec_decoder_t; static int mpeg2dec_can_handle (video_decoder_t *this_gen, int buf_type) { return ((buf_type & 0xFFFF0000) == BUF_VIDEO_MPEG) ; } - static void mpeg2dec_init (video_decoder_t *this_gen, vo_instance_t *video_out) { mpeg2dec_decoder_t *this = (mpeg2dec_decoder_t *) this_gen; + printf ("libmpeg2: init \n"); mpeg2_init (&this->mpeg2, video_out); video_out->open(video_out); this->video_out = video_out; - - /* debugging purposes */ - /*this->mpeg_file = open ("/tmp/video.mpv",O_CREAT | O_WRONLY | O_TRUNC, 0644);*/ + pthread_mutex_init (&this->lock, NULL); } static void mpeg2dec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { mpeg2dec_decoder_t *this = (mpeg2dec_decoder_t *) this_gen; + printf ("libmpeg2: decode_data...\n"); + + pthread_mutex_lock (&this->lock); + if (buf->decoder_info[0] == 0) { mpeg2_find_sequence_header (&this->mpeg2, buf->content, buf->content + buf->size); } else { - /* debugging purposes */ - /* write (this->mpeg_file, buf->content, buf->size); */ - mpeg2_decode_data (&this->mpeg2, buf->content, buf->content + buf->size, - buf->PTS, buf->SCR); - - this->video_out->decoder_started(this->video_out); + buf->pts, buf->scr); } + pthread_mutex_unlock (&this->lock); + + printf ("libmpeg2: decode_data...done\n"); } static void mpeg2dec_flush (video_decoder_t *this_gen) { mpeg2dec_decoder_t *this = (mpeg2dec_decoder_t *) this_gen; + pthread_mutex_lock (&this->lock); + printf ("libmpeg2: flush\n"); + mpeg2_flush (&this->mpeg2); + pthread_mutex_unlock (&this->lock); } static void mpeg2dec_close (video_decoder_t *this_gen) { mpeg2dec_decoder_t *this = (mpeg2dec_decoder_t *) this_gen; + printf ("libmpeg2: close\n"); + mpeg2_close (&this->mpeg2); this->video_out->close(this->video_out); - /* debugging purposes */ - /* - close (this->mpeg_file); - this->mpeg_file = -1; - */ + pthread_mutex_destroy (&this->lock); + } static char *mpeg2dec_get_id(void) { diff --git a/src/libspucc/xine_decoder.c b/src/libspucc/xine_decoder.c index 07fa47dc3..cfde5387b 100644 --- a/src/libspucc/xine_decoder.c +++ b/src/libspucc/xine_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: xine_decoder.c,v 1.3 2002/01/07 23:04:26 cvogler Exp $ + * $Id: xine_decoder.c,v 1.4 2002/02/09 07:13:23 guenter Exp $ * * closed caption spu decoder. receive data by events. * @@ -276,7 +276,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if(this->cc_cfg.can_cc) { decode_cc(this->ccdec, buf->content, buf->size, - buf->PTS, buf->SCR); + buf->pts, buf->scr); } } pthread_mutex_unlock(&this->cc_mutex); diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c index e92586a52..ee824d9d1 100644 --- a/src/libspudec/xine_decoder.c +++ b/src/libspudec/xine_decoder.c @@ -19,7 +19,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_decoder.c,v 1.55 2002/01/15 20:22:43 jcdutton Exp $ + * $Id: xine_decoder.c,v 1.56 2002/02/09 07:13:23 guenter Exp $ * * stuff needed to turn libspu into a xine decoder plugin */ @@ -179,6 +179,7 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) { // spu_overlay_event_t *event; // spu_object_t *object; // vo_overlay_t *overlay; + video_overlay_instance_t *ovl_instance = this->vo_out->get_overlay_instance (this->vo_out); int pending = 1; this->cur_seq = &this->spu_stream_state[stream_id].ra_seq; @@ -255,9 +256,10 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) { //if (this->state.menu == 0) { if (1) { /* Subtitle */ - if( this->menu_handle < 0 ) - this->menu_handle = this->vo_out->overlay_source->get_handle(this->vo_out->overlay_source,1); - + if( this->menu_handle < 0 ) { + this->menu_handle = ovl_instance->get_handle(ovl_instance,1); + } + if( this->menu_handle < 0 ) { printf("libspudec: No video_overlay handles left for menu\n"); return; @@ -301,9 +303,10 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) { */ } else { /* Menu */ - if( this->menu_handle < 0 ) - this->menu_handle = this->vo_out->overlay_source->get_handle(this->vo_out->overlay_source,1); - + if( this->menu_handle < 0 ) { + this->menu_handle = ovl_instance->get_handle (ovl_instance, 1); + } + if( this->menu_handle < 0 ) { printf("libspudec: No video_overlay handles left for menu\n"); return; @@ -330,7 +333,7 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) { + (this->state.delay*1000); printf("libspudec: vpts current time estimation around discontinuity\n"); } - this->vo_out->overlay_source->add_event(this->vo_out->overlay_source, (void *)&this->event); + ovl_instance->add_event(ovl_instance, (void *)&this->event); } else { pending = 0; } @@ -339,12 +342,13 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) { } static void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { - uint8_t *p; - uint32_t packet_len; - uint32_t stream_id; - uint32_t header_len; - pci_t *pci; - dsi_t *dsi; + uint8_t *p; + uint32_t packet_len; + uint32_t stream_id; + uint32_t header_len; + pci_t *pci; + dsi_t *dsi; + video_overlay_instance_t *ovl_instance = this->vo_out->get_overlay_instance (this->vo_out); p = buf->content; if (p[0] || p[1] || (p[2] != 1)) { @@ -416,7 +420,7 @@ static void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { /* Hide menu spu between menus */ printf("libspudec:nav:SHOULD HIDE SPU here\n"); if( this->menu_handle < 0 ) { - this->menu_handle = this->vo_out->overlay_source->get_handle(this->vo_out->overlay_source,1); + this->menu_handle = ovl_instance->get_handle(ovl_instance,1); } if( this->menu_handle >= 0 ) { metronom_t *metronom = this->xine->metronom; @@ -427,7 +431,7 @@ static void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { instead as an aproximation. */ this->event.vpts = metronom->got_spu_packet(metronom, pci->pci_gi.vobu_s_ptm, 0, 0); - this->vo_out->overlay_source->add_event(this->vo_out->overlay_source, (void *)&this->event); + ovl_instance->add_event(ovl_instance, (void *)&this->event); } else { printf("libspudec: No video_overlay handles left for menu\n"); } @@ -483,9 +487,9 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if ( this->spu_stream_state[stream_id].stream_filter == 0) return; - if (buf->PTS) { + if (buf->pts) { metronom_t *metronom = this->xine->metronom; - uint32_t vpts = metronom->got_spu_packet(metronom, buf->PTS, 0, buf->SCR); + uint32_t vpts = metronom->got_spu_packet(metronom, buf->pts, 0, buf->scr); if (vpts < this->buf_pts) { /* FIXME: Don't do this yet, @@ -496,7 +500,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } this->spu_stream_state[stream_id].vpts = vpts; /* Show timer */ - this->spu_stream_state[stream_id].pts = buf->PTS; /* Required to match up with NAV packets */ + this->spu_stream_state[stream_id].pts = buf->pts; /* Required to match up with NAV packets */ } /* if (this->ra_complete) { @@ -528,19 +532,20 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } static void spudec_close (spu_decoder_t *this_gen) { - spudec_decoder_t *this = (spudec_decoder_t *) this_gen; - int i; + spudec_decoder_t *this = (spudec_decoder_t *) this_gen; + int i; + video_overlay_instance_t *ovl_instance = this->vo_out->get_overlay_instance (this->vo_out); if( this->menu_handle >= 0 ) - this->vo_out->overlay_source->free_handle(this->vo_out->overlay_source, - this->menu_handle); + ovl_instance->free_handle(ovl_instance, + this->menu_handle); this->menu_handle = -1; for (i=0; i < MAX_STREAMS; i++) { if( this->spu_stream_state[i].overlay_handle >= 0 ) - this->vo_out->overlay_source->free_handle(this->vo_out->overlay_source, - this->spu_stream_state[i].overlay_handle); + ovl_instance->free_handle(ovl_instance, + this->spu_stream_state[i].overlay_handle); this->spu_stream_state[i].overlay_handle = -1; } } @@ -566,11 +571,15 @@ static void spudec_nextseq(spudec_decoder_t* this) { static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) { spudec_decoder_t *this = (spudec_decoder_t *) this_gen; xine_spu_event_t *event = (xine_spu_event_t *) event_gen; + video_overlay_instance_t *ovl_instance; if((!this) || (!event)) { return; } + if (this->vo_out) + ovl_instance = this->vo_out->get_overlay_instance (this->vo_out); + switch (event->event.type) { case XINE_EVENT_SPU_BUTTON: { @@ -650,7 +659,7 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) { overlay_event->event_type = EVENT_HIDE_MENU; } overlay_event->vpts = 0; /* Activate it NOW */ - this->vo_out->overlay_source->add_event(this->vo_out->overlay_source, (void *)overlay_event); + ovl_instance->add_event (ovl_instance, (void *)overlay_event); } break; case XINE_EVENT_SPU_CLUT: diff --git a/src/libsputext/xine_decoder.c b/src/libsputext/xine_decoder.c index 2fb5725a9..90eb173cf 100644 --- a/src/libsputext/xine_decoder.c +++ b/src/libsputext/xine_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: xine_decoder.c,v 1.11 2002/01/08 16:47:56 cvogler Exp $ + * $Id: xine_decoder.c,v 1.12 2002/02/09 07:13:23 guenter Exp $ * * code based on mplayer module: * @@ -791,14 +791,14 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } else { - uint32_t pts, pts_end; - int32_t pts_factor; + int64_t pts, pts_end; + int64_t pts_factor; int frame_num; subtitle_t *subtitle; subtitle = NULL; - pts = buf->PTS; + pts = buf->pts; pts_end = pts; frame_num = buf->decoder_info[1]; @@ -820,7 +820,10 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if (subtitle->start > frame_num) return; + /* FIXME FIXME FIXME pts_factor = this->xine->metronom->get_video_rate (this->xine->metronom); + */ + pts_factor = 3000; pts += this->xine->metronom->video_wrap_offset; diff --git a/src/libvorbis/xine_decoder.c b/src/libvorbis/xine_decoder.c index cd0517e29..4e85b0678 100644 --- a/src/libvorbis/xine_decoder.c +++ b/src/libvorbis/xine_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: xine_decoder.c,v 1.5 2002/01/05 21:54:17 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.6 2002/02/09 07:13:24 guenter Exp $ * * (ogg/)vorbis audio decoder plugin (libvorbis wrapper) for xine */ @@ -41,7 +41,7 @@ typedef struct vorbis_decoder_s { audio_decoder_t audio_decoder; - uint32_t pts; + int64_t pts; ao_instance_t *audio_out; int output_sampling_rate; @@ -204,12 +204,12 @@ static void vorbis_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } } - audio_buffer->vpts = buf->PTS; + audio_buffer->vpts = buf->pts; audio_buffer->num_frames = bout; this->audio_out->put_buffer (this->audio_out, audio_buffer); - buf->PTS=0; + buf->pts=0; vorbis_synthesis_read(&this->vd,bout); } } diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c index 0d8f123d2..3c9dacd51 100644 --- a/src/libw32dll/w32codec.c +++ b/src/libw32dll/w32codec.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: w32codec.c,v 1.62 2002/01/22 01:55:12 miguelfreitas Exp $ + * $Id: w32codec.c,v 1.63 2002/02/09 07:13:24 guenter Exp $ * * routines for using w32 codecs * DirectShow support by Miguel Freitas (Nov/2001) @@ -127,11 +127,11 @@ typedef struct w32a_decoder_s { unsigned char *buf; int size; - uint32_t pts; - uint32_t scr; + int64_t pts; + int64_t scr; /* these are used for pts estimation */ - uint32_t lastpts, sumpts, sumsize; + int64_t lastpts, sumpts, sumsize; unsigned char *outbuf; int outsize; @@ -633,9 +633,10 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { this->bih.biHeight, 42, IMGFMT_YUY2, - this->video_step, VO_BOTH_FIELDS); + img->duration = this->video_step; + if (this->outfmt==IMGFMT_YUY2) img_buffer = img->base[0]; @@ -717,8 +718,8 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { } } - img->PTS = buf->PTS; - img->SCR = buf->SCR; + img->pts = buf->pts; + img->scr = buf->scr; if(ret || this->skipframes) { if( !this->skipframes ) printf("w32codec: Error decompressing frame, err=%ld\n", (long)ret); @@ -976,8 +977,8 @@ static void w32a_decode_audio (w32a_decoder_t *this, unsigned char *data, uint32_t size, int frame_end, - uint32_t pts, - uint32_t scr) { + int64_t pts, + int64_t scr) { static ACMSTREAMHEADER ash; HRESULT hr; @@ -1128,7 +1129,7 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { w32a_decode_audio (this, buf->content, buf->size, buf->decoder_info[0]==2, - buf->PTS, buf->SCR); + buf->pts, buf->scr); } } diff --git a/src/video_out/alphablend.c b/src/video_out/alphablend.c index 8646d2864..2c819b86e 100644 --- a/src/video_out/alphablend.c +++ b/src/video_out/alphablend.c @@ -34,6 +34,7 @@ #include <string.h> #include <stdlib.h> +#include <stdio.h> #include <inttypes.h> #include "video_out.h" diff --git a/src/video_out/video_out_fb.c b/src/video_out/video_out_fb.c index 0c073845c..8dbbd0f46 100644 --- a/src/video_out/video_out_fb.c +++ b/src/video_out/video_out_fb.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_fb.c,v 1.4 2002/01/22 01:43:13 miguelfreitas Exp $ + * $Id: video_out_fb.c,v 1.5 2002/02/09 07:13:24 guenter Exp $ * * video_out_fb.c, frame buffer xine driver by Miguel Freitas * @@ -154,7 +154,7 @@ static uint32_t fb_get_capabilities (vo_driver_t *this_gen) { static void fb_frame_copy (vo_frame_t *vo_img, uint8_t **src) { fb_frame_t *frame = (fb_frame_t *) vo_img ; - fb_driver_t *this = (fb_driver_t *) vo_img->instance->driver; + fb_driver_t *this = (fb_driver_t *) vo_img->driver; xine_profiler_start_count (this->prof_yuv2rgb); @@ -176,7 +176,7 @@ static void fb_frame_copy (vo_frame_t *vo_img, uint8_t **src) { static void fb_frame_field (vo_frame_t *vo_img, int which_field) { fb_frame_t *frame = (fb_frame_t *) vo_img ; - fb_driver_t *this = (fb_driver_t *) vo_img->instance->driver; + fb_driver_t *this = (fb_driver_t *) vo_img->driver; switch (which_field) { case VO_TOP_FIELD: @@ -226,6 +226,7 @@ static vo_frame_t *fb_alloc_frame (vo_driver_t *this_gen) { frame->vo_frame.copy = fb_frame_copy; frame->vo_frame.field = fb_frame_field; frame->vo_frame.dispose = fb_frame_dispose; + frame->vo_frame.driver = this_gen; return (vo_frame_t *) frame; } diff --git a/src/video_out/video_out_opengl.c b/src/video_out/video_out_opengl.c index 8a2993de9..23e690719 100644 --- a/src/video_out/video_out_opengl.c +++ b/src/video_out/video_out_opengl.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_opengl.c,v 1.4 2002/01/23 23:27:10 f1rmb Exp $ + * $Id: video_out_opengl.c,v 1.5 2002/02/09 07:13:24 guenter Exp $ * * video_out_glut.c, glut based OpenGL rendering interface for xine * Matthias Hopf <mat@mshopf.de> @@ -231,7 +231,7 @@ static uint32_t opengl_get_capabilities (vo_driver_t *this_gen) { static void opengl_frame_copy (vo_frame_t *vo_img, uint8_t **src) { opengl_frame_t *frame = (opengl_frame_t *) vo_img ; - opengl_driver_t *this = (opengl_driver_t *) vo_img->instance->driver; + opengl_driver_t *this = (opengl_driver_t *) vo_img->driver; /*fprintf (stderr, "*** frame_copy\n"); */ xine_profiler_start_count (this->prof_yuv2rgb); @@ -301,12 +301,13 @@ static vo_frame_t *opengl_alloc_frame (vo_driver_t *this_gen) { pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* - * supply required functions + * supply required functions/fields */ frame->vo_frame.copy = opengl_frame_copy; frame->vo_frame.field = opengl_frame_field; frame->vo_frame.dispose = opengl_frame_dispose; + frame->vo_frame.driver = this_gen; return (vo_frame_t *) frame; } diff --git a/src/video_out/video_out_syncfb.c b/src/video_out/video_out_syncfb.c index 87a042c61..ce34a6b1c 100644 --- a/src/video_out/video_out_syncfb.c +++ b/src/video_out/video_out_syncfb.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_syncfb.c,v 1.52 2002/01/24 23:09:53 guenter Exp $ + * $Id: video_out_syncfb.c,v 1.53 2002/02/09 07:13:24 guenter Exp $ * * video_out_syncfb.c, SyncFB (for Matrox G200/G400 cards) interface for xine * @@ -327,10 +327,6 @@ static void write_frame_sfb(syncfb_driver_t* this, syncfb_frame_t* frame) } break; - case IMGFMT_RGB: - printf("video_out_syncfb: error. (RGB565 not yet supported)\n"); - break; - default: printf("video_out_syncfb: error. (unknown frame format)\n"); break; @@ -545,10 +541,6 @@ static void syncfb_adapt_to_output_area(syncfb_driver_t* this, this->syncfb_config.src_palette = VIDEO_PALETTE_YUV422; break; - case IMGFMT_RGB: - this->syncfb_config.src_palette = VIDEO_PALETTE_RGB565; - break; - default: this->syncfb_config.src_palette = 0; break; diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 6d5ccb918..61e9b3fb2 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.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_xshm.c,v 1.55 2002/01/15 20:35:24 jcdutton Exp $ + * $Id: video_out_xshm.c,v 1.56 2002/02/09 07:13:24 guenter Exp $ * * video_out_xshm.c, X11 shared memory extension interface for xine * @@ -349,7 +349,7 @@ static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { static void xshm_frame_copy (vo_frame_t *vo_img, uint8_t **src) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; - xshm_driver_t *this = (xshm_driver_t *) vo_img->instance->driver; + xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; xine_profiler_start_count (this->prof_yuv2rgb); @@ -371,7 +371,7 @@ static void xshm_frame_copy (vo_frame_t *vo_img, uint8_t **src) { static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; - xshm_driver_t *this = (xshm_driver_t *) vo_img->instance->driver; + xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; switch (which_field) { case VO_TOP_FIELD: @@ -391,7 +391,7 @@ static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { static void xshm_frame_dispose (vo_frame_t *vo_img) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; - xshm_driver_t *this = (xshm_driver_t *) vo_img->instance->driver; + xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; if (frame->image) { XLockDisplay (this->display); @@ -417,13 +417,14 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* - * supply required functions + * supply required functions/fields */ frame->vo_frame.copy = xshm_frame_copy; frame->vo_frame.field = xshm_frame_field; frame->vo_frame.dispose = xshm_frame_dispose; - + frame->vo_frame.driver = this_gen; + return (vo_frame_t *) frame; } diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 68fd7b15d..30aadd009 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.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_xv.c,v 1.90 2002/01/24 23:09:54 guenter Exp $ + * $Id: video_out_xv.c,v 1.91 2002/02/09 07:13:24 guenter Exp $ * * video_out_xv.c, X11 video extension interface for xine * @@ -97,7 +97,6 @@ struct xv_driver_s { Display *display; int screen; Drawable drawable; - unsigned int xv_format_rgb; unsigned int xv_format_yv12; unsigned int xv_format_yuy2; XVisualInfo vinfo; @@ -184,7 +183,7 @@ static void xv_frame_field (vo_frame_t *vo_img, int which_field) { static void xv_frame_dispose (vo_frame_t *vo_img) { xv_frame_t *frame = (xv_frame_t *) vo_img ; - xv_driver_t *this = (xv_driver_t *) vo_img->instance->driver; + xv_driver_t *this = (xv_driver_t *) vo_img->driver; if (frame->image) { XLockDisplay (this->display); @@ -220,6 +219,8 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) { frame->vo_frame.field = xv_frame_field; frame->vo_frame.dispose = xv_frame_dispose; + frame->vo_frame.driver = this_gen; + return (vo_frame_t *) frame; } @@ -258,9 +259,6 @@ static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo, case IMGFMT_YV12: xv_format = this->xv_format_yv12; break; - case IMGFMT_RGB: - xv_format = this->xv_format_rgb; - break; case IMGFMT_YUY2: xv_format = this->xv_format_yuy2; break; @@ -842,11 +840,15 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; xv_frame_t *frame = (xv_frame_t *) frame_gen; + printf ("video_out_xv: xv_display_frame...\n"); + if (this->expecting_event) { frame->vo_frame.displayed (&frame->vo_frame); this->expecting_event--; + printf ("video_out_xv: xv_display_frame... not displayed, waiting for completion event\n"); + } else { xv_add_recent_frame (this, frame); this->cur_frame = frame; @@ -862,8 +864,12 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { if (this->deinterlace_enabled && this->deinterlace_method) xv_deinterlace_frame (this); + printf ("video_out_xv: xv_display_frame... lock display...\n"); + XLockDisplay (this->display); + printf ("video_out_xv: xv_display_frame... lock display...locked\n"); + if (this->use_shm) { XvShmPutImage(this->display, this->xv_port, this->drawable, this->gc, this->cur_frame->image, @@ -887,6 +893,8 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { XUnlockDisplay (this->display); } + + printf ("video_out_xv: xv_display_frame... done\n"); } static int xv_get_property (vo_driver_t *this_gen, int property) { @@ -1450,7 +1458,6 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->xv_format_yv12 = 0; this->xv_format_yuy2 = 0; - this->xv_format_rgb = 0; for(i = 0; i < formats; i++) { #ifdef XV_LOG @@ -1466,10 +1473,6 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->xv_format_yuy2 = fo[i].id; this->capabilities |= VO_CAP_YUY2; printf("video_out_xv: this adaptor supports the yuy2 format.\n"); - } else if (fo[i].id == IMGFMT_RGB) { - this->xv_format_rgb = fo[i].id; - this->capabilities |= VO_CAP_RGB; - printf("video_out_xv: this adaptor supports the rgb format.\n"); } } 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) + |