X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fsubtitle.c;h=ca6b6caa7e71699a52a036b5a3c0fecee844b2da;hb=750ec8a01ef0fe940cf1cceb19d9fe6cb0f18e3b;hp=0ec9ecb8939ff133f243fae6f2a927088bd9c959;hpb=997c6c3419170b68d41ff8ee5b27b26166138984;p=vlc diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c index 0ec9ecb893..ca6b6caa7e 100644 --- a/modules/demux/subtitle.c +++ b/modules/demux/subtitle.c @@ -1,7 +1,7 @@ /***************************************************************************** * subtitle.c: Demux for subtitle text files. ***************************************************************************** - * Copyright (C) 1999-2004 VideoLAN + * Copyright (C) 1999-2004 the VideoLAN team * $Id$ * * Authors: Laurent Aimar @@ -19,26 +19,26 @@ * * 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, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ +#include + +#include #include #include -#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif #include -#include #include #include "vlc_video.h" - - -#if (!defined( WIN32 ) || defined(__MINGW32__)) -# include -#endif +#include "charset.h" /***************************************************************************** * Module descriptor @@ -47,31 +47,36 @@ static int Open ( vlc_object_t *p_this ); static void Close( vlc_object_t *p_this ); #define SUB_DELAY_LONGTEXT \ - "Delay subtitles (in 1/10s)" + N_("Apply a delay to all subtitles (in 1/10s, eg 100 means 10s).") #define SUB_FPS_LONGTEXT \ - "Override frames per second. " \ - "It will only work with MicroDVD subtitles." + N_("Override the normal frames per second settings. " \ + "This will only work with MicroDVD and SubRIP (SRT) subtitles.") #define SUB_TYPE_LONGTEXT \ - "One from \"microdvd\", \"subrip\", \"ssa1\", \"ssa2-4\", \"vplayer\" " \ - "\"sami\" (auto for autodetection, it should always work)." -static char *ppsz_sub_type[] = + N_("Force the subtiles format. Valid values are : \"microdvd\", " \ + "\"subrip\", \"ssa1\", \"ssa2-4\", \"ass\", \"vplayer\" " \ + "\"sami\", \"dvdsubtitle\" and \"auto\" (meaning autodetection, this " \ + "should always work).") +static const char *ppsz_sub_type[] = { "auto", "microdvd", "subrip", "subviewer", "ssa1", - "ssa2-4", "vplayer", "sami" + "ssa2-4", "ass", "vplayer", "sami", "dvdsubtitle" }; vlc_module_begin(); - set_description( _("Text subtitles demux") ); + set_shortname( _("Subtitles")); + set_description( _("Text subtitles parser") ); set_capability( "demux2", 0 ); + set_category( CAT_INPUT ); + set_subcategory( SUBCAT_INPUT_DEMUX ); add_float( "sub-fps", 0.0, NULL, N_("Frames per second"), SUB_FPS_LONGTEXT, VLC_TRUE ); add_integer( "sub-delay", 0, NULL, N_("Subtitles delay"), SUB_DELAY_LONGTEXT, VLC_TRUE ); - add_string( "sub-type", "auto", NULL, "Subtitles fileformat", + add_string( "sub-type", "auto", NULL, N_("Subtitles format"), SUB_TYPE_LONGTEXT, VLC_TRUE ); - change_string_list( ppsz_sub_type, 0, 0 ); + change_string_list( ppsz_sub_type, NULL, NULL ); set_callbacks( Open, Close ); add_shortcut( "subtitle" ); @@ -87,9 +92,11 @@ enum SUB_TYPE_SUBRIP, SUB_TYPE_SSA1, SUB_TYPE_SSA2_4, + SUB_TYPE_ASS, SUB_TYPE_VPLAYER, SUB_TYPE_SAMI, SUB_TYPE_SUBVIEWER, + SUB_TYPE_DVDSUBTITLE }; typedef struct @@ -103,8 +110,8 @@ static void TextUnload( text_t * ); typedef struct { - mtime_t i_start; - mtime_t i_stop; + int64_t i_start; + int64_t i_stop; char *psz_text; } subtitle_t; @@ -117,9 +124,7 @@ struct demux_sys_t es_out_id_t *es; int64_t i_next_demux_date; - int64_t i_microsecperframe; - mtime_t i_original_mspf; char *psz_header; int i_subtitle; @@ -129,48 +134,52 @@ struct demux_sys_t int64_t i_length; }; -static int ParseMicroDvd ( demux_t *, subtitle_t * ); -static int ParseSubRip ( demux_t *, subtitle_t * ); -static int ParseSubViewer( demux_t *, subtitle_t * ); -static int ParseSSA ( demux_t *, subtitle_t * ); -static int ParseVplayer ( demux_t *, subtitle_t * ); -static int ParseSami ( demux_t *, subtitle_t * ); +static int ParseMicroDvd ( demux_t *, subtitle_t * ); +static int ParseSubRip ( demux_t *, subtitle_t * ); +static int ParseSubViewer ( demux_t *, subtitle_t * ); +static int ParseSSA ( demux_t *, subtitle_t * ); +static int ParseVplayer ( demux_t *, subtitle_t * ); +static int ParseSami ( demux_t *, subtitle_t * ); +static int ParseDVDSubtitle( demux_t *, subtitle_t * ); static struct { - char *psz_type_name; + const char *psz_type_name; int i_type; - char *psz_name; + const char *psz_name; int (*pf_read)( demux_t *, subtitle_t* ); } sub_read_subtitle_function [] = { - { "microdvd", SUB_TYPE_MICRODVD, "MicroDVD", ParseMicroDvd }, - { "subrip", SUB_TYPE_SUBRIP, "SubRIP", ParseSubRip }, - { "subviewer", SUB_TYPE_SUBVIEWER, "SubViewer",ParseSubViewer }, - { "ssa1", SUB_TYPE_SSA1, "SSA-1", ParseSSA }, - { "ssa2-4", SUB_TYPE_SSA2_4, "SSA-2/3/4",ParseSSA }, - { "vplayer", SUB_TYPE_VPLAYER, "VPlayer", ParseVplayer }, - { "sami", SUB_TYPE_SAMI, "SAMI", ParseSami }, - { NULL, SUB_TYPE_UNKNOWN, "Unknown", NULL } + { "microdvd", SUB_TYPE_MICRODVD, "MicroDVD", ParseMicroDvd }, + { "subrip", SUB_TYPE_SUBRIP, "SubRIP", ParseSubRip }, + { "subviewer", SUB_TYPE_SUBVIEWER, "SubViewer", ParseSubViewer }, + { "ssa1", SUB_TYPE_SSA1, "SSA-1", ParseSSA }, + { "ssa2-4", SUB_TYPE_SSA2_4, "SSA-2/3/4", ParseSSA }, + { "ass", SUB_TYPE_ASS, "SSA/ASS", ParseSSA }, + { "vplayer", SUB_TYPE_VPLAYER, "VPlayer", ParseVplayer }, + { "sami", SUB_TYPE_SAMI, "SAMI", ParseSami }, + { "dvdsubtitle",SUB_TYPE_DVDSUBTITLE, "DVDSubtitle", ParseDVDSubtitle }, + { NULL, SUB_TYPE_UNKNOWN, "Unknown", NULL } }; static int Demux( demux_t * ); static int Control( demux_t *, int, va_list ); -static void Fix( demux_t * ); +/*static void Fix( demux_t * );*/ /***************************************************************************** * Module initializer *****************************************************************************/ static int Open ( vlc_object_t *p_this ) { - demux_t *p_demux = (demux_t*)p_this; - demux_sys_t *p_sys; - es_format_t fmt; - float f_fps; - char *psz_type; + demux_t *p_demux = (demux_t*)p_this; + demux_sys_t *p_sys; + es_format_t fmt; + input_thread_t *p_input; + float f_fps; + char *psz_type; int (*pf_read)( demux_t *, subtitle_t* ); - int i, i_max; + int i, i_max; if( strcmp( p_demux->psz_demux, "subtitle" ) ) { @@ -181,28 +190,30 @@ static int Open ( vlc_object_t *p_this ) p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); - p_sys->psz_header = NULL; - p_sys->i_subtitle = 0; - p_sys->i_subtitles= 0; - p_sys->subtitle = NULL; - + p_sys->psz_header = NULL; + p_sys->i_subtitle = 0; + p_sys->i_subtitles = 0; + p_sys->subtitle = NULL; + p_sys->i_microsecperframe = 0; /* Get the FPS */ + /* Check for fps of the video when available */ p_sys->i_microsecperframe = 40000; /* default to 25 fps */ - f_fps = var_CreateGetFloat( p_demux, "sub-fps" ); - if( f_fps >= 1.0 ) + p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT ); + if( p_input ) { - p_sys->i_microsecperframe = (mtime_t)( (float)1000000 / f_fps ); + f_fps = var_GetFloat( p_input, "sub-original-fps" ); + if( f_fps >= 1.0 ) + p_sys->i_microsecperframe = (int64_t)( (float)1000000 / f_fps ); + + vlc_object_release( p_input ); } - f_fps = var_CreateGetFloat( p_demux, "sub-original-fps" ); + /* Check for override of the fps */ + f_fps = var_CreateGetFloat( p_demux, "sub-fps" ); if( f_fps >= 1.0 ) { - p_sys->i_original_mspf = (mtime_t)( (float)1000000 / f_fps ); - } - else - { - p_sys->i_original_mspf = 0; + p_sys->i_microsecperframe = (int64_t)( (float)1000000 / f_fps ); } /* Get or probe the type */ @@ -260,28 +271,29 @@ static int Open ( vlc_object_t *p_this ) p_sys->i_type = SUB_TYPE_SUBRIP; break; } - else if( sscanf( s, - "!: This is a Sub Station Alpha v%d.x script.", - &i_dummy ) == 1) + else if( !strncasecmp( s, "!: This is a Sub Station Alpha v1", 33 ) ) { - if( i_dummy <= 1 ) - { - p_sys->i_type = SUB_TYPE_SSA1; - } - else - { - p_sys->i_type = SUB_TYPE_SSA2_4; /* I hope this will work */ - } + p_sys->i_type = SUB_TYPE_SSA1; + break; + } + else if( !strncasecmp( s, "ScriptType: v4.00+", 18 ) ) + { + p_sys->i_type = SUB_TYPE_ASS; break; } - else if( strcasestr( s, "This is a Sub Station Alpha v4 script" ) ) + else if( !strncasecmp( s, "ScriptType: v4.00", 17 ) ) { - p_sys->i_type = SUB_TYPE_SSA2_4; /* I hope this will work */ + p_sys->i_type = SUB_TYPE_SSA2_4; break; } else if( !strncasecmp( s, "Dialogue: Marked", 16 ) ) { - p_sys->i_type = SUB_TYPE_SSA2_4; /* could be wrong */ + p_sys->i_type = SUB_TYPE_SSA2_4; + break; + } + else if( !strncasecmp( s, "Dialogue:", 9 ) ) + { + p_sys->i_type = SUB_TYPE_ASS; break; } else if( strcasestr( s, "[INFORMATION]" ) ) @@ -295,6 +307,12 @@ static int Open ( vlc_object_t *p_this ) p_sys->i_type = SUB_TYPE_VPLAYER; break; } + else if( sscanf( s, "{T %d:%d:%d:%d", &i_dummy, &i_dummy, + &i_dummy, &i_dummy ) == 4 ) + { + p_sys->i_type = SUB_TYPE_DVDSUBTITLE; + break; + } free( s ); s = NULL; @@ -303,7 +321,7 @@ static int Open ( vlc_object_t *p_this ) if( s ) free( s ); /* It will nearly always work even for non seekable stream thanks the - * caching system, and if it fails we loose just a few sub */ + * caching system, and if it fails we lose just a few sub */ if( stream_Seek( p_demux->s, 0 ) ) { msg_Warn( p_demux, "failed to rewind" ); @@ -312,6 +330,7 @@ static int Open ( vlc_object_t *p_this ) if( p_sys->i_type == SUB_TYPE_UNKNOWN ) { msg_Err( p_demux, "failed to recognize subtitle type" ); + free( p_sys ); return VLC_EGENERIC; } @@ -341,6 +360,10 @@ static int Open ( vlc_object_t *p_this ) sizeof(subtitle_t) * i_max ) ) ) { msg_Err( p_demux, "out of memory"); + if( p_sys->subtitle != NULL ) + free( p_sys->subtitle ); + TextUnload( &p_sys->txt ); + free( p_sys ); return VLC_ENOMEM; } } @@ -368,7 +391,8 @@ static int Open ( vlc_object_t *p_this ) /* *** add subtitle ES *** */ if( p_sys->i_type == SUB_TYPE_SSA1 || - p_sys->i_type == SUB_TYPE_SSA2_4 ) + p_sys->i_type == SUB_TYPE_SSA2_4 || + p_sys->i_type == SUB_TYPE_ASS ) { es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','s','a',' ' ) ); } @@ -501,7 +525,7 @@ static int Demux( demux_t *p_demux ) if( p_sys->i_subtitle >= p_sys->i_subtitles ) return 0; - i_maxdate = p_sys->i_next_demux_date; + i_maxdate = p_sys->i_next_demux_date - var_GetTime( p_demux->p_parent, "spu-delay" );; if( i_maxdate <= 0 && p_sys->i_subtitle < p_sys->i_subtitles ) { /* Should not happen */ @@ -563,6 +587,7 @@ static int Demux( demux_t *p_demux ) /***************************************************************************** * Fix: fix time stamp and order of subtitle *****************************************************************************/ +#ifdef USE_THIS_UNUSED_PIECE_OF_CODE static void Fix( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; @@ -596,6 +621,7 @@ static void Fix( demux_t *p_demux ) } } while( !b_done ); } +#endif static int TextLoad( text_t *txt, stream_t *s ) { @@ -619,7 +645,7 @@ static int TextLoad( text_t *txt, stream_t *s ) if( txt->i_line_count >= i_line_max ) { i_line_max += 100; - txt->line = realloc( txt->line, i_line_max * sizeof( char*) ); + txt->line = realloc( txt->line, i_line_max * sizeof( char * ) ); } } @@ -669,19 +695,20 @@ static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle ) * each line: * {n1}{n2}Line1|Line2|Line3.... * where n1 and n2 are the video frame number... - * + * {n2} can also be {} */ char *s; char buffer_text[MAX_LINE + 1]; - unsigned int i_start; - unsigned int i_stop; + int i_start; + int i_stop; unsigned int i; p_subtitle->i_start = 0; p_subtitle->i_stop = 0; p_subtitle->psz_text = NULL; +next: for( ;; ) { if( ( s = TextGetLine( txt ) ) == NULL ) @@ -698,6 +725,16 @@ static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle ) break; } } + if( i_start == 1 && i_stop == 1 ) + { + /* We found a possible setting of the framerate "{1}{1}23.976" */ + /* Check if it's usable, and if the sub-fps is not set */ + float tmp = us_strtod( buffer_text, NULL ); + if( tmp >= 1.0 && !var_GetFloat( p_demux, "sub-fps" ) >= 1.0 ) + p_sys->i_microsecperframe = (int64_t)( (float)1000000 / tmp ); + goto next; + } + /* replace | by \n */ for( i = 0; i < strlen( buffer_text ); i++ ) { @@ -707,8 +744,8 @@ static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle ) } } - p_subtitle->i_start = (mtime_t)i_start * p_sys->i_microsecperframe; - p_subtitle->i_stop = (mtime_t)i_stop * p_sys->i_microsecperframe; + p_subtitle->i_start = (int64_t)i_start * p_sys->i_microsecperframe; + p_subtitle->i_stop = (int64_t)i_stop * p_sys->i_microsecperframe; p_subtitle->psz_text = strndup( buffer_text, MAX_LINE ); return( 0 ); } @@ -730,8 +767,8 @@ static int ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle ) char *s; char buffer_text[ 10 * MAX_LINE]; int i_buffer_text; - mtime_t i_start; - mtime_t i_stop; + int64_t i_start; + int64_t i_stop; p_subtitle->i_start = 0; p_subtitle->i_stop = 0; @@ -749,15 +786,15 @@ static int ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle ) &h1, &m1, &s1, &d1, &h2, &m2, &s2, &d2 ) == 8 ) { - i_start = ( (mtime_t)h1 * 3600*1000 + - (mtime_t)m1 * 60*1000 + - (mtime_t)s1 * 1000 + - (mtime_t)d1 ) * 1000; + i_start = ( (int64_t)h1 * 3600*1000 + + (int64_t)m1 * 60*1000 + + (int64_t)s1 * 1000 + + (int64_t)d1 ) * 1000; - i_stop = ( (mtime_t)h2 * 3600*1000 + - (mtime_t)m2 * 60*1000 + - (mtime_t)s2 * 1000 + - (mtime_t)d2 ) * 1000; + i_stop = ( (int64_t)h2 * 3600*1000 + + (int64_t)m2 * 60*1000 + + (int64_t)s2 * 1000 + + (int64_t)d2 ) * 1000; /* Now read text until an empty line */ for( i_buffer_text = 0;; ) @@ -776,17 +813,6 @@ static int ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle ) p_subtitle->i_start = i_start; p_subtitle->i_stop = i_stop; p_subtitle->psz_text = strdup( buffer_text ); - /* If framerate is available, use sub-fps */ - if( p_sys->i_microsecperframe != 0 && - p_sys->i_original_mspf != 0) - { - p_subtitle->i_start = (mtime_t)i_start * - p_sys->i_microsecperframe/ - p_sys->i_original_mspf; - p_subtitle->i_stop = (mtime_t)i_stop * - p_sys->i_microsecperframe / - p_sys->i_original_mspf; - } return 0; } else @@ -823,8 +849,8 @@ static int ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle ) char *s; char buffer_text[ 10 * MAX_LINE]; int i_buffer_text; - mtime_t i_start; - mtime_t i_stop; + int64_t i_start; + int64_t i_stop; p_subtitle->i_start = 0; p_subtitle->i_stop = 0; @@ -842,15 +868,15 @@ static int ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle ) &h1, &m1, &s1, &d1, &h2, &m2, &s2, &d2 ) == 8 ) { - i_start = ( (mtime_t)h1 * 3600*1000 + - (mtime_t)m1 * 60*1000 + - (mtime_t)s1 * 1000 + - (mtime_t)d1 ) * 1000; + i_start = ( (int64_t)h1 * 3600*1000 + + (int64_t)m1 * 60*1000 + + (int64_t)s1 * 1000 + + (int64_t)d1 ) * 1000; - i_stop = ( (mtime_t)h2 * 3600*1000 + - (mtime_t)m2 * 60*1000 + - (mtime_t)s2 * 1000 + - (mtime_t)d2 ) * 1000; + i_stop = ( (int64_t)h2 * 3600*1000 + + (int64_t)m2 * 60*1000 + + (int64_t)s2 * 1000 + + (int64_t)d2 ) * 1000; /* Now read text until an empty line */ for( i_buffer_text = 0;; ) @@ -909,9 +935,10 @@ static int ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle ) text_t *txt = &p_sys->txt; char buffer_text[ 10 * MAX_LINE]; + char buffer_text2[ 10 * MAX_LINE]; char *s; - mtime_t i_start; - mtime_t i_stop; + int64_t i_start; + int64_t i_stop; p_subtitle->i_start = 0; p_subtitle->i_stop = 0; @@ -920,7 +947,6 @@ static int ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle ) for( ;; ) { int h1, m1, s1, c1, h2, m2, s2, c2; - int i_dummy; if( ( s = TextGetLine( txt ) ) == NULL ) { @@ -928,33 +954,45 @@ static int ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle ) } p_subtitle->psz_text = malloc( strlen( s ) ); + /* We expect (SSA2-4): + * Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text + * Dialogue: Marked=0,0:02:40.65,0:02:41.79,Wolf main,Cher,0000,0000,0000,,Et les enregistrements de ses ondes delta ? + * + * SSA-1 is similar but only has 8 commas up untill the subtitle text. Probably the Effect field is no present, but not 100 % sure. + */ + + /* For ASS: + * Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text + * Dialogue: Layer#,0:02:40.65,0:02:41.79,Wolf main,Cher,0000,0000,0000,,Et les enregistrements de ses ondes delta ? + */ if( sscanf( s, - "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d%[^\r\n]", - &i_dummy, + "Dialogue: %[^,],%d:%d:%d.%d,%d:%d:%d.%d,%[^\r\n]", + buffer_text2, &h1, &m1, &s1, &c1, &h2, &m2, &s2, &c2, buffer_text ) == 10 ) { - i_start = ( (mtime_t)h1 * 3600*1000 + - (mtime_t)m1 * 60*1000 + - (mtime_t)s1 * 1000 + - (mtime_t)c1 * 10 ) * 1000; + i_start = ( (int64_t)h1 * 3600*1000 + + (int64_t)m1 * 60*1000 + + (int64_t)s1 * 1000 + + (int64_t)c1 * 10 ) * 1000; - i_stop = ( (mtime_t)h2 * 3600*1000 + - (mtime_t)m2 * 60*1000 + - (mtime_t)s2 * 1000 + - (mtime_t)c2 * 10 ) * 1000; + i_stop = ( (int64_t)h2 * 3600*1000 + + (int64_t)m2 * 60*1000 + + (int64_t)s2 * 1000 + + (int64_t)c2 * 10 ) * 1000; /* The dec expects: ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text */ + /* (Layer comes from ASS specs ... it's empty for SSA.) */ if( p_sys->i_type == SUB_TYPE_SSA1 ) { sprintf( p_subtitle->psz_text, - ",%d%s", i_dummy, strdup( buffer_text) ); + ",%s", strdup( buffer_text) ); /* SSA1 has only 8 commas before the text starts, not 9 */ } else { sprintf( p_subtitle->psz_text, - ",%d,%s", i_dummy, strdup( buffer_text) ); + ",,%s", strdup( buffer_text) ); /* ReadOrder, Layer, %s(rest of fields) */ } p_subtitle->i_start = i_start; p_subtitle->i_stop = i_stop; @@ -966,12 +1004,12 @@ static int ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle ) if( p_sys->psz_header != NULL ) { if( !( p_sys->psz_header = realloc( p_sys->psz_header, - strlen( p_sys->psz_header ) + strlen( s ) + 2 ) ) ) + strlen( p_sys->psz_header ) + 1 + strlen( s ) + 2 ) ) ) { msg_Err( p_demux, "out of memory"); return VLC_ENOMEM; } - p_sys->psz_header = strcat( p_sys->psz_header, strdup( s ) ); + p_sys->psz_header = strcat( p_sys->psz_header, s ); p_sys->psz_header = strcat( p_sys->psz_header, "\n" ); } else @@ -981,7 +1019,7 @@ static int ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle ) msg_Err( p_demux, "out of memory"); return VLC_ENOMEM; } - p_sys->psz_header = strdup( s ); + p_sys->psz_header = s; p_sys->psz_header = strcat( p_sys->psz_header, "\n" ); } } @@ -1002,7 +1040,7 @@ static int ParseVplayer( demux_t *p_demux, subtitle_t *p_subtitle ) */ char *p; char buffer_text[MAX_LINE + 1]; - mtime_t i_start; + int64_t i_start; unsigned int i; p_subtitle->i_start = 0; @@ -1024,9 +1062,9 @@ static int ParseVplayer( demux_t *p_demux, subtitle_t *p_subtitle ) memset( buffer_text, '\0', MAX_LINE ); if( sscanf( p, "%d:%d:%d%[ :]%[^\r\n]", &h, &m, &s, &c, buffer_text ) == 5 ) { - i_start = ( (mtime_t)h * 3600*1000 + - (mtime_t)m * 60*1000 + - (mtime_t)s * 1000 ) * 1000; + i_start = ( (int64_t)h * 3600*1000 + + (int64_t)m * 60*1000 + + (int64_t)s * 1000 ) * 1000; break; } } @@ -1046,7 +1084,7 @@ static int ParseVplayer( demux_t *p_demux, subtitle_t *p_subtitle ) return( 0 ); } -static char *ParseSamiSearch( text_t *txt, char *psz_start, char *psz_str ) +static char *ParseSamiSearch( text_t *txt, char *psz_start, const char *psz_str ) { if( psz_start ) { @@ -1083,7 +1121,7 @@ static int ParseSami( demux_t *p_demux, subtitle_t *p_subtitle ) text_t *txt = &p_sys->txt; char *p; - int i_start; + int64_t i_start; int i_text; char buffer_text[10*MAX_LINE + 1]; @@ -1173,3 +1211,79 @@ static int ParseSami( demux_t *p_demux, subtitle_t *p_subtitle ) return( VLC_SUCCESS ); #undef ADDC } + +static int ParseDVDSubtitle( demux_t *p_demux, subtitle_t *p_subtitle ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + text_t *txt = &p_sys->txt; + + /* + * {T h1:m1:s1:c1 + * Line1 + * Line2 + * ... + * } + * + */ + char *s; + char buffer_text[ 10 * MAX_LINE]; + int i_buffer_text; + int64_t i_start; + + p_subtitle->i_start = 0; + p_subtitle->i_stop = 0; + p_subtitle->psz_text = NULL; + + for( ;; ) + { + int h1, m1, s1, c1; + if( ( s = TextGetLine( txt ) ) == NULL ) + { + return( VLC_EGENERIC ); + } + if( sscanf( s, + "{T %d:%d:%d:%d", + &h1, &m1, &s1, &c1 ) == 4 ) + { + i_start = ( (int64_t)h1 * 3600*1000 + + (int64_t)m1 * 60*1000 + + (int64_t)s1 * 1000 + + (int64_t)c1 * 10) * 1000; + + /* Now read text until a line containing "}" */ + for( i_buffer_text = 0;; ) + { + int i_len; + if( ( s = TextGetLine( txt ) ) == NULL ) + { + return( VLC_EGENERIC ); + } + + i_len = strlen( s ); + if( i_len == 1 && s[0] == '}' ) + { + /* "}" -> end of this subtitle */ + buffer_text[__MAX( i_buffer_text - 1, 0 )] = '\0'; + p_subtitle->i_start = i_start; + p_subtitle->i_stop = 0; + p_subtitle->psz_text = strdup( buffer_text ); + return 0; + } + else + { + if( i_buffer_text + i_len + 1 < 10 * MAX_LINE ) + { + memcpy( buffer_text + i_buffer_text, + s, + i_len ); + i_buffer_text += i_len; + + buffer_text[i_buffer_text] = '\n'; + i_buffer_text++; + } + } + } + } + } +} +