From 96920b7a5c210b72e2e23afa1c41d1e30b9c7a45 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Mon, 13 Jan 2003 02:15:07 +0000 Subject: - add option to adjust spu sync (works for both dvd and external subtitles) - implement some master/slave stuff - implement subtitle mrl: xine movie.mpg#subtitle:whatever.sub CVS patchset: 3887 CVS date: 2003/01/13 02:15:07 --- src/libsputext/xine_decoder.c | 33 +++++++++++--------- src/xine-engine/metronom.c | 23 ++++++-------- src/xine-engine/metronom.h | 4 ++- src/xine-engine/xine.c | 67 ++++++++++++++++++++++++++++++++++++---- src/xine-engine/xine_interface.c | 9 +++++- src/xine-engine/xine_internal.h | 8 +++-- 6 files changed, 104 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/libsputext/xine_decoder.c b/src/libsputext/xine_decoder.c index de539d87d..d8aa774b3 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.48 2003/01/12 15:29:08 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.49 2003/01/13 02:15:08 miguelfreitas Exp $ * */ @@ -182,6 +182,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { int uses_time; int32_t start, end, diff; int64_t start_vpts, end_vpts; + int64_t spu_offset; int i; uint32_t *val; char *str; @@ -209,10 +210,12 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { #endif } - if( this->stream->master_stream ) - xine_get_current_info (this->stream->master_stream, &extra_info, sizeof(extra_info) ); - else - xine_get_current_info (this->stream, &extra_info, sizeof(extra_info) ); + spu_offset = this->stream->master->metronom->get_option (this->stream->metronom, + METRONOM_SPU_OFFSET); + start += (spu_offset / 90); + end += (spu_offset / 90); + + xine_get_current_info (this->stream->master, &extra_info, sizeof(extra_info) ); if( !this->seek_count ) { this->seek_count = extra_info.seek_count; @@ -221,7 +224,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { while(this->seek_count == extra_info.seek_count) { /* initialize decoder if needed */ - if( !this->width || !this->height || !this->img_duration ) { + if( !this->width || !this->height || !this->img_duration || !this->osd ) { if( this->stream->video_out->status(this->stream->video_out, NULL, &this->width, &this->height, &this->img_duration )) { @@ -283,11 +286,15 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } } - if( this->stream->master_stream ) - status = xine_get_status (this->stream->master_stream); - else - status = xine_get_status (this->stream); + status = xine_get_status (this->stream->master); + + if( status == XINE_STATUS_QUIT || status == XINE_STATUS_STOP ) { + this->width = this->height = 0; + return; + } + status = xine_get_status (this->stream); + if( status == XINE_STATUS_QUIT || status == XINE_STATUS_STOP ) { this->width = this->height = 0; return; @@ -295,11 +302,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { xine_usec_sleep (50000); - if( this->stream->master_stream ) - xine_get_current_info (this->stream->master_stream, &extra_info, sizeof(extra_info) ); - else - xine_get_current_info (this->stream, &extra_info, sizeof(extra_info) ); - + xine_get_current_info (this->stream->master, &extra_info, sizeof(extra_info) ); } } diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index b76c07ce9..75e031e2f 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.109 2003/01/11 03:47:01 miguelfreitas Exp $ + * $Id: metronom.c,v 1.110 2003/01/13 02:15:07 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -48,8 +48,6 @@ #define VIDEO_DRIFT_TOLERANCE 45000 #define AUDIO_DRIFT_TOLERANCE 45000 -/*#define OLD_DRIFT_CORRECTION 1*/ - /* redefine abs as macro to handle 64-bit diffs. i guess llabs may not be available everywhere */ #define abs(x) ( ((x)<0) ? -(x) : (x) ) @@ -273,7 +271,7 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) { pthread_mutex_lock (&this->lock); - vpts = pts + this->vpts_offset; + vpts = pts + this->vpts_offset + this->spu_offset; /* no vpts going backwards please */ if( vpts < this->spu_vpts ) @@ -549,15 +547,9 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, * we want. however, adding the error to the vpts_offset will force video * to change it's frame rate to keep in sync with us. */ -#if OLD_DRIFT_CORRECTION - this->audio_vpts += nsamples * (this->pts_per_smpls-this->audio_drift_step) - / AUDIO_SAMPLE_NUM; - this->audio_samples += nsamples; -#else this->audio_vpts += nsamples * this->pts_per_smpls / AUDIO_SAMPLE_NUM; this->audio_samples += nsamples; this->vpts_offset += nsamples * this->audio_drift_step / AUDIO_SAMPLE_NUM; -#endif #ifdef LOG printf ("metronom: audio vpts for %10lld : %10lld\n", pts, vpts); @@ -577,12 +569,12 @@ static void metronom_set_option (metronom_t *this, int option, int64_t value) { this->av_offset = value; printf ("metronom: av_offset=%lld pts\n", this->av_offset); break; + case METRONOM_SPU_OFFSET: + this->spu_offset = value; + printf ("metronom: av_offset=%lld pts\n", this->spu_offset); + break; case METRONOM_ADJ_VPTS_OFFSET: -#if OLD_DRIFT_CORRECTION - this->vpts_offset += value; -#else this->audio_vpts += value; -#endif /*#ifdef LOG*/ /* that message should be rare, please report otherwise. @@ -622,6 +614,8 @@ static int64_t metronom_get_option (metronom_t *this, int option) { switch (option) { case METRONOM_AV_OFFSET: return this->av_offset; + case METRONOM_SPU_OFFSET: + return this->spu_offset; case METRONOM_FRAME_DURATION: return this->img_duration; } @@ -774,6 +768,7 @@ metronom_t * metronom_init (int have_audio, xine_stream_t *stream) { pthread_mutex_init (&this->lock, NULL); this->av_offset = 0; + this->spu_offset = 0; this->vpts_offset = 0; /* initialize video stuff */ diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 3cc17aab6..76f24039f 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.42 2003/01/11 03:47:01 miguelfreitas Exp $ + * $Id: metronom.h,v 1.43 2003/01/13 02:15:07 miguelfreitas Exp $ * * metronom: general pts => virtual calculation/assoc * @@ -180,6 +180,7 @@ struct metronom_s { int64_t audio_drift_step; int64_t av_offset; + int64_t spu_offset; pthread_mutex_t lock; @@ -207,6 +208,7 @@ struct metronom_s { #define METRONOM_AV_OFFSET 2 #define METRONOM_ADJ_VPTS_OFFSET 3 #define METRONOM_FRAME_DURATION 4 +#define METRONOM_SPU_OFFSET 5 metronom_t *metronom_init (int have_audio, xine_stream_t *stream); diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 02da19b60..edeb59d99 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.214 2003/01/11 12:51:19 miguelfreitas Exp $ + * $Id: xine.c,v 1.215 2003/01/13 02:15:07 miguelfreitas Exp $ * * top-level xine functions * @@ -218,6 +218,9 @@ void xine_stop (xine_stream_t *stream) { if (stream->video_out) stream->video_out->flush(stream->video_out); + if (stream->slave) + xine_stop(stream->slave); + pthread_mutex_unlock (&stream->frontend_lock); } @@ -226,6 +229,15 @@ static void xine_close_internal (xine_stream_t *stream) { int i ; + if( stream->slave ) { + xine_close( stream->slave ); + if( stream->slave_is_subtitle ) { + xine_dispose(stream->slave); + stream->slave = NULL; + stream->slave_is_subtitle = 0; + } + } + xine_stop_internal( stream ); #ifdef LOG @@ -362,7 +374,14 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->finished_count_audio = 0; stream->finished_count_video = 0; stream->err = 0; - + + /* + * initial master/slave + */ + stream->master = stream; + stream->slave = NULL; + stream->slave_is_subtitle = 0; + /* * init mutexes and conditions */ @@ -600,6 +619,39 @@ static int xine_open_internal (xine_stream_t *stream, const char *mrl) { } continue; } + if (strncasecmp(stream_setup, "subtitle", 8) == 0) { + if (*(stream_setup += 8) == ':') { + char *tmp = ++stream_setup; + char *subtitle_mrl; + stream_setup = strchr(stream_setup, ';'); + if (stream_setup) { + subtitle_mrl = (char *)malloc(stream_setup - tmp + 1); + memcpy(subtitle_mrl, tmp, stream_setup - tmp); + subtitle_mrl[stream_setup - tmp] = '\0'; + } else { + subtitle_mrl = (char *)malloc(strlen(tmp)); + memcpy(subtitle_mrl, tmp, strlen(tmp)); + subtitle_mrl[strlen(tmp)] = '\0'; + } + stream->slave = xine_stream_new (stream->xine, NULL, stream->video_out ); + if( xine_open( stream->slave, subtitle_mrl ) ) { + printf("xine: subtitle mrl opened\n"); + stream->slave->master = stream; + stream->slave_is_subtitle = 1; + } else { + printf("xine: error opening subtitle mrl\n"); + xine_dispose( stream->slave ); + stream->slave = NULL; + } + free(subtitle_mrl); + } else { + printf("xine: error while parsing mrl\n"); + stream->err = XINE_ERROR_MALFORMED_MRL; + stream->status = XINE_STATUS_STOP; + return 0; + } + continue; + } { /* when we got here, the stream setup parameter must be a config entry */ char *tmp = stream_setup; @@ -719,7 +771,7 @@ int xine_open (xine_stream_t *stream, const char *mrl) { #endif ret = xine_open_internal (stream, mrl); - + pthread_mutex_unlock (&stream->frontend_lock); return ret; @@ -814,6 +866,8 @@ int xine_play (xine_stream_t *stream, int start_pos, int start_time) { pthread_mutex_lock (&stream->frontend_lock); ret = xine_play_internal (stream, start_pos, start_time/1000); + if( stream->slave ) + xine_play (stream->slave, start_pos, start_time/1000); pthread_mutex_unlock (&stream->frontend_lock); @@ -857,7 +911,8 @@ void xine_dispose (xine_stream_t *stream) { video_decoder_shutdown (stream); stream->osd_renderer->close( stream->osd_renderer ); - stream->video_out->exit (stream->video_out); + /* it makes no sense to dispose a video port on stream dispose */ + /* stream->video_out->exit (stream->video_out); */ stream->video_fifo->dispose (stream->video_fifo); pthread_mutex_destroy (&stream->frontend_lock); @@ -1305,8 +1360,8 @@ int xine_trick_mode (xine_stream_t *stream, int mode, int value) { int xine_stream_master_slave(xine_stream_t *master, xine_stream_t *slave, int affection) { - master->slave_stream = slave; - slave->master_stream = master; + master->slave = slave; + slave->master = master; return 1; } diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 959f41469..307c6aaaa 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.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_interface.c,v 1.37 2002/12/27 22:49:38 esnel Exp $ + * $Id: xine_interface.c,v 1.38 2003/01/13 02:15:07 miguelfreitas Exp $ * * convenience/abstraction layer, functions to implement * libxine's public interface @@ -322,6 +322,10 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_AV_OFFSET: stream->metronom->set_option (stream->metronom, METRONOM_AV_OFFSET, value); break; + + case XINE_PARAM_SPU_OFFSET: + stream->metronom->set_option (stream->metronom, METRONOM_SPU_OFFSET, value); + break; case XINE_PARAM_AUDIO_CHANNEL_LOGICAL: pthread_mutex_lock (&stream->frontend_lock); @@ -402,6 +406,9 @@ int xine_get_param (xine_stream_t *stream, int param) { case XINE_PARAM_AV_OFFSET: return stream->metronom->get_option (stream->metronom, METRONOM_AV_OFFSET); + + case XINE_PARAM_SPU_OFFSET: + return stream->metronom->get_option (stream->metronom, METRONOM_SPU_OFFSET); case XINE_PARAM_AUDIO_CHANNEL_LOGICAL: return stream->audio_channel_user; diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index cc10e167d..7aeeff679 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_internal.h,v 1.124 2003/01/11 03:47:01 miguelfreitas Exp $ + * $Id: xine_internal.h,v 1.125 2003/01/13 02:15:07 miguelfreitas Exp $ * */ @@ -212,8 +212,8 @@ struct xine_stream_s { /* master/slave streams */ - xine_stream_t *master_stream; - xine_stream_t *slave_stream; + xine_stream_t *master; + xine_stream_t *slave; /* seeking slowdown */ int first_frame_flag; @@ -245,6 +245,8 @@ struct xine_stream_s { xine_post_out_t video_source; xine_post_out_t audio_source; + int slave_is_subtitle; /* ... and will be automaticaly disposed */ + int err; }; -- cgit v1.2.3