X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fsubsdec.c;h=93547c46990464820bcf8b5cf860116435edc8c6;hb=50b658157c6d80cc1a9a5e0e1eae28a94d42e420;hp=dd9115e7a02c9702186a602abd1451eb894bc1ad;hpb=354c7ab964f7e4bcc31a39ed0358b7f8c1135d38;p=vlc diff --git a/modules/codec/subsdec.c b/modules/codec/subsdec.c index dd9115e7a0..93547c4699 100644 --- a/modules/codec/subsdec.c +++ b/modules/codec/subsdec.c @@ -2,7 +2,7 @@ * subsdec.c : text subtitles decoder ***************************************************************************** * Copyright (C) 2000-2001 VideoLAN - * $Id: subsdec.c,v 1.4 2003/11/05 00:17:50 hartman Exp $ + * $Id$ * * Authors: Gildas Bazin * Samuel Hocevar @@ -25,14 +25,11 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include /* memcpy(), memset() */ - #include #include #include + #include -#include #if defined(HAVE_ICONV) #include @@ -56,12 +53,12 @@ struct decoder_sys_t * Local prototypes *****************************************************************************/ static int OpenDecoder ( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void DecodeBlock ( decoder_t *, block_t ** ); static void ParseText ( decoder_t *, block_t *, vout_thread_t * ); +static void StripTags ( char * ); #define DEFAULT_NAME "System Default" @@ -89,23 +86,29 @@ static char *ppsz_encodings[] = { DEFAULT_NAME, "ASCII", "UTF-8", "", "C99", "JAVA", "UCS-2", "UCS-2BE", "UCS-2LE", "UCS-4", "UCS-4BE", "UCS-4LE", "", "HZ", "GBK", "GB18030", "JOHAB", "ARMSCII-8", "Georgian-Academy", "Georgian-PS", "TIS-620", "MuleLao-1", "VISCII", "TCVN", - "HPROMAN8", "NEXTSTEP", NULL }; + "HPROMAN8", "NEXTSTEP" }; #endif +static int pi_justification[] = { 0, 1, 2 }; +static char *ppsz_justification_text[] = {N_("Center"),N_("Left"),N_("Right")}; + #define ENCODING_TEXT N_("Subtitles text encoding") -#define ENCODING_LONGTEXT N_("Change the encoding used in text subtitles") +#define ENCODING_LONGTEXT N_("Set the encoding used in text subtitles") #define ALIGN_TEXT N_("Subtitles justification") -#define ALIGN_LONGTEXT N_("Change the justification of substitles (0=center, 1=left, 2=right)") +#define ALIGN_LONGTEXT N_("Set the justification of subtitles") vlc_module_begin(); set_description( _("text subtitles decoder") ); set_capability( "decoder", 50 ); - set_callbacks( OpenDecoder, NULL ); + set_callbacks( OpenDecoder, CloseDecoder ); - add_category_hint( N_("Subtitles"), NULL, VLC_FALSE ); - add_integer( "subsdec-align", 0, NULL, ALIGN_TEXT, ALIGN_LONGTEXT, VLC_TRUE ); + add_integer( "subsdec-align", 0, NULL, ALIGN_TEXT, ALIGN_LONGTEXT, + VLC_TRUE ); + change_integer_list( pi_justification, ppsz_justification_text, 0 ); #if defined(HAVE_ICONV) - add_string_from_list( "subsdec-encoding", DEFAULT_NAME, ppsz_encodings, NULL, ENCODING_TEXT, ENCODING_LONGTEXT, VLC_FALSE ); + add_string( "subsdec-encoding", DEFAULT_NAME, NULL, + ENCODING_TEXT, ENCODING_LONGTEXT, VLC_FALSE ); + change_string_list( ppsz_encodings, 0, 0 ); #endif vlc_module_end(); @@ -117,104 +120,108 @@ vlc_module_end(); *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { - decoder_t *p_dec = (decoder_t*)p_this; + decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; + vlc_value_t val; - if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','u','b','t') && - p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','s','a',' ') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','u','b','t') && + p_dec->fmt_in.i_codec != VLC_FOURCC('s','s','a',' ') ) { return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; + p_dec->pf_decode_sub = DecodeBlock; /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - return VLC_SUCCESS; -} - -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - subtitle_data_t *p_demux_data = (subtitle_data_t *)p_dec->p_fifo->p_demux_data; - vlc_value_t val; - 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; #if defined(HAVE_ICONV) - var_Create( p_dec, "subsdec-encoding", - VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Get( p_dec, "subsdec-encoding", &val ); - if( !strcmp( val.psz_string, DEFAULT_NAME ) ) + if( p_dec->fmt_in.subs.psz_encoding && *p_dec->fmt_in.subs.psz_encoding ) { - char *psz_charset =(char*)malloc( 100 ); - vlc_current_charset( &psz_charset ); - p_sys->iconv_handle = iconv_open( "UTF-8", psz_charset ); - free( psz_charset ); + msg_Dbg( p_dec, "using character encoding: %s", + p_dec->fmt_in.subs.psz_encoding ); + p_sys->iconv_handle = iconv_open( "UTF-8", + p_dec->fmt_in.subs.psz_encoding ); } else { - p_sys->iconv_handle = iconv_open( "UTF-8", val.psz_string ); - } + var_Create( p_dec, "subsdec-encoding", + VLC_VAR_STRING | VLC_VAR_DOINHERIT ); + var_Get( p_dec, "subsdec-encoding", &val ); + if( !strcmp( val.psz_string, DEFAULT_NAME ) ) + { + char *psz_charset =(char*)malloc( 100 ); + vlc_current_charset( &psz_charset ); + p_sys->iconv_handle = iconv_open( "UTF-8", psz_charset ); + msg_Dbg( p_dec, "using character encoding: %s", psz_charset ); + free( psz_charset ); + } + else if( val.psz_string ) + { + msg_Dbg( p_dec, "using character encoding: %s", val.psz_string ); + p_sys->iconv_handle = iconv_open( "UTF-8", val.psz_string ); + } - if( p_sys->iconv_handle == (iconv_t)-1 ) - { - msg_Warn( p_dec, "Unable to do requested conversion" ); - } + if( p_sys->iconv_handle == (iconv_t)-1 ) + { + msg_Warn( p_dec, "unable to do requested conversion" ); + } - if( val.psz_string ) free( val.psz_string ); + if( val.psz_string ) free( val.psz_string ); + } #else - msg_Dbg( p_dec, "No iconv support available" ); -#endif -#if 1 - if( p_demux_data ) - msg_Dbg( p_dec, p_demux_data->psz_header ); + msg_Dbg( p_dec, "no iconv support available" ); #endif return VLC_SUCCESS; } /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with complete subtitles units. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { vout_thread_t *p_vout; + if( !pp_block || *pp_block == NULL ) + { + return; + } + /* Here we are dealing with text subtitles */ p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); - if( !p_vout ) + if( p_vout ) + { + ParseText( p_dec, *pp_block, p_vout ); + vlc_object_release( p_vout ); + } + else { msg_Warn( p_dec, "couldn't find a video output, trashing subtitle" ); - return VLC_SUCCESS; } - ParseText( p_dec, p_block, p_vout ); - vlc_object_release( p_vout ); - - return VLC_SUCCESS; + block_Release( *pp_block ); + *pp_block = NULL; } /***************************************************************************** - * EndDecoder: clean up the decoder + * CloseDecoder: clean up the decoder *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) +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; vout_thread_t *p_vout; @@ -246,8 +253,6 @@ static int EndDecoder( decoder_t *p_dec ) #endif free( p_sys ); - - return VLC_SUCCESS; } /***************************************************************************** @@ -266,7 +271,7 @@ static void ParseText( decoder_t *p_dec, block_t *p_block, msg_Warn( p_dec, "subtitle without a date" ); return; } - + /* Check validity of packet data */ if( p_block->i_buffer <= 1 || p_block->p_buffer[0] == '\0' ) { @@ -285,7 +290,7 @@ static void ParseText( decoder_t *p_dec, block_t *p_block, { char *psz_new_subtitle; char *psz_convert_buffer_out; - const char *psz_convert_buffer_in; + char *psz_convert_buffer_in; size_t ret, inbytes_left, outbytes_left; psz_new_subtitle = malloc( 6 * strlen( psz_subtitle ) ); @@ -299,7 +304,9 @@ static void ParseText( decoder_t *p_dec, block_t *p_block, if( inbytes_left ) { - msg_Warn( p_dec, "Something fishy happened during conversion" ); + msg_Warn( p_dec, "Failed to convert subtitle encoding, dropping subtitle.\nTry setting a different character-encoding for the subtitle." ); + free( psz_subtitle ); + return; } else { @@ -309,7 +316,7 @@ static void ParseText( decoder_t *p_dec, block_t *p_block, } #endif - if( p_dec->p_fifo->i_fourcc == VLC_FOURCC('s','s','a',' ') ) + if( p_dec->fmt_in.i_codec == VLC_FOURCC('s','s','a',' ') ) { /* Decode SSA strings */ /* We expect: ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text */ @@ -363,11 +370,55 @@ static void ParseText( decoder_t *p_dec, block_t *p_block, break; } } - - vout_ShowTextAbsolute( p_vout, psz_subtitle, NULL, - OSD_ALIGN_BOTTOM | p_sys->i_align, - i_align_h, i_align_v, - p_block->i_pts, p_block->i_dts ); + StripTags( psz_subtitle ); + vout_ShowTextAbsolute( p_vout, SUBT1_CHAN, psz_subtitle, NULL, + OSD_ALIGN_BOTTOM | p_sys->i_align, i_align_h, + i_align_v, p_block->i_pts, + p_block->i_length ? p_block->i_pts + p_block->i_length : 0 ); free( psz_subtitle ); } + +static void StripTags( char *psz_text ) +{ + int i_left_moves = 0; + vlc_bool_t b_inside_tag = VLC_FALSE; + int i = 0; + int i_tag_start = -1; + while( psz_text[ i ] ) + { + if( !b_inside_tag ) + { + if( psz_text[ i ] == '<' ) + { + b_inside_tag = VLC_TRUE; + i_tag_start = i; + } + psz_text[ i - i_left_moves ] = psz_text[ i ]; + } + else + { + if( ( psz_text[ i ] == ' ' ) || + ( psz_text[ i ] == '\t' ) || + ( psz_text[ i ] == '\n' ) || + ( psz_text[ i ] == '\r' ) ) + { + b_inside_tag = VLC_FALSE; + i_tag_start = -1; + } + else if( psz_text[ i ] == '>' ) + { + i_left_moves += i - i_tag_start + 1; + i_tag_start = -1; + b_inside_tag = VLC_FALSE; + } + else + { + psz_text[ i - i_left_moves ] = psz_text[ i ]; + } + } + i++; + } + psz_text[ i - i_left_moves ] = '\0'; +} +