LCOV - code coverage report
Current view: top level - ietf - rtcp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 150 191 78.5 %
Date: 2021-04-29 23:48:07 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / IETF RTP/RTSP/SDP sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC 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 Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : #include <gpac/internal/ietf_dev.h>
      28             : 
      29             : #ifndef GPAC_DISABLE_STREAMING
      30             : 
      31             : #include <gpac/bitstream.h>
      32             : 
      33             : GF_EXPORT
      34          31 : u32 gf_rtp_read_rtcp(GF_RTPChannel *ch, u8 *buffer, u32 buffer_size)
      35             : {
      36             :         GF_Err e;
      37             :         u32 res;
      38             : 
      39             :         //only if the socket exist (otherwise RTSP interleaved channel)
      40          31 :         if (!ch || !ch->rtcp) return 0;
      41          31 :         if (ch->no_select) {
      42           0 :                 e = gf_sk_receive_no_select(ch->rtcp, buffer, buffer_size, &res);
      43             :         } else {
      44          31 :                 e = gf_sk_receive(ch->rtcp, buffer, buffer_size, &res);
      45             :         }
      46          31 :         if (e) return 0;
      47          31 :         return res;
      48             : }
      49             : 
      50             : GF_EXPORT
      51          31 : GF_Err gf_rtp_decode_rtcp(GF_RTPChannel *ch, u8 *pck, u32 pck_size, Bool *has_sr)
      52             : {
      53             :         GF_RTCPHeader rtcp_hdr;
      54             :         char sdes_buffer[300];
      55             :         u32 i, sender_ssrc, cur_ssrc, val, sdes_type, sdes_len, res, first;
      56             :         GF_Err e = GF_OK;
      57             : 
      58          31 :         if (has_sr) *has_sr = GF_FALSE;
      59             : 
      60             :         //bad RTCP packet
      61          31 :         if (pck_size < 4 ) return GF_NON_COMPLIANT_BITSTREAM;
      62          31 :         gf_bs_reassign_buffer(ch->bs_r, pck, pck_size);
      63             : 
      64             :         first = 1;
      65         137 :         while (pck_size) {
      66             :                 //global header
      67          75 :                 rtcp_hdr.Version = gf_bs_read_int(ch->bs_r, 2);
      68          75 :                 if (rtcp_hdr.Version != 2 ) {
      69             :                         return GF_NOT_SUPPORTED;
      70             :                 }
      71          75 :                 rtcp_hdr.Padding = gf_bs_read_int(ch->bs_r, 1);
      72          75 :                 rtcp_hdr.Count = gf_bs_read_int(ch->bs_r, 5);
      73          75 :                 rtcp_hdr.PayloadType = gf_bs_read_u8(ch->bs_r);
      74          75 :                 rtcp_hdr.Length = 1 + gf_bs_read_u16(ch->bs_r);
      75             : 
      76             :                 //check pck size
      77          75 :                 if (pck_size < (u32) rtcp_hdr.Length * 4) {
      78             :                         //we return OK
      79             :                         return GF_CORRUPTED_DATA;
      80             :                 }
      81             :                 //subtract this RTCP pck size
      82          75 :                 pck_size -= rtcp_hdr.Length * 4;
      83             : 
      84             :                 /*we read the RTCP header*/
      85             :                 rtcp_hdr.Length -= 1;
      86             : 
      87             :                 //in all RTCP Compounds (>1 pck), the first RTCP report SHALL be SR or RR without padding
      88          75 :                 if (first) {
      89          31 :                         if ( ( (rtcp_hdr.PayloadType!=200) && (rtcp_hdr.PayloadType!=201) )
      90          31 :                                 || rtcp_hdr.Padding
      91             :                            ) {
      92           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTCP] Corrupted RTCP packet: payload type %d (200 or 201 expected) - Padding %d (0 expected)\n", rtcp_hdr.PayloadType, rtcp_hdr.Padding));
      93             :                                 return GF_CORRUPTED_DATA;
      94             :                         }
      95             :                         first = 0;
      96             :                 }
      97             : 
      98             :                 //specific extensions
      99          75 :                 switch (rtcp_hdr.PayloadType) {
     100             :                 //Sender report - we assume there's only one sender
     101          31 :                 case 200:
     102             :                         /*sender ssrc*/
     103          31 :                         sender_ssrc = gf_bs_read_u32(ch->bs_r);
     104          31 :                         rtcp_hdr.Length -= 1;
     105             :                         /*not for us...*/
     106          31 :                         if (ch->SenderSSRC && (ch->SenderSSRC != sender_ssrc)) break;
     107             : 
     108          31 :                         if (ch->first_SR) {
     109          18 :                                 gf_rtp_get_next_report_time(ch);
     110          18 :                                 ch->SenderSSRC = sender_ssrc;
     111             :                         }
     112          31 :                         ch->last_report_time = gf_rtp_get_report_time();
     113             : 
     114          31 :                         ch->last_SR_NTP_sec = gf_bs_read_u32(ch->bs_r);
     115          31 :                         ch->last_SR_NTP_frac = gf_bs_read_u32(ch->bs_r);
     116          31 :                         ch->last_SR_rtp_time = gf_bs_read_u32(ch->bs_r);
     117          31 :                         /*nb_pck =  */gf_bs_read_u32(ch->bs_r);
     118          31 :                         /*nb_bytes =*/gf_bs_read_u32(ch->bs_r);
     119             : 
     120          31 :                         rtcp_hdr.Length -= 5;
     121          31 :                         if (has_sr) *has_sr = GF_TRUE;
     122             : 
     123             : #ifndef GPAC_DISABLE_LOG
     124          31 :                         if (gf_log_tool_level_on(GF_LOG_RTP, GF_LOG_INFO))  {
     125             : #ifndef _WIN32_WCE
     126           0 :                                 time_t gtime = ch->last_SR_NTP_sec - GF_NTP_SEC_1900_TO_1970;
     127           0 :                                 const char *ascTime = asctime(gf_gmtime(&gtime));
     128             : #else
     129             :                                 const char *ascTime = "Not Available";
     130             : #endif
     131           0 :                                 GF_LOG(ch->first_SR ? GF_LOG_INFO : GF_LOG_DEBUG, GF_LOG_RTP, ("[RTP] RTCP %sSR: SSRC %d - RTP Time %u - Nb Pck %d - Nb Bytes %d - Time %s\n",
     132             :                                                                                            ch->first_SR ? "Initial " : "",
     133             :                                                                  ch->SenderSSRC,
     134             :                                                                  ch->last_SR_rtp_time,
     135             :                                                                  ch->total_pck,
     136             :                                                                  ch->total_bytes,
     137             :                                                                  ascTime
     138             :                                                                 ));
     139             :                         }
     140             : #endif
     141             : 
     142          31 :                         ch->first_SR = 0;
     143             : 
     144             :                         //common encoding for SR and RR
     145          31 :                         goto process_reports;
     146             : 
     147             : 
     148           0 :                 case 201:
     149             :                         //sender ssrc
     150           0 :                         /*sender_ssrc = */gf_bs_read_u32(ch->bs_r);
     151           0 :                         rtcp_hdr.Length -= 1;
     152             : 
     153          75 : process_reports:
     154             : 
     155             : #if 0
     156             :                         //process all reports - we actually don't since we do not handle sources
     157             :                         //to add
     158             :                         for (i=0; i<rtcp_hdr.Count; i++) {
     159             :                                 //ssrc slot
     160             :                                 cur_ssrc = gf_bs_read_u32(ch->bs_r);
     161             :                                 //frac lost
     162             :                                 gf_bs_read_u8(ch->bs_r);
     163             :                                 //cumulative lost
     164             :                                 gf_bs_read_u24(ch->bs_r);
     165             :                                 //extended seq num
     166             :                                 gf_bs_read_u32(ch->bs_r);
     167             :                                 //jitter
     168             :                                 gf_bs_read_u32(ch->bs_r);
     169             :                                 //LSR
     170             :                                 gf_bs_read_u32(ch->bs_r);
     171             :                                 //DLSR
     172             :                                 gf_bs_read_u32(ch->bs_r);
     173             : 
     174             :                                 rtcp_hdr.Length -= 6;
     175             :                         }
     176             :                         //remaining bytes? we skip (this includes padding and crypto - not supported)
     177             : #endif
     178             :                         break;
     179             : 
     180             :                 //SDES
     181             :                 case 202:
     182          31 :                         for (i=0; i<rtcp_hdr.Count; i++) {
     183          31 :                                 /*cur_ssrc = */gf_bs_read_u32(ch->bs_r);
     184          31 :                                 rtcp_hdr.Length -= 1;
     185             : 
     186             :                                 val = 0;
     187             :                                 while (1) {
     188          93 :                                         sdes_type = gf_bs_read_u8(ch->bs_r);
     189          62 :                                         val += 1;
     190          62 :                                         if (!sdes_type) break;
     191          31 :                                         sdes_len = gf_bs_read_u8(ch->bs_r);
     192          31 :                                         val += 1;
     193          31 :                                         gf_bs_read_data(ch->bs_r, sdes_buffer, sdes_len);
     194          31 :                                         sdes_buffer[sdes_len] = 0;
     195          31 :                                         val += sdes_len;
     196             :                                 }
     197             : 
     198             :                                 //re-align on 32bit
     199          31 :                                 res = val%4;
     200          31 :                                 if (res) {
     201          31 :                                         gf_bs_skip_bytes(ch->bs_r, (4-res));
     202          31 :                                         val = val/4 + 1;
     203             :                                 } else {
     204           0 :                                         val = val/4;
     205             :                                 }
     206          31 :                                 rtcp_hdr.Length -= val;
     207             :                         }
     208             :                         break;
     209             : 
     210             :                 //BYE packet - close the channel - we work with 1 SSRC only */
     211             :                 case 203:
     212           0 :                         for (i=0; i<rtcp_hdr.Count; i++) {
     213          13 :                                 cur_ssrc = gf_bs_read_u32(ch->bs_r);
     214          13 :                                 rtcp_hdr.Length -= 1;
     215          13 :                                 if (ch->SenderSSRC == cur_ssrc) {
     216             :                                         e = GF_EOS;
     217             :                                         break;
     218             :                                 }
     219             :                         }
     220             :                         //extra info - skip it
     221          13 :                         while (rtcp_hdr.Length) {
     222           0 :                                 gf_bs_read_u32(ch->bs_r);
     223           0 :                                 rtcp_hdr.Length -= 1;
     224             :                         }
     225             :                         break;
     226             :                 /*
     227             :                                 //APP packet
     228             :                                 case 204:
     229             : 
     230             : 
     231             :                                         //sender ssrc
     232             :                                         sender_ssrc = gf_bs_read_u32(bs);
     233             :                                         //ASCI 4 char type
     234             :                                         gf_bs_read_u8(bs);
     235             :                                         gf_bs_read_u8(bs);
     236             :                                         gf_bs_read_u8(bs);
     237             :                                         gf_bs_read_u8(bs);
     238             : 
     239             :                                         rtcp_hdr.Length -= 2;
     240             : 
     241             :                                         //till endd of pck
     242             :                                         gf_bs_read_data(bs, sdes_buffer, rtcp_hdr.Length*4);
     243             :                                         rtcp_hdr.Length = 0;
     244             :                                         break;
     245             :                 */
     246           0 :                 default:
     247             :                         //read all till end
     248           0 :                         gf_bs_read_data(ch->bs_r, sdes_buffer, rtcp_hdr.Length*4);
     249             :                         rtcp_hdr.Length = 0;
     250           0 :                         break;
     251             :                 }
     252             :                 //WE SHALL CONSUME EVERYTHING otherwise the packet is bad
     253          75 :                 if (rtcp_hdr.Length) {
     254             :                         return GF_CORRUPTED_DATA;
     255             :                 }
     256             :         }
     257             :         return e;
     258             : }
     259             : 
     260          37 : static u32 RTCP_FormatReport(GF_RTPChannel *ch, GF_BitStream *bs, u32 NTP_Time)
     261             : {
     262             :         u32 length, is_sr, sec, frac, expected, val, size;
     263             :         s32 extended, expect_diff, loss_diff;
     264             :         Double f;
     265             : 
     266          37 :         is_sr = ch->pck_sent_since_last_sr ? 1 : 0;
     267             : 
     268          37 :         if (ch->forced_ntp_sec) {
     269          37 :                 sec = ch->forced_ntp_sec;
     270          37 :                 frac = ch->forced_ntp_frac;
     271             :                 is_sr = 1;
     272             :         } else {
     273           0 :                 gf_net_get_ntp(&sec, &frac);
     274             :         }
     275             : 
     276             :         //common header
     277             :         //version
     278          37 :         gf_bs_write_int(bs, 2, 2);
     279             :         //padding - reports are aligned
     280          37 :         gf_bs_write_int(bs, 0, 1);
     281             :         //count - only one for now in RR, 0 in sender mode
     282          37 :         gf_bs_write_int(bs, !is_sr, 5);
     283             :         //if we have sent stuff send an SR, otherwise an RR. We need to determine whether
     284             :         //we are active or not
     285             :         //type
     286          37 :         gf_bs_write_u8(bs, is_sr ? 200 : 201);
     287             :         //length = (num of 32bit words in full pck) - 1
     288             :         //we're updating only one ssrc for now in RR and none in SR
     289          37 :         length = is_sr ? 6 : (1 + 6 * 1);
     290          37 :         gf_bs_write_u16(bs, length);
     291             : 
     292             :         //sender SSRC
     293          37 :         gf_bs_write_u32(bs, ch->SSRC);
     294             : 
     295             :         size = 8;
     296             : 
     297             : 
     298             :         //SenderReport part
     299          37 :         if (is_sr) {
     300             :                 //sender time
     301          37 :                 gf_bs_write_u32(bs, sec);
     302          37 :                 gf_bs_write_u32(bs, frac);
     303             :                 //RTP time at this time
     304          37 :                 f = 1000 * (sec - ch->last_pck_ntp_sec);
     305          37 :                 f += ((frac - ch->last_pck_ntp_frac) >> 4) / 0x10000;
     306          37 :                 f /= 1000;
     307          37 :                 f *= ch->TimeScale;
     308          37 :                 val = (u32) f + ch->last_pck_ts;
     309          37 :                 gf_bs_write_u32(bs, val);
     310             :                 //num pck sent
     311          37 :                 gf_bs_write_u32(bs, ch->num_pck_sent);
     312             :                 //num payload bytes sent
     313          37 :                 gf_bs_write_u32(bs, ch->num_payload_bytes);
     314             : 
     315             : 
     316             :                 size += 20;
     317             :                 //nota: as we only support single-way channels we are done for SR...
     318          37 :                 return size;
     319             :         }
     320             :         //loop through all our sources (1) and send information...
     321           0 :         gf_bs_write_u32(bs, ch->SenderSSRC);
     322             : 
     323             :         //Fraction lost and cumulative lost
     324           0 :         extended = ( (ch->num_sn_loops << 16) | ch->last_pck_sn);
     325           0 :         expected = extended - ch->rtp_first_SN;
     326           0 :         expect_diff = expected - ch->tot_num_pck_expected;
     327           0 :         loss_diff = expect_diff - ch->last_num_pck_rcv;
     328             : 
     329           0 :         if (!expect_diff || (loss_diff <= 0)) loss_diff = 0;
     330           0 :         else loss_diff = (loss_diff<<8) / expect_diff;
     331             : 
     332           0 :         gf_bs_write_u8(bs, loss_diff);
     333             : 
     334             :         //update and write cumulative loss
     335           0 :         ch->tot_num_pck_rcv += ch->last_num_pck_rcv;
     336           0 :         ch->tot_num_pck_expected = expected;
     337           0 :         gf_bs_write_u24(bs, (expected - ch->tot_num_pck_rcv));
     338             : 
     339             :         //Extend sequence number
     340           0 :         gf_bs_write_u32(bs, extended);
     341             : 
     342             : 
     343             :         //Jitter
     344             :         //RTP specs annexe A.8
     345           0 :         gf_bs_write_u32(bs, ( ch->Jitter >> 4));
     346             :         //LSR
     347           0 :         if (ch->last_SR_NTP_sec) {
     348           0 :                 val = ( ((ch->last_SR_NTP_sec  & 0x0000ffff) << 16) |  ((ch->last_SR_NTP_frac & 0xffff0000) >> 16));
     349             :         } else {
     350             :                 val = 0;
     351             :         }
     352           0 :         gf_bs_write_u32(bs, val);
     353             : 
     354             :         // DLSR
     355           0 :         gf_bs_write_u32(bs, (NTP_Time - ch->last_report_time));
     356             : 
     357             : 
     358             : #ifndef GPAC_DISABLE_LOG
     359           0 :         if (gf_log_tool_level_on(GF_LOG_RTP, GF_LOG_DEBUG))  {
     360             : #ifndef _WIN32_WCE
     361           0 :                 time_t gtime = ch->last_SR_NTP_sec - GF_NTP_SEC_1900_TO_1970;
     362           0 :                 const char *ascTime = asctime(gf_gmtime(&gtime));
     363             : #else
     364             :                 const char *ascTime = "Not Available";
     365             : #endif
     366           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTP] RTCP-RR: SSRC %d Jitter %d extended %d expect_diff %d loss_diff %d time %s\n",
     367             :                                                   ch->SSRC,
     368             :                                                   ch->Jitter >> 4,
     369             :                                                   extended,
     370             :                                                   expect_diff,
     371             :                                                   loss_diff,
     372             :                                                   ascTime
     373             :                                                  ));
     374             :         }
     375             : #endif
     376             : 
     377             :         size += 24;
     378             :         return size;
     379             : }
     380             : 
     381             : 
     382          51 : static u32 RTCP_FormatSDES(GF_RTPChannel *ch, GF_BitStream *bs)
     383             : {
     384             :         u32 length, padd;
     385             : 
     386             :         //we start with header and SSRC: 2x32 bits word
     387             :         length = 8;
     388             :         //ten only send one CName item is type (1byte) , len (1byte), data (len byte) +  NULL marker (0 on 1 byte) at the end of the item list
     389          51 :         length += 2 + (u32) strlen(ch->CName) + 1;
     390             :         //we padd the end of the content to 32-bit boundary, and set length to the number of 32 bit words
     391          51 :         padd = length % 4;
     392          51 :         if (padd*4 != 0) {
     393             :                 //padding octets
     394          51 :                 padd = 4 - padd;
     395          51 :                 length = length/4 + 1;
     396             :         } else {
     397             :                 padd = 0;
     398           0 :                 length = length/4;
     399             :         }
     400             : 
     401             :         //common part as usual
     402          51 :         gf_bs_write_int(bs, 2, 2);
     403             :         //notify padding? according to RFC1889 "In a compound RTCP packet, padding should
     404             :         //only be required on the last individual packet because the compound packet is
     405             :         //encrypted as a whole" -> we write it without notifying it (this is a bit messy in
     406             :         //the spec IMO)
     407          51 :         gf_bs_write_int(bs, 0, 1);
     408             :         //report count is one
     409          51 :         gf_bs_write_int(bs, 1, 5);
     410             :         //SDES pck type
     411          51 :         gf_bs_write_u8(bs, 202);
     412             :         //write length minus one
     413          51 :         gf_bs_write_u16(bs, length - 1);
     414             : 
     415             :         //SSRC
     416          51 :         gf_bs_write_u32(bs, ch->SSRC);
     417             : 
     418             :         //CNAME type
     419          51 :         gf_bs_write_u8(bs, 1);
     420             :         //length and cname
     421          51 :         gf_bs_write_u8(bs, (u32) strlen(ch->CName));
     422          51 :         gf_bs_write_data(bs, ch->CName, (u32) strlen(ch->CName));
     423             : 
     424          51 :         gf_bs_write_u8(bs, 0);
     425             : 
     426             :         //32-align field with 0
     427          51 :         gf_bs_write_int(bs, 0, 8*padd);
     428          51 :         return (length + 1)*4;
     429             : }
     430             : 
     431             : 
     432          30 : static u32 RTCP_FormatBYE(GF_RTPChannel *ch, GF_BitStream *bs)
     433             : {
     434             :         //version
     435          30 :         gf_bs_write_int(bs, 2, 2);
     436             :         //no padding
     437          30 :         gf_bs_write_int(bs, 0, 1);
     438             :         //count - only one for now
     439          30 :         gf_bs_write_int(bs, 1, 5);
     440             :         //type=BYE
     441          30 :         gf_bs_write_u8(bs, 203);
     442             :         //length = (num of 32bit words in full pck) - 1
     443          30 :         gf_bs_write_u16(bs, 1);
     444             : 
     445             :         //sender SSRC
     446          30 :         gf_bs_write_u32(bs, ch->SSRC);
     447          30 :         return 8;
     448             : }
     449             : 
     450             : GF_EXPORT
     451          30 : GF_Err gf_rtp_send_bye(GF_RTPChannel *ch)
     452             : {
     453             :         GF_BitStream *bs;
     454             :         u32 report_size;
     455             :         u8 *report_buf;
     456             :         GF_Err e = GF_OK;
     457             : 
     458          30 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     459             : 
     460             :         /*k were received/sent send the RR/SR - note we don't wait for next Repor and force its emission now*/
     461          30 :         if (ch->last_num_pck_rcv || ch->pck_sent_since_last_sr) {
     462          16 :                 RTCP_FormatReport(ch, bs, gf_rtp_get_report_time());
     463             :         }
     464             : 
     465             :         //always send SDES (CNAME shall be sent at each RTCP)
     466          30 :         RTCP_FormatSDES(ch, bs);
     467             : 
     468             :         //send BYE
     469          30 :         RTCP_FormatBYE(ch, bs);
     470             : 
     471             : 
     472          30 :         report_buf = NULL;
     473          30 :         report_size = 0;
     474          30 :         gf_bs_get_content(bs, &report_buf, &report_size);
     475          30 :         gf_bs_del(bs);
     476             : 
     477          30 :         if (ch->rtcp) {
     478          30 :                 e = gf_sk_send(ch->rtcp, report_buf, report_size);
     479             :         } else {
     480           0 :                 if (ch->send_interleave)
     481           0 :                         e = ch->send_interleave(ch->interleave_cbk1, ch->interleave_cbk2, GF_TRUE, report_buf, report_size);
     482             :                 else
     483             :                         e = GF_BAD_PARAM;
     484             :         }
     485          30 :         gf_free(report_buf);
     486          30 :         return e;
     487             : }
     488             : 
     489             : GF_EXPORT
     490        1632 : GF_Err gf_rtp_send_rtcp_report(GF_RTPChannel *ch)
     491             : {
     492             :         u32 Time, report_size;
     493             :         GF_BitStream *bs;
     494             :         u8 *report_buf;
     495             :         GF_Err e = GF_OK;
     496             :         
     497             : 
     498             :         /*skip first SR when acting as a receiver*/
     499        1632 :         if (!ch->forced_ntp_sec && ch->first_SR) return GF_OK;
     500        1606 :         Time = gf_rtp_get_report_time();
     501        1606 :         if ( Time < ch->next_report_time) return GF_OK;
     502             : 
     503          21 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     504             : 
     505             :         //pck were received/sent send the RR/SR
     506          21 :         if (ch->last_num_pck_rcv || ch->pck_sent_since_last_sr || ch->forced_ntp_sec) {
     507          21 :                 RTCP_FormatReport(ch, bs, Time);
     508             :         }
     509             : 
     510             :         //always send SDES (CNAME shall be sent at each RTCP)
     511          21 :         RTCP_FormatSDES(ch, bs);
     512             : 
     513             : 
     514             :         //get content
     515          21 :         report_buf = NULL;
     516          21 :         report_size = 0;
     517          21 :         gf_bs_get_content(bs, &report_buf, &report_size);
     518          21 :         gf_bs_del(bs);
     519             : 
     520          21 :         if (ch->rtcp) {
     521          20 :                 e = gf_sk_send(ch->rtcp, report_buf, report_size);
     522             :         } else {
     523           1 :                 if (ch->send_interleave)
     524           1 :                         e = ch->send_interleave(ch->interleave_cbk1, ch->interleave_cbk2, GF_TRUE, report_buf, report_size);
     525             :                 else
     526             :                         e = GF_BAD_PARAM;
     527             :         }
     528             : 
     529          21 :         ch->rtcp_bytes_sent += report_size;
     530             : 
     531          21 :         gf_free(report_buf);
     532             : 
     533          21 :         if (!e) {
     534             :                 //Update the channel record if no error - otherwise next RTCP will triger an RR
     535          21 :                 ch->last_num_pck_rcv = ch->last_num_pck_expected = ch->last_num_pck_loss = 0;
     536          21 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTCP] SSRC %d: sending RTCP report\n", ch->SSRC));
     537             :         }
     538             :         else {
     539           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTCP] SSRC %d: error when sending RTCP report\n", ch->SSRC));
     540             :         }
     541          21 :         gf_rtp_get_next_report_time(ch);
     542          21 :         return e;
     543             : }
     544             : 
     545             : #if 0 //unused
     546             : 
     547             : enum
     548             : {
     549             :         GF_RTCP_INFO_NAME = 0,
     550             :         GF_RTCP_INFO_EMAIL,
     551             :         GF_RTCP_INFO_PHONE,
     552             :         GF_RTCP_INFO_LOCATION,
     553             :         GF_RTCP_INFO_TOOL,
     554             :         GF_RTCP_INFO_NOTE,
     555             :         GF_RTCP_INFO_PRIV
     556             : };
     557             : 
     558             : 
     559             : #define RTCP_SAFE_FREE(p) if (p) gf_free(p);    \
     560             :                                         p = NULL;
     561             : 
     562             : GF_Err gf_rtp_set_info_rtcp(GF_RTPChannel *ch, u32 InfoCode, char *info_string)
     563             : {
     564             :         if (!ch) return GF_BAD_PARAM;
     565             : 
     566             :         switch (InfoCode) {
     567             :         case GF_RTCP_INFO_NAME:
     568             :                 RTCP_SAFE_FREE(ch->s_name);
     569             :                 if (info_string) ch->s_name = gf_strdup(info_string);
     570             :                 break;
     571             :         case GF_RTCP_INFO_EMAIL:
     572             :                 RTCP_SAFE_FREE(ch->s_email);
     573             :                 if (info_string) ch->s_email = gf_strdup(info_string);
     574             :                 break;
     575             :         case GF_RTCP_INFO_PHONE:
     576             :                 RTCP_SAFE_FREE(ch->s_phone);
     577             :                 if (info_string) ch->s_phone = gf_strdup(info_string);
     578             :                 break;
     579             :         case GF_RTCP_INFO_LOCATION:
     580             :                 RTCP_SAFE_FREE(ch->s_location);
     581             :                 if (info_string) ch->s_location = gf_strdup(info_string);
     582             :                 break;
     583             :         case GF_RTCP_INFO_TOOL:
     584             :                 RTCP_SAFE_FREE(ch->s_tool);
     585             :                 if (info_string) ch->s_tool = gf_strdup(info_string);
     586             :                 break;
     587             :         case GF_RTCP_INFO_NOTE:
     588             :                 RTCP_SAFE_FREE(ch->s_note);
     589             :                 if (info_string) ch->s_note = gf_strdup(info_string);
     590             :                 break;
     591             :         case GF_RTCP_INFO_PRIV:
     592             :                 RTCP_SAFE_FREE(ch->s_priv);
     593             :                 if (info_string) ch->s_name = gf_strdup(info_string);
     594             :                 break;
     595             :         default:
     596             :                 return GF_BAD_PARAM;
     597             :         }
     598             :         return GF_OK;
     599             : }
     600             : 
     601             : #endif
     602             : 
     603             : 
     604             : #endif /*GPAC_DISABLE_STREAMING*/

Generated by: LCOV version 1.13