Ignore:
Timestamp:
Jan 20, 2010 1:02:37 AM (11 years ago)
Author:
nanang
Message:

Ticket #969:

  • implemented progressive discard algorithm, discard rate is calculated from ratio of effective size to effective burst level.
  • updated jbuf to clarify prefetch and burst level distinction, previously they are stored in same var, i.e: prefetch, while the semantic is actually different.
  • updated STABLE_HISTORY_LIMIT in jbuf, it is now 20 (was 100), to adjust burst level faster.
  • added test case of periodic-spike-burst-case in jbtest.dat for testing the new algorithm.
  • updated stream to limit the rate of jbuf empty/lost log messages, it will only log first empty/lost event, then log again once jbuf returning normal frame (also counter of previous empty/lost frames).
  • minor updates on jbuf.c: variable names, logs, added burst to jbuf state.
  • minor updates on jbuf_test.c: handle comment in test session header, seq jump is now 20 (was 5000).
File:
1 edited

Legend:

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

    r3015 r3065  
    7373    unsigned         head;              /**< index of head, pointed frame 
    7474                                             will be returned by next GET   */ 
    75     unsigned         size;              /**< current size of framelist.     */ 
     75    unsigned         size;              /**< current size of framelist,  
     76                                             including discarded frames.    */ 
     77    unsigned         discarded_num;     /**< current number of discarded  
     78                                             frames.                        */ 
    7679    int              origin;            /**< original index of flist_head   */ 
     80 
    7781} jb_framelist_t; 
    7882 
     
    8690    pj_size_t       jb_max_count;       /**< capacity of jitter buffer,  
    8791                                             in frames                      */ 
    88     int             jb_def_prefetch;    /**< Default prefetch               */ 
     92    int             jb_init_prefetch;   /**< Initial prefetch               */ 
    8993    int             jb_min_prefetch;    /**< Minimum allowable prefetch     */ 
    9094    int             jb_max_prefetch;    /**< Maximum allowable prefetch     */ 
     
    109113    int             jb_last_op;         /**< last operation executed  
    110114                                             (put/get)                      */ 
     115    int             jb_eff_level;       /**< effective burst level          */ 
    111116    int             jb_prefetch;        /**< no. of frame to insert before  
    112117                                             removing some (at the beginning  
     
    121126    int             jb_last_del_seq;    /**< Seq # of last frame deleted    */ 
    122127 
     128    int             jb_last_discard_seq;/**< Seq # of last frame discarded  */ 
     129 
    123130    /* Statistics */ 
    124131    pj_math_stat    jb_delay;           /**< Delay statistics of jitter buffer  
     
    136143#define JB_STATUS_PREFETCHING   2 
    137144 
     145 
     146/* === Experimental feature === */ 
     147 
     148/* Progressive discard algorithm introduced to reduce JB latency 
     149 * by discarding incoming frames with adaptive aggressiveness based on 
     150 * actual burst level. 
     151 */ 
     152#define PROGRESSIVE_DISCARD 1 
     153 
     154/* Internal JB frame flag, discarded frame will not be returned by JB to 
     155 * application, it's just simply discarded. 
     156 */ 
     157#define PJMEDIA_JB_DISCARDED_FRAME 1024 
     158 
     159/* == End of experimental feature == */ 
     160 
     161 
    138162/* Enabling this would log the jitter buffer state about once per  
    139163 * second. 
     
    146170 
    147171static pj_status_t jb_framelist_reset(jb_framelist_t *framelist); 
     172static unsigned jb_framelist_remove_head(jb_framelist_t *framelist, 
     173                                         unsigned count); 
    148174 
    149175static pj_status_t jb_framelist_init( pj_pool_t *pool, 
     
    175201                                            framelist->max_count); 
    176202 
     203 
    177204    return jb_framelist_reset(framelist); 
    178205 
     
    190217    framelist->origin = INVALID_OFFSET; 
    191218    framelist->size = 0; 
     219    framelist->discarded_num = 0; 
     220 
    192221 
    193222    //pj_bzero(framelist->content,  
     
    218247 
    219248 
     249static unsigned jb_framelist_eff_size(const jb_framelist_t *framelist)  
     250{ 
     251    return (framelist->size - framelist->discarded_num); 
     252} 
     253 
     254static int jb_framelist_origin(const jb_framelist_t *framelist)  
     255{ 
     256    return framelist->origin; 
     257} 
     258 
     259 
    220260static pj_bool_t jb_framelist_get(jb_framelist_t *framelist, 
    221261                                  void *frame, pj_size_t *size, 
     
    224264{ 
    225265    if (framelist->size) { 
    226         pj_memcpy(frame,  
    227                   framelist->content +  
    228                   framelist->head * framelist->frame_size, 
    229                   framelist->frame_size); 
    230         *p_type = (pjmedia_jb_frame_type)  
    231                   framelist->frame_type[framelist->head]; 
    232         if (size) 
    233             *size   = framelist->content_len[framelist->head]; 
    234         if (bit_info) 
    235             *bit_info = framelist->bit_info[framelist->head]; 
    236  
    237         //pj_bzero(framelist->content +  
    238         //       framelist->head * framelist->frame_size, 
    239         //       framelist->frame_size); 
    240         framelist->frame_type[framelist->head] = PJMEDIA_JB_MISSING_FRAME; 
    241         framelist->content_len[framelist->head] = 0; 
    242         framelist->bit_info[framelist->head] = 0; 
    243  
    244         framelist->origin++; 
    245         framelist->head = (framelist->head + 1) % framelist->max_count; 
    246         framelist->size--; 
    247          
    248         return PJ_TRUE; 
    249     } else { 
    250         pj_bzero(frame, framelist->frame_size); 
    251  
    252         return PJ_FALSE; 
    253     } 
    254 } 
    255  
    256  
     266 
     267        /* Skip discarded frames */ 
     268        while (framelist->frame_type[framelist->head] == 
     269               PJMEDIA_JB_DISCARDED_FRAME) 
     270        { 
     271            jb_framelist_remove_head(framelist, 1); 
     272        } 
     273 
     274        /* Return the head frame if any */ 
     275        if (framelist->size) { 
     276            pj_memcpy(frame,  
     277                      framelist->content +  
     278                      framelist->head * framelist->frame_size, 
     279                      framelist->frame_size); 
     280            *p_type = (pjmedia_jb_frame_type)  
     281                      framelist->frame_type[framelist->head]; 
     282            if (size) 
     283                *size   = framelist->content_len[framelist->head]; 
     284            if (bit_info) 
     285                *bit_info = framelist->bit_info[framelist->head]; 
     286 
     287            //pj_bzero(framelist->content +  
     288            //   framelist->head * framelist->frame_size, 
     289            //   framelist->frame_size); 
     290            framelist->frame_type[framelist->head] = PJMEDIA_JB_MISSING_FRAME; 
     291            framelist->content_len[framelist->head] = 0; 
     292            framelist->bit_info[framelist->head] = 0; 
     293 
     294            framelist->origin++; 
     295            framelist->head = (framelist->head + 1) % framelist->max_count; 
     296            framelist->size--; 
     297         
     298            return PJ_TRUE; 
     299        } 
     300    } 
     301 
     302    /* No frame available */ 
     303    pj_bzero(frame, framelist->frame_size); 
     304 
     305    return PJ_FALSE; 
     306} 
     307 
     308 
     309/* Remove oldest frames as many as param 'count' */ 
    257310static unsigned jb_framelist_remove_head(jb_framelist_t *framelist, 
    258311                                         unsigned count)  
     
    265318        unsigned step1,step2; 
    266319        unsigned tmp = framelist->head+count; 
     320        unsigned i; 
    267321 
    268322        if (tmp > framelist->max_count) { 
     
    272326            step1 = count; 
    273327            step2 = 0; 
     328        } 
     329 
     330        for (i = framelist->head; i < (framelist->head + step1); ++i) { 
     331            if (framelist->frame_type[i] == PJMEDIA_JB_DISCARDED_FRAME) { 
     332                pj_assert(framelist->discarded_num > 0); 
     333                framelist->discarded_num--; 
     334            } 
    274335        } 
    275336 
     
    281342                  step1*sizeof(framelist->frame_type[0])); 
    282343        pj_bzero(framelist->content_len+framelist->head, 
    283                   step1*sizeof(framelist->content_len[0])); 
     344                 step1*sizeof(framelist->content_len[0])); 
    284345 
    285346        if (step2) { 
     347            for (i = 0; i < step2; ++i) { 
     348                if (framelist->frame_type[i] == PJMEDIA_JB_DISCARDED_FRAME) { 
     349                    pj_assert(framelist->discarded_num > 0); 
     350                    framelist->discarded_num--; 
     351                } 
     352            } 
    286353            //pj_bzero( framelist->content, 
    287354            //        step2*framelist->frame_size); 
     
    307374                                       const void *frame, 
    308375                                       unsigned frame_size, 
    309                                        pj_uint32_t bit_info) 
     376                                       pj_uint32_t bit_info, 
     377                                       unsigned frame_type) 
    310378{ 
    311379    int distance; 
    312     unsigned where; 
     380    unsigned pos; 
    313381    enum { MAX_MISORDER = 100 }; 
    314382    enum { MAX_DROPOUT = 3000 }; 
     
    316384    assert(frame_size <= framelist->frame_size); 
    317385 
    318     /* too late or duplicated or sequence restart */ 
     386    /* too late or sequence restart */ 
    319387    if (index < framelist->origin) { 
    320388        if (framelist->origin - index < MAX_MISORDER) { 
    321             /* too late or duplicated */ 
     389            /* too late */ 
    322390            return PJ_ETOOSMALL; 
    323391        } else { 
     
    329397    /* if jbuf is empty, just reset the origin */ 
    330398    if (framelist->size == 0) { 
     399        pj_assert(framelist->discarded_num == 0); 
    331400        framelist->origin = index; 
    332401    } 
     
    349418 
    350419    /* get the slot position */ 
    351     where = (framelist->head + distance) % framelist->max_count; 
     420    pos = (framelist->head + distance) % framelist->max_count; 
    352421 
    353422    /* if the slot is occupied, it must be duplicated frame, ignore it. */ 
    354     if (framelist->frame_type[where] != PJMEDIA_JB_MISSING_FRAME) 
     423    if (framelist->frame_type[pos] != PJMEDIA_JB_MISSING_FRAME) 
    355424        return PJ_EEXISTS; 
    356425 
    357426    /* put the frame into the slot */ 
    358     pj_memcpy(framelist->content + where * framelist->frame_size, 
    359               frame, frame_size); 
    360     framelist->frame_type[where] = PJMEDIA_JB_NORMAL_FRAME; 
    361     framelist->content_len[where] = frame_size; 
    362     framelist->bit_info[where] = bit_info; 
     427    framelist->frame_type[pos] = frame_type; 
     428    framelist->content_len[pos] = frame_size; 
     429    framelist->bit_info[pos] = bit_info; 
     430 
     431    /* update framelist size */ 
    363432    if (framelist->origin + (int)framelist->size <= index) 
    364433        framelist->size = distance + 1; 
    365434 
    366     return PJ_SUCCESS; 
     435    if(PJMEDIA_JB_NORMAL_FRAME == frame_type) { 
     436        /* copy frame content */ 
     437        pj_memcpy(framelist->content + pos * framelist->frame_size, 
     438                  frame, frame_size); 
     439        return PJ_SUCCESS; 
     440    } else { 
     441        /* frame is being discarded */ 
     442        framelist->discarded_num++; 
     443        return PJ_EIGNORED; 
     444    } 
    367445} 
    368446 
     
    402480    jb->jb_min_shrink_gap= MIN_SHRINK_GAP_MSEC / ptime; 
    403481    jb->jb_max_burst     = MAX_BURST_MSEC / ptime; 
     482    jb->jb_last_discard_seq = 0; 
     483 
    404484    pj_math_stat_init(&jb->jb_delay); 
    405485    pj_math_stat_init(&jb->jb_burst); 
     
    424504 
    425505    jb->jb_min_prefetch = jb->jb_max_prefetch =  
    426         jb->jb_prefetch = jb->jb_def_prefetch = prefetch; 
     506        jb->jb_prefetch = jb->jb_init_prefetch = prefetch; 
    427507 
    428508    return PJ_SUCCESS; 
     
    444524                     PJ_EINVAL); 
    445525 
    446     jb->jb_prefetch = jb->jb_def_prefetch = prefetch; 
     526    jb->jb_prefetch = jb->jb_init_prefetch = prefetch; 
    447527    jb->jb_min_prefetch = min_prefetch; 
    448528    jb->jb_max_prefetch = max_prefetch; 
     
    469549PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb) 
    470550{ 
    471     TRACE__((jb->jb_name.ptr, "" 
    472             "JB summary:" 
    473             " size=%d prefetch=%d," 
    474             " delay (min/max/avg/dev)=%d/%d/%d/%d ms," 
    475             " burst (min/max/avg/dev)=%d/%d/%d/%d frames," 
    476             " lost=%d discard=%d empty=%d", 
    477             jb->jb_framelist.size, jb->jb_prefetch, 
    478             jb->jb_delay.min, jb->jb_delay.max, jb->jb_delay.mean,  
    479             pj_math_stat_get_stddev(&jb->jb_delay), 
    480             jb->jb_burst.min, jb->jb_burst.max, jb->jb_burst.mean,  
    481             pj_math_stat_get_stddev(&jb->jb_burst), 
    482             jb->jb_lost, jb->jb_discard, jb->jb_empty)); 
     551    PJ_LOG(5, (jb->jb_name.ptr, "" 
     552               "JB summary:\n" 
     553               "  size=%d prefetch=%d level=%d\n" 
     554               "  delay (min/max/avg/dev)=%d/%d/%d/%d ms\n" 
     555               "  burst (min/max/avg/dev)=%d/%d/%d/%d frames\n" 
     556               " lost=%d discard=%d empty=%d", 
     557               jb->jb_framelist.size, jb->jb_prefetch, jb->jb_eff_level, 
     558               jb->jb_delay.min, jb->jb_delay.max, jb->jb_delay.mean,  
     559               pj_math_stat_get_stddev(&jb->jb_delay), 
     560               jb->jb_burst.min, jb->jb_burst.max, jb->jb_burst.mean,  
     561               pj_math_stat_get_stddev(&jb->jb_burst), 
     562               jb->jb_lost, jb->jb_discard, jb->jb_empty)); 
    483563 
    484564    return jb_framelist_destroy(&jb->jb_framelist); 
     
    490570    int diff, cur_size; 
    491571 
    492     cur_size = jb_framelist_size(&jb->jb_framelist); 
     572    cur_size = jb_framelist_eff_size(&jb->jb_framelist); 
    493573    pj_math_stat_update(&jb->jb_burst, jb->jb_level); 
    494574    jb->jb_max_hist_level = PJ_MAX(jb->jb_max_hist_level, jb->jb_level); 
    495575 
    496576    /* Burst level is decreasing */ 
    497     if (jb->jb_level < jb->jb_prefetch) { 
    498  
    499         enum { STABLE_HISTORY_LIMIT = 100 }; 
     577    if (jb->jb_level < jb->jb_eff_level) { 
     578 
     579        enum { STABLE_HISTORY_LIMIT = 20 }; 
    500580         
    501581        jb->jb_stable_hist++; 
    502582         
    503         /* Only update the prefetch if 'stable' condition is reached  
    504          * (not just short time impulse) 
     583        /* Only update the effective level (and prefetch) if 'stable'  
     584         * condition is reached (not just short time impulse) 
    505585         */ 
    506586        if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) { 
    507587         
    508             diff = (jb->jb_prefetch - jb->jb_max_hist_level) / 3; 
     588            diff = (jb->jb_eff_level - jb->jb_max_hist_level) / 3; 
    509589 
    510590            if (diff < 1) 
    511591                diff = 1; 
    512592 
    513             jb->jb_prefetch -= diff; 
    514             if (jb->jb_prefetch < jb->jb_min_prefetch)  
    515                 jb->jb_prefetch = jb->jb_min_prefetch; 
     593            /* Update effective burst level */ 
     594            jb->jb_eff_level -= diff; 
     595 
     596            /* Update prefetch based on level */ 
     597            if (jb->jb_init_prefetch) { 
     598                jb->jb_prefetch = jb->jb_eff_level; 
     599                if (jb->jb_prefetch < jb->jb_min_prefetch)  
     600                    jb->jb_prefetch = jb->jb_min_prefetch; 
     601            } 
    516602 
    517603            /* Reset history */ 
     
    519605            jb->jb_stable_hist = 0; 
    520606 
    521             TRACE__((jb->jb_name.ptr,"jb updated(1), prefetch=%d, size=%d", 
    522                      jb->jb_prefetch, cur_size)); 
     607            TRACE__((jb->jb_name.ptr,"jb updated(1), lvl=%d pre=%d, size=%d", 
     608                     jb->jb_eff_level, jb->jb_prefetch, cur_size)); 
    523609        } 
    524610    } 
    525611 
    526612    /* Burst level is increasing */ 
    527     else if (jb->jb_level > jb->jb_prefetch) { 
    528  
    529         /* Instaneous set prefetch to recent maximum level (max_hist_level) */ 
    530         jb->jb_prefetch = PJ_MIN(jb->jb_max_hist_level, 
    531                                  (int)(jb->jb_max_count*4/5)); 
    532         if (jb->jb_prefetch > jb->jb_max_prefetch) 
    533             jb->jb_prefetch = jb->jb_max_prefetch; 
     613    else if (jb->jb_level > jb->jb_eff_level) { 
     614 
     615        /* Instaneous set effective burst level to recent maximum level */ 
     616        jb->jb_eff_level = PJ_MIN(jb->jb_max_hist_level, 
     617                                  (int)(jb->jb_max_count*4/5)); 
     618 
     619        /* Update prefetch based on level */ 
     620        if (jb->jb_init_prefetch) { 
     621            jb->jb_prefetch = jb->jb_eff_level; 
     622            if (jb->jb_prefetch > jb->jb_max_prefetch) 
     623                jb->jb_prefetch = jb->jb_max_prefetch; 
     624        } 
    534625 
    535626        jb->jb_stable_hist = 0; 
     
    537628        //jb->jb_max_hist_level = 0; 
    538629 
    539         TRACE__((jb->jb_name.ptr,"jb updated(2), prefetch=%d, size=%d",  
    540                  jb->jb_prefetch, cur_size)); 
     630        TRACE__((jb->jb_name.ptr,"jb updated(2), lvl=%d pre=%d, size=%d",  
     631                 jb->jb_eff_level, jb->jb_prefetch, cur_size)); 
    541632    } 
    542633 
     
    549640PJ_INLINE(void) jbuf_update(pjmedia_jbuf *jb, int oper) 
    550641{ 
    551     int diff, burst_level; 
    552  
    553642    if(jb->jb_last_op != oper) { 
    554643        jb->jb_last_op = oper; 
     
    594683     */ 
    595684 
     685    /* Shrinking due of drift will be implicitly done by progressive discard, 
     686     * so just disable it when progressive discard is active. 
     687     */ 
     688#if !PROGRESSIVE_DISCARD 
     689 
    596690    if (jb->jb_status != JB_STATUS_PROCESSING) 
    597691        return; 
    598692 
    599     burst_level = PJ_MAX(jb->jb_prefetch, jb->jb_level); 
    600     diff = jb_framelist_size(&jb->jb_framelist) - burst_level*2; 
    601  
    602     if (diff >= SAFE_SHRINKING_DIFF) { 
    603         /* Check and adjust jb_last_del_seq, in case there was seq restart */ 
    604         if (jb->jb_framelist.origin < jb->jb_last_del_seq) 
    605             jb->jb_last_del_seq = jb->jb_framelist.origin; 
    606  
    607         if (jb->jb_framelist.origin - jb->jb_last_del_seq >= 
    608             jb->jb_min_shrink_gap) 
    609         { 
    610             /* Shrink slowly, one frame per cycle */ 
    611             diff = 1; 
    612  
    613             /* Drop frame(s)! */ 
    614             diff = jb_framelist_remove_head(&jb->jb_framelist, diff); 
    615             jb->jb_last_del_seq = jb->jb_framelist.origin; 
    616             jb->jb_discard += diff; 
    617  
    618             TRACE__((jb->jb_name.ptr,  
    619                      "JB shrinking %d frame(s), cur size=%d", diff, 
    620                      jb_framelist_size(&jb->jb_framelist))); 
    621         } 
    622     } 
     693    { 
     694        int diff, burst_level; 
     695 
     696        burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level); 
     697        diff = jb_framelist_eff_size(&jb->jb_framelist) - burst_level*2; 
     698 
     699        if (diff >= SAFE_SHRINKING_DIFF) { 
     700            int seq_origin; 
     701 
     702            /* Check and adjust jb_last_del_seq, in case there was  
     703             * seq restart  
     704             */ 
     705            seq_origin = jb_framelist_origin(&jb->jb_framelist); 
     706            if (seq_origin < jb->jb_last_del_seq) 
     707                jb->jb_last_del_seq = seq_origin; 
     708 
     709            if (seq_origin - jb->jb_last_del_seq >= jb->jb_min_shrink_gap) 
     710            { 
     711                /* Shrink slowly, one frame per cycle */ 
     712                diff = 1; 
     713 
     714                /* Drop frame(s)! */ 
     715                diff = jb_framelist_remove_head(&jb->jb_framelist, diff); 
     716                jb->jb_last_del_seq = jb_framelist_origin(&jb->jb_framelist); 
     717                jb->jb_discard += diff; 
     718 
     719                TRACE__((jb->jb_name.ptr,  
     720                         "JB shrinking %d frame(s), cur size=%d", diff, 
     721                         jb_framelist_eff_size(&jb->jb_framelist))); 
     722            } 
     723        } 
     724    } 
     725 
     726#endif /* !PROGRESSIVE_DISCARD */ 
     727 
    623728} 
    624729 
     
    639744{ 
    640745    pj_size_t min_frame_size; 
    641     int prev_size, cur_size; 
     746    int new_size, cur_size, frame_type = PJMEDIA_JB_NORMAL_FRAME; 
    642747    pj_status_t status; 
    643748 
    644     /* Get JB size before PUT */ 
    645     prev_size = jb_framelist_size(&jb->jb_framelist); 
     749    cur_size = jb_framelist_eff_size(&jb->jb_framelist); 
     750 
     751#if PROGRESSIVE_DISCARD 
     752    { 
     753        unsigned interval, seq_delta; 
     754        unsigned burst_level, burst_factor; 
     755 
     756        /* Calculating discard interval (aggressiveness) based on 
     757         * (current size / burst level). 
     758         */ 
     759        if (jb->jb_status == JB_STATUS_PROCESSING) { 
     760            burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level); 
     761            burst_factor = cur_size / burst_level; 
     762            /* Tolerate small spikes */ 
     763            if ((burst_level <= 5) && (burst_factor < 3)) 
     764                burst_factor = 0; 
     765        } else { 
     766            burst_factor = 0; 
     767        } 
     768 
     769        switch (burst_factor) { 
     770        case 0: 
     771            interval = 0; 
     772            break; 
     773        case 1: 
     774            interval = 7; 
     775            break; 
     776        case 2: 
     777            interval = 5; 
     778            break; 
     779        default: 
     780            interval = 4; 
     781            break; 
     782        } 
     783 
     784        /* Do the math now to see if we should discard this packet. 
     785         * Calculate the distance from the last sequence 
     786         * discarded. If negative, then this is an out of 
     787         * order frame so just proceed with discard. Else 
     788         * see if the delta is at least the intervals worth away 
     789         * from the last frame discarded. 
     790         */ 
     791        seq_delta = (pj_uint16_t)(frame_seq - jb->jb_last_discard_seq); 
     792        if ((0 != interval) && (seq_delta >= interval)) { 
     793            frame_type = PJMEDIA_JB_DISCARDED_FRAME; 
     794            jb->jb_last_discard_seq = frame_seq; 
     795 
     796            TRACE__((jb->jb_name.ptr,  
     797                    "Discarding frame #%d: eff=%d disc=%d orig:%d" 
     798                    " seq_delta:%d", 
     799                    frame_seq, 
     800                    cur_size, 
     801                    jb_framelist_size(&jb->jb_framelist) - cur_size, 
     802                    jb_framelist_origin(&jb->jb_framelist), 
     803                    (int)seq_delta)); 
     804        } 
     805    } 
     806#endif /* PROGRESSIVE_DISCARD */ 
    646807     
     808 
    647809    /* Attempt to store the frame */ 
    648810    min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size); 
    649811    status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame, 
    650                                  min_frame_size, bit_info); 
     812                                 min_frame_size, bit_info, frame_type); 
    651813     
    652     /* Jitter buffer is full, cannot store the frame */ 
     814    /* Jitter buffer is full, remove some older frames */ 
    653815    while (status == PJ_ETOOMANY) { 
     816        int distance; 
    654817        unsigned removed; 
    655818 
    656         removed = jb_framelist_remove_head(&jb->jb_framelist, 
    657                                            PJ_MAX(jb->jb_max_count/4, 1)); 
     819        /* When progressive discard activated, just remove as few as possible 
     820         * just to make this frame in. 
     821         */ 
     822#if PROGRESSIVE_DISCARD 
     823        /* The cases of seq-jump, out-of-order, and seq restart should have 
     824         * been handled/normalized by previous call of jb_framelist_put_at(). 
     825         * So we're confident about 'distance' value here. 
     826         */ 
     827        distance = (frame_seq - jb_framelist_origin(&jb->jb_framelist)) - 
     828                   jb->jb_max_count + 1; 
     829        pj_assert(distance > 0); 
     830#else 
     831        distance = PJ_MAX(jb->jb_max_count/4, 1); 
     832#endif 
     833        removed = jb_framelist_remove_head(&jb->jb_framelist, distance); 
    658834        status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame, 
    659                                      min_frame_size, bit_info); 
     835                                     min_frame_size, bit_info, frame_type); 
    660836 
    661837        jb->jb_discard += removed; 
    662838    } 
    663839 
    664     /* Get JB size after PUT */ 
    665     cur_size = jb_framelist_size(&jb->jb_framelist); 
     840    /* Get new JB size after PUT */ 
     841    new_size = jb_framelist_eff_size(&jb->jb_framelist); 
    666842 
    667843    /* Return the flag if this frame is discarded */ 
     
    672848        if (jb->jb_status == JB_STATUS_PREFETCHING) { 
    673849            TRACE__((jb->jb_name.ptr, "PUT prefetch_cnt=%d/%d",  
    674                      cur_size, jb->jb_prefetch)); 
    675             if (cur_size >= jb->jb_prefetch) 
     850                     new_size, jb->jb_prefetch)); 
     851            if (new_size >= jb->jb_prefetch) 
    676852                jb->jb_status = JB_STATUS_PROCESSING; 
    677853        } 
    678         jb->jb_level += (cur_size > prev_size ? cur_size-prev_size : 1); 
     854        jb->jb_level += (new_size > cur_size ? new_size-cur_size : 1); 
    679855        jbuf_update(jb, JB_OP_PUT); 
    680856    } else 
     
    701877                                     pj_uint32_t *bit_info) 
    702878{ 
    703     int cur_size; 
    704  
    705     cur_size = jb_framelist_size(&jb->jb_framelist); 
    706  
    707     if (cur_size == 0) { 
    708         /* jitter buffer empty */ 
    709  
    710         if (jb->jb_def_prefetch) 
    711             jb->jb_status = JB_STATUS_PREFETCHING; 
    712  
    713         //pj_bzero(frame, jb->jb_frame_size); 
    714         *p_frame_type = PJMEDIA_JB_ZERO_EMPTY_FRAME; 
    715         if (size) 
    716             *size = 0; 
    717  
    718         jb->jb_empty++; 
    719  
    720     } else if (jb->jb_status == JB_STATUS_PREFETCHING) { 
     879    if (jb->jb_status == JB_STATUS_PREFETCHING) { 
    721880 
    722881        /* Can't return frame because jitter buffer is filling up 
     
    730889 
    731890        TRACE__((jb->jb_name.ptr, "GET prefetch_cnt=%d/%d", 
    732                  cur_size, jb->jb_prefetch)); 
     891                 jb_framelist_eff_size(&jb->jb_framelist), jb->jb_prefetch)); 
    733892 
    734893        jb->jb_empty++; 
     
    736895    } else { 
    737896 
    738         pjmedia_jb_frame_type ftype = PJMEDIA_JB_MISSING_FRAME; 
     897        pjmedia_jb_frame_type ftype = PJMEDIA_JB_NORMAL_FRAME; 
    739898        pj_bool_t res; 
    740899 
    741         /* Retrieve a frame from frame list */ 
     900        /* Try to retrieve a frame from frame list */ 
    742901        res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype,  
    743902                               bit_info); 
    744         pj_assert(res); 
    745  
    746         /* We've successfully retrieved a frame from the frame list, but 
    747          * the frame could be a blank frame! 
    748          */ 
    749         if (ftype == PJMEDIA_JB_NORMAL_FRAME) { 
    750             *p_frame_type = PJMEDIA_JB_NORMAL_FRAME; 
     903        if (res) { 
     904            /* We've successfully retrieved a frame from the frame list, but 
     905             * the frame could be a blank frame! 
     906             */ 
     907            if (ftype == PJMEDIA_JB_NORMAL_FRAME) { 
     908                *p_frame_type = PJMEDIA_JB_NORMAL_FRAME; 
     909            } else { 
     910                *p_frame_type = PJMEDIA_JB_MISSING_FRAME; 
     911                jb->jb_lost++; 
     912            } 
     913 
     914            /* Store delay history at the first GET */ 
     915            if (jb->jb_last_op == JB_OP_PUT) { 
     916                unsigned cur_size; 
     917 
     918                /* We've just retrieved one frame, so add one to cur_size */ 
     919                cur_size = jb_framelist_eff_size(&jb->jb_framelist) + 1; 
     920                pj_math_stat_update(&jb->jb_delay,  
     921                                    cur_size*jb->jb_frame_ptime); 
     922            } 
    751923        } else { 
    752             *p_frame_type = PJMEDIA_JB_MISSING_FRAME; 
    753             jb->jb_lost++; 
    754         } 
    755  
    756         /* Calculate delay on the first GET */ 
    757         if (jb->jb_last_op == JB_OP_PUT) 
    758             pj_math_stat_update(&jb->jb_delay, cur_size * jb->jb_frame_ptime); 
     924            /* Jitter buffer is empty */ 
     925            if (jb->jb_prefetch) 
     926                jb->jb_status = JB_STATUS_PREFETCHING; 
     927 
     928            //pj_bzero(frame, jb->jb_frame_size); 
     929            *p_frame_type = PJMEDIA_JB_ZERO_EMPTY_FRAME; 
     930            if (size) 
     931                *size = 0; 
     932 
     933            jb->jb_empty++; 
     934        } 
    759935    } 
    760936 
     
    775951    state->max_prefetch = jb->jb_max_prefetch; 
    776952     
     953    state->burst = jb->jb_eff_level; 
    777954    state->prefetch = jb->jb_prefetch; 
    778     state->size = jb_framelist_size(&jb->jb_framelist); 
     955    state->size = jb_framelist_eff_size(&jb->jb_framelist); 
    779956     
    780957    state->avg_delay = jb->jb_delay.mean; 
     
    790967    return PJ_SUCCESS; 
    791968} 
     969 
Note: See TracChangeset for help on using the changeset viewer.