📄 subsusf.c
字号:
/***************************************************************************** * subsusf.c : USF subtitles decoder ***************************************************************************** * Copyright (C) 2000-2006 the VideoLAN team * $Id: ff8e3d77113758e888ebe8eabf2728f59f33a439 $ * * Authors: Bernie Purcell <bitmap@videolan.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. *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "subsdec.h"#include <vlc_plugin.h>/***************************************************************************** * Local prototypes *****************************************************************************/static int OpenDecoder ( vlc_object_t * );static void CloseDecoder ( vlc_object_t * );static subpicture_t *DecodeBlock ( decoder_t *, block_t ** );static char *CreatePlainText( char * );static int ParseImageAttachments( decoder_t *p_dec );static subpicture_t *ParseText ( decoder_t *, block_t * );static void ParseUSFHeader( decoder_t * );static subpicture_region_t *ParseUSFString( decoder_t *, char *, subpicture_t * );static subpicture_region_t *LoadEmbeddedImage( decoder_t *p_dec, subpicture_t *p_spu, const char *psz_filename, int i_transparent_color );/***************************************************************************** * Module descriptor. *****************************************************************************/vlc_module_begin(); set_capability( "decoder", 40 ); set_shortname( N_("USFSubs")); set_description( N_("USF subtitles decoder") ); set_callbacks( OpenDecoder, CloseDecoder ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_SCODEC ); /* We inherit subsdec-align and subsdec-formatted from subsdec.c */vlc_module_end();/***************************************************************************** * OpenDecoder: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/static int OpenDecoder( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; vlc_value_t val; if( p_dec->fmt_in.i_codec != VLC_FOURCC('u','s','f',' ') ) { return VLC_EGENERIC; } p_dec->pf_decode_sub = DecodeBlock; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)calloc(1, sizeof(decoder_sys_t)) ) == NULL ) { return VLC_ENOMEM; } /* Unused fields of p_sys - not needed for USF decoding */ p_sys->b_ass = false; p_sys->iconv_handle = (vlc_iconv_t)-1; p_sys->b_autodetect_utf8 = false; /* init of p_sys */ p_sys->i_align = 0; p_sys->i_original_height = -1; p_sys->i_original_width = -1; TAB_INIT( p_sys->i_ssa_styles, p_sys->pp_ssa_styles ); TAB_INIT( p_sys->i_images, p_sys->pp_images ); /* USF subtitles are mandated to be UTF-8, so don't need vlc_iconv */ var_Create( p_dec, "subsdec-align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_dec, "subsdec-align", &val ); p_sys->i_align = val.i_int; ParseImageAttachments( p_dec ); if( var_CreateGetBool( p_dec, "subsdec-formatted" ) ) { if( p_dec->fmt_in.i_extra > 0 ) ParseUSFHeader( p_dec ); } return VLC_SUCCESS;}/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with complete subtitles units. ****************************************************************************/static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ){ subpicture_t *p_spu; block_t *p_block; if( !pp_block || *pp_block == NULL ) return NULL; p_block = *pp_block; if( p_block->i_rate != 0 ) p_block->i_length = p_block->i_length * p_block->i_rate / INPUT_RATE_DEFAULT; p_spu = ParseText( p_dec, p_block ); block_Release( p_block ); *pp_block = NULL; return p_spu;}/***************************************************************************** * CloseDecoder: clean up the decoder *****************************************************************************/static void CloseDecoder( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; if( p_sys->pp_ssa_styles ) { int i; for( i = 0; i < p_sys->i_ssa_styles; i++ ) { if( !p_sys->pp_ssa_styles[i] ) continue; free( p_sys->pp_ssa_styles[i]->psz_stylename ); free( p_sys->pp_ssa_styles[i]->font_style.psz_fontname ); free( p_sys->pp_ssa_styles[i] ); } TAB_CLEAN( p_sys->i_ssa_styles, p_sys->pp_ssa_styles ); } if( p_sys->pp_images ) { int i; for( i = 0; i < p_sys->i_images; i++ ) { if( !p_sys->pp_images[i] ) continue; if( p_sys->pp_images[i]->p_pic ) picture_Release( p_sys->pp_images[i]->p_pic ); free( p_sys->pp_images[i]->psz_filename ); free( p_sys->pp_images[i] ); } TAB_CLEAN( p_sys->i_images, p_sys->pp_images ); } free( p_sys );}/***************************************************************************** * ParseText: parse an text subtitle packet and send it to the video output *****************************************************************************/static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block ){ decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu = NULL; char *psz_subtitle = NULL; /* We cannot display a subpicture with no date */ if( p_block->i_pts == 0 ) { msg_Warn( p_dec, "subtitle without a date" ); return NULL; } /* Check validity of packet data */ /* An "empty" line containing only \0 can be used to force and ephemer picture from the screen */ if( p_block->i_buffer < 1 ) { msg_Warn( p_dec, "no subtitle data" ); return NULL; } /* Should be resiliant against bad subtitles */ psz_subtitle = strndup( (const char *)p_block->p_buffer, p_block->i_buffer ); if( psz_subtitle == NULL ) return NULL; /* USF Subtitles are mandated to be UTF-8 -- make sure it is */ if (EnsureUTF8( psz_subtitle ) == NULL) { msg_Err( p_dec, "USF subtitles must be in UTF-8 format.\n" "This stream contains USF subtitles which aren't." ); } /* Create the subpicture unit */ p_spu = p_dec->pf_spu_buffer_new( p_dec ); if( !p_spu ) { msg_Warn( p_dec, "can't get spu buffer" ); free( psz_subtitle ); return NULL; } p_spu->b_pausable = true; /* Decode USF strings */ p_spu->p_region = ParseUSFString( p_dec, psz_subtitle, p_spu ); p_spu->i_start = p_block->i_pts; p_spu->i_stop = p_block->i_pts + p_block->i_length; p_spu->b_ephemer = (p_block->i_length == 0); p_spu->b_absolute = false; p_spu->i_original_picture_width = p_sys->i_original_width; p_spu->i_original_picture_height = p_sys->i_original_height; free( psz_subtitle ); return p_spu;}static char *GrabAttributeValue( const char *psz_attribute, const char *psz_tag_start ){ if( psz_attribute && psz_tag_start ) { char *psz_tag_end = strchr( psz_tag_start, '>' ); char *psz_found = strcasestr( psz_tag_start, psz_attribute ); if( psz_found ) { psz_found += strlen( psz_attribute ); if(( *(psz_found++) == '=' ) && ( *(psz_found++) == '\"' )) { if( psz_found < psz_tag_end ) { int i_len = strcspn( psz_found, "\"" ); return strndup( psz_found, i_len ); } } } } return NULL;}static ssa_style_t *ParseStyle( decoder_sys_t *p_sys, char *psz_subtitle ){ ssa_style_t *p_style = NULL; char *psz_style = GrabAttributeValue( "style", psz_subtitle ); if( psz_style ) { int i; for( i = 0; i < p_sys->i_ssa_styles; i++ ) { if( !strcmp( p_sys->pp_ssa_styles[i]->psz_stylename, psz_style ) ) p_style = p_sys->pp_ssa_styles[i]; } free( psz_style ); } return p_style;}static int ParsePositionAttributeList( char *psz_subtitle, int *i_align, int *i_x, int *i_y ){ int i_mask = 0; char *psz_align = GrabAttributeValue( "alignment", psz_subtitle ); char *psz_margin_x = GrabAttributeValue( "horizontal-margin", psz_subtitle ); char *psz_margin_y = GrabAttributeValue( "vertical-margin", psz_subtitle ); /* -- UNSUPPORTED char *psz_relative = GrabAttributeValue( "relative-to", psz_subtitle ); char *psz_rotate_x = GrabAttributeValue( "rotate-x", psz_subtitle ); char *psz_rotate_y = GrabAttributeValue( "rotate-y", psz_subtitle ); char *psz_rotate_z = GrabAttributeValue( "rotate-z", psz_subtitle ); */ *i_align = SUBPICTURE_ALIGN_BOTTOM; *i_x = 0; *i_y = 0; if( psz_align ) { if( !strcasecmp( "TopLeft", psz_align ) ) *i_align = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT; else if( !strcasecmp( "TopCenter", psz_align ) ) *i_align = SUBPICTURE_ALIGN_TOP; else if( !strcasecmp( "TopRight", psz_align ) ) *i_align = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_RIGHT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -