summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c
diff options
context:
space:
mode:
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.c159
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;
+}