Ignore:
Timestamp:
Feb 25, 2006 9:15:49 PM (18 years ago)
Author:
bennylp
Message:

Fixed echo in conference, and add ability to shrink buffer in jitter buffer

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/conference.c

    r228 r229  
    9292    pj_snd_stream        *snd_rec;      /**< Sound recorder stream.         */ 
    9393    pj_snd_stream        *snd_player;   /**< Sound player stream.           */ 
     94    pj_mutex_t           *mutex;        /**< Conference mutex.              */ 
    9495    struct conf_port    **ports;        /**< Array of ports.                */ 
    9596    pj_uint16_t          *uns_buf;      /**< Buf for unsigned conversion    */ 
     
    100101}; 
    101102 
     103 
     104/* Extern */ 
     105unsigned char linear2ulaw(int pcm_val); 
    102106 
    103107/* Prototypes */ 
     
    261265    conf->uns_buf = pj_pool_zalloc(pool, samples_per_frame * 
    262266                                         sizeof(conf->uns_buf[0])); 
     267 
     268    /* Create mutex. */ 
     269    status = pj_mutex_create_simple(pool, "conf", &conf->mutex); 
     270    if (status != PJ_SUCCESS) 
     271        return status; 
     272 
     273 
    263274    /* Done */ 
    264275 
     
    365376    suspend_sound(conf); 
    366377    destroy_sound(conf); 
     378    pj_mutex_destroy(conf->mutex); 
    367379 
    368380    return PJ_SUCCESS; 
     
    386398                     PJ_EINVAL); 
    387399 
     400    pj_mutex_lock(conf->mutex); 
     401 
    388402    if (conf->port_cnt >= conf->max_ports) { 
    389403        pj_assert(!"Too many ports"); 
     404        pj_mutex_unlock(conf->mutex); 
    390405        return PJ_ETOOMANY; 
    391406    } 
     
    401416    /* Create port structure. */ 
    402417    status = create_conf_port(pool, conf, port_name, &conf_port); 
    403     if (status != PJ_SUCCESS) 
     418    if (status != PJ_SUCCESS) { 
     419        pj_mutex_unlock(conf->mutex); 
    404420        return status; 
     421    } 
    405422 
    406423    /* Set the port */ 
     
    413430    /* Done. */ 
    414431    *p_port = index; 
     432 
     433    pj_mutex_unlock(conf->mutex); 
    415434 
    416435    return PJ_SUCCESS; 
     
    462481    PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL); 
    463482    PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL); 
     483 
     484    pj_mutex_lock(conf->mutex); 
    464485 
    465486    src_port = conf->ports[src_slot]; 
     
    481502    } 
    482503 
     504    pj_mutex_unlock(conf->mutex); 
     505 
    483506    return PJ_SUCCESS; 
    484507} 
     
    501524    PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL); 
    502525    PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL); 
     526 
     527    pj_mutex_lock(conf->mutex); 
    503528 
    504529    src_port = conf->ports[src_slot]; 
     
    522547    } 
    523548 
     549    pj_mutex_unlock(conf->mutex); 
     550 
    524551    return PJ_SUCCESS; 
    525552} 
     
    545572     * device's threads! 
    546573     */ 
    547     //suspend_sound(conf); 
     574 
     575    pj_mutex_lock(conf->mutex); 
    548576 
    549577    conf_port = conf->ports[port]; 
     
    578606    --conf->port_cnt; 
    579607 
    580     /* Reactivate sound device if there are connections */ 
    581     if (conf->connect_cnt != 0) { 
    582         //resume_sound(conf); 
    583     } else { 
     608    /* Stop sound if there's no connection. */ 
     609    if (conf->connect_cnt == 0) { 
    584610        destroy_sound(conf); 
    585611    } 
    586612 
    587     pj_thread_sleep(60); 
     613    pj_mutex_unlock(conf->mutex); 
     614 
    588615    return PJ_SUCCESS; 
    589616} 
     
    659686    pjmedia_conf *conf = user_data; 
    660687    pj_int16_t *output_buf = output; 
    661     unsigned i, j; 
     688    unsigned ci, cj, i, j; 
    662689     
    663690    PJ_UNUSED_ARG(timestamp); 
     
    666693    TRACE_(("p")); 
    667694 
    668     /* Clear all port's tmp buffers. */ 
    669     for (i=0; i<conf->max_ports; ++i) { 
     695    pj_mutex_lock(conf->mutex); 
     696 
     697    /* Zero all port's temporary buffers. */ 
     698    for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) { 
    670699        struct conf_port *conf_port = conf->ports[i]; 
    671700        pj_uint32_t *sum_buf; 
    672701 
     702        /* Skip empty slot. */ 
    673703        if (!conf_port) 
    674704            continue; 
     705 
     706        ++ci; 
    675707 
    676708        conf_port->sources = 0; 
     
    681713    } 
    682714 
    683     /* Get frames from all ports, and "add" the signal  
     715    /* Get frames from all ports, and "mix" the signal  
    684716     * to sum_buf of all listeners of the port. 
    685717     */ 
    686     for (i=0; i<conf->max_ports; ++i) { 
     718    for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { 
    687719        struct conf_port *conf_port = conf->ports[i]; 
    688720        pj_int32_t level; 
    689         pj_bool_t silence; 
    690721 
    691722        /* Skip empty port. */ 
     
    693724            continue; 
    694725 
     726        ++ci; 
     727 
    695728        /* Skip if we're not allowed to receive from this port. */ 
    696729        if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) { 
    697             TRACE_(("rxdis:%d ", i)); 
    698730            continue; 
    699731        } 
    700732 
    701733        /* Get frame from this port.  
    702          * If port has rx_buffer (e.g. sound port), then get the frame  
    703          * from the rx_buffer instead. 
     734         * For port zero (sound port), get the frame  from the rx_buffer 
     735         * instead. 
    704736         */ 
    705737        if (i==0) { 
     
    712744            } 
    713745 
     746            /* Skip if this port is muted/disabled. */ 
     747            if (conf_port->rx_setting != PJMEDIA_PORT_ENABLE) { 
     748                continue; 
     749            } 
     750 
     751 
     752            /* Skip if no port is listening to the microphone */ 
     753            if (conf_port->listener_cnt == 0) { 
     754                continue; 
     755            } 
     756 
    714757            rx_buf = conf_port->rx_buf[conf_port->rx_read]; 
    715758            for (j=0; j<conf->samples_per_frame; ++j) { 
     
    726769            pjmedia_port_get_frame(conf_port->port, &frame); 
    727770 
    728             if (frame.type == PJMEDIA_FRAME_TYPE_NONE) 
     771           if (frame.type == PJMEDIA_FRAME_TYPE_NONE) 
    729772                continue; 
    730773        } 
     
    738781            continue; 
    739782 
    740         /* Do we have signal? */ 
    741         silence = pjmedia_silence_det_detect_silence(conf_port->vad, 
    742                                                      output,  
    743                                                      conf->samples_per_frame, 
    744                                                      &level); 
    745  
    746         /* Skip if we don't have signal. */ 
    747         if (silence) { 
    748             TRACE_(("sil:%d ", i)); 
    749             continue; 
    750         } 
    751  
    752         /* Convert the buffer to unsigned value */ 
     783        /* Get the signal level. */ 
     784        level = pjmedia_calc_avg_signal(output, conf->samples_per_frame); 
     785 
     786        /* Convert level to 8bit complement ulaw */ 
     787        level = linear2ulaw(level) ^ 0xff; 
     788 
     789        /* Convert the buffer to unsigned 16bit value */ 
    753790        for (j=0; j<conf->samples_per_frame; ++j) 
    754791            conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)output)[j]); 
    755792 
    756793        /* Add the signal to all listeners. */ 
    757         for (j=0; j<conf->max_ports; ++j) { 
     794        for (j=0, cj=0;  
     795             j<conf->max_ports && cj<(unsigned)conf_port->listener_cnt; 
     796             ++j)  
     797        { 
    758798            struct conf_port *listener = conf->ports[j]; 
    759799            pj_uint32_t *sum_buf; 
     
    763803                continue; 
    764804 
     805            /* Skip if this is not the listener. */ 
     806            if (!conf_port->listeners[j]) 
     807                continue; 
     808 
     809            ++cj; 
     810 
    765811            /* Skip if this listener doesn't want to receive audio */ 
    766812            if (listener->tx_setting != PJMEDIA_PORT_ENABLE) 
    767813                continue; 
    768814 
    769             //TRACE_(("mix:%d->%d ", i, j)); 
    770  
     815            /* Mix the buffer */ 
    771816            sum_buf = listener->sum_buf; 
    772817            for (k=0; k<conf->samples_per_frame; ++k) 
    773                 sum_buf[k] += conf->uns_buf[k]; 
    774  
    775             listener->sources++; 
     818                sum_buf[k] += (conf->uns_buf[k] * level); 
     819 
     820            listener->sources += level; 
    776821        } 
    777822    } 
    778823 
    779824    /* For all ports, calculate avg signal. */ 
    780     for (i=0; i<conf->max_ports; ++i) { 
     825    for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { 
    781826        struct conf_port *conf_port = conf->ports[i]; 
    782827        pjmedia_frame frame; 
     
    785830        if (!conf_port) 
    786831            continue; 
     832 
     833        ++ci; 
    787834 
    788835        if (conf_port->tx_setting == PJMEDIA_PORT_MUTE) { 
     
    800847        } 
    801848 
    802         // 
    803         // TODO: 
    804         //  When there's no source, not transmit the frame, but instead 
    805         //  transmit a 'silence' frame. This is to allow the 'port' to 
    806         //  do some processing, such as updating timestamp for RTP session 
    807         //  or transmit signal when it's in the middle of transmitting DTMF. 
    808         // 
    809  
    810849        target_buf = (conf_port->cur_tx_buf==conf_port->tx_buf1? 
    811850                        conf_port->tx_buf2 : conf_port->tx_buf1); 
     
    813852        if (conf_port->sources) { 
    814853            for (j=0; j<conf->samples_per_frame; ++j) { 
    815                 target_buf[j] = unsigned2pcm(conf_port->sum_buf[j] / conf_port->sources); 
     854                target_buf[j] = unsigned2pcm(conf_port->sum_buf[j] /  
     855                                             conf_port->sources); 
    816856            } 
    817857        } 
     
    821861 
    822862        pj_memset(&frame, 0, sizeof(frame)); 
    823         if (conf_port->sources) 
    824             frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    825         else 
     863        if (conf_port->sources) { 
     864 
     865            pj_bool_t is_silence = PJ_FALSE; 
     866 
     867            /* Apply silence detection. */ 
     868#if 0 
     869            is_silence = pjmedia_silence_det_detect(conf_port->vad, 
     870                                                    target_buf, 
     871                                                    conf->samples_per_frame, 
     872                                                    NULL); 
     873#endif 
     874            frame.type = is_silence ? PJMEDIA_FRAME_TYPE_NONE :  
     875                                      PJMEDIA_FRAME_TYPE_AUDIO; 
     876 
     877        } else 
    826878            frame.type = PJMEDIA_FRAME_TYPE_NONE; 
    827879 
     
    836888 
    837889    /* Return sound playback frame. */ 
    838     for (j=0; j<conf->samples_per_frame; ++j) 
    839         output_buf[j] = conf->ports[0]->cur_tx_buf[j]; 
     890    if (conf->ports[0]->sources) { 
     891        for (j=0; j<conf->samples_per_frame; ++j) 
     892            output_buf[j] = conf->ports[0]->cur_tx_buf[j]; 
     893    } else { 
     894        for (j=0; j<conf->samples_per_frame; ++j) 
     895            output_buf[j] = 0; 
     896    } 
     897 
     898    pj_mutex_unlock(conf->mutex); 
    840899 
    841900    return PJ_SUCCESS; 
     
    863922        TRACE_(("rxerr ")); 
    864923    } 
     924 
     925    /* Skip if this port is muted/disabled. */ 
     926    if (snd_port->rx_setting != PJMEDIA_PORT_ENABLE) 
     927        return PJ_SUCCESS; 
     928 
     929    /* Skip if no port is listening to the microphone */ 
     930    if (snd_port->listener_cnt == 0) 
     931        return PJ_SUCCESS; 
    865932 
    866933 
Note: See TracChangeset for help on using the changeset viewer.