Changeset 4d243c1d7853c7021befe5edd0ac4e051193ae8a

Show
Ignore:
Timestamp:
21/11/06 11:46:12 (2 years ago)
Author:
Jean-Paul Saman <jpsaman@videolan.org>
git-committer:
Jean-Paul Saman <jpsaman@videolan.org> 1164105972 +0000
git-parent:

[cec120d523341b08cdc3cba2674fb014f9e99a49]

git-author:
Jean-Paul Saman <jpsaman@videolan.org> 1164105972 +0000
Message:

Rewrote internal RTCP to support multiple client connections. TODO: rtcp scheduling function, server socket, hooking it up with RTP stream_out connections.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • configure.ac

    r8d7b588 r4d243c1  
    14491449  VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display stream_out_transcode stream_out_bridge stream_out_mosaic_bridge stream_out_autodel]) 
    14501450#  VLC_ADD_PLUGINS([stream_out_transrate]) 
     1451  VLC_ADD_PLUGINS([rtcp]) 
    14511452  VLC_ADD_PLUGINS([profile_parser]) 
    14521453 
  • modules/mux/rtp/Modules.am

    r4f617c5 r4d243c1  
    1 SOURCES_rtcp =     rtcp.c rtcp.h rtp.h 
     1SOURCES_rtcp = rtcp.c rtcp.h rtp.h 
  • modules/mux/rtp/rtcp.c

    re2afd14 r4d243c1  
    2323 *****************************************************************************/ 
    2424 
     25#include <stdlib.h> 
    2526#include <netinet/in.h> 
    26 #include <sys/time.h> 
    2727#include <sys/time.h> 
    2828 
     
    3434#include "rtcp.h" 
    3535 
    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; 
     36static 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 
     41static 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 */ 
     47static 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 
     62static 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 
     78int 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 
     98int 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 */ 
     118int 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 */ 
     144int 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 */ 
     165uint64_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 */ 
     213void 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 */ 
     274static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); 
     275static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); 
     276static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); 
     277static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); 
     278static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); 
     279static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ); 
     280 
     281/*-------------------------------------------------------------------------- 
     282 * Local functions 
     283 *-------------------------------------------------------------------------- 
     284 */ 
     285static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ) 
     286
     287    rtcp_t *p_rtcp = (rtcp_t *) p_this; 
    51288    unsigned int i = 0; 
    52289 
    53     if( !p_rtcp && !p_buffer
     290    if( !p_pkt
    54291        return VLC_EGENERIC; 
    55292 
    56293    msg_Dbg( p_this, "decoding record: SR" ); 
    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 ); 
    93358    } 
    94359    return VLC_SUCCESS; 
    95360} 
    96361 
    97 static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer
    98 { 
    99     unsigned int u_ssrc_count
     362static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt
     363{ 
     364    rtcp_t *p_rtcp = (rtcp_t *) p_this
    100365    unsigned int i = 0; 
    101366 
    102     if( !p_rtcp && !p_buffer
     367    if( !p_pkt
    103368        return VLC_EGENERIC; 
    104369 
    105370    msg_Dbg( p_this, "decoding record: RR" ); 
    106371 
    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 ); 
    137421    } 
    138422    return VLC_SUCCESS; 
    139423} 
    140424 
    141 static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ) 
    142 
    143     if( !p_rtcp && !p_buffer ) 
     425static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ) 
     426
     427    rtcp_t *p_rtcp = (rtcp_t *) p_this; 
     428    unsigned int i = 0; 
     429 
     430    if( !p_pkt ) 
    144431        return VLC_EGENERIC; 
    145432 
    146433    msg_Dbg( p_this, "decoding record: SDES" ); 
    147434 
    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 ); 
    163521    } 
    164522    return VLC_SUCCESS; 
    165523} 
    166524 
    167 static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ) 
    168 
    169     if( !p_rtcp && !p_buffer ) 
     525static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ) 
     526
     527    rtcp_t    *p_rtcp = (rtcp_t *) p_this; 
     528    uint32_t  u_ssrc = 0; 
     529    uint8_t   u_length = 0; 
     530    int       i = 0; 
     531 
     532    if( !p_pkt ) 
    170533        return VLC_EGENERIC; 
    171534 
    172535    msg_Dbg( p_this, "decoding record: BYE" ); 
     536 
     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++ ) 
     541    { 
     542        u_ssrc = bs_read( p_rtcp->bs, 8 ); 
     543        p_rtcp->pf_del_client( p_this, u_ssrc ); 
     544    } 
    173545    return VLC_SUCCESS; 
    174546} 
    175547 
    176 static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ) 
    177 
    178     if( !p_rtcp && !p_buffer ) 
     548static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ) 
     549
     550    rtcp_t        *p_rtcp = (rtcp_t *) p_this; 
     551    rtcp_client_t *p_client = NULL; 
     552    char  psz_name[4]; 
     553    char* psz_data = NULL; 
     554    uint32_t u_ssrc = 0; 
     555    uint32_t i_pos = 0; 
     556    uint32_t i = 0; 
     557    int   result = 0; 
     558 
     559    if( !p_pkt ) 
    179560        return VLC_EGENERIC; 
    180561 
    181562    msg_Dbg( p_this, "decoding record: APP" ); 
     563 
     564    u_ssrc = bs_read( p_rtcp->bs, 32 ); 
     565 
     566    result = p_rtcp->pf_find_client( p_this, u_ssrc, &i_pos ); 
     567    if( result == VLC_EGENERIC ) 
     568    { 
     569        result = p_rtcp->pf_add_client( p_this, p_pkt->u_ssrc, &i_pos ); 
     570        if( result == VLC_EGENERIC ) 
     571            return VLC_ENOMEM; 
     572    } 
     573 
     574    vlc_mutex_lock( &p_rtcp->object_lock ); 
     575    p_client = p_rtcp->pp_clients[i_pos]; 
     576 
     577    for( i = 0 ; i < 4; i++ ) 
     578    { 
     579        psz_name[i] = bs_read( p_rtcp->bs, 8 ); 
     580    } 
     581    psz_name[4] = '\0'; 
     582     
     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; 
     587 
     588    psz_data = (char *) malloc( p_pkt->u_length ); 
     589    if( !psz_data ) { 
     590        vlc_mutex_unlock( &p_rtcp->object_lock ); 
     591        return VLC_EGENERIC; 
     592    } 
     593 
     594    for( i = 0; i < p_pkt->u_length; i-- ) 
     595    { 
     596        psz_data[i] = bs_read( p_rtcp->bs, 8 ); 
     597    } 
     598    psz_data[p_pkt->u_length] = '\0'; 
     599 
     600    p_pkt->report.app.psz_data = strdup( psz_data ); 
     601    p_pkt->report.app.u_length = p_pkt->u_length; 
     602 
     603    p_client = NULL; 
     604    vlc_mutex_unlock( &p_rtcp->object_lock ); 
     605 
    182606    /* Just ignore this packet */ 
    183607    return VLC_SUCCESS; 
     
    187611 * Decode incoming RTCP packet and inspect the records types. 
    188612 */ 
    189 int rtcp_decode( vlc_object_t *p_this, rtcp_t *p_rtcp, block_t *p_block ) 
    190 
    191     uint8_t *p_buffer = NULL; 
    192     unsigned int i_length = 0; 
    193     unsigned int i; 
    194  
    195     if( !p_rtcp && !p_block ) 
     613int rtcp_pkt_decode( vlc_object_t *p_this, rtcp_pkt_t *p_pkt, block_t *p_block ) 
     614
     615    rtcp_t *p_rtcp = (rtcp_t *) p_this; 
     616 
     617    if( !p_pkt && !p_block ) 
    196618        return VLC_EGENERIC; 
    197619 
    198     i_length = p_block->i_buffer; 
    199     p_buffer = p_block->p_buffer; 
    200  
    201     for( i=0; i<i_length; ++i ) 
    202     { 
    203         p_rtcp->u_count = p_buffer[i] & 0xF8; 
    204         p_rtcp->u_version = p_buffer[i] & 0x03; 
    205         p_rtcp->u_payload_type = p_buffer[i+1]; 
    206         p_rtcp->u_length = (p_buffer[i+2]<<8) + p_buffer[i+3]; 
    207         msg_Dbg( p_this, "New RTCP packet: count %d, version %d, type %d, lenght %d", 
    208             p_rtcp->u_count, 
    209             p_rtcp->u_version, 
    210             p_rtcp->u_payload_type, 
    211             p_rtcp->u_length ); 
    212  
    213         switch( p_rtcp->u_payload_type ) 
     620    bs_init( p_rtcp->bs, p_block->p_buffer, p_block->i_buffer ); 
     621 
     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 ); 
     627 
     628    if( p_pkt->u_payload_type != RTCP_SDES ) 
     629        p_pkt->u_ssrc = bs_read( p_rtcp->bs, 32 ); 
     630 
     631    msg_Dbg( p_this, "New RTCP packet: version %d, padding %s, count %d, " 
     632                     "type %d, length %d, SSRC %d", 
     633        p_pkt->u_version, 
     634        p_pkt->b_padding ? "true" : "false", 
     635        p_pkt->u_report, 
     636        p_pkt->u_payload_type, 
     637        p_pkt->u_length, 
     638        p_pkt->u_ssrc ); 
     639 
     640    while( !bs_eof( p_rtcp->bs ) ) 
     641    { 
     642        uint32_t i_pos = 0; 
     643         
     644        switch( p_pkt->u_payload_type ) 
    214645        { 
    215646            case RTCP_SR: 
    216                 rtcp_decode_SR( p_this, p_rtcp, p_buffer ); 
     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 ); 
    217650                break; 
     651 
    218652            case RTCP_RR: 
    219                 rtcp_decode_RR( p_this, p_rtcp, p_buffer ); 
     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 ); 
    220656                break; 
     657 
    221658            case RTCP_SDES: 
    222                 rtcp_decode_SDES( p_this, p_rtcp, p_buffer ); 
     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 ); 
    223662                break; 
     663 
    224664            case RTCP_BYE: 
    225                 rtcp_decode_BYE( p_this, p_rtcp, p_buffer ); 
     665                rtcp_decode_BYE( p_this, p_pkt ); 
     666#if 0 
     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 ); 
     669#endif 
     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 ); 
     672 
     673                if( p_rtcp->u_active < p_rtcp->u_members ) 
     674                { 
     675                    rtcp_event_t event = EVENT_BYE; 
     676                     
     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 - 
     681                                        (mtime_t) 
     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; 
     687                } 
     688                else p_rtcp->u_members++; 
    226689                break; 
     690 
    227691            case RTCP_APP: 
    228                 rtcp_decode_APP( p_this, p_rtcp, p_buffer ); 
     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 ); 
    229695                break; 
     696 
    230697            default: 
    231698                return VLC_EGENERIC; 
     
    238705 * Create RTCP records for reporting to server. 
    239706 */ 
    240 block_t *rtcp_encode( vlc_object_t *p_this, int type ) 
    241 { 
    242     rtcp_t  *p_rtcp = NULL; 
    243     block_t *p_block = NULL; 
    244  
    245     p_rtcp = (rtcp_t *) malloc( sizeof( rtcp_t ) ); 
    246     if( !p_rtcp ) 
    247         return NULL; 
    248     memset( p_rtcp, 0 , sizeof( rtcp_t ) ); 
    249     p_rtcp->u_version = 2; 
    250     p_rtcp->u_payload_type = type; 
    251     p_rtcp->u_length = RTCP_HEADER_LEN; 
     707rtcp_pkt_t *rtcp_pkt_new( vlc_object_t *p_this, int type ) 
     708{ 
     709    rtcp_pkt_t *p_pkt = NULL; 
     710 
     711    p_pkt = (rtcp_pkt_t *) malloc( sizeof( rtcp_pkt_t ) ); 
     712    if( !p_pkt ) 
     713        return NULL; 
     714 
     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; 
    252719 
    253720    switch( type ) 
    254721    { 
    255         case RTCP_SR: p_rtcp->u_length += sizeof(rtcp_SR); break; 
    256         case RTCP_RR: p_rtcp->u_length += sizeof(rtcp_RR); break; 
     722        case RTCP_SR: 
     723            p_pkt->u_length += sizeof(rtcp_SR_t); 
     724            break; 
     725        case RTCP_RR: 
     726            p_pkt->u_length += sizeof(rtcp_RR_t); 
     727            break; 
    257728        case RTCP_SDES: 
    258             p_rtcp->u_length += sizeof(rtcp_SDES) + strlen(p_rtcp->report.sdes.p_data); 
    259             break; 
    260         case RTCP_BYE:  p_rtcp->u_length += sizeof(rtcp_BYE);  break; 
    261         case RTCP_APP:  /* ignore: p_rtcp->u_length += sizeof(rtcp_APP); */ break; 
    262     } 
    263  
    264     /* FIXME: Maybe this should be a buffer pool instead */ 
    265     p_block = block_New( p_this, p_rtcp->u_length ); 
    266     return p_block; 
    267 
    268  
    269 static block_t *rtcp_encode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp ) 
    270 
     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; 
     732            break; 
     733        case RTCP_BYE: 
     734            p_pkt->u_length += sizeof(rtcp_BYE_t); 
     735            break; 
     736        case RTCP_APP: 
     737            p_pkt->u_length += sizeof(rtcp_APP_t); 
     738            break; 
     739        default: 
     740            free(p_pkt); 
     741            return NULL; 
     742    } 
     743    return p_pkt; 
     744
     745 
     746void rtcp_pkt_del( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ) 
     747
     748    if( !p_pkt ) 
     749        return; 
     750 
     751    switch( p_pkt->u_payload_type ) 
     752    { 
     753        case RTCP_SR: 
     754        case RTCP_RR: 
     755            break; 
     756        case RTCP_SDES: 
     757            if( p_pkt->report.sdes.pp_items ) 
     758            { 
     759                uint32_t i = 0; 
     760 
     761                for( i = 0; i < p_pkt->report.sdes.u_items; i++ ) 
     762                { 
     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 ); 
     770                    free( p_old ); 
     771                } 
     772            } 
     773            break; 
     774        case RTCP_BYE: 
     775            break; 
     776        case RTCP_APP: 
     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 ); 
     781            break; 
     782        default: 
     783            msg_Err( p_this, "unknown RTCP packet type %d: " 
     784                             "possible leaking of memory.", 
     785                            p_pkt->u_payload_type ); 
     786            break; 
     787    } 
     788    free( p_pkt ); 
     789
     790 
     791block_t *rtcp_encode_SR( vlc_object_t *p_this, rtcp_pkt_t *p_pkt ) 
     792
     793    rtcp_t *p_rtcp = (rtcp_t *) p_this; 
    271794    mtime_t ntp_time; 
    272795    bs_t bits, *s = &bits; 
    273796    block_t *p_block = NULL; 
     797    rtcp_stats_t *p_stats = NULL; 
     798    rtcp_client_t *p_client = NULL; 
     799    uint32_t i_pos = 0; 
     800    int result = 0; 
     801 
     802    if( p_pkt->u_payload_type != RTCP_SR ) 
     803        return NULL; 
    274804 
    275805    /* FIXME: Maybe this should be a buffer pool instead */ 
    276     p_block = block_New( p_this, p_rtcp->u_length ); 
     806    p_block = block_New( p_this, p_pkt->u_length ); 
    277807    if( !p_block ) 
    278808        return NULL; 
     
    281811 
    282812    /* Fill in header */ 
    283     bs_write( s, 5, p_rtcp->u_count ); 
     813    bs_write( s, 2, p_pkt->u_version ); 
    284814    bs_write( s, 1, 0 ); /* padding */ 
    285     bs_write( s, 2, p_rtcp->u_version ); 
    286     bs_write( s, 8, p_rtcp->u_payload_type ); 
    287     bs_write( s, 16, p_rtcp->u_length ); 
    288  
    289     /* fill in record */ 
    290     bs_write( s, 32, htonl( p_rtcp->report.sr.u_ssrc ) ); 
    291  
     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 ); 
     819 
     820    /* sender info */ 
    292821    ntp_time = mdate(); 
    293     bs_write( s, 32, htonl( ((unsigned int)(ntp_time>>32)) ) ); /* ntp_timestampH */ 
    294     bs_write( s, 32, htonl( ((unsigned int)ntp_time)) );/* ntp_timestampL */ 
     822    bs_write( s, 32, ((unsigned int)(ntp_time>>32)) ); /* ntp_timestampH */ 
     823    bs_write( s, 32, ((unsigned int)ntp_time) );/* ntp_timestampL */ 
    295824 
    296825    /* FIXME: Make sure to generate a good RTP server timestamp. 
    297         p_rtcp->report.sr.rtp_timestamp = htonl( 
     826        p_pkt->report.sr.rtp_timestamp = htonl( 
    298827        (unsigned int) ((double)ntp_time.tv_sec + 
    299828        (double)ntp_time.tv_usec/1000000.) * p_mux->rate 
    300829        + session->start_rtptime ); */ 
    301     bs_write( s, 32, htonl( p_rtcp->report.sr.rtp_timestamp ) ); 
    302     bs_write( s, 32, htonl( p_rtcp->report.sr.u_pkt_count ) ); 
    303     bs_write( s, 32, htonl( p_rtcp->report.sr.u_octet_count ) ); 
    304  
     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 ); 
     833 
     834    /* report block */ 
     835    result = p_rtcp->pf_find_client( p_this, p_pkt->u_ssrc, &i_pos ); 
     836    if( result == VLC_EGENERIC ) 
     837    { 
     838        msg_Err( p_this, "SR: SSRC identifier doesn't exists", p_pkt->u_ssrc ); 
     839        free( p_block ); 
     840        return NULL; 
     841    } 
     842 
     843    vlc_mutex_lock( &p_rtcp->object_lock ); 
     844    p_client = p_rtcp->pp_clients[i_pos]; 
     845 
     846    p_stats = p_client->p_stats; 
     847    if( !p_stats ) { 
     848        msg_Err( p_this, "SR: SSRC identifier doesn't exists", p_pkt->u_ssrc ); 
     849        free( p_block ); <