subsass.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:16k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * subsass.c : ASS/SSA subtitles decoder
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2006 the VideoLAN team
  5.  * $Id: e642673288c6426079a4a1cf27c6679268fa018e $
  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. #include "subsdec.h"
  29. void ParseSSAString( decoder_t *p_dec,
  30.                      char *psz_subtitle,
  31.                      subpicture_t *p_spu_in )
  32. {
  33.     /* We expect MKV formatted SSA:
  34.      * ReadOrder, Layer, Style, CharacterName, MarginL, MarginR,
  35.      * MarginV, Effect, Text */
  36.     decoder_sys_t   *p_sys = p_dec->p_sys;
  37.     subpicture_t    *p_spu = p_spu_in;
  38.     ssa_style_t     *p_style = NULL;
  39.     char            *psz_new_subtitle = NULL;
  40.     char            *psz_buffer_sub = NULL;
  41.     char            *psz_style = NULL;
  42.     char            *psz_style_start = NULL;
  43.     char            *psz_style_end = NULL;
  44.     int             i_text = 0, i_comma = 0, i_strlen = 0, i;
  45.     int             i_margin_l = 0, i_margin_r = 0, i_margin_v = 0;
  46.     psz_buffer_sub = psz_subtitle;
  47.     p_spu->p_region->psz_html = NULL;
  48.     i_comma = 0;
  49.     while( i_comma < 8 && *psz_buffer_sub != '' )
  50.     {
  51.         if( *psz_buffer_sub == ',' )
  52.         {
  53.             i_comma++;
  54.             if( i_comma == 2 )
  55.                 psz_style_start = &psz_buffer_sub[1];
  56.             else if( i_comma == 3 )
  57.                 psz_style_end = &psz_buffer_sub[0];
  58.             else if( i_comma == 4 )
  59.                 i_margin_l = (int)strtol( &psz_buffer_sub[1], NULL, 10 );
  60.             else if( i_comma == 5 )
  61.                 i_margin_r = (int)strtol( &psz_buffer_sub[1], NULL, 10 );
  62.             else if( i_comma == 6 )
  63.                 i_margin_v = (int)strtol( &psz_buffer_sub[1], NULL, 10 );
  64.         }
  65.         psz_buffer_sub++;
  66.     }
  67.     if( *psz_buffer_sub == '' && i_comma == 8 )
  68.     {
  69.         msg_Dbg( p_dec, "couldn't find all fields in this SSA line" );
  70.         return;
  71.     }
  72.     psz_new_subtitle = malloc( strlen( psz_buffer_sub ) + 1);
  73.     i_text = 0;
  74.     while( psz_buffer_sub[0] != '' )
  75.     {
  76.         if( psz_buffer_sub[0] == '\' && psz_buffer_sub[1] == 'n' )
  77.         {
  78.             psz_new_subtitle[i_text] = ' ';
  79.             i_text++;
  80.             psz_buffer_sub += 2;
  81.         }
  82.         else if( psz_buffer_sub[0] == '\' && psz_buffer_sub[1] == 'N' )
  83.         {
  84.             psz_new_subtitle[i_text] = 'n';
  85.             i_text++;
  86.             psz_buffer_sub += 2;
  87.         }
  88.         else if( psz_buffer_sub[0] == '{' )
  89.         {
  90.             /* { } Control code in SSA. Cannot be escaped */
  91.             while( psz_buffer_sub[0] != '' &&
  92.                    psz_buffer_sub[0] != '}' )
  93.             {
  94.                 psz_buffer_sub++;
  95.             }
  96.             if( psz_buffer_sub[0] == '}' ) psz_buffer_sub++;
  97.         }
  98.         else
  99.         {
  100.             psz_new_subtitle[i_text] = psz_buffer_sub[0];
  101.             i_text++;
  102.             psz_buffer_sub++;
  103.         }
  104.     }
  105.     psz_new_subtitle[i_text] = '';
  106.     i_strlen = __MAX( psz_style_end - psz_style_start, 0);
  107.     psz_style = strndup( psz_style_start, i_strlen );
  108.     for( i = 0; i < p_sys->i_ssa_styles; i++ )
  109.     {
  110.         if( !strcmp( p_sys->pp_ssa_styles[i]->psz_stylename, psz_style ) )
  111.             p_style = p_sys->pp_ssa_styles[i];
  112.     }
  113.     free( psz_style );
  114.     p_spu->p_region->psz_text = psz_new_subtitle;
  115.     if( p_style == NULL )
  116.     {
  117.         p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM | p_sys->i_align;
  118.         p_spu->p_region->i_x = p_sys->i_align ? 20 : 0;
  119.         p_spu->p_region->i_y = 10;
  120.     }
  121.     else
  122.     {
  123.         msg_Dbg( p_dec, "style is: %s", p_style->psz_stylename);
  124.         p_spu->p_region->p_style = &p_style->font_style;
  125.         p_spu->p_region->i_align = p_style->i_align;
  126.         if( p_style->i_align & SUBPICTURE_ALIGN_LEFT )
  127.         {
  128.             p_spu->p_region->i_x = (i_margin_l) ? i_margin_l : p_style->i_margin_h;
  129.         }
  130.         else if( p_style->i_align & SUBPICTURE_ALIGN_RIGHT )
  131.         {
  132.             p_spu->p_region->i_x = (i_margin_r) ? i_margin_r : p_style->i_margin_h;
  133.         }
  134.         p_spu->p_region->i_y = (i_margin_v) ? i_margin_v : p_style->i_margin_v;
  135.     }
  136. }
  137. /*****************************************************************************
  138.  * ParseColor: SSA stores color in BBGGRR, in ASS it uses AABBGGRR
  139.  * The string value in the string can be a pure integer, or hexadecimal &HBBGGRR
  140.  *****************************************************************************/
  141. static void ParseColor( char *psz_color, int *pi_color, int *pi_alpha )
  142. {
  143.     int i_color = 0;
  144.     if( !strncasecmp( psz_color, "&H", 2 ) )
  145.     {
  146.         /* textual HEX representation */
  147.         i_color = (int) strtol( psz_color+2, NULL, 16 );
  148.     }
  149.     else i_color = (int) strtol( psz_color, NULL, 0 );
  150.     *pi_color = 0;
  151.     *pi_color |= ( ( i_color & 0x000000FF ) << 16 ); /* Red */
  152.     *pi_color |= ( ( i_color & 0x0000FF00 ) );       /* Green */
  153.     *pi_color |= ( ( i_color & 0x00FF0000 ) >> 16 ); /* Blue */
  154.     if( pi_alpha != NULL )
  155.         *pi_alpha = ( i_color & 0xFF000000 ) >> 24;
  156. }
  157. /*****************************************************************************
  158.  * ParseSSAHeader: Retrieve global formatting information etc
  159.  *****************************************************************************/
  160. void ParseSSAHeader( decoder_t *p_dec )
  161. {
  162.     decoder_sys_t *p_sys = p_dec->p_sys;
  163.     char *psz_parser = NULL;
  164.     char *psz_header = malloc( p_dec->fmt_in.i_extra+1 );
  165.     int i_section_type = 1;
  166.     memcpy( psz_header, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
  167.     psz_header[ p_dec->fmt_in.i_extra] = '';
  168.     /* Handle [Script Info] section */
  169.     psz_parser = strcasestr( psz_header, "[Script Info]" );
  170.     if( psz_parser == NULL ) goto eof;
  171.     psz_parser = GotoNextLine( psz_parser );
  172.     while( psz_parser[0] != '' )
  173.     {
  174.         int temp;
  175.         char buffer_text[MAX_LINE + 1];
  176.         if( psz_parser[0] == '!' || psz_parser[0] == ';' ) /* comment */;
  177.         else if( sscanf( psz_parser, "PlayResX: %d", &temp ) == 1 )
  178.             p_sys->i_original_width = ( temp > 0 ) ? temp : -1;
  179.         else if( sscanf( psz_parser, "PlayResY: %d", &temp ) == 1 )
  180.             p_sys->i_original_height = ( temp > 0 ) ? temp : -1;
  181.         else if( sscanf( psz_parser, "Script Type: %8192s", buffer_text ) == 1 )
  182.         {
  183.             if( !strcasecmp( buffer_text, "V4.00+" ) ) p_sys->b_ass = true;
  184.         }
  185.         else if( !strncasecmp( psz_parser, "[V4 Styles]", 11 ) )
  186.             i_section_type = 1;
  187.         else if( !strncasecmp( psz_parser, "[V4+ Styles]", 12) )
  188.         {
  189.             i_section_type = 2;
  190.             p_sys->b_ass = true;
  191.         }
  192.         else if( !strncasecmp( psz_parser, "[Events]", 8 ) )
  193.             i_section_type = 4;
  194.         else if( !strncasecmp( psz_parser, "Style:", 6 ) )
  195.         {
  196.             int i_font_size, i_bold, i_italic, i_border, i_outline, i_shadow,
  197.                 i_underline, i_strikeout, i_scale_x, i_scale_y, i_spacing,
  198.                 i_align, i_margin_l, i_margin_r, i_margin_v;
  199.             char psz_temp_stylename[MAX_LINE+1];
  200.             char psz_temp_fontname[MAX_LINE+1];
  201.             char psz_temp_color1[MAX_LINE+1];
  202.             char psz_temp_color2[MAX_LINE+1];
  203.             char psz_temp_color3[MAX_LINE+1];
  204.             char psz_temp_color4[MAX_LINE+1];
  205.             if( i_section_type == 1 ) /* V4 */
  206.             {
  207.                 if( sscanf( psz_parser, "Style: %8192[^,],%8192[^,],%d,%8192[^,],%8192[^,],%8192[^,],%8192[^,],%d,%d,%d,%d,%d,%d,%d,%d,%d%*[^rn]",
  208.                     psz_temp_stylename, psz_temp_fontname, &i_font_size,
  209.                     psz_temp_color1, psz_temp_color2, psz_temp_color3,
  210.                     psz_temp_color4, &i_bold, &i_italic,
  211.                     &i_border, &i_outline, &i_shadow, &i_align, &i_margin_l,
  212.                     &i_margin_r, &i_margin_v ) == 16 )
  213.                 {
  214.                     ssa_style_t *p_style = malloc( sizeof(ssa_style_t) );
  215.                     p_style->psz_stylename = strdup( psz_temp_stylename );
  216.                     p_style->font_style.psz_fontname = strdup( psz_temp_fontname );
  217.                     p_style->font_style.i_font_size = i_font_size;
  218.                     ParseColor( psz_temp_color1, &p_style->font_style.i_font_color, NULL );
  219.                     ParseColor( psz_temp_color4, &p_style->font_style.i_shadow_color, NULL );
  220.                     p_style->font_style.i_outline_color = p_style->font_style.i_shadow_color;
  221.                     p_style->font_style.i_font_alpha = p_style->font_style.i_outline_alpha
  222.                                                      = p_style->font_style.i_shadow_alpha = 0x00;
  223.                     p_style->font_style.i_style_flags = 0;
  224.                     if( i_bold ) p_style->font_style.i_style_flags |= STYLE_BOLD;
  225.                     if( i_italic ) p_style->font_style.i_style_flags |= STYLE_ITALIC;
  226.                     if( i_border == 1 )
  227.                         p_style->font_style.i_style_flags |= (STYLE_ITALIC | STYLE_OUTLINE);
  228.                     else if( i_border == 3 )
  229.                     {
  230.                         p_style->font_style.i_style_flags |= STYLE_BACKGROUND;
  231.                         p_style->font_style.i_background_color = p_style->font_style.i_shadow_color;
  232.                         p_style->font_style.i_background_alpha = p_style->font_style.i_shadow_alpha;
  233.                     }
  234.                     p_style->font_style.i_shadow_width = i_shadow;
  235.                     p_style->font_style.i_outline_width = i_outline;
  236.                     p_style->i_align = 0;
  237.                     if( i_align == 1 || i_align == 5 || i_align == 9 )
  238.                         p_style->i_align |= SUBPICTURE_ALIGN_LEFT;
  239.                     if( i_align == 3 || i_align == 7 || i_align == 11 )
  240.                         p_style->i_align |= SUBPICTURE_ALIGN_RIGHT;
  241.                     if( i_align < 4 )
  242.                         p_style->i_align |= SUBPICTURE_ALIGN_BOTTOM;
  243.                     else if( i_align < 8 )
  244.                         p_style->i_align |= SUBPICTURE_ALIGN_TOP;
  245.                     p_style->i_margin_h = ( p_style->i_align & SUBPICTURE_ALIGN_RIGHT ) ?
  246.                                                         i_margin_r : i_margin_l;
  247.                     p_style->i_margin_v = i_margin_v;
  248.                     p_style->i_margin_percent_h = 0;
  249.                     p_style->i_margin_percent_v = 0;
  250.                     p_style->font_style.i_karaoke_background_color = 0xffffff;
  251.                     p_style->font_style.i_karaoke_background_alpha = 0xff;
  252.                     TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_style );
  253.                 }
  254.                 else msg_Warn( p_dec, "SSA v4 styleline parsing failed" );
  255.             }
  256.             else if( i_section_type == 2 ) /* V4+ */
  257.             {
  258.                 /* Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour,
  259.                    Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline,
  260.                    Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
  261.                 */
  262.                 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%*[^rn]",
  263.                     psz_temp_stylename, psz_temp_fontname, &i_font_size,
  264.                     psz_temp_color1, psz_temp_color2, psz_temp_color3, psz_temp_color4, &i_bold, &i_italic,
  265.                     &i_underline, &i_strikeout, &i_scale_x, &i_scale_y, &i_spacing, &i_border, &i_outline,
  266.                     &i_shadow, &i_align, &i_margin_l, &i_margin_r, &i_margin_v ) == 21 )
  267.                 {
  268.                     ssa_style_t *p_style = malloc( sizeof(ssa_style_t) );
  269.                     p_style->psz_stylename = strdup( psz_temp_stylename );
  270.                     p_style->font_style.psz_fontname = strdup( psz_temp_fontname );
  271.                     p_style->font_style.i_font_size = i_font_size;
  272.                     ParseColor( psz_temp_color1, &p_style->font_style.i_font_color,
  273.                                 &p_style->font_style.i_font_alpha );
  274.                     ParseColor( psz_temp_color3, &p_style->font_style.i_outline_color,
  275.                                 &p_style->font_style.i_outline_alpha );
  276.                     ParseColor( psz_temp_color4, &p_style->font_style.i_shadow_color,
  277.                                 &p_style->font_style.i_shadow_alpha );
  278.                     p_style->font_style.i_style_flags = 0;
  279.                     if( i_bold ) p_style->font_style.i_style_flags |= STYLE_BOLD;
  280.                     if( i_italic ) p_style->font_style.i_style_flags |= STYLE_ITALIC;
  281.                     if( i_underline ) p_style->font_style.i_style_flags |= STYLE_UNDERLINE;
  282.                     if( i_strikeout ) p_style->font_style.i_style_flags |= STYLE_STRIKEOUT;
  283.                     if( i_border == 1 ) p_style->font_style.i_style_flags |= (STYLE_ITALIC | STYLE_OUTLINE);
  284.                     else if( i_border == 3 )
  285.                     {
  286.                         p_style->font_style.i_style_flags |= STYLE_BACKGROUND;
  287.                         p_style->font_style.i_background_color = p_style->font_style.i_shadow_color;
  288.                         p_style->font_style.i_background_alpha = p_style->font_style.i_shadow_alpha;
  289.                     }
  290.                     p_style->font_style.i_shadow_width  = ( i_border == 1 ) ? i_shadow : 0;
  291.                     p_style->font_style.i_outline_width = ( i_border == 1 ) ? i_outline : 0;
  292.                     p_style->font_style.i_spacing = i_spacing;
  293.                     //p_style->font_style.f_angle = f_angle;
  294.                     p_style->i_align = 0;
  295.                     if( i_align == 0x1 || i_align == 0x4 || i_align == 0x7 )
  296.                         p_style->i_align |= SUBPICTURE_ALIGN_LEFT;
  297.                     if( i_align == 0x3 || i_align == 0x6 || i_align == 0x9 )
  298.                         p_style->i_align |= SUBPICTURE_ALIGN_RIGHT;
  299.                     if( i_align == 0x7 || i_align == 0x8 || i_align == 0x9 )
  300.                         p_style->i_align |= SUBPICTURE_ALIGN_TOP;
  301.                     if( i_align == 0x1 || i_align == 0x2 || i_align == 0x3 )
  302.                         p_style->i_align |= SUBPICTURE_ALIGN_BOTTOM;
  303.                     p_style->i_margin_h = ( p_style->i_align & SUBPICTURE_ALIGN_RIGHT ) ?
  304.                                             i_margin_r : i_margin_l;
  305.                     p_style->i_margin_v = i_margin_v;
  306.                     p_style->i_margin_percent_h = 0;
  307.                     p_style->i_margin_percent_v = 0;
  308.                     p_style->font_style.i_karaoke_background_color = 0xffffff;
  309.                     p_style->font_style.i_karaoke_background_alpha = 0xff;
  310.                     /*TODO: Ignored: angle i_scale_x|y (fontscaling), i_encoding */
  311.                     TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_style );
  312.                 }
  313.                 else msg_Dbg( p_dec, "SSA V4+ styleline parsing failed" );
  314.             }
  315.         }
  316.         psz_parser = GotoNextLine( psz_parser );
  317.     }
  318. eof:
  319.     free( psz_header );
  320.     return;
  321. }