1 /*****************************************************************************
2 * rtcp.c: RTP/RTCP source file
3 *****************************************************************************
4 * Copyright (C) 2005-2007 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 *****************************************************************************/
25 #include <netinet/in.h>
32 #include <vlc_common.h>
34 #include <vlc_block.h>
39 void send_RTCP( vlc_object_t *p_this, rtcp_event_t );
40 void rtcp_schedule( vlc_object_t *p_this, mtime_t, rtcp_event_t );
42 /* SDES support functions */
43 static int SDES_client_item_add( rtcp_client_t *p_client, int i_item, char *psz_name )
45 rtcp_SDES_item_t *p_item = NULL;
47 p_item = (rtcp_SDES_item_t *) malloc( sizeof( rtcp_SDES_item_t ) );
50 p_item->u_type = i_item;
51 p_item->psz_data = strdup( psz_name );
52 p_item->i_index = p_client->i_items + 1;;
53 INSERT_ELEM( p_client->pp_sdes, p_client->i_items,
54 p_item->i_index, p_item );
58 static int SDES_client_item_del( rtcp_client_t *p_client )
62 for( i=0; i < p_client->i_items; i++ )
64 rtcp_SDES_item_t *p_old = p_client->pp_sdes[i];
65 REMOVE_ELEM( p_client->pp_sdes, p_client->i_items, i );
67 free( p_old->psz_data );
73 int rtcp_add_client( vlc_object_t *p_this, uint32_t u_ssrc, uint32_t *i_pos )
75 rtcp_t *p_rtcp = (rtcp_t *) p_this;
76 rtcp_client_t *p_client = NULL;
78 vlc_object_lock( p_rtcp );
79 p_client = (rtcp_client_t*) malloc( sizeof(rtcp_client_t) );
82 p_client->i_index = p_rtcp->i_clients + 1;
83 p_client->b_deleted = false;
84 *i_pos = p_client->i_index ;
85 INSERT_ELEM( p_rtcp->pp_clients, p_rtcp->i_clients,
86 p_client->i_index, p_client );
89 vlc_object_unlock( p_rtcp );
93 int rtcp_del_client( vlc_object_t *p_this, uint32_t u_ssrc )
95 rtcp_t *p_rtcp = (rtcp_t *) p_this;
98 vlc_object_lock( p_rtcp );
99 if( p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ) == VLC_SUCCESS )
101 rtcp_client_t *p_old = p_rtcp->pp_clients[i_pos];
103 p_old->b_deleted = true;
104 p_old->i_timeout = 5 * (p_rtcp->i_date - p_rtcp->i_last_date) +
107 /* BYE message is sent by rtcp_destroy_client() */
109 vlc_object_unlock( p_rtcp );
113 /* rtcp_cleanup_clients should not be called too often */
114 int rtcp_cleanup_clients( vlc_object_t *p_this )
116 rtcp_t *p_rtcp = (rtcp_t *) p_this;
119 vlc_object_lock( p_rtcp );
120 for( i=0; i < p_rtcp->i_clients; i++ )
122 rtcp_client_t *p_old = p_rtcp->pp_clients[i];
124 if( p_old->b_deleted &&
125 (p_old->i_timeout > mdate()) )
127 REMOVE_ELEM( p_rtcp->pp_clients, p_rtcp->i_clients, i );
129 SDES_client_item_del( p_old );
133 vlc_object_unlock( p_rtcp );
137 /* Close communication with clients and release allocated objects */
138 int rtcp_destroy_clients( vlc_object_t *p_this )
140 rtcp_t *p_rtcp = (rtcp_t *) p_this;
143 for( i=0; i < p_rtcp->i_clients; i++ )
145 rtcp_pkt_t *pkt = NULL;
146 rtcp_client_t *p_old = p_rtcp->pp_clients[i];
148 p_rtcp->pf_del_client( p_this, p_old->u_ssrc );
149 pkt = rtcp_pkt_new( p_this, RTCP_BYE );
152 block_t *p_block = NULL;
153 p_block = rtcp_encode_BYE( p_this, pkt, strdup("server is leaving") );
156 * send_RTCP( p_this, p_block );
161 /* wait till all clients have been signalled */
162 while( p_rtcp->i_clients != 0 )
164 p_rtcp->pf_cleanup_clients( p_this );
170 /* rtcp_find_client should be called with the object lock held.
171 * vlc_mutex_lock( &p_rtcp->obj_lock );
173 int rtcp_find_client( vlc_object_t *p_this, uint32_t u_ssrc, uint32_t *i_pos )
175 rtcp_t *p_rtcp = (rtcp_t *) p_this;
178 for( i=0; i < p_rtcp->i_clients; i++ )
180 if( p_rtcp->pp_clients[i]->u_ssrc == u_ssrc )
190 /*--------------------------------------------------------------------------
191 * rtcp_interval - Calculate the interval in seconds for sending RTCP packets.
192 *--------------------------------------------------------------------------
194 uint64_t rtcp_interval( vlc_object_t *p_this, uint64_t u_bandwidth, uint32_t u_ssrc,
195 bool b_sender, bool b_first )
197 rtcp_t *p_rtcp = (rtcp_t *) p_this;
198 rtcp_client_t *p_client = NULL;
199 uint32_t i_rtcp_min = 5; /* seconds */
201 double i_bandwidth = u_bandwidth;
202 const double i_compensation = 2.71828 - 1.5;
203 double i_interval = 0;
204 int n = p_rtcp->i_clients;
207 i_rtcp_min = (i_rtcp_min >> 1);
209 if( (double)(p_rtcp->u_active) <= (double)(p_rtcp->u_clients * 0.25) )
213 i_bandwidth = i_bandwidth * 0.25;
214 n = p_rtcp->u_active;
218 i_bandwidth = i_bandwidth * ( 1 - 0.25 );
219 n = n - p_rtcp->u_active;
222 /* calculate average time between reports */
223 p_client = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
227 i_interval = p_client->p_stats->u_avg_pkt_size * ( n / i_bandwidth );
228 if( i_interval < i_rtcp_min )
229 i_interval = i_rtcp_min;
230 i_interval = i_interval * ( drand48() + 0.5 );
231 i_interval = (double) (i_interval / i_compensation);
233 return (uint64_t)i_interval;
236 /*--------------------------------------------------------------------------
237 * rtcp_expire - decides to sent an RTCP report or a BYE record
238 *--------------------------------------------------------------------------
240 void rtcp_expire( vlc_object_t *p_this, rtcp_event_t rtcp_event, uint64_t u_bandwidth,
241 uint32_t u_ssrc, bool b_sender, bool *b_first )
243 rtcp_t *p_rtcp = (rtcp_t *) p_this;
244 rtcp_client_t *p_client = NULL;
245 rtcp_stats_t *p_stats = NULL;
246 mtime_t i_interval = 0;
249 p_client = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos );
252 p_stats = (rtcp_stats_t*) p_client->p_stats;
253 i_interval = (mtime_t) rtcp_interval( p_this, u_bandwidth,
254 u_ssrc, b_sender, *b_first );
255 p_rtcp->i_next_date = p_rtcp->i_last_date + i_interval;
260 if( p_rtcp->i_next_date <= p_rtcp->i_date )
261 send_RTCP( p_this, rtcp_event );
263 rtcp_schedule( p_this, p_rtcp->i_next_date, rtcp_event );
267 if( p_rtcp->i_next_date <= p_rtcp->i_date )
269 send_RTCP( p_this, rtcp_event );
271 /* Magic numbers are from RFC 3550 page 92
272 * 1.0/16.0 = 0.0625 and
275 p_stats->u_avg_pkt_size = (uint64_t)
276 ( (double) ( (double)p_stats->u_sent_pkt_size / ((double)0.0625) ) +
277 ( ((double)0.9357) * p_stats->u_avg_pkt_size ) );
280 p_rtcp->i_last_date = p_rtcp->i_date;
281 i_interval = rtcp_interval( p_this, u_bandwidth,
282 u_ssrc, b_sender, *b_first );
283 rtcp_schedule( p_this, p_rtcp->i_next_date + i_interval, rtcp_event );
288 rtcp_schedule( p_this, p_rtcp->i_next_date, rtcp_event );
292 p_rtcp->i_date = p_rtcp->i_next_date;
295 /*--------------------------------------------------------------------------
296 * Local functions prototoypes
297 *--------------------------------------------------------------------------
299 static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt );
300 static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt );
301 static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt );
302 static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt );
303 static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt );
304 static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_pkt_t *p_pkt );
306 /*--------------------------------------------------------------------------
308 *--------------------------------------------------------------------------
310 static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
312 rtcp_t *p_rtcp = (rtcp_t *) p_this;
318 msg_Dbg( p_this, "decoding record: SR" );
320 /* parse sender info */
321 p_pkt->u_payload_type = RTCP_SR;
322 p_pkt->report.sr.ntp_timestampH = bs_read( p_rtcp->bs, 32 );
323 p_pkt->report.sr.ntp_timestampL = bs_read( p_rtcp->bs, 32 );
324 p_pkt->report.sr.rtp_timestamp = bs_read( p_rtcp->bs, 32 );
325 p_pkt->report.sr.u_pkt_count = bs_read( p_rtcp->bs, 32 ); /*sender*/
326 p_pkt->report.sr.u_octet_count = bs_read( p_rtcp->bs, 32 ); /*sender*/
328 /* parse report block */
329 for( i=0; i < p_pkt->u_report; i++ )
331 rtcp_client_t *p_client = NULL;
335 u_ssrc = bs_read( p_rtcp->bs, 32 );
337 if( p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ) == VLC_EGENERIC )
339 if( p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
342 vlc_object_lock( p_rtcp );
343 p_client = p_rtcp->pp_clients[i_pos];
345 p_client->p_stats->u_SR_received++;
346 p_client->p_stats->u_pkt_count++;
347 p_client->p_stats->u_octet_count++;
349 msg_Dbg( p_this, "SR received %d, packet count %d, octect count %d, SSRC count %d",
350 p_client->p_stats->u_SR_received,
351 p_client->p_stats->u_pkt_count,
352 p_client->p_stats->u_octet_count,
355 p_client->p_stats->u_fraction_lost = bs_read( p_rtcp->bs, 8 );
356 p_client->p_stats->u_pkt_lost = bs_read( p_rtcp->bs, 24 );
357 p_client->p_stats->u_highest_seq_no = bs_read( p_rtcp->bs, 32 );
358 p_client->p_stats->u_jitter = bs_read( p_rtcp->bs, 32 );
359 p_client->p_stats->u_last_SR = bs_read( p_rtcp->bs, 32 );
360 p_client->p_stats->u_delay_since_last_SR = (mtime_t) bs_read( p_rtcp->bs, 32 );
362 /* Magic numbers are from RFC 3550 page 92
363 * 1.0/16.0 = 0.0625 and
366 p_client->p_stats->u_avg_pkt_size = (uint64_t)
367 ( (double)((double)p_client->p_stats->u_sent_pkt_size * (double)(0.0625)) +
368 ((double)(0.9375) * p_client->p_stats->u_avg_pkt_size) );
370 msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, "
371 "jitter %d, last SR %d, delay %lld",
372 p_client->p_stats->u_fraction_lost,
373 p_client->p_stats->u_pkt_lost,
374 p_client->p_stats->u_highest_seq_no,
375 p_client->p_stats->u_jitter,
376 p_client->p_stats->u_last_SR,
377 p_client->p_stats->u_delay_since_last_SR );
379 vlc_object_unlock( p_rtcp );
384 static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
386 rtcp_t *p_rtcp = (rtcp_t *) p_this;
392 msg_Dbg( p_this, "decoding record: RR" );
394 for( i=0; i < p_pkt->u_report; i++ )
396 rtcp_client_t *p_client = NULL;
400 u_ssrc = bs_read( p_rtcp->bs, 32 );
402 if( p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ) == VLC_EGENERIC )
404 if( p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
408 vlc_object_lock( p_rtcp );
409 p_client = p_rtcp->pp_clients[i_pos];
411 p_client->p_stats->u_RR_received++;
412 msg_Dbg( p_this, "RR received %d, SSRC %d",
413 p_client->p_stats->u_RR_received, u_ssrc );
415 p_client->p_stats->u_fraction_lost = bs_read( p_rtcp->bs, 8 );
416 p_client->p_stats->u_pkt_lost = bs_read( p_rtcp->bs, 24 );
417 p_client->p_stats->u_highest_seq_no = bs_read( p_rtcp->bs, 32 );
418 p_client->p_stats->u_jitter = bs_read( p_rtcp->bs, 32 );
419 p_client->p_stats->u_last_SR = bs_read( p_rtcp->bs, 32 );
420 p_client->p_stats->u_delay_since_last_SR = (mtime_t) bs_read( p_rtcp->bs, 32 );
422 /* Magic numbers are from RFC 3550 page 92
423 * 1.0/16.0 = 0.0625 and
426 p_client->p_stats->u_avg_pkt_size = (uint64_t)
427 ( (double)((double)p_client->p_stats->u_sent_pkt_size * (double)(0.0625)) +
428 ((double)(0.9375) * p_client->p_stats->u_avg_pkt_size) );
430 msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, "
431 "jitter %d, last SR %d, delay %lld",
432 p_client->p_stats->u_fraction_lost,
433 p_client->p_stats->u_pkt_lost,
434 p_client->p_stats->u_highest_seq_no,
435 p_client->p_stats->u_jitter,
436 p_client->p_stats->u_last_SR,
437 p_client->p_stats->u_delay_since_last_SR );
439 vlc_object_unlock( p_rtcp );
444 static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
446 rtcp_t *p_rtcp = (rtcp_t *) p_this;
452 msg_Dbg( p_this, "decoding record: SDES" );
454 for( i = 0; i < p_pkt->u_report; i++ )
456 rtcp_client_t *p_client = NULL;
460 uint8_t u_length = 0;
463 u_ssrc = bs_read( p_rtcp->bs, 32 );
465 if( p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ) == VLC_EGENERIC )
467 if( p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
471 vlc_object_lock( p_rtcp );
472 p_client = p_rtcp->pp_clients[i_pos];
474 u_item = bs_read( p_rtcp->bs, 8 );
477 case RTCP_SDES_CNAME:
479 case RTCP_SDES_EMAIL:
480 case RTCP_SDES_PHONE:
487 u_length = bs_read( p_rtcp->bs, 8 );
488 for( i = 0 ; i < u_length; i++ )
490 psz_name[i] = bs_read( p_rtcp->bs, 8 );
492 SDES_client_item_add( p_client, u_item, psz_name );
496 case RTCP_SDES_PRIV: /* ignoring these */
498 uint8_t u_prefix_len = 0;
499 uint8_t u_length = 0;
500 char psz_prefix_name[255];
503 u_length = bs_read( p_rtcp->bs, 8 );
504 u_prefix_len = bs_read( p_rtcp->bs, 8 );
505 if( u_prefix_len > 254 )
508 for( i=0 ; i < u_prefix_len; i++ )
510 psz_prefix_name[i] = bs_read( p_rtcp->bs, 8 );
512 psz_prefix_name[255] = '\0';
513 SDES_client_item_add( p_client, u_item, psz_prefix_name );
515 for( i=0 ; i < u_length; i++ )
517 psz_name[i] = bs_read( p_rtcp->bs, 8 );
519 psz_name[255] = '\0';
520 SDES_client_item_add( p_client, u_item, psz_name );
527 /* Magic numbers are from RFC 3550 page 92
528 * 1.0/16.0 = 0.0625 and
531 p_client->p_stats->u_avg_pkt_size = (uint64_t)
532 ( (double)((double)p_client->p_stats->u_sent_pkt_size * (double)(0.0625)) +
533 ((double)(0.9375) * p_client->p_stats->u_avg_pkt_size) );
536 vlc_object_unlock( p_rtcp );
541 static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
543 rtcp_t *p_rtcp = (rtcp_t *) p_this;
545 uint8_t u_length = 0;
551 msg_Dbg( p_this, "decoding record: BYE" );
553 u_ssrc = bs_read( p_rtcp->bs, 32 );
554 p_rtcp->pf_del_client( p_this, u_ssrc );
555 u_length = p_pkt->u_length-1;
556 for( i = 0 ; i < u_length; i++ )
558 u_ssrc = bs_read( p_rtcp->bs, 8 );
559 p_rtcp->pf_del_client( p_this, u_ssrc );
564 static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
566 rtcp_t *p_rtcp = (rtcp_t *) p_this;
567 rtcp_client_t *p_client = NULL;
569 char* psz_data = NULL;
577 msg_Dbg( p_this, "decoding record: APP" );
579 u_ssrc = bs_read( p_rtcp->bs, 32 );
581 if( p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ) == VLC_EGENERIC )
583 if( p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
587 vlc_object_lock( p_rtcp );
588 p_client = p_rtcp->pp_clients[i_pos];
590 for( i = 0 ; i < 4; i++ )
592 psz_name[i] = bs_read( p_rtcp->bs, 8 );
596 p_pkt->u_payload_type = RTCP_APP;
597 p_pkt->report.app.psz_prefix = strdup( psz_name );
598 p_pkt->report.app.u_prefix_len = 4;
599 p_pkt->u_length -= 4;
601 psz_data = (char *) malloc( p_pkt->u_length );
603 vlc_object_unlock( p_rtcp );
607 for( i = 0; i < p_pkt->u_length; i-- )
609 psz_data[i] = bs_read( p_rtcp->bs, 8 );
611 psz_data[p_pkt->u_length] = '\0';
613 p_pkt->report.app.psz_data = strdup( psz_data );
614 p_pkt->report.app.u_length = p_pkt->u_length;
617 vlc_object_unlock( p_rtcp );
619 /* Just ignore this packet */
623 /* Decode RTCP packet
624 * Decode incoming RTCP packet and inspect the records types.
626 int rtcp_pkt_decode( vlc_object_t *p_this, rtcp_pkt_t *p_pkt, block_t *p_block )
628 rtcp_t *p_rtcp = (rtcp_t *) p_this;
630 if( !p_pkt && !p_block )
633 bs_init( p_rtcp->bs, p_block->p_buffer, p_block->i_buffer );
635 p_pkt->u_version = bs_read( p_rtcp->bs, 2 );
636 p_pkt->b_padding = bs_read( p_rtcp->bs, 1 ) ? true : false;
637 p_pkt->u_report = bs_read( p_rtcp->bs, 5 );
638 p_pkt->u_payload_type = bs_read( p_rtcp->bs, 8 );
639 p_pkt->u_length = bs_read( p_rtcp->bs, 16 );
641 if( p_pkt->u_payload_type != RTCP_SDES )
642 p_pkt->u_ssrc = bs_read( p_rtcp->bs, 32 );
644 msg_Dbg( p_this, "New RTCP packet: version %d, padding %s, count %d, "
645 "type %d, length %d, SSRC %d",
647 p_pkt->b_padding ? "true" : "false",
649 p_pkt->u_payload_type,
653 while( !bs_eof( p_rtcp->bs ) )
657 switch( p_pkt->u_payload_type )
660 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
661 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
662 rtcp_decode_SR( p_this, p_pkt );
666 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
667 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
668 rtcp_decode_RR( p_this, p_pkt );
672 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
673 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
674 rtcp_decode_SDES( p_this, p_pkt );
678 rtcp_decode_BYE( p_this, p_pkt );
680 if( p_rtcp->pf_find_sender( p_this, pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
681 p_rtcp->pf_del_sender( p_this, p_pkt->u_ssrc );
683 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
684 p_rtcp->pf_del_client( p_this, p_pkt->u_ssrc );
686 if( p_rtcp->u_active < p_rtcp->u_members )
688 rtcp_event_t event = EVENT_BYE;
690 p_rtcp->i_next_date = p_rtcp->i_date +
691 (mtime_t) ( (p_rtcp->u_active / p_rtcp->u_members) *
692 (p_rtcp->i_next_date - p_rtcp->i_date) );
693 p_rtcp->i_last_date = p_rtcp->i_date -
695 ( (mtime_t)(p_rtcp->u_active / p_rtcp->u_members) *
696 (p_rtcp->i_date - p_rtcp->i_last_date) );
697 /* schedule for next period */
698 rtcp_schedule( VLC_OBJECT(p_rtcp), p_rtcp->i_next_date, event );
699 p_rtcp->u_members = p_rtcp->u_active;
701 else p_rtcp->u_members++;
705 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
706 p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos );
707 rtcp_decode_APP( p_this, p_pkt );
718 * Create RTCP records for reporting to server.
720 rtcp_pkt_t *rtcp_pkt_new( vlc_object_t *p_this, int type )
722 rtcp_pkt_t *p_pkt = NULL;
724 p_pkt = (rtcp_pkt_t *) malloc( sizeof( rtcp_pkt_t ) );
728 memset( p_pkt, 0 , sizeof( rtcp_pkt_t ) );
729 p_pkt->u_version = 2;
730 p_pkt->u_payload_type = type;
731 p_pkt->u_length = RTCP_HEADER_LEN;
736 p_pkt->u_length += sizeof(rtcp_SR_t);
739 p_pkt->u_length += sizeof(rtcp_RR_t);
742 p_pkt->u_length += sizeof(rtcp_SDES_t);
743 if( p_pkt->report.sdes.pp_items )
744 p_pkt->u_length += p_pkt->report.sdes.u_items;
747 p_pkt->u_length += sizeof(rtcp_BYE_t);
750 p_pkt->u_length += sizeof(rtcp_APP_t);
759 void rtcp_pkt_del( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
764 switch( p_pkt->u_payload_type )
770 if( p_pkt->report.sdes.pp_items )
774 for( i = 0; i < p_pkt->report.sdes.u_items; i++ )
776 rtcp_SDES_item_t *p_old =
777 p_pkt->report.sdes.pp_items[i];
778 REMOVE_ELEM( p_pkt->report.sdes.pp_items,
779 p_pkt->report.sdes.u_items, i );
780 p_pkt->report.sdes.u_items--;
781 if( p_old->psz_data )
782 free( p_old->psz_data );
790 if( p_pkt->report.app.psz_prefix )
791 free( p_pkt->report.app.psz_prefix );
792 if( p_pkt->report.app.psz_data )
793 free( p_pkt->report.app.psz_data );
796 msg_Err( p_this, "unknown RTCP packet type %d: "
797 "possible leaking of memory.",
798 p_pkt->u_payload_type );
804 block_t *rtcp_encode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
806 rtcp_t *p_rtcp = (rtcp_t *) p_this;
808 bs_t bits, *s = &bits;
809 block_t *p_block = NULL;
810 rtcp_stats_t *p_stats = NULL;
811 rtcp_client_t *p_client = NULL;
814 if( p_pkt->u_payload_type != RTCP_SR )
817 /* FIXME: Maybe this should be a buffer pool instead */
818 p_block = block_New( p_this, p_pkt->u_length );
822 bs_init( s, p_block->p_buffer, p_block->i_buffer );
825 bs_write( s, 2, p_pkt->u_version );
826 bs_write( s, 1, 0 ); /* padding */
827 bs_write( s, 5, p_pkt->u_report );
828 bs_write( s, 8, p_pkt->u_payload_type );
829 bs_write( s, 16, p_pkt->u_length );
830 bs_write( s, 32, p_pkt->u_ssrc );
834 bs_write( s, 32, ((unsigned int)(ntp_time>>32)) ); /* ntp_timestampH */
835 bs_write( s, 32, ((unsigned int)ntp_time) );/* ntp_timestampL */
837 /* FIXME: Make sure to generate a good RTP server timestamp.
838 p_pkt->report.sr.rtp_timestamp = htonl(
839 (unsigned int) ((double)ntp_time.tv_sec +
840 (double)ntp_time.tv_usec/1000000.) * p_mux->rate
841 + session->start_rtptime ); */
842 bs_write( s, 32, p_pkt->report.sr.rtp_timestamp );
843 bs_write( s, 32, p_pkt->report.sr.u_pkt_count );
844 bs_write( s, 32, p_pkt->report.sr.u_octet_count );
847 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
849 msg_Err( p_this, "SR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
854 vlc_object_lock( p_rtcp );
855 p_client = p_rtcp->pp_clients[i_pos];
857 p_stats = p_client->p_stats;
859 msg_Err( p_this, "SR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
863 bs_write( s, 32, p_stats->l_dest_SSRC );
864 bs_write( s, 8, p_stats->u_fraction_lost );
865 bs_write( s, 24, p_stats->u_pkt_lost );
866 bs_write( s, 32, p_stats->u_highest_seq_no );
867 bs_write( s, 32, p_stats->u_jitter );
868 bs_write( s, 32, p_stats->u_last_SR );
869 bs_write( s, 32, p_stats->u_delay_since_last_SR );
872 vlc_object_unlock( p_rtcp );
874 /* possible SR extension */
878 block_t *rtcp_encode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
880 rtcp_t *p_rtcp = (rtcp_t *) p_this;
881 bs_t bits, *s = &bits;
882 block_t *p_block = NULL;
883 rtcp_stats_t *p_stats = NULL;
884 rtcp_client_t *p_client = NULL;
887 if( p_pkt->u_payload_type != RTCP_RR )
890 /* FIXME: Maybe this should be a buffer pool instead */
891 p_block = block_New( p_this, p_pkt->u_length );
895 bs_init( s, p_block->p_buffer, p_block->i_buffer );
898 bs_write( s, 2, p_pkt->u_version );
899 bs_write( s, 1, 0 ); /* padding */
900 bs_write( s, 5, p_pkt->u_report );
901 bs_write( s, 8, p_pkt->u_payload_type );
902 bs_write( s, 16, p_pkt->u_length );
903 bs_write( s, 32, p_pkt->u_ssrc );
906 if( p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
908 msg_Err( p_this, "RR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
913 vlc_object_lock( p_rtcp );
914 p_client = p_rtcp->pp_clients[i_pos];
916 p_stats = p_client->p_stats;
918 msg_Err( p_this, "RR: SSRC identifier doesn't exists", p_pkt->u_ssrc );
922 bs_write( s, 32, p_stats->l_dest_SSRC );
923 bs_write( s, 8, p_stats->u_fraction_lost );
924 bs_write( s, 24, p_stats->u_pkt_lost );
925 bs_write( s, 32, p_stats->u_highest_seq_no );
926 bs_write( s, 32, p_stats->u_jitter );
927 bs_write( s, 32, p_stats->u_last_RR );
928 bs_write( s, 32, p_stats->u_delay_since_last_RR );
931 vlc_object_unlock( p_rtcp );
933 /* possible RR extension */
937 block_t *rtcp_encode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt )
939 bs_t bits, *s = &bits;
940 block_t *p_block = NULL;
943 if( p_pkt->u_payload_type != RTCP_SDES )
946 /* FIXME: Maybe this should be a buffer pool instead */
947 p_block = block_New( p_this, p_pkt->u_length );
951 bs_init( s, p_block->p_buffer, p_block->i_buffer );
954 bs_write( s, 2, p_pkt->u_version );
955 bs_write( s, 1, 0 ); /* padding */
956 bs_write( s, 5, p_pkt->u_report ); /* Number of SSRC/CSRC chunks */
957 bs_write( s, 8, p_pkt->u_payload_type );
958 bs_write( s, 16, p_pkt->u_length );
959 bs_write( s, 32, p_pkt->u_ssrc );
962 for( i_chunks = 0; i_chunks < p_pkt->u_report; i_chunks++ )
966 for( i_item = 0 ; i_item < p_pkt->report.sdes.u_items; i_item++ )
968 uint32_t i_count = strlen( p_pkt->report.sdes.pp_items[i_item]->psz_data );
969 uint8_t u_octet = i_count / 8; /* Octect count ??*/
970 rtcp_SDES_item_t *p_item = p_pkt->report.sdes.pp_items[i_item];
971 uint32_t i_pos, i_pad, i_padding;
973 bs_write( s, 8, p_item->u_type );
974 bs_write( s, 8, u_octet );
976 for( i_pos = 0; i_pos < i_count; i_pos++ )
978 /* FIXME: must be UTF 8 encoded */
979 bs_write( s, 8, p_item->psz_data[i_pos] );
982 /* do we need padding to 32 bit boundary? */
984 if( ((i_count + 2) % 4) != 0 )
985 i_padding = (i_count + 2) - (((i_count + 2) % 4) << 2);
986 for( i_pad = 0; i_pad < i_padding; i_pad++ )
995 block_t *rtcp_encode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt, char *psz_reason )
997 bs_t bits, *s = &bits;
998 block_t *p_block = NULL;
999 uint32_t i_count = strlen( psz_reason );
1000 uint8_t u_octet = i_count / 8; /* Octect count ??*/
1001 int32_t i_pos, i_pad, i_padding;
1003 if( p_pkt->u_payload_type != RTCP_BYE )
1006 /* FIXME: Maybe this should be a buffer pool instead */
1007 p_block = block_New( p_this, p_pkt->u_length );
1011 bs_init( s, p_block->p_buffer, p_block->i_buffer );
1013 /* Fill in header */
1014 bs_write( s, 2, p_pkt->u_version );
1015 bs_write( s, 1, 0 ); /* padding */
1016 bs_write( s, 5, p_pkt->u_report ); /* Number of SSRC/CSRC chunks */
1017 bs_write( s, 8, p_pkt->u_payload_type );
1018 bs_write( s, 16, p_pkt->u_length );
1019 bs_write( s, 32, p_pkt->u_ssrc );
1021 /* Give reason for leaving */
1022 //FIXME: bs_write( s, 8, p_item->u_type );
1023 bs_write( s, 8, u_octet );
1025 for( i_pos = 0; i_pos < i_count; i_pos++ )
1027 /* FIXME: must be UTF 8 encoded */
1028 bs_write( s, 8, psz_reason[i_pos] );
1031 /* do we need padding to 32 bit boundary? */
1033 if( ((i_count + 2) % 4) != 0 )
1034 i_padding = (i_count + 2) - (((i_count + 2) % 4) << 2);
1035 for( i_pad = 0; i_pad < i_padding; i_pad++ )
1037 bs_write( s, 8, 0 );