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