Ticket #438: delaybuf.patch

File delaybuf.patch, 6.1 KB (added by nanang, 11 years ago)

Added idle operation detection, delay buffer will automatically shift its state to STATE_PAUSE if idle detected

  • pjmedia/src/pjmedia/delaybuf.c

     
    3838{ 
    3939    STATE_WAITING, 
    4040    STATE_LEARNING, 
     41    STATE_PAUSED, 
    4142    STATE_RUNNING 
    4243}; 
    4344 
     
    6364 */ 
    6465#define SAFE_MARGIN     2 
    6566 
     67/* Delay buf will continuously detect activity of operations. If only one 
     68 * operation is called sequentially (bursting) for more than max_level +  
     69 * IDLE_MARGIN, delay buffer will assume the other operation is idle and  
     70 * delay buffer will automatically change its state to STATE_PAUSED. 
     71 */ 
     72#define IDLE_MARGIN     2 
     73 
    6674/* 
    6775 * Some experimental data (with SAFE_MARGIN=1): 
    6876 * 
     
    97105    unsigned         buf_cnt;           /**< Number of buffered samples      */ 
    98106    unsigned         max_cnt;           /**< Max number of buffered samples  */ 
    99107 
    100     struct { 
    101         unsigned     level;             /**< Burst level storage on learning */ 
    102     } op[2]; 
     108    unsigned         level;             /**< Burst level storage on learning */ 
    103109    enum OP          last_op;           /**< Last op (GET or PUT) of learning*/ 
    104110    unsigned         state_count;       /**< Counter of op cycles of learning*/ 
    105111 
    106112    unsigned         max_level;         /**< Learning result: burst level    */ 
    107113 
    108114    pjmedia_wsola   *wsola;             /**< Drift handler                   */ 
     115     
     116    unsigned         max_burst;         /**< Maximum burst before media flow  
     117                                             is suspended                    */ 
    109118}; 
    110119 
    111120PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool, 
     
    135144    pj_ansi_strncpy(b->obj_name, name, PJ_MAX_OBJ_NAME-1); 
    136145    b->samples_per_frame = samples_per_frame; 
    137146    b->max_frames = max_frames; 
     147    b->max_burst = max_frames + IDLE_MARGIN; 
    138148 
    139149    status = pj_lock_create_recursive_mutex(pool, b->obj_name,  
    140150                                            &b->lock); 
     
    145155                   pj_pool_zalloc(pool, samples_per_frame * max_frames *  
    146156                                  sizeof(pj_int16_t)); 
    147157 
     158    status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame,  
     159                                  PJMEDIA_WSOLA_NO_PLC, &b->wsola); 
     160    if (status != PJ_SUCCESS) 
     161        return status; 
     162 
    148163    if (delay >= 0) { 
     164        /* Fixed delay */ 
    149165        if (delay == 0) 
    150166            delay = 1; 
    151167        b->max_level = delay; 
    152168        b->max_cnt = delay * samples_per_frame; 
    153169        b->state = STATE_RUNNING; 
    154170    } else { 
     171        /* Learning the best delay */ 
    155172        b->max_cnt = max_frames * samples_per_frame; 
    156         b->last_op = OP_UNDEFINED; 
    157173        b->state = STATE_WAITING; 
    158174    } 
     175    b->last_op = OP_UNDEFINED; 
    159176 
    160     status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame,  
    161                                   PJMEDIA_WSOLA_NO_PLC, &b->wsola); 
    162     if (status != PJ_SUCCESS) 
    163         return status; 
    164  
    165177    *p_b = b; 
    166178 
    167179    TRACE__((b->obj_name,"Delay buffer created")); 
     
    241253 
    242254        b->buf_cnt -= erase_cnt; 
    243255 
    244         PJ_LOG(5,(b->obj_name,"Successfully shrinking %d samples, " 
     256        PJ_LOG(5,(b->obj_name,"Overflow, %d samples reduced, " 
    245257                  "buf_cnt=%d", erase_cnt, b->buf_cnt)); 
    246258    } 
    247259 
     
    280292        return; 
    281293    } 
    282294 
    283     shrink_buffer(b, old_max_cnt - new_max_cnt); 
     295    /* If current samples number is more than new max cnt,  
     296     * we need to shrink buffer first */ 
     297    if (b->buf_cnt > new_max_cnt) 
     298        shrink_buffer(b, b->buf_cnt - new_max_cnt); 
    284299 
    285300    /* Adjust buffer to accomodate the new max_cnt so the samples is secured. 
    286301     * This is done by make get_pos = 0  
     
    320335 
    321336static void update(pjmedia_delay_buf *b, enum OP op) 
    322337{ 
    323     enum OP other = (enum OP) !op; 
     338    switch (b->state) { 
    324339 
    325     switch (b->state) { 
    326340    case STATE_RUNNING: 
     341        if (op != b->last_op) { 
     342            b->last_op = op; 
     343            b->level = 1; 
     344            break; 
     345        } 
     346        ++b->level; 
     347 
     348        if (b->level > b->max_burst) { 
     349            b->state = STATE_PAUSED; 
     350            pjmedia_delay_buf_reset(b); 
     351            PJ_LOG(5,(b->obj_name, "Delay buffer suspended")); 
     352        } 
     353 
    327354        break; 
     355 
     356    case STATE_PAUSED: 
     357        if (op != b->last_op) { 
     358            b->last_op = op; 
     359            b->level = 1; 
     360            b->state = STATE_RUNNING; 
     361            PJ_LOG(5,(b->obj_name, "Delay buffer resumed")); 
     362        } 
     363        break; 
     364 
    328365    case STATE_WAITING: 
    329         ++b->op[op].level; 
    330         if (b->op[other].level != 0) { 
    331             ++b->state_count; 
    332             if (b->state_count == WAITING_COUNT) { 
     366        if (op != b->last_op) { 
     367            b->last_op = op; 
     368            if (++b->state_count == WAITING_COUNT) { 
    333369                /* Start learning */ 
    334370                pjmedia_delay_buf_learn(b); 
     371                break; 
    335372            } 
    336373        } 
    337         b->last_op = op; 
    338374        break; 
     375 
    339376    case STATE_LEARNING: 
    340         ++b->op[op].level; 
    341         if (b->last_op == other) { 
    342             unsigned last_level = b->op[other].level; 
    343             if (last_level > b->max_level) 
    344                 b->max_level = last_level; 
    345             b->op[other].level = 0; 
    346             b->state_count++; 
    347             if (b->state_count == LEARN_COUNT) { 
     377        if (op != b->last_op) { 
     378            b->last_op = op; 
     379            if (b->level > b->max_level) 
     380                b->max_level = b->level; 
     381            b->level = 1; 
     382 
     383            if (++b->state_count == LEARN_COUNT) { 
    348384                /* give SAFE_MARGIN compensation for added stability */ 
    349385                b->max_level += SAFE_MARGIN; 
     386                b->max_burst = b->max_level + IDLE_MARGIN; 
    350387                 
    351388                /* buffer not enough! */ 
    352389                if (b->max_level > b->max_frames) { 
     
    366403                PJ_LOG(4,(b->obj_name,"Delay buffer start running, level=%u", 
    367404                          b->max_level)); 
    368405            } 
     406         
     407            break; 
    369408        } 
    370         b->last_op = op; 
     409 
     410        ++b->level; 
    371411        break; 
    372412    } 
    373413 
     
    391431        return status; 
    392432    } 
    393433 
     434    if (b->state == STATE_PAUSED) { 
     435        pj_lock_release(b->lock); 
     436        return PJ_SUCCESS; 
     437    } 
     438 
    394439    /* Overflow checking */ 
    395440    if (b->buf_cnt + b->samples_per_frame > b->max_cnt) 
    396441    { 
     
    434479 
    435480    update(b, OP_GET); 
    436481 
     482    if (b->state == STATE_PAUSED) { 
     483        pjmedia_zero_samples(frame, b->samples_per_frame); 
     484        pj_lock_release(b->lock); 
     485        return PJ_SUCCESS; 
     486    } 
     487 
    437488    /* Starvation checking */ 
    438489    if (b->buf_cnt < b->samples_per_frame) { 
    439490 
     
    504555    pj_lock_acquire(b->lock); 
    505556 
    506557    b->last_op = OP_UNDEFINED; 
    507     b->op[OP_GET].level = b->op[OP_PUT].level = 0; 
     558    b->level = 1; 
    508559    b->state = STATE_LEARNING; 
    509560    b->state_count = 0; 
    510     b->max_level = 0; 
     561    b->max_level = 1; 
    511562    b->max_cnt = b->max_frames * b->samples_per_frame; 
    512563 
    513564    pjmedia_delay_buf_reset(b); 
     
    532583 
    533584    pj_lock_release(b->lock); 
    534585 
    535     PJ_LOG(5,(b->obj_name,"Delay buffer resetted")); 
     586    PJ_LOG(5,(b->obj_name,"Delay buffer is reset")); 
    536587 
    537588    return PJ_SUCCESS; 
    538589}