~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/codec/subtitles/subsass.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * subsass.c : ASS/SSA subtitles decoder
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2000-2006 the VideoLAN team
 
5
 * $Id$
 
6
 *
 
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
 
8
 *          Samuel Hocevar <sam@zoy.org>
 
9
 *          Derk-Jan Hartman <hartman at videolan dot org>
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 
24
 *****************************************************************************/
 
25
#ifdef HAVE_CONFIG_H
 
26
# include "config.h"
 
27
#endif
 
28
 
 
29
#include "subsdec.h"
 
30
 
 
31
 
 
32
void ParseSSAString( decoder_t *p_dec,
 
33
                     char *psz_subtitle,
 
34
                     subpicture_t *p_spu_in )
 
35
{
 
36
    /* We expect MKV formatted SSA:
 
37
     * ReadOrder, Layer, Style, CharacterName, MarginL, MarginR,
 
38
     * MarginV, Effect, Text */
 
39
    decoder_sys_t   *p_sys = p_dec->p_sys;
 
40
    subpicture_t    *p_spu = p_spu_in;
 
41
    ssa_style_t     *p_style = NULL;
 
42
    char            *psz_new_subtitle = NULL;
 
43
    char            *psz_buffer_sub = NULL;
 
44
    char            *psz_style = NULL;
 
45
    char            *psz_style_start = NULL;
 
46
    char            *psz_style_end = NULL;
 
47
    int             i_text = 0, i_comma = 0, i_strlen = 0, i;
 
48
    int             i_margin_l = 0, i_margin_r = 0, i_margin_v = 0;
 
49
 
 
50
    psz_buffer_sub = psz_subtitle;
 
51
 
 
52
    p_spu->p_region->psz_html = NULL;
 
53
 
 
54
    i_comma = 0;
 
55
    while( i_comma < 8 && *psz_buffer_sub != '\0' )
 
56
    {
 
57
        if( *psz_buffer_sub == ',' )
 
58
        {
 
59
            i_comma++;
 
60
            if( i_comma == 2 )
 
61
                psz_style_start = &psz_buffer_sub[1];
 
62
            else if( i_comma == 3 )
 
63
                psz_style_end = &psz_buffer_sub[0];
 
64
            else if( i_comma == 4 )
 
65
                i_margin_l = (int)strtol( &psz_buffer_sub[1], NULL, 10 );
 
66
            else if( i_comma == 5 )
 
67
                i_margin_r = (int)strtol( &psz_buffer_sub[1], NULL, 10 );
 
68
            else if( i_comma == 6 )
 
69
                i_margin_v = (int)strtol( &psz_buffer_sub[1], NULL, 10 );
 
70
        }
 
71
        psz_buffer_sub++;
 
72
    }
 
73
 
 
74
    if( *psz_buffer_sub == '\0' && i_comma == 8 )
 
75
    {
 
76
        msg_Dbg( p_dec, "couldn't find all fields in this SSA line" );
 
77
        return;
 
78
    }
 
79
 
 
80
    psz_new_subtitle = malloc( strlen( psz_buffer_sub ) + 1);
 
81
    i_text = 0;
 
82
    while( psz_buffer_sub[0] != '\0' )
 
83
    {
 
84
        if( psz_buffer_sub[0] == '\\' && psz_buffer_sub[1] == 'n' )
 
85
        {
 
86
            psz_new_subtitle[i_text] = ' ';
 
87
            i_text++;
 
88
            psz_buffer_sub += 2;
 
89
        }
 
90
        else if( psz_buffer_sub[0] == '\\' && psz_buffer_sub[1] == 'N' )
 
91
        {
 
92
            psz_new_subtitle[i_text] = '\n';
 
93
            i_text++;
 
94
            psz_buffer_sub += 2;
 
95
        }
 
96
        else if( psz_buffer_sub[0] == '{' &&
 
97
                 psz_buffer_sub[1] == '\\' )
 
98
        {
 
99
            /* SSA control code */
 
100
            while( psz_buffer_sub[0] != '\0' &&
 
101
                   psz_buffer_sub[0] != '}' )
 
102
            {
 
103
                psz_buffer_sub++;
 
104
            }
 
105
            psz_buffer_sub++;
 
106
        }
 
107
        else
 
108
        {
 
109
            psz_new_subtitle[i_text] = psz_buffer_sub[0];
 
110
            i_text++;
 
111
            psz_buffer_sub++;
 
112
        }
 
113
    }
 
114
    psz_new_subtitle[i_text] = '\0';
 
115
 
 
116
    i_strlen = __MAX( psz_style_end - psz_style_start, 0);
 
117
    psz_style = strndup( psz_style_start, i_strlen );
 
118
 
 
119
    for( i = 0; i < p_sys->i_ssa_styles; i++ )
 
120
    {
 
121
        if( !strcmp( p_sys->pp_ssa_styles[i]->psz_stylename, psz_style ) )
 
122
            p_style = p_sys->pp_ssa_styles[i];
 
123
    }
 
124
    free( psz_style );
 
125
 
 
126
    p_spu->p_region->psz_text = psz_new_subtitle;
 
127
    if( p_style == NULL )
 
128
    {
 
129
        p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM | p_sys->i_align;
 
130
        p_spu->i_x = p_sys->i_align ? 20 : 0;
 
131
        p_spu->i_y = 10;
 
132
    }
 
133
    else
 
134
    {
 
135
        msg_Dbg( p_dec, "style is: %s", p_style->psz_stylename);
 
136
        p_spu->p_region->p_style = &p_style->font_style;
 
137
        p_spu->p_region->i_align = p_style->i_align;
 
138
        if( p_style->i_align & SUBPICTURE_ALIGN_LEFT )
 
139
        {
 
140
            p_spu->i_x = (i_margin_l) ? i_margin_l : p_style->i_margin_h;
 
141
        }
 
142
        else if( p_style->i_align & SUBPICTURE_ALIGN_RIGHT )
 
143
        {
 
144
            p_spu->i_x = (i_margin_r) ? i_margin_r : p_style->i_margin_h;
 
145
        }
 
146
        p_spu->i_y = (i_margin_v) ? i_margin_v : p_style->i_margin_v;
 
147
    }
 
148
}
 
149
 
 
150
/*****************************************************************************
 
151
 * ParseColor: SSA stores color in BBGGRR, in ASS it uses AABBGGRR
 
152
 * The string value in the string can be a pure integer, or hexadecimal &HBBGGRR
 
153
 *****************************************************************************/
 
154
static void ParseColor( char *psz_color, int *pi_color, int *pi_alpha )
 
155
{
 
156
    int i_color = 0;
 
157
    if( !strncasecmp( psz_color, "&H", 2 ) )
 
158
    {
 
159
        /* textual HEX representation */
 
160
        i_color = (int) strtol( psz_color+2, NULL, 16 );
 
161
    }
 
162
    else i_color = (int) strtol( psz_color, NULL, 0 );
 
163
 
 
164
    *pi_color = 0;
 
165
    *pi_color |= ( ( i_color & 0x000000FF ) << 16 ); /* Red */
 
166
    *pi_color |= ( ( i_color & 0x0000FF00 ) );       /* Green */
 
167
    *pi_color |= ( ( i_color & 0x00FF0000 ) >> 16 ); /* Blue */
 
168
 
 
169
    if( pi_alpha != NULL )
 
170
        *pi_alpha = ( i_color & 0xFF000000 ) >> 24;
 
171
}
 
172
 
 
173
/*****************************************************************************
 
174
 * ParseSSAHeader: Retrieve global formatting information etc
 
175
 *****************************************************************************/
 
176
void ParseSSAHeader( decoder_t *p_dec )
 
177
{
 
178
    decoder_sys_t *p_sys = p_dec->p_sys;
 
179
    char *psz_parser = NULL;
 
180
    char *psz_header = malloc( p_dec->fmt_in.i_extra+1 );
 
181
    int i_section_type = 1;
 
182
 
 
183
    memcpy( psz_header, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
 
184
    psz_header[ p_dec->fmt_in.i_extra] = '\0';
 
185
 
 
186
    /* Handle [Script Info] section */
 
187
    psz_parser = strcasestr( psz_header, "[Script Info]" );
 
188
    if( psz_parser == NULL ) goto eof;
 
189
 
 
190
    psz_parser = GotoNextLine( psz_parser );
 
191
 
 
192
    while( psz_parser[0] != '\0' )
 
193
    {
 
194
        int temp;
 
195
        char buffer_text[MAX_LINE + 1];
 
196
 
 
197
        if( psz_parser[0] == '!' || psz_parser[0] == ';' ) /* comment */;
 
198
        else if( sscanf( psz_parser, "PlayResX: %d", &temp ) == 1 )
 
199
            p_sys->i_original_width = ( temp > 0 ) ? temp : -1;
 
200
        else if( sscanf( psz_parser, "PlayResY: %d", &temp ) == 1 )
 
201
            p_sys->i_original_height = ( temp > 0 ) ? temp : -1;
 
202
        else if( sscanf( psz_parser, "Script Type: %8192s", buffer_text ) == 1 )
 
203
        {
 
204
            if( !strcasecmp( buffer_text, "V4.00+" ) ) p_sys->b_ass = true;
 
205
        }
 
206
        else if( !strncasecmp( psz_parser, "[V4 Styles]", 11 ) )
 
207
            i_section_type = 1;
 
208
        else if( !strncasecmp( psz_parser, "[V4+ Styles]", 12) )
 
209
        {
 
210
            i_section_type = 2;
 
211
            p_sys->b_ass = true;
 
212
        }
 
213
        else if( !strncasecmp( psz_parser, "[Events]", 8 ) )
 
214
            i_section_type = 4;
 
215
        else if( !strncasecmp( psz_parser, "Style:", 6 ) )
 
216
        {
 
217
            int i_font_size, i_bold, i_italic, i_border, i_outline, i_shadow,
 
218
                i_underline, i_strikeout, i_scale_x, i_scale_y, i_spacing,
 
219
                i_align, i_margin_l, i_margin_r, i_margin_v;
 
220
 
 
221
            char psz_temp_stylename[MAX_LINE+1];
 
222
            char psz_temp_fontname[MAX_LINE+1];
 
223
            char psz_temp_color1[MAX_LINE+1];
 
224
            char psz_temp_color2[MAX_LINE+1];
 
225
            char psz_temp_color3[MAX_LINE+1];
 
226
            char psz_temp_color4[MAX_LINE+1];
 
227
 
 
228
            if( i_section_type == 1 ) /* V4 */
 
229
            {
 
230
                if( sscanf( psz_parser, "Style: %8192[^,],%8192[^,],%d,%8192[^,],%8192[^,],%8192[^,],%8192[^,],%d,%d,%d,%d,%d,%d,%d,%d,%d%*[^\r\n]",
 
231
                    psz_temp_stylename, psz_temp_fontname, &i_font_size,
 
232
                    psz_temp_color1, psz_temp_color2, psz_temp_color3,
 
233
                    psz_temp_color4, &i_bold, &i_italic,
 
234
                    &i_border, &i_outline, &i_shadow, &i_align, &i_margin_l,
 
235
                    &i_margin_r, &i_margin_v ) == 16 )
 
236
                {
 
237
                    ssa_style_t *p_style = malloc( sizeof(ssa_style_t) );
 
238
 
 
239
                    p_style->psz_stylename = strdup( psz_temp_stylename );
 
240
                    p_style->font_style.psz_fontname = strdup( psz_temp_fontname );
 
241
                    p_style->font_style.i_font_size = i_font_size;
 
242
 
 
243
                    ParseColor( psz_temp_color1, &p_style->font_style.i_font_color, NULL );
 
244
                    ParseColor( psz_temp_color4, &p_style->font_style.i_shadow_color, NULL );
 
245
                    p_style->font_style.i_outline_color = p_style->font_style.i_shadow_color;
 
246
                    p_style->font_style.i_font_alpha = p_style->font_style.i_outline_alpha
 
247
                                                     = p_style->font_style.i_shadow_alpha = 0x00;
 
248
                    p_style->font_style.i_style_flags = 0;
 
249
                    if( i_bold ) p_style->font_style.i_style_flags |= STYLE_BOLD;
 
250
                    if( i_italic ) p_style->font_style.i_style_flags |= STYLE_ITALIC;
 
251
 
 
252
                    if( i_border == 1 )
 
253
                        p_style->font_style.i_style_flags |= (STYLE_ITALIC | STYLE_OUTLINE);
 
254
                    else if( i_border == 3 )
 
255
                    {
 
256
                        p_style->font_style.i_style_flags |= STYLE_BACKGROUND;
 
257
                        p_style->font_style.i_background_color = p_style->font_style.i_shadow_color;
 
258
                        p_style->font_style.i_background_alpha = p_style->font_style.i_shadow_alpha;
 
259
                    }
 
260
                    p_style->font_style.i_shadow_width = i_shadow;
 
261
                    p_style->font_style.i_outline_width = i_outline;
 
262
 
 
263
                    p_style->i_align = 0;
 
264
                    if( i_align == 1 || i_align == 5 || i_align == 9 )
 
265
                        p_style->i_align |= SUBPICTURE_ALIGN_LEFT;
 
266
                    if( i_align == 3 || i_align == 7 || i_align == 11 )
 
267
                        p_style->i_align |= SUBPICTURE_ALIGN_RIGHT;
 
268
                    if( i_align < 4 )
 
269
                        p_style->i_align |= SUBPICTURE_ALIGN_BOTTOM;
 
270
                    else if( i_align < 8 )
 
271
                        p_style->i_align |= SUBPICTURE_ALIGN_TOP;
 
272
 
 
273
                    p_style->i_margin_h = ( p_style->i_align & SUBPICTURE_ALIGN_RIGHT ) ?
 
274
                                                        i_margin_r : i_margin_l;
 
275
                    p_style->i_margin_v = i_margin_v;
 
276
                    p_style->i_margin_percent_h = 0;
 
277
                    p_style->i_margin_percent_v = 0;
 
278
 
 
279
                    p_style->font_style.i_karaoke_background_color = 0xffffff;
 
280
                    p_style->font_style.i_karaoke_background_alpha = 0xff;
 
281
 
 
282
                    TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_style );
 
283
                }
 
284
                else msg_Warn( p_dec, "SSA v4 styleline parsing failed" );
 
285
            }
 
286
            else if( i_section_type == 2 ) /* V4+ */
 
287
            {
 
288
                /* Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour,
 
289
                   Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline,
 
290
                   Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
 
291
                */
 
292
                if( sscanf( psz_parser, "Style: %8192[^,],%8192[^,],%d,%8192[^,],%8192[^,],%8192[^,],%8192[^,],%d,%d,%d,%d,%d,%d,%d,%*f,%d,%d,%d,%d,%d,%d,%d%*[^\r\n]",
 
293
                    psz_temp_stylename, psz_temp_fontname, &i_font_size,
 
294
                    psz_temp_color1, psz_temp_color2, psz_temp_color3, psz_temp_color4, &i_bold, &i_italic,
 
295
                    &i_underline, &i_strikeout, &i_scale_x, &i_scale_y, &i_spacing, &i_border, &i_outline,
 
296
                    &i_shadow, &i_align, &i_margin_l, &i_margin_r, &i_margin_v ) == 21 )
 
297
                {
 
298
                    ssa_style_t *p_style = malloc( sizeof(ssa_style_t) );
 
299
 
 
300
                    p_style->psz_stylename = strdup( psz_temp_stylename );
 
301
                    p_style->font_style.psz_fontname = strdup( psz_temp_fontname );
 
302
                    p_style->font_style.i_font_size = i_font_size;
 
303
                    ParseColor( psz_temp_color1, &p_style->font_style.i_font_color,
 
304
                                &p_style->font_style.i_font_alpha );
 
305
                    ParseColor( psz_temp_color3, &p_style->font_style.i_outline_color,
 
306
                                &p_style->font_style.i_outline_alpha );
 
307
                    ParseColor( psz_temp_color4, &p_style->font_style.i_shadow_color,
 
308
                                &p_style->font_style.i_shadow_alpha );
 
309
 
 
310
                    p_style->font_style.i_style_flags = 0;
 
311
                    if( i_bold ) p_style->font_style.i_style_flags |= STYLE_BOLD;
 
312
                    if( i_italic ) p_style->font_style.i_style_flags |= STYLE_ITALIC;
 
313
                    if( i_underline ) p_style->font_style.i_style_flags |= STYLE_UNDERLINE;
 
314
                    if( i_strikeout ) p_style->font_style.i_style_flags |= STYLE_STRIKEOUT;
 
315
                    if( i_border == 1 ) p_style->font_style.i_style_flags |= (STYLE_ITALIC | STYLE_OUTLINE);
 
316
                    else if( i_border == 3 )
 
317
                    {
 
318
                        p_style->font_style.i_style_flags |= STYLE_BACKGROUND;
 
319
                        p_style->font_style.i_background_color = p_style->font_style.i_shadow_color;
 
320
                        p_style->font_style.i_background_alpha = p_style->font_style.i_shadow_alpha;
 
321
                    }
 
322
                    p_style->font_style.i_shadow_width  = ( i_border == 1 ) ? i_shadow : 0;
 
323
                    p_style->font_style.i_outline_width = ( i_border == 1 ) ? i_outline : 0;
 
324
                    p_style->font_style.i_spacing = i_spacing;
 
325
                    //p_style->font_style.f_angle = f_angle;
 
326
 
 
327
                    p_style->i_align = 0;
 
328
                    if( i_align == 0x1 || i_align == 0x4 || i_align == 0x7 )
 
329
                        p_style->i_align |= SUBPICTURE_ALIGN_LEFT;
 
330
                    if( i_align == 0x3 || i_align == 0x6 || i_align == 0x9 )
 
331
                        p_style->i_align |= SUBPICTURE_ALIGN_RIGHT;
 
332
                    if( i_align == 0x7 || i_align == 0x8 || i_align == 0x9 )
 
333
                        p_style->i_align |= SUBPICTURE_ALIGN_TOP;
 
334
                    if( i_align == 0x1 || i_align == 0x2 || i_align == 0x3 )
 
335
                        p_style->i_align |= SUBPICTURE_ALIGN_BOTTOM;
 
336
                    p_style->i_margin_h = ( p_style->i_align & SUBPICTURE_ALIGN_RIGHT ) ?
 
337
                                            i_margin_r : i_margin_l;
 
338
                    p_style->i_margin_v = i_margin_v;
 
339
                    p_style->i_margin_percent_h = 0;
 
340
                    p_style->i_margin_percent_v = 0;
 
341
 
 
342
                    p_style->font_style.i_karaoke_background_color = 0xffffff;
 
343
                    p_style->font_style.i_karaoke_background_alpha = 0xff;
 
344
 
 
345
                    /*TODO: Ignored: angle i_scale_x|y (fontscaling), i_encoding */
 
346
                    TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_style );
 
347
                }
 
348
                else msg_Dbg( p_dec, "SSA V4+ styleline parsing failed" );
 
349
            }
 
350
        }
 
351
        psz_parser = GotoNextLine( psz_parser );
 
352
    }
 
353
 
 
354
eof:
 
355
    free( psz_header );
 
356
    return;
 
357
}
 
358
 
 
359