Commit a5058059 authored by Clément Stenac's avatar Clément Stenac

Support for moving averages (Refs:#473)

Get input bitrate
parent b7e2456f
......@@ -229,6 +229,9 @@ struct counter_t
int i_type;
int i_samples;
counter_sample_t ** pp_samples;
mtime_t update_interval;
mtime_t last_update;
};
struct stats_handler_t
......@@ -245,6 +248,8 @@ VLC_EXPORT( int, __stats_Update, (vlc_object_t*, char *, vlc_value_t) );
VLC_EXPORT( int, __stats_Create, (vlc_object_t*, char *, int, int) );
#define stats_Get( a,b,c,d ) __stats_Create( VLC_OBJECT(a), b, c, d )
VLC_EXPORT( int, __stats_Get, (vlc_object_t*, int, char *, vlc_value_t*) );
#define stats_CounterGet( a,b,c) __stats_CounterGet( VLC_OBJECT(a), b, c )
VLC_EXPORT( counter_t*, __stats_CounterGet, (vlc_object_t*, int, char * ) );
#define stats_GetInteger( a,b,c,d ) __stats_GetInteger( VLC_OBJECT(a), b, c, d )
static inline int __stats_GetInteger( vlc_object_t *p_obj, int i_id,
......@@ -256,6 +261,15 @@ static inline int __stats_GetInteger( vlc_object_t *p_obj, int i_id,
return i_ret;
}
#define stats_GetFloat(a,b,c,d ) __stats_GetFloat( VLC_OBJECT(a), b, c, d )
static inline int __stats_GetFloat( vlc_object_t *p_obj, int i_id,
char *psz_name, float *value )
{
vlc_value_t val;
int i_ret = __stats_Get( p_obj, i_id, psz_name, &val );
*value = val.f_float;
return i_ret;
}
#define stats_UpdateInteger( a,b,c ) __stats_UpdateInteger( VLC_OBJECT(a),b,c )
static inline int __stats_UpdateInteger( vlc_object_t *p_obj, char *psz_name,
int i )
......@@ -264,7 +278,14 @@ static inline int __stats_UpdateInteger( vlc_object_t *p_obj, char *psz_name,
val.i_int = i;
return __stats_Update( p_obj, psz_name, val );
}
#define stats_UpdateFloat( a,b,c ) __stats_UpdateFloat( VLC_OBJECT(a),b,c )
static inline int __stats_UpdateFloat( vlc_object_t *p_obj, char *psz_name,
float f )
{
vlc_value_t val;
val.f_float = f;
return __stats_Update( p_obj, psz_name, val );
}
struct input_stats_t
{
......@@ -275,7 +296,8 @@ struct input_stats_t
int i_read_packets;
int i_read_bytes;
float f_last_bitrate;
float f_bitrate;
float f_average_bitrate;
/* Decoders */
......
......@@ -145,6 +145,7 @@ int vlc_getnameinfo (const struct sockaddr *, int, char *, int, int *, int);
int vlm_ExecuteCommand (vlm_t *, const char *, vlm_message_t **);
char * config_GetUserDir (void);
httpd_stream_t * httpd_StreamNew (httpd_host_t *, const char *psz_url, const char *psz_mime, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl);
int __stats_CounterGet (vlc_object_t*, int, char *);
int __config_GetType (vlc_object_t *, const char *);
void __vlc_thread_ready (vlc_object_t *);
int playlist_Export (playlist_t *, const char *, const char *);
......@@ -881,6 +882,7 @@ struct module_symbols_t
void (*stats_ComputeInputStats_inner) (input_thread_t*, input_stats_t*);
void (*stats_DumpInputStats_inner) (input_stats_t *);
void (*stats_ReinitInputStats_inner) (input_stats_t *);
int (*__stats_CounterGet_inner) (vlc_object_t*, int, char *);
};
# if defined (__PLUGIN__)
# define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
......@@ -1307,6 +1309,7 @@ struct module_symbols_t
# define stats_ComputeInputStats (p_symbols)->stats_ComputeInputStats_inner
# define stats_DumpInputStats (p_symbols)->stats_DumpInputStats_inner
# define stats_ReinitInputStats (p_symbols)->stats_ReinitInputStats_inner
# define __stats_CounterGet (p_symbols)->__stats_CounterGet_inner
# elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
/******************************************************************
* STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
......@@ -1736,6 +1739,7 @@ struct module_symbols_t
((p_symbols)->stats_ComputeInputStats_inner) = stats_ComputeInputStats; \
((p_symbols)->stats_DumpInputStats_inner) = stats_DumpInputStats; \
((p_symbols)->stats_ReinitInputStats_inner) = stats_ReinitInputStats; \
((p_symbols)->__stats_CounterGet_inner) = __stats_CounterGet; \
(p_symbols)->net_ConvertIPv4_deprecated = NULL; \
# endif /* __PLUGIN__ */
......
......@@ -674,10 +674,15 @@ static int Init( input_thread_t * p_input, vlc_bool_t b_quick )
*/
if( !b_quick )
{
counter_t *p_counter;
stats_Create( p_input, "read_bytes", VLC_VAR_INTEGER, STATS_COUNTER );
stats_Create( p_input, "read_packets", VLC_VAR_INTEGER, STATS_COUNTER );
stats_Create( p_input, "input_bitrate", VLC_VAR_FLOAT,
STATS_DERIVATIVE );
p_counter = stats_CounterGet( p_input, p_input->i_object_id,
"input_bitrate" );
if( p_counter ) p_counter->update_interval = 1000000;
psz = var_GetString( p_input, "sout" );
if( *psz && strncasecmp( p_input->input.p_item->psz_uri, "vlc:", 4 ) )
{
......
......@@ -1565,12 +1565,16 @@ static int AReadStream( stream_t *s, void *p_read, int i_read )
stream_sys_t *p_sys = s->p_sys;
access_t *p_access = p_sys->p_access;
int i_read_orig = i_read;
int i_total;
if( !p_sys->i_list )
{
i_read = p_access->pf_read( p_access, p_read, i_read );
stats_UpdateInteger( s->p_parent->p_parent , "read_bytes", i_read );
stats_UpdateInteger( s->p_parent->p_parent , "input_bitrate", i_read );
stats_GetInteger( s, s->p_parent->p_parent->i_object_id,
"read_bytes", &i_total );
stats_UpdateFloat( s->p_parent->p_parent , "input_bitrate",
(float)i_total );
stats_UpdateInteger( s->p_parent->p_parent , "read_packets", 1 );
return i_read;
}
......@@ -1601,7 +1605,10 @@ static int AReadStream( stream_t *s, void *p_read, int i_read )
/* Update read bytes in input */
stats_UpdateInteger( s->p_parent->p_parent , "read_bytes", i_read );
stats_UpdateInteger( s->p_parent->p_parent , "input_bitrate", i_read );
stats_GetInteger( s, s->p_parent->p_parent->i_object_id,
"read_bytes", &i_total );
stats_UpdateFloat( s->p_parent->p_parent , "input_bitrate",
(float)i_total );
stats_UpdateInteger( s->p_parent->p_parent , "read_packets", 1 );
return i_read;
}
......
......@@ -32,7 +32,7 @@
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static counter_t *stats_GetCounter( stats_handler_t *p_handler, int i_object_id,
static counter_t *GetCounter( stats_handler_t *p_handler, int i_object_id,
char *psz_name );
static int stats_CounterUpdate( stats_handler_t *p_handler,
counter_t *p_counter,
......@@ -44,6 +44,17 @@ static stats_handler_t *stats_HandlerGet( vlc_object_t *p_this );
* Exported functions
*****************************************************************************/
/**
* Create a statistics counter
* \param p_this the object for which to create the counter
* \param psz_name the name
* \param i_type the type of stored data. One of VLC_VAR_STRING,
* VLC_VAR_INTEGER, VLC_VAR_FLOAT
* \param i_compute_type the aggregation type. One of STATS_LAST (always
* keep the last value), STATS_COUNTER (increment by the passed value),
* STATS_MAX (keep the maximum passed value), STATS_MIN, or STATS_DERIVATIVE
* (keep a time derivative of the value)
*/
int __stats_Create( vlc_object_t *p_this, char *psz_name, int i_type,
int i_compute_type )
{
......@@ -62,6 +73,9 @@ int __stats_Create( vlc_object_t *p_this, char *psz_name, int i_type,
p_counter->i_samples = 0;
p_counter->pp_samples = NULL;
p_counter->update_interval = 0;
p_counter->last_update = 0;
INSERT_ELEM( p_handler->pp_counters,
p_handler->i_counters,
p_handler->i_counters,
......@@ -72,8 +86,12 @@ int __stats_Create( vlc_object_t *p_this, char *psz_name, int i_type,
return VLC_SUCCESS;
}
/** Update a counter element with new values
* \param p_this the object in which to update
* \param psz_name the name
* \param val the vlc_value union containing the new value to aggregate. For
* more information on how data is aggregated, \see __stats_Create
*/
int __stats_Update( vlc_object_t *p_this, char *psz_name, vlc_value_t val )
{
int i_ret;
......@@ -86,7 +104,7 @@ int __stats_Update( vlc_object_t *p_this, char *psz_name, vlc_value_t val )
vlc_mutex_lock( &p_handler->object_lock );
/* Look for existing element */
p_counter = stats_GetCounter( p_handler, p_this->i_object_id,
p_counter = GetCounter( p_handler, p_this->i_object_id,
psz_name );
if( !p_counter )
{
......@@ -101,6 +119,14 @@ int __stats_Update( vlc_object_t *p_this, char *psz_name, vlc_value_t val )
return i_ret;
}
/** Get the aggregated value for a counter
* \param p_this an object
* \param i_object_id the object id from which we want the data
* \param psz_name the name of the couner
* \param val a pointer to an initialized vlc_value union. It will contain the
* retrieved value
* \return an error code
*/
int __stats_Get( vlc_object_t *p_this, int i_object_id, char *psz_name, vlc_value_t *val )
{
counter_t *p_counter;
......@@ -112,7 +138,7 @@ int __stats_Get( vlc_object_t *p_this, int i_object_id, char *psz_name, vlc_valu
/* Look for existing element */
p_counter = stats_GetCounter( p_handler, i_object_id,
p_counter = GetCounter( p_handler, i_object_id,
psz_name );
if( !p_counter )
{
......@@ -127,14 +153,67 @@ int __stats_Get( vlc_object_t *p_this, int i_object_id, char *psz_name, vlc_valu
return VLC_EGENERIC;
}
/* FIXME: Does not work for all types, maybe */
switch( p_counter->i_compute_type )
{
case STATS_LAST:
case STATS_MIN:
case STATS_MAX:
case STATS_COUNTER:
*val = p_counter->pp_samples[0]->value;
break;
case STATS_DERIVATIVE:
if( p_counter->i_type == VLC_VAR_INTEGER )
{
float f = ( p_counter->pp_samples[0]->value.i_int -
p_counter->pp_samples[1]->value.i_int ) /
(float)( p_counter->pp_samples[0]->date -
p_counter->pp_samples[1]->date );
val->i_int = (int)f;
}
else
{
float f = (float)( p_counter->pp_samples[0]->value.f_float -
p_counter->pp_samples[1]->value.f_float ) /
(float)( p_counter->pp_samples[0]->date -
p_counter->pp_samples[1]->date );
val->i_int = (int)f;
val->f_float = f;
}
break;
}
vlc_object_release( p_handler );
vlc_mutex_unlock( &p_handler->object_lock );
return VLC_SUCCESS;;
}
/** Get a statistics counter structure. This allows for low-level modifications
* \param p_this a parent object
* \param i_object_id the object from which to retrieve data
* \param psz_name the name
* \return the counter, or NULL if not found (or handler not created yet)
*/
counter_t *__stats_CounterGet( vlc_object_t *p_this, int i_object_id,
char *psz_name )
{
counter_t *p_counter;
/* Get stats handler singleton */
stats_handler_t *p_handler = stats_HandlerGet( p_this );
if( !p_handler ) return NULL;
vlc_mutex_lock( &p_handler->object_lock );
/* Look for existing element */
p_counter = GetCounter( p_handler, p_this->i_object_id,
psz_name );
vlc_mutex_unlock( &p_handler->object_lock );
vlc_object_release( p_handler );
return p_counter;
}
void stats_ComputeInputStats( input_thread_t *p_input,
input_stats_t *p_stats )
{
......@@ -144,21 +223,26 @@ void stats_ComputeInputStats( input_thread_t *p_input,
&p_stats->i_read_packets );
stats_GetInteger( p_input, p_input->i_object_id, "read_bytes",
&p_stats->i_read_bytes );
stats_GetFloat( p_input, p_input->i_object_id, "input_bitrate",
&p_stats->f_bitrate );
vlc_mutex_unlock( &p_stats->lock );
}
void stats_ReinitInputStats( input_stats_t *p_stats )
{
p_stats->i_read_packets = p_stats->i_read_bytes =
p_stats->f_last_bitrate = p_stats->f_average_bitrate =
p_stats->f_bitrate = p_stats->f_average_bitrate =
p_stats->i_displayed_pictures = p_stats->i_lost_pictures = 0;
}
void stats_DumpInputStats( input_stats_t *p_stats )
{
vlc_mutex_lock( &p_stats->lock );
fprintf( stderr, "Read packets : %i (%i bytes)\n",
p_stats->i_read_packets, p_stats->i_read_bytes );
/* f_bitrate is in bytes / microsecond
* *1000 => bytes / millisecond => kbytes / seconds */
fprintf( stderr, "Read packets : %i (%i bytes) - %f kB/s\n",
p_stats->i_read_packets, p_stats->i_read_bytes,
p_stats->f_bitrate * 1000 );
vlc_mutex_unlock( &p_stats->lock );
}
......@@ -233,7 +317,35 @@ static int stats_CounterUpdate( stats_handler_t *p_handler,
}
}
break;
case STATS_DERIVATIVE:
{
counter_sample_t *p_new, *p_old;
if( mdate() - p_counter->last_update < p_counter->update_interval )
{
return VLC_EGENERIC;
}
p_counter->last_update = mdate();
if( p_counter->i_type != VLC_VAR_FLOAT &&
p_counter->i_type != VLC_VAR_INTEGER )
{
msg_Err( p_handler, "Unable to compute DERIVATIVE for this type");
return VLC_EGENERIC;
}
/* Insert the new one at the beginning */
p_new = (counter_sample_t*)malloc( sizeof( counter_sample_t ) );
p_new->value = val;
p_new->date = p_counter->last_update;
INSERT_ELEM( p_counter->pp_samples, p_counter->i_samples,
0, p_new );
if( p_counter->i_samples == 3 )
{
p_old = p_counter->pp_samples[2];
REMOVE_ELEM( p_counter->pp_samples, p_counter->i_samples, 2 );
free( p_old );
}
break;
}
case STATS_COUNTER:
if( p_counter->i_samples > 1)
{
......@@ -268,8 +380,7 @@ static int stats_CounterUpdate( stats_handler_t *p_handler,
return VLC_SUCCESS;
}
static counter_t *stats_GetCounter( stats_handler_t *p_handler, int i_object_id,
static counter_t *GetCounter( stats_handler_t *p_handler, int i_object_id,
char *psz_name )
{
int i;
......@@ -285,6 +396,9 @@ static counter_t *stats_GetCounter( stats_handler_t *p_handler, int i_object_id,
return NULL;
}
static stats_handler_t *stats_HandlerGet( vlc_object_t *p_this )
{
stats_handler_t *p_handler = (stats_handler_t*)
......
......@@ -581,6 +581,8 @@ static void RunThread ( playlist_t *p_playlist )
mtime_t i_vout_destroyed_date = 0;
mtime_t i_sout_destroyed_date = 0;
int i_loops;
playlist_item_t *p_autodelete_item = NULL;
/* Tell above that we're ready */
......@@ -588,6 +590,7 @@ static void RunThread ( playlist_t *p_playlist )
while( !p_playlist->b_die )
{
i_loops++;
if( p_playlist->p_interaction )
{
intf_InteractionManage( p_playlist );
......@@ -617,9 +620,14 @@ static void RunThread ( playlist_t *p_playlist )
/* If there is an input, check that it doesn't need to die. */
if( p_playlist->p_input )
{
if( i_loops % 5 == 0 )
{
stats_ComputeInputStats( p_playlist->p_input,
p_playlist->p_input->input.p_item->p_stats );
// stats_DumpInputStats(
// p_playlist->p_input->input.p_item->p_stats );
}
/* This input is dead. Remove it ! */
if( p_playlist->p_input->b_dead )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment