Ignore:
Timestamp:
Aug 26, 2008 8:09:03 PM (16 years ago)
Author:
nanang
Message:

Added PLC & VAD features to codec L16.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c

    r2039 r2247  
    2121#include <pjmedia/errno.h> 
    2222#include <pjmedia/endpoint.h> 
     23#include <pjmedia/plc.h> 
     24#include <pjmedia/silencedet.h> 
    2325#include <pj/assert.h> 
    2426#include <pj/pool.h> 
     
    3133 */ 
    3234#if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC != 0 
     35 
     36#define PLC_DISABLED    0 
    3337 
    3438 
     
    7882                                 unsigned output_buf_len,  
    7983                                 struct pjmedia_frame *output); 
     84#if !PLC_DISABLED 
     85static pj_status_t  l16_recover(pjmedia_codec *codec, 
     86                                unsigned output_buf_len, 
     87                                struct pjmedia_frame *output); 
     88#endif 
    8089 
    8190/* Definition for L16 codec operations. */ 
     
    8897    &l16_parse, 
    8998    &l16_encode, 
    90     &l16_decode 
     99    &l16_decode, 
     100    &l16_recover 
    91101}; 
    92102 
     
    108118    pj_pool_t                  *pool; 
    109119    pj_mutex_t                 *mutex; 
    110     pjmedia_codec               codec_list; 
    111120} l16_factory; 
    112121 
     
    115124struct l16_data 
    116125{ 
    117     unsigned frame_size;    /* Frame size, in bytes */ 
     126    pj_pool_t           *pool; 
     127    unsigned             frame_size;    /* Frame size, in bytes */ 
     128    unsigned             clock_rate;    /* Clock rate */ 
     129 
     130    pj_bool_t            plc_enabled; 
     131#if !PLC_DISABLED 
     132    pjmedia_plc         *plc; 
     133#endif 
     134    pj_bool_t            vad_enabled; 
     135    pjmedia_silence_det *vad; 
     136    pj_timestamp         last_tx; 
    118137}; 
    119138 
     
    139158    l16_factory.base.factory_data = NULL; 
    140159    l16_factory.endpt = endpt; 
    141  
    142     pj_list_init(&l16_factory.codec_list); 
    143160 
    144161    /* Create pool */ 
     
    253270    attr->setting.frm_per_pkt = 1; 
    254271 
    255     /* Default all flag bits disabled. */ 
     272    attr->setting.vad = 1; 
     273#if !PLC_DISABLED 
     274    attr->setting.plc = 1; 
     275#endif 
    256276 
    257277    return PJ_SUCCESS; 
     
    421441    struct l16_data *data; 
    422442    unsigned ptime; 
     443    pj_pool_t *pool; 
     444 
     445    pj_status_t status; 
    423446 
    424447    PJ_ASSERT_RETURN(factory==&l16_factory.base, PJ_EINVAL); 
     
    427450    pj_mutex_lock(l16_factory.mutex); 
    428451 
    429     /* Allocate new codec if no more is available */ 
    430     if (pj_list_empty(&l16_factory.codec_list)) { 
    431  
    432         codec = PJ_POOL_ALLOC_T(l16_factory.pool, pjmedia_codec); 
    433         codec->codec_data = pj_pool_alloc(l16_factory.pool,  
    434                                           sizeof(struct l16_data)); 
    435         codec->factory = factory; 
    436         codec->op = &l16_op; 
    437  
    438     } else { 
    439         codec = l16_factory.codec_list.next; 
    440         pj_list_erase(codec); 
    441     } 
     452 
     453    pool = pjmedia_endpt_create_pool(l16_factory.endpt, "l16", 4000, 4000); 
     454    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec); 
     455    codec->codec_data = pj_pool_alloc(pool, sizeof(struct l16_data)); 
     456    codec->factory = factory; 
     457    codec->op = &l16_op; 
    442458 
    443459    /* Init private data */ 
     
    445461    data = (struct l16_data*) codec->codec_data; 
    446462    data->frame_size = ptime * id->clock_rate * id->channel_cnt * 2 / 1000; 
    447  
    448     /* Zero the list, for error detection in l16_dealloc_codec */ 
    449     codec->next = codec->prev = NULL; 
     463    data->clock_rate = id->clock_rate; 
     464    data->pool = pool; 
     465 
     466#if !PLC_DISABLED 
     467    /* Create PLC */ 
     468    status = pjmedia_plc_create(pool, id->clock_rate,  
     469                                data->frame_size >> 1, 0,  
     470                                &data->plc); 
     471    if (status != PJ_SUCCESS) { 
     472        pj_mutex_unlock(l16_factory.mutex); 
     473        return status; 
     474    } 
     475#endif 
     476 
     477    /* Create silence detector */ 
     478    status = pjmedia_silence_det_create(pool, id->clock_rate,  
     479                                        data->frame_size >> 1, 
     480                                        &data->vad); 
     481    if (status != PJ_SUCCESS) { 
     482        pj_mutex_unlock(l16_factory.mutex); 
     483        return status; 
     484    } 
    450485 
    451486    *p_codec = codec; 
     
    460495                                     pjmedia_codec *codec ) 
    461496{ 
    462      
     497    struct l16_data *data; 
     498 
     499    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL); 
    463500    PJ_ASSERT_RETURN(factory==&l16_factory.base, PJ_EINVAL); 
    464  
    465     /* Check that this node has not been deallocated before */ 
    466     pj_assert (codec->next==NULL && codec->prev==NULL); 
    467     if (codec->next!=NULL || codec->prev!=NULL) { 
    468         return PJ_EINVALIDOP; 
    469     } 
    470501 
    471502    /* Lock mutex. */ 
    472503    pj_mutex_lock(l16_factory.mutex); 
    473504 
    474     /* Insert at the back of the list */ 
    475     pj_list_insert_before(&l16_factory.codec_list, codec); 
     505    /* Just release codec data pool */ 
     506    data = (struct l16_data*) codec->codec_data; 
     507    pj_assert(data); 
     508    pj_pool_release(data->pool); 
    476509 
    477510    /* Unlock mutex. */ 
     
    509542                               const pjmedia_codec_param *attr ) 
    510543{ 
    511     /* Don't want to do anything. */ 
    512     PJ_UNUSED_ARG(codec); 
    513     PJ_UNUSED_ARG(attr); 
    514     return PJ_EINVALIDOP; 
     544    struct l16_data *data = (struct l16_data*) codec->codec_data; 
     545 
     546    pj_assert(data != NULL); 
     547 
     548    data->vad_enabled = (attr->setting.vad != 0); 
     549    data->plc_enabled = (attr->setting.plc != 0); 
     550 
     551    return PJ_SUCCESS; 
    515552} 
    516553 
     
    549586                              struct pjmedia_frame *output) 
    550587{ 
     588    struct l16_data *data = (struct l16_data*) codec->codec_data; 
    551589    const pj_int16_t *samp = (const pj_int16_t*) input->buf; 
    552590    const pj_int16_t *samp_end = samp + input->size/sizeof(pj_int16_t); 
    553591    pj_int16_t *samp_out = (pj_int16_t*) output->buf;     
    554592 
    555  
    556     PJ_UNUSED_ARG(codec); 
    557  
     593    pj_assert(data && input && output); 
    558594 
    559595    /* Check output buffer length */ 
     
    561597        return PJMEDIA_CODEC_EFRMTOOSHORT; 
    562598 
     599    /* Detect silence */ 
     600    if (data->vad_enabled) { 
     601        pj_bool_t is_silence; 
     602        pj_int32_t silence_duration; 
     603 
     604        silence_duration = pj_timestamp_diff32(&data->last_tx,  
     605                                               &input->timestamp); 
     606 
     607        is_silence = pjmedia_silence_det_detect(data->vad,  
     608                                                (const pj_int16_t*) input->buf, 
     609                                                (input->size >> 1), 
     610                                                NULL); 
     611        if (is_silence && 
     612            PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 && 
     613            silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD* 
     614                               (int)data->clock_rate/1000) 
     615        { 
     616            output->type = PJMEDIA_FRAME_TYPE_NONE; 
     617            output->buf = NULL; 
     618            output->size = 0; 
     619            output->timestamp = input->timestamp; 
     620            return PJ_SUCCESS; 
     621        } else { 
     622            data->last_tx = input->timestamp; 
     623        } 
     624    } 
    563625 
    564626    /* Encode */ 
     
    583645                              struct pjmedia_frame *output) 
    584646{ 
     647    struct l16_data *l16_data = (struct l16_data*) codec->codec_data; 
    585648    const pj_int16_t *samp = (const pj_int16_t*) input->buf; 
    586649    const pj_int16_t *samp_end = samp + input->size/sizeof(pj_int16_t); 
    587650    pj_int16_t *samp_out = (pj_int16_t*) output->buf;     
    588651 
    589  
    590     PJ_UNUSED_ARG(codec); 
     652    pj_assert(l16_data != NULL); 
     653    PJ_ASSERT_RETURN(input && output, PJ_EINVAL); 
    591654 
    592655 
     
    608671    output->size = input->size; 
    609672 
    610     return PJ_SUCCESS; 
    611 } 
    612  
     673#if !PLC_DISABLED 
     674    if (l16_data->plc_enabled) 
     675        pjmedia_plc_save( l16_data->plc, (pj_int16_t*)output->buf); 
     676#endif 
     677 
     678    return PJ_SUCCESS; 
     679} 
     680 
     681#if !PLC_DISABLED 
     682/* 
     683 * Recover lost frame. 
     684 */ 
     685static pj_status_t  l16_recover(pjmedia_codec *codec, 
     686                                      unsigned output_buf_len, 
     687                                      struct pjmedia_frame *output) 
     688{ 
     689    struct l16_data *data = (struct l16_data*) codec->codec_data; 
     690 
     691    PJ_ASSERT_RETURN(data->plc_enabled, PJ_EINVALIDOP); 
     692 
     693    PJ_ASSERT_RETURN(output_buf_len >= data->frame_size,  
     694                     PJMEDIA_CODEC_EPCMTOOSHORT); 
     695 
     696    pjmedia_plc_generate(data->plc, (pj_int16_t*)output->buf); 
     697    output->size = data->frame_size; 
     698 
     699    return PJ_SUCCESS; 
     700} 
     701#endif 
    613702 
    614703#endif  /* PJMEDIA_HAS_L16_CODEC */ 
Note: See TracChangeset for help on using the changeset viewer.