diff options
-rw-r--r-- | src/demuxers/demux_mpeg_block.c | 157 | ||||
-rw-r--r-- | src/xine-engine/audio_decoder.c | 10 | ||||
-rw-r--r-- | src/xine-engine/buffer.h | 4 | ||||
-rw-r--r-- | src/xine-engine/metronom.c | 45 | ||||
-rw-r--r-- | src/xine-engine/metronom.h | 41 | ||||
-rw-r--r-- | src/xine-engine/video_decoder.c | 16 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 15 |
7 files changed, 190 insertions, 98 deletions
diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index ee1348dc0..b590102fa 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000, 2001 the xine project + * Copyright (C) 2000-2002 the xine project * - * This file is part of xine, a unix video player. + * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -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.79 2002/03/12 02:55:37 miguelfreitas Exp $ + * $Id: demux_mpeg_block.c,v 1.80 2002/03/20 23:12:58 guenter Exp $ * * demultiplexer for mpeg 1/2 program streams * @@ -75,6 +75,7 @@ typedef struct demux_mpeg_block_s { uint8_t *scratch; int64_t last_scr; + int64_t nav_last_end_pts; } demux_mpeg_block_t ; @@ -91,10 +92,16 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf = this->input->read_block (this->input, this->video_fifo, this->blocksize); +#ifdef LOG + printf ("demux_mpeg_block: read_block\n"); +#endif + if (buf==NULL) { xine_next_mrl_event_t event; +#ifdef LOG printf ("demux_mpeg_block: read_block failed\n"); +#endif /* * check if seamless branching is possible @@ -107,13 +114,17 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m if (event.handled) { char *next_mrl = event.mrl; - + +#ifdef LOG printf ("demux_mpeg_block: checking if we can branch to %s\n", next_mrl); +#endif if (next_mrl && this->input->is_branch_possible && this->input->is_branch_possible (this->input, next_mrl)) { +#ifdef LOG printf ("demux_mpeg_block: branching\n"); +#endif this->input->close (this->input); this->input->open (this->input, next_mrl); @@ -139,7 +150,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m /* If this is not a block for the demuxer, pass it * straight through. */ - if(buf->type != BUF_DEMUX_BLOCK) { + if (buf->type != BUF_DEMUX_BLOCK) { buf_element_t *cbuf; this->video_fifo->put (this->video_fifo, buf); @@ -153,6 +164,13 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m this->audio_fifo->put (this->audio_fifo, cbuf); } +#ifdef LOG + printf ("demux_mpeg_block: type %08x != BUF_DEMUX_BLOCK\n", buf->type); +#endif + /* + if (buf->type == BUF_CONTROL_NOP) + this->send_disc = 1; + */ return; } @@ -210,10 +228,14 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m scr |= p[7] << 5; scr |= (p[8] & 0xF8) >> 3; /* optional - decode extension: - scr *=300; - scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) ); + scr *=300; + scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) ); */ +#ifdef LOG + printf ("demux_mpeg_block: SCR=%lld\n", scr); +#endif + /* buf->scr = scr; */ /* mux_rate */ @@ -228,8 +250,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m p += 14 + num_stuffing_bytes; } - } - + } if (p[3] == 0xbb) { /* program stream system header */ @@ -257,9 +278,70 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m return; } + packet_len = p[4] << 8 | p[5]; + stream_id = p[3]; + + if (stream_id == 0xbf) { /* NAV Packet */ + + int64_t start_pts, end_pts; + + start_pts = (p[7+12] << 24); + start_pts |= (p[7+13] << 16); + start_pts |= (p[7+14] << 8); + start_pts |= p[7+15]; + + end_pts = (p[7+16] << 24); + end_pts |= (p[7+17] << 16); + end_pts |= (p[7+18] << 8); + end_pts |= p[7+19]; + + buf->content = p; + buf->size = packet_len; + buf->type = BUF_SPU_NAV; + 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); + +#ifdef LOG + printf ("demux_mpeg_block: NAV packet, start pts = %lld, end_pts = %lld\n", + start_pts, end_pts); +#endif + + if (this->nav_last_end_pts != start_pts) { + +#ifdef LOG + printf ("demux_mpeg_block: informing metronom about new start pts\n"); +#endif + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = start_pts; + 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_NEWPTS; + buf->disc_off = start_pts; + this->audio_fifo->put (this->audio_fifo, buf); + } + + } + + this->nav_last_end_pts = end_pts; + this->last_scr = end_pts; + + /* + for (i=0; i<120; i++) + printf ("%02x ", p[i]); + printf ("\n"); + */ + + return ; + } + +#if 0 /* discontinuity ? */ - if( scr ) - { + if (scr) { int64_t scr_diff = scr - this->last_scr; #ifdef LOG @@ -267,12 +349,12 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m scr, this->last_scr, scr_diff); #endif - if (abs(scr_diff) > DISC_TRESHOLD && !preview_mode) { + if ((abs(scr_diff) > DISC_TRESHOLD) && !preview_mode) { buf_element_t *buf; #ifdef LOG - printf ("demux_mpeg_block: DISCONTINUITY!\n"); + printf ("demux_mpeg_block: DISCONTINUITY/NEWPTS!\n"); #endif buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); @@ -289,19 +371,8 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m } this->last_scr = scr; } +#endif - packet_len = p[4] << 8 | p[5]; - stream_id = p[3]; - - if (stream_id == 0xbf) { /* NAV Packet */ - buf->content = p; - buf->size = packet_len; - buf->type = BUF_SPU_NAV; - 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 ; - } if (bMpeg1) { @@ -340,11 +411,11 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m PTS |= p[ 3] << 7 ; PTS |= (p[ 4] & 0xFE) >> 1 ; /* DTS decoding code is working, but not used in xine - DTS = (p[ 5] & 0x0E) << 29 ; - DTS |= p[ 6] << 22 ; - DTS |= (p[ 7] & 0xFE) << 14 ; - DTS |= p[ 8] << 7 ; - DTS |= (p[ 9] & 0xFE) >> 1 ; + DTS = (p[ 5] & 0x0E) << 29 ; + DTS |= p[ 6] << 22 ; + DTS |= (p[ 7] & 0xFE) << 14 ; + DTS |= p[ 8] << 7 ; + DTS |= (p[ 9] & 0xFE) >> 1 ; */ p += 10; packet_len -= 10; @@ -371,20 +442,24 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m PTS |= p[12] << 7 ; PTS |= (p[13] & 0xFE) >> 1 ; +#ifdef LOG + printf ("demux_mpeg_block: pts = %lld\n", PTS); +#endif + } else PTS = 0; /* code is working but not used in xine - if (p[7] & 0x40) { + if (p[7] & 0x40) { - DTS = (p[14] & 0x0E) << 29 ; - DTS |= p[15] << 22 ; - DTS |= (p[16] & 0xFE) << 14 ; - DTS |= p[17] << 7 ; - DTS |= (p[18] & 0xFE) >> 1 ; + DTS = (p[14] & 0x0E) << 29 ; + DTS |= p[15] << 22 ; + DTS |= (p[16] & 0xFE) << 14 ; + DTS |= p[17] << 7 ; + DTS |= (p[18] & 0xFE) >> 1 ; - } else - DTS = 0; + } else + DTS = 0; */ @@ -394,8 +469,6 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m packet_len -= header_len + 3; } - PTS &= 0x7FFFFFFF ; /* 31 bit only (for signed calculations) */ - if (stream_id == 0xbd) { int track, spu_id; @@ -534,7 +607,6 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m return ; } - buf->free_buffer (buf); return ; @@ -797,7 +869,8 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen, this->rate = demux_mpeg_block_estimate_rate (this); - this->last_scr = 0; + this->last_scr = 0; + this->nav_last_end_pts = 0; if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 2ed4c0522..e85aa40a1 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.66 2002/03/18 22:45:53 guenter Exp $ + * $Id: audio_decoder.c,v 1.67 2002/03/20 23:12:58 guenter Exp $ * * * functions that implement audio decoding @@ -84,7 +84,7 @@ 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->handle_audio_discontinuity (this->metronom, DISC_STREAMSTART, 0); break; @@ -129,9 +129,11 @@ void *audio_decoder_loop (void *this_gen) { break; case BUF_CONTROL_DISCONTINUITY: - printf ("audio_decoder: discontinuity ahead\n"); + this->metronom->handle_audio_discontinuity (this->metronom, DISC_RELATIVE, buf->disc_off); + break; - this->metronom->expect_audio_discontinuity (this->metronom, buf->disc_off); + case BUF_CONTROL_NEWPTS: + this->metronom->handle_audio_discontinuity (this->metronom, DISC_ABSOLUTE, buf->disc_off); break; case BUF_CONTROL_AUDIO_CHANNEL: diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index e818d9cbf..e0a0a6630 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.36 2002/03/16 20:53:50 guenter Exp $ + * $Id: buffer.h,v 1.37 2002/03/20 23:12:58 guenter Exp $ * * * contents: @@ -69,6 +69,8 @@ extern "C" { #define BUF_CONTROL_NOP 0x01040000 #define BUF_CONTROL_AUDIO_CHANNEL 0x01050000 #define BUF_CONTROL_SPU_CHANNEL 0x01060000 +#define BUF_CONTROL_NEWPTS 0x01070000 +#define BUF_CONTROL_SEEK 0x01080000 /* video buffer types: (please keep in sync with buffer_types.c) */ diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 80745a727..f589a9554 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.70 2002/03/12 22:23:14 guenter Exp $ + * $Id: metronom.c,v 1.71 2002/03/20 23:12:58 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -274,7 +274,7 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts, return vpts; } -static void metronom_handle_video_discontinuity (metronom_t *this, int is_stream_start, +static void metronom_handle_video_discontinuity (metronom_t *this, int type, int64_t disc_off) { pthread_mutex_lock (&this->lock); @@ -282,8 +282,8 @@ static void metronom_handle_video_discontinuity (metronom_t *this, int is_stream this->video_discontinuity_count++; pthread_cond_signal (&this->video_discontinuity_reached); - printf ("metronom: video discontinuity #%d, disc_off is %lld\n", - this->video_discontinuity_count, disc_off); + printf ("metronom: video discontinuity #%d, type is %d, disc_off is %lld\n", + this->video_discontinuity_count, type, disc_off); if (this->have_audio) { while (this->audio_discontinuity_count < @@ -304,24 +304,23 @@ static void metronom_handle_video_discontinuity (metronom_t *this, int is_stream if (this->in_discontinuity) this->vpts_offset = this->next_vpts_offset; - if (is_stream_start) { - this->vpts_offset = this->video_vpts; + switch (type) { + case DISC_STREAMSTART: + this->vpts_offset = this->video_vpts; this->in_discontinuity = 0; - } else { + break; + case DISC_ABSOLUTE: + this->next_vpts_offset = this->video_vpts - disc_off; + this->in_discontinuity = 30; + break; + case DISC_RELATIVE: this->next_vpts_offset = this->vpts_offset - disc_off; this->in_discontinuity = 30; + break; } pthread_mutex_unlock (&this->lock); } -static void metronom_video_stream_start (metronom_t *this) { - metronom_handle_video_discontinuity (this, 1, 0); -} - -static void metronom_expect_video_discontinuity (metronom_t *this, int64_t disc_off) { - metronom_handle_video_discontinuity (this, 0, disc_off); -} - static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { int64_t vpts; @@ -399,7 +398,7 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { pthread_mutex_unlock (&this->lock); } -static void metronom_expect_audio_discontinuity (metronom_t *this, +static void metronom_handle_audio_discontinuity (metronom_t *this, int type, int64_t disc_off) { pthread_mutex_lock (&this->lock); @@ -407,8 +406,8 @@ static void metronom_expect_audio_discontinuity (metronom_t *this, this->audio_discontinuity_count++; pthread_cond_signal (&this->audio_discontinuity_reached); - printf ("metronom: audio discontinuity #%d, disc_off %lld\n", - this->audio_discontinuity_count, disc_off); + printf ("metronom: audio discontinuity #%d, type is %d, disc_off %lld\n", + this->audio_discontinuity_count, type, disc_off); while ( this->audio_discontinuity_count > this->video_discontinuity_count ) { @@ -429,10 +428,6 @@ static void metronom_expect_audio_discontinuity (metronom_t *this, pthread_mutex_unlock (&this->lock); } -static void metronom_audio_stream_start (metronom_t *this) { - metronom_expect_audio_discontinuity (this, 0); -} - static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, int nsamples) { @@ -587,10 +582,8 @@ metronom_t * metronom_init (int have_audio, void *xine) { this->got_video_frame = metronom_got_video_frame; this->got_audio_samples = metronom_got_audio_samples; this->got_spu_packet = metronom_got_spu_packet; - this->audio_stream_start = metronom_audio_stream_start; - this->video_stream_start = metronom_video_stream_start; - this->expect_audio_discontinuity = metronom_expect_audio_discontinuity; - this->expect_video_discontinuity = metronom_expect_video_discontinuity; + this->handle_audio_discontinuity = metronom_handle_audio_discontinuity; + this->handle_video_discontinuity = metronom_handle_video_discontinuity; this->set_av_offset = metronom_set_av_offset; this->get_av_offset = metronom_get_av_offset; this->start_clock = metronom_start_clock; diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 9e486a222..08b64eb57 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: metronom.h,v 1.22 2002/03/12 19:51:29 guenter Exp $ + * $Id: metronom.h,v 1.23 2002/03/20 23:12:58 guenter Exp $ * * metronom: general pts => virtual calculation/assoc * @@ -55,6 +55,11 @@ extern "C" { typedef struct metronom_s metronom_t ; typedef struct scr_plugin_s scr_plugin_t; + /* see below */ +#define DISC_STREAMSTART 0 +#define DISC_RELATIVE 1 +#define DISC_ABSOLUTE 2 + struct metronom_s { /* @@ -116,27 +121,27 @@ struct metronom_s { * tell metronom about discontinuities. * * 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. + * demux stage. * - * 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 - * good. + * there are different types of discontinuities: * - * (the time between discontinuity is detected to where it is corrected - * may be called "discontinuity window". Inside this window we cannot - * use the xxx_wrap_offset for any pts -> vpts calculation as the result - * would be wrong. The vpts values will be predicted for pts == 0 and - * whenever we get a new pts we can calculate the new xxx_wrap_offset) + * DISC_STREAMSTART : new stream starts, expect pts values to start + * from zero immediately + * DISC_RELATIVE : typically a wrap-around, expect pts with + * a specified offset from the former ones soon + * DISC_ABSOLUTE : typically a new menu stream (nav packets) + * pts will start from given value soon * + * for DISC_RELATIVE and DISC_ABSOLUTE metronom will enter a + * special discontinuity mode which means that it will ignore + * pts values for some time (about 1sec) to ignore any held-back + * reference frames that are flushed out of decoders containing + * pts values that do not mach the new offset. Then it will + * just switch to the new disc_offset and resume synced operation. + * */ - void (*expect_audio_discontinuity) (metronom_t *this, int64_t disc_off); - void (*expect_video_discontinuity) (metronom_t *this, int64_t disc_off); - - void (*audio_stream_start) (metronom_t *this); - void (*video_stream_start) (metronom_t *this); + void (*handle_audio_discontinuity) (metronom_t *this, int type, int64_t disc_off); + void (*handle_video_discontinuity) (metronom_t *this, int type, int64_t disc_off); /* * manually correct audio <-> video sync diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index 6604d2c33..cf6eccb43 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.78 2002/03/16 20:53:50 guenter Exp $ + * $Id: video_decoder.c,v 1.79 2002/03/20 23:12:58 guenter Exp $ * */ @@ -106,7 +106,7 @@ void *video_decoder_loop (void *this_gen) { pthread_mutex_unlock (&this->finished_lock); - this->metronom->video_stream_start (this->metronom); + this->metronom->handle_video_discontinuity (this->metronom, DISC_STREAMSTART, 0); break; @@ -186,7 +186,17 @@ void *video_decoder_loop (void *this_gen) { this->video_in_discontinuity = 1; - this->metronom->expect_video_discontinuity (this->metronom, buf->disc_off); + this->metronom->handle_video_discontinuity (this->metronom, DISC_RELATIVE, buf->disc_off); + + this->video_in_discontinuity = 0; + break; + + case BUF_CONTROL_NEWPTS: + printf ("video_decoder: new pts %lld\n", buf->disc_off); + + this->video_in_discontinuity = 1; + + this->metronom->handle_video_discontinuity (this->metronom, DISC_ABSOLUTE, buf->disc_off); this->video_in_discontinuity = 0; break; diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 2850f3616..4af47c3c3 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.c,v 1.80 2002/03/14 04:31:49 miguelfreitas Exp $ + * $Id: video_out.c,v 1.81 2002/03/20 23:12:58 guenter Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -258,9 +258,12 @@ static int vo_frame_draw (vo_frame_t *img) { diff = pic_vpts - cur_vpts; frames_to_skip = ((-1 * diff) / img->duration + 3) * 2; + if (frames_to_skip<0) + frames_to_skip = 0; + #ifdef LOG - printf ("video_out: delivery diff : %lld, current vpts is %lld\n", - diff, cur_vpts); + printf ("video_out: delivery diff : %lld, current vpts is %lld, %d frames to skip\n", + diff, cur_vpts, frames_to_skip); #endif if (img->display_locked) { @@ -286,6 +289,10 @@ static int vo_frame_draw (vo_frame_t *img) { vo_append_to_img_buf_queue (this->display_img_buf_queue, img); } else { +#ifdef LOG + printf ("video_out: bad_frame\n"); +#endif + this->num_frames_skipped++; pthread_mutex_lock (&img->mutex); @@ -669,7 +676,7 @@ static void *video_out_loop (void *this_gen) { if (usec_to_sleep>0) xine_usec_sleep (usec_to_sleep); - } while (usec_to_sleep > 0); + } while ( (usec_to_sleep > 0) && this->video_loop_running); } |