1 /* $Id$ */
2 /*
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 /*
21  * Based on implementation kindly contributed by Switchlab, Ltd.
22  */
23 #include <pjmedia/jbuf.h>
24 #include <pjmedia/errno.h>
25 #include <pj/pool.h>
26 #include <pj/assert.h>
27 #include <pj/log.h>
28 #include <pj/math.h>
29 #include <pj/string.h>
30 
31 
32 #define THIS_FILE   "jbuf.c"
33 
34 
35 /* Invalid sequence number, used as the initial value. */
36 #define INVALID_OFFSET		-9999
37 
38 /* Maximum burst length, whenever an operation is bursting longer than
39  * this value, JB will assume that the opposite operation was idle.
40  */
41 #define MAX_BURST_MSEC		1000
42 
43 /* Number of OP switches to be performed in JB_STATUS_INITIALIZING, before
44  * JB can switch its states to JB_STATUS_PROCESSING.
45  */
46 #define INIT_CYCLE		10
47 
48 
49 /* Maximum frame index in JB framelist (estimated).
50  * As index is calculated as (RTP-timestamp/timestamp-span), the maximum index
51  * usually ranging from MAXUINT32/9000 (10 fps video at 90kHz) to MAXUINT32/80
52  * (10 ms audio at 8000Hz), lets take the 'lowest'.
53  */
54 #define MAX_FRAME_INDEX		(0xFFFFFFFF/9000)
55 
56 
57 /* Minimal difference between JB size and 2*burst-level to perform
58  * JB shrinking in static discard algorithm.
59  */
60 #define STA_DISC_SAFE_SHRINKING_DIFF	1
61 
62 
63 /* Struct of JB internal buffer, represented in a circular buffer containing
64  * frame content, frame type, frame length, and frame bit info.
65  */
66 typedef struct jb_framelist_t
67 {
68     /* Settings */
69     unsigned	     frame_size;	/**< maximum size of frame	    */
70     unsigned	     max_count;		/**< maximum number of frames	    */
71 
72     /* Buffers */
73     char	    *content;		/**< frame content array	    */
74     int		    *frame_type;	/**< frame type array		    */
75     pj_size_t	    *content_len;	/**< frame length array		    */
76     pj_uint32_t	    *bit_info;		/**< frame bit info array	    */
77     pj_uint32_t	    *ts;		/**< timestamp array		    */
78 
79     /* States */
80     unsigned	     head;		/**< index of head, pointed frame
81 					     will be returned by next GET   */
82     unsigned	     size;		/**< current size of framelist,
83 					     including discarded frames.    */
84     unsigned	     discarded_num;	/**< current number of discarded
85 					     frames.			    */
86     int		     origin;		/**< original index of flist_head   */
87 
88 } jb_framelist_t;
89 
90 
91 typedef void (*discard_algo)(pjmedia_jbuf *jb);
92 static void jbuf_discard_static(pjmedia_jbuf *jb);
93 static void jbuf_discard_progressive(pjmedia_jbuf *jb);
94 
95 
96 struct pjmedia_jbuf
97 {
98     /* Settings (consts) */
99     pj_str_t	    jb_name;		/**< jitter buffer name		    */
100     pj_size_t	    jb_frame_size;	/**< frame size			    */
101     unsigned	    jb_frame_ptime;	/**< frame duration.		    */
102     pj_size_t	    jb_max_count;	/**< capacity of jitter buffer,
103 					     in frames			    */
104     int		    jb_init_prefetch;	/**< Initial prefetch		    */
105     int		    jb_min_prefetch;	/**< Minimum allowable prefetch	    */
106     int		    jb_max_prefetch;	/**< Maximum allowable prefetch	    */
107     int		    jb_max_burst;	/**< maximum possible burst, whenever
108 					     burst exceeds this value, it
109 					     won't be included in level
110 					     calculation		    */
111     int		    jb_min_shrink_gap;	/**< How often can we shrink	    */
112     discard_algo    jb_discard_algo;	/**< Discard algorithm		    */
113 
114     /* Buffer */
115     jb_framelist_t  jb_framelist;	/**< the buffer			    */
116 
117     /* States */
118     int		    jb_level;		/**< delay between source &
119 					     destination (calculated according
120 					     of the number of burst get/put
121 					     operations)		    */
122     int		    jb_max_hist_level;  /**< max level during the last level
123 					     calculations		    */
124     int		    jb_stable_hist;	/**< num of times the delay has	been
125 					     lower then the prefetch num    */
126     int		    jb_last_op;		/**< last operation executed
127 					     (put/get)			    */
128     int		    jb_eff_level;	/**< effective burst level	    */
129     int		    jb_prefetch;	/**< no. of frame to insert before
130 					     removing some (at the beginning
131 					     of the framelist->content
132 					     operation), the value may be
133 					     continuously updated based on
134 					     current frame burst level.	    */
135     pj_bool_t	    jb_prefetching;	/**< flag if jbuf is prefetching.   */
136     int		    jb_status;		/**< status is 'init' until the	first
137 					     'put' operation		    */
138     int		    jb_init_cycle_cnt;	/**< status is 'init' until the	first
139 					     'put' operation		    */
140 
141     int		    jb_discard_ref;	/**< Seq # of last frame deleted or
142 					     discarded			    */
143     unsigned	    jb_discard_dist;	/**< Distance from jb_discard_ref
144 					     to perform discard (in frm)    */
145 
146     /* Statistics */
147     pj_math_stat    jb_delay;		/**< Delay statistics of jitter buffer
148 					     (in ms)			    */
149     pj_math_stat    jb_burst;		/**< Burst statistics (in frames)   */
150     unsigned	    jb_lost;		/**< Number of lost frames.	    */
151     unsigned	    jb_discard;		/**< Number of discarded frames.    */
152     unsigned	    jb_empty;		/**< Number of empty/prefetching frame
153 					     returned by GET. */
154 };
155 
156 
157 #define JB_STATUS_INITIALIZING	0
158 #define JB_STATUS_PROCESSING	1
159 
160 
161 
162 /* Progressive discard algorithm introduced to reduce JB latency
163  * by discarding incoming frames with adaptive aggressiveness based on
164  * actual burst level.
165  */
166 #define PROGRESSIVE_DISCARD 1
167 
168 /* Internal JB frame flag, discarded frame will not be returned by JB to
169  * application, it's just simply discarded.
170  */
171 #define PJMEDIA_JB_DISCARDED_FRAME 1024
172 
173 
174 
175 /* Enabling this would log the jitter buffer state about once per
176  * second.
177  */
178 #if 0
179 #  define TRACE__(args)	    PJ_LOG(5,args)
180 #else
181 #  define TRACE__(args)
182 #endif
183 
184 static pj_status_t jb_framelist_reset(jb_framelist_t *framelist);
185 static unsigned jb_framelist_remove_head(jb_framelist_t *framelist,
186 					 unsigned count);
187 
jb_framelist_init(pj_pool_t * pool,jb_framelist_t * framelist,unsigned frame_size,unsigned max_count)188 static pj_status_t jb_framelist_init( pj_pool_t *pool,
189 				      jb_framelist_t *framelist,
190 				      unsigned frame_size,
191 				      unsigned max_count)
192 {
193     PJ_ASSERT_RETURN(pool && framelist, PJ_EINVAL);
194 
195     pj_bzero(framelist, sizeof(jb_framelist_t));
196 
197     framelist->frame_size   = frame_size;
198     framelist->max_count    = max_count;
199     framelist->content	    = (char*)
200 			      pj_pool_alloc(pool,
201 					    (pj_size_t)framelist->frame_size*
202 					    framelist->max_count);
203     framelist->frame_type   = (int*)
204 			      pj_pool_alloc(pool,
205 					    sizeof(framelist->frame_type[0])*
206 					    framelist->max_count);
207     framelist->content_len  = (pj_size_t*)
208 			      pj_pool_alloc(pool,
209 					    sizeof(framelist->content_len[0])*
210 					    framelist->max_count);
211     framelist->bit_info	    = (pj_uint32_t*)
212 			      pj_pool_alloc(pool,
213 					    sizeof(framelist->bit_info[0])*
214 					    framelist->max_count);
215     framelist->ts	    = (pj_uint32_t*)
216 			      pj_pool_alloc(pool,
217 					    sizeof(framelist->ts[0])*
218 					    framelist->max_count);
219 
220     return jb_framelist_reset(framelist);
221 
222 }
223 
jb_framelist_destroy(jb_framelist_t * framelist)224 static pj_status_t jb_framelist_destroy(jb_framelist_t *framelist)
225 {
226     PJ_UNUSED_ARG(framelist);
227     return PJ_SUCCESS;
228 }
229 
jb_framelist_reset(jb_framelist_t * framelist)230 static pj_status_t jb_framelist_reset(jb_framelist_t *framelist)
231 {
232     framelist->head = 0;
233     framelist->origin = INVALID_OFFSET;
234     framelist->size = 0;
235     framelist->discarded_num = 0;
236 
237 
238     //pj_bzero(framelist->content,
239     //	     framelist->frame_size *
240     //	     framelist->max_count);
241 
242     pj_memset(framelist->frame_type,
243 	      PJMEDIA_JB_MISSING_FRAME,
244 	      sizeof(framelist->frame_type[0]) *
245 	      framelist->max_count);
246 
247     pj_bzero(framelist->content_len,
248 	     sizeof(framelist->content_len[0]) *
249 	     framelist->max_count);
250 
251     //pj_bzero(framelist->bit_info,
252     //	     sizeof(framelist->bit_info[0]) *
253     //	     framelist->max_count);
254 
255     return PJ_SUCCESS;
256 }
257 
258 
jb_framelist_size(const jb_framelist_t * framelist)259 static unsigned jb_framelist_size(const jb_framelist_t *framelist)
260 {
261     return framelist->size;
262 }
263 
264 
jb_framelist_eff_size(const jb_framelist_t * framelist)265 static unsigned jb_framelist_eff_size(const jb_framelist_t *framelist)
266 {
267     return (framelist->size - framelist->discarded_num);
268 }
269 
jb_framelist_origin(const jb_framelist_t * framelist)270 static int jb_framelist_origin(const jb_framelist_t *framelist)
271 {
272     return framelist->origin;
273 }
274 
275 
jb_framelist_get(jb_framelist_t * framelist,void * frame,pj_size_t * size,pjmedia_jb_frame_type * p_type,pj_uint32_t * bit_info,pj_uint32_t * ts,int * seq)276 static pj_bool_t jb_framelist_get(jb_framelist_t *framelist,
277 				  void *frame, pj_size_t *size,
278 				  pjmedia_jb_frame_type *p_type,
279 				  pj_uint32_t *bit_info,
280 				  pj_uint32_t *ts,
281 				  int *seq)
282 {
283     if (framelist->size) {
284 	pj_bool_t prev_discarded = PJ_FALSE;
285 
286 	/* Skip discarded frames */
287 	while (framelist->frame_type[framelist->head] ==
288 	       PJMEDIA_JB_DISCARDED_FRAME)
289 	{
290 	    jb_framelist_remove_head(framelist, 1);
291 	    prev_discarded = PJ_TRUE;
292 	}
293 
294 	/* Return the head frame if any */
295 	if (framelist->size) {
296 	    if (prev_discarded) {
297 		/* Ticket #1188: when previous frame(s) was discarded, return
298 		 * 'missing' frame to trigger PLC to get smoother signal.
299 		 */
300 		*p_type = PJMEDIA_JB_MISSING_FRAME;
301 		if (size)
302 		    *size = 0;
303 		if (bit_info)
304 		    *bit_info = 0;
305 	    } else {
306 		pj_size_t frm_size = framelist->content_len[framelist->head];
307 		pj_size_t max_size = size? *size : frm_size;
308 		pj_size_t copy_size = PJ_MIN(max_size, frm_size);
309 
310 		/* Buffer size should not be smaller than frame size. */
311 		if (max_size < frm_size) {
312 		    pj_assert(!"Buffer too small");
313 		    PJ_LOG(4, (THIS_FILE, "Warning: buffer too small for the "
314 					  "retrieved frame!"));
315 		}
316 
317 		pj_memcpy(frame,
318 			  framelist->content +
319 			  framelist->head * framelist->frame_size,
320 			  copy_size);
321 		*p_type = (pjmedia_jb_frame_type)
322 			  framelist->frame_type[framelist->head];
323 		if (size)
324 		    *size = copy_size;
325 		if (bit_info)
326 		    *bit_info = framelist->bit_info[framelist->head];
327 	    }
328 	    if (ts)
329 		*ts = framelist->ts[framelist->head];
330 	    if (seq)
331 		*seq = framelist->origin;
332 
333 	    //pj_bzero(framelist->content +
334 	    //	 framelist->head * framelist->frame_size,
335 	    //	 framelist->frame_size);
336 	    framelist->frame_type[framelist->head] = PJMEDIA_JB_MISSING_FRAME;
337 	    framelist->content_len[framelist->head] = 0;
338 	    framelist->bit_info[framelist->head] = 0;
339 	    framelist->ts[framelist->head] = 0;
340 
341 	    framelist->origin++;
342 	    framelist->head = (framelist->head + 1) % framelist->max_count;
343 	    framelist->size--;
344 
345 	    return PJ_TRUE;
346 	}
347     }
348 
349     /* No frame available */
350     pj_bzero(frame, framelist->frame_size);
351 
352     return PJ_FALSE;
353 }
354 
355 
jb_framelist_peek(jb_framelist_t * framelist,unsigned offset,const void ** frame,pj_size_t * size,pjmedia_jb_frame_type * type,pj_uint32_t * bit_info,pj_uint32_t * ts,int * seq)356 static pj_bool_t jb_framelist_peek(jb_framelist_t *framelist,
357 				   unsigned offset,
358 				   const void **frame,
359 				   pj_size_t *size,
360 				   pjmedia_jb_frame_type *type,
361 				   pj_uint32_t *bit_info,
362 				   pj_uint32_t *ts,
363 				   int *seq)
364 {
365     unsigned pos, idx;
366 
367     if (offset >= jb_framelist_eff_size(framelist))
368 	return PJ_FALSE;
369 
370     pos = framelist->head;
371     idx = offset;
372 
373     /* Find actual peek position, note there may be discarded frames */
374     while (1) {
375 	if (framelist->frame_type[pos] != PJMEDIA_JB_DISCARDED_FRAME) {
376 	    if (idx == 0)
377 		break;
378 	    else
379 		--idx;
380 	}
381 	pos = (pos + 1) % framelist->max_count;
382     }
383 
384     /* Return the frame pointer */
385     if (frame)
386 	*frame = framelist->content + pos*framelist->frame_size;
387     if (type)
388 	*type = (pjmedia_jb_frame_type)
389 		framelist->frame_type[pos];
390     if (size)
391 	*size = framelist->content_len[pos];
392     if (bit_info)
393 	*bit_info = framelist->bit_info[pos];
394     if (ts)
395 	*ts = framelist->ts[pos];
396     if (seq)
397 	*seq = framelist->origin + offset;
398 
399     return PJ_TRUE;
400 }
401 
402 
403 /* Remove oldest frames as many as param 'count' */
jb_framelist_remove_head(jb_framelist_t * framelist,unsigned count)404 static unsigned jb_framelist_remove_head(jb_framelist_t *framelist,
405 					 unsigned count)
406 {
407     if (count > framelist->size)
408 	count = framelist->size;
409 
410     if (count) {
411 	/* may be done in two steps if overlapping */
412 	unsigned step1,step2;
413 	unsigned tmp = framelist->head+count;
414 	unsigned i;
415 
416 	if (tmp > framelist->max_count) {
417 	    step1 = framelist->max_count - framelist->head;
418 	    step2 = count-step1;
419 	} else {
420 	    step1 = count;
421 	    step2 = 0;
422 	}
423 
424 	for (i = framelist->head; i < (framelist->head + step1); ++i) {
425 	    if (framelist->frame_type[i] == PJMEDIA_JB_DISCARDED_FRAME) {
426 		pj_assert(framelist->discarded_num > 0);
427 		framelist->discarded_num--;
428 	    }
429 	}
430 
431 	//pj_bzero(framelist->content +
432 	//	    framelist->head * framelist->frame_size,
433 	//          step1*framelist->frame_size);
434 	pj_memset(framelist->frame_type+framelist->head,
435 		  PJMEDIA_JB_MISSING_FRAME,
436 		  step1*sizeof(framelist->frame_type[0]));
437 	pj_bzero(framelist->content_len+framelist->head,
438 		 step1*sizeof(framelist->content_len[0]));
439 
440 	if (step2) {
441 	    for (i = 0; i < step2; ++i) {
442 		if (framelist->frame_type[i] == PJMEDIA_JB_DISCARDED_FRAME) {
443 		    pj_assert(framelist->discarded_num > 0);
444 		    framelist->discarded_num--;
445 		}
446 	    }
447 	    //pj_bzero( framelist->content,
448 	    //	      step2*framelist->frame_size);
449 	    pj_memset(framelist->frame_type,
450 		      PJMEDIA_JB_MISSING_FRAME,
451 		      step2*sizeof(framelist->frame_type[0]));
452 	    pj_bzero (framelist->content_len,
453 		      step2*sizeof(framelist->content_len[0]));
454 	}
455 
456 	/* update states */
457 	framelist->origin += count;
458 	framelist->head = (framelist->head + count) % framelist->max_count;
459 	framelist->size -= count;
460     }
461 
462     return count;
463 }
464 
465 
jb_framelist_put_at(jb_framelist_t * framelist,int index,const void * frame,unsigned frame_size,pj_uint32_t bit_info,pj_uint32_t ts,unsigned frame_type)466 static pj_status_t jb_framelist_put_at(jb_framelist_t *framelist,
467 				       int index,
468 				       const void *frame,
469 				       unsigned frame_size,
470 				       pj_uint32_t bit_info,
471 				       pj_uint32_t ts,
472 				       unsigned frame_type)
473 {
474     int distance;
475     unsigned pos;
476     enum { MAX_MISORDER = 100 };
477     enum { MAX_DROPOUT = 3000 };
478 
479     PJ_ASSERT_RETURN(frame_size <= framelist->frame_size, PJ_EINVAL);
480 
481     /* get distance of this frame to the first frame in the buffer */
482     distance = index - framelist->origin;
483 
484     /* too late or sequence restart or far jump */
485     if (distance < 0) {
486 	if (framelist->origin - index < MAX_MISORDER) {
487 	    /* too late */
488 	    TRACE__((THIS_FILE,"Put frame #%d: too late (distance=%d)",
489 			       index, distance));
490 	    return PJ_ETOOSMALL;
491 	} else if (framelist->origin + framelist->size >= MAX_FRAME_INDEX) {
492 	    /* sequence restart */
493 	    TRACE__((THIS_FILE,"Put frame #%d: sequence restart (distance=%d, "
494 			       "orig=%d, size=%d)",
495 			       index, distance, framelist->origin,
496 			       framelist->size));
497 	    framelist->origin = index - framelist->size;
498 	    distance = framelist->size;
499 	} else {
500 	    /* jump too far, reset the buffer */
501 	    TRACE__((THIS_FILE,"Put frame #%d: far jump (distance=%d)",
502 			       index, distance));
503 	    jb_framelist_reset(framelist);
504 	    framelist->origin = index;
505 	    distance = 0;
506 	}
507     }
508 
509     /* if jbuf is empty, just reset the origin */
510     if (framelist->size == 0) {
511 	pj_assert(framelist->discarded_num == 0);
512 	TRACE__((THIS_FILE,"Put frame #%d: origin reset (from %d) as JB empty",
513 			   index, framelist->origin));
514 	framelist->origin = index;
515 	distance = 0;
516     }
517 
518     /* far jump, the distance is greater than buffer capacity */
519     if (distance >= (int)framelist->max_count) {
520 	if (distance > MAX_DROPOUT) {
521 	    /* jump too far, reset the buffer */
522 	    TRACE__((THIS_FILE,"Put frame #%d: far jump (distance=%d)",
523 			       index, distance));
524 	    jb_framelist_reset(framelist);
525 	    framelist->origin = index;
526 	    distance = 0;
527 	} else {
528 	    /* otherwise, reject the frame */
529 	    TRACE__((THIS_FILE,"Put frame #%d: rejected due to JB full",
530 			       index));
531 	    return PJ_ETOOMANY;
532 	}
533     }
534 
535     /* get the slot position */
536     pos = (framelist->head + distance) % framelist->max_count;
537 
538     /* if the slot is occupied, it must be duplicated frame, ignore it. */
539     if (framelist->frame_type[pos] != PJMEDIA_JB_MISSING_FRAME) {
540 	TRACE__((THIS_FILE,"Put frame #%d maybe a duplicate, ignored", index));
541 	return PJ_EEXISTS;
542     }
543 
544     /* put the frame into the slot */
545     framelist->frame_type[pos] = frame_type;
546     framelist->content_len[pos] = frame_size;
547     framelist->bit_info[pos] = bit_info;
548     framelist->ts[pos] = ts;
549 
550     /* update framelist size */
551     if (framelist->origin + (int)framelist->size <= index)
552 	framelist->size = distance + 1;
553 
554     if(PJMEDIA_JB_NORMAL_FRAME == frame_type) {
555 	/* copy frame content */
556 	pj_memcpy(framelist->content + pos * framelist->frame_size,
557 		  frame, frame_size);
558     }
559 
560     return PJ_SUCCESS;
561 }
562 
563 
jb_framelist_discard(jb_framelist_t * framelist,int index)564 static pj_status_t jb_framelist_discard(jb_framelist_t *framelist,
565 				        int index)
566 {
567     unsigned pos;
568 
569     PJ_ASSERT_RETURN(index >= framelist->origin &&
570 		     index <  framelist->origin + (int)framelist->size,
571 		     PJ_EINVAL);
572 
573     /* Get the slot position */
574     pos = (framelist->head + (index - framelist->origin)) %
575 	  framelist->max_count;
576 
577     /* Discard the frame */
578     framelist->frame_type[pos] = PJMEDIA_JB_DISCARDED_FRAME;
579     framelist->discarded_num++;
580 
581     return PJ_SUCCESS;
582 }
583 
584 
585 enum pjmedia_jb_op
586 {
587     JB_OP_INIT  = -1,
588     JB_OP_PUT   = 1,
589     JB_OP_GET   = 2
590 };
591 
592 
pjmedia_jbuf_create(pj_pool_t * pool,const pj_str_t * name,unsigned frame_size,unsigned ptime,unsigned max_count,pjmedia_jbuf ** p_jb)593 PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool,
594 					const pj_str_t *name,
595 					unsigned frame_size,
596 					unsigned ptime,
597 					unsigned max_count,
598 					pjmedia_jbuf **p_jb)
599 {
600     pjmedia_jbuf *jb;
601     pj_status_t status;
602 
603     jb = PJ_POOL_ZALLOC_T(pool, pjmedia_jbuf);
604 
605     status = jb_framelist_init(pool, &jb->jb_framelist, frame_size, max_count);
606     if (status != PJ_SUCCESS)
607 	return status;
608 
609     pj_strdup_with_null(pool, &jb->jb_name, name);
610     jb->jb_frame_size	 = frame_size;
611     jb->jb_frame_ptime   = ptime;
612     jb->jb_prefetch	 = PJ_MIN(PJMEDIA_JB_DEFAULT_INIT_DELAY,max_count*4/5);
613     jb->jb_min_prefetch  = 0;
614     jb->jb_max_prefetch  = max_count*4/5;
615     jb->jb_max_count	 = max_count;
616     jb->jb_min_shrink_gap= PJMEDIA_JBUF_DISC_MIN_GAP / ptime;
617     jb->jb_max_burst	 = PJ_MAX(MAX_BURST_MSEC / ptime, max_count*3/4);
618 
619     pj_math_stat_init(&jb->jb_delay);
620     pj_math_stat_init(&jb->jb_burst);
621 
622     pjmedia_jbuf_set_discard(jb, PJMEDIA_JB_DISCARD_PROGRESSIVE);
623     pjmedia_jbuf_reset(jb);
624 
625     *p_jb = jb;
626     return PJ_SUCCESS;
627 }
628 
629 
pjmedia_jbuf_set_ptime(pjmedia_jbuf * jb,unsigned ptime)630 PJ_DEF(pj_status_t) pjmedia_jbuf_set_ptime( pjmedia_jbuf *jb,
631 					    unsigned ptime)
632 {
633     PJ_ASSERT_RETURN(jb, PJ_EINVAL);
634 
635     jb->jb_frame_ptime    = ptime;
636     jb->jb_min_shrink_gap = PJMEDIA_JBUF_DISC_MIN_GAP / ptime;
637     jb->jb_max_burst	  = PJ_MAX(MAX_BURST_MSEC / ptime,
638     				   jb->jb_max_count*3/4);
639 
640     return PJ_SUCCESS;
641 }
642 
643 
644 /*
645  * Set the jitter buffer to fixed delay mode. The default behavior
646  * is to adapt the delay with actual packet delay.
647  *
648  */
pjmedia_jbuf_set_fixed(pjmedia_jbuf * jb,unsigned prefetch)649 PJ_DEF(pj_status_t) pjmedia_jbuf_set_fixed( pjmedia_jbuf *jb,
650 					    unsigned prefetch)
651 {
652     PJ_ASSERT_RETURN(jb, PJ_EINVAL);
653     PJ_ASSERT_RETURN(prefetch <= jb->jb_max_count, PJ_EINVAL);
654 
655     jb->jb_min_prefetch = jb->jb_max_prefetch =
656 	jb->jb_prefetch = jb->jb_init_prefetch = prefetch;
657 
658     pjmedia_jbuf_set_discard(jb, PJMEDIA_JB_DISCARD_NONE);
659     return PJ_SUCCESS;
660 }
661 
662 
663 /*
664  * Set the jitter buffer to adaptive mode.
665  */
pjmedia_jbuf_set_adaptive(pjmedia_jbuf * jb,unsigned prefetch,unsigned min_prefetch,unsigned max_prefetch)666 PJ_DEF(pj_status_t) pjmedia_jbuf_set_adaptive( pjmedia_jbuf *jb,
667 					       unsigned prefetch,
668 					       unsigned min_prefetch,
669 					       unsigned max_prefetch)
670 {
671     PJ_ASSERT_RETURN(jb, PJ_EINVAL);
672     PJ_ASSERT_RETURN(min_prefetch <= max_prefetch &&
673 		     prefetch <= max_prefetch &&
674 		     max_prefetch <= jb->jb_max_count,
675 		     PJ_EINVAL);
676 
677     jb->jb_prefetch = jb->jb_init_prefetch = prefetch;
678     jb->jb_min_prefetch = min_prefetch;
679     jb->jb_max_prefetch = max_prefetch;
680 
681     return PJ_SUCCESS;
682 }
683 
684 
pjmedia_jbuf_set_discard(pjmedia_jbuf * jb,pjmedia_jb_discard_algo algo)685 PJ_DEF(pj_status_t) pjmedia_jbuf_set_discard( pjmedia_jbuf *jb,
686 					      pjmedia_jb_discard_algo algo)
687 {
688     PJ_ASSERT_RETURN(jb, PJ_EINVAL);
689     PJ_ASSERT_RETURN(algo >= PJMEDIA_JB_DISCARD_NONE &&
690 		     algo <= PJMEDIA_JB_DISCARD_PROGRESSIVE,
691 		     PJ_EINVAL);
692 
693     switch(algo) {
694     case PJMEDIA_JB_DISCARD_PROGRESSIVE:
695 	jb->jb_discard_algo = &jbuf_discard_progressive;
696 	break;
697     case PJMEDIA_JB_DISCARD_STATIC:
698 	jb->jb_discard_algo = &jbuf_discard_static;
699 	break;
700     default:
701 	jb->jb_discard_algo = NULL;
702 	break;
703     }
704 
705     return PJ_SUCCESS;
706 }
707 
708 
pjmedia_jbuf_reset(pjmedia_jbuf * jb)709 PJ_DEF(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb)
710 {
711     jb->jb_level	 = 0;
712     jb->jb_last_op	 = JB_OP_INIT;
713     jb->jb_stable_hist	 = 0;
714     jb->jb_status	 = JB_STATUS_INITIALIZING;
715     jb->jb_init_cycle_cnt= 0;
716     jb->jb_max_hist_level= 0;
717     jb->jb_prefetching   = (jb->jb_prefetch != 0);
718     jb->jb_discard_dist  = 0;
719 
720     jb_framelist_reset(&jb->jb_framelist);
721 
722     return PJ_SUCCESS;
723 }
724 
725 
pjmedia_jbuf_destroy(pjmedia_jbuf * jb)726 PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb)
727 {
728     PJ_LOG(5, (jb->jb_name.ptr, ""
729 	       "JB summary:\n"
730 	       "  size=%d/eff=%d prefetch=%d level=%d\n"
731 	       "  delay (min/max/avg/dev)=%d/%d/%d/%d ms\n"
732 	       "  burst (min/max/avg/dev)=%d/%d/%d/%d frames\n"
733 	       "  lost=%d discard=%d empty=%d",
734 	       jb_framelist_size(&jb->jb_framelist),
735 	       jb_framelist_eff_size(&jb->jb_framelist),
736 	       jb->jb_prefetch, jb->jb_eff_level,
737 	       jb->jb_delay.min, jb->jb_delay.max, jb->jb_delay.mean,
738 	       pj_math_stat_get_stddev(&jb->jb_delay),
739 	       jb->jb_burst.min, jb->jb_burst.max, jb->jb_burst.mean,
740 	       pj_math_stat_get_stddev(&jb->jb_burst),
741 	       jb->jb_lost, jb->jb_discard, jb->jb_empty));
742 
743     return jb_framelist_destroy(&jb->jb_framelist);
744 }
745 
pjmedia_jbuf_is_full(const pjmedia_jbuf * jb)746 PJ_DEF(pj_bool_t) pjmedia_jbuf_is_full(const pjmedia_jbuf *jb)
747 {
748     return jb->jb_framelist.size == jb->jb_framelist.max_count;
749 }
750 
jbuf_calculate_jitter(pjmedia_jbuf * jb)751 static void jbuf_calculate_jitter(pjmedia_jbuf *jb)
752 {
753     int diff, cur_size;
754 
755     cur_size = jb_framelist_eff_size(&jb->jb_framelist);
756     pj_math_stat_update(&jb->jb_burst, jb->jb_level);
757     jb->jb_max_hist_level = PJ_MAX(jb->jb_max_hist_level, jb->jb_level);
758 
759     /* Burst level is decreasing */
760     if (jb->jb_level < jb->jb_eff_level) {
761 
762 	enum { STABLE_HISTORY_LIMIT = 20 };
763 
764 	jb->jb_stable_hist++;
765 
766 	/* Only update the effective level (and prefetch) if 'stable'
767 	 * condition is reached (not just short time impulse)
768 	 */
769 	if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) {
770 
771 	    diff = (jb->jb_eff_level - jb->jb_max_hist_level) / 3;
772 
773 	    if (diff < 1)
774 		diff = 1;
775 
776 	    /* Update effective burst level */
777 	    jb->jb_eff_level -= diff;
778 
779 	    /* Update prefetch based on level */
780 	    if (jb->jb_init_prefetch) {
781 		jb->jb_prefetch = jb->jb_eff_level;
782 		if (jb->jb_prefetch < jb->jb_min_prefetch)
783 		    jb->jb_prefetch = jb->jb_min_prefetch;
784 		if (jb->jb_prefetch > jb->jb_max_prefetch)
785 		    jb->jb_prefetch = jb->jb_max_prefetch;
786 	    }
787 
788 	    /* Reset history */
789 	    jb->jb_max_hist_level = 0;
790 	    jb->jb_stable_hist = 0;
791 
792 	    TRACE__((jb->jb_name.ptr,"jb updated(1), lvl=%d pre=%d, size=%d",
793 		     jb->jb_eff_level, jb->jb_prefetch, cur_size));
794 	    PJ_UNUSED_ARG(cur_size); /* Warning about unused var */
795 	}
796     }
797 
798     /* Burst level is increasing */
799     else if (jb->jb_level > jb->jb_eff_level) {
800 
801 	/* Instaneous set effective burst level to recent maximum level */
802 	jb->jb_eff_level = PJ_MIN(jb->jb_max_hist_level,
803 				  (int)(jb->jb_max_count*4/5));
804 
805 	/* Update prefetch based on level */
806 	if (jb->jb_init_prefetch) {
807 	    jb->jb_prefetch = jb->jb_eff_level;
808 	    if (jb->jb_prefetch > jb->jb_max_prefetch)
809 		jb->jb_prefetch = jb->jb_max_prefetch;
810 	    if (jb->jb_prefetch < jb->jb_min_prefetch)
811 		jb->jb_prefetch = jb->jb_min_prefetch;
812 	}
813 
814 	jb->jb_stable_hist = 0;
815 	/* Do not reset max_hist_level. */
816 	//jb->jb_max_hist_level = 0;
817 
818 	TRACE__((jb->jb_name.ptr,"jb updated(2), lvl=%d pre=%d, size=%d",
819 		 jb->jb_eff_level, jb->jb_prefetch, cur_size));
820     }
821 
822     /* Level is unchanged */
823     else {
824 	jb->jb_stable_hist = 0;
825     }
826 }
827 
828 
jbuf_discard_static(pjmedia_jbuf * jb)829 static void jbuf_discard_static(pjmedia_jbuf *jb)
830 {
831     /* These code is used for shortening the delay in the jitter buffer.
832      * It needs shrink only when there is possibility of drift. Drift
833      * detection is performed by inspecting the jitter buffer size, if
834      * its size is twice of current burst level, there can be drift.
835      *
836      * Moreover, normally drift level is quite low, so JB shouldn't need
837      * to shrink aggresively, it will shrink maximum one frame per
838      * PJMEDIA_JBUF_DISC_MIN_GAP ms. Theoritically, JB may handle drift level
839      * as much as = FRAME_PTIME/PJMEDIA_JBUF_DISC_MIN_GAP * 100%
840      *
841      * Whenever there is drift, where PUT > GET, this method will keep
842      * the latency (JB size) as much as twice of burst level.
843      */
844 
845     /* Shrinking due of drift will be implicitly done by progressive discard,
846      * so just disable it when progressive discard is active.
847      */
848     int diff, burst_level;
849 
850     burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level);
851     diff = jb_framelist_eff_size(&jb->jb_framelist) - burst_level*2;
852 
853     if (diff >= STA_DISC_SAFE_SHRINKING_DIFF) {
854 	int seq_origin;
855 
856 	/* Check and adjust jb_discard_ref, in case there was
857 	 * seq restart
858 	 */
859 	seq_origin = jb_framelist_origin(&jb->jb_framelist);
860 	if (seq_origin < jb->jb_discard_ref)
861 	    jb->jb_discard_ref = seq_origin;
862 
863 	if (seq_origin - jb->jb_discard_ref >= jb->jb_min_shrink_gap)
864 	{
865 	    /* Shrink slowly, one frame per cycle */
866 	    diff = 1;
867 
868 	    /* Drop frame(s)! */
869 	    diff = jb_framelist_remove_head(&jb->jb_framelist, diff);
870 	    jb->jb_discard_ref = jb_framelist_origin(&jb->jb_framelist);
871 	    jb->jb_discard += diff;
872 
873 	    TRACE__((jb->jb_name.ptr,
874 		     "JB shrinking %d frame(s), cur size=%d", diff,
875 		     jb_framelist_eff_size(&jb->jb_framelist)));
876 	}
877     }
878 }
879 
880 
jbuf_discard_progressive(pjmedia_jbuf * jb)881 static void jbuf_discard_progressive(pjmedia_jbuf *jb)
882 {
883     unsigned cur_size, burst_level, overflow, T, discard_dist;
884     int last_seq;
885 
886     /* Should be done in PUT operation */
887     if (jb->jb_last_op != JB_OP_PUT)
888 	return;
889 
890     /* Check if latency is longer than burst */
891     cur_size = jb_framelist_eff_size(&jb->jb_framelist);
892     burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level);
893     if (cur_size <= burst_level) {
894 	/* Reset any scheduled discard */
895 	jb->jb_discard_dist = 0;
896 	return;
897     }
898 
899     /* Estimate discard duration needed for adjusting latency */
900     if (burst_level <= PJMEDIA_JBUF_PRO_DISC_MIN_BURST)
901 	T = PJMEDIA_JBUF_PRO_DISC_T1;
902     else if (burst_level >= PJMEDIA_JBUF_PRO_DISC_MAX_BURST)
903 	T = PJMEDIA_JBUF_PRO_DISC_T2;
904     else
905 	T = PJMEDIA_JBUF_PRO_DISC_T1 +
906 	    (PJMEDIA_JBUF_PRO_DISC_T2 - PJMEDIA_JBUF_PRO_DISC_T1) *
907 	    (burst_level - PJMEDIA_JBUF_PRO_DISC_MIN_BURST) /
908 	    (PJMEDIA_JBUF_PRO_DISC_MAX_BURST-PJMEDIA_JBUF_PRO_DISC_MIN_BURST);
909 
910     /* Calculate current discard distance */
911     overflow = cur_size - burst_level;
912     discard_dist = T / overflow / jb->jb_frame_ptime;
913 
914     /* Get last seq number in the JB */
915     last_seq = jb_framelist_origin(&jb->jb_framelist) +
916 	       jb_framelist_size(&jb->jb_framelist) - 1;
917 
918     /* Setup new discard schedule if none, otherwise, update the existing
919      * discard schedule (can be delayed or accelerated).
920      */
921     if (jb->jb_discard_dist == 0) {
922 	/* Setup new discard schedule */
923 	jb->jb_discard_ref = last_seq;
924     } else if (last_seq < jb->jb_discard_ref) {
925 	/* Seq restarted, update discard reference */
926     	jb->jb_discard_ref = last_seq;
927     }
928     jb->jb_discard_dist = PJ_MAX(jb->jb_min_shrink_gap, (int)discard_dist);
929 
930     /* Check if we need to discard now */
931     if (last_seq >= (jb->jb_discard_ref + (int)jb->jb_discard_dist)) {
932 	int discard_seq;
933 
934 	discard_seq = jb->jb_discard_ref + jb->jb_discard_dist;
935 	if (discard_seq < jb_framelist_origin(&jb->jb_framelist))
936 	    discard_seq = jb_framelist_origin(&jb->jb_framelist);
937 
938 	jb_framelist_discard(&jb->jb_framelist, discard_seq);
939 
940 	TRACE__((jb->jb_name.ptr,
941 		"Discard #%d: ref=#%d dist=%d orig=%d size=%d/%d "
942 		"burst=%d/%d",
943 		discard_seq,
944 		jb->jb_discard_ref,
945 		jb->jb_discard_dist,
946 		jb_framelist_origin(&jb->jb_framelist),
947 		cur_size,
948 		jb_framelist_size(&jb->jb_framelist),
949 		jb->jb_eff_level,
950 		burst_level));
951 
952 	/* Update discard reference */
953 	jb->jb_discard_ref = discard_seq;
954     }
955 }
956 
957 
jbuf_update(pjmedia_jbuf * jb,int oper)958 PJ_INLINE(void) jbuf_update(pjmedia_jbuf *jb, int oper)
959 {
960     if(jb->jb_last_op != oper) {
961 	jb->jb_last_op = oper;
962 
963 	if (jb->jb_status == JB_STATUS_INITIALIZING) {
964 	    /* Switch status 'initializing' -> 'processing' after some OP
965 	     * switch cycles and current OP is GET (burst level is calculated
966 	     * based on PUT burst), so burst calculation is guaranted to be
967 	     * performed right after the status switching.
968 	     */
969 	    if (++jb->jb_init_cycle_cnt >= INIT_CYCLE && oper == JB_OP_GET) {
970 		jb->jb_status = JB_STATUS_PROCESSING;
971 		/* To make sure the burst calculation will be done right after
972 		 * this, adjust burst level if it exceeds max burst level.
973 		 */
974 		jb->jb_level = PJ_MIN(jb->jb_level, jb->jb_max_burst);
975 	    } else {
976 		jb->jb_level = 0;
977 		return;
978 	    }
979 	}
980 
981 	/* Perform jitter calculation based on PUT burst-level only, since
982 	 * GET burst-level may not be accurate, e.g: when VAD is active.
983 	 * Note that when burst-level is too big, i.e: exceeds jb_max_burst,
984 	 * the GET op may be idle, in this case, we better skip the jitter
985 	 * calculation.
986 	 */
987 	if (oper == JB_OP_GET && jb->jb_level <= jb->jb_max_burst)
988 	    jbuf_calculate_jitter(jb);
989 
990 	jb->jb_level = 0;
991     }
992 
993     /* Call discard algorithm */
994     if (jb->jb_status == JB_STATUS_PROCESSING && jb->jb_discard_algo) {
995 	(*jb->jb_discard_algo)(jb);
996     }
997 }
998 
pjmedia_jbuf_put_frame(pjmedia_jbuf * jb,const void * frame,pj_size_t frame_size,int frame_seq)999 PJ_DEF(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb,
1000 				     const void *frame,
1001 				     pj_size_t frame_size,
1002 				     int frame_seq)
1003 {
1004     pjmedia_jbuf_put_frame3(jb, frame, frame_size, 0, frame_seq, 0, NULL);
1005 }
1006 
pjmedia_jbuf_put_frame2(pjmedia_jbuf * jb,const void * frame,pj_size_t frame_size,pj_uint32_t bit_info,int frame_seq,pj_bool_t * discarded)1007 PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb,
1008 				     const void *frame,
1009 				     pj_size_t frame_size,
1010 				     pj_uint32_t bit_info,
1011 				     int frame_seq,
1012 				     pj_bool_t *discarded)
1013 {
1014     pjmedia_jbuf_put_frame3(jb, frame, frame_size, bit_info, frame_seq, 0,
1015 			    discarded);
1016 }
1017 
pjmedia_jbuf_put_frame3(pjmedia_jbuf * jb,const void * frame,pj_size_t frame_size,pj_uint32_t bit_info,int frame_seq,pj_uint32_t ts,pj_bool_t * discarded)1018 PJ_DEF(void) pjmedia_jbuf_put_frame3(pjmedia_jbuf *jb,
1019 				     const void *frame,
1020 				     pj_size_t frame_size,
1021 				     pj_uint32_t bit_info,
1022 				     int frame_seq,
1023 				     pj_uint32_t ts,
1024 				     pj_bool_t *discarded)
1025 {
1026     pj_size_t min_frame_size;
1027     int new_size, cur_size;
1028     pj_status_t status;
1029 
1030     cur_size = jb_framelist_eff_size(&jb->jb_framelist);
1031 
1032     /* Check if frame size is larger than JB frame size */
1033     if (frame_size > jb->jb_frame_size) {
1034 	PJ_LOG(4, (THIS_FILE, "Warning: frame too large for jitter buffer, "
1035 		   "it will be truncated!"));
1036     }
1037 
1038     /* Attempt to store the frame */
1039     min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size);
1040     status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame,
1041 				 (unsigned)min_frame_size, bit_info, ts,
1042 				 PJMEDIA_JB_NORMAL_FRAME);
1043 
1044     /* Jitter buffer is full, remove some older frames */
1045     while (status == PJ_ETOOMANY) {
1046 	int distance;
1047 	unsigned removed;
1048 
1049 	/* Remove as few as possible just to make this frame in. Note that
1050 	 * the cases of seq-jump, out-of-order, and seq restart should have
1051 	 * been handled/normalized by previous call of jb_framelist_put_at().
1052 	 * So we're confident about 'distance' value here.
1053 	 */
1054 	distance = (frame_seq - jb_framelist_origin(&jb->jb_framelist)) -
1055 		   (int)jb->jb_max_count + 1;
1056 	pj_assert(distance > 0);
1057 
1058 	removed = jb_framelist_remove_head(&jb->jb_framelist, distance);
1059 	status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame,
1060 				     (unsigned)min_frame_size, bit_info, ts,
1061 				     PJMEDIA_JB_NORMAL_FRAME);
1062 
1063 	jb->jb_discard += removed;
1064     }
1065 
1066     /* Get new JB size after PUT */
1067     new_size = jb_framelist_eff_size(&jb->jb_framelist);
1068 
1069     /* Return the flag if this frame is discarded */
1070     if (discarded)
1071 	*discarded = (status != PJ_SUCCESS);
1072 
1073     if (status == PJ_SUCCESS) {
1074 	if (jb->jb_prefetching) {
1075 	    TRACE__((jb->jb_name.ptr, "PUT prefetch_cnt=%d/%d",
1076 		     new_size, jb->jb_prefetch));
1077 	    if (new_size >= jb->jb_prefetch)
1078 		jb->jb_prefetching = PJ_FALSE;
1079 	}
1080 	jb->jb_level += (new_size > cur_size ? new_size-cur_size : 1);
1081 	jbuf_update(jb, JB_OP_PUT);
1082     } else
1083 	jb->jb_discard++;
1084 }
1085 
1086 /*
1087  * Get frame from jitter buffer.
1088  */
pjmedia_jbuf_get_frame(pjmedia_jbuf * jb,void * frame,char * p_frame_type)1089 PJ_DEF(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,
1090 				     void *frame,
1091 				     char *p_frame_type)
1092 {
1093     pjmedia_jbuf_get_frame3(jb, frame, NULL, p_frame_type, NULL,
1094 			    NULL, NULL);
1095 }
1096 
1097 /*
1098  * Get frame from jitter buffer.
1099  */
pjmedia_jbuf_get_frame2(pjmedia_jbuf * jb,void * frame,pj_size_t * size,char * p_frame_type,pj_uint32_t * bit_info)1100 PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb,
1101 				     void *frame,
1102 				     pj_size_t *size,
1103 				     char *p_frame_type,
1104 				     pj_uint32_t *bit_info)
1105 {
1106     pjmedia_jbuf_get_frame3(jb, frame, size, p_frame_type, bit_info,
1107 			    NULL, NULL);
1108 }
1109 
1110 /*
1111  * Get frame from jitter buffer.
1112  */
pjmedia_jbuf_get_frame3(pjmedia_jbuf * jb,void * frame,pj_size_t * size,char * p_frame_type,pj_uint32_t * bit_info,pj_uint32_t * ts,int * seq)1113 PJ_DEF(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb,
1114 				     void *frame,
1115 				     pj_size_t *size,
1116 				     char *p_frame_type,
1117 				     pj_uint32_t *bit_info,
1118 				     pj_uint32_t *ts,
1119 				     int *seq)
1120 {
1121     if (jb->jb_prefetching) {
1122 
1123 	/* Can't return frame because jitter buffer is filling up
1124 	 * minimum prefetch.
1125 	 */
1126 
1127 	//pj_bzero(frame, jb->jb_frame_size);
1128 	*p_frame_type = PJMEDIA_JB_ZERO_PREFETCH_FRAME;
1129 	if (size)
1130 	    *size = 0;
1131 
1132 	TRACE__((jb->jb_name.ptr, "GET prefetch_cnt=%d/%d",
1133 		 jb_framelist_eff_size(&jb->jb_framelist), jb->jb_prefetch));
1134 
1135 	jb->jb_empty++;
1136 
1137     } else {
1138 
1139 	pjmedia_jb_frame_type ftype = PJMEDIA_JB_NORMAL_FRAME;
1140 	pj_bool_t res;
1141 
1142 	/* Try to retrieve a frame from frame list */
1143 	res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype,
1144 			       bit_info, ts, seq);
1145 	if (res) {
1146 	    /* We've successfully retrieved a frame from the frame list, but
1147 	     * the frame could be a blank frame!
1148 	     */
1149 	    if (ftype == PJMEDIA_JB_NORMAL_FRAME) {
1150 		*p_frame_type = PJMEDIA_JB_NORMAL_FRAME;
1151 	    } else {
1152 		*p_frame_type = PJMEDIA_JB_MISSING_FRAME;
1153 		jb->jb_lost++;
1154 	    }
1155 
1156 	    /* Store delay history at the first GET */
1157 	    if (jb->jb_last_op == JB_OP_PUT) {
1158 		unsigned cur_size;
1159 
1160 		/* We've just retrieved one frame, so add one to cur_size */
1161 		cur_size = jb_framelist_eff_size(&jb->jb_framelist) + 1;
1162 		pj_math_stat_update(&jb->jb_delay,
1163 				    cur_size*jb->jb_frame_ptime);
1164 	    }
1165 	} else {
1166 	    /* Jitter buffer is empty */
1167 	    if (jb->jb_prefetch)
1168 		jb->jb_prefetching = PJ_TRUE;
1169 
1170 	    //pj_bzero(frame, jb->jb_frame_size);
1171 	    *p_frame_type = PJMEDIA_JB_ZERO_EMPTY_FRAME;
1172 	    if (size)
1173 		*size = 0;
1174 
1175 	    jb->jb_empty++;
1176 	}
1177     }
1178 
1179     jb->jb_level++;
1180     jbuf_update(jb, JB_OP_GET);
1181 }
1182 
1183 /*
1184  * Get jitter buffer state.
1185  */
pjmedia_jbuf_get_state(const pjmedia_jbuf * jb,pjmedia_jb_state * state)1186 PJ_DEF(pj_status_t) pjmedia_jbuf_get_state( const pjmedia_jbuf *jb,
1187 					    pjmedia_jb_state *state )
1188 {
1189     PJ_ASSERT_RETURN(jb && state, PJ_EINVAL);
1190 
1191     state->frame_size = (unsigned)jb->jb_frame_size;
1192     state->min_prefetch = jb->jb_min_prefetch;
1193     state->max_prefetch = jb->jb_max_prefetch;
1194     state->max_count = jb->jb_max_count;
1195 
1196     state->burst = jb->jb_eff_level;
1197     state->prefetch = jb->jb_prefetch;
1198     state->size = jb_framelist_eff_size(&jb->jb_framelist);
1199 
1200     state->avg_delay = jb->jb_delay.mean;
1201     state->min_delay = jb->jb_delay.min;
1202     state->max_delay = jb->jb_delay.max;
1203     state->dev_delay = pj_math_stat_get_stddev(&jb->jb_delay);
1204 
1205     state->avg_burst = jb->jb_burst.mean;
1206     state->empty = jb->jb_empty;
1207     state->discard = jb->jb_discard;
1208     state->lost = jb->jb_lost;
1209 
1210     return PJ_SUCCESS;
1211 }
1212 
1213 
pjmedia_jbuf_peek_frame(pjmedia_jbuf * jb,unsigned offset,const void ** frame,pj_size_t * size,char * p_frm_type,pj_uint32_t * bit_info,pj_uint32_t * ts,int * seq)1214 PJ_DEF(void) pjmedia_jbuf_peek_frame( pjmedia_jbuf *jb,
1215 				      unsigned offset,
1216 				      const void **frame,
1217 				      pj_size_t *size,
1218 				      char *p_frm_type,
1219 				      pj_uint32_t *bit_info,
1220 				      pj_uint32_t *ts,
1221 				      int *seq)
1222 {
1223     pjmedia_jb_frame_type ftype;
1224     pj_bool_t res;
1225 
1226     res = jb_framelist_peek(&jb->jb_framelist, offset, frame, size, &ftype,
1227 			    bit_info, ts, seq);
1228     if (!res)
1229 	*p_frm_type = PJMEDIA_JB_ZERO_EMPTY_FRAME;
1230     else if (ftype == PJMEDIA_JB_NORMAL_FRAME)
1231 	*p_frm_type = PJMEDIA_JB_NORMAL_FRAME;
1232     else
1233 	*p_frm_type = PJMEDIA_JB_MISSING_FRAME;
1234 }
1235 
1236 
pjmedia_jbuf_remove_frame(pjmedia_jbuf * jb,unsigned frame_cnt)1237 PJ_DEF(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb,
1238 					   unsigned frame_cnt)
1239 {
1240     unsigned count, last_discard_num;
1241 
1242     last_discard_num = jb->jb_framelist.discarded_num;
1243     count = jb_framelist_remove_head(&jb->jb_framelist, frame_cnt);
1244 
1245     /* Remove some more when there were discarded frames included */
1246     while (jb->jb_framelist.discarded_num < last_discard_num) {
1247 	/* Calculate frames count to be removed next */
1248 	frame_cnt = last_discard_num - jb->jb_framelist.discarded_num;
1249 
1250 	/* Normalize non-discarded frames count just been removed */
1251 	count -= frame_cnt;
1252 
1253 	/* Remove more frames */
1254 	last_discard_num = jb->jb_framelist.discarded_num;
1255 	count += jb_framelist_remove_head(&jb->jb_framelist, frame_cnt);
1256     }
1257 
1258     return count;
1259 }
1260