~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjmedia/src/pjmedia/jbuf.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: jbuf.c 4100 2012-04-26 16:57:47Z nanang $ */
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
 
 */
58
 
typedef 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
 
 
83
 
typedef void (*discard_algo)(pjmedia_jbuf *jb);
84
 
static void jbuf_discard_static(pjmedia_jbuf *jb);
85
 
static void jbuf_discard_progressive(pjmedia_jbuf *jb);
86
 
 
87
 
 
88
 
struct 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 1
171
 
#  define TRACE__(args)     PJ_LOG(5,args)
172
 
#else
173
 
#  define TRACE__(args)
174
 
#endif
175
 
 
176
 
static pj_status_t jb_framelist_reset(jb_framelist_t *framelist);
177
 
static unsigned jb_framelist_remove_head(jb_framelist_t *framelist,
178
 
                                         unsigned count);
179
 
 
180
 
static 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
 
 
216
 
static pj_status_t jb_framelist_destroy(jb_framelist_t *framelist)
217
 
{
218
 
    PJ_UNUSED_ARG(framelist);
219
 
    return PJ_SUCCESS;
220
 
}
221
 
 
222
 
static 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
 
 
251
 
static unsigned jb_framelist_size(const jb_framelist_t *framelist)
252
 
{
253
 
    return framelist->size;
254
 
}
255
 
 
256
 
 
257
 
static unsigned jb_framelist_eff_size(const jb_framelist_t *framelist)
258
 
{
259
 
    return (framelist->size - framelist->discarded_num);
260
 
}
261
 
 
262
 
static int jb_framelist_origin(const jb_framelist_t *framelist)
263
 
{
264
 
    return framelist->origin;
265
 
}
266
 
 
267
 
 
268
 
static 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
 
 
337
 
static 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' */
385
 
static 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
 
 
447
 
static 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
 
 
522
 
static 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
 
 
543
 
enum pjmedia_jb_op
544
 
{
545
 
    JB_OP_INIT  = -1,
546
 
    JB_OP_PUT   = 1,
547
 
    JB_OP_GET   = 2
548
 
};
549
 
 
550
 
 
551
 
PJ_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
 
 */
593
 
PJ_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
 
    return PJ_SUCCESS;
603
 
}
604
 
 
605
 
 
606
 
/*
607
 
 * Set the jitter buffer to adaptive mode.
608
 
 */
609
 
PJ_DEF(pj_status_t) pjmedia_jbuf_set_adaptive( pjmedia_jbuf *jb,
610
 
                                               unsigned prefetch,
611
 
                                               unsigned min_prefetch,
612
 
                                               unsigned max_prefetch)
613
 
{
614
 
    PJ_ASSERT_RETURN(jb, PJ_EINVAL);
615
 
    PJ_ASSERT_RETURN(min_prefetch <= max_prefetch &&
616
 
                     prefetch <= max_prefetch &&
617
 
                     max_prefetch <= jb->jb_max_count,
618
 
                     PJ_EINVAL);
619
 
 
620
 
    jb->jb_prefetch = jb->jb_init_prefetch = prefetch;
621
 
    jb->jb_min_prefetch = min_prefetch;
622
 
    jb->jb_max_prefetch = max_prefetch;
623
 
 
624
 
    return PJ_SUCCESS;
625
 
}
626
 
 
627
 
 
628
 
PJ_DEF(pj_status_t) pjmedia_jbuf_set_discard( pjmedia_jbuf *jb,
629
 
                                              pjmedia_jb_discard_algo algo)
630
 
{
631
 
    PJ_ASSERT_RETURN(jb, PJ_EINVAL);
632
 
    PJ_ASSERT_RETURN(algo >= PJMEDIA_JB_DISCARD_NONE &&
633
 
                     algo <= PJMEDIA_JB_DISCARD_PROGRESSIVE,
634
 
                     PJ_EINVAL);
635
 
 
636
 
    switch(algo) {
637
 
    case PJMEDIA_JB_DISCARD_PROGRESSIVE:
638
 
        jb->jb_discard_algo = &jbuf_discard_progressive;
639
 
        break;
640
 
    case PJMEDIA_JB_DISCARD_STATIC:
641
 
        jb->jb_discard_algo = &jbuf_discard_static;
642
 
        break;
643
 
    default:
644
 
        jb->jb_discard_algo = NULL;
645
 
        break;
646
 
    }
647
 
 
648
 
    return PJ_SUCCESS;
649
 
}
650
 
 
651
 
 
652
 
PJ_DEF(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb)
653
 
{
654
 
    jb->jb_level         = 0;
655
 
    jb->jb_last_op       = JB_OP_INIT;
656
 
    jb->jb_stable_hist   = 0;
657
 
    jb->jb_status        = JB_STATUS_INITIALIZING;
658
 
    jb->jb_init_cycle_cnt= 0;
659
 
    jb->jb_max_hist_level= 0;
660
 
    jb->jb_prefetching   = (jb->jb_prefetch != 0);
661
 
    jb->jb_discard_dist  = 0;
662
 
 
663
 
    jb_framelist_reset(&jb->jb_framelist);
664
 
 
665
 
    return PJ_SUCCESS;
666
 
}
667
 
 
668
 
 
669
 
PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb)
670
 
{
671
 
    PJ_LOG(5, (jb->jb_name.ptr, ""
672
 
               "JB summary:\n"
673
 
               "  size=%d/eff=%d prefetch=%d level=%d\n"
674
 
               "  delay (min/max/avg/dev)=%d/%d/%d/%d ms\n"
675
 
               "  burst (min/max/avg/dev)=%d/%d/%d/%d frames\n"
676
 
               "  lost=%d discard=%d empty=%d",
677
 
               jb_framelist_size(&jb->jb_framelist),
678
 
               jb_framelist_eff_size(&jb->jb_framelist),
679
 
               jb->jb_prefetch, jb->jb_eff_level,
680
 
               jb->jb_delay.min, jb->jb_delay.max, jb->jb_delay.mean,
681
 
               pj_math_stat_get_stddev(&jb->jb_delay),
682
 
               jb->jb_burst.min, jb->jb_burst.max, jb->jb_burst.mean,
683
 
               pj_math_stat_get_stddev(&jb->jb_burst),
684
 
               jb->jb_lost, jb->jb_discard, jb->jb_empty));
685
 
 
686
 
    return jb_framelist_destroy(&jb->jb_framelist);
687
 
}
688
 
 
689
 
PJ_DEF(pj_bool_t) pjmedia_jbuf_is_full(const pjmedia_jbuf *jb)
690
 
{
691
 
    return jb->jb_framelist.size == jb->jb_framelist.max_count;
692
 
}
693
 
 
694
 
static void jbuf_calculate_jitter(pjmedia_jbuf *jb)
695
 
{
696
 
    int diff, cur_size;
697
 
 
698
 
    cur_size = jb_framelist_eff_size(&jb->jb_framelist);
699
 
    pj_math_stat_update(&jb->jb_burst, jb->jb_level);
700
 
    jb->jb_max_hist_level = PJ_MAX(jb->jb_max_hist_level, jb->jb_level);
701
 
 
702
 
    /* Burst level is decreasing */
703
 
    if (jb->jb_level < jb->jb_eff_level) {
704
 
 
705
 
        enum { STABLE_HISTORY_LIMIT = 20 };
706
 
 
707
 
        jb->jb_stable_hist++;
708
 
 
709
 
        /* Only update the effective level (and prefetch) if 'stable'
710
 
         * condition is reached (not just short time impulse)
711
 
         */
712
 
        if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) {
713
 
 
714
 
            diff = (jb->jb_eff_level - jb->jb_max_hist_level) / 3;
715
 
 
716
 
            if (diff < 1)
717
 
                diff = 1;
718
 
 
719
 
            /* Update effective burst level */
720
 
            jb->jb_eff_level -= diff;
721
 
 
722
 
            /* Update prefetch based on level */
723
 
            if (jb->jb_init_prefetch) {
724
 
                jb->jb_prefetch = jb->jb_eff_level;
725
 
                if (jb->jb_prefetch < jb->jb_min_prefetch)
726
 
                    jb->jb_prefetch = jb->jb_min_prefetch;
727
 
            }
728
 
 
729
 
            /* Reset history */
730
 
            jb->jb_max_hist_level = 0;
731
 
            jb->jb_stable_hist = 0;
732
 
 
733
 
            TRACE__((jb->jb_name.ptr,"jb updated(1), lvl=%d pre=%d, size=%d",
734
 
                     jb->jb_eff_level, jb->jb_prefetch, cur_size));
735
 
        }
736
 
    }
737
 
 
738
 
    /* Burst level is increasing */
739
 
    else if (jb->jb_level > jb->jb_eff_level) {
740
 
 
741
 
        /* Instaneous set effective burst level to recent maximum level */
742
 
        jb->jb_eff_level = PJ_MIN(jb->jb_max_hist_level,
743
 
                                  (int)(jb->jb_max_count*4/5));
744
 
 
745
 
        /* Update prefetch based on level */
746
 
        if (jb->jb_init_prefetch) {
747
 
            jb->jb_prefetch = jb->jb_eff_level;
748
 
            if (jb->jb_prefetch > jb->jb_max_prefetch)
749
 
                jb->jb_prefetch = jb->jb_max_prefetch;
750
 
        }
751
 
 
752
 
        jb->jb_stable_hist = 0;
753
 
        /* Do not reset max_hist_level. */
754
 
        //jb->jb_max_hist_level = 0;
755
 
 
756
 
        TRACE__((jb->jb_name.ptr,"jb updated(2), lvl=%d pre=%d, size=%d",
757
 
                 jb->jb_eff_level, jb->jb_prefetch, cur_size));
758
 
    }
759
 
 
760
 
    /* Level is unchanged */
761
 
    else {
762
 
        jb->jb_stable_hist = 0;
763
 
    }
764
 
}
765
 
 
766
 
 
767
 
static void jbuf_discard_static(pjmedia_jbuf *jb)
768
 
{
769
 
    /* These code is used for shortening the delay in the jitter buffer.
770
 
     * It needs shrink only when there is possibility of drift. Drift
771
 
     * detection is performed by inspecting the jitter buffer size, if
772
 
     * its size is twice of current burst level, there can be drift.
773
 
     *
774
 
     * Moreover, normally drift level is quite low, so JB shouldn't need
775
 
     * to shrink aggresively, it will shrink maximum one frame per
776
 
     * PJMEDIA_JBUF_DISC_MIN_GAP ms. Theoritically, JB may handle drift level
777
 
     * as much as = FRAME_PTIME/PJMEDIA_JBUF_DISC_MIN_GAP * 100%
778
 
     *
779
 
     * Whenever there is drift, where PUT > GET, this method will keep
780
 
     * the latency (JB size) as much as twice of burst level.
781
 
     */
782
 
 
783
 
    /* Shrinking due of drift will be implicitly done by progressive discard,
784
 
     * so just disable it when progressive discard is active.
785
 
     */
786
 
    int diff, burst_level;
787
 
 
788
 
    burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level);
789
 
    diff = jb_framelist_eff_size(&jb->jb_framelist) - burst_level*2;
790
 
 
791
 
    if (diff >= STA_DISC_SAFE_SHRINKING_DIFF) {
792
 
        int seq_origin;
793
 
 
794
 
        /* Check and adjust jb_discard_ref, in case there was
795
 
         * seq restart
796
 
         */
797
 
        seq_origin = jb_framelist_origin(&jb->jb_framelist);
798
 
        if (seq_origin < jb->jb_discard_ref)
799
 
            jb->jb_discard_ref = seq_origin;
800
 
 
801
 
        if (seq_origin - jb->jb_discard_ref >= jb->jb_min_shrink_gap)
802
 
        {
803
 
            /* Shrink slowly, one frame per cycle */
804
 
            diff = 1;
805
 
 
806
 
            /* Drop frame(s)! */
807
 
            diff = jb_framelist_remove_head(&jb->jb_framelist, diff);
808
 
            jb->jb_discard_ref = jb_framelist_origin(&jb->jb_framelist);
809
 
            jb->jb_discard += diff;
810
 
 
811
 
            TRACE__((jb->jb_name.ptr,
812
 
                     "JB shrinking %d frame(s), cur size=%d", diff,
813
 
                     jb_framelist_eff_size(&jb->jb_framelist)));
814
 
        }
815
 
    }
816
 
}
817
 
 
818
 
 
819
 
static void jbuf_discard_progressive(pjmedia_jbuf *jb)
820
 
{
821
 
    unsigned cur_size, burst_level, overflow, T, discard_dist;
822
 
    int last_seq;
823
 
 
824
 
    /* Should be done in PUT operation */
825
 
    if (jb->jb_last_op != JB_OP_PUT)
826
 
        return;
827
 
 
828
 
    /* Check if latency is longer than burst */
829
 
    cur_size = jb_framelist_eff_size(&jb->jb_framelist);
830
 
    burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level);
831
 
    if (cur_size <= burst_level) {
832
 
        /* Reset any scheduled discard */
833
 
        jb->jb_discard_dist = 0;
834
 
        return;
835
 
    }
836
 
 
837
 
    /* Estimate discard duration needed for adjusting latency */
838
 
    if (burst_level <= PJMEDIA_JBUF_PRO_DISC_MIN_BURST)
839
 
        T = PJMEDIA_JBUF_PRO_DISC_T1;
840
 
    else if (burst_level >= PJMEDIA_JBUF_PRO_DISC_MAX_BURST)
841
 
        T = PJMEDIA_JBUF_PRO_DISC_T2;
842
 
    else
843
 
        T = PJMEDIA_JBUF_PRO_DISC_T1 +
844
 
            (PJMEDIA_JBUF_PRO_DISC_T2 - PJMEDIA_JBUF_PRO_DISC_T1) *
845
 
            (burst_level - PJMEDIA_JBUF_PRO_DISC_MIN_BURST) /
846
 
            (PJMEDIA_JBUF_PRO_DISC_MAX_BURST-PJMEDIA_JBUF_PRO_DISC_MIN_BURST);
847
 
 
848
 
    /* Calculate current discard distance */
849
 
    overflow = cur_size - burst_level;
850
 
    discard_dist = T / overflow / jb->jb_frame_ptime;
851
 
 
852
 
    /* Get last seq number in the JB */
853
 
    last_seq = jb_framelist_origin(&jb->jb_framelist) +
854
 
               jb_framelist_size(&jb->jb_framelist) - 1;
855
 
 
856
 
    /* Setup new discard schedule if none, otherwise, update the existing
857
 
     * discard schedule (can be delayed or accelerated).
858
 
     */
859
 
    if (jb->jb_discard_dist == 0) {
860
 
        /* Setup new discard schedule */
861
 
        jb->jb_discard_ref = last_seq;
862
 
    } else if (last_seq < jb->jb_discard_ref) {
863
 
        /* Seq restarted, update discard reference */
864
 
        jb->jb_discard_ref = last_seq;
865
 
    }
866
 
    jb->jb_discard_dist = PJ_MAX(jb->jb_min_shrink_gap, (int)discard_dist);
867
 
 
868
 
    /* Check if we need to discard now */
869
 
    if (last_seq >= (jb->jb_discard_ref + (int)jb->jb_discard_dist)) {
870
 
        int discard_seq;
871
 
 
872
 
        discard_seq = jb->jb_discard_ref + jb->jb_discard_dist;
873
 
        if (discard_seq < jb_framelist_origin(&jb->jb_framelist))
874
 
            discard_seq = jb_framelist_origin(&jb->jb_framelist);
875
 
 
876
 
        jb_framelist_discard(&jb->jb_framelist, discard_seq);
877
 
 
878
 
        TRACE__((jb->jb_name.ptr,
879
 
                "Discard #%d: ref=#%d dist=%d orig=%d size=%d/%d "
880
 
                "burst=%d/%d",
881
 
                discard_seq,
882
 
                jb->jb_discard_ref,
883
 
                jb->jb_discard_dist,
884
 
                jb_framelist_origin(&jb->jb_framelist),
885
 
                cur_size,
886
 
                jb_framelist_size(&jb->jb_framelist),
887
 
                jb->jb_eff_level,
888
 
                burst_level));
889
 
 
890
 
        /* Update discard reference */
891
 
        jb->jb_discard_ref = discard_seq;
892
 
    }
893
 
}
894
 
 
895
 
 
896
 
PJ_INLINE(void) jbuf_update(pjmedia_jbuf *jb, int oper)
897
 
{
898
 
    if(jb->jb_last_op != oper) {
899
 
        jb->jb_last_op = oper;
900
 
 
901
 
        if (jb->jb_status == JB_STATUS_INITIALIZING) {
902
 
            /* Switch status 'initializing' -> 'processing' after some OP
903
 
             * switch cycles and current OP is GET (burst level is calculated
904
 
             * based on PUT burst), so burst calculation is guaranted to be
905
 
             * performed right after the status switching.
906
 
             */
907
 
            if (++jb->jb_init_cycle_cnt >= INIT_CYCLE && oper == JB_OP_GET) {
908
 
                jb->jb_status = JB_STATUS_PROCESSING;
909
 
                /* To make sure the burst calculation will be done right after
910
 
                 * this, adjust burst level if it exceeds max burst level.
911
 
                 */
912
 
                jb->jb_level = PJ_MIN(jb->jb_level, jb->jb_max_burst);
913
 
            } else {
914
 
                jb->jb_level = 0;
915
 
                return;
916
 
            }
917
 
        }
918
 
 
919
 
        /* Perform jitter calculation based on PUT burst-level only, since
920
 
         * GET burst-level may not be accurate, e.g: when VAD is active.
921
 
         * Note that when burst-level is too big, i.e: exceeds jb_max_burst,
922
 
         * the GET op may be idle, in this case, we better skip the jitter
923
 
         * calculation.
924
 
         */
925
 
        if (oper == JB_OP_GET && jb->jb_level <= jb->jb_max_burst)
926
 
            jbuf_calculate_jitter(jb);
927
 
 
928
 
        jb->jb_level = 0;
929
 
    }
930
 
 
931
 
    /* Call discard algorithm */
932
 
    if (jb->jb_status == JB_STATUS_PROCESSING && jb->jb_discard_algo) {
933
 
        (*jb->jb_discard_algo)(jb);
934
 
    }
935
 
}
936
 
 
937
 
PJ_DEF(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb,
938
 
                                     const void *frame,
939
 
                                     pj_size_t frame_size,
940
 
                                     int frame_seq)
941
 
{
942
 
    pjmedia_jbuf_put_frame3(jb, frame, frame_size, 0, frame_seq, 0, NULL);
943
 
}
944
 
 
945
 
PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb,
946
 
                                     const void *frame,
947
 
                                     pj_size_t frame_size,
948
 
                                     pj_uint32_t bit_info,
949
 
                                     int frame_seq,
950
 
                                     pj_bool_t *discarded)
951
 
{
952
 
    pjmedia_jbuf_put_frame3(jb, frame, frame_size, bit_info, frame_seq, 0,
953
 
                            discarded);
954
 
}
955
 
 
956
 
PJ_DEF(void) pjmedia_jbuf_put_frame3(pjmedia_jbuf *jb,
957
 
                                     const void *frame,
958
 
                                     pj_size_t frame_size,
959
 
                                     pj_uint32_t bit_info,
960
 
                                     int frame_seq,
961
 
                                     pj_uint32_t ts,
962
 
                                     pj_bool_t *discarded)
963
 
{
964
 
    pj_size_t min_frame_size;
965
 
    int new_size, cur_size;
966
 
    pj_status_t status;
967
 
 
968
 
    cur_size = jb_framelist_eff_size(&jb->jb_framelist);
969
 
 
970
 
    /* Attempt to store the frame */
971
 
    min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size);
972
 
    status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame,
973
 
                                 min_frame_size, bit_info, ts,
974
 
                                 PJMEDIA_JB_NORMAL_FRAME);
975
 
 
976
 
    /* Jitter buffer is full, remove some older frames */
977
 
    while (status == PJ_ETOOMANY) {
978
 
        int distance;
979
 
        unsigned removed;
980
 
 
981
 
        /* Remove as few as possible just to make this frame in. Note that
982
 
         * the cases of seq-jump, out-of-order, and seq restart should have
983
 
         * been handled/normalized by previous call of jb_framelist_put_at().
984
 
         * So we're confident about 'distance' value here.
985
 
         */
986
 
        distance = (frame_seq - jb_framelist_origin(&jb->jb_framelist)) -
987
 
                   jb->jb_max_count + 1;
988
 
        pj_assert(distance > 0);
989
 
 
990
 
        removed = jb_framelist_remove_head(&jb->jb_framelist, distance);
991
 
        status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame,
992
 
                                     min_frame_size, bit_info, ts,
993
 
                                     PJMEDIA_JB_NORMAL_FRAME);
994
 
 
995
 
        jb->jb_discard += removed;
996
 
    }
997
 
 
998
 
    /* Get new JB size after PUT */
999
 
    new_size = jb_framelist_eff_size(&jb->jb_framelist);
1000
 
 
1001
 
    /* Return the flag if this frame is discarded */
1002
 
    if (discarded)
1003
 
        *discarded = (status != PJ_SUCCESS);
1004
 
 
1005
 
    if (status == PJ_SUCCESS) {
1006
 
        if (jb->jb_prefetching) {
1007
 
            TRACE__((jb->jb_name.ptr, "PUT prefetch_cnt=%d/%d",
1008
 
                     new_size, jb->jb_prefetch));
1009
 
            if (new_size >= jb->jb_prefetch)
1010
 
                jb->jb_prefetching = PJ_FALSE;
1011
 
        }
1012
 
        jb->jb_level += (new_size > cur_size ? new_size-cur_size : 1);
1013
 
        jbuf_update(jb, JB_OP_PUT);
1014
 
    } else
1015
 
        jb->jb_discard++;
1016
 
}
1017
 
 
1018
 
/*
1019
 
 * Get frame from jitter buffer.
1020
 
 */
1021
 
PJ_DEF(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,
1022
 
                                     void *frame,
1023
 
                                     char *p_frame_type)
1024
 
{
1025
 
    pjmedia_jbuf_get_frame3(jb, frame, NULL, p_frame_type, NULL,
1026
 
                            NULL, NULL);
1027
 
}
1028
 
 
1029
 
/*
1030
 
 * Get frame from jitter buffer.
1031
 
 */
1032
 
PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb,
1033
 
                                     void *frame,
1034
 
                                     pj_size_t *size,
1035
 
                                     char *p_frame_type,
1036
 
                                     pj_uint32_t *bit_info)
1037
 
{
1038
 
    pjmedia_jbuf_get_frame3(jb, frame, size, p_frame_type, bit_info,
1039
 
                            NULL, NULL);
1040
 
}
1041
 
 
1042
 
/*
1043
 
 * Get frame from jitter buffer.
1044
 
 */
1045
 
PJ_DEF(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb,
1046
 
                                     void *frame,
1047
 
                                     pj_size_t *size,
1048
 
                                     char *p_frame_type,
1049
 
                                     pj_uint32_t *bit_info,
1050
 
                                     pj_uint32_t *ts,
1051
 
                                     int *seq)
1052
 
{
1053
 
    if (jb->jb_prefetching) {
1054
 
 
1055
 
        /* Can't return frame because jitter buffer is filling up
1056
 
         * minimum prefetch.
1057
 
         */
1058
 
 
1059
 
        //pj_bzero(frame, jb->jb_frame_size);
1060
 
        *p_frame_type = PJMEDIA_JB_ZERO_PREFETCH_FRAME;
1061
 
        if (size)
1062
 
            *size = 0;
1063
 
 
1064
 
        TRACE__((jb->jb_name.ptr, "GET prefetch_cnt=%d/%d",
1065
 
                 jb_framelist_eff_size(&jb->jb_framelist), jb->jb_prefetch));
1066
 
 
1067
 
        jb->jb_empty++;
1068
 
 
1069
 
    } else {
1070
 
 
1071
 
        pjmedia_jb_frame_type ftype = PJMEDIA_JB_NORMAL_FRAME;
1072
 
        pj_bool_t res;
1073
 
 
1074
 
        /* Try to retrieve a frame from frame list */
1075
 
        res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype,
1076
 
                               bit_info, ts, seq);
1077
 
        if (res) {
1078
 
            /* We've successfully retrieved a frame from the frame list, but
1079
 
             * the frame could be a blank frame!
1080
 
             */
1081
 
            if (ftype == PJMEDIA_JB_NORMAL_FRAME) {
1082
 
                *p_frame_type = PJMEDIA_JB_NORMAL_FRAME;
1083
 
            } else {
1084
 
                *p_frame_type = PJMEDIA_JB_MISSING_FRAME;
1085
 
                jb->jb_lost++;
1086
 
            }
1087
 
 
1088
 
            /* Store delay history at the first GET */
1089
 
            if (jb->jb_last_op == JB_OP_PUT) {
1090
 
                unsigned cur_size;
1091
 
 
1092
 
                /* We've just retrieved one frame, so add one to cur_size */
1093
 
                cur_size = jb_framelist_eff_size(&jb->jb_framelist) + 1;
1094
 
                pj_math_stat_update(&jb->jb_delay,
1095
 
                                    cur_size*jb->jb_frame_ptime);
1096
 
            }
1097
 
        } else {
1098
 
            /* Jitter buffer is empty */
1099
 
            if (jb->jb_prefetch)
1100
 
                jb->jb_prefetching = PJ_TRUE;
1101
 
 
1102
 
            //pj_bzero(frame, jb->jb_frame_size);
1103
 
            *p_frame_type = PJMEDIA_JB_ZERO_EMPTY_FRAME;
1104
 
            if (size)
1105
 
                *size = 0;
1106
 
 
1107
 
            jb->jb_empty++;
1108
 
        }
1109
 
    }
1110
 
 
1111
 
    jb->jb_level++;
1112
 
    jbuf_update(jb, JB_OP_GET);
1113
 
}
1114
 
 
1115
 
/*
1116
 
 * Get jitter buffer state.
1117
 
 */
1118
 
PJ_DEF(pj_status_t) pjmedia_jbuf_get_state( const pjmedia_jbuf *jb,
1119
 
                                            pjmedia_jb_state *state )
1120
 
{
1121
 
    PJ_ASSERT_RETURN(jb && state, PJ_EINVAL);
1122
 
 
1123
 
    state->frame_size = jb->jb_frame_size;
1124
 
    state->min_prefetch = jb->jb_min_prefetch;
1125
 
    state->max_prefetch = jb->jb_max_prefetch;
1126
 
 
1127
 
    state->burst = jb->jb_eff_level;
1128
 
    state->prefetch = jb->jb_prefetch;
1129
 
    state->size = jb_framelist_eff_size(&jb->jb_framelist);
1130
 
 
1131
 
    state->avg_delay = jb->jb_delay.mean;
1132
 
    state->min_delay = jb->jb_delay.min;
1133
 
    state->max_delay = jb->jb_delay.max;
1134
 
    state->dev_delay = pj_math_stat_get_stddev(&jb->jb_delay);
1135
 
 
1136
 
    state->avg_burst = jb->jb_burst.mean;
1137
 
    state->empty = jb->jb_empty;
1138
 
    state->discard = jb->jb_discard;
1139
 
    state->lost = jb->jb_lost;
1140
 
 
1141
 
    return PJ_SUCCESS;
1142
 
}
1143
 
 
1144
 
 
1145
 
PJ_DEF(void) pjmedia_jbuf_peek_frame( pjmedia_jbuf *jb,
1146
 
                                      unsigned offset,
1147
 
                                      const void **frame,
1148
 
                                      pj_size_t *size,
1149
 
                                      char *p_frm_type,
1150
 
                                      pj_uint32_t *bit_info,
1151
 
                                      pj_uint32_t *ts,
1152
 
                                      int *seq)
1153
 
{
1154
 
    pjmedia_jb_frame_type ftype;
1155
 
    pj_bool_t res;
1156
 
 
1157
 
    res = jb_framelist_peek(&jb->jb_framelist, offset, frame, size, &ftype,
1158
 
                            bit_info, ts, seq);
1159
 
    if (!res)
1160
 
        *p_frm_type = PJMEDIA_JB_ZERO_EMPTY_FRAME;
1161
 
    else if (ftype == PJMEDIA_JB_NORMAL_FRAME)
1162
 
        *p_frm_type = PJMEDIA_JB_NORMAL_FRAME;
1163
 
    else
1164
 
        *p_frm_type = PJMEDIA_JB_MISSING_FRAME;
1165
 
}
1166
 
 
1167
 
 
1168
 
PJ_DEF(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb,
1169
 
                                           unsigned frame_cnt)
1170
 
{
1171
 
    unsigned count, last_discard_num;
1172
 
 
1173
 
    last_discard_num = jb->jb_framelist.discarded_num;
1174
 
    count = jb_framelist_remove_head(&jb->jb_framelist, frame_cnt);
1175
 
 
1176
 
    /* Remove some more when there were discarded frames included */
1177
 
    while (jb->jb_framelist.discarded_num < last_discard_num) {
1178
 
        /* Calculate frames count to be removed next */
1179
 
        frame_cnt = last_discard_num - jb->jb_framelist.discarded_num;
1180
 
 
1181
 
        /* Normalize non-discarded frames count just been removed */
1182
 
        count -= frame_cnt;
1183
 
 
1184
 
        /* Remove more frames */
1185
 
        last_discard_num = jb->jb_framelist.discarded_num;
1186
 
        count += jb_framelist_remove_head(&jb->jb_framelist, frame_cnt);
1187
 
    }
1188
 
 
1189
 
    return count;
1190
 
}