1 /*****************************************************************************
2 * rtcp.c: RTP/RTCP source file
3 *****************************************************************************
4 * Copyright (C) 2005 M2X
8 * Authors: Jean-Paul Saman <jpsaman #_at_# videolan dot org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
26 #include <netinet/in.h>
31 #include <vlc_block.h>
36 static void send_RTCP( vlc_object_t *p_this, rtcp_event_t rtcp_event )
38 /* FIXME: higher level functions that should be in another file */
41 static void rtcp_schedule( vlc_object_t *p_this, uint64_t i_sched, rtcp_event_t rtcp_event )
43 /* FIXME: higher level functions that should be in another file */
46 /* SDES support functions */
47 static int SDES_client_item_add( rtcp_client_t *p_client, int i_item, char *psz_name )
49 rtcp_SDES_item_t *p_item = NULL;
51 p_item = (rtcp_SDES_item_t *) malloc( sizeof( rtcp_SDES_item_t ) );
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 );
62 static int SDES_client_item_del( rtcp_client_t *p_client )
66 for( i=0; i < p_client->i_items; i++ )
68 rtcp_SDES_item_t *p_old = p_client->pp_sdes[i];
69 REMOVE_ELEM( p_client->pp_sdes, p_client->i_items, i );
72 free( p_old->psz_data );
78 int rtcp_add_client( vlc_object_t *p_this, uint32_t u_ssrc, uint32_t *i_pos )
80 rtcp_t *p_rtcp = (rtcp_t *) p_this;
81 rtcp_client_t *p_client = NULL;
83 vlc_mutex_lock( &p_rtcp->object_lock );
84 p_client = (rtcp_client_t*) malloc( sizeof(rtcp_client_t) );
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 );
94 vlc_mutex_unlock( &p_rtcp->object_lock );
98 int rtcp_del_client( vlc_object_t *p_this, uint32_t u_ssrc )
100 rtcp_t *p_rtcp = (rtcp_t *) p_this;
103 vlc_mutex_lock( &p_rtcp->object_lock );
104 if( p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ) == VLC_SUCCESS )
106 rtcp_client_t *p_old = p_rtcp->pp_clients[i_pos];
108 p_old->b_deleted = VLC_TRUE;
109 p_old->i_timeout = 5 * (p_rtcp->i_date - p_rtcp->i_last_date) +
113 vlc_mutex_unlock( &p_rtcp->object_lock );
117 /* rtcp_cleanup_clients should not be called too often */
118 int rtcp_cleanup_clients( vlc_object_t *p_this )
120 rtcp_t *p_rtcp = (rtcp_t *) p_this;
123 vlc_mutex_lock( &p_rtcp->object_lock );
124 for( i=0; i < p_rtcp->i_clients; i++ )
126 rtcp_client_t *p_old = p_rtcp->pp_clients[i];
128 if( p_old->b_deleted &&
129 (p_old->i_timeout > mdate()) )
131 REMOVE_ELEM( p_rtcp->pp_clients, p_rtcp->i_clients, i );
133 SDES_client_item_del( p_old );
137 vlc_mutex_unlock( &p_rtcp->object_lock );
141 /* rtcp_find_client should be called with the object lock held.
142 * vlc_mutex_lock( &p_rtcp->obj_lock );
144 int rtcp_find_client( vlc_object_t *p_this, uint32_t u_ssrc, uint32_t *i_pos )
146 rtcp_t *p_rtcp = (rtcp_t *) p_this;
149 for( i=0; i < p_rtcp->i_clients; i++ )
151 if( p_rtcp->pp_clients[i]->u_ssrc == u_ssrc )
161 /*--------------------------------------------------------------------------
162 * rtcp_interval - Calculate the interval in seconds for sending RTCP packets.
163 *--------------------------------------------------------------------------
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 )
168 rtcp_t *p_rtcp = (rtcp_t *) p_this;
169 rtcp_client_t *p_client = NULL;
170 uint32_t i_rtcp_min = 5; /* seconds */
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;
177 int u_ssrc = 0; /* FIXME: how to know which client we look for?? */
180 i_rtcp_min = (i_rtcp_min >> 1);
182 if( (double)(p_rtcp->u_active) <= (double)(p_rtcp->u_clients * 0.25) )
186 i_bandwidth = i_bandwidth * 0.25;
187 n = p_rtcp->u_active;
191 i_bandwidth = i_bandwidth * ( 1 - 0.25 );
192 n = n - p_rtcp->u_active;
195 /* calculate average time between reports */
196 p_client = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
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);
206 return (uint64_t)i_interval;
209 /*--------------------------------------------------------------------------
210 * rtcp_expire - decides to sent an RTCP report or a BYE record
211 *--------------------------------------------------------------------------
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 )
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;
222 int u_ssrc = 0; /* FIXME: how to know which client we look for?? */
224 p_client = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
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;
235 if( p_rtcp->i_next_date <= p_rtcp->i_date )
236 send_RTCP( p_this, rtcp_event );
238 rtcp_schedule( p_this, p_rtcp->i_next_date, rtcp_event );
242 if( p_rtcp->i_next_date <= p_rtcp->i_date )
244 send_RTCP( p_this, rtcp_event );
246 /* Magic numbers are from RFC 3550 page 92
247 * 1.0/16.0 = 0.0625 and
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 ) );
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;
263 rtcp_schedule( p_this, p_rtcp->i_next_date, rtcp_event );
267 p_rtcp->i_date = p_rtcp->i_next_date;
270 /*--------------------------------------------------------------------------
271 * Local functions prototoypes
272 *--------------------------------------------------------------------------
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 );
281 /*--------------------------------------------------------------------------
283 *--------------------------------------------------------------------------
285 static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
287 rtcp_t *p_rtcp = (rtcp_t *) p_this;
293 msg_Dbg( p_this, "decoding record: SR" );
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*/
303 /* parse report block */
304 for( i=0; i < p_pkt->u_report; i++ )
306 rtcp_client_t *p_client = NULL;
311 u_ssrc = bs_read( p_rtcp->bs, 32 );
313 result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
314 if( result == VLC_EGENERIC )
316 result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
317 if( result == VLC_EGENERIC )
320 vlc_mutex_lock( &p_rtcp->object_lock );
321 p_client = p_rtcp->pp_clients[i_pos];
323 p_client->p_stats->u_SR_received++;
324 p_client->p_stats->u_pkt_count++;
325 p_client->p_stats->u_octet_count++;
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,
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 );
340 /* Magic numbers are from RFC 3550 page 92
341 * 1.0/16.0 = 0.0625 and
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) );
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 );
357 vlc_mutex_unlock( &p_rtcp->object_lock );
362 static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
364 rtcp_t *p_rtcp = (rtcp_t *) p_this;
370 msg_Dbg( p_this, "decoding record: RR" );
372 for( i=0; i < p_pkt->u_report; i++ )
374 rtcp_client_t *p_client = NULL;
379 u_ssrc = bs_read( p_rtcp->bs, 32 );
381 result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
382 if( result == VLC_EGENERIC )
384 result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
385 if( result == VLC_EGENERIC )
389 vlc_mutex_lock( &p_rtcp->object_lock );
390 p_client = p_rtcp->pp_clients[i_pos];
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 );
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 );
403 /* Magic numbers are from RFC 3550 page 92
404 * 1.0/16.0 = 0.0625 and
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) );
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 );
420 vlc_mutex_unlock( &p_rtcp->object_lock );
425 static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
427 rtcp_t *p_rtcp = (rtcp_t *) p_this;
433 msg_Dbg( p_this, "decoding record: SDES" );
435 for( i = 0; i < p_pkt->u_report; i++ )
437 rtcp_client_t *p_client = NULL;
441 uint8_t u_length = 0;
445 u_ssrc = bs_read( p_rtcp->bs, 32 );
447 result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
448 if( result == VLC_EGENERIC )
450 result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
451 if( result == VLC_EGENERIC )
455 vlc_mutex_lock( &p_rtcp->object_lock );
456 p_client = p_rtcp->pp_clients[i_pos];
458 u_item = bs_read( p_rtcp->bs, 8 );
461 case RTCP_SDES_CNAME:
463 case RTCP_SDES_EMAIL:
464 case RTCP_SDES_PHONE:
471 u_length = bs_read( p_rtcp->bs, 8 );
472 for( i = 0 ; i < u_length; i++ )
474 psz_name[i] = bs_read( p_rtcp->bs, 8 );
476 SDES_client_item_add( p_client, u_item, psz_name );
480 case RTCP_SDES_PRIV: /* ignoring these */
482 uint8_t u_prefix_len = 0;
483 uint8_t u_length = 0;
484 char psz_prefix_name[255];
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 )
492 for( i=0 ; i < u_prefix_len; i++ )
494 psz_prefix_name[i] = bs_read( p_rtcp->bs, 8 );
496 psz_prefix_name[255] = '\0';
497 SDES_client_item_add( p_client, u_item, psz_prefix_name );
499 for( i=0 ; i < u_length; i++ )
501 psz_name[i] = bs_read( p_rtcp->bs, 8 );
503 psz_name[255] = '\0';
504 SDES_client_item_add( p_client, u_item, psz_name );
511 /* Magic numbers are from RFC 3550 page 92
512 * 1.0/16.0 = 0.0625 and
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) );
520 vlc_mutex_unlock( &p_rtcp->object_lock );
525 static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
527 rtcp_t *p_rtcp = (rtcp_t *) p_this;
529 uint8_t u_length = 0;
535 msg_Dbg( p_this, "decoding record: BYE" );
537 u_ssrc = bs_read( p_rtcp->bs, 32 );
538 p_rtcp->pf_del_client( p_this, u_ssrc );
539 u_length = p_pkt->u_length-1;
540 for( i = 0 ; i < u_length; i++ )
542 u_ssrc = bs_read( p_rtcp->bs, 8 );
543 p_rtcp->pf_del_client( p_this, u_ssrc );
548 static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
550 rtcp_t *p_rtcp = (rtcp_t *) p_this;
551 rtcp_client_t *p_client = NULL;
553 char* psz_data = NULL;
562 msg_Dbg( p_this, "decoding record: APP" );
564 u_ssrc = bs_read( p_rtcp->bs, 32 );
566 result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
567 if( result == VLC_EGENERIC )
569 result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
570 if( result == VLC_EGENERIC )
574 vlc_mutex_lock( &p_rtcp->object_lock );
575 p_client = p_rtcp->pp_clients[i_pos];
577 for( i = 0 ; i < 4; i++ )
579 psz_name[i] = bs_read( p_rtcp->bs, 8 );
583 p_pkt->u_payload_type = RTCP_APP;
584 p_pkt->report.app.psz_prefix = strdup( psz_name );
585 p_pkt->report.app.u_prefix_len = 4;
586 p_pkt->u_length -= 4;
588 psz_data = (char *) malloc( p_pkt->u_length );
590 vlc_mutex_unlock( &p_rtcp->object_lock );
594 for( i = 0; i < p_pkt->u_length; i-- )
596 psz_data[i] = bs_read( p_rtcp->bs, 8 );
598 psz_data[p_pkt->u_length] = '\0';
600 p_pkt->report.app.psz_data = strdup( psz_data );
601 p_pkt->report.app.u_length = p_pkt->u_length;
604 vlc_mutex_unlock( &p_rtcp->object_lock );
606 /* Just ignore this packet */
610 /* Decode RTCP packet
611 * Decode incoming RTCP packet and inspect the records types.
613 int rtcp_pkt_decode( vlc_object_t *p_this, rtcp_pkt_t *p_pkt, block_t *p_block )
615 rtcp_t *p_rtcp = (rtcp_t *) p_this;
617 if( !p_pkt && !p_block )
620 bs_init( p_rtcp->bs, p_block->p_buffer, p_block->i_buffer );
622 p_pkt->u_version = bs_read( p_rtcp->bs, 2 );
623 p_pkt->b_padding = bs_read( p_rtcp->bs, 1 ) ? VLC_TRUE : VLC_FALSE;
624 p_pkt->u_report = bs_read( p_rtcp->bs, 5 );
625 p_pkt->u_payload_type = bs_read( p_rtcp->bs, 8 );
626 p_pkt->u_length = bs_read( p_rtcp->bs, 16 );
628 if( p_pkt->u_payload_type != RTCP_SDES )
629 p_pkt->u_ssrc = bs_read( p_rtcp->bs, 32 );
631 msg_Dbg( p_this, "New RTCP packet: version %d, padding %s, count %d, "
632 "type %d, length %d, SSRC %d",
634 p_pkt->b_padding ? "true" : "false",
636 p_pkt->u_payload_type,
640 while( !bs_eof( p_rtcp->bs ) )
644 switch( p_pkt->u_payload_type )
647 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
648 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
649 rtcp_decode_SR( p_this, p_pkt );
653 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
654 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
655 rtcp_decode_RR( p_this, p_pkt );
659 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
660 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
661 rtcp_decode_SDES( p_this, p_pkt );
665 rtcp_decode_BYE( p_this, p_pkt );
667 if( p_rtcp->pf_find_sender( p_this, pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
668 p_rtcp->pf_del_sender( p_this, p_pkt->u_ssrc );
670 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
671 p_rtcp->pf_del_client( p_this, p_pkt->u_ssrc );
673 if( p_rtcp->u_active < p_rtcp->u_members )
675 rtcp_event_t event = EVENT_BYE;
677 p_rtcp->i_next_date = p_rtcp->i_date +
678 (mtime_t) ( (p_rtcp->u_active / p_rtcp->u_members) *
679 (p_rtcp->i_next_date - p_rtcp->i_date) );
680 p_rtcp->i_last_date = p_rtcp->i_date -
682 ( (mtime_t)(p_rtcp->u_active / p_rtcp->u_members) *
683 (p_rtcp->i_date - p_rtcp->i_last_date) );
684 /* schedule for next period */
685 rtcp_schedule( VLC_OBJECT(p_rtcp), p_rtcp->i_next_date, event );
686 p_rtcp->u_members = p_rtcp->u_active;
688 else p_rtcp->u_members++;
692 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
693 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
694 rtcp_decode_APP( p_this, p_pkt );
705 * Create RTCP records for reporting to server.
707 rtcp_pkt_t *rtcp_pkt_new( vlc_object_t *p_this, int type )
709 rtcp_pkt_t *p_pkt = NULL;
711 p_pkt = (rtcp_pkt_t *) malloc( sizeof( rtcp_pkt_t ) );
715 memset( p_pkt, 0 , sizeof( rtcp_pkt_t ) );
716 p_pkt->u_version = 2;
717 p_pkt->u_payload_type = type;
718 p_pkt->u_length = RTCP_HEADER_LEN;
723 p_pkt->u_length += sizeof(rtcp_SR_t);
726 p_pkt->u_length += sizeof(rtcp_RR_t);
729 p_pkt->u_length += sizeof(rtcp_SDES_t);
730 if( p_pkt->report.sdes.pp_items )
731 p_pkt->u_length += p_pkt->report.sdes.u_items;
734 p_pkt->u_length += sizeof(rtcp_BYE_t);
737 p_pkt->u_length += sizeof(rtcp_APP_t);
746 void rtcp_pkt_del( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
751 switch( p_pkt->u_payload_type )
757 if( p_pkt->report.sdes.pp_items )
761 for( i = 0; i < p_pkt->report.sdes.u_items; i++ )
763 rtcp_SDES_item_t *p_old =
764 p_pkt->report.sdes.pp_items[i];
765 REMOVE_ELEM( p_pkt->report.sdes.pp_items,
766 p_pkt->report.sdes.u_items, i );
767 p_pkt->report.sdes.u_items--;
768 if( p_old->psz_data )
769 free( p_old->psz_data );
777 if( p_pkt->report.app.psz_prefix )
778 free( p_pkt->report.app.psz_prefix );
779 if( p_pkt->report.app.psz_data )
780 free( p_pkt->report.app.psz_data );
783 msg_Err( p_this, "unknown RTCP packet type %d: "
784 "possible leaking of memory.",
785 p_pkt->u_payload_type );
791 block_t *rtcp_encode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
793 rtcp_t *p_rtcp = (rtcp_t *) p_this;
795 bs_t bits, *s = &bits;
796 block_t *p_block = NULL;
797 rtcp_stats_t *p_stats = NULL;
798 rtcp_client_t *p_client = NULL;
802 if( p_pkt->u_payload_type != RTCP_SR )
805 /* FIXME: Maybe this should be a buffer pool instead */
806 p_block = block_New( p_this, p_pkt->u_length );
810 bs_init( s, p_block->p_buffer, p_block->i_buffer );
813 bs_write( s, 2, p_pkt->u_version );
814 bs_write( s, 1, 0 ); /* padding */
815 bs_write( s, 5, p_pkt->u_report );
816 bs_write( s, 8, p_pkt->u_payload_type );
817 bs_write( s, 16, p_pkt->u_length );
818 bs_write( s, 32, p_pkt->u_ssrc );
822 bs_write( s, 32, ((unsigned int)(ntp_time>>32)) ); /* ntp_timestampH */
823 bs_write( s, 32, ((unsigned int)ntp_time) );/* ntp_timestampL */
825 /* FIXME: Make sure to generate a good RTP server timestamp.
826 p_pkt->report.sr.rtp_timestamp = htonl(
827 (unsigned int) ((double)ntp_time.tv_sec +
828 (double)ntp_time.tv_usec/1000000.) * p_mux->rate
829 + session->start_rtptime ); */
830 bs_write( s, 32, p_pkt->report.sr.rtp_timestamp );
831 bs_write( s, 32, p_pkt->report.sr.u_pkt_count );
832 bs_write( s, 32, p_pkt->report.sr.u_octet_count );
835 result = p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos );
836 if( result == VLC_EGENERIC )
838 msg_Err( p_this, "SR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
843 vlc_mutex_lock( &p_rtcp->object_lock );
844 p_client = p_rtcp->pp_clients[i_pos];
846 p_stats = p_client->p_stats;
848 msg_Err( p_this, "SR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
852 bs_write( s, 32, p_stats->l_dest_SSRC );
853 bs_write( s, 8, p_stats->u_fraction_lost );
854 bs_write( s, 24, p_stats->u_pkt_lost );
855 bs_write( s, 32, p_stats->u_highest_seq_no );
856 bs_write( s, 32, p_stats->u_jitter );
857 bs_write( s, 32, p_stats->u_last_SR );
858 bs_write( s, 32, p_stats->u_delay_since_last_SR );
861 vlc_mutex_unlock( &p_rtcp->object_lock );
863 /* possible SR extension */
867 block_t *rtcp_encode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
869 rtcp_t *p_rtcp = (rtcp_t *) p_this;
870 bs_t bits, *s = &bits;
871 block_t *p_block = NULL;
872 rtcp_stats_t *p_stats = NULL;
873 rtcp_client_t *p_client = NULL;
877 if( p_pkt->u_payload_type != RTCP_RR )
880 /* FIXME: Maybe this should be a buffer pool instead */
881 p_block = block_New( p_this, p_pkt->u_length );
885 bs_init( s, p_block->p_buffer, p_block->i_buffer );
888 bs_write( s, 2, p_pkt->u_version );
889 bs_write( s, 1, 0 ); /* padding */
890 bs_write( s, 5, p_pkt->u_report );
891 bs_write( s, 8, p_pkt->u_payload_type );
892 bs_write( s, 16, p_pkt->u_length );
893 bs_write( s, 32, p_pkt->u_ssrc );
896 result = p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos );
897 if( result == VLC_EGENERIC )
899 msg_Err( p_this, "RR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
904 vlc_mutex_lock( &p_rtcp->object_lock );
905 p_client = p_rtcp->pp_clients[i_pos];
907 p_stats = p_client->p_stats;
909 msg_Err( p_this, "RR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
913 bs_write( s, 32, p_stats->l_dest_SSRC );
914 bs_write( s, 8, p_stats->u_fraction_lost );
915 bs_write( s, 24, p_stats->u_pkt_lost );
916 bs_write( s, 32, p_stats->u_highest_seq_no );
917 bs_write( s, 32, p_stats->u_jitter );
918 bs_write( s, 32, p_stats->u_last_RR );
919 bs_write( s, 32, p_stats->u_delay_since_last_RR );
922 vlc_mutex_unlock( &p_rtcp->object_lock );
924 /* possible RR extension */
928 block_t *rtcp_encode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
930 bs_t bits, *s = &bits;
931 block_t *p_block = NULL;
934 if( p_pkt->u_payload_type != RTCP_SDES )
937 /* FIXME: Maybe this should be a buffer pool instead */
938 p_block = block_New( p_this, p_pkt->u_length );
942 bs_init( s, p_block->p_buffer, p_block->i_buffer );
945 bs_write( s, 2, p_pkt->u_version );
946 bs_write( s, 1, 0 ); /* padding */
947 bs_write( s, 5, p_pkt->u_report ); /* Number of SSRC/CSRC chunks */
948 bs_write( s, 8, p_pkt->u_payload_type );
949 bs_write( s, 16, p_pkt->u_length );
950 bs_write( s, 32, p_pkt->u_ssrc );
953 for( i_chunks = 0; i_chunks < p_pkt->u_report; i_chunks++ )
957 for( i_item = 0 ; i_item < p_pkt->report.sdes.u_items; i_item++ )
959 uint32_t i_count = strlen( p_pkt->report.sdes.pp_items[i_item]->psz_data );
960 uint8_t u_octet = i_count / 8; /* Octect count ??*/
961 rtcp_SDES_item_t *p_item = p_pkt->report.sdes.pp_items[i_item];
962 uint32_t i_pos, i_pad, i_padding;
964 bs_write( s, 8, p_item->u_type );
965 bs_write( s, 8, u_octet );
967 for( i_pos = 0; i_pos < i_count; i_pos++ )
969 /* FIXME: must be UTF 8 encoded */
970 bs_write( s, 8, p_item->psz_data[i_pos] );
973 /* do we need padding to 32 bit boundary? */
975 if( ((i_count + 2) % 4) != 0 )
976 i_padding = (i_count + 2) - (((i_count + 2) % 4) << 2);
977 for( i_pad = 0; i_pad < i_padding; i_pad++ )
986 block_t *rtcp_encode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt, char *psz_reason )
988 bs_t bits, *s = &bits;
989 block_t *p_block = NULL;
990 uint32_t i_count = strlen( psz_reason );
991 uint8_t u_octet = i_count / 8; /* Octect count ??*/
992 uint32_t i_pos, i_pad, i_padding;
994 if( p_pkt->u_payload_type != RTCP_BYE )
997 /* FIXME: Maybe this should be a buffer pool instead */
998 p_block = block_New( p_this, p_pkt->u_length );
1002 bs_init( s, p_block->p_buffer, p_block->i_buffer );
1004 /* Fill in header */
1005 bs_write( s, 2, p_pkt->u_version );
1006 bs_write( s, 1, 0 ); /* padding */
1007 bs_write( s, 5, p_pkt->u_report ); /* Number of SSRC/CSRC chunks */
1008 bs_write( s, 8, p_pkt->u_payload_type );
1009 bs_write( s, 16, p_pkt->u_length );
1010 bs_write( s, 32, p_pkt->u_ssrc );
1012 /* Give reason for leaving */
1013 //FIXME: bs_write( s, 8, p_item->u_type );
1014 bs_write( s, 8, u_octet );
1016 for( i_pos = 0; i_pos < i_count; i_pos++ )
1018 /* FIXME: must be UTF 8 encoded */
1019 bs_write( s, 8, psz_reason[i_pos] );
1022 /* do we need padding to 32 bit boundary? */
1024 if( ((i_count + 2) % 4) != 0 )
1025 i_padding = (i_count + 2) - (((i_count + 2) % 4) << 2);
1026 for( i_pad = 0; i_pad < i_padding; i_pad++ )
1028 bs_write( s, 8, 0 );