]> git.sesse.net Git - vlc/commitdiff
Support for moving averages (Refs:#473)
authorClément Stenac <zorglub@videolan.org>
Thu, 12 Jan 2006 21:21:36 +0000 (21:21 +0000)
committerClément Stenac <zorglub@videolan.org>
Thu, 12 Jan 2006 21:21:36 +0000 (21:21 +0000)
Get input bitrate

include/vlc_messages.h
include/vlc_symbols.h
src/input/input.c
src/input/stream.c
src/misc/stats.c
src/playlist/playlist.c

index 4027fa510e6d88c7d05b98ded52b0560cc0aecf9..bbe3ff50766c4c0fe071682ef07ee7c6a9526659 100644 (file)
@@ -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 */
index 97f7c433cf26a7130051b0ea7e061d7a02d007f6..b3ba93ab3bffc28bd70eacfbbb35b2f7f2f21015 100644 (file)
@@ -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__ */
index c34104dbe8a2fb27ced523dfdaf3637a11f6aa0a..8a7696252dbcc7a5fb298fe2a96555580da394a6 100644 (file)
@@ -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 ) )
         {
index c3bec91be25c6cdf8236539f401ed791be84dad0..620ce36a23c17ea4c8e956d22e6facc82f0faea9 100644 (file)
@@ -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;
 }
index d88ef18e1cf58799785dc94e97de1e0e5bf7541b..6f2d33b29f3989989e6c15841089676f19a76b10 100644 (file)
@@ -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,8 +104,8 @@ 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,
-                                  psz_name );
+    p_counter = GetCounter( p_handler, p_this->i_object_id,
+                            psz_name );
     if( !p_counter )
     {
         vlc_mutex_unlock( &p_handler->object_lock );
@@ -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,8 +138,8 @@ 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,
-                                  psz_name );
+    p_counter = GetCounter( p_handler, i_object_id,
+                            psz_name );
     if( !p_counter )
     {
         vlc_mutex_unlock( &p_handler->object_lock );
@@ -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 */
-    *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 )
 {
@@ -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,9 +380,8 @@ 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,
-                                    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++ )
@@ -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*)
index 00567988abc5d150343e080397ed1682278c0f41..303661ba4b73bb4990d57e8602213a998da73143 100644 (file)
@@ -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 );
@@ -618,8 +621,13 @@ 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 )
         {
-            stats_ComputeInputStats( 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 )