int i_type;
int i_samples;
counter_sample_t ** pp_samples;
+
+ mtime_t update_interval;
+ mtime_t last_update;
};
struct stats_handler_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,
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 )
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
{
int i_read_packets;
int i_read_bytes;
- float f_last_bitrate;
+ float f_bitrate;
+
float f_average_bitrate;
/* Decoders */
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 *);
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
# 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.
((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__ */
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;
}
/* 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;
}
/*****************************************************************************
* 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,
* 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 )
{
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,
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;
vlc_mutex_lock( &p_handler->object_lock );
/* Look for existing element */
- p_counter = stats_GetCounter( p_handler, p_this->i_object_id,
- psz_name );
+ p_counter = GetCounter( p_handler, p_this->i_object_id,
+ psz_name );
if( !p_counter )
{
vlc_mutex_unlock( &p_handler->object_lock );
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;
/* Look for existing element */
- p_counter = stats_GetCounter( p_handler, i_object_id,
- psz_name );
+ p_counter = GetCounter( p_handler, i_object_id,
+ psz_name );
if( !p_counter )
{
vlc_mutex_unlock( &p_handler->object_lock );
return VLC_EGENERIC;
}
- /* FIXME: Does not work for all types, maybe */
- *val = p_counter->pp_samples[0]->value;
+ 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 )
{
&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 );
}
}
}
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)
{
return VLC_SUCCESS;
}
-
-static counter_t *stats_GetCounter( stats_handler_t *p_handler, int i_object_id,
- char *psz_name )
+static counter_t *GetCounter( stats_handler_t *p_handler, int i_object_id,
+ char *psz_name )
{
int i;
for( i = 0; i< p_handler->i_counters; i++ )
return NULL;
}
+
+
+
static stats_handler_t *stats_HandlerGet( vlc_object_t *p_this )
{
stats_handler_t *p_handler = (stats_handler_t*)