From: Clément Stenac Date: Fri, 10 Dec 2004 18:58:22 +0000 (+0000) Subject: *experimental* input pre-parsing support. X-Git-Tag: 0.8.2~1534 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=01aca2cc006e2c2ef00bc5ca723180e27ab15a76;p=vlc *experimental* input pre-parsing support. Won't work for many things (only those for which metadata can be gotten during initialization). Processing is done asynchronously, use playlist_PreparseEnqueue to add an item to the queue. --- diff --git a/include/vlc_access.h b/include/vlc_access.h index 94e7f3bd0b..28495b4a08 100644 --- a/include/vlc_access.h +++ b/include/vlc_access.h @@ -104,8 +104,8 @@ struct access_t access_sys_t *p_sys; }; -#define access2_New( a, b, c, d ) __access2_New(VLC_OBJECT(a), b, c, d ) -VLC_EXPORT( access_t *, __access2_New, ( vlc_object_t *p_obj, char *psz_access, char *psz_demux, char *psz_path ) ); +#define access2_New( a, b, c, d, e ) __access2_New(VLC_OBJECT(a), b, c, d, e ) +VLC_EXPORT( access_t *, __access2_New, ( vlc_object_t *p_obj, char *psz_access, char *psz_demux, char *psz_path, vlc_bool_t b_quick ) ); VLC_EXPORT( void, access2_Delete, ( access_t * ) ); static inline int access2_vaControl( access_t *p_access, int i_query, va_list args ) diff --git a/include/vlc_common.h b/include/vlc_common.h index 1b03a8531c..197549ba1b 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -225,6 +225,7 @@ typedef struct playlist_export_t playlist_export_t; typedef struct services_discovery_t services_discovery_t; typedef struct services_discovery_sys_t services_discovery_sys_t; typedef struct playlist_add_t playlist_add_t; +typedef struct playlist_preparse_t playlist_preparse_t; /* Modules */ typedef struct module_bank_t module_bank_t; diff --git a/include/vlc_demux.h b/include/vlc_demux.h index 9ab59a73ce..7c4385ba9b 100644 --- a/include/vlc_demux.h +++ b/include/vlc_demux.h @@ -109,8 +109,8 @@ enum demux_query_e }; /* stream_t *s could be null and then it mean a access+demux in one */ -#define demux2_New( a, b, c, d, e, f ) __demux2_New(VLC_OBJECT(a),b,c,d,e,f) -VLC_EXPORT( demux_t *, __demux2_New, ( vlc_object_t *p_obj, char *psz_access, char *psz_demux, char *psz_path, stream_t *s, es_out_t *out ) ); +#define demux2_New( a, b, c, d, e, f,g ) __demux2_New(VLC_OBJECT(a),b,c,d,e,f,g) +VLC_EXPORT( demux_t *, __demux2_New, ( vlc_object_t *p_obj, char *psz_access, char *psz_demux, char *psz_path, stream_t *s, es_out_t *out, vlc_bool_t ) ); VLC_EXPORT( void, demux2_Delete, ( demux_t * ) ); VLC_EXPORT( int, demux2_vaControlHelper, ( stream_t *, int64_t i_start, int64_t i_end, int i_bitrate, int i_align, int i_query, va_list args ) ); diff --git a/include/vlc_input.h b/include/vlc_input.h index bf988a87f1..205aa06932 100644 --- a/include/vlc_input.h +++ b/include/vlc_input.h @@ -398,6 +398,8 @@ struct input_thread_t *****************************************************************************/ #define input_CreateThread(a,b) __input_CreateThread(VLC_OBJECT(a),b) VLC_EXPORT( input_thread_t *, __input_CreateThread, ( vlc_object_t *, input_item_t * ) ); +#define input_Preparse(a,b) __input_Preparse(VLC_OBJECT(a),b) +VLC_EXPORT( int, __input_Preparse, ( vlc_object_t *, input_item_t * ) ); VLC_EXPORT( void, input_StopThread, ( input_thread_t * ) ); VLC_EXPORT( void, input_DestroyThread, ( input_thread_t * ) ); diff --git a/include/vlc_playlist.h b/include/vlc_playlist.h index f71493fc5a..c1c85d4c6a 100644 --- a/include/vlc_playlist.h +++ b/include/vlc_playlist.h @@ -127,6 +127,14 @@ struct services_discovery_t void (*pf_run) ( services_discovery_t *); }; +struct playlist_preparse_t +{ + VLC_COMMON_MEMBERS + vlc_mutex_t lock; + int i_waiting; + input_item_t **pp_waiting; +}; + /** * Structure containing information about the playlist @@ -191,9 +199,11 @@ struct playlist_t vlc_bool_t b_request; /**< Set to true by the requester The playlist sets it back to false when processing the request */ - vlc_mutex_t lock; /**< Lock to protect request */ + vlc_mutex_t lock; /**< Lock to protect request */ } request; + playlist_preparse_t *p_preparse; + /*@}*/ }; @@ -238,6 +248,7 @@ VLC_EXPORT( int, playlist_Control, ( playlist_t *, int, ... ) ); VLC_EXPORT( int, playlist_Clear, ( playlist_t * ) ); +VLC_EXPORT( int, playlist_PreparseEnqueue, (playlist_t *, input_item_t *) ); /* Services discovery */ diff --git a/modules/gui/wxwindows/playlist.cpp b/modules/gui/wxwindows/playlist.cpp index a237b8d2d6..2af3ef15c5 100644 --- a/modules/gui/wxwindows/playlist.cpp +++ b/modules/gui/wxwindows/playlist.cpp @@ -90,6 +90,7 @@ enum PopupPlay_Event, PopupPlayThis_Event, + PopupPreparse_Event, PopupSort_Event, PopupDel_Event, PopupEna_Event, @@ -150,6 +151,7 @@ BEGIN_EVENT_TABLE(Playlist, wxFrame) /* Popup events */ EVT_MENU( PopupPlay_Event, Playlist::OnPopupPlay) EVT_MENU( PopupPlayThis_Event, Playlist::OnPopupPlay) + EVT_MENU( PopupPreparse_Event, Playlist::OnPopupPreparse) EVT_MENU( PopupSort_Event, Playlist::OnPopupSort) EVT_MENU( PopupDel_Event, Playlist::OnPopupDel) EVT_MENU( PopupEna_Event, Playlist::OnPopupEna) @@ -266,6 +268,7 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): popup_menu = new wxMenu; popup_menu->Append( PopupPlay_Event, wxU(_("Play")) ); popup_menu->Append( PopupPlayThis_Event, wxU(_("Play this branch")) ); + popup_menu->Append( PopupPreparse_Event, wxU(_("Preparse")) ); popup_menu->Append( PopupSort_Event, wxU(_("Sort this branch")) ); popup_menu->Append( PopupDel_Event, wxU(_("Delete")) ); popup_menu->Append( PopupEna_Event, wxU(_("Enable/Disable")) ); @@ -1139,8 +1142,9 @@ void Playlist::OnActivateItem( wxTreeEvent& event ) playlist_item_t *p_item,*p_node; playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,FIND_ANYWHERE ); + PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData( - event.GetItem() ); + event.GetItem() ); wxTreeItemId parent = treectrl->GetItemParent( event.GetItem() ); PlaylistItem *p_wxparent = (PlaylistItem *)treectrl->GetItemData( parent ); @@ -1380,9 +1384,6 @@ void Playlist::OnPopup( wxContextMenuEvent& event ) Playlist::PopupMenu( popup_menu, ScreenToClient( wxGetMousePosition() ) ); } - else - { - } } void Playlist::OnPopupPlay( wxMenuEvent& event ) @@ -1424,6 +1425,38 @@ void Playlist::OnPopupPlay( wxMenuEvent& event ) vlc_object_release( p_playlist ); } +void Playlist::OnPopupPreparse( wxMenuEvent& event ) +{ + playlist_t *p_playlist = + (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist == NULL ) + { + return; + } + if( p_popup_item != NULL ) + { + if( p_popup_item->i_children == -1 ) + { + playlist_PreparseEnqueue( p_playlist, &p_popup_item->input ); + } + else + { + int i = 0; + playlist_item_t *p_parent = p_popup_item; + for( i = 0; i< p_parent->i_children ; i++ ) + { + wxMenuEvent dummy; + i_popup_item = FindItem( treectrl->GetRootItem(), + p_parent->pp_children[i] ); + p_popup_item = p_parent->pp_children[i]; + OnPopupPreparse( dummy ); + } + } + } + vlc_object_release( p_playlist ); +} + void Playlist::OnPopupDel( wxMenuEvent& event ) { PlaylistItem *p_wxitem; diff --git a/modules/gui/wxwindows/timer.cpp b/modules/gui/wxwindows/timer.cpp index 468c535ba2..0fd0ec0267 100644 --- a/modules/gui/wxwindows/timer.cpp +++ b/modules/gui/wxwindows/timer.cpp @@ -108,9 +108,14 @@ void Timer::Notify() /* Update the input */ if( p_intf->p_sys->p_input == NULL ) { - p_intf->p_sys->p_input = - (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT, - FIND_ANYWHERE ); + playlist_t *p_playlist = + (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist != NULL ) + { + p_intf->p_sys->p_input = p_playlist->p_input; + vlc_object_release( p_playlist ); + } /* Refresh interface */ if( p_intf->p_sys->p_input ) @@ -140,7 +145,6 @@ void Timer::Notify() p_main_interface->statusbar->SetStatusText( wxT(""), 0 ); p_main_interface->statusbar->SetStatusText( wxT(""), 2 ); - vlc_object_release( p_intf->p_sys->p_input ); p_intf->p_sys->p_input = NULL; } diff --git a/modules/gui/wxwindows/wxwindows.cpp b/modules/gui/wxwindows/wxwindows.cpp index 59b87f261a..b7f2bdbfed 100644 --- a/modules/gui/wxwindows/wxwindows.cpp +++ b/modules/gui/wxwindows/wxwindows.cpp @@ -175,11 +175,6 @@ static void Close( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; - if( p_intf->p_sys->p_input ) - { - vlc_object_release( p_intf->p_sys->p_input ); - } - vlc_mutex_lock( &p_intf->object_lock ); p_intf->b_dead = VLC_TRUE; vlc_mutex_unlock( &p_intf->object_lock ); diff --git a/modules/gui/wxwindows/wxwindows.h b/modules/gui/wxwindows/wxwindows.h index 7949d147b9..600be59c74 100644 --- a/modules/gui/wxwindows/wxwindows.h +++ b/modules/gui/wxwindows/wxwindows.h @@ -846,6 +846,7 @@ private: playlist_item_t *p_popup_parent; void OnPopup( wxContextMenuEvent& event ); void OnPopupPlay( wxMenuEvent& event ); + void OnPopupPreparse( wxMenuEvent& event ); void OnPopupSort( wxMenuEvent& event ); void OnPopupDel( wxMenuEvent& event ); void OnPopupEna( wxMenuEvent& event ); diff --git a/src/input/access.c b/src/input/access.c index dfca13c716..48bccdba03 100644 --- a/src/input/access.c +++ b/src/input/access.c @@ -31,7 +31,8 @@ * access2_New: *****************************************************************************/ access_t *__access2_New( vlc_object_t *p_obj, - char *psz_access, char *psz_demux, char *psz_path ) + char *psz_access, char *psz_demux, char *psz_path, + vlc_bool_t b_quick ) { access_t *p_access = vlc_object_create( p_obj, VLC_OBJECT_ACCESS ); @@ -42,12 +43,13 @@ access_t *__access2_New( vlc_object_t *p_obj, } /* Parse URL */ - p_access->psz_access = strdup( psz_access ); + p_access->psz_access = b_quick ? strdup( "file" ) : strdup( psz_access ); p_access->psz_path = strdup( psz_path ); p_access->psz_demux = strdup( "" ); - msg_Dbg( p_obj, "access2_New: access='%s' path='%s'", - p_access->psz_access, p_access->psz_path ); + if( !b_quick ) + msg_Dbg( p_obj, "access2_New: access='%s' path='%s'", + p_access->psz_access, p_access->psz_path ); p_access->pf_read = NULL; p_access->pf_block = NULL; @@ -66,7 +68,8 @@ access_t *__access2_New( vlc_object_t *p_obj, vlc_object_attach( p_access, p_obj ); p_access->p_module = - module_Need( p_access, "access2", p_access->psz_access, VLC_FALSE ); + module_Need( p_access, "access2", p_access->psz_access, + b_quick ? VLC_TRUE : VLC_FALSE ); if( p_access->p_module == NULL ) { diff --git a/src/input/demux.c b/src/input/demux.c index 9a7bb048f4..b014b5a6b7 100644 --- a/src/input/demux.c +++ b/src/input/demux.c @@ -33,7 +33,7 @@ *****************************************************************************/ demux_t *__demux2_New( vlc_object_t *p_obj, char *psz_access, char *psz_demux, char *psz_path, - stream_t *s, es_out_t *out ) + stream_t *s, es_out_t *out, vlc_bool_t b_quick ) { demux_t *p_demux = vlc_object_create( p_obj, VLC_OBJECT_DEMUX ); char *psz_module; @@ -55,8 +55,11 @@ demux_t *__demux2_New( vlc_object_t *p_obj, p_demux->psz_demux = var_GetString( p_obj, "demux" ); } - msg_Dbg( p_obj, "demux2_New: access='%s' demux='%s' path='%s'", - p_demux->psz_access, p_demux->psz_demux, p_demux->psz_path ); + if( !b_quick ) + { + msg_Dbg( p_obj, "demux2_New: access='%s' demux='%s' path='%s'", + p_demux->psz_access, p_demux->psz_demux, p_demux->psz_path ); + } p_demux->s = s; p_demux->out = out; @@ -79,8 +82,8 @@ demux_t *__demux2_New( vlc_object_t *p_obj, * - no .mp3, .a52, ... (aac is added as it works only by file ext anyway * - wav can't be added 'cause of a52 and dts in them as raw audio */ - static struct { char *ext; char *demux; } exttodemux[] = - { + static struct { char *ext; char *demux; } exttodemux[] = + { { "aac", "aac" }, { "aiff", "aiff" }, { "asf", "asf" }, { "wmv", "asf" }, { "wma", "asf" }, @@ -98,17 +101,40 @@ demux_t *__demux2_New( vlc_object_t *p_obj, { "rm", "rm" }, { NULL, NULL }, }; + /* Here, we don't mind if it does not work, it must be quick */ + static struct { char *ext; char *demux; } exttodemux_quick[] = + { + { "mp3", "mpga" }, + { "ogg", "ogg" }, + { "wma", "asf" }, + { NULL, NULL } + }; char *psz_ext = strrchr( p_demux->psz_path, '.' ) + 1; int i; - for( i = 0; exttodemux[i].ext != NULL; i++ ) + if( !b_quick ) + { + for( i = 0; exttodemux[i].ext != NULL; i++ ) + { + if( !strcasecmp( psz_ext, exttodemux[i].ext ) ) + { + psz_module = exttodemux[i].demux; + break; + } + } + } + else { - if( !strcasecmp( psz_ext, exttodemux[i].ext ) ) + for( i = 0; exttodemux_quick[i].ext != NULL; i++ ) { - psz_module = exttodemux[i].demux; - break; + if( !strcasecmp( psz_ext, exttodemux_quick[i].ext ) ) + { + psz_module = exttodemux_quick[i].demux; + break; + } } + } } @@ -486,7 +512,8 @@ static int DStreamThread( stream_t *s ) demux_t *p_demux; /* Create the demuxer */ - if( !(p_demux = demux2_New( s, "", p_sys->psz_name, "", s, p_sys->out )) ) + if( !(p_demux = demux2_New( s, "", p_sys->psz_name, "", s, p_sys->out, + VLC_FALSE )) ) { return VLC_EGENERIC; } diff --git a/src/input/input.c b/src/input/input.c index df9aba94d3..401eb46712 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -44,7 +44,7 @@ *****************************************************************************/ static int Run ( input_thread_t *p_input ); -static int Init ( input_thread_t *p_input ); +static int Init ( input_thread_t *p_input, vlc_bool_t b_quick ); static void Error( input_thread_t *p_input ); static void End ( input_thread_t *p_input ); @@ -55,9 +55,9 @@ static vlc_bool_t Control( input_thread_t *, int, vlc_value_t ); static int UpdateFromAccess( input_thread_t * ); static int UpdateFromDemux( input_thread_t * ); -static int UpdateMeta( input_thread_t * ); +static int UpdateMeta( input_thread_t *, vlc_bool_t ); -static void UpdateItemLength( input_thread_t *, int64_t i_length ); +static void UpdateItemLength( input_thread_t *, int64_t i_length, vlc_bool_t ); static void ParseOption( input_thread_t *p_input, const char *psz_option ); @@ -67,7 +67,8 @@ static void MRLSections( input_thread_t *, char *, int *, int *, int *, int *); static input_source_t *InputSourceNew( input_thread_t *); static int InputSourceInit( input_thread_t *, input_source_t *, - char *, char *psz_forced_demux ); + char *, char *psz_forced_demux, + vlc_bool_t b_quick ); static void InputSourceClean( input_thread_t *, input_source_t * ); static void SlaveDemux( input_thread_t *p_input ); @@ -237,6 +238,99 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent, return p_input; } +/***************************************************************************** + * input_PreParse: Lightweight input for playlist item preparsing + *****************************************************************************/ +int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ) +{ + input_thread_t *p_input; /* thread descriptor */ + int i; + + /* Allocate descriptor */ + p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT ); + if( p_input == NULL ) + { + msg_Err( p_parent, "out of memory" ); + return VLC_EGENERIC; + } + + /* Init Common fields */ + p_input->b_eof = VLC_FALSE; + p_input->b_can_pace_control = VLC_TRUE; + p_input->i_start = 0; + p_input->i_time = 0; + p_input->i_stop = 0; + p_input->i_title = 0; + p_input->title = NULL; + p_input->i_title_offset = p_input->i_seekpoint_offset = 0; + p_input->i_state = INIT_S; + p_input->i_rate = INPUT_RATE_DEFAULT; + p_input->i_bookmark = 0; + p_input->bookmark = NULL; + p_input->p_meta = NULL; + p_input->p_es_out = NULL; + p_input->p_sout = NULL; + p_input->b_out_pace_control = VLC_FALSE; + p_input->i_pts_delay = 0; + + /* Init Input fields */ + p_input->input.p_item = p_item; + p_input->input.p_access = NULL; + p_input->input.p_stream = NULL; + p_input->input.p_demux = NULL; + p_input->input.b_title_demux = VLC_FALSE; + p_input->input.i_title = 0; + p_input->input.title = NULL; + p_input->input.i_title_offset = p_input->input.i_seekpoint_offset = 0; + p_input->input.b_can_pace_control = VLC_TRUE; + p_input->input.b_eof = VLC_FALSE; + p_input->input.i_cr_average = 0; + + /* No slave */ + p_input->i_slave = 0; + p_input->slave = NULL; + + /* Init control buffer */ + vlc_mutex_init( p_input, &p_input->lock_control ); + p_input->i_control = 0; + + /* Parse input options */ + vlc_mutex_lock( &p_item->lock ); + for( i = 0; i < p_item->i_options; i++ ) + { + ParseOption( p_input, p_item->ppsz_options[i] ); + } + vlc_mutex_unlock( &p_item->lock ); + + /* Create Object Variables for private use only */ + input_ConfigVarInit( p_input ); + + p_input->input.i_cr_average = var_GetInteger( p_input, "cr-average" ); + + /* Now we can attach our new input */ + vlc_object_attach( p_input, p_parent ); + + Init( p_input, VLC_TRUE ); + + /* Clean up master */ + InputSourceClean( p_input, &p_input->input ); + + /* Kill access and demux */ + if( p_input->input.p_access ) p_input->input.p_access->b_die = VLC_TRUE; + if( p_input->input.p_demux ) p_input->input.p_access->b_die = VLC_TRUE; + + /* Unload all modules */ + if( p_input->p_es_out ) input_EsOutDelete( p_input->p_es_out ); + + /* Delete meta */ + if( p_input->p_meta ) vlc_meta_Delete( p_input->p_meta ); + + vlc_object_detach( p_input ); + vlc_object_destroy( p_input ); + + return VLC_SUCCESS; +} + /***************************************************************************** * input_StopThread: mark an input thread as zombie ***************************************************************************** @@ -313,7 +407,7 @@ static int Run( input_thread_t *p_input ) /* Signal that the thread is launched */ vlc_thread_ready( p_input ); - if( Init( p_input ) ) + if( Init( p_input, VLC_FALSE ) ) { /* If we failed, wait before we are killed, and exit */ p_input->b_error = VLC_TRUE; @@ -467,7 +561,7 @@ static int Run( input_thread_t *p_input ) if( old_val.i_time != val.i_time ) { - UpdateItemLength( p_input, i_length ); + UpdateItemLength( p_input, i_length, VLC_TRUE ); } } @@ -505,10 +599,8 @@ static int Run( input_thread_t *p_input ) return 0; } -/***************************************************************************** - * Init: init the input Thread - *****************************************************************************/ -static int Init( input_thread_t * p_input ) + +static int Init( input_thread_t * p_input, vlc_bool_t b_quick ) { char *psz; char *psz_subtitle; @@ -519,18 +611,22 @@ static int Init( input_thread_t * p_input ) int i, i_delay; /* Initialize optional stream output. (before access/demuxer) */ - psz = var_GetString( p_input, "sout" ); - if( *psz ) + if( !b_quick ) { - p_input->p_sout = sout_NewInstance( p_input, psz ); - if( p_input->p_sout == NULL ) + psz = var_GetString( p_input, "sout" ); + if( *psz ) { - msg_Err( p_input, "cannot start stream output instance, aborting" ); - free( psz ); - return VLC_EGENERIC; + p_input->p_sout = sout_NewInstance( p_input, psz ); + if( p_input->p_sout == NULL ) + { + msg_Err( p_input, "cannot start stream output instance," \ + "aborting" ); + free( psz ); + return VLC_EGENERIC; + } } + free( psz ); } - free( psz ); /* Create es out */ p_input->p_es_out = input_EsOutNew( p_input ); @@ -538,40 +634,43 @@ static int Init( input_thread_t * p_input ) es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE ); if( InputSourceInit( p_input, &p_input->input, - p_input->input.p_item->psz_uri, NULL ) ) + p_input->input.p_item->psz_uri, NULL, b_quick ) ) { goto error; } /* Create global title (from master) */ - p_input->i_title = p_input->input.i_title; - p_input->title = p_input->input.title; - p_input->i_title_offset = p_input->input.i_title_offset; - p_input->i_seekpoint_offset = p_input->input.i_seekpoint_offset; - if( p_input->i_title > 0 ) + if( !b_quick ) { - /* Setup variables */ - input_ControlVarNavigation( p_input ); - input_ControlVarTitle( p_input, 0 ); - } + p_input->i_title = p_input->input.i_title; + p_input->title = p_input->input.title; + p_input->i_title_offset = p_input->input.i_title_offset; + p_input->i_seekpoint_offset = p_input->input.i_seekpoint_offset; + if( p_input->i_title > 0 ) + { + /* Setup variables */ + input_ControlVarNavigation( p_input ); + input_ControlVarTitle( p_input, 0 ); + } - /* Global flag */ - p_input->b_can_pace_control = p_input->input.b_can_pace_control; - p_input->b_can_pause = p_input->input.b_can_pause; + /* Global flag */ + p_input->b_can_pace_control = p_input->input.b_can_pace_control; + p_input->b_can_pause = p_input->input.b_can_pause; - /* Fix pts delay */ - if( p_input->i_pts_delay <= 0 ) - p_input->i_pts_delay = DEFAULT_PTS_DELAY; + /* Fix pts delay */ + if( p_input->i_pts_delay <= 0 ) + p_input->i_pts_delay = DEFAULT_PTS_DELAY; - /* If the desynchronisation requested by the user is < 0, we need to - * cache more data. */ - var_Get( p_input, "audio-desync", &val ); - if( val.i_int < 0 ) p_input->i_pts_delay -= (val.i_int * 1000); + /* If the desynchronisation requested by the user is < 0, we need to + * cache more data. */ + var_Get( p_input, "audio-desync", &val ); + if( val.i_int < 0 ) p_input->i_pts_delay -= (val.i_int * 1000); - /* Update cr_average depending on the caching */ - p_input->input.i_cr_average *= (10 * p_input->i_pts_delay / 200000); - p_input->input.i_cr_average /= 10; - if( p_input->input.i_cr_average <= 0 ) p_input->input.i_cr_average = 1; + /* Update cr_average depending on the caching */ + p_input->input.i_cr_average *= (10 * p_input->i_pts_delay / 200000); + p_input->input.i_cr_average /= 10; + if( p_input->input.i_cr_average <= 0 ) p_input->input.i_cr_average = 1; + } /* Load master infos */ /* Init length */ @@ -579,224 +678,239 @@ static int Init( input_thread_t * p_input ) &val.i_time ) && val.i_time > 0 ) { var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL ); - - UpdateItemLength( p_input, val.i_time ); + UpdateItemLength( p_input, val.i_time, b_quick ); p_input->input.p_item->i_duration = val.i_time; } /* Start title/chapter */ - val.i_int = p_input->input.i_title_start - - p_input->input.i_title_offset; - if( val.i_int > 0 && val.i_int < p_input->input.i_title ) - input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val ); - val.i_int = p_input->input.i_seekpoint_start - - p_input->input.i_seekpoint_offset; - if( val.i_int > 0 /* TODO: check upper boundary */ ) - input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val ); - - /* Start time*/ - /* Set start time */ - p_input->i_start = (int64_t)var_GetInteger( p_input, "start-time" ) * - I64C(1000000); - p_input->i_stop = (int64_t)var_GetInteger( p_input, "stop-time" ) * - I64C(1000000); - - if( p_input->i_start > 0 ) - { - if( p_input->i_start >= val.i_time ) + if( !b_quick ) + { + val.i_int = p_input->input.i_title_start - + p_input->input.i_title_offset; + if( val.i_int > 0 && val.i_int < p_input->input.i_title ) + input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val ); + val.i_int = p_input->input.i_seekpoint_start - + p_input->input.i_seekpoint_offset; + if( val.i_int > 0 /* TODO: check upper boundary */ ) + input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val ); + + /* Start time*/ + /* Set start time */ + p_input->i_start = (int64_t)var_GetInteger( p_input, "start-time" ) * + I64C(1000000); + p_input->i_stop = (int64_t)var_GetInteger( p_input, "stop-time" ) * + I64C(1000000); + + if( p_input->i_start > 0 ) { - msg_Warn( p_input, "invalid start-time ignored" ); - } - else - { - vlc_value_t s; + if( p_input->i_start >= val.i_time ) + { + msg_Warn( p_input, "invalid start-time ignored" ); + } + else + { + vlc_value_t s; - msg_Dbg( p_input, "start-time: %ds", - (int)( p_input->i_start / I64C(1000000) ) ); + msg_Dbg( p_input, "start-time: %ds", + (int)( p_input->i_start / I64C(1000000) ) ); - s.i_time = p_input->i_start; - input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s ); + s.i_time = p_input->i_start; + input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s ); + } } - } - if( p_input->i_stop > 0 && p_input->i_stop <= p_input->i_start ) - { - msg_Warn( p_input, "invalid stop-time ignored" ); - p_input->i_stop = 0; - } - - - /* Load subtitles */ - /* Get fps and set it if not already set */ - if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) && - f_fps > 1.0 ) - { - vlc_value_t fps; - float f_requested_fps; - - var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT ); - var_SetFloat( p_input, "sub-original-fps", f_fps ); - - f_requested_fps = var_CreateGetFloat( p_input, "sub-fps" ); - if( f_requested_fps != f_fps ) + if( p_input->i_stop > 0 && p_input->i_stop <= p_input->i_start ) { - var_Create( p_input, "sub-fps", VLC_VAR_FLOAT| VLC_VAR_DOINHERIT ); - var_SetFloat( p_input, "sub-fps", f_requested_fps ); + msg_Warn( p_input, "invalid stop-time ignored" ); + p_input->i_stop = 0; } - } - i_delay = var_CreateGetInteger( p_input, "sub-delay" ); - if( i_delay != 0 ) - { - var_SetTime( p_input, "spu-delay", (mtime_t)i_delay * 100000 ); - } + /* Load subtitles */ + /* Get fps and set it if not already set */ + if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) && + f_fps > 1.0 ) + { + float f_requested_fps; + var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT ); + var_SetFloat( p_input, "sub-original-fps", f_fps ); - /* Look for and add subtitle files */ - psz_subtitle = var_GetString( p_input, "sub-file" ); - if( *psz_subtitle ) - { - input_source_t *sub; - vlc_value_t count; - vlc_value_t list; + f_requested_fps = var_CreateGetFloat( p_input, "sub-fps" ); + if( f_requested_fps != f_fps ) + { + var_Create( p_input, "sub-fps", VLC_VAR_FLOAT| + VLC_VAR_DOINHERIT ); + var_SetFloat( p_input, "sub-fps", f_requested_fps ); + } + } - msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle ); + i_delay = var_CreateGetInteger( p_input, "sub-delay" ); + if( i_delay != 0 ) + { + var_SetTime( p_input, "spu-delay", (mtime_t)i_delay * 100000 ); + } - var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL ); - /* */ - sub = InputSourceNew( p_input ); - if( !InputSourceInit( p_input, sub, psz_subtitle, "subtitle" ) ) + /* Look for and add subtitle files */ + psz_subtitle = var_GetString( p_input, "sub-file" ); + if( *psz_subtitle ) { - TAB_APPEND( p_input->i_slave, p_input->slave, sub ); + input_source_t *sub; + vlc_value_t count; + vlc_value_t list; + + msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle ); - /* Select the ES */ - if( !var_Change( p_input, "spu-es", VLC_VAR_GETLIST, &list, NULL ) ) + var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL ); + + /* */ + sub = InputSourceNew( p_input ); + if( !InputSourceInit( p_input, sub, psz_subtitle, "subtitle", + VLC_FALSE ) ) { - if( count.i_int == 0 ) - count.i_int++; /* if it was first one, there is disable too */ + TAB_APPEND( p_input->i_slave, p_input->slave, sub ); - if( count.i_int < list.p_list->i_count ) + /* Select the ES */ + if( !var_Change( p_input, "spu-es", VLC_VAR_GETLIST, &list, + NULL ) ) { - input_ControlPush( p_input, INPUT_CONTROL_SET_ES, - &list.p_list->p_values[count.i_int] ); + if( count.i_int == 0 ) + count.i_int++; + /* if it was first one, there is disable too */ + + if( count.i_int < list.p_list->i_count ) + { + input_ControlPush( p_input, INPUT_CONTROL_SET_ES, + &list.p_list->p_values[count.i_int] ); + } + var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, + NULL ); } - var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL ); } } - } - - var_Get( p_input, "sub-autodetect-file", &val ); - if( val.b_bool ) - { - char *psz_autopath = var_GetString( p_input, "sub-autodetect-path" ); - char **subs = subtitles_Detect( p_input, psz_autopath, - p_input->input.p_item->psz_uri ); - input_source_t *sub; - for( i = 0; subs[i] != NULL; i++ ) + var_Get( p_input, "sub-autodetect-file", &val ); + if( val.b_bool ) { - if( strcmp( psz_subtitle, subs[i] ) ) + char *psz_autopath = var_GetString( p_input, "sub-autodetect-path" ); + char **subs = subtitles_Detect( p_input, psz_autopath, + p_input->input.p_item->psz_uri ); + input_source_t *sub; + + for( i = 0; subs[i] != NULL; i++ ) { - sub = InputSourceNew( p_input ); - if( !InputSourceInit( p_input, sub, subs[i], "subtitle" ) ) + if( strcmp( psz_subtitle, subs[i] ) ) { - TAB_APPEND( p_input->i_slave, p_input->slave, sub ); + sub = InputSourceNew( p_input ); + if( !InputSourceInit( p_input, sub, subs[i], "subtitle", + VLC_FALSE ) ) + { + TAB_APPEND( p_input->i_slave, p_input->slave, sub ); + } } + free( subs[i] ); } - free( subs[i] ); + free( subs ); + free( psz_autopath ); } - free( subs ); - free( psz_autopath ); - } - free( psz_subtitle ); + free( psz_subtitle ); - /* Look for slave */ - psz = var_GetString( p_input, "input-slave" ); - if( *psz ) - { - char *psz_delim; - input_source_t *slave; - while( psz && *psz ) + /* Look for slave */ + psz = var_GetString( p_input, "input-slave" ); + if( *psz ) { - while( *psz == ' ' || *psz == '#' ) - { - psz++; - } - if( ( psz_delim = strchr( psz, '#' ) ) ) + char *psz_delim; + input_source_t *slave; + while( psz && *psz ) { - *psz_delim++ = '\0'; - } - if( *psz == 0 ) - { - break; - } + while( *psz == ' ' || *psz == '#' ) + { + psz++; + } + if( ( psz_delim = strchr( psz, '#' ) ) ) + { + *psz_delim++ = '\0'; + } + if( *psz == 0 ) + { + break; + } - msg_Dbg( p_input, "adding slave '%s'", psz ); - slave = InputSourceNew( p_input ); - if( !InputSourceInit( p_input, slave, psz, NULL ) ) - { - TAB_APPEND( p_input->i_slave, p_input->slave, slave ); + msg_Dbg( p_input, "adding slave '%s'", psz ); + slave = InputSourceNew( p_input ); + if( !InputSourceInit( p_input, slave, psz, NULL, VLC_FALSE ) ) + { + TAB_APPEND( p_input->i_slave, p_input->slave, slave ); + } + psz = psz_delim; } - psz = psz_delim; } + if( psz ) free( psz ); + } + else + { + p_input->i_start = 0; + p_input->i_start = 0; } - if( psz ) free( psz ); /* Set up es_out */ - es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE ); - i_es_out_mode = ES_OUT_MODE_AUTO; - val.p_list = NULL; - if( p_input->p_sout ) + if( !b_quick ) { - var_Get( p_input, "sout-all", &val ); - if ( val.b_bool ) + es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE ); + i_es_out_mode = ES_OUT_MODE_AUTO; + val.p_list = NULL; + if( p_input->p_sout ) { - i_es_out_mode = ES_OUT_MODE_ALL; - val.p_list = NULL; - } - else - { - var_Get( p_input, "programs", &val ); - if ( val.p_list && val.p_list->i_count ) + var_Get( p_input, "sout-all", &val ); + if ( val.b_bool ) { - i_es_out_mode = ES_OUT_MODE_PARTIAL; - /* Note : we should remove the "program" callback. */ + i_es_out_mode = ES_OUT_MODE_ALL; + val.p_list = NULL; } else - var_Change( p_input, "programs", VLC_VAR_FREELIST, &val, NULL ); + { + var_Get( p_input, "programs", &val ); + if ( val.p_list && val.p_list->i_count ) + { + i_es_out_mode = ES_OUT_MODE_PARTIAL; + /* Note : we should remove the "program" callback. */ + } + else + var_Change( p_input, "programs", VLC_VAR_FREELIST, &val, + NULL ); + } } - } - es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, i_es_out_mode ); - - /* Inform the demuxer about waited group (needed only for DVB) */ - if( i_es_out_mode == ES_OUT_MODE_ALL ) - { - demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1, NULL ); - } - else if( i_es_out_mode == ES_OUT_MODE_PARTIAL ) - { - demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1, - val.p_list ); - } - else - { - demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, - (int) var_GetInteger( p_input, "program" ), NULL ); - } + es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, i_es_out_mode ); - if( p_input->p_sout ) - { - if( p_input->p_sout->i_out_pace_nocontrol > 0 ) + /* Inform the demuxer about waited group (needed only for DVB) */ + if( i_es_out_mode == ES_OUT_MODE_ALL ) + { + demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1, NULL ); + } + else if( i_es_out_mode == ES_OUT_MODE_PARTIAL ) { - p_input->b_out_pace_control = VLC_FALSE; + demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1, + val.p_list ); } else { - p_input->b_out_pace_control = VLC_TRUE; + demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, + (int) var_GetInteger( p_input, "program" ), NULL ); + } + + if( p_input->p_sout ) + { + if( p_input->p_sout->i_out_pace_nocontrol > 0 ) + { + p_input->b_out_pace_control = VLC_FALSE; + } + else + { + p_input->b_out_pace_control = VLC_TRUE; + } + msg_Dbg( p_input, "starting in %s mode", + p_input->b_out_pace_control ? "asynch" : "synch" ); } - msg_Dbg( p_input, "starting in %s mode", - p_input->b_out_pace_control ? "asynch" : "synch" ); } /* Get meta data from users */ @@ -817,61 +931,69 @@ static int Init( input_thread_t * p_input ) vlc_meta_Delete( p_meta_tmp ); } - if( !p_input->input.p_access || - access2_Control( p_input->input.p_access, ACCESS_GET_META, &p_meta_tmp)) - p_meta_tmp = NULL; - - if( p_meta == NULL ) + /* Access_file does not give any meta, and there are no slave */ + if( !b_quick ) { - p_meta = p_meta_tmp; - } - else if( p_meta_tmp ) - { - vlc_meta_Merge( p_meta, p_meta_tmp ); - vlc_meta_Delete( p_meta_tmp ); - } + if( !p_input->input.p_access || + access2_Control( p_input->input.p_access, ACCESS_GET_META, + &p_meta_tmp)) + p_meta_tmp = NULL; - /* Get meta data from slave input */ - for( i = 0; i < p_input->i_slave; i++ ) - { - vlc_meta_t *p_meta_slave; - - if( !demux2_Control( p_input->slave[i]->p_demux, - DEMUX_GET_META, &p_meta_slave ) ) + if( p_meta == NULL ) { - if( p_meta == NULL ) - { - p_meta = p_meta_slave; - } - else if( p_meta_slave ) - { - vlc_meta_Merge( p_meta, p_meta_slave ); - vlc_meta_Delete( p_meta_slave ); - } + p_meta = p_meta_tmp; + } + else if( p_meta_tmp ) + { + vlc_meta_Merge( p_meta, p_meta_tmp ); + vlc_meta_Delete( p_meta_tmp ); } - if( p_input->slave[i]->p_access && - !access2_Control( p_input->slave[i]->p_access, - ACCESS_GET_META, &p_meta_slave ) ) + /* Get meta data from slave input */ + for( i = 0; i < p_input->i_slave; i++ ) { - if( p_meta == NULL ) + vlc_meta_t *p_meta_slave; + + if( !demux2_Control( p_input->slave[i]->p_demux, + DEMUX_GET_META, &p_meta_slave ) ) { - p_meta = p_meta_slave; + if( p_meta == NULL ) + { + p_meta = p_meta_slave; + } + else if( p_meta_slave ) + { + vlc_meta_Merge( p_meta, p_meta_slave ); + vlc_meta_Delete( p_meta_slave ); + } } - else if( p_meta_slave ) + + if( p_input->slave[i]->p_access && + !access2_Control( p_input->slave[i]->p_access, + ACCESS_GET_META, &p_meta_slave ) ) { - vlc_meta_Merge( p_meta, p_meta_slave ); - vlc_meta_Delete( p_meta_slave ); + if( p_meta == NULL ) + { + p_meta = p_meta_slave; + } + else if( p_meta_slave ) + { + vlc_meta_Merge( p_meta, p_meta_slave ); + vlc_meta_Delete( p_meta_slave ); + } } } - } p_input->p_meta = p_meta; - UpdateMeta( p_input ); + UpdateMeta( p_input, b_quick ); - msg_Dbg( p_input, "`%s' sucessfully opened", - p_input->input.p_item->psz_uri ); + if( !b_quick ) + { + msg_Dbg( p_input, "`%s' sucessfully opened", + p_input->input.p_item->psz_uri ); + + } /* Trigger intf update for this item */ /* Playlist has a callback on this variable and will forward @@ -1407,7 +1529,8 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, { input_source_t *slave = InputSourceNew( p_input ); - if( !InputSourceInit( p_input, slave, val.psz_string, NULL ) ) + if( !InputSourceInit( p_input, slave, val.psz_string, NULL, + VLC_FALSE ) ) { vlc_meta_t *p_meta_new = NULL; vlc_meta_t *p_meta; @@ -1465,7 +1588,7 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, { p_input->p_meta = p_meta_new; } - UpdateMeta( p_input ); + UpdateMeta( p_input, VLC_FALSE ); } TAB_APPEND( p_input->i_slave, p_input->slave, slave ); @@ -1584,7 +1707,7 @@ static int UpdateFromAccess( input_thread_t *p_input ) p_input->p_meta = p_meta; } - UpdateMeta( p_input ); + UpdateMeta( p_input, VLC_FALSE ); var_SetBool( p_input, "item-change", p_input->input.p_item->i_id ); } p_access->info.i_update &= ~INPUT_UPDATE_META; @@ -1622,7 +1745,7 @@ static int UpdateFromAccess( input_thread_t *p_input ) /***************************************************************************** * UpdateMeta: *****************************************************************************/ -static int UpdateMeta( input_thread_t *p_input ) +static int UpdateMeta( input_thread_t *p_input, vlc_bool_t b_quick ) { vlc_meta_t *p_meta = p_input->p_meta; int i; @@ -1630,11 +1753,12 @@ static int UpdateMeta( input_thread_t *p_input ) if( !p_meta || p_meta->i_meta == 0 ) return VLC_SUCCESS; - msg_Dbg( p_input, "meta information:" ); + if( !b_quick ) msg_Dbg( p_input, "meta information:" ); for( i = 0; i < p_meta->i_meta; i++ ) { - msg_Dbg( p_input, " - '%s' = '%s'", - _(p_meta->name[i]), p_meta->value[i] ); + if( !b_quick ) + msg_Dbg( p_input, " - '%s' = '%s'", + _(p_meta->name[i]), p_meta->value[i] ); if( !strcmp(p_meta->name[i], VLC_META_TITLE) && p_meta->value[i] && !p_input->input.p_item->b_fixed_name ) @@ -1682,7 +1806,8 @@ static int UpdateMeta( input_thread_t *p_input ) /***************************************************************************** * UpdateItemLength: *****************************************************************************/ -static void UpdateItemLength( input_thread_t *p_input, int64_t i_length ) +static void UpdateItemLength( input_thread_t *p_input, int64_t i_length, + vlc_bool_t b_quick ) { playlist_t *p_playlist; char psz_buffer[MSTRTIME_MAX_SIZE]; @@ -1690,11 +1815,15 @@ static void UpdateItemLength( input_thread_t *p_input, int64_t i_length ) vlc_mutex_lock( &p_input->input.p_item->lock ); p_input->input.p_item->i_duration = i_length; vlc_mutex_unlock( &p_input->input.p_item->lock ); - p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_PARENT); - var_SetInteger( p_playlist, "item-change", - p_input->input.p_item->i_id ); - vlc_object_release( p_playlist ); - + + p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, + FIND_PARENT); + if( p_playlist ) + { + var_SetInteger( p_playlist, "item-change", + p_input->input.p_item->i_id ); + vlc_object_release( p_playlist ); + } input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Duration"), msecstotimestr( psz_buffer, i_length / 1000 ) ); @@ -1726,7 +1855,7 @@ static input_source_t *InputSourceNew( input_thread_t *p_input ) *****************************************************************************/ static int InputSourceInit( input_thread_t *p_input, input_source_t *in, char *psz_mrl, - char *psz_forced_demux ) + char *psz_forced_demux, vlc_bool_t b_quick ) { char *psz_dup = strdup( psz_mrl ); char *psz_access; @@ -1735,27 +1864,38 @@ static int InputSourceInit( input_thread_t *p_input, vlc_value_t val; /* Split uri */ - MRLSplit( p_input, psz_dup, &psz_access, &psz_demux, &psz_path ); + if( !b_quick ) + { + MRLSplit( p_input, psz_dup, &psz_access, &psz_demux, &psz_path ); - msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'", - psz_mrl, psz_access, psz_demux, psz_path ); + msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'", + psz_mrl, psz_access, psz_demux, psz_path ); - /* Hack to allow udp://@:port syntax */ - if( !psz_access || - (strncmp( psz_access, "udp", 3 ) && strncmp( psz_access, "rtp", 3 )) ) + /* Hack to allow udp://@:port syntax */ + if( !psz_access || + (strncmp( psz_access, "udp", 3 ) && + strncmp( psz_access, "rtp", 3 )) ) - /* Find optional titles and seekpoints */ - MRLSections( p_input, psz_path, &in->i_title_start, &in->i_title_end, - &in->i_seekpoint_start, &in->i_seekpoint_end ); + /* Find optional titles and seekpoints */ + MRLSections( p_input, psz_path, &in->i_title_start, &in->i_title_end, + &in->i_seekpoint_start, &in->i_seekpoint_end ); - if( psz_forced_demux && *psz_forced_demux ) - psz_demux = psz_forced_demux; + if( psz_forced_demux && *psz_forced_demux ) + psz_demux = psz_forced_demux; - /* Try access_demux if no demux given */ - if( *psz_demux == '\0' ) + /* Try access_demux if no demux given */ + if( *psz_demux == '\0' ) + { + in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path, + NULL, p_input->p_es_out, VLC_FALSE ); + } + } + else { - in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path, - NULL, p_input->p_es_out ); + psz_path = psz_mrl; + msg_Dbg( p_input, "trying to preparse %s", psz_path ); + psz_demux = strdup( "" ); + psz_access = strdup( "file" ); } if( in->p_demux ) @@ -1790,18 +1930,20 @@ static int InputSourceInit( input_thread_t *p_input, int64_t i_pts_delay; /* Now try a real access */ - in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path ); + in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path, + b_quick ); /* Access failed, URL encoded ? */ if( in->p_access == NULL && strchr( psz_path, '%' ) ) { DecodeUrl( psz_path ); - msg_Dbg( p_input, "retying with access `%s' demux `%s' path `%s'", + msg_Dbg( p_input, "retrying with access `%s' demux `%s' path `%s'", psz_access, psz_demux, psz_path ); in->p_access = access2_New( p_input, - psz_access, psz_demux, psz_path ); + psz_access, psz_demux, psz_path, + b_quick ); } #ifndef WIN32 /* Remove this gross hack from the win32 build as colons * are forbidden in filenames on Win32. */ @@ -1817,7 +1959,8 @@ static int InputSourceInit( input_thread_t *p_input, psz_path = psz_dup; in->p_access = access2_New( p_input, - psz_access, psz_demux, psz_path ); + psz_access, psz_demux, psz_path, + b_quick ); } #endif @@ -1828,29 +1971,32 @@ static int InputSourceInit( input_thread_t *p_input, } /* Get infos from access */ - access2_Control( in->p_access, - ACCESS_GET_PTS_DELAY, &i_pts_delay ); - p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay ); + if( !b_quick ) + { + access2_Control( in->p_access, + ACCESS_GET_PTS_DELAY, &i_pts_delay ); + p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay ); - in->b_title_demux = VLC_FALSE; - if( access2_Control( in->p_access, ACCESS_GET_TITLE_INFO, - &in->title, &in->i_title, - &in->i_title_offset, &in->i_seekpoint_offset ) ) + in->b_title_demux = VLC_FALSE; + if( access2_Control( in->p_access, ACCESS_GET_TITLE_INFO, + &in->title, &in->i_title, + &in->i_title_offset, &in->i_seekpoint_offset ) ) - { - in->i_title = 0; - in->title = NULL; + { + in->i_title = 0; + in->title = NULL; + } + access2_Control( in->p_access, ACCESS_CAN_CONTROL_PACE, + &in->b_can_pace_control ); + access2_Control( in->p_access, ACCESS_CAN_PAUSE, + &in->b_can_pause ); + access2_Control( in->p_access, ACCESS_CAN_SEEK, + &val.b_bool ); + var_Set( p_input, "seekable", val ); } - access2_Control( in->p_access, ACCESS_CAN_CONTROL_PACE, - &in->b_can_pace_control ); - access2_Control( in->p_access, ACCESS_CAN_PAUSE, - &in->b_can_pause ); - access2_Control( in->p_access, ACCESS_CAN_SEEK, - &val.b_bool ); - var_Set( p_input, "seekable", val ); /* Create the stream_t */ - in->p_stream = stream_AccessNew( in->p_access ); + in->p_stream = stream_AccessNew( in->p_access, b_quick ); if( in->p_stream == NULL ) { msg_Warn( p_input, "cannot create a stream_t from access" ); @@ -1863,7 +2009,7 @@ static int InputSourceInit( input_thread_t *p_input, psz_demux = in->p_access->psz_demux; } in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path, - in->p_stream, p_input->p_es_out ); + in->p_stream, p_input->p_es_out, b_quick ); if( in->p_demux == NULL ) { msg_Err( p_input, "no suitable demux module for `%s/%s://%s'", @@ -1872,7 +2018,7 @@ static int InputSourceInit( input_thread_t *p_input, } /* TODO get title from demux */ - if( in->i_title <= 0 ) + if( !b_quick && in->i_title <= 0 ) { if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO, &in->title, &in->i_title, diff --git a/src/input/input_internal.h b/src/input/input_internal.h index fc5d4aff32..78adb94e4d 100644 --- a/src/input/input_internal.h +++ b/src/input/input_internal.h @@ -102,7 +102,7 @@ void input_ControlVarTitle( input_thread_t *, int i_title ); void input_ConfigVarInit ( input_thread_t * ); /* stream.c */ -stream_t *stream_AccessNew( access_t *p_access ); +stream_t *stream_AccessNew( access_t *p_access, vlc_bool_t ); void stream_AccessDelete( stream_t *s ); void stream_AccessReset( stream_t *s ); void stream_AccessUpdate( stream_t *s ); diff --git a/src/input/stream.c b/src/input/stream.c index 4dfaa2f929..2cb50efe5b 100644 --- a/src/input/stream.c +++ b/src/input/stream.c @@ -136,6 +136,9 @@ struct stream_sys_t int i_seek_count; int64_t i_seek_time; } stat; + + /* Preparse mode ? */ + vlc_bool_t b_quick; }; /* Method 1: */ @@ -157,7 +160,7 @@ static int AStreamControl( stream_t *, int i_query, va_list ); /**************************************************************************** * stream_AccessNew: create a stream from a access ****************************************************************************/ -stream_t *stream_AccessNew( access_t *p_access ) +stream_t *stream_AccessNew( access_t *p_access, vlc_bool_t b_quick ) { stream_t *s = vlc_object_create( p_access, VLC_OBJECT_STREAM ); stream_sys_t *p_sys; @@ -188,6 +191,8 @@ stream_t *stream_AccessNew( access_t *p_access ) p_sys->stat.i_seek_count = 0; p_sys->stat.i_seek_time = 0; + p_sys->b_quick = b_quick; + /* Peek */ p_sys->i_peek = 0; p_sys->p_peek = NULL; @@ -1129,8 +1134,9 @@ static void AStreamPrebufferStream( stream_t *s ) int64_t i_first = 0; int64_t i_start; - int64_t i_prebuffer = (s->p_sys->p_access->info.i_title > 1 || - s->p_sys->p_access->info.i_seekpoint > 1) ? STREAM_CACHE_PREBUFFER_SIZE : STREAM_CACHE_TRACK_SIZE / 3; + int64_t i_prebuffer = p_sys->b_quick ? STREAM_CACHE_TRACK_SIZE /100 : + ((s->p_sys->p_access->info.i_title > 1 || + s->p_sys->p_access->info.i_seekpoint > 1) ? STREAM_CACHE_PREBUFFER_SIZE : STREAM_CACHE_TRACK_SIZE / 3); msg_Dbg( s, "pre buffering" ); i_start = mdate(); diff --git a/src/playlist/playlist.c b/src/playlist/playlist.c index 26958b4987..5bfc4296a5 100644 --- a/src/playlist/playlist.c +++ b/src/playlist/playlist.c @@ -43,6 +43,7 @@ * Local prototypes *****************************************************************************/ static void RunThread ( playlist_t * ); +static void RunPreparse( playlist_preparse_t * ); static playlist_item_t * NextItem ( playlist_t * ); static int PlayItem ( playlist_t *, playlist_item_t * ); @@ -147,6 +148,31 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) return NULL; } + /* Preparsing stuff */ + p_playlist->p_preparse = vlc_object_create( p_playlist, + sizeof( playlist_preparse_t ) ); + if( !p_playlist->p_preparse ) + { + msg_Err( p_playlist, "unable to create preparser" ); + vlc_object_destroy( p_playlist ); + return NULL; + } + + p_playlist->p_preparse->i_waiting = 0; + p_playlist->p_preparse->pp_waiting = NULL; + vlc_mutex_init( p_playlist->p_preparse, + &p_playlist->p_preparse->object_lock ); + + vlc_object_attach( p_playlist->p_preparse, p_playlist ); + if( vlc_thread_create( p_playlist->p_preparse, "preparser", + RunPreparse, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) + { + msg_Err( p_playlist, "cannot spawn preparse thread" ); + vlc_object_detach( p_playlist->p_preparse ); + vlc_object_destroy( p_playlist->p_preparse ); + return NULL; + } + /* The object has been initialized, now attach it */ vlc_object_attach( p_playlist, p_parent ); @@ -171,8 +197,13 @@ int playlist_Destroy( playlist_t * p_playlist ) p_playlist->pp_sds[i]->psz_module ); } + vlc_thread_join( p_playlist->p_preparse ); vlc_thread_join( p_playlist ); + vlc_object_detach( p_playlist->p_preparse ); + + vlc_mutex_destroy( &p_playlist->p_preparse->object_lock ); + var_Destroy( p_playlist, "intf-change" ); var_Destroy( p_playlist, "item-change" ); var_Destroy( p_playlist, "playlist-current" ); @@ -195,6 +226,7 @@ int playlist_Destroy( playlist_t * p_playlist ) free( p_view ); } + vlc_object_destroy( p_playlist->p_preparse ); vlc_object_destroy( p_playlist ); return VLC_SUCCESS; @@ -368,6 +400,18 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ) return VLC_SUCCESS; } +int playlist_PreparseEnqueue( playlist_t *p_playlist, + input_item_t *p_item ) +{ + vlc_mutex_lock( &p_playlist->p_preparse->object_lock ); + INSERT_ELEM( p_playlist->p_preparse->pp_waiting, + p_playlist->p_preparse->i_waiting, + p_playlist->p_preparse->i_waiting, + p_item ); + vlc_mutex_unlock( &p_playlist->p_preparse->object_lock ); + return VLC_SUCCESS; +} + /* Destroy remaining objects */ static mtime_t ObjectGarbageCollector( playlist_t *p_playlist, int i_type, @@ -641,6 +685,37 @@ static void RunThread ( playlist_t *p_playlist ) } } +/* Queue for items to preparse */ +static void RunPreparse ( playlist_preparse_t *p_obj ) +{ + playlist_t *p_playlist = p_obj->p_parent; + vlc_bool_t b_sleep; + + /* Tell above that we're ready */ + vlc_thread_ready( p_obj ); + + while( !p_playlist->b_die ) + { + vlc_mutex_lock( &p_obj->object_lock ); + + if( p_obj->i_waiting > 0 ) + { + input_Preparse( p_playlist, p_obj->pp_waiting[0] ); + var_SetInteger( p_playlist, "item-change", + p_obj->pp_waiting[0]->i_id ); + REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 ); + } + b_sleep = ( p_obj->i_waiting == 0 ); + + vlc_mutex_unlock( &p_obj->object_lock ); + + if( p_obj->i_waiting == 0 ) + { + msleep( INTF_IDLE_SLEEP ); + } + } +} + /***************************************************************************** * NextItem ***************************************************************************** @@ -840,6 +915,10 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) playlist_view_t *p_view = playlist_ViewFind( p_playlist, p_playlist->status.i_view ); + fprintf(stderr,"Finding next of %s within %s, view %i\n", + p_playlist->status.p_item ? p_playlist->status.p_item->input.psz_name : "coincoin", + p_playlist->status.p_node->input.psz_name, + p_playlist->status.i_view) ; p_new = playlist_FindNextFromParent( p_playlist, p_playlist->status.i_view, p_view->p_root,