src/jitterctl.c

00001 /*
00002   The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
00003   Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014 
00015   You should have received a copy of the GNU Lesser General Public
00016   License along with this library; if not, write to the Free Software
00017   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 /***************************************************************************
00020  *            jitterctl.c
00021  *
00022  *  Mon Nov  8 11:53:21 2004
00023  *  Copyright  2004  Simon MORLAT
00024  *  Email simon.morlat@linphone.org
00025  ****************************************************************************/
00026 
00027 #include "ortp/rtpsession.h"
00028 #include "ortp/payloadtype.h"
00029 #include "ortp/ortp.h"
00030 #include "utils.h"
00031 #include <math.h>
00032 
00033 #define JC_BETA 0.03    /*allows a clock slide around 3% */
00034 #define JC_GAMMA (JC_BETA)
00035 
00036 #include "jitterctl.h"
00037 
00038 void jitter_control_init(JitterControl *ctl, int base_jiitt_time, PayloadType *payload){
00039         ctl->count=0;
00040         ctl->slide=0;
00041         ctl->jitter=0;
00042         ctl->inter_jitter=0;
00043         ctl->slide=0;
00044         if (base_jiitt_time!=-1) ctl->jitt_comp = base_jiitt_time;
00045         /* convert in timestamp unit: */
00046         if (payload!=NULL){
00047                 jitter_control_set_payload(ctl,payload);
00048         }
00049         ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts;
00050         ctl->corrective_slide=0;
00051 }
00052 
00053 void jitter_control_enable_adaptive(JitterControl *ctl, bool_t val){
00054         ctl->adaptive=val;
00055 }
00056 
00057 void jitter_control_set_payload(JitterControl *ctl, PayloadType *pt){
00058         ctl->jitt_comp_ts =
00059                         (int) (((double) ctl->jitt_comp / 1000.0) * (pt->clock_rate));
00060         ctl->corrective_step=(160 * 8000 )/pt->clock_rate; /* This formula got to me after some beers */
00061         ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts;
00062 }
00063 
00064 
00065 void jitter_control_dump_stats(JitterControl *ctl){
00066         ortp_message("JitterControl:\n\tslide=%g,jitter=%g,count=%i",
00067                         ctl->slide,ctl->jitter, ctl->count);
00068 }
00069 
00070 
00071 void jitter_control_update_corrective_slide(JitterControl *ctl){
00072         int tmp;
00073         tmp=(int)(ctl->slide)-ctl->corrective_slide;
00074         if (tmp>ctl->corrective_step) ctl->corrective_slide+=ctl->corrective_step;
00075         else if (tmp<-ctl->corrective_step) ctl->corrective_slide-=ctl->corrective_step;
00076 }
00077 
00078 /*
00079  The algorithm computes two values:
00080         slide: an average of difference between the expected and the socket-received timestamp
00081         jitter: an average of the absolute value of the difference between socket-received timestamp and slide.
00082         slide is used to make clock-slide detection and correction.
00083         jitter is added to the initial jitt_comp_time value. It compensates bursty packets arrival (packets
00084         not arriving at regular interval ).
00085 */
00086 void jitter_control_new_packet(JitterControl *ctl, uint32_t packet_ts, uint32_t cur_str_ts, int32_t * slide, int32_t *safe_delay){
00087         int diff=packet_ts - cur_str_ts;
00088         float gap;
00089         int d;
00090         //printf("diff=%g\n",diff);
00091         
00092         ctl->count++;
00093         ctl->slide= (float) ((ctl->slide*(1-JC_BETA)) + ((float)diff*JC_BETA));
00094         gap=(float) fabs((float)diff - ctl->slide);
00095         ctl->jitter=(float) ((ctl->jitter*(1-JC_GAMMA)) + (gap*JC_GAMMA));
00096         d=diff-ctl->olddiff;
00097         ctl->inter_jitter=(float) (ctl->inter_jitter+ (( (float)abs(d) - ctl->inter_jitter)*(1/16.0)));
00098         ctl->olddiff=diff;
00099         if (ctl->adaptive){
00100                 if (ctl->count%50==0) {
00101                         /*jitter_control_dump_stats(ctl);*/
00102                 }
00103                 /* the following is nearly equivalent, but maybe it consumes more CPU: ?*/
00104                 /*ctl->corrective_slide=(((int)ctl->slide)/ctl->corrective_step)*ctl->corrective_step;*/
00105                 
00106                 ctl->adapt_jitt_comp_ts=(int) MAX(ctl->jitt_comp_ts,ctl->jitter);
00107                 
00108                 *slide=(int32_t)ctl->slide;
00109                 *safe_delay=(int32_t)ctl->adapt_jitt_comp_ts;
00110         }else {
00111                 *slide=0;
00112                 *safe_delay=(int32_t)ctl->jitt_comp_ts;
00113         }
00114         return ;
00115 }
00116 
00117 
00126 void
00127 rtp_session_set_jitter_compensation (RtpSession * session, int milisec)
00128 {
00129         PayloadType *payload=NULL;
00130         if (session->rcv.pt!=-1) {
00131                 payload = rtp_profile_get_payload (session->rcv.profile,session->rcv.pt);
00132         }/*else not set yet */
00133         jitter_control_init(&session->rtp.jittctl,milisec,payload);
00134 }
00135 
00136 void rtp_session_enable_adaptive_jitter_compensation(RtpSession *session, bool_t val){
00137         jitter_control_enable_adaptive(&session->rtp.jittctl,val);
00138 }
00139 
00140 bool_t rtp_session_adaptive_jitter_compensation_enabled(RtpSession *session){
00141         return session->rtp.jittctl.adaptive;
00142 }

Generated on Fri Jun 22 17:30:27 2007 for oRTP by  doxygen 1.5.1