/*****************************************************************************
* vout_subpictures.c : subpicture management functions
*****************************************************************************
- * Copyright (C) 2000-2005 the VideoLAN team
+ * Copyright (C) 2000-2007 the VideoLAN team
* $Id$
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
static picture_t *spu_new_video_buffer( filter_t * );
static void spu_del_video_buffer( filter_t *, picture_t * );
+static int spu_ParseChain( spu_t * );
+static void spu_DeleteChain( spu_t * );
+static int SubFilterCallback( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
+
struct filter_owner_sys_t
{
spu_t *p_spu;
*/
int spu_Init( spu_t *p_spu )
{
- char *psz_parser;
vlc_value_t val;
/* If the user requested a sub margin, we force the position. */
p_spu->i_margin = val.i_int;
var_Create( p_spu, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
- var_Get( p_spu, "sub-filter", &val );
+ var_AddCallback( p_spu, "sub-filter", SubFilterCallback, p_spu );
+
+ spu_ParseChain( p_spu );
+ return VLC_EGENERIC;
+}
+
+int spu_ParseChain( spu_t *p_spu )
+{
+ char *psz_parser;
+ vlc_value_t val;
+ var_Get( p_spu, "sub-filter", &val );
psz_parser = val.psz_string;
while( psz_parser && *psz_parser )
{
- config_chain_t *p_cfg; /* Do we ever need to free this ? */
+ config_chain_t *p_cfg;
char *psz_name;
psz_parser = config_ChainCreate( &psz_name, &p_cfg, psz_parser );
vlc_object_attach( p_spu->pp_filter[p_spu->i_filter], p_spu );
p_spu->pp_filter[p_spu->i_filter]->pf_sub_buffer_new = sub_new_buffer;
p_spu->pp_filter[p_spu->i_filter]->pf_sub_buffer_del = sub_del_buffer;
- p_spu->pp_filter[p_spu->i_filter]->p_cfg = p_cfg;;
+ p_spu->pp_filter[p_spu->i_filter]->p_cfg = p_cfg;
p_spu->pp_filter[p_spu->i_filter]->p_module =
module_Need( p_spu->pp_filter[p_spu->i_filter],
- "sub filter", psz_name, 0 );
+ "sub filter", psz_name, VLC_TRUE );
if( p_spu->pp_filter[p_spu->i_filter]->p_module )
{
filter_owner_sys_t *p_sys = malloc( sizeof(filter_owner_sys_t) );
else
{
msg_Dbg( p_spu, "no sub filter found" );
+ config_ChainDestroy( p_spu->pp_filter[p_spu->i_filter]->p_cfg );
vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] );
vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] );
}
vlc_object_destroy( p_spu->p_scale );
}
+ spu_DeleteChain( p_spu );
+
+ vlc_mutex_destroy( &p_spu->subpicture_lock );
+ vlc_object_destroy( p_spu );
+}
+
+static void spu_DeleteChain( spu_t *p_spu )
+{
+ if( p_spu->i_filter )
while( p_spu->i_filter-- )
{
module_Unneed( p_spu->pp_filter[p_spu->i_filter],
p_spu->pp_filter[p_spu->i_filter]->p_module );
free( p_spu->pp_filter[p_spu->i_filter]->p_owner );
+ config_ChainDestroy( p_spu->pp_filter[p_spu->i_filter]->p_cfg );
vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] );
vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] );
}
-
- vlc_mutex_destroy( &p_spu->subpicture_lock );
- vlc_object_destroy( p_spu );
}
/**
video_format_t *p_fmt )
{
subpicture_region_t *p_region = malloc( sizeof(subpicture_region_t) );
+ if( !p_region ) return NULL;
+
memset( p_region, 0, sizeof(subpicture_region_t) );
p_region->p_next = 0;
p_region->p_cache = 0;
if( !p_region->picture.i_planes )
{
free( p_region );
- free( p_fmt->p_palette );
+ if( p_fmt->p_palette ) free( p_fmt->p_palette );
return NULL;
}
picture_t *p_pic )
{
subpicture_region_t *p_region = malloc( sizeof(subpicture_region_t) );
+ (void)p_this;
memset( p_region, 0, sizeof(subpicture_region_t) );
p_region->p_next = 0;
p_region->p_cache = 0;
if( p_region->psz_text )
free( p_region->psz_text );
+ if( p_region->psz_html )
+ free( p_region->psz_html );
//free( p_region->p_style ); FIXME --fenrir plugin does not allocate the memory for it. I think it might lead to segfault, video renderer can live longer than the decoder
free( p_region );
}
p_spu->p_blend->fmt_out.video.i_aspect = p_fmt->i_aspect;
p_spu->p_blend->fmt_out.video.i_chroma = p_fmt->i_chroma;
p_spu->p_blend->fmt_in.video.i_chroma = VLC_FOURCC('Y','U','V','P');
+ /* XXX: We'll also be using it for YUVA and RGBA blending ... */
p_spu->p_blend->p_module =
module_Need( p_spu->p_blend, "video blending", 0, 0 );
if( psz_modulename && *psz_modulename )
{
p_spu->p_text->p_module =
- module_Need( p_spu->p_text, "text renderer", psz_modulename, VLC_TRUE );
+ module_Need( p_spu->p_text, "text renderer",
+ psz_modulename, VLC_TRUE );
}
if( !p_spu->p_text->p_module )
{
{
i_scale_height = i_scale_height * p_fmt->i_height /
p_subpic->i_original_picture_height;
- i_scale_width = i_scale_height * i_scale_height / p_fmt->i_height;
+ i_scale_width = i_scale_height * i_scale_height / p_fmt->i_height;
}
/* Set default subpicture aspect ratio */
p_spu->p_scale->fmt_out.video.i_chroma =
p_spu->p_scale->fmt_in.video.i_chroma =
VLC_FOURCC('Y','U','V','P');
+ /* XXX: We'll also be using it for YUVA and RGBA blending ... */
p_spu->p_scale->fmt_in.video.i_width =
p_spu->p_scale->fmt_in.video.i_height = 32;
p_spu->p_scale->fmt_out.video.i_width =
if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )
{
- if( p_spu->p_text && p_spu->p_text->p_module &&
- p_spu->p_text->pf_render_text )
+ if( p_spu->p_text && p_spu->p_text->p_module )
{
- p_region->i_align = p_subpic->i_flags;
- p_spu->p_text->pf_render_text( p_spu->p_text,
- p_region, p_region );
+ if( p_spu->p_text->pf_render_html && p_region->psz_html )
+ {
+ p_spu->p_text->pf_render_html( p_spu->p_text,
+ p_region, p_region );
+ }
+ else if( p_spu->p_text->pf_render_text )
+ {
+ p_spu->p_text->pf_render_text( p_spu->p_text,
+ p_region, p_region );
+ }
}
}
/* Force palette if requested */
- if( p_spu->b_force_palette && VLC_FOURCC('Y','U','V','P') ==
- p_region->fmt.i_chroma )
+ if( p_spu->b_force_palette &&
+ (VLC_FOURCC('Y','U','V','P') == p_region->fmt.i_chroma) )
{
memcpy( p_region->fmt.p_palette->palette,
p_spu->palette, 16 );
p_region->p_cache->fmt = p_spu->p_scale->fmt_out.video;
p_region->p_cache->i_x = p_region->i_x * i_scale_width / 1000;
p_region->p_cache->i_y = p_region->i_y * i_scale_height / 1000;
+ p_region->p_cache->i_align = p_region->i_align;
p_pic = p_spu->p_scale->pf_video_filter(
p_spu->p_scale, &p_region->p_cache->picture );
p_region = p_region->p_cache;
}
- if( p_subpic->i_flags & SUBPICTURE_ALIGN_BOTTOM )
+ if( p_region->i_align & SUBPICTURE_ALIGN_BOTTOM )
{
i_y_offset = p_fmt->i_height - p_region->fmt.i_height -
- p_subpic->i_y;
+ p_subpic->i_y - p_region->i_y;
}
- else if ( !(p_subpic->i_flags & SUBPICTURE_ALIGN_TOP) )
+ else if ( !(p_region->i_align & SUBPICTURE_ALIGN_TOP) )
{
i_y_offset = p_fmt->i_height / 2 - p_region->fmt.i_height / 2;
}
- if( p_subpic->i_flags & SUBPICTURE_ALIGN_RIGHT )
+ if( p_region->i_align & SUBPICTURE_ALIGN_RIGHT )
{
i_x_offset = p_fmt->i_width - p_region->fmt.i_width -
- i_subpic_x;
+ i_subpic_x - p_region->i_x;
}
- else if ( !(p_subpic->i_flags & SUBPICTURE_ALIGN_LEFT) )
+ else if ( !(p_region->i_align & SUBPICTURE_ALIGN_LEFT) )
{
i_x_offset = p_fmt->i_width / 2 - p_region->fmt.i_width / 2;
}
p_subpic->i_y * i_scale_height / 1000;
}
-
+
i_x_offset = __MAX( i_x_offset, 0 );
i_y_offset = __MAX( i_y_offset, 0 );
static int CropCallback( vlc_object_t *p_object, char const *psz_var,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
+ (void)psz_var; (void)oldval; (void)newval;
UpdateSPU( (spu_t *)p_data, p_object );
return VLC_SUCCESS;
}
static subpicture_t *spu_new_buffer( filter_t *p_filter )
{
subpicture_t *p_subpic = (subpicture_t *)malloc(sizeof(subpicture_t));
+ (void)p_filter;
memset( p_subpic, 0, sizeof(subpicture_t) );
p_subpic->b_absolute = VLC_TRUE;
static void spu_del_video_buffer( filter_t *p_filter, picture_t *p_pic )
{
+ (void)p_filter;
if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
if( p_pic ) free( p_pic );
}
+
+static int SubFilterCallback( vlc_object_t *p_object, char const *psz_var,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ (void)p_object; (void)oldval; (void)newval;
+
+ if( !strcmp( psz_var, "sub-filter" ) )
+ {
+ spu_t *p_spu = (spu_t *)p_data;
+ vlc_mutex_lock( &p_spu->subpicture_lock );
+ spu_DeleteChain( p_spu );
+ spu_ParseChain( p_spu );
+ vlc_mutex_unlock( &p_spu->subpicture_lock );
+ }
+ return VLC_SUCCESS;
+}