X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvout_subpictures.c;h=daecbeeb054c9ec74a891c1769c782b1229bda31;hb=e259db6fefa6941b1a9cc2c01de8536c53b3ec01;hp=e4724d8e64b9650319fd36bffb794977d337c818;hpb=f756ebd7197ef940aead1ac78865c6bb58d0e502;p=vlc diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c index e4724d8e64..daecbeeb05 100644 --- a/src/video_output/vout_subpictures.c +++ b/src/video_output/vout_subpictures.c @@ -26,11 +26,16 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include #include #include #include #include +#include "../libvlc.h" /***************************************************************************** * Local prototypes @@ -53,6 +58,8 @@ static void spu_DeleteChain( spu_t * ); static int SubFilterCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); +static int sub_filter_allocation_init( filter_t *, void * ); +static void sub_filter_allocation_clear( filter_t * ); struct filter_owner_sys_t { spu_t *p_spu; @@ -64,6 +71,7 @@ enum { SCALE_TEXT, SCALE_SIZE }; + /** * Creates the subpicture unit * @@ -72,7 +80,8 @@ enum { spu_t *__spu_Create( vlc_object_t *p_this ) { int i_index; - spu_t *p_spu = vlc_object_create( p_this, VLC_OBJECT_SPU ); + spu_t *p_spu = vlc_custom_create( p_this, sizeof( spu_t ), + VLC_OBJECT_GENERIC, "subpicture" ); for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++) { @@ -82,16 +91,19 @@ spu_t *__spu_Create( vlc_object_t *p_this ) p_spu->p_blend = NULL; p_spu->p_text = NULL; p_spu->p_scale = NULL; - p_spu->i_filter = 0; p_spu->pf_control = spu_vaControlDefault; /* Register the default subpicture channel */ p_spu->i_channel = 2; - vlc_mutex_init( p_this, &p_spu->subpicture_lock ); + vlc_mutex_init( &p_spu->subpicture_lock ); vlc_object_attach( p_spu, p_this ); + p_spu->p_chain = filter_chain_New( p_spu, "sub filter", false, + sub_filter_allocation_init, + sub_filter_allocation_clear, + p_spu ); return p_spu; } @@ -119,57 +131,14 @@ int spu_Init( spu_t *p_spu ) 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 ) + char *psz_parser = var_GetString( p_spu, "sub-filter" ); + if( filter_chain_AppendFromString( p_spu->p_chain, psz_parser ) < 0 ) { - config_chain_t *p_cfg; - char *psz_name; - - psz_parser = config_ChainCreate( &psz_name, &p_cfg, psz_parser ); - - msg_Dbg( p_spu, "adding sub-filter: %s", psz_name ); - - p_spu->pp_filter[p_spu->i_filter] = - vlc_object_create( p_spu, VLC_OBJECT_FILTER ); - 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_module = - module_Need( p_spu->pp_filter[p_spu->i_filter], - "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) ); - if( p_sys ) - { - p_spu->pp_filter[p_spu->i_filter]->p_owner = p_sys; - spu_Control( p_spu, SPU_CHANNEL_REGISTER, &p_sys->i_channel ); - p_sys->p_spu = p_spu; - p_spu->i_filter++; - } - } - 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] ); - } - - if( p_spu->i_filter >= 10 ) - { - msg_Dbg( p_spu, "can't add anymore filters" ); - } - - free( psz_name ); + free( psz_parser ); + return VLC_EGENERIC; } - if( val.psz_string ) free( val.psz_string ); + free( psz_parser ); return VLC_SUCCESS; } @@ -199,7 +168,7 @@ void spu_Destroy( spu_t *p_spu ) module_Unneed( p_spu->p_blend, p_spu->p_blend->p_module ); vlc_object_detach( p_spu->p_blend ); - vlc_object_destroy( p_spu->p_blend ); + vlc_object_release( p_spu->p_blend ); } if( p_spu->p_text ) @@ -208,7 +177,7 @@ void spu_Destroy( spu_t *p_spu ) module_Unneed( p_spu->p_text, p_spu->p_text->p_module ); vlc_object_detach( p_spu->p_text ); - vlc_object_destroy( p_spu->p_text ); + vlc_object_release( p_spu->p_text ); } if( p_spu->p_scale ) @@ -217,28 +186,18 @@ void spu_Destroy( spu_t *p_spu ) module_Unneed( p_spu->p_scale, p_spu->p_scale->p_module ); vlc_object_detach( p_spu->p_scale ); - vlc_object_destroy( p_spu->p_scale ); + vlc_object_release( p_spu->p_scale ); } spu_DeleteChain( p_spu ); vlc_mutex_destroy( &p_spu->subpicture_lock ); - vlc_object_destroy( p_spu ); + vlc_object_release( p_spu ); } static void spu_DeleteChain( spu_t *p_spu ) { - if( p_spu->i_filter ) - while( p_spu->i_filter ) - { - 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] ); - } + filter_chain_Delete( p_spu->p_chain ); } /** @@ -247,7 +206,7 @@ static void spu_DeleteChain( spu_t *p_spu ) * \param p_this the object in which to destroy the subpicture unit * \param b_attach to select attach or detach */ -void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, vlc_bool_t b_attach ) +void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, bool b_attach ) { vlc_object_t *p_input; @@ -276,7 +235,7 @@ void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, vlc_bool_t b_attach ) */ static void RegionPictureRelease( picture_t *p_pic ) { - if( p_pic->p_data_orig ) free( p_pic->p_data_orig ); + free( p_pic->p_data_orig ); } subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this, video_format_t *p_fmt ) @@ -285,6 +244,7 @@ subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this, if( !p_region ) return NULL; memset( p_region, 0, sizeof(subpicture_region_t) ); + p_region->i_alpha = 0xff; p_region->p_next = NULL; p_region->p_cache = NULL; p_region->fmt = *p_fmt; @@ -306,7 +266,7 @@ subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this, if( !p_region->picture.i_planes ) { free( p_region ); - if( p_fmt->p_palette ) free( p_fmt->p_palette ); + free( p_fmt->p_palette ); return NULL; } @@ -330,6 +290,7 @@ subpicture_region_t *__spu_MakeRegion( vlc_object_t *p_this, (void)p_this; if( !p_region ) return NULL; memset( p_region, 0, sizeof(subpicture_region_t) ); + p_region->i_alpha = 0xff; p_region->p_next = 0; p_region->p_cache = 0; p_region->fmt = *p_fmt; @@ -358,13 +319,11 @@ void __spu_DestroyRegion( vlc_object_t *p_this, subpicture_region_t *p_region ) if( !p_region ) return; if( p_region->picture.pf_release ) p_region->picture.pf_release( &p_region->picture ); - if( p_region->fmt.p_palette ) free( p_region->fmt.p_palette ); + free( p_region->fmt.p_palette ); if( p_region->p_cache ) __spu_DestroyRegion( p_this, p_region->p_cache ); - if( p_region->psz_text ) - free( p_region->psz_text ); - if( p_region->psz_html ) - free( p_region->psz_html ); + free( p_region->psz_text ); + 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 ); } @@ -441,9 +400,9 @@ subpicture_t *spu_CreateSubpicture( spu_t *p_spu ) /* Copy subpicture information, set some default values */ memset( p_subpic, 0, sizeof(subpicture_t) ); p_subpic->i_status = RESERVED_SUBPICTURE; - p_subpic->b_absolute = VLC_TRUE; - p_subpic->b_pausable = VLC_FALSE; - p_subpic->b_fade = VLC_FALSE; + p_subpic->b_absolute = true; + p_subpic->b_pausable = false; + p_subpic->b_fade = false; p_subpic->i_alpha = 0xFF; p_subpic->p_region = NULL; p_subpic->pf_render = NULL; @@ -515,10 +474,21 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, { int i_source_video_width; int i_source_video_height; + subpicture_t *p_subpic_v = p_subpic; /* Get lock */ vlc_mutex_lock( &p_spu->subpicture_lock ); + for( p_subpic_v = p_subpic; + p_subpic_v != NULL && p_subpic_v->i_status != FREE_SUBPICTURE; + p_subpic_v = p_subpic_v->p_next ) + { + if( p_subpic_v->pf_pre_render ) + { + p_subpic_v->pf_pre_render( p_fmt, p_spu, p_subpic_v, mdate() ); + } + } + if( i_scale_width_orig <= 0 ) i_scale_width_orig = 1; if( i_scale_height_orig <= 0 ) @@ -530,7 +500,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, /* Check i_status again to make sure spudec hasn't destroyed the subpic */ while( ( p_subpic != NULL ) && ( p_subpic->i_status != FREE_SUBPICTURE ) ) { - subpicture_region_t *p_region = p_subpic->p_region; + subpicture_region_t *p_region; int pi_scale_width[ SCALE_SIZE ]; int pi_scale_height[ SCALE_SIZE ]; int pi_subpic_x[ SCALE_SIZE ]; @@ -550,6 +520,18 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, for( k = 0; k < SCALE_SIZE ; k++ ) pi_subpic_x[ k ] = p_subpic->i_x; + if( p_subpic->pf_update_regions ) + { + if ( p_subpic->p_region ) { + spu_DestroyRegion( p_spu, p_subpic->p_region ); + } + p_subpic->p_region = p_region = p_subpic->pf_update_regions( p_fmt, p_spu, p_subpic, mdate() ); + } + else + { + p_region = p_subpic->p_region; + } + /* Load the blending module */ if( !p_spu->p_blend && p_region ) { @@ -592,14 +574,14 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, { p_spu->p_text->p_module = module_Need( p_spu->p_text, "text renderer", - psz_modulename, VLC_TRUE ); + psz_modulename, true ); } if( !p_spu->p_text->p_module ) { p_spu->p_text->p_module = module_Need( p_spu->p_text, "text renderer", 0, 0 ); } - if( psz_modulename ) free( psz_modulename ); + free( psz_modulename ); } if( p_spu->p_text ) @@ -737,7 +719,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, while( p_region ) { video_format_t orig_fmt = p_region->fmt; - vlc_bool_t b_rerender_text = VLC_FALSE; + bool b_rerender_text = false; int i_fade_alpha = 255; int i_x_offset; int i_y_offset; @@ -780,7 +762,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, var_Set( p_spu->p_text, "spu-elapsed", val ); var_Create( p_spu->p_text, "text-rerender", VLC_VAR_BOOL ); - var_SetBool( p_spu->p_text, "text-rerender", VLC_FALSE ); + var_SetBool( p_spu->p_text, "text-rerender", false ); var_Create( p_spu->p_text, "scale", VLC_VAR_INTEGER ); var_SetInteger( p_spu->p_text, "scale", @@ -874,6 +856,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, p_region->p_cache->i_x = p_region->i_x * pi_scale_width[ i_scale_idx ] / 1000; p_region->p_cache->i_y = p_region->i_y * pi_scale_height[ i_scale_idx ] / 1000; p_region->p_cache->i_align = p_region->i_align; + p_region->p_cache->i_alpha = p_region->i_alpha; p_pic = p_spu->p_scale->pf_video_filter( p_spu->p_scale, &p_region->p_cache->picture ); @@ -933,7 +916,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, i_y_offset = __MAX( i_y_offset, 0 ); if( ( p_spu->i_margin != 0 ) && - ( p_spu->b_force_crop == VLC_FALSE ) ) + ( p_spu->b_force_crop == false ) ) { int i_diff = 0; int i_low = (i_y_offset - p_spu->i_margin) * i_inv_scale_y / 1000; @@ -1033,7 +1016,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, { p_spu->p_blend->pf_video_blend( p_spu->p_blend, p_pic_dst, p_pic_src, &p_region->picture, i_x_offset, i_y_offset, - i_fade_alpha * p_subpic->i_alpha / 255 ); + i_fade_alpha * p_subpic->i_alpha * p_region->i_alpha / 65025 ); } else { @@ -1076,7 +1059,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, * more difficult to guess if a subpicture has to be rendered or not. *****************************************************************************/ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date, - vlc_bool_t b_paused ) + bool b_paused ) { int i_index, i_channel; subpicture_t *p_subpic = NULL; @@ -1084,16 +1067,7 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date, mtime_t ephemer_date; /* Run subpicture filters */ - for( i_index = 0; i_index < p_spu->i_filter; i_index++ ) - { - subpicture_t *p_subpic_filter; - p_subpic_filter = p_spu->pp_filter[i_index]-> - pf_sub_filter( p_spu->pp_filter[i_index], display_date ); - if( p_subpic_filter ) - { - spu_DisplaySubpicture( p_spu, p_subpic_filter ); - } - } + filter_chain_SubFilter( p_spu->p_chain, display_date ); /* We get an easily parsable chained list of subpictures which * ends with NULL since p_subpic was initialized to NULL. */ @@ -1249,12 +1223,12 @@ static void UpdateSPU( spu_t *p_spu, vlc_object_t *p_object ) { vlc_value_t val; - p_spu->b_force_palette = VLC_FALSE; - p_spu->b_force_crop = VLC_FALSE; + p_spu->b_force_palette = false; + p_spu->b_force_crop = false; if( var_Get( p_object, "highlight", &val ) || !val.b_bool ) return; - p_spu->b_force_crop = VLC_TRUE; + p_spu->b_force_crop = true; var_Get( p_object, "x-start", &val ); p_spu->i_crop_x = val.i_int; var_Get( p_object, "y-start", &val ); @@ -1267,7 +1241,7 @@ static void UpdateSPU( spu_t *p_spu, vlc_object_t *p_object ) if( var_Get( p_object, "menu-palette", &val ) == VLC_SUCCESS ) { memcpy( p_spu->palette, val.p_address, 16 ); - p_spu->b_force_palette = VLC_TRUE; + p_spu->b_force_palette = true; } msg_Dbg( p_object, "crop: %i,%i,%i,%i, palette forced: %i", @@ -1312,7 +1286,7 @@ static subpicture_t *spu_new_buffer( filter_t *p_filter ) subpicture_t *p_subpic = (subpicture_t *)malloc(sizeof(subpicture_t)); if( !p_subpic ) return NULL; memset( p_subpic, 0, sizeof(subpicture_t) ); - p_subpic->b_absolute = VLC_TRUE; + p_subpic->b_absolute = true; p_subpic->pf_create_region = __spu_CreateRegion; p_subpic->pf_make_region = __spu_MakeRegion; @@ -1358,7 +1332,7 @@ static void spu_del_video_buffer( filter_t *p_filter, picture_t *p_pic ) (void)p_filter; if( p_pic ) { - if( p_pic->p_data_orig ) free( p_pic->p_data_orig ); + free( p_pic->p_data_orig ); free( p_pic ); } } @@ -1366,7 +1340,8 @@ static void spu_del_video_buffer( filter_t *p_filter, picture_t *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; + VLC_UNUSED(p_object); VLC_UNUSED(oldval); + VLC_UNUSED(newval); VLC_UNUSED(psz_var); spu_t *p_spu = (spu_t *)p_data; vlc_mutex_lock( &p_spu->subpicture_lock ); @@ -1375,3 +1350,25 @@ static int SubFilterCallback( vlc_object_t *p_object, char const *psz_var, vlc_mutex_unlock( &p_spu->subpicture_lock ); return VLC_SUCCESS; } + +static int sub_filter_allocation_init( filter_t *p_filter, void *p_data ) +{ + spu_t *p_spu = (spu_t *)p_data; + + p_filter->pf_sub_buffer_new = sub_new_buffer; + p_filter->pf_sub_buffer_del = sub_del_buffer; + + filter_owner_sys_t *p_sys = malloc( sizeof(filter_owner_sys_t) ); + if( !p_sys ) return VLC_EGENERIC; + + p_filter->p_owner = p_sys; + spu_Control( p_spu, SPU_CHANNEL_REGISTER, &p_sys->i_channel ); + p_sys->p_spu = p_spu; + + return VLC_SUCCESS; +} + +static void sub_filter_allocation_clear( filter_t *p_filter ) +{ + free( p_filter->p_owner ); +}