X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fsubtitle.c;h=060ddef0aab9f8c6aac53723e648b942af8c7416;hb=1d8fa38783a9e68ed9dfcc380eb63ac142d85907;hp=8133c0680fad799cc72a8a7e078fc78ec3941051;hpb=62f7a588292d4ea7a9a40a3ad4724f40e4954be9;p=vlc diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c index 8133c0680f..060ddef0aa 100644 --- a/modules/demux/subtitle.c +++ b/modules/demux/subtitle.c @@ -37,11 +37,6 @@ #include #include "vlc_video.h" - -#if (!defined( WIN32 ) || defined(__MINGW32__)) -# include -#endif - /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -54,17 +49,20 @@ static void Close( vlc_object_t *p_this ); "Override frames per second. " \ "It will only work with MicroDVD subtitles." #define SUB_TYPE_LONGTEXT \ - "One from \"microdvd\", \"subrip\", \"ssa1\", \"ssa2-4\", \"vplayer\" " \ + "One from \"microdvd\", \"subrip\", \"ssa1\", \"ssa2-4\", \"ass\", \"vplayer\" " \ "\"sami\" (auto for autodetection, it should always work)." static char *ppsz_sub_type[] = { "auto", "microdvd", "subrip", "subviewer", "ssa1", - "ssa2-4", "vplayer", "sami" + "ssa2-4", "ass", "vplayer", "sami" }; vlc_module_begin(); + set_shortname( _("Subtitles")); set_description( _("Text subtitles demux") ); 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 ); @@ -89,6 +87,7 @@ enum SUB_TYPE_SUBRIP, SUB_TYPE_SSA1, SUB_TYPE_SSA2_4, + SUB_TYPE_ASS, SUB_TYPE_VPLAYER, SUB_TYPE_SAMI, SUB_TYPE_SUBVIEWER, @@ -151,6 +150,7 @@ static struct { "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 }, { NULL, SUB_TYPE_UNKNOWN, "Unknown", NULL } @@ -190,12 +190,15 @@ static int Open ( vlc_object_t *p_this ) /* Get the FPS */ - p_sys->i_microsecperframe = 40000; /* default to 25 fps */ f_fps = var_CreateGetFloat( p_demux, "sub-fps" ); if( f_fps >= 1.0 ) { p_sys->i_microsecperframe = (int64_t)( (float)1000000 / f_fps ); } + else + { + p_sys->i_microsecperframe = 0; + } f_fps = var_CreateGetFloat( p_demux, "sub-original-fps" ); if( f_fps >= 1.0 ) @@ -262,28 +265,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]" ) ) @@ -370,7 +374,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',' ' ) ); } @@ -503,7 +508,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 */ @@ -671,7 +676,7 @@ 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; @@ -680,6 +685,10 @@ static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle ) int i_stop; unsigned int i; + int i_microsecperframe = 40000; /* default to 25 fps */ + if( p_sys->i_microsecperframe > 0 ) + i_microsecperframe = p_sys->i_microsecperframe; + p_subtitle->i_start = 0; p_subtitle->i_stop = 0; p_subtitle->psz_text = NULL; @@ -709,8 +718,8 @@ static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle ) } } - 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->i_start = (int64_t)i_start * i_microsecperframe; + p_subtitle->i_stop = (int64_t)i_stop * i_microsecperframe; p_subtitle->psz_text = strndup( buffer_text, MAX_LINE ); return( 0 ); } @@ -911,6 +920,7 @@ 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; int64_t i_start; int64_t i_stop; @@ -922,7 +932,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 ) { @@ -930,9 +939,20 @@ 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 ) @@ -948,15 +968,16 @@ static int ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle ) (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;