* sub ->subtitle : converted sub.c to a 'real' demux2.
authorLaurent Aimar <fenrir@videolan.org>
Fri, 25 Jun 2004 18:35:56 +0000 (18:35 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Fri, 25 Jun 2004 18:35:56 +0000 (18:35 +0000)
 * input.c: added basic multi-input support for subtitle.
 * avi, mp4: don't exit anymore when no es selected.

13 files changed:
configure.ac
modules/demux/Modules.am
modules/demux/avi/avi.c
modules/demux/mp4/mp4.c
modules/demux/subtitle.c [new file with mode: 0644]
modules/demux/util/Modules.am
modules/demux/util/sub.c [deleted file]
modules/demux/util/sub.h [deleted file]
src/input/decoder.c
src/input/es_out.c
src/input/input.c
src/input/input_internal.h
src/input/stream.c

index 819a7cd..7757969 100644 (file)
@@ -900,7 +900,7 @@ VLC_ADD_PLUGINS([aout_file])
 VLC_ADD_PLUGINS([i420_rgb i420_yuy2 i422_yuy2 i420_ymga])
 VLC_ADD_PLUGINS([m3u playlist export sgimb])
 VLC_ADD_PLUGINS([rawvideo])
-VLC_ADD_PLUGINS([wav araw demuxsub adpcm a52sys dtssys au])
+VLC_ADD_PLUGINS([wav araw subtitle adpcm a52sys dtssys au])
 VLC_ADD_PLUGINS([access_file access_udp access_tcp access_http ipv4 access_mms])
 VLC_ADD_PLUGINS([access_ftp access_directory sap http])
 
index fa7c803..e923751 100644 (file)
@@ -20,3 +20,4 @@ SOURCES_pva = pva.c
 SOURCES_aiff = aiff.c
 SOURCES_sgimb = sgimb.c
 SOURCES_mjpeg = mjpeg.c
+SOURCES_subtitle = subtitle.c
index 44b7c2c..695ff7d 100644 (file)
@@ -610,8 +610,17 @@ static int Demux_Seekable( demux_t *p_demux )
 
     if( i_track_count <= 0 )
     {
+        int64_t i_length = p_sys->i_length * (mtime_t)1000000;
+
+        p_sys->i_time += 25*1000;  /* read 25ms */
+        if( i_length > 0 )
+        {
+            if( p_sys->i_time >= i_length )
+                return 0;
+            return 1;
+        }
         msg_Warn( p_demux, "no track selected, exiting..." );
-        return( 0 );
+        return 0;
     }
 
     /* wait for the good time */
index d5bab26..253dce0 100644 (file)
@@ -528,6 +528,17 @@ static int Demux( demux_t *p_demux )
 
     if( i_track_selected <= 0 )
     {
+        p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
+        if( p_sys->i_timescale > 0 )
+        {
+            int64_t i_length = (mtime_t)1000000 *
+                               (mtime_t)p_sys->i_duration /
+                               (mtime_t)p_sys->i_timescale;
+            if( MP4_GetMoviePTS( p_sys ) >= i_length )
+                return 0;
+            return 1;
+        }
+
         msg_Warn( p_demux, "no track selected, exiting..." );
         return 0;
     }
diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c
new file mode 100644 (file)
index 0000000..a3c60f3
--- /dev/null
@@ -0,0 +1,1374 @@
+/*****************************************************************************
+ * subtitle.c: Demux for text and vobsub files.
+ *****************************************************************************
+ * Copyright (C) 1999-2004 VideoLAN
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Derk-Jan Hartman <hartman at videolan dot org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#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
+ *****************************************************************************/
+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)"
+#define SUB_FPS_LONGTEXT \
+    "Override frames per second. " \
+    "It will only work with MicroDVD 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[] =
+{
+    "auto", "microdvd", "subrip", "subviewer", "ssa1",
+    "ssa2-4", "vplayer", "sami", "vobsub"
+};
+
+vlc_module_begin();
+    set_description( _("Text subtitles demux") );
+    set_capability( "demux2", 0 );
+    add_float( "sub-fps", 0.0, NULL,
+               N_("Frames per second"),
+               SUB_FPS_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();
+
+/*****************************************************************************
+ * Prototypes:
+ *****************************************************************************/
+enum
+{
+    SUB_TYPE_UNKNOWN = -1,
+    SUB_TYPE_MICRODVD,
+    SUB_TYPE_SUBRIP,
+    SUB_TYPE_SSA1,
+    SUB_TYPE_SSA2_4,
+    SUB_TYPE_VPLAYER,
+    SUB_TYPE_SAMI,
+    SUB_TYPE_SUBVIEWER,
+    SUB_TYPE_VOBSUB,
+};
+
+typedef struct
+{
+    int     i_line_count;
+    int     i_line;
+    char    **line;
+} text_t;
+static int  TextLoad( text_t *, stream_t *s );
+static void TextUnload( text_t * );
+
+typedef struct
+{
+    mtime_t i_start;
+    mtime_t i_stop;
+
+    char    *psz_text;
+    int     i_vobsub_location;
+} subtitle_t;
+
+
+struct demux_sys_t
+{
+    int         i_type;
+    text_t      txt;
+    es_out_id_t *es;
+
+    int64_t     i_next_demux_date;
+
+    int64_t     i_microsecperframe;
+
+    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;
+};
+
+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  ParseVobSubIDX( demux_t *, subtitle_t * );
+
+static int  DemuxVobSub( demux_t *, block_t * );
+
+static struct
+{
+    char *psz_type_name;
+    int  i_type;
+    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 },
+    { "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
+
+/*****************************************************************************
+ * 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;
+    int  (*pf_read)( demux_t *, subtitle_t* );
+    int i, i_max;
+
+    if( strcmp( p_demux->psz_demux, "subtitle" ) &&
+        strcmp( p_demux->psz_demux, "vobsub" ) )
+    {
+        msg_Dbg( p_demux, "subtitle demux discarded" );
+        return VLC_EGENERIC;
+    }
+
+    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->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 );
+    }
+
+    /* Get or probe the type */
+    p_sys->i_type = SUB_TYPE_UNKNOWN;
+    psz_type = var_CreateGetString( p_demux, "sub-type" );
+    if( *psz_type )
+    {
+        int i;
+
+        for( i = 0; ; i++ )
+        {
+            if( sub_read_subtitle_function[i].psz_type_name == NULL )
+                break;
+
+            if( !strcmp( sub_read_subtitle_function[i].psz_type_name,
+                         psz_type ) )
+            {
+                p_sys->i_type = sub_read_subtitle_function[i].i_type;
+                break;
+            }
+        }
+    }
+    free( psz_type );
+
+    /* Probe if unknown type */
+    if( p_sys->i_type == SUB_TYPE_UNKNOWN )
+    {
+        int     i_try;
+        char    *s;
+
+        msg_Dbg( p_demux, "autodetecting subtitle format" );
+        for( i_try = 0; i_try < 256; i_try++ )
+        {
+            int i_dummy;
+
+            if( ( s = stream_ReadLine( p_demux->s ) ) == NULL )
+                break;
+
+            if( strcasestr( s, "<SAMI>" ) )
+            {
+                p_sys->i_type = SUB_TYPE_SAMI;
+                break;
+            }
+            else if( sscanf( s, "{%d}{%d}", &i_dummy, &i_dummy ) == 2 ||
+                     sscanf( s, "{%d}{}", &i_dummy ) == 1)
+            {
+                p_sys->i_type = SUB_TYPE_MICRODVD;
+                break;
+            }
+            else if( sscanf( s,
+                             "%d:%d:%d,%d --> %d:%d:%d,%d",
+                             &i_dummy,&i_dummy,&i_dummy,&i_dummy,
+                             &i_dummy,&i_dummy,&i_dummy,&i_dummy ) == 8 )
+            {
+                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)
+            {
+                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 */
+                }
+                break;
+            }
+            else if( strcasestr( s, "This is a Sub Station Alpha v4 script" ) )
+            {
+                p_sys->i_type = SUB_TYPE_SSA2_4; /* I hope this will work */
+                break;
+            }
+            else if( !strncasecmp( s, "Dialogue: Marked", 16  ) )
+            {
+                p_sys->i_type = SUB_TYPE_SSA2_4; /* could be wrong */
+                break;
+            }
+            else if( strcasestr( s, "[INFORMATION]" ) )
+            {
+                p_sys->i_type = SUB_TYPE_SUBVIEWER; /* I hope this will work */
+                break;
+            }
+            else if( sscanf( s, "%d:%d:%d:", &i_dummy, &i_dummy, &i_dummy ) == 3 ||
+                     sscanf( s, "%d:%d:%d ", &i_dummy, &i_dummy, &i_dummy ) == 3 )
+            {
+                p_sys->i_type = SUB_TYPE_VPLAYER;
+                break;
+            }
+            else if( strcasestr( s, "# VobSub index file" ) )
+            {
+                p_sys->i_type = SUB_TYPE_VOBSUB;
+                break;
+            }
+        }
+
+        /* 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 ) )
+        {
+            msg_Warn( p_demux, "failed to rewind" );
+        }
+    }
+    if( p_sys->i_type == SUB_TYPE_UNKNOWN )
+    {
+        msg_Err( p_demux, "failed to recognize subtitle type" );
+        return VLC_EGENERIC;
+    }
+
+    for( i = 0; ; i++ )
+    {
+        if( sub_read_subtitle_function[i].i_type == p_sys->i_type )
+        {
+            msg_Dbg( p_demux, "detected %s format",
+                     sub_read_subtitle_function[i].psz_name );
+            pf_read = sub_read_subtitle_function[i].pf_read;
+            break;
+        }
+    }
+
+    msg_Dbg( p_demux, "loading all subtitles..." );
+
+    /* Load the whole file */
+    TextLoad( &p_sys->txt, p_demux->s );
+
+    /* Parse it */
+    for( i_max = 0;; )
+    {
+        if( p_sys->i_subtitles >= i_max )
+        {
+            i_max += 500;
+            if( !( p_sys->subtitle = realloc( p_sys->subtitle,
+                                              sizeof(subtitle_t) * i_max ) ) )
+            {
+                msg_Err( p_demux, "out of memory");
+                return VLC_ENOMEM;
+            }
+        }
+
+        if( pf_read( p_demux, &p_sys->subtitle[p_sys->i_subtitles] ) )
+            break;
+
+        p_sys->i_subtitles++;
+    }
+    /* Unload */
+    TextUnload( &p_sys->txt );
+
+    msg_Dbg(p_demux, "loaded %d subtitles", p_sys->i_subtitles );
+
+    /* 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 )
+    {
+        p_sys->i_length = p_sys->subtitle[p_sys->i_subtitles-1].i_stop;
+        /* +1 to avoid 0 */
+        if( p_sys->i_length <= 0 )
+            p_sys->i_length = p_sys->subtitle[p_sys->i_subtitles-1].i_start+1;
+    }
+
+    /* *** 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 )
+    {
+        es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','s','a',' ' ) );
+    }
+    else
+    {
+        es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','u','b','t' ) );
+    }
+    if( p_sys->psz_header != NULL )
+    {
+        fmt.i_extra = strlen( p_sys->psz_header ) + 1;
+        fmt.p_extra = strdup( p_sys->psz_header );
+    }
+    p_sys->es = es_out_Add( p_demux->out, &fmt );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close: Close subtitle demux
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+    demux_t *p_demux = (demux_t*)p_this;
+    demux_sys_t *p_sys = p_demux->p_sys;
+    int i;
+
+    for( i = 0; i < p_sys->i_subtitles; i++ )
+    {
+        if( p_sys->subtitle[i].psz_text )
+            free( p_sys->subtitle[i].psz_text );
+    }
+    if( p_sys->subtitle )
+        free( p_sys->subtitle );
+
+    if( p_sys->p_vobsub_file )
+        fclose( p_sys->p_vobsub_file );
+
+    free( p_sys );
+}
+
+/*****************************************************************************
+ * Control:
+ *****************************************************************************/
+static int Control( demux_t *p_demux, int i_query, va_list args )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    int64_t *pi64, i64;
+    double *pf, f;
+
+    switch( i_query )
+    {
+        case DEMUX_GET_LENGTH:
+            pi64 = (int64_t*)va_arg( args, int64_t * );
+            *pi64 = p_sys->i_length;
+            return VLC_SUCCESS;
+
+        case DEMUX_GET_TIME:
+            pi64 = (int64_t*)va_arg( args, int64_t * );
+            if( p_sys->i_subtitle < p_sys->i_subtitles )
+            {
+                *pi64 = p_sys->subtitle[p_sys->i_subtitle].i_start;
+                return VLC_SUCCESS;
+            }
+            return VLC_EGENERIC;
+
+        case DEMUX_SET_TIME:
+            i64 = (int64_t)va_arg( args, int64_t );
+            p_sys->i_subtitle = 0;
+            while( p_sys->i_subtitle < p_sys->i_subtitles &&
+                   p_sys->subtitle[p_sys->i_subtitle].i_start < i64 )
+            {
+                p_sys->i_subtitle++;
+            }
+            if( p_sys->i_subtitle >= p_sys->i_subtitles )
+                return VLC_EGENERIC;
+            return VLC_SUCCESS;
+
+        case DEMUX_GET_POSITION:
+            pf = (double*)va_arg( args, double * );
+            if( p_sys->i_subtitle >= p_sys->i_subtitles )
+            {
+                *pf = 1.0;
+            }
+            else if( p_sys->i_subtitles > 0 )
+            {
+                *pf = (double)p_sys->subtitle[p_sys->i_subtitle].i_start /
+                      (double)p_sys->i_length;
+            }
+            else
+            {
+                *pf = 0.0;
+            }
+            return VLC_SUCCESS;
+
+        case DEMUX_SET_POSITION:
+            f = (double)va_arg( args, double );
+            i64 = f * p_sys->i_length;
+
+            p_sys->i_subtitle = 0;
+            while( p_sys->i_subtitle < p_sys->i_subtitles &&
+                   p_sys->subtitle[p_sys->i_subtitle].i_start < i64 )
+            {
+                p_sys->i_subtitle++;
+            }
+            if( p_sys->i_subtitle >= p_sys->i_subtitles )
+                return VLC_EGENERIC;
+            return VLC_SUCCESS;
+
+        case DEMUX_SET_NEXT_DEMUX_TIME:
+            p_sys->i_next_demux_date = (int64_t)va_arg( args, int64_t );
+            return VLC_SUCCESS;
+
+        case DEMUX_GET_FPS:
+        case DEMUX_GET_META:
+        case DEMUX_GET_TITLE_INFO:
+            return VLC_EGENERIC;
+
+        default:
+            msg_Err( p_demux, "unknown query in subtitle control" );
+            return VLC_EGENERIC;
+    }
+}
+
+/*****************************************************************************
+ * Demux: Send subtitle to decoder
+ *****************************************************************************/
+static int Demux( demux_t *p_demux )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    int64_t i_maxdate;
+
+    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 );
+    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 )
+        {
+            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;
+            }
+
+            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 );
+            }
+            p_sys->i_subtitle++;
+        }
+    }
+    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;
+            }
+
+            /* pts */
+            p_block->i_pts = p_sys->subtitle[p_sys->i_subtitle].i_start;
+
+            /* demux this block */
+            DemuxVobSub( p_demux, p_block );
+
+            p_sys->i_subtitle++;
+        }
+    }
+
+    /* */
+    p_sys->i_next_demux_date = 0;
+
+    return 1;
+}
+
+/*****************************************************************************
+ * Fix: fix time stamp and order of subtitle
+ *****************************************************************************/
+static void Fix( demux_t *p_demux )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    vlc_bool_t b_done;
+    int     i_index;
+
+    /* *** fix order (to be sure...) *** */
+    /* We suppose that there are near in order and this durty bubble sort
+     * wont take too much time
+     */
+    do
+    {
+        b_done = VLC_TRUE;
+        for( i_index = 1; i_index < p_sys->i_subtitles; i_index++ )
+        {
+            if( p_sys->subtitle[i_index].i_start <
+                    p_sys->subtitle[i_index - 1].i_start )
+            {
+                subtitle_t sub_xch;
+                memcpy( &sub_xch,
+                        p_sys->subtitle + i_index - 1,
+                        sizeof( subtitle_t ) );
+                memcpy( p_sys->subtitle + i_index - 1,
+                        p_sys->subtitle + i_index,
+                        sizeof( subtitle_t ) );
+                memcpy( p_sys->subtitle + i_index,
+                        &sub_xch,
+                        sizeof( subtitle_t ) );
+                b_done = VLC_FALSE;
+            }
+        }
+    } while( !b_done );
+}
+
+static int TextLoad( text_t *txt, stream_t *s )
+{
+    int   i_line_max;
+
+    /* init txt */
+    i_line_max          = 500;
+    txt->i_line_count   = 0;
+    txt->i_line         = 0;
+    txt->line           = calloc( i_line_max, sizeof( char * ) );
+
+    /* load the complete file */
+    for( ;; )
+    {
+        char *psz = stream_ReadLine( s );
+
+        if( psz == NULL )
+            break;
+
+        txt->line[txt->i_line_count++] = psz;
+        if( txt->i_line_count >= i_line_max )
+        {
+            i_line_max += 100;
+            txt->line = realloc( txt->line, i_line_max * sizeof( char*) );
+        }
+    }
+
+    if( txt->i_line_count <= 0 )
+    {
+        free( txt->line );
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+static void TextUnload( text_t *txt )
+{
+    int i;
+
+    for( i = 0; i < txt->i_line_count; i++ )
+    {
+        free( txt->line[i] );
+    }
+    free( txt->line );
+    txt->i_line       = 0;
+    txt->i_line_count = 0;
+}
+
+static char *TextGetLine( text_t *txt )
+{
+    if( txt->i_line >= txt->i_line_count )
+        return( NULL );
+
+    return txt->line[txt->i_line++];
+}
+static void TextPreviousLine( text_t *txt )
+{
+    if( txt->i_line > 0 )
+        txt->i_line--;
+}
+
+/*****************************************************************************
+ * Specific Subtitle function
+ *****************************************************************************/
+#define MAX_LINE 8192
+static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    text_t      *txt = &p_sys->txt;
+    /*
+     * each line:
+     *  {n1}{n2}Line1|Line2|Line3....
+     * where n1 and n2 are the video frame number...
+     *
+     */
+    char *s;
+
+    char buffer_text[MAX_LINE + 1];
+    unsigned int    i_start;
+    unsigned int    i_stop;
+    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( ;; )
+    {
+        if( ( s = TextGetLine( txt ) ) == NULL )
+        {
+            return( VLC_EGENERIC );
+        }
+        i_start = 0;
+        i_stop  = 0;
+
+        memset( buffer_text, '\0', MAX_LINE );
+        if( sscanf( s, "{%d}{}%[^\r\n]", &i_start, buffer_text ) == 2 ||
+            sscanf( s, "{%d}{%d}%[^\r\n]", &i_start, &i_stop, buffer_text ) == 3)
+        {
+            break;
+        }
+    }
+    /* replace | by \n */
+    for( i = 0; i < strlen( buffer_text ); i++ )
+    {
+        if( buffer_text[i] == '|' )
+        {
+            buffer_text[i] = '\n';
+        }
+    }
+
+    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->psz_text = strndup( buffer_text, MAX_LINE );
+    return( 0 );
+}
+
+static int  ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    text_t      *txt = &p_sys->txt;
+
+    /*
+     * n
+     * h1:m1:s1,d1 --> h2:m2:s2,d2
+     * Line1
+     * Line2
+     * ...
+     * [empty line]
+     *
+     */
+    char *s;
+    char buffer_text[ 10 * MAX_LINE];
+    int  i_buffer_text;
+    mtime_t     i_start;
+    mtime_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, d1, h2, m2, s2, d2;
+        if( ( s = TextGetLine( txt ) ) == NULL )
+        {
+            return( VLC_EGENERIC );
+        }
+        if( sscanf( s,
+                    "%d:%d:%d,%d --> %d:%d:%d,%d",
+                    &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_stop  = ( (mtime_t)h2 * 3600*1000 +
+                        (mtime_t)m2 * 60*1000 +
+                        (mtime_t)s2 * 1000 +
+                        (mtime_t)d2 ) * 1000;
+
+            /* Now read text until an empty line */
+            for( i_buffer_text = 0;; )
+            {
+                int i_len;
+                if( ( s = TextGetLine( txt ) ) == NULL )
+                {
+                    return( VLC_EGENERIC );
+                }
+
+                i_len = strlen( s );
+                if( i_len <= 1 )
+                {
+                    /* empty line -> end of this subtitle */
+                    buffer_text[__MAX( i_buffer_text - 1, 0 )] = '\0';
+                    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_original_mspf /
+                                              p_sys->i_microsecperframe;
+                        p_subtitle->i_stop  = (mtime_t)i_stop  *
+                                              p_sys->i_original_mspf /
+                                              p_sys->i_microsecperframe;
+                    }
+                    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++;
+                    }
+                }
+            }
+        }
+    }
+}
+
+static int  ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    text_t      *txt = &p_sys->txt;
+
+    /*
+     * h1:m1:s1.d1,h2:m2:s2.d2
+     * Line1[br]Line2
+     * Line3
+     * ...
+     * [empty line]
+     * ( works with subviewer and subviewer v2 )
+     */
+    char *s;
+    char buffer_text[ 10 * MAX_LINE];
+    int  i_buffer_text;
+    mtime_t     i_start;
+    mtime_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, d1, h2, m2, s2, d2;
+        if( ( s = TextGetLine( txt ) ) == NULL )
+        {
+            return( VLC_EGENERIC );
+        }
+        if( sscanf( s,
+                    "%d:%d:%d.%d,%d:%d:%d.%d",
+                    &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_stop  = ( (mtime_t)h2 * 3600*1000 +
+                        (mtime_t)m2 * 60*1000 +
+                        (mtime_t)s2 * 1000 +
+                        (mtime_t)d2 ) * 1000;
+
+            /* Now read text until an empty line */
+            for( i_buffer_text = 0;; )
+            {
+                int i_len, i;
+                if( ( s = TextGetLine( txt ) ) == NULL )
+                {
+                    return( VLC_EGENERIC );
+                }
+
+                i_len = strlen( s );
+                if( i_len <= 1 )
+                {
+                    /* empty line -> end of this subtitle */
+                    buffer_text[__MAX( i_buffer_text - 1, 0 )] = '\0';
+                    p_subtitle->i_start = i_start;
+                    p_subtitle->i_stop = i_stop;
+
+                    /* replace [br] by \n */
+                    for( i = 0; i < strlen( 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 ));
+                        }
+                    }
+                    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++;
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+static int  ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    text_t      *txt = &p_sys->txt;
+
+    char buffer_text[ 10 * MAX_LINE];
+    char *s;
+    mtime_t     i_start;
+    mtime_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 )
+        {
+            return( VLC_EGENERIC );
+        }
+        p_subtitle->psz_text = malloc( strlen( s ) );
+
+        if( sscanf( s,
+                    "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d%[^\r\n]",
+                    &i_dummy,
+                    &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_stop  = ( (mtime_t)h2 * 3600*1000 +
+                        (mtime_t)m2 * 60*1000 +
+                        (mtime_t)s2 * 1000 +
+                        (mtime_t)c2 * 10 ) * 1000;
+
+            /* The dec expects: ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text */
+            if( p_sys->i_type == SUB_TYPE_SSA1 )
+            {
+                sprintf( p_subtitle->psz_text,
+                         ",%d%s", i_dummy, strdup( buffer_text) );
+            }
+            else
+            {
+                sprintf( p_subtitle->psz_text,
+                         ",%d,%s", i_dummy, strdup( buffer_text) );
+            }
+            p_subtitle->i_start = i_start;
+            p_subtitle->i_stop = i_stop;
+            return 0;
+        }
+        else
+        {
+            /* All the other stuff we add to the header field */
+            if( p_sys->psz_header != NULL )
+            {
+                if( !( p_sys->psz_header = realloc( p_sys->psz_header,
+                          strlen( p_sys->psz_header ) + 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, "\n" );
+            }
+            else
+            {
+                if( !( p_sys->psz_header = malloc( strlen( s ) + 2 ) ) )
+                {
+                    msg_Err( p_demux, "out of memory");
+                    return VLC_ENOMEM;
+                }
+                p_sys->psz_header = strdup( s );
+                p_sys->psz_header = strcat( p_sys->psz_header, "\n" );
+            }
+        }
+    }
+}
+
+static int  ParseVplayer( demux_t *p_demux, subtitle_t *p_subtitle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    text_t      *txt = &p_sys->txt;
+
+    /*
+     * each line:
+     *  h:m:s:Line1|Line2|Line3....
+     *  or
+     *  h:m:s Line1|Line2|Line3....
+     *
+     */
+    char *p;
+    char buffer_text[MAX_LINE + 1];
+    mtime_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( ;; )
+    {
+        int h, m, s;
+        char c;
+
+        if( ( p = TextGetLine( txt ) ) == NULL )
+        {
+            return( VLC_EGENERIC );
+        }
+
+        i_start = 0;
+
+        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;
+            break;
+        }
+    }
+
+    /* replace | by \n */
+    for( i = 0; i < strlen( buffer_text ); i++ )
+    {
+        if( buffer_text[i] == '|' )
+        {
+            buffer_text[i] = '\n';
+        }
+    }
+    p_subtitle->i_start = i_start;
+
+    p_subtitle->i_stop  = 0;
+    p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
+    return( 0 );
+}
+
+static char *ParseSamiSearch( text_t *txt, char *psz_start, char *psz_str )
+{
+    if( psz_start )
+    {
+        if( strcasestr( psz_start, psz_str ) )
+        {
+            char *s = strcasestr( psz_start, psz_str );
+
+            s += strlen( psz_str );
+
+            return( s );
+        }
+    }
+    for( ;; )
+    {
+        char *p;
+        if( ( p = TextGetLine( txt ) ) == NULL )
+        {
+            return NULL;
+        }
+        if( strcasestr( p, psz_str ) )
+        {
+            char *s = strcasestr( p, psz_str );
+
+            s += strlen( psz_str );
+
+            return(  s);
+        }
+    }
+}
+
+static int  ParseSami( demux_t *p_demux, subtitle_t *p_subtitle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    text_t      *txt = &p_sys->txt;
+
+    char *p;
+    int 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 ) \
+    if( i_text < 10*MAX_LINE )      \
+    {                               \
+        buffer_text[i_text++] = c;  \
+        buffer_text[i_text] = '\0'; \
+    }
+
+    /* search "Start=" */
+    if( !( p = ParseSamiSearch( txt, NULL, "Start=" ) ) )
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* get start value */
+    i_start = strtol( p, &p, 0 );
+
+    /* search <P */
+    if( !( p = ParseSamiSearch( txt, p, "<P" ) ) )
+    {
+        return VLC_EGENERIC;
+    }
+    /* search > */
+    if( !( p = ParseSamiSearch( txt, p, ">" ) ) )
+    {
+        return VLC_EGENERIC;
+    }
+
+    i_text = 0;
+    buffer_text[0] = '\0';
+    /* now get all txt until  a "Start=" line */
+    for( ;; )
+    {
+        if( *p )
+        {
+            if( *p == '<' )
+            {
+                if( !strncasecmp( p, "<br", 3 ) )
+                {
+                    ADDC( '\n' );
+                }
+                else if( strcasestr( p, "Start=" ) )
+                {
+                    TextPreviousLine( txt );
+                    break;
+                }
+                p = ParseSamiSearch( txt, p, ">" );
+            }
+            else if( !strncmp( p, "&nbsp;", 6 ) )
+            {
+                ADDC( ' ' );
+                p += 6;
+            }
+            else if( *p == '\t' )
+            {
+                ADDC( ' ' );
+                p++;
+            }
+            else
+            {
+                ADDC( *p );
+                p++;
+            }
+        }
+        else
+        {
+            p = TextGetLine( txt );
+        }
+
+        if( p == NULL )
+        {
+            break;
+        }
+    }
+
+    p_subtitle->i_start = i_start * 1000;
+    p_subtitle->i_stop  = 0;
+    p_subtitle->psz_text = strndup( buffer_text, 10*MAX_LINE );
+
+    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;
+}
index 287afb8..e9f3b2a 100644 (file)
@@ -7,8 +7,4 @@ SOURCES_id3tag = \
        id3genres.h \
        $(NULL)
 
-SOURCES_demuxsub = \
-       sub.c \
-       sub.h \
-       $(NULL)
 
diff --git a/modules/demux/util/sub.c b/modules/demux/util/sub.c
deleted file mode 100644 (file)
index 6492abc..0000000
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*****************************************************************************
- * sub.c: subtitle demux for external subtitle files
- *****************************************************************************
- * Copyright (C) 1999-2004 VideoLAN
- * $Id$
- *
- * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- *          Derk-Jan Hartman <hartman at videolan dot org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <ctype.h>
-
-#include <vlc/vlc.h>
-#include <vlc/input.h>
-#include "vlc_video.h"
-#include <codecs.h>
-
-#include "sub.h"
-
-#if (!defined( WIN32 ) || defined(__MINGW32__))
-#    include <dirent.h>
-#endif
-
-#define DVD_VIDEO_LB_LEN 2048
-
-static int  Open ( vlc_object_t *p_this );
-
-static int  sub_open ( subtitle_demux_t *p_sub,
-                       input_thread_t  *p_input,
-                       char  *psz_name,
-                       mtime_t i_microsecperframe );
-static int  sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate );
-static int  sub_seek ( subtitle_demux_t *p_sub, mtime_t i_date );
-static void sub_close( subtitle_demux_t *p_sub );
-
-static void sub_fix( subtitle_demux_t *p_sub );
-
-static char *ppsz_sub_type[] = { "auto", "microdvd", "subrip", "subviewer", "ssa1",
-  "ssa2-4", "vplayer", "sami", "vobsub" };
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-#define SUB_DELAY_LONGTEXT \
-    "Delay subtitles (in 1/10s)"
-#define SUB_FPS_LONGTEXT \
-    "Override frames per second. " \
-    "It will only work with MicroDVD subtitles."
-#define SUB_TYPE_LONGTEXT \
-    "One from \"microdvd\", \"subrip\", \"ssa1\", \"ssa2-4\", \"vplayer\" " \
-    "\"sami\" (auto for autodetection, it should always work)."
-
-vlc_module_begin();
-    set_description( _("Text subtitles demux") );
-    set_capability( "subtitle demux", 12 );
-    add_float( "sub-fps", 0.0, NULL,
-               N_("Frames per second"),
-               SUB_FPS_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, NULL );
-vlc_module_end();
-
-/*****************************************************************************
- * Module initializer
- *****************************************************************************/
-static int Open ( vlc_object_t *p_this )
-{
-    subtitle_demux_t *p_sub = (subtitle_demux_t*)p_this;
-
-    p_sub->pf_open  = sub_open;
-    p_sub->pf_demux = sub_demux;
-    p_sub->pf_seek  = sub_seek;
-    p_sub->pf_close = sub_close;
-
-    /* Initialize the variables */
-    var_Create( p_this, "sub-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
-    var_Create( p_this, "sub-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
-    var_Create( p_this, "sub-type", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-
-    return VLC_SUCCESS;
-}
-#define MAX_TRY     256
-#define MAX_LINE    2048
-
-#define FREE( p ) if( p ) { free( p); (p) = NULL; }
-
-typedef struct
-{
-    int     i_line_count;
-    int     i_line;
-    char    **line;
-} text_t;
-
-static int  text_load( text_t *txt, char *psz_name )
-{
-    FILE *f;
-    int   i_line_max;
-
-    /* init txt */
-    i_line_max          = 100;
-    txt->i_line_count   = 0;
-    txt->i_line         = 0;
-    txt->line           = calloc( i_line_max, sizeof( char * ) );
-
-    /* open file */
-    if( !( f = fopen( psz_name, "rb" ) ) )
-    {
-        return VLC_EGENERIC;
-    }
-
-    /* load the complete file */
-    for( ;; )
-    {
-        char buffer[8096];
-        char *p;
-
-        if( fgets( buffer, 8096, f ) <= 0)
-        {
-            break;
-        }
-        while( ( p = strchr( buffer, '\r' ) ) )
-        {
-            *p = '\0';
-        }
-        while( ( p = strchr( buffer, '\n' ) ) )
-        {
-            *p = '\0';
-        }
-
-        txt->line[txt->i_line_count++] = strdup( buffer );
-
-        if( txt->i_line_count >= i_line_max )
-        {
-            i_line_max += 100;
-            txt->line = realloc( txt->line, i_line_max * sizeof( char*) );
-        }
-    }
-
-    fclose( f );
-
-    if( txt->i_line_count <= 0 )
-    {
-        FREE( txt->line );
-        return( VLC_EGENERIC );
-    }
-
-    return( VLC_SUCCESS );
-}
-static void text_unload( text_t *txt )
-{
-    int i;
-
-    for( i = 0; i < txt->i_line_count; i++ )
-    {
-        FREE( txt->line[i] );
-    }
-    FREE( txt->line );
-    txt->i_line       = 0;
-    txt->i_line_count = 0;
-}
-
-static char *text_get_line( text_t *txt )
-{
-    if( txt->i_line >= txt->i_line_count )
-    {
-        return( NULL );
-    }
-
-    return( txt->line[txt->i_line++] );
-}
-static void text_previous_line( text_t *txt )
-{
-    if( txt->i_line > 0 )
-    {
-        txt->i_line--;
-    }
-}
-static void text_rewind( text_t *txt )
-{
-    txt->i_line = 0;
-}
-
-static int  sub_MicroDvdRead( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
-static int  sub_SubRipRead  ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
-static int  sub_SubViewer   ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
-static int  sub_SSARead     ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
-static int  sub_Vplayer     ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
-static int  sub_Sami        ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
-static int  sub_VobSubIDX   ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
-
-static int  DemuxVobSub     ( subtitle_demux_t *, block_t * );
-
-static struct
-{
-    char *psz_type_name;
-    int  i_type;
-    char *psz_name;
-    int  (*pf_read_subtitle)    ( subtitle_demux_t *, text_t *, subtitle_t*, mtime_t );
-} sub_read_subtitle_function [] =
-{
-    { "microdvd",   SUB_TYPE_MICRODVD,  "MicroDVD", sub_MicroDvdRead },
-    { "subrip",     SUB_TYPE_SUBRIP,    "SubRIP",   sub_SubRipRead },
-    { "subviewer",  SUB_TYPE_SUBVIEWER, "SubViewer",sub_SubViewer },
-    { "ssa1",       SUB_TYPE_SSA1,      "SSA-1",    sub_SSARead },
-    { "ssa2-4",     SUB_TYPE_SSA2_4,    "SSA-2/3/4",sub_SSARead },
-    { "vplayer",    SUB_TYPE_VPLAYER,   "VPlayer",  sub_Vplayer },
-    { "sami",       SUB_TYPE_SAMI,      "SAMI",     sub_Sami },
-    { "vobsub",     SUB_TYPE_VOBSUB,    "VobSub",   sub_VobSubIDX },
-    { NULL,         SUB_TYPE_UNKNOWN,   "Unknown",  NULL }
-};
-
-/*****************************************************************************
- * sub_open: Open a subtitle file and add subtitle ES
- *****************************************************************************/
-static int sub_open( subtitle_demux_t *p_sub, input_thread_t  *p_input,
-                     char *psz_name, mtime_t i_microsecperframe )
-{
-    text_t  txt;
-    vlc_value_t val;
-    es_format_t fmt;
-    int i, i_sub_type, i_max;
-    int (*pf_read_subtitle)( subtitle_demux_t *, text_t *, subtitle_t *,
-                             mtime_t ) = NULL;
-
-    p_sub->i_sub_type = SUB_TYPE_UNKNOWN;
-    p_sub->p_es = NULL;
-    p_sub->i_subtitles = 0;
-    p_sub->subtitle = NULL;
-    p_sub->p_vobsub_file = 0;
-    p_sub->i_original_mspf = i_microsecperframe;
-    p_sub->p_input = p_input;
-
-    if( !psz_name || !*psz_name )
-    {
-        msg_Err( p_sub, "no subtitle file specified" );
-        return VLC_EGENERIC;
-    }
-
-    /* *** load the file *** */
-    if( text_load( &txt, psz_name ) )
-    {
-        msg_Err( p_sub, "cannot open `%s' subtitle file", psz_name );
-        return VLC_EGENERIC;
-    }
-
-    msg_Dbg( p_sub, "opened `%s'", psz_name );
-
-    var_Get( p_sub, "sub-fps", &val );
-    if( val.i_int >= 1.0 )
-    {
-        i_microsecperframe = (mtime_t)( (float)1000000 / val.f_float );
-    }
-    else if( val.f_float == 0 )
-    {
-        /* No value given */
-        i_microsecperframe = 0;
-    }
-    else if( val.f_float <= 0 )
-    {
-        /* invalid value, default = 25fps */
-        i_microsecperframe = 40000;
-    }
-
-    var_Get( p_sub, "sub-type", &val);
-    if( val.psz_string && *val.psz_string )
-    {
-        int i;
-
-        for( i = 0; ; i++ )
-        {
-            if( sub_read_subtitle_function[i].psz_type_name == NULL )
-            {
-                i_sub_type = SUB_TYPE_UNKNOWN;
-                break;
-            }
-            if( !strcmp( sub_read_subtitle_function[i].psz_type_name,
-                         val.psz_string ) )
-            {
-                i_sub_type = sub_read_subtitle_function[i].i_type;
-                break;
-            }
-        }
-    }
-    else
-    {
-        i_sub_type = SUB_TYPE_UNKNOWN;
-    }
-    FREE( val.psz_string );
-
-    /* *** Now try to autodetect subtitle format *** */
-    if( i_sub_type == SUB_TYPE_UNKNOWN )
-    {
-        int     i_try;
-        char    *s;
-
-        msg_Dbg( p_input, "trying to autodetect file format" );
-        for( i_try = 0; i_try < MAX_TRY; i_try++ )
-        {
-            int i_dummy;
-
-            if( ( s = text_get_line( &txt ) ) == NULL )
-            {
-                break;
-            }
-
-            if( strcasestr( s, "<SAMI>" ) )
-            {
-                i_sub_type = SUB_TYPE_SAMI;
-                break;
-            }
-            else if( sscanf( s, "{%d}{%d}", &i_dummy, &i_dummy ) == 2 ||
-                     sscanf( s, "{%d}{}", &i_dummy ) == 1)
-            {
-                i_sub_type = SUB_TYPE_MICRODVD;
-                break;
-            }
-            else if( sscanf( s,
-                             "%d:%d:%d,%d --> %d:%d:%d,%d",
-                             &i_dummy,&i_dummy,&i_dummy,&i_dummy,
-                             &i_dummy,&i_dummy,&i_dummy,&i_dummy ) == 8 )
-            {
-                i_sub_type = SUB_TYPE_SUBRIP;
-                break;
-            }
-            else if( sscanf( s,
-                             "!: This is a Sub Station Alpha v%d.x script.",
-                             &i_dummy ) == 1)
-            {
-                if( i_dummy <= 1 )
-                {
-                    i_sub_type = SUB_TYPE_SSA1;
-                }
-                else
-                {
-                    i_sub_type = SUB_TYPE_SSA2_4; /* I hope this will work */
-                }
-                break;
-            }
-            else if( strcasestr( s, "This is a Sub Station Alpha v4 script" ) )
-            {
-                i_sub_type = SUB_TYPE_SSA2_4; /* I hope this will work */
-                break;
-            }
-            else if( !strncasecmp( s, "Dialogue: Marked", 16  ) )
-            {
-                i_sub_type = SUB_TYPE_SSA2_4; /* could be wrong */
-                break;
-            }
-            else if( strcasestr( s, "[INFORMATION]" ) )
-            {
-                i_sub_type = SUB_TYPE_SUBVIEWER; /* I hope this will work */
-                break;
-            }
-            else if( sscanf( s, "%d:%d:%d:", &i_dummy, &i_dummy, &i_dummy ) == 3 ||
-                     sscanf( s, "%d:%d:%d ", &i_dummy, &i_dummy, &i_dummy ) == 3 )
-            {
-                i_sub_type = SUB_TYPE_VPLAYER;
-                break;
-            }
-            else if( strcasestr( s, "# VobSub index file" ) )
-            {
-                i_sub_type = SUB_TYPE_VOBSUB;
-                break;
-            }
-        }
-
-        text_rewind( &txt );
-    }
-
-    /* *** Load this file in memory *** */
-    for( i = 0; ; i++ )
-    {
-        if( sub_read_subtitle_function[i].i_type == SUB_TYPE_UNKNOWN )
-        {
-            msg_Dbg( p_input, "unknown subtitle file" );
-            text_unload( &txt );
-            return VLC_EGENERIC;
-        }
-
-        if( sub_read_subtitle_function[i].i_type == i_sub_type )
-        {
-            msg_Dbg( p_input, "detected %s format",
-                    sub_read_subtitle_function[i].psz_name );
-            p_sub->i_sub_type = i_sub_type;
-            pf_read_subtitle = sub_read_subtitle_function[i].pf_read_subtitle;
-            break;
-        }
-    }
-
-    for( i_max = 0;; )
-    {
-        if( p_sub->i_subtitles >= i_max )
-        {
-            i_max += 128;
-            if( !( p_sub->subtitle = realloc( p_sub->subtitle,
-                                              sizeof(subtitle_t) * i_max ) ) )
-            {
-                msg_Err( p_sub, "out of memory");
-                return VLC_ENOMEM;
-            }
-        }
-        if( pf_read_subtitle( p_sub, &txt,
-                              p_sub->subtitle + p_sub->i_subtitles,
-                              i_microsecperframe ) < 0 )
-        {
-            break;
-        }
-        p_sub->i_subtitles++;
-    }
-    msg_Dbg( p_sub, "loaded %d subtitles", p_sub->i_subtitles );
-
-    /* *** Close the file *** */
-    text_unload( &txt );
-
-    /* *** fix subtitle (order and time) *** */
-    p_sub->i_subtitle = 0;  /* will be modified by sub_fix */
-    
-    if( p_sub->i_sub_type != SUB_TYPE_VOBSUB )
-    {
-        sub_fix( p_sub );
-    }
-
-    /* *** add subtitle ES *** */
-    if( p_sub->i_sub_type == SUB_TYPE_VOBSUB )
-    {
-        int i_len = strlen( psz_name );
-        char *psz_vobname = strdup(psz_name);
-
-        strcpy( psz_vobname + i_len - 4, ".sub" );
-
-        /* open file */
-        if( !( p_sub->p_vobsub_file = fopen( psz_vobname, "rb" ) ) )
-        {
-            msg_Err( p_sub, "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_sub->i_sub_type == SUB_TYPE_SSA1 ||
-             p_sub->i_sub_type == SUB_TYPE_SSA2_4 )
-    {
-        es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','s','a',' ' ) );
-    }
-    else
-    {
-        es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','u','b','t' ) );
-    }
-    if( p_sub->psz_header != NULL )
-    {
-        fmt.i_extra = strlen( p_sub->psz_header ) + 1;
-        fmt.p_extra = strdup( p_sub->psz_header );
-    }
-    p_sub->p_es = es_out_Add( p_input->p_es_out, &fmt );
-    p_sub->i_previously_selected = 0;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * sub_demux: Send subtitle to decoder until i_maxdate
- *****************************************************************************/
-static int  sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
-{
-    input_thread_t *p_input = p_sub->p_input;
-    vlc_bool_t     b;
-    vlc_value_t    val;
-
-    es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, p_sub->p_es, &b );
-    if( b && !p_sub->i_previously_selected )
-    {
-        p_sub->i_previously_selected = 1;
-        p_sub->pf_seek( p_sub, i_maxdate );
-        return VLC_SUCCESS;
-    }
-    else if( !b && p_sub->i_previously_selected )
-    {
-        p_sub->i_previously_selected = 0;
-        return VLC_SUCCESS;
-    }
-
-    if( p_sub->i_sub_type != SUB_TYPE_VOBSUB )
-    {
-        while( p_sub->i_subtitle < p_sub->i_subtitles &&
-               p_sub->subtitle[p_sub->i_subtitle].i_start < i_maxdate )
-        {
-            block_t *p_block;
-            int i_len = strlen( p_sub->subtitle[p_sub->i_subtitle].psz_text ) + 1;
-
-            if( i_len <= 1 )
-            {
-                /* empty subtitle */
-                p_sub->i_subtitle++;
-                continue;
-            }
-
-            if( ( p_block = block_New( p_sub->p_input, i_len ) ) == NULL )
-            {
-                p_sub->i_subtitle++;
-                continue;
-            }
-
-            if( p_sub->subtitle[p_sub->i_subtitle].i_start < 0 )
-            {
-                p_sub->i_subtitle++;
-                continue;
-            }
-
-            p_block->i_pts = p_sub->subtitle[p_sub->i_subtitle].i_start;
-            p_block->i_dts = p_block->i_pts;
-            if( p_sub->subtitle[p_sub->i_subtitle].i_stop > 0 )
-            {
-                p_block->i_length =
-                    p_sub->subtitle[p_sub->i_subtitle].i_stop - p_block->i_pts;
-            }
-
-            memcpy( p_block->p_buffer,
-                    p_sub->subtitle[p_sub->i_subtitle].psz_text, i_len );
-            if( p_block->i_pts > 0 )
-            {
-                es_out_Send( p_input->p_es_out, p_sub->p_es, p_block );
-            }
-            else
-            {
-                block_Release( p_block );
-            }
-            p_sub->i_subtitle++;
-        }
-    }
-    else
-    {
-        while( p_sub->i_subtitle < p_sub->i_subtitles &&
-               p_sub->subtitle[p_sub->i_subtitle].i_start < i_maxdate )
-        {
-            int i_pos = p_sub->subtitle[p_sub->i_subtitle].i_vobsub_location;
-            block_t *p_block;
-            int i_size = 0;
-
-            /* first compute SPU size */
-            if( p_sub->i_subtitle + 1 < p_sub->i_subtitles )
-            {
-                i_size = p_sub->subtitle[p_sub->i_subtitle+1].i_vobsub_location - i_pos;
-            }
-            if( i_size <= 0 ) i_size = 65535;   /* Invalid or EOF */
-
-            /* Seek at the right place (could be avoid if sub_seek is fixed to do his job) */
-            if( fseek( p_sub->p_vobsub_file, i_pos, SEEK_SET ) )
-            {
-                msg_Warn( p_sub, "cannot seek at right vobsub location %d", i_pos );
-                p_sub->i_subtitle++;
-                continue;
-            }
-
-            /* allocate a packet */
-            if( ( p_block = block_New( p_sub, i_size ) ) == NULL )
-            {
-                p_sub->i_subtitle++;
-                continue;
-            }
-
-            /* read data */
-            p_block->i_buffer = fread( p_block->p_buffer, 1, i_size, p_sub->p_vobsub_file );
-            if( p_block->i_buffer <= 6 )
-            {
-                block_Release( p_block );
-                p_sub->i_subtitle++;
-                continue;
-            }
-
-            /* pts */
-            p_block->i_pts = p_sub->subtitle[p_sub->i_subtitle].i_start;
-
-            /* demux this block */
-            DemuxVobSub( p_sub, p_block );
-
-            p_sub->i_subtitle++;
-        }
-    }
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * sub_seek: Seek to i_date
- *****************************************************************************/
-static int  sub_seek ( subtitle_demux_t *p_sub, mtime_t i_date )
-{
-    /* should be fast enough... */
-    p_sub->i_subtitle = 0;
-    while( p_sub->i_subtitle < p_sub->i_subtitles &&
-           p_sub->subtitle[p_sub->i_subtitle].i_start < i_date )
-    {
-        p_sub->i_subtitle++;
-    }
-    return( 0 );
-}
-
-/*****************************************************************************
- * sub_close: Close subtitle demux
- *****************************************************************************/
-static void sub_close( subtitle_demux_t *p_sub )
-{
-    if( p_sub->subtitle )
-    {
-        int i;
-        for( i = 0; i < p_sub->i_subtitles; i++ )
-        {
-            if( p_sub->subtitle[i].psz_text )
-            {
-                free( p_sub->subtitle[i].psz_text );
-            }
-        }
-        free( p_sub->subtitle );
-    }
-    if( p_sub->p_vobsub_file )
-    {
-        fclose( p_sub->p_vobsub_file );
-    }
-}
-
-/*****************************************************************************
- * sub_fix: fix time stamp and order of subtitle
- *****************************************************************************/
-static void  sub_fix( subtitle_demux_t *p_sub )
-{
-    int     i_index;
-    int     i_done;
-
-    /* *** fix order (to be sure...) *** */
-    /* We suppose that there are near in order and this durty bubble sort
-     * wont take too much time
-     */
-    do
-    {
-        i_done = 1;
-        for( i_index = 1; i_index < p_sub->i_subtitles; i_index++ )
-        {
-            if( p_sub->subtitle[i_index].i_start <
-                    p_sub->subtitle[i_index - 1].i_start )
-            {
-                subtitle_t sub_xch;
-                memcpy( &sub_xch,
-                        p_sub->subtitle + i_index - 1,
-                        sizeof( subtitle_t ) );
-                memcpy( p_sub->subtitle + i_index - 1,
-                        p_sub->subtitle + i_index,
-                        sizeof( subtitle_t ) );
-                memcpy( p_sub->subtitle + i_index,
-                        &sub_xch,
-                        sizeof( subtitle_t ) );
-                i_done = 0;
-            }
-        }
-    } while( !i_done );
-}
-
-
-
-/*****************************************************************************
- * Specific Subtitle function
- *****************************************************************************/
-static int  sub_MicroDvdRead( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe)
-{
-    /*
-     * each line:
-     *  {n1}{n2}Line1|Line2|Line3....
-     * where n1 and n2 are the video frame number...
-     *
-     */
-    char *s;
-
-    char buffer_text[MAX_LINE + 1];
-    unsigned int    i_start;
-    unsigned int    i_stop;
-    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( ;; )
-    {
-        if( ( s = text_get_line( txt ) ) == NULL )
-        {
-            return( VLC_EGENERIC );
-        }
-        i_start = 0;
-        i_stop  = 0;
-
-        memset( buffer_text, '\0', MAX_LINE );
-        if( sscanf( s, "{%d}{}%[^\r\n]", &i_start, buffer_text ) == 2 ||
-            sscanf( s, "{%d}{%d}%[^\r\n]", &i_start, &i_stop, buffer_text ) == 3)
-        {
-            break;
-        }
-    }
-    /* replace | by \n */
-    for( i = 0; i < strlen( buffer_text ); i++ )
-    {
-        if( buffer_text[i] == '|' )
-        {
-            buffer_text[i] = '\n';
-        }
-    }
-    if( i_microsecperframe == 0)
-    {
-        i_microsecperframe = 40000;
-    }
-    p_subtitle->i_start = (mtime_t)i_start * (mtime_t)i_microsecperframe;
-    p_subtitle->i_stop  = (mtime_t)i_stop  * (mtime_t)i_microsecperframe;
-    p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
-    return( 0 );
-}
-
-static int  sub_SubRipRead( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe )
-{
-    /*
-     * n
-     * h1:m1:s1,d1 --> h2:m2:s2,d2
-     * Line1
-     * Line2
-     * ...
-     * [empty line]
-     *
-     */
-    char *s;
-    char buffer_text[ 10 * MAX_LINE];
-    int  i_buffer_text;
-    mtime_t     i_start;
-    mtime_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, d1, h2, m2, s2, d2;
-        if( ( s = text_get_line( txt ) ) == NULL )
-        {
-            return( VLC_EGENERIC );
-        }
-        if( sscanf( s,
-                    "%d:%d:%d,%d --> %d:%d:%d,%d",
-                    &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_stop  = ( (mtime_t)h2 * 3600*1000 +
-                        (mtime_t)m2 * 60*1000 +
-                        (mtime_t)s2 * 1000 +
-                        (mtime_t)d2 ) * 1000;
-
-            /* Now read text until an empty line */
-            for( i_buffer_text = 0;; )
-            {
-                int i_len;
-                if( ( s = text_get_line( txt ) ) == NULL )
-                {
-                    return( VLC_EGENERIC );
-                }
-
-                i_len = strlen( s );
-                if( i_len <= 1 )
-                {
-                    /* empty line -> end of this subtitle */
-                    buffer_text[__MAX( i_buffer_text - 1, 0 )] = '\0';
-                    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( i_microsecperframe != 0 && p_sub->i_original_mspf != 0)
-                    {
-                        p_subtitle->i_start = (mtime_t)i_start *
-                                              (mtime_t)p_sub->i_original_mspf /
-                                              (mtime_t)i_microsecperframe;
-                        p_subtitle->i_stop  = (mtime_t)i_stop  *
-                                              (mtime_t)p_sub->i_original_mspf /
-                                              (mtime_t)i_microsecperframe;
-                    }
-                    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++;
-                    }
-                }
-            }
-        }
-    }
-}
-
-static int  sub_SubViewer( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe )
-{
-    /*
-     * h1:m1:s1.d1,h2:m2:s2.d2
-     * Line1[br]Line2
-     * Line3
-     * ...
-     * [empty line]
-     * ( works with subviewer and subviewer v2 )
-     */
-    char *s;
-    char buffer_text[ 10 * MAX_LINE];
-    int  i_buffer_text;
-    mtime_t     i_start;
-    mtime_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, d1, h2, m2, s2, d2;
-        if( ( s = text_get_line( txt ) ) == NULL )
-        {
-            return( VLC_EGENERIC );
-        }
-        if( sscanf( s,
-                    "%d:%d:%d.%d,%d:%d:%d.%d",
-                    &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_stop  = ( (mtime_t)h2 * 3600*1000 +
-                        (mtime_t)m2 * 60*1000 +
-                        (mtime_t)s2 * 1000 +
-                        (mtime_t)d2 ) * 1000;
-
-            /* Now read text until an empty line */
-            for( i_buffer_text = 0;; )
-            {
-                int i_len, i;
-                if( ( s = text_get_line( txt ) ) == NULL )
-                {
-                    return( VLC_EGENERIC );
-                }
-
-                i_len = strlen( s );
-                if( i_len <= 1 )
-                {
-                    /* empty line -> end of this subtitle */
-                    buffer_text[__MAX( i_buffer_text - 1, 0 )] = '\0';
-                    p_subtitle->i_start = i_start;
-                    p_subtitle->i_stop = i_stop;
-
-                    /* replace [br] by \n */
-                    for( i = 0; i < strlen( 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 ));
-                        }
-                    }
-                    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++;
-                    }
-                }
-            }
-        }
-    }
-}
-
-
-static int  sub_SSARead( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe )
-{
-    char buffer_text[ 10 * MAX_LINE];
-    char *s;
-    mtime_t     i_start;
-    mtime_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 = text_get_line( txt ) ) == NULL )
-        {
-            return( VLC_EGENERIC );
-        }
-        p_subtitle->psz_text = malloc( strlen( s ) );
-
-        if( sscanf( s,
-                    "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d%[^\r\n]",
-                    &i_dummy,
-                    &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_stop  = ( (mtime_t)h2 * 3600*1000 +
-                        (mtime_t)m2 * 60*1000 +
-                        (mtime_t)s2 * 1000 +
-                        (mtime_t)c2 * 10 ) * 1000;
-
-            /* The dec expects: ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text */
-            if( p_sub->i_sub_type == SUB_TYPE_SSA1 )
-            {
-                sprintf( p_subtitle->psz_text, ",%d%s", i_dummy, strdup( buffer_text) );
-            }
-            else
-            {
-                sprintf( p_subtitle->psz_text, ",%d,%s", i_dummy, strdup( buffer_text) );
-            }
-            p_subtitle->i_start = i_start;
-            p_subtitle->i_stop = i_stop;
-            return( 0 );
-        }
-        else
-        {
-            /* All the other stuff we add to the header field */
-            if( p_sub->psz_header != NULL )
-            {
-                if( !( p_sub->psz_header = realloc( p_sub->psz_header,
-                          strlen( p_sub->psz_header ) + strlen( s ) + 2 ) ) )
-                {
-                    msg_Err( p_sub, "out of memory");
-                    return VLC_ENOMEM;
-                }
-                p_sub->psz_header = strcat( p_sub->psz_header, strdup( s ) );
-                p_sub->psz_header = strcat( p_sub->psz_header, "\n" );
-            }
-            else
-            {
-                if( !( p_sub->psz_header = malloc( strlen( s ) + 2 ) ) )
-                {
-                    msg_Err( p_sub, "out of memory");
-                    return VLC_ENOMEM;
-                }
-                p_sub->psz_header = strdup( s );
-                p_sub->psz_header = strcat( p_sub->psz_header, "\n" );
-            }
-        }
-    }
-}
-
-static int  sub_Vplayer( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe)
-{
-    /*
-     * each line:
-     *  h:m:s:Line1|Line2|Line3....
-     *  or
-     *  h:m:s Line1|Line2|Line3....
-     *
-     */
-    char *p;
-    char buffer_text[MAX_LINE + 1];
-    mtime_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( ;; )
-    {
-        int h, m, s;
-        char c;
-
-        if( ( p = text_get_line( txt ) ) == NULL )
-        {
-            return( VLC_EGENERIC );
-        }
-
-        i_start = 0;
-
-        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;
-            break;
-        }
-    }
-
-    /* replace | by \n */
-    for( i = 0; i < strlen( buffer_text ); i++ )
-    {
-        if( buffer_text[i] == '|' )
-        {
-            buffer_text[i] = '\n';
-        }
-    }
-    p_subtitle->i_start = i_start;
-
-    p_subtitle->i_stop  = 0;
-    p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
-    return( 0 );
-}
-
-static char *sub_SamiSearch( text_t *txt, char *psz_start, char *psz_str )
-{
-    if( psz_start )
-    {
-        if( strcasestr( psz_start, psz_str ) )
-        {
-            char *s = strcasestr( psz_start, psz_str );
-
-            s += strlen( psz_str );
-
-            return( s );
-        }
-    }
-    for( ;; )
-    {
-        char *p;
-        if( ( p = text_get_line( txt ) ) == NULL )
-        {
-            return NULL;
-        }
-        if( strcasestr( p, psz_str ) )
-        {
-            char *s = strcasestr( p, psz_str );
-
-            s += strlen( psz_str );
-
-            return(  s);
-        }
-    }
-}
-
-static int  sub_Sami( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe )
-{
-    char *p;
-    int 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 ) \
-    if( i_text < 10*MAX_LINE )      \
-    {                               \
-        buffer_text[i_text++] = c;  \
-        buffer_text[i_text] = '\0'; \
-    }
-
-    /* search "Start=" */
-    if( !( p = sub_SamiSearch( txt, NULL, "Start=" ) ) )
-    {
-        return VLC_EGENERIC;
-    }
-
-    /* get start value */
-    i_start = strtol( p, &p, 0 );
-
-    /* search <P */
-    if( !( p = sub_SamiSearch( txt, p, "<P" ) ) )
-    {
-        return VLC_EGENERIC;
-    }
-    /* search > */
-    if( !( p = sub_SamiSearch( txt, p, ">" ) ) )
-    {
-        return VLC_EGENERIC;
-    }
-
-    i_text = 0;
-    buffer_text[0] = '\0';
-    /* now get all txt until  a "Start=" line */
-    for( ;; )
-    {
-        if( *p )
-        {
-            if( *p == '<' )
-            {
-                if( !strncasecmp( p, "<br", 3 ) )
-                {
-                    ADDC( '\n' );
-                }
-                else if( strcasestr( p, "Start=" ) )
-                {
-                    text_previous_line( txt );
-                    break;
-                }
-                p = sub_SamiSearch( txt, p, ">" );
-            }
-            else if( !strncmp( p, "&nbsp;", 6 ) )
-            {
-                ADDC( ' ' );
-                p += 6;
-            }
-            else if( *p == '\t' )
-            {
-                ADDC( ' ' );
-                p++;
-            }
-            else
-            {
-                ADDC( *p );
-                p++;
-            }
-        }
-        else
-        {
-            p = text_get_line( txt );
-        }
-
-        if( p == NULL )
-        {
-            break;
-        }
-    }
-
-    p_subtitle->i_start = i_start * 1000;
-    p_subtitle->i_stop  = 0;
-    p_subtitle->psz_text = strndup( buffer_text, 10*MAX_LINE );
-
-    return( VLC_SUCCESS );
-#undef ADDC
-}
-
-static int  sub_VobSubIDX( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe)
-{
-    /*
-     * 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 = text_get_line( 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( subtitle_demux_t *p_demux, block_t *p_bk )
-{
-    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_demux->p_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->p_input->p_es_out, p_demux->p_es, p_pkt );
-
-            p_bk->i_pts = 0;    /* only first packet has a pts */
-        }
-        else
-        {
-            block_Release( p_pkt );
-            continue;
-        }
-    }
-
-    return VLC_SUCCESS;
-}
diff --git a/modules/demux/util/sub.h b/modules/demux/util/sub.h
deleted file mode 100644 (file)
index 4fe8c85..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*****************************************************************************
- * sub.h
- *****************************************************************************
- * Copyright (C) 2001-2004 VideoLAN
- * $Id$
- *
- * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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.
- *****************************************************************************/
-
-#include "../ps.h"
-
-#define SUB_TYPE_MICRODVD   0x00
-#define SUB_TYPE_SUBRIP     0x01
-#define SUB_TYPE_SSA1       0x02
-#define SUB_TYPE_SSA2_4     0x03
-#define SUB_TYPE_VPLAYER    0x04
-#define SUB_TYPE_SAMI       0x05
-#define SUB_TYPE_SUBVIEWER  0x06
-#define SUB_TYPE_VOBSUB     0x100
-#define SUB_TYPE_UNKNOWN    0xffff
-
-typedef struct subtitle_s
-{
-    mtime_t i_start;
-    mtime_t i_stop;
-
-    char    *psz_text;
-    int     i_vobsub_location;
-
-} subtitle_t;
-
-typedef struct subtitle_demux_s
-{
-    VLC_COMMON_MEMBERS
-
-    module_t        *p_module;
-
-    int     (*pf_open) ( struct subtitle_demux_s *p_sub,
-                         input_thread_t*p_input,
-                         char *psz_name,
-                         mtime_t i_microsecperframe );
-    int     (*pf_demux)( struct subtitle_demux_s *p_sub, mtime_t i_maxdate );
-    int     (*pf_seek) ( struct subtitle_demux_s *p_sub, mtime_t i_date );
-    void    (*pf_close)( struct subtitle_demux_s *p_sub );
-
-    /* *** private *** */
-    input_thread_t      *p_input;
-    int                 i_sub_type;
-
-    char                *psz_header;
-    int                 i_subtitle;
-    int                 i_subtitles;
-    subtitle_t          *subtitle;
-    es_out_id_t         *p_es;
-    int                 i_previously_selected; /* to make pf_seek */
-    FILE                *p_vobsub_file;
-    mtime_t             i_original_mspf;
-
-} subtitle_demux_t;
-
-/*****************************************************************************
- * subtitle_New: Start a new subtitle demux instance (but subtitle ES isn't
- *               selected by default.
- *****************************************************************************
- * Return: NULL if failed, else a pointer on a new subtitle_demux_t.
- *
- * XXX: - if psz_name is NULL then --sub-file is read
- *      - i_microsecperframe is used only for microdvd file. (overriden
- *        by --sub-fps )
- *
- *****************************************************************************/
-static inline subtitle_demux_t *subtitle_New( input_thread_t *p_input,
-                                              char *psz_name,
-                                              mtime_t i_microsecperframe )
-{
-    subtitle_demux_t *p_sub;
-
-    p_sub = vlc_object_create( p_input, sizeof( subtitle_demux_t ) );
-    p_sub->psz_object_name = "subtitle demux";
-    vlc_object_attach( p_sub, p_input );
-    p_sub->p_module = module_Need( p_sub, "subtitle demux", NULL, 0 );
-
-    if( p_sub->p_module &&
-        p_sub->pf_open( p_sub, p_input, psz_name, i_microsecperframe ) >=0 )
-    {
-        msg_Info( p_input, "subtitle started" );
-
-    }
-    else
-    {
-        msg_Warn( p_input, "failed to start subtitle demux" );
-        vlc_object_detach( p_sub );
-        if( p_sub->p_module )
-        {
-            module_Unneed( p_sub, p_sub->p_module );
-        }
-        vlc_object_destroy( p_sub );
-        p_sub = NULL;
-    }
-
-    return( p_sub );
-}
-
-/*****************************************************************************
- * subtitle_Demux: send subtitle to decoder from last date to i_max
- *****************************************************************************/
-static inline int subtitle_Demux( subtitle_demux_t *p_sub, mtime_t i_max )
-{
-    return( p_sub->pf_demux( p_sub, i_max ) );
-}
-
-/*****************************************************************************
- * subtitle_Seek: Seek to i_date
- *****************************************************************************/
-static inline int subtitle_Seek( subtitle_demux_t *p_sub, mtime_t i_date )
-{
-    return( p_sub->pf_seek( p_sub, i_date ) );
-}
-
-/*****************************************************************************
- * subtitle_Close: Stop ES decoder and free all memory included p_sub.
- *****************************************************************************/
-static inline void subtitle_Close( subtitle_demux_t *p_sub )
-{
-    msg_Info( p_sub, "subtitle stopped" );
-    if( p_sub )
-    {
-        p_sub->pf_close( p_sub );
-        vlc_object_detach( p_sub );
-        if( p_sub->p_module )
-        {
-            module_Unneed( p_sub, p_sub->p_module );
-        }
-        vlc_object_destroy( p_sub );
-    }
-}
-
index 671a002..0ab0c75 100644 (file)
@@ -250,6 +250,15 @@ void input_DecoderDiscontinuity( decoder_t * p_dec )
     input_DecoderDecode( p_dec, p_null );
 }
 
+vlc_bool_t input_DecoderEmpty( decoder_t * p_dec )
+{
+    if( p_dec->p_owner->b_own_thread && p_dec->p_owner->p_fifo->i_depth > 0 )
+    {
+        return VLC_FALSE;
+    }
+    return VLC_TRUE;
+}
+
 #if 0
 /**
  * Create a NULL packet for padding in case of a data loss
index 0c3ad7f..9acc456 100644 (file)
@@ -242,6 +242,21 @@ void input_EsOutSetDelay( es_out_t *out, int i_cat, int64_t i_delay )
         p_sys->i_spu_delay = i_delay;
 }
 
+vlc_bool_t input_EsOutDecodersEmpty( es_out_t *out )
+{
+    es_out_sys_t      *p_sys = out->p_sys;
+    int i;
+
+    for( i = 0; i < p_sys->i_es; i++ )
+    {
+        es_out_id_t *es = p_sys->es[i];
+
+        if( es->p_dec && !input_DecoderEmpty( es->p_dec ) )
+            return VLC_FALSE;
+    }
+    return VLC_TRUE;
+}
+
 /*****************************************************************************
  *
  *****************************************************************************/
index 91f9b30..0740c01 100644 (file)
@@ -62,7 +62,8 @@ static void DecodeUrl  ( char * );
 static void MRLSplit( input_thread_t *, char *, char **, char **, char ** );
 
 static input_source_t *InputSourceNew( input_thread_t *);
-static int  InputSourceInit( input_thread_t *, input_source_t *, char * );
+static int  InputSourceInit( input_thread_t *, input_source_t *,
+                             char *, char *psz_forced_demux );
 static void InputSourceClean( input_thread_t *, input_source_t * );
 
 static void SlaveDemux( input_thread_t *p_input );
@@ -146,7 +147,6 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
     /* Init control buffer */
     vlc_mutex_init( p_input, &p_input->lock_control );
     p_input->i_control = 0;
-    p_input->p_sys = NULL;
 
     /* Parse input options */
     vlc_mutex_lock( &p_item->lock );
@@ -444,17 +444,15 @@ static int Run( input_thread_t *p_input )
 
                 if( old_val.i_time != val.i_time )
                 {
-                    /* TODO */
-#if 0
                     char psz_buffer[MSTRTIME_MAX_SIZE];
 
-                    vlc_mutex_lock( &p_input->p_item->lock );
-                    p_input->p_item->i_duration = i_length;
-                    vlc_mutex_unlock( &p_input->p_item->lock );
+                    vlc_mutex_lock( &p_input->input.p_item->lock );
+                    p_input->input.p_item->i_duration = i_length;
+                    vlc_mutex_unlock( &p_input->input.p_item->lock );
 
-                    input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Duration"),
-                       msecstotimestr( psz_buffer, i_length / 1000 ) );
-#endif
+                    input_Control( p_input, INPUT_ADD_INFO,
+                                   _("General"), _("Duration"),
+                    msecstotimestr( psz_buffer, i_length / 1000 ) );
                 }
             }
 
@@ -500,7 +498,9 @@ static int Run( input_thread_t *p_input )
 static int Init( input_thread_t * p_input )
 {
     char *psz;
+    char *psz_subtitle;
     vlc_value_t val;
+    double f_fps;
 
     /* Initialize optional stream output. (before access/demuxer) */
     psz = var_GetString( p_input, "sout" );
@@ -522,7 +522,7 @@ static int Init( input_thread_t * p_input )
     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
 
     if( InputSourceInit( p_input, &p_input->input,
-                         p_input->input.p_item->psz_uri ) )
+                         p_input->input.p_item->psz_uri, NULL ) )
     {
         goto error;
     }
@@ -564,11 +564,6 @@ static int Init( input_thread_t * p_input )
     if( val.i_int < 0 )
         p_input->i_pts_delay -= (val.i_int * 1000);
 
-    /* Init input_thread_sys_t */
-    p_input->p_sys = malloc( sizeof( input_thread_sys_t ) );
-    p_input->p_sys->i_sub = 0;
-    p_input->p_sys->sub   = NULL;
-
     /* TODO: check meta data from users */
 
     /* TODO: get meta data from demuxer */
@@ -611,8 +606,78 @@ static int Init( input_thread_t * p_input )
     }
 
 
-    /* TODO: do subtitle loading (and slave) */
+    /* Load subtitles */
+    /* Get fps and set it if not already set */
+    if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) &&
+        f_fps > 1.0 )
+    {
+        vlc_value_t fps;
+
+        if( var_Get( p_input, "sub-fps", &fps ) )
+        {
+            var_Create( p_input, "sub-fps", VLC_VAR_FLOAT| VLC_VAR_DOINHERIT );
+            var_SetFloat( p_input, "sub-fps", f_fps );
+        }
+    }
+
+    /* Look for and add subtitle files */
+    psz_subtitle = var_GetString( p_input, "sub-file" );
+    if( *psz_subtitle )
+    {
+        input_source_t *sub;
+        vlc_value_t count;
+        vlc_value_t list;
+
+        msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle );
+
+        var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL );
+
+        /* */
+        sub = InputSourceNew( p_input );
+        if( !InputSourceInit( p_input, sub, psz_subtitle, "subtitle" ) )
+        {
+            TAB_APPEND( p_input->i_slave, p_input->slave, sub );
+
+            /* Select the ES */
+            if( !var_Change( p_input, "spu-es", VLC_VAR_GETLIST, &list, NULL ) )
+            {
+                if( count.i_int == 0 )
+                    count.i_int++;  /* if it was first one, there is disable too */
+
+                if( count.i_int < list.p_list->i_count )
+                {
+                    input_ControlPush( p_input, INPUT_CONTROL_SET_ES, &list.p_list->p_values[count.i_int] );
+                }
+                var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );
+            }
+        }
+    }
+
+    var_Get( p_input, "sub-autodetect-file", &val );
+    if( val.b_bool )
+    {
+        char *psz_autopath = var_GetString( p_input, "sub-autodetect-path" );
+        char **subs = subtitles_Detect( p_input, psz_autopath,
+                                        p_input->input.p_item->psz_uri );
+        input_source_t *sub;
+        int i;
 
+        for( i = 0; subs[i] != NULL; i++ )
+        {
+            if( strcmp( psz_subtitle, subs[i] ) )
+            {
+                sub = InputSourceNew( p_input );
+                if( !InputSourceInit( p_input, sub, subs[i], "subtitle" ) )
+                {
+                    TAB_APPEND( p_input->i_slave, p_input->slave, sub );
+                }
+            }
+            free( subs[i] );
+        }
+        free( subs );
+        free( psz_autopath );
+    }
+    free( psz_subtitle );
 
     /* Set up es_out */
     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
@@ -974,26 +1039,6 @@ static void End( input_thread_t * p_input )
             vlc_object_release( p_pl );
     }
 
-    /* TODO subs */
-#if 0
-    /* Destroy subtitles demuxers */
-    if( p_input->p_sys )
-    {
-        for( i = 0; i < p_input->p_sys->i_sub; i++ )
-        {
-            subtitle_Close( p_input->p_sys->sub[i] );
-        }
-        if( p_input->p_sys->i_sub > 0 )
-        {
-            free( p_input->p_sys->sub );
-        }
-
-    }
-#endif
-
-    /* Free input_thread_sys_t */
-    free( p_input->p_sys );
-
     /* Tell we're dead */
     p_input->b_dead = VLC_TRUE;
 }
@@ -1496,7 +1541,8 @@ static input_source_t *InputSourceNew( input_thread_t *p_input )
  * InputSourceInit:
  *****************************************************************************/
 static int InputSourceInit( input_thread_t *p_input,
-                            input_source_t *in, char *psz_mrl )
+                            input_source_t *in, char *psz_mrl,
+                            char *psz_forced_demux )
 {
     char *psz_dup = strdup( psz_mrl );
     char *psz_access;
@@ -1510,6 +1556,8 @@ static int InputSourceInit( input_thread_t *p_input,
     msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
              psz_mrl, psz_access, psz_demux, psz_path );
 
+    if( psz_forced_demux && *psz_forced_demux )
+        psz_demux = psz_forced_demux;
 
     /* Try access_demux if no demux given */
     if( *psz_access && *psz_demux == '\0' )
@@ -1571,7 +1619,7 @@ static int InputSourceInit( input_thread_t *p_input,
             *psz_access == '\0' && ( *psz_demux || *psz_path ) )
         {
             free( psz_dup );
-            psz_dup = strdup( in->p_item->psz_uri );
+            psz_dup = strdup( psz_mrl );
             psz_access = "";
             psz_demux = "";
             psz_path = psz_dup;
@@ -1583,8 +1631,7 @@ static int InputSourceInit( input_thread_t *p_input,
 
         if( in->p_access == NULL )
         {
-            msg_Err( p_input, "no suitable access module for `%s'",
-                     in->p_item->psz_uri );
+            msg_Err( p_input, "no suitable access module for `%s'", psz_mrl );
             goto error;
         }
 
@@ -1717,7 +1764,7 @@ static void SlaveDemux( input_thread_t *p_input )
                     i_ret = 0;
                     break;
                 }
-                msg_Dbg( p_input, "slave time=%lld input=%lld", i_stime, i_time );
+                //msg_Dbg( p_input, "slave time=%lld input=%lld", i_stime, i_time );
                 if( i_stime >= i_time )
                     break;
 
index fc446ce..edc39d5 100644 (file)
@@ -23,9 +23,6 @@
 
 #ifndef _INPUT_INTERNAL_H
 #define _INPUT_INTERNAL_H 1
-#include "../../modules/demux/util/sub.h"
-
-
 
 enum input_control_e
 {
@@ -60,13 +57,6 @@ enum input_control_e
     INPUT_CONTROL_SET_AUDIO_DELAY,
     INPUT_CONTROL_SET_SPU_DELAY,
 };
-struct input_thread_sys_t
-{
-    /* subtitles */
-    int              i_sub;
-    subtitle_demux_t **sub;
-};
-
 
 /* Internal helpers */
 static inline void input_ControlPush( input_thread_t *p_input,
@@ -114,15 +104,17 @@ stream_t *stream_AccessNew( access_t *p_access );
 void stream_AccessDelete( stream_t *s );
 void stream_AccessReset( stream_t *s );
 
-/* Decoder FIXME make it public */
-void input_DecoderDiscontinuity( decoder_t * p_dec );
+/* decoder.c FIXME make it public ?*/
+void       input_DecoderDiscontinuity( decoder_t * p_dec );
+vlc_bool_t input_DecoderEmpty( decoder_t * p_dec );
 
 /* es_out.c */
-es_out_t *input_EsOutNew( input_thread_t * );
-void      input_EsOutDelete( es_out_t * );
+es_out_t  *input_EsOutNew( input_thread_t * );
+void       input_EsOutDelete( es_out_t * );
 es_out_id_t *input_EsOutGetFromID( es_out_t *, int i_id );
-void      input_EsOutDiscontinuity( es_out_t *, vlc_bool_t b_audio );
-void      input_EsOutSetDelay( es_out_t *, int i_cat, int64_t );
+void       input_EsOutDiscontinuity( es_out_t *, vlc_bool_t b_audio );
+void       input_EsOutSetDelay( es_out_t *, int i_cat, int64_t );
+vlc_bool_t input_EsOutDecodersEmpty( es_out_t * );
 
 /* clock.c */
 enum /* Synchro states */
index 94855f8..2cbae6f 100644 (file)
@@ -1152,35 +1152,76 @@ static void AStreamPrebufferStream( stream_t *s )
  * \param s Stream handle to read from
  * \return A null-terminated string. This must be freed,
  */
-/* FIXME don't use stupid MAX_LINE -> do the same than net_ReadLine */
-#define MAX_LINE 1024
+#define STREAM_PROBE_LINE 1024
 char *stream_ReadLine( stream_t *s )
 {
-    uint8_t *p_data;
-    char    *p_line;
-    int      i_data;
-    int      i = 0;
-    i_data = stream_Peek( s, &p_data, MAX_LINE );
+    char    *p_line = NULL;
+    int      i_line = 0;
 
-    while( i < i_data && p_data[i] != '\n' &&  p_data[i] != '\r' )
-    {
-        i++;
-    }
-    if( i_data <= 0 )
-    {
-        return NULL;
-    }
-    else
+    for( ;; )
     {
-        p_line = malloc( i + 1 );
-        if( p_line == NULL )
+        char *psz_lf, *psz_cr;
+        uint8_t *p_data;
+        int      i_data;
+
+        int i_read;
+
+        /* Probe new data */
+        i_data = stream_Peek( s, &p_data, STREAM_PROBE_LINE );
+
+        if( i_data <= 0 )   /* No data */
+            goto exit;
+
+        /* See if there is a '\n' */
+        psz_lf = memchr( p_data, '\n', __MAX( i_data - 1, 1 ) );
+        psz_cr = memchr( p_data, '\r', __MAX( i_data - 1, 1 ) );
+
+        if( psz_lf && !psz_cr && p_data[i_data-1] == '\r' )
         {
-            msg_Err( s, "out of memory" );
-            return NULL;
+            psz_cr = &p_data[i_data-1];
         }
-        i = stream_Read( s, p_line, i + 1 );
-        p_line[ i - 1 ] = '\0';
+        if( psz_cr && !psz_lf && p_data[i_data-1] == '\n' )
+        {
+            psz_lf = &p_data[i_data-1];
+        }
+
+        if( psz_lf || psz_cr )
+        {
+            char *psz;
+            if( !psz_lf  )
+                psz = psz_cr;
+            else if( !psz_cr )
+                psz = psz_lf;
+            else
+                psz = __MIN( psz_cr, psz_lf );
+
+            i_read = (psz - (char*)p_data) + 1;
+            p_line = realloc( p_line, i_read + 1 ); /* +1 for easy \0 append */
+            i_read = stream_Read( s, &p_line[i_line], i_read );
+            if( i_read > 0 )
+                i_line += i_read;
+
+            goto exit;
+        }
+
+        /* Read data (+1 for easy \0 append) */
+        p_line = realloc( p_line, i_line + STREAM_PROBE_LINE + 1 );
+        i_read = stream_Read( s, &p_line[i_line], STREAM_PROBE_LINE );
 
-        return p_line;
+        if( i_read <= 0 )
+            goto exit;
+        i_line += i_read;
     }
+
+exit:
+    while( i_line > 0 &&
+           ( p_line[i_line-1] == '\n' || p_line[i_line-1] == '\r' ) )
+    {
+        i_line--;
+    }
+    if( i_line > 0 )
+        p_line[i_line] = '\0';
+
+    return p_line;
 }
+