static void SegmentDoSplit( tx3g_segment_t *p_segment, uint16_t i_start, uint16_t i_end, tx3g_segment_t **pp_segment_left, tx3g_segment_t **pp_segment_middle, tx3g_segment_t **pp_segment_right ) { tx3g_segment_t *p_segment_left = NULL, *p_segment_right = NULL, *p_segment_middle = NULL; if ( (p_segment->i_size - i_start < 1) || (p_segment->i_size - i_end < 1) ) goto error; if ( i_start > 0 ) { char* psz_text = str8indup( p_segment->s->psz_text, 0, i_start ); p_segment_left = tx3g_segment_New( psz_text ); free( psz_text ); if ( !p_segment_left ) goto error; p_segment_left->s->style = text_style_Duplicate( p_segment->s->style ); p_segment_left->i_size = str8len( p_segment_left->s->psz_text ); } char* psz_text = str8indup( p_segment->s->psz_text, i_start, i_end - i_start + 1 ); p_segment_middle = tx3g_segment_New( psz_text ); free( psz_text ); if ( !p_segment_middle ) goto error; p_segment_middle->s->style = text_style_Duplicate( p_segment->s->style ); p_segment_middle->i_size = str8len( p_segment_middle->s->psz_text ); if ( i_end < (p_segment->i_size - 1) ) { char* psz_text = str8indup( p_segment->s->psz_text, i_end + 1, p_segment->i_size - i_end - 1 ); p_segment_right = tx3g_segment_New( psz_text ); free( psz_text ); if ( !p_segment_right ) goto error; p_segment_right->s->style = text_style_Duplicate( p_segment->s->style ); p_segment_right->i_size = str8len( p_segment_right->s->psz_text ); } if ( p_segment_left ) p_segment_left->p_next3g = p_segment_middle; if ( p_segment_right ) p_segment_middle->p_next3g = p_segment_right; *pp_segment_left = p_segment_left; *pp_segment_middle = p_segment_middle; *pp_segment_right = p_segment_right; return; error: if( p_segment_middle ) { text_segment_Delete( p_segment_middle->s ); free( p_segment_middle ); } if( p_segment_left ) { text_segment_Delete( p_segment_left->s ); free( p_segment_left ); } *pp_segment_left = *pp_segment_middle = *pp_segment_right = NULL; }
void text_segment_ChainDelete( text_segment_t *segment ) { while( segment != NULL ) { text_segment_t *p_next = segment->p_next; text_segment_Delete( segment ); segment = p_next; } }
static bool SegmentSplit( tx3g_segment_t *p_prev, tx3g_segment_t **pp_segment, const uint16_t i_start, const uint16_t i_end, const text_style_t *p_styles ) { tx3g_segment_t *p_segment_left = NULL, *p_segment_middle = NULL, *p_segment_right = NULL; if ( (*pp_segment)->i_size == 0 ) return false; if ( i_start > i_end ) return false; if ( (size_t)(i_end - i_start) > (*pp_segment)->i_size - 1 ) return false; if ( i_end > (*pp_segment)->i_size - 1 ) return false; SegmentDoSplit( *pp_segment, i_start, i_end, &p_segment_left, &p_segment_middle, &p_segment_right ); if ( !p_segment_middle ) { /* Failed */ text_segment_Delete( p_segment_left->s ); free( p_segment_left ); text_segment_Delete( p_segment_right->s ); free( p_segment_right ); return false; } tx3g_segment_t *p_next3g = (*pp_segment)->p_next3g; text_segment_Delete( (*pp_segment)->s ); free( *pp_segment ); *pp_segment = ( p_segment_left ) ? p_segment_left : p_segment_middle ; if ( p_prev ) p_prev->p_next3g = *pp_segment; if ( p_segment_right ) p_segment_right->p_next3g = p_next3g; else p_segment_middle->p_next3g = p_next3g; text_style_Delete( p_segment_middle->s->style ); p_segment_middle->s->style = text_style_Duplicate( p_styles ); return true; }
void subpicture_region_Delete( subpicture_region_t *p_region ) { if( !p_region ) return; if( p_region->p_private ) subpicture_region_private_Delete( p_region->p_private ); if( p_region->p_picture ) picture_Release( p_region->p_picture ); text_segment_Delete( p_region->p_text ); free( p_region->fmt.p_palette ); free( p_region ); }
text_segment_t *text_segment_NewInheritStyle( const text_style_t* p_style ) { if ( !p_style ) return NULL; //FIXME: Allow this, even if it is an alias to text_segment_New( NULL ) ? text_segment_t* p_segment = text_segment_New( NULL ); if ( unlikely( !p_segment ) ) return NULL; p_segment->style = text_style_Duplicate( p_style ); if ( unlikely( !p_segment->style ) ) { text_segment_Delete( p_segment ); return NULL; } return p_segment; }
/***************************************************************************** * Decode: *****************************************************************************/ static int Decode( decoder_t *p_dec, block_t *p_block ) { subpicture_t *p_spu = NULL; if( p_block == NULL ) /* No Drain */ return VLCDEC_SUCCESS; if( ( p_block->i_flags & (BLOCK_FLAG_CORRUPTED) ) || p_block->i_buffer < sizeof(uint16_t) ) { block_Release( p_block ); return VLCDEC_SUCCESS; } uint8_t *p_buf = p_block->p_buffer; /* Read our raw string and create the styled segment for HTML */ uint16_t i_psz_bytelength = GetWBE( p_buf ); const uint8_t *p_pszstart = p_block->p_buffer + sizeof(uint16_t); char *psz_subtitle; if ( i_psz_bytelength > 2 && ( !memcmp( p_pszstart, "\xFE\xFF", 2 ) || !memcmp( p_pszstart, "\xFF\xFE", 2 ) ) ) { psz_subtitle = FromCharset( "UTF-16", p_pszstart, i_psz_bytelength ); if ( !psz_subtitle ) return VLCDEC_SUCCESS; } else { psz_subtitle = malloc( i_psz_bytelength + 1 ); if ( !psz_subtitle ) return VLCDEC_SUCCESS; memcpy( psz_subtitle, p_pszstart, i_psz_bytelength ); psz_subtitle[ i_psz_bytelength ] = '\0'; } p_buf += i_psz_bytelength + sizeof(uint16_t); for( uint16_t i=0; i < i_psz_bytelength; i++ ) if ( psz_subtitle[i] == '\r' ) psz_subtitle[i] = '\n'; tx3g_segment_t *p_segment3g = tx3g_segment_New( psz_subtitle ); p_segment3g->i_size = str8len( psz_subtitle ); if ( p_dec->fmt_in.subs.p_style ) p_segment3g->s->style = text_style_Duplicate( p_dec->fmt_in.subs.p_style ); free( psz_subtitle ); if ( !p_segment3g->s->psz_text ) { text_segment_Delete( p_segment3g->s ); free( p_segment3g ); return VLCDEC_SUCCESS; } /* Create the subpicture unit */ p_spu = decoder_NewSubpictureText( p_dec ); if( !p_spu ) { text_segment_Delete( p_segment3g->s ); free( p_segment3g ); return VLCDEC_SUCCESS; } subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; /* Parse our styles */ while( (size_t)(p_buf - p_block->p_buffer) + 8 < p_block->i_buffer ) { uint32_t i_atomsize = GetDWBE( p_buf ); vlc_fourcc_t i_atomtype = VLC_FOURCC(p_buf[4],p_buf[5],p_buf[6],p_buf[7]); p_buf += 8; switch( i_atomtype ) { case VLC_FOURCC('s','t','y','l'): { if ( (size_t)(p_buf - p_block->p_buffer) < 14 ) break; uint16_t i_nbrecords = GetWBE(p_buf); uint16_t i_cur_record = 0; p_buf += 2; while( i_cur_record++ < i_nbrecords ) { if ( (size_t)(p_buf - p_block->p_buffer) < 12 ) break; uint16_t i_start = __MIN( GetWBE(p_buf), i_psz_bytelength - 1 ); uint16_t i_end = __MIN( GetWBE(p_buf + 2), i_psz_bytelength - 1 ); text_style_t style; memset( &style, 0, sizeof(text_style_t) ); style.i_style_flags = ConvertFlags( p_buf[6] ); style.i_font_size = p_buf[7]; style.i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> RGB style.i_font_alpha = GetDWBE(p_buf+8) & 0xFF; style.i_features = STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA; ApplySegmentStyle( &p_segment3g, i_start, i_end, &style ); if ( i_nbrecords == 1 ) { if ( p_buf[6] ) { if( (p_spu_sys->p_default_style->i_style_flags = ConvertFlags( p_buf[6] )) ) p_spu_sys->p_default_style->i_features |= STYLE_HAS_FLAGS; } p_spu_sys->p_default_style->i_font_size = p_buf[7]; p_spu_sys->p_default_style->i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB p_spu_sys->p_default_style->i_font_alpha = (GetDWBE(p_buf+8) & 0xFF) << 24; p_spu_sys->p_default_style->i_features |= (STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA); } p_buf += 12; } } break; case VLC_FOURCC('d','r','p','o'): if ( (size_t)(p_buf - p_block->p_buffer) < 4 ) break; p_spu_sys->p_default_style->i_shadow_width = __MAX( GetWBE(p_buf), GetWBE(p_buf+2) ); break; case VLC_FOURCC('d','r','p','t'): if ( (size_t)(p_buf - p_block->p_buffer) < 2 ) break; p_spu_sys->p_default_style->i_shadow_alpha = GetWBE(p_buf); p_spu_sys->p_default_style->i_features |= STYLE_HAS_SHADOW_ALPHA; break; default: break; } p_buf += i_atomsize; } 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_sys->region.inner_align = SUBPICTURE_ALIGN_BOTTOM; FontSizeConvert( p_dec->fmt_in.subs.p_style, p_spu_sys->p_default_style ); /* Unwrap */ text_segment_t *p_text_segments = p_segment3g->s; text_segment_t *p_cur = p_text_segments; while( p_segment3g ) { FontSizeConvert( p_dec->fmt_in.subs.p_style, p_segment3g->s->style ); tx3g_segment_t * p_old = p_segment3g; p_segment3g = p_segment3g->p_next3g; free( p_old ); if( p_segment3g ) p_cur->p_next = p_segment3g->s; p_cur = p_cur->p_next; } p_spu_sys->region.p_segments = p_text_segments; block_Release( p_block ); decoder_QueueSub( p_dec, p_spu ); return VLCDEC_SUCCESS; }