/*****************************************************************************
* subtitle.c: Demux for subtitle text files.
*****************************************************************************
- * Copyright (C) 1999-2004 the VideoLAN team
+ * Copyright (C) 1999-2007 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
/*****************************************************************************
* Preamble
*****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc_input.h>
+
+#include <string.h>
#include <stdlib.h>
#include <errno.h>
#endif
#include <ctype.h>
-#include <vlc/vlc.h>
-#include <vlc/input.h>
-#include "vlc_video.h"
+#include <vlc_demux.h>
+#include <vlc_charset.h>
/*****************************************************************************
* Module descriptor
static void Close( vlc_object_t *p_this );
#define SUB_DELAY_LONGTEXT \
- "Apply a delay to all subtitles (in 1/10s, eg 100 means 10s)."
+ N_("Apply a delay to all subtitles (in 1/10s, eg 100 means 10s).")
#define SUB_FPS_LONGTEXT \
- "Override the normal frames per second settings. " \
- "This will only work with MicroDVD and SubRIP (SRT) subtitles."
+ N_("Override the normal frames per second settings. " \
+ "This will only work with MicroDVD and SubRIP (SRT) subtitles.")
#define SUB_TYPE_LONGTEXT \
- "Force the subtiles format. Valid values are : \"microdvd\", \"subrip\"," \
- "\"ssa1\", \"ssa2-4\", \"ass\", \"vplayer\" " \
- "\"sami\", \"dvdsubtitle\" and \"auto\" (meaning autodetection, this " \
- "should always work)."
-static char *ppsz_sub_type[] =
+ N_("Force the subtiles format. Valid values are : \"microdvd\", " \
+ "\"subrip\", \"ssa1\", \"ssa2-4\", \"ass\", \"vplayer\" " \
+ "\"sami\", \"dvdsubtitle\", \"mpl2\" and \"auto\" (meaning autodetection, this " \
+ "should always work).")
+static const char *ppsz_sub_type[] =
{
"auto", "microdvd", "subrip", "subviewer", "ssa1",
- "ssa2-4", "ass", "vplayer", "sami", "dvdsubtitle"
+ "ssa2-4", "ass", "vplayer", "sami", "dvdsubtitle", "mpl2"
};
vlc_module_begin();
SUB_DELAY_LONGTEXT, VLC_TRUE );
add_string( "sub-type", "auto", NULL, N_("Subtitles format"),
SUB_TYPE_LONGTEXT, VLC_TRUE );
- change_string_list( ppsz_sub_type, 0, 0 );
+ change_string_list( ppsz_sub_type, NULL, NULL );
set_callbacks( Open, Close );
add_shortcut( "subtitle" );
SUB_TYPE_VPLAYER,
SUB_TYPE_SAMI,
SUB_TYPE_SUBVIEWER,
- SUB_TYPE_DVDSUBTITLE
+ SUB_TYPE_DVDSUBTITLE,
+ SUB_TYPE_MPL2
};
typedef struct
es_out_id_t *es;
int64_t i_next_demux_date;
-
int64_t i_microsecperframe;
- int64_t i_original_mspf;
char *psz_header;
int i_subtitle;
static int ParseVplayer ( demux_t *, subtitle_t * );
static int ParseSami ( demux_t *, subtitle_t * );
static int ParseDVDSubtitle( demux_t *, subtitle_t * );
+static int ParseMPL2 ( demux_t *, subtitle_t * );
static struct
{
- char *psz_type_name;
+ const char *psz_type_name;
int i_type;
- char *psz_name;
+ const char *psz_name;
int (*pf_read)( demux_t *, subtitle_t* );
} sub_read_subtitle_function [] =
{
{ "vplayer", SUB_TYPE_VPLAYER, "VPlayer", ParseVplayer },
{ "sami", SUB_TYPE_SAMI, "SAMI", ParseSami },
{ "dvdsubtitle",SUB_TYPE_DVDSUBTITLE, "DVDSubtitle", ParseDVDSubtitle },
+ { "mpl2", SUB_TYPE_MPL2, "MPL2", ParseMPL2 },
{ NULL, SUB_TYPE_UNKNOWN, "Unknown", NULL }
};
*****************************************************************************/
static int Open ( vlc_object_t *p_this )
{
- demux_t *p_demux = (demux_t*)p_this;
- demux_sys_t *p_sys;
- es_format_t fmt;
- float f_fps;
- char *psz_type;
+ demux_t *p_demux = (demux_t*)p_this;
+ demux_sys_t *p_sys;
+ es_format_t fmt;
+ input_thread_t *p_input;
+ float f_fps;
+ char *psz_type;
int (*pf_read)( demux_t *, subtitle_t* );
- int i, i_max;
+ int i, i_max;
if( strcmp( p_demux->psz_demux, "subtitle" ) )
{
p_demux->pf_demux = Demux;
p_demux->pf_control = Control;
p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
- p_sys->psz_header = NULL;
- p_sys->i_subtitle = 0;
- p_sys->i_subtitles= 0;
- p_sys->subtitle = NULL;
-
+ p_sys->psz_header = NULL;
+ p_sys->i_subtitle = 0;
+ p_sys->i_subtitles = 0;
+ p_sys->subtitle = NULL;
+ p_sys->i_microsecperframe = 40000;
/* Get the FPS */
- f_fps = var_CreateGetFloat( p_demux, "sub-fps" );
- if( f_fps >= 1.0 )
- {
- p_sys->i_microsecperframe = (int64_t)( (float)1000000 / f_fps );
- }
- else
+ p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
+ if( p_input )
{
- p_sys->i_microsecperframe = 0;
+ f_fps = var_GetFloat( p_input, "sub-original-fps" );
+ if( f_fps >= 1.0 )
+ p_sys->i_microsecperframe = (int64_t)( (float)1000000 / f_fps );
+
+ msg_Dbg( p_demux, "Movie fps: %f", f_fps );
+ vlc_object_release( p_input );
}
- f_fps = var_CreateGetFloat( p_demux, "sub-original-fps" );
+ /* Check for override of the fps */
+ f_fps = var_CreateGetFloat( p_demux, "sub-fps" );
if( f_fps >= 1.0 )
{
- p_sys->i_original_mspf = (int64_t)( (float)1000000 / f_fps );
- }
- else
- {
- p_sys->i_original_mspf = 0;
+ p_sys->i_microsecperframe = (int64_t)( (float)1000000 / f_fps );
+ msg_Dbg( p_demux, "Override subtitle fps %f", f_fps );
}
/* Get or probe the type */
p_sys->i_type = SUB_TYPE_DVDSUBTITLE;
break;
}
+ else if( sscanf( s, "[%d][%d]", &i_dummy, &i_dummy ) == 2 ||
+ sscanf( s, "[%d][]", &i_dummy ) == 1)
+ {
+ p_sys->i_type = SUB_TYPE_MPL2;
+ break;
+ }
free( s );
s = NULL;
int i_stop;
unsigned int i;
- int i_microsecperframe = 40000; /* default to 25 fps */
- if( p_sys->i_microsecperframe > 0 )
- i_microsecperframe = p_sys->i_microsecperframe;
-
p_subtitle->i_start = 0;
p_subtitle->i_stop = 0;
p_subtitle->psz_text = NULL;
+next:
for( ;; )
{
if( ( s = TextGetLine( txt ) ) == NULL )
break;
}
}
+ if( i_start == 1 && i_stop == 1 )
+ {
+ /* We found a possible setting of the framerate "{1}{1}23.976" */
+ /* Check if it's usable, and if the sub-fps is not set */
+ float tmp = us_strtod( buffer_text, NULL );
+ if( tmp > 0.0 && var_GetFloat( p_demux, "sub-fps" ) <= 0.0 )
+ p_sys->i_microsecperframe = (int64_t)( (float)1000000 / tmp );
+ goto next;
+ }
+
/* replace | by \n */
for( i = 0; i < strlen( buffer_text ); i++ )
{
}
}
- p_subtitle->i_start = (int64_t)i_start * i_microsecperframe;
- p_subtitle->i_stop = (int64_t)i_stop * i_microsecperframe;
+ p_subtitle->i_start = (int64_t)i_start * p_sys->i_microsecperframe;
+ p_subtitle->i_stop = (int64_t)i_stop * p_sys->i_microsecperframe;
p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
return( 0 );
}
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 = (int64_t)i_start *
- p_sys->i_microsecperframe/
- p_sys->i_original_mspf;
- p_subtitle->i_stop = (int64_t)i_stop *
- p_sys->i_microsecperframe /
- p_sys->i_original_mspf;
- }
return 0;
}
else
return( 0 );
}
-static char *ParseSamiSearch( text_t *txt, char *psz_start, char *psz_str )
+static char *ParseSamiSearch( text_t *txt, char *psz_start, const char *psz_str )
{
if( psz_start )
{
}
}
+static int ParseMPL2( 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...
+ * [n2] can also be []
+ */
+ char *s;
+
+ char buffer_text[MAX_LINE + 1];
+ int i_start;
+ int i_stop;
+ unsigned int i;
+
+ p_subtitle->i_start = 0;
+ p_subtitle->i_stop = 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 = (int64_t)i_start * 100000;
+ p_subtitle->i_stop = (int64_t)i_stop * 100000;
+ p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
+ return( 0 );
+}