Changeset 3814


Ignore:
Timestamp:
Oct 13, 2011 9:02:41 AM (8 years ago)
Author:
nanang
Message:

Re #1378:

  • Implemented new algorithm for JB progressive discard.
  • Added new API and for setting JB discard algorithm at run-time.
  • Updated JB test for the new algorithm.
Location:
pjproject/branches/1.x/pjmedia
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/1.x/pjmedia/build/Jbtest.dat

    r3569 r3814  
    2020# 3. Success conditions, started with '!', followed by condition name  
    2121#    and its maximum tolerable value, in frames unit. Recognized condition  
    22 #    names are: burst, discard, lost, empty, delay. These conditions will 
    23 #    be verified with jitter buffer statistics after all session test data 
    24 #    are executed. 
     22#    names are: burst, discard, lost, empty, delay, delay_min. These 
     23#    conditions will be verified with jitter buffer statistics after all 
     24#    session test data are executed. 
    2525#    Example: 
    26 #    !delay 10  <- maximum average delay of jbuf is 10 frames 
     26#    !delay 10  <- average delay of jbuf is 10 frames 
    2727# 
    2828# 4. Session test data, containing sequence of jitter buffer events, 
     
    296296!lost       50 <- ticket #1188, normal frame after discarded frame is flagged 'lost' to align signal 
    297297!empty      0 
    298 !delay      25 <- average delay, JB is able to adapt the delay 
    299 PPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPP PPPPPPPPPP 
     298!delay_min  2  <- minimum delay, JB is able to adapt the delay 
     299PPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPP PPPPPPPPPP 
     300PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     301PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     302PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     303PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     304PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     305PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     306PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     307PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     308PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     309PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     310PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     311PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     312PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     313PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     314PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     315PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     316PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
    300317PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
    301318PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     
    350367!lost       50 <- ticket #1188, normal frame after discarded frame is flagged 'lost' to align signal 
    351368!empty      0 
    352 !delay      20 <- average delay, twice of minimal prefetch 
     369!delay_min  20 <- minimum delay, twice of minimal prefetch 
    353370PPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPP PPPPPPPPPP 
    354371PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG 
     
    370387= Large PUT burst at beginning, then normal with burst level 10 and periodic burst spikes 
    371388%adaptive 0 0 40 
    372 !burst      10 
     389!burst      12 
    373390!discard    300 <- not so relevant for long period session with many delay adjustments needed (i.e: for first burst and periodic spikes) 
    374391!lost       300 <- ticket #1188, normal frame after discarded frame is flagged 'lost' to align signal 
  • pjproject/branches/1.x/pjmedia/include/pjmedia/config.h

    r3745 r3814  
    887887 */ 
    888888#ifndef PJMEDIA_STREAM_KA_INTERVAL 
    889 #       define PJMEDIA_STREAM_KA_INTERVAL           5 
     889#   define PJMEDIA_STREAM_KA_INTERVAL               5 
     890#endif 
     891 
     892 
     893/** 
     894 * Minimum gap between two consecutive discards in jitter buffer, 
     895 * in milliseconds. 
     896 * 
     897 * Default: 200 ms 
     898 */ 
     899#ifndef PJMEDIA_JBUF_DISC_MIN_GAP 
     900#   define PJMEDIA_JBUF_DISC_MIN_GAP                200 
     901#endif 
     902 
     903 
     904/** 
     905 * Minimum burst level reference used for calculating discard duration 
     906 * in jitter buffer progressive discard algorithm, in frames. 
     907 *  
     908 * Default: 1 frame 
     909 */ 
     910#ifndef PJMEDIA_JBUF_PRO_DISC_MIN_BURST 
     911#   define PJMEDIA_JBUF_PRO_DISC_MIN_BURST          1 
     912#endif 
     913 
     914 
     915/** 
     916 * Maximum burst level reference used for calculating discard duration 
     917 * in jitter buffer progressive discard algorithm, in frames. 
     918 *  
     919 * Default: 200 frames 
     920 */ 
     921#ifndef PJMEDIA_JBUF_PRO_DISC_MAX_BURST 
     922#   define PJMEDIA_JBUF_PRO_DISC_MAX_BURST          100 
     923#endif 
     924 
     925 
     926/** 
     927 * Duration for progressive discard algotithm in jitter buffer to discard 
     928 * an excessive frame when burst is equal to or lower than 
     929 * PJMEDIA_JBUF_PRO_DISC_MIN_BURST, in milliseconds. 
     930 * 
     931 * Default: 2000 ms 
     932 */ 
     933#ifndef PJMEDIA_JBUF_PRO_DISC_T1 
     934#   define PJMEDIA_JBUF_PRO_DISC_T1                 2000 
     935#endif 
     936 
     937 
     938/** 
     939 * Duration for progressive discard algotithm in jitter buffer to discard 
     940 * an excessive frame when burst is equal to or lower than 
     941 * PJMEDIA_JBUF_PRO_DISC_MAX_BURST, in milliseconds. 
     942 * 
     943 * Default: 10000 ms 
     944 */ 
     945#ifndef PJMEDIA_JBUF_PRO_DISC_T2 
     946#   define PJMEDIA_JBUF_PRO_DISC_T2                 10000 
    890947#endif 
    891948 
  • pjproject/branches/1.x/pjmedia/include/pjmedia/jbuf.h

    r3553 r3814  
    4949 * Types of frame returned by the jitter buffer. 
    5050 */ 
    51 enum pjmedia_jb_frame_type  
     51typedef enum pjmedia_jb_frame_type  
    5252{ 
    5353    PJMEDIA_JB_MISSING_FRAME       = 0, /**< No frame because it's missing  */ 
     
    5757    PJMEDIA_JB_ZERO_EMPTY_FRAME    = 3  /**< Zero frame is being returned 
    5858                                             because JB is empty.           */ 
    59 }; 
    60  
    61  
    62 /** 
    63  * @see pjmedia_jb_frame_type. 
    64  */ 
    65 typedef enum pjmedia_jb_frame_type pjmedia_jb_frame_type; 
     59} pjmedia_jb_frame_type; 
     60 
     61 
     62/** 
     63 * Enumeration of jitter buffer discard algorithm. The jitter buffer 
     64 * continuously calculates the jitter level to get the optimum latency at 
     65 * any time and in order to adjust the latency, the jitter buffer may need 
     66 * to discard some frames. 
     67 */ 
     68typedef enum pjmedia_jb_discard_algo 
     69{ 
     70    /** 
     71     * Jitter buffer should not discard any frame, except when the jitter 
     72     * buffer is full and a new frame arrives, one frame will be discarded 
     73     * to make space for the new frame. 
     74     */ 
     75    PJMEDIA_JB_DISCARD_NONE        = 0, 
     76 
     77    /** 
     78     * Only discard one frame in at least 200ms when the latency is considered 
     79     * much higher than it should be. When the jitter buffer is full and a new 
     80     * frame arrives, one frame will be discarded to make space for the new 
     81     * frame. 
     82     */ 
     83    PJMEDIA_JB_DISCARD_STATIC, 
     84 
     85    /** 
     86     * The discard rate is dynamically calculated based on actual parameters 
     87     * such as jitter level and latency. When the jitter buffer is full and 
     88     * a new frame arrives, one frame will be discarded to make space for the 
     89     * new frame. 
     90     */ 
     91    PJMEDIA_JB_DISCARD_PROGRESSIVE 
     92 
     93} pjmedia_jb_discard_algo; 
    6694 
    6795 
     
    6997 * This structure describes jitter buffer state. 
    7098 */ 
    71 struct pjmedia_jb_state 
     99typedef struct pjmedia_jb_state 
    72100{ 
    73101    /* Setting */ 
     
    90118    unsigned    discard;            /**< Number of discarded frames.        */ 
    91119    unsigned    empty;              /**< Number of empty on GET events.     */ 
    92 }; 
    93  
    94  
    95 /** 
    96  * @see pjmedia_jb_state 
    97  */ 
    98 typedef struct pjmedia_jb_state pjmedia_jb_state; 
     120} pjmedia_jb_state; 
    99121 
    100122 
     
    114136 * Create an adaptive jitter buffer according to the specification. If 
    115137 * application wants to have a fixed jitter buffer, it may call 
    116  * #pjmedia_jbuf_set_fixed() after the jitter buffer is created. 
     138 * #pjmedia_jbuf_set_fixed() after the jitter buffer is created. Also 
     139 * if application wants to alter the discard algorithm, which the default 
     140 * PJMEDIA_JB_DISCARD_PROGRESSIVE, it may call #pjmedia_jbuf_set_discard(). 
    117141 * 
    118142 * This function may allocate large chunk of memory to keep the frames in  
     
    178202                                                unsigned min_prefetch, 
    179203                                                unsigned max_prefetch); 
     204 
     205 
     206/** 
     207 * Set the jitter buffer discard algorithm. The default discard algorithm, 
     208 * set in jitter buffer creation, is PJMEDIA_JB_DISCARD_PROGRESSIVE. 
     209 * 
     210 * @param jb            The jitter buffer. 
     211 * @param algo          The discard algorithm to be used. 
     212 * 
     213 * @return              PJ_SUCCESS on success. 
     214 */ 
     215PJ_DECL(pj_status_t) pjmedia_jbuf_set_discard(pjmedia_jbuf *jb, 
     216                                              pjmedia_jb_discard_algo algo); 
    180217 
    181218 
  • pjproject/branches/1.x/pjmedia/src/pjmedia/jbuf.c

    r3779 r3814  
    3333 
    3434 
    35 /* Minimal difference between JB size and 2*burst-level to perform  
    36  * JB shrinking.  
    37  */ 
    38 #define SAFE_SHRINKING_DIFF     1 
    39  
    40 /* Minimal gap (in ms) between JB shrinking */ 
    41 #define MIN_SHRINK_GAP_MSEC     200 
    42  
    4335/* Invalid sequence number, used as the initial value. */ 
    4436#define INVALID_OFFSET          -9999 
     
    5345 */ 
    5446#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 
    5553 
    5654 
     
    8280 
    8381 
     82typedef void (*discard_algo)(pjmedia_jbuf *jb); 
     83static void jbuf_discard_static(pjmedia_jbuf *jb); 
     84static void jbuf_discard_progressive(pjmedia_jbuf *jb); 
     85 
     86 
    8487struct pjmedia_jbuf 
    8588{ 
     
    98101                                             calculation                    */ 
    99102    int             jb_min_shrink_gap;  /**< How often can we shrink        */ 
     103    discard_algo    jb_discard_algo;    /**< Discard algorithm              */ 
    100104 
    101105    /* Buffer */ 
     
    125129    int             jb_init_cycle_cnt;  /**< status is 'init' until the first  
    126130                                             'put' operation                */ 
    127     int             jb_last_del_seq;    /**< Seq # of last frame deleted    */ 
    128  
    129     int             jb_last_discard_seq;/**< Seq # of last frame discarded  */ 
     131 
     132    int             jb_discard_ref;     /**< Seq # of last frame deleted or 
     133                                             discarded                      */ 
     134    unsigned        jb_discard_dist;    /**< Distance from jb_discard_ref 
     135                                             to perform discard (in frm)    */ 
    130136 
    131137    /* Statistics */ 
     
    393399    enum { MAX_DROPOUT = 3000 }; 
    394400 
    395     assert(frame_size <= framelist->frame_size); 
     401    PJ_ASSERT_RETURN(frame_size <= framelist->frame_size, PJ_EINVAL); 
    396402 
    397403    /* too late or sequence restart */ 
     
    448454        pj_memcpy(framelist->content + pos * framelist->frame_size, 
    449455                  frame, frame_size); 
    450         return PJ_SUCCESS; 
    451     } else { 
    452         /* frame is being discarded */ 
    453         framelist->discarded_num++; 
    454         return PJ_EIGNORED; 
    455     } 
    456 } 
    457  
     456    } 
     457 
     458    return PJ_SUCCESS; 
     459} 
     460 
     461 
     462static pj_status_t jb_framelist_discard(jb_framelist_t *framelist, 
     463                                        int index) 
     464{ 
     465    unsigned pos; 
     466 
     467    PJ_ASSERT_RETURN(index >= framelist->origin && 
     468                     index <  framelist->origin + (int)framelist->size, 
     469                     PJ_EINVAL); 
     470 
     471    /* Get the slot position */ 
     472    pos = (framelist->head + (index - framelist->origin)) % 
     473          framelist->max_count; 
     474 
     475    /* Discard the frame */ 
     476    framelist->frame_type[pos] = PJMEDIA_JB_DISCARDED_FRAME; 
     477    framelist->discarded_num++; 
     478 
     479    return PJ_SUCCESS; 
     480} 
    458481 
    459482 
     
    489512    jb->jb_max_prefetch  = max_count*4/5; 
    490513    jb->jb_max_count     = max_count; 
    491     jb->jb_min_shrink_gap= MIN_SHRINK_GAP_MSEC / ptime; 
     514    jb->jb_min_shrink_gap= PJMEDIA_JBUF_DISC_MIN_GAP / ptime; 
    492515    jb->jb_max_burst     = PJ_MAX(MAX_BURST_MSEC / ptime, max_count*3/4); 
    493     jb->jb_last_discard_seq = 0; 
    494516 
    495517    pj_math_stat_init(&jb->jb_delay); 
    496518    pj_math_stat_init(&jb->jb_burst); 
    497519 
     520    pjmedia_jbuf_set_discard(jb, PJMEDIA_JB_DISCARD_PROGRESSIVE); 
    498521    pjmedia_jbuf_reset(jb); 
    499522 
     
    538561    jb->jb_min_prefetch = min_prefetch; 
    539562    jb->jb_max_prefetch = max_prefetch; 
     563 
     564    return PJ_SUCCESS; 
     565} 
     566 
     567 
     568PJ_DEF(pj_status_t) pjmedia_jbuf_set_discard( pjmedia_jbuf *jb, 
     569                                              pjmedia_jb_discard_algo algo) 
     570{ 
     571    PJ_ASSERT_RETURN(jb, PJ_EINVAL); 
     572    PJ_ASSERT_RETURN(algo >= PJMEDIA_JB_DISCARD_NONE && 
     573                     algo <= PJMEDIA_JB_DISCARD_PROGRESSIVE, 
     574                     PJ_EINVAL); 
     575 
     576    switch(algo) { 
     577    case PJMEDIA_JB_DISCARD_PROGRESSIVE: 
     578        jb->jb_discard_algo = &jbuf_discard_progressive; 
     579        break; 
     580    case PJMEDIA_JB_DISCARD_STATIC: 
     581        jb->jb_discard_algo = &jbuf_discard_static; 
     582        break; 
     583    default: 
     584        jb->jb_discard_algo = NULL; 
     585        break; 
     586    } 
    540587 
    541588    return PJ_SUCCESS; 
     
    552599    jb->jb_max_hist_level= 0; 
    553600    jb->jb_prefetching   = (jb->jb_prefetch != 0); 
     601    jb->jb_discard_dist  = 0; 
    554602 
    555603    jb_framelist_reset(&jb->jb_framelist); 
     
    563611    PJ_LOG(5, (jb->jb_name.ptr, "" 
    564612               "JB summary:\n" 
    565                "  size=%d prefetch=%d level=%d\n" 
     613               "  size=%d/eff=%d prefetch=%d level=%d\n" 
    566614               "  delay (min/max/avg/dev)=%d/%d/%d/%d ms\n" 
    567615               "  burst (min/max/avg/dev)=%d/%d/%d/%d frames\n" 
    568616               "  lost=%d discard=%d empty=%d", 
    569                jb->jb_framelist.size, jb->jb_prefetch, jb->jb_eff_level, 
     617               jb_framelist_size(&jb->jb_framelist),  
     618               jb_framelist_eff_size(&jb->jb_framelist),  
     619               jb->jb_prefetch, jb->jb_eff_level, 
    570620               jb->jb_delay.min, jb->jb_delay.max, jb->jb_delay.mean,  
    571621               pj_math_stat_get_stddev(&jb->jb_delay), 
     
    649699    } 
    650700} 
     701 
     702 
     703static void jbuf_discard_static(pjmedia_jbuf *jb) 
     704{ 
     705    /* These code is used for shortening the delay in the jitter buffer. 
     706     * It needs shrink only when there is possibility of drift. Drift 
     707     * detection is performed by inspecting the jitter buffer size, if 
     708     * its size is twice of current burst level, there can be drift. 
     709     * 
     710     * Moreover, normally drift level is quite low, so JB shouldn't need 
     711     * to shrink aggresively, it will shrink maximum one frame per  
     712     * PJMEDIA_JBUF_DISC_MIN_GAP ms. Theoritically, JB may handle drift level  
     713     * as much as = FRAME_PTIME/PJMEDIA_JBUF_DISC_MIN_GAP * 100% 
     714     * 
     715     * Whenever there is drift, where PUT > GET, this method will keep  
     716     * the latency (JB size) as much as twice of burst level. 
     717     */ 
     718 
     719    /* Shrinking due of drift will be implicitly done by progressive discard, 
     720     * so just disable it when progressive discard is active. 
     721     */ 
     722    int diff, burst_level; 
     723 
     724    burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level); 
     725    diff = jb_framelist_eff_size(&jb->jb_framelist) - burst_level*2; 
     726 
     727    if (diff >= STA_DISC_SAFE_SHRINKING_DIFF) { 
     728        int seq_origin; 
     729 
     730        /* Check and adjust jb_discard_ref, in case there was  
     731         * seq restart  
     732         */ 
     733        seq_origin = jb_framelist_origin(&jb->jb_framelist); 
     734        if (seq_origin < jb->jb_discard_ref) 
     735            jb->jb_discard_ref = seq_origin; 
     736 
     737        if (seq_origin - jb->jb_discard_ref >= jb->jb_min_shrink_gap) 
     738        { 
     739            /* Shrink slowly, one frame per cycle */ 
     740            diff = 1; 
     741 
     742            /* Drop frame(s)! */ 
     743            diff = jb_framelist_remove_head(&jb->jb_framelist, diff); 
     744            jb->jb_discard_ref = jb_framelist_origin(&jb->jb_framelist); 
     745            jb->jb_discard += diff; 
     746 
     747            TRACE__((jb->jb_name.ptr,  
     748                     "JB shrinking %d frame(s), cur size=%d", diff, 
     749                     jb_framelist_eff_size(&jb->jb_framelist))); 
     750        } 
     751    } 
     752} 
     753 
     754 
     755static void jbuf_discard_progressive(pjmedia_jbuf *jb) 
     756{ 
     757    unsigned cur_size, burst_level, overflow, T, discard_dist; 
     758    int last_seq; 
     759 
     760    /* Should be done in PUT operation */ 
     761    if (jb->jb_last_op != JB_OP_PUT) 
     762        return; 
     763 
     764    /* Check if latency is longer than burst */ 
     765    cur_size = jb_framelist_eff_size(&jb->jb_framelist); 
     766    burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level); 
     767    if (cur_size <= burst_level) { 
     768        /* Reset any scheduled discard */ 
     769        jb->jb_discard_dist = 0; 
     770        return; 
     771    } 
     772 
     773    /* Estimate discard duration needed for adjusting latency */ 
     774    if (burst_level <= PJMEDIA_JBUF_PRO_DISC_MIN_BURST) 
     775        T = PJMEDIA_JBUF_PRO_DISC_T1; 
     776    else if (burst_level >= PJMEDIA_JBUF_PRO_DISC_MAX_BURST) 
     777        T = PJMEDIA_JBUF_PRO_DISC_T2; 
     778    else 
     779        T = PJMEDIA_JBUF_PRO_DISC_T1 +  
     780            (PJMEDIA_JBUF_PRO_DISC_T2 - PJMEDIA_JBUF_PRO_DISC_T1) * 
     781            (burst_level - PJMEDIA_JBUF_PRO_DISC_MIN_BURST) / 
     782            (PJMEDIA_JBUF_PRO_DISC_MAX_BURST-PJMEDIA_JBUF_PRO_DISC_MIN_BURST); 
     783 
     784    /* Calculate current discard distance */ 
     785    overflow = cur_size - burst_level; 
     786    discard_dist = T / overflow / jb->jb_frame_ptime; 
     787 
     788    /* Get last seq number in the JB */ 
     789    last_seq = jb_framelist_origin(&jb->jb_framelist) + 
     790               jb_framelist_size(&jb->jb_framelist) - 1; 
     791 
     792    /* Setup new discard schedule if none, otherwise, update the existing 
     793     * discard schedule (can be delayed or accelerated). 
     794     */ 
     795    if (jb->jb_discard_dist == 0) { 
     796        /* Setup new discard schedule */ 
     797        jb->jb_discard_ref = last_seq; 
     798    } else if (last_seq < jb->jb_discard_ref) { 
     799        /* Seq restarted, update discard reference */ 
     800        jb->jb_discard_ref = last_seq; 
     801    } 
     802    jb->jb_discard_dist = PJ_MAX(jb->jb_min_shrink_gap, (int)discard_dist); 
     803 
     804    /* Check if we need to discard now */ 
     805    if (last_seq >= (jb->jb_discard_ref + (int)jb->jb_discard_dist)) { 
     806        int discard_seq; 
     807         
     808        discard_seq = jb->jb_discard_ref + jb->jb_discard_dist; 
     809        if (discard_seq < jb_framelist_origin(&jb->jb_framelist)) 
     810            discard_seq = jb_framelist_origin(&jb->jb_framelist); 
     811 
     812        jb_framelist_discard(&jb->jb_framelist, discard_seq); 
     813 
     814        TRACE__((jb->jb_name.ptr,  
     815                "Discard #%d: ref=#%d dist=%d orig=%d size=%d/%d " 
     816                "burst=%d/%d", 
     817                discard_seq, 
     818                jb->jb_discard_ref, 
     819                jb->jb_discard_dist, 
     820                jb_framelist_origin(&jb->jb_framelist), 
     821                cur_size, 
     822                jb_framelist_size(&jb->jb_framelist), 
     823                jb->jb_eff_level, 
     824                burst_level)); 
     825 
     826        /* Update discard reference */ 
     827        jb->jb_discard_ref = discard_seq; 
     828    } 
     829} 
     830     
    651831 
    652832PJ_INLINE(void) jbuf_update(pjmedia_jbuf *jb, int oper) 
     
    685865    } 
    686866 
    687     /* These code is used for shortening the delay in the jitter buffer. 
    688      * It needs shrink only when there is possibility of drift. Drift 
    689      * detection is performed by inspecting the jitter buffer size, if 
    690      * its size is twice of current burst level, there can be drift. 
    691      * 
    692      * Moreover, normally drift level is quite low, so JB shouldn't need 
    693      * to shrink aggresively, it will shrink maximum one frame per  
    694      * MIN_SHRINK_GAP_MSEC ms. Theoritically, JB may handle drift level  
    695      * as much as = FRAME_PTIME/MIN_SHRINK_GAP_MSEC * 100% 
    696      * 
    697      * Whenever there is drift, where PUT > GET, this method will keep  
    698      * the latency (JB size) as much as twice of burst level. 
    699      */ 
    700  
    701     /* Shrinking due of drift will be implicitly done by progressive discard, 
    702      * so just disable it when progressive discard is active. 
    703      */ 
    704 #if !PROGRESSIVE_DISCARD 
    705  
    706     if (jb->jb_status != JB_STATUS_PROCESSING) 
    707         return; 
    708  
    709     { 
    710         int diff, burst_level; 
    711  
    712         burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level); 
    713         diff = jb_framelist_eff_size(&jb->jb_framelist) - burst_level*2; 
    714  
    715         if (diff >= SAFE_SHRINKING_DIFF) { 
    716             int seq_origin; 
    717  
    718             /* Check and adjust jb_last_del_seq, in case there was  
    719              * seq restart  
    720              */ 
    721             seq_origin = jb_framelist_origin(&jb->jb_framelist); 
    722             if (seq_origin < jb->jb_last_del_seq) 
    723                 jb->jb_last_del_seq = seq_origin; 
    724  
    725             if (seq_origin - jb->jb_last_del_seq >= jb->jb_min_shrink_gap) 
    726             { 
    727                 /* Shrink slowly, one frame per cycle */ 
    728                 diff = 1; 
    729  
    730                 /* Drop frame(s)! */ 
    731                 diff = jb_framelist_remove_head(&jb->jb_framelist, diff); 
    732                 jb->jb_last_del_seq = jb_framelist_origin(&jb->jb_framelist); 
    733                 jb->jb_discard += diff; 
    734  
    735                 TRACE__((jb->jb_name.ptr,  
    736                          "JB shrinking %d frame(s), cur size=%d", diff, 
    737                          jb_framelist_eff_size(&jb->jb_framelist))); 
    738             } 
    739         } 
    740     } 
    741  
    742 #endif /* !PROGRESSIVE_DISCARD */ 
    743  
     867    /* Call discard algorithm */ 
     868    if (jb->jb_status == JB_STATUS_PROCESSING && jb->jb_discard_algo) { 
     869        (*jb->jb_discard_algo)(jb); 
     870    } 
    744871} 
    745872 
     
    760887{ 
    761888    pj_size_t min_frame_size; 
    762     int new_size, cur_size, frame_type = PJMEDIA_JB_NORMAL_FRAME; 
     889    int new_size, cur_size; 
    763890    pj_status_t status; 
    764891 
    765892    cur_size = jb_framelist_eff_size(&jb->jb_framelist); 
    766  
    767 #if PROGRESSIVE_DISCARD 
    768     { 
    769         unsigned interval, seq_delta; 
    770         unsigned burst_level = 0, overflow_pct = 0; 
    771  
    772         /* Calculating percentage of burst overflow */ 
    773         if (jb->jb_status == JB_STATUS_PROCESSING) { 
    774             burst_level = PJ_MAX(jb->jb_eff_level, jb->jb_level); 
    775             if (cur_size > (int)burst_level) 
    776                 overflow_pct = (cur_size - burst_level) * 100 / burst_level; 
    777         } 
    778  
    779         /* Deciding discard interval (aggressiveness) based on 
    780          * burst overflow percentage. 
    781          */ 
    782         if (burst_level <= 5 && overflow_pct < 200) { 
    783             /* Tolerate spikes on relatively small burst level */ 
    784             interval = 0; 
    785         } else if (overflow_pct >= 200) { 
    786             /* Overflow >= 200% */ 
    787             interval = 4; 
    788         } else if (overflow_pct >= 100) { 
    789             /* Overflow >= 100% */ 
    790             interval = 5; 
    791         } else if (overflow_pct >= 10) { 
    792             /* Overflow >= 10% */ 
    793             interval = 7; 
    794         } else { 
    795             /* Overflow < 10%, tolerable */ 
    796             interval = 0; 
    797         } 
    798  
    799         /* Do the math now to see if we should discard this packet. 
    800          * Calculate the distance from the last sequence 
    801          * discarded. If negative, then this is an out of 
    802          * order frame so just proceed with discard. Else 
    803          * see if the delta is at least the intervals worth away 
    804          * from the last frame discarded. 
    805          */ 
    806         seq_delta = (pj_uint16_t)(frame_seq - jb->jb_last_discard_seq); 
    807         if ((0 != interval) && (seq_delta >= interval)) { 
    808             frame_type = PJMEDIA_JB_DISCARDED_FRAME; 
    809             jb->jb_last_discard_seq = frame_seq; 
    810  
    811             TRACE__((jb->jb_name.ptr,  
    812                     "Discarding frame #%d: eff=%d disc=%d orig:%d" 
    813                     " seq_delta:%d", 
    814                     frame_seq, 
    815                     cur_size, 
    816                     jb_framelist_size(&jb->jb_framelist) - cur_size, 
    817                     jb_framelist_origin(&jb->jb_framelist), 
    818                     (int)seq_delta)); 
    819         } 
    820     } 
    821 #endif /* PROGRESSIVE_DISCARD */ 
    822      
    823893 
    824894    /* Attempt to store the frame */ 
    825895    min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size); 
    826896    status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame, 
    827                                  min_frame_size, bit_info, frame_type); 
     897                                 min_frame_size, bit_info, 
     898                                 PJMEDIA_JB_NORMAL_FRAME); 
    828899     
    829900    /* Jitter buffer is full, remove some older frames */ 
     
    832903        unsigned removed; 
    833904 
    834         /* When progressive discard activated, just remove as few as possible 
    835          * just to make this frame in. 
    836          */ 
    837 #if PROGRESSIVE_DISCARD 
    838         /* The cases of seq-jump, out-of-order, and seq restart should have 
     905        /* Remove as few as possible just to make this frame in. Note that 
     906         * the cases of seq-jump, out-of-order, and seq restart should have 
    839907         * been handled/normalized by previous call of jb_framelist_put_at(). 
    840908         * So we're confident about 'distance' value here. 
     
    843911                   jb->jb_max_count + 1; 
    844912        pj_assert(distance > 0); 
    845 #else 
    846         distance = PJ_MAX(jb->jb_max_count/4, 1); 
    847 #endif 
     913 
    848914        removed = jb_framelist_remove_head(&jb->jb_framelist, distance); 
    849915        status = jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame, 
    850                                      min_frame_size, bit_info, frame_type); 
     916                                     min_frame_size, bit_info, 
     917                                     PJMEDIA_JB_NORMAL_FRAME); 
    851918 
    852919        jb->jb_discard += removed; 
  • pjproject/branches/1.x/pjmedia/src/test/jbuf_test.c

    r3553 r3814  
    4444    int lost; 
    4545    int empty; 
    46     int delay;      /**< Maximum delay, in frames.          */ 
     46    int delay;      /**< Average delay, in frames.          */ 
     47    int delay_min;  /**< Minimum delay, in frames.          */ 
    4748} test_cond_t; 
    4849 
     
    7071        else if (pj_ansi_stricmp(cond_st, "delay") == 0) 
    7172            cond->delay = cond_val; 
     73        else if (pj_ansi_stricmp(cond_st, "delay_min") == 0) 
     74            cond->delay_min = cond_val; 
    7275        else if (pj_ansi_stricmp(cond_st, "discard") == 0) 
    7376            cond->discard = cond_val; 
     
    218221        cond.burst = -1; 
    219222        cond.delay = -1; 
     223        cond.delay_min = -1; 
    220224        cond.discard = -1; 
    221225        cond.empty = -1; 
     
    314318            rc |= 2; 
    315319        } 
     320        if (cond.delay_min >= 0 && (int)state.min_delay/JB_PTIME > cond.delay_min) { 
     321            printf("! 'Minimum delay' should be %d, it is %d\n",  
     322                   cond.delay_min, state.min_delay/JB_PTIME); 
     323            rc |= 32; 
     324        } 
    316325        if (cond.discard >= 0 && (int)state.discard > cond.discard) { 
    317326            printf("! 'Discard' should be %d, it is %d\n", 
Note: See TracChangeset for help on using the changeset viewer.