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
* );
69 static void UpdateItemLength( input_thread_t
*, int64_t i_length
);
71 static void MRLSections( input_thread_t
*, char *, int *, int *, int *, int *);
73 static input_source_t
*InputSourceNew( input_thread_t
*);
74 static int InputSourceInit( input_thread_t
*, input_source_t
*,
75 const char *, const char *psz_forced_demux
);
76 static void InputSourceClean( input_source_t
* );
78 //static void InputGetAttachments( input_thread_t *, 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
, vlc_meta_t
*p_meta
);
83 static void InputUpdateMeta( input_thread_t
*p_input
, vlc_meta_t
*p_meta
);
85 static sout_instance_t
*SoutFind( vlc_object_t
*p_parent
, input_item_t
*p_item
, vlc_bool_t
* );
86 static void SoutKeep( sout_instance_t
* );
88 static void DemuxMeta( input_thread_t
*p_input
, vlc_meta_t
*p_meta
, demux_t
*p_demux
);
89 static void AppendAttachment( int *pi_attachment
, input_attachment_t
***ppp_attachment
,
90 int i_new
, input_attachment_t
**pp_new
);
92 /*****************************************************************************
93 * This function creates a new input, and returns a pointer
94 * to its description. On error, it returns NULL.
96 * Variables for _public_ use:
99 * - rate,rate-slower, rate-faster
100 * - position, position-offset
101 * - time, time-offset
102 * - title,title-next,title-prev
103 * - chapter,chapter-next, chapter-prev
104 * - program, audio-es, video-es, spu-es
105 * - audio-delay, spu-delay
110 * - seekable (if you can seek, it doesn't say if 'bar display' has be shown or not, for that check position != 0.0)
111 * * For intf callback upon changes
113 * TODO explain when Callback is called
114 * TODO complete this list (?)
115 *****************************************************************************/
116 static input_thread_t
*Create( vlc_object_t
*p_parent
, input_item_t
*p_item
,
117 const char *psz_header
, vlc_bool_t b_quick
, sout_instance_t
*p_sout
)
119 input_thread_t
*p_input
= NULL
; /* thread descriptor */
123 /* Allocate descriptor */
124 p_input
= vlc_object_create( p_parent
, VLC_OBJECT_INPUT
);
125 if( p_input
== NULL
)
127 msg_Err( p_parent
, "out of memory" );
130 MALLOC_NULL( p_input
->p
, input_thread_private_t
);
132 /* One "randomly" selected input thread is responsible for computing
133 * the global stats. Check if there is already someone doing this */
134 if( p_input
->p_libvlc
->p_playlist
->p_stats
&& !b_quick
)
136 vlc_mutex_lock( &p_input
->p_libvlc
->p_playlist
->p_stats
->lock
);
137 if( p_input
->p_libvlc
->p_playlist
->p_stats_computer
== NULL
)
139 p_input
->p_libvlc
->p_playlist
->p_stats_computer
= p_input
;
141 vlc_mutex_unlock( &p_input
->p_libvlc
->p_playlist
->p_stats
->lock
);
144 p_input
->b_preparsing
= b_quick
;
145 p_input
->psz_header
= psz_header
? strdup( psz_header
) : NULL
;
147 /* Init Common fields */
148 p_input
->b_eof
= VLC_FALSE
;
149 p_input
->b_can_pace_control
= VLC_TRUE
;
150 p_input
->p
->i_start
= 0;
152 p_input
->p
->i_stop
= 0;
153 p_input
->p
->i_run
= 0;
154 p_input
->p
->i_title
= 0;
155 p_input
->p
->title
= NULL
;
156 p_input
->p
->i_title_offset
= p_input
->p
->i_seekpoint_offset
= 0;
157 p_input
->i_state
= INIT_S
;
158 p_input
->p
->i_rate
= INPUT_RATE_DEFAULT
;
159 TAB_INIT( p_input
->p
->i_bookmark
, p_input
->p
->bookmark
);
160 TAB_INIT( p_input
->p
->i_attachment
, p_input
->p
->attachment
);
161 p_input
->p
->p_es_out
= NULL
;
162 p_input
->p
->p_sout
= NULL
;
163 p_input
->p
->b_sout_keep
= VLC_FALSE
;
164 p_input
->p
->b_out_pace_control
= VLC_FALSE
;
165 p_input
->i_pts_delay
= 0;
167 /* Init Input fields */
168 p_input
->p
->input
.p_item
= p_item
;
169 p_input
->p
->input
.p_access
= NULL
;
170 p_input
->p
->input
.p_stream
= NULL
;
171 p_input
->p
->input
.p_demux
= NULL
;
172 p_input
->p
->input
.b_title_demux
= VLC_FALSE
;
173 p_input
->p
->input
.i_title
= 0;
174 p_input
->p
->input
.title
= NULL
;
175 p_input
->p
->input
.i_title_offset
= p_input
->p
->input
.i_seekpoint_offset
= 0;
176 p_input
->p
->input
.b_can_pace_control
= VLC_TRUE
;
177 p_input
->p
->input
.b_eof
= VLC_FALSE
;
178 p_input
->p
->input
.i_cr_average
= 0;
180 vlc_mutex_lock( &p_item
->lock
);
182 if( !p_item
->p_stats
)
183 p_item
->p_stats
= stats_NewInputStats( p_input
);
184 vlc_mutex_unlock( &p_item
->lock
);
187 p_input
->p
->i_slave
= 0;
188 p_input
->p
->slave
= NULL
;
190 /* Init control buffer */
191 vlc_mutex_init( p_input
, &p_input
->p
->lock_control
);
192 p_input
->p
->i_control
= 0;
194 /* Parse input options */
195 vlc_mutex_lock( &p_item
->lock
);
196 for( i
= 0; i
< p_item
->i_options
; i
++ )
197 var_OptionParse( p_input
, p_item
->ppsz_options
[i
] );
198 vlc_mutex_unlock( &p_item
->lock
);
200 /* Create Object Variables for private use only */
201 input_ConfigVarInit( p_input
);
203 /* Create Objects variables for public Get and Set */
204 input_ControlVarInit( p_input
);
206 p_input
->p
->input
.i_cr_average
= var_GetInteger( p_input
, "cr-average" );
208 if( !p_input
->b_preparsing
)
210 var_Get( p_input
, "bookmarks", &val
);
213 /* FIXME: have a common cfg parsing routine used by sout and others */
214 char *psz_parser
, *psz_start
, *psz_end
;
215 psz_parser
= val
.psz_string
;
216 while( (psz_start
= strchr( psz_parser
, '{' ) ) )
218 seekpoint_t
*p_seekpoint
= vlc_seekpoint_New();
221 psz_end
= strchr( psz_start
, '}' );
222 if( !psz_end
) break;
223 psz_parser
= psz_end
+ 1;
224 backup
= *psz_parser
;
227 while( (psz_end
= strchr( psz_start
, ',' ) ) )
230 if( !strncmp( psz_start
, "name=", 5 ) )
232 p_seekpoint
->psz_name
= strdup(psz_start
+ 5);
234 else if( !strncmp( psz_start
, "bytes=", 6 ) )
236 p_seekpoint
->i_byte_offset
= atoll(psz_start
+ 6);
238 else if( !strncmp( psz_start
, "time=", 5 ) )
240 p_seekpoint
->i_time_offset
= atoll(psz_start
+ 5) *
243 psz_start
= psz_end
+ 1;
245 msg_Dbg( p_input
, "adding bookmark: %s, bytes="I64Fd
", time="I64Fd
,
246 p_seekpoint
->psz_name
, p_seekpoint
->i_byte_offset
,
247 p_seekpoint
->i_time_offset
);
248 input_Control( p_input
, INPUT_ADD_BOOKMARK
, p_seekpoint
);
249 vlc_seekpoint_Delete( p_seekpoint
);
250 *psz_parser
= backup
;
252 free( val
.psz_string
);
256 /* Remove 'Now playing' info as it is probably outdated */
257 input_Control( p_input
, INPUT_DEL_INFO
,
258 _(VLC_META_INFO_CAT
),
259 _(VLC_META_NOW_PLAYING
) );
260 input_item_SetNowPlaying( p_item
, NULL
);
263 if( p_input
->b_preparsing
)
264 p_input
->i_flags
|= OBJECT_FLAGS_QUIET
| OBJECT_FLAGS_NOINTERACT
;
268 p_input
->p
->p_sout
= p_sout
;
270 /* Attach only once we are ready */
271 vlc_object_attach( p_input
, p_parent
);
276 static void Destroy( input_thread_t
*p_input
, sout_instance_t
**pp_sout
)
278 vlc_object_detach( p_input
);
279 input_thread_private_t
*priv
= p_input
->p
;
286 *pp_sout
= priv
->p_sout
;
287 else if( priv
->b_sout_keep
)
288 SoutKeep( priv
->p_sout
);
290 sout_DeleteInstance( priv
->p_sout
);
293 vlc_object_destroy( p_input
);
294 vlc_mutex_destroy( &priv
->lock_control
);
299 * Initialize an input thread and run it. You will need to monitor the
300 * thread to clean up after it is done
302 * \param p_parent a vlc_object
303 * \param p_item an input item
304 * \return a pointer to the spawned input thread
306 input_thread_t
*__input_CreateThread( vlc_object_t
*p_parent
,
307 input_item_t
*p_item
)
309 vlc_bool_t b_sout_keep
;
310 sout_instance_t
*p_sout
= SoutFind( p_parent
, p_item
, &b_sout_keep
);
311 input_thread_t
*p_input
= __input_CreateThreadExtended( p_parent
, p_item
, NULL
, p_sout
);
313 if( !p_input
&& p_sout
)
316 p_input
->p
->b_sout_keep
= b_sout_keep
;
321 input_thread_t
*__input_CreateThreadExtended( vlc_object_t
*p_parent
,
322 input_item_t
*p_item
,
323 const char *psz_log
, sout_instance_t
*p_sout
)
325 input_thread_t
*p_input
;
327 p_input
= Create( p_parent
, p_item
, psz_log
, VLC_FALSE
, p_sout
);
331 /* Create thread and wait for its readiness. */
332 if( vlc_thread_create( p_input
, "input", Run
,
333 VLC_THREAD_PRIORITY_INPUT
, VLC_TRUE
) )
335 input_ChangeState( p_input
, ERROR_S
);
336 msg_Err( p_input
, "cannot create input thread" );
337 Destroy( p_input
, &p_sout
);
345 * Initialize an input thread and run it. This thread will clean after himself,
346 * you can forget about it. It can work either in blocking or non-blocking mode
348 * \param p_parent a vlc_object
349 * \param p_item an input item
350 * \param b_block should we block until read is finished ?
351 * \return the input object id if non blocking, an error code else
353 int __input_Read( vlc_object_t
*p_parent
, input_item_t
*p_item
,
356 vlc_bool_t b_sout_keep
;
357 sout_instance_t
*p_sout
= SoutFind( p_parent
, p_item
, &b_sout_keep
);
358 input_thread_t
*p_input
;
360 p_input
= Create( p_parent
, p_item
, NULL
, VLC_FALSE
, p_sout
);
361 if( !p_input
&& p_sout
)
366 p_input
->p
->b_sout_keep
= b_sout_keep
;
370 RunAndDestroy( p_input
);
375 if( vlc_thread_create( p_input
, "input", RunAndDestroy
,
376 VLC_THREAD_PRIORITY_INPUT
, VLC_TRUE
) )
378 input_ChangeState( p_input
, ERROR_S
);
379 msg_Err( p_input
, "cannot create input thread" );
380 Destroy( p_input
, NULL
);
384 return p_input
->i_object_id
;
388 * Initialize an input and initialize it to preparse the item
389 * This function is blocking. It will only accept to parse files
391 * \param p_parent a vlc_object_t
392 * \param p_item an input item
393 * \return VLC_SUCCESS or an error
395 int __input_Preparse( vlc_object_t
*p_parent
, input_item_t
*p_item
)
397 input_thread_t
*p_input
;
399 /* Allocate descriptor */
400 p_input
= Create( p_parent
, p_item
, NULL
, VLC_TRUE
, NULL
);
404 if( !Init( p_input
) )
407 Destroy( p_input
, NULL
);
413 * Request a running input thread to stop and die
415 * \param the input thread to stop
417 void input_StopThread( input_thread_t
*p_input
)
422 /* Set die for input */
423 vlc_object_kill( p_input
);
424 /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */
426 /* We cannot touch p_input fields directly (we come from another thread),
427 * so use the vlc_object_find way, it's perfectly safe */
429 /* Set die for all access */
430 p_list
= vlc_list_find( p_input
, VLC_OBJECT_ACCESS
, FIND_CHILD
);
431 for( i
= 0; i
< p_list
->i_count
; i
++ )
433 vlc_object_kill( p_list
->p_values
[i
].p_object
);
435 vlc_list_release( p_list
);
437 /* Set die for all stream */
438 p_list
= vlc_list_find( p_input
, VLC_OBJECT_STREAM
, FIND_CHILD
);
439 for( i
= 0; i
< p_list
->i_count
; i
++ )
441 vlc_object_kill( p_list
->p_values
[i
].p_object
);
443 vlc_list_release( p_list
);
445 /* Set die for all demux */
446 p_list
= vlc_list_find( p_input
, VLC_OBJECT_DEMUX
, FIND_CHILD
);
447 for( i
= 0; i
< p_list
->i_count
; i
++ )
449 vlc_object_kill( p_list
->p_values
[i
].p_object
);
451 vlc_list_release( p_list
);
453 input_ControlPush( p_input
, INPUT_CONTROL_SET_DIE
, NULL
);
457 * Clean up a dead input thread
458 * This function does not return until the thread is effectively cancelled.
460 * \param the input thread to kill
462 void input_DestroyThread( input_thread_t
*p_input
)
464 input_DestroyThreadExtended( p_input
, NULL
);
467 void input_DestroyThreadExtended( input_thread_t
*p_input
, sout_instance_t
**pp_sout
)
469 /* Join the thread */
470 vlc_thread_join( p_input
);
473 Destroy( p_input
, pp_sout
);
476 /*****************************************************************************
477 * Run: main thread loop
478 * This is the "normal" thread that spawns the input processing chain,
479 * reads the stream, cleans up and waits
480 *****************************************************************************/
481 static int Run( input_thread_t
*p_input
)
483 /* Signal that the thread is launched */
484 vlc_thread_ready( p_input
);
486 if( Init( p_input
) )
488 /* If we failed, wait before we are killed, and exit */
489 p_input
->b_error
= VLC_TRUE
;
490 playlist_Signal( pl_Get( p_input
) );
494 /* Tell we're dead */
495 p_input
->b_dead
= VLC_TRUE
;
502 if( !p_input
->b_eof
&& !p_input
->b_error
&& p_input
->p
->input
.b_eof
)
504 /* We have finish to demux data but not to play them */
505 while( !p_input
->b_die
)
507 if( input_EsOutDecodersEmpty( p_input
->p
->p_es_out
) )
510 msg_Dbg( p_input
, "waiting decoder fifos to empty" );
512 msleep( INPUT_IDLE_SLEEP
);
515 /* We have finished */
516 p_input
->b_eof
= VLC_TRUE
;
517 playlist_Signal( pl_Get( p_input
) );
520 /* Wait until we are asked to die */
521 if( !p_input
->b_die
)
532 /*****************************************************************************
533 * RunAndDestroy: main thread loop
534 * This is the "just forget me" thread that spawns the input processing chain,
535 * reads the stream, cleans up and releases memory
536 *****************************************************************************/
537 static int RunAndDestroy( input_thread_t
*p_input
)
539 /* Signal that the thread is launched */
540 vlc_thread_ready( p_input
);
542 if( Init( p_input
) )
547 if( !p_input
->b_eof
&& !p_input
->b_error
&& p_input
->p
->input
.b_eof
)
549 /* We have finished demuxing data but not playing it */
550 while( !p_input
->b_die
)
552 if( input_EsOutDecodersEmpty( p_input
->p
->p_es_out
) )
555 msg_Dbg( p_input
, "waiting decoder fifos to empty" );
557 msleep( INPUT_IDLE_SLEEP
);
560 /* We have finished */
561 p_input
->b_eof
= VLC_TRUE
;
569 Destroy( p_input
, NULL
);
573 /*****************************************************************************
574 * Main loop: Fill buffers from access, and demux
575 *****************************************************************************/
576 static void MainLoop( input_thread_t
*p_input
)
578 int64_t i_start_mdate
= mdate();
579 int64_t i_intf_update
= 0;
582 while( !p_input
->b_die
&& !p_input
->b_error
&& !p_input
->p
->input
.b_eof
)
584 vlc_bool_t b_force_update
= VLC_FALSE
;
590 if( p_input
->i_state
!= PAUSE_S
)
592 if( ( p_input
->p
->i_stop
> 0 && p_input
->i_time
>= p_input
->p
->i_stop
) ||
593 ( p_input
->p
->i_run
> 0 && i_start_mdate
+p_input
->p
->i_run
< mdate() ) )
596 i_ret
= p_input
->p
->input
.p_demux
->pf_demux(p_input
->p
->input
.p_demux
);
601 if( p_input
->p
->input
.b_title_demux
&&
602 p_input
->p
->input
.p_demux
->info
.i_update
)
604 i_ret
= UpdateFromDemux( p_input
);
605 b_force_update
= VLC_TRUE
;
607 else if( !p_input
->p
->input
.b_title_demux
&&
608 p_input
->p
->input
.p_access
&&
609 p_input
->p
->input
.p_access
->info
.i_update
)
611 i_ret
= UpdateFromAccess( p_input
);
612 b_force_update
= VLC_TRUE
;
616 if( i_ret
== 0 ) /* EOF */
620 var_Get( p_input
, "input-repeat", &repeat
);
621 if( repeat
.i_int
== 0 )
623 /* End of file - we do not set b_die because only the
624 * playlist is allowed to do so. */
625 input_ChangeState( p_input
, END_S
);
626 msg_Dbg( p_input
, "EOF reached" );
627 p_input
->p
->input
.b_eof
= VLC_TRUE
;
631 msg_Dbg( p_input
, "repeating the same input (%d)",
633 if( repeat
.i_int
> 0 )
636 var_Set( p_input
, "input-repeat", repeat
);
639 /* Seek to start title/seekpoint */
640 val
.i_int
= p_input
->p
->input
.i_title_start
-
641 p_input
->p
->input
.i_title_offset
;
642 if( val
.i_int
< 0 || val
.i_int
>= p_input
->p
->input
.i_title
)
644 input_ControlPush( p_input
,
645 INPUT_CONTROL_SET_TITLE
, &val
);
647 val
.i_int
= p_input
->p
->input
.i_seekpoint_start
-
648 p_input
->p
->input
.i_seekpoint_offset
;
649 if( val
.i_int
> 0 /* TODO: check upper boundary */ )
650 input_ControlPush( p_input
,
651 INPUT_CONTROL_SET_SEEKPOINT
, &val
);
653 /* Seek to start position */
654 if( p_input
->p
->i_start
> 0 )
656 val
.i_time
= p_input
->p
->i_start
;
657 input_ControlPush( p_input
, INPUT_CONTROL_SET_TIME
,
663 input_ControlPush( p_input
, INPUT_CONTROL_SET_POSITION
,
668 i_start_mdate
= mdate();
673 p_input
->b_error
= VLC_TRUE
;
676 if( i_ret
> 0 && p_input
->p
->i_slave
> 0 )
678 SlaveDemux( p_input
);
688 vlc_mutex_lock( &p_input
->p
->lock_control
);
689 ControlReduce( p_input
);
690 while( !ControlPopNoLock( p_input
, &i_type
, &val
) )
692 msg_Dbg( p_input
, "control type=%d", i_type
);
693 if( Control( p_input
, i_type
, val
) )
694 b_force_update
= VLC_TRUE
;
696 vlc_mutex_unlock( &p_input
->p
->lock_control
);
698 if( b_force_update
|| i_intf_update
< mdate() )
702 int64_t i_time
, i_length
;
703 /* update input status variables */
704 if( !demux2_Control( p_input
->p
->input
.p_demux
,
705 DEMUX_GET_POSITION
, &f_pos
) )
707 val
.f_float
= (float)f_pos
;
708 var_Change( p_input
, "position", VLC_VAR_SETVALUE
, &val
, NULL
);
710 if( !demux2_Control( p_input
->p
->input
.p_demux
,
711 DEMUX_GET_TIME
, &i_time
) )
713 p_input
->i_time
= i_time
;
715 var_Change( p_input
, "time", VLC_VAR_SETVALUE
, &val
, NULL
);
717 if( !demux2_Control( p_input
->p
->input
.p_demux
,
718 DEMUX_GET_LENGTH
, &i_length
) )
721 var_Get( p_input
, "length", &old_val
);
722 val
.i_time
= i_length
;
723 var_Change( p_input
, "length", VLC_VAR_SETVALUE
, &val
, NULL
);
725 if( old_val
.i_time
!= val
.i_time
)
727 UpdateItemLength( p_input
, i_length
);
731 var_SetBool( p_input
, "intf-change", VLC_TRUE
);
732 i_intf_update
= mdate() + I64C(150000);
734 /* 150ms * 8 = ~ 1 second */
735 if( ++i_updates
% 8 == 0 )
737 stats_ComputeInputStats( p_input
, p_input
->p
->input
.p_item
->p_stats
);
738 /* Are we the thread responsible for computing global stats ? */
739 if( p_input
->p_libvlc
->p_playlist
->p_stats_computer
== p_input
)
741 stats_ComputeGlobalStats( p_input
->p_libvlc
->p_playlist
,
742 p_input
->p_libvlc
->p_playlist
->p_stats
);
748 static int Init( input_thread_t
* p_input
)
758 /* Initialize optional stream output. (before access/demuxer)
759 * XXX: we add a special case if the uri starts by vlc.
760 * else 'vlc in.file --sout "" vlc:quit' cannot work (the output will
761 * be destroyed in case of a file).
762 * (this will break playing of file starting by 'vlc:' but I don't
763 * want to add more logic, just force file by file:// or code it ;)
765 memset( &p_input
->p
->counters
, 0, sizeof( p_input
->p
->counters
) );
766 vlc_mutex_init( p_input
, &p_input
->p
->counters
.counters_lock
);
768 for( i
= 0; i
< p_input
->p
->input
.p_item
->i_options
; i
++ )
770 if( !strncmp( p_input
->p
->input
.p_item
->ppsz_options
[i
], "meta-file", 9 ) )
772 msg_Dbg( p_input
, "Input is a meta file: disabling unneeded options" );
773 var_SetString( p_input
, "sout", "" );
774 var_SetBool( p_input
, "sout-all", VLC_FALSE
);
775 var_SetString( p_input
, "input-slave", "" );
776 var_SetInteger( p_input
, "input-repeat", 0 );
777 var_SetString( p_input
, "sub-file", "" );
778 var_SetBool( p_input
, "sub-autodetect-file", VLC_FALSE
);
782 if( !p_input
->b_preparsing
)
784 /* Prepare statistics */
785 #define INIT_COUNTER( c, type, compute ) p_input->p->counters.p_##c = \
786 stats_CounterCreate( p_input, VLC_VAR_##type, STATS_##compute);
787 if( p_input
->p_libvlc
->b_stats
)
789 INIT_COUNTER( read_bytes
, INTEGER
, COUNTER
);
790 INIT_COUNTER( read_packets
, INTEGER
, COUNTER
);
791 INIT_COUNTER( demux_read
, INTEGER
, COUNTER
);
792 INIT_COUNTER( input_bitrate
, FLOAT
, DERIVATIVE
);
793 INIT_COUNTER( demux_bitrate
, FLOAT
, DERIVATIVE
);
794 INIT_COUNTER( played_abuffers
, INTEGER
, COUNTER
);
795 INIT_COUNTER( lost_abuffers
, INTEGER
, COUNTER
);
796 INIT_COUNTER( displayed_pictures
, INTEGER
, COUNTER
);
797 INIT_COUNTER( lost_pictures
, INTEGER
, COUNTER
);
798 INIT_COUNTER( decoded_audio
, INTEGER
, COUNTER
);
799 INIT_COUNTER( decoded_video
, INTEGER
, COUNTER
);
800 INIT_COUNTER( decoded_sub
, INTEGER
, COUNTER
);
801 p_input
->p
->counters
.p_sout_send_bitrate
= NULL
;
802 p_input
->p
->counters
.p_sout_sent_packets
= NULL
;
803 p_input
->p
->counters
.p_sout_sent_bytes
= NULL
;
804 if( p_input
->p
->counters
.p_demux_bitrate
)
805 p_input
->p
->counters
.p_demux_bitrate
->update_interval
= 1000000;
806 if( p_input
->p
->counters
.p_input_bitrate
)
807 p_input
->p
->counters
.p_input_bitrate
->update_interval
= 1000000;
810 /* Find a usable sout and attach it to p_input */
811 psz
= var_GetNonEmptyString( p_input
, "sout" );
812 if( psz
&& strncasecmp( p_input
->p
->input
.p_item
->psz_uri
, "vlc:", 4 ) )
814 /* Check the validity of the provided sout */
815 if( p_input
->p
->p_sout
)
817 if( strcmp( p_input
->p
->p_sout
->psz_sout
, psz
) )
819 msg_Dbg( p_input
, "destroying unusable sout" );
821 sout_DeleteInstance( p_input
->p
->p_sout
);
822 p_input
->p
->p_sout
= NULL
;
826 if( p_input
->p
->p_sout
)
829 msg_Dbg( p_input
, "sout keep: reusing sout" );
830 msg_Dbg( p_input
, "sout keep: you probably want to use "
831 "gather stream_out" );
832 vlc_object_attach( p_input
->p
->p_sout
, p_input
);
836 /* Create a new one */
837 p_input
->p
->p_sout
= sout_NewInstance( p_input
, psz
);
839 if( !p_input
->p
->p_sout
)
841 input_ChangeState( p_input
, ERROR_S
);
842 msg_Err( p_input
, "cannot start stream output instance, " \
849 if( p_input
->p_libvlc
->b_stats
)
851 INIT_COUNTER( sout_sent_packets
, INTEGER
, COUNTER
);
852 INIT_COUNTER (sout_sent_bytes
, INTEGER
, COUNTER
);
853 INIT_COUNTER( sout_send_bitrate
, FLOAT
, DERIVATIVE
);
854 if( p_input
->p
->counters
.p_sout_send_bitrate
)
855 p_input
->p
->counters
.p_sout_send_bitrate
->update_interval
=
859 else if( p_input
->p
->p_sout
)
861 msg_Dbg( p_input
, "destroying useless sout" );
863 sout_DeleteInstance( p_input
->p
->p_sout
);
864 p_input
->p
->p_sout
= NULL
;
870 p_input
->p
->p_es_out
= input_EsOutNew( p_input
);
871 es_out_Control( p_input
->p
->p_es_out
, ES_OUT_SET_ACTIVE
, VLC_FALSE
);
872 es_out_Control( p_input
->p
->p_es_out
, ES_OUT_SET_MODE
, ES_OUT_MODE_NONE
);
874 var_Create( p_input
, "bit-rate", VLC_VAR_INTEGER
);
875 var_Create( p_input
, "sample-rate", VLC_VAR_INTEGER
);
877 if( InputSourceInit( p_input
, &p_input
->p
->input
,
878 p_input
->p
->input
.p_item
->psz_uri
, NULL
) )
883 /* Create global title (from master) */
884 if( !p_input
->b_preparsing
)
886 p_input
->p
->i_title
= p_input
->p
->input
.i_title
;
887 p_input
->p
->title
= p_input
->p
->input
.title
;
888 p_input
->p
->i_title_offset
= p_input
->p
->input
.i_title_offset
;
889 p_input
->p
->i_seekpoint_offset
= p_input
->p
->input
.i_seekpoint_offset
;
890 if( p_input
->p
->i_title
> 0 )
892 /* Setup variables */
893 input_ControlVarNavigation( p_input
);
894 input_ControlVarTitle( p_input
, 0 );
898 p_input
->b_can_pace_control
= p_input
->p
->input
.b_can_pace_control
;
899 p_input
->p
->b_can_pause
= p_input
->p
->input
.b_can_pause
;
902 if( p_input
->i_pts_delay
< 0 )
903 p_input
->i_pts_delay
= 0;
905 /* If the desynchronisation requested by the user is < 0, we need to
906 * cache more data. */
907 var_Get( p_input
, "audio-desync", &val
);
908 if( val
.i_int
< 0 ) p_input
->i_pts_delay
-= (val
.i_int
* 1000);
910 /* Update cr_average depending on the caching */
911 p_input
->p
->input
.i_cr_average
*= (10 * p_input
->i_pts_delay
/ 200000);
912 p_input
->p
->input
.i_cr_average
/= 10;
913 if( p_input
->p
->input
.i_cr_average
< 10 ) p_input
->p
->input
.i_cr_average
= 10;
916 /* Load master infos */
918 if( !demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_GET_LENGTH
,
919 &val
.i_time
) && val
.i_time
> 0 )
921 var_Change( p_input
, "length", VLC_VAR_SETVALUE
, &val
, NULL
);
922 UpdateItemLength( p_input
, val
.i_time
);
926 val
.i_time
= input_item_GetDuration( p_input
->p
->input
.p_item
);
928 { /* fallback: gets length from metadata */
929 var_Change( p_input
, "length", VLC_VAR_SETVALUE
, &val
, NULL
);
930 UpdateItemLength( p_input
, val
.i_time
);
934 /* Start title/chapter */
935 if( !p_input
->b_preparsing
)
937 val
.i_int
= p_input
->p
->input
.i_title_start
-
938 p_input
->p
->input
.i_title_offset
;
939 if( val
.i_int
> 0 && val
.i_int
< p_input
->p
->input
.i_title
)
940 input_ControlPush( p_input
, INPUT_CONTROL_SET_TITLE
, &val
);
941 val
.i_int
= p_input
->p
->input
.i_seekpoint_start
-
942 p_input
->p
->input
.i_seekpoint_offset
;
943 if( val
.i_int
> 0 /* TODO: check upper boundary */ )
944 input_ControlPush( p_input
, INPUT_CONTROL_SET_SEEKPOINT
, &val
);
948 p_input
->p
->i_start
= I64C(1000000) * var_GetInteger( p_input
, "start-time" );
949 p_input
->p
->i_stop
= I64C(1000000) * var_GetInteger( p_input
, "stop-time" );
950 p_input
->p
->i_run
= I64C(1000000) * var_GetInteger( p_input
, "run-time" );
951 if( p_input
->p
->i_run
< 0 )
953 msg_Warn( p_input
, "invalid run-time ignored" );
954 p_input
->p
->i_run
= 0;
957 if( p_input
->p
->i_start
> 0 )
959 if( p_input
->p
->i_start
>= val
.i_time
)
961 msg_Warn( p_input
, "invalid start-time ignored" );
967 msg_Dbg( p_input
, "starting at time: %ds",
968 (int)( p_input
->p
->i_start
/ I64C(1000000) ) );
970 s
.i_time
= p_input
->p
->i_start
;
971 input_ControlPush( p_input
, INPUT_CONTROL_SET_TIME
, &s
);
974 if( p_input
->p
->i_stop
> 0 && p_input
->p
->i_stop
<= p_input
->p
->i_start
)
976 msg_Warn( p_input
, "invalid stop-time ignored" );
977 p_input
->p
->i_stop
= 0;
981 /* Get fps and set it if not already set */
982 if( !demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_GET_FPS
, &f_fps
) &&
985 float f_requested_fps
;
987 var_Create( p_input
, "sub-original-fps", VLC_VAR_FLOAT
);
988 var_SetFloat( p_input
, "sub-original-fps", f_fps
);
990 f_requested_fps
= var_CreateGetFloat( p_input
, "sub-fps" );
991 if( f_requested_fps
!= f_fps
)
993 var_Create( p_input
, "sub-fps", VLC_VAR_FLOAT
|
995 var_SetFloat( p_input
, "sub-fps", f_requested_fps
);
999 i_delay
= var_CreateGetInteger( p_input
, "sub-delay" );
1002 var_SetTime( p_input
, "spu-delay", (mtime_t
)i_delay
* 100000 );
1005 /* Look for and add subtitle files */
1006 psz_subtitle
= var_GetNonEmptyString( p_input
, "sub-file" );
1007 if( psz_subtitle
!= NULL
)
1009 msg_Dbg( p_input
, "forced subtitle: %s", psz_subtitle
);
1010 input_AddSubtitles( p_input
, psz_subtitle
, VLC_FALSE
);
1013 var_Get( p_input
, "sub-autodetect-file", &val
);
1016 char *psz_autopath
= var_GetNonEmptyString( p_input
, "sub-autodetect-path" );
1017 char **subs
= subtitles_Detect( p_input
, psz_autopath
,
1018 p_input
->p
->input
.p_item
->psz_uri
);
1019 input_source_t
*sub
;
1021 if( psz_autopath
== NULL
)
1022 psz_autopath
= strdup("");
1024 /* Try to autoselect the first autodetected subtitles file
1025 * if no subtitles file was specified */
1026 if( ( psz_subtitle
== NULL
) && subs
&& subs
[0] )
1028 input_AddSubtitles( p_input
, subs
[0], VLC_FALSE
);
1033 /* Then, just add the following subtitles files */
1034 for( ; subs
&& subs
[i
]; i
++ )
1036 if( !psz_subtitle
|| strcmp( psz_subtitle
, subs
[i
] ) )
1038 sub
= InputSourceNew( p_input
);
1039 if( !InputSourceInit( p_input
, sub
, subs
[i
], "subtitle" ) )
1041 TAB_APPEND( p_input
->p
->i_slave
, p_input
->p
->slave
, sub
);
1047 if( subs
) free( subs
);
1048 if( psz_autopath
) free( psz_autopath
);
1050 free( psz_subtitle
);
1052 /* Look for slave */
1053 psz
= var_GetNonEmptyString( p_input
, "input-slave" );
1057 input_source_t
*slave
;
1058 while( psz
&& *psz
)
1060 while( *psz
== ' ' || *psz
== '#' )
1064 if( ( psz_delim
= strchr( psz
, '#' ) ) )
1066 *psz_delim
++ = '\0';
1073 msg_Dbg( p_input
, "adding slave input '%s'", psz
);
1074 slave
= InputSourceNew( p_input
);
1075 if( !InputSourceInit( p_input
, slave
, psz
, NULL
) )
1077 TAB_APPEND( p_input
->p
->i_slave
, p_input
->p
->slave
, slave
);
1087 p_input
->p
->i_start
= 0;
1088 p_input
->p
->i_start
= 0;
1092 if( !p_input
->b_preparsing
)
1094 es_out_Control( p_input
->p
->p_es_out
, ES_OUT_SET_ACTIVE
, VLC_TRUE
);
1095 i_es_out_mode
= ES_OUT_MODE_AUTO
;
1097 if( p_input
->p
->p_sout
)
1099 var_Get( p_input
, "sout-all", &val
);
1102 i_es_out_mode
= ES_OUT_MODE_ALL
;
1107 var_Get( p_input
, "programs", &val
);
1108 if ( val
.p_list
&& val
.p_list
->i_count
)
1110 i_es_out_mode
= ES_OUT_MODE_PARTIAL
;
1111 /* Note : we should remove the "program" callback. */
1114 var_Change( p_input
, "programs", VLC_VAR_FREELIST
, &val
,
1118 es_out_Control( p_input
->p
->p_es_out
, ES_OUT_SET_MODE
, i_es_out_mode
);
1120 /* Inform the demuxer about waited group (needed only for DVB) */
1121 if( i_es_out_mode
== ES_OUT_MODE_ALL
)
1123 demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_SET_GROUP
, -1, NULL
);
1125 else if( i_es_out_mode
== ES_OUT_MODE_PARTIAL
)
1127 demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_SET_GROUP
, -1,
1132 demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_SET_GROUP
,
1133 (int) var_GetInteger( p_input
, "program" ), NULL
);
1136 if( p_input
->p
->p_sout
)
1138 if( p_input
->p
->p_sout
->i_out_pace_nocontrol
> 0 )
1140 p_input
->p
->b_out_pace_control
= VLC_FALSE
;
1144 p_input
->p
->b_out_pace_control
= VLC_TRUE
;
1147 if( p_input
->b_can_pace_control
&& p_input
->p
->b_out_pace_control
)
1149 /* We don't want a high input priority here or we'll
1150 * end-up sucking up all the CPU time */
1151 vlc_thread_set_priority( p_input
, VLC_THREAD_PRIORITY_LOW
);
1154 msg_Dbg( p_input
, "starting in %s mode",
1155 p_input
->p
->b_out_pace_control
? "async" : "sync" );
1159 p_meta
= vlc_meta_New();
1160 /* Get meta data from users */
1161 InputMetaUser( p_input
, p_meta
);
1163 /* Get meta data from master input */
1164 DemuxMeta( p_input
, p_meta
, p_input
->p
->input
.p_demux
);
1166 /* Access_file does not give any meta, and there are no slave */
1167 if( !p_input
->b_preparsing
)
1169 if( p_input
->p
->input
.p_access
)
1170 access2_Control( p_input
->p
->input
.p_access
, ACCESS_GET_META
,
1173 /* Get meta data from slave input */
1174 for( i
= 0; i
< p_input
->p
->i_slave
; i
++ )
1176 DemuxMeta( p_input
, p_meta
, p_input
->p
->slave
[i
]->p_demux
);
1177 if( p_input
->p
->slave
[i
]->p_access
)
1179 access2_Control( p_input
->p
->slave
[i
]->p_access
,
1180 ACCESS_GET_META
, p_meta
);
1185 InputUpdateMeta( p_input
, p_meta
);
1187 if( !p_input
->b_preparsing
)
1189 msg_Dbg( p_input
, "`%s' successfully opened",
1190 p_input
->p
->input
.p_item
->psz_uri
);
1194 /* initialization is complete */
1195 input_ChangeState( p_input
, PLAYING_S
);
1200 input_ChangeState( p_input
, ERROR_S
);
1202 if( p_input
->p
->p_es_out
)
1203 input_EsOutDelete( p_input
->p
->p_es_out
);
1205 if( p_input
->p
->p_sout
)
1207 vlc_object_detach( p_input
->p
->p_sout
);
1208 sout_DeleteInstance( p_input
->p
->p_sout
);
1212 if( !p_input
->b_preparsing
&& p_input
->p_libvlc
->b_stats
)
1214 #define EXIT_COUNTER( c ) do { if( p_input->p->counters.p_##c ) \
1215 stats_CounterClean( p_input->p->counters.p_##c );\
1216 p_input->p->counters.p_##c = NULL; } while(0)
1217 EXIT_COUNTER( read_bytes
);
1218 EXIT_COUNTER( read_packets
);
1219 EXIT_COUNTER( demux_read
);
1220 EXIT_COUNTER( input_bitrate
);
1221 EXIT_COUNTER( demux_bitrate
);
1222 EXIT_COUNTER( played_abuffers
);
1223 EXIT_COUNTER( lost_abuffers
);
1224 EXIT_COUNTER( displayed_pictures
);
1225 EXIT_COUNTER( lost_pictures
);
1226 EXIT_COUNTER( decoded_audio
);
1227 EXIT_COUNTER( decoded_video
);
1228 EXIT_COUNTER( decoded_sub
);
1230 if( p_input
->p
->p_sout
)
1232 EXIT_COUNTER( sout_sent_packets
);
1233 EXIT_COUNTER (sout_sent_bytes
);
1234 EXIT_COUNTER( sout_send_bitrate
);
1239 /* Mark them deleted */
1240 p_input
->p
->input
.p_demux
= NULL
;
1241 p_input
->p
->input
.p_stream
= NULL
;
1242 p_input
->p
->input
.p_access
= NULL
;
1243 p_input
->p
->p_es_out
= NULL
;
1244 p_input
->p
->p_sout
= NULL
;
1246 return VLC_EGENERIC
;
1249 /*****************************************************************************
1250 * Error: RunThread() error loop
1251 *****************************************************************************
1252 * This function is called when an error occurred during thread main's loop.
1253 *****************************************************************************/
1254 static void Error( input_thread_t
*p_input
)
1256 while( !p_input
->b_die
)
1259 input_ChangeState( p_input
, ERROR_S
);
1260 msleep( INPUT_IDLE_SLEEP
);
1264 /*****************************************************************************
1265 * End: end the input thread
1266 *****************************************************************************/
1267 static void End( input_thread_t
* p_input
)
1271 /* We are at the end */
1272 input_ChangeState( p_input
, END_S
);
1274 /* Clean control variables */
1275 input_ControlVarClean( p_input
);
1277 /* Clean up master */
1278 InputSourceClean( &p_input
->p
->input
);
1281 for( i
= 0; i
< p_input
->p
->i_slave
; i
++ )
1283 InputSourceClean( p_input
->p
->slave
[i
] );
1284 free( p_input
->p
->slave
[i
] );
1286 if( p_input
->p
->slave
) free( p_input
->p
->slave
);
1288 /* Unload all modules */
1289 if( p_input
->p
->p_es_out
)
1290 input_EsOutDelete( p_input
->p
->p_es_out
);
1292 if( !p_input
->b_preparsing
)
1294 #define CL_CO( c ) stats_CounterClean( p_input->p->counters.p_##c ); p_input->p->counters.p_##c = NULL;
1295 if( p_input
->p_libvlc
->b_stats
)
1297 /* make sure we are up to date */
1298 stats_ComputeInputStats( p_input
, p_input
->p
->input
.p_item
->p_stats
);
1299 if( p_input
->p_libvlc
->p_playlist
->p_stats_computer
== p_input
)
1301 stats_ComputeGlobalStats( p_input
->p_libvlc
->p_playlist
,
1302 p_input
->p_libvlc
->p_playlist
->p_stats
);
1303 p_input
->p_libvlc
->p_playlist
->p_stats_computer
= NULL
;
1305 CL_CO( read_bytes
);
1306 CL_CO( read_packets
);
1307 CL_CO( demux_read
);
1308 CL_CO( input_bitrate
);
1309 CL_CO( demux_bitrate
);
1310 CL_CO( played_abuffers
);
1311 CL_CO( lost_abuffers
);
1312 CL_CO( displayed_pictures
);
1313 CL_CO( lost_pictures
);
1314 CL_CO( decoded_audio
) ;
1315 CL_CO( decoded_video
);
1316 CL_CO( decoded_sub
) ;
1319 /* Close optional stream output instance */
1320 if( p_input
->p
->p_sout
)
1322 CL_CO( sout_sent_packets
);
1323 CL_CO( sout_sent_bytes
);
1324 CL_CO( sout_send_bitrate
);
1326 vlc_object_detach( p_input
->p
->p_sout
);
1331 if( p_input
->p
->i_attachment
> 0 )
1333 for( i
= 0; i
< p_input
->p
->i_attachment
; i
++ )
1334 vlc_input_attachment_Delete( p_input
->p
->attachment
[i
] );
1335 TAB_CLEAN( p_input
->p
->i_attachment
, p_input
->p
->attachment
);
1338 vlc_mutex_destroy( &p_input
->p
->counters
.counters_lock
);
1340 /* Tell we're dead */
1341 p_input
->b_dead
= VLC_TRUE
;
1344 static sout_instance_t
*SoutFind( vlc_object_t
*p_parent
, input_item_t
*p_item
, vlc_bool_t
*pb_sout_keep
)
1346 vlc_bool_t b_keep_sout
= var_CreateGetBool( p_parent
, "sout-keep" );
1347 sout_instance_t
*p_sout
= NULL
;
1350 /* Search sout-keep options
1351 * XXX it has to be done here, but it is duplicated work :( */
1352 vlc_mutex_lock( &p_item
->lock
);
1353 for( i
= 0; i
< p_item
->i_options
; i
++ )
1355 const char *psz_option
= p_item
->ppsz_options
[i
];
1358 if( *psz_option
== ':' )
1361 if( !strcmp( psz_option
, "sout-keep" ) )
1362 b_keep_sout
= VLC_TRUE
;
1363 else if( !strcmp( psz_option
, "no-sout-keep" ) || !strcmp( psz_option
, "nosout-keep" ) )
1364 b_keep_sout
= VLC_FALSE
;
1366 vlc_mutex_unlock( &p_item
->lock
);
1368 /* Find a potential sout to reuse
1369 * XXX it might be unusable but this will be checked later */
1372 /* Remove the sout from the playlist garbage collector */
1373 playlist_t
*p_playlist
= pl_Yield( p_parent
);
1375 vlc_mutex_lock( &p_playlist
->gc_lock
);
1376 p_sout
= vlc_object_find( p_playlist
, VLC_OBJECT_SOUT
, FIND_CHILD
);
1379 if( p_sout
->p_parent
!= VLC_OBJECT(p_playlist
) )
1381 vlc_object_release( p_sout
);
1386 vlc_object_detach( p_sout
); /* Remove it from the GC */
1388 vlc_object_release( p_sout
);
1391 vlc_mutex_unlock( &p_playlist
->gc_lock
);
1393 pl_Release( p_parent
);
1397 *pb_sout_keep
= b_keep_sout
;
1401 static void SoutKeep( sout_instance_t
*p_sout
)
1403 /* attach sout to the playlist */
1404 playlist_t
*p_playlist
= pl_Yield( p_sout
);
1406 msg_Dbg( p_sout
, "sout has been kept" );
1407 vlc_object_attach( p_sout
, p_playlist
);
1409 pl_Release( p_sout
);
1412 /*****************************************************************************
1414 *****************************************************************************/
1415 static inline int ControlPopNoLock( input_thread_t
*p_input
,
1416 int *pi_type
, vlc_value_t
*p_val
)
1418 if( p_input
->p
->i_control
<= 0 )
1420 return VLC_EGENERIC
;
1423 *pi_type
= p_input
->p
->control
[0].i_type
;
1424 *p_val
= p_input
->p
->control
[0].val
;
1426 p_input
->p
->i_control
--;
1427 if( p_input
->p
->i_control
> 0 )
1431 for( i
= 0; i
< p_input
->p
->i_control
; i
++ )
1433 p_input
->p
->control
[i
].i_type
= p_input
->p
->control
[i
+1].i_type
;
1434 p_input
->p
->control
[i
].val
= p_input
->p
->control
[i
+1].val
;
1441 static void ControlReduce( input_thread_t
*p_input
)
1448 for( i
= 1; i
< p_input
->p
->i_control
; i
++ )
1450 const int i_lt
= p_input
->p
->control
[i
-1].i_type
;
1451 const int i_ct
= p_input
->p
->control
[i
].i_type
;
1453 /* XXX We can't merge INPUT_CONTROL_SET_ES */
1454 /* msg_Dbg( p_input, "[%d/%d] l=%d c=%d", i, p_input->p->i_control,
1458 ( i_ct
== INPUT_CONTROL_SET_STATE
||
1459 i_ct
== INPUT_CONTROL_SET_RATE
||
1460 i_ct
== INPUT_CONTROL_SET_POSITION
||
1461 i_ct
== INPUT_CONTROL_SET_TIME
||
1462 i_ct
== INPUT_CONTROL_SET_PROGRAM
||
1463 i_ct
== INPUT_CONTROL_SET_TITLE
||
1464 i_ct
== INPUT_CONTROL_SET_SEEKPOINT
||
1465 i_ct
== INPUT_CONTROL_SET_BOOKMARK
) )
1468 // msg_Dbg( p_input, "merged at %d", i );
1469 /* Remove the i-1 */
1470 for( j
= i
; j
< p_input
->p
->i_control
; j
++ )
1471 p_input
->p
->control
[j
-1] = p_input
->p
->control
[j
];
1472 p_input
->p
->i_control
--;
1476 /* TODO but that's not that important
1477 - merge SET_X with SET_X_CMD
1478 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
1479 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
1486 static vlc_bool_t
Control( input_thread_t
*p_input
, int i_type
,
1489 vlc_bool_t b_force_update
= VLC_FALSE
;
1491 if( !p_input
) return b_force_update
;
1495 case INPUT_CONTROL_SET_DIE
:
1496 msg_Dbg( p_input
, "control: stopping input" );
1497 /* Mark all submodules to die */
1498 if( p_input
->p
->input
.p_access
)
1499 vlc_object_kill( p_input
->p
->input
.p_access
);
1500 if( p_input
->p
->input
.p_stream
)
1501 vlc_object_kill( p_input
->p
->input
.p_stream
);
1502 vlc_object_kill( p_input
->p
->input
.p_demux
);
1504 vlc_object_kill( p_input
);
1507 case INPUT_CONTROL_SET_POSITION
:
1508 case INPUT_CONTROL_SET_POSITION_OFFSET
:
1511 if( i_type
== INPUT_CONTROL_SET_POSITION
)
1513 f_pos
= val
.f_float
;
1517 /* Should not fail */
1518 demux2_Control( p_input
->p
->input
.p_demux
,
1519 DEMUX_GET_POSITION
, &f_pos
);
1520 f_pos
+= val
.f_float
;
1522 if( f_pos
< 0.0 ) f_pos
= 0.0;
1523 if( f_pos
> 1.0 ) f_pos
= 1.0;
1524 /* Reset the decoders states and clock sync (before calling the demuxer */
1525 input_EsOutChangePosition( p_input
->p
->p_es_out
);
1526 if( demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_SET_POSITION
,
1529 msg_Err( p_input
, "INPUT_CONTROL_SET_POSITION(_OFFSET) "
1530 "%2.1f%% failed", f_pos
* 100 );
1534 if( p_input
->p
->i_slave
> 0 )
1535 SlaveSeek( p_input
);
1537 b_force_update
= VLC_TRUE
;
1542 case INPUT_CONTROL_SET_TIME
:
1543 case INPUT_CONTROL_SET_TIME_OFFSET
:
1548 if( i_type
== INPUT_CONTROL_SET_TIME
)
1550 i_time
= val
.i_time
;
1554 /* Should not fail */
1555 demux2_Control( p_input
->p
->input
.p_demux
,
1556 DEMUX_GET_TIME
, &i_time
);
1557 i_time
+= val
.i_time
;
1559 if( i_time
< 0 ) i_time
= 0;
1561 /* Reset the decoders states and clock sync (before calling the demuxer */
1562 input_EsOutChangePosition( p_input
->p
->p_es_out
);
1564 i_ret
= demux2_Control( p_input
->p
->input
.p_demux
,
1565 DEMUX_SET_TIME
, i_time
);
1570 /* Emulate it with a SET_POS */
1571 demux2_Control( p_input
->p
->input
.p_demux
,
1572 DEMUX_GET_LENGTH
, &i_length
);
1575 double f_pos
= (double)i_time
/ (double)i_length
;
1576 i_ret
= demux2_Control( p_input
->p
->input
.p_demux
,
1577 DEMUX_SET_POSITION
, f_pos
);
1582 msg_Warn( p_input
, "INPUT_CONTROL_SET_TIME(_OFFSET) "I64Fd
1583 " failed or not possible", i_time
);
1587 if( p_input
->p
->i_slave
> 0 )
1588 SlaveSeek( p_input
);
1590 b_force_update
= VLC_TRUE
;
1595 case INPUT_CONTROL_SET_STATE
:
1596 if( ( val
.i_int
== PLAYING_S
&& p_input
->i_state
== PAUSE_S
) ||
1597 ( val
.i_int
== PAUSE_S
&& p_input
->i_state
== PAUSE_S
) )
1600 if( p_input
->p
->input
.p_access
)
1601 i_ret
= access2_Control( p_input
->p
->input
.p_access
,
1602 ACCESS_SET_PAUSE_STATE
, VLC_FALSE
);
1604 i_ret
= demux2_Control( p_input
->p
->input
.p_demux
,
1605 DEMUX_SET_PAUSE_STATE
, VLC_FALSE
);
1609 /* FIXME What to do ? */
1610 msg_Warn( p_input
, "cannot unset pause -> EOF" );
1611 vlc_mutex_unlock( &p_input
->p
->lock_control
);
1612 input_ControlPush( p_input
, INPUT_CONTROL_SET_DIE
, NULL
);
1613 vlc_mutex_lock( &p_input
->p
->lock_control
);
1616 b_force_update
= VLC_TRUE
;
1618 /* Switch to play */
1619 p_input
->i_state
= PLAYING_S
;
1620 val
.i_int
= PLAYING_S
;
1621 var_Change( p_input
, "state", VLC_VAR_SETVALUE
, &val
, NULL
);
1625 input_EsOutChangeState( p_input
->p
->p_es_out
);
1627 else if( val
.i_int
== PAUSE_S
&& p_input
->i_state
== PLAYING_S
&&
1628 p_input
->p
->b_can_pause
)
1631 if( p_input
->p
->input
.p_access
)
1632 i_ret
= access2_Control( p_input
->p
->input
.p_access
,
1633 ACCESS_SET_PAUSE_STATE
, VLC_TRUE
);
1635 i_ret
= demux2_Control( p_input
->p
->input
.p_demux
,
1636 DEMUX_SET_PAUSE_STATE
, VLC_TRUE
);
1638 b_force_update
= VLC_TRUE
;
1642 msg_Warn( p_input
, "cannot set pause state" );
1643 val
.i_int
= p_input
->i_state
;
1647 val
.i_int
= PAUSE_S
;
1650 /* Switch to new state */
1651 p_input
->i_state
= val
.i_int
;
1652 var_Change( p_input
, "state", VLC_VAR_SETVALUE
, &val
, NULL
);
1656 input_EsOutChangeState( p_input
->p
->p_es_out
);
1658 else if( val
.i_int
== PAUSE_S
&& !p_input
->p
->b_can_pause
)
1660 b_force_update
= VLC_TRUE
;
1662 /* Correct "state" value */
1663 val
.i_int
= p_input
->i_state
;
1664 var_Change( p_input
, "state", VLC_VAR_SETVALUE
, &val
, NULL
);
1666 else if( val
.i_int
!= PLAYING_S
&& val
.i_int
!= PAUSE_S
)
1668 msg_Err( p_input
, "invalid state in INPUT_CONTROL_SET_STATE" );
1672 case INPUT_CONTROL_SET_RATE
:
1673 case INPUT_CONTROL_SET_RATE_SLOWER
:
1674 case INPUT_CONTROL_SET_RATE_FASTER
:
1678 if( i_type
== INPUT_CONTROL_SET_RATE
)
1684 static const int ppi_factor
[][2] = {
1685 {1,64}, {1,32}, {1,16}, {1,8}, {1,4}, {1,3}, {1,2}, {2,3},
1687 {3,2}, {2,1}, {3,1}, {4,1}, {8,1}, {16,1}, {32,1}, {64,1},
1696 for( i
= 0; ppi_factor
[i
][0] != 0; i
++ )
1698 const int i_test_r
= INPUT_RATE_DEFAULT
* ppi_factor
[i
][0] / ppi_factor
[i
][1];
1699 const int i_test_e
= abs(p_input
->p
->i_rate
- i_test_r
);
1700 if( i_test_e
< i_error
)
1706 assert( i_idx
>= 0 && ppi_factor
[i_idx
][0] != 0 );
1708 if( i_type
== INPUT_CONTROL_SET_RATE_SLOWER
)
1710 if( ppi_factor
[i_idx
+1][0] > 0 )
1711 i_rate
= INPUT_RATE_DEFAULT
* ppi_factor
[i_idx
+1][0] / ppi_factor
[i_idx
+1][1];
1713 i_rate
= INPUT_RATE_MAX
+1;
1717 assert( i_type
== INPUT_CONTROL_SET_RATE_FASTER
);
1719 i_rate
= INPUT_RATE_DEFAULT
* ppi_factor
[i_idx
-1][0] / ppi_factor
[i_idx
-1][1];
1721 i_rate
= INPUT_RATE_MIN
-1;
1725 if( i_rate
< INPUT_RATE_MIN
)
1727 msg_Dbg( p_input
, "cannot set rate faster" );
1728 i_rate
= INPUT_RATE_MIN
;
1730 else if( i_rate
> INPUT_RATE_MAX
)
1732 msg_Dbg( p_input
, "cannot set rate slower" );
1733 i_rate
= INPUT_RATE_MAX
;
1735 if( i_rate
!= INPUT_RATE_DEFAULT
&&
1736 ( !p_input
->b_can_pace_control
||
1737 ( p_input
->p
->p_sout
&& !p_input
->p
->b_out_pace_control
) ) )
1739 msg_Dbg( p_input
, "cannot change rate" );
1740 i_rate
= INPUT_RATE_DEFAULT
;
1742 if( i_rate
!= p_input
->p
->i_rate
)
1745 var_Change( p_input
, "rate", VLC_VAR_SETVALUE
, &val
, NULL
);
1747 p_input
->p
->i_rate
= i_rate
;
1749 input_EsOutChangeRate( p_input
->p
->p_es_out
);
1751 b_force_update
= VLC_TRUE
;
1756 case INPUT_CONTROL_SET_PROGRAM
:
1757 /* No need to force update, es_out does it if needed */
1758 es_out_Control( p_input
->p
->p_es_out
,
1759 ES_OUT_SET_GROUP
, val
.i_int
);
1761 demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_SET_GROUP
, val
.i_int
,
1765 case INPUT_CONTROL_SET_ES
:
1766 /* No need to force update, es_out does it if needed */
1767 es_out_Control( p_input
->p
->p_es_out
, ES_OUT_SET_ES
,
1768 input_EsOutGetFromID( p_input
->p
->p_es_out
,
1772 case INPUT_CONTROL_SET_AUDIO_DELAY
:
1773 input_EsOutSetDelay( p_input
->p
->p_es_out
,
1774 AUDIO_ES
, val
.i_time
);
1775 var_Change( p_input
, "audio-delay", VLC_VAR_SETVALUE
, &val
, NULL
);
1778 case INPUT_CONTROL_SET_SPU_DELAY
:
1779 input_EsOutSetDelay( p_input
->p
->p_es_out
,
1780 SPU_ES
, val
.i_time
);
1781 var_Change( p_input
, "spu-delay", VLC_VAR_SETVALUE
, &val
, NULL
);
1784 case INPUT_CONTROL_SET_TITLE
:
1785 case INPUT_CONTROL_SET_TITLE_NEXT
:
1786 case INPUT_CONTROL_SET_TITLE_PREV
:
1787 if( p_input
->p
->input
.b_title_demux
&&
1788 p_input
->p
->input
.i_title
> 0 )
1791 /* FIXME handle demux title */
1792 demux_t
*p_demux
= p_input
->p
->input
.p_demux
;
1795 if( i_type
== INPUT_CONTROL_SET_TITLE_PREV
)
1796 i_title
= p_demux
->info
.i_title
- 1;
1797 else if( i_type
== INPUT_CONTROL_SET_TITLE_NEXT
)
1798 i_title
= p_demux
->info
.i_title
+ 1;
1800 i_title
= val
.i_int
;
1802 if( i_title
>= 0 && i_title
< p_input
->p
->input
.i_title
)
1804 input_EsOutChangePosition( p_input
->p
->p_es_out
);
1806 demux2_Control( p_demux
, DEMUX_SET_TITLE
, i_title
);
1807 input_ControlVarTitle( p_input
, i_title
);
1810 else if( p_input
->p
->input
.i_title
> 0 )
1812 access_t
*p_access
= p_input
->p
->input
.p_access
;
1815 if( i_type
== INPUT_CONTROL_SET_TITLE_PREV
)
1816 i_title
= p_access
->info
.i_title
- 1;
1817 else if( i_type
== INPUT_CONTROL_SET_TITLE_NEXT
)
1818 i_title
= p_access
->info
.i_title
+ 1;
1820 i_title
= val
.i_int
;
1822 if( i_title
>= 0 && i_title
< p_input
->p
->input
.i_title
)
1824 input_EsOutChangePosition( p_input
->p
->p_es_out
);
1826 access2_Control( p_access
, ACCESS_SET_TITLE
, i_title
);
1827 stream_AccessReset( p_input
->p
->input
.p_stream
);
1831 case INPUT_CONTROL_SET_SEEKPOINT
:
1832 case INPUT_CONTROL_SET_SEEKPOINT_NEXT
:
1833 case INPUT_CONTROL_SET_SEEKPOINT_PREV
:
1834 if( p_input
->p
->input
.b_title_demux
&&
1835 p_input
->p
->input
.i_title
> 0 )
1837 demux_t
*p_demux
= p_input
->p
->input
.p_demux
;
1839 int64_t i_input_time
;
1840 int64_t i_seekpoint_time
;
1842 if( i_type
== INPUT_CONTROL_SET_SEEKPOINT_PREV
)
1844 i_seekpoint
= p_demux
->info
.i_seekpoint
;
1845 i_seekpoint_time
= p_input
->p
->input
.title
[p_demux
->info
.i_title
]->seekpoint
[i_seekpoint
]->i_time_offset
;
1846 if( i_seekpoint_time
>= 0 &&
1847 !demux2_Control( p_demux
,
1848 DEMUX_GET_TIME
, &i_input_time
) )
1850 if ( i_input_time
< i_seekpoint_time
+ 3000000 )
1856 else if( i_type
== INPUT_CONTROL_SET_SEEKPOINT_NEXT
)
1857 i_seekpoint
= p_demux
->info
.i_seekpoint
+ 1;
1859 i_seekpoint
= val
.i_int
;
1861 if( i_seekpoint
>= 0 && i_seekpoint
<
1862 p_input
->p
->input
.title
[p_demux
->info
.i_title
]->i_seekpoint
)
1865 input_EsOutChangePosition( p_input
->p
->p_es_out
);
1867 demux2_Control( p_demux
, DEMUX_SET_SEEKPOINT
, i_seekpoint
);
1870 else if( p_input
->p
->input
.i_title
> 0 )
1872 demux_t
*p_demux
= p_input
->p
->input
.p_demux
;
1873 access_t
*p_access
= p_input
->p
->input
.p_access
;
1875 int64_t i_input_time
;
1876 int64_t i_seekpoint_time
;
1878 if( i_type
== INPUT_CONTROL_SET_SEEKPOINT_PREV
)
1880 i_seekpoint
= p_access
->info
.i_seekpoint
;
1881 i_seekpoint_time
= p_input
->p
->input
.title
[p_access
->info
.i_title
]->seekpoint
[i_seekpoint
]->i_time_offset
;
1882 if( i_seekpoint_time
>= 0 &&
1883 demux2_Control( p_demux
,
1884 DEMUX_GET_TIME
, &i_input_time
) )
1886 if ( i_input_time
< i_seekpoint_time
+ 3000000 )
1892 else if( i_type
== INPUT_CONTROL_SET_SEEKPOINT_NEXT
)
1893 i_seekpoint
= p_access
->info
.i_seekpoint
+ 1;
1895 i_seekpoint
= val
.i_int
;
1897 if( i_seekpoint
>= 0 && i_seekpoint
<
1898 p_input
->p
->input
.title
[p_access
->info
.i_title
]->i_seekpoint
)
1900 input_EsOutChangePosition( p_input
->p
->p_es_out
);
1902 access2_Control( p_access
, ACCESS_SET_SEEKPOINT
,
1904 stream_AccessReset( p_input
->p
->input
.p_stream
);
1909 case INPUT_CONTROL_ADD_SLAVE
:
1910 if( val
.psz_string
)
1912 input_source_t
*slave
= InputSourceNew( p_input
);
1914 if( !InputSourceInit( p_input
, slave
, val
.psz_string
, NULL
) )
1920 msg_Dbg( p_input
, "adding %s as slave on the fly",
1924 if( demux2_Control( p_input
->p
->input
.p_demux
,
1925 DEMUX_GET_TIME
, &i_time
) )
1927 msg_Err( p_input
, "demux doesn't like DEMUX_GET_TIME" );
1928 InputSourceClean( slave
);
1932 if( demux2_Control( slave
->p_demux
,
1933 DEMUX_SET_TIME
, i_time
) )
1935 msg_Err( p_input
, "seek failed for new slave" );
1936 InputSourceClean( slave
);
1941 /* Get meta (access and demux) */
1942 p_meta
= vlc_meta_New();
1943 access2_Control( slave
->p_access
, ACCESS_GET_META
,
1945 demux2_Control( slave
->p_demux
, DEMUX_GET_META
, p_meta
);
1946 InputUpdateMeta( p_input
, p_meta
);
1948 TAB_APPEND( p_input
->p
->i_slave
, p_input
->p
->slave
, slave
);
1953 msg_Warn( p_input
, "failed to add %s as slave",
1957 free( val
.psz_string
);
1961 case INPUT_CONTROL_SET_BOOKMARK
:
1963 msg_Err( p_input
, "not yet implemented" );
1967 return b_force_update
;
1970 /*****************************************************************************
1972 *****************************************************************************/
1973 static int UpdateFromDemux( input_thread_t
*p_input
)
1975 demux_t
*p_demux
= p_input
->p
->input
.p_demux
;
1978 if( p_demux
->info
.i_update
& INPUT_UPDATE_TITLE
)
1980 v
.i_int
= p_demux
->info
.i_title
;
1981 var_Change( p_input
, "title", VLC_VAR_SETVALUE
, &v
, NULL
);
1983 input_ControlVarTitle( p_input
, p_demux
->info
.i_title
);
1985 p_demux
->info
.i_update
&= ~INPUT_UPDATE_TITLE
;
1987 if( p_demux
->info
.i_update
& INPUT_UPDATE_SEEKPOINT
)
1989 v
.i_int
= p_demux
->info
.i_seekpoint
;
1990 var_Change( p_input
, "chapter", VLC_VAR_SETVALUE
, &v
, NULL
);
1992 p_demux
->info
.i_update
&= ~INPUT_UPDATE_SEEKPOINT
;
1994 p_demux
->info
.i_update
&= ~INPUT_UPDATE_SIZE
;
1996 /* Hmmm only works with master input */
1997 if( p_input
->p
->input
.p_demux
== p_demux
)
1999 int i_title_end
= p_input
->p
->input
.i_title_end
-
2000 p_input
->p
->input
.i_title_offset
;
2001 int i_seekpoint_end
= p_input
->p
->input
.i_seekpoint_end
-
2002 p_input
->p
->input
.i_seekpoint_offset
;
2004 if( i_title_end
>= 0 && i_seekpoint_end
>= 0 )
2006 if( p_demux
->info
.i_title
> i_title_end
||
2007 ( p_demux
->info
.i_title
== i_title_end
&&
2008 p_demux
->info
.i_seekpoint
> i_seekpoint_end
) ) return 0;
2010 else if( i_seekpoint_end
>=0 )
2012 if( p_demux
->info
.i_seekpoint
> i_seekpoint_end
) return 0;
2014 else if( i_title_end
>= 0 )
2016 if( p_demux
->info
.i_title
> i_title_end
) return 0;
2023 /*****************************************************************************
2025 *****************************************************************************/
2026 static int UpdateFromAccess( input_thread_t
*p_input
)
2028 access_t
*p_access
= p_input
->p
->input
.p_access
;
2031 if( p_access
->info
.i_update
& INPUT_UPDATE_TITLE
)
2033 v
.i_int
= p_access
->info
.i_title
;
2034 var_Change( p_input
, "title", VLC_VAR_SETVALUE
, &v
, NULL
);
2036 input_ControlVarTitle( p_input
, p_access
->info
.i_title
);
2038 stream_AccessUpdate( p_input
->p
->input
.p_stream
);
2040 p_access
->info
.i_update
&= ~INPUT_UPDATE_TITLE
;
2042 if( p_access
->info
.i_update
& INPUT_UPDATE_SEEKPOINT
)
2044 v
.i_int
= p_access
->info
.i_seekpoint
;
2045 var_Change( p_input
, "chapter", VLC_VAR_SETVALUE
, &v
, NULL
);
2046 p_access
->info
.i_update
&= ~INPUT_UPDATE_SEEKPOINT
;
2048 if( p_access
->info
.i_update
& INPUT_UPDATE_META
)
2050 /* TODO maybe multi - access ? */
2051 vlc_meta_t
*p_meta
= vlc_meta_New();
2052 access2_Control( p_input
->p
->input
.p_access
,ACCESS_GET_META
, p_meta
);
2053 InputUpdateMeta( p_input
, p_meta
);
2054 var_SetInteger( pl_Get( p_input
), "item-change", p_input
->p
->input
.p_item
->i_id
);
2055 p_access
->info
.i_update
&= ~INPUT_UPDATE_META
;
2058 p_access
->info
.i_update
&= ~INPUT_UPDATE_SIZE
;
2060 /* Hmmm only works with master input */
2061 if( p_input
->p
->input
.p_access
== p_access
)
2063 int i_title_end
= p_input
->p
->input
.i_title_end
-
2064 p_input
->p
->input
.i_title_offset
;
2065 int i_seekpoint_end
= p_input
->p
->input
.i_seekpoint_end
-
2066 p_input
->p
->input
.i_seekpoint_offset
;
2068 if( i_title_end
>= 0 && i_seekpoint_end
>=0 )
2070 if( p_access
->info
.i_title
> i_title_end
||
2071 ( p_access
->info
.i_title
== i_title_end
&&
2072 p_access
->info
.i_seekpoint
> i_seekpoint_end
) ) return 0;
2074 else if( i_seekpoint_end
>=0 )
2076 if( p_access
->info
.i_seekpoint
> i_seekpoint_end
) return 0;
2078 else if( i_title_end
>= 0 )
2080 if( p_access
->info
.i_title
> i_title_end
) return 0;
2087 /*****************************************************************************
2089 *****************************************************************************/
2090 static void UpdateItemLength( input_thread_t
*p_input
, int64_t i_length
)
2092 input_item_SetDuration( p_input
->p
->input
.p_item
, (mtime_t
) i_length
);
2094 if( !p_input
->b_preparsing
)
2096 pl_Yield( p_input
);
2097 var_SetInteger( pl_Get( p_input
), "item-change",
2098 p_input
->p
->input
.p_item
->i_id
);
2099 pl_Release( p_input
)
2103 /*****************************************************************************
2105 *****************************************************************************/
2106 static input_source_t
*InputSourceNew( input_thread_t
*p_input
)
2108 input_source_t
*in
= (input_source_t
*) malloc( sizeof( input_source_t
) );
2112 msg_Err( p_input
, "out of memory for new input source" );
2117 in
->p_access
= NULL
;
2118 in
->p_stream
= NULL
;
2120 in
->b_title_demux
= VLC_FALSE
;
2121 TAB_INIT( in
->i_title
, in
->title
);
2122 in
->b_can_pace_control
= VLC_TRUE
;
2123 in
->b_eof
= VLC_FALSE
;
2125 in
->i_cr_average
= 0;
2130 /*****************************************************************************
2132 *****************************************************************************/
2133 static int InputSourceInit( input_thread_t
*p_input
,
2134 input_source_t
*in
, const char *psz_mrl
,
2135 const char *psz_forced_demux
)
2137 char psz_dup
[strlen (psz_mrl
) + 1];
2138 const char *psz_access
;
2139 const char *psz_demux
;
2146 strcpy( psz_dup
, psz_mrl
);
2148 if( !in
) return VLC_EGENERIC
;
2149 if( !p_input
) return VLC_EGENERIC
;
2152 if( !p_input
->b_preparsing
)
2154 MRLSplit( VLC_OBJECT(p_input
), psz_dup
,
2155 &psz_access
, &psz_demux
, &psz_path
);
2157 msg_Dbg( p_input
, "`%s' gives access `%s' demux `%s' path `%s'",
2158 psz_mrl
, psz_access
, psz_demux
, psz_path
);
2160 /* Hack to allow udp://@:port syntax */
2162 (strncmp( psz_access
, "udp", 3 ) &&
2163 strncmp( psz_access
, "rtp", 3 )) )
2165 /* Find optional titles and seekpoints */
2166 MRLSections( p_input
, psz_path
, &in
->i_title_start
, &in
->i_title_end
,
2167 &in
->i_seekpoint_start
, &in
->i_seekpoint_end
);
2169 if( psz_forced_demux
&& *psz_forced_demux
)
2171 psz_demux
= psz_forced_demux
;
2173 else if( !psz_demux
|| *psz_demux
== '\0' )
2175 /* special hack for forcing a demuxer with --demux=module
2176 * (and do nothing with a list) */
2177 char *psz_var_demux
= var_GetNonEmptyString( p_input
, "demux" );
2179 if( psz_var_demux
!= NULL
&&
2180 !strchr(psz_var_demux
, ',' ) &&
2181 !strchr(psz_var_demux
, ':' ) )
2183 psz_demux
= psz_var_demux
;
2185 msg_Dbg( p_input
, "enforced demux ` %s'", psz_demux
);
2189 /* Try access_demux if no demux given */
2190 if( *psz_demux
== '\0' )
2192 in
->p_demux
= demux2_New( p_input
, psz_access
, psz_demux
, psz_path
,
2193 NULL
, p_input
->p
->p_es_out
, VLC_FALSE
);
2199 if( !strncmp( psz_path
, "file://", 7 ) )
2201 msg_Dbg( p_input
, "trying to pre-parse %s", psz_path
);
2203 psz_access
= "file";
2208 int64_t i_pts_delay
;
2210 /* Get infos from access_demux */
2211 demux2_Control( in
->p_demux
,
2212 DEMUX_GET_PTS_DELAY
, &i_pts_delay
);
2213 p_input
->i_pts_delay
= __MAX( p_input
->i_pts_delay
, i_pts_delay
);
2215 in
->b_title_demux
= VLC_TRUE
;
2216 if( demux2_Control( in
->p_demux
, DEMUX_GET_TITLE_INFO
,
2217 &in
->title
, &in
->i_title
,
2218 &in
->i_title_offset
, &in
->i_seekpoint_offset
) )
2223 demux2_Control( in
->p_demux
, DEMUX_CAN_CONTROL_PACE
,
2224 &in
->b_can_pace_control
);
2225 demux2_Control( in
->p_demux
, DEMUX_CAN_PAUSE
,
2229 demux2_Control( in->p_demux, DEMUX_CAN_SEEK,
2235 int64_t i_pts_delay
;
2237 input_ChangeState( p_input
, OPENING_S
);
2239 /* Now try a real access */
2240 in
->p_access
= access2_New( p_input
, psz_access
, psz_demux
, psz_path
,
2241 p_input
->b_preparsing
);
2243 /* Access failed, URL encoded ? */
2244 if( in
->p_access
== NULL
&& strchr( psz_path
, '%' ) )
2246 decode_URI( psz_path
);
2248 msg_Dbg( p_input
, "retrying with access `%s' demux `%s' path `%s'",
2249 psz_access
, psz_demux
, psz_path
);
2251 in
->p_access
= access2_New( p_input
,
2252 psz_access
, psz_demux
, psz_path
,
2253 p_input
->b_preparsing
);
2255 /* access failed, maybe our access detection was wrong.
2256 * Retry with the full name */
2257 if( in
->p_access
== NULL
&& strchr( psz_mrl
, ':' ) )
2259 msg_Dbg( p_input
, "retrying with access `' demux `' path `%s'",
2261 psz_demux
=strdup("");
2262 in
->p_access
= access2_New( p_input
,
2264 p_input
->b_preparsing
);
2266 if( in
->p_access
== NULL
)
2268 msg_Err( p_input
, "open of `%s' failed: %s", psz_mrl
,
2270 intf_UserFatal( VLC_OBJECT( p_input
), VLC_FALSE
,
2271 _("Your input can't be opened"),
2272 _("VLC is unable to open the MRL '%s'."
2273 " Check the log for details."), psz_mrl
);
2278 psz_tmp
= psz
= var_GetNonEmptyString( p_input
, "access-filter" );
2279 while( psz
&& *psz
)
2281 access_t
*p_access
= in
->p_access
;
2282 char *end
= strchr( psz
, ':' );
2287 in
->p_access
= access2_FilterNew( in
->p_access
, psz
);
2288 if( in
->p_access
== NULL
)
2290 in
->p_access
= p_access
;
2291 msg_Warn( p_input
, "failed to insert access filter %s",
2299 /* Get infos from access */
2300 if( !p_input
->b_preparsing
)
2302 access2_Control( in
->p_access
,
2303 ACCESS_GET_PTS_DELAY
, &i_pts_delay
);
2304 p_input
->i_pts_delay
= __MAX( p_input
->i_pts_delay
, i_pts_delay
);
2306 in
->b_title_demux
= VLC_FALSE
;
2307 if( access2_Control( in
->p_access
, ACCESS_GET_TITLE_INFO
,
2308 &in
->title
, &in
->i_title
,
2309 &in
->i_title_offset
, &in
->i_seekpoint_offset
) )
2315 access2_Control( in
->p_access
, ACCESS_CAN_CONTROL_PACE
,
2316 &in
->b_can_pace_control
);
2317 access2_Control( in
->p_access
, ACCESS_CAN_PAUSE
,
2319 access2_Control( in
->p_access
, ACCESS_CAN_SEEK
,
2321 var_Set( p_input
, "seekable", val
);
2324 input_ChangeState( p_input
, BUFFERING_S
);
2326 /* Create the stream_t */
2327 in
->p_stream
= stream_AccessNew( in
->p_access
, p_input
->b_preparsing
);
2328 if( in
->p_stream
== NULL
)
2330 msg_Warn( p_input
, "cannot create a stream_t from access" );
2334 /* Open a demuxer */
2335 if( *psz_demux
== '\0' && *in
->p_access
->psz_demux
)
2337 psz_demux
= in
->p_access
->psz_demux
;
2341 /* Take access redirections into account */
2342 char *psz_real_path
;
2343 char *psz_buf
= NULL
;
2344 if( in
->p_access
->psz_path
)
2346 const char *psz_a
, *psz_d
;
2347 psz_buf
= strdup( in
->p_access
->psz_path
);
2348 MRLSplit( VLC_OBJECT(p_input
), psz_buf
,
2349 &psz_a
, &psz_d
, &psz_real_path
);
2353 psz_real_path
= psz_path
;
2355 in
->p_demux
= demux2_New( p_input
, psz_access
, psz_demux
,
2357 in
->p_stream
, p_input
->p
->p_es_out
,
2358 p_input
->b_preparsing
);
2362 if( in
->p_demux
== NULL
)
2364 msg_Err( p_input
, "no suitable demux module for `%s/%s://%s'",
2365 psz_access
, psz_demux
, psz_path
);
2366 intf_UserFatal( VLC_OBJECT( p_input
), VLC_FALSE
,
2367 _("VLC can't recognize the input's format"),
2368 _("The format of '%s' cannot be detected. "
2369 "Have a look the log for details."), psz_mrl
);
2373 /* Get title from demux */
2374 if( !p_input
->b_preparsing
&& in
->i_title
<= 0 )
2376 if( demux2_Control( in
->p_demux
, DEMUX_GET_TITLE_INFO
,
2377 &in
->title
, &in
->i_title
,
2378 &in
->i_title_offset
, &in
->i_seekpoint_offset
))
2380 TAB_INIT( in
->i_title
, in
->title
);
2384 in
->b_title_demux
= VLC_TRUE
;
2390 * FIXME improve for b_preparsing: move it after GET_META and check psz_arturl */
2391 if( 1 || !p_input
->b_preparsing
)
2394 input_attachment_t
**attachment
;
2395 if( !demux2_Control( in
->p_demux
, DEMUX_GET_ATTACHMENTS
,
2396 &attachment
, &i_attachment
) )
2398 vlc_mutex_lock( &p_input
->p
->input
.p_item
->lock
);
2399 AppendAttachment( &p_input
->p
->i_attachment
, &p_input
->p
->attachment
,
2400 i_attachment
, attachment
);
2401 vlc_mutex_unlock( &p_input
->p
->input
.p_item
->lock
);
2404 if( !demux2_Control( in
->p_demux
, DEMUX_GET_FPS
, &f_fps
) )
2406 vlc_mutex_lock( &p_input
->p
->input
.p_item
->lock
);
2408 vlc_mutex_unlock( &p_input
->p
->input
.p_item
->lock
);
2411 if( var_GetInteger( p_input
, "clock-synchro" ) != -1 )
2412 in
->b_can_pace_control
= !var_GetInteger( p_input
, "clock-synchro" );
2417 input_ChangeState( p_input
, ERROR_S
);
2420 demux2_Delete( in
->p_demux
);
2423 stream_Delete( in
->p_stream
);
2426 access2_Delete( in
->p_access
);
2428 return VLC_EGENERIC
;
2431 /*****************************************************************************
2433 *****************************************************************************/
2434 static void InputSourceClean( input_source_t
*in
)
2439 demux2_Delete( in
->p_demux
);
2442 stream_Delete( in
->p_stream
);
2445 access2_Delete( in
->p_access
);
2447 if( in
->i_title
> 0 )
2449 for( i
= 0; i
< in
->i_title
; i
++ )
2450 vlc_input_title_Delete( in
->title
[i
] );
2451 TAB_CLEAN( in
->i_title
, in
->title
);
2455 static void SlaveDemux( input_thread_t
*p_input
)
2460 if( demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_GET_TIME
, &i_time
) )
2462 msg_Err( p_input
, "demux doesn't like DEMUX_GET_TIME" );
2466 for( i
= 0; i
< p_input
->p
->i_slave
; i
++ )
2468 input_source_t
*in
= p_input
->p
->slave
[i
];
2474 if( demux2_Control( in
->p_demux
, DEMUX_SET_NEXT_DEMUX_TIME
, i_time
) )
2479 if( demux2_Control( in
->p_demux
, DEMUX_GET_TIME
, &i_stime
) )
2481 msg_Err( p_input
, "slave[%d] doesn't like "
2482 "DEMUX_GET_TIME -> EOF", i
);
2487 if( i_stime
>= i_time
)
2490 if( ( i_ret
= in
->p_demux
->pf_demux( in
->p_demux
) ) <= 0 )
2496 i_ret
= in
->p_demux
->pf_demux( in
->p_demux
);
2501 msg_Dbg( p_input
, "slave %d EOF", i
);
2502 in
->b_eof
= VLC_TRUE
;
2507 static void SlaveSeek( input_thread_t
*p_input
)
2512 if( !p_input
) return;
2514 if( demux2_Control( p_input
->p
->input
.p_demux
, DEMUX_GET_TIME
, &i_time
) )
2516 msg_Err( p_input
, "demux doesn't like DEMUX_GET_TIME" );
2520 for( i
= 0; i
< p_input
->p
->i_slave
; i
++ )
2522 input_source_t
*in
= p_input
->p
->slave
[i
];
2524 if( demux2_Control( in
->p_demux
, DEMUX_SET_TIME
, i_time
) )
2526 msg_Err( p_input
, "seek failed for slave %d -> EOF", i
);
2527 in
->b_eof
= VLC_TRUE
;
2532 /*****************************************************************************
2534 *****************************************************************************/
2535 static void InputMetaUser( input_thread_t
*p_input
, vlc_meta_t
*p_meta
)
2539 if( !p_meta
) return;
2541 /* Get meta information from user */
2542 #define GET_META( field, s ) \
2543 var_Get( p_input, (s), &val ); \
2544 if( *val.psz_string ) \
2545 vlc_meta_Set( p_meta, vlc_meta_ ## field, val.psz_string ); \
2546 free( val.psz_string )
2548 GET_META( Title
, "meta-title" );
2549 GET_META( Artist
, "meta-artist" );
2550 GET_META( Genre
, "meta-genre" );
2551 GET_META( Copyright
, "meta-copyright" );
2552 GET_META( Description
, "meta-description" );
2553 GET_META( Date
, "meta-date" );
2554 GET_META( URL
, "meta-url" );
2558 /*****************************************************************************
2559 * InputUpdateMeta: merge p_item meta data with p_meta taking care of
2560 * arturl and locking issue.
2561 *****************************************************************************/
2562 static void InputUpdateMeta( input_thread_t
*p_input
, vlc_meta_t
*p_meta
)
2564 input_item_t
*p_item
= p_input
->p
->input
.p_item
;
2565 char * psz_arturl
= NULL
;
2566 char *psz_title
= NULL
;
2568 int i_arturl_event
= VLC_FALSE
;
2573 psz_arturl
= input_item_GetArtURL( p_item
);
2575 vlc_mutex_lock( &p_item
->lock
);
2576 if( vlc_meta_Get( p_meta
, vlc_meta_Title
) && !p_item
->b_fixed_name
)
2577 psz_title
= strdup( vlc_meta_Get( p_meta
, vlc_meta_Title
) );
2579 vlc_meta_Merge( p_item
->p_meta
, p_meta
);
2581 if( psz_arturl
&& *psz_arturl
)
2583 vlc_meta_Set( p_item
->p_meta
, vlc_meta_ArtworkURL
, psz_arturl
);
2584 i_arturl_event
= VLC_TRUE
;
2587 vlc_meta_Delete( p_meta
);
2589 if( psz_arturl
&& !strncmp( psz_arturl
, "attachment://", strlen("attachment") ) )
2591 /* Don't look for art cover if sout
2592 * XXX It can change when sout has meta data support */
2593 if( p_input
->p
->p_sout
&& !p_input
->b_preparsing
)
2595 vlc_meta_Set( p_item
->p_meta
, vlc_meta_ArtworkURL
, "" );
2596 i_arturl_event
= VLC_TRUE
;
2600 input_ExtractAttachmentAndCacheArt( p_input
);
2606 if( vlc_dictionary_keys_count( &p_item
->p_meta
->extra_tags
) > 0 )
2608 p_meta
= vlc_meta_New();
2609 vlc_meta_Merge( p_meta
, input_item_GetMetaObject( p_item
) );
2611 vlc_mutex_unlock( &p_item
->lock
);
2613 input_item_SetPreparsed( p_item
, VLC_TRUE
);
2615 if( i_arturl_event
== VLC_TRUE
)
2619 /* Notify interested third parties */
2620 event
.type
= vlc_InputItemMetaChanged
;
2621 event
.u
.input_item_meta_changed
.meta_type
= vlc_meta_ArtworkURL
;
2622 vlc_event_send( &p_item
->event_manager
, &event
);
2627 input_Control( p_input
, INPUT_SET_NAME
, psz_title
);
2633 char ** ppsz_all_keys
= vlc_dictionary_all_keys( &p_meta
->extra_tags
);
2634 for( i
= 0; ppsz_all_keys
[i
]; i
++ )
2636 input_Control( p_input
, INPUT_ADD_INFO
, _(VLC_META_INFO_CAT
), _(ppsz_all_keys
[i
]),
2637 vlc_dictionary_value_for_key( &p_meta
->extra_tags
, ppsz_all_keys
[i
] ) );
2638 free( ppsz_all_keys
[i
] );
2640 free( ppsz_all_keys
);
2641 vlc_meta_Delete( p_meta
);
2644 /** \todo handle sout meta */
2648 static inline vlc_bool_t
IsValidAccess( const char *psz
)
2652 while( ( c
= *psz
) != '\0' )
2657 if( ( !isascii( c
) || !isalnum( c
) ) && c
!= '-' && ( c
!= '/' ) )
2661 /* should not happen though */
2665 static void AppendAttachment( int *pi_attachment
, input_attachment_t
***ppp_attachment
,
2666 int i_new
, input_attachment_t
**pp_new
)
2668 int i_attachment
= *pi_attachment
;
2669 input_attachment_t
**attachment
= *ppp_attachment
;
2672 attachment
= realloc( attachment
,
2673 sizeof(input_attachment_t
**) * ( i_attachment
+ i_new
) );
2674 for( i
= 0; i
< i_new
; i
++ )
2675 attachment
[i_attachment
++] = pp_new
[i
];
2680 *pi_attachment
= i_attachment
;
2681 *ppp_attachment
= attachment
;
2684 static void DemuxMeta( input_thread_t
*p_input
, vlc_meta_t
*p_meta
, demux_t
*p_demux
)
2691 /* XXX I am not sure it is a great idea, besides, there is more than that
2692 * if we want to do it right */
2693 vlc_mutex_lock( &p_item
->lock
);
2694 if( p_item
->p_meta
&& (p_item
->p_meta
->i_status
& ITEM_PREPARSED
) )
2696 vlc_mutex_unlock( &p_item
->lock
);
2699 vlc_mutex_unlock( &p_item
->lock
);
2702 demux2_Control( p_demux
, DEMUX_GET_META
, p_meta
);
2703 if( demux2_Control( p_demux
, DEMUX_HAS_UNSUPPORTED_META
, &b_bool
) )
2708 p_demux
->p_private
= malloc( sizeof( demux_meta_t
) );
2709 if(! p_demux
->p_private
)
2712 p_id3
= module_Need( p_demux
, "meta reader", NULL
, 0 );
2715 demux_meta_t
*p_demux_meta
= (demux_meta_t
*)p_demux
->p_private
;
2717 if( p_demux_meta
->p_meta
)
2719 vlc_meta_Merge( p_meta
, p_demux_meta
->p_meta
);
2720 vlc_meta_Delete( p_demux_meta
->p_meta
);
2723 if( p_demux_meta
->i_attachments
> 0 )
2725 vlc_mutex_lock( &p_input
->p
->input
.p_item
->lock
);
2726 AppendAttachment( &p_input
->p
->i_attachment
, &p_input
->p
->attachment
,
2727 p_demux_meta
->i_attachments
, p_demux_meta
->attachments
);
2728 vlc_mutex_unlock( &p_input
->p
->input
.p_item
->lock
);
2730 module_Unneed( p_demux
, p_id3
);
2732 free( p_demux
->p_private
);
2736 /*****************************************************************************
2737 * MRLSplit: parse the access, demux and url part of the
2738 * Media Resource Locator.
2739 *****************************************************************************/
2740 void MRLSplit( vlc_object_t
*p_input
, char *psz_dup
,
2741 const char **ppsz_access
, const char **ppsz_demux
,
2744 const char *psz_access
= "";
2745 const char *psz_demux
= "";
2749 psz
= strchr( psz_dup
, ':' );
2753 /* Guess whether ':' is part of a local filename, or separates
2754 * access/demux from path */
2755 if( !IsValidAccess( psz_dup
) )
2757 #if defined( WIN32 ) || defined( UNDER_CE )
2758 else if( ( psz
- psz_dup
== 1 ) && isalpha( psz_dup
[0] ) )
2760 msg_Dbg( p_input
, "drive letter %c: found in source", *psz_dup
);
2769 if( psz
[0] == '/' && psz
[1] == '/' ) psz
+= 2;
2773 psz
= strchr( psz_dup
, '/' );
2780 psz_access
= psz_dup
;
2787 *ppsz_access
= psz_access
;
2788 *ppsz_demux
= psz_demux
;
2789 *ppsz_path
= psz_path
;
2792 /*****************************************************************************
2793 * MRLSections: parse title and seekpoint info from the Media Resource Locator.
2796 * [url][@[title-start][:chapter-start][-[title-end][:chapter-end]]]
2797 *****************************************************************************/
2798 static void MRLSections( input_thread_t
*p_input
, char *psz_source
,
2799 int *pi_title_start
, int *pi_title_end
,
2800 int *pi_chapter_start
, int *pi_chapter_end
)
2802 char *psz
, *psz_end
, *psz_next
, *psz_check
;
2804 *pi_title_start
= *pi_title_end
= -1;
2805 *pi_chapter_start
= *pi_chapter_end
= -1;
2807 /* Start by parsing titles and chapters */
2808 if( !psz_source
|| !( psz
= strrchr( psz_source
, '@' ) ) ) return;
2810 /* Check we are really dealing with a title/chapter section */
2811 psz_check
= psz
+ 1;
2812 if( !*psz_check
) return;
2813 if( isdigit(*psz_check
) ) strtol( psz_check
, &psz_check
, 0 );
2814 if( *psz_check
!= ':' && *psz_check
!= '-' && *psz_check
) return;
2815 if( *psz_check
== ':' && ++psz_check
)
2816 if( isdigit(*psz_check
) ) strtol( psz_check
, &psz_check
, 0 );
2817 if( *psz_check
!= '-' && *psz_check
) return;
2818 if( *psz_check
== '-' && ++psz_check
)
2819 if( isdigit(*psz_check
) ) strtol( psz_check
, &psz_check
, 0 );
2820 if( *psz_check
!= ':' && *psz_check
) return;
2821 if( *psz_check
== ':' && ++psz_check
)
2822 if( isdigit(*psz_check
) ) strtol( psz_check
, &psz_check
, 0 );
2823 if( *psz_check
) return;
2825 /* Separate start and end */
2827 if( ( psz_end
= strchr( psz
, '-' ) ) ) *psz_end
++ = 0;
2829 /* Look for the start title */
2830 *pi_title_start
= strtol( psz
, &psz_next
, 0 );
2831 if( !*pi_title_start
&& psz
== psz_next
) *pi_title_start
= -1;
2832 *pi_title_end
= *pi_title_start
;
2835 /* Look for the start chapter */
2837 *pi_chapter_start
= strtol( psz
, &psz_next
, 0 );
2838 if( !*pi_chapter_start
&& psz
== psz_next
) *pi_chapter_start
= -1;
2839 *pi_chapter_end
= *pi_chapter_start
;
2843 /* Look for the end title */
2844 *pi_title_end
= strtol( psz_end
, &psz_next
, 0 );
2845 if( !*pi_title_end
&& psz_end
== psz_next
) *pi_title_end
= -1;
2848 /* Look for the end chapter */
2849 if( *psz_end
) psz_end
++;
2850 *pi_chapter_end
= strtol( psz_end
, &psz_next
, 0 );
2851 if( !*pi_chapter_end
&& psz_end
== psz_next
) *pi_chapter_end
= -1;
2854 msg_Dbg( p_input
, "source=`%s' title=%d/%d seekpoint=%d/%d",
2855 psz_source
, *pi_title_start
, *pi_chapter_start
,
2856 *pi_title_end
, *pi_chapter_end
);
2859 /*****************************************************************************
2860 * input_AddSubtitles: add a subtitles file and enable it
2861 *****************************************************************************/
2862 vlc_bool_t
input_AddSubtitles( input_thread_t
*p_input
, char *psz_subtitle
,
2863 vlc_bool_t b_check_extension
)
2865 input_source_t
*sub
;
2868 char *psz_path
, *psz_extension
;
2870 if( b_check_extension
&& !subtitles_Filter( psz_subtitle
) )
2875 /* if we are provided a subtitle.sub file,
2876 * see if we don't have a subtitle.idx and use it instead */
2877 psz_path
= strdup( psz_subtitle
);
2880 psz_extension
= strrchr( psz_path
, '.');
2881 if( psz_extension
&& strcmp( psz_extension
, ".sub" ) == 0 )
2885 strcpy( psz_extension
, ".idx" );
2886 /* FIXME: a portable wrapper for stat() or access() would be more suited */
2887 if( ( f
= utf8_fopen( psz_path
, "rt" ) ) )
2890 msg_Dbg( p_input
, "using %s subtitles file instead of %s",
2891 psz_path
, psz_subtitle
);
2892 strcpy( psz_subtitle
, psz_path
);
2898 var_Change( p_input
, "spu-es", VLC_VAR_CHOICESCOUNT
, &count
, NULL
);
2900 sub
= InputSourceNew( p_input
);
2901 if( !InputSourceInit( p_input
, sub
, psz_subtitle
, "subtitle" ) )
2903 TAB_APPEND( p_input
->p
->i_slave
, p_input
->p
->slave
, sub
);
2906 if( !var_Change( p_input
, "spu-es", VLC_VAR_GETLIST
, &list
, NULL
) )
2908 if( count
.i_int
== 0 )
2910 /* if it was first one, there is disable too */
2912 if( count
.i_int
< list
.p_list
->i_count
)
2914 input_ControlPush( p_input
, INPUT_CONTROL_SET_ES
,
2915 &list
.p_list
->p_values
[count
.i_int
] );
2917 var_Change( p_input
, "spu-es", VLC_VAR_FREELIST
, &list
, NULL
);