X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Finput.c;h=cc5e82813212de27d1785821d6f8537a86a7bc99;hb=a5c83dda798f93cc7a76bbb50d89352117e6ec46;hp=9914457420f191c61a33d5db502ceb11a5f11347;hpb=61ee17a85417817e8046fe5373f160f5349cbf07;p=vlc diff --git a/src/input/input.c b/src/input/input.c index 9914457420..cc5e828132 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -43,7 +43,6 @@ #include #include #include -#include #ifdef HAVE_SYS_STAT_H # include @@ -60,7 +59,7 @@ static int RunAndDestroy ( input_thread_t *p_input ); static input_thread_t * Create ( vlc_object_t *, input_item_t *, const char *, bool, sout_instance_t * ); static int Init ( input_thread_t *p_input ); -static void Error ( input_thread_t *p_input ); +static void WaitDie ( input_thread_t *p_input ); static void End ( input_thread_t *p_input ); static void MainLoop( input_thread_t *p_input ); @@ -87,9 +86,6 @@ static void SlaveSeek( input_thread_t *p_input ); static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta ); static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta ); -static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, bool * ); -static void SoutKeep( sout_instance_t * ); - static void DemuxMeta( input_thread_t *p_input, vlc_meta_t *p_meta, demux_t *p_demux ); static void AccessMeta( input_thread_t * p_input, vlc_meta_t *p_meta ); static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment, @@ -116,6 +112,7 @@ static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_atta * - seekable (if you can seek, it doesn't say if 'bar display' has be shown * or not, for that check position != 0.0) * - can-pause + * - teletext-es to get the index of spu track that is teletext --1 if no teletext) * * For intf callback upon changes * - intf-change * - rate-change for when playback rate changes @@ -135,16 +132,16 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, p_input = vlc_custom_create( p_parent, sizeof( *p_input ), VLC_OBJECT_INPUT, input_name ); if( p_input == NULL ) - { - msg_Err( p_parent, "out of memory" ); return NULL; - } /* Construct a nice name for the input timer */ char psz_timer_name[255]; char * psz_name = input_item_GetName( p_item ); snprintf( psz_timer_name, sizeof(psz_timer_name), "input launching for '%s'", psz_name ); + + msg_Dbg( p_input, "Creating an input for '%s'", psz_name); + free( psz_name ); /* Start a timer to mesure how long it takes @@ -169,6 +166,12 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, p_input->b_preparsing = b_quick; p_input->psz_header = psz_header ? strdup( psz_header ) : NULL; + /* Init events */ + vlc_event_manager_t * p_em = &p_input->p->event_manager; + vlc_event_manager_init_with_vlc_object( p_em, p_input ); + vlc_event_manager_register_event_type( p_em, vlc_InputStateChanged ); + vlc_event_manager_register_event_type( p_em, vlc_InputSelectedStreamChanged ); + /* Init Common fields */ p_input->b_eof = false; p_input->b_can_pace_control = true; @@ -185,8 +188,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, TAB_INIT( p_input->p->i_attachment, p_input->p->attachment ); p_input->p->p_es_out = NULL; p_input->p->p_sout = NULL; - p_input->p->b_owns_its_sout = true; - p_input->p->b_sout_keep = false; p_input->p->b_out_pace_control = false; p_input->i_pts_delay = 0; @@ -293,20 +294,17 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, /* */ if( p_sout ) - { p_input->p->p_sout = p_sout; - p_input->p->b_owns_its_sout = false; - } memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) ); vlc_mutex_init( &p_input->p->counters.counters_lock ); - /* Attach only once we are ready */ - vlc_object_attach( p_input, p_parent ); - /* Set the destructor when we are sure we are initialized */ vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor ); + /* Attach only once we are ready */ + vlc_object_attach( p_input, p_parent ); + return p_input; } @@ -317,19 +315,19 @@ static void Destructor( input_thread_t * p_input ) { input_thread_private_t *priv = p_input->p; +#ifndef NDEBUG + char * psz_name = input_item_GetName( p_input->p->input.p_item ); + msg_Dbg( p_input, "Destroying the input for '%s'", psz_name); + free( psz_name ); +#endif + + vlc_event_manager_fini( &p_input->p->event_manager ); + stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING ); stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING ); #ifdef ENABLE_SOUT - if( priv->b_owns_its_sout && priv->p_sout ) - { - if( priv->b_sout_keep ) - SoutKeep( priv->p_sout ); - else - { - sout_DeleteInstance( priv->p_sout ); - priv->p_sout = NULL; - } - } + if( priv->p_sout ) + sout_DeleteInstance( priv->p_sout ); #endif vlc_gc_decref( p_input->p->input.p_item ); @@ -350,15 +348,7 @@ static void Destructor( input_thread_t * p_input ) input_thread_t *__input_CreateThread( vlc_object_t *p_parent, input_item_t *p_item ) { - bool b_sout_keep; - sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep ); - input_thread_t *p_input = __input_CreateThreadExtended( p_parent, p_item, NULL, p_sout ); - - if( !p_input && p_sout ) - SoutKeep( p_sout ); - - p_input->p->b_sout_keep = b_sout_keep; - return p_input; + return __input_CreateThreadExtended( p_parent, p_item, NULL, NULL ); } /* */ @@ -387,7 +377,7 @@ input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent, } /** - * Initialize an input thread and run it. This thread will clean after himself, + * Initialize an input thread and run it. This thread will clean after itself, * you can forget about it. It can work either in blocking or non-blocking mode * * \param p_parent a vlc_object @@ -398,17 +388,11 @@ input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent, int __input_Read( vlc_object_t *p_parent, input_item_t *p_item, bool b_block ) { - bool b_sout_keep; - sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep ); input_thread_t *p_input; - p_input = Create( p_parent, p_item, NULL, false, p_sout ); - if( !p_input && p_sout ) - { - SoutKeep( p_sout ); + p_input = Create( p_parent, p_item, NULL, false, NULL ); + if( !p_input ) return VLC_EGENERIC; - } - p_input->p->b_sout_keep = b_sout_keep; if( b_block ) { @@ -460,49 +444,39 @@ int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ) * * \param the input thread to stop */ -void input_StopThread( input_thread_t *p_input ) +static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj ) { vlc_list_t *p_list; int i; - /* Set die for input */ - vlc_object_kill( p_input ); - /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */ - - /* We cannot touch p_input fields directly (we come from another thread), - * so use the vlc_object_find way, it's perfectly safe */ - - /* Set die for all access */ - p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD ); - for( i = 0; i < p_list->i_count; i++ ) - { - vlc_object_kill( p_list->p_values[i].p_object ); - } - vlc_list_release( p_list ); + if( p_obj->i_object_type == VLC_OBJECT_VOUT || + p_obj->i_object_type == VLC_OBJECT_AOUT || + p_obj == VLC_OBJECT(p_input->p->p_sout) ) + return; - /* Set die for all stream */ - p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD ); - for( i = 0; i < p_list->i_count; i++ ) - { - vlc_object_kill( p_list->p_values[i].p_object ); - } - vlc_list_release( p_list ); + vlc_object_kill( p_obj ); - /* Set die for all demux */ - p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD ); + p_list = vlc_list_children( p_obj ); for( i = 0; i < p_list->i_count; i++ ) - { - vlc_object_kill( p_list->p_values[i].p_object ); - } + ObjectKillChildrens( p_input, p_list->p_values[i].p_object ); vlc_list_release( p_list ); +} +void input_StopThread( input_thread_t *p_input ) +{ + /* Set die for input and ALL of this childrens (even (grand-)grand-childrens) + * It is needed here even if it is done in INPUT_CONTROL_SET_DIE handler to + * unlock the control loop */ + ObjectKillChildrens( p_input, VLC_OBJECT(p_input) ); input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL ); } sout_instance_t * input_DetachSout( input_thread_t *p_input ) { - p_input->p->b_owns_its_sout = false; - return p_input->p->p_sout; + sout_instance_t *p_sout = p_input->p->p_sout; + vlc_object_detach( p_sout ); + p_input->p->p_sout = NULL; + return p_sout; } /***************************************************************************** @@ -520,16 +494,7 @@ static int Run( input_thread_t *p_input ) /* If we failed, wait before we are killed, and exit */ p_input->b_error = true; - /* FIXME: we don't want to depend on the playlist */ - playlist_t * p_playlist = vlc_object_find( p_input, - VLC_OBJECT_PLAYLIST, FIND_PARENT ); - if( p_playlist ) - { - playlist_Signal( p_playlist ); - vlc_object_release( p_playlist ); - } - - Error( p_input ); + WaitDie( p_input ); /* Tell we're dead */ p_input->b_dead = true; @@ -554,13 +519,13 @@ static int Run( input_thread_t *p_input ) /* We have finished */ p_input->b_eof = true; - playlist_Signal( libvlc_priv (p_input->p_libvlc)->p_playlist ); + input_ChangeState( p_input, END_S ); } /* Wait until we are asked to die */ if( !p_input->b_die ) { - Error( p_input ); + WaitDie( p_input ); } /* Clean up */ @@ -665,7 +630,6 @@ static void MainLoop( input_thread_t *p_input ) { /* End of file - we do not set b_die because only the * playlist is allowed to do so. */ - input_ChangeState( p_input, END_S ); msg_Dbg( p_input, "EOF reached" ); p_input->p->input.b_eof = true; } @@ -1298,13 +1262,13 @@ error: } /***************************************************************************** - * Error: RunThread() error loop + * WaitDie: Wait until we are asked to die. ***************************************************************************** * This function is called when an error occurred during thread main's loop. *****************************************************************************/ -static void Error( input_thread_t *p_input ) +static void WaitDie( input_thread_t *p_input ) { - input_ChangeState( p_input, ERROR_S ); + input_ChangeState( p_input, p_input->b_error ? ERROR_S : END_S ); while( !p_input->b_die ) { /* Sleep a while */ @@ -1323,7 +1287,7 @@ static void End( input_thread_t * p_input ) input_ChangeState( p_input, END_S ); /* Clean control variables */ - input_ControlVarClean( p_input ); + input_ControlVarStop( p_input ); /* Clean up master */ InputSourceClean( &p_input->p->input ); @@ -1392,76 +1356,6 @@ static void End( input_thread_t * p_input ) p_input->b_dead = true; } -static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, bool *pb_sout_keep ) -{ - bool b_keep_sout = var_CreateGetBool( p_parent, "sout-keep" ); - sout_instance_t *p_sout = NULL; - int i; - - /* Search sout-keep options - * XXX it has to be done here, but it is duplicated work :( */ - vlc_mutex_lock( &p_item->lock ); - for( i = 0; i < p_item->i_options; i++ ) - { - const char *psz_option = p_item->ppsz_options[i]; - if( !psz_option ) - continue; - if( *psz_option == ':' ) - psz_option++; - - if( !strcmp( psz_option, "sout-keep" ) ) - b_keep_sout = true; - else if( !strcmp( psz_option, "no-sout-keep" ) || !strcmp( psz_option, "nosout-keep" ) ) - b_keep_sout = false; - } - vlc_mutex_unlock( &p_item->lock ); - - /* Find a potential sout to reuse - * XXX it might be unusable but this will be checked later */ - if( b_keep_sout ) - { - playlist_t *p_playlist = vlc_object_find( p_parent->p_libvlc, - VLC_OBJECT_PLAYLIST, FIND_CHILD ); - if( p_playlist ) - { - vlc_mutex_lock( &p_playlist->gc_lock ); - p_sout = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD ); - if( p_sout ) - { - if( p_sout->p_parent != VLC_OBJECT( p_playlist ) ) - { - vlc_object_release( p_sout ); - p_sout = NULL; - } - else - { - vlc_object_detach( p_sout ); /* Remove it from the GC */ - vlc_object_release( p_sout ); - } - } - vlc_mutex_unlock( &p_playlist->gc_lock ); - vlc_object_release( p_playlist ); - } - } - - if( pb_sout_keep ) - *pb_sout_keep = b_keep_sout; - - return p_sout; -} - -static void SoutKeep( sout_instance_t *p_sout ) -{ - playlist_t * p_playlist = vlc_object_find( p_sout, VLC_OBJECT_PLAYLIST, - FIND_PARENT ); - if( !p_playlist ) return; - - msg_Dbg( p_sout, "sout has been kept" ); - vlc_object_attach( p_sout, p_playlist ); - - vlc_object_release( p_playlist ); -} - /***************************************************************************** * Control *****************************************************************************/ @@ -1547,14 +1441,9 @@ static bool Control( input_thread_t *p_input, int i_type, { case INPUT_CONTROL_SET_DIE: msg_Dbg( p_input, "control: stopping input" ); - /* Mark all submodules to die */ - if( p_input->p->input.p_access ) - vlc_object_kill( p_input->p->input.p_access ); - if( p_input->p->input.p_stream ) - vlc_object_kill( p_input->p->input.p_stream ); - vlc_object_kill( p_input->p->input.p_demux ); - vlc_object_kill( p_input ); + /* Mark all submodules to die */ + ObjectKillChildrens( p_input, VLC_OBJECT(p_input) ); break; case INPUT_CONTROL_SET_POSITION: @@ -1669,9 +1558,7 @@ static bool Control( input_thread_t *p_input, int i_type, b_force_update = true; /* Switch to play */ - p_input->i_state = PLAYING_S; - val.i_int = PLAYING_S; - var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL ); + input_ChangeStateWithVarCallback( p_input, PLAYING_S, false ); /* */ if( !i_ret ) @@ -1680,7 +1567,7 @@ static bool Control( input_thread_t *p_input, int i_type, else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S && p_input->p->b_can_pause ) { - int i_ret; + int i_ret, state; if( p_input->p->input.p_access ) i_ret = access_Control( p_input->p->input.p_access, ACCESS_SET_PAUSE_STATE, true ); @@ -1693,16 +1580,15 @@ static bool Control( input_thread_t *p_input, int i_type, if( i_ret ) { msg_Warn( p_input, "cannot set pause state" ); - val.i_int = p_input->i_state; + state = p_input->i_state; } else { - val.i_int = PAUSE_S; + state = PAUSE_S; } /* Switch to new state */ - p_input->i_state = val.i_int; - var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL ); + input_ChangeStateWithVarCallback( p_input, state, false ); /* */ if( !i_ret ) @@ -1713,8 +1599,7 @@ static bool Control( input_thread_t *p_input, int i_type, b_force_update = true; /* Correct "state" value */ - val.i_int = p_input->i_state; - var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL ); + input_ChangeStateWithVarCallback( p_input, p_input->i_state, false ); } else if( val.i_int != PLAYING_S && val.i_int != PAUSE_S ) { @@ -2955,3 +2840,12 @@ bool input_AddSubtitles( input_thread_t *p_input, char *psz_subtitle, return true; } + +/***************************************************************************** + * input_get_event_manager + *****************************************************************************/ +vlc_event_manager_t * +input_get_event_manager( input_thread_t *p_input ) +{ + return &p_input->p->event_manager; +}