vobsub.c

来自「video linux conference」· C语言 代码 · 共 619 行 · 第 1/2 页

C
619
字号
/***************************************************************************** * subtitle.c: Demux vobsub files. ***************************************************************************** * Copyright (C) 1999-2004 VideoLAN * $Id: vobsub.c 9961 2005-02-16 22:01:41Z robux4 $ * * 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 <vlc/vlc.h>#include <vlc/input.h>#include "vlc_video.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( _("Vobsub subtitles demux") );    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    set_capability( "demux2", 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;} vobsub_track_t;struct demux_sys_t{    int64_t     i_next_demux_date;    int64_t     i_length;    text_t      txt;    FILE        *p_vobsub_file;        /* all tracks */    int            i_tracks;    vobsub_track_t *track;        int         i_original_frame_width;    int         i_original_frame_height;};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_file = 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;    /* 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 );            }        }    }    i_len = strlen( p_demux->psz_path );    psz_vobname = strdup( p_demux->psz_path );    strcpy( psz_vobname + i_len - 4, ".sub" );    /* open file */    if( !( p_sys->p_vobsub_file = fopen( psz_vobname, "rb" ) ) )    {        msg_Err( p_demux, "couldn't open .sub Vobsub file: %s",                 psz_vobname );        free( p_sys );        free( psz_vobname );        return VLC_EGENERIC;    }    free( psz_vobname );    return VLC_SUCCESS;}/***************************************************************************** * Close: Close subtitle demux *****************************************************************************/static void Close( vlc_object_t *p_this ){    demux_t *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys = p_demux->p_sys;    /* Clean all subs from all tracks    if( p_sys->subtitle )        free( p_sys->subtitle );*/    if( p_sys->p_vobsub_file )        fclose( p_sys->p_vobsub_file );    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++ )            {                vlc_bool_t 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++ )            {                vlc_bool_t 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:

⌨️ 快捷键说明

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