Changeset 1775


Ignore:
Timestamp:
Feb 3, 2008 4:55:31 PM (12 years ago)
Author:
nanang
Message:

Ticket #461:

  • added JB phases(idle, learning, running)
  • changed jb_vbuf_shrink_to() to jb_vbuf_shrink(), the size param specifies the shrink size
  • added jb_vbuf_expand
  • modified insert_samples(), automatically insert new frames needed to jb
Location:
pjproject/branches/projects/jbuf2/pjmedia
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/jbuf2/pjmedia/include/pjmedia/jbuf2.h

    r1770 r1775  
    4949 */ 
    5050typedef struct pjmedia_jb2_t pjmedia_jb2_t; 
     51 
     52/** 
     53 * Types of jitter buffer phase. 
     54 */ 
     55typedef enum pjmedia_jb2_phase  
     56{ 
     57    PJMEDIA_JB_PH_IDLE      = 0,        /**< No activity in PUT/GET or both */ 
     58    PJMEDIA_JB_PH_LEARNING  = 1,        /**< Normal encoded frame */ 
     59    PJMEDIA_JB_PH_RUNNING   = 2,        /**< Normal PCM frame */ 
     60} pjmedia_jb2_phase; 
    5161 
    5262/** 
     
    7989typedef struct pjmedia_jb2_state 
    8090{ 
    81     /* frames */ 
     91    pjmedia_jb2_phase phase; 
     92 
     93    /* in frames */ 
    8294    pj_uint16_t  level; 
    8395    pj_uint32_t  frame_cnt; 
    8496     
    85     /* samples */ 
     97    /* in samples */ 
    8698    pj_int32_t   drift; 
    8799    pj_uint32_t  drift_span; 
     
    97109typedef struct pjmedia_jb2_stat 
    98110{ 
    99     /* frames */ 
     111    /* in frames */ 
    100112    pj_uint32_t  lost; 
    101113    pj_uint32_t  late; 
     
    104116    pj_uint32_t  in; 
    105117 
    106     /* ticks */ 
     118    /* in ticks */ 
    107119    pj_uint32_t  full; 
    108120    pj_uint32_t  empty; 
    109121 
    110     /* samples */ 
     122    /* in samples */ 
    111123    pj_uint32_t  max_size; 
    112124    pj_int32_t   max_drift; 
     
    114126    pj_int32_t   max_comp; 
    115127 
    116     /* ticks */ 
     128    /* in frames */ 
    117129    pj_uint16_t  max_level; 
    118130} pjmedia_jb2_stat; 
  • pjproject/branches/projects/jbuf2/pjmedia/src/pjmedia/jbuf2.c

    r1773 r1775  
    118118 * 
    119119 * History structure: 
    120  * - JB holds array of history, each element represent condition of JB at  
     120 * - JB holds array of history, each element represents condition of JB at  
    121121 *   specified time t (marked by tick), ordered as the newest is the first. 
    122122 * - History has age, when it is expired, history will be shifted/discarded. 
     
    177177    pj_int16_t               cur_level; 
    178178    pj_uint32_t              tick; 
    179     pj_bool_t                idle; 
    180179    jb_drift_state           drift_state; 
    181180 
     
    202201        pj_list_erase(f); 
    203202    } else if (jb->state.frame_cnt >= jb->setting.max_frames) { 
    204         TRACE__((THIS_FILE, "Frame numbers exceeds max(%d)!", 
     203        TRACE__((THIS_FILE, "Frame numbers(%d) exceeds max(%d)!", 
    205204            jb->state.frame_cnt, jb->setting.max_frames)); 
    206205        return NULL; 
     
    233232    pjmedia_jb2_t *jb; 
    234233    jb_frame_list *f[8]; 
    235     int cnt; 
     234    unsigned cnt; 
    236235 
    237236    /* public */ 
    238     int size; 
     237    unsigned size; 
    239238} jb_vbuf; 
    240239 
     
    270269static pj_int16_t jb_vbuf_get_sample(jb_vbuf *buf, unsigned idx) 
    271270{ 
    272     int i; 
     271    unsigned i; 
    273272    unsigned idx_ = idx; 
    274273     
     
    289288                                   pj_int16_t val) 
    290289{ 
    291     int i; 
     290    unsigned i; 
    292291    unsigned idx_ = idx; 
    293292     
     
    304303} 
    305304 
    306 /* Can only shrink */ 
    307 static void jb_vbuf_shrink_to(jb_vbuf *buf, int size) 
     305static void jb_vbuf_shrink(jb_vbuf *buf, unsigned size) 
    308306{ 
    309307    int i; 
    310308     
    311     pj_assert(buf && size < buf->size); 
    312  
    313     for (i = buf->cnt-1; i>=0 && buf->size>size; --i) { 
    314         if ((buf->size - (int)buf->f[i]->frame.size) >= size) { 
     309    pj_assert(buf && size <= buf->size); 
     310 
     311    for (i = buf->cnt-1; i>=0 && size>0; --i) { 
     312        if (buf->f[i]->frame.size <= size) { 
    315313            buf->cnt--; 
    316314            buf->size -= buf->f[i]->frame.size; 
     315            size -= buf->f[i]->frame.size; 
    317316            /* modify jb */ 
    318317            buf->jb->state.cur_size -= buf->f[i]->frame.size/2; 
    319318            buf->f[i]->frame.size = 0; 
    320             //release_frame(buf->jb, buf->f[i]); 
    321319        } else { 
    322             int diff = buf->size - size; 
    323             buf->f[i]->frame.size -= diff; 
    324             buf->size -= diff; 
     320            buf->f[i]->frame.size -= size; 
     321            buf->size -= size; 
    325322            /* modify jb */ 
    326             buf->jb->state.cur_size -= diff/2; 
    327         } 
     323            buf->jb->state.cur_size -= size/2; 
     324            size = 0; 
     325        } 
     326    } 
     327} 
     328 
     329static void jb_vbuf_expand(jb_vbuf *buf, unsigned size) 
     330{ 
     331    jb_frame_list *f; 
     332    int step; 
     333 
     334    pj_assert(buf); 
     335 
     336    while (size > 0) { 
     337        step = PJ_MIN(buf->jb->setting.frame_size, size); 
     338 
     339        f = alloc_frame(buf->jb); 
     340        f->frame.pt = buf->f[buf->cnt-1]->frame.pt; 
     341        f->frame.seq = buf->f[buf->cnt-1]->frame.seq; 
     342        f->frame.size = step; 
     343        f->frame.ts = buf->f[buf->cnt-1]->frame.ts; 
     344        f->frame.type = buf->f[buf->cnt-1]->frame.type; 
     345 
     346        pj_list_insert_after(buf->f[buf->cnt - 1], f); 
     347        buf->jb->state.cur_size += step/2; 
     348 
     349        pj_assert(buf->cnt <= sizeof(buf->f)/sizeof(buf->f[0])); 
     350        buf->f[buf->cnt++] = f; 
     351        buf->size += step; 
     352 
     353        size -= step; 
    328354    } 
    329355} 
     
    362388    pj_bzero(&jb->state, sizeof(pjmedia_jb2_state)); 
    363389    jb->state.frame_cnt = i; 
    364     jb->state.level = 1; 
     390    jb->state.level = 0; 
    365391 
    366392    /* Reset drift state */ 
    367393    pj_bzero(&jb->drift_state, sizeof(jb_drift_state)); 
    368394 
    369     /* Set not idle */ 
    370     jb->idle = PJ_FALSE; 
     395    /* Set start learning */ 
     396    jb->state.phase = PJMEDIA_JB_PH_LEARNING; 
    371397 
    372398    /* Reset current level */ 
     
    511537    pos = jb->frames.prev; 
    512538 
    513     if (jb->idle) 
     539    if (jb->state.phase == PJMEDIA_JB_PH_IDLE) 
    514540        goto ON_RETURN; 
    515541 
     
    557583    tmp->frame.pt = f->pt; 
    558584    tmp->frame.seq = f->seq; 
    559     tmp->frame.size = (f->seq == 1? 160: f->size); 
     585    tmp->frame.size = f->size; 
    560586    tmp->frame.ts = f->ts; 
    561587    tmp->frame.type = f->type; 
     
    566592    /* Decode frame(s) if needed */ 
    567593    if (tmp->frame.type == PJMEDIA_JB_FT_NORMAL_RAW_FRAME) { 
    568         if (f->seq == 1) 
    569             jb->state.cur_size += 80; 
    570         else 
    571             jb->state.cur_size += jb->setting.samples_per_frame; 
     594        jb->state.cur_size += jb->setting.samples_per_frame; 
    572595    } 
    573596    else if (tmp->prev != &jb->frames &&  
     
    596619    update_state(jb, PJ_TRUE); 
    597620 
    598     if (jb->idle) 
     621    if (jb->state.phase == PJMEDIA_JB_PH_IDLE) 
    599622        goto ON_RETURN; 
    600623 
     
    698721    /* Not enough samples in PCM buffer */ 
    699722    if (jb->state.cur_size < jb->setting.samples_per_frame) { 
     723        if (jb->state.phase != PJMEDIA_JB_PH_LEARNING) { 
     724            TRACE__((THIS_FILE,"Not enough PCM samples (%d)!",  
     725                     jb->state.cur_size)); 
     726            ++jb->stat.empty; 
     727        } 
    700728        goto RETURN_EMPTY_FRAME; 
    701729    } 
     
    727755            tmp->frame.size -= i; 
    728756 
    729             /* Shift buffer, don't shift the pointer! */ 
     757            /* Shift the buffer, don't shift the pointer! */ 
    730758            pj_memmove(tmp->frame.buffer, (pj_int8_t*)tmp->frame.buffer + i,  
    731759                       tmp->frame.size); 
     
    738766    jb->state.cur_size -= jb->setting.samples_per_frame; 
    739767 
     768    /* JB still learning the level */ 
     769    if (jb->state.phase == PJMEDIA_JB_PH_LEARNING) 
     770        goto RETURN_EMPTY_FRAME; 
     771 
    740772    goto ON_RETURN; 
    741773 
    742774RETURN_EMPTY_FRAME: 
    743     TRACE__((THIS_FILE,"Return empty frame!")); 
    744  
    745     ++jb->stat.empty; 
    746775 
    747776    f->type = PJMEDIA_JB_FT_NULL_FRAME; 
     
    752781    pj_bzero(f->buffer, f->size); 
    753782 
    754     /* Instead of return zero samples, it'd be better to return noise */ 
     783    /* Instead of returning zero samples, it'd be better to return noise */ 
    755784 
    756785ON_RETURN: 
     
    767796 
    768797        /* JB idle? */ 
    769         if (jb->idle) { 
     798        if (jb->state.phase == PJMEDIA_JB_PH_IDLE) { 
    770799            TRACE__((THIS_FILE, "Idle ended, reinit jitter buffer.")); 
    771             jb->idle = PJ_FALSE; 
    772800 
    773801            /* Reinit JB */ 
     
    803831            /* Calculate optimum size */ 
    804832            jb->state.opt_size = jb->setting.samples_per_frame * level_sum / 
    805                                  level_factor + jb->setting.samples_per_frame; 
     833                                 level_factor 
     834                                 + jb->setting.samples_per_frame / 2; 
    806835            if (jb->state.opt_size > 
    807836                jb->setting.max_frames * jb->setting.samples_per_frame) 
     
    812841 
    813842            } 
     843 
     844            /* Switching phase: learning -> running, 
     845             * if history has shifted and current size reaches optimum size. 
     846             */ 
     847            if (jb->state.phase == PJMEDIA_JB_PH_LEARNING) {  
     848                if (jb->hist[1].level > 0 &&  
     849                    jb->state.cur_size >= jb->state.opt_size) 
     850                { 
     851                    jb->state.phase = PJMEDIA_JB_PH_RUNNING; 
     852                    TRACE__((THIS_FILE, "JB start running (%d>=%d)",  
     853                             jb->state.cur_size, jb->state.opt_size)); 
     854                } else { 
     855                    TRACE__((THIS_FILE, "Learning %d->%d", jb->state.cur_size, 
     856                             jb->state.opt_size)); 
     857                } 
     858            } 
     859 
     860 
    814861#ifdef INC_OPT_SIZE_TO_DRIFT_CALC 
    815862            /* Include opt_size to drift calculation */ 
     
    836883        /* Check idle */ 
    837884        if (jb->hist[0].in == jb->stat.in || jb->hist[0].out == jb->stat.out) { 
    838             if (!jb->idle) 
     885            if (jb->state.phase != PJMEDIA_JB_PH_IDLE) 
    839886                TRACE__((THIS_FILE, "Idle operation detected.")); 
    840887 
    841             jb->idle = PJ_TRUE; 
     888            jb->state.phase = PJMEDIA_JB_PH_IDLE; 
    842889 
    843890            goto SHIFT_HISTORY; 
     
    887934/* Find matching samples pattern, longest possible distance for !left_ref */ 
    888935static pj_status_t find_matched_window(jb_vbuf *buf, pj_bool_t left_ref,  
    889                                        int pref_dist, 
     936                                       unsigned pref_dist, 
    890937                                       unsigned *ref_, unsigned *match_) 
    891938{ 
     
    945992/* Find matching samples pattern, shortest possible distance for !left_ref */ 
    946993static pj_status_t find_matched_window2(jb_vbuf *buf, pj_bool_t left_ref,  
    947                                        int pref_dist, 
     994                                       unsigned pref_dist, 
    948995                                       unsigned *ref_, unsigned *match_) 
    949996{ 
    950997    const int MATCH_THRESHOLD = MATCH_WINDOW_LEN*1200; 
    951     unsigned ref, ptr, end; 
     998    int ref, ptr, end; 
    952999    int i, similarity, s1, s2; 
    9531000 
     
    9711018        ref = buf->size/2 - MATCH_WINDOW_LEN; 
    9721019        end = -1; 
    973         ptr = ref - MATCH_WINDOW_LEN; 
     1020        if (ref - MATCH_WINDOW_LEN >= (int)pref_dist) 
     1021            ptr = ref - MATCH_WINDOW_LEN - pref_dist; 
     1022        else 
     1023            ptr = ref - MATCH_WINDOW_LEN; 
    9741024    } 
    9751025 
     
    9901040            return PJ_SUCCESS; 
    9911041        } 
    992         ptr += left_ref ? -1 : -1; 
     1042        --ptr; 
    9931043    } 
    9941044 
     
    9961046} 
    9971047 
    998 /* Add n samples to buf, the additional samples will be put in dest, 
     1048/* Add n samples for buf, the additional samples will be put in dest, 
    9991049 * the buf may be modified but the buf size is not. Function will return 
    10001050 * the number of inserted samples. 
    10011051 */ 
    1002 static int insert_samples(jb_vbuf *buf, int n,  
    1003                           void *dest, pj_size_t dest_size) 
    1004 { 
    1005     unsigned ref, match; 
     1052static int insert_samples(jb_vbuf *buf, int n) 
     1053{ 
     1054    unsigned ref, match, dest; 
    10061055    pj_status_t status; 
    10071056    int i, distance; 
     
    10111060        n = MATCH_WINDOW_LEN; 
    10121061 
    1013     if (n > (int)dest_size / 2) 
    1014         n = dest_size / 2; 
    1015  
    1016     status = find_matched_window(buf, PJ_FALSE, n, &ref, &match); 
     1062    status = find_matched_window2(buf, PJ_FALSE, n, &ref, &match); 
    10171063    if (status != PJ_SUCCESS)  
    10181064        return 0; 
     
    10201066    distance = ref - match; 
    10211067    pj_assert(distance > 0); 
     1068 
     1069    dest = buf->size/2; 
     1070    jb_vbuf_expand(buf, distance*2); 
    10221071 
    10231072    // memcpy 
    10241073    for (i = 0; i < distance; ++i) { 
    10251074        s1 = jb_vbuf_get_sample(buf, match + MATCH_WINDOW_LEN + i); 
    1026         *((pj_int16_t*)dest + i) = s1; 
     1075        jb_vbuf_set_sample(buf, dest + i, s1); 
    10271076    } 
    10281077 
     
    10681117 
    10691118    // memmove 
    1070     for (i = 0; i < buf->size/2 - distance - MATCH_WINDOW_LEN; ++i) { 
     1119    for (i = 0; i < (int)buf->size/2 - distance - MATCH_WINDOW_LEN; ++i) { 
    10711120        s1 = jb_vbuf_get_sample(buf, match + MATCH_WINDOW_LEN + i); 
    10721121        jb_vbuf_set_sample(buf, ref + MATCH_WINDOW_LEN + i, s1); 
    10731122    } 
    10741123 
    1075     jb_vbuf_shrink_to(buf, buf->size - distance*2); 
     1124    jb_vbuf_shrink(buf, distance*2); 
    10761125 
    10771126    return distance; 
     
    11751224    culprit += jb->drift_state.pending; 
    11761225 
    1177     /* Culprit may be negative when pending is negative. 
    1178      * pending the compensation if this happens. 
     1226    /* Culprit may be negative when pending is negative, 
     1227     * which means last compensation was more than needed, 
     1228     * nothing to compensate if this happens. 
    11791229     */ 
    1180     if (culprit < 0) { 
     1230    if (culprit <= 0) { 
    11811231        jb->drift_state.pending = culprit; 
    11821232        return; 
    11831233    } 
    1184  
    1185     /* Nothing to compensate */ 
    1186     if (!culprit) 
    1187         return; 
    11881234 
    11891235    orig_cur_size = jb->state.cur_size; 
     
    12051251        int deleted = 0; 
    12061252 
    1207         //if (jb->state.cur_size > 
    1208         //    (jb->setting.samples_per_frame + culprit)) 
     1253        if (culprit > (int)jb->state.cur_size || 
     1254            jb->state.cur_size > 
     1255            (jb->setting.samples_per_frame + culprit)) 
    12091256        { 
    12101257            deleted = delete_samples(&buf, culprit); 
     
    12211268 
    12221269        int inserted = 0; 
    1223         jb_frame_list *tmp_f; 
    12241270         
    1225         tmp_f = alloc_frame(jb); 
    1226         if (tmp_f) { 
    1227             inserted = insert_samples(&buf, 
    1228                                       culprit, tmp_f->frame.buffer,  
    1229                                       jb->setting.frame_size); 
    1230  
    1231             if (inserted > 0) { 
    1232                 tmp_f->frame.pt = buf.f[buf.cnt-1]->frame.pt; 
    1233                 tmp_f->frame.seq = buf.f[buf.cnt-1]->frame.seq; 
    1234                 tmp_f->frame.size = inserted * sample_size; 
    1235                 tmp_f->frame.ts = buf.f[buf.cnt-1]->frame.ts; 
    1236                 tmp_f->frame.type = buf.f[buf.cnt-1]->frame.type; 
    1237              
    1238                 jb->state.cur_size += inserted; 
    1239                 pj_list_insert_after(buf.f[buf.cnt-1], tmp_f); 
    1240             } else { 
    1241                 pj_list_push_back(&jb->frames_pool, tmp_f); 
    1242             } 
    1243         } 
     1271        inserted = insert_samples(&buf, culprit); 
     1272 
    12441273        jb->drift_state.pending = culprit - inserted; 
    12451274 
Note: See TracChangeset for help on using the changeset viewer.