| 36 | | static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_block ); |
|---|
| 37 | | static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ); |
|---|
| 38 | | static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ); |
|---|
| 39 | | static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ); |
|---|
| 40 | | static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ); |
|---|
| 41 | | static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ); |
|---|
| 42 | | |
|---|
| 43 | | static block_t *rtcp_encode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp ); |
|---|
| 44 | | static block_t *rtcp_encode_RR( vlc_object_t *p_this, rtcp_t *p_rtcp ); |
|---|
| 45 | | static block_t *rtcp_encode_SDES( vlc_object_t *p_this, rtcp_t *p_rtcp ); |
|---|
| 46 | | static block_t *rtcp_encode_BYE( vlc_object_t *p_this, rtcp_t *p_rtcp ); |
|---|
| 47 | | |
|---|
| 48 | | static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ) |
|---|
| 49 | | { |
|---|
| 50 | | unsigned int u_ssrc_count; |
|---|
| | 36 | static void send_RTCP( vlc_object_t *p_this, rtcp_event_t rtcp_event ) |
|---|
| | 37 | { |
|---|
| | 38 | /* FIXME: higher level functions that should be in another file */ |
|---|
| | 39 | } |
|---|
| | 40 | |
|---|
| | 41 | static void rtcp_schedule( vlc_object_t *p_this, uint64_t i_sched, rtcp_event_t rtcp_event ) |
|---|
| | 42 | { |
|---|
| | 43 | /* FIXME: higher level functions that should be in another file */ |
|---|
| | 44 | } |
|---|
| | 45 | |
|---|
| | 46 | /* SDES support functions */ |
|---|
| | 47 | static int SDES_client_item_add( rtcp_client_t *p_client, int i_item, char *psz_name ) |
|---|
| | 48 | { |
|---|
| | 49 | rtcp_SDES_item_t *p_item = NULL; |
|---|
| | 50 | |
|---|
| | 51 | p_item = (rtcp_SDES_item_t *) malloc( sizeof( rtcp_SDES_item_t ) ); |
|---|
| | 52 | if( !p_item ) |
|---|
| | 53 | return VLC_EGENERIC; |
|---|
| | 54 | p_item->u_type = i_item; |
|---|
| | 55 | p_item->psz_data = strdup( psz_name ); |
|---|
| | 56 | p_item->i_index = p_client->i_items + 1;; |
|---|
| | 57 | INSERT_ELEM( p_client->pp_sdes, p_client->i_items, |
|---|
| | 58 | p_item->i_index, p_item ); |
|---|
| | 59 | return VLC_EGENERIC; |
|---|
| | 60 | } |
|---|
| | 61 | |
|---|
| | 62 | static int SDES_client_item_del( rtcp_client_t *p_client ) |
|---|
| | 63 | { |
|---|
| | 64 | uint32_t i = 0; |
|---|
| | 65 | |
|---|
| | 66 | for( i=0; i < p_client->i_items; i++ ) |
|---|
| | 67 | { |
|---|
| | 68 | rtcp_SDES_item_t *p_old = p_client->pp_sdes[i]; |
|---|
| | 69 | REMOVE_ELEM( p_client->pp_sdes, p_client->i_items, i ); |
|---|
| | 70 | p_client->i_items--; |
|---|
| | 71 | if( p_old->psz_data) |
|---|
| | 72 | free( p_old->psz_data ); |
|---|
| | 73 | free( p_old ); |
|---|
| | 74 | } |
|---|
| | 75 | return VLC_SUCCESS; |
|---|
| | 76 | } |
|---|
| | 77 | |
|---|
| | 78 | int rtcp_add_client( vlc_object_t *p_this, uint32_t u_ssrc, uint32_t *i_pos ) |
|---|
| | 79 | { |
|---|
| | 80 | rtcp_t *p_rtcp = (rtcp_t *) p_this; |
|---|
| | 81 | rtcp_client_t *p_client = NULL; |
|---|
| | 82 | |
|---|
| | 83 | vlc_mutex_lock( &p_rtcp->object_lock ); |
|---|
| | 84 | p_client = (rtcp_client_t*) malloc( sizeof(rtcp_client_t) ); |
|---|
| | 85 | if( !p_client ) |
|---|
| | 86 | return VLC_EGENERIC; |
|---|
| | 87 | p_client->i_index = p_rtcp->i_clients + 1; |
|---|
| | 88 | p_client->b_deleted = VLC_FALSE; |
|---|
| | 89 | *i_pos = p_client->i_index ; |
|---|
| | 90 | INSERT_ELEM( p_rtcp->pp_clients, p_rtcp->i_clients, |
|---|
| | 91 | p_client->i_index, p_client ); |
|---|
| | 92 | p_rtcp->i_clients++; |
|---|
| | 93 | p_rtcp->u_clients++; |
|---|
| | 94 | vlc_mutex_unlock( &p_rtcp->object_lock ); |
|---|
| | 95 | return VLC_SUCCESS; |
|---|
| | 96 | } |
|---|
| | 97 | |
|---|
| | 98 | int rtcp_del_client( vlc_object_t *p_this, uint32_t u_ssrc ) |
|---|
| | 99 | { |
|---|
| | 100 | rtcp_t *p_rtcp = (rtcp_t *) p_this; |
|---|
| | 101 | uint32_t i_pos = 0; |
|---|
| | 102 | |
|---|
| | 103 | vlc_mutex_lock( &p_rtcp->object_lock ); |
|---|
| | 104 | if( p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ) == VLC_SUCCESS ) |
|---|
| | 105 | { |
|---|
| | 106 | rtcp_client_t *p_old = p_rtcp->pp_clients[i_pos]; |
|---|
| | 107 | |
|---|
| | 108 | p_old->b_deleted = VLC_TRUE; |
|---|
| | 109 | p_old->i_timeout = 5 * (p_rtcp->i_date - p_rtcp->i_last_date) + |
|---|
| | 110 | p_rtcp->i_next_date; |
|---|
| | 111 | p_rtcp->u_clients--; |
|---|
| | 112 | } |
|---|
| | 113 | vlc_mutex_unlock( &p_rtcp->object_lock ); |
|---|
| | 114 | return VLC_SUCCESS; |
|---|
| | 115 | } |
|---|
| | 116 | |
|---|
| | 117 | /* rtcp_cleanup_clients should not be called too often */ |
|---|
| | 118 | int rtcp_cleanup_clients( vlc_object_t *p_this ) |
|---|
| | 119 | { |
|---|
| | 120 | rtcp_t *p_rtcp = (rtcp_t *) p_this; |
|---|
| | 121 | uint32_t i = 0; |
|---|
| | 122 | |
|---|
| | 123 | vlc_mutex_lock( &p_rtcp->object_lock ); |
|---|
| | 124 | for( i=0; i < p_rtcp->i_clients; i++ ) |
|---|
| | 125 | { |
|---|
| | 126 | rtcp_client_t *p_old = p_rtcp->pp_clients[i]; |
|---|
| | 127 | |
|---|
| | 128 | if( p_old->b_deleted && |
|---|
| | 129 | (p_old->i_timeout > mdate()) ) |
|---|
| | 130 | { |
|---|
| | 131 | REMOVE_ELEM( p_rtcp->pp_clients, p_rtcp->i_clients, i ); |
|---|
| | 132 | p_rtcp->i_clients--; |
|---|
| | 133 | SDES_client_item_del( p_old ); |
|---|
| | 134 | free( p_old ); |
|---|
| | 135 | } |
|---|
| | 136 | } |
|---|
| | 137 | vlc_mutex_unlock( &p_rtcp->object_lock ); |
|---|
| | 138 | return VLC_SUCCESS; |
|---|
| | 139 | } |
|---|
| | 140 | |
|---|
| | 141 | /* rtcp_find_client should be called with the object lock held. |
|---|
| | 142 | * vlc_mutex_lock( &p_rtcp->obj_lock ); |
|---|
| | 143 | */ |
|---|
| | 144 | int rtcp_find_client( vlc_object_t *p_this, uint32_t u_ssrc, uint32_t *i_pos ) |
|---|
| | 145 | { |
|---|
| | 146 | rtcp_t *p_rtcp = (rtcp_t *) p_this; |
|---|
| | 147 | uint32_t i = 0; |
|---|
| | 148 | |
|---|
| | 149 | for( i=0; i < p_rtcp->i_clients; i++ ) |
|---|
| | 150 | { |
|---|
| | 151 | if( p_rtcp->pp_clients[i]->u_ssrc == u_ssrc ) |
|---|
| | 152 | { |
|---|
| | 153 | *i_pos = i; |
|---|
| | 154 | return VLC_SUCCESS; |
|---|
| | 155 | } |
|---|
| | 156 | } |
|---|
| | 157 | *i_pos = -1; |
|---|
| | 158 | return VLC_EGENERIC; |
|---|
| | 159 | } |
|---|
| | 160 | |
|---|
| | 161 | /*-------------------------------------------------------------------------- |
|---|
| | 162 | * rtcp_interval - Calculate the interval in seconds for sending RTCP packets. |
|---|
| | 163 | *-------------------------------------------------------------------------- |
|---|
| | 164 | */ |
|---|
| | 165 | uint64_t rtcp_interval( vlc_object_t *p_this, uint64_t u_bandwidth, |
|---|
| | 166 | vlc_bool_t b_sender, vlc_bool_t b_first ) |
|---|
| | 167 | { |
|---|
| | 168 | rtcp_t *p_rtcp = (rtcp_t *) p_this; |
|---|
| | 169 | rtcp_client_t *p_client = NULL; |
|---|
| | 170 | uint32_t i_rtcp_min = 5; /* seconds */ |
|---|
| | 171 | uint32_t i_pos = 0; |
|---|
| | 172 | double i_bandwidth = u_bandwidth; |
|---|
| | 173 | const double i_compensation = 2.71828 - 1.5; |
|---|
| | 174 | double i_interval = 0; |
|---|
| | 175 | int n = p_rtcp->i_clients; |
|---|
| | 176 | |
|---|
| | 177 | int u_ssrc = 0; /* FIXME: how to know which client we look for?? */ |
|---|
| | 178 | |
|---|
| | 179 | if( b_first ) |
|---|
| | 180 | i_rtcp_min = (i_rtcp_min >> 1); |
|---|
| | 181 | |
|---|
| | 182 | if( (double)(p_rtcp->u_active) <= (double)(p_rtcp->u_clients * 0.25) ) |
|---|
| | 183 | { |
|---|
| | 184 | if( b_sender ) |
|---|
| | 185 | { |
|---|
| | 186 | i_bandwidth = i_bandwidth * 0.25; |
|---|
| | 187 | n = p_rtcp->u_active; |
|---|
| | 188 | } |
|---|
| | 189 | else |
|---|
| | 190 | { |
|---|
| | 191 | i_bandwidth = i_bandwidth * ( 1 - 0.25 ); |
|---|
| | 192 | n = n - p_rtcp->u_active; |
|---|
| | 193 | } |
|---|
| | 194 | } |
|---|
| | 195 | /* calculate average time between reports */ |
|---|
| | 196 | p_client = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ); |
|---|
| | 197 | if( !p_client ) |
|---|
| | 198 | return -1; |
|---|
| | 199 | |
|---|
| | 200 | i_interval = p_client->p_stats->u_avg_pkt_size * ( n / i_bandwidth ); |
|---|
| | 201 | if( i_interval < i_rtcp_min ) |
|---|
| | 202 | i_interval = i_rtcp_min; |
|---|
| | 203 | i_interval = i_interval * ( drand48() + 0.5 ); |
|---|
| | 204 | i_interval = (double) (i_interval / i_compensation); |
|---|
| | 205 | |
|---|
| | 206 | return (uint64_t)i_interval; |
|---|
| | 207 | } |
|---|
| | 208 | |
|---|
| | 209 | /*-------------------------------------------------------------------------- |
|---|
| | 210 | * rtcp_expire - decides to sent an RTCP report or a BYE record |
|---|
| | 211 | *-------------------------------------------------------------------------- |
|---|
| | 212 | */ |
|---|
| | 213 | void rtcp_expire( vlc_object_t *p_this, rtcp_event_t rtcp_event, |
|---|
| | 214 | uint64_t u_bandwidth, vlc_bool_t b_sender, vlc_bool_t *b_first ) |
|---|
| | 215 | { |
|---|
| | 216 | rtcp_t *p_rtcp = (rtcp_t *) p_this; |
|---|
| | 217 | rtcp_client_t *p_client = NULL; |
|---|
| | 218 | rtcp_stats_t *p_stats = NULL; |
|---|
| | 219 | mtime_t i_interval = 0; |
|---|
| | 220 | uint32_t i_pos = 0; |
|---|
| | 221 | |
|---|
| | 222 | int u_ssrc = 0; /* FIXME: how to know which client we look for?? */ |
|---|
| | 223 | |
|---|
| | 224 | p_client = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ); |
|---|
| | 225 | if( !p_client ) |
|---|
| | 226 | return; |
|---|
| | 227 | p_stats = (rtcp_stats_t*) p_client->p_stats; |
|---|
| | 228 | i_interval = (mtime_t) rtcp_interval( p_this, u_bandwidth, |
|---|
| | 229 | b_sender, *b_first ); |
|---|
| | 230 | p_rtcp->i_next_date = p_rtcp->i_last_date + i_interval; |
|---|
| | 231 | |
|---|
| | 232 | switch( rtcp_event ) |
|---|
| | 233 | { |
|---|
| | 234 | case EVENT_BYE: |
|---|
| | 235 | if( p_rtcp->i_next_date <= p_rtcp->i_date ) |
|---|
| | 236 | send_RTCP( p_this, rtcp_event ); |
|---|
| | 237 | else |
|---|
| | 238 | rtcp_schedule( p_this, p_rtcp->i_next_date, rtcp_event ); |
|---|
| | 239 | break; |
|---|
| | 240 | |
|---|
| | 241 | case EVENT_REPORT: |
|---|
| | 242 | if( p_rtcp->i_next_date <= p_rtcp->i_date ) |
|---|
| | 243 | { |
|---|
| | 244 | send_RTCP( p_this, rtcp_event ); |
|---|
| | 245 | |
|---|
| | 246 | /* Magic numbers are from RFC 3550 page 92 |
|---|
| | 247 | * 1.0/16.0 = 0.0625 and |
|---|
| | 248 | * 15.0/16.0 = 0.9375 |
|---|
| | 249 | */ |
|---|
| | 250 | p_stats->u_avg_pkt_size = (uint64_t) |
|---|
| | 251 | ( (double) ( (double)p_stats->u_sent_pkt_size / ((double)0.0625) ) + |
|---|
| | 252 | ( ((double)0.9357) * p_stats->u_avg_pkt_size ) ); |
|---|
| | 253 | |
|---|
| | 254 | /* recalculate */ |
|---|
| | 255 | p_rtcp->i_last_date = p_rtcp->i_date; |
|---|
| | 256 | i_interval = rtcp_interval( p_this, u_bandwidth, |
|---|
| | 257 | b_sender, *b_first ); |
|---|
| | 258 | rtcp_schedule( p_this, p_rtcp->i_next_date + i_interval, rtcp_event ); |
|---|
| | 259 | *b_first = VLC_FALSE; |
|---|
| | 260 | } |
|---|
| | 261 | else |
|---|
| | 262 | { |
|---|
| | 263 | rtcp_schedule( p_this, p_rtcp->i_next_date, rtcp_event ); |
|---|
| | 264 | } |
|---|
| | 265 | break; |
|---|
| | 266 | } |
|---|
| | 267 | p_rtcp->i_date = p_rtcp->i_next_date; |
|---|
| | 268 | } |
|---|
| | 269 | |
|---|
| | 270 | /*-------------------------------------------------------------------------- |
|---|
| | 271 | * Local functions prototoypes |
|---|
| | 272 | *-------------------------------------------------------------------------- |
|---|
| | 273 | */ |
|---|
| | 274 | static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); |
|---|
| | 275 | static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); |
|---|
| | 276 | static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); |
|---|
| | 277 | static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); |
|---|
| | 278 | static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); |
|---|
| | 279 | static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); |
|---|
| | 280 | |
|---|
| | 281 | /*-------------------------------------------------------------------------- |
|---|
| | 282 | * Local functions |
|---|
| | 283 | *-------------------------------------------------------------------------- |
|---|
| | 284 | */ |
|---|
| | 285 | static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ) |
|---|
| | 286 | { |
|---|
| | 287 | rtcp_t *p_rtcp = (rtcp_t *) p_this; |
|---|
| 57 | | p_rtcp->stats.u_SR_received++; |
|---|
| 58 | | p_rtcp->stats.u_pkt_count = p_buffer[20+RTCP_HEADER_LEN]; |
|---|
| 59 | | p_rtcp->stats.u_octet_count = p_buffer[24+RTCP_HEADER_LEN]; |
|---|
| 60 | | u_ssrc_count = p_buffer[RTCP_HEADER_LEN] & 0x1f; |
|---|
| 61 | | msg_Dbg( p_this, "SR received %d, packet count %d, octect count %d, SSRC count %d", |
|---|
| 62 | | p_rtcp->stats.u_SR_received, |
|---|
| 63 | | p_rtcp->stats.u_pkt_count, |
|---|
| 64 | | p_rtcp->stats.u_octet_count, |
|---|
| 65 | | u_ssrc_count ); |
|---|
| 66 | | |
|---|
| 67 | | for( i=0; i < u_ssrc_count; i++ ) |
|---|
| 68 | | { |
|---|
| 69 | | unsigned char count[4]; |
|---|
| 70 | | |
|---|
| 71 | | p_rtcp->stats.u_fract_lost = p_buffer[32+RTCP_HEADER_LEN]; |
|---|
| 72 | | |
|---|
| 73 | | count[0] = 0; |
|---|
| 74 | | count[1] = p_buffer[33+RTCP_HEADER_LEN]; |
|---|
| 75 | | count[2] = p_buffer[34+RTCP_HEADER_LEN]; |
|---|
| 76 | | count[3] = p_buffer[35+RTCP_HEADER_LEN]; |
|---|
| 77 | | |
|---|
| 78 | | /* FIXME: I don't like the sight of this */ |
|---|
| 79 | | p_rtcp->stats.u_pkt_lost = ntohl((int)count); |
|---|
| 80 | | |
|---|
| 81 | | p_rtcp->stats.u_highest_seq_no = ntohl( p_buffer[36+RTCP_HEADER_LEN] ); |
|---|
| 82 | | p_rtcp->stats.u_jitter = ntohl( p_buffer[40+RTCP_HEADER_LEN] ); |
|---|
| 83 | | p_rtcp->stats.u_last_SR = ntohl( p_buffer[44+RTCP_HEADER_LEN] ); |
|---|
| 84 | | p_rtcp->stats.u_delay_since_last_SR = (mtime_t) ntohl( p_buffer[48+RTCP_HEADER_LEN] ); |
|---|
| 85 | | |
|---|
| 86 | | msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, jitter %d, last SR %d, delay %lld", |
|---|
| 87 | | p_rtcp->stats.u_fract_lost, |
|---|
| 88 | | p_rtcp->stats.u_pkt_lost, |
|---|
| 89 | | p_rtcp->stats.u_highest_seq_no, |
|---|
| 90 | | p_rtcp->stats.u_jitter, |
|---|
| 91 | | p_rtcp->stats.u_last_SR, |
|---|
| 92 | | p_rtcp->stats.u_delay_since_last_SR ); |
|---|
| | 294 | |
|---|
| | 295 | /* parse sender info */ |
|---|
| | 296 | p_pkt->u_payload_type = RTCP_SR; |
|---|
| | 297 | p_pkt->report.sr.ntp_timestampH = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 298 | p_pkt->report.sr.ntp_timestampL = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 299 | p_pkt->report.sr.rtp_timestamp = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 300 | p_pkt->report.sr.u_pkt_count = bs_read( p_rtcp->bs, 32 ); /*sender*/ |
|---|
| | 301 | p_pkt->report.sr.u_octet_count = bs_read( p_rtcp->bs, 32 ); /*sender*/ |
|---|
| | 302 | |
|---|
| | 303 | /* parse report block */ |
|---|
| | 304 | for( i=0; i < p_pkt->u_report; i++ ) |
|---|
| | 305 | { |
|---|
| | 306 | rtcp_client_t *p_client = NULL; |
|---|
| | 307 | uint32_t i_pos = 0; |
|---|
| | 308 | uint32_t u_ssrc = 0; |
|---|
| | 309 | int result = 0; |
|---|
| | 310 | |
|---|
| | 311 | u_ssrc = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 312 | |
|---|
| | 313 | result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ); |
|---|
| | 314 | if( result == VLC_EGENERIC ) |
|---|
| | 315 | { |
|---|
| | 316 | result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ); |
|---|
| | 317 | if( result == VLC_EGENERIC ) |
|---|
| | 318 | return VLC_ENOMEM; |
|---|
| | 319 | } |
|---|
| | 320 | vlc_mutex_lock( &p_rtcp->object_lock ); |
|---|
| | 321 | p_client = p_rtcp->pp_clients[i_pos]; |
|---|
| | 322 | |
|---|
| | 323 | p_client->p_stats->u_SR_received++; |
|---|
| | 324 | p_client->p_stats->u_pkt_count++; |
|---|
| | 325 | p_client->p_stats->u_octet_count++; |
|---|
| | 326 | |
|---|
| | 327 | msg_Dbg( p_this, "SR received %d, packet count %d, octect count %d, SSRC count %d", |
|---|
| | 328 | p_client->p_stats->u_SR_received, |
|---|
| | 329 | p_client->p_stats->u_pkt_count, |
|---|
| | 330 | p_client->p_stats->u_octet_count, |
|---|
| | 331 | p_pkt->u_ssrc ); |
|---|
| | 332 | |
|---|
| | 333 | p_client->p_stats->u_fraction_lost = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 334 | p_client->p_stats->u_pkt_lost = bs_read( p_rtcp->bs, 24 ); |
|---|
| | 335 | p_client->p_stats->u_highest_seq_no = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 336 | p_client->p_stats->u_jitter = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 337 | p_client->p_stats->u_last_SR = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 338 | p_client->p_stats->u_delay_since_last_SR = (mtime_t) bs_read( p_rtcp->bs, 32 ); |
|---|
| | 339 | |
|---|
| | 340 | /* Magic numbers are from RFC 3550 page 92 |
|---|
| | 341 | * 1.0/16.0 = 0.0625 and |
|---|
| | 342 | * 15.0/16.0 = 0.9375 |
|---|
| | 343 | */ |
|---|
| | 344 | p_client->p_stats->u_avg_pkt_size = (uint64_t) |
|---|
| | 345 | ( (double)((double)p_client->p_stats->u_sent_pkt_size * (double)(0.0625)) + |
|---|
| | 346 | ((double)(0.9375) * p_client->p_stats->u_avg_pkt_size) ); |
|---|
| | 347 | |
|---|
| | 348 | msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, " |
|---|
| | 349 | "jitter %d, last SR %d, delay %lld", |
|---|
| | 350 | p_client->p_stats->u_fraction_lost, |
|---|
| | 351 | p_client->p_stats->u_pkt_lost, |
|---|
| | 352 | p_client->p_stats->u_highest_seq_no, |
|---|
| | 353 | p_client->p_stats->u_jitter, |
|---|
| | 354 | p_client->p_stats->u_last_SR, |
|---|
| | 355 | p_client->p_stats->u_delay_since_last_SR ); |
|---|
| | 356 | p_client = NULL; |
|---|
| | 357 | vlc_mutex_unlock( &p_rtcp->object_lock ); |
|---|
| 107 | | p_rtcp->stats.u_RR_received++; |
|---|
| 108 | | u_ssrc_count = (p_buffer[RTCP_HEADER_LEN] & 0x1f); |
|---|
| 109 | | msg_Dbg( p_this, "RR received %d, SSRC count %d", p_rtcp->stats.u_RR_received, u_ssrc_count ); |
|---|
| 110 | | |
|---|
| 111 | | for( i=0; i < u_ssrc_count; i++ ) |
|---|
| 112 | | { |
|---|
| 113 | | unsigned char count[4]; |
|---|
| 114 | | |
|---|
| 115 | | p_rtcp->stats.u_fract_lost = p_buffer[12+RTCP_HEADER_LEN]; |
|---|
| 116 | | |
|---|
| 117 | | count[0] = 0; |
|---|
| 118 | | count[1] = p_buffer[13+RTCP_HEADER_LEN]; |
|---|
| 119 | | count[2] = p_buffer[14+RTCP_HEADER_LEN]; |
|---|
| 120 | | count[3] = p_buffer[15+RTCP_HEADER_LEN]; |
|---|
| 121 | | |
|---|
| 122 | | /* FIXME: I don't like the sight of this */ |
|---|
| 123 | | p_rtcp->stats.u_pkt_lost = ntohl((int)count); |
|---|
| 124 | | |
|---|
| 125 | | p_rtcp->stats.u_highest_seq_no = ntohl( p_buffer[16+RTCP_HEADER_LEN] ); |
|---|
| 126 | | p_rtcp->stats.u_jitter = ntohl( p_buffer[20+RTCP_HEADER_LEN] ); |
|---|
| 127 | | p_rtcp->stats.u_last_RR = ntohl( p_buffer[24+RTCP_HEADER_LEN] ); |
|---|
| 128 | | p_rtcp->stats.u_delay_since_last_RR = (mtime_t) ntohl( p_buffer[28+RTCP_HEADER_LEN] ); |
|---|
| 129 | | |
|---|
| 130 | | msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, jitter %d, last RR %d, delay %lld", |
|---|
| 131 | | p_rtcp->stats.u_fract_lost, |
|---|
| 132 | | p_rtcp->stats.u_pkt_lost, |
|---|
| 133 | | p_rtcp->stats.u_highest_seq_no, |
|---|
| 134 | | p_rtcp->stats.u_jitter, |
|---|
| 135 | | p_rtcp->stats.u_last_RR, |
|---|
| 136 | | p_rtcp->stats.u_delay_since_last_RR ); |
|---|
| | 372 | for( i=0; i < p_pkt->u_report; i++ ) |
|---|
| | 373 | { |
|---|
| | 374 | rtcp_client_t *p_client = NULL; |
|---|
| | 375 | uint32_t i_pos = 0; |
|---|
| | 376 | uint32_t u_ssrc = 0; |
|---|
| | 377 | int result = 0; |
|---|
| | 378 | |
|---|
| | 379 | u_ssrc = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 380 | |
|---|
| | 381 | result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ); |
|---|
| | 382 | if( result == VLC_EGENERIC ) |
|---|
| | 383 | { |
|---|
| | 384 | result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ); |
|---|
| | 385 | if( result == VLC_EGENERIC ) |
|---|
| | 386 | return VLC_ENOMEM; |
|---|
| | 387 | } |
|---|
| | 388 | |
|---|
| | 389 | vlc_mutex_lock( &p_rtcp->object_lock ); |
|---|
| | 390 | p_client = p_rtcp->pp_clients[i_pos]; |
|---|
| | 391 | |
|---|
| | 392 | p_client->p_stats->u_RR_received++; |
|---|
| | 393 | msg_Dbg( p_this, "RR received %d, SSRC %d", |
|---|
| | 394 | p_client->p_stats->u_RR_received, u_ssrc ); |
|---|
| | 395 | |
|---|
| | 396 | p_client->p_stats->u_fraction_lost = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 397 | p_client->p_stats->u_pkt_lost = bs_read( p_rtcp->bs, 24 ); |
|---|
| | 398 | p_client->p_stats->u_highest_seq_no = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 399 | p_client->p_stats->u_jitter = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 400 | p_client->p_stats->u_last_SR = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 401 | p_client->p_stats->u_delay_since_last_SR = (mtime_t) bs_read( p_rtcp->bs, 32 ); |
|---|
| | 402 | |
|---|
| | 403 | /* Magic numbers are from RFC 3550 page 92 |
|---|
| | 404 | * 1.0/16.0 = 0.0625 and |
|---|
| | 405 | * 15.0/16.0 = 0.9375 |
|---|
| | 406 | */ |
|---|
| | 407 | p_client->p_stats->u_avg_pkt_size = (uint64_t) |
|---|
| | 408 | ( (double)((double)p_client->p_stats->u_sent_pkt_size * (double)(0.0625)) + |
|---|
| | 409 | ((double)(0.9375) * p_client->p_stats->u_avg_pkt_size) ); |
|---|
| | 410 | |
|---|
| | 411 | msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, " |
|---|
| | 412 | "jitter %d, last SR %d, delay %lld", |
|---|
| | 413 | p_client->p_stats->u_fraction_lost, |
|---|
| | 414 | p_client->p_stats->u_pkt_lost, |
|---|
| | 415 | p_client->p_stats->u_highest_seq_no, |
|---|
| | 416 | p_client->p_stats->u_jitter, |
|---|
| | 417 | p_client->p_stats->u_last_SR, |
|---|
| | 418 | p_client->p_stats->u_delay_since_last_SR ); |
|---|
| | 419 | p_client = NULL; |
|---|
| | 420 | vlc_mutex_unlock( &p_rtcp->object_lock ); |
|---|
| 148 | | switch( p_buffer[8] ) |
|---|
| 149 | | { |
|---|
| 150 | | case RTCP_INFO_CNAME: |
|---|
| 151 | | p_rtcp->stats.l_dest_SSRC = ntohs( (int)(p_buffer[4+RTCP_HEADER_LEN]) ); |
|---|
| 152 | | break; |
|---|
| 153 | | case RTCP_INFO_NAME: |
|---|
| 154 | | case RTCP_INFO_EMAIL: |
|---|
| 155 | | case RTCP_INFO_PHONE: |
|---|
| 156 | | case RTCP_INFO_LOC: |
|---|
| 157 | | case RTCP_INFO_TOOL: |
|---|
| 158 | | case RTCP_INFO_NOTE: |
|---|
| 159 | | case RTCP_INFO_PRIV: /* ignoring these */ |
|---|
| 160 | | break; |
|---|
| 161 | | default: |
|---|
| 162 | | return VLC_EGENERIC; |
|---|
| | 435 | for( i = 0; i < p_pkt->u_report; i++ ) |
|---|
| | 436 | { |
|---|
| | 437 | rtcp_client_t *p_client = NULL; |
|---|
| | 438 | uint32_t i_pos = 0; |
|---|
| | 439 | uint32_t u_ssrc = 0; |
|---|
| | 440 | uint8_t u_item = 0; |
|---|
| | 441 | uint8_t u_length = 0; |
|---|
| | 442 | int i = 0; |
|---|
| | 443 | int result = 0; |
|---|
| | 444 | |
|---|
| | 445 | u_ssrc = bs_read( p_rtcp->bs, 32 ); |
|---|
| | 446 | |
|---|
| | 447 | result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ); |
|---|
| | 448 | if( result == VLC_EGENERIC ) |
|---|
| | 449 | { |
|---|
| | 450 | result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ); |
|---|
| | 451 | if( result == VLC_EGENERIC ) |
|---|
| | 452 | return VLC_ENOMEM; |
|---|
| | 453 | } |
|---|
| | 454 | |
|---|
| | 455 | vlc_mutex_lock( &p_rtcp->object_lock ); |
|---|
| | 456 | p_client = p_rtcp->pp_clients[i_pos]; |
|---|
| | 457 | |
|---|
| | 458 | u_item = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 459 | switch( u_item ) |
|---|
| | 460 | { |
|---|
| | 461 | case RTCP_SDES_CNAME: |
|---|
| | 462 | case RTCP_SDES_NAME: |
|---|
| | 463 | case RTCP_SDES_EMAIL: |
|---|
| | 464 | case RTCP_SDES_PHONE: |
|---|
| | 465 | case RTCP_SDES_LOC: |
|---|
| | 466 | case RTCP_SDES_TOOL: |
|---|
| | 467 | case RTCP_SDES_NOTE: |
|---|
| | 468 | { |
|---|
| | 469 | char psz_name[255]; |
|---|
| | 470 | |
|---|
| | 471 | u_length = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 472 | for( i = 0 ; i < u_length; i++ ) |
|---|
| | 473 | { |
|---|
| | 474 | psz_name[i] = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 475 | } |
|---|
| | 476 | SDES_client_item_add( p_client, u_item, psz_name ); |
|---|
| | 477 | } |
|---|
| | 478 | break; |
|---|
| | 479 | |
|---|
| | 480 | case RTCP_SDES_PRIV: /* ignoring these */ |
|---|
| | 481 | { |
|---|
| | 482 | uint8_t u_prefix_len = 0; |
|---|
| | 483 | uint8_t u_length = 0; |
|---|
| | 484 | char psz_prefix_name[255]; |
|---|
| | 485 | char psz_name[255]; |
|---|
| | 486 | |
|---|
| | 487 | u_length = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 488 | u_prefix_len = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 489 | if( u_prefix_len > 254 ) |
|---|
| | 490 | u_prefix_len = 254; |
|---|
| | 491 | |
|---|
| | 492 | for( i=0 ; i < u_prefix_len; i++ ) |
|---|
| | 493 | { |
|---|
| | 494 | psz_prefix_name[i] = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 495 | } |
|---|
| | 496 | psz_prefix_name[255] = '\0'; |
|---|
| | 497 | SDES_client_item_add( p_client, u_item, psz_prefix_name ); |
|---|
| | 498 | |
|---|
| | 499 | for( i=0 ; i < u_length; i++ ) |
|---|
| | 500 | { |
|---|
| | 501 | psz_name[i] = bs_read( p_rtcp->bs, 8 ); |
|---|
| | 502 | } |
|---|
| | 503 | psz_name[255] = '\0'; |
|---|
| | 504 | SDES_client_item_add( p_client, u_item, psz_name ); |
|---|
| | 505 | } |
|---|
| | 506 | break; |
|---|
| | 507 | |
|---|
| | 508 | default: |
|---|
| | 509 | return VLC_EGENERIC; |
|---|
| | 510 | } |
|---|
| | 511 | /* Magic numbers are from RFC 3550 page 92 |
|---|
| | 512 | * 1.0/16.0 = 0.0625 and |
|---|
| | 513 | * 15.0/16.0 = 0.9375 |
|---|
| | 514 | */ |
|---|
| | 515 | p_client->p_stats->u_avg_pkt_size = (uint64_t) |
|---|
| | 516 | ( (double)((double)p_client->p_stats->u_sent_pkt_size * (double)(0.0625)) + |
|---|
| | 517 | ((double)(0.9375) * p_client->p_stats->u_avg_pkt_size) ); |
|---|
| | 518 | |
|---|
| | 519 | p_client = NULL; |
|---|
| | 520 | vlc_mutex_unlock( &p_rtcp->object_lock ); |
|---|