sub.c

来自「VLC媒体播放程序」· C语言 代码 · 共 1,224 行 · 第 1/3 页

C
1,224
字号
/***************************************************************************** * sub.c: subtitle demux for external subtitle files ***************************************************************************** * Copyright (C) 1999-2004 VideoLAN * $Id: sub.c,v 1.52 2004/02/22 15:59:53 fenrir Exp $ * * 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 2048static 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", "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", 25.0, NULL,               N_("Frames per second"),               SUB_FPS_LONGTEXT, VLC_TRUE );    add_integer( "sub-delay", 0, NULL,                 N_("Delay subtitles (in 1/10s)"),                 SUB_DELAY_LONGTEXT, VLC_TRUE );    add_string( "sub-type", "auto", NULL, "Subtitles fileformat",                SUB_TYPE_LONGTEXT, VLC_TRUE );        change_string_list( ppsz_sub_type, 0, 0 );    set_callbacks( Open, 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_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 },    { "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 }};static char * local_stristr( char *psz_big, char *psz_little){    char *p_pos = psz_big;    if (!psz_big || !psz_little || !*psz_little) return psz_big;    while (*p_pos)    {        if (toupper(*p_pos) == toupper(*psz_little))        {            char * psz_cur1 = p_pos + 1;            char * psz_cur2 = psz_little + 1;            while (*psz_cur1 && *psz_cur2 && toupper(*psz_cur1) == toupper(*psz_cur2))            {                psz_cur1++;                psz_cur2++;            }            if (!*psz_cur2) return p_pos;        }        p_pos++;    }    return 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->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 )    {        i_microsecperframe = 40000; /* default: 25fps */    }    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( local_stristr( 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( local_stristr( 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( 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( local_stristr( 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 )

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?