diff options
Diffstat (limited to 'kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c')
-rw-r--r-- | kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c new file mode 100644 index 00000000..50ecba97 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c @@ -0,0 +1,159 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <ortp.h> +#include "rtpmod.h" +#include "jitterctl.h" + + +void split_and_queue(queue_t *q, int maxrqsz, mblk_t *mp, rtp_header_t *rtp, int *discarded) +{ + mblk_t *mdata,*tmp; + int header_size; + *discarded=0; + header_size=RTP_FIXED_HEADER_SIZE+ (4*rtp->cc); + if ((mp->b_wptr - mp->b_rptr)==header_size){ + ortp_debug("Rtp packet contains no data."); + (*discarded)++; + freemsg(mp); + return; + } + /* creates a new mblk_t to be linked with the rtp header*/ + mdata=dupb(mp); + + mp->b_wptr=mp->b_rptr+header_size; + mdata->b_rptr+=header_size; + /* link proto with data */ + mp->b_cont=mdata; + /* and then add the packet to the queue */ + + rtp_putq(q,mp); + /* make some checks: q size must not exceed RtpStream::max_rq_size */ + while (q->q_mcount > maxrqsz) + { + /* remove the oldest mblk_t */ + tmp=getq(q); + if (mp!=NULL) + { + ortp_debug("rtp_putq: Queue is full. Discarding message with ts=%i",((rtp_header_t*)mp->b_rptr)->timestamp); + freemsg(tmp); + (*discarded)++; + } + } +} + +void rtp_parse(RtpSession *session, mblk_t *mp, guint32 local_str_ts) +{ + gint i; + rtp_header_t *rtp; + int msgsize; + RtpStream *rtpstream=&session->rtp; + rtp_stats_t *stats=&rtpstream->stats; + + g_return_if_fail(mp!=NULL); + + msgsize=msgdsize(mp); + ortp_global_stats.hw_recv+=msgsize; + stats->hw_recv+=msgsize; + ortp_global_stats.packet_recv++; + stats->packet_recv++; + + session->rtp.hwrcv_since_last_SR++; + + rtp=(rtp_header_t*)mp->b_rptr; + if (rtp->version!=2) + { + ortp_debug("Receiving rtp packet with version number !=2...discarded"); + stats->bad++; + ortp_global_stats.bad++; + freemsg(mp); + return; + } + + /* convert all header data from network order to host order */ + rtp->seq_number=ntohs(rtp->seq_number); + rtp->timestamp=ntohl(rtp->timestamp); + rtp->ssrc=ntohl(rtp->ssrc); + /* convert csrc if necessary */ + if (rtp->cc*sizeof(guint32) > (msgsize-RTP_FIXED_HEADER_SIZE)){ + ortp_debug("Receiving too short rtp packet."); + stats->bad++; + ortp_global_stats.bad++; + freemsg(mp); + return; + } + for (i=0;i<rtp->cc;i++) + rtp->csrc[i]=ntohl(rtp->csrc[i]); + if (session->recv_ssrc!=0) + { + /*the ssrc is set, so we must check it */ + if (session->recv_ssrc!=rtp->ssrc){ + /*ortp_debug("rtp_parse: bad ssrc - %i",rtp->ssrc);*/ + session->recv_ssrc=rtp->ssrc; + rtp_signal_table_emit(&session->on_ssrc_changed); + } + }else session->recv_ssrc=rtp->ssrc; + + /* update some statistics */ + if (rtp->seq_number>rtpstream->hwrcv_extseq.split.lo){ + rtpstream->hwrcv_extseq.split.lo=rtp->seq_number; + }else if (rtp->seq_number<200 && rtpstream->hwrcv_extseq.split.lo>((1<<16) - 200)){ + /* this is a check for sequence number looping */ + rtpstream->hwrcv_extseq.split.lo=rtp->seq_number; + rtpstream->hwrcv_extseq.split.hi++; + } + + + /* check for possible telephone events */ + if (rtp->paytype==session->telephone_events_pt){ + split_and_queue(&session->rtp.tev_rq,session->rtp.max_rq_size,mp,rtp,&i); + stats->discarded+=i; + ortp_global_stats.discarded+=i; + return; + } + + if (!(session->flags & RTP_SESSION_RECV_SYNC)){ + gint32 slide=0; + gint32 safe_delay=0; + jitter_control_new_packet(&session->rtp.jittctl,rtp->timestamp,local_str_ts,&slide,&safe_delay); + + session->rtp.rcv_diff_ts=session->rtp.hwrcv_diff_ts + slide - safe_delay; + ortp_debug(" rcv_diff_ts=%i", session->rtp.rcv_diff_ts); + + /* detect timestamp important jumps in the future, to workaround stupid rtp senders */ + if (RTP_TIMESTAMP_IS_NEWER_THAN(rtp->timestamp,session->rtp.rcv_last_ts+session->rtp.ts_jump)){ + ortp_debug("rtp_parse: timestamp jump ?"); + rtp_signal_table_emit2(&session->on_timestamp_jump,&rtp->timestamp); + } + else if (RTP_TIMESTAMP_IS_NEWER_THAN(session->rtp.rcv_last_ts,rtp->timestamp)){ + /* avoid very old packet to enqueued, because the user is no more supposed to get them */ + ortp_debug("rtp_parse: silently discarding very old packet (ts=%i)",rtp->timestamp); + freemsg(mp); + stats->outoftime++; + ortp_global_stats.outoftime++; + return; + } + + } + + split_and_queue(&session->rtp.rq,session->rtp.max_rq_size,mp,rtp,&i); + stats->discarded+=i; + ortp_global_stats.discarded+=i; +} |