X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvideo_output.c;h=67f16216e0862cf3a91cef50e4f500542668ce5e;hb=f0c83daa831d070058e04142791eb9d9d0423e0b;hp=30a091775858193d88db6cd9e67623146a30d8fb;hpb=b71fdec3e886d080214779e374bb98aec8fc1f91;p=vlc diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 30a0917758..67f16216e0 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -5,7 +5,7 @@ * It includes functions allowing to open a new thread, send pictures to a * thread, and destroy a previously oppened video output thread. ***************************************************************************** - * Copyright (C) 2000-2004 the VideoLAN team + * Copyright (C) 2000-2007 the VideoLAN team * $Id$ * * Authors: Vincent Seguin @@ -29,6 +29,10 @@ /***************************************************************************** * Preamble *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include /* free() */ @@ -53,6 +57,8 @@ * helpers */ #include "input/input_internal.h" +#include "modules/modules.h" + /***************************************************************************** * Local prototypes *****************************************************************************/ @@ -60,12 +66,13 @@ static int InitThread ( vout_thread_t * ); static void RunThread ( vout_thread_t * ); static void ErrorThread ( vout_thread_t * ); static void EndThread ( vout_thread_t * ); -static void DestroyThread ( vout_thread_t * ); static void AspectRatio ( int, int *, int * ); static int BinaryLog ( uint32_t ); static void MaskToShift ( int *, int *, uint32_t ); +static void vout_Destructor ( vlc_object_t * p_this ); + /* Object variables callbacks */ static int DeinterlaceCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); @@ -81,6 +88,9 @@ int vout_Snapshot( vout_thread_t *, picture_t * ); static int ParseVideoFilter2Chain( vout_thread_t *, char * ); static void RemoveVideoFilters2( vout_thread_t *p_vout ); +/* Display media title in OSD */ +static void DisplayTitleOnOSD( vout_thread_t *p_vout ); + /***************************************************************************** * Video Filter2 functions *****************************************************************************/ @@ -118,11 +128,9 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout, /* Reattach video output to playlist before bailing out */ if( p_vout ) { - playlist_t *p_playlist = pl_Yield( p_this ); - spu_Attach( p_vout->p_spu, p_this, VLC_FALSE ); + spu_Attach( p_vout->p_spu, p_this, false ); vlc_object_detach( p_vout ); - vlc_object_attach( p_vout, p_playlist ); - pl_Release( p_this ); + vlc_object_attach( p_vout, p_this->p_libvlc ); } return NULL; } @@ -138,18 +146,16 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout, if( !p_vout ) { - playlist_t *p_playlist = pl_Yield( p_this ); - vlc_mutex_lock( &p_playlist->gc_lock ); - p_vout = vlc_object_find( p_playlist, + p_vout = vlc_object_find( p_this->p_libvlc, VLC_OBJECT_VOUT, FIND_CHILD ); /* only first children of p_input for unused vout */ - if( p_vout && p_vout->p_parent != (vlc_object_t *)p_playlist ) + if( p_vout && p_vout->p_parent != VLC_OBJECT(p_this->p_libvlc) ) { vlc_object_release( p_vout ); p_vout = NULL; } - vlc_mutex_unlock( &p_playlist->gc_lock ); - pl_Release( p_this ); + if( p_vout ) + vlc_object_detach( p_vout ); /* Remove it from the GC */ } } @@ -179,20 +185,18 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout, if( !psz_filter_chain && !p_vout->psz_filter_chain ) { - p_vout->b_filter_change = VLC_FALSE; + p_vout->b_filter_change = false; } - if( psz_filter_chain ) free( psz_filter_chain ); + free( psz_filter_chain ); } if( ( p_vout->fmt_render.i_width != p_fmt->i_width ) || ( p_vout->fmt_render.i_height != p_fmt->i_height ) || - ( p_vout->fmt_render.i_chroma != p_fmt->i_chroma ) || ( p_vout->fmt_render.i_aspect != p_fmt->i_aspect ) || p_vout->b_filter_change ) { /* We are not interested in this format, close this vout */ - vlc_object_detach( p_vout ); vlc_object_release( p_vout ); vout_Destroy( p_vout ); p_vout = NULL; @@ -200,9 +204,10 @@ vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout, else { /* This video output is cool! Hijack it. */ - vlc_object_detach( p_vout ); - spu_Attach( p_vout->p_spu, p_this, VLC_TRUE ); + spu_Attach( p_vout->p_spu, p_this, true ); vlc_object_attach( p_vout, p_this ); + if( p_vout->b_title_show ) + DisplayTitleOnOSD( p_vout ); vlc_object_release( p_vout ); } } @@ -228,7 +233,6 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) vout_thread_t * p_vout; /* thread descriptor */ input_thread_t * p_input_thread; int i_index; /* loop variable */ - char * psz_plugin; vlc_value_t val, text; unsigned int i_width = p_fmt->i_width; @@ -236,6 +240,10 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) vlc_fourcc_t i_chroma = p_fmt->i_chroma; unsigned int i_aspect = p_fmt->i_aspect; + config_chain_t *p_cfg; + char *psz_parser; + char *psz_name; + /* Allocate descriptor */ p_vout = vlc_object_create( p_parent, VLC_OBJECT_VOUT ); if( p_vout == NULL ) @@ -308,6 +316,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) /* Initialize locks */ vlc_mutex_init( p_vout, &p_vout->picture_lock ); vlc_mutex_init( p_vout, &p_vout->change_lock ); + vlc_mutex_init( p_vout, &p_vout->vfilter_lock ); /* Mouse coordinates */ var_Create( p_vout, "mouse-x", VLC_VAR_INTEGER ); @@ -318,7 +327,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) /* Initialize subpicture unit */ p_vout->p_spu = spu_Create( p_vout ); - spu_Attach( p_vout->p_spu, p_parent, VLC_TRUE ); + spu_Attach( p_vout->p_spu, p_parent, true ); /* Attach the new object now so we can use var inheritance below */ vlc_object_attach( p_vout, p_parent ); @@ -347,12 +356,15 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) else { /* continue the parent's filter chain */ - char *psz_end; + char *psz_tmp; - psz_end = strchr( ((vout_thread_t *)p_parent)->psz_filter_chain, ':' ); - if( psz_end && *(psz_end+1) ) - p_vout->psz_filter_chain = strdup( psz_end+1 ); - else p_vout->psz_filter_chain = NULL; + /* Ugly hack to jump to our configuration chain */ + p_vout->psz_filter_chain + = ((vout_thread_t *)p_parent)->psz_filter_chain; + p_vout->psz_filter_chain + = config_ChainCreate( &psz_tmp, &p_cfg, p_vout->psz_filter_chain ); + config_ChainDestroy( p_cfg ); + free( psz_tmp ); /* Create a video filter2 var ... but don't inherit values */ var_Create( p_vout, "video-filter", VLC_VAR_STRING ); @@ -360,7 +372,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) } var_AddCallback( p_vout, "video-filter", VideoFilter2Callback, NULL ); - p_vout->b_vfilter_change = VLC_TRUE; + p_vout->b_vfilter_change = true; p_vout->i_vfilters = 0; /* Choose the video output module */ @@ -368,32 +380,27 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) { var_Create( p_vout, "vout", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_vout, "vout", &val ); - psz_plugin = val.psz_string; + psz_parser = val.psz_string; } else { - /* the filter chain is a string list of filters separated by double - * colons */ - char *psz_end; - - psz_end = strchr( p_vout->psz_filter_chain, ':' ); - if( psz_end ) - psz_plugin = strndup( p_vout->psz_filter_chain, - psz_end - p_vout->psz_filter_chain ); - else psz_plugin = strdup( p_vout->psz_filter_chain ); + psz_parser = strdup( p_vout->psz_filter_chain ); } /* Create the vout thread */ + config_ChainCreate( &psz_name, &p_cfg, psz_parser ); + free( psz_parser ); + p_vout->p_cfg = p_cfg; p_vout->p_module = module_Need( p_vout, ( p_vout->psz_filter_chain && *p_vout->psz_filter_chain ) ? - "video filter" : "video output", psz_plugin, 0 ); + "video filter" : "video output", psz_name, p_vout->psz_filter_chain && *p_vout->psz_filter_chain ); + free( psz_name ); - if( psz_plugin ) free( psz_plugin ); if( p_vout->p_module == NULL ) { msg_Err( p_vout, "no suitable vout module" ); vlc_object_detach( p_vout ); - vlc_object_destroy( p_vout ); + vlc_object_release( p_vout ); return NULL; } @@ -419,11 +426,10 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) if( var_Get( p_vout, "deinterlace-mode", &val ) == VLC_SUCCESS ) { var_Set( p_vout, "deinterlace", val ); - if( val.psz_string ) free( val.psz_string ); + free( val.psz_string ); } var_AddCallback( p_vout, "deinterlace", DeinterlaceCallback, NULL ); - var_Create( p_vout, "vout-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); text.psz_string = _("Filters"); var_Change( p_vout, "vout-filter", VLC_VAR_SETTEXT, &text, NULL ); @@ -443,12 +449,11 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) } if( vlc_thread_create( p_vout, "video output", RunThread, - VLC_THREAD_PRIORITY_OUTPUT, VLC_TRUE ) ) + VLC_THREAD_PRIORITY_OUTPUT, true ) ) { msg_Err( p_vout, "out of memory" ); module_Unneed( p_vout, p_vout->p_module ); - vlc_object_detach( p_vout ); - vlc_object_destroy( p_vout ); + vlc_object_release( p_vout ); return NULL; } @@ -457,15 +462,12 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) msg_Err( p_vout, "video output creation failed" ); /* Make sure the thread is destroyed */ - p_vout->b_die = VLC_TRUE; - - vlc_thread_join( p_vout ); - - vlc_object_detach( p_vout ); - vlc_object_destroy( p_vout ); + vlc_object_release( p_vout ); return NULL; } + vlc_object_set_destructor( p_vout, vout_Destructor ); + return p_vout; } @@ -479,38 +481,55 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) *****************************************************************************/ void vout_Destroy( vout_thread_t *p_vout ) { - vout_thread_t *p_another_vout; - playlist_t *p_playlist = pl_Yield( p_vout ); + /* XXX: should go in the destructor */ + var_Destroy( p_vout, "intf-change" ); - /* Request thread destruction */ - p_vout->b_die = VLC_TRUE; - vlc_thread_join( p_vout ); + vlc_object_release( p_vout ); +} - var_Destroy( p_vout, "intf-change" ); +static void vout_Destructor( vlc_object_t * p_this ) +{ + vout_thread_t *p_vout = (vout_thread_t *)p_this; - if( p_vout->psz_filter_chain ) free( p_vout->psz_filter_chain ); + /* Destroy the locks */ + vlc_mutex_destroy( &p_vout->picture_lock ); + vlc_mutex_destroy( &p_vout->change_lock ); + vlc_mutex_destroy( &p_vout->vfilter_lock ); - /* Free structure */ - vlc_object_destroy( p_vout ); -#ifndef __APPLE__ - /* This is a dirty hack for mostly Linux, where there is no way to get the GUI - back if you closed it while playing video. This is solved in Mac OS X, - where we have this novelty called menubar, that will always allow you access - to the applications main functionality. They should try that on linux sometime */ - p_another_vout = vlc_object_find( p_playlist, - VLC_OBJECT_VOUT, FIND_ANYWHERE ); - if( p_another_vout == NULL ) + /* Release the module */ + if( p_vout->p_module ) { - vlc_value_t val; - val.b_bool = VLC_TRUE; - var_Set( p_playlist, "intf-show", val ); + module_Unneed( p_vout, p_vout->p_module ); + } + + free( p_vout->psz_filter_chain ); + + config_ChainDestroy( p_vout->p_cfg ); + +#ifndef __APPLE__ + vout_thread_t *p_another_vout; + + playlist_t *p_playlist = pl_Get( p_vout ); + if( p_playlist->b_die ) return; + vlc_object_yield( p_playlist ); +/* This is a dirty hack for mostly Linux, where there is no way to get the GUI + back if you closed it while playing video. This is solved in Mac OS X, + where we have this novelty called menubar, that will always allow you access + to the applications main functionality. They should try that on linux sometime */ + p_another_vout = vlc_object_find( p_this->p_libvlc, + VLC_OBJECT_VOUT, FIND_ANYWHERE ); + if( p_another_vout == NULL ) + { + vlc_value_t val; + val.b_bool = true; + var_Set( p_playlist, "intf-show", val ); } else { vlc_object_release( p_another_vout ); } -#endif vlc_object_release( p_playlist ); +#endif } /***************************************************************************** @@ -728,7 +747,7 @@ static void RunThread( vout_thread_t *p_vout) input_thread_t *p_input = NULL ; /* Parent input, if it exists */ vlc_value_t val; - vlc_bool_t b_drop_late; + bool b_drop_late; int i_displayed = 0, i_lost = 0, i_loops = 0; @@ -745,11 +764,10 @@ static void RunThread( vout_thread_t *p_vout) vlc_thread_ready( p_vout ); if( p_vout->b_error ) - { - /* Destroy thread structures allocated by Create and InitThread */ - DestroyThread( p_vout ); return; - } + + if( p_vout->b_title_show ) + DisplayTitleOnOSD( p_vout ); /* * Main loop - it is not executed if an error occurred during @@ -762,15 +780,7 @@ static void RunThread( vout_thread_t *p_vout) display_date = 0; current_date = mdate(); - if( p_input && p_input->b_die ) - { - vlc_object_release( p_input ); - p_input = NULL; - } - i_loops++; - if( i_loops % 20 == 0 ) - { if( !p_input ) { p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, @@ -786,8 +796,9 @@ static void RunThread( vout_thread_t *p_vout) i_displayed , NULL); i_displayed = i_lost = 0; vlc_mutex_unlock( &p_input->p->counters.counters_lock ); + vlc_object_release( p_input ); + p_input = NULL; } - } #if 0 p_vout->c_loops++; if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) ) @@ -872,7 +883,7 @@ static void RunThread( vout_thread_t *p_vout) p_picture->i_status = DESTROYED_PICTURE; p_vout->i_heap_size--; } - msg_Warn( p_vout, "late picture skipped ("I64Fd")", + msg_Warn( p_vout, "late picture skipped (%"PRId64")", current_date - display_date ); i_lost++; vlc_mutex_unlock( &p_vout->picture_lock ); @@ -899,7 +910,7 @@ static void RunThread( vout_thread_t *p_vout) } i_lost++; msg_Warn( p_vout, "vout warning: early picture skipped " - "("I64Fd")", display_date - current_date + "(%"PRId64")", display_date - current_date - p_vout->i_pts_delay ); vlc_mutex_unlock( &p_vout->picture_lock ); @@ -939,9 +950,10 @@ static void RunThread( vout_thread_t *p_vout) } /* Video Filter2 stuff */ - if( p_vout->b_vfilter_change == VLC_TRUE ) + if( p_vout->b_vfilter_change == true ) { int i; + vlc_mutex_lock( &p_vout->vfilter_lock ); RemoveVideoFilters2( p_vout ); for( i = 0; i < p_vout->i_vfilters_cfg; i++ ) { @@ -968,7 +980,8 @@ static void RunThread( vout_thread_t *p_vout) p_vfilter->p_cfg = p_vout->p_vfilters_cfg[i]; p_vfilter->p_module = module_Need( p_vfilter, "video filter2", - p_vout->psz_vfilters[i], 0 ); + p_vout->psz_vfilters[i], + true ); if( p_vfilter->p_module ) { @@ -984,10 +997,11 @@ static void RunThread( vout_thread_t *p_vout) msg_Err( p_vout, "no video filter found (%s)", p_vout->psz_vfilters[i] ); vlc_object_detach( p_vfilter ); - vlc_object_destroy( p_vfilter ); + vlc_object_release( p_vfilter ); } } - p_vout->b_vfilter_change = VLC_FALSE; + p_vout->b_vfilter_change = false; + vlc_mutex_unlock( &p_vout->vfilter_lock ); } if( p_picture ) @@ -1024,7 +1038,7 @@ static void RunThread( vout_thread_t *p_vout) if( p_picture && p_vout->b_snapshot ) { - p_vout->b_snapshot = VLC_FALSE; + p_vout->b_snapshot = false; vout_Snapshot( p_vout, p_picture ); } @@ -1039,7 +1053,10 @@ static void RunThread( vout_thread_t *p_vout) FIND_PARENT ); } p_subpic = spu_SortSubpictures( p_vout->p_spu, display_date, - p_input ? var_GetBool( p_input, "state" ) == PAUSE_S : VLC_FALSE ); + p_input ? var_GetBool( p_input, "state" ) == PAUSE_S : false ); + if( p_input ) + vlc_object_release( p_input ); + p_input = NULL; } /* @@ -1203,9 +1220,6 @@ static void RunThread( vout_thread_t *p_vout) /* End of thread */ EndThread( p_vout ); - - /* Destroy thread structures allocated by CreateThread */ - DestroyThread( p_vout ); } /***************************************************************************** @@ -1260,7 +1274,7 @@ static void EndThread( vout_thread_t *p_vout ) } /* Destroy subpicture unit */ - spu_Attach( p_vout->p_spu, VLC_OBJECT(p_vout), VLC_FALSE ); + spu_Attach( p_vout->p_spu, VLC_OBJECT(p_vout), false ); spu_Destroy( p_vout->p_spu ); /* Destroy the video filters2 */ @@ -1273,25 +1287,6 @@ static void EndThread( vout_thread_t *p_vout ) vlc_mutex_unlock( &p_vout->change_lock ); } -/***************************************************************************** - * DestroyThread: thread destruction - ***************************************************************************** - * This function is called when the thread ends. It frees all ressources - * allocated by CreateThread. Status is available at this stage. - *****************************************************************************/ -static void DestroyThread( vout_thread_t *p_vout ) -{ - /* Destroy the locks */ - vlc_mutex_destroy( &p_vout->picture_lock ); - vlc_mutex_destroy( &p_vout->change_lock ); - - /* Release the module */ - if( p_vout && p_vout->p_module ) - { - module_Unneed( p_vout, p_vout->p_module ); - } -} - /* following functions are local */ static int ReduceHeight( int i_ratio ) @@ -1392,12 +1387,13 @@ static void MaskToShift( int *pi_left, int *pi_right, uint32_t i_mask ) * vout_VarCallback: generic callback for intf variables *****************************************************************************/ int vout_VarCallback( vlc_object_t * p_this, const char * psz_variable, - vlc_value_t old_value, vlc_value_t new_value, - void * unused ) + vlc_value_t oldval, vlc_value_t newval, + void *p_data ) { vout_thread_t * p_vout = (vout_thread_t *)p_this; vlc_value_t val; - val.b_bool = VLC_TRUE; + (void)psz_variable; (void)newval; (void)oldval; (void)p_data; + val.b_bool = true; var_Set( p_vout, "intf-change", val ); return VLC_SUCCESS; } @@ -1431,11 +1427,7 @@ static void SuxorRestartVideoES( suxor_thread_t *p_this ) vlc_object_release( p_this->p_input ); -#ifdef WIN32 - CloseHandle( p_this->thread_id ); -#endif - - vlc_object_destroy( p_this ); + vlc_object_release( p_this ); } /***************************************************************************** @@ -1451,6 +1443,7 @@ static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd, char *psz_mode = newval.psz_string; char *psz_filter, *psz_deinterlace = NULL; + (void)psz_cmd; (void)oldval; (void)p_data; var_Get( p_vout, "vout-filter", &val ); psz_filter = val.psz_string; @@ -1486,12 +1479,12 @@ static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd, } vlc_object_release( p_input ); - val.b_bool = VLC_TRUE; + val.b_bool = true; var_Set( p_vout, "intf-change", val ); val.psz_string = psz_filter; var_Set( p_vout, "vout-filter", val ); - if( psz_filter ) free( psz_filter ); + free( psz_filter ); return VLC_SUCCESS; } @@ -1502,6 +1495,7 @@ static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd, vout_thread_t *p_vout = (vout_thread_t *)p_this; input_thread_t *p_input; vlc_value_t val; + (void)psz_cmd; (void)oldval; (void)p_data; p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT ); @@ -1511,7 +1505,7 @@ static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd, return( VLC_EGENERIC ); } - val.b_bool = VLC_TRUE; + val.b_bool = true; var_Set( p_vout, "intf-change", val ); /* Modify input as well because the vout might have to be restarted */ @@ -1527,10 +1521,10 @@ static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd, suxor_thread_t *p_suxor = vlc_object_create( p_vout, sizeof(suxor_thread_t) ); p_suxor->p_input = p_input; - p_vout->b_filter_change = VLC_TRUE; + p_vout->b_filter_change = true; vlc_object_yield( p_input ); vlc_thread_create( p_suxor, "suxor", SuxorRestartVideoES, - VLC_THREAD_PRIORITY_LOW, VLC_FALSE ); + VLC_THREAD_PRIORITY_LOW, false ); } vlc_object_release( p_input ); @@ -1550,6 +1544,7 @@ static int ParseVideoFilter2Chain( vout_thread_t *p_vout, char *psz_vfilters ) p_vout->p_vfilters_cfg[p_vout->i_vfilters_cfg]; config_ChainDestroy( p_cfg ); free( p_vout->psz_vfilters[p_vout->i_vfilters_cfg] ); + p_vout->psz_vfilters[p_vout->i_vfilters_cfg] = NULL; } p_vout->i_vfilters_cfg = 0; if( psz_vfilters && *psz_vfilters ) @@ -1565,7 +1560,7 @@ static int ParseVideoFilter2Chain( vout_thread_t *p_vout, char *psz_vfilters ) msg_Dbg( p_vout, "adding vfilter: %s", p_vout->psz_vfilters[p_vout->i_vfilters_cfg] ); p_vout->i_vfilters_cfg++; - if( psz_parser && psz_parser ) + if( psz_parser && *psz_parser ) { if( p_vout->i_vfilters_cfg == MAX_VFILTERS ) { @@ -1584,9 +1579,12 @@ static int VideoFilter2Callback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { vout_thread_t *p_vout = (vout_thread_t *)p_this; + (void)psz_cmd; (void)oldval; (void)p_data; + vlc_mutex_lock( &p_vout->vfilter_lock ); ParseVideoFilter2Chain( p_vout, newval.psz_string ); - p_vout->b_vfilter_change = VLC_TRUE; + p_vout->b_vfilter_change = true; + vlc_mutex_unlock( &p_vout->vfilter_lock ); return VLC_SUCCESS; } @@ -1604,7 +1602,73 @@ static void RemoveVideoFilters2( vout_thread_t *p_vout ) } free( p_vout->pp_vfilters[i]->p_owner ); - vlc_object_destroy( p_vout->pp_vfilters[i] ); + vlc_object_release( p_vout->pp_vfilters[i] ); } p_vout->i_vfilters = 0; } + +static void DisplayTitleOnOSD( vout_thread_t *p_vout ) +{ + input_thread_t *p_input; + mtime_t i_now, i_stop; + + p_input = (input_thread_t *)vlc_object_find( p_vout, + VLC_OBJECT_INPUT, FIND_ANYWHERE ); + if( p_input ) + { + i_now = mdate(); + i_stop = i_now + (mtime_t)(p_vout->i_title_timeout * 1000); + char *psz_nowplaying = + input_item_GetNowPlaying( input_GetItem( p_input ) ); + char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) ); + char *psz_name = input_item_GetTitle( input_GetItem( p_input ) ); + if( EMPTY_STR( psz_name ) ) + { + free( psz_name ); + psz_name = input_item_GetName( input_GetItem( p_input ) ); + } + if( !EMPTY_STR( psz_nowplaying ) ) + { + vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, + psz_nowplaying, NULL, + p_vout->i_title_position, + 30 + p_vout->fmt_in.i_width + - p_vout->fmt_in.i_visible_width + - p_vout->fmt_in.i_x_offset, + 20 + p_vout->fmt_in.i_y_offset, + i_now, i_stop ); + } + else if( !EMPTY_STR( psz_artist ) ) + { + char *psz_string = NULL; + if( asprintf( &psz_string, "%s - %s", psz_name, psz_artist ) != -1 ) + { + vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, + psz_string, NULL, + p_vout->i_title_position, + 30 + p_vout->fmt_in.i_width + - p_vout->fmt_in.i_visible_width + - p_vout->fmt_in.i_x_offset, + 20 + p_vout->fmt_in.i_y_offset, + i_now, i_stop ); + free( psz_string ); + } + } + else + { + vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, + psz_name, NULL, + p_vout->i_title_position, + 30 + p_vout->fmt_in.i_width + - p_vout->fmt_in.i_visible_width + - p_vout->fmt_in.i_x_offset, + 20 + p_vout->fmt_in.i_y_offset, + i_now, i_stop ); + } + vlc_object_release( p_input ); + free( psz_artist ); + free( psz_name ); + free( psz_nowplaying ); + } +} +