]> git.sesse.net Git - vlc/blob - src/misc/stats.c
Remove unused counter_t members
[vlc] / src / misc / stats.c
1 /*****************************************************************************
2  * stats.c: Statistics handling
3  *****************************************************************************
4  * Copyright (C) 2006 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <stdio.h>                                               /* required */
34
35 #include "input/input_internal.h"
36
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40 static int CounterUpdate( vlc_object_t *p_this,
41                           counter_t *p_counter,
42                           vlc_value_t val, vlc_value_t * );
43
44 /*****************************************************************************
45  * Exported functions
46  *****************************************************************************/
47
48 #undef stats_CounterCreate
49 /**
50  * Create a statistics counter
51  * \param p_this a VLC object
52  * \param i_type the type of stored data. One of VLC_VAR_STRING,
53  * VLC_VAR_INTEGER, VLC_VAR_FLOAT
54  * \param i_compute_type the aggregation type. One of STATS_LAST (always
55  * keep the last value), STATS_COUNTER (increment by the passed value),
56  * STATS_MAX (keep the maximum passed value), STATS_MIN, or STATS_DERIVATIVE
57  * (keep a time derivative of the value)
58  */
59 counter_t * stats_CounterCreate( vlc_object_t *p_this,
60                                    int i_type, int i_compute_type )
61 {
62     counter_t *p_counter = (counter_t*) malloc( sizeof( counter_t ) ) ;
63     (void)p_this;
64
65     if( !p_counter ) return NULL;
66     p_counter->i_compute_type = i_compute_type;
67     p_counter->i_type = i_type;
68     p_counter->i_samples = 0;
69     p_counter->pp_samples = NULL;
70
71     p_counter->update_interval = 0;
72     p_counter->last_update = 0;
73
74     return p_counter;
75 }
76
77 /** Update a counter element with new values
78  * \param p_this a VLC object
79  * \param p_counter the counter to update
80  * \param val the vlc_value union containing the new value to aggregate. For
81  * more information on how data is aggregated, \see stats_Create
82  * \param val_new a pointer that will be filled with new data
83  */
84 int stats_Update( vlc_object_t *p_this, counter_t *p_counter,
85                   vlc_value_t val, vlc_value_t *val_new )
86 {
87     if( !libvlc_stats (p_this) || !p_counter ) return VLC_EGENERIC;
88     return CounterUpdate( p_this, p_counter, val, val_new );
89 }
90
91 #undef stats_Get
92 /** Get the aggregated value for a counter
93  * \param p_this an object
94  * \param p_counter the counter
95  * \param val a pointer to an initialized vlc_value union. It will contain the
96  * retrieved value
97  * \return an error code
98  */
99 int stats_Get( vlc_object_t *p_this, counter_t *p_counter, vlc_value_t *val )
100 {
101     if( !libvlc_stats (p_this) || !p_counter || p_counter->i_samples == 0 )
102     {
103         val->i_int = 0;
104         return VLC_EGENERIC;
105     }
106
107     switch( p_counter->i_compute_type )
108     {
109     case STATS_COUNTER:
110         *val = p_counter->pp_samples[0]->value;
111         break;
112     case STATS_DERIVATIVE:
113         /* Not ready yet */
114         if( p_counter->i_samples < 2 )
115         {
116             val->i_int = 0;
117             return VLC_EGENERIC;
118         }
119         if( p_counter->i_type == VLC_VAR_INTEGER )
120         {
121             float f = ( p_counter->pp_samples[0]->value.i_int -
122                         p_counter->pp_samples[1]->value.i_int ) /
123                     (float)(  p_counter->pp_samples[0]->date -
124                               p_counter->pp_samples[1]->date );
125             val->i_int = (int64_t)f;
126         }
127         else
128         {
129             float f = (float)( p_counter->pp_samples[0]->value.f_float -
130                                p_counter->pp_samples[1]->value.f_float ) /
131                       (float)( p_counter->pp_samples[0]->date -
132                                p_counter->pp_samples[1]->date );
133             val->f_float = f;
134         }
135         break;
136     }
137     return VLC_SUCCESS;;
138 }
139
140 input_stats_t *stats_NewInputStats( input_thread_t *p_input )
141 {
142     (void)p_input;
143     input_stats_t *p_stats = calloc( 1, sizeof(input_stats_t) );
144     if( !p_stats )
145         return NULL;
146
147     vlc_mutex_init( &p_stats->lock );
148     stats_ReinitInputStats( p_stats );
149
150     return p_stats;
151 }
152
153 void stats_ComputeInputStats( input_thread_t *p_input, input_stats_t *p_stats )
154 {
155     if( !libvlc_stats (p_input) ) return;
156
157     vlc_mutex_lock( &p_input->p->counters.counters_lock );
158     vlc_mutex_lock( &p_stats->lock );
159
160     /* Input */
161     stats_GetInteger( p_input, p_input->p->counters.p_read_packets,
162                       &p_stats->i_read_packets );
163     stats_GetInteger( p_input, p_input->p->counters.p_read_bytes,
164                       &p_stats->i_read_bytes );
165     stats_GetFloat( p_input, p_input->p->counters.p_input_bitrate,
166                     &p_stats->f_input_bitrate );
167     stats_GetInteger( p_input, p_input->p->counters.p_demux_read,
168                       &p_stats->i_demux_read_bytes );
169     stats_GetFloat( p_input, p_input->p->counters.p_demux_bitrate,
170                     &p_stats->f_demux_bitrate );
171     stats_GetInteger( p_input, p_input->p->counters.p_demux_corrupted,
172                       &p_stats->i_demux_corrupted );
173     stats_GetInteger( p_input, p_input->p->counters.p_demux_discontinuity,
174                       &p_stats->i_demux_discontinuity );
175
176     /* Decoders */
177     stats_GetInteger( p_input, p_input->p->counters.p_decoded_video,
178                       &p_stats->i_decoded_video );
179     stats_GetInteger( p_input, p_input->p->counters.p_decoded_audio,
180                       &p_stats->i_decoded_audio );
181
182     /* Sout */
183     if( p_input->p->counters.p_sout_send_bitrate )
184     {
185         stats_GetInteger( p_input, p_input->p->counters.p_sout_sent_packets,
186                           &p_stats->i_sent_packets );
187         stats_GetInteger( p_input, p_input->p->counters.p_sout_sent_bytes,
188                           &p_stats->i_sent_bytes );
189         stats_GetFloat  ( p_input, p_input->p->counters.p_sout_send_bitrate,
190                           &p_stats->f_send_bitrate );
191     }
192
193     /* Aout */
194     stats_GetInteger( p_input, p_input->p->counters.p_played_abuffers,
195                       &p_stats->i_played_abuffers );
196     stats_GetInteger( p_input, p_input->p->counters.p_lost_abuffers,
197                       &p_stats->i_lost_abuffers );
198
199     /* Vouts */
200     stats_GetInteger( p_input, p_input->p->counters.p_displayed_pictures,
201                       &p_stats->i_displayed_pictures );
202     stats_GetInteger( p_input, p_input->p->counters.p_lost_pictures,
203                       &p_stats->i_lost_pictures );
204
205     vlc_mutex_unlock( &p_stats->lock );
206     vlc_mutex_unlock( &p_input->p->counters.counters_lock );
207 }
208
209 void stats_ReinitInputStats( input_stats_t *p_stats )
210 {
211     vlc_mutex_lock( &p_stats->lock );
212     p_stats->i_read_packets = p_stats->i_read_bytes =
213     p_stats->f_input_bitrate = p_stats->f_average_input_bitrate =
214     p_stats->i_demux_read_packets = p_stats->i_demux_read_bytes =
215     p_stats->f_demux_bitrate = p_stats->f_average_demux_bitrate =
216     p_stats->i_demux_corrupted = p_stats->i_demux_discontinuity =
217     p_stats->i_displayed_pictures = p_stats->i_lost_pictures =
218     p_stats->i_played_abuffers = p_stats->i_lost_abuffers =
219     p_stats->i_decoded_video = p_stats->i_decoded_audio =
220     p_stats->i_sent_bytes = p_stats->i_sent_packets = p_stats->f_send_bitrate
221      = 0;
222     vlc_mutex_unlock( &p_stats->lock );
223 }
224
225 void stats_CounterClean( counter_t *p_c )
226 {
227     if( p_c )
228     {
229         int i = p_c->i_samples - 1 ;
230         while( i >= 0 )
231         {
232             counter_sample_t *p_s = p_c->pp_samples[i];
233             REMOVE_ELEM( p_c->pp_samples, p_c->i_samples, i );
234             free( p_s );
235             i--;
236         }
237         free( p_c );
238     }
239 }
240
241
242 /********************************************************************
243  * Following functions are local
244  ********************************************************************/
245
246 /**
247  * Update a statistics counter, according to its type
248  * If needed, perform a bit of computation (derivative, mostly)
249  * This function must be entered with stats handler lock
250  * \param p_counter the counter to update
251  * \param val the "new" value
252  * \return an error code
253  */
254 static int CounterUpdate( vlc_object_t *p_handler,
255                           counter_t *p_counter,
256                           vlc_value_t val, vlc_value_t *new_val )
257 {
258     switch( p_counter->i_compute_type )
259     {
260     case STATS_DERIVATIVE:
261     {
262         counter_sample_t *p_new, *p_old;
263         mtime_t now = mdate();
264         if( now - p_counter->last_update < p_counter->update_interval )
265         {
266             return VLC_EGENERIC;
267         }
268         p_counter->last_update = now;
269         if( p_counter->i_type != VLC_VAR_FLOAT &&
270             p_counter->i_type != VLC_VAR_INTEGER )
271         {
272             msg_Err( p_handler, "Unable to compute DERIVATIVE for this type");
273             return VLC_EGENERIC;
274         }
275         /* Insert the new one at the beginning */
276         p_new = (counter_sample_t*)malloc( sizeof( counter_sample_t ) );
277         p_new->value = val;
278         p_new->date = p_counter->last_update;
279         INSERT_ELEM( p_counter->pp_samples, p_counter->i_samples,
280                      0, p_new );
281
282         if( p_counter->i_samples == 3 )
283         {
284             p_old = p_counter->pp_samples[2];
285             REMOVE_ELEM( p_counter->pp_samples, p_counter->i_samples, 2 );
286             free( p_old );
287         }
288         break;
289     }
290     case STATS_COUNTER:
291         if( p_counter->i_samples > 1)
292         {
293             msg_Err( p_handler, "LAST counter has several samples !" );
294             return VLC_EGENERIC;
295         }
296         if( p_counter->i_samples == 0 )
297         {
298             counter_sample_t *p_new = (counter_sample_t*)malloc(
299                                                sizeof( counter_sample_t ) );
300             p_new->value.i_int = 0;
301
302             INSERT_ELEM( p_counter->pp_samples, p_counter->i_samples,
303                          p_counter->i_samples, p_new );
304         }
305         if( p_counter->i_samples == 1 )
306         {
307             switch( p_counter->i_type )
308             {
309             case VLC_VAR_INTEGER:
310                 p_counter->pp_samples[0]->value.i_int += val.i_int;
311                 if( new_val )
312                     new_val->i_int = p_counter->pp_samples[0]->value.i_int;
313                 break;
314             case VLC_VAR_FLOAT:
315                 p_counter->pp_samples[0]->value.f_float += val.f_float;
316                 if( new_val )
317                     new_val->f_float = p_counter->pp_samples[0]->value.f_float;
318             }
319         }
320         break;
321     }
322     return VLC_SUCCESS;
323 }