⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subtitle.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * subtitle.c: Demux for subtitle text files. ***************************************************************************** * Copyright (C) 1999-2004 VideoLAN * $Id: subtitle.c 11159 2005-05-24 19:52:57Z hartman $ * * 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>#ifdef HAVE_SYS_TYPES_H#   include <sys/types.h>#endif#include <ctype.h>#include <vlc/vlc.h>#include <vlc/input.h>#include "vlc_video.h"/***************************************************************************** * 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\", \"ass\", \"vplayer\" " \    "\"sami\" (auto for autodetection, it should always work)."static char *ppsz_sub_type[] ={    "auto", "microdvd", "subrip", "subviewer", "ssa1",    "ssa2-4", "ass", "vplayer", "sami"};vlc_module_begin();    set_shortname( _("Subtitles"));    set_description( _("Text subtitles demux") );    set_capability( "demux2", 0 );    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    add_float( "sub-fps", 0.0, NULL,               N_("Frames per second"),               SUB_FPS_LONGTEXT, VLC_TRUE );    add_integer( "sub-delay", 0, NULL,               N_("Subtitles delay"),               SUB_DELAY_LONGTEXT, VLC_TRUE );    add_string( "sub-type", "auto", NULL, "Subtitles fileformat",                SUB_TYPE_LONGTEXT, VLC_TRUE );        change_string_list( ppsz_sub_type, 0, 0 );    set_callbacks( Open, Close );    add_shortcut( "subtitle" );vlc_module_end();/***************************************************************************** * Prototypes: *****************************************************************************/enum{    SUB_TYPE_UNKNOWN = -1,    SUB_TYPE_MICRODVD,    SUB_TYPE_SUBRIP,    SUB_TYPE_SSA1,    SUB_TYPE_SSA2_4,    SUB_TYPE_ASS,    SUB_TYPE_VPLAYER,    SUB_TYPE_SAMI,    SUB_TYPE_SUBVIEWER,};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{    int64_t i_start;    int64_t i_stop;    char    *psz_text;} 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;    int64_t     i_original_mspf;    char        *psz_header;    int         i_subtitle;    int         i_subtitles;    subtitle_t  *subtitle;    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 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 },    { "ass",        SUB_TYPE_ASS,       "SSA/ASS",  ParseSSA },    { "vplayer",    SUB_TYPE_VPLAYER,   "VPlayer",  ParseVplayer },    { "sami",       SUB_TYPE_SAMI,      "SAMI",     ParseSami },    { NULL,         SUB_TYPE_UNKNOWN,   "Unknown",  NULL }};static int Demux( demux_t * );static int Control( demux_t *, int, va_list );static void Fix( demux_t * );/***************************************************************************** * 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" ) )    {        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;    /* 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_sys->i_microsecperframe = 0;    }    f_fps = var_CreateGetFloat( p_demux, "sub-original-fps" );    if( f_fps >= 1.0 )    {        p_sys->i_original_mspf = (int64_t)( (float)1000000 / f_fps );    }    else    {        p_sys->i_original_mspf = 0;    }    /* Get or probe the type */    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 = NULL;        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( !strncasecmp( s, "!: This is a Sub Station Alpha v1", 33 ) )            {                p_sys->i_type = SUB_TYPE_SSA1;                break;            }            else if( !strncasecmp( s, "ScriptType: v4.00+", 18 ) )            {                p_sys->i_type = SUB_TYPE_ASS;                break;            }            else if( !strncasecmp( s, "ScriptType: v4.00", 17 ) )            {                p_sys->i_type = SUB_TYPE_SSA2_4;                break;            }            else if( !strncasecmp( s, "Dialogue: Marked", 16  ) )            {                p_sys->i_type = SUB_TYPE_SSA2_4;                break;            }            else if( !strncasecmp( s, "Dialogue:", 9  ) )            {                p_sys->i_type = SUB_TYPE_ASS;                break;            }            else if( strcasestr( s, "[INFORMATION]" ) )            {                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;            }            free( s );            s = NULL;        }        if( s ) free( s );        /* It will nearly always work even for non seekable stream thanks the         * caching system, and if it fails we loose just a few sub */        if( stream_Seek( p_demux->s, 0 ) )        {            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;    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_SSA1 ||             p_sys->i_type == SUB_TYPE_SSA2_4 ||             p_sys->i_type == SUB_TYPE_ASS )    {        es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','s','a',' ' ) );    }    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 ){

⌨️ 快捷键说明

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