summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-01-11 03:47:01 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-01-11 03:47:01 +0000
commit9d4ebc4801effe30c2af538d00864993299e06fe (patch)
tree63ab498c0e5b5e8d7664c3b6fdebff5691e4fdb8
parent263770caece699a5677a9017fa668c2ff30f4f76 (diff)
downloadxine-lib-9d4ebc4801effe30c2af538d00864993299e06fe.tar.gz
xine-lib-9d4ebc4801effe30c2af538d00864993299e06fe.tar.bz2
brand-new external subtitles support. (yes, it works!)
tested with asf, avi and mpeg but any media should work. todo: - clean up the master/slave stuff and public api. - implement seeking on demux_sputext.c (it must seek to closest subtitle) - general cleaning up and bugfixing CVS patchset: 3860 CVS date: 2003/01/11 03:47:01
-rw-r--r--src/libsputext/demux_sputext.c6
-rw-r--r--src/libsputext/xine_decoder.c305
-rw-r--r--src/xine-engine/audio_out.c7
-rw-r--r--src/xine-engine/metronom.c10
-rw-r--r--src/xine-engine/metronom.h3
-rw-r--r--src/xine-engine/video_out.c7
-rw-r--r--src/xine-engine/xine.c23
-rw-r--r--src/xine-engine/xine_internal.h9
8 files changed, 214 insertions, 156 deletions
diff --git a/src/libsputext/demux_sputext.c b/src/libsputext/demux_sputext.c
index 11e956dad..f95ce177e 100644
--- a/src/libsputext/demux_sputext.c
+++ b/src/libsputext/demux_sputext.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_sputext.c,v 1.6 2003/01/10 22:23:54 miguelfreitas Exp $
+ * $Id: demux_sputext.c,v 1.7 2003/01/11 03:47:01 miguelfreitas Exp $
*
* code based on old libsputext/xine_decoder.c
*
@@ -819,8 +819,8 @@ static int demux_sputext_next (demux_sputext_t *this_gen) {
val = (uint32_t * )buf->content;
*val++ = sub->lines;
*val++ = this->uses_time;
- *val++ = sub->start * 10;
- *val++ = sub->end * 10;
+ *val++ = (this->uses_time) ? sub->start * 10 : sub->start;
+ *val++ = (this->uses_time) ? sub->end * 10 : sub->end;
str = (char *)val;
for (line = 0; line < sub->lines; line++, str+=strlen(str)+1) {
if( strlen(sub->text[line]) > SUB_BUFSIZE )
diff --git a/src/libsputext/xine_decoder.c b/src/libsputext/xine_decoder.c
index e4db27b16..d6b3d3666 100644
--- a/src/libsputext/xine_decoder.c
+++ b/src/libsputext/xine_decoder.c
@@ -17,15 +17,8 @@
* 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.42 2003/01/10 22:23:54 miguelfreitas Exp $
+ * $Id: xine_decoder.c,v 1.43 2003/01/11 03:47:01 miguelfreitas Exp $
*
- * code based on mplayer module:
- *
- * Subtitle reader with format autodetection
- *
- * Written by laaz
- * Some code cleanup & realloc() by A'rpi/ESP-team
- * dunnowhat sub format by szabi
*/
#include <stdlib.h>
@@ -77,6 +70,7 @@ typedef struct sputext_decoder_s {
int output_open;
+ int lines;
char text[SUB_MAX_TEXT][SUB_BUFSIZE];
float mpsub_position;
@@ -85,7 +79,6 @@ typedef struct sputext_decoder_s {
int height; /* frame height */
int font_size;
int line_height;
- int uses_time;
char *font;
@@ -95,6 +88,7 @@ typedef struct sputext_decoder_s {
osd_renderer_t *renderer;
osd_object_t *osd;
+ int64_t img_duration;
int64_t last_subtitle_end; /* no new subtitle before this vpts */
} sputext_decoder_t;
@@ -135,154 +129,181 @@ static void update_font_size (sputext_decoder_t *this) {
}
}
-static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
- sputext_decoder_t *this = (sputext_decoder_t *) this_gen;
- int64_t current_time;
- uint32_t start, end;
+static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t sub_end ) {
- if( !this->width || !this->height || !this->renderer ) {
-
+ int line, y;
+ int font_size;
+
+ this->renderer->filled_rect (this->osd, 0, 0, this->width-1, this->line_height * SUB_MAX_TEXT - 1, 0);
+
+ y = (SUB_MAX_TEXT - this->lines) * this->line_height;
+ font_size = this->font_size;
+
+ for (line=0; line<this->lines; line++) {
+ int w,h,x;
+
+ while(1) {
+ this->renderer->get_text_size( this->osd, this->text[line],
+ &w, &h);
+ x = (this->width - w) / 2;
+
+ if( w > this->width && font_size > 16 ) {
+ font_size -= 4;
+ this->renderer->set_font (this->osd, this->font, font_size);
+ } else {
+ break;
+ }
+ }
+
+ this->renderer->render_text (this->osd, x, y + line*this->line_height,
+ this->text[line], OSD_TEXT1);
}
+
+ if( font_size != this->font_size )
+ this->renderer->set_font (this->osd, this->font, this->font_size);
+
+ if( this->last_subtitle_end && sub_start < this->last_subtitle_end ) {
+ sub_start = this->last_subtitle_end;
+ }
+ this->last_subtitle_end = sub_end;
+
+ this->renderer->set_text_palette (this->osd, -1, OSD_TEXT1);
+ this->renderer->show (this->osd, sub_start);
+ this->renderer->hide (this->osd, sub_end);
+
+//#ifdef LOG
+ printf ("sputext: scheduling subtitle >%s< at %lld until %lld, current time is %lld\n",
+ this->text[0], sub_start, sub_end,
+ this->stream->xine->clock->get_current_time (this->stream->xine->clock));
+//#endif
+}
-#if 0
- if (buf->decoder_flags & BUF_FLAG_HEADER) {
- this->width = buf->decoder_info[1];
- this->height = buf->decoder_info[2];
-
- this->renderer = this->stream->osd_renderer;
- this->osd = NULL;
-
- update_font_size (this);
-
- current_time = this->stream->xine->clock->get_current_time (this->stream->xine->clock);
- this->renderer->show (this->osd, current_time);
- this->renderer->hide (this->osd, current_time+300000);
-
- } else {
- int64_t sub_start, sub_end;
+static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
- /* don't want to see subtitle */
- if(this->stream->spu_channel_user == -2)
- return;
+ sputext_decoder_t *this = (sputext_decoder_t *) this_gen;
+ int uses_time;
+ int32_t start, end, diff;
+ int64_t start_vpts, end_vpts;
+ int i;
+ uint32_t *val;
+ char *str;
+ extra_info_t extra_info;
+ int seek_count;
+ int status;
+
+ val = (uint32_t * )buf->content;
+ this->lines = *val++;
+ uses_time = *val++;
+ start = *val++;
+ end = *val++;
+ str = (char *)val;
+ for (i = 0; i < this->lines; i++, str+=strlen(str)+1) {
+ strcpy( this->text[i], str );
+ }
+
+ printf("libsputext: decoder data [%s]\n", this->text[0]);
+ printf("libsputext: mode %d timming %d->%d\n", uses_time, start, end);
+ if( end <= start ) {
+ printf("libsputext: discarding subtitle with invalid timming\n");
+ }
+
+ 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) );
+ seek_count = extra_info.seek_count;
- /*
- * find out which subtitle to display
- */
- if (!this->uses_time) {
- int frame_num;
- int64_t pts_factor;
- long frame_offset;
-
- frame_num = buf->decoder_info[1];
-
- /* FIXME FIXME FIXME
- pts_factor = this->stream->metronom->get_video_rate (this->stream->metronom);
- */
- pts_factor = 3000;
-
- frame_offset = this->time_offset * 900 / pts_factor;
-
- while ( (this->cur < this->num)
- && (this->text[this->cur].start + frame_offset < frame_num) )
- this->cur++;
-
- if (this->cur >= this->num)
- return;
-
- subtitle = &this->subtitles[this->cur];
-
- if (subtitle->start + frame_offset > frame_num)
- return;
-
- sub_start = this->stream->metronom->got_spu_packet(this->stream->metronom, buf->pts);
- sub_end = sub_start + (subtitle->end - subtitle->start) * pts_factor;
-
- } else {
- uint32_t start_tenth;
-
- start_tenth = buf->pts/900;
-
-#ifdef LOG
- printf ("sputext: searching for spu for %d\n", start_tenth);
-#endif
-
- while ( (this->cur < this->num)
- && (this->subtitles[this->cur].start + this->time_offset < start_tenth) )
- this->cur++;
-
- if (this->cur >= this->num)
- return;
-
-#ifdef LOG
- printf ("sputext: found >%s<, start %ld, end %ld\n", this->subtitles[this->cur].text[0],
- this->subtitles[this->cur].start + this->time_offset, this->subtitles[this->cur].end);
-#endif
-
- subtitle = &this->subtitles[this->cur];
-
- if (subtitle->start + this->time_offset > (start_tenth+20))
- return;
-
- sub_start = this->stream->metronom->got_spu_packet(this->stream->metronom, (subtitle->start+this->time_offset)*900);
- sub_end = sub_start + (subtitle->end - subtitle->start)*900;
+ do {
+
+ /* initialize decoder if needed */
+ if( !this->width || !this->height ) {
+
+ if( this->stream->video_out->status(this->stream->video_out, NULL,
+ &this->width, &this->height )) {
+
+ if( this->width && this->height ) {
+ this->renderer = this->stream->osd_renderer;
+
+ if( this->stream->master_stream )
+ this->img_duration = this->stream->master_stream->metronom->get_option(
+ this->stream->master_stream->metronom, METRONOM_FRAME_DURATION);
+ else
+ this->img_duration = this->stream->metronom->get_option(
+ this->stream->metronom, METRONOM_FRAME_DURATION);
+
+ this->osd = NULL;
+
+ update_font_size (this);
+ }
+ }
}
-
- if( !sub_start )
- return;
-
- if (subtitle) {
- int line, y;
- int font_size;
-
- this->renderer->filled_rect (this->osd, 0, 0, this->width-1, this->line_height * SUB_MAX_TEXT - 1, 0);
-
- y = (SUB_MAX_TEXT - subtitle->lines) * this->line_height;
- font_size = this->font_size;
+
+ if( this->osd && this->last_subtitle_end < extra_info.vpts ) {
- for (line=0; line<subtitle->lines; line++) {
- int w,h,x;
+ /* try to use frame number mode */
+ if( !uses_time && extra_info.frame_number ) {
+
+ diff = end - extra_info.frame_number;
- while(1) {
- this->renderer->get_text_size( this->osd, subtitle->text[line],
- &w, &h);
- x = (this->width - w) / 2;
+ /* discard old subtitles */
+ if( diff < 0 )
+ return;
- if( w > this->width && font_size > 16 ) {
- font_size -= 4;
- this->renderer->set_font (this->osd, this->font, font_size);
- } else {
- break;
- }
+ diff = start - extra_info.frame_number;
+
+ /* draw it if less than 2 seconds left */
+ if( diff < 2*90000 / this->img_duration ) {
+ start_vpts = extra_info.vpts + diff * this->img_duration;
+ end_vpts = start_vpts + (end-start) * this->img_duration;
+
+ draw_subtitle(this, start_vpts, end_vpts);
+ return;
}
- this->renderer->render_text (this->osd, x, y + line*this->line_height, subtitle->text[line], OSD_TEXT1);
- }
-
- if( font_size != this->font_size )
- this->renderer->set_font (this->osd, this->font, this->font_size);
-
- if( this->last_subtitle_end && sub_start < this->last_subtitle_end ) {
- sub_start = this->last_subtitle_end;
- }
- this->last_subtitle_end = sub_end;
+ } else {
- this->renderer->set_text_palette (this->osd, -1, OSD_TEXT1);
- this->renderer->show (this->osd, sub_start);
- this->renderer->hide (this->osd, sub_end);
-
-#ifdef LOG
- printf ("sputext: scheduling subtitle >%s< at %lld until %lld, current time is %lld\n",
- subtitle->text[0], sub_start, sub_end,
- this->stream->metronom->get_current_time (this->stream->metronom));
-#endif
-
+ if( !uses_time ) {
+ start = start * this->img_duration / 90;
+ end = end * this->img_duration / 90;
+ uses_time = 1;
+ }
+
+ diff = end - extra_info.input_time;
+
+ /* discard old subtitles */
+ if( diff < 0 )
+ return;
+
+ diff = start - extra_info.input_time;
+
+ /* draw it if less than 2 seconds left */
+ if( diff < 2000 ) {
+ start_vpts = extra_info.vpts + diff * 90;
+ end_vpts = start_vpts + (end-start) * 90;
+
+ draw_subtitle(this, start_vpts, end_vpts);
+ return;
+ }
+ }
}
- this->cur++;
- }
-#endif
+
+ 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) );
+
+ if( this->stream->master_stream )
+ status = xine_get_status (this->stream->master_stream);
+ else
+ status = xine_get_status (this->stream);
+
+ } while(seek_count == extra_info.seek_count && status != XINE_STATUS_QUIT &&
+ status != XINE_STATUS_STOP);
}
@@ -395,6 +416,8 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) {
sputext_class_t *this ;
+ printf("libsputext: init class\n");
+
this = (sputext_class_t *) xine_xmalloc (sizeof (sputext_class_t));
this->class.open_plugin = sputext_class_open_plugin;
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index 7cb1e1d74..b98fe7940 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.97 2003/01/10 19:15:16 miguelfreitas Exp $
+ * $Id: audio_out.c,v 1.98 2003/01/11 03:47:01 miguelfreitas Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -913,7 +913,8 @@ static void ao_put_buffer (xine_audio_port_t *this_gen,
buf->vpts = stream->metronom->got_audio_samples (stream->metronom, pts,
buf->num_frames);
-
+ buf->extra_info->vpts = buf->vpts;
+
#ifdef LOG
printf ("audio_out: ao_put_buffer, pts=%lld, vpts=%lld\n",
pts, buf->vpts);
@@ -1137,7 +1138,7 @@ static int ao_status (xine_audio_port_t *this_gen, xine_stream_t *stream,
pthread_mutex_lock(&this->streams_lock);
for (cur = xine_list_first_content(this->streams); cur;
cur = xine_list_next_content(this->streams))
- if (cur == stream) {
+ if (cur == stream || !stream) {
*bits = this->input.bits;
*rate = this->input.rate;
*mode = this->input.mode;
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index 92c209ede..b76c07ce9 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.108 2002/12/23 10:03:50 miguelfreitas Exp $
+ * $Id: metronom.c,v 1.109 2003/01/11 03:47:01 miguelfreitas Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -398,6 +398,8 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
this->img_cpt = 0;
this->last_video_pts = pts;
img->duration = this->img_duration;
+ } else {
+ this->img_duration = img->duration;
}
@@ -439,7 +441,9 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
} else {
if (!img->duration) {
img->duration = this->img_duration;
- }
+ } else {
+ this->img_duration = img->duration;
+ }
}
@@ -618,6 +622,8 @@ static int64_t metronom_get_option (metronom_t *this, int option) {
switch (option) {
case METRONOM_AV_OFFSET:
return this->av_offset;
+ case METRONOM_FRAME_DURATION:
+ return this->img_duration;
}
printf ("metronom: unknown option in get_option: %d\n",
option);
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h
index 949729010..3cc17aab6 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.41 2002/11/20 11:57:49 mroi Exp $
+ * $Id: metronom.h,v 1.42 2003/01/11 03:47:01 miguelfreitas Exp $
*
* metronom: general pts => virtual calculation/assoc
*
@@ -206,6 +206,7 @@ struct metronom_s {
#define METRONOM_AV_OFFSET 2
#define METRONOM_ADJ_VPTS_OFFSET 3
+#define METRONOM_FRAME_DURATION 4
metronom_t *metronom_init (int have_audio, xine_stream_t *stream);
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 7610a5a07..336242c3d 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.132 2003/01/10 19:15:16 miguelfreitas Exp $
+ * $Id: video_out.c,v 1.133 2003/01/11 03:47:01 miguelfreitas Exp $
*
* frame allocation / queuing / scheduling / output functions
*/
@@ -306,7 +306,8 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
stream->metronom->got_video_frame (stream->metronom, img);
pic_vpts = img->vpts;
-
+ img->extra_info->vpts = img->vpts;
+
cur_vpts = this->clock->get_current_time(this->clock);
this->last_delivery_pts = cur_vpts;
@@ -963,7 +964,7 @@ static int vo_status (xine_video_port_t *this_gen, xine_stream_t *stream,
pthread_mutex_lock(&this->streams_lock);
for (cur = xine_list_first_content(this->streams); cur;
cur = xine_list_next_content(this->streams))
- if (cur == stream) {
+ if (cur == stream || !stream) {
*width = this->current_width;
*height = this->current_height;
ret = 1;
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index be02eff0c..2df867c5d 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.212 2003/01/10 21:11:12 miguelfreitas Exp $
+ * $Id: xine.c,v 1.213 2003/01/11 03:47:01 miguelfreitas Exp $
*
* top-level xine functions
*
@@ -107,6 +107,9 @@ void extra_info_merge( extra_info_t *dst, extra_info_t *src ) {
if( src->seek_count )
dst->seek_count = src->seek_count;
+
+ if( src->vpts )
+ dst->vpts = src->vpts;
}
static void xine_set_speed_internal (xine_stream_t *stream, int speed) {
@@ -1029,13 +1032,22 @@ static int xine_get_current_position (xine_stream_t *stream) {
pthread_mutex_unlock( &stream->current_extra_info_lock );
if (len == 0) len = stream->input_plugin->get_length (stream->input_plugin);
- share /= (double) len * 65536;
+ share /= (double) len;
+ share *= 65536;
pthread_mutex_unlock (&stream->frontend_lock);
return (int) share;
}
+void xine_get_current_info (xine_stream_t *stream, extra_info_t *extra_info, int size) {
+
+ pthread_mutex_lock( &stream->current_extra_info_lock );
+ memcpy( extra_info, stream->current_extra_info, size );
+ pthread_mutex_unlock( &stream->current_extra_info_lock );
+}
+
+
int xine_get_status (xine_stream_t *stream) {
return stream->status;
}
@@ -1289,3 +1301,10 @@ int xine_trick_mode (xine_stream_t *stream, int mode, int value) {
abort ();
}
+int xine_stream_master_slave(xine_stream_t *master, xine_stream_t *slave,
+ int affection) {
+ master->slave_stream = slave;
+ slave->master_stream = master;
+ return 1;
+}
+
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index c046b92d8..cc10e167d 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.123 2003/01/10 19:15:17 miguelfreitas Exp $
+ * $Id: xine_internal.h,v 1.124 2003/01/11 03:47:01 miguelfreitas Exp $
*
*/
@@ -210,6 +210,11 @@ struct xine_stream_s {
int stream_info[XINE_STREAM_INFO_MAX];
char *meta_info [XINE_STREAM_INFO_MAX];
+
+ /* master/slave streams */
+ xine_stream_t *master_stream;
+ xine_stream_t *slave_stream;
+
/* seeking slowdown */
int first_frame_flag;
pthread_mutex_t first_frame_lock;
@@ -269,6 +274,8 @@ void audio_decoder_shutdown (xine_stream_t *stream);
void extra_info_reset( extra_info_t *extra_info );
void extra_info_merge( extra_info_t *dst, extra_info_t *src );
+
+void xine_get_current_info (xine_stream_t *stream, extra_info_t *extra_info, int size);
/* demuxer helper functions from demux.c */