rtcp_report.c

Go to the documentation of this file.
00001 /* * 
00002  * This file is part of libnemesi
00003  *
00004  * Copyright (C) 2007 by LScube team <team@streaming.polito.it>
00005  * See AUTHORS for more details
00006  * 
00007  * libnemesi is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * libnemesi is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with libnemesi; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  *  
00021  * */
00022 
00028 #include "rtcp.h"
00029 #include "comm.h"
00030 #include "utils.h"
00031 
00038 int rtcp_build_rr(rtp_session * rtp_sess, rtcp_pkt * pkt)
00039 {
00040     struct timeval now, offset;
00041     uint32_t linear;
00042     rtp_ssrc *stm_src;
00043     rtcp_rr_t *rr;
00044     uint32_t expected, expected_interval, received_interval, lost_interval;
00045     int32_t lost;
00046 
00047     rr = pkt->r.rr.rr;
00048     pkt->common.len = 0;
00049 
00050     for (stm_src = rtp_sess->ssrc_queue; stm_src; stm_src = stm_src->next) {
00051         if ((pkt->common.len * 4 + 2) > (MAX_PKT_SIZE - 4 * 6))
00052             /* No space left in UDP pkt */
00053             break;
00054         if (stm_src->ssrc_stats.received_prior !=
00055             stm_src->ssrc_stats.received) {
00056             pkt->common.count++;
00057             rr->ssrc = htonl(stm_src->ssrc);
00058 
00059             expected =
00060                 stm_src->ssrc_stats.cycles +
00061                 stm_src->ssrc_stats.max_seq -
00062                 stm_src->ssrc_stats.base_seq + 1;
00063             expected_interval =
00064                 expected - stm_src->ssrc_stats.expected_prior;
00065             stm_src->ssrc_stats.expected_prior = expected;
00066             received_interval =
00067                 stm_src->ssrc_stats.received -
00068                 stm_src->ssrc_stats.received_prior;
00069             stm_src->ssrc_stats.received_prior =
00070                 stm_src->ssrc_stats.received;
00071             lost_interval = expected_interval - received_interval;
00072 
00073             if ((expected_interval == 0) || (lost_interval <= 0))
00074                 rr->fraction = 0;
00075             else
00076                 rr->fraction =
00077                     (uint8_t) ((lost_interval << 8) /
00078                          expected_interval);
00079 
00080             lost = min((int32_t)
00081                    (expected - stm_src->ssrc_stats.received -
00082                     1), 0x7fffff);
00083             lost = max(lost, -(1 << 23));
00084             rr->lost = ((lost&0xff) << 16)  |
00085                         (lost&0xff00)       |
00086                         ((lost&0xff0000)>>16);
00087 
00088             rr->last_seq =
00089                 htonl(stm_src->ssrc_stats.cycles +
00090                   stm_src->ssrc_stats.max_seq);
00091             rr->jitter =
00092                 htonl((uint32_t) stm_src->ssrc_stats.jitter);
00093             rr->last_sr =
00094                 htonl(((stm_src->ssrc_stats.
00095                     ntplastsr[0] & 0x0000ffff) << 16) |
00096                   ((stm_src->ssrc_stats.
00097                     ntplastsr[1] & 0xffff0000)
00098                    >> 16));
00099 
00100             gettimeofday(&now, NULL);
00101             nms_timeval_subtract(&offset, &now,
00102                      &(stm_src->ssrc_stats.lastsr));
00103             linear =
00104                 (offset.tv_sec +
00105                  (float) offset.tv_usec / 1000000) * (1 << 16);
00106             rr->dlsr =
00107                 ((stm_src->ssrc_stats.lastsr.tv_sec !=
00108                   0) ? htonl(linear) : 0);
00109 
00110             rr++;
00111         }
00112     }
00113 
00114     pkt->common.ver = RTP_VERSION;
00115     pkt->common.pad = 0;
00116     pkt->common.pt = RTCP_RR;
00117     pkt->common.len = htons(pkt->common.count * 6 + 1);
00118     pkt->r.rr.ssrc = htonl(rtp_sess->local_ssrc);
00119 
00120     return (pkt->common.count * 6 + 2);
00121 }
00122 
00128 int rtcp_send_rr(rtp_session * rtp_sess)
00129 {
00130     rtcp_pkt *pkt;
00131     int len;
00132     uint32_t rr_buff[MAX_PKT_SIZE];
00133     rtp_ssrc *stm_src;
00134 
00135     memset(rr_buff, 0, MAX_PKT_SIZE * sizeof(uint32_t));
00136     pkt = (rtcp_pkt *) rr_buff;
00137 
00138     len = rtcp_build_rr(rtp_sess, pkt);    /* in 32 bit words */
00139     pkt = (rtcp_pkt *) (rr_buff + len);
00140     len += rtcp_build_sdes(rtp_sess, pkt, (MAX_PKT_SIZE >> 2) - len);    /* in 32 bit words */
00141 
00142     for (stm_src = rtp_sess->ssrc_queue; stm_src; stm_src = stm_src->next)
00143         if ( !(stm_src->no_rtcp) && stm_src->rtp_sess->transport.RTCP.sock.fd > 0) {
00144             switch(stm_src->rtp_sess->transport.type) {
00145             case UDP:
00146                 if (sendto(stm_src->rtp_sess->transport.RTCP.sock.fd,
00147                        rr_buff, (len << 2), 0, stm_src->rtcp_from.addr,
00148                        stm_src->rtcp_from.addr_len) < 0)
00149                     nms_printf(NMSML_WARN,
00150                            "WARNING! Error while sending UDP RTCP pkt\n");
00151                 else
00152                     nms_printf(NMSML_DBG3,
00153                            "RTCP RR packet sent\n");
00154                 break;
00155             case SCTP:
00156             case TCP:
00157                 if (send(stm_src->rtp_sess->transport.RTCP.sock.fd,
00158                        rr_buff, (len << 2), 0) < 0)
00159                     nms_printf(NMSML_WARN,
00160                            "WARNING! Error while sending local RTCP pkt\n");
00161                 else
00162                     nms_printf(NMSML_DBG3,
00163                            "RTCP RR packet sent\n");
00164                 break;
00165             default:
00166                 nms_printf(NMSML_WARN, "Unsupported transport type on send_rr\n");
00167                 break;
00168             }
00169         }
00170 
00171     return len;
00172 }
00173 
00177 int rtcp_parse_rr(rtcp_pkt * pkt)
00178 {
00179     // TODO: handle rr packet
00180     nms_printf(NMSML_DBG3, "Received RR from SSRC: %u\n", pkt->r.rr.ssrc);
00181     return 0;
00182 }
00183 
00191 int rtcp_parse_sr(rtp_ssrc * stm_src, rtcp_pkt * pkt)
00192 {
00193     nms_printf(NMSML_DBG3, "Received SR from SSRC: %u\n", pkt->r.sr.ssrc);
00194     gettimeofday(&(stm_src->ssrc_stats.lastsr), NULL);
00195     stm_src->ssrc_stats.ntplastsr[0] = ntohl(pkt->r.sr.si.ntp_seq);
00196     stm_src->ssrc_stats.ntplastsr[1] = ntohl(pkt->r.sr.si.ntp_frac);
00197     /* Per ora, non ci interessa altro. */
00198     /* Forse le altre informazioni possono */
00199     /* servire per un monitor RTP/RTCP */
00200     return 0;
00201 }

Generated on Tue Feb 3 03:10:02 2009 for libnemesi by  doxygen 1.5.4