1 /*****************************************************************************
2 * stats.c: Statistics handling
3 *****************************************************************************
4 * Copyright (C) 2006 VLC authors and VideoLAN
7 * Authors: Clément Stenac <zorglub@videolan.org>
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.
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.
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 *****************************************************************************/
28 #include <vlc_common.h>
29 #include "input/input_internal.h"
32 * Create a statistics counter
33 * \param i_compute_type the aggregation type. One of STATS_LAST (always
34 * keep the last value), STATS_COUNTER (increment by the passed value),
35 * STATS_MAX (keep the maximum passed value), STATS_MIN, or STATS_DERIVATIVE
36 * (keep a time derivative of the value)
38 counter_t
* stats_CounterCreate( int i_compute_type
)
40 counter_t
*p_counter
= (counter_t
*) malloc( sizeof( counter_t
) ) ;
42 if( !p_counter
) return NULL
;
43 p_counter
->i_compute_type
= i_compute_type
;
44 p_counter
->i_samples
= 0;
45 p_counter
->pp_samples
= NULL
;
47 p_counter
->last_update
= 0;
52 static inline int64_t stats_GetTotal(const counter_t
*counter
)
54 if (counter
== NULL
|| counter
->i_samples
== 0)
56 return counter
->pp_samples
[0]->value
;
59 static inline float stats_GetRate(const counter_t
*counter
)
61 if (counter
== NULL
|| counter
->i_samples
< 2)
64 return (counter
->pp_samples
[0]->value
- counter
->pp_samples
[1]->value
)
65 / (float)(counter
->pp_samples
[0]->date
- counter
->pp_samples
[1]->date
);
68 input_stats_t
*stats_NewInputStats( input_thread_t
*p_input
)
71 input_stats_t
*p_stats
= calloc( 1, sizeof(input_stats_t
) );
75 vlc_mutex_init( &p_stats
->lock
);
76 stats_ReinitInputStats( p_stats
);
81 void stats_ComputeInputStats(input_thread_t
*input
, input_stats_t
*st
)
83 input_thread_private_t
*priv
= input_priv(input
);
85 if (!libvlc_stats(input
))
88 vlc_mutex_lock(&priv
->counters
.counters_lock
);
89 vlc_mutex_lock(&st
->lock
);
92 st
->i_read_packets
= stats_GetTotal(priv
->counters
.p_read_packets
);
93 st
->i_read_bytes
= stats_GetTotal(priv
->counters
.p_read_bytes
);
94 st
->f_input_bitrate
= stats_GetRate(priv
->counters
.p_input_bitrate
);
95 st
->i_demux_read_bytes
= stats_GetTotal(priv
->counters
.p_demux_read
);
96 st
->f_demux_bitrate
= stats_GetRate(priv
->counters
.p_demux_bitrate
);
97 st
->i_demux_corrupted
= stats_GetTotal(priv
->counters
.p_demux_corrupted
);
98 st
->i_demux_discontinuity
= stats_GetTotal(priv
->counters
.p_demux_discontinuity
);
101 st
->i_decoded_video
= stats_GetTotal(priv
->counters
.p_decoded_video
);
102 st
->i_decoded_audio
= stats_GetTotal(priv
->counters
.p_decoded_audio
);
105 if (priv
->counters
.p_sout_send_bitrate
)
107 st
->i_sent_packets
= stats_GetTotal(priv
->counters
.p_sout_sent_packets
);
108 st
->i_sent_bytes
= stats_GetTotal(priv
->counters
.p_sout_sent_bytes
);
109 st
->f_send_bitrate
= stats_GetRate(priv
->counters
.p_sout_send_bitrate
);
113 st
->i_played_abuffers
= stats_GetTotal(priv
->counters
.p_played_abuffers
);
114 st
->i_lost_abuffers
= stats_GetTotal(priv
->counters
.p_lost_abuffers
);
117 st
->i_displayed_pictures
= stats_GetTotal(priv
->counters
.p_displayed_pictures
);
118 st
->i_lost_pictures
= stats_GetTotal(priv
->counters
.p_lost_pictures
);
120 vlc_mutex_unlock(&st
->lock
);
121 vlc_mutex_unlock(&priv
->counters
.counters_lock
);
124 void stats_ReinitInputStats( input_stats_t
*p_stats
)
126 vlc_mutex_lock( &p_stats
->lock
);
127 p_stats
->i_read_packets
= p_stats
->i_read_bytes
=
128 p_stats
->f_input_bitrate
= p_stats
->f_average_input_bitrate
=
129 p_stats
->i_demux_read_packets
= p_stats
->i_demux_read_bytes
=
130 p_stats
->f_demux_bitrate
= p_stats
->f_average_demux_bitrate
=
131 p_stats
->i_demux_corrupted
= p_stats
->i_demux_discontinuity
=
132 p_stats
->i_displayed_pictures
= p_stats
->i_lost_pictures
=
133 p_stats
->i_played_abuffers
= p_stats
->i_lost_abuffers
=
134 p_stats
->i_decoded_video
= p_stats
->i_decoded_audio
=
135 p_stats
->i_sent_bytes
= p_stats
->i_sent_packets
= p_stats
->f_send_bitrate
137 vlc_mutex_unlock( &p_stats
->lock
);
140 void stats_CounterClean( counter_t
*p_c
)
144 for( int i
= 0; i
< p_c
->i_samples
; i
++ )
145 free( p_c
->pp_samples
[i
] );
146 TAB_CLEAN(p_c
->i_samples
, p_c
->pp_samples
);
152 /** Update a counter element with new values
153 * \param p_counter the counter to update
154 * \param val the vlc_value union containing the new value to aggregate. For
155 * more information on how data is aggregated, \see stats_Create
156 * \param val_new a pointer that will be filled with new data
158 void stats_Update( counter_t
*p_counter
, uint64_t val
, uint64_t *new_val
)
163 switch( p_counter
->i_compute_type
)
165 case STATS_DERIVATIVE
:
167 counter_sample_t
*p_new
, *p_old
;
168 mtime_t now
= mdate();
169 if( now
- p_counter
->last_update
< CLOCK_FREQ
)
171 p_counter
->last_update
= now
;
172 /* Insert the new one at the beginning */
173 p_new
= (counter_sample_t
*)malloc( sizeof( counter_sample_t
) );
174 if (unlikely(p_new
== NULL
))
175 return; /* NOTE: Losing sample here */
178 p_new
->date
= p_counter
->last_update
;
179 TAB_INSERT(p_counter
->i_samples
, p_counter
->pp_samples
, p_new
, 0);
181 if( p_counter
->i_samples
== 3 )
183 p_old
= p_counter
->pp_samples
[2];
184 TAB_ERASE(p_counter
->i_samples
, p_counter
->pp_samples
, 2);
190 if( p_counter
->i_samples
== 0 )
192 counter_sample_t
*p_new
= (counter_sample_t
*)malloc(
193 sizeof( counter_sample_t
) );
194 if (unlikely(p_new
== NULL
))
195 return; /* NOTE: Losing sample here */
199 TAB_APPEND(p_counter
->i_samples
, p_counter
->pp_samples
, p_new
);
201 if( p_counter
->i_samples
== 1 )
203 p_counter
->pp_samples
[0]->value
+= val
;
205 *new_val
= p_counter
->pp_samples
[0]->value
;