Ignore:
Timestamp:
Feb 9, 2006 2:01:40 PM (18 years ago)
Author:
bennylp
Message:

Updated with new jitter buffer, and statistics in pjsua

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/jbuf.c

    r129 r169  
    1818 */ 
    1919#include <pjmedia/jbuf.h> 
    20 #include <pj/log.h> 
     20#include <pjmedia/errno.h> 
    2121#include <pj/pool.h> 
    2222#include <pj/assert.h> 
     
    2424 
    2525 
    26 /* 
    27  * At the current state, this is basicly an ugly jitter buffer. 
    28  * It worked before by observing level, bit it doesn't work. 
    29  * Then I used the size, which makes the level obsolete. 
    30  * That's why it's ugly! 
    31  */ 
    32  
    33 #define MAX_SEQ_RANGE   1000    /* Range in which sequence is considered still within session */ 
    34 #define UPDATE_DURATION 20      /* Number of frames retrieved before jitter is updated */ 
    35  
    36 #define THIS_FILE   "jbuf" 
    37  
    38 /* Individual frame in the frame list. */  
    39 struct pj_jbframe 
    40 { 
    41     pj_uint32_t  extseq; 
    42     void        *buf; 
     26 
     27struct jb_framelist 
     28{ 
     29    char        *flist_buffer; 
     30    int         *flist_frame_type; 
     31    unsigned     flist_frame_size; 
     32    unsigned     flist_max_count; 
     33    unsigned     flist_empty; 
     34    unsigned     flist_head; 
     35    unsigned     flist_tail; 
     36    unsigned     flist_origin; 
    4337}; 
    4438 
    4539 
    46 /* Jitter buffer state. */  
    47 typedef enum jb_state_t 
    48 { 
    49     JB_PREFETCH, 
    50     JB_NORMAL, 
    51 } jb_state_t; 
    52  
    53  
    54 /* Jitter buffer last operation. */  
    55 typedef enum jb_op_t 
    56 { 
    57     JB_PUT, 
    58     JB_GET, 
    59 } jb_op_t; 
    60  
    61  
    62 /* Short name for convenience. */  
    63 typedef struct pj_jitter_buffer JB; 
    64  
    65  
    66 /* Initialize framelist. */  
    67 static pj_status_t 
    68 pj_framelist_init( pj_jbframelist *lst, pj_pool_t *pool, unsigned maxcount ) 
    69 { 
    70     PJ_LOG(5, (THIS_FILE, "..pj_frame_list_init [lst=%p], maxcount=%d", lst, maxcount)); 
    71  
    72     pj_memset(lst, 0, sizeof(*lst)); 
    73     lst->maxcount = maxcount; 
    74     lst->frames = pj_pool_calloc( pool, maxcount, sizeof(*lst->frames) ); 
    75     if (lst->frames == NULL) { 
    76         PJ_LOG(1,(THIS_FILE, "Unable to allocate frame list!")); 
    77         return -1; 
    78     } 
    79     return 0;     
    80 } 
    81  
    82 /* Reset framelist. */ 
    83 static void  
    84 pj_framelist_reset( pj_jbframelist *lst ) 
    85 { 
    86     PJ_LOG(6, (THIS_FILE, "..pj_frame_list_reset [lst=%p]", lst)); 
    87  
    88     lst->count = 0; 
    89     lst->head = 0; 
    90     lst->frames[0].extseq = 0; 
    91 } 
    92  
    93 /* Put a buffer with the specified sequence into the ordered list. */  
    94 static int  
    95 pj_framelist_put( pj_jbframelist *lst, pj_uint32_t extseq, void *buf ) 
    96 { 
    97     unsigned pos = (unsigned)-1; 
    98     pj_uint32_t startseq = lst->frames[lst->head].extseq; 
    99  
    100     if (lst->count == 0) { 
    101         /* Empty list. Initialize frame list. */ 
    102         PJ_LOG(6, (THIS_FILE, "    ..pj_frame_list_put [lst=%p], empty, seq=%u@pos=%d",  
    103                    lst, extseq, lst->head)); 
    104  
    105         lst->head = 0; 
    106         lst->count = 1; 
    107         lst->frames[0].buf = buf; 
    108         lst->frames[0].extseq = extseq; 
    109         return 0; 
     40typedef struct jb_framelist jb_framelist; 
     41 
     42struct pjmedia_jbuf 
     43{ 
     44    jb_framelist    jb_framelist; 
     45    pj_size_t       jb_frame_size;        // frame size  
     46    pj_size_t       jb_max_count;         // max frames in the jitter framelist->flist_buffer 
     47 
     48    int             jb_level;             // delay between source & destination 
     49                                          // (calculated according of the number of get/put operations) 
     50    int             jb_last_level;        // last delay  
     51    int             jb_last_jitter;       // last jitter calculated 
     52    int             jb_max_hist_jitter;   // max jitter during the last jitter calculations 
     53    int             jb_stable_hist;       // num of times the delay has been lower then the prefetch num 
     54    int             jb_last_op;           // last operation executed on the framelist->flist_buffer (put/get) 
     55    int             jb_last_seq_no;       // seq no. of the last frame inserted to the framelist->flist_buffer 
     56    int             jb_prefetch;          // no. of frame to insert before removing some 
     57                                          // (at the beginning of the framelist->flist_buffer operation) 
     58    int             jb_prefetch_cnt;      // prefetch counter 
     59    int             jb_status;            // status is 'init' until the first 'put' operation 
     60 
     61 
     62}; 
     63 
     64 
     65#define JB_STATUS_INITIALIZING  0 
     66#define JB_STATUS_PROCESSING    1 
     67 
     68#define PJ_ABS(x)       ((x > 0) ? (x) : -(x)) 
     69#define PJ_MAX(x, y)    ((x > y) ? (x) : (y)) 
     70#define PJ_MIN(x, y)    ((x < y) ? (x) : (y)) 
     71 
     72 
     73 
     74static pj_status_t jb_framelist_init( pj_pool_t *pool, 
     75                                      jb_framelist *framelist, 
     76                                      unsigned frame_size, 
     77                                      unsigned max_count)  
     78{ 
     79    PJ_ASSERT_RETURN(pool && framelist, PJ_EINVAL); 
     80 
     81    pj_memset(framelist, 0, sizeof(jb_framelist)); 
     82 
     83    framelist->flist_frame_size = frame_size; 
     84    framelist->flist_max_count = max_count; 
     85    framelist->flist_buffer = pj_pool_zalloc(pool, 
     86                                             framelist->flist_frame_size *  
     87                                             framelist->flist_max_count); 
     88 
     89    framelist->flist_frame_type = pj_pool_zalloc(pool,  
     90                                                 sizeof(framelist->flist_frame_type[0]) *  
     91                                                 framelist->flist_max_count); 
     92 
     93    framelist->flist_empty = 1; 
     94    framelist->flist_head = framelist->flist_tail = framelist->flist_origin = 0; 
     95 
     96    return PJ_SUCCESS; 
     97 
     98} 
     99 
     100static pj_status_t jb_framelist_destroy(jb_framelist *framelist)  
     101{ 
     102    PJ_UNUSED_ARG(framelist); 
     103    return PJ_SUCCESS; 
     104} 
     105 
     106 
     107static unsigned jb_framelist_size(jb_framelist *framelist)  
     108{ 
     109    if (framelist->flist_tail == framelist->flist_head) { 
     110        return framelist->flist_empty ? 0 : framelist->flist_max_count; 
     111    } else { 
     112        return (framelist->flist_tail - framelist->flist_head +  
     113                framelist->flist_max_count) % framelist->flist_max_count; 
     114    } 
     115} 
     116 
     117 
     118static pj_bool_t jb_framelist_get(jb_framelist *framelist, 
     119                                  void *frame, 
     120                                  pjmedia_jb_frame_type *p_type)  
     121{ 
     122    if (!framelist->flist_empty) { 
     123        pj_memcpy(frame,  
     124                  framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 
     125                  framelist->flist_frame_size); 
     126        *p_type = (pjmedia_jb_frame_type) framelist->flist_frame_type[framelist->flist_head]; 
     127 
     128        pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 
     129                  0, framelist->flist_frame_size); 
     130        framelist->flist_frame_type[framelist->flist_head] = 0; 
     131 
     132        framelist->flist_origin++; 
     133        framelist->flist_head = ++framelist->flist_head % framelist->flist_max_count; 
     134        if (framelist->flist_head == framelist->flist_tail)  
     135            framelist->flist_empty = PJ_TRUE; 
    110136         
    111     } else if (extseq < startseq) { 
    112         /* The sequence number is lower than our oldest packet. This can mean 
    113            two things: 
    114             - old packet has been receieved, or 
    115             - the sequence number has wrapped around. 
    116          */   
    117         if (startseq + lst->maxcount <= extseq) { 
    118             /* The sequence number has wrapped around, but it is beyond 
    119                the capacity of the list (i.e. too soon). 
    120              */ 
    121             PJ_LOG(5, (THIS_FILE, "    ..pj_frame_list_put TOO_SOON! [lst=%p] seq=%u, startseq=%d",  
    122                        lst, extseq, startseq)); 
    123             return PJ_JB_STATUS_TOO_SOON; 
    124  
    125         } else if (startseq-extseq > lst->maxcount && startseq+lst->maxcount > extseq) { 
    126             /* The sequence number has wrapped around, and it is still inside 
    127                the 'window' of the framelist. 
    128              */ 
    129             pos = extseq - startseq; 
     137        return PJ_TRUE; 
     138 
     139    } else { 
     140        pj_memset(frame, 0, framelist->flist_frame_size); 
     141        return PJ_FALSE; 
     142    } 
     143} 
     144 
     145 
     146static void jb_framelist_remove_head( jb_framelist *framelist, 
     147                                      unsigned count)  
     148{ 
     149    unsigned cur_size; 
     150 
     151    cur_size = jb_framelist_size(framelist); 
     152    if (count > cur_size)  
     153        count = cur_size; 
     154 
     155    if (count) { 
     156        // may be done in two steps if overlapping 
     157        unsigned step1,step2; 
     158        unsigned tmp = framelist->flist_head+count; 
     159 
     160        if (tmp > framelist->flist_max_count) { 
     161            step1 = framelist->flist_max_count - framelist->flist_head; 
     162            step2 = count-step1; 
    130163        } else { 
    131             /* The new frame is too old. */ 
    132             PJ_LOG(5, (THIS_FILE, "    ..pj_frame_list_put TOO_OLD! [lst=%p] seq=%u, startseq=%d",  
    133                        lst, extseq, startseq)); 
    134             return PJ_JB_STATUS_TOO_OLD; 
     164            step1 = count; 
     165            step2 = 0; 
    135166        } 
    136          
    137     } else if (extseq > startseq + lst->maxcount) { 
    138         /* Two possibilities here. Either: 
    139             - packet is really too soon, or 
    140             - sequence number of startseq has just wrapped around, and old packet 
    141               which hasn't wrapped is received. 
    142          */ 
    143         if (extseq < MAX_SEQ_RANGE /*approx 20 seconds with 50 fps*/) { 
    144             PJ_LOG(5, (THIS_FILE, "    ..pj_frame_list_put TOO_SOON! [lst=%p] seq=%u, startseq=%d",  
    145                        lst, extseq, startseq)); 
    146             return PJ_JB_STATUS_TOO_SOON; 
    147         } else { 
    148             PJ_LOG(5, (THIS_FILE, "    ..pj_frame_list_put TOO_OLD! [lst=%p] seq=%u, startseq=%d",  
    149                        lst, extseq, startseq)); 
    150             return PJ_JB_STATUS_TOO_OLD; 
     167 
     168        pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 
     169                  0, 
     170                  step1*framelist->flist_frame_size); 
     171        pj_memset(framelist->flist_frame_type+framelist->flist_head, 
     172                  0, 
     173                  step1*sizeof(framelist->flist_frame_type[0])); 
     174 
     175        if (step2) { 
     176            pj_memset(framelist->flist_buffer, 
     177                      0, 
     178                      step2*framelist->flist_frame_size); 
     179            pj_memset(framelist->flist_frame_type, 
     180                      0, 
     181                      step2*sizeof(framelist->flist_frame_type[0])); 
    151182        } 
    152     }  
    153  
    154     /* The new frame is within the framelist capacity. 
    155        Calculate position where to put it in the list. 
    156      */ 
    157     if (pos == (unsigned)-1) 
    158         pos = ((extseq - startseq) + lst->head) % lst->maxcount; 
    159  
    160     pj_assert(pos < lst->maxcount); 
    161      
    162     /* Update count only if we're not overwriting existing frame. */ 
    163     if (lst->frames[pos].buf == NULL) 
    164         ++lst->count; 
    165  
    166     lst->frames[pos].buf = buf; 
    167     lst->frames[pos].extseq = extseq; 
    168  
    169     PJ_LOG(6, (THIS_FILE, "    ..pj_frame_list_put [lst=%p] seq=%u, startseq=%d, head=%d, pos=%d",  
    170                lst, extseq, startseq, lst->head, pos)); 
    171     return 0; 
    172 } 
    173  
    174 /* Get the first element of the list. */  
    175 static int  
    176 pj_framelist_get( pj_jbframelist *lst, pj_uint32_t *extseq, void **buf ) 
    177 { 
    178     if (lst->count == 0) { 
    179         /* Empty. */ 
    180         *buf = NULL; 
    181         *extseq = 0; 
    182         PJ_LOG(6, (THIS_FILE, "    ..pj_frame_list_get [lst=%p], empty!", lst)); 
    183         return -1; 
    184          
    185     } else { 
    186         *buf = lst->frames[lst->head].buf; 
    187         *extseq = lst->frames[lst->head].extseq; 
    188         lst->frames[lst->head].buf = NULL; 
    189  
    190         PJ_LOG(6, (THIS_FILE, "    ..pj_frame_list_get [lst=%p] seq=%u, head=%d",  
    191                    lst, *extseq, lst->head)); 
    192  
    193         lst->head = (lst->head + 1) % lst->maxcount; 
    194         --lst->count; 
    195         return 0; 
    196     } 
    197 } 
    198  
    199  
    200 /***************************************************************************** 
    201  * Reset jitter buffer.  
    202  **************************************************************************** 
    203 */ 
    204 PJ_DEF(void) pj_jb_reset(JB *jb) 
    205 { 
    206     PJ_LOG(6, (THIS_FILE, "pj_jb_reset [jb=%p]", jb)); 
    207  
    208     jb->level = jb->max_level = 1; 
    209     jb->prefetch = jb->min; 
    210     jb->get_cnt = 0; 
    211     jb->lastseq = 0; 
    212     jb->state = JB_PREFETCH; 
    213     jb->upd_count = 0; 
    214     jb->last_op = -1; 
    215     pj_framelist_reset( &jb->lst ); 
    216 } 
    217  
    218  
    219 /***************************************************************************** 
    220  * Create jitter buffer. 
    221  ***************************************************************************** 
    222  */  
    223 PJ_DEF(pj_status_t) pj_jb_init( pj_jitter_buffer *jb, pj_pool_t *pool,  
    224                                 unsigned min, unsigned max, unsigned maxcount) 
    225 { 
     183 
     184        // update pointers 
     185        framelist->flist_origin += count; 
     186        framelist->flist_head = (framelist->flist_head+count) % framelist->flist_max_count; 
     187        if (framelist->flist_head == framelist->flist_tail)  
     188            framelist->flist_empty = PJ_TRUE; 
     189    } 
     190} 
     191 
     192 
     193static pj_bool_t jb_framelist_put_at(jb_framelist *framelist, 
     194                                     unsigned index, 
     195                                     const void *frame, 
     196                                     unsigned frame_size)  
     197{ 
     198    unsigned where; 
     199 
     200    // too late 
     201    if (index < framelist->flist_origin)  
     202        return PJ_FALSE; 
     203 
     204    // too soon 
     205    if ((index > (framelist->flist_origin + framelist->flist_max_count - 1)) && !framelist->flist_empty)  
     206        return PJ_FALSE; 
     207 
     208    assert(frame_size <= framelist->flist_frame_size); 
     209 
     210    if (!framelist->flist_empty) { 
     211        unsigned cur_size; 
     212 
     213        where = (index - framelist->flist_origin + framelist->flist_head) % framelist->flist_max_count; 
     214 
     215        // update framelist->flist_tail pointer 
     216        cur_size = jb_framelist_size(framelist); 
     217        if (index >= framelist->flist_origin + cur_size) { 
     218            unsigned diff = (index - (framelist->flist_origin + cur_size)); 
     219            framelist->flist_tail = (framelist->flist_tail + diff + 1) % framelist->flist_max_count; 
     220        } 
     221    } else { 
     222        where = framelist->flist_tail; 
     223        framelist->flist_origin = index; 
     224        framelist->flist_tail = (++framelist->flist_tail % framelist->flist_max_count); 
     225        framelist->flist_empty = PJ_FALSE; 
     226    } 
     227 
     228    pj_memcpy(framelist->flist_buffer + where * framelist->flist_frame_size,  
     229              frame, frame_size); 
     230 
     231    framelist->flist_frame_type[where] = PJMEDIA_JB_NORMAL_FRAME; 
     232 
     233    return PJ_TRUE; 
     234} 
     235 
     236 
     237 
     238enum pjmedia_jb_op 
     239{ 
     240    JB_OP_INIT  = -1, 
     241    JB_OP_PUT   = 1, 
     242    JB_OP_GET   = 2 
     243}; 
     244 
     245 
     246PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool,  
     247                                        int frame_size,  
     248                                        int initial_prefetch,  
     249                                        int max_count, 
     250                                        pjmedia_jbuf **p_jb) 
     251{ 
     252    pjmedia_jbuf *jb; 
    226253    pj_status_t status; 
    227254 
    228     if (maxcount <= max) { 
    229         maxcount = max * 5 / 4; 
    230         PJ_LOG(3,(THIS_FILE, "Jitter buffer maximum count was adjusted.")); 
    231     } 
    232  
    233     jb->min = min; 
    234     jb->max = max; 
    235  
    236     status = pj_framelist_init( &jb->lst, pool, maxcount ); 
     255    jb = pj_pool_zalloc(pool, sizeof(pjmedia_jbuf)); 
     256 
     257    status = jb_framelist_init(pool, &jb->jb_framelist, frame_size, max_count); 
    237258    if (status != PJ_SUCCESS) 
    238259        return status; 
    239260 
    240     pj_jb_reset(jb); 
    241  
    242     PJ_LOG(4, (THIS_FILE, "pj_jb_init success [jb=%p], min=%d, max=%d, maxcount=%d",  
    243                           jb, min, max, maxcount)); 
     261    jb->jb_frame_size    = frame_size; 
     262    jb->jb_last_seq_no   = -1; 
     263    jb->jb_level         = 0; 
     264    jb->jb_last_level    = 0; 
     265    jb->jb_last_jitter   = 0; 
     266    jb->jb_last_op       = JB_OP_INIT; 
     267    jb->jb_prefetch      = PJ_MIN(initial_prefetch, max_count*4/5); 
     268    jb->jb_prefetch_cnt  = 0; 
     269    jb->jb_stable_hist   = 0; 
     270    jb->jb_status        = JB_STATUS_INITIALIZING; 
     271    jb->jb_max_hist_jitter = 0; 
     272    jb->jb_max_count     = max_count; 
     273 
     274    *p_jb = jb; 
    244275    return PJ_SUCCESS; 
    245276} 
    246277 
    247278 
    248 /***************************************************************************** 
    249  * Put a packet to the jitter buffer. 
    250  ***************************************************************************** 
    251  */  
    252 PJ_DEF(pj_status_t) pj_jb_put( JB *jb, pj_uint32_t extseq, void *buf ) 
    253 { 
    254     unsigned distance; 
    255     int status; 
     279PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb) 
     280{ 
     281    return jb_framelist_destroy(&jb->jb_framelist); 
     282} 
     283 
     284 
     285static void jbuf_calculate_jitter(pjmedia_jbuf *jb) 
     286{ 
     287    enum { STABLE_HISTORY_LIMIT = (500/20) }; 
     288 
     289    jb->jb_last_jitter = PJ_ABS(jb->jb_level-jb->jb_last_level); 
     290    jb->jb_last_level = jb->jb_level; 
     291    jb->jb_max_hist_jitter = PJ_MAX(jb->jb_max_hist_jitter,jb->jb_last_jitter); 
    256292     
    257     PJ_LOG(6, (THIS_FILE, "==> pj_jb_put [jb=%p], seq=%u, buf=%p", jb, extseq, buf)); 
    258  
    259     if (jb->lastseq == 0) 
    260         jb->lastseq = extseq - 1; 
    261  
    262     /* Calculate distance between this packet and last received packet 
    263        to detect long jump (indicating probably remote has just been 
    264        restarted. 
    265      */ 
    266     distance = (extseq > jb->lastseq) ? extseq - jb->lastseq : jb->lastseq - extseq; 
    267     if (distance > MAX_SEQ_RANGE) { 
    268         /* Distance is out of range, reset jitter while maintaining current jitter 
    269            level. 
    270          */ 
    271         int old_level = jb->level; 
    272         int old_prefetch = jb->prefetch; 
    273  
    274         PJ_LOG(4, (THIS_FILE, "    ..[jb=%p] distance out of range, resetting", jb)); 
    275  
    276         pj_jb_reset(jb); 
    277         jb->level = old_level; 
    278         jb->prefetch = old_prefetch; 
    279         distance = 1; 
    280         jb->lastseq = extseq - 1; 
    281     } 
    282      
    283     jb->lastseq = extseq; 
    284  
    285     status = pj_framelist_put( &jb->lst, extseq, buf ); 
    286     if (status == PJ_JB_STATUS_TOO_OLD) 
    287         return -1; 
    288  
    289     if (status == PJ_JB_STATUS_TOO_SOON) { 
    290         /* TODO: discard old packets.. */ 
    291         /* No, don't do it without putting a way to inform application so that 
    292            it can free the memory */ 
    293     } 
    294  
    295  
    296     if (jb->last_op != JB_PUT) { 
    297         if (jb->state != JB_PREFETCH) 
    298             jb->level--; 
    299     } else { 
    300         jb->level++; 
    301     } 
    302  
    303     if ((int)jb->lst.count > jb->max_level) 
    304         jb->max_level++; 
    305  
    306     jb->last_op = JB_PUT; 
    307     return 0; 
    308 } 
    309  
    310  
    311 /* 
    312  * Update jitter buffer algorithm. 
    313  */ 
    314 static void jb_update(JB *jb, int apply, int log_info) 
    315 { 
    316     unsigned abs_level = jb->max_level > 0 ? jb->max_level : -jb->max_level; 
    317     unsigned new_prefetch; 
    318  
    319     /* Update prefetch count */ 
    320     if (abs_level > jb->prefetch) 
    321         new_prefetch = (jb->prefetch + abs_level*9 + 1) / 10; 
    322     else { 
    323         new_prefetch = (jb->prefetch*4 + abs_level) / 5; 
    324         pj_assert(new_prefetch <= jb->prefetch); 
    325     } 
    326  
    327     if (log_info) { 
    328         PJ_LOG(5, (THIS_FILE, "    ..jb_update [jb=%p], level=%d, max_level=%d, old_prefetch=%d, new_prefetch=%d",  
    329                               jb, jb->level, jb->max_level, jb->prefetch, new_prefetch)); 
    330     } else { 
    331         PJ_LOG(6, (THIS_FILE, "    ..jb_update [jb=%p], level=%d, max_level=%d, old_prefetch=%d, new_prefetch=%d",  
    332                               jb, jb->level, jb->max_level, jb->prefetch, new_prefetch)); 
    333     } 
    334  
    335     if (new_prefetch < jb->min) new_prefetch = jb->min; 
    336     if (new_prefetch > jb->max) new_prefetch = jb->max; 
    337  
    338     /* If jitter buffer is empty, set state to JB_PREFETCH, taking care of the 
    339        new prefetch setting. 
    340      */ 
    341     if (jb->lst.count == 0) { 
    342         jb->state = JB_PREFETCH; 
    343         jb->get_cnt = 0; 
    344     } else { 
    345         /* Check if delay is too long, which in this case probably better to 
    346            discard some frames.. 
    347          */ 
    348         /* No, don't do it without putting a way to inform application so that 
    349            it can free the memory */ 
    350     } 
    351  
    352  
    353     if (apply) { 
    354         jb->prefetch = new_prefetch; 
    355         if (jb->max_level > 0) 
    356             jb->max_level--; 
    357     } else { 
    358         jb->level = new_prefetch; 
    359     } 
    360 } 
    361  
    362  
    363 /***************************************************************************** 
    364  * Get the oldest frame from jitter buffer. 
    365  ***************************************************************************** 
    366  */  
    367 PJ_DEF(pj_status_t) pj_jb_get( JB *jb, pj_uint32_t *extseq, void **buf ) 
    368 { 
    369     pj_status_t status; 
    370      
    371     PJ_LOG(6, (THIS_FILE, "<== pj_jb_get [jb=%p]", jb)); 
    372  
    373     /* 
    374      * Check whether we're ready to give frame. When we're in JB_PREFETCH state, 
    375      * only give frames only when: 
    376      *  - the buffer has enough frames in it (jb->list.count > jb->prefetch), OR 
    377      *  - after 'prefetch' attempts, there's still no frame, which in this 
    378      *    case PJ_JB_STATUS_FRAME_NULL will be returned by the next check. 
    379      */ 
    380     if (jb->state == JB_PREFETCH && jb->lst.count <= jb->prefetch && jb->get_cnt < jb->prefetch) { 
    381         jb->get_cnt++;    
    382         jb->last_op = JB_GET; 
    383         PJ_LOG(5, (THIS_FILE, "    ..[jb=%p] bufferring...", jb)); 
    384         return PJ_JB_STATUS_FRAME_NULL; 
    385     } 
    386  
    387     /* Attempt to get one frame from the list. */ 
    388     status = pj_framelist_get( &jb->lst, extseq, buf ); 
    389     if (status != 0) { 
    390         PJ_LOG(6, (THIS_FILE, "    ..[jb=%p] no packet!", jb)); 
    391         status = jb->lst.count ? PJ_JB_STATUS_FRAME_MISSING : PJ_JB_STATUS_FRAME_NULL; 
    392         jb_update(jb, 1, 0); 
    393         return status; 
    394     } 
    395  
    396     /* Force state to NORMAL */ 
    397     jb->state = JB_NORMAL; 
    398  
    399     /* Increase level only when last operation is GET. 
    400      * This is to prevent level from increasing during silence period, which 
    401      * no packets is receieved. 
    402      */ 
    403     if (jb->last_op != JB_GET) { 
    404         int apply; 
    405  
    406         //jb->level++; 
    407         jb->last_op = JB_GET; 
    408  
    409         apply = (++jb->upd_count > UPDATE_DURATION); 
    410         if (apply) 
    411             jb->upd_count = 0; 
    412  
    413         jb_update(jb, apply, apply); 
    414     } 
    415  
    416     PJ_LOG(6, (THIS_FILE, "    ..[jb=%p] seq=%u, level=%d, prefetch=%d, size=%u, delay=%d",  
    417                           jb, *extseq, jb->level, jb->prefetch, jb->lst.count, 
    418                           jb->lastseq - *extseq)); 
    419     return 0; 
    420 } 
    421  
    422  
     293    if (jb->jb_last_jitter< jb->jb_prefetch) { 
     294        jb->jb_stable_hist += jb->jb_last_jitter; 
     295        if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) { 
     296            int seq_diff = (jb->jb_prefetch - jb->jb_max_hist_jitter)/3; 
     297            if (seq_diff<1) seq_diff = 1; 
     298 
     299            jb->jb_prefetch -= seq_diff; 
     300            if (jb->jb_prefetch < 1) jb->jb_prefetch = 1; 
     301 
     302            jb->jb_stable_hist = 0; 
     303            jb->jb_max_hist_jitter = 0; 
     304        } 
     305    } else { 
     306        jb->jb_prefetch = PJ_MIN(jb->jb_last_jitter,(int)(jb->jb_max_count*4/5)); 
     307        jb->jb_stable_hist = 0; 
     308        jb->jb_max_hist_jitter = 0; 
     309    } 
     310} 
     311 
     312static void jbuf_update(pjmedia_jbuf *jb, int oper) 
     313{ 
     314    if(jb->jb_last_op != oper) { 
     315        jbuf_calculate_jitter(jb); 
     316        jb->jb_last_op = oper; 
     317    } 
     318} 
     319 
     320PJ_DEF(pj_status_t) pjmedia_jbuf_put_frame(pjmedia_jbuf *jb,  
     321                                           const void *frame,  
     322                                           pj_size_t frame_size,  
     323                                           int frame_seq) 
     324{ 
     325    pj_size_t min_frame_size; 
     326    int seq_diff; 
     327 
     328    if (jb->jb_last_seq_no == -1)       { 
     329        jb->jb_last_seq_no = frame_seq - 1; 
     330    } 
     331 
     332    seq_diff = frame_seq - jb->jb_last_seq_no; 
     333    jb->jb_last_seq_no = PJ_MAX(jb->jb_last_seq_no, frame_seq); 
     334    if (seq_diff > 0) jb->jb_level += seq_diff; 
     335 
     336    if(jb->jb_status == JB_STATUS_INITIALIZING) { 
     337        jb->jb_status = JB_STATUS_PROCESSING; 
     338        jb->jb_level = 0; 
     339        jb->jb_last_level = 0; 
     340        jb->jb_last_jitter = 0; 
     341    } else { 
     342        jbuf_update(jb, JB_OP_PUT); 
     343    } 
     344 
     345    min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size); 
     346    if (seq_diff > 0) { 
     347 
     348        while (!jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size)) { 
     349            jb_framelist_remove_head(&jb->jb_framelist,PJ_MAX(jb->jb_max_count/4,1)); 
     350        } 
     351 
     352        if (jb->jb_prefetch_cnt < jb->jb_prefetch)       
     353            jb->jb_prefetch_cnt += seq_diff; 
     354 
     355    } 
     356    else 
     357    { 
     358        jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size); 
     359    } 
     360 
     361    return PJ_SUCCESS; 
     362} 
     363 
     364PJ_DEF(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,  
     365                                            void *frame,  
     366                                            char *p_frame_type) 
     367{ 
     368    pjmedia_jb_frame_type ftype; 
     369 
     370    jb->jb_level--; 
     371 
     372    jbuf_update(jb, JB_OP_GET); 
     373 
     374    if (jb_framelist_size(&jb->jb_framelist) == 0) { 
     375        jb->jb_prefetch_cnt = 0; 
     376    } 
     377 
     378    if ((jb->jb_prefetch_cnt < jb->jb_prefetch) || !jb_framelist_get(&jb->jb_framelist,frame,&ftype)) { 
     379        pj_memset(frame, 0, jb->jb_frame_size); 
     380        *p_frame_type = PJMEDIA_JB_ZERO_FRAME; 
     381        return PJ_SUCCESS; 
     382    } 
     383 
     384    if (ftype == PJMEDIA_JB_NORMAL_FRAME) { 
     385        *p_frame_type   = PJMEDIA_JB_NORMAL_FRAME; 
     386    } else { 
     387        *p_frame_type   = PJMEDIA_JB_MISSING_FRAME; 
     388    } 
     389 
     390    return PJ_SUCCESS; 
     391} 
     392 
     393PJ_DEF(unsigned) pjmedia_jbuf_get_prefetch_size(pjmedia_jbuf *jb) 
     394{ 
     395    return jb->jb_prefetch; 
     396} 
     397 
     398PJ_DEF(unsigned) pjmedia_jbuf_get_current_size(pjmedia_jbuf *jb) 
     399{ 
     400    return jb_framelist_size(&jb->jb_framelist); 
     401} 
     402 
     403 
Note: See TracChangeset for help on using the changeset viewer.