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

📄 vobsub.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * subtitle.c: Demux vobsub files. ***************************************************************************** * Copyright (C) 1999-2004 the VideoLAN team * $Id: 508a42cbd68994286ea573522551e91bfaac9c20 $ * * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <errno.h>#include <sys/types.h>#include <vlc_demux.h>#include <vlc_charset.h>#include "ps.h"#define MAX_LINE 8192/***************************************************************************** * Module descriptor *****************************************************************************/static int  Open ( vlc_object_t *p_this );static void Close( vlc_object_t *p_this );vlc_module_begin();    set_description( N_("Vobsub subtitles parser") );    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    set_capability( "demux", 1 );    set_callbacks( Open, Close );    add_shortcut( "vobsub" );    add_shortcut( "subtitle" );vlc_module_end();/***************************************************************************** * Prototypes: *****************************************************************************/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;    int     i_vobsub_location;} subtitle_t;typedef struct{    es_format_t fmt;    es_out_id_t *p_es;    int         i_track_id;    int         i_current_subtitle;    int         i_subtitles;    subtitle_t  *p_subtitles;    int64_t     i_delay;} vobsub_track_t;struct demux_sys_t{    int64_t     i_next_demux_date;    int64_t     i_length;    text_t      txt;    stream_t    *p_vobsub_stream;    /* all tracks */    int            i_tracks;    vobsub_track_t *track;    int         i_original_frame_width;    int         i_original_frame_height;    bool  b_palette;    uint32_t    palette[16];};static int Demux( demux_t * );static int Control( demux_t *, int, va_list );static int ParseVobSubIDX( demux_t * );static int DemuxVobSub( demux_t *, block_t *);/***************************************************************************** * Module initializer *****************************************************************************/static int Open ( vlc_object_t *p_this ){    demux_t     *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys;    char *psz_vobname, *s;    int i_len;    if( ( s = stream_ReadLine( p_demux->s ) ) != NULL )    {        if( !strcasestr( s, "# VobSub index file" ) )        {            msg_Dbg( p_demux, "this doesn't seem to be a vobsub file" );            free( s );            if( stream_Seek( p_demux->s, 0 ) )            {                msg_Warn( p_demux, "failed to rewind" );            }            return VLC_EGENERIC;        }        free( s );    }    else    {        msg_Dbg( p_demux, "could not read vobsub IDX file" );        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->i_length = 0;    p_sys->p_vobsub_stream = NULL;    p_sys->i_tracks = 0;    p_sys->track = (vobsub_track_t *)malloc( sizeof( vobsub_track_t ) );    p_sys->i_original_frame_width = -1;    p_sys->i_original_frame_height = -1;    p_sys->b_palette = false;    memset( p_sys->palette, 0, 16 * sizeof( uint32_t ) );    /* Load the whole file */    TextLoad( &p_sys->txt, p_demux->s );    /* Parse it */    ParseVobSubIDX( p_demux );    /* Unload */    TextUnload( &p_sys->txt );    /* Find the total length of the vobsubs */    if( p_sys->i_tracks > 0 )    {        int i;        for( i = 0; i < p_sys->i_tracks; i++ )        {            if( p_sys->track[i].i_subtitles > 1 )            {                if( p_sys->track[i].p_subtitles[p_sys->track[i].i_subtitles-1].i_start > p_sys->i_length )                    p_sys->i_length = (int64_t) p_sys->track[i].p_subtitles[p_sys->track[i].i_subtitles-1].i_start + ( 1 *1000 *1000 );            }        }    }    if( asprintf( &psz_vobname, "%s://%s", p_demux->psz_access, p_demux->psz_path ) == -1 )    {        free( p_sys );        return VLC_EGENERIC;    }    i_len = strlen( psz_vobname );    if( i_len >= 4 ) memcpy( psz_vobname + i_len - 4, ".sub", 4 );    /* open file */    p_sys->p_vobsub_stream = stream_UrlNew( p_demux, psz_vobname );    if( p_sys->p_vobsub_stream == NULL )    {        msg_Err( p_demux, "couldn't open .sub Vobsub file: %s",                 psz_vobname );        free( psz_vobname );        free( p_sys );        return VLC_EGENERIC;    }    free( psz_vobname );    return VLC_SUCCESS;}/***************************************************************************** * Close: Close subtitle demux *****************************************************************************/static void Close( vlc_object_t *p_this ){    int i;    demux_t *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys = p_demux->p_sys;    /* Clean all subs from all tracks */    for( i = 0; i < p_sys->i_tracks; i++ )        free( p_sys->track[i].p_subtitles );    free( p_sys->track );    if( p_sys->p_vobsub_stream )        stream_Delete( p_sys->p_vobsub_stream );    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;    int i;    double *pf, f;    switch( i_query )    {        case DEMUX_GET_LENGTH:            pi64 = (int64_t*)va_arg( args, int64_t * );            *pi64 = (int64_t) p_sys->i_length;            return VLC_SUCCESS;        case DEMUX_GET_TIME:            pi64 = (int64_t*)va_arg( args, int64_t * );            for( i = 0; i < p_sys->i_tracks; i++ )            {                bool b_selected;                /* Check the ES is selected */                es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,                                p_sys->track[i].p_es, &b_selected );                if( b_selected ) break;            }            if( i < p_sys->i_tracks && p_sys->track[i].i_current_subtitle < p_sys->track[i].i_subtitles )            {                *pi64 = p_sys->track[i].p_subtitles[p_sys->track[i].i_current_subtitle].i_start;                return VLC_SUCCESS;            }            return VLC_EGENERIC;        case DEMUX_SET_TIME:            i64 = (int64_t)va_arg( args, int64_t );            for( i = 0; i < p_sys->i_tracks; i++ )            {                p_sys->track[i].i_current_subtitle = 0;                while( p_sys->track[i].i_current_subtitle < p_sys->track[i].i_subtitles &&                       p_sys->track[i].p_subtitles[p_sys->track[i].i_current_subtitle].i_start < i64 )                {                    p_sys->track[i].i_current_subtitle++;                }                if( p_sys->track[i].i_current_subtitle >= p_sys->track[i].i_subtitles )                    return VLC_EGENERIC;            }            return VLC_SUCCESS;        case DEMUX_GET_POSITION:            pf = (double*)va_arg( args, double * );            for( i = 0; i < p_sys->i_tracks; i++ )            {                bool b_selected;                /* Check the ES is selected */                es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,                                p_sys->track[i].p_es, &b_selected );                if( b_selected ) break;            }            if( p_sys->track[i].i_current_subtitle >= p_sys->track[i].i_subtitles )            {                *pf = 1.0;            }            else if( p_sys->track[i].i_subtitles > 0 )            {                *pf = (double)p_sys->track[i].p_subtitles[p_sys->track[i].i_current_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 = (int64_t) f * p_sys->i_length;            for( i = 0; i < p_sys->i_tracks; i++ )            {                p_sys->track[i].i_current_subtitle = 0;                while( p_sys->track[i].i_current_subtitle < p_sys->track[i].i_subtitles &&                       p_sys->track[i].p_subtitles[p_sys->track[i].i_current_subtitle].i_start < i64 )                {                    p_sys->track[i].i_current_subtitle++;                }                if( p_sys->track[i].i_current_subtitle >= p_sys->track[i].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;    int i, i_read;    for( i = 0; i < p_sys->i_tracks; i++ )    {#define tk p_sys->track[i]        if( tk.i_current_subtitle >= tk.i_subtitles )            continue;        i_maxdate = (int64_t) p_sys->i_next_demux_date;        if( i_maxdate <= 0 && tk.i_current_subtitle < tk.i_subtitles )        {            /* Should not happen */            i_maxdate = (int64_t) tk.p_subtitles[tk.i_current_subtitle].i_start + 1;        }

⌨️ 快捷键说明

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