]> git.sesse.net Git - vlc/blobdiff - modules/demux/subtitle.c
mkv.cpp: fix some memory leaks
[vlc] / modules / demux / subtitle.c
index a3c60f39095bd9835cb7d725bf3e89ddf50186f3..309b5128c092b6742797a9332012ebca6889b5fd 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
- * subtitle.c: Demux for text and vobsub files.
+ * subtitle.c: Demux for subtitle text files.
  *****************************************************************************
- * Copyright (C) 1999-2004 VideoLAN
+ * Copyright (C) 1999-2004 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 #include <stdlib.h>
 
 #include <errno.h>
-#include <sys/types.h>
+#ifdef HAVE_SYS_TYPES_H
+#   include <sys/types.h>
+#endif
 #include <ctype.h>
 
 #include <vlc/vlc.h>
 #include <vlc/input.h>
 #include "vlc_video.h"
 
-#include "../ps.h"
-
-#if (!defined( WIN32 ) || defined(__MINGW32__))
-#    include <dirent.h>
-#endif
-
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
@@ -53,27 +49,32 @@ 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", "vobsub"
+    "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 );
+    add_integer( "sub-delay", 0, NULL,
+               N_("Subtitles delay"),
+               SUB_DELAY_LONGTEXT, VLC_TRUE );
     add_string( "sub-type", "auto", NULL, "Subtitles fileformat",
                 SUB_TYPE_LONGTEXT, VLC_TRUE );
         change_string_list( ppsz_sub_type, 0, 0 );
     set_callbacks( Open, Close );
 
     add_shortcut( "subtitle" );
-    add_shortcut( "vobsub" );
 vlc_module_end();
 
 /*****************************************************************************
@@ -86,10 +87,10 @@ 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_VOBSUB,
 };
 
 typedef struct
@@ -103,11 +104,10 @@ 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;
-    int     i_vobsub_location;
 } subtitle_t;
 
 
@@ -120,13 +120,12 @@ struct demux_sys_t
     int64_t     i_next_demux_date;
 
     int64_t     i_microsecperframe;
+    int64_t     i_original_mspf;
 
     char        *psz_header;
     int         i_subtitle;
     int         i_subtitles;
     subtitle_t  *subtitle;
-    FILE        *p_vobsub_file;
-    mtime_t     i_original_mspf;
 
     int64_t     i_length;
 };
@@ -137,9 +136,6 @@ 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  ParseVobSubIDX( demux_t *, subtitle_t * );
-
-static int  DemuxVobSub( demux_t *, block_t * );
 
 static struct
 {
@@ -154,18 +150,16 @@ 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 },
-    { "vobsub",     SUB_TYPE_VOBSUB,    "VobSub",   ParseVobSubIDX },
     { NULL,         SUB_TYPE_UNKNOWN,   "Unknown",  NULL }
 };
 
 static int Demux( demux_t * );
 static int Control( demux_t *, int, va_list );
 
-static void Fix( demux_t * );
-
-#define DVD_VIDEO_LB_LEN 2048
+/*static void Fix( demux_t * );*/
 
 /*****************************************************************************
  * Module initializer
@@ -180,8 +174,7 @@ static int Open ( vlc_object_t *p_this )
     int  (*pf_read)( demux_t *, subtitle_t* );
     int i, i_max;
 
-    if( strcmp( p_demux->psz_demux, "subtitle" ) &&
-        strcmp( p_demux->psz_demux, "vobsub" ) )
+    if( strcmp( p_demux->psz_demux, "subtitle" ) )
     {
         msg_Dbg( p_demux, "subtitle demux discarded" );
         return VLC_EGENERIC;
@@ -194,16 +187,27 @@ static int Open ( vlc_object_t *p_this )
     p_sys->i_subtitle = 0;
     p_sys->i_subtitles= 0;
     p_sys->subtitle   = NULL;
-    p_sys->p_vobsub_file = NULL;
-    p_sys->i_original_mspf = 0;
 
 
     /* 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 = (mtime_t)( (float)1000000 / f_fps );
+        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 )
+    {
+        p_sys->i_original_mspf = (int64_t)( (float)1000000 / f_fps );
+    }
+    else
+    {
+        p_sys->i_original_mspf = 0;
     }
 
     /* Get or probe the type */
@@ -232,7 +236,7 @@ static int Open ( vlc_object_t *p_this )
     if( p_sys->i_type == SUB_TYPE_UNKNOWN )
     {
         int     i_try;
-        char    *s;
+        char    *s = NULL;
 
         msg_Dbg( p_demux, "autodetecting subtitle format" );
         for( i_try = 0; i_try < 256; i_try++ )
@@ -261,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]" ) )
@@ -296,13 +301,13 @@ static int Open ( vlc_object_t *p_this )
                 p_sys->i_type = SUB_TYPE_VPLAYER;
                 break;
             }
-            else if( strcasestr( s, "# VobSub index file" ) )
-            {
-                p_sys->i_type = SUB_TYPE_VOBSUB;
-                break;
-            }
+
+            free( s );
+            s = NULL;
         }
 
+        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 */
         if( stream_Seek( p_demux->s, 0 ) )
@@ -313,6 +318,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;
     }
 
@@ -342,6 +348,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;
             }
         }
@@ -358,10 +368,6 @@ static int Open ( vlc_object_t *p_this )
 
     /* Fix subtitle (order and time) *** */
     p_sys->i_subtitle = 0;
-    if( p_sys->i_type != SUB_TYPE_VOBSUB )
-    {
-        Fix( p_demux );
-    }
     p_sys->i_length = 0;
     if( p_sys->i_subtitles > 0 )
     {
@@ -372,25 +378,9 @@ static int Open ( vlc_object_t *p_this )
     }
 
     /* *** add subtitle ES *** */
-    if( p_sys->i_type == SUB_TYPE_VOBSUB )
-    {
-        int i_len = strlen( p_demux->psz_path );
-        char *psz_vobname = strdup( p_demux->psz_path );
-
-        strcpy( psz_vobname + i_len - 4, ".sub" );
-
-        /* open file */
-        if( !( p_sys->p_vobsub_file = fopen( psz_vobname, "rb" ) ) )
-        {
-            msg_Err( p_demux, "couldn't open .sub Vobsub file: %s",
-                     psz_vobname );
-        }
-        free( psz_vobname );
-
-        es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','p','u',' ' ) );
-    }
-    else if( p_sys->i_type == SUB_TYPE_SSA1 ||
-             p_sys->i_type == SUB_TYPE_SSA2_4 )
+    if( p_sys->i_type == SUB_TYPE_SSA1 ||
+             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',' ' ) );
     }
@@ -425,9 +415,6 @@ static void Close( vlc_object_t *p_this )
     if( p_sys->subtitle )
         free( p_sys->subtitle );
 
-    if( p_sys->p_vobsub_file )
-        fclose( p_sys->p_vobsub_file );
-
     free( p_sys );
 }
 
@@ -464,6 +451,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             {
                 p_sys->i_subtitle++;
             }
+
             if( p_sys->i_subtitle >= p_sys->i_subtitles )
                 return VLC_EGENERIC;
             return VLC_SUCCESS;
@@ -525,113 +513,57 @@ 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;
-    msg_Dbg( p_demux, "sub demux until %lld", i_maxdate );
+    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 */
         i_maxdate = p_sys->subtitle[p_sys->i_subtitle].i_start + 1;
     }
 
-    if( p_sys->i_type != SUB_TYPE_VOBSUB )
+    while( p_sys->i_subtitle < p_sys->i_subtitles &&
+           p_sys->subtitle[p_sys->i_subtitle].i_start < i_maxdate )
     {
-        while( p_sys->i_subtitle < p_sys->i_subtitles &&
-               p_sys->subtitle[p_sys->i_subtitle].i_start < i_maxdate )
-        {
-            block_t *p_block;
-            int i_len = strlen( p_sys->subtitle[p_sys->i_subtitle].psz_text ) + 1;
-
-            msg_Dbg( p_demux, "sub[%d] '%s'", p_sys->i_subtitle, p_sys->subtitle[p_sys->i_subtitle].psz_text );
-            if( i_len <= 1 )
-            {
-                /* empty subtitle */
-                p_sys->i_subtitle++;
-                continue;
-            }
-
-            if( ( p_block = block_New( p_demux, i_len ) ) == NULL )
-            {
-                p_sys->i_subtitle++;
-                continue;
-            }
+        block_t *p_block;
+        int i_len = strlen( p_sys->subtitle[p_sys->i_subtitle].psz_text ) + 1;
 
-            if( p_sys->subtitle[p_sys->i_subtitle].i_start < 0 )
-            {
-                p_sys->i_subtitle++;
-                continue;
-            }
-
-            p_block->i_pts = p_sys->subtitle[p_sys->i_subtitle].i_start;
-            p_block->i_dts = p_block->i_pts;
-            if( p_sys->subtitle[p_sys->i_subtitle].i_stop > 0 )
-            {
-                p_block->i_length =
-                    p_sys->subtitle[p_sys->i_subtitle].i_stop - p_block->i_pts;
-            }
-
-            memcpy( p_block->p_buffer,
-                    p_sys->subtitle[p_sys->i_subtitle].psz_text, i_len );
-            if( p_block->i_pts > 0 )
-            {
-                es_out_Send( p_demux->out, p_sys->es, p_block );
-            }
-            else
-            {
-                block_Release( p_block );
-            }
+        if( i_len <= 1 )
+        {
+            /* empty subtitle */
             p_sys->i_subtitle++;
+            continue;
         }
-    }
-    else
-    {
-        while( p_sys->i_subtitle < p_sys->i_subtitles &&
-               p_sys->subtitle[p_sys->i_subtitle].i_start < i_maxdate )
-        {
-            int i_pos = p_sys->subtitle[p_sys->i_subtitle].i_vobsub_location;
-            block_t *p_block;
-            int i_size = 0;
-
-            /* first compute SPU size */
-            if( p_sys->i_subtitle + 1 < p_sys->i_subtitles )
-            {
-                i_size = p_sys->subtitle[p_sys->i_subtitle+1].i_vobsub_location - i_pos;
-            }
-            if( i_size <= 0 ) i_size = 65535;   /* Invalid or EOF */
 
-            /* Seek at the right place */
-            if( fseek( p_sys->p_vobsub_file, i_pos, SEEK_SET ) )
-            {
-                msg_Warn( p_demux,
-                          "cannot seek at right vobsub location %d", i_pos );
-                p_sys->i_subtitle++;
-                continue;
-            }
-
-            /* allocate a packet */
-            if( ( p_block = block_New( p_demux, i_size ) ) == NULL )
-            {
-                p_sys->i_subtitle++;
-                continue;
-            }
-
-            /* read data */
-            p_block->i_buffer = fread( p_block->p_buffer, 1, i_size,
-                                       p_sys->p_vobsub_file );
-            if( p_block->i_buffer <= 6 )
-            {
-                block_Release( p_block );
-                p_sys->i_subtitle++;
-                continue;
-            }
+        if( ( p_block = block_New( p_demux, i_len ) ) == NULL )
+        {
+            p_sys->i_subtitle++;
+            continue;
+        }
 
-            /* pts */
-            p_block->i_pts = p_sys->subtitle[p_sys->i_subtitle].i_start;
+        if( p_sys->subtitle[p_sys->i_subtitle].i_start < 0 )
+        {
+            p_sys->i_subtitle++;
+            continue;
+        }
 
-            /* demux this block */
-            DemuxVobSub( p_demux, p_block );
+        p_block->i_pts = p_sys->subtitle[p_sys->i_subtitle].i_start;
+        p_block->i_dts = p_block->i_pts;
+        if( p_sys->subtitle[p_sys->i_subtitle].i_stop > 0 )
+        {
+            p_block->i_length =
+                p_sys->subtitle[p_sys->i_subtitle].i_stop - p_block->i_pts;
+        }
 
-            p_sys->i_subtitle++;
+        memcpy( p_block->p_buffer,
+                p_sys->subtitle[p_sys->i_subtitle].psz_text, i_len );
+        if( p_block->i_pts > 0 )
+        {
+            es_out_Send( p_demux->out, p_sys->es, p_block );
+        }
+        else
+        {
+            block_Release( p_block );
         }
+        p_sys->i_subtitle++;
     }
 
     /* */
@@ -643,6 +575,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;
@@ -676,6 +609,7 @@ static void Fix( demux_t *p_demux )
         }
     } while( !b_done );
 }
+#endif
 
 static int TextLoad( text_t *txt, stream_t *s )
 {
@@ -749,18 +683,21 @@ 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;
 
+    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->i_vobsub_location  = 0;
     p_subtitle->psz_text = NULL;
 
     for( ;; )
@@ -788,8 +725,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 * i_microsecperframe;
+    p_subtitle->i_stop  = (int64_t)i_stop  * i_microsecperframe;
     p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
     return( 0 );
 }
@@ -811,12 +748,11 @@ 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;
-    p_subtitle->i_vobsub_location  = 0;
     p_subtitle->psz_text = NULL;
 
     for( ;; )
@@ -831,15 +767,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;; )
@@ -851,7 +787,7 @@ static int  ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle )
                 }
 
                 i_len = strlen( s );
-                if( i_len <= 1 )
+                if( i_len <= 0 )
                 {
                     /* empty line -> end of this subtitle */
                     buffer_text[__MAX( i_buffer_text - 1, 0 )] = '\0';
@@ -862,12 +798,12 @@ static int  ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle )
                     if( p_sys->i_microsecperframe != 0 &&
                         p_sys->i_original_mspf != 0)
                     {
-                        p_subtitle->i_start = (mtime_t)i_start *
-                                              p_sys->i_original_mspf /
-                                              p_sys->i_microsecperframe;
-                        p_subtitle->i_stop  = (mtime_t)i_stop  *
-                                              p_sys->i_original_mspf /
-                                              p_sys->i_microsecperframe;
+                        p_subtitle->i_start = (int64_t)i_start *
+                                              p_sys->i_microsecperframe/
+                                              p_sys->i_original_mspf;
+                        p_subtitle->i_stop  = (int64_t)i_stop  *
+                                              p_sys->i_microsecperframe /
+                                              p_sys->i_original_mspf;
                     }
                     return 0;
                 }
@@ -905,12 +841,11 @@ 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;
-    p_subtitle->i_vobsub_location  = 0;
     p_subtitle->psz_text = NULL;
 
     for( ;; )
@@ -925,15 +860,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;; )
@@ -945,7 +880,7 @@ static int  ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle )
                 }
 
                 i_len = strlen( s );
-                if( i_len <= 1 )
+                if( i_len <= 0 )
                 {
                     /* empty line -> end of this subtitle */
                     buffer_text[__MAX( i_buffer_text - 1, 0 )] = '\0';
@@ -953,14 +888,15 @@ static int  ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle )
                     p_subtitle->i_stop = i_stop;
 
                     /* replace [br] by \n */
-                    for( i = 0; i < strlen( buffer_text ) - 3; i++ )
+                    for( i = 0; i < i_buffer_text - 3; i++ )
                     {
                         if( buffer_text[i] == '[' && buffer_text[i+1] == 'b' &&
                             buffer_text[i+2] == 'r' && buffer_text[i+3] == ']' )
                         {
                             char *temp = buffer_text + i + 1;
                             buffer_text[i] = '\n';
-                            memmove( temp, temp+3, strlen( temp-3 ));
+                            memmove( temp, temp+3, strlen( temp ) -3 );
+                            temp[strlen( temp )-3] = '\0';
                         }
                     }
                     p_subtitle->psz_text = strdup( buffer_text );
@@ -991,19 +927,18 @@ 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;
-    p_subtitle->i_vobsub_location  = 0;
     p_subtitle->psz_text = NULL;
 
     for( ;; )
     {
         int h1, m1, s1, c1, h2, m2, s2, c2;
-        int i_dummy;
 
         if( ( s = TextGetLine( txt ) ) == NULL )
         {
@@ -1011,33 +946,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;
@@ -1085,12 +1032,11 @@ 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;
     p_subtitle->i_stop  = 0;
-    p_subtitle->i_vobsub_location  = 0;
     p_subtitle->psz_text = NULL;
 
     for( ;; )
@@ -1108,9 +1054,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;
         }
     }
@@ -1167,14 +1113,13 @@ 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];
 
     p_subtitle->i_start = 0;
     p_subtitle->i_stop  = 0;
-    p_subtitle->i_vobsub_location  = 0;
     p_subtitle->psz_text = NULL;
 
 #define ADDC( c ) \
@@ -1258,117 +1203,3 @@ static int  ParseSami( demux_t *p_demux, subtitle_t *p_subtitle )
     return( VLC_SUCCESS );
 #undef ADDC
 }
-
-static int  ParseVobSubIDX( demux_t *p_demux, subtitle_t *p_subtitle )
-{
-    demux_sys_t *p_sys = p_demux->p_sys;
-    text_t      *txt = &p_sys->txt;
-
-    /*
-     * Parse the idx file. Each line:
-     * timestamp: hh:mm:ss:mss, filepos: loc
-     * hexint is the hex location of the vobsub in the .sub file
-     *
-     */
-    char *p;
-    char buffer_text[MAX_LINE + 1];
-    unsigned int    i_start, i_location;
-
-    p_subtitle->i_start = 0;
-    p_subtitle->i_stop  = 0;
-    p_subtitle->i_vobsub_location  = 0;
-    p_subtitle->psz_text = NULL;
-
-    for( ;; )
-    {
-        unsigned int h, m, s, ms, loc;
-
-        if( ( p = TextGetLine( txt ) ) == NULL )
-        {
-            return( VLC_EGENERIC );
-        }
-        i_start = 0;
-
-        memset( buffer_text, '\0', MAX_LINE );
-        if( sscanf( p, "timestamp: %d:%d:%d:%d, filepos: %x%[^\r\n]",
-                    &h, &m, &s, &ms, &loc, buffer_text ) == 5 )
-        {
-            i_start = ( (mtime_t)h * 3600*1000 +
-                        (mtime_t)m * 60*1000 +
-                        (mtime_t)s * 1000 +
-                        (mtime_t)ms ) * 1000;
-            i_location = loc;
-            break;
-        }
-    }
-    p_subtitle->i_start = (mtime_t)i_start;
-    p_subtitle->i_stop  = 0;
-    p_subtitle->psz_text = NULL;
-    p_subtitle->i_vobsub_location = i_location;
-    fprintf( stderr, "time: %x, location: %x\n", i_start, i_location );
-    return( 0 );
-}
-
-static int  DemuxVobSub( demux_t *p_demux, block_t *p_bk )
-{
-    demux_sys_t *p_sys = p_demux->p_sys;
-    uint8_t     *p = p_bk->p_buffer;
-    uint8_t     *p_end = &p_bk->p_buffer[p_bk->i_buffer];
-
-    while( p < p_end )
-    {
-        int i_size = ps_pkt_size( p, p_end - p );
-        block_t *p_pkt;
-        int      i_id;
-        int      i_spu;
-
-        if( i_size <= 0 )
-        {
-            break;
-        }
-        if( p[0] != 0 || p[1] != 0 || p[2] != 0x01 )
-        {
-            msg_Warn( p_demux, "invalid PES" );
-            break;
-        }
-
-        if( p[3] != 0xbd )
-        {
-            msg_Dbg( p_demux, "we don't need these ps packets (id=0x1%2.2x)", p[3] );
-            p += i_size;
-            continue;
-        }
-
-        /* Create a block */
-        p_pkt = block_New( p_demux, i_size );
-        memcpy( p_pkt->p_buffer, p, i_size);
-        p += i_size;
-
-        i_id = ps_pkt_id( p_pkt );
-        if( (i_id&0xffe0) != 0xbd20 ||
-            ps_pkt_parse_pes( p_pkt, 1 ) )
-        {
-            block_Release( p_pkt );
-            continue;
-        }
-        i_spu = i_id&0x1f;
-        msg_Dbg( p_demux, "SPU track %d size %d", i_spu, i_size );
-
-        /* FIXME i_spu == determines which of the spu tracks we will show. */
-        if( p_sys->es && i_spu == 0 )
-        {
-            p_pkt->i_dts = p_pkt->i_pts = p_bk->i_pts;
-            p_pkt->i_length = 0;
-            es_out_Send( p_demux->out, p_sys->es, p_pkt );
-
-            p_bk->i_pts = 0;    /* only first packet has a pts */
-        }
-        else
-        {
-            block_Release( p_pkt );
-            continue;
-        }
-    }
-
-    return VLC_SUCCESS;
-}