From c6b73779878a2e152a40e644bb2029c2c3f41056 Mon Sep 17 00:00:00 2001 From: Gildas Bazin Date: Fri, 17 Sep 2004 09:11:50 +0000 Subject: [PATCH] * src/video_output/vout_subpictures.c: support for subpictures filters. * src/libvlc.h: new --sub-filter config option + added a new subpictures category that regroups all the subpictures options. --- include/vlc_filter.h | 7 +- include/vlc_spu.h | 9 ++- modules/misc/freetype.c | 4 +- modules/stream_out/transcode.c | 3 +- src/libvlc.h | 113 +++++++++++++++++----------- src/video_output/video_output.c | 4 +- src/video_output/vout_subpictures.c | 89 ++++++++++++++++++++-- 7 files changed, 168 insertions(+), 61 deletions(-) diff --git a/include/vlc_filter.h b/include/vlc_filter.h index f032946fd5..b6e2251ede 100644 --- a/include/vlc_filter.h +++ b/include/vlc_filter.h @@ -57,8 +57,7 @@ struct filter_t picture_t *, picture_t *, int, int ); - subpicture_t * ( *pf_subpicture_filter ) ( filter_t * ); - + subpicture_t * ( *pf_sub_filter ) ( filter_t *, mtime_t ); subpicture_t * ( *pf_render_string ) ( filter_t *, block_t * ); /* @@ -75,8 +74,8 @@ struct filter_t void ( * pf_picture_unlink) ( filter_t *, picture_t * ); /* SPU output callbacks */ - subpicture_t * ( * pf_spu_buffer_new) ( filter_t * ); - void ( * pf_spu_buffer_del) ( filter_t *, subpicture_t * ); + subpicture_t * ( * pf_sub_buffer_new) ( filter_t * ); + void ( * pf_sub_buffer_del) ( filter_t *, subpicture_t * ); /* Private structure for the owner of the decoder */ filter_owner_sys_t *p_owner; diff --git a/include/vlc_spu.h b/include/vlc_spu.h index dfffd86f22..f02dca0b41 100644 --- a/include/vlc_spu.h +++ b/include/vlc_spu.h @@ -52,6 +52,10 @@ struct spu_t uint8_t pi_alpha[4]; /**< forced alpha palette */ int ( *pf_control ) ( spu_t *, int, va_list ); + + /* Supciture filters */ + filter_t *pp_filter[10]; + int i_filter; }; static inline int spu_vaControl( spu_t *p_spu, int i_query, va_list args ) @@ -83,8 +87,9 @@ enum spu_query_e * \addtogroup subpicture * @{ */ -#define spu_Init(a) __spu_Init(VLC_OBJECT(a)) -VLC_EXPORT( spu_t *, __spu_Init, ( vlc_object_t * ) ); +#define spu_Create(a) __spu_Create(VLC_OBJECT(a)) +VLC_EXPORT( spu_t *, __spu_Create, ( vlc_object_t * ) ); +VLC_EXPORT( int, spu_Init, ( spu_t * ) ); VLC_EXPORT( void, spu_Destroy, ( spu_t * ) ); void spu_Attach( spu_t *, vlc_object_t *, vlc_bool_t ); diff --git a/modules/misc/freetype.c b/modules/misc/freetype.c index e1599ad9ff..0acceb6095 100644 --- a/modules/misc/freetype.c +++ b/modules/misc/freetype.c @@ -419,7 +419,7 @@ static subpicture_t *RenderText( filter_t *p_filter, block_t *p_block ) line.yMax = 0; /* Create and initialize a subpicture */ - p_subpic = p_filter->pf_spu_buffer_new( p_filter ); + p_subpic = p_filter->pf_sub_buffer_new( p_filter ); if( !p_subpic ) goto error; p_subpic->i_start = p_block->i_pts; @@ -601,7 +601,7 @@ static subpicture_t *RenderText( filter_t *p_filter, block_t *p_block ) error: FreeString( p_string ); - if( p_subpic ) p_filter->pf_spu_buffer_del( p_filter, p_subpic ); + if( p_subpic ) p_filter->pf_sub_buffer_del( p_filter, p_subpic ); block_Release( p_block ); return NULL; } diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c index bdaa17281f..cde12c19a6 100644 --- a/modules/stream_out/transcode.c +++ b/modules/stream_out/transcode.c @@ -1820,7 +1820,8 @@ static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id ) } else if( !p_sys->p_spu ) { - p_sys->p_spu = spu_Init( p_stream ); + p_sys->p_spu = spu_Create( p_stream ); + spu_Init( p_sys->p_spu ); } return VLC_SUCCESS; diff --git a/src/libvlc.h b/src/libvlc.h index 9f9a6c8b45..896f5a3d7b 100644 --- a/src/libvlc.h +++ b/src/libvlc.h @@ -232,16 +232,6 @@ static char *ppsz_align_descriptions[] = #define VIDEO_ON_TOP_LONGTEXT N_("Always place the video window on top of " \ "other windows." ) -#define SPUMARGIN_TEXT N_("Force SPU position") -#define SPUMARGIN_LONGTEXT N_( \ - "You can use this option to place the subtitles under the movie, " \ - "instead of over the movie. Try several positions.") - -#define OSD_TEXT N_("On Screen Display") -#define OSD_LONGTEXT N_( \ - "VLC can display messages on the video. This is called OSD (On Screen " \ - "Display). You can disable this feature here.") - #define FILTER_TEXT N_("Video filter module") #define FILTER_LONGTEXT N_( \ "This will allow you to add a post-processing filter to enhance the " \ @@ -299,12 +289,12 @@ static char *ppsz_align_descriptions[] = #define INPUT_CHAN_TEXT N_("Choose audio channel") #define INPUT_CHAN_LONGTEXT N_( \ "Give the stream number of the audio channel you want to use in a DVD " \ - "(from 1 to n).") + "(from 0 to n).") -#define INPUT_SUBT_TEXT N_("Choose subtitle track") -#define INPUT_SUBT_LONGTEXT N_( \ +#define INPUT_SUB_TEXT N_("Choose subtitle track") +#define INPUT_SUB_LONGTEXT N_( \ "Give the stream number of the subtitle channel you want to use " \ - "(from 1 to n).") + "(from 0 to n).") #define INPUT_REPEAT_TEXT N_("Number of time the same input will be repeated") #define INPUT_REPEAT_LONGTEXT N_("Number of time the same input will be repeated") @@ -323,6 +313,28 @@ static char *ppsz_align_descriptions[] = "the form \"{name=bookmark-name,time=optional-time-offset," \ "bytes=optional-byte-offset},{etc...}\"") +#define SUB_CAT_LONGTEXT N_( \ + "These options allow you to modify the behavior of the subpictures " \ + "subsystem. You can for example enable subpictures filters (logo, ...). " \ + "Enable these filters here and configure them in the " \ + "\"subpictures filters\" modules section. You can also set many " \ + "miscellaneous subpictures options." ) + +#define SPUMARGIN_TEXT N_("Force SPU position") +#define SPUMARGIN_LONGTEXT N_( \ + "You can use this option to place the subtitles under the movie, " \ + "instead of over the movie. Try several positions.") + +#define OSD_TEXT N_("On Screen Display") +#define OSD_LONGTEXT N_( \ + "VLC can display messages on the video. This is called OSD (On Screen " \ + "Display). You can disable this feature here.") + +#define SUB_FILTER_TEXT N_("Subpictures filter module") +#define SUB_FILTER_LONGTEXT N_( \ + "This will allow you to add a subpictures filter for instance to overlay "\ + "a logo.") + #define SUB_AUTO_TEXT N_("Autodetect subtitle files") #define SUB_AUTO_LONGTEXT \ N_("Automatically detect a subtitle file, if no subtitle filename is " \ @@ -795,17 +807,19 @@ vlc_module_begin(); add_integer_with_range( "saved-volume", AOUT_VOLUME_DEFAULT, AOUT_VOLUME_MIN, AOUT_VOLUME_MAX, NULL, VOLUME_SAVE_TEXT, VOLUME_SAVE_LONGTEXT, VLC_TRUE ); - add_integer( "aout-rate", -1, NULL, AOUT_RATE_TEXT, AOUT_RATE_LONGTEXT, VLC_TRUE ); + add_integer( "aout-rate", -1, NULL, AOUT_RATE_TEXT, + AOUT_RATE_LONGTEXT, VLC_TRUE ); #if !defined( SYS_DARWIN ) - add_bool( "hq-resampling", 1, NULL, AOUT_RESAMP_TEXT, AOUT_RESAMP_LONGTEXT, VLC_TRUE ); + add_bool( "hq-resampling", 1, NULL, AOUT_RESAMP_TEXT, + AOUT_RESAMP_LONGTEXT, VLC_TRUE ); #endif add_bool( "spdif", 0, NULL, SPDIF_TEXT, SPDIF_LONGTEXT, VLC_FALSE ); - add_integer( "audio-desync", 0, NULL, DESYNC_TEXT, DESYNC_LONGTEXT, VLC_TRUE ); - add_string("audio-filter",0,NULL,AUDIO_FILTER_TEXT, - AUDIO_FILTER_LONGTEXT,VLC_FALSE); + add_integer( "audio-desync", 0, NULL, DESYNC_TEXT, + DESYNC_LONGTEXT, VLC_TRUE ); + add_string( "audio-filter", 0, NULL,AUDIO_FILTER_TEXT, + AUDIO_FILTER_LONGTEXT, VLC_FALSE ); add_module( "audio-channel-mixer", "audio filter", NULL, NULL, - AUDIO_CHANNEL_MIXER, AUDIO_CHANNEL_MIXER_LONGTEXT, - VLC_FALSE ); + AUDIO_CHANNEL_MIXER, AUDIO_CHANNEL_MIXER_LONGTEXT, VLC_FALSE ); /* Video options */ add_category_hint( N_("Video"), VOUT_CAT_LONGTEXT , VLC_FALSE ); @@ -822,17 +836,17 @@ vlc_module_begin(); add_integer( "align", 0, NULL, ALIGN_TEXT, ALIGN_LONGTEXT, VLC_TRUE ); change_integer_list( pi_align_values, ppsz_align_descriptions, 0 ); add_float( "zoom", 1, NULL, ZOOM_TEXT, ZOOM_LONGTEXT, VLC_TRUE ); - add_bool( "grayscale", 0, NULL, GRAYSCALE_TEXT, GRAYSCALE_LONGTEXT, VLC_TRUE ); + add_bool( "grayscale", 0, NULL, GRAYSCALE_TEXT, + GRAYSCALE_LONGTEXT, VLC_TRUE ); add_bool( "fullscreen", 0, NULL, FULLSCREEN_TEXT, - FULLSCREEN_LONGTEXT, VLC_FALSE ); + FULLSCREEN_LONGTEXT, VLC_FALSE ); + change_short('F'); #ifndef SYS_DARWIN add_bool( "overlay", 1, NULL, OVERLAY_TEXT, OVERLAY_LONGTEXT, VLC_TRUE ); #endif - add_bool( "video-on-top", 0, NULL, VIDEO_ON_TOP_TEXT, VIDEO_ON_TOP_LONGTEXT, VLC_FALSE ); - add_integer( "spumargin", -1, NULL, SPUMARGIN_TEXT, - SPUMARGIN_LONGTEXT, VLC_TRUE ); - add_bool( "osd", 1, NULL, OSD_TEXT, OSD_LONGTEXT, VLC_FALSE ); + add_bool( "video-on-top", 0, NULL, VIDEO_ON_TOP_TEXT, + VIDEO_ON_TOP_LONGTEXT, VLC_FALSE ); add_module( "filter", "video filter", NULL, NULL, FILTER_TEXT, FILTER_LONGTEXT, VLC_FALSE ); add_string( "aspect-ratio", "", NULL, @@ -841,6 +855,27 @@ vlc_module_begin(); add_string( "pixel-ratio", "1", NULL, PIXEL_RATIO_TEXT, PIXEL_RATIO_TEXT ); #endif + /* Subpictures options */ + add_category_hint( N_("Subpictures"), SUB_CAT_LONGTEXT , VLC_FALSE ); + add_bool( "osd", 1, NULL, OSD_TEXT, OSD_LONGTEXT, VLC_FALSE ); + add_bool( "sub-autodetect-file", VLC_TRUE, NULL, + SUB_AUTO_TEXT, SUB_AUTO_LONGTEXT, VLC_FALSE ); + add_integer( "sub-autodetect-fuzzy", 3, NULL, + SUB_FUZZY_TEXT, SUB_FUZZY_LONGTEXT, VLC_TRUE ); +#ifdef WIN32 +# define SUB_PATH ".\\subtitles" +#else +# define SUB_PATH "./Subtitles, ./subtitles" +#endif + add_string( "sub-autodetect-path", SUB_PATH, NULL, + SUB_PATH_TEXT, SUB_PATH_LONGTEXT, VLC_TRUE ); + add_file( "sub-file", NULL, NULL, SUB_FILE_TEXT, + SUB_FILE_LONGTEXT, VLC_TRUE ); + add_integer( "spumargin", -1, NULL, SPUMARGIN_TEXT, + SPUMARGIN_LONGTEXT, VLC_TRUE ); + add_module( "sub-filter", "subpicture filter", NULL, NULL, + SUB_FILTER_TEXT, SUB_FILTER_LONGTEXT, VLC_TRUE ); + /* Input options */ add_category_hint( N_("Input"), INPUT_CAT_LONGTEXT , VLC_FALSE ); add_integer( "cr-average", 40, NULL, CR_AVERAGE_TEXT, @@ -848,7 +883,8 @@ vlc_module_begin(); add_integer( "server-port", 1234, NULL, SERVER_PORT_TEXT, SERVER_PORT_LONGTEXT, VLC_FALSE ); add_integer( "mtu", 1500, NULL, MTU_TEXT, MTU_LONGTEXT, VLC_TRUE ); - add_string( "iface-addr", "", NULL, IFACE_ADDR_TEXT, IFACE_ADDR_LONGTEXT, VLC_TRUE ); + add_string( "iface-addr", "", NULL, IFACE_ADDR_TEXT, + IFACE_ADDR_LONGTEXT, VLC_TRUE ); add_integer( "program", 0, NULL, INPUT_PROGRAM_TEXT, INPUT_PROGRAM_LONGTEXT, VLC_TRUE ); @@ -857,20 +893,7 @@ vlc_module_begin(); add_integer( "audio-channel", -1, NULL, INPUT_CHAN_TEXT, INPUT_CHAN_LONGTEXT, VLC_FALSE ); add_integer( "spu-channel", -1, NULL, - INPUT_SUBT_TEXT, INPUT_SUBT_LONGTEXT, VLC_FALSE ); - add_bool( "sub-autodetect-file", VLC_TRUE, NULL, - SUB_AUTO_TEXT, SUB_AUTO_LONGTEXT, VLC_FALSE ); - add_integer( "sub-autodetect-fuzzy", 3, NULL, - SUB_FUZZY_TEXT, SUB_FUZZY_LONGTEXT, VLC_TRUE ); -#ifdef WIN32 -# define SUB_PATH ".\\subtitles" -#else -# define SUB_PATH "./Subtitles, ./subtitles" -#endif - add_string( "sub-autodetect-path", SUB_PATH, NULL, - SUB_PATH_TEXT, SUB_PATH_LONGTEXT, VLC_TRUE ); - add_file( "sub-file", NULL, NULL, - SUB_FILE_TEXT, SUB_FILE_LONGTEXT, VLC_TRUE ); + INPUT_SUB_TEXT, INPUT_SUB_LONGTEXT, VLC_FALSE ); add_integer( "input-repeat", 0, NULL, INPUT_REPEAT_TEXT, INPUT_REPEAT_LONGTEXT, VLC_TRUE ); add_integer( "start-time", 0, NULL, @@ -914,8 +937,10 @@ vlc_module_begin(); /* Decoder options */ add_category_hint( N_("Decoders"), CODEC_CAT_LONGTEXT , VLC_TRUE ); - add_module( "codec", "decoder", NULL, NULL, CODEC_TEXT, CODEC_LONGTEXT, VLC_TRUE ); - add_module( "encoder", "encoder", NULL, NULL, ENCODER_TEXT, ENCODER_LONGTEXT, VLC_TRUE ); + add_module( "codec", "decoder", NULL, NULL, CODEC_TEXT, + CODEC_LONGTEXT, VLC_TRUE ); + add_module( "encoder", "encoder", NULL, NULL, ENCODER_TEXT, + ENCODER_LONGTEXT, VLC_TRUE ); /* Stream output options */ diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index a4a1736e52..5bdbb12b85 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -287,12 +287,14 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, var_Create( p_vout, "mouse-clicked", VLC_VAR_INTEGER ); /* Initialize subpicture unit */ - p_vout->p_spu = spu_Init( p_vout ); + p_vout->p_spu = spu_Create( p_vout ); spu_Attach( p_vout->p_spu, p_parent, VLC_TRUE ); /* Attach the new object now so we can use var inheritance below */ vlc_object_attach( p_vout, p_parent ); + spu_Init( p_vout->p_spu ); + /* Take care of some "interface/control" related initialisations */ vout_IntfInit( p_vout ); diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c index 725e0823e3..2515b99e7b 100644 --- a/src/video_output/vout_subpictures.c +++ b/src/video_output/vout_subpictures.c @@ -46,17 +46,19 @@ static void UpdateSPU ( spu_t *, vlc_object_t * ); static int CropCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); +static subpicture_t *sub_new_buffer( filter_t * ); +static void sub_del_buffer( filter_t *, subpicture_t * ); static subpicture_t *spu_new_buffer( filter_t * ); static void spu_del_buffer( filter_t *, subpicture_t * ); static picture_t *spu_new_video_buffer( filter_t * ); static void spu_del_video_buffer( filter_t *, picture_t * ); /** - * Initialise the subpicture unit + * Creates the subpicture unit * * \param p_this the parent object which creates the subpicture unit */ -spu_t *__spu_Init( vlc_object_t *p_this ) +spu_t *__spu_Create( vlc_object_t *p_this ) { int i_index; spu_t *p_spu = vlc_object_create( p_this, VLC_OBJECT_SPU ); @@ -70,6 +72,7 @@ spu_t *__spu_Init( 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; /* Register the default subpicture channel */ p_spu->i_channel = 1; @@ -78,10 +81,50 @@ spu_t *__spu_Init( vlc_object_t *p_this ) vlc_object_attach( p_spu, p_this ); + return p_spu; +} + +/** + * Initialise the subpicture unit + * + * \param p_spu the subpicture unit object + */ +int spu_Init( spu_t *p_spu ) +{ + char *psz_filter, *psz_filter_orig; + vlc_value_t val; + /* If the user requested an SPU margin, we force the position. */ - p_spu->i_margin = config_GetInt( p_spu, "spumargin" ); + var_Create( p_spu, "spumargin", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Get( p_spu, "spumargin", &val ); + 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 ); + psz_filter = psz_filter_orig = val.psz_string; + if( psz_filter && *psz_filter ) + { + 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_owner = + (filter_owner_sys_t *)p_spu; + p_spu->pp_filter[p_spu->i_filter]->p_module = + module_Need( p_spu->pp_filter[p_spu->i_filter], + "subpicture filter", psz_filter, 0 ); + if( p_spu->pp_filter[p_spu->i_filter]->p_module ) p_spu->i_filter++; + else + { + msg_Dbg( p_spu, "no subpicture filter found" ); + vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] ); + vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] ); + } + } + if( psz_filter_orig ) free( psz_filter_orig ); - return p_spu; + return VLC_EGENERIC; } /** @@ -131,6 +174,14 @@ void spu_Destroy( spu_t *p_spu ) vlc_object_destroy( p_spu->p_scale ); } + 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 ); + 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 ); } @@ -401,8 +452,8 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, p_spu->p_text->fmt_out.video.i_visible_height = p_fmt->i_height; - p_spu->p_text->pf_spu_buffer_new = spu_new_buffer; - p_spu->p_text->pf_spu_buffer_del = spu_del_buffer; + p_spu->p_text->pf_sub_buffer_new = spu_new_buffer; + p_spu->p_text->pf_sub_buffer_del = spu_del_buffer; p_spu->p_text->p_module = module_Need( p_spu->p_text, "text renderer", 0, 0 ); @@ -473,7 +524,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, *p_region = *p_subpic_tmp->p_region; p_region->p_next = tmp_region.p_next; *p_subpic_tmp->p_region = tmp_region; - p_spu->p_text->pf_spu_buffer_del( p_spu->p_text, + p_spu->p_text->pf_sub_buffer_del( p_spu->p_text, p_subpic_tmp ); } } @@ -670,6 +721,18 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date ) subpicture_t *p_ephemer = NULL; mtime_t ephemer_date = 0; + /* 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 ); + } + } + /* We get an easily parsable chained list of subpictures which * ends with NULL since p_subpic was initialized to NULL. */ for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ ) @@ -905,6 +968,18 @@ static int CropCallback( vlc_object_t *p_object, char const *psz_var, /***************************************************************************** * Buffers allocation callbacks for the filters *****************************************************************************/ +static subpicture_t *sub_new_buffer( filter_t *p_filter ) +{ + spu_t *p_spu = (spu_t *)p_filter->p_owner; + return spu_CreateSubpicture( p_spu ); +} + +static void sub_del_buffer( filter_t *p_filter, subpicture_t *p_subpic ) +{ + spu_t *p_spu = (spu_t *)p_filter->p_owner; + spu_DestroySubpicture( p_spu, p_subpic ); +} + static subpicture_t *spu_new_buffer( filter_t *p_filter ) { subpicture_t *p_subpic = (subpicture_t *)malloc(sizeof(subpicture_t)); -- 2.39.2