<div dir="ltr"><div>Here are examples of video and subtitle files which reproduce bug:</div><div><br></div><a href="http://www.archive.org/download/MIT6.046JF05MPEG4/ocw-6.046-02nov2005-220k_512kb.mp4">http://www.archive.org/download/MIT6.046JF05MPEG4/ocw-6.046-02nov2005-220k_512kb.mp4</a><br>
<div><a href="http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-introduction-to-algorithms-sma-5503-fall-2005/video-lectures/lecture-14-competitive-analysis-self-organizing-lists/ocw-6.046-lec14.srt">http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-introduction-to-algorithms-sma-5503-fall-2005/video-lectures/lecture-14-competitive-analysis-self-organizing-lists/ocw-6.046-lec14.srt</a><br>
</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Nov 15, 2013 at 12:35 PM, Maxim Bublis <span dir="ltr"><<a href="mailto:b@codemonkey.ru" target="_blank">b@codemonkey.ru</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Sorry for message duplications, something gone wrong with my internet connection.</div><div class="gmail_extra">
<div><div class="h5"><br><br><div class="gmail_quote">On Fri, Nov 15, 2013 at 1:34 AM, Maxim Bublis <span dir="ltr"><<a href="mailto:b@codemonkey.ru" target="_blank">b@codemonkey.ru</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This patch fixes SubRip subtitles parsing with missing microseconds.<br>
This patch also makes redundant SUB_TYPE_SUBRIP_DOT format as both<br>
delimiters (dot and comma) are now supported equally.<br>
<br>
---<br>
modules/demux/subtitle.c | 140 +++++++++++++++++++++++++++++++++--------------<br>
1 file changed, 99 insertions(+), 41 deletions(-)<br>
<br>
diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c<br>
index 9435ba7..a9c3e45 100644<br>
--- a/modules/demux/subtitle.c<br>
+++ b/modules/demux/subtitle.c<br>
@@ -95,7 +95,6 @@ enum<br>
SUB_TYPE_UNKNOWN = -1,<br>
SUB_TYPE_MICRODVD,<br>
SUB_TYPE_SUBRIP,<br>
- SUB_TYPE_SUBRIP_DOT, /* Invalid SubRip file (dot instead of comma) */<br>
SUB_TYPE_SSA1,<br>
SUB_TYPE_SSA2_4,<br>
SUB_TYPE_ASS,<br>
@@ -171,7 +170,6 @@ struct demux_sys_t<br>
<br>
static int ParseMicroDvd ( demux_t *, subtitle_t *, int );<br>
static int ParseSubRip ( demux_t *, subtitle_t *, int );<br>
-static int ParseSubRipDot ( demux_t *, subtitle_t *, int );<br>
static int ParseSubViewer ( demux_t *, subtitle_t *, int );<br>
static int ParseSSA ( demux_t *, subtitle_t *, int );<br>
static int ParseVplayer ( demux_t *, subtitle_t *, int );<br>
@@ -198,7 +196,6 @@ static const struct<br>
{<br>
{ "microdvd", SUB_TYPE_MICRODVD, "MicroDVD", ParseMicroDvd },<br>
{ "subrip", SUB_TYPE_SUBRIP, "SubRIP", ParseSubRip },<br>
- { "subrip-dot", SUB_TYPE_SUBRIP_DOT, "SubRIP(Dot)", ParseSubRipDot },<br>
{ "subviewer", SUB_TYPE_SUBVIEWER, "SubViewer", ParseSubViewer },<br>
{ "ssa1", SUB_TYPE_SSA1, "SSA-1", ParseSSA },<br>
{ "ssa2-4", SUB_TYPE_SSA2_4, "SSA-2/3/4", ParseSSA },<br>
@@ -335,21 +332,29 @@ static int Open ( vlc_object_t *p_this )<br>
p_sys->i_type = SUB_TYPE_MICRODVD;<br>
break;<br>
}<br>
- else if( sscanf( s,<br>
- "%d:%d:%d,%d --> %d:%d:%d,%d",<br>
+ else if( sscanf( s, "%d:%d:%d,%d --> %d:%d:%d,%d",<br>
&i_dummy,&i_dummy,&i_dummy,&i_dummy,<br>
- &i_dummy,&i_dummy,&i_dummy,&i_dummy ) == 8 )<br>
- {<br>
- p_sys->i_type = SUB_TYPE_SUBRIP;<br>
- break;<br>
- }<br>
- else if( sscanf( s,<br>
- "%d:%d:%d.%d --> %d:%d:%d.%d",<br>
+ &i_dummy,&i_dummy,&i_dummy,&i_dummy ) == 8 ||<br>
+ sscanf( s, "%d:%d:%d --> %d:%d:%d,%d",<br>
+ &i_dummy,&i_dummy,&i_dummy,&i_dummy,<br>
+ &i_dummy,&i_dummy,&i_dummy ) == 7 ||<br>
+ sscanf( s, "%d:%d:%d,%d --> %d:%d:%d",<br>
+ &i_dummy,&i_dummy,&i_dummy,&i_dummy,<br>
+ &i_dummy,&i_dummy,&i_dummy ) == 7 ||<br>
+ sscanf( s, "%d:%d:%d.%d --> %d:%d:%d.%d",<br>
&i_dummy,&i_dummy,&i_dummy,&i_dummy,<br>
- &i_dummy,&i_dummy,&i_dummy,&i_dummy ) == 8 )<br>
+ &i_dummy,&i_dummy,&i_dummy,&i_dummy ) == 8 ||<br>
+ sscanf( s, "%d:%d:%d --> %d:%d:%d.%d",<br>
+ &i_dummy,&i_dummy,&i_dummy,&i_dummy,<br>
+ &i_dummy,&i_dummy,&i_dummy ) == 7 ||<br>
+ sscanf( s, "%d:%d:%d.%d --> %d:%d:%d",<br>
+ &i_dummy,&i_dummy,&i_dummy,&i_dummy,<br>
+ &i_dummy,&i_dummy,&i_dummy ) == 7 ||<br>
+ sscanf( s, "%d:%d:%d --> %d:%d:%d",<br>
+ &i_dummy,&i_dummy,&i_dummy,<br>
+ &i_dummy,&i_dummy,&i_dummy ) == 6 )<br>
{<br>
- msg_Err( p_demux, "Detected invalid SubRip file, playing anyway" );<br>
- p_sys->i_type = SUB_TYPE_SUBRIP_DOT;<br>
+ p_sys->i_type = SUB_TYPE_SUBRIP;<br>
break;<br>
}<br>
else if( !strncasecmp( s, "!: This is a Sub Station Alpha v1", 33 ) )<br>
@@ -899,7 +904,7 @@ static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle,<br>
* We ignore line number for SubRip<br>
*/<br>
static int ParseSubRipSubViewer( demux_t *p_demux, subtitle_t *p_subtitle,<br>
- const char *psz_fmt,<br>
+ int (* pf_parse_timing)(subtitle_t *, const char *),<br>
bool b_replace_br )<br>
{<br>
demux_sys_t *p_sys = p_demux->p_sys;<br>
@@ -909,26 +914,14 @@ static int ParseSubRipSubViewer( demux_t *p_demux, subtitle_t *p_subtitle,<br>
for( ;; )<br>
{<br>
const char *s = TextGetLine( txt );<br>
- int h1, m1, s1, d1, h2, m2, s2, d2;<br>
<br>
if( !s )<br>
return VLC_EGENERIC;<br>
<br>
- if( sscanf( s, psz_fmt,<br>
- &h1, &m1, &s1, &d1,<br>
- &h2, &m2, &s2, &d2 ) == 8 )<br>
+ if( pf_parse_timing( p_subtitle, s) == VLC_SUCCESS &&<br>
+ p_subtitle->i_start < p_subtitle->i_stop )<br>
{<br>
- p_subtitle->i_start = ( (int64_t)h1 * 3600*1000 +<br>
- (int64_t)m1 * 60*1000 +<br>
- (int64_t)s1 * 1000 +<br>
- (int64_t)d1 ) * 1000;<br>
-<br>
- p_subtitle->i_stop = ( (int64_t)h2 * 3600*1000 +<br>
- (int64_t)m2 * 60*1000 +<br>
- (int64_t)s2 * 1000 +<br>
- (int64_t)d2 ) * 1000;<br>
- if( p_subtitle->i_start < p_subtitle->i_stop )<br>
- break;<br>
+ break;<br>
}<br>
}<br>
<br>
@@ -972,6 +965,56 @@ static int ParseSubRipSubViewer( demux_t *p_demux, subtitle_t *p_subtitle,<br>
}<br>
}<br>
}<br>
+<br>
+/* subtitle_ParseSubRipTimingValue<br>
+ * Parses SubRip timing value.<br>
+ */<br>
+static int subtitle_ParseSubRipTimingValue(int64_t *timing_value,<br>
+ const char *s)<br>
+{<br>
+ int h1, m1, s1, d1 = 0;<br>
+<br>
+ if ( sscanf( s, "%d:%d:%d,%d",<br>
+ &h1, &m1, &s1, &d1 ) == 4 ||<br>
+ sscanf( s, "%d:%d:%d.%d",<br>
+ &h1, &m1, &s1, &d1 ) == 4 ||<br>
+ sscanf( s, "%d:%d:%d",<br>
+ &h1, &m1, &s1) == 3 )<br>
+ {<br>
+ (*timing_value) = ( (int64_t)h1 * 3600 * 1000 +<br>
+ (int64_t)m1 * 60 * 1000 +<br>
+ (int64_t)s1 * 1000 +<br>
+ (int64_t)d1 ) * 1000;<br>
+<br>
+ return VLC_SUCCESS;<br>
+ }<br>
+<br>
+ return VLC_EGENERIC;<br>
+}<br>
+<br>
+/* subtitle_ParseSubRipTiming<br>
+ * Parses SubRip timing.<br>
+ */<br>
+static int subtitle_ParseSubRipTiming( subtitle_t *p_subtitle,<br>
+ const char *s )<br>
+{<br>
+ int i_result = VLC_EGENERIC;<br>
+ char *psz_start, *psz_stop;<br>
+ psz_start = malloc( strlen(s) );<br>
+ psz_stop = malloc( strlen(s) );<br>
+<br>
+ if( sscanf( s, "%s --> %s", psz_start, psz_stop) == 2 &&<br>
+ subtitle_ParseSubRipTimingValue( &p_subtitle->i_start, psz_start ) == VLC_SUCCESS &&<br>
+ subtitle_ParseSubRipTimingValue( &p_subtitle->i_stop, psz_stop ) == VLC_SUCCESS )<br>
+ {<br>
+ i_result = VLC_SUCCESS;<br>
+ }<br>
+<br>
+ free(psz_start);<br>
+ free(psz_stop);<br>
+<br>
+ return i_result;<br>
+}<br>
/* ParseSubRip<br>
*/<br>
static int ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle,<br>
@@ -979,20 +1022,35 @@ static int ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle,<br>
{<br>
VLC_UNUSED( i_idx );<br>
return ParseSubRipSubViewer( p_demux, p_subtitle,<br>
- "%d:%d:%d,%d --> %d:%d:%d,%d",<br>
+ &subtitle_ParseSubRipTiming,<br>
false );<br>
}<br>
-/* ParseSubRipDot<br>
- * Special version for buggy file using '.' instead of ','<br>
+<br>
+/* subtitle_ParseSubViewerTiming<br>
+ * Parses SubViewer timing.<br>
*/<br>
-static int ParseSubRipDot( demux_t *p_demux, subtitle_t *p_subtitle,<br>
- int i_idx )<br>
+static int subtitle_ParseSubViewerTiming( subtitle_t *p_subtitle,<br>
+ const char *s )<br>
{<br>
- VLC_UNUSED( i_idx );<br>
- return ParseSubRipSubViewer( p_demux, p_subtitle,<br>
- "%d:%d:%d.%d --> %d:%d:%d.%d",<br>
- false );<br>
+ int h1, m1, s1, d1, h2, m2, s2, d2;<br>
+<br>
+ if( sscanf( s, "%d:%d:%d.%d,%d:%d:%d.%d",<br>
+ &h1, &m1, &s1, &d1, &h2, &m2, &s2, &d2) == 8 )<br>
+ {<br>
+ p_subtitle->i_start = ( (int64_t)h1 * 3600*1000 +<br>
+ (int64_t)m1 * 60*1000 +<br>
+ (int64_t)s1 * 1000 +<br>
+ (int64_t)d1 ) * 1000;<br>
+<br>
+ p_subtitle->i_stop = ( (int64_t)h2 * 3600*1000 +<br>
+ (int64_t)m2 * 60*1000 +<br>
+ (int64_t)s2 * 1000 +<br>
+ (int64_t)d2 ) * 1000;<br>
+ return VLC_SUCCESS;<br>
+ }<br>
+ return VLC_EGENERIC;<br>
}<br>
+<br>
/* ParseSubViewer<br>
*/<br>
static int ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle,<br>
@@ -1001,7 +1059,7 @@ static int ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle,<br>
VLC_UNUSED( i_idx );<br>
<br>
return ParseSubRipSubViewer( p_demux, p_subtitle,<br>
- "%d:%d:%d.%d,%d:%d:%d.%d",<br>
+ &subtitle_ParseSubViewerTiming,<br>
true );<br>
}<br>
<span><font color="#888888"><br>
--<br>
Maxim Bublis<br>
<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div></div></div><span class="HOEnZb"><font color="#888888">-- <br>Maxim Bublis
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Maxim Bublis
</div>