📄 subsusf.c
字号:
} else if( p_text_region ) { p_region_upto->p_next = p_text_region; p_region_upto = p_region_upto->p_next; } } } else if(( !strncasecmp( psz_subtitle, "<image ", 7 )) || ( !strncasecmp( psz_subtitle, "<image>", 7 ))) { subpicture_region_t *p_image_region = NULL; char *psz_end = strcasestr( psz_subtitle, "</image>" ); char *psz_content = strchr( psz_subtitle, '>' ); int i_transparent = -1; /* If a colorkey parameter is specified, then we have to map * that index in the picture through as transparent (it is * required by the USF spec but is also recommended that if the * creator really wants a transparent colour that they use a * type like PNG that properly supports it; this goes doubly * for VLC because the pictures are stored internally in YUV * and the resulting colour-matching may not produce the * desired results.) */ char *psz_tmp = GrabAttributeValue( "colorkey", psz_subtitle ); if( psz_tmp ) { if( *psz_tmp == '#' ) i_transparent = strtol( psz_tmp + 1, NULL, 16 ) & 0x00ffffff; free( psz_tmp ); } if( psz_content && ( psz_content < psz_end ) ) { char *psz_filename = strndup( &psz_content[1], psz_end - &psz_content[1] ); if( psz_filename ) { p_image_region = LoadEmbeddedImage( p_dec, p_spu, psz_filename, i_transparent ); free( psz_filename ); } } if( psz_end ) psz_end += strcspn( psz_end, ">" ) + 1; if( p_image_region ) { SetupPositions( p_image_region, psz_subtitle ); p_image_region->p_next = NULL; p_image_region->psz_text = NULL; p_image_region->psz_html = NULL; } if( !p_region_first ) { p_region_first = p_region_upto = p_image_region; } else if( p_image_region ) { p_region_upto->p_next = p_image_region; p_region_upto = p_region_upto->p_next; } } if( psz_end ) psz_subtitle = psz_end - 1; psz_subtitle += strcspn( psz_subtitle, ">" ); } psz_subtitle++; } return p_region_first;}/***************************************************************************** * ParseUSFHeader: Retrieve global formatting information etc *****************************************************************************/static void ParseUSFHeader( decoder_t *p_dec ){ stream_t *p_sub = NULL; xml_t *p_xml = NULL; xml_reader_t *p_xml_reader = NULL; p_sub = stream_MemoryNew( VLC_OBJECT(p_dec), p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra, true ); if( !p_sub ) return; p_xml = xml_Create( p_dec ); if( p_xml ) { p_xml_reader = xml_ReaderCreate( p_xml, p_sub ); if( p_xml_reader ) { /* Look for Root Node */ if( xml_ReaderRead( p_xml_reader ) == 1 ) { char *psz_node = xml_ReaderName( p_xml_reader ); if( !strcasecmp( "usfsubtitles", psz_node ) ) ParseUSFHeaderTags( p_dec, p_xml_reader ); free( psz_node ); } xml_ReaderDelete( p_xml, p_xml_reader ); } xml_Delete( p_xml ); } stream_Delete( p_sub );}/* Function now handles tags which has attribute values, and tries * to deal with &' commands too. It no longer modifies the string * in place, so that the original text can be reused */static char *StripTags( char *psz_subtitle ){ char *psz_text_start; char *psz_text; psz_text = psz_text_start = malloc( strlen( psz_subtitle ) + 1 ); if( !psz_text_start ) return NULL; while( *psz_subtitle ) { /* Mask out any pre-existing LFs in the subtitle */ if( *psz_subtitle == '\n' ) *psz_subtitle = ' '; if( *psz_subtitle == '<' ) { if( strncasecmp( psz_subtitle, "<br/>", 5 ) == 0 ) *psz_text++ = '\n'; psz_subtitle += strcspn( psz_subtitle, ">" ); } else if( *psz_subtitle == '&' ) { if( !strncasecmp( psz_subtitle, "<", 4 )) { *psz_text++ = '<'; psz_subtitle += strcspn( psz_subtitle, ";" ); } else if( !strncasecmp( psz_subtitle, ">", 4 )) { *psz_text++ = '>'; psz_subtitle += strcspn( psz_subtitle, ";" ); } else if( !strncasecmp( psz_subtitle, "&", 5 )) { *psz_text++ = '&'; psz_subtitle += strcspn( psz_subtitle, ";" ); } else if( !strncasecmp( psz_subtitle, """, 6 )) { *psz_text++ = '\"'; psz_subtitle += strcspn( psz_subtitle, ";" ); } else { /* Assume it is just a normal ampersand */ *psz_text++ = '&'; } } else { *psz_text++ = *psz_subtitle; } psz_subtitle++; } *psz_text = '\0'; psz_text_start = realloc( psz_text_start, strlen( psz_text_start ) + 1 ); return psz_text_start;}/* Turn a HTML subtitle, turn into a plain-text version, * complete with sensible whitespace compaction */static char *CreatePlainText( char *psz_subtitle ){ char *psz_text = StripTags( psz_subtitle ); char *s; if( !psz_text ) return NULL; s = strpbrk( psz_text, "\t\r\n " ); while( s ) { int k; char spc = ' '; int i_whitespace = strspn( s, "\t\r\n " ); /* Favour '\n' over other whitespaces - if one of these * occurs in the whitespace use a '\n' as our value, * otherwise just use a ' ' */ for( k = 0; k < i_whitespace; k++ ) if( s[k] == '\n' ) spc = '\n'; if( i_whitespace > 1 ) { memmove( &s[1], &s[i_whitespace], strlen( s ) - i_whitespace + 1 ); } *s++ = spc; s = strpbrk( s, "\t\r\n " ); } return psz_text;}/**************************************************************************** * download and resize image located at psz_url ***************************************************************************/static subpicture_region_t *LoadEmbeddedImage( decoder_t *p_dec, subpicture_t *p_spu, const char *psz_filename, int i_transparent_color ){ decoder_sys_t *p_sys = p_dec->p_sys; subpicture_region_t *p_region; video_format_t fmt_out; int k; picture_t *p_pic = NULL; for( k = 0; k < p_sys->i_images; k++ ) { if( p_sys->pp_images && !strcmp( p_sys->pp_images[k]->psz_filename, psz_filename ) ) { p_pic = p_sys->pp_images[k]->p_pic; break; } } if( !p_pic ) { msg_Err( p_dec, "Unable to read image %s", psz_filename ); return NULL; } /* Display the feed's image */ memset( &fmt_out, 0, sizeof( video_format_t)); fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A'); fmt_out.i_aspect = VOUT_ASPECT_FACTOR; fmt_out.i_sar_num = fmt_out.i_sar_den = 1; fmt_out.i_width = fmt_out.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch; fmt_out.i_height = fmt_out.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines; p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt_out ); if( !p_region ) { msg_Err( p_dec, "cannot allocate SPU region" ); return NULL; } vout_CopyPicture( p_dec, &p_region->picture, p_pic ); /* This isn't the best way to do this - if you really want transparency, then * you're much better off using an image type that supports it like PNG. The * spec requires this support though. */ if( i_transparent_color > 0 ) { uint8_t i_r = ( i_transparent_color >> 16 ) & 0xff; uint8_t i_g = ( i_transparent_color >> 8 ) & 0xff; uint8_t i_b = ( i_transparent_color ) & 0xff; uint8_t i_y = ( ( ( 66 * i_r + 129 * i_g + 25 * i_b + 128 ) >> 8 ) + 16 ); uint8_t i_u = ( ( -38 * i_r - 74 * i_g + 112 * i_b + 128 ) >> 8 ) + 128 ; uint8_t i_v = ( ( 112 * i_r - 94 * i_g - 18 * i_b + 128 ) >> 8 ) + 128 ; if( ( p_region->picture.Y_PITCH == p_region->picture.U_PITCH ) && ( p_region->picture.Y_PITCH == p_region->picture.V_PITCH ) && ( p_region->picture.Y_PITCH == p_region->picture.A_PITCH ) ) { int i_lines = p_region->picture.p[ Y_PLANE ].i_lines; if( i_lines > p_region->picture.p[ U_PLANE ].i_lines ) i_lines = p_region->picture.p[ U_PLANE ].i_lines; if( i_lines > p_region->picture.p[ V_PLANE ].i_lines ) i_lines = p_region->picture.p[ V_PLANE ].i_lines; if( i_lines > p_region->picture.p[ A_PLANE ].i_lines ) i_lines = p_region->picture.p[ A_PLANE ].i_lines; int i; for( i = 0; i < p_region->picture.A_PITCH * i_lines; i++ ) { if(( p_region->picture.Y_PIXELS[ i ] == i_y ) && ( p_region->picture.U_PIXELS[ i ] == i_u ) && ( p_region->picture.V_PIXELS[ i ] == i_v ) ) { p_region->picture.A_PIXELS[ i ] = 1; } } } } return p_region;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -