#include "demux.h"
#include "stream.h"
#include "item.h"
-#include "ressource.h"
+#include "resource.h"
#include <vlc_sout.h>
#include "../stream_output/stream_output.h"
-#include <vlc_interface.h>
+#include <vlc_dialog.h>
#include <vlc_url.h>
#include <vlc_charset.h>
#include <vlc_strings.h>
static void *RunAndDestroy ( vlc_object_t *p_this );
static input_thread_t * Create ( vlc_object_t *, input_item_t *,
- const char *, bool, input_ressource_t * );
+ const char *, bool, input_resource_t * );
static int Init ( input_thread_t *p_input );
static void End ( input_thread_t *p_input );
static void MainLoop( input_thread_t *p_input );
*****************************************************************************/
static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
const char *psz_header, bool b_quick,
- input_ressource_t *p_ressource )
+ input_resource_t *p_resource )
{
static const char input_name[] = "input";
input_thread_t *p_input = NULL; /* thread descriptor */
- vlc_value_t val;
int i;
/* Allocate descriptor */
if( !p_input->p )
return NULL;
- /* One "randomly" selected input thread is responsible for computing
- * the global stats. Check if there is already someone doing this */
- if( p_input->p_libvlc->p_stats && !b_quick )
- {
- libvlc_priv_t *p_private = libvlc_priv( p_input->p_libvlc );
- vlc_mutex_lock( &p_input->p_libvlc->p_stats->lock );
- if( p_private->p_stats_computer == NULL )
- p_private->p_stats_computer = p_input;
- vlc_mutex_unlock( &p_input->p_libvlc->p_stats->lock );
- }
-
p_input->b_preparsing = b_quick;
p_input->psz_header = psz_header ? strdup( psz_header ) : NULL;
p_input->p->slave = NULL;
/* */
- if( p_ressource )
- p_input->p->p_ressource = p_ressource;
+ if( p_resource )
+ p_input->p->p_resource = p_resource;
else
- p_input->p->p_ressource = input_ressource_New();
- input_ressource_SetInput( p_input->p->p_ressource, p_input );
+ p_input->p->p_resource = input_resource_New();
+ input_resource_SetInput( p_input->p->p_resource, p_input );
/* Init control buffer */
vlc_mutex_init( &p_input->p->lock_control );
vlc_cond_init( &p_input->p->wait_control );
p_input->p->i_control = 0;
+ p_input->p->b_abort = false;
/* Parse input options */
vlc_mutex_lock( &p_item->lock );
/* */
if( !p_input->b_preparsing )
{
- var_Get( p_input, "bookmarks", &val );
- if( val.psz_string )
+ char *psz_bookmarks = var_GetNonEmptyString( p_input, "bookmarks" );
+ if( psz_bookmarks )
{
/* FIXME: have a common cfg parsing routine used by sout and others */
char *psz_parser, *psz_start, *psz_end;
- psz_parser = val.psz_string;
+ psz_parser = psz_bookmarks;
while( (psz_start = strchr( psz_parser, '{' ) ) )
{
seekpoint_t *p_seekpoint;
vlc_seekpoint_Delete( p_seekpoint );
*psz_parser = backup;
}
- free( val.psz_string );
+ free( psz_bookmarks );
}
}
stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING );
stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING );
- if( p_input->p->p_ressource )
- input_ressource_Delete( p_input->p->p_ressource );
+ if( p_input->p->p_resource )
+ input_resource_Delete( p_input->p->p_resource );
vlc_gc_decref( p_input->p->p_item );
/* */
input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
input_item_t *p_item,
- const char *psz_log, input_ressource_t *p_ressource )
+ const char *psz_log, input_resource_t *p_resource )
{
input_thread_t *p_input;
- p_input = Create( p_parent, p_item, psz_log, false, p_ressource );
+ p_input = Create( p_parent, p_item, psz_log, false, p_resource );
if( !p_input )
return NULL;
/**
* Initialize an input and initialize it to preparse the item
- * This function is blocking. It will only accept to parse files
+ * This function is blocking. It will only accept parsing regular files.
*
* \param p_parent a vlc_object_t
* \param p_item an input item
* \return VLC_SUCCESS or an error
*/
-int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
+int input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
{
input_thread_t *p_input;
*
* \param the input thread to stop
*/
-void input_StopThread( input_thread_t *p_input )
+void input_StopThread( input_thread_t *p_input, bool b_abort )
{
/* Set die for input and ALL of this childrens (even (grand-)grand-childrens)
* It is needed here even if it is done in INPUT_CONTROL_SET_DIE handler to
* unlock the control loop */
ObjectKillChildrens( p_input, VLC_OBJECT(p_input) );
+ vlc_mutex_lock( &p_input->p->lock_control );
+ p_input->p->b_abort |= b_abort;
+ vlc_mutex_unlock( &p_input->p->lock_control );
+
input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
}
-input_ressource_t *input_DetachRessource( input_thread_t *p_input )
+input_resource_t *input_DetachResource( input_thread_t *p_input )
{
assert( p_input->b_dead );
- input_ressource_t *p_ressource = p_input->p->p_ressource;
- input_ressource_SetInput( p_ressource, NULL );
+ input_resource_SetInput( p_input->p->p_resource, NULL );
- p_input->p->p_ressource = NULL;
+ input_resource_t *p_resource = input_resource_Detach( p_input->p->p_resource );
p_input->p->p_sout = NULL;
- return p_ressource;
+ return p_resource;
}
/**
exit:
/* Tell we're dead */
+ vlc_mutex_lock( &p_input->p->lock_control );
+ const bool b_abort = p_input->p->b_abort;
+ vlc_mutex_unlock( &p_input->p->lock_control );
+
+ if( b_abort )
+ input_SendEventAbort( p_input );
input_SendEventDead( p_input );
+
vlc_restorecancel( canc );
return NULL;
}
if( i_ret == 0 ) /* EOF */
{
- vlc_value_t repeat;
-
- var_Get( p_input, "input-repeat", &repeat );
- if( repeat.i_int == 0 )
+ int i_repeat = var_GetInteger( p_input, "input-repeat" );
+ if( i_repeat == 0 )
{
/* End of file - we do not set b_die because only the
* playlist is allowed to do so. */
{
vlc_value_t val;
- msg_Dbg( p_input, "repeating the same input (%d)",
- repeat.i_int );
- if( repeat.i_int > 0 )
+ msg_Dbg( p_input, "repeating the same input (%d)", i_repeat );
+ if( i_repeat > 0 )
{
- repeat.i_int--;
- var_Set( p_input, "input-repeat", repeat );
+ i_repeat--;
+ var_SetInteger( p_input, "input-repeat", i_repeat );
}
/* Seek to start title/seekpoint */
static void MainLoopStatistic( input_thread_t *p_input )
{
stats_ComputeInputStats( p_input, p_input->p->p_item->p_stats );
- /* Are we the thread responsible for computing global stats ? */
- if( libvlc_priv( p_input->p_libvlc )->p_stats_computer == p_input )
- {
- stats_ComputeGlobalStats( p_input->p_libvlc,
- p_input->p_libvlc->p_stats );
- }
input_SendEventStatistics( p_input );
}
INIT_COUNTER( demux_read, INTEGER, COUNTER );
INIT_COUNTER( input_bitrate, FLOAT, DERIVATIVE );
INIT_COUNTER( demux_bitrate, FLOAT, DERIVATIVE );
+ INIT_COUNTER( demux_corrupted, INTEGER, COUNTER );
+ INIT_COUNTER( demux_discontinuity, INTEGER, COUNTER );
INIT_COUNTER( played_abuffers, INTEGER, COUNTER );
INIT_COUNTER( lost_abuffers, INTEGER, COUNTER );
INIT_COUNTER( displayed_pictures, INTEGER, COUNTER );
char *psz = var_GetNonEmptyString( p_input, "sout" );
if( psz && strncasecmp( p_input->p->p_item->psz_uri, "vlc:", 4 ) )
{
- p_input->p->p_sout = input_ressource_RequestSout( p_input->p->p_ressource, NULL, psz );
+ p_input->p->p_sout = input_resource_RequestSout( p_input->p->p_resource, NULL, psz );
if( !p_input->p->p_sout )
{
input_ChangeState( p_input, ERROR_S );
}
else
{
- input_ressource_RequestSout( p_input->p->p_ressource, NULL, NULL );
+ input_resource_RequestSout( p_input->p->p_resource, NULL, NULL );
}
free( psz );
{
/* Setup variables */
input_ControlVarNavigation( p_input );
- input_ControlVarTitle( p_input, 0 );
+ input_SendEventTitle( p_input, 0 );
}
/* Global flag */
msg_Warn( p_input, "invalid stop-time ignored" );
p_input->p->i_stop = 0;
}
+ p_input->p->b_fast_seek = var_GetBool( p_input, "input-fast-seek" );
}
static void LoadSubtitles( input_thread_t *p_input )
val.p_list = NULL;
if( p_input->p->p_sout )
{
- var_Get( p_input, "sout-all", &val );
- if( val.b_bool )
+ if( var_GetBool( p_input, "sout-all" ) )
{
i_es_out_mode = ES_OUT_MODE_ALL;
val.p_list = NULL;
#ifdef ENABLE_SOUT
ret = InitSout( p_input );
if( ret != VLC_SUCCESS )
- return ret; /* FIXME: goto error; should be better here */
+ goto error_stats;
#endif
/* Create es out */
InputUpdateMeta( p_input, p_meta );
}
- if( !p_input->b_preparsing )
- {
- msg_Dbg( p_input, "`%s' successfully opened",
- p_input->p->p_item->psz_uri );
-
- }
+ msg_Dbg( p_input, "`%s' successfully opened",
+ p_input->p->p_item->psz_uri );
/* initialization is complete */
input_ChangeState( p_input, PLAYING_S );
es_out_Delete( p_input->p->p_es_out );
if( p_input->p->p_es_out_display )
es_out_Delete( p_input->p->p_es_out_display );
- if( p_input->p->p_ressource )
+ if( p_input->p->p_resource )
{
if( p_input->p->p_sout )
- input_ressource_RequestSout( p_input->p->p_ressource,
+ input_resource_RequestSout( p_input->p->p_resource,
p_input->p->p_sout, NULL );
- input_ressource_SetInput( p_input->p->p_ressource, NULL );
+ input_resource_SetInput( p_input->p->p_resource, NULL );
}
+#ifdef ENABLE_SOUT
+error_stats:
+#endif
if( !p_input->b_preparsing && libvlc_stats( p_input ) )
{
#define EXIT_COUNTER( c ) do { if( p_input->p->counters.p_##c ) \
EXIT_COUNTER( demux_read );
EXIT_COUNTER( input_bitrate );
EXIT_COUNTER( demux_bitrate );
+ EXIT_COUNTER( demux_corrupted );
+ EXIT_COUNTER( demux_discontinuity );
EXIT_COUNTER( played_abuffers );
EXIT_COUNTER( lost_abuffers );
EXIT_COUNTER( displayed_pictures );
#define CL_CO( c ) stats_CounterClean( p_input->p->counters.p_##c ); p_input->p->counters.p_##c = NULL;
if( libvlc_stats( p_input ) )
{
- libvlc_priv_t *p_private = libvlc_priv( p_input->p_libvlc );
-
/* make sure we are up to date */
stats_ComputeInputStats( p_input, p_input->p->p_item->p_stats );
- if( p_private->p_stats_computer == p_input )
- {
- stats_ComputeGlobalStats( p_input->p_libvlc,
- p_input->p_libvlc->p_stats );
- /* FIXME how can it be thread safe ? */
- p_private->p_stats_computer = NULL;
- }
CL_CO( read_bytes );
CL_CO( read_packets );
CL_CO( demux_read );
CL_CO( input_bitrate );
CL_CO( demux_bitrate );
+ CL_CO( demux_corrupted );
+ CL_CO( demux_discontinuity );
CL_CO( played_abuffers );
CL_CO( lost_abuffers );
CL_CO( displayed_pictures );
}
/* */
- input_ressource_RequestSout( p_input->p->p_ressource,
+ input_resource_RequestSout( p_input->p->p_resource,
p_input->p->p_sout, NULL );
- input_ressource_SetInput( p_input->p->p_ressource, NULL );
+ input_resource_SetInput( p_input->p->p_resource, NULL );
}
/*****************************************************************************
/* Reset the decoders states and clock sync (before calling the demuxer */
es_out_SetTime( p_input->p->p_es_out, -1 );
if( demux_Control( p_input->p->input.p_demux, DEMUX_SET_POSITION,
- f_pos ) )
+ f_pos, !p_input->p->b_fast_seek ) )
{
msg_Err( p_input, "INPUT_CONTROL_SET_POSITION(_OFFSET) "
"%2.1f%% failed", f_pos * 100 );
es_out_SetTime( p_input->p->p_es_out, -1 );
i_ret = demux_Control( p_input->p->input.p_demux,
- DEMUX_SET_TIME, i_time );
+ DEMUX_SET_TIME, i_time,
+ !p_input->p->b_fast_seek );
if( i_ret )
{
int64_t i_length;
{
double f_pos = (double)i_time / (double)i_length;
i_ret = demux_Control( p_input->p->input.p_demux,
- DEMUX_SET_POSITION, f_pos );
+ DEMUX_SET_POSITION, f_pos,
+ !p_input->p->b_fast_seek );
}
}
if( i_ret )
es_out_SetTime( p_input->p->p_es_out, -1 );
demux_Control( p_demux, DEMUX_SET_TITLE, i_title );
- input_ControlVarTitle( p_input, i_title );
+ input_SendEventTitle( p_input, i_title );
}
}
else if( p_input->p->input.i_title > 0 )
stream_Control( p_input->p->input.p_stream, STREAM_CONTROL_ACCESS,
ACCESS_SET_TITLE, i_title );
+ input_SendEventTitle( p_input, i_title );
}
}
break;
es_out_SetTime( p_input->p->p_es_out, -1 );
demux_Control( p_demux, DEMUX_SET_SEEKPOINT, i_seekpoint );
+ input_SendEventSeekpoint( p_input, p_demux->info.i_title, i_seekpoint );
}
}
else if( p_input->p->input.i_title > 0 )
stream_Control( p_input->p->input.p_stream, STREAM_CONTROL_ACCESS,
ACCESS_SET_SEEKPOINT, i_seekpoint );
+ input_SendEventSeekpoint( p_input, p_access->info.i_title, i_seekpoint );
}
}
break;
break;
}
if( demux_Control( slave->p_demux,
- DEMUX_SET_TIME, i_time ) )
+ DEMUX_SET_TIME, i_time, true ) )
{
msg_Err( p_input, "seek failed for new slave" );
InputSourceClean( slave );
const char *psz_access;
const char *psz_demux;
char *psz_path;
- vlc_value_t val;
double f_fps;
strcpy( psz_dup, psz_mrl );
var_SetBool( p_input, "can-rate", !in->b_can_pace_control || in->b_can_rate_control ); /* XXX temporary because of es_out_timeshift*/
var_SetBool( p_input, "can-rewind", !in->b_rescale_ts && !in->b_can_pace_control );
- int ret = demux_Control( in->p_demux, DEMUX_CAN_SEEK,
- &val.b_bool );
- if( ret != VLC_SUCCESS )
- val.b_bool = false;
- var_Set( p_input, "can-seek", val );
+ bool b_can_seek;
+ if( demux_Control( in->p_demux, DEMUX_CAN_SEEK, &b_can_seek ) )
+ b_can_seek = false;
+ var_SetBool( p_input, "can-seek", b_can_seek );
}
else
{
{
msg_Err( p_input, "open of `%s' failed: %s", psz_mrl,
msg_StackMsg() );
- intf_UserFatal( VLC_OBJECT( p_input), false,
- _("Your input can't be opened"),
- _("VLC is unable to open the MRL '%s'."
+ dialog_Fatal( p_input, _("Your input can't be opened"),
+ _("VLC is unable to open the MRL '%s'."
" Check the log for details."), psz_mrl );
goto error;
}
/* Get infos from access */
if( !p_input->b_preparsing )
{
+ bool b_can_seek;
access_Control( in->p_access,
ACCESS_GET_PTS_DELAY, &in->i_pts_delay );
in->b_can_rate_control = in->b_can_pace_control;
in->b_rescale_ts = true;
- access_Control( in->p_access, ACCESS_CAN_PAUSE,
- &in->b_can_pause );
+ access_Control( in->p_access, ACCESS_CAN_PAUSE, &in->b_can_pause );
var_SetBool( p_input, "can-pause", in->b_can_pause || !in->b_can_pace_control ); /* XXX temporary because of es_out_timeshift*/
var_SetBool( p_input, "can-rate", !in->b_can_pace_control || in->b_can_rate_control ); /* XXX temporary because of es_out_timeshift*/
var_SetBool( p_input, "can-rewind", !in->b_rescale_ts && !in->b_can_pace_control );
- access_Control( in->p_access, ACCESS_CAN_SEEK,
- &val.b_bool );
- var_Set( p_input, "can-seek", val );
+ access_Control( in->p_access, ACCESS_CAN_SEEK, &b_can_seek );
+ var_SetBool( p_input, "can-seek", b_can_seek );
}
/* */
}
{
- /* Take access redirections into account */
+ /* Take access/stream redirections into account */
char *psz_real_path;
char *psz_buf = NULL;
- if( in->p_access->psz_path )
+ if( in->p_stream->psz_path )
{
const char *psz_a, *psz_d;
- psz_buf = strdup( in->p_access->psz_path );
+ psz_buf = strdup( in->p_stream->psz_path );
input_SplitMRL( &psz_a, &psz_d, &psz_real_path, psz_buf );
}
else
{
msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
psz_access, psz_demux, psz_path );
- intf_UserFatal( VLC_OBJECT( p_input ), false,
- _("VLC can't recognize the input's format"),
- _("The format of '%s' cannot be detected. "
+ dialog_Fatal( VLC_OBJECT( p_input ),
+ _("VLC can't recognize the input's format"),
+ _("The format of '%s' cannot be detected. "
"Have a look at the log for details."), psz_mrl );
goto error;
}
{
input_source_t *in = p_input->p->slave[i];
- if( demux_Control( in->p_demux, DEMUX_SET_TIME, i_time ) )
+ if( demux_Control( in->p_demux, DEMUX_SET_TIME, i_time, true ) )
{
if( !in->b_eof )
msg_Err( p_input, "seek failed for slave %d -> EOF", i );
*****************************************************************************/
static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta )
{
- vlc_value_t val;
-
/* Get meta information from user */
#define GET_META( field, s ) do { \
- var_Get( p_input, (s), &val ); \
- if( val.psz_string && *val.psz_string ) \
- vlc_meta_Set( p_meta, vlc_meta_ ## field, val.psz_string ); \
- free( val.psz_string ); } while(0)
+ char *psz_string = var_GetNonEmptyString( p_input, (s) ); \
+ if( psz_string ) \
+ vlc_meta_Set( p_meta, vlc_meta_ ## field, psz_string ); \
+ free( psz_string ); } while(0)
GET_META( Title, "meta-title" );
GET_META( Artist, "meta-artist" );
vlc_meta_Delete( p_meta );
+ if( !psz_arturl || *psz_arturl == '\0' )
+ {
+ const char *psz_tmp = vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL );
+ if( psz_tmp )
+ psz_arturl = strdup( psz_tmp );
+ }
+ vlc_mutex_unlock( &p_item->lock );
+
if( psz_arturl && *psz_arturl )
{
- vlc_meta_Set( p_item->p_meta, vlc_meta_ArtworkURL, psz_arturl );
+ input_item_SetArtURL( p_item, psz_arturl );
if( !strncmp( psz_arturl, "attachment://", strlen("attachment") ) )
{
/* Don't look for art cover if sout
* XXX It can change when sout has meta data support */
if( p_input->p->p_sout && !p_input->b_preparsing )
- vlc_meta_Set( p_item->p_meta, vlc_meta_ArtworkURL, "" );
+ input_item_SetArtURL( p_item, "" );
else
input_ExtractAttachmentAndCacheArt( p_input );
}
}
free( psz_arturl );
- vlc_mutex_unlock( &p_item->lock );
-
if( psz_title )
{
input_item_SetName( p_item, psz_title );