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 "rtpsession_priv.h"
00032 #include <math.h>
00033 
00034 #define JC_BETA 0.01    
00035 #define JC_GAMMA (JC_BETA)
00036 
00037 #include "jitterctl.h"
00038 
00039 void jitter_control_init(JitterControl *ctl, int base_jiitt_time, PayloadType *payload){
00040         ctl->count=0;
00041         ctl->slide=0;
00042         ctl->jitter=0;
00043         ctl->inter_jitter=0;
00044         ctl->slide=0;
00045         if (base_jiitt_time!=-1) ctl->jitt_comp = base_jiitt_time;
00046         /* convert in timestamp unit: */
00047         if (payload!=NULL){
00048                 jitter_control_set_payload(ctl,payload);
00049         }
00050         ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts;
00051         ctl->corrective_slide=0;
00052 }
00053 
00054 void jitter_control_enable_adaptive(JitterControl *ctl, bool_t val){
00055         ctl->adaptive=val;
00056 }
00057 
00058 void jitter_control_set_payload(JitterControl *ctl, PayloadType *pt){
00059         ctl->jitt_comp_ts =
00060                         (int) (((double) ctl->jitt_comp / 1000.0) * (pt->clock_rate));
00061         ctl->corrective_step=(160 * 8000 )/pt->clock_rate; /* This formula got to me after some beers */
00062         ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts;
00063 }
00064 
00065 
00066 void jitter_control_dump_stats(JitterControl *ctl){
00067         ortp_message("JitterControl:\n\tslide=%g,jitter=%g,count=%i",
00068                         ctl->slide,ctl->jitter, ctl->count);
00069 }
00070 
00071 
00072 void jitter_control_update_corrective_slide(JitterControl *ctl){
00073         int tmp;
00074         tmp=(int)(ctl->slide)-ctl->corrective_slide;
00075         if (tmp>ctl->corrective_step) ctl->corrective_slide+=ctl->corrective_step;
00076         else if (tmp<-ctl->corrective_step) ctl->corrective_slide-=ctl->corrective_step;
00077 }
00078 
00079 /*
00080  The algorithm computes two values:
00081         slide: an average of difference between the expected and the socket-received timestamp
00082         jitter: an average of the absolute value of the difference between socket-received timestamp and slide.
00083         slide is used to make clock-slide detection and correction.
00084         jitter is added to the initial jitt_comp_time value. It compensates bursty packets arrival (packets
00085         not arriving at regular interval ).
00086 */
00087 void jitter_control_new_packet(JitterControl *ctl, uint32_t packet_ts, uint32_t cur_str_ts, int32_t * slide, int32_t *safe_delay){
00088         int diff=packet_ts - cur_str_ts;
00089         float gap;
00090         int d;
00091         //printf("diff=%g\n",diff);
00092         if (ctl->count==0){
00093                 ctl->slide=diff;
00094                 ctl->jitter=0;
00095         }else{
00096                 ctl->slide= (float) ((ctl->slide*(1-JC_BETA)) + ((float)diff*JC_BETA));
00097         }
00098         gap=(float) fabs((float)diff - ctl->slide);
00099         ctl->jitter=(float) ((ctl->jitter*(1-JC_GAMMA)) + (gap*JC_GAMMA));
00100         d=diff-ctl->olddiff;
00101         ctl->inter_jitter=(float) (ctl->inter_jitter+ (( (float)abs(d) - ctl->inter_jitter)*(1/16.0)));
00102         ctl->olddiff=diff;
00103         ctl->count++;
00104         if (ctl->adaptive){
00105                 if (ctl->count%50==0) {
00106                         /*jitter_control_dump_stats(ctl);*/
00107                 }
00108                 /* the following is nearly equivalent, but maybe it consumes more CPU: ?*/
00109                 /*ctl->corrective_slide=(((int)ctl->slide)/ctl->corrective_step)*ctl->corrective_step;*/
00110                 
00111                 ctl->adapt_jitt_comp_ts=(int) MAX(ctl->jitt_comp_ts,ctl->jitter);
00112                 
00113                 *slide=(int32_t)ctl->slide;
00114                 *safe_delay=(int32_t)ctl->adapt_jitt_comp_ts;
00115         }else {
00116                 *slide=0;
00117                 *safe_delay=(int32_t)ctl->jitt_comp_ts;
00118         }
00119         return ;
00120 }
00121 
00122 
00131 void
00132 rtp_session_set_jitter_compensation (RtpSession * session, int milisec)
00133 {
00134         PayloadType *payload=NULL;
00135         if (session->rcv.pt!=-1) {
00136                 payload = rtp_profile_get_payload (session->rcv.profile,session->rcv.pt);
00137         }/*else not set yet */
00138         jitter_control_init(&session->rtp.jittctl,milisec,payload);
00139 }
00140 
00141 void rtp_session_enable_adaptive_jitter_compensation(RtpSession *session, bool_t val){
00142         jitter_control_enable_adaptive(&session->rtp.jittctl,val);
00143 }
00144 
00145 bool_t rtp_session_adaptive_jitter_compensation_enabled(RtpSession *session){
00146         return session->rtp.jittctl.adaptive;
00147 }
00148 
00149 void rtp_session_enable_jitter_buffer(RtpSession *session, bool_t enabled){
00150         session->rtp.jittctl.enabled=enabled;
00151         session->flags|=RTP_SESSION_RECV_SYNC;
00152 }
00153 
00154 bool_t rtp_session_jitter_buffer_enabled(const RtpSession *session){
00155         return session->rtp.jittctl.enabled;
00156 }
00157 
00158 void rtp_session_set_jitter_buffer_params(RtpSession *session, const JBParameters *par){
00159         /* FIXME min_size and max_size to be implemented */
00160         rtp_session_set_jitter_compensation(session,par->nom_size);
00161         jitter_control_enable_adaptive(&session->rtp.jittctl,par->adaptive);
00162 }
00163 
00164 void rtp_session_get_jitter_buffer_params(RtpSession *session, JBParameters *par){
00165         int nom_size=session->rtp.jittctl.jitt_comp;
00166         par->min_size=nom_size;
00167         par->nom_size=nom_size;
00168         par->max_size=-1;
00169         par->adaptive=session->rtp.jittctl.adaptive;
00170 }
00171 

Generated on Thu Feb 14 16:11:17 2008 for oRTP by  doxygen 1.5.4