Changeset 1972 for pjproject/trunk


Ignore:
Timestamp:
May 30, 2008 11:30:24 AM (16 years ago)
Author:
nanang
Message:

Updated delaybuf to learn burst level in realtime instead of only in the beginning, this can optimize the latency and increase adaptivity

Location:
pjproject/trunk/pjmedia
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/delaybuf.h

    r1833 r1972  
    6969 * @param clock_rate        Number of samples processed per second. 
    7070 * @param samples_per_frame Number of samples per frame. 
    71  * @param max_frames        Maximum number of delay to be accommodated, 
    72  *                          in number of frames. 
    73  * @param delay             The delay to be applied, in number of frames. 
    74  *                          If the value is -1 or 0, the delay buffer will 
    75  *                          learn about the delay automatically. If 
    76  *                          the value is greater than zero, then this 
    77  *                          value will be used and no learning will be 
    78  *                          performed. 
     71 * @param channel_count     Number of channel per frame. 
     72 * @param max_delay         Maximum number of delay to be accommodated, 
     73 *                          in ms, if this value is negative or less than  
     74 *                          one frame time, default maximum delay used is 
     75 *                          400 ms. 
    7976 * @param option            Option flags, must be zero for now. 
    8077 * @param p_b               Pointer to receive the delay buffer instance. 
     
    8885                                              unsigned clock_rate, 
    8986                                              unsigned samples_per_frame, 
    90                                               unsigned max_frames, 
    91                                               int delay, 
     87                                              unsigned channel_count, 
     88                                              unsigned max_delay, 
    9289                                              unsigned options, 
    9390                                              pjmedia_delay_buf **p_b); 
     
    128125 
    129126/** 
    130  * Reinitiate learning state. This will clear the buffer's content. 
    131  * 
    132  * @param b                 The delay buffer. 
    133  * 
    134  * @return                  PJ_SUCCESS on success or the appropriate error. 
    135  */ 
    136 PJ_DECL(pj_status_t) pjmedia_delay_buf_learn(pjmedia_delay_buf *b); 
    137  
    138 /** 
    139127 * Reset delay buffer. This will clear the buffer's content. But keep 
    140128 * the learning result. 
  • pjproject/trunk/pjmedia/src/pjmedia/conference.c

    r1929 r1972  
    419419    struct conf_port *conf_port; 
    420420    pj_status_t status; 
     421    unsigned ptime; 
    421422 
    422423    /* Create port */ 
     
    426427 
    427428    /* Passive port has delay buf. */ 
     429    ptime = conf->samples_per_frame * 1000 / conf->clock_rate /  
     430            conf->channel_count; 
    428431    status = pjmedia_delay_buf_create(pool, name->ptr,  
    429432                                      conf->clock_rate, 
    430433                                      conf->samples_per_frame, 
    431                                       RX_BUF_COUNT, /* max */ 
    432                                       -1, /* delay */ 
     434                                      conf->channel_count, 
     435                                      RX_BUF_COUNT * ptime, /* max delay */ 
    433436                                      0, /* options */ 
    434437                                      &conf_port->delay_buf); 
  • pjproject/trunk/pjmedia/src/pjmedia/delaybuf.c

    r1847 r1972  
    2424#include <pj/lock.h> 
    2525#include <pj/log.h> 
     26#include <pj/math.h> 
    2627#include <pj/pool.h> 
    2728 
     
    3334#endif 
    3435 
    35  
    36 /* Type of states of delay buffer */ 
    37 enum state 
    38 { 
    39     STATE_WAITING, 
    40     STATE_LEARNING, 
    41     STATE_RUNNING 
     36/* Operation types of delay buffer */ 
     37enum OP 
     38{ 
     39    OP_PUT, 
     40    OP_GET 
    4241}; 
    4342 
    44 /* Type of operation of delay buffer */ 
    45 enum OP 
    46 { 
    47     OP_PUT, 
    48     OP_GET, 
    49     OP_UNDEFINED 
    50 }; 
    51  
    52 /* The following macros represent cycles of test. Since there are two 
    53  * operations performed (get & put), these macros minimum value must be 2  
    54  * and should be even number. 
    55  */ 
    56 #define WAITING_COUNT   4 
    57 #define LEARN_COUNT     16 
    58  
    59 /* Number of buffers to add to learnt level for additional stability 
    60  * Please note that wsola_discard() needs minimum 3 frames, so max buffer  
    61  * count should be minimally 3, setting SAFE_MARGIN to 2 will guarantees  
    62  * this. 
    63  */ 
    64 #define SAFE_MARGIN     2 
    65  
    66 /* 
    67  * Some experimental data (with SAFE_MARGIN=1): 
    68  * 
    69  * System 1: 
    70  *  - XP, WMME, 10ms ptime,  
    71  *  - Sennheiser Headset+USB sound card 
    72  *  - Stable delaybuf level: 6, on WAITING_COUNT=4 and LEARNING_COUNT=48 
    73  * 
    74  * System 2: 
    75  *  - XP, WMME, 10ms ptime 
    76  *  - Onboard SoundMAX Digital Audio 
    77  *  - Stable delaybuf level: 6, on WAITING_COUNT=4 and LEARNING_COUNT=48 
    78  * 
    79  * System 3: 
    80  *  - MacBook Core 2 Duo, OSX 10.5, 10ms ptime 
    81  *  - Stable delaybuf level: 2, on WAITING_COUNT=4 and LEARNING_COUNT=8 
    82  */ 
    83  
     43/* Specify time for delaybuf to recalculate effective delay, in ms. 
     44 */ 
     45#define RECALC_TIME         2000 
     46 
     47/* Default value of maximum delay, in ms, this value is used when  
     48 * maximum delay requested is less than ptime (one frame length). 
     49 */ 
     50#define DEFAULT_MAX_DELAY   400 
     51 
     52/* Number of frames to add to learnt level for additional stability. 
     53 */ 
     54#define SAFE_MARGIN         0 
     55 
     56/* This structure describes internal delaybuf settings and states. 
     57 */ 
    8458struct pjmedia_delay_buf 
    8559{ 
     60    /* Properties and configuration */ 
    8661    char             obj_name[PJ_MAX_OBJ_NAME]; 
    87  
    8862    pj_lock_t       *lock;              /**< Lock object.                    */ 
    89  
    9063    pj_int16_t      *frame_buf; 
    91     enum state       state;             /**< State of delay buffer           */ 
    9264    unsigned         samples_per_frame; /**< Number of samples in one frame  */ 
    93     unsigned         max_frames;        /**< Buffer allocated, in frames     */ 
    94  
     65    unsigned         ptime;             /**< Frame time, in ms               */ 
     66    unsigned         channel_count;     /**< Channel count, in ms            */ 
     67    unsigned         max_cnt;           /**< Max buffered samples, in samples*/ 
     68 
     69    /* Buffer pointer and counter */ 
    9570    unsigned         put_pos;           /**< Position for put op, in samples */ 
    9671    unsigned         get_pos;           /**< Position for get op, in samples */ 
    9772    unsigned         buf_cnt;           /**< Number of buffered samples      */ 
    98     unsigned         max_cnt;           /**< Max number of buffered samples  */ 
    99  
    100     struct { 
    101         unsigned     level;             /**< Burst level storage on learning */ 
    102     } op[2]; 
     73    unsigned         eff_cnt;           /**< Effective count of buffered  
     74                                             samples to keep the optimum 
     75                                             balance between delay and  
     76                                             stability. This is calculated  
     77                                             based on burst level.           */ 
     78 
     79    /* Learning vars */ 
     80    unsigned         level;             /**< Burst level counter             */ 
    10381    enum OP          last_op;           /**< Last op (GET or PUT) of learning*/ 
    104     unsigned         state_count;       /**< Counter of op cycles of learning*/ 
    105  
    106     unsigned         max_level;         /**< Learning result: burst level    */ 
    107  
     82    int              recalc_timer;      /**< Timer for recalculating max_level*/ 
     83    unsigned         max_level;         /**< Current max burst level         */ 
     84 
     85    /* Drift handler */ 
    10886    pjmedia_wsola   *wsola;             /**< Drift handler                   */ 
    10987}; 
     88 
    11089 
    11190PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool, 
     
    11392                                              unsigned clock_rate, 
    11493                                              unsigned samples_per_frame, 
    115                                               unsigned max_frames, 
    116                                               int delay, 
     94                                              unsigned channel_count, 
     95                                              unsigned max_delay, 
    11796                                              unsigned options, 
    11897                                              pjmedia_delay_buf **p_b) 
     
    121100    pj_status_t status; 
    122101 
    123     PJ_ASSERT_RETURN(pool && samples_per_frame && max_frames && p_b, PJ_EINVAL); 
    124     PJ_ASSERT_RETURN((int)max_frames >= delay, PJ_EINVAL); 
     102    PJ_ASSERT_RETURN(pool && samples_per_frame && clock_rate && channel_count && 
     103                     p_b, PJ_EINVAL); 
    125104    PJ_ASSERT_RETURN(options==0, PJ_EINVAL); 
    126105 
     
    134113 
    135114    pj_ansi_strncpy(b->obj_name, name, PJ_MAX_OBJ_NAME-1); 
     115 
    136116    b->samples_per_frame = samples_per_frame; 
    137     b->max_frames = max_frames; 
     117    b->channel_count = channel_count; 
     118    b->ptime = samples_per_frame * 1000 / clock_rate / channel_count; 
     119    if (max_delay < b->ptime) 
     120        max_delay = PJ_MAX(DEFAULT_MAX_DELAY, b->ptime); 
     121 
     122    b->max_cnt = samples_per_frame * max_delay / b->ptime; 
     123    b->eff_cnt = b->max_cnt >> 1; 
     124    b->recalc_timer = RECALC_TIME; 
    138125 
    139126    status = pj_lock_create_recursive_mutex(pool, b->obj_name,  
     
    143130 
    144131    b->frame_buf = (pj_int16_t*) 
    145                    pj_pool_zalloc(pool, samples_per_frame * max_frames *  
    146                                   sizeof(pj_int16_t)); 
    147  
    148     if (delay >= 0) { 
    149         if (delay == 0) 
    150             delay = 1; 
    151         b->max_level = delay; 
    152         b->max_cnt = delay * samples_per_frame; 
    153         b->state = STATE_RUNNING; 
    154     } else { 
    155         b->max_cnt = max_frames * samples_per_frame; 
    156         b->last_op = OP_UNDEFINED; 
    157         b->state = STATE_WAITING; 
    158     } 
     132                    pj_pool_zalloc(pool, b->max_cnt * sizeof(pj_int16_t)); 
    159133 
    160134    status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1, 
     
    183157 
    184158    pj_lock_release(b->lock); 
     159 
    185160    pj_lock_destroy(b->lock); 
    186161    b->lock = NULL; 
     
    263238} 
    264239 
    265 static void set_max_cnt(pjmedia_delay_buf *b, unsigned new_max_cnt) 
    266 { 
    267     unsigned old_max_cnt = b->max_cnt; 
    268  
    269     /* nothing to adjust */ 
    270     if (old_max_cnt == new_max_cnt) 
     240/* Fast increase, slow decrease */ 
     241#define AGC_UP(cur, target) cur = (cur + target*3) >> 2 
     242#define AGC_DOWN(cur, target) cur = (cur*3 + target) >> 2 
     243#define AGC(cur, target) \ 
     244    if (cur < target) AGC_UP(cur, target); \ 
     245    else AGC_DOWN(cur, target) 
     246 
     247static void update(pjmedia_delay_buf *b, enum OP op) 
     248{ 
     249    /* Sequential operation */ 
     250    if (op == b->last_op) { 
     251        ++b->level; 
    271252        return; 
    272  
    273     /* For now, only support shrinking */ 
    274     pj_assert(old_max_cnt > new_max_cnt); 
    275  
    276     /* Buffer empty, only need to reset pointers then set new max directly */ 
    277     if (b->buf_cnt == 0) { 
    278         b->put_pos = b->get_pos = 0; 
    279         b->max_cnt = new_max_cnt; 
    280         return; 
    281     } 
    282  
    283     /* If samples number in the buffer > new_max_cnt, reduce samples first */ 
    284     if (b->buf_cnt > new_max_cnt) 
    285         shrink_buffer(b, b->buf_cnt - new_max_cnt); 
    286  
    287     /* Adjust buffer to accomodate the new max_cnt so the samples is secured. 
    288      * This is done by make get_pos = 0  
    289      */ 
    290     if (b->get_pos <= b->put_pos) { 
    291         /* sssss .. sssss 
    292          *   ^         ^ 
    293          *   G         P 
     253    }  
     254 
     255    /* Switching operation */ 
     256    if (b->level > b->max_level) 
     257        b->max_level = b->level; 
     258 
     259    b->recalc_timer -= (b->level * b->ptime) >> 1; 
     260 
     261    b->last_op = op; 
     262    b->level = 1; 
     263 
     264    /* Recalculate effective count based on max_level */ 
     265    if (b->recalc_timer <= 0) { 
     266        unsigned new_eff_cnt = (b->max_level+SAFE_MARGIN)*b->samples_per_frame; 
     267 
     268        /* Smoothening effective count transition */ 
     269        AGC(b->eff_cnt, new_eff_cnt); 
     270         
     271        /* Make sure the new effective count is multiplication of  
     272         * channel_count, so let's round it up. 
    294273         */ 
    295         /* Consistency checking */ 
    296         pj_assert((b->put_pos - b->get_pos) <= new_max_cnt); 
    297         pj_assert((b->put_pos - b->get_pos) == b->buf_cnt); 
    298  
    299         pjmedia_move_samples(b->frame_buf, &b->frame_buf[b->get_pos],  
    300                              b->get_pos); 
    301         b->put_pos -= b->get_pos; 
    302         b->get_pos = 0; 
    303     } else { 
    304         /* sssss .. sssss 
    305          *          ^  ^ 
    306          *          P  G 
    307          */ 
    308         unsigned d = old_max_cnt - b->get_pos; 
    309  
    310         /* Consistency checking */ 
    311         pj_assert((b->get_pos - b->put_pos) >= (old_max_cnt - new_max_cnt)); 
    312  
    313         /* Make get_pos = 0, shift right the leftmost block first */ 
    314         pjmedia_move_samples(&b->frame_buf[d], b->frame_buf, d); 
    315         pjmedia_copy_samples(b->frame_buf, &b->frame_buf[b->get_pos], d); 
    316         b->put_pos += d; 
    317         b->get_pos = 0; 
    318     } 
    319  
    320     b->max_cnt = new_max_cnt; 
    321 } 
    322  
    323 static void update(pjmedia_delay_buf *b, enum OP op) 
    324 { 
    325     enum OP other = (enum OP) !op; 
    326  
    327     switch (b->state) { 
    328     case STATE_RUNNING: 
    329         break; 
    330     case STATE_WAITING: 
    331         ++b->op[op].level; 
    332         if (b->op[other].level != 0) { 
    333             ++b->state_count; 
    334             if (b->state_count == WAITING_COUNT) { 
    335                 /* Start learning */ 
    336                 pjmedia_delay_buf_learn(b); 
    337             } 
    338         } 
    339         b->last_op = op; 
    340         break; 
    341     case STATE_LEARNING: 
    342         ++b->op[op].level; 
    343         if (b->last_op == other) { 
    344             unsigned last_level = b->op[other].level; 
    345             if (last_level > b->max_level) 
    346                 b->max_level = last_level; 
    347             b->op[other].level = 0; 
    348             b->state_count++; 
    349             if (b->state_count == LEARN_COUNT) { 
    350                 /* give SAFE_MARGIN compensation for added stability */ 
    351                 b->max_level += SAFE_MARGIN; 
    352                  
    353                 /* buffer not enough! */ 
    354                 if (b->max_level > b->max_frames) { 
    355                     PJ_LOG(4,(b->obj_name,"Delay buffer learning result (%d)" 
    356                               " exceeds the maximum delay allowed (%d)", 
    357                               b->max_level, 
    358                               b->max_frames)); 
    359  
    360                     b->max_level = b->max_frames; 
    361                 } 
    362  
    363                 /* we need to set new max_cnt & adjust buffer */ 
    364                 set_max_cnt(b, b->max_level * b->samples_per_frame); 
    365  
    366                 b->state = STATE_RUNNING; 
    367  
    368                 PJ_LOG(4,(b->obj_name,"Delay buffer start running, level=%u", 
    369                           b->max_level)); 
    370             } 
    371         } 
    372         b->last_op = op; 
    373         break; 
    374     } 
    375  
    376      
     274        if (b->eff_cnt % b->channel_count) 
     275            b->eff_cnt += b->channel_count - (b->eff_cnt % b->channel_count); 
     276 
     277        TRACE__((b->obj_name,"Cur eff_cnt=%d", b->eff_cnt)); 
     278         
     279        b->max_level = 0; 
     280        b->recalc_timer = RECALC_TIME; 
     281    } 
     282 
     283    /* See if we need to shrink the buffer to reduce delay */ 
     284    if (b->buf_cnt > b->samples_per_frame + b->eff_cnt) { 
     285        unsigned erase_cnt = b->samples_per_frame >> 1; 
     286        unsigned old_buf_cnt = b->buf_cnt; 
     287 
     288        shrink_buffer(b, erase_cnt); 
     289        PJ_LOG(5,(b->obj_name,"Buffer size adjusted from %d to %d", 
     290                  old_buf_cnt, b->buf_cnt)); 
     291    } 
    377292} 
    378293 
     
    500415} 
    501416 
    502 PJ_DEF(pj_status_t) pjmedia_delay_buf_learn(pjmedia_delay_buf *b) 
     417 
     418PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b) 
    503419{ 
    504420    PJ_ASSERT_RETURN(b, PJ_EINVAL); 
     
    506422    pj_lock_acquire(b->lock); 
    507423 
    508     b->last_op = OP_UNDEFINED; 
    509     b->op[OP_GET].level = b->op[OP_PUT].level = 0; 
    510     b->state = STATE_LEARNING; 
    511     b->state_count = 0; 
    512     b->max_level = 0; 
    513     b->max_cnt = b->max_frames * b->samples_per_frame; 
    514  
    515     pjmedia_delay_buf_reset(b); 
    516  
    517     pj_lock_release(b->lock); 
    518  
    519     PJ_LOG(5,(b->obj_name,"Delay buffer start learning")); 
    520  
    521     return PJ_SUCCESS; 
    522 } 
    523  
    524 PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b) 
    525 { 
    526     PJ_ASSERT_RETURN(b, PJ_EINVAL); 
    527  
    528     pj_lock_acquire(b->lock); 
     424    b->recalc_timer = RECALC_TIME; 
    529425 
    530426    /* clean up buffer */ 
  • pjproject/trunk/pjmedia/src/pjmedia/sound_port.c

    r1836 r1972  
    373373    pjmedia_snd_port *snd_port; 
    374374    pj_status_t status; 
     375    unsigned ptime; 
    375376 
    376377    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
     
    389390     
    390391#if PJMEDIA_SOUND_USE_DELAYBUF 
     392    ptime = samples_per_frame * 1000 / (clock_rate * channel_count); 
     393 
    391394    status = pjmedia_delay_buf_create(pool, "snd_buff",  
    392                                       clock_rate, samples_per_frame,  
    393                                       PJMEDIA_SOUND_BUFFER_COUNT, -1,  
     395                                      clock_rate, samples_per_frame, 
     396                                      channel_count, 
     397                                      PJMEDIA_SOUND_BUFFER_COUNT * ptime, 
    394398                                      0, &snd_port->delay_buf); 
    395399    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    396400#else 
    397401    PJ_UNUSED_ARG(status); 
     402    PJ_UNUSED_ARG(ptime); 
    398403#endif 
    399404 
  • pjproject/trunk/pjmedia/src/pjmedia/splitcomb.c

    r1866 r1972  
    308308    struct splitcomb *sc = (struct splitcomb*) splitcomb; 
    309309    struct reverse_port *rport; 
    310     unsigned buf_cnt; 
     310    unsigned buf_cnt, ptime; 
    311311    pjmedia_port *port; 
    312312    pj_status_t status; 
     
    347347        buf_cnt = MAX_BUF_CNT; 
    348348 
     349    ptime = port->info.samples_per_frame * 1000 / port->info.clock_rate / 
     350            port->info.channel_count; 
     351 
    349352    rport->max_burst = MAX_BURST; 
    350353    rport->max_null_frames = MAX_NULL_FRAMES; 
     
    354357                                      port->info.clock_rate, 
    355358                                      port->info.samples_per_frame, 
    356                                       buf_cnt, -1, 0, 
     359                                      port->info.channel_count, 
     360                                      buf_cnt * ptime, 0, 
    357361                                      &rport->buf[DIR_DOWNSTREAM].dbuf); 
    358362    if (status != PJ_SUCCESS) { 
     
    364368                                      port->info.clock_rate, 
    365369                                      port->info.samples_per_frame, 
    366                                       buf_cnt, -1, 0, 
     370                                      port->info.channel_count, 
     371                                      buf_cnt * ptime, 0, 
    367372                                      &rport->buf[DIR_UPSTREAM].dbuf); 
    368373    if (status != PJ_SUCCESS) { 
Note: See TracChangeset for help on using the changeset viewer.