Ignore:
Timestamp:
Feb 29, 2008 5:19:42 PM (12 years ago)
Author:
bennylp
Message:

Ticket #438: Workaround for frame bursts from audio devices: added wsola in delaybuf, and put delaybuf in the bridge

File:
1 edited

Legend:

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

    r1715 r1833  
    1919#include <pjmedia/conference.h> 
    2020#include <pjmedia/alaw_ulaw.h> 
     21#include <pjmedia/delaybuf.h> 
    2122#include <pjmedia/errno.h> 
    2223#include <pjmedia/port.h> 
     
    5758#define THIS_FILE       "conference.c" 
    5859 
    59 /* When delay buffer is used, we only need 1 frame buffering */ 
    60 #if defined(PJMEDIA_SOUND_USE_DELAYBUF) && PJMEDIA_SOUND_USE_DELAYBUF!=0 
    61 #   define RX_BUF_COUNT     1 
    62 #else 
    63 #   define RX_BUF_COUNT     PJMEDIA_SOUND_BUFFER_COUNT 
    64 #endif 
     60#define RX_BUF_COUNT        PJMEDIA_SOUND_BUFFER_COUNT 
    6561 
    6662#define BYTES_PER_SAMPLE    2 
     
    184180    unsigned             tx_buf_count;  /**< # of samples in the buffer.    */ 
    185181 
    186     /* Snd buffers is a special buffer for sound device port (port 0, master 
    187      * port). It's not used by other ports. 
     182    /* Delay buffer is a special buffer for sound device port (port 0, master 
     183     * port) and other passive ports (sound device port is also passive port). 
    188184     * 
    189      * There are multiple numbers of this buffer, because we can not expect 
    190      * the mic and speaker thread to run equally after one another. In most 
    191      * systems, each thread will run multiple times before the other thread 
    192      * gains execution time. For example, in my system, mic thread is called 
    193      * three times, then speaker thread is called three times, and so on. 
    194      */ 
    195     int                  snd_write_pos, snd_read_pos; 
    196     pj_int16_t          *snd_buf[RX_BUF_COUNT]; /**< Buffer                 */ 
     185     * We need the delay buffer because we can not expect the mic and speaker  
     186     * thread to run equally after one another. In most systems, each thread  
     187     * will run multiple times before the other thread gains execution time.  
     188     * For example, in my system, mic thread is called three times, then  
     189     * speaker thread is called three times, and so on. This we call burst. 
     190     * 
     191     * There is also possibility of drift, unbalanced rate between put_frame 
     192     * and get_frame operation, in passive ports. If drift happens, snd_buf 
     193     * needs to be expanded or shrinked.  
     194     * 
     195     * Burst and drift are handled by delay buffer. 
     196     */ 
     197    pjmedia_delay_buf   *delay_buf; 
    197198}; 
    198199 
     
    227228                                  pjmedia_frame *frame); 
    228229static pj_status_t destroy_port(pjmedia_port *this_port); 
     230static pj_status_t destroy_port_pasv(pjmedia_port *this_port); 
    229231 
    230232 
     
    378380{ 
    379381    struct conf_port *conf_port; 
    380     unsigned i; 
    381382    pj_status_t status; 
    382383 
     
    386387        return status; 
    387388 
    388     /* Passive port has rx buffers. */ 
    389     for (i=0; i<RX_BUF_COUNT; ++i) { 
    390         conf_port->snd_buf[i] = (pj_int16_t*) 
    391                                 pj_pool_zalloc(pool, conf->samples_per_frame * 
    392                                               sizeof(conf_port->snd_buf[0][0])); 
    393         if (conf_port->snd_buf[i] == NULL) { 
    394             return PJ_ENOMEM; 
    395         } 
    396     } 
    397     conf_port->snd_write_pos = 0; 
    398     conf_port->snd_read_pos = 0; 
     389    /* Passive port has delay buf. */ 
     390    status = pjmedia_delay_buf_create(pool, name->ptr,  
     391                                      conf->clock_rate, 
     392                                      conf->samples_per_frame, 
     393                                      RX_BUF_COUNT, /* max */ 
     394                                      -1, /* delay */ 
     395                                      0, /* options */ 
     396                                      &conf_port->delay_buf); 
     397    if (status != PJ_SUCCESS) 
     398        return status; 
    399399 
    400400    *p_conf_port = conf_port; 
     
    445445                                              0,    /* Options */ 
    446446                                              &conf->snd_dev_port); 
     447 
    447448        } 
    448449 
     
    607608} 
    608609 
     610static pj_status_t destroy_port_pasv(pjmedia_port *this_port) { 
     611    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata; 
     612    struct conf_port *port = conf->ports[this_port->port_data.ldata]; 
     613    pj_status_t status; 
     614 
     615    status = pjmedia_delay_buf_destroy(port->delay_buf); 
     616    if (status == PJ_SUCCESS) 
     617        port->delay_buf = NULL; 
     618 
     619    return status; 
     620} 
    609621 
    610622/* 
     
    786798    port->get_frame = &get_frame_pasv; 
    787799    port->put_frame = &put_frame; 
    788     port->on_destroy = NULL; 
     800    port->on_destroy = &destroy_port_pasv; 
    789801 
    790802     
     
    955967                  dst_port->name.ptr)); 
    956968 
    957          
     969        /* if source port is passive port and has no listener, reset delaybuf */ 
     970        if (src_port->delay_buf && src_port->listener_cnt == 0) 
     971            pjmedia_delay_buf_reset(src_port->delay_buf); 
    958972    } 
    959973 
     
    16171631        } 
    16181632 
    1619         /* Get frame from this port.  
    1620          * For port zero (sound port) and passive ports, get the frame  from  
    1621          * the rx_buffer instead. 
     1633        /* Get frame from this port. 
     1634         * For passive ports, get the frame from the delay_buf. 
     1635         * For other ports, get the frame from the port.  
    16221636         */ 
    1623         if (conf_port->port == NULL) { 
    1624             pj_int16_t *snd_buf; 
    1625  
    1626             if (conf_port->snd_read_pos == conf_port->snd_write_pos) { 
    1627                 conf_port->snd_read_pos =  
    1628                     (conf_port->snd_write_pos+RX_BUF_COUNT-RX_BUF_COUNT/2) %  
    1629                         RX_BUF_COUNT; 
    1630             } 
    1631  
    1632             /* Skip if this port is muted/disabled. */ 
    1633             if (conf_port->rx_setting != PJMEDIA_PORT_ENABLE) { 
    1634                 conf_port->rx_level = 0; 
     1637        if (conf_port->delay_buf != NULL) { 
     1638            pj_status_t status; 
     1639         
     1640            status = pjmedia_delay_buf_get(conf_port->delay_buf, 
     1641                                  (pj_int16_t*)frame->buf); 
     1642            if (status != PJ_SUCCESS) 
    16351643                continue; 
    1636             } 
    1637  
    1638             snd_buf = conf_port->snd_buf[conf_port->snd_read_pos]; 
    1639             pjmedia_copy_samples((pj_int16_t*)frame->buf, snd_buf,  
    1640                                  conf->samples_per_frame); 
    1641             conf_port->snd_read_pos = (conf_port->snd_read_pos+1) % RX_BUF_COUNT; 
    16421644 
    16431645        } else { 
     
    18311833 
    18321834/* 
    1833  * Recorder callback. 
     1835 * Recorder (or passive port) callback. 
    18341836 */ 
    18351837static pj_status_t put_frame(pjmedia_port *this_port,  
     
    18381840    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata; 
    18391841    struct conf_port *port = conf->ports[this_port->port_data.ldata]; 
    1840     const pj_int16_t *input = (const pj_int16_t*) frame->buf; 
    1841     pj_int16_t *target_snd_buf; 
     1842    pj_status_t status; 
    18421843 
    18431844    /* Check for correct size. */ 
     
    18461847                      PJMEDIA_ENCSAMPLESPFRAME); 
    18471848 
     1849    /* Check existance of delay_buf instance */ 
     1850    PJ_ASSERT_RETURN( port->delay_buf, PJ_EBUG ); 
     1851 
    18481852    /* Skip if this port is muted/disabled. */ 
    18491853    if (port->rx_setting != PJMEDIA_PORT_ENABLE) { 
     
    18561860    } 
    18571861 
    1858  
    1859     /* Determine which rx_buffer to fill in */ 
    1860     target_snd_buf = port->snd_buf[port->snd_write_pos]; 
    1861      
    1862     /* Copy samples from audio device to target rx_buffer */ 
    1863     pjmedia_copy_samples(target_snd_buf, input, conf->samples_per_frame); 
    1864  
    1865     /* Switch buffer */ 
    1866     port->snd_write_pos = (port->snd_write_pos+1)%RX_BUF_COUNT; 
    1867  
    1868  
    1869     return PJ_SUCCESS; 
    1870 } 
    1871  
     1862    status = pjmedia_delay_buf_put(port->delay_buf, (pj_int16_t*)frame->buf); 
     1863 
     1864    return status; 
     1865} 
     1866 
Note: See TracChangeset for help on using the changeset viewer.