rtp_recv.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 
00027 #include "rtp.h"
00028 #include "rtpptdefs.h"
00029 #include "bufferpool.h"
00030 
00039 static int rtp_hdr_val_chk(rtp_pkt * pkt, int len)
00040 {
00041     if (RTP_PAYLOAD_SIZE(pkt, len) < 0) {
00042 //      if (len < 12) {
00043         nms_printf(NMSML_ERR,
00044                "RTP packet too small (%d: smaller than RTP header size)!!!\n",
00045                len);
00046         return 1;
00047     }
00048 
00049     if (pkt->ver != RTP_VERSION) {
00050         nms_printf(NMSML_WARN,
00051                "RTP Header not valid: mismatching version number!"
00052                BLANK_LINE);
00053         return 1;
00054     }
00055     if ((pkt->pt >= 200) && (pkt->pt <= 204)) {
00056         nms_printf(NMSML_WARN,
00057                "RTP Header not valid: mismatching payload type!"
00058                BLANK_LINE);
00059         return 1;
00060     }
00061     if ((pkt->pad)
00062         && (*(((uint8_t *) pkt) + len - 1) >
00063         (len - ((uint8_t *) (pkt->data) - (uint8_t *) pkt)))) {
00064         nms_printf(NMSML_WARN,
00065                "RTP Header not valid: mismatching lenght!"
00066                BLANK_LINE);
00067         return 1;
00068     }
00069     if ((pkt->cc)
00070         && (pkt->cc >
00071         (len - ((uint8_t *) (pkt->data) - (uint8_t *) pkt)) -
00072         ((*(((uint8_t *) pkt) + len - 1)) * pkt->pad))) {
00073         nms_printf(NMSML_WARN,
00074                "RTP Header not valid: mismatching CSRC count!"
00075                BLANK_LINE);
00076         return 1;
00077     }
00078 
00079     return 0;
00080 }
00081 
00090 static void rtp_init_seq(rtp_ssrc * stm_src, uint16_t seq)
00091 {
00092     struct rtp_ssrc_stats *stats = &(stm_src->ssrc_stats);
00093 
00094     stats->base_seq = seq - 1;    // FIXME: in rfc 3550 it's set to seq.
00095     stats->max_seq = seq;
00096     stats->bad_seq = RTP_SEQ_MOD + 1;
00097     stats->cycles = 0;
00098     stats->received = 0;
00099     stats->received_prior = 0;
00100     stats->expected_prior = 1;
00101 
00102     // our initializations
00103     // enqueue this SSRC in active SSRCs queue of RTP session.
00104     stm_src->next_active = stm_src->rtp_sess->active_ssrc_queue;
00105     stm_src->rtp_sess->active_ssrc_queue = stm_src;
00106 
00107     return;
00108 }
00109 
00119 void rtp_update_seq(rtp_ssrc * stm_src, uint16_t seq)
00120 {
00121     struct rtp_ssrc_stats *stats = &(stm_src->ssrc_stats);
00122     uint16_t udelta = seq - stats->max_seq;
00123 
00124     if (stats->probation) {
00125         if (seq == stats->max_seq + 1) {
00126             stats->probation--;
00127             stats->max_seq = seq;
00128             if (stats->probation == 0) {
00129                 rtp_init_seq(stm_src, seq);
00130                 stats->received++;
00131                 return;
00132             }
00133         } else {
00134             stats->probation = MIN_SEQUENTIAL - 1;
00135             stats->max_seq = seq;
00136         }
00137         return;
00138     } else if (udelta < MAX_DROPOUT) {
00139         if (seq < stats->max_seq) {
00140             /*
00141              * Sequence number wrapped - count another 64k cycle.
00142              */
00143             stats->cycles += RTP_SEQ_MOD;
00144         }
00145         stats->max_seq = seq;
00146     } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
00147         /* the sequence number made a very large jump */
00148         if (seq == stats->bad_seq) {
00149             rtp_init_seq(stm_src, seq);
00150         } else {
00151             stats->bad_seq = (seq + 1) & (RTP_SEQ_MOD - 1);
00152             return;
00153         }
00154     }            /* else {
00155                    duplicate or reorder packet
00156                    } */
00157     stats->received++;
00158     return;
00159 }
00160 
00170 int rtp_recv(rtp_session * rtp_sess)
00171 {
00172 
00173     int n;
00174     unsigned rate;
00175     int slot;
00176     rtp_pkt *pkt;
00177     rtp_ssrc *stm_src;
00178     struct timeval now;
00179     unsigned transit;
00180     int delta;
00181 
00182     struct sockaddr_storage serveraddr;
00183     nms_sockaddr server =
00184         { (struct sockaddr *) &serveraddr, sizeof(serveraddr) };
00185 
00186     if ((slot = bpget(rtp_sess->bp)) < 0) {
00187         nms_printf(NMSML_VERB,
00188                "No more space in Playout Buffer!" BLANK_LINE);
00189         return 1;
00190     }
00191 
00192     if ((n = recvfrom(rtp_sess->transport.RTP.sock.fd,
00193                       &(rtp_sess->bp->bufferpool[slot]),
00194                       BP_SLOT_SIZE, 0, server.addr, &server.addr_len)) == -1) {
00195         switch (errno) {
00196         case EBADF:
00197             nms_printf(NMSML_ERR,
00198                    "RTP recvfrom: invalid descriptor\n");
00199             break;
00200 #ifndef WIN32
00201         case ENOTSOCK:
00202             nms_printf(NMSML_ERR, "RTP recvfrom: not a socket\n");
00203             break;
00204 #endif
00205         case EINTR:
00206             nms_printf(NMSML_ERR,
00207                    "RTP recvfrom: The receive was interrupted by delivery"
00208                    " of a signal\n");
00209             break;
00210         case EFAULT:
00211             nms_printf(NMSML_ERR,
00212                    "RTP recvfrom: The buffer points outside userspace\n");
00213             break;
00214         case EINVAL:
00215             nms_printf(NMSML_ERR,
00216                    "RTP recvfrom: Invalid argument passed.\n");
00217             break;
00218         default:
00219             nms_printf(NMSML_ERR, "in RTP recvfrom\n");
00220             break;
00221         }
00222         return 1;
00223     }
00224     gettimeofday(&now, NULL);
00225 
00226     pkt = (rtp_pkt *)(&rtp_sess->bp->bufferpool[slot]);
00227 
00228     if (rtp_hdr_val_chk(pkt, n)) {
00229         nms_printf(NMSML_NORM, "RTP header validity check FAILED!\n");
00230         bpfree(rtp_sess->bp, slot);
00231         return 0;
00232     }
00233 
00234     switch (rtp_ssrc_check (rtp_sess, RTP_PKT_SSRC(pkt),
00235                             &stm_src, &server, RTP)) {
00236     case SSRC_KNOWN:
00237         if (stm_src->done_seek) {
00238             stm_src->ssrc_stats.probation = 0;
00239             stm_src->ssrc_stats.max_seq = RTP_PKT_SEQ(pkt);
00240             stm_src->ssrc_stats.firstts = RTP_PKT_TS(pkt);
00241             stm_src->ssrc_stats.lastts = RTP_PKT_TS(pkt);
00242             stm_src->ssrc_stats.firsttv = now;
00243             stm_src->ssrc_stats.jitter = 0;
00244 
00245             stm_src->ssrc_stats.base_seq = RTP_PKT_SEQ(pkt) - 1;    // FIXME: in rfc 3550 it's set to seq.
00246             stm_src->ssrc_stats.bad_seq = RTP_SEQ_MOD + 1;
00247             stm_src->ssrc_stats.cycles = 0;
00248             stm_src->ssrc_stats.received = 0;
00249             stm_src->ssrc_stats.received_prior = 0;
00250             stm_src->ssrc_stats.expected_prior = 1;
00251         }
00252 
00253         rtp_update_seq(stm_src, RTP_PKT_SEQ(pkt));
00254         rtp_update_fps(stm_src, RTP_PKT_TS(pkt), RTP_PKT_PT(pkt));
00255 
00256         if (!rtp_sess->ptdefs[pkt->pt]
00257             || !(rate = (rtp_sess->ptdefs[pkt->pt]->rate)))
00258             rate = RTP_DEF_CLK_RATE;
00259 
00260         transit = (uint32_t) (((double) now.tv_sec +
00261                    (double) now.tv_usec / 1000000.0) *
00262                    (double) rate) - ntohl(pkt->time);
00263         delta = transit - stm_src->ssrc_stats.transit;
00264         stm_src->ssrc_stats.transit = transit;
00265 
00266         if (stm_src->done_seek) {
00267             nms_printf(NMSML_NORM, "Seek reset performed on %u\n", stm_src->ssrc_stats.firstts);
00268             stm_src->done_seek = 0;
00269         }
00270         else {
00271             if (delta < 0)
00272                 delta = -delta;
00273             stm_src->ssrc_stats.jitter +=
00274                 (1. / 16.) * ((double) delta - stm_src->ssrc_stats.jitter);
00275         }
00276         break;
00277     case SSRC_NEW:
00278         rtp_sess->sess_stats.senders++;
00279         rtp_sess->sess_stats.members++;
00280     case SSRC_RTPNEW:
00281         stm_src->ssrc_stats.probation = MIN_SEQUENTIAL;
00282         stm_src->ssrc_stats.max_seq = RTP_PKT_SEQ(pkt) - 1;
00283 
00284         if (!rtp_sess->ptdefs[pkt->pt]
00285             || !(rate = (rtp_sess->ptdefs[pkt->pt]->rate)))
00286             rate = RTP_DEF_CLK_RATE;
00287         (stm_src->ssrc_stats).transit =
00288             (uint32_t) (((double) now.tv_sec +
00289                    (double) now.tv_usec / 1000000.0) *
00290                   (double) rate) - ntohl(pkt->time);
00291 
00292         (stm_src->ssrc_stats).jitter = 0;
00293         (stm_src->ssrc_stats).firstts = RTP_PKT_TS(pkt);
00294         stm_src->ssrc_stats.lastts = RTP_PKT_TS(pkt);
00295         (stm_src->ssrc_stats).firsttv = now;
00296 
00297         rtp_update_seq(stm_src, RTP_PKT_SEQ(pkt));
00298         rtp_update_fps(stm_src, RTP_PKT_TS(pkt), RTP_PKT_PT(pkt));
00299         break;
00300     case SSRC_COLLISION:
00301         bprmv(rtp_sess->bp, stm_src->po, slot);
00302         return 0;
00303         break;
00304     case -1:
00305         return 1;
00306         break;
00307     default:
00308         break;
00309     }
00310 
00311     switch (poadd(stm_src->po, slot, stm_src->ssrc_stats.cycles)) {
00312     case PKT_DUPLICATED:
00313         nms_printf(NMSML_VERB,
00314                "WARNING: Duplicate packet found... discarded\n");
00315         bpfree(rtp_sess->bp, slot);
00316         return 0;
00317         break;
00318     case PKT_MISORDERED:
00319         nms_printf(NMSML_VERB,
00320                "WARNING: Misordered packet found... reordered\n");
00321         break;
00322     default:
00323         break;
00324     }
00325 
00326     stm_src->po->pobuff[slot].pktlen = n;
00327 
00328     return 0;
00329 }

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