1 /*****************************************************************************
2 * input.c: input thread
3 *****************************************************************************
4 * Copyright (C) 1998-2007 the VideoLAN team
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Laurent Aimar <fenrir@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include "input_internal.h"
36 #include "../stream_output/stream_output.h"
38 #include <vlc_playlist.h>
39 #include <vlc_interface.h>
41 #include <vlc_demux.h>
42 #include <vlc_charset.h>
44 #ifdef HAVE_SYS_STAT_H
45 # include <sys/stat.h>
48 /*****************************************************************************
50 *****************************************************************************/
51 static int Run ( input_thread_t *p_input );
52 static int RunAndDestroy ( input_thread_t *p_input );
54 static input_thread_t * Create ( vlc_object_t *, input_item_t *,
55 const char *, vlc_bool_t, sout_instance_t * );
56 static int Init ( input_thread_t *p_input );
57 static void Error ( input_thread_t *p_input );
58 static void End ( input_thread_t *p_input );
59 static void MainLoop( input_thread_t *p_input );
60 static void Destroy( input_thread_t *p_input, sout_instance_t **pp_sout );
62 static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
63 static void ControlReduce( input_thread_t * );
64 static vlc_bool_t Control( input_thread_t *, int, vlc_value_t );
66 static int UpdateFromAccess( input_thread_t * );
67 static int UpdateFromDemux( input_thread_t * );
68 static int UpdateMeta( input_thread_t * );
70 static void UpdateItemLength( input_thread_t *, int64_t i_length );
72 static void MRLSections( input_thread_t *, char *, int *, int *, int *, int *);
74 static input_source_t *InputSourceNew( input_thread_t *);
75 static int InputSourceInit( input_thread_t *, input_source_t *,
76 const char *, const char *psz_forced_demux );
77 static void InputSourceClean( input_source_t * );
79 static void SlaveDemux( input_thread_t *p_input );
80 static void SlaveSeek( input_thread_t *p_input );
82 static void InputMetaUser( input_thread_t *p_input );
84 static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, vlc_bool_t * );
85 static void SoutKeep( sout_instance_t * );
87 /*****************************************************************************
88 * This function creates a new input, and returns a pointer
89 * to its description. On error, it returns NULL.
91 * Variables for _public_ use:
94 * - rate,rate-slower, rate-faster
95 * - position, position-offset
97 * - title,title-next,title-prev
98 * - chapter,chapter-next, chapter-prev
99 * - program, audio-es, video-es, spu-es
100 * - audio-delay, spu-delay
105 * - seekable (if you can seek, it doesn't say if 'bar display' has be shown or not, for that check position != 0.0)
106 * * For intf callback upon changes
108 * TODO explain when Callback is called
109 * TODO complete this list (?)
110 *****************************************************************************/
111 static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
112 const char *psz_header, vlc_bool_t b_quick, sout_instance_t *p_sout )
114 input_thread_t *p_input = NULL; /* thread descriptor */
118 /* Allocate descriptor */
119 p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
120 if( p_input == NULL )
122 msg_Err( p_parent, "out of memory" );
125 MALLOC_NULL( p_input->p, input_thread_private_t );
127 /* One "randomly" selected input thread is responsible for computing
128 * the global stats. Check if there is already someone doing this */
129 if( p_input->p_libvlc->p_playlist->p_stats && !b_quick )
131 vlc_mutex_lock( &p_input->p_libvlc->p_playlist->p_stats->lock );
132 if( p_input->p_libvlc->p_playlist->p_stats_computer == NULL )
134 p_input->p_libvlc->p_playlist->p_stats_computer = p_input;
136 vlc_mutex_unlock( &p_input->p_libvlc->p_playlist->p_stats->lock );
139 p_input->b_preparsing = b_quick;
140 p_input->psz_header = psz_header ? strdup( psz_header ) : NULL;
142 /* Init Common fields */
143 p_input->b_eof = VLC_FALSE;
144 p_input->b_can_pace_control = VLC_TRUE;
145 p_input->p->i_start = 0;
147 p_input->p->i_stop = 0;
148 p_input->p->i_title = 0;
149 p_input->p->title = NULL;
150 p_input->p->i_title_offset = p_input->p->i_seekpoint_offset = 0;
151 p_input->i_state = INIT_S;
152 p_input->p->i_rate = INPUT_RATE_DEFAULT;
153 p_input->p->i_bookmark = 0;
154 p_input->p->bookmark = NULL;
155 p_input->p->p_meta = NULL;
156 p_input->p->p_es_out = NULL;
157 p_input->p->p_sout = NULL;
158 p_input->p->b_sout_keep = VLC_FALSE;
159 p_input->p->b_out_pace_control = VLC_FALSE;
160 p_input->i_pts_delay = 0;
162 /* Init Input fields */
163 p_input->p->input.p_item = p_item;
164 p_input->p->input.p_access = NULL;
165 p_input->p->input.p_stream = NULL;
166 p_input->p->input.p_demux = NULL;
167 p_input->p->input.b_title_demux = VLC_FALSE;
168 p_input->p->input.i_title = 0;
169 p_input->p->input.title = NULL;
170 p_input->p->input.i_title_offset = p_input->p->input.i_seekpoint_offset = 0;
171 p_input->p->input.b_can_pace_control = VLC_TRUE;
172 p_input->p->input.b_eof = VLC_FALSE;
173 p_input->p->input.i_cr_average = 0;
175 if( !p_input->p->input.p_item->p_meta )
176 p_input->p->input.p_item->p_meta = vlc_meta_New();
178 if( !p_item->p_stats )
180 p_item->p_stats = (input_stats_t*)malloc( sizeof( input_stats_t ) );
181 vlc_mutex_init( p_input, &p_item->p_stats->lock );
182 stats_ReinitInputStats( p_item->p_stats );
186 p_input->p->i_slave = 0;
187 p_input->p->slave = NULL;
189 /* Init control buffer */
190 vlc_mutex_init( p_input, &p_input->p->lock_control );
191 p_input->p->i_control = 0;
193 /* Parse input options */
194 vlc_mutex_lock( &p_item->lock );
195 for( i = 0; i < p_item->i_options; i++ )
196 var_OptionParse( p_input, p_item->ppsz_options[i] );
197 vlc_mutex_unlock( &p_item->lock );
199 /* Create Object Variables for private use only */
200 input_ConfigVarInit( p_input );
202 /* Create Objects variables for public Get and Set */
203 input_ControlVarInit( p_input );
205 p_input->p->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
207 if( !p_input->b_preparsing )
209 var_Get( p_input, "bookmarks", &val );
212 /* FIXME: have a common cfg parsing routine used by sout and others */
213 char *psz_parser, *psz_start, *psz_end;
214 psz_parser = val.psz_string;
215 while( (psz_start = strchr( psz_parser, '{' ) ) )
217 seekpoint_t *p_seekpoint = vlc_seekpoint_New();
220 psz_end = strchr( psz_start, '}' );
221 if( !psz_end ) break;
222 psz_parser = psz_end + 1;
223 backup = *psz_parser;
226 while( (psz_end = strchr( psz_start, ',' ) ) )
229 if( !strncmp( psz_start, "name=", 5 ) )
231 p_seekpoint->psz_name = psz_start + 5;
233 else if( !strncmp( psz_start, "bytes=", 6 ) )
235 p_seekpoint->i_byte_offset = atoll(psz_start + 6);
237 else if( !strncmp( psz_start, "time=", 5 ) )
239 p_seekpoint->i_time_offset = atoll(psz_start + 5) *
242 psz_start = psz_end + 1;
244 msg_Dbg( p_input, "adding bookmark: %s, bytes="I64Fd", time="I64Fd,
245 p_seekpoint->psz_name, p_seekpoint->i_byte_offset,
246 p_seekpoint->i_time_offset );
247 input_Control( p_input, INPUT_ADD_BOOKMARK, p_seekpoint );
248 vlc_seekpoint_Delete( p_seekpoint );
249 *psz_parser = backup;
251 free( val.psz_string );
255 /* Remove 'Now playing' info as it is probably outdated */
256 input_Control( p_input, INPUT_DEL_INFO, _(VLC_META_INFO_CAT), VLC_META_NOW_PLAYING );
257 vlc_meta_SetNowPlaying( p_item->p_meta, NULL );
260 if( p_input->b_preparsing )
261 p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
265 p_input->p->p_sout = p_sout;
267 /* Attach only once we are ready */
268 vlc_object_attach( p_input, p_parent );
273 static void Destroy( input_thread_t *p_input, sout_instance_t **pp_sout )
275 vlc_object_detach( p_input );
279 if( p_input->p->p_sout )
282 *pp_sout = p_input->p->p_sout;
283 else if( p_input->p->b_sout_keep )
284 SoutKeep( p_input->p->p_sout );
286 sout_DeleteInstance( p_input->p->p_sout );
289 vlc_mutex_destroy( &p_input->p->lock_control );
292 vlc_object_destroy( p_input );
296 * Initialize an input thread and run it. You will need to monitor the
297 * thread to clean up after it is done
299 * \param p_parent a vlc_object
300 * \param p_item an input item
301 * \return a pointer to the spawned input thread
303 input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
304 input_item_t *p_item )
306 vlc_bool_t b_sout_keep;
307 sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep );
308 input_thread_t *p_input = __input_CreateThreadExtended( p_parent, p_item, NULL, p_sout );
310 if( !p_input && p_sout )
313 p_input->p->b_sout_keep = b_sout_keep;
318 input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
319 input_item_t *p_item,
320 const char *psz_log, sout_instance_t *p_sout )
322 input_thread_t *p_input;
324 p_input = Create( p_parent, p_item, psz_log, VLC_FALSE, p_sout );
328 /* Create thread and wait for its readiness. */
329 if( vlc_thread_create( p_input, "input", Run,
330 VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
332 input_ChangeState( p_input, ERROR_S );
333 msg_Err( p_input, "cannot create input thread" );
334 Destroy( p_input, &p_sout );
342 * Initialize an input thread and run it. This thread will clean after himself,
343 * you can forget about it. It can work either in blocking or non-blocking mode
345 * \param p_parent a vlc_object
346 * \param p_item an input item
347 * \param b_block should we block until read is finished ?
348 * \return the input object id if non blocking, an error code else
350 int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
353 vlc_bool_t b_sout_keep;
354 sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep );
355 input_thread_t *p_input;
357 p_input = Create( p_parent, p_item, NULL, VLC_FALSE, p_sout );
358 if( !p_input && p_sout )
363 p_input->p->b_sout_keep = b_sout_keep;
367 RunAndDestroy( p_input );
372 if( vlc_thread_create( p_input, "input", RunAndDestroy,
373 VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
375 input_ChangeState( p_input, ERROR_S );
376 msg_Err( p_input, "cannot create input thread" );
377 Destroy( p_input, NULL );
381 return p_input->i_object_id;
385 * Initialize an input and initialize it to preparse the item
386 * This function is blocking. It will only accept to parse files
388 * \param p_parent a vlc_object_t
389 * \param p_item an input item
390 * \return VLC_SUCCESS or an error
392 int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
394 input_thread_t *p_input;
396 /* Allocate descriptor */
397 p_input = Create( p_parent, p_item, NULL, VLC_TRUE, NULL );
401 if( !Init( p_input ) )
404 Destroy( p_input, NULL );
410 * Request a running input thread to stop and die
412 * \param the input thread to stop
414 void input_StopThread( input_thread_t *p_input )
419 /* Set die for input */
420 vlc_object_kill( p_input );
421 /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */
423 /* We cannot touch p_input fields directly (we come from another thread),
424 * so use the vlc_object_find way, it's perfectly safe */
426 /* Set die for all access */
427 p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD );
428 for( i = 0; i < p_list->i_count; i++ )
430 vlc_object_kill( p_list->p_values[i].p_object );
432 vlc_list_release( p_list );
434 /* Set die for all stream */
435 p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD );
436 for( i = 0; i < p_list->i_count; i++ )
438 vlc_object_kill( p_list->p_values[i].p_object );
440 vlc_list_release( p_list );
442 /* Set die for all demux */
443 p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD );
444 for( i = 0; i < p_list->i_count; i++ )
446 vlc_object_kill( p_list->p_values[i].p_object );
448 vlc_list_release( p_list );
450 input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
454 * Clean up a dead input thread
455 * This function does not return until the thread is effectively cancelled.
457 * \param the input thread to kill
459 void input_DestroyThread( input_thread_t *p_input )
461 input_DestroyThreadExtended( p_input, NULL );
464 void input_DestroyThreadExtended( input_thread_t *p_input, sout_instance_t **pp_sout )
466 /* Join the thread */
467 vlc_thread_join( p_input );
470 Destroy( p_input, pp_sout );
473 /*****************************************************************************
474 * Run: main thread loop
475 * This is the "normal" thread that spawns the input processing chain,
476 * reads the stream, cleans up and waits
477 *****************************************************************************/
478 static int Run( input_thread_t *p_input )
480 /* Signal that the thread is launched */
481 vlc_thread_ready( p_input );
483 if( Init( p_input ) )
485 /* If we failed, wait before we are killed, and exit */
486 p_input->b_error = VLC_TRUE;
487 playlist_Signal( pl_Get( p_input ) );
491 /* Tell we're dead */
492 p_input->b_dead = VLC_TRUE;
499 if( !p_input->b_eof && !p_input->b_error && p_input->p->input.b_eof )
501 /* We have finish to demux data but not to play them */
502 while( !p_input->b_die )
504 if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
507 msg_Dbg( p_input, "waiting decoder fifos to empty" );
509 msleep( INPUT_IDLE_SLEEP );
512 /* We have finished */
513 p_input->b_eof = VLC_TRUE;
514 playlist_Signal( pl_Get( p_input ) );
517 /* Wait until we are asked to die */
518 if( !p_input->b_die )
529 /*****************************************************************************
530 * RunAndDestroy: main thread loop
531 * This is the "just forget me" thread that spawns the input processing chain,
532 * reads the stream, cleans up and releases memory
533 *****************************************************************************/
534 static int RunAndDestroy( input_thread_t *p_input )
536 /* Signal that the thread is launched */
537 vlc_thread_ready( p_input );
539 if( Init( p_input ) )
544 if( !p_input->b_eof && !p_input->b_error && p_input->p->input.b_eof )
546 /* We have finished demuxing data but not playing it */
547 while( !p_input->b_die )
549 if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
552 msg_Dbg( p_input, "waiting decoder fifos to empty" );
554 msleep( INPUT_IDLE_SLEEP );
557 /* We have finished */
558 p_input->b_eof = VLC_TRUE;
566 Destroy( p_input, NULL );
570 /*****************************************************************************
571 * Main loop: Fill buffers from access, and demux
572 *****************************************************************************/
573 static void MainLoop( input_thread_t *p_input )
575 int64_t i_intf_update = 0;
578 while( !p_input->b_die && !p_input->b_error && !p_input->p->input.b_eof )
580 vlc_bool_t b_force_update = VLC_FALSE;
586 if( p_input->i_state != PAUSE_S )
588 if( p_input->p->i_stop <= 0 || p_input->i_time < p_input->p->i_stop )
589 i_ret=p_input->p->input.p_demux->pf_demux(p_input->p->input.p_demux);
596 if( p_input->p->input.b_title_demux &&
597 p_input->p->input.p_demux->info.i_update )
599 i_ret = UpdateFromDemux( p_input );
600 b_force_update = VLC_TRUE;
602 else if( !p_input->p->input.b_title_demux &&
603 p_input->p->input.p_access &&
604 p_input->p->input.p_access->info.i_update )
606 i_ret = UpdateFromAccess( p_input );
607 b_force_update = VLC_TRUE;
611 if( i_ret == 0 ) /* EOF */
615 var_Get( p_input, "input-repeat", &repeat );
616 if( repeat.i_int == 0 )
618 /* End of file - we do not set b_die because only the
619 * playlist is allowed to do so. */
620 input_ChangeState( p_input, END_S );
621 msg_Dbg( p_input, "EOF reached" );
622 p_input->p->input.b_eof = VLC_TRUE;
626 msg_Dbg( p_input, "repeating the same input (%d)",
628 if( repeat.i_int > 0 )
631 var_Set( p_input, "input-repeat", repeat );
634 /* Seek to start title/seekpoint */
635 val.i_int = p_input->p->input.i_title_start -
636 p_input->p->input.i_title_offset;
637 if( val.i_int < 0 || val.i_int >= p_input->p->input.i_title )
639 input_ControlPush( p_input,
640 INPUT_CONTROL_SET_TITLE, &val );
642 val.i_int = p_input->p->input.i_seekpoint_start -
643 p_input->p->input.i_seekpoint_offset;
644 if( val.i_int > 0 /* TODO: check upper boundary */ )
645 input_ControlPush( p_input,
646 INPUT_CONTROL_SET_SEEKPOINT, &val );
648 /* Seek to start position */
649 if( p_input->p->i_start > 0 )
651 val.i_time = p_input->p->i_start;
652 input_ControlPush( p_input, INPUT_CONTROL_SET_TIME,
658 input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION,
665 p_input->b_error = VLC_TRUE;
668 if( i_ret > 0 && p_input->p->i_slave > 0 )
670 SlaveDemux( p_input );
680 vlc_mutex_lock( &p_input->p->lock_control );
681 ControlReduce( p_input );
682 while( !ControlPopNoLock( p_input, &i_type, &val ) )
684 msg_Dbg( p_input, "control type=%d", i_type );
685 if( Control( p_input, i_type, val ) )
686 b_force_update = VLC_TRUE;
688 vlc_mutex_unlock( &p_input->p->lock_control );
690 if( b_force_update || i_intf_update < mdate() )
694 int64_t i_time, i_length;
695 /* update input status variables */
696 if( !demux2_Control( p_input->p->input.p_demux,
697 DEMUX_GET_POSITION, &f_pos ) )
699 val.f_float = (float)f_pos;
700 var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
702 if( !demux2_Control( p_input->p->input.p_demux,
703 DEMUX_GET_TIME, &i_time ) )
705 p_input->i_time = i_time;
707 var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
709 if( !demux2_Control( p_input->p->input.p_demux,
710 DEMUX_GET_LENGTH, &i_length ) )
713 var_Get( p_input, "length", &old_val );
714 val.i_time = i_length;
715 var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
717 if( old_val.i_time != val.i_time )
719 UpdateItemLength( p_input, i_length );
723 var_SetBool( p_input, "intf-change", VLC_TRUE );
724 i_intf_update = mdate() + I64C(150000);
726 /* 150ms * 8 = ~ 1 second */
727 if( ++i_updates % 8 == 0 )
729 stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
730 /* Are we the thread responsible for computing global stats ? */
731 if( p_input->p_libvlc->p_playlist->p_stats_computer == p_input )
733 stats_ComputeGlobalStats( p_input->p_libvlc->p_playlist,
734 p_input->p_libvlc->p_playlist->p_stats );
740 static int Init( input_thread_t * p_input )
750 /* Initialize optional stream output. (before access/demuxer)
751 * XXX: we add a special case if the uri starts by vlc.
752 * else 'vlc in.file --sout "" vlc:quit' cannot work (the output will
753 * be destroyed in case of a file).
754 * (this will break playing of file starting by 'vlc:' but I don't
755 * want to add more logic, just force file by file:// or code it ;)
757 memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
758 vlc_mutex_init( p_input, &p_input->p->counters.counters_lock );
760 if( !p_input->b_preparsing )
762 /* Prepare statistics */
763 #define INIT_COUNTER( c, type, compute ) p_input->p->counters.p_##c = \
764 stats_CounterCreate( p_input, VLC_VAR_##type, STATS_##compute);
765 if( p_input->p_libvlc->b_stats )
767 INIT_COUNTER( read_bytes, INTEGER, COUNTER );
768 INIT_COUNTER( read_packets, INTEGER, COUNTER );
769 INIT_COUNTER( demux_read, INTEGER, COUNTER );
770 INIT_COUNTER( input_bitrate, FLOAT, DERIVATIVE );
771 INIT_COUNTER( demux_bitrate, FLOAT, DERIVATIVE );
772 INIT_COUNTER( played_abuffers, INTEGER, COUNTER );
773 INIT_COUNTER( lost_abuffers, INTEGER, COUNTER );
774 INIT_COUNTER( displayed_pictures, INTEGER, COUNTER );
775 INIT_COUNTER( lost_pictures, INTEGER, COUNTER );
776 INIT_COUNTER( decoded_audio, INTEGER, COUNTER );
777 INIT_COUNTER( decoded_video, INTEGER, COUNTER );
778 INIT_COUNTER( decoded_sub, INTEGER, COUNTER );
779 p_input->p->counters.p_sout_send_bitrate = NULL;
780 p_input->p->counters.p_sout_sent_packets = NULL;
781 p_input->p->counters.p_sout_sent_bytes = NULL;
782 if( p_input->p->counters.p_demux_bitrate )
783 p_input->p->counters.p_demux_bitrate->update_interval = 1000000;
784 if( p_input->p->counters.p_input_bitrate )
785 p_input->p->counters.p_input_bitrate->update_interval = 1000000;
788 /* Find a usable sout and attach it to p_input */
789 psz = var_GetString( p_input, "sout" );
790 if( *psz && strncasecmp( p_input->p->input.p_item->psz_uri, "vlc:", 4 ) )
792 /* Check the validity of the provided sout */
793 if( p_input->p->p_sout )
795 if( strcmp( p_input->p->p_sout->psz_sout, psz ) )
797 msg_Dbg( p_input, "destroying unusable sout" );
799 sout_DeleteInstance( p_input->p->p_sout );
800 p_input->p->p_sout = NULL;
804 if( p_input->p->p_sout )
807 msg_Dbg( p_input, "sout keep: reusing sout" );
808 msg_Dbg( p_input, "sout keep: you probably want to use "
809 "gather stream_out" );
810 vlc_object_attach( p_input->p->p_sout, p_input );
814 /* Create a new one */
815 p_input->p->p_sout = sout_NewInstance( p_input, psz );
817 if( !p_input->p->p_sout )
819 input_ChangeState( p_input, ERROR_S );
820 msg_Err( p_input, "cannot start stream output instance, " \
827 if( p_input->p_libvlc->b_stats )
829 INIT_COUNTER( sout_sent_packets, INTEGER, COUNTER );
830 INIT_COUNTER (sout_sent_bytes, INTEGER, COUNTER );
831 INIT_COUNTER( sout_send_bitrate, FLOAT, DERIVATIVE );
832 if( p_input->p->counters.p_sout_send_bitrate )
833 p_input->p->counters.p_sout_send_bitrate->update_interval =
837 else if( p_input->p->p_sout )
839 msg_Dbg( p_input, "destroying useless sout" );
841 sout_DeleteInstance( p_input->p->p_sout );
842 p_input->p->p_sout = NULL;
848 p_input->p->p_es_out = input_EsOutNew( p_input );
849 es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
850 es_out_Control( p_input->p->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
852 var_Create( p_input, "bit-rate", VLC_VAR_INTEGER );
853 var_Create( p_input, "sample-rate", VLC_VAR_INTEGER );
855 if( InputSourceInit( p_input, &p_input->p->input,
856 p_input->p->input.p_item->psz_uri, NULL ) )
861 /* Create global title (from master) */
862 if( !p_input->b_preparsing )
864 p_input->p->i_title = p_input->p->input.i_title;
865 p_input->p->title = p_input->p->input.title;
866 p_input->p->i_title_offset = p_input->p->input.i_title_offset;
867 p_input->p->i_seekpoint_offset = p_input->p->input.i_seekpoint_offset;
868 if( p_input->p->i_title > 0 )
870 /* Setup variables */
871 input_ControlVarNavigation( p_input );
872 input_ControlVarTitle( p_input, 0 );
876 p_input->b_can_pace_control = p_input->p->input.b_can_pace_control;
877 p_input->p->b_can_pause = p_input->p->input.b_can_pause;
880 if( p_input->i_pts_delay < 0 )
881 p_input->i_pts_delay = 0;
883 /* If the desynchronisation requested by the user is < 0, we need to
884 * cache more data. */
885 var_Get( p_input, "audio-desync", &val );
886 if( val.i_int < 0 ) p_input->i_pts_delay -= (val.i_int * 1000);
888 /* Update cr_average depending on the caching */
889 p_input->p->input.i_cr_average *= (10 * p_input->i_pts_delay / 200000);
890 p_input->p->input.i_cr_average /= 10;
891 if( p_input->p->input.i_cr_average < 10 ) p_input->p->input.i_cr_average = 10;
894 /* Load master infos */
896 if( !demux2_Control( p_input->p->input.p_demux, DEMUX_GET_LENGTH,
897 &val.i_time ) && val.i_time > 0 )
899 var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
900 UpdateItemLength( p_input, val.i_time );
901 p_input->p->input.p_item->i_duration = val.i_time;
904 /* Start title/chapter */
905 if( !p_input->b_preparsing )
907 val.i_int = p_input->p->input.i_title_start -
908 p_input->p->input.i_title_offset;
909 if( val.i_int > 0 && val.i_int < p_input->p->input.i_title )
910 input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
911 val.i_int = p_input->p->input.i_seekpoint_start -
912 p_input->p->input.i_seekpoint_offset;
913 if( val.i_int > 0 /* TODO: check upper boundary */ )
914 input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val );
918 p_input->p->i_start = (int64_t)var_GetInteger( p_input, "start-time" ) *
920 p_input->p->i_stop = (int64_t)var_GetInteger( p_input, "stop-time" ) *
923 if( p_input->p->i_start > 0 )
925 if( p_input->p->i_start >= val.i_time )
927 msg_Warn( p_input, "invalid start-time ignored" );
933 msg_Dbg( p_input, "starting at time: %ds",
934 (int)( p_input->p->i_start / I64C(1000000) ) );
936 s.i_time = p_input->p->i_start;
937 input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s );
940 if( p_input->p->i_stop > 0 && p_input->p->i_stop <= p_input->p->i_start )
942 msg_Warn( p_input, "invalid stop-time ignored" );
943 p_input->p->i_stop = 0;
947 /* Get fps and set it if not already set */
948 if( !demux2_Control( p_input->p->input.p_demux, DEMUX_GET_FPS, &f_fps ) &&
951 float f_requested_fps;
953 var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT );
954 var_SetFloat( p_input, "sub-original-fps", f_fps );
956 f_requested_fps = var_CreateGetFloat( p_input, "sub-fps" );
957 if( f_requested_fps != f_fps )
959 var_Create( p_input, "sub-fps", VLC_VAR_FLOAT|
961 var_SetFloat( p_input, "sub-fps", f_requested_fps );
965 i_delay = var_CreateGetInteger( p_input, "sub-delay" );
968 var_SetTime( p_input, "spu-delay", (mtime_t)i_delay * 100000 );
971 /* Look for and add subtitle files */
972 psz_subtitle = var_GetString( p_input, "sub-file" );
975 msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle );
976 input_AddSubtitles( p_input, psz_subtitle, VLC_FALSE );
979 var_Get( p_input, "sub-autodetect-file", &val );
982 char *psz_autopath = var_GetString( p_input, "sub-autodetect-path" );
983 char **subs = subtitles_Detect( p_input, psz_autopath,
984 p_input->p->input.p_item->psz_uri );
988 /* Try to autoselect the first autodetected subtitles file
989 * if no subtitles file was specified */
990 if( *psz_subtitle == 0 && subs && subs[0] )
992 input_AddSubtitles( p_input, subs[0], VLC_FALSE );
997 /* Then, just add the following subtitles files */
998 for( ; subs && subs[i]; i++ )
1000 if( strcmp( psz_subtitle, subs[i] ) )
1002 sub = InputSourceNew( p_input );
1003 if( !InputSourceInit( p_input, sub, subs[i], "subtitle" ) )
1005 TAB_APPEND( p_input->p->i_slave, p_input->p->slave, sub );
1011 if( subs ) free( subs );
1012 if( psz_autopath ) free( psz_autopath );
1014 free( psz_subtitle );
1016 /* Look for slave */
1017 psz = var_GetString( p_input, "input-slave" );
1021 input_source_t *slave;
1022 while( psz && *psz )
1024 while( *psz == ' ' || *psz == '#' )
1028 if( ( psz_delim = strchr( psz, '#' ) ) )
1030 *psz_delim++ = '\0';
1037 msg_Dbg( p_input, "adding slave input '%s'", psz );
1038 slave = InputSourceNew( p_input );
1039 if( !InputSourceInit( p_input, slave, psz, NULL ) )
1041 TAB_APPEND( p_input->p->i_slave, p_input->p->slave, slave );
1047 if( psz ) free( psz );
1051 p_input->p->i_start = 0;
1052 p_input->p->i_start = 0;
1056 if( !p_input->b_preparsing )
1058 es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
1059 i_es_out_mode = ES_OUT_MODE_AUTO;
1061 if( p_input->p->p_sout )
1063 var_Get( p_input, "sout-all", &val );
1066 i_es_out_mode = ES_OUT_MODE_ALL;
1071 var_Get( p_input, "programs", &val );
1072 if ( val.p_list && val.p_list->i_count )
1074 i_es_out_mode = ES_OUT_MODE_PARTIAL;
1075 /* Note : we should remove the "program" callback. */
1078 var_Change( p_input, "programs", VLC_VAR_FREELIST, &val,
1082 es_out_Control( p_input->p->p_es_out, ES_OUT_SET_MODE, i_es_out_mode );
1084 /* Inform the demuxer about waited group (needed only for DVB) */
1085 if( i_es_out_mode == ES_OUT_MODE_ALL )
1087 demux2_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP, -1, NULL );
1089 else if( i_es_out_mode == ES_OUT_MODE_PARTIAL )
1091 demux2_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP, -1,
1096 demux2_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP,
1097 (int) var_GetInteger( p_input, "program" ), NULL );
1100 if( p_input->p->p_sout )
1102 if( p_input->p->p_sout->i_out_pace_nocontrol > 0 )
1104 p_input->p->b_out_pace_control = VLC_FALSE;
1108 p_input->p->b_out_pace_control = VLC_TRUE;
1111 if( p_input->b_can_pace_control && p_input->p->b_out_pace_control )
1113 /* We don't want a high input priority here or we'll
1114 * end-up sucking up all the CPU time */
1115 vlc_thread_set_priority( p_input, VLC_THREAD_PRIORITY_LOW );
1118 msg_Dbg( p_input, "starting in %s mode",
1119 p_input->p->b_out_pace_control ? "async" : "sync" );
1123 p_meta = p_input->p->input.p_item->p_meta;
1124 /* Get meta data from users */
1125 InputMetaUser( p_input );
1126 /* Get meta data from master input */
1127 demux2_Control( p_input->p->input.p_demux, DEMUX_GET_META, p_meta );
1129 /* Access_file does not give any meta, and there are no slave */
1130 if( !p_input->b_preparsing )
1132 if( p_input->p->input.p_access )
1133 access2_Control( p_input->p->input.p_access, ACCESS_GET_META,
1136 /* Get meta data from slave input */
1137 for( i = 0; i < p_input->p->i_slave; i++ )
1139 demux2_Control( p_input->p->slave[i]->p_demux,
1140 DEMUX_GET_META, p_meta );
1141 if( p_input->p->slave[i]->p_access )
1143 access2_Control( p_input->p->slave[i]->p_access,
1144 ACCESS_GET_META, p_meta );
1149 UpdateMeta( p_input );
1151 if( !p_input->b_preparsing )
1153 msg_Dbg( p_input, "`%s' successfully opened",
1154 p_input->p->input.p_item->psz_uri );
1158 /* initialization is complete */
1159 input_ChangeState( p_input, PLAYING_S );
1164 input_ChangeState( p_input, ERROR_S );
1166 if( p_input->p->p_es_out )
1167 input_EsOutDelete( p_input->p->p_es_out );
1169 if( p_input->p->p_sout )
1171 vlc_object_detach( p_input->p->p_sout );
1172 sout_DeleteInstance( p_input->p->p_sout );
1176 if( !p_input->b_preparsing && p_input->p_libvlc->b_stats )
1178 #define EXIT_COUNTER( c ) do { if( p_input->p->counters.p_##c ) \
1179 stats_CounterClean( p_input->p->counters.p_##c );\
1180 p_input->p->counters.p_##c = NULL; } while(0)
1181 EXIT_COUNTER( read_bytes );
1182 EXIT_COUNTER( read_packets );
1183 EXIT_COUNTER( demux_read );
1184 EXIT_COUNTER( input_bitrate );
1185 EXIT_COUNTER( demux_bitrate );
1186 EXIT_COUNTER( played_abuffers );
1187 EXIT_COUNTER( lost_abuffers );
1188 EXIT_COUNTER( displayed_pictures );
1189 EXIT_COUNTER( lost_pictures );
1190 EXIT_COUNTER( decoded_audio );
1191 EXIT_COUNTER( decoded_video );
1192 EXIT_COUNTER( decoded_sub );
1194 if( p_input->p->p_sout )
1196 EXIT_COUNTER( sout_sent_packets );
1197 EXIT_COUNTER (sout_sent_bytes );
1198 EXIT_COUNTER( sout_send_bitrate );
1203 /* Mark them deleted */
1204 p_input->p->input.p_demux = NULL;
1205 p_input->p->input.p_stream = NULL;
1206 p_input->p->input.p_access = NULL;
1207 p_input->p->p_es_out = NULL;
1208 p_input->p->p_sout = NULL;
1210 return VLC_EGENERIC;
1213 /*****************************************************************************
1214 * Error: RunThread() error loop
1215 *****************************************************************************
1216 * This function is called when an error occurred during thread main's loop.
1217 *****************************************************************************/
1218 static void Error( input_thread_t *p_input )
1220 while( !p_input->b_die )
1223 input_ChangeState( p_input, ERROR_S );
1224 msleep( INPUT_IDLE_SLEEP );
1228 /*****************************************************************************
1229 * End: end the input thread
1230 *****************************************************************************/
1231 static void End( input_thread_t * p_input )
1235 /* We are at the end */
1236 input_ChangeState( p_input, END_S );
1238 /* Clean control variables */
1239 input_ControlVarClean( p_input );
1241 /* Clean up master */
1242 InputSourceClean( &p_input->p->input );
1245 for( i = 0; i < p_input->p->i_slave; i++ )
1247 InputSourceClean( p_input->p->slave[i] );
1248 free( p_input->p->slave[i] );
1250 if( p_input->p->slave ) free( p_input->p->slave );
1252 /* Unload all modules */
1253 if( p_input->p->p_es_out )
1254 input_EsOutDelete( p_input->p->p_es_out );
1256 if( !p_input->b_preparsing )
1258 #define CL_CO( c ) stats_CounterClean( p_input->p->counters.p_##c ); p_input->p->counters.p_##c = NULL;
1259 if( p_input->p_libvlc->b_stats )
1261 /* make sure we are up to date */
1262 stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
1263 if( p_input->p_libvlc->p_playlist->p_stats_computer == p_input )
1265 stats_ComputeGlobalStats( p_input->p_libvlc->p_playlist,
1266 p_input->p_libvlc->p_playlist->p_stats );
1267 p_input->p_libvlc->p_playlist->p_stats_computer = NULL;
1269 CL_CO( read_bytes );
1270 CL_CO( read_packets );
1271 CL_CO( demux_read );
1272 CL_CO( input_bitrate );
1273 CL_CO( demux_bitrate );
1274 CL_CO( played_abuffers );
1275 CL_CO( lost_abuffers );
1276 CL_CO( displayed_pictures );
1277 CL_CO( lost_pictures );
1278 CL_CO( decoded_audio) ;
1279 CL_CO( decoded_video );
1280 CL_CO( decoded_sub) ;
1283 /* Close optional stream output instance */
1284 if( p_input->p->p_sout )
1286 CL_CO( sout_sent_packets );
1287 CL_CO( sout_sent_bytes );
1288 CL_CO( sout_send_bitrate );
1290 vlc_object_detach( p_input->p->p_sout );
1295 vlc_mutex_destroy( &p_input->p->counters.counters_lock );
1297 /* Tell we're dead */
1298 p_input->b_dead = VLC_TRUE;
1301 static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, vlc_bool_t *pb_sout_keep )
1303 vlc_bool_t b_keep_sout = var_CreateGetBool( p_parent, "sout-keep" );
1304 sout_instance_t *p_sout = NULL;
1307 /* Search sout-keep options
1308 * XXX it has to be done here, but it is duplicated work :( */
1309 vlc_mutex_lock( &p_item->lock );
1310 for( i = 0; i < p_item->i_options; i++ )
1312 const char *psz_option = p_item->ppsz_options[i];
1315 if( *psz_option == ':' )
1318 if( !strcmp( psz_option, "sout-keep" ) )
1319 b_keep_sout = VLC_TRUE;
1320 else if( !strcmp( psz_option, "no-sout-keep" ) || !strcmp( psz_option, "nosout-keep" ) )
1321 b_keep_sout = VLC_FALSE;
1323 vlc_mutex_unlock( &p_item->lock );
1325 /* Find a potential sout to reuse
1326 * XXX it might be unusable but this will be checked later */
1329 /* Remove the sout from the playlist garbage collector */
1330 playlist_t *p_playlist = pl_Yield( p_parent );
1332 vlc_mutex_lock( &p_playlist->gc_lock );
1333 p_sout = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD );
1336 if( p_sout->p_parent != VLC_OBJECT(p_playlist) )
1338 vlc_object_release( p_sout );
1343 vlc_object_detach( p_sout ); /* Remove it from the GC */
1345 vlc_object_release( p_sout );
1348 vlc_mutex_unlock( &p_playlist->gc_lock );
1350 pl_Release( p_parent );
1354 *pb_sout_keep = b_keep_sout;
1358 static void SoutKeep( sout_instance_t *p_sout )
1360 /* attach sout to the playlist */
1361 playlist_t *p_playlist = pl_Yield( p_sout );
1363 msg_Dbg( p_sout, "sout has been kept" );
1364 vlc_object_attach( p_sout, p_playlist );
1366 pl_Release( p_sout );
1369 /*****************************************************************************
1371 *****************************************************************************/
1372 static inline int ControlPopNoLock( input_thread_t *p_input,
1373 int *pi_type, vlc_value_t *p_val )
1375 if( p_input->p->i_control <= 0 )
1377 return VLC_EGENERIC;
1380 *pi_type = p_input->p->control[0].i_type;
1381 *p_val = p_input->p->control[0].val;
1383 p_input->p->i_control--;
1384 if( p_input->p->i_control > 0 )
1388 for( i = 0; i < p_input->p->i_control; i++ )
1390 p_input->p->control[i].i_type = p_input->p->control[i+1].i_type;
1391 p_input->p->control[i].val = p_input->p->control[i+1].val;
1398 static void ControlReduce( input_thread_t *p_input )
1405 for( i = 1; i < p_input->p->i_control; i++ )
1407 const int i_lt = p_input->p->control[i-1].i_type;
1408 const int i_ct = p_input->p->control[i].i_type;
1410 /* XXX We can't merge INPUT_CONTROL_SET_ES */
1411 /* msg_Dbg( p_input, "[%d/%d] l=%d c=%d", i, p_input->p->i_control,
1415 ( i_ct == INPUT_CONTROL_SET_STATE ||
1416 i_ct == INPUT_CONTROL_SET_RATE ||
1417 i_ct == INPUT_CONTROL_SET_POSITION ||
1418 i_ct == INPUT_CONTROL_SET_TIME ||
1419 i_ct == INPUT_CONTROL_SET_PROGRAM ||
1420 i_ct == INPUT_CONTROL_SET_TITLE ||
1421 i_ct == INPUT_CONTROL_SET_SEEKPOINT ||
1422 i_ct == INPUT_CONTROL_SET_BOOKMARK ) )
1425 // msg_Dbg( p_input, "merged at %d", i );
1426 /* Remove the i-1 */
1427 for( j = i; j < p_input->p->i_control; j++ )
1428 p_input->p->control[j-1] = p_input->p->control[j];
1429 p_input->p->i_control--;
1433 /* TODO but that's not that important
1434 - merge SET_X with SET_X_CMD
1435 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
1436 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
1443 static vlc_bool_t Control( input_thread_t *p_input, int i_type,
1446 vlc_bool_t b_force_update = VLC_FALSE;
1448 if( !p_input ) return b_force_update;
1452 case INPUT_CONTROL_SET_DIE:
1453 msg_Dbg( p_input, "control: stopping input" );
1454 /* Mark all submodules to die */
1455 if( p_input->p->input.p_access )
1456 vlc_object_kill( p_input->p->input.p_access );
1457 if( p_input->p->input.p_stream )
1458 vlc_object_kill( p_input->p->input.p_stream );
1459 vlc_object_kill( p_input->p->input.p_demux );
1461 vlc_object_kill( p_input );
1464 case INPUT_CONTROL_SET_POSITION:
1465 case INPUT_CONTROL_SET_POSITION_OFFSET:
1468 if( i_type == INPUT_CONTROL_SET_POSITION )
1470 f_pos = val.f_float;
1474 /* Should not fail */
1475 demux2_Control( p_input->p->input.p_demux,
1476 DEMUX_GET_POSITION, &f_pos );
1477 f_pos += val.f_float;
1479 if( f_pos < 0.0 ) f_pos = 0.0;
1480 if( f_pos > 1.0 ) f_pos = 1.0;
1481 /* Reset the decoders states and clock sync (before calling the demuxer */
1482 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1483 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE, VLC_FALSE );
1484 if( demux2_Control( p_input->p->input.p_demux, DEMUX_SET_POSITION,
1487 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION(_OFFSET) "
1488 "%2.1f%% failed", f_pos * 100 );
1492 if( p_input->p->i_slave > 0 )
1493 SlaveSeek( p_input );
1495 b_force_update = VLC_TRUE;
1500 case INPUT_CONTROL_SET_TIME:
1501 case INPUT_CONTROL_SET_TIME_OFFSET:
1506 if( i_type == INPUT_CONTROL_SET_TIME )
1508 i_time = val.i_time;
1512 /* Should not fail */
1513 demux2_Control( p_input->p->input.p_demux,
1514 DEMUX_GET_TIME, &i_time );
1515 i_time += val.i_time;
1517 if( i_time < 0 ) i_time = 0;
1519 /* Reset the decoders states and clock sync (before calling the demuxer */
1520 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1521 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE, VLC_FALSE );
1523 i_ret = demux2_Control( p_input->p->input.p_demux,
1524 DEMUX_SET_TIME, i_time );
1529 /* Emulate it with a SET_POS */
1530 demux2_Control( p_input->p->input.p_demux,
1531 DEMUX_GET_LENGTH, &i_length );
1534 double f_pos = (double)i_time / (double)i_length;
1535 i_ret = demux2_Control( p_input->p->input.p_demux,
1536 DEMUX_SET_POSITION, f_pos );
1541 msg_Warn( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) "I64Fd
1542 " failed or not possible", i_time );
1546 if( p_input->p->i_slave > 0 )
1547 SlaveSeek( p_input );
1549 b_force_update = VLC_TRUE;
1554 case INPUT_CONTROL_SET_STATE:
1555 if( ( val.i_int == PLAYING_S && p_input->i_state == PAUSE_S ) ||
1556 ( val.i_int == PAUSE_S && p_input->i_state == PAUSE_S ) )
1559 if( p_input->p->input.p_access )
1560 i_ret = access2_Control( p_input->p->input.p_access,
1561 ACCESS_SET_PAUSE_STATE, VLC_FALSE );
1563 i_ret = demux2_Control( p_input->p->input.p_demux,
1564 DEMUX_SET_PAUSE_STATE, VLC_FALSE );
1568 /* FIXME What to do ? */
1569 msg_Warn( p_input, "cannot unset pause -> EOF" );
1570 vlc_mutex_unlock( &p_input->p->lock_control );
1571 input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
1572 vlc_mutex_lock( &p_input->p->lock_control );
1575 b_force_update = VLC_TRUE;
1577 /* Switch to play */
1578 p_input->i_state = PLAYING_S;
1579 val.i_int = PLAYING_S;
1580 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
1583 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1585 else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S &&
1586 p_input->p->b_can_pause )
1589 if( p_input->p->input.p_access )
1590 i_ret = access2_Control( p_input->p->input.p_access,
1591 ACCESS_SET_PAUSE_STATE, VLC_TRUE );
1593 i_ret = demux2_Control( p_input->p->input.p_demux,
1594 DEMUX_SET_PAUSE_STATE, VLC_TRUE );
1596 b_force_update = VLC_TRUE;
1600 msg_Warn( p_input, "cannot set pause state" );
1601 val.i_int = p_input->i_state;
1605 val.i_int = PAUSE_S;
1608 /* Switch to new state */
1609 p_input->i_state = val.i_int;
1610 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
1612 /* Send discontinuity to decoders (it will allow them to flush
1614 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_FALSE, VLC_FALSE );
1616 else if( val.i_int == PAUSE_S && !p_input->p->b_can_pause )
1618 b_force_update = VLC_TRUE;
1620 /* Correct "state" value */
1621 val.i_int = p_input->i_state;
1622 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
1624 else if( val.i_int != PLAYING_S && val.i_int != PAUSE_S )
1626 msg_Err( p_input, "invalid state in INPUT_CONTROL_SET_STATE" );
1630 case INPUT_CONTROL_SET_RATE:
1631 case INPUT_CONTROL_SET_RATE_SLOWER:
1632 case INPUT_CONTROL_SET_RATE_FASTER:
1636 if( i_type == INPUT_CONTROL_SET_RATE_SLOWER )
1637 i_rate = p_input->p->i_rate * 2;
1638 else if( i_type == INPUT_CONTROL_SET_RATE_FASTER )
1639 i_rate = p_input->p->i_rate / 2;
1643 if( i_rate < INPUT_RATE_MIN )
1645 msg_Dbg( p_input, "cannot set rate faster" );
1646 i_rate = INPUT_RATE_MIN;
1648 else if( i_rate > INPUT_RATE_MAX )
1650 msg_Dbg( p_input, "cannot set rate slower" );
1651 i_rate = INPUT_RATE_MAX;
1653 if( i_rate != INPUT_RATE_DEFAULT &&
1654 ( !p_input->b_can_pace_control ||
1655 ( p_input->p->p_sout && !p_input->p->b_out_pace_control ) ) )
1657 msg_Dbg( p_input, "cannot change rate" );
1658 i_rate = INPUT_RATE_DEFAULT;
1660 if( i_rate != p_input->p->i_rate )
1663 var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
1665 /* We will not send audio data if new rate != default */
1666 if( i_rate != INPUT_RATE_DEFAULT && p_input->p->i_rate == INPUT_RATE_DEFAULT )
1667 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE, VLC_TRUE );
1669 p_input->p->i_rate = i_rate;
1672 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1674 b_force_update = VLC_TRUE;
1679 case INPUT_CONTROL_SET_PROGRAM:
1680 /* No need to force update, es_out does it if needed */
1681 es_out_Control( p_input->p->p_es_out,
1682 ES_OUT_SET_GROUP, val.i_int );
1684 demux2_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP, val.i_int,
1688 case INPUT_CONTROL_SET_ES:
1689 /* No need to force update, es_out does it if needed */
1690 es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ES,
1691 input_EsOutGetFromID( p_input->p->p_es_out,
1695 case INPUT_CONTROL_SET_AUDIO_DELAY:
1696 input_EsOutSetDelay( p_input->p->p_es_out,
1697 AUDIO_ES, val.i_time );
1698 var_Change( p_input, "audio-delay", VLC_VAR_SETVALUE, &val, NULL );
1701 case INPUT_CONTROL_SET_SPU_DELAY:
1702 input_EsOutSetDelay( p_input->p->p_es_out,
1703 SPU_ES, val.i_time );
1704 var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
1707 case INPUT_CONTROL_SET_TITLE:
1708 case INPUT_CONTROL_SET_TITLE_NEXT:
1709 case INPUT_CONTROL_SET_TITLE_PREV:
1710 if( p_input->p->input.b_title_demux &&
1711 p_input->p->input.i_title > 0 )
1714 /* FIXME handle demux title */
1715 demux_t *p_demux = p_input->p->input.p_demux;
1718 if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
1719 i_title = p_demux->info.i_title - 1;
1720 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
1721 i_title = p_demux->info.i_title + 1;
1723 i_title = val.i_int;
1725 if( i_title >= 0 && i_title < p_input->p->input.i_title )
1727 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1728 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE, VLC_FALSE );
1730 demux2_Control( p_demux, DEMUX_SET_TITLE, i_title );
1731 input_ControlVarTitle( p_input, i_title );
1734 else if( p_input->p->input.i_title > 0 )
1736 access_t *p_access = p_input->p->input.p_access;
1739 if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
1740 i_title = p_access->info.i_title - 1;
1741 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
1742 i_title = p_access->info.i_title + 1;
1744 i_title = val.i_int;
1746 if( i_title >= 0 && i_title < p_input->p->input.i_title )
1748 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1749 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE, VLC_FALSE );
1751 access2_Control( p_access, ACCESS_SET_TITLE, i_title );
1752 stream_AccessReset( p_input->p->input.p_stream );
1756 case INPUT_CONTROL_SET_SEEKPOINT:
1757 case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
1758 case INPUT_CONTROL_SET_SEEKPOINT_PREV:
1759 if( p_input->p->input.b_title_demux &&
1760 p_input->p->input.i_title > 0 )
1762 demux_t *p_demux = p_input->p->input.p_demux;
1764 int64_t i_input_time;
1765 int64_t i_seekpoint_time;
1767 if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
1769 i_seekpoint = p_demux->info.i_seekpoint;
1770 i_seekpoint_time = p_input->p->input.title[p_demux->info.i_title]->seekpoint[i_seekpoint]->i_time_offset;
1771 if( i_seekpoint_time >= 0 &&
1772 !demux2_Control( p_demux,
1773 DEMUX_GET_TIME, &i_input_time ) )
1775 if ( i_input_time < i_seekpoint_time + 3000000 )
1781 else if( i_type == INPUT_CONTROL_SET_SEEKPOINT_NEXT )
1782 i_seekpoint = p_demux->info.i_seekpoint + 1;
1784 i_seekpoint = val.i_int;
1786 if( i_seekpoint >= 0 && i_seekpoint <
1787 p_input->p->input.title[p_demux->info.i_title]->i_seekpoint )
1789 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1790 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE, VLC_FALSE );
1792 demux2_Control( p_demux, DEMUX_SET_SEEKPOINT, i_seekpoint );
1795 else if( p_input->p->input.i_title > 0 )
1797 demux_t *p_demux = p_input->p->input.p_demux;
1798 access_t *p_access = p_input->p->input.p_access;
1800 int64_t i_input_time;
1801 int64_t i_seekpoint_time;
1803 if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
1805 i_seekpoint = p_access->info.i_seekpoint;
1806 i_seekpoint_time = p_input->p->input.title[p_access->info.i_title]->seekpoint[i_seekpoint]->i_time_offset;
1807 if( i_seekpoint_time >= 0 &&
1808 demux2_Control( p_demux,
1809 DEMUX_GET_TIME, &i_input_time ) )
1811 if ( i_input_time < i_seekpoint_time + 3000000 )
1817 else if( i_type == INPUT_CONTROL_SET_SEEKPOINT_NEXT )
1818 i_seekpoint = p_access->info.i_seekpoint + 1;
1820 i_seekpoint = val.i_int;
1822 if( i_seekpoint >= 0 && i_seekpoint <
1823 p_input->p->input.title[p_access->info.i_title]->i_seekpoint )
1825 es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1826 input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE, VLC_FALSE );
1828 access2_Control( p_access, ACCESS_SET_SEEKPOINT,
1830 stream_AccessReset( p_input->p->input.p_stream );
1835 case INPUT_CONTROL_ADD_SLAVE:
1836 if( val.psz_string )
1838 input_source_t *slave = InputSourceNew( p_input );
1840 if( !InputSourceInit( p_input, slave, val.psz_string, NULL ) )
1842 vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta;
1846 msg_Dbg( p_input, "adding %s as slave on the fly",
1850 if( demux2_Control( p_input->p->input.p_demux,
1851 DEMUX_GET_TIME, &i_time ) )
1853 msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
1854 InputSourceClean( slave );
1858 if( demux2_Control( slave->p_demux,
1859 DEMUX_SET_TIME, i_time ) )
1861 msg_Err( p_input, "seek failed for new slave" );
1862 InputSourceClean( slave );
1867 /* Get meta (access and demux) */
1868 access2_Control( slave->p_access, ACCESS_GET_META,
1870 demux2_Control( slave->p_demux, DEMUX_GET_META, p_meta );
1871 UpdateMeta( p_input );
1873 TAB_APPEND( p_input->p->i_slave, p_input->p->slave, slave );
1878 msg_Warn( p_input, "failed to add %s as slave",
1882 free( val.psz_string );
1886 case INPUT_CONTROL_SET_BOOKMARK:
1888 msg_Err( p_input, "not yet implemented" );
1892 return b_force_update;
1895 /*****************************************************************************
1897 *****************************************************************************/
1898 static int UpdateFromDemux( input_thread_t *p_input )
1900 demux_t *p_demux = p_input->p->input.p_demux;
1903 if( p_demux->info.i_update & INPUT_UPDATE_TITLE )
1905 v.i_int = p_demux->info.i_title;
1906 var_Change( p_input, "title", VLC_VAR_SETVALUE, &v, NULL );
1908 input_ControlVarTitle( p_input, p_demux->info.i_title );
1910 p_demux->info.i_update &= ~INPUT_UPDATE_TITLE;
1912 if( p_demux->info.i_update & INPUT_UPDATE_SEEKPOINT )
1914 v.i_int = p_demux->info.i_seekpoint;
1915 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &v, NULL);
1917 p_demux->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
1919 p_demux->info.i_update &= ~INPUT_UPDATE_SIZE;
1921 /* Hmmm only works with master input */
1922 if( p_input->p->input.p_demux == p_demux )
1924 int i_title_end = p_input->p->input.i_title_end -
1925 p_input->p->input.i_title_offset;
1926 int i_seekpoint_end = p_input->p->input.i_seekpoint_end -
1927 p_input->p->input.i_seekpoint_offset;
1929 if( i_title_end >= 0 && i_seekpoint_end >= 0 )
1931 if( p_demux->info.i_title > i_title_end ||
1932 ( p_demux->info.i_title == i_title_end &&
1933 p_demux->info.i_seekpoint > i_seekpoint_end ) ) return 0;
1935 else if( i_seekpoint_end >=0 )
1937 if( p_demux->info.i_seekpoint > i_seekpoint_end ) return 0;
1939 else if( i_title_end >= 0 )
1941 if( p_demux->info.i_title > i_title_end ) return 0;
1948 /*****************************************************************************
1950 *****************************************************************************/
1951 static int UpdateFromAccess( input_thread_t *p_input )
1953 access_t *p_access = p_input->p->input.p_access;
1956 if( p_access->info.i_update & INPUT_UPDATE_TITLE )
1958 v.i_int = p_access->info.i_title;
1959 var_Change( p_input, "title", VLC_VAR_SETVALUE, &v, NULL );
1961 input_ControlVarTitle( p_input, p_access->info.i_title );
1963 stream_AccessUpdate( p_input->p->input.p_stream );
1965 p_access->info.i_update &= ~INPUT_UPDATE_TITLE;
1967 if( p_access->info.i_update & INPUT_UPDATE_SEEKPOINT )
1969 v.i_int = p_access->info.i_seekpoint;
1970 var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &v, NULL);
1971 p_access->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
1973 if( p_access->info.i_update & INPUT_UPDATE_META )
1975 /* TODO maybe multi - access ? */
1976 vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta;
1977 access2_Control( p_input->p->input.p_access,ACCESS_GET_META, p_meta );
1978 UpdateMeta( p_input );
1979 var_SetBool( p_input, "item-change", p_input->p->input.p_item->i_id );
1980 p_access->info.i_update &= ~INPUT_UPDATE_META;
1983 p_access->info.i_update &= ~INPUT_UPDATE_SIZE;
1985 /* Hmmm only works with master input */
1986 if( p_input->p->input.p_access == p_access )
1988 int i_title_end = p_input->p->input.i_title_end -
1989 p_input->p->input.i_title_offset;
1990 int i_seekpoint_end = p_input->p->input.i_seekpoint_end -
1991 p_input->p->input.i_seekpoint_offset;
1993 if( i_title_end >= 0 && i_seekpoint_end >=0 )
1995 if( p_access->info.i_title > i_title_end ||
1996 ( p_access->info.i_title == i_title_end &&
1997 p_access->info.i_seekpoint > i_seekpoint_end ) ) return 0;
1999 else if( i_seekpoint_end >=0 )
2001 if( p_access->info.i_seekpoint > i_seekpoint_end ) return 0;
2003 else if( i_title_end >= 0 )
2005 if( p_access->info.i_title > i_title_end ) return 0;
2012 /*****************************************************************************
2014 *****************************************************************************/
2015 static int UpdateMeta( input_thread_t *p_input )
2017 vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta;
2021 if( p_meta->psz_title && !p_input->p->input.p_item->b_fixed_name )
2022 input_Control( p_input, INPUT_SET_NAME, p_meta->psz_title );
2024 /** \todo handle sout meta */
2029 /*****************************************************************************
2031 *****************************************************************************/
2032 static void UpdateItemLength( input_thread_t *p_input, int64_t i_length )
2034 vlc_mutex_lock( &p_input->p->input.p_item->lock );
2035 p_input->p->input.p_item->i_duration = i_length;
2036 vlc_mutex_unlock( &p_input->p->input.p_item->lock );
2038 if( !p_input->b_preparsing )
2040 pl_Yield( p_input );
2041 var_SetInteger( pl_Get( p_input ), "item-change",
2042 p_input->p->input.p_item->i_id );
2043 pl_Release( p_input )
2047 /*****************************************************************************
2049 *****************************************************************************/
2050 static input_source_t *InputSourceNew( input_thread_t *p_input )
2052 input_source_t *in = (input_source_t*) malloc( sizeof( input_source_t ) );
2056 msg_Err( p_input, "out of memory for new input source" );
2061 in->p_access = NULL;
2062 in->p_stream = NULL;
2064 in->b_title_demux = VLC_FALSE;
2067 in->b_can_pace_control = VLC_TRUE;
2068 in->b_eof = VLC_FALSE;
2069 in->i_cr_average = 0;
2074 /*****************************************************************************
2076 *****************************************************************************/
2077 static int InputSourceInit( input_thread_t *p_input,
2078 input_source_t *in, const char *psz_mrl,
2079 const char *psz_forced_demux )
2081 char psz_dup[strlen (psz_mrl) + 1];
2082 const char *psz_access;
2083 const char *psz_demux;
2089 strcpy( psz_dup, psz_mrl );
2091 if( !in ) return VLC_EGENERIC;
2092 if( !p_input ) return VLC_EGENERIC;
2095 if( !p_input->b_preparsing )
2097 MRLSplit( VLC_OBJECT(p_input), psz_dup,
2098 &psz_access, &psz_demux, &psz_path );
2100 msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
2101 psz_mrl, psz_access, psz_demux, psz_path );
2103 /* Hack to allow udp://@:port syntax */
2105 (strncmp( psz_access, "udp", 3 ) &&
2106 strncmp( psz_access, "rtp", 3 )) )
2108 /* Find optional titles and seekpoints */
2109 MRLSections( p_input, psz_path, &in->i_title_start, &in->i_title_end,
2110 &in->i_seekpoint_start, &in->i_seekpoint_end );
2112 if( psz_forced_demux && *psz_forced_demux )
2114 psz_demux = psz_forced_demux;
2116 else if( !psz_demux || *psz_demux == '\0' )
2118 /* special hack for forcing a demuxer with --demux=module
2119 * (and do nothing with a list) */
2120 char *psz_var_demux = var_GetString( p_input, "demux" );
2122 if( *psz_var_demux != '\0' &&
2123 !strchr(psz_var_demux, ',' ) &&
2124 !strchr(psz_var_demux, ':' ) )
2126 psz_demux = psz_var_demux;
2128 msg_Dbg( p_input, "enforced demux ` %s'", psz_demux );
2130 else if( psz_var_demux )
2132 free( psz_var_demux );
2136 /* Try access_demux if no demux given */
2137 if( *psz_demux == '\0' )
2139 in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
2140 NULL, p_input->p->p_es_out, VLC_FALSE );
2146 if( !strncmp( psz_path, "file://", 7 ) )
2148 msg_Dbg( p_input, "trying to pre-parse %s", psz_path );
2150 psz_access = "file";
2155 int64_t i_pts_delay;
2157 /* Get infos from access_demux */
2158 demux2_Control( in->p_demux,
2159 DEMUX_GET_PTS_DELAY, &i_pts_delay );
2160 p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
2162 in->b_title_demux = VLC_TRUE;
2163 if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
2164 &in->title, &in->i_title,
2165 &in->i_title_offset, &in->i_seekpoint_offset ) )
2170 demux2_Control( in->p_demux, DEMUX_CAN_CONTROL_PACE,
2171 &in->b_can_pace_control );
2172 demux2_Control( in->p_demux, DEMUX_CAN_PAUSE,
2176 demux2_Control( in->p_demux, DEMUX_CAN_SEEK,
2182 int64_t i_pts_delay;
2184 input_ChangeState( p_input, OPENING_S );
2186 /* Now try a real access */
2187 in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path,
2188 p_input->b_preparsing );
2190 /* Access failed, URL encoded ? */
2191 if( in->p_access == NULL && strchr( psz_path, '%' ) )
2193 decode_URI( psz_path );
2195 msg_Dbg( p_input, "retrying with access `%s' demux `%s' path `%s'",
2196 psz_access, psz_demux, psz_path );
2198 in->p_access = access2_New( p_input,
2199 psz_access, psz_demux, psz_path,
2200 p_input->b_preparsing );
2203 if( in->p_access == NULL )
2205 msg_Err( p_input, "open of `%s' failed: %s", psz_mrl,
2207 intf_UserFatal( VLC_OBJECT( p_input), VLC_FALSE,
2208 _("Your input can't be opened"),
2209 _("VLC is unable to open the MRL '%s'."
2210 " Check the log for details."), psz_mrl );
2215 psz_tmp = psz = var_GetString( p_input, "access-filter" );
2216 while( psz && *psz )
2218 access_t *p_access = in->p_access;
2219 char *end = strchr( psz, ':' );
2224 in->p_access = access2_FilterNew( in->p_access, psz );
2225 if( in->p_access == NULL )
2227 in->p_access = p_access;
2228 msg_Warn( p_input, "failed to insert access filter %s",
2234 if( psz_tmp ) free( psz_tmp );
2236 /* Get infos from access */
2237 if( !p_input->b_preparsing )
2239 access2_Control( in->p_access,
2240 ACCESS_GET_PTS_DELAY, &i_pts_delay );
2241 p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
2243 in->b_title_demux = VLC_FALSE;
2244 if( access2_Control( in->p_access, ACCESS_GET_TITLE_INFO,
2245 &in->title, &in->i_title,
2246 &in->i_title_offset, &in->i_seekpoint_offset ) )
2252 access2_Control( in->p_access, ACCESS_CAN_CONTROL_PACE,
2253 &in->b_can_pace_control );
2254 access2_Control( in->p_access, ACCESS_CAN_PAUSE,
2256 access2_Control( in->p_access, ACCESS_CAN_SEEK,
2258 var_Set( p_input, "seekable", val );
2261 input_ChangeState( p_input, BUFFERING_S );
2263 /* Create the stream_t */
2264 in->p_stream = stream_AccessNew( in->p_access, p_input->b_preparsing );
2265 if( in->p_stream == NULL )
2267 msg_Warn( p_input, "cannot create a stream_t from access" );
2271 /* Open a demuxer */
2272 if( *psz_demux == '\0' && *in->p_access->psz_demux )
2274 psz_demux = in->p_access->psz_demux;
2278 /* Take access redirections into account */
2279 char *psz_real_path;
2280 char *psz_buf = NULL;
2281 if( in->p_access->psz_path )
2283 const char *psz_a, *psz_d;
2284 psz_buf = strdup( in->p_access->psz_path );
2285 MRLSplit( VLC_OBJECT(p_input), psz_buf,
2286 &psz_a, &psz_d, &psz_real_path );
2290 psz_real_path = psz_path;
2292 in->p_demux = demux2_New( p_input, psz_access, psz_demux,
2294 in->p_stream, p_input->p->p_es_out,
2295 p_input->b_preparsing );
2299 if( in->p_demux == NULL )
2301 msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
2302 psz_access, psz_demux, psz_path );
2303 intf_UserFatal( VLC_OBJECT( p_input ), VLC_FALSE,
2304 _("Can't recognize the input's format"),
2305 _("The format of '%s' can't be detected. "
2306 "Have a look the log for details."), psz_mrl );
2310 /* TODO get title from demux */
2311 if( !p_input->b_preparsing && in->i_title <= 0 )
2313 if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
2314 &in->title, &in->i_title,
2315 &in->i_title_offset, &in->i_seekpoint_offset ))
2322 in->b_title_demux = VLC_TRUE;
2327 if( var_GetInteger( p_input, "clock-synchro" ) != -1 )
2328 in->b_can_pace_control = !var_GetInteger( p_input, "clock-synchro" );
2333 input_ChangeState( p_input, ERROR_S );
2336 demux2_Delete( in->p_demux );
2339 stream_Delete( in->p_stream );
2342 access2_Delete( in->p_access );
2344 return VLC_EGENERIC;
2347 /*****************************************************************************
2349 *****************************************************************************/
2350 static void InputSourceClean( input_source_t *in )
2353 demux2_Delete( in->p_demux );
2356 stream_Delete( in->p_stream );
2359 access2_Delete( in->p_access );
2361 if( in->i_title > 0 )
2364 for( i = 0; i < in->i_title; i++ )
2366 vlc_input_title_Delete( in->title[i] );
2372 static void SlaveDemux( input_thread_t *p_input )
2377 if( demux2_Control( p_input->p->input.p_demux, DEMUX_GET_TIME, &i_time ) )
2379 msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
2383 for( i = 0; i < p_input->p->i_slave; i++ )
2385 input_source_t *in = p_input->p->slave[i];
2391 if( demux2_Control( in->p_demux, DEMUX_SET_NEXT_DEMUX_TIME, i_time ) )
2396 if( demux2_Control( in->p_demux, DEMUX_GET_TIME, &i_stime ) )
2398 msg_Err( p_input, "slave[%d] doesn't like "
2399 "DEMUX_GET_TIME -> EOF", i );
2404 if( i_stime >= i_time )
2407 if( ( i_ret = in->p_demux->pf_demux( in->p_demux ) ) <= 0 )
2413 i_ret = in->p_demux->pf_demux( in->p_demux );
2418 msg_Dbg( p_input, "slave %d EOF", i );
2419 in->b_eof = VLC_TRUE;
2424 static void SlaveSeek( input_thread_t *p_input )
2429 if( !p_input ) return;
2431 if( demux2_Control( p_input->p->input.p_demux, DEMUX_GET_TIME, &i_time ) )
2433 msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
2437 for( i = 0; i < p_input->p->i_slave; i++ )
2439 input_source_t *in = p_input->p->slave[i];
2441 if( demux2_Control( in->p_demux, DEMUX_SET_TIME, i_time ) )
2443 msg_Err( p_input, "seek failed for slave %d -> EOF", i );
2444 in->b_eof = VLC_TRUE;
2449 /*****************************************************************************
2451 *****************************************************************************/
2452 static void InputMetaUser( input_thread_t *p_input )
2454 vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta;
2457 if( !p_meta ) return;
2459 /* Get meta information from user */
2460 #define GET_META( field, s ) \
2461 var_Get( p_input, (s), &val ); \
2462 if( *val.psz_string ) { \
2463 if( p_meta->psz_ ## field ) free ( p_meta->psz_ ## field ); \
2464 p_meta->psz_ ## field = strdup( val.psz_string ); \
2466 free( val.psz_string )
2468 GET_META( title, "meta-title" );
2469 GET_META( artist, "meta-artist" );
2470 GET_META( genre, "meta-genre" );
2471 GET_META( copyright, "meta-copyright" );
2472 GET_META( description, "meta-description" );
2473 GET_META( date, "meta-date" );
2474 GET_META( url, "meta-url" );
2478 /*****************************************************************************
2479 * MRLSplit: parse the access, demux and url part of the
2480 * Media Resource Locator.
2481 *****************************************************************************/
2482 void MRLSplit( vlc_object_t *p_input, char *psz_dup,
2483 const char **ppsz_access, const char **ppsz_demux,
2486 const char *psz_access = "";
2487 const char *psz_demux = "";
2489 char *psz, *psz_check;
2491 psz = strchr( psz_dup, ':' );
2493 /* '@' not allowed in access/demux part */
2494 psz_check = strchr( psz_dup, '@' );
2495 if( psz_check && psz_check < psz ) psz = 0;
2497 #if defined( WIN32 ) || defined( UNDER_CE )
2498 if( psz - psz_dup == 1 )
2500 msg_Dbg( p_input, "drive letter %c: found in source", *psz_dup );
2511 if( psz[0] == '/' && psz[1] == '/' ) psz += 2;
2515 psz = strchr( psz_dup, '/' );
2522 psz_access = psz_dup;
2529 *ppsz_access = psz_access;
2530 *ppsz_demux = psz_demux;
2531 *ppsz_path = psz_path;
2534 /*****************************************************************************
2535 * MRLSections: parse title and seekpoint info from the Media Resource Locator.
2538 * [url][@[title-start][:chapter-start][-[title-end][:chapter-end]]]
2539 *****************************************************************************/
2540 static void MRLSections( input_thread_t *p_input, char *psz_source,
2541 int *pi_title_start, int *pi_title_end,
2542 int *pi_chapter_start, int *pi_chapter_end )
2544 char *psz, *psz_end, *psz_next, *psz_check;
2546 *pi_title_start = *pi_title_end = -1;
2547 *pi_chapter_start = *pi_chapter_end = -1;
2549 /* Start by parsing titles and chapters */
2550 if( !psz_source || !( psz = strrchr( psz_source, '@' ) ) ) return;
2552 /* Check we are really dealing with a title/chapter section */
2553 psz_check = psz + 1;
2554 if( !*psz_check ) return;
2555 if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
2556 if( *psz_check != ':' && *psz_check != '-' && *psz_check ) return;
2557 if( *psz_check == ':' && ++psz_check )
2558 if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
2559 if( *psz_check != '-' && *psz_check ) return;
2560 if( *psz_check == '-' && ++psz_check )
2561 if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
2562 if( *psz_check != ':' && *psz_check ) return;
2563 if( *psz_check == ':' && ++psz_check )
2564 if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
2565 if( *psz_check ) return;
2567 /* Separate start and end */
2569 if( ( psz_end = strchr( psz, '-' ) ) ) *psz_end++ = 0;
2571 /* Look for the start title */
2572 *pi_title_start = strtol( psz, &psz_next, 0 );
2573 if( !*pi_title_start && psz == psz_next ) *pi_title_start = -1;
2574 *pi_title_end = *pi_title_start;
2577 /* Look for the start chapter */
2579 *pi_chapter_start = strtol( psz, &psz_next, 0 );
2580 if( !*pi_chapter_start && psz == psz_next ) *pi_chapter_start = -1;
2581 *pi_chapter_end = *pi_chapter_start;
2585 /* Look for the end title */
2586 *pi_title_end = strtol( psz_end, &psz_next, 0 );
2587 if( !*pi_title_end && psz_end == psz_next ) *pi_title_end = -1;
2590 /* Look for the end chapter */
2591 if( *psz_end ) psz_end++;
2592 *pi_chapter_end = strtol( psz_end, &psz_next, 0 );
2593 if( !*pi_chapter_end && psz_end == psz_next ) *pi_chapter_end = -1;
2596 msg_Dbg( p_input, "source=`%s' title=%d/%d seekpoint=%d/%d",
2597 psz_source, *pi_title_start, *pi_chapter_start,
2598 *pi_title_end, *pi_chapter_end );
2601 /*****************************************************************************
2602 * input_AddSubtitles: add a subtitles file and enable it
2603 *****************************************************************************/
2604 vlc_bool_t input_AddSubtitles( input_thread_t *p_input, char *psz_subtitle,
2605 vlc_bool_t b_check_extension )
2607 input_source_t *sub;
2610 char *psz_path, *psz_extension;
2612 if( b_check_extension && !subtitles_Filter( psz_subtitle ) )
2617 /* if we are provided a subtitle.sub file,
2618 * see if we don't have a subtitle.idx and use it instead */
2619 psz_path = strdup( psz_subtitle );
2622 psz_extension = strrchr( psz_path, '.');
2623 if( psz_extension && strcmp( psz_extension, ".sub" ) == 0 )
2627 strcpy( psz_extension, ".idx" );
2628 /* FIXME: a portable wrapper for stat() or access() would be more suited */
2629 if( ( f = utf8_fopen( psz_path, "rt" ) ) )
2632 msg_Dbg( p_input, "using %s subtitles file instead of %s",
2633 psz_path, psz_subtitle );
2634 strcpy( psz_subtitle, psz_path );
2640 var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL );
2642 sub = InputSourceNew( p_input );
2643 if( !InputSourceInit( p_input, sub, psz_subtitle, "subtitle" ) )
2645 TAB_APPEND( p_input->p->i_slave, p_input->p->slave, sub );
2648 if( !var_Change( p_input, "spu-es", VLC_VAR_GETLIST, &list, NULL ) )
2650 if( count.i_int == 0 )
2652 /* if it was first one, there is disable too */
2654 if( count.i_int < list.p_list->i_count )
2656 input_ControlPush( p_input, INPUT_CONTROL_SET_ES,
2657 &list.p_list->p_values[count.i_int] );
2659 var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );