Changeset 1778


Ignore:
Timestamp:
Feb 4, 2008 11:52:43 PM (17 years ago)
Author:
nanang
Message:

Ticket #461:

  • added param userdata to JB callbacks
  • added a bit optimization on pjmedia_jb2_get_frame(): shifting pointer instead of shifting frame buffer(memmove) when only parts of PCM frame needed
  • modified DTX handling mechanism: detects jumping timestamp but good sequence to generate noise/silence frames, instead of relying on abnormal drift.
  • modified behaviour on failure of allocating frame
  • moved abnormal drift detection from compensate_drift() to update_state()
  • added/removed some log for debugging purpose
Location:
pjproject/branches/projects/jbuf2/pjmedia
Files:
2 edited

Legend:

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

    r1775 r1778  
    5656{ 
    5757    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 */ 
     58    PJMEDIA_JB_PH_LEARNING  = 1,        /**< Learning */ 
     59    PJMEDIA_JB_PH_RUNNING   = 2,        /**< Running */ 
    6060} pjmedia_jb2_phase; 
    6161 
     
    137137 
    138138/** 
     139 * This structure describes jitter buffer callback 
     140 */ 
     141typedef struct pjmedia_jb2_cb 
     142{ 
     143    pj_status_t (*decode) (pjmedia_jb2_frame *frame, void *userdata); 
     144    pj_status_t (*plc)    (pjmedia_jb2_frame *frame, void *userdata); 
     145    pj_status_t (*cng)    (pjmedia_jb2_frame *frame, void *userdata); 
     146    void                  *user_data; 
     147} pjmedia_jb2_cb; 
     148 
     149 
     150/** 
    139151 * This structure describes jitter buffer current status. 
    140152 */ 
     
    162174 
    163175} pjmedia_jb2_setting; 
    164  
    165 typedef struct pjmedia_jb2_cb 
    166 { 
    167     pj_status_t (*decode) (pjmedia_jb2_frame *frame); 
    168     pj_status_t (*plc)    (pjmedia_jb2_frame *frame); 
    169     pj_status_t (*cng)    (pjmedia_jb2_frame *frame); 
    170 } pjmedia_jb2_cb; 
    171176 
    172177 
  • pjproject/branches/projects/jbuf2/pjmedia/src/pjmedia/jbuf2.c

    r1775 r1778  
    4242/* Max frames specifies maximum frames allowed to be allocated. 
    4343 */ 
    44 #define MAX_FRAMES              100 
     44#define MAX_FRAMES              20 
    4545 
    4646/* History constants specify entries number of history, 
     
    133133    PJ_DECL_LIST_MEMBER(struct jb_frame_list); 
    134134    pjmedia_jb2_frame   frame; 
     135    void                *orig_buffer; 
    135136} jb_frame_list; 
    136137 
     
    168169    pjmedia_jb2_state        state; 
    169170 
    170     /* last get frame */ 
     171    /* frame history */ 
    171172    pjmedia_jb2_frame        last_frame_out; 
     173    pjmedia_jb2_frame        last_frame_cn; 
    172174 
    173175    /* state update */ 
     
    183185}; 
    184186 
    185 static void init_jb(pjmedia_jb2_t *jb); 
    186187static void update_state(pjmedia_jb2_t *jb, pj_bool_t on_get); 
    187188static void compensate_drift(pjmedia_jb2_t *jb); 
     
    201202        pj_list_erase(f); 
    202203    } else if (jb->state.frame_cnt >= jb->setting.max_frames) { 
    203         TRACE__((THIS_FILE, "Frame numbers(%d) exceeds max(%d)!", 
    204             jb->state.frame_cnt, jb->setting.max_frames)); 
     204        TRACE__((THIS_FILE, "Frame numbers %d(=%d?) exceeds max(%d)!", 
     205            jb->state.frame_cnt, pj_list_size(&jb->frames),  
     206            jb->setting.max_frames)); 
    205207        return NULL; 
    206208    } else { 
     
    210212            return NULL; 
    211213        } 
    212         f->frame.buffer = pj_pool_alloc(jb->pool, jb->setting.frame_size); 
    213         if (NULL == f->frame.buffer) return NULL; 
     214        f->orig_buffer = pj_pool_alloc(jb->pool, jb->setting.frame_size); 
     215        f->frame.buffer = f->orig_buffer; 
     216        if (NULL == f->frame.buffer) { 
     217            TRACE__((THIS_FILE, "Failed to allocate frame buffer!")); 
     218            return NULL; 
     219        } 
    214220        ++jb->state.frame_cnt; 
    215221    } 
     
    223229    pj_list_erase(f); 
    224230    pj_list_push_back(&jb->frames_pool, f); 
     231    f->frame.buffer = f->orig_buffer; 
    225232} 
    226233 
     
    327334} 
    328335 
    329 static void jb_vbuf_expand(jb_vbuf *buf, unsigned size) 
     336static pj_bool_t jb_vbuf_expand(jb_vbuf *buf, unsigned size) 
    330337{ 
    331338    jb_frame_list *f; 
    332339    int step; 
     340    int orig_buf_cnt = buf->cnt; 
    333341 
    334342    pj_assert(buf); 
     
    338346 
    339347        f = alloc_frame(buf->jb); 
     348        if (!f) { 
     349            unsigned i; 
     350            /* Rollback */ 
     351            for (i=orig_buf_cnt; i<buf->cnt; ++i) { 
     352                buf->size -= buf->f[i]->frame.size; 
     353                buf->jb->state.cur_size -= buf->f[i]->frame.size/2; 
     354                release_frame(buf->jb, buf->f[i]); 
     355            } 
     356            buf->cnt = orig_buf_cnt; 
     357            return PJ_FALSE; 
     358        } 
     359 
    340360        f->frame.pt = buf->f[buf->cnt-1]->frame.pt; 
    341361        f->frame.seq = buf->f[buf->cnt-1]->frame.seq; 
     
    353373        size -= step; 
    354374    } 
    355 } 
    356  
    357 static void init_jb(pjmedia_jb2_t *jb) 
     375    return PJ_TRUE; 
     376} 
     377 
     378/* Decode consecutive undecoded frames. */ 
     379static pj_status_t decode_frames(pjmedia_jb2_t *jb, jb_frame_list* start, 
     380                                 int max) 
     381{ 
     382    jb_frame_list* tmp = start; 
     383    pj_status_t status; 
     384 
     385    PJ_ASSERT_RETURN(jb && start && jb->cb.decode, PJ_EINVAL); 
     386 
     387    /* Decoded already */ 
     388    if (start->frame.type != PJMEDIA_JB_FT_NORMAL_FRAME) 
     389        return PJ_SUCCESS; 
     390 
     391    /* In the beginning, make sure it is sequenced from last_frame_out, 
     392     * otherwise we cannot detect packet loss. 
     393     */ 
     394    if (start->prev == &jb->frames &&                           /* beginning */ 
     395        jb->last_frame_out.seq &&                        /* last out defined */ 
     396        start->frame.seq > jb->last_frame_out.seq &&         /* bad sequence */ 
     397        (start->frame.seq - jb->last_frame_out.seq > 1)) 
     398    { 
     399        return PJ_SUCCESS; 
     400    } 
     401 
     402    /* Not in the beginning, make sure previous frame is sequenced & decoded */ 
     403    if (start->prev != &jb->frames &&                       /* not beginning */ 
     404        ((start->frame.seq > start->prev->frame.seq &&       /* bad sequence */ 
     405         (start->frame.seq - start->prev->frame.seq > 1)) || 
     406        start->prev->frame.type == PJMEDIA_JB_FT_NORMAL_FRAME)) /* undecoded */ 
     407    { 
     408        return PJ_SUCCESS; 
     409    } 
     410 
     411    do { 
     412        status = jb->cb.decode(&tmp->frame, jb->cb.user_data); 
     413         
     414        if (status != PJ_SUCCESS) { 
     415            TRACE__((THIS_FILE,"Failed to decode frame!")); 
     416            release_frame(jb, tmp); 
     417            return PJMEDIA_JB2_EFAILDECODE; 
     418        } 
     419        tmp->frame.type = PJMEDIA_JB_FT_NORMAL_RAW_FRAME; 
     420        tmp = tmp->next; 
     421         
     422        jb->state.cur_size += jb->setting.samples_per_frame; 
     423 
     424    } while (tmp != &jb->frames &&  
     425             tmp->frame.type == PJMEDIA_JB_FT_NORMAL_FRAME && 
     426             (tmp->frame.ts - tmp->prev->frame.ts <=  
     427             jb->setting.samples_per_frame) && 
     428             (!max || --max > 0)); 
     429 
     430    return PJ_SUCCESS; 
     431} 
     432 
     433PJ_DEF(pj_status_t) pjmedia_jb2_create( pj_pool_t *pool, 
     434                                          const pj_str_t *name, 
     435                                          const pjmedia_jb2_setting *setting, 
     436                                          const pjmedia_jb2_cb *cb, 
     437                                          pjmedia_jb2_t **p_jb ) 
     438{ 
     439    pjmedia_jb2_t *jb; 
     440 
     441    PJ_ASSERT_RETURN(pool && setting && cb && p_jb, PJ_EINVAL); 
     442 
     443    if (setting->max_frames > MAX_FRAMES) { 
     444        PJ_LOG(4,(THIS_FILE, "Max frames requested is too big!")); 
     445        return PJ_EINVAL; 
     446    } 
     447 
     448    jb = PJ_POOL_ZALLOC_T(pool, pjmedia_jb2_t); 
     449    jb->pool = pool; 
     450 
     451    if (name) 
     452        pj_strdup_with_null(jb->pool, &jb->name, name); 
     453    else 
     454        pj_strdup2_with_null(pool, &jb->name, "jb2"); 
     455 
     456    pj_list_init(&jb->frames_pool); 
     457    pj_list_init(&jb->frames); 
     458 
     459    jb->setting = *setting; 
     460    jb->cb = *cb; 
     461 
     462    /* Init CN frame */ 
     463    pj_bzero(&jb->last_frame_cn, sizeof(jb->last_frame_cn)); 
     464    jb->last_frame_cn.buffer = pj_pool_zalloc(pool, setting->frame_size); 
     465    jb->last_frame_cn.size = 0; 
     466 
     467    if (!jb->setting.max_frames) 
     468        jb->setting.max_frames = MAX_FRAMES; 
     469     
     470    pjmedia_jb2_reset(jb); 
     471 
     472    *p_jb = jb; 
     473 
     474    return PJ_SUCCESS; 
     475} 
     476 
     477PJ_DEF(pj_status_t) pjmedia_jb2_destroy(pjmedia_jb2_t *jb) 
     478{ 
     479    pjmedia_jb2_stat jb_stat; 
     480    pjmedia_jb2_state jb_state; 
     481 
     482    PJ_ASSERT_RETURN(jb, PJ_EINVAL); 
     483 
     484    pjmedia_jb2_get_state(jb, &jb_state); 
     485    PJ_LOG(5, (jb->name.ptr, "JB state:")); 
     486    PJ_LOG(5, (jb->name.ptr, "Drift\t = %5d/%d", jb_state.drift,  
     487                                                 jb_state.drift_span)); 
     488    PJ_LOG(5, (jb->name.ptr, "Level\t = %5d ticks", jb_state.level)); 
     489    PJ_LOG(5, (jb->name.ptr, "Size\t = %5d samples", jb_state.cur_size)); 
     490    PJ_LOG(5, (jb->name.ptr, "Opt.Size\t = %5d samples", jb_state.opt_size)); 
     491    PJ_LOG(5, (jb->name.ptr, "Pool\t = %5d frames", jb_state.frame_cnt)); 
     492 
     493    pjmedia_jb2_get_stat(jb, &jb_stat); 
     494    PJ_LOG(5, (jb->name.ptr, "JB statistic:")); 
     495    PJ_LOG(5, (jb->name.ptr, "in \t = %5d frames", jb_stat.in)); 
     496    PJ_LOG(5, (jb->name.ptr, "out\t = %5d frames", jb_stat.out)); 
     497    PJ_LOG(5, (jb->name.ptr, "lost\t = %5d frames", jb_stat.lost)); 
     498    PJ_LOG(5, (jb->name.ptr, "late\t = %5d frames", jb_stat.late)); 
     499    PJ_LOG(5, (jb->name.ptr, "ooo\t = %5d frames", jb_stat.ooo)); 
     500    PJ_LOG(5, (jb->name.ptr, "empty\t = %5d times", jb_stat.empty)); 
     501    PJ_LOG(5, (jb->name.ptr, "full\t = %5d times", jb_stat.full)); 
     502    PJ_LOG(5, (jb->name.ptr, "max_size\t = %5d samples", jb_stat.max_size)); 
     503    PJ_LOG(5, (jb->name.ptr, "max_level\t = %5d", jb_stat.max_level)); 
     504    PJ_LOG(5, (jb->name.ptr, "max_comp\t = %5d samples", jb_stat.max_comp)); 
     505    PJ_LOG(5, (jb->name.ptr, "max_drift\t = %5d/%d", jb_stat.max_drift,  
     506                                    jb_stat.max_drift_span)); 
     507 
     508    return PJ_SUCCESS; 
     509} 
     510 
     511PJ_DEF(pj_status_t) pjmedia_jb2_reset(pjmedia_jb2_t *jb) 
    358512{ 
    359513    jb_frame_list *f, *next_f; 
    360514    int i; 
     515 
     516    PJ_ASSERT_RETURN(jb, PJ_EINVAL); 
     517 
     518    /* Reset tick */ 
     519    jb->tick = 0; 
    361520 
    362521    /* Reset frames */ 
     
    369528    pj_list_init(&jb->frames); 
    370529 
    371     /* Init last frame out */ 
     530    /* Init frame history */ 
    372531    pj_bzero(&jb->last_frame_out, sizeof(jb->last_frame_out)); 
    373532 
     
    400559    jb->drift_state.acc_mod_span = 1; 
    401560 
    402     /* Inform user about JB (re)init */ 
    403 } 
    404  
    405 /* Decode all consecutive undecoded frames. */ 
    406 static pj_status_t decode_frames(pjmedia_jb2_t *jb, jb_frame_list* start, 
    407                                  int max) 
    408 { 
    409     jb_frame_list* tmp = start; 
    410     pj_status_t status; 
    411  
    412     PJ_ASSERT_RETURN(jb && start && jb->cb.decode, PJ_EINVAL); 
    413  
    414     /* Decoded already */ 
    415     if (start->frame.type != PJMEDIA_JB_FT_NORMAL_FRAME) 
    416         return PJ_SUCCESS; 
    417  
    418     do { 
    419         status = jb->cb.decode(&tmp->frame); 
    420          
    421         pj_assert(tmp->frame.size == jb->setting.frame_size); 
    422  
    423         if (status != PJ_SUCCESS) { 
    424             TRACE__((THIS_FILE,"Failed to decode frame!")); 
    425             return PJMEDIA_JB2_EFAILDECODE; 
    426         } 
    427         tmp->frame.type = PJMEDIA_JB_FT_NORMAL_RAW_FRAME; 
    428         tmp = tmp->next; 
    429          
    430         jb->state.cur_size += jb->setting.samples_per_frame; 
    431  
    432     } while (tmp != &jb->frames &&  
    433              tmp->frame.type == PJMEDIA_JB_FT_NORMAL_FRAME && 
    434              (tmp->frame.ts - tmp->prev->frame.ts ==  
    435              jb->setting.samples_per_frame) && 
    436              (!max || --max > 0)); 
    437  
    438     return PJ_SUCCESS; 
    439 } 
    440  
    441 PJ_DEF(pj_status_t) pjmedia_jb2_create( pj_pool_t *pool, 
    442                                           const pj_str_t *name, 
    443                                           const pjmedia_jb2_setting *setting, 
    444                                           const pjmedia_jb2_cb *cb, 
    445                                           pjmedia_jb2_t **p_jb ) 
    446 { 
    447     pjmedia_jb2_t *jb; 
    448  
    449     PJ_ASSERT_RETURN(pool && setting && cb && p_jb, PJ_EINVAL); 
    450  
    451     if (setting->max_frames > MAX_FRAMES) { 
    452         PJ_LOG(4,(THIS_FILE, "Max frames requested is too big!")); 
    453         return PJ_EINVAL; 
    454     } 
    455  
    456     jb = PJ_POOL_ZALLOC_T(pool, pjmedia_jb2_t); 
    457     jb->pool = pool; 
    458  
    459     if (name) 
    460         pj_strdup_with_null(jb->pool, &jb->name, name); 
    461     else 
    462         pj_strdup2(pool, &jb->name, "jb2"); 
    463  
    464     pj_list_init(&jb->frames_pool); 
    465     pj_list_init(&jb->frames); 
    466  
    467     jb->setting = *setting; 
    468     jb->cb = *cb; 
    469  
    470     pjmedia_jb2_reset(jb); 
    471  
    472     *p_jb = jb; 
    473  
    474     return PJ_SUCCESS; 
    475 } 
    476  
    477 PJ_DEF(pj_status_t) pjmedia_jb2_destroy(pjmedia_jb2_t *jb) 
    478 { 
    479     PJ_UNUSED_ARG(jb); 
    480     PJ_ASSERT_RETURN(jb, PJ_EINVAL); 
    481  
    482     return PJ_SUCCESS; 
    483 } 
    484  
    485 PJ_DEF(pj_status_t) pjmedia_jb2_reset(pjmedia_jb2_t *jb) 
    486 { 
    487     PJ_ASSERT_RETURN(jb, PJ_EINVAL); 
    488  
    489     /* Reset tick */ 
    490     jb->tick = 0; 
    491  
    492     /* Reset statistic */ 
    493     pj_bzero(&jb->stat, sizeof(pjmedia_jb2_stat)); 
    494  
    495     if (!jb->setting.max_frames) 
    496         jb->setting.max_frames = MAX_FRAMES; 
    497      
    498     /* Init buffers */ 
    499     init_jb(jb); 
    500  
    501561    return PJ_SUCCESS; 
    502562} 
     
    593653    if (tmp->frame.type == PJMEDIA_JB_FT_NORMAL_RAW_FRAME) { 
    594654        jb->state.cur_size += jb->setting.samples_per_frame; 
    595     } 
    596     else if (tmp->prev != &jb->frames &&  
    597              (tmp->frame.ts - tmp->prev->frame.ts ==  
    598              jb->setting.samples_per_frame) && 
    599              tmp->prev->frame.type != PJMEDIA_JB_FT_NORMAL_FRAME) 
    600     { 
     655    } else { 
    601656        status = decode_frames(jb, tmp, 0); 
    602657    } 
     
    620675 
    621676    if (jb->state.phase == PJMEDIA_JB_PH_IDLE) 
    622         goto ON_RETURN; 
     677        goto RETURN_EMPTY_FRAME; 
    623678 
    624679    /* Check first frame */ 
     
    632687            jb_frame_list *tmp_plc; 
    633688 
     689            ++jb->stat.in; 
     690            ++jb->stat.lost; 
     691 
    634692            /* Generate PLC frame*/ 
    635693            tmp_plc = alloc_frame(jb); 
    636             if (!tmp_plc) return PJ_ENOMEM; 
    637  
    638             /* Fill buffer with PLC */ 
    639             if (jb->cb.plc) { 
    640                 status = jb->cb.plc(&tmp_plc->frame); 
    641                 if (status != PJ_SUCCESS) 
    642                     return status; 
     694            if (!tmp_plc) { 
     695                status = PJ_ENOMEM; 
     696                jb->last_frame_out = tmp->frame; 
     697                release_frame(jb, tmp); 
     698                goto RETURN_EMPTY_FRAME; 
    643699            } 
    644  
    645             tmp_plc->frame.type = PJMEDIA_JB_FT_INTERP_RAW_FRAME; 
    646700            tmp_plc->frame.pt = jb->last_frame_out.pt; 
    647701            tmp_plc->frame.seq = jb->last_frame_out.seq + 1; 
     
    649703            tmp_plc->frame.ts = jb->last_frame_out.ts +  
    650704                                jb->setting.samples_per_frame; 
    651  
    652705            pj_list_push_front(&jb->frames, tmp_plc); 
    653             ++jb->stat.in; 
    654             ++jb->stat.lost; 
    655             TRACE__((THIS_FILE,"Frame lost!")); 
     706 
     707            /* Fill buffer with PLC */ 
     708            if (jb->cb.plc) { 
     709                status = jb->cb.plc(&tmp_plc->frame, jb->cb.user_data); 
     710                if (status != PJ_SUCCESS) { 
     711                    TRACE__((THIS_FILE,"PLC failed")); 
     712                    jb->last_frame_out = tmp->frame; 
     713                    release_frame(jb, tmp_plc); 
     714                    goto RETURN_EMPTY_FRAME; 
     715                } 
     716                tmp_plc->frame.type = PJMEDIA_JB_FT_INTERP_RAW_FRAME; 
     717 
     718                TRACE__((THIS_FILE,"Lost frame recovered!")); 
     719            } else { 
     720                pj_bzero(tmp_plc->frame.buffer, jb->setting.frame_size); 
     721                tmp_plc->frame.type = PJMEDIA_JB_FT_NULL_FRAME; 
     722                TRACE__((THIS_FILE,"Lost frame!")); 
     723            } 
    656724 
    657725            jb->state.cur_size += jb->setting.samples_per_frame; 
    658726        } 
    659727 
    660         /* Or there is CN packet */ 
    661         else if (tmp->frame.pt == PT_CN) { 
    662             unsigned cn_samples; 
    663             jb_frame_list *tmp_cn, *pos; 
    664  
    665             /* Generate CN frames */ 
    666             if (jb->last_frame_out.ts) 
    667                 cn_samples = tmp->frame.ts - jb->last_frame_out.ts; 
     728        /* Or there is CN packet/jumping timestamp */ 
     729        else if (tmp->frame.pt == PT_CN || (jb->last_frame_out.ts &&  
     730                (tmp->frame.ts - jb->last_frame_out.ts >  
     731                jb->setting.samples_per_frame))) 
     732        { 
     733            unsigned cn_frames; 
     734 
     735            /* Count CN frames */ 
     736            if (jb->last_frame_out.ts && tmp->frame.ts > jb->last_frame_out.ts) 
     737                cn_frames = (tmp->frame.ts - jb->last_frame_out.ts) /  
     738                            jb->setting.samples_per_frame; 
    668739            else 
    669                 cn_samples = jb->setting.samples_per_frame; 
    670  
    671             pos = &jb->frames; 
    672             for (i = 0; i<cn_samples; i += jb->setting.samples_per_frame) 
    673             { 
    674                 tmp_cn = alloc_frame(jb); 
    675                 if (!tmp_cn) return PJ_ENOMEM; 
    676  
    677                 /* Fill buffer with CNG */ 
    678                 status = jb->cb.cng(&tmp_cn->frame); 
    679                 if (status != PJ_SUCCESS) 
    680                     return status; 
    681  
    682                 tmp_cn->frame.type = PJMEDIA_JB_FT_INTERP_RAW_FRAME; 
    683                 tmp_cn->frame.pt = jb->last_frame_out.pt; 
    684                 tmp_cn->frame.seq = tmp->frame.seq; 
    685                 tmp_cn->frame.size = jb->setting.frame_size; 
    686                 tmp_cn->frame.ts = jb->last_frame_out.seq + i + 
    687                                    jb->setting.samples_per_frame; 
    688  
    689                 pj_list_insert_after(pos, tmp_cn); 
    690                 pos = tmp_cn; 
    691                 jb->state.cur_size += jb->setting.samples_per_frame; 
     740                cn_frames = 1; 
     741 
     742            jb->last_frame_out = tmp->frame; 
     743 
     744            if (tmp->frame.pt == PT_CN) { 
     745                /* Save CN info */ 
     746                jb->last_frame_cn.size = tmp->frame.size; 
     747                pj_memcpy(jb->last_frame_cn.buffer, tmp->frame.buffer,  
     748                          tmp->frame.size); 
     749                jb->stat.in += cn_frames; 
     750                release_frame(jb, tmp); 
     751            } else { 
     752                jb->stat.in += cn_frames - 1; 
     753                status = decode_frames(jb, tmp, 2); 
    692754            } 
    693  
    694             /* Discard this CN frame, replaced by real PCM frames */ 
    695             release_frame(jb, tmp); 
    696  
    697             /* Update statistic */ 
    698             jb->stat.in += cn_samples - 1; 
    699755        } 
    700756 
     
    705761             */ 
    706762            status = decode_frames(jb, tmp, 2); 
    707             if (status != PJ_SUCCESS) 
    708                 return status; 
    709         } 
    710     } 
    711  
    712     /* Compensate drift right before any frame fetched */ 
    713     compensate_drift(jb); 
     763        } 
     764    } 
    714765 
    715766    /* Consistency checking, when cur_size!=0, there should be frame(s) 
    716767     * in the JB frames list. 
    717768     */ 
    718     pj_assert((jb->state.cur_size==0) ||  
     769    pj_assert((jb->state.cur_size == 0) ||  
    719770              (!pj_list_empty(&jb->frames) && jb->state.cur_size)); 
    720771 
    721772    /* Not enough samples in PCM buffer */ 
    722     if (jb->state.cur_size < jb->setting.samples_per_frame) { 
     773    if (jb->state.cur_size == 0) { 
    723774        if (jb->state.phase != PJMEDIA_JB_PH_LEARNING) { 
    724             TRACE__((THIS_FILE,"Not enough PCM samples (%d)!",  
    725                      jb->state.cur_size)); 
     775            TRACE__((THIS_FILE,"JB empty!")); 
    726776            ++jb->stat.empty; 
    727777        } 
     778 
    728779        goto RETURN_EMPTY_FRAME; 
    729780    } 
     781 
     782    /* Compensate drift right before any frame fetched */ 
     783    compensate_drift(jb); 
    730784 
    731785    /* Prepare the requested frame */ 
     
    739793     
    740794    /* Fill frame buffer, make sure size == setting.frame_size */ 
    741     while (f->size < jb->setting.frame_size) { 
     795    while (f->size < jb->setting.frame_size && jb->state.cur_size) { 
    742796        next_frm = tmp->next; 
    743797 
     
    754808            pj_memcpy((pj_int8_t*)f->buffer + f->size, tmp->frame.buffer, i); 
    755809            tmp->frame.size -= i; 
    756  
    757             /* Shift the buffer, don't shift the pointer! */ 
    758             pj_memmove(tmp->frame.buffer, (pj_int8_t*)tmp->frame.buffer + i,  
    759                        tmp->frame.size); 
    760         } 
     810            tmp->frame.buffer = (pj_int8_t*)tmp->frame.buffer + i; 
     811        } 
     812 
     813        pj_assert(jb->state.cur_size >= (i/ 
     814                    (jb->setting.frame_size/jb->setting.samples_per_frame))); 
     815        jb->state.cur_size -= i/ 
     816                    (jb->setting.frame_size/jb->setting.samples_per_frame); 
    761817 
    762818        f->size += i; 
     
    764820    } 
    765821 
    766     jb->state.cur_size -= jb->setting.samples_per_frame; 
     822    if (jb->tick % 100 == 0) { 
     823        pjmedia_jb2_state jb_state; 
     824 
     825        pjmedia_jb2_get_state(jb, &jb_state); 
     826        PJ_LOG(5, (jb->name.ptr, "JB state:")); 
     827        PJ_LOG(5, (jb->name.ptr, "Drift\t = %5d/%d", jb_state.drift,  
     828                                                     jb_state.drift_span)); 
     829        PJ_LOG(5, (jb->name.ptr, "Level\t = %5d ticks", jb_state.level)); 
     830        PJ_LOG(5, (jb->name.ptr, "Size\t = %5d samples", jb_state.cur_size)); 
     831        PJ_LOG(5, (jb->name.ptr, "Opt.Size\t = %5d samples", jb_state.opt_size)); 
     832        PJ_LOG(5, (jb->name.ptr, "Pool\t = %5d frames", jb_state.frame_cnt)); 
     833    } 
    767834 
    768835    /* JB still learning the level */ 
    769     if (jb->state.phase == PJMEDIA_JB_PH_LEARNING) 
    770         goto RETURN_EMPTY_FRAME; 
     836    //if (jb->state.phase == PJMEDIA_JB_PH_LEARNING) 
     837        //goto RETURN_EMPTY_FRAME; 
    771838 
    772839    goto ON_RETURN; 
     
    774841RETURN_EMPTY_FRAME: 
    775842 
    776     f->type = PJMEDIA_JB_FT_NULL_FRAME; 
    777843    f->pt = jb->last_frame_out.pt; 
    778844    f->seq = jb->last_frame_out.seq; 
    779     f->size = jb->setting.frame_size; 
    780845    f->ts = jb->last_frame_out.ts; 
    781     pj_bzero(f->buffer, f->size); 
    782846 
    783847    /* Instead of returning zero samples, it'd be better to return noise */ 
     848    if (jb->cb.cng && jb->last_frame_cn.size) { 
     849        f->type = PJMEDIA_JB_FT_INTERP_RAW_FRAME; 
     850        f->size = jb->last_frame_cn.size; 
     851        pj_memcpy(f->buffer, jb->last_frame_cn.buffer, f->size); 
     852        status = jb->cb.cng(f, jb->cb.user_data); 
     853        if (status != PJ_SUCCESS) { 
     854            f->type = PJMEDIA_JB_FT_NULL_FRAME; 
     855            f->size = jb->setting.frame_size; 
     856            pj_bzero(f->buffer, f->size); 
     857            TRACE__((THIS_FILE,"CNG failed")); 
     858        } 
     859    } else { 
     860        f->type = PJMEDIA_JB_FT_NULL_FRAME; 
     861        f->size = jb->setting.frame_size; 
     862        pj_bzero(f->buffer, f->size); 
     863    } 
    784864 
    785865ON_RETURN: 
     
    800880 
    801881            /* Reinit JB */ 
    802             init_jb(jb); 
     882            pjmedia_jb2_reset(jb); 
    803883        } 
    804884 
     
    866946#endif 
    867947 
    868             TRACE__((THIS_FILE, "History=%s Level=%d Opt.size=%d", dbg_hist,  
    869                                 jb->state.level, jb->state.opt_size)); 
     948            TRACE__((THIS_FILE, "History=%s level=%d opt.size=%d cur.size=%d",  
     949                                dbg_hist, jb->state.level,  
     950                                jb->state.opt_size, jb->state.cur_size)); 
    870951        } 
    871952        /* Reset level counter */ 
     
    902983        jb->state.drift = new_drift; 
    903984        jb->state.drift_span = new_drift_span; 
     985 
     986        /* Validate drift by comparing current drift to drift margin constant. 
     987         * Note that the drift value need to be rescaled to the same span before 
     988         * comparing. 
     989         */ 
     990       // drift_span = PJ_MIN(jb->stat.in - jb->hist[HISTORY_COUNT-1].in, 
     991                            //jb->stat.out - jb->hist[HISTORY_COUNT-1].out) 
     992                     //* (int)jb->setting.samples_per_frame; 
     993       // drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN / drift_span; 
     994        new_drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN /  
     995                (int)jb->state.drift_span; 
     996        if (PJ_ABS(new_drift) > MAX_DRIFT_MARGIN) { 
     997            TRACE__((THIS_FILE, "Abnormal drift (%d/%d), reinit jitter buffer!", 
     998                     new_drift, MAX_DRIFT_MARGIN_SPAN)); 
     999 
     1000            /* Reinit JB */ 
     1001            pjmedia_jb2_reset(jb); 
     1002        } 
     1003 
    9041004 
    9051005        TRACE__((THIS_FILE, "Drift info update: %d/%d (in=%d out=%d)", 
     
    9371037                                       unsigned *ref_, unsigned *match_) 
    9381038{ 
    939     const int MATCH_THRESHOLD = MATCH_WINDOW_LEN*1200; 
     1039    const int MATCH_THRESHOLD = MATCH_WINDOW_LEN*1000; 
    9401040    unsigned ref, ptr, end; 
    9411041    int i, similarity, s1, s2; 
     
    10681168 
    10691169    dest = buf->size/2; 
    1070     jb_vbuf_expand(buf, distance*2); 
     1170    if (!jb_vbuf_expand(buf, distance*2)) 
     1171        return 0; 
    10711172 
    10721173    // memcpy 
     
    11321233    jb_vbuf buf; 
    11331234    int sample_size, uncomp_cnt; 
    1134     pj_int32_t drift, itmp; 
     1235    pj_int32_t itmp; 
    11351236 
    11361237    /* No drift, just leave */ 
    11371238    if (!jb->state.drift || !jb->state.drift_span) { 
    11381239        jb->drift_state.last_ts = 0; 
    1139         return; 
    1140     } 
    1141  
    1142     /* Validate drift by comparing current drift to drift margin constant. 
    1143      * Note that the drift value need to be rescaled to the same span before 
    1144      * comparing. 
    1145      */ 
    1146    // drift_span = PJ_MIN(jb->stat.in - jb->hist[HISTORY_COUNT-1].in, 
    1147                         //jb->stat.out - jb->hist[HISTORY_COUNT-1].out) 
    1148                  //* (int)jb->setting.samples_per_frame; 
    1149    // drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN / drift_span; 
    1150     drift = jb->state.drift * MAX_DRIFT_MARGIN_SPAN /  
    1151             (int)jb->state.drift_span; 
    1152     if (PJ_ABS(drift) > MAX_DRIFT_MARGIN) { 
    1153         TRACE__((THIS_FILE, "Abnormal drift (%d/%d), reinit jitter buffer!", 
    1154                  drift, MAX_DRIFT_MARGIN_SPAN)); 
    1155  
    1156         /* Reinit JB */ 
    1157         init_jb(jb); 
    1158  
    11591240        return; 
    11601241    } 
     
    11951276    itmp *= uncomp_cnt; 
    11961277 
    1197     TRACE__((THIS_FILE, "Introducing new culprit:%d/%d mod:%d cur_size:%d",  
    1198              culprit, buf.cnt, itmp, jb->state.cur_size)); 
     1278    //TRACE__((THIS_FILE, "Introducing new culprit:%d/%d mod:%d cur_size:%d",  
     1279             //culprit, buf.cnt, itmp, jb->state.cur_size)); 
    11991280    pj_assert(buf.size/2 <= (int)jb->state.cur_size); 
    12001281 
     
    12241305    culprit += jb->drift_state.pending; 
    12251306 
     1307    /* Normalization here, drift calculation is not always accurate, 
     1308     * a bit hacky. 
     1309     */ 
     1310    if (culprit > (int) jb->state.opt_size) 
     1311        //&&  
     1312        //PJ_ABS(jb->state.cur_size-jb->state.opt_size) <= jb->setting.frame_size) 
     1313    { 
     1314        culprit = 0; 
     1315    } 
     1316 
    12261317    /* Culprit may be negative when pending is negative, 
    12271318     * which means last compensation was more than needed, 
     
    12461337     
    12471338    /* IN > OUT (need to shrink) */ 
    1248     /* Simple method: just drop samples */ 
    12491339    if (jb->state.drift > 0) { 
    12501340 
     
    12641354 
    12651355    /* IN < OUT ==> (need to grow) */ 
    1266     /* Another simple method: insert null samples */ 
    12671356    else { 
    12681357 
Note: See TracChangeset for help on using the changeset viewer.