subtitle.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:33k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * subtitle.c: Demux for subtitle text files.
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2004 VideoLAN
  5.  * $Id: subtitle.c 9114 2004-11-02 20:52:45Z hartman $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Derk-Jan Hartman <hartman at videolan dot org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>
  28. #include <errno.h>
  29. #ifdef HAVE_SYS_TYPES_H
  30. #   include <sys/types.h>
  31. #endif
  32. #include <ctype.h>
  33. #include <vlc/vlc.h>
  34. #include <vlc/input.h>
  35. #include "vlc_video.h"
  36. #if (!defined( WIN32 ) || defined(__MINGW32__))
  37. #    include <dirent.h>
  38. #endif
  39. /*****************************************************************************
  40.  * Module descriptor
  41.  *****************************************************************************/
  42. static int  Open ( vlc_object_t *p_this );
  43. static void Close( vlc_object_t *p_this );
  44. #define SUB_DELAY_LONGTEXT 
  45.     "Delay subtitles (in 1/10s)"
  46. #define SUB_FPS_LONGTEXT 
  47.     "Override frames per second. " 
  48.     "It will only work with MicroDVD subtitles."
  49. #define SUB_TYPE_LONGTEXT 
  50.     "One from "microdvd", "subrip", "ssa1", "ssa2-4", "vplayer" " 
  51.     ""sami" (auto for autodetection, it should always work)."
  52. static char *ppsz_sub_type[] =
  53. {
  54.     "auto", "microdvd", "subrip", "subviewer", "ssa1",
  55.     "ssa2-4", "vplayer", "sami"
  56. };
  57. vlc_module_begin();
  58.     set_description( _("Text subtitles demux") );
  59.     set_capability( "demux2", 0 );
  60.     add_float( "sub-fps", 0.0, NULL,
  61.                N_("Frames per second"),
  62.                SUB_FPS_LONGTEXT, VLC_TRUE );
  63.     add_integer( "sub-delay", 0, NULL,
  64.                N_("Subtitles delay"),
  65.                SUB_DELAY_LONGTEXT, VLC_TRUE );
  66.     add_string( "sub-type", "auto", NULL, "Subtitles fileformat",
  67.                 SUB_TYPE_LONGTEXT, VLC_TRUE );
  68.         change_string_list( ppsz_sub_type, 0, 0 );
  69.     set_callbacks( Open, Close );
  70.     add_shortcut( "subtitle" );
  71. vlc_module_end();
  72. /*****************************************************************************
  73.  * Prototypes:
  74.  *****************************************************************************/
  75. enum
  76. {
  77.     SUB_TYPE_UNKNOWN = -1,
  78.     SUB_TYPE_MICRODVD,
  79.     SUB_TYPE_SUBRIP,
  80.     SUB_TYPE_SSA1,
  81.     SUB_TYPE_SSA2_4,
  82.     SUB_TYPE_VPLAYER,
  83.     SUB_TYPE_SAMI,
  84.     SUB_TYPE_SUBVIEWER,
  85. };
  86. typedef struct
  87. {
  88.     int     i_line_count;
  89.     int     i_line;
  90.     char    **line;
  91. } text_t;
  92. static int  TextLoad( text_t *, stream_t *s );
  93. static void TextUnload( text_t * );
  94. typedef struct
  95. {
  96.     int64_t i_start;
  97.     int64_t i_stop;
  98.     char    *psz_text;
  99. } subtitle_t;
  100. struct demux_sys_t
  101. {
  102.     int         i_type;
  103.     text_t      txt;
  104.     es_out_id_t *es;
  105.     int64_t     i_next_demux_date;
  106.     int64_t     i_microsecperframe;
  107.     int64_t     i_original_mspf;
  108.     char        *psz_header;
  109.     int         i_subtitle;
  110.     int         i_subtitles;
  111.     subtitle_t  *subtitle;
  112.     int64_t     i_length;
  113. };
  114. static int  ParseMicroDvd ( demux_t *, subtitle_t * );
  115. static int  ParseSubRip   ( demux_t *, subtitle_t * );
  116. static int  ParseSubViewer( demux_t *, subtitle_t * );
  117. static int  ParseSSA      ( demux_t *, subtitle_t * );
  118. static int  ParseVplayer  ( demux_t *, subtitle_t * );
  119. static int  ParseSami     ( demux_t *, subtitle_t * );
  120. static struct
  121. {
  122.     char *psz_type_name;
  123.     int  i_type;
  124.     char *psz_name;
  125.     int  (*pf_read)( demux_t *, subtitle_t* );
  126. } sub_read_subtitle_function [] =
  127. {
  128.     { "microdvd",   SUB_TYPE_MICRODVD,  "MicroDVD", ParseMicroDvd },
  129.     { "subrip",     SUB_TYPE_SUBRIP,    "SubRIP",   ParseSubRip },
  130.     { "subviewer",  SUB_TYPE_SUBVIEWER, "SubViewer",ParseSubViewer },
  131.     { "ssa1",       SUB_TYPE_SSA1,      "SSA-1",    ParseSSA },
  132.     { "ssa2-4",     SUB_TYPE_SSA2_4,    "SSA-2/3/4",ParseSSA },
  133.     { "vplayer",    SUB_TYPE_VPLAYER,   "VPlayer",  ParseVplayer },
  134.     { "sami",       SUB_TYPE_SAMI,      "SAMI",     ParseSami },
  135.     { NULL,         SUB_TYPE_UNKNOWN,   "Unknown",  NULL }
  136. };
  137. static int Demux( demux_t * );
  138. static int Control( demux_t *, int, va_list );
  139. static void Fix( demux_t * );
  140. /*****************************************************************************
  141.  * Module initializer
  142.  *****************************************************************************/
  143. static int Open ( vlc_object_t *p_this )
  144. {
  145.     demux_t     *p_demux = (demux_t*)p_this;
  146.     demux_sys_t *p_sys;
  147.     es_format_t fmt;
  148.     float f_fps;
  149.     char *psz_type;
  150.     int  (*pf_read)( demux_t *, subtitle_t* );
  151.     int i, i_max;
  152.     if( strcmp( p_demux->psz_demux, "subtitle" ) )
  153.     {
  154.         msg_Dbg( p_demux, "subtitle demux discarded" );
  155.         return VLC_EGENERIC;
  156.     }
  157.     p_demux->pf_demux = Demux;
  158.     p_demux->pf_control = Control;
  159.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  160.     p_sys->psz_header = NULL;
  161.     p_sys->i_subtitle = 0;
  162.     p_sys->i_subtitles= 0;
  163.     p_sys->subtitle   = NULL;
  164.     /* Get the FPS */
  165.     f_fps = var_CreateGetFloat( p_demux, "sub-fps" );
  166.     if( f_fps >= 1.0 )
  167.     {
  168.         p_sys->i_microsecperframe = (int64_t)( (float)1000000 / f_fps );
  169.     }
  170.     else
  171.     {
  172.         p_sys->i_microsecperframe = 0;
  173.     }
  174.     f_fps = var_CreateGetFloat( p_demux, "sub-original-fps" );
  175.     if( f_fps >= 1.0 )
  176.     {
  177.         p_sys->i_original_mspf = (int64_t)( (float)1000000 / f_fps );
  178.     }
  179.     else
  180.     {
  181.         p_sys->i_original_mspf = 0;
  182.     }
  183.     /* Get or probe the type */
  184.     p_sys->i_type = SUB_TYPE_UNKNOWN;
  185.     psz_type = var_CreateGetString( p_demux, "sub-type" );
  186.     if( *psz_type )
  187.     {
  188.         int i;
  189.         for( i = 0; ; i++ )
  190.         {
  191.             if( sub_read_subtitle_function[i].psz_type_name == NULL )
  192.                 break;
  193.             if( !strcmp( sub_read_subtitle_function[i].psz_type_name,
  194.                          psz_type ) )
  195.             {
  196.                 p_sys->i_type = sub_read_subtitle_function[i].i_type;
  197.                 break;
  198.             }
  199.         }
  200.     }
  201.     free( psz_type );
  202.     /* Probe if unknown type */
  203.     if( p_sys->i_type == SUB_TYPE_UNKNOWN )
  204.     {
  205.         int     i_try;
  206.         char    *s = NULL;
  207.         msg_Dbg( p_demux, "autodetecting subtitle format" );
  208.         for( i_try = 0; i_try < 256; i_try++ )
  209.         {
  210.             int i_dummy;
  211.             if( ( s = stream_ReadLine( p_demux->s ) ) == NULL )
  212.                 break;
  213.             if( strcasestr( s, "<SAMI>" ) )
  214.             {
  215.                 p_sys->i_type = SUB_TYPE_SAMI;
  216.                 break;
  217.             }
  218.             else if( sscanf( s, "{%d}{%d}", &i_dummy, &i_dummy ) == 2 ||
  219.                      sscanf( s, "{%d}{}", &i_dummy ) == 1)
  220.             {
  221.                 p_sys->i_type = SUB_TYPE_MICRODVD;
  222.                 break;
  223.             }
  224.             else if( sscanf( s,
  225.                              "%d:%d:%d,%d --> %d:%d:%d,%d",
  226.                              &i_dummy,&i_dummy,&i_dummy,&i_dummy,
  227.                              &i_dummy,&i_dummy,&i_dummy,&i_dummy ) == 8 )
  228.             {
  229.                 p_sys->i_type = SUB_TYPE_SUBRIP;
  230.                 break;
  231.             }
  232.             else if( sscanf( s,
  233.                              "!: This is a Sub Station Alpha v%d.x script.",
  234.                              &i_dummy ) == 1)
  235.             {
  236.                 if( i_dummy <= 1 )
  237.                 {
  238.                     p_sys->i_type = SUB_TYPE_SSA1;
  239.                 }
  240.                 else
  241.                 {
  242.                     p_sys->i_type = SUB_TYPE_SSA2_4; /* I hope this will work */
  243.                 }
  244.                 break;
  245.             }
  246.             else if( strcasestr( s, "This is a Sub Station Alpha v4 script" ) )
  247.             {
  248.                 p_sys->i_type = SUB_TYPE_SSA2_4; /* I hope this will work */
  249.                 break;
  250.             }
  251.             else if( !strncasecmp( s, "Dialogue: Marked", 16  ) )
  252.             {
  253.                 p_sys->i_type = SUB_TYPE_SSA2_4; /* could be wrong */
  254.                 break;
  255.             }
  256.             else if( strcasestr( s, "[INFORMATION]" ) )
  257.             {
  258.                 p_sys->i_type = SUB_TYPE_SUBVIEWER; /* I hope this will work */
  259.                 break;
  260.             }
  261.             else if( sscanf( s, "%d:%d:%d:", &i_dummy, &i_dummy, &i_dummy ) == 3 ||
  262.                      sscanf( s, "%d:%d:%d ", &i_dummy, &i_dummy, &i_dummy ) == 3 )
  263.             {
  264.                 p_sys->i_type = SUB_TYPE_VPLAYER;
  265.                 break;
  266.             }
  267.             free( s );
  268.             s = NULL;
  269.         }
  270.         if( s ) free( s );
  271.         /* It will nearly always work even for non seekable stream thanks the
  272.          * caching system, and if it fails we loose just a few sub */
  273.         if( stream_Seek( p_demux->s, 0 ) )
  274.         {
  275.             msg_Warn( p_demux, "failed to rewind" );
  276.         }
  277.     }
  278.     if( p_sys->i_type == SUB_TYPE_UNKNOWN )
  279.     {
  280.         msg_Err( p_demux, "failed to recognize subtitle type" );
  281.         return VLC_EGENERIC;
  282.     }
  283.     for( i = 0; ; i++ )
  284.     {
  285.         if( sub_read_subtitle_function[i].i_type == p_sys->i_type )
  286.         {
  287.             msg_Dbg( p_demux, "detected %s format",
  288.                      sub_read_subtitle_function[i].psz_name );
  289.             pf_read = sub_read_subtitle_function[i].pf_read;
  290.             break;
  291.         }
  292.     }
  293.     msg_Dbg( p_demux, "loading all subtitles..." );
  294.     /* Load the whole file */
  295.     TextLoad( &p_sys->txt, p_demux->s );
  296.     /* Parse it */
  297.     for( i_max = 0;; )
  298.     {
  299.         if( p_sys->i_subtitles >= i_max )
  300.         {
  301.             i_max += 500;
  302.             if( !( p_sys->subtitle = realloc( p_sys->subtitle,
  303.                                               sizeof(subtitle_t) * i_max ) ) )
  304.             {
  305.                 msg_Err( p_demux, "out of memory");
  306.                 return VLC_ENOMEM;
  307.             }
  308.         }
  309.         if( pf_read( p_demux, &p_sys->subtitle[p_sys->i_subtitles] ) )
  310.             break;
  311.         p_sys->i_subtitles++;
  312.     }
  313.     /* Unload */
  314.     TextUnload( &p_sys->txt );
  315.     msg_Dbg(p_demux, "loaded %d subtitles", p_sys->i_subtitles );
  316.     /* Fix subtitle (order and time) *** */
  317.     p_sys->i_subtitle = 0;
  318.     p_sys->i_length = 0;
  319.     if( p_sys->i_subtitles > 0 )
  320.     {
  321.         p_sys->i_length = p_sys->subtitle[p_sys->i_subtitles-1].i_stop;
  322.         /* +1 to avoid 0 */
  323.         if( p_sys->i_length <= 0 )
  324.             p_sys->i_length = p_sys->subtitle[p_sys->i_subtitles-1].i_start+1;
  325.     }
  326.     /* *** add subtitle ES *** */
  327.     if( p_sys->i_type == SUB_TYPE_SSA1 ||
  328.              p_sys->i_type == SUB_TYPE_SSA2_4 )
  329.     {
  330.         es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','s','a',' ' ) );
  331.     }
  332.     else
  333.     {
  334.         es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','u','b','t' ) );
  335.     }
  336.     if( p_sys->psz_header != NULL )
  337.     {
  338.         fmt.i_extra = strlen( p_sys->psz_header ) + 1;
  339.         fmt.p_extra = strdup( p_sys->psz_header );
  340.     }
  341.     p_sys->es = es_out_Add( p_demux->out, &fmt );
  342.     return VLC_SUCCESS;
  343. }
  344. /*****************************************************************************
  345.  * Close: Close subtitle demux
  346.  *****************************************************************************/
  347. static void Close( vlc_object_t *p_this )
  348. {
  349.     demux_t *p_demux = (demux_t*)p_this;
  350.     demux_sys_t *p_sys = p_demux->p_sys;
  351.     int i;
  352.     for( i = 0; i < p_sys->i_subtitles; i++ )
  353.     {
  354.         if( p_sys->subtitle[i].psz_text )
  355.             free( p_sys->subtitle[i].psz_text );
  356.     }
  357.     if( p_sys->subtitle )
  358.         free( p_sys->subtitle );
  359.     free( p_sys );
  360. }
  361. /*****************************************************************************
  362.  * Control:
  363.  *****************************************************************************/
  364. static int Control( demux_t *p_demux, int i_query, va_list args )
  365. {
  366.     demux_sys_t *p_sys = p_demux->p_sys;
  367.     int64_t *pi64, i64;
  368.     double *pf, f;
  369.     switch( i_query )
  370.     {
  371.         case DEMUX_GET_LENGTH:
  372.             pi64 = (int64_t*)va_arg( args, int64_t * );
  373.             *pi64 = p_sys->i_length;
  374.             return VLC_SUCCESS;
  375.         case DEMUX_GET_TIME:
  376.             pi64 = (int64_t*)va_arg( args, int64_t * );
  377.             if( p_sys->i_subtitle < p_sys->i_subtitles )
  378.             {
  379.                 *pi64 = p_sys->subtitle[p_sys->i_subtitle].i_start;
  380.                 return VLC_SUCCESS;
  381.             }
  382.             return VLC_EGENERIC;
  383.         case DEMUX_SET_TIME:
  384.             i64 = (int64_t)va_arg( args, int64_t );
  385.             p_sys->i_subtitle = 0;
  386.             while( p_sys->i_subtitle < p_sys->i_subtitles &&
  387.                    p_sys->subtitle[p_sys->i_subtitle].i_start < i64 )
  388.             {
  389.                 p_sys->i_subtitle++;
  390.             }
  391.             if( p_sys->i_subtitle >= p_sys->i_subtitles )
  392.                 return VLC_EGENERIC;
  393.             return VLC_SUCCESS;
  394.         case DEMUX_GET_POSITION:
  395.             pf = (double*)va_arg( args, double * );
  396.             if( p_sys->i_subtitle >= p_sys->i_subtitles )
  397.             {
  398.                 *pf = 1.0;
  399.             }
  400.             else if( p_sys->i_subtitles > 0 )
  401.             {
  402.                 *pf = (double)p_sys->subtitle[p_sys->i_subtitle].i_start /
  403.                       (double)p_sys->i_length;
  404.             }
  405.             else
  406.             {
  407.                 *pf = 0.0;
  408.             }
  409.             return VLC_SUCCESS;
  410.         case DEMUX_SET_POSITION:
  411.             f = (double)va_arg( args, double );
  412.             i64 = f * p_sys->i_length;
  413.             p_sys->i_subtitle = 0;
  414.             while( p_sys->i_subtitle < p_sys->i_subtitles &&
  415.                    p_sys->subtitle[p_sys->i_subtitle].i_start < i64 )
  416.             {
  417.                 p_sys->i_subtitle++;
  418.             }
  419.             if( p_sys->i_subtitle >= p_sys->i_subtitles )
  420.                 return VLC_EGENERIC;
  421.             return VLC_SUCCESS;
  422.         case DEMUX_SET_NEXT_DEMUX_TIME:
  423.             p_sys->i_next_demux_date = (int64_t)va_arg( args, int64_t );
  424.             return VLC_SUCCESS;
  425.         case DEMUX_GET_FPS:
  426.         case DEMUX_GET_META:
  427.         case DEMUX_GET_TITLE_INFO:
  428.             return VLC_EGENERIC;
  429.         default:
  430.             msg_Err( p_demux, "unknown query in subtitle control" );
  431.             return VLC_EGENERIC;
  432.     }
  433. }
  434. /*****************************************************************************
  435.  * Demux: Send subtitle to decoder
  436.  *****************************************************************************/
  437. static int Demux( demux_t *p_demux )
  438. {
  439.     demux_sys_t *p_sys = p_demux->p_sys;
  440.     int64_t i_maxdate;
  441.     if( p_sys->i_subtitle >= p_sys->i_subtitles )
  442.         return 0;
  443.     i_maxdate = p_sys->i_next_demux_date;
  444.     if( i_maxdate <= 0 && p_sys->i_subtitle < p_sys->i_subtitles )
  445.     {
  446.         /* Should not happen */
  447.         i_maxdate = p_sys->subtitle[p_sys->i_subtitle].i_start + 1;
  448.     }
  449.     while( p_sys->i_subtitle < p_sys->i_subtitles &&
  450.            p_sys->subtitle[p_sys->i_subtitle].i_start < i_maxdate )
  451.     {
  452.         block_t *p_block;
  453.         int i_len = strlen( p_sys->subtitle[p_sys->i_subtitle].psz_text ) + 1;
  454.         if( i_len <= 1 )
  455.         {
  456.             /* empty subtitle */
  457.             p_sys->i_subtitle++;
  458.             continue;
  459.         }
  460.         if( ( p_block = block_New( p_demux, i_len ) ) == NULL )
  461.         {
  462.             p_sys->i_subtitle++;
  463.             continue;
  464.         }
  465.         if( p_sys->subtitle[p_sys->i_subtitle].i_start < 0 )
  466.         {
  467.             p_sys->i_subtitle++;
  468.             continue;
  469.         }
  470.         p_block->i_pts = p_sys->subtitle[p_sys->i_subtitle].i_start;
  471.         p_block->i_dts = p_block->i_pts;
  472.         if( p_sys->subtitle[p_sys->i_subtitle].i_stop > 0 )
  473.         {
  474.             p_block->i_length =
  475.                 p_sys->subtitle[p_sys->i_subtitle].i_stop - p_block->i_pts;
  476.         }
  477.         memcpy( p_block->p_buffer,
  478.                 p_sys->subtitle[p_sys->i_subtitle].psz_text, i_len );
  479.         if( p_block->i_pts > 0 )
  480.         {
  481.             es_out_Send( p_demux->out, p_sys->es, p_block );
  482.         }
  483.         else
  484.         {
  485.             block_Release( p_block );
  486.         }
  487.         p_sys->i_subtitle++;
  488.     }
  489.     /* */
  490.     p_sys->i_next_demux_date = 0;
  491.     return 1;
  492. }
  493. /*****************************************************************************
  494.  * Fix: fix time stamp and order of subtitle
  495.  *****************************************************************************/
  496. static void Fix( demux_t *p_demux )
  497. {
  498.     demux_sys_t *p_sys = p_demux->p_sys;
  499.     vlc_bool_t b_done;
  500.     int     i_index;
  501.     /* *** fix order (to be sure...) *** */
  502.     /* We suppose that there are near in order and this durty bubble sort
  503.      * wont take too much time
  504.      */
  505.     do
  506.     {
  507.         b_done = VLC_TRUE;
  508.         for( i_index = 1; i_index < p_sys->i_subtitles; i_index++ )
  509.         {
  510.             if( p_sys->subtitle[i_index].i_start <
  511.                     p_sys->subtitle[i_index - 1].i_start )
  512.             {
  513.                 subtitle_t sub_xch;
  514.                 memcpy( &sub_xch,
  515.                         p_sys->subtitle + i_index - 1,
  516.                         sizeof( subtitle_t ) );
  517.                 memcpy( p_sys->subtitle + i_index - 1,
  518.                         p_sys->subtitle + i_index,
  519.                         sizeof( subtitle_t ) );
  520.                 memcpy( p_sys->subtitle + i_index,
  521.                         &sub_xch,
  522.                         sizeof( subtitle_t ) );
  523.                 b_done = VLC_FALSE;
  524.             }
  525.         }
  526.     } while( !b_done );
  527. }
  528. static int TextLoad( text_t *txt, stream_t *s )
  529. {
  530.     int   i_line_max;
  531.     /* init txt */
  532.     i_line_max          = 500;
  533.     txt->i_line_count   = 0;
  534.     txt->i_line         = 0;
  535.     txt->line           = calloc( i_line_max, sizeof( char * ) );
  536.     /* load the complete file */
  537.     for( ;; )
  538.     {
  539.         char *psz = stream_ReadLine( s );
  540.         if( psz == NULL )
  541.             break;
  542.         txt->line[txt->i_line_count++] = psz;
  543.         if( txt->i_line_count >= i_line_max )
  544.         {
  545.             i_line_max += 100;
  546.             txt->line = realloc( txt->line, i_line_max * sizeof( char*) );
  547.         }
  548.     }
  549.     if( txt->i_line_count <= 0 )
  550.     {
  551.         free( txt->line );
  552.         return VLC_EGENERIC;
  553.     }
  554.     return VLC_SUCCESS;
  555. }
  556. static void TextUnload( text_t *txt )
  557. {
  558.     int i;
  559.     for( i = 0; i < txt->i_line_count; i++ )
  560.     {
  561.         free( txt->line[i] );
  562.     }
  563.     free( txt->line );
  564.     txt->i_line       = 0;
  565.     txt->i_line_count = 0;
  566. }
  567. static char *TextGetLine( text_t *txt )
  568. {
  569.     if( txt->i_line >= txt->i_line_count )
  570.         return( NULL );
  571.     return txt->line[txt->i_line++];
  572. }
  573. static void TextPreviousLine( text_t *txt )
  574. {
  575.     if( txt->i_line > 0 )
  576.         txt->i_line--;
  577. }
  578. /*****************************************************************************
  579.  * Specific Subtitle function
  580.  *****************************************************************************/
  581. #define MAX_LINE 8192
  582. static int ParseMicroDvd( demux_t *p_demux, subtitle_t *p_subtitle )
  583. {
  584.     demux_sys_t *p_sys = p_demux->p_sys;
  585.     text_t      *txt = &p_sys->txt;
  586.     /*
  587.      * each line:
  588.      *  {n1}{n2}Line1|Line2|Line3....
  589.      * where n1 and n2 are the video frame number...
  590.      *
  591.      */
  592.     char *s;
  593.     char buffer_text[MAX_LINE + 1];
  594.     int    i_start;
  595.     int    i_stop;
  596.     unsigned int i;
  597.     int i_microsecperframe = 40000; /* default to 25 fps */
  598.     if( p_sys->i_microsecperframe > 0 ) 
  599.         i_microsecperframe = p_sys->i_microsecperframe;
  600.     
  601.     p_subtitle->i_start = 0;
  602.     p_subtitle->i_stop  = 0;
  603.     p_subtitle->psz_text = NULL;
  604.     for( ;; )
  605.     {
  606.         if( ( s = TextGetLine( txt ) ) == NULL )
  607.         {
  608.             return( VLC_EGENERIC );
  609.         }
  610.         i_start = 0;
  611.         i_stop  = 0;
  612.         memset( buffer_text, '', MAX_LINE );
  613.         if( sscanf( s, "{%d}{}%[^rn]", &i_start, buffer_text ) == 2 ||
  614.             sscanf( s, "{%d}{%d}%[^rn]", &i_start, &i_stop, buffer_text ) == 3)
  615.         {
  616.             break;
  617.         }
  618.     }
  619.     /* replace | by n */
  620.     for( i = 0; i < strlen( buffer_text ); i++ )
  621.     {
  622.         if( buffer_text[i] == '|' )
  623.         {
  624.             buffer_text[i] = 'n';
  625.         }
  626.     }
  627.     p_subtitle->i_start = (int64_t)i_start * i_microsecperframe;
  628.     p_subtitle->i_stop  = (int64_t)i_stop  * i_microsecperframe;
  629.     p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
  630.     return( 0 );
  631. }
  632. static int  ParseSubRip( demux_t *p_demux, subtitle_t *p_subtitle )
  633. {
  634.     demux_sys_t *p_sys = p_demux->p_sys;
  635.     text_t      *txt = &p_sys->txt;
  636.     /*
  637.      * n
  638.      * h1:m1:s1,d1 --> h2:m2:s2,d2
  639.      * Line1
  640.      * Line2
  641.      * ...
  642.      * [empty line]
  643.      *
  644.      */
  645.     char *s;
  646.     char buffer_text[ 10 * MAX_LINE];
  647.     int  i_buffer_text;
  648.     int64_t     i_start;
  649.     int64_t     i_stop;
  650.     p_subtitle->i_start = 0;
  651.     p_subtitle->i_stop  = 0;
  652.     p_subtitle->psz_text = NULL;
  653.     for( ;; )
  654.     {
  655.         int h1, m1, s1, d1, h2, m2, s2, d2;
  656.         if( ( s = TextGetLine( txt ) ) == NULL )
  657.         {
  658.             return( VLC_EGENERIC );
  659.         }
  660.         if( sscanf( s,
  661.                     "%d:%d:%d,%d --> %d:%d:%d,%d",
  662.                     &h1, &m1, &s1, &d1,
  663.                     &h2, &m2, &s2, &d2 ) == 8 )
  664.         {
  665.             i_start = ( (int64_t)h1 * 3600*1000 +
  666.                         (int64_t)m1 * 60*1000 +
  667.                         (int64_t)s1 * 1000 +
  668.                         (int64_t)d1 ) * 1000;
  669.             i_stop  = ( (int64_t)h2 * 3600*1000 +
  670.                         (int64_t)m2 * 60*1000 +
  671.                         (int64_t)s2 * 1000 +
  672.                         (int64_t)d2 ) * 1000;
  673.             /* Now read text until an empty line */
  674.             for( i_buffer_text = 0;; )
  675.             {
  676.                 int i_len;
  677.                 if( ( s = TextGetLine( txt ) ) == NULL )
  678.                 {
  679.                     return( VLC_EGENERIC );
  680.                 }
  681.                 i_len = strlen( s );
  682.                 if( i_len <= 0 )
  683.                 {
  684.                     /* empty line -> end of this subtitle */
  685.                     buffer_text[__MAX( i_buffer_text - 1, 0 )] = '';
  686.                     p_subtitle->i_start = i_start;
  687.                     p_subtitle->i_stop = i_stop;
  688.                     p_subtitle->psz_text = strdup( buffer_text );
  689.                     /* If framerate is available, use sub-fps */
  690.                     if( p_sys->i_microsecperframe != 0 &&
  691.                         p_sys->i_original_mspf != 0)
  692.                     {
  693.                         p_subtitle->i_start = (int64_t)i_start *
  694.                                               p_sys->i_microsecperframe/
  695.                                               p_sys->i_original_mspf;
  696.                         p_subtitle->i_stop  = (int64_t)i_stop  *
  697.                                               p_sys->i_microsecperframe /
  698.                                               p_sys->i_original_mspf;
  699.                     }
  700.                     return 0;
  701.                 }
  702.                 else
  703.                 {
  704.                     if( i_buffer_text + i_len + 1 < 10 * MAX_LINE )
  705.                     {
  706.                         memcpy( buffer_text + i_buffer_text,
  707.                                 s,
  708.                                 i_len );
  709.                         i_buffer_text += i_len;
  710.                         buffer_text[i_buffer_text] = 'n';
  711.                         i_buffer_text++;
  712.                     }
  713.                 }
  714.             }
  715.         }
  716.     }
  717. }
  718. static int  ParseSubViewer( demux_t *p_demux, subtitle_t *p_subtitle )
  719. {
  720.     demux_sys_t *p_sys = p_demux->p_sys;
  721.     text_t      *txt = &p_sys->txt;
  722.     /*
  723.      * h1:m1:s1.d1,h2:m2:s2.d2
  724.      * Line1[br]Line2
  725.      * Line3
  726.      * ...
  727.      * [empty line]
  728.      * ( works with subviewer and subviewer v2 )
  729.      */
  730.     char *s;
  731.     char buffer_text[ 10 * MAX_LINE];
  732.     int  i_buffer_text;
  733.     int64_t     i_start;
  734.     int64_t     i_stop;
  735.     p_subtitle->i_start = 0;
  736.     p_subtitle->i_stop  = 0;
  737.     p_subtitle->psz_text = NULL;
  738.     for( ;; )
  739.     {
  740.         int h1, m1, s1, d1, h2, m2, s2, d2;
  741.         if( ( s = TextGetLine( txt ) ) == NULL )
  742.         {
  743.             return( VLC_EGENERIC );
  744.         }
  745.         if( sscanf( s,
  746.                     "%d:%d:%d.%d,%d:%d:%d.%d",
  747.                     &h1, &m1, &s1, &d1,
  748.                     &h2, &m2, &s2, &d2 ) == 8 )
  749.         {
  750.             i_start = ( (int64_t)h1 * 3600*1000 +
  751.                         (int64_t)m1 * 60*1000 +
  752.                         (int64_t)s1 * 1000 +
  753.                         (int64_t)d1 ) * 1000;
  754.             i_stop  = ( (int64_t)h2 * 3600*1000 +
  755.                         (int64_t)m2 * 60*1000 +
  756.                         (int64_t)s2 * 1000 +
  757.                         (int64_t)d2 ) * 1000;
  758.             /* Now read text until an empty line */
  759.             for( i_buffer_text = 0;; )
  760.             {
  761.                 int i_len, i;
  762.                 if( ( s = TextGetLine( txt ) ) == NULL )
  763.                 {
  764.                     return( VLC_EGENERIC );
  765.                 }
  766.                 i_len = strlen( s );
  767.                 if( i_len <= 0 )
  768.                 {
  769.                     /* empty line -> end of this subtitle */
  770.                     buffer_text[__MAX( i_buffer_text - 1, 0 )] = '';
  771.                     p_subtitle->i_start = i_start;
  772.                     p_subtitle->i_stop = i_stop;
  773.                     /* replace [br] by n */
  774.                     for( i = 0; i < i_buffer_text - 3; i++ )
  775.                     {
  776.                         if( buffer_text[i] == '[' && buffer_text[i+1] == 'b' &&
  777.                             buffer_text[i+2] == 'r' && buffer_text[i+3] == ']' )
  778.                         {
  779.                             char *temp = buffer_text + i + 1;
  780.                             buffer_text[i] = 'n';
  781.                             memmove( temp, temp+3, strlen( temp ) -3 );
  782.                             temp[strlen( temp )-3] = '';
  783.                         }
  784.                     }
  785.                     p_subtitle->psz_text = strdup( buffer_text );
  786.                     return( 0 );
  787.                 }
  788.                 else
  789.                 {
  790.                     if( i_buffer_text + i_len + 1 < 10 * MAX_LINE )
  791.                     {
  792.                         memcpy( buffer_text + i_buffer_text,
  793.                                 s,
  794.                                 i_len );
  795.                         i_buffer_text += i_len;
  796.                         buffer_text[i_buffer_text] = 'n';
  797.                         i_buffer_text++;
  798.                     }
  799.                 }
  800.             }
  801.         }
  802.     }
  803. }
  804. static int  ParseSSA( demux_t *p_demux, subtitle_t *p_subtitle )
  805. {
  806.     demux_sys_t *p_sys = p_demux->p_sys;
  807.     text_t      *txt = &p_sys->txt;
  808.     char buffer_text[ 10 * MAX_LINE];
  809.     char *s;
  810.     int64_t     i_start;
  811.     int64_t     i_stop;
  812.     p_subtitle->i_start = 0;
  813.     p_subtitle->i_stop  = 0;
  814.     p_subtitle->psz_text = NULL;
  815.     for( ;; )
  816.     {
  817.         int h1, m1, s1, c1, h2, m2, s2, c2;
  818.         int i_dummy;
  819.         if( ( s = TextGetLine( txt ) ) == NULL )
  820.         {
  821.             return( VLC_EGENERIC );
  822.         }
  823.         p_subtitle->psz_text = malloc( strlen( s ) );
  824.         if( sscanf( s,
  825.                     "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d%[^rn]",
  826.                     &i_dummy,
  827.                     &h1, &m1, &s1, &c1,
  828.                     &h2, &m2, &s2, &c2,
  829.                     buffer_text ) == 10 )
  830.         {
  831.             i_start = ( (int64_t)h1 * 3600*1000 +
  832.                         (int64_t)m1 * 60*1000 +
  833.                         (int64_t)s1 * 1000 +
  834.                         (int64_t)c1 * 10 ) * 1000;
  835.             i_stop  = ( (int64_t)h2 * 3600*1000 +
  836.                         (int64_t)m2 * 60*1000 +
  837.                         (int64_t)s2 * 1000 +
  838.                         (int64_t)c2 * 10 ) * 1000;
  839.             /* The dec expects: ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text */
  840.             if( p_sys->i_type == SUB_TYPE_SSA1 )
  841.             {
  842.                 sprintf( p_subtitle->psz_text,
  843.                          ",%d%s", i_dummy, strdup( buffer_text) );
  844.             }
  845.             else
  846.             {
  847.                 sprintf( p_subtitle->psz_text,
  848.                          ",%d,%s", i_dummy, strdup( buffer_text) );
  849.             }
  850.             p_subtitle->i_start = i_start;
  851.             p_subtitle->i_stop = i_stop;
  852.             return 0;
  853.         }
  854.         else
  855.         {
  856.             /* All the other stuff we add to the header field */
  857.             if( p_sys->psz_header != NULL )
  858.             {
  859.                 if( !( p_sys->psz_header = realloc( p_sys->psz_header,
  860.                           strlen( p_sys->psz_header ) + strlen( s ) + 2 ) ) )
  861.                 {
  862.                     msg_Err( p_demux, "out of memory");
  863.                     return VLC_ENOMEM;
  864.                 }
  865.                 p_sys->psz_header = strcat( p_sys->psz_header, strdup( s ) );
  866.                 p_sys->psz_header = strcat( p_sys->psz_header, "n" );
  867.             }
  868.             else
  869.             {
  870.                 if( !( p_sys->psz_header = malloc( strlen( s ) + 2 ) ) )
  871.                 {
  872.                     msg_Err( p_demux, "out of memory");
  873.                     return VLC_ENOMEM;
  874.                 }
  875.                 p_sys->psz_header = strdup( s );
  876.                 p_sys->psz_header = strcat( p_sys->psz_header, "n" );
  877.             }
  878.         }
  879.     }
  880. }
  881. static int  ParseVplayer( demux_t *p_demux, subtitle_t *p_subtitle )
  882. {
  883.     demux_sys_t *p_sys = p_demux->p_sys;
  884.     text_t      *txt = &p_sys->txt;
  885.     /*
  886.      * each line:
  887.      *  h:m:s:Line1|Line2|Line3....
  888.      *  or
  889.      *  h:m:s Line1|Line2|Line3....
  890.      *
  891.      */
  892.     char *p;
  893.     char buffer_text[MAX_LINE + 1];
  894.     int64_t    i_start;
  895.     unsigned int i;
  896.     p_subtitle->i_start = 0;
  897.     p_subtitle->i_stop  = 0;
  898.     p_subtitle->psz_text = NULL;
  899.     for( ;; )
  900.     {
  901.         int h, m, s;
  902.         char c;
  903.         if( ( p = TextGetLine( txt ) ) == NULL )
  904.         {
  905.             return( VLC_EGENERIC );
  906.         }
  907.         i_start = 0;
  908.         memset( buffer_text, '', MAX_LINE );
  909.         if( sscanf( p, "%d:%d:%d%[ :]%[^rn]", &h, &m, &s, &c, buffer_text ) == 5 )
  910.         {
  911.             i_start = ( (int64_t)h * 3600*1000 +
  912.                         (int64_t)m * 60*1000 +
  913.                         (int64_t)s * 1000 ) * 1000;
  914.             break;
  915.         }
  916.     }
  917.     /* replace | by n */
  918.     for( i = 0; i < strlen( buffer_text ); i++ )
  919.     {
  920.         if( buffer_text[i] == '|' )
  921.         {
  922.             buffer_text[i] = 'n';
  923.         }
  924.     }
  925.     p_subtitle->i_start = i_start;
  926.     p_subtitle->i_stop  = 0;
  927.     p_subtitle->psz_text = strndup( buffer_text, MAX_LINE );
  928.     return( 0 );
  929. }
  930. static char *ParseSamiSearch( text_t *txt, char *psz_start, char *psz_str )
  931. {
  932.     if( psz_start )
  933.     {
  934.         if( strcasestr( psz_start, psz_str ) )
  935.         {
  936.             char *s = strcasestr( psz_start, psz_str );
  937.             s += strlen( psz_str );
  938.             return( s );
  939.         }
  940.     }
  941.     for( ;; )
  942.     {
  943.         char *p;
  944.         if( ( p = TextGetLine( txt ) ) == NULL )
  945.         {
  946.             return NULL;
  947.         }
  948.         if( strcasestr( p, psz_str ) )
  949.         {
  950.             char *s = strcasestr( p, psz_str );
  951.             s += strlen( psz_str );
  952.             return(  s);
  953.         }
  954.     }
  955. }
  956. static int  ParseSami( demux_t *p_demux, subtitle_t *p_subtitle )
  957. {
  958.     demux_sys_t *p_sys = p_demux->p_sys;
  959.     text_t      *txt = &p_sys->txt;
  960.     char *p;
  961.     int64_t i_start;
  962.     int  i_text;
  963.     char buffer_text[10*MAX_LINE + 1];
  964.     p_subtitle->i_start = 0;
  965.     p_subtitle->i_stop  = 0;
  966.     p_subtitle->psz_text = NULL;
  967. #define ADDC( c ) 
  968.     if( i_text < 10*MAX_LINE )      
  969.     {                               
  970.         buffer_text[i_text++] = c;  
  971.         buffer_text[i_text] = ''; 
  972.     }
  973.     /* search "Start=" */
  974.     if( !( p = ParseSamiSearch( txt, NULL, "Start=" ) ) )
  975.     {
  976.         return VLC_EGENERIC;
  977.     }
  978.     /* get start value */
  979.     i_start = strtol( p, &p, 0 );
  980.     /* search <P */
  981.     if( !( p = ParseSamiSearch( txt, p, "<P" ) ) )
  982.     {
  983.         return VLC_EGENERIC;
  984.     }
  985.     /* search > */
  986.     if( !( p = ParseSamiSearch( txt, p, ">" ) ) )
  987.     {
  988.         return VLC_EGENERIC;
  989.     }
  990.     i_text = 0;
  991.     buffer_text[0] = '';
  992.     /* now get all txt until  a "Start=" line */
  993.     for( ;; )
  994.     {
  995.         if( *p )
  996.         {
  997.             if( *p == '<' )
  998.             {
  999.                 if( !strncasecmp( p, "<br", 3 ) )
  1000.                 {
  1001.                     ADDC( 'n' );
  1002.                 }
  1003.                 else if( strcasestr( p, "Start=" ) )
  1004.                 {
  1005.                     TextPreviousLine( txt );
  1006.                     break;
  1007.                 }
  1008.                 p = ParseSamiSearch( txt, p, ">" );
  1009.             }
  1010.             else if( !strncmp( p, "&nbsp;", 6 ) )
  1011.             {
  1012.                 ADDC( ' ' );
  1013.                 p += 6;
  1014.             }
  1015.             else if( *p == 't' )
  1016.             {
  1017.                 ADDC( ' ' );
  1018.                 p++;
  1019.             }
  1020.             else
  1021.             {
  1022.                 ADDC( *p );
  1023.                 p++;
  1024.             }
  1025.         }
  1026.         else
  1027.         {
  1028.             p = TextGetLine( txt );
  1029.         }
  1030.         if( p == NULL )
  1031.         {
  1032.             break;
  1033.         }
  1034.     }
  1035.     p_subtitle->i_start = i_start * 1000;
  1036.     p_subtitle->i_stop  = 0;
  1037.     p_subtitle->psz_text = strndup( buffer_text, 10*MAX_LINE );
  1038.     return( VLC_SUCCESS );
  1039. #undef ADDC
  1040. }