Changeset 822 for pjproject


Ignore:
Timestamp:
Nov 23, 2006 7:32:13 AM (18 years ago)
Author:
bennylp
Message:

Worked on the AEC. Apply constant delay bufferring for the AEC,
and also consider sound device latency when applying EC. It
sounds like working although it still doesn't perfectly cancel
the echo.

EC is now by default enabled in PJSUA.

Location:
pjproject/trunk
Files:
9 edited

Legend:

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

    r690 r822  
    8383 * @param samples_per_frame Number of samples per frame. 
    8484 * @param tail_ms           Tail length, miliseconds. 
     85 * @param latency_ms        Total lacency introduced by playback and  
     86 *                          recording device. Set to zero if the latency 
     87 *                          is not known. 
    8588 * @param options           Options. If PJMEDIA_ECHO_SIMPLE is specified, 
    8689 *                          then a simple echo suppressor implementation  
     
    9699                                         unsigned samples_per_frame, 
    97100                                         unsigned tail_ms, 
     101                                         unsigned latency_ms, 
    98102                                         unsigned options, 
    99103                                         pjmedia_echo_state **p_echo ); 
  • pjproject/trunk/pjmedia/include/pjmedia/echo_port.h

    r690 r822  
    4747 * @param dn_port       Downstream port. 
    4848 * @param tail_ms       Tail length in miliseconds. 
     49 * @param latency_ms    Total lacency introduced by playback and  
     50 *                      recording device. Set to zero if the latency 
     51 *                      is not known. 
    4952 * @param options       Options, as in #pjmedia_echo_create(). 
    5053 * @param p_port        Pointer to receive the port instance. 
     
    5558                                              pjmedia_port *dn_port, 
    5659                                              unsigned tail_ms, 
     60                                              unsigned latency_ms, 
    5761                                              unsigned options, 
    5862                                              pjmedia_port **p_port ); 
  • pjproject/trunk/pjmedia/src/pjmedia/echo_common.c

    r655 r822  
    3838                            unsigned samples_per_frame, 
    3939                            unsigned tail_ms, 
     40                            unsigned latency_ms, 
    4041                            unsigned options, 
    4142                            void **p_state ); 
     
    6263                                      unsigned samples_per_frame, 
    6364                                      unsigned tail_ms, 
     65                                      unsigned latency_ms, 
    6466                                      unsigned options, 
    6567                                      void **p_state ); 
     
    9597                                      unsigned samples_per_frame, 
    9698                                      unsigned tail_ms, 
     99                                      unsigned latency_ms, 
    97100                                      unsigned options, 
    98101                                      void **p_state ); 
     
    131134                                         unsigned samples_per_frame, 
    132135                                         unsigned tail_ms, 
     136                                         unsigned latency_ms, 
    133137                                         unsigned options, 
    134138                                         pjmedia_echo_state **p_echo ) 
     
    146150    if (options & PJMEDIA_ECHO_SIMPLE) { 
    147151        ec->op = &echo_supp_op; 
    148         status = (*echo_supp_op.ec_create)(pool, clock_rate,  
    149                                            samples_per_frame, 
    150                                            tail_ms, options, 
     152        status = (*echo_supp_op.ec_create)(pool, clock_rate, samples_per_frame, 
     153                                           tail_ms, latency_ms, options, 
    151154                                           &ec->state); 
    152155    } else { 
     
    154157        status = (*aec_op.ec_create)(pool, clock_rate,  
    155158                                     samples_per_frame, 
    156                                      tail_ms, options, 
     159                                     tail_ms, latency_ms, options, 
    157160                                     &ec->state); 
    158161    } 
  • pjproject/trunk/pjmedia/src/pjmedia/echo_port.c

    r653 r822  
    4747                                             pjmedia_port *dn_port, 
    4848                                             unsigned tail_ms, 
     49                                             unsigned latency_ms, 
    4950                                             unsigned options, 
    5051                                             pjmedia_port **p_port ) 
     
    6970    status = pjmedia_echo_create(pool, dn_port->info.clock_rate,  
    7071                                 dn_port->info.samples_per_frame, 
    71                                  tail_ms, options, &ec->ec); 
     72                                 tail_ms, latency_ms, options, &ec->ec); 
    7273    if (status != PJ_SUCCESS) 
    7374        return status; 
  • pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c

    r653 r822  
    3030 
    3131 
    32 #define THIS_FILE   "echo_speex.c" 
    33 #define BUF_COUNT   8 
     32#define THIS_FILE       "echo_speex.c" 
     33#define BUF_COUNT       20 
     34#define MIN_PREFETCH    4 
     35#define MAX_PREFETCH    12 
     36 
     37 
     38 
     39#if 0 
     40# define TRACE_(expr)  PJ_LOG(5,expr) 
     41#else 
     42# define TRACE_(expr) 
     43#endif 
     44 
     45 
     46typedef struct pjmedia_frame_queue pjmedia_frame_queue; 
     47 
     48struct fq_frame 
     49{ 
     50    PJ_DECL_LIST_MEMBER(struct fq_frame); 
     51    void        *buf; 
     52    unsigned     size; 
     53    pj_uint32_t  seq; 
     54}; 
     55 
     56struct pjmedia_frame_queue 
     57{ 
     58    char             obj_name[PJ_MAX_OBJ_NAME]; 
     59    unsigned         frame_size; 
     60    int              samples_per_frame; 
     61    unsigned         count; 
     62    unsigned         max_count; 
     63    struct fq_frame  frame_list; 
     64    struct fq_frame  free_list; 
     65 
     66    int              seq_delay; 
     67    int              prefetch_count; 
     68}; 
     69 
     70PJ_DEF(pj_status_t) pjmedia_frame_queue_create( pj_pool_t *pool, 
     71                                                const char *name, 
     72                                                unsigned frame_size, 
     73                                                unsigned samples_per_frame, 
     74                                                unsigned max_count, 
     75                                                pjmedia_frame_queue **p_fq) 
     76{ 
     77    pjmedia_frame_queue *fq; 
     78    unsigned i; 
     79 
     80    fq = pj_pool_zalloc(pool, sizeof(pjmedia_frame_queue)); 
     81 
     82    pj_ansi_snprintf(fq->obj_name, sizeof(fq->obj_name), name, fq); 
     83    fq->obj_name[sizeof(fq->obj_name)-1] = '\0'; 
     84 
     85    fq->max_count = max_count; 
     86    fq->frame_size = frame_size; 
     87    fq->samples_per_frame = samples_per_frame; 
     88    fq->count = 0; 
     89 
     90    pj_list_init(&fq->frame_list); 
     91    pj_list_init(&fq->free_list); 
     92 
     93    for (i=0; i<max_count; ++i) { 
     94        struct fq_frame *f; 
     95 
     96        f = pj_pool_zalloc(pool, sizeof(struct fq_frame)); 
     97        f->buf = pj_pool_alloc(pool, frame_size); 
     98 
     99        pj_list_push_back(&fq->free_list, f); 
     100         
     101    } 
     102 
     103    *p_fq = fq; 
     104    return PJ_SUCCESS; 
     105} 
     106 
     107PJ_DEF(pj_status_t) pjmedia_frame_queue_init( pjmedia_frame_queue *fq, 
     108                                              int seq_delay, 
     109                                              int prefetch_count) 
     110{ 
     111    if (prefetch_count > MAX_PREFETCH) 
     112        prefetch_count = MAX_PREFETCH; 
     113 
     114    fq->seq_delay = seq_delay; 
     115    fq->prefetch_count = prefetch_count; 
     116    fq->count = 0; 
     117    pj_list_merge_first(&fq->free_list, &fq->frame_list); 
     118 
     119    PJ_LOG(5,(fq->obj_name, "AEC reset, delay=%d, prefetch=%d",  
     120              fq->seq_delay, fq->prefetch_count)); 
     121 
     122    return PJ_SUCCESS; 
     123} 
     124 
     125PJ_DEF(pj_bool_t) pjmedia_frame_queue_empty( pjmedia_frame_queue *fq ) 
     126{ 
     127    return pj_list_empty(&fq->frame_list); 
     128} 
     129 
     130PJ_DEF(int) pjmedia_frame_queue_get_prefetch( pjmedia_frame_queue *fq ) 
     131{ 
     132    return fq->prefetch_count; 
     133} 
     134 
     135PJ_DEF(pj_status_t) pjmedia_frame_queue_put( pjmedia_frame_queue *fq, 
     136                                             const void *framebuf, 
     137                                             unsigned size, 
     138                                             pj_uint32_t timestamp ) 
     139{ 
     140    struct fq_frame *f; 
     141 
     142    TRACE_((fq->obj_name, "PUT seq=%d, count=%d",  
     143            timestamp / fq->samples_per_frame, fq->count)); 
     144 
     145    if (pj_list_empty(&fq->free_list)) { 
     146        PJ_LOG(5,(fq->obj_name,  
     147                  " AEC info: queue is full, frame discarded " 
     148                  "[count=%d, seq=%d]", 
     149                  fq->max_count, timestamp / fq->samples_per_frame)); 
     150        return PJ_ETOOMANY; 
     151    } 
     152 
     153    PJ_ASSERT_RETURN(size <= fq->frame_size, PJ_ETOOBIG); 
     154 
     155    f = fq->free_list.next; 
     156    pj_list_erase(f); 
     157 
     158    pj_memcpy(f->buf, framebuf, size); 
     159    f->size = size; 
     160    f->seq = timestamp / fq->samples_per_frame; 
     161 
     162    pj_list_push_back(&fq->frame_list, f); 
     163    ++fq->count; 
     164 
     165    return PJ_SUCCESS; 
     166} 
     167 
     168PJ_DEF(pj_status_t) pjmedia_frame_queue_get( pjmedia_frame_queue *fq, 
     169                                             pj_uint32_t get_timestamp, 
     170                                             void **framebuf, 
     171                                             unsigned *size ) 
     172{ 
     173    pj_uint32_t frame_seq; 
     174    struct fq_frame *f; 
     175 
     176    frame_seq = get_timestamp/fq->samples_per_frame + fq->seq_delay - 
     177                fq->prefetch_count; 
     178 
     179    TRACE_((fq->obj_name, "GET seq=%d for seq=%d delay=%d, prefetch=%d",  
     180            get_timestamp/fq->samples_per_frame, frame_seq, fq->seq_delay,  
     181            fq->prefetch_count)); 
     182 
     183    *size = 0; 
     184 
     185    /* Remove old frames */ 
     186    for (;!pj_list_empty(&fq->frame_list);) { 
     187        f = fq->frame_list.next; 
     188        if (f->seq >= frame_seq) 
     189            break; 
     190 
     191        PJ_LOG(5,(fq->obj_name,  
     192                  " AEC Info: old frame removed (seq=%d, want=%d, count=%d)", 
     193                  f->seq, frame_seq, fq->count)); 
     194        pj_list_erase(f); 
     195        --fq->count; 
     196        pj_list_push_back(&fq->free_list, f); 
     197    } 
     198 
     199    if (pj_list_empty(&fq->frame_list)) { 
     200        PJ_LOG(5,(fq->obj_name,  
     201                  " AEC Info: empty queue for seq=%d!", 
     202                  frame_seq)); 
     203        return PJ_ENOTFOUND; 
     204    } 
     205 
     206    f = fq->frame_list.next; 
     207 
     208    if (f->seq > frame_seq) { 
     209        PJ_LOG(5,(fq->obj_name,  
     210                  " AEC Info: prefetching (first seq=%d)", 
     211                  f->seq)); 
     212        return -1; 
     213    } 
     214 
     215    pj_list_erase(f); 
     216    --fq->count; 
     217 
     218    *framebuf = (void*)f->buf; 
     219    *size = f->size; 
     220 
     221    TRACE_((fq->obj_name, " returning frame with seq=%d, count=%d",  
     222            f->seq, fq->count)); 
     223 
     224    pj_list_push_front(&fq->free_list, f); 
     225    return PJ_SUCCESS; 
     226} 
    34227 
    35228/* 
     
    40233                                      unsigned samples_per_frame, 
    41234                                      unsigned tail_ms, 
     235                                      unsigned latency_ms, 
    42236                                      unsigned options, 
    43237                                      void **p_state ); 
     
    55249 
    56250 
    57 struct frame 
    58 { 
    59     pj_int16_t     *buf; 
     251enum 
     252{ 
     253    TS_FLAG_PLAY = 1, 
     254    TS_FLAG_REC  = 2, 
     255    TS_FLAG_OK   = 3, 
    60256}; 
    61257 
     
    65261    SpeexPreprocessState *preprocess; 
    66262 
    67     unsigned         samples_per_frame; 
    68     unsigned         options; 
    69     pj_int16_t      *tmp_frame; 
    70     spx_int32_t     *residue; 
    71  
    72     pj_lock_t       *lock;              /* To protect buffers, if required  */ 
    73  
    74     unsigned         rpos;              /* Index to get oldest frame.       */ 
    75     unsigned         wpos;              /* Index to put newest frame.       */ 
    76     struct frame     frames[BUF_COUNT]; /* Playback frame buffers.          */ 
     263    unsigned              samples_per_frame; 
     264    unsigned              prefetch; 
     265    unsigned              options; 
     266    pj_int16_t           *tmp_frame; 
     267    spx_int32_t          *residue; 
     268 
     269    pj_uint32_t           play_ts, 
     270                          rec_ts, 
     271                          ts_flag; 
     272 
     273    pjmedia_frame_queue  *frame_queue; 
     274    pj_lock_t            *lock;         /* To protect buffers, if required  */ 
    77275} speex_ec; 
    78276 
     
    86284                                     unsigned samples_per_frame, 
    87285                                     unsigned tail_ms, 
     286                                     unsigned latency_ms, 
    88287                                     unsigned options, 
    89288                                     void **p_echo ) 
     
    91290    speex_ec *echo; 
    92291    int sampling_rate; 
    93     unsigned i; 
    94     int disabled; 
     292    int disabled, enabled; 
    95293    pj_status_t status; 
    96294 
     
    111309 
    112310    echo->samples_per_frame = samples_per_frame; 
     311    echo->prefetch = (latency_ms * clock_rate / 1000) / samples_per_frame; 
     312    if (echo->prefetch < MIN_PREFETCH) 
     313        echo->prefetch = MIN_PREFETCH; 
     314    if (echo->prefetch > MAX_PREFETCH) 
     315        echo->prefetch = MAX_PREFETCH; 
    113316    echo->options = options; 
    114317 
     
    130333    /* Disable all preprocessing, we only want echo cancellation */ 
    131334    disabled = 0; 
     335    enabled = 1; 
    132336    speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE,  
    133                          &disabled); 
     337                         &enabled); 
    134338    speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC,  
    135339                         &disabled); 
     
    150354    /* Create temporary frame to receive residue */ 
    151355    echo->residue = pj_pool_zalloc(pool, sizeof(spx_int32_t) *  
    152                                             samples_per_frame); 
     356                                            (samples_per_frame+1)); 
    153357    PJ_ASSERT_RETURN(echo->residue != NULL, PJ_ENOMEM); 
    154358 
    155     /* Create internal playback buffers */ 
    156     for (i=0; i<BUF_COUNT; ++i) { 
    157         echo->frames[i].buf = pj_pool_zalloc(pool, samples_per_frame * 2); 
    158         PJ_ASSERT_RETURN(echo->frames[i].buf != NULL, PJ_ENOMEM); 
    159     } 
    160  
     359    /* Create frame queue */ 
     360    status = pjmedia_frame_queue_create(pool, "aec%p", samples_per_frame*2, 
     361                                        samples_per_frame, BUF_COUNT,  
     362                                        &echo->frame_queue); 
     363    if (status != PJ_SUCCESS) { 
     364        speex_preprocess_state_destroy(echo->preprocess); 
     365        speex_echo_state_destroy(echo->state); 
     366        pj_lock_destroy(echo->lock); 
     367        return status; 
     368    } 
    161369 
    162370    /* Done */ 
     
    164372 
    165373    PJ_LOG(4,(THIS_FILE, "Speex Echo canceller/AEC created, clock_rate=%d, " 
    166                          "samples per frame=%d, tail length=%d ms",  
    167                          clock_rate, 
    168                          samples_per_frame, 
    169                          tail_ms)); 
     374                         "samples per frame=%d, tail length=%d ms, " 
     375                         "latency=%d ms",  
     376                         clock_rate, samples_per_frame, tail_ms, latency_ms)); 
    170377    return PJ_SUCCESS; 
    171378 
     
    216423 
    217424    /* The AEC must be configured to support internal playback buffer */ 
    218     PJ_ASSERT_RETURN(echo->frames[0].buf != NULL, PJ_EINVALIDOP); 
     425    PJ_ASSERT_RETURN(echo->frame_queue!= NULL, PJ_EINVALIDOP); 
    219426 
    220427    pj_lock_acquire(echo->lock); 
    221428 
    222     /* Check for overflows */ 
    223     if (echo->wpos == echo->rpos) { 
    224         PJ_LOG(5,(THIS_FILE, "Speex AEC overflow (playback runs faster, " 
    225                              "wpos=%d, rpos=%d)", 
    226                              echo->wpos, echo->rpos)); 
    227         echo->rpos = (echo->wpos - BUF_COUNT/2) % BUF_COUNT; 
    228         speex_echo_state_reset(echo->state); 
    229     } 
    230  
    231     /* Save fhe frame */ 
    232     pjmedia_copy_samples(echo->frames[echo->wpos].buf, 
    233                          play_frm, echo->samples_per_frame); 
    234     echo->wpos = (echo->wpos+1) % BUF_COUNT; 
     429    /* Inc timestamp */ 
     430    echo->play_ts += echo->samples_per_frame; 
     431 
     432    /* Initialize frame delay. */ 
     433    if ((echo->ts_flag & TS_FLAG_PLAY) == 0) { 
     434        echo->ts_flag |= TS_FLAG_PLAY; 
     435 
     436        if (echo->ts_flag == TS_FLAG_OK) { 
     437            int seq_delay; 
     438 
     439            seq_delay = ((int)echo->play_ts - (int)echo->rec_ts) /  
     440                            (int)echo->samples_per_frame; 
     441            pjmedia_frame_queue_init(echo->frame_queue, seq_delay,  
     442                                     echo->prefetch); 
     443        } 
     444    } 
     445 
     446    pjmedia_frame_queue_put(echo->frame_queue, play_frm,  
     447                            echo->samples_per_frame*2, echo->play_ts); 
    235448 
    236449    pj_lock_release(echo->lock); 
     
    248461{ 
    249462    speex_ec *echo = state; 
    250     pj_status_t status; 
     463    pj_status_t status = PJ_SUCCESS; 
    251464 
    252465    /* Sanity checks */ 
     
    254467 
    255468    /* The AEC must be configured to support internal playback buffer */ 
    256     PJ_ASSERT_RETURN(echo->frames[0].buf != NULL, PJ_EINVALIDOP); 
     469    PJ_ASSERT_RETURN(echo->frame_queue!= NULL, PJ_EINVALIDOP); 
    257470 
    258471    /* Lock mutex */ 
    259472    pj_lock_acquire(echo->lock); 
    260473 
    261  
    262     /* Check for underflow */ 
    263     if (echo->rpos == echo->wpos) { 
    264         /* Return frame as it is */ 
    265         pj_lock_release(echo->lock); 
    266  
    267         PJ_LOG(5,(THIS_FILE, "Speex AEC underflow (capture runs faster than " 
    268                              "playback, wpos=%d, rpos=%d)",  
    269                              echo->wpos, echo->rpos)); 
    270         echo->rpos = (echo->wpos - BUF_COUNT/2) % BUF_COUNT; 
    271         speex_echo_state_reset(echo->state); 
    272  
    273         return PJ_SUCCESS; 
    274     } 
    275      
     474    /* Inc timestamp */ 
     475    echo->rec_ts += echo->samples_per_frame; 
     476 
     477    /* Init frame delay. */ 
     478    if ((echo->ts_flag & TS_FLAG_REC) == 0) { 
     479        echo->ts_flag |= TS_FLAG_REC; 
     480 
     481        if (echo->ts_flag == TS_FLAG_OK) { 
     482            int seq_delay; 
     483 
     484            seq_delay = ((int)echo->play_ts - (int)echo->rec_ts) /  
     485                            (int)echo->samples_per_frame; 
     486            pjmedia_frame_queue_init(echo->frame_queue, seq_delay,  
     487                                     echo->prefetch); 
     488        } 
     489    } 
    276490 
    277491    /* Cancel echo */ 
    278     status = speex_aec_cancel_echo(echo, rec_frm,  
    279                                    echo->frames[echo->rpos].buf, options, 
    280                                    NULL); 
    281  
    282     echo->rpos = (echo->rpos + 1) % BUF_COUNT; 
     492    if (echo->ts_flag == TS_FLAG_OK) { 
     493        void *play_buf; 
     494        unsigned size = 0; 
     495         
     496        if (pjmedia_frame_queue_empty(echo->frame_queue)) { 
     497            int seq_delay, prefetch; 
     498 
     499            seq_delay = ((int)echo->play_ts - (int)echo->rec_ts) /  
     500                            (int)echo->samples_per_frame; 
     501            prefetch = pjmedia_frame_queue_get_prefetch(echo->frame_queue); 
     502            //++prefetch; 
     503            pjmedia_frame_queue_init(echo->frame_queue, seq_delay, prefetch); 
     504            status = -1; 
     505 
     506        } else { 
     507            status = pjmedia_frame_queue_get(echo->frame_queue, echo->rec_ts, 
     508                                             &play_buf, &size); 
     509            if (size != 0) { 
     510                speex_aec_cancel_echo(echo, rec_frm, (pj_int16_t*)play_buf, 
     511                                      options, NULL); 
     512            }    
     513        } 
     514 
     515        if (status != PJ_SUCCESS) 
     516            speex_echo_state_reset(echo->state); 
     517    } 
    283518 
    284519    pj_lock_release(echo->lock); 
    285     return status; 
     520    return PJ_SUCCESS; 
    286521} 
    287522 
     
    320555} 
    321556 
     557  
  • pjproject/trunk/pjmedia/src/pjmedia/sound_port.c

    r744 r822  
    493493        status = pjmedia_echo_create(pool, snd_port->clock_rate,  
    494494                                    snd_port->samples_per_frame,  
    495                                     tail_ms, options, &snd_port->ec_state); 
     495                                    tail_ms, delay_ms, 
     496                                    options, &snd_port->ec_state); 
    496497        if (status != PJ_SUCCESS) 
    497498            snd_port->ec_state = NULL; 
  • pjproject/trunk/pjsip-apps/src/samples/aectest.c

    r815 r822  
    3636#define THIS_FILE   "playfile.c" 
    3737#define PTIME       20 
     38#define TAIL_LENGTH 800 
    3839 
    3940static const char *desc =  
     
    175176 
    176177    /* Customize AEC */ 
    177     pjmedia_snd_port_set_aec(snd, pool, 800); 
     178    pjmedia_snd_port_set_ec(snd, pool, TAIL_LENGTH, 0); 
    178179 
    179180    /* Connect sound to the port */ 
  • pjproject/trunk/pjsip-apps/src/samples/debug.c

    r693 r822  
    2828 *  #include "playfile.c" 
    2929 */ 
    30 #include "tonegen.c" 
     30#include "aectest.c" 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r813 r822  
    22162216 */ 
    22172217#ifndef PJSUA_MAX_CONF_PORTS 
    2218 #   define PJSUA_MAX_CONF_PORTS     254 
     2218#   define PJSUA_MAX_CONF_PORTS         254 
    22192219#endif 
    22202220 
    2221 #define PJSUA_DEFAULT_CLOCK_RATE    16000 
    2222 #define PJSUA_DEFAULT_CODEC_QUALITY 5 
    2223 #define PJSUA_DEFAULT_ILBC_MODE     20 
    2224 #define PJSUA_DEFAULT_EC_TAIL_LEN   0 
     2221#ifndef PJSUA_DEFAULT_CLOCK_RATE 
     2222#   define PJSUA_DEFAULT_CLOCK_RATE     16000 
     2223#endif 
     2224 
     2225#ifndef PJSUA_DEFAULT_CODEC_QUALITY 
     2226#   define PJSUA_DEFAULT_CODEC_QUALITY  5 
     2227#endif 
     2228 
     2229#ifndef PJSUA_DEFAULT_ILBC_MODE 
     2230#   define PJSUA_DEFAULT_ILBC_MODE      20 
     2231#endif 
     2232 
     2233 
     2234#ifndef PJSUA_DEFAULT_EC_TAIL_LEN 
     2235#   define PJSUA_DEFAULT_EC_TAIL_LEN    600 
     2236#endif 
    22252237 
    22262238 
Note: See TracChangeset for help on using the changeset viewer.