1 /*
2 * The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) implementation with additional features.
3 * Copyright (C) 2017 Belledonne Communications SARL
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 /***************************************************************************
20 * jitterctl.c
21 *
22 * Mon Nov 8 11:53:21 2004
23 * Copyright 2004 Simon MORLAT
24 * Email simon.morlat@linphone.org
25 ****************************************************************************/
26
27 #include "ortp/rtpsession.h"
28 #include "ortp/payloadtype.h"
29 #include "ortp/ortp.h"
30 #include "utils.h"
31 #include "rtpsession_priv.h"
32 #include <math.h>
33
34 #define JC_BETA .01
35 #define JC_GAMMA (JC_BETA)
36
37 #include "jitterctl.h"
38
jitter_control_init(JitterControl * ctl,PayloadType * payload)39 void jitter_control_init(JitterControl *ctl, PayloadType *payload){
40 ctl->count=0;
41 ctl->clock_offset_ts=0;
42 ctl->prev_clock_offset_ts=0;
43 ctl->jitter=0;
44 ctl->inter_jitter=0;
45 ctl->cum_jitter_buffer_count=0;
46 ctl->cum_jitter_buffer_size=0;
47 ctl->corrective_slide=0;
48
49 ctl->clock_rate=8000;
50 ctl->adapt_refresh_prev_ts=0;
51
52 if (payload!=NULL){
53 jitter_control_set_payload(ctl,payload);
54 }
55 }
56
57
jitter_control_enable_adaptive(JitterControl * ctl,bool_t val)58 void jitter_control_enable_adaptive(JitterControl *ctl, bool_t val){
59 ctl->params.adaptive=val;
60 }
61
jitter_control_set_payload(JitterControl * ctl,PayloadType * pt)62 void jitter_control_set_payload(JitterControl *ctl, PayloadType *pt){
63 ctl->jitt_comp_ts =
64 (int) (((double) ctl->params.nom_size / 1000.0) * (pt->clock_rate));
65 /*make correction by not less than 10ms */
66 ctl->corrective_step=(int) (0.01 * (float)pt->clock_rate);
67 ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts;
68 ctl->clock_rate=pt->clock_rate;
69 }
70
71
jitter_control_dump_stats(JitterControl * ctl)72 void jitter_control_dump_stats(JitterControl *ctl){
73 ortp_message("JitterControl:\n\tslide=%g,jitter=%g,adapt_jitt_comp_ts=%i,corrective_slide=%i, count=%i",
74 (double)ctl->clock_offset_ts,ctl->jitter, ctl->adapt_jitt_comp_ts, ctl->corrective_slide,ctl->count);
75 }
76
77 /*the goal of this method is to compute "corrective_slide": a timestamp unit'd value to be added
78 to recv timestamp to make them reflect the instant they are delivered by the jitter buffer. */
jitter_control_update_corrective_slide(JitterControl * ctl)79 void jitter_control_update_corrective_slide(JitterControl *ctl){
80 int tmp;
81 tmp=(int)(ctl->clock_offset_ts-ctl->prev_clock_offset_ts);
82 if (tmp>ctl->corrective_step) {
83 ctl->corrective_slide+=ctl->corrective_step;
84 ctl->prev_clock_offset_ts=ctl->clock_offset_ts+ctl->corrective_step;
85 }
86 else if (tmp<-ctl->corrective_step) {
87 ctl->corrective_slide-=ctl->corrective_step;
88 ctl->prev_clock_offset_ts=ctl->clock_offset_ts-ctl->corrective_step;
89 }
90 }
91
jitter_control_update_size(JitterControl * ctl,queue_t * q)92 void jitter_control_update_size(JitterControl *ctl, queue_t *q){
93 mblk_t *newest=qlast(q);
94 mblk_t *oldest=qbegin(q);
95 uint32_t newest_ts,oldest_ts;
96 if (newest==NULL) return;
97 newest_ts=rtp_get_timestamp(newest);
98 oldest_ts=rtp_get_timestamp(oldest);
99 ctl->cum_jitter_buffer_count++;
100 ctl->cum_jitter_buffer_size+=(uint32_t)(newest_ts-oldest_ts);
101 }
102
jitter_control_compute_mean_size(JitterControl * ctl)103 float jitter_control_compute_mean_size(JitterControl *ctl){
104 if (ctl->cum_jitter_buffer_count!=0){
105 double tmp=((double)ctl->cum_jitter_buffer_size)/(double)ctl->cum_jitter_buffer_count;
106 ctl->cum_jitter_buffer_size=0;
107 ctl->cum_jitter_buffer_count=0;
108 ctl->jitter_buffer_mean_size = 1000.0f*(float)tmp/(float)ctl->clock_rate;
109 return ctl->jitter_buffer_mean_size;
110 }
111 return 0;
112 }
113
rtp_session_init_jitter_buffer(RtpSession * session)114 void rtp_session_init_jitter_buffer(RtpSession *session){
115 PayloadType *payload=NULL;
116
117 if (session->rcv.pt!=-1) {
118 payload = rtp_profile_get_payload (session->rcv.profile,session->rcv.pt);
119 }/*else not set yet */
120 jitter_control_init(&session->rtp.jittctl,payload);
121 }
122
123 /**
124 *@param session: a RtpSession
125 *@param milisec: the time interval in milisec to be jitter compensed.
126 *
127 * Sets the time interval for which packet are buffered instead of being delivered to the
128 * application.
129 **/
130 void
rtp_session_set_jitter_compensation(RtpSession * session,int milisec)131 rtp_session_set_jitter_compensation (RtpSession * session, int milisec)
132 {
133 session->rtp.jittctl.params.min_size = session->rtp.jittctl.params.nom_size = milisec;
134 rtp_session_init_jitter_buffer(session);
135 }
136
rtp_session_enable_adaptive_jitter_compensation(RtpSession * session,bool_t val)137 void rtp_session_enable_adaptive_jitter_compensation(RtpSession *session, bool_t val){
138 jitter_control_enable_adaptive(&session->rtp.jittctl,val);
139 }
140
rtp_session_adaptive_jitter_compensation_enabled(RtpSession * session)141 bool_t rtp_session_adaptive_jitter_compensation_enabled(RtpSession *session){
142 return session->rtp.jittctl.params.adaptive;
143 }
144
rtp_session_enable_jitter_buffer(RtpSession * session,bool_t enabled)145 void rtp_session_enable_jitter_buffer(RtpSession *session, bool_t enabled){
146 session->rtp.jittctl.params.enabled = enabled;
147 session->flags|=RTP_SESSION_RECV_SYNC;
148 }
149
rtp_session_jitter_buffer_enabled(const RtpSession * session)150 bool_t rtp_session_jitter_buffer_enabled(const RtpSession *session){
151 return session->rtp.jittctl.params.enabled;
152 }
153
rtp_session_set_jitter_buffer_params(RtpSession * session,const JBParameters * par)154 void rtp_session_set_jitter_buffer_params(RtpSession *session, const JBParameters *par){
155 if (par == &session->rtp.jittctl.params) return;
156 memcpy(&session->rtp.jittctl.params, par, sizeof (JBParameters));
157 rtp_session_init_jitter_buffer(session);
158 }
159
rtp_session_get_jitter_buffer_params(RtpSession * session,JBParameters * par)160 void rtp_session_get_jitter_buffer_params(RtpSession *session, JBParameters *par){
161 memcpy(par, &session->rtp.jittctl.params, sizeof(JBParameters));
162 }
163
164
165 /*
166 The algorithm computes two values:
167 slide: an average of difference between the expected and the socket-received timestamp
168 jitter: an average of the absolute value of the difference between socket-received timestamp and slide.
169 slide is used to make clock-slide detection and correction.
170 jitter is added to the initial jitt_comp_time value. It compensates bursty packets arrival (packets
171 not arriving at regular interval ).
172 */
jitter_control_new_packet(JitterControl * ctl,uint32_t packet_ts,uint32_t cur_str_ts)173 void jitter_control_new_packet(JitterControl *ctl, uint32_t packet_ts, uint32_t cur_str_ts){
174 switch (ctl->params.buffer_algorithm){
175 case OrtpJitterBufferBasic:
176 jitter_control_new_packet_basic (ctl, packet_ts, cur_str_ts);
177 break;
178 case OrtpJitterBufferRecursiveLeastSquare:
179 jitter_control_new_packet_rls (ctl, packet_ts, cur_str_ts);
180 break;
181 default:
182 ortp_fatal("No such new packet strategy: %d", ctl->params.buffer_algorithm);
183 break;
184 }
185 ctl->count++;
186 }
187
jitter_control_update_interarrival_jitter(JitterControl * ctl,int32_t diff)188 static void jitter_control_update_interarrival_jitter(JitterControl *ctl, int32_t diff){
189 /*compute interarrival jitter*/
190 int32_t delta;
191 delta=diff-ctl->olddiff;
192 ctl->inter_jitter=(float) (ctl->inter_jitter+ (( (float)abs(delta) - ctl->inter_jitter)*(1/16.0)));
193 ctl->olddiff=diff;
194 }
195
jitter_control_new_packet_basic(JitterControl * ctl,uint32_t packet_ts,uint32_t cur_str_ts)196 void jitter_control_new_packet_basic(JitterControl *ctl, uint32_t packet_ts, uint32_t cur_str_ts){
197 int32_t diff = packet_ts - cur_str_ts;
198 double gap,slide;
199
200 if (ctl->count==0){
201 ctl->clock_offset_ts=ctl->prev_clock_offset_ts=diff;
202 slide=(double)diff;
203 ctl->olddiff=diff;
204 ctl->jitter=0;
205 }else{
206 slide=((double)ctl->clock_offset_ts*(1-JC_BETA)) + ((double)diff*JC_BETA);
207 }
208 gap=(double)diff - slide;
209 gap=gap<0 ? -gap : 0; /*compute only for late packets*/
210 ctl->jitter=(float) ((ctl->jitter*(1-JC_GAMMA)) + (gap*JC_GAMMA));
211 jitter_control_update_interarrival_jitter(ctl, diff);
212
213 if (ctl->params.adaptive){
214 if (ctl->count%50==0) {
215 ctl->adapt_jitt_comp_ts=(int) MAX(ctl->jitt_comp_ts,2*ctl->jitter);
216 //jitter_control_dump_stats(ctl);
217 }
218 ctl->clock_offset_ts=(int32_t)slide;
219 }else {
220 /*ctl->slide and jitter size are not updated*/
221 }
222 }
223
time_for_log(JitterControl * ctl,uint32_t cur_str_ts)224 static bool_t time_for_log(JitterControl *ctl, uint32_t cur_str_ts){
225 int32_t elapsed = (int32_t)(cur_str_ts - ctl->last_log_ts);
226 if (elapsed >= 5*ctl->clock_rate){
227 ctl->last_log_ts = cur_str_ts;
228 return TRUE;
229 }
230 return FALSE;
231 }
232
jitter_control_local_ts_to_remote_ts_rls(JitterControl * ctl,uint32_t local_ts)233 static uint32_t jitter_control_local_ts_to_remote_ts_rls(JitterControl *ctl, uint32_t local_ts){
234 return (uint32_t)( (int64_t)(ctl->capped_clock_ratio*(double)(local_ts - ctl->local_ts_start) + ctl->clock_offset_ts));
235 }
236
237 /**************************** RLS *********************************/
jitter_control_new_packet_rls(JitterControl * ctl,uint32_t packet_ts,uint32_t cur_str_ts)238 void jitter_control_new_packet_rls(JitterControl *ctl, uint32_t packet_ts, uint32_t cur_str_ts){
239 int32_t diff = packet_ts - cur_str_ts;
240 int deviation;
241 bool_t jb_size_updated = FALSE;
242
243 if (ctl->count==0){
244 ctl->clock_offset_ts = ctl->prev_clock_offset_ts = (int32_t)packet_ts;
245 /*
246 * Offset compensation. In order to avoid managing the rollover of the uint32_t timestamp, the timestamps passed
247 * to the kalman filter are substracted with their initial value.
248 * This allows a video stream to run 13hours (clockrate: 90 000), which looks at first sight
249 * sufficient for a VoIP application.
250 */
251 ctl->local_ts_start = cur_str_ts;
252 ctl->remote_ts_start = packet_ts;
253 ctl->olddiff = diff;
254 ctl->jitter = 0;
255
256 ortp_extremum_init(&ctl->max_ts_deviation, (int)(ctl->params.refresh_ms / 1000.f * ctl->clock_rate));
257 ortp_extremum_record_max(&ctl->max_ts_deviation, 0, (float)ctl->jitt_comp_ts);
258
259 // clock rates should be the same
260 ortp_kalman_rls_init(&ctl->kalman_rls, 1.0, 0.0);
261 ctl->capped_clock_ratio = ctl->kalman_rls.m;
262 }
263
264 /*Compute the deviation from the value predicted by the kalman filter*/
265 deviation = abs((int32_t)(packet_ts - jitter_control_local_ts_to_remote_ts_rls(ctl, cur_str_ts)));
266
267 /*update the kalman filter*/
268 ortp_kalman_rls_record(&ctl->kalman_rls, cur_str_ts - ctl->local_ts_start, packet_ts - ctl->remote_ts_start);
269
270 ctl->capped_clock_ratio = MAX(.5, MIN(ctl->kalman_rls.m, 2));
271
272 if (.5f<ctl->kalman_rls.m && ctl->kalman_rls.m<2.f){
273 /*realistic clock ratio, the filter is well converged*/
274 ctl->clock_offset_ts = (int32_t)((int32_t)ctl->kalman_rls.b + ctl->remote_ts_start);
275 }else{
276 ctl->clock_offset_ts = diff;
277 }
278
279 /*ortp_message("deviation=%g ms", 1000.0*deviation/(double)ctl->clock_rate);*/
280
281 jitter_control_update_interarrival_jitter(ctl, diff);
282 cur_str_ts -= ctl->local_ts_start;
283
284 if (ctl->params.adaptive){
285 bool_t max_updated = ortp_extremum_record_max(&ctl->max_ts_deviation, cur_str_ts, (float)deviation);
286 float max_deviation = MAX(ortp_extremum_get_previous(&ctl->max_ts_deviation), ortp_extremum_get_current(&ctl->max_ts_deviation));
287 if (max_updated && max_deviation > ctl->adapt_jitt_comp_ts){
288 ctl->adapt_jitt_comp_ts=(int)max_deviation;
289 jb_size_updated = TRUE;
290 }else if (max_deviation < ctl->params.ramp_threshold/100.f*ctl->adapt_jitt_comp_ts){
291 /*Jitter is decreasing. Make a smooth descent to avoid dropping lot of packets*/
292 if ( (int32_t)(cur_str_ts - ctl->adapt_refresh_prev_ts) > ((ctl->params.ramp_refresh_ms*ctl->clock_rate)/1000)) {
293 ctl->adapt_jitt_comp_ts -= (ctl->params.ramp_step_ms * ctl->clock_rate) / 1000;
294 jb_size_updated = TRUE;
295 }
296 }
297 if (jb_size_updated){
298 int min_size_ts = (ctl->params.min_size * ctl->clock_rate) / 1000;
299 int max_size_ts = (ctl->params.max_size * ctl->clock_rate) / 1000;
300 if (ctl->adapt_jitt_comp_ts < min_size_ts){
301 ctl->adapt_jitt_comp_ts = min_size_ts;
302 }else if (ctl->adapt_jitt_comp_ts > max_size_ts){
303 ctl->adapt_jitt_comp_ts = max_size_ts;
304 }
305 ctl->adapt_refresh_prev_ts = cur_str_ts;
306 jb_size_updated = TRUE;
307 }
308 }
309 if (time_for_log(ctl, cur_str_ts)){
310 ortp_message("jitter buffer %s: target-size: %f ms, effective-size: %f (min: %i nom: %i, max: %i)",jb_size_updated ? "updated" : "stable",
311 ((float)ctl->adapt_jitt_comp_ts/(float)ctl->clock_rate)*1000.0,
312 ctl->jitter_buffer_mean_size,
313 ctl->params.min_size, ctl->params.nom_size, ctl->params.max_size);
314 ortp_message("jitter buffer rls stats: count=%d, clockrate=%i"
315 ", offset=%g clock_ratio=%g"
316 ", capped_offset=%i capped_clock_ratio=%f"
317 ", max_ts_deviation=%f prev_max_ts_deviation=%f"
318 ", deviation=%i"
319 ", RLS VARIABLES: P[0][0]=%f, P[1][0]=%f, P[0][1]=%f, P[1][1]=%f"
320 , ctl->count, ctl->clock_rate
321 , ctl->kalman_rls.b, ctl->kalman_rls.m
322 , (int) ctl->clock_offset_ts, (float)ctl->capped_clock_ratio
323 , ortp_extremum_get_current(&ctl->max_ts_deviation), ortp_extremum_get_previous(&ctl->max_ts_deviation)
324 , deviation
325 , ctl->kalman_rls.P[0][0], ctl->kalman_rls.P[1][0], ctl->kalman_rls.P[0][1], ctl->kalman_rls.P[1][1]);
326 }
327 }
328
jitter_control_get_compensated_timestamp(JitterControl * obj,uint32_t user_ts)329 uint32_t jitter_control_get_compensated_timestamp(JitterControl *obj , uint32_t user_ts){
330 uint32_t ret = 0;
331 switch (obj->params.buffer_algorithm){
332 case OrtpJitterBufferBasic:
333 ret = (uint32_t)( (int64_t)user_ts+obj->clock_offset_ts-(int64_t)obj->adapt_jitt_comp_ts);
334 break;
335 case OrtpJitterBufferRecursiveLeastSquare:
336 ret = jitter_control_local_ts_to_remote_ts_rls(obj, user_ts) - obj->adapt_jitt_comp_ts;
337 break;
338 default:
339 ortp_fatal("No such new packet strategy: %d", obj->params.buffer_algorithm);
340 break;
341 }
342 return ret;
343 }
344
345