summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Heinchen <heinchen@users.sourceforge.net>2003-04-16 23:05:25 +0000
committerAndreas Heinchen <heinchen@users.sourceforge.net>2003-04-16 23:05:25 +0000
commitf3258d2a32d2cbfb887d2f048ead4dd45b73d114 (patch)
treeed9c41bfe4a494b38acb60f7213c527b03927e88
parent4bb76c8facd16a1bcaa354476775fdd3904e7386 (diff)
downloadxine-lib-f3258d2a32d2cbfb887d2f048ead4dd45b73d114.tar.gz
xine-lib-f3258d2a32d2cbfb887d2f048ead4dd45b73d114.tar.bz2
preperations for support of bold and italic typefaces in ogm subtitles
CVS patchset: 4629 CVS date: 2003/04/16 23:05:25
-rw-r--r--src/demuxers/demux_ogg.c43
-rw-r--r--src/libsputext/Makefile.am4
-rw-r--r--src/libsputext/xine_decoder_ogm.c565
-rw-r--r--src/xine-engine/buffer.h3
4 files changed, 576 insertions, 39 deletions
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c
index d39544bdf..985ed9f78 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.80 2003/04/15 23:54:40 heinchen Exp $
+ * $Id: demux_ogg.c,v 1.81 2003/04/16 23:05:25 heinchen Exp $
*
* demultiplexer for ogg streams
*
@@ -358,46 +358,13 @@ static void send_ogg_buf (demux_ogg_t *this,
val = (uint32_t * )buf->content;
- /*num_lines will be set later, when we know the correct value*/
- *val++ = 0;
-
- /*times are in ms*/
- *val++ = 1;
*val++ = start;
*val++ = end;
str = (char *)val;
- for ( i=0, ignore=0, lines=0 ; i<strlen(subtitle) ; i++ ) {
- /*fixme: the maximum SUB_BUFSIZE isn't considered*/
- /*fixme: font tags aren't ignored correctly*/
- switch (subtitle[i]) {
- case '<':
- ignore=1;
- break;
- case '>':
- ignore=0;
- break;
- case 13:
- if (ignore==0) {
- str[0]=0;
- lines++;
- str+=1;
- }
- break;
- default:
- if (ignore==0) {
- str[0]=subtitle[i];
- str+=1;
- }
- break;
- }
- str[0]=0;
- }
-
- val = (uint32_t * )buf->content;
- *val = lines;
-
- this->video_fifo->put (this->video_fifo, buf);
+ memcpy (str, subtitle, 1+strlen(subtitle));
+
+ this->video_fifo->put (this->video_fifo, buf);
}
}
}
@@ -800,7 +767,7 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
#endif
this->preview_buffers[stream_num] = 2;
channel= this->num_spu_streams++;
- this->buf_types[stream_num] = BUF_SPU_TEXT | channel;
+ this->buf_types[stream_num] = BUF_SPU_OGM | channel;
} else {
printf ("demux_ogg: unknown stream type (signature >%.8s<). hex dump of bos packet follows:\n",
op.packet);
diff --git a/src/libsputext/Makefile.am b/src/libsputext/Makefile.am
index f4e99aec1..2612723e3 100644
--- a/src/libsputext/Makefile.am
+++ b/src/libsputext/Makefile.am
@@ -17,6 +17,10 @@ xineplug_decode_sputext_la_SOURCES = xine_decoder.c
xineplug_decode_sputext_la_LIBADD = $(XINELIB)
xineplug_decode_sputext_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
+xineplug_decode_spuogm_la_SOURCES = xine_decoder_ogm.c
+xineplug_decode_spuogm_la_LIBADD = $(XINELIB)
+xineplug_decode_spuogm_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
+
##
## Install header files (default=$includedir/xine)
##
diff --git a/src/libsputext/xine_decoder_ogm.c b/src/libsputext/xine_decoder_ogm.c
new file mode 100644
index 000000000..06f5688d4
--- /dev/null
+++ b/src/libsputext/xine_decoder_ogm.c
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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_ogm.c,v 1.1 2003/04/16 23:06:38 heinchen Exp $
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include "buffer.h"
+#include "xine_internal.h"
+#include "xineutils.h"
+#include "osd.h"
+
+/*
+#define LOG 1
+*/
+
+#define SUB_MAX_TEXT 5
+
+
+#define SUB_BUFSIZE 1024
+
+typedef enum {
+ SUBTITLE_SIZE_SMALL = 0,
+ SUBTITLE_SIZE_NORMAL,
+ SUBTITLE_SIZE_LARGE,
+
+ SUBTITLE_SIZE_NUM /* number of values in enum */
+} subtitle_size;
+
+
+typedef struct spuogm_class_s {
+ spu_decoder_class_t class;
+
+ char *src_encoding; /* encoding of subtitle file */
+
+ xine_t *xine;
+
+} spuogm_class_t;
+
+
+typedef struct spuogm_decoder_s {
+ spu_decoder_t spu_decoder;
+
+ spuogm_class_t *class;
+ xine_stream_t *stream;
+
+ int lines;
+ char text[SUB_MAX_TEXT][SUB_BUFSIZE];
+
+ int width; /* frame width */
+ int height; /* frame height */
+ int font_size;
+ int line_height;
+ int seek_count;
+ int master_started;
+ int slave_started;
+
+ char *font; /* subtitle font */
+ subtitle_size subtitle_size; /* size of subtitles */
+ int vertical_offset;
+
+ osd_renderer_t *renderer;
+ osd_object_t *osd;
+
+ int64_t img_duration;
+ int64_t last_subtitle_end; /* no new subtitle before this vpts */
+} spuogm_decoder_t;
+
+
+static void update_font_size (spuogm_decoder_t *this) {
+ static int sizes[SUBTITLE_SIZE_NUM][4] = {
+ { 16, 16, 16, 20 }, /* SUBTITLE_SIZE_SMALL */
+ { 16, 16, 20, 24 }, /* SUBTITLE_SIZE_NORMAL */
+ { 16, 20, 24, 32 }, /* SUBTITLE_SIZE_LARGE */
+ };
+
+ int *vec = sizes[this->subtitle_size];
+ int y;
+
+ if( this->width >= 512 )
+ this->font_size = vec[3];
+ else if( this->width >= 384 )
+ this->font_size = vec[2];
+ else if( this->width >= 320 )
+ this->font_size = vec[1];
+ else
+ this->font_size = vec[0];
+
+ this->line_height = this->font_size + 10;
+
+ y = this->height - (SUB_MAX_TEXT * this->line_height) - 5;
+
+ if(((y - this->vertical_offset) >= 0) && ((y - this->vertical_offset) <= this->height))
+ y -= this->vertical_offset;
+
+ if( this->osd )
+ this->renderer->free_object (this->osd);
+
+ if(this->renderer) {
+ this->osd = this->renderer->new_object (this->renderer,
+ this->width,
+ SUB_MAX_TEXT * this->line_height);
+
+ this->renderer->set_font (this->osd, this->font, this->font_size);
+ this->renderer->set_position (this->osd, 0, y);
+ }
+}
+
+static int get_width(spuogm_decoder_t *this, char* text) {
+ int i=0,width=0,w,dummy;
+ char letter[2]={0, 0};
+
+ while (i<=strlen(text)) {
+ switch (text[i]) {
+ case '<':
+ if (!strncmp("<b>", text+i, 3)) {
+ /*Do somethink to enable BOLD typeface*/
+ i=i+3;
+ break;
+ } else if (!strncmp("</b>", text+i, 3)) {
+ /*Do somethink to disable BOLD typeface*/
+ i=i+4;
+ break;
+ } else if (!strncmp("<i>", text+i, 3)) {
+ /*Do somethink to enable italics typeface*/
+ i=i+3;
+ break;
+ } else if (!strncmp("</i>", text+i, 3)) {
+ /*Do somethink to disable italics typeface*/
+ i=i+4;
+ break;
+ } else if (!strncmp("<font>", text+i, 3)) {
+ /*Do somethink to disable typing
+ fixme - no teststreams*/
+ i=i+6;
+ break;
+ } else if (!strncmp("</font>", text+i, 3)) {
+ /*Do somethink to enable typing
+ fixme - no teststreams*/
+ i=i+7;
+ break;
+ }
+default:
+ letter[0]=text[i];
+ this->renderer->get_text_size( this->osd, letter, &w, &dummy);
+ width=width+w;
+ i++;
+ }
+ }
+
+ return width;
+}
+
+static void render_line(spuogm_decoder_t *this, int x, int y, char* text) {
+ int i=0,w,dummy;
+ char letter[2]={0,0};
+
+ while (i<=strlen(text)) {
+ switch (text[i]) {
+ case '<':
+ if (!strncmp("<b>", text+i, 3)) {
+ /*Do somethink to enable BOLD typeface*/
+ i=i+3;
+ break;
+ } else if (!strncmp("</b>", text+i, 3)) {
+ /*Do somethink to disable BOLD typeface*/
+ i=i+4;
+ break;
+ } else if (!strncmp("<i>", text+i, 3)) {
+ /*Do somethink to enable italics typeface*/
+ i=i+3;
+ break;
+ } else if (!strncmp("</i>", text+i, 3)) {
+ /*Do somethink to disable italics typeface*/
+ i=i+4;
+ break;
+ } else if (!strncmp("<font>", text+i, 3)) {
+ /*Do somethink to disable typing
+ fixme - no teststreams*/
+ i=i+6;
+ break;
+ } else if (!strncmp("</font>", text+i, 3)) {
+ /*Do somethink to enable typing
+ fixme - no teststreams*/
+ i=i+7;
+ break;
+ }
+ default:
+ letter[0]=text[i];
+ this->renderer->render_text( this->osd, x, y, letter,
+ this->class->src_encoding,OSD_TEXT1);
+ this->renderer->get_text_size( this->osd, letter, &w, &dummy);
+ x=x+w;
+ i++;
+ }
+ }
+}
+
+static void draw_subtitle(spuogm_decoder_t *this, int64_t sub_start, int64_t sub_end ) {
+
+ 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,x;
+
+ while(1) {
+ w=get_width( this, this->text[line]);
+ 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;
+ }
+ }
+ render_line(this, x, y + line*this->line_height, this->text[line]);
+ }
+
+ 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 ("spuogm: 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
+}
+
+
+static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
+
+ spuogm_decoder_t *this = (spuogm_decoder_t *) this_gen;
+ int32_t start, end, diff;
+ int64_t start_vpts, end_vpts;
+ int64_t spu_offset;
+ int i;
+ uint32_t *val;
+ char *str;
+ extra_info_t extra_info;
+ int status;
+
+ /* filter unwanted streams */
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW)
+ return;
+ if ((this->stream->spu_channel & 0x1f) != (buf->type & 0x1f))
+ return;
+
+ val = (uint32_t * )buf->content;
+ start = *val++;
+ end = *val++;
+ str = (char *)val;
+
+ this->lines=0;
+
+
+ i=0;
+ while (i<strlen(str)+1) {
+ switch (str[i]) {
+ case 13:
+ str=&str[i+1];
+ this->text[ this->lines ][i]=0;
+ this->lines=this->lines+1;
+ i=0;
+ break;
+ default:
+ this->text[ this->lines ][i]=str[i];
+ if (i<SUB_BUFSIZE-1)
+ i++;
+ }
+ }
+
+#ifdef LOG
+ printf("libspuogm: decoder data [%s]\n", this->text[0]);
+ printf("libspuogm: timing %d->%d\n", start, end);
+#endif
+
+ if( end <= start ) {
+#ifdef LOG
+ printf("libspuogm: discarding subtitle with invalid timing\n");
+#endif
+ }
+
+ spu_offset = this->stream->master->metronom->get_option (this->stream->master->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;
+ }
+
+ while(this->seek_count == extra_info.seek_count) {
+
+ /* initialize decoder if needed */
+ 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 )) {
+
+ if( this->width && this->height && this->img_duration ) {
+ this->renderer = this->stream->osd_renderer;
+
+ update_font_size (this);
+ }
+ }
+ }
+
+ if( this->osd ) {
+
+ diff = end - extra_info.input_time;
+
+ /* discard old subtitles */
+ if( diff < 0 ) {
+#ifdef LOG
+ printf("libspuogm: discarding old\n");
+#endif
+ 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;
+ }
+ }
+
+ status = xine_get_status (this->stream->master);
+
+ if( this->master_started && (status == XINE_STATUS_QUIT ||
+ status == XINE_STATUS_STOP) ) {
+#ifdef LOG
+ printf("libspuogm: master stopped\n");
+#endif
+ this->width = this->height = 0;
+ return;
+ }
+ if( status == XINE_STATUS_PLAY )
+ this->master_started = 1;
+
+ status = xine_get_status (this->stream);
+
+ if( this->slave_started && (status == XINE_STATUS_QUIT ||
+ status == XINE_STATUS_STOP) ) {
+#ifdef LOG
+ printf("libspuogm: slave stopped\n");
+#endif
+ this->width = this->height = 0;
+ return;
+ }
+ if( status == XINE_STATUS_PLAY )
+ this->slave_started = 1;
+
+ xine_usec_sleep (50000);
+
+ xine_get_current_info (this->stream->master, &extra_info, sizeof(extra_info) );
+ }
+#ifdef LOG
+ printf("libspuogm: seek_count mismatch\n");
+#endif
+}
+
+
+static void spudec_reset (spu_decoder_t *this_gen) {
+ spuogm_decoder_t *this = (spuogm_decoder_t *) this_gen;
+
+ this->width = this->height = 0;
+ this->seek_count = 0;
+}
+
+static void spudec_discontinuity (spu_decoder_t *this_gen) {
+ /* spuogm_decoder_t *this = (spuogm_decoder_t *) this_gen; */
+
+}
+
+static void spudec_dispose (spu_decoder_t *this_gen) {
+ spuogm_decoder_t *this = (spuogm_decoder_t *) this_gen;
+
+ if (this->osd) {
+ this->renderer->free_object (this->osd);
+ this->osd = NULL;
+ }
+ free(this);
+}
+
+static void update_vertical_offset(void *this_gen, xine_cfg_entry_t *entry)
+{
+ spuogm_decoder_t *this = (spuogm_decoder_t *)this_gen;
+
+ this->vertical_offset = entry->num_value;
+ update_font_size(this);
+}
+
+static void update_osd_font(void *this_gen, xine_cfg_entry_t *entry)
+{
+ spuogm_decoder_t *this = (spuogm_decoder_t *)this_gen;
+
+ this->font = entry->str_value;
+
+ if( this->renderer )
+ this->renderer->set_font (this->osd, this->font, this->font_size);
+
+ printf("libspuogm: spu_font = %s\n", this->font );
+}
+
+static void update_subtitle_size(void *this_gen, xine_cfg_entry_t *entry)
+{
+ spuogm_decoder_t *this = (spuogm_decoder_t *)this_gen;
+
+ this->subtitle_size = entry->num_value;
+
+ update_font_size (this_gen);
+}
+
+static spu_decoder_t *spuogm_class_open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream) {
+
+#ifdef LOG
+ printf ("libspuogm: plugin opened\n");
+#endif
+
+ spuogm_class_t *class = (spuogm_class_t *)class_gen;
+ spuogm_decoder_t *this ;
+ static char *subtitle_size_strings[] = { "small", "normal", "large", NULL };
+
+ this = (spuogm_decoder_t *) xine_xmalloc (sizeof (spuogm_decoder_t));
+
+ this->spu_decoder.decode_data = spudec_decode_data;
+ this->spu_decoder.reset = spudec_reset;
+ this->spu_decoder.discontinuity = spudec_discontinuity;
+ this->spu_decoder.dispose = spudec_dispose;
+ this->spu_decoder.get_nav_pci = NULL;
+ this->spu_decoder.set_button = NULL;
+ this->spu_decoder.dispose = spudec_dispose;
+
+ this->class = class;
+ this->stream = stream;
+
+ this->font = class->xine->config->register_string(class->xine->config,
+ "misc.spu_font",
+ "sans",
+ _("font for external subtitles"),
+ NULL, 0, update_osd_font, this);
+ this->subtitle_size = class->xine->config->register_enum(class->xine->config,
+ "misc.spu_subtitle_size",
+ 1,
+ subtitle_size_strings,
+ _("subtitle size (relative window size)"),
+ NULL, 0, update_subtitle_size, this);
+
+ this->vertical_offset = class->xine->config->register_num(class->xine->config,
+ "misc.spu_vertical_offset",
+ 0,
+ _("subtitle vertical offset (relative window size)"),
+ NULL, 0, update_vertical_offset, this);
+
+ return (spu_decoder_t *) this;
+}
+
+static void spuogm_class_dispose (spu_decoder_class_t *this) {
+ free (this);
+}
+
+static char *spuogm_class_get_identifier (spu_decoder_class_t *this) {
+ return "spuogm";
+}
+
+static char *spuogm_class_get_description (spu_decoder_class_t *this) {
+ return "ogm subtitle decoder plugin";
+}
+
+static void update_src_encoding(void *this_gen, xine_cfg_entry_t *entry)
+{
+ spuogm_class_t *this = (spuogm_class_t *)this_gen;
+
+ this->src_encoding = entry->str_value;
+ printf("libspuogm: spu_src_encoding = %s\n", this->src_encoding );
+}
+
+static void *init_spu_decoder_plugin (xine_t *xine, void *data) {
+
+ spuogm_class_t *this ;
+
+#ifdef LOG
+ printf("libspuogm: init class\n");
+#endif
+
+ this = (spuogm_class_t *) xine_xmalloc (sizeof (spuogm_class_t));
+
+ this->class.open_plugin = spuogm_class_open_plugin;
+ this->class.get_identifier = spuogm_class_get_identifier;
+ this->class.get_description = spuogm_class_get_description;
+ this->class.dispose = spuogm_class_dispose;
+
+ this->xine = xine;
+
+ this->src_encoding = xine->config->register_string(xine->config,
+ "misc.spu_src_encoding",
+ "iso-8859-1",
+ _("encoding of subtitles"),
+ NULL, 10, update_src_encoding, this);
+
+ return &this->class;
+}
+
+
+/* plugin catalog information */
+static uint32_t supported_types[] = { BUF_SPU_OGM, 0 };
+
+static decoder_info_t spudec_info = {
+ supported_types, /* supported types */
+ 1 /* priority */
+};
+
+plugin_info_t xine_plugin_info[] = {
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_SPU_DECODER, 13, "spuogm", XINE_VERSION_CODE, &spudec_info, &init_spu_decoder_plugin },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h
index 98d8bb67a..205f13b2b 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.106 2003/03/30 15:19:46 tmattern Exp $
+ * $Id: buffer.h,v 1.107 2003/04/16 23:05:27 heinchen Exp $
*
*
* contents:
@@ -207,6 +207,7 @@ extern "C" {
#define BUF_SPU_DVB 0x04030000
#define BUF_SPU_SVCD 0x04040000
#define BUF_SPU_CVD 0x04050000
+#define BUF_SPU_OGM 0x04060000
/* demuxer block types: */