diff options
author | František Dvořák <valtri@users.sourceforge.net> | 2004-06-11 09:47:29 +0000 |
---|---|---|
committer | František Dvořák <valtri@users.sourceforge.net> | 2004-06-11 09:47:29 +0000 |
commit | c450de308294d4dd0e4a6d86b28a59ce72801330 (patch) | |
tree | a94984c43e5bcbc9695324b884fbecd43e5c575b | |
parent | cda7393846ea62539cb4582eff20b6b83c4fca81 (diff) | |
download | xine-lib-c450de308294d4dd0e4a6d86b28a59ce72801330.tar.gz xine-lib-c450de308294d4dd0e4a6d86b28a59ce72801330.tar.bz2 |
Patch with improvements for libsputext from Vincent Pelletier - word wrap and enhanced subtitle parser.
CVS patchset: 6673
CVS date: 2004/06/11 09:47:29
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | src/libsputext/demux_sputext.c | 132 | ||||
-rw-r--r-- | src/libsputext/xine_decoder.c | 168 |
4 files changed, 266 insertions, 38 deletions
@@ -486,5 +486,8 @@ Moritz Bunkus <moritz@bunkus.org> Szymon Stefanek <s.stefanek@libero.it> Improved DVB mrls and dvbs, dvbc and dvbt support +Vincent Pelletier <subdino2004@yahoo.fr> + Word wrap and other improvements in libsputext. + (let us know if we've forgotten anyone) @@ -23,6 +23,7 @@ * add support for XVR-100 (Radeon-based) framebuffers to video_out_pgx64 * support DTS audio in AVI * revised FLAC playback subsystem + * subtitles improvements - word wrap and new subtitle format variants xine-lib (1-rc4a) * audio out now uses a more user friendly "Speaker arrangement" config item; diff --git a/src/libsputext/demux_sputext.c b/src/libsputext/demux_sputext.c index 664e6b702..9a754b62f 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.34 2004/04/26 17:50:08 mroi Exp $ + * $Id: demux_sputext.c,v 1.35 2004/06/11 09:47:30 valtri Exp $ * * code based on old libsputext/xine_decoder.c * @@ -100,7 +100,7 @@ typedef struct { typedef struct demux_sputext_class_s { demux_class_t demux_class; - + int max_timeout; /* default timeout of hidding subtitles */ } demux_sputext_class_t; @@ -109,6 +109,7 @@ typedef struct demux_sputext_class_s { * Demuxer code start */ +#define FORMAT_UNKNOWN -1 #define FORMAT_MICRODVD 0 #define FORMAT_SUBRIP 1 #define FORMAT_SUBVIEWER 2 @@ -314,11 +315,15 @@ static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *cu while (1) { if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) continue; + if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) { + if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) + continue; + } current->start = a1*360000+a2*6000+a3*100+a4; current->end = b1*360000+b2*6000+b3*100+b4; - if (!read_line_from_input(this, line, LINE_LEN)) return NULL; + if (!read_line_from_input(this, line, LINE_LEN)) + return NULL; p=q=line; for (current->lines=1; current->lines < SUB_MAX_TEXT; current->lines++) { @@ -339,34 +344,91 @@ static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *cu static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *current) { char line[LINE_LEN + 1]; int a1,a2,a3,a4,b1,b2,b3,b4; - char *p=NULL; - int i,len; - - memset (current, 0, sizeof(subtitle_t)); + int i,end_sub; - while (!current->text[0]) { - if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - - if ((len=sscanf (line, "%d:%d:%d,%d --> %d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8) - continue; - current->start = a1*360000+a2*6000+a3*100+a4/10; - current->end = b1*360000+b2*6000+b3*100+b4/10; - for (i=0; i<SUB_MAX_TEXT;) { - if (!read_line_from_input(this, line, LINE_LEN)) break; - len=0; - for (p=line; *p!='\n' && *p!='\r' && *p; p++,len++); - if (len) { - current->text[i]=(char *)xine_xmalloc (len+1); - if (!current->text[i]) return ERR; - strncpy (current->text[i], line, len); current->text[i][len]='\0'; - i++; - } else { - break; + memset(current,0,sizeof(subtitle_t)); + do { + if(!read_line_from_input(this,line,LINE_LEN)) + return NULL; + } while(sscanf(line,"%d:%d:%d,%d --> %d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8); + current->start = a1*360000+a2*6000+a3*100+a4/10; + current->end = b1*360000+b2*6000+b3*100+b4/10; + i=0; + end_sub=0; + do { + char *p; /* pointer to the curently read char */ + char temp_line[SUB_BUFSIZE]; /* subtitle line that will be transfered to current->text[i] */ + int temp_index; /* ... and its index wich 'points' to the first EMPTY place -> last read char is at temp_index-1 if temp_index>0 */ + temp_line[SUB_BUFSIZE-1]='\0'; /* just in case... */ + if(!read_line_from_input(this,line,LINE_LEN)) { + if(i) + break; /* if something was read, transmit it */ + else + return NULL; /* if not, repport EOF */ + } + for(temp_index=0,p=line;*p!='\0' && !end_sub && temp_index<SUB_BUFSIZE && i<SUB_MAX_TEXT;p++) { + switch(*p) { + case '\\': + if(*(p+1)=='N' || *(p+1)=='n') { + temp_line[temp_index++]='\0'; /* end of curent line */ + p++; + } else + temp_line[temp_index++]=*p; + break; + case '{': +#if 0 /* italic not implemented in renderer, ignore them for now */ + if(!strncmp(p,"{\\i1}",5) && temp_index+3<SUB_BUFSIZE) { + temp_line[temp_index++]='<'; + temp_line[temp_index++]='i'; + temp_line[temp_index++]='>'; +#else + if(!strncmp(p,"{\\i1}",5)) { +#endif + p+=4; + } +#if 0 /* italic not implemented in renderer, ignore them for now */ + else if(!strncmp(p,"{\\i0}",5) && temp_index+4<SUB_BUFSIZE) { + temp_line[temp_index++]='<'; + temp_line[temp_index++]='/'; + temp_line[temp_index++]='i'; + temp_line[temp_index++]='>'; +#else + else if(!strncmp(p,"{\\i0}",5)) { +#endif + p+=4; + } + else + temp_line[temp_index++]=*p; + break; + case '\r': /* just ignore '\r's */ + break; + case '\n': + temp_line[temp_index++]='\0'; + break; + default: + temp_line[temp_index++]=*p; + break; + } + if(temp_index>0) { + if(temp_index==SUB_BUFSIZE) + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many characters in a subtitle line\n"); + if(temp_line[temp_index-1]=='\0' || temp_index==SUB_BUFSIZE) { + if(temp_index>1) { /* more than 1 char (including '\0') -> that is a valid one */ + current->text[i]=(char *)xine_xmalloc(temp_index); + if(!current->text[i]) + return ERR; + strncpy(current->text[i],temp_line,temp_index); /* temp_index<=SUB_BUFSIZE is always true here */ + i++; + temp_index=0; + } else + end_sub=1; + } } } - current->lines=i; - } - + } while(i<SUB_MAX_TEXT && !end_sub); + if(i>=SUB_MAX_TEXT) + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); + current->lines=i; return current; } @@ -903,7 +965,7 @@ static int sub_autodetect (demux_sputext_t *this) { while (j < 100) { j++; if (!read_line_from_input(this, line, LINE_LEN)) - return -1; + return FORMAT_UNKNOWN; if ((sscanf (line, "{%d}{}", &i)==1) || (sscanf (line, "{%d}{%d}", &i, &i)==2)) { @@ -924,6 +986,12 @@ static int sub_autodetect (demux_sputext_t *this) { return FORMAT_SUBVIEWER; } + if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d", &i, &i, &i, &i, &i, &i, &i, &i)==8){ + this->uses_time=1; + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subviewer subtitle format detected\n"); + return FORMAT_SUBVIEWER; + } + if (strstr (line, "<SAMI>")) { this->uses_time=1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "sami subtitle format detected\n"); @@ -986,7 +1054,7 @@ static int sub_autodetect (demux_sputext_t *this) { } } - return -1; /* too many bad lines */ + return FORMAT_UNKNOWN; /* too many bad lines */ } static subtitle_t *sub_read_file (demux_sputext_t *this) { @@ -1019,7 +1087,7 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) { this->buflen = 0; this->format=sub_autodetect (this); - if (this->format==-1) { + if (this->format==FORMAT_UNKNOWN) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Could not determine file format\n"); return NULL; } diff --git a/src/libsputext/xine_decoder.c b/src/libsputext/xine_decoder.c index 6e351651e..07f520f0d 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.81 2004/06/04 14:37:33 mroi Exp $ + * $Id: xine_decoder.c,v 1.82 2004/06/11 09:47:30 valtri Exp $ * */ @@ -299,17 +299,173 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su if( this->renderer ) this->renderer->set_font (this->osd, this->class->font, this->font_size); } - + + font_size = this->font_size; + this->renderer->set_encoding(this->osd, this->class->src_encoding); + + for (line = 0; line < this->lines; line++) /* first, check lenghts and word-wrap if needed */ + { + int w, h; + if( this->ogm ) + w = ogm_get_width( this, this->text[line]); + else + this->renderer->get_text_size( this->osd, this->text[line], &w, &h); + if( w > this->width ) { /* line is too long */ + int chunks=(int)(w/this->width)+(w%this->width?1:0); + if( this->lines+chunks <= SUB_MAX_TEXT && chunks>1 ) { /* try adding newlines while keeping existing ones */ + int a; + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,"Partial subtitle line splitting in %i chunks\n",chunks); + for(a=this->lines-1;a>=0;a--) { + if(a>line) /* lines after the too-long one */ + memcpy(this->text[a+chunks-1],this->text[a],SUB_BUFSIZE); + else if(a==line) { /* line to be splitted */ + int b,len=strlen(this->text[line]); + char *p=this->text[line]; + for(b=0;b<chunks;b++) { + char *c; + if(b==chunks-1) /* if we are reading the last chunk, copy it completly */ + strncpy(this->text[line+b],p,SUB_BUFSIZE); + else { + for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--); + if(*c==' ') { + *c='\0'; + if(b) /* we are reading something that has to be moved to another line */ + strncpy(this->text[line+b],p,SUB_BUFSIZE); + p=c+1; + } + } + } + } + } + this->lines+=chunks-1; + } else { /* regenerate all the lines to find something that better fits */ + char buf[SUB_BUFSIZE*SUB_MAX_TEXT]; + int a,w,h,chunks; + buf[0]='\0'; + for(a=0;a<this->lines;a++) { + if(a) { + int len=strlen(buf); + buf[len]=' '; + buf[len+1]='\0'; + } + strcat(buf,this->text[a]); + } + if( this->ogm ) + w = ogm_get_width( this, buf); + else + this->renderer->get_text_size( this->osd, buf, &w, &h); + chunks=(int)(w/this->width)+(w%this->width?1:0); + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Complete subtitle line splitting in %i chunks\n",chunks); + if(chunks<=SUB_MAX_TEXT) {/* if the length is over than SUB_MAX_TEXT*this->width nothing can be done */ + int b,len=strlen(buf); + char *p=buf; + for(b=0;b<chunks;b++) { + char *c; + if(b==chunks-1) /* if we are reading the last chunk, copy it completly */ + strncpy(this->text[b],p,SUB_BUFSIZE); + else { + for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--); + if(*c==' ') { + *c='\0'; + strncpy(this->text[b],p,SUB_BUFSIZE); + p=c+1; + } + } + } + this->lines=chunks; + } else + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Subtitle too long to be splited\n"); + line=this->lines; + } + } + } + + font_size = this->font_size; + this->renderer->set_encoding(this->osd, this->class->src_encoding); + + for (line = 0; line < this->lines; line++) /* first, check lenghts and word-wrap if needed */ + { + int w, h; + if( this->ogm ) + w = ogm_get_width( this, this->text[line]); + else + this->renderer->get_text_size( this->osd, this->text[line], &w, &h); + if( w > this->width ) { /* line is too long */ + int chunks=(int)(w/this->width)+(w%this->width?1:0); + if( this->lines+chunks <= SUB_MAX_TEXT && chunks>1 ) { /* try adding newlines while keeping existing ones */ + int a; + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,"Partial subtitle line splitting in %i chunks\n",chunks); + for(a=this->lines-1;a>=0;a--) { + if(a>line) /* lines after the too-long one */ + memcpy(this->text[a+chunks-1],this->text[a],SUB_BUFSIZE); + else if(a==line) { /* line to be splitted */ + int b,len=strlen(this->text[line]); + char *p=this->text[line]; + for(b=0;b<chunks;b++) { + char *c; + if(b==chunks-1) /* if we are reading the last chunk, copy it completly */ + strncpy(this->text[line+b],p,SUB_BUFSIZE); + else { + for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--); + if(*c==' ') { + *c='\0'; + if(b) /* we are reading something that has to be moved to another line */ + strncpy(this->text[line+b],p,SUB_BUFSIZE); + p=c+1; + } + } + } + } + } + this->lines+=chunks-1; + } else { /* regenerate all the lines to find something that better fits */ + char buf[SUB_BUFSIZE*SUB_MAX_TEXT]; + int a,w,h,chunks; + buf[0]='\0'; + for(a=0;a<this->lines;a++) { + if(a) { + int len=strlen(buf); + buf[len]=' '; + buf[len+1]='\0'; + } + strcat(buf,this->text[a]); + } + if( this->ogm ) + w = ogm_get_width( this, buf); + else + this->renderer->get_text_size( this->osd, buf, &w, &h); + chunks=(int)(w/this->width)+(w%this->width?1:0); + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Complete subtitle line splitting in %i chunks\n",chunks); + if(chunks<=SUB_MAX_TEXT) {/* if the length is over than SUB_MAX_TEXT*this->width nothing can be done */ + int b,len=strlen(buf); + char *p=buf; + for(b=0;b<chunks;b++) { + char *c; + if(b==chunks-1) /* if we are reading the last chunk, copy it completly */ + strncpy(this->text[b],p,SUB_BUFSIZE); + else { + for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--); + if(*c==' ') { + *c='\0'; + strncpy(this->text[b],p,SUB_BUFSIZE); + p=c+1; + } + } + } + this->lines=chunks; + } else + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Subtitle too long to be splited\n"); + line=this->lines; + } + } + } + if (this->last_lines) this->renderer->filled_rect (this->osd, 0, this->line_height * (SUB_MAX_TEXT - this->last_lines), this->width - 1, this->line_height * SUB_MAX_TEXT - 1, 0); this->last_lines = this->lines; - y = (SUB_MAX_TEXT - this->lines) * this->line_height; - font_size = this->font_size; - this->renderer->set_encoding(this->osd, this->class->src_encoding); - for (line = 0; line < this->lines; line++) { int w, h, x; |