Ignore:
Timestamp:
Mar 17, 2006 12:16:01 AM (18 years ago)
Author:
bennylp
Message:

Added feature in conference bridge to get and set the signal level of individual port and individual stream direction

File:
1 edited

Legend:

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

    r322 r323  
    2222#include <pjmedia/resample.h> 
    2323#include <pjmedia/silencedet.h> 
    24 #include <pjmedia/sound.h> 
     24#include <pjmedia/sound_port.h> 
    2525#include <pjmedia/stream.h> 
    2626#include <pj/assert.h> 
     
    4747 * 
    4848 * TX and RX directions are always viewed from the conference bridge's point 
    49  * of view, and NOT from the port's point of view.  
     49 * of view, and NOT from the port's point of view. So TX means the bridge 
     50 * is transmitting to the port, RX means the bridge is receiving from the 
     51 * port. 
    5052 */ 
    5153 
     
    6870    unsigned             samples_per_frame; /**< Port's samples per frame.  */ 
    6971 
     72    /* Calculated signal levels: */ 
     73    pj_bool_t            need_tx_level; /**< Need to calculate tx level?    */ 
     74    unsigned             tx_level;      /**< Last tx level to this port.    */ 
     75    unsigned             rx_level;      /**< Last rx level from this port.  */ 
     76 
     77    /* The normalized signal level adjustment. 
     78     * A value of 128 means there's no adjustment. 
     79     */ 
     80    unsigned             tx_adj_level;  /**< Adjustment for TX.             */ 
     81    unsigned             rx_adj_level;  /**< Adjustment for RX.             */ 
     82 
    7083    /* Resample, for converting clock rate, if they're different. */ 
    7184    pjmedia_resample    *rx_resample; 
     
    7487    /* RX buffer is temporary buffer to be used when there is mismatch 
    7588     * between port's sample rate or ptime with conference's sample rate 
    76      * or ptime. When both sample rate and ptime of the port match the 
    77      * conference settings, this buffer will not be used. 
     89     * or ptime. The buffer is used for sampling rate conversion AND/OR to 
     90     * buffer the samples until there are enough samples to fulfill a  
     91     * complete frame to be processed by the bridge. 
     92     * 
     93     * When both sample rate AND ptime of the port match the conference  
     94     * settings, this buffer will not be created. 
    7895     *  
    7996     * This buffer contains samples at port's clock rate. 
     
    86103 
    87104    /* Mix buf is a temporary buffer used to calculate the average signal 
    88      * received by this port from all other ports. 
     105     * received by this port from all other ports. Samples from all ports 
     106     * that are transmitting to this port will be accumulated here, then 
     107     * they will be divided by the sources count before the samples are put 
     108     * to the TX buffer of this port. 
    89109     * 
    90110     * This buffer contains samples at bridge's clock rate. 
     
    98118    /* Tx buffer is a temporary buffer to be used when there's mismatch  
    99119     * between port's clock rate or ptime with conference's sample rate 
    100      * or ptime. When both sample rate and ptime of the port match the 
    101      * conference's settings, this buffer will not be used. 
     120     * or ptime. This buffer is used as the source of the sampling rate 
     121     * conversion AND/OR to buffer the samples until there are enough 
     122     * samples to fulfill a complete frame to be transmitted to the port. 
     123     * 
     124     * When both sample rate and ptime of the port match the bridge's  
     125     * settings, this buffer will not be created. 
    102126     *  
    103127     * This buffer contains samples at port's clock rate. 
     
    109133    unsigned             tx_buf_count;  /**< # of samples in the buffer.    */ 
    110134 
    111     /* Snd buffers is a special buffer for sound device port (port 0).  
    112      * It's not used by other ports. 
     135    /* Snd buffers is a special buffer for sound device port (port 0, master 
     136     * port). It's not used by other ports. 
    113137     * 
    114138     * There are multiple numbers of this buffer, because we can not expect 
     
    132156    unsigned              port_cnt;     /**< Current number of ports.       */ 
    133157    unsigned              connect_cnt;  /**< Total number of connections    */ 
    134     pjmedia_snd_stream   *snd_rec;      /**< Sound recorder stream.         */ 
    135     pjmedia_snd_stream   *snd_player;   /**< Sound player stream.           */ 
     158    pjmedia_snd_port     *snd_rec;      /**< Sound recorder stream.         */ 
     159    pjmedia_snd_port     *snd_player;   /**< Sound player stream.           */ 
     160    pjmedia_port         *master_port;  /**< Port zero's port.              */ 
    136161    pj_mutex_t           *mutex;        /**< Conference mutex.              */ 
    137162    struct conf_port    **ports;        /**< Array of ports.                */ 
     
    148173 
    149174/* Prototypes */ 
    150 static pj_status_t play_cb( /* in */  void *user_data, 
    151                             /* in */  pj_uint32_t timestamp, 
    152                             /* out */ void *output, 
    153                             /* out */ unsigned size); 
    154 static pj_status_t rec_cb(  /* in */  void *user_data, 
    155                             /* in */  pj_uint32_t timestamp, 
    156                             /* in */  const void *input, 
    157                             /* in*/   unsigned size); 
     175static pj_status_t put_frame(pjmedia_port *this_port,  
     176                             const pjmedia_frame *frame); 
     177static pj_status_t get_frame(pjmedia_port *this_port,  
     178                             pjmedia_frame *frame); 
     179 
    158180 
    159181/* 
     
    179201    conf_port->rx_setting = PJMEDIA_PORT_ENABLE; 
    180202    conf_port->tx_setting = PJMEDIA_PORT_ENABLE; 
     203 
     204    /* Default level adjustment is 128 (which means no adjustment) */ 
     205    conf_port->tx_adj_level = 128; 
     206    conf_port->rx_adj_level = 128; 
    181207 
    182208    /* Create transmit flag array */ 
     
    310336    conf->port_cnt++; 
    311337 
     338 
     339    /* Create sound devices: */ 
     340 
     341    /* Create recorder only if mic is not disabled. */ 
     342    if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0 && 
     343        (conf->options & PJMEDIA_CONF_NO_MIC) == 0)  
     344    { 
     345        status = pjmedia_snd_port_create_rec( pool, -1, conf->clock_rate,  
     346                                              conf->channel_count,  
     347                                              conf->samples_per_frame, 
     348                                              conf->bits_per_sample, 
     349                                              0,    /* Options */ 
     350                                              &conf->snd_rec); 
     351        if (status != PJ_SUCCESS) { 
     352            conf->snd_rec = NULL; 
     353            return status; 
     354        } 
     355    } 
     356 
     357    /* Create player device */ 
     358    if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) { 
     359        status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate,  
     360                                                conf->channel_count, 
     361                                                conf->samples_per_frame, 
     362                                                conf->bits_per_sample,  
     363                                                0,      /* options */ 
     364                                                &conf->snd_player); 
     365        if (status != PJ_SUCCESS) { 
     366            if (conf->snd_rec) { 
     367                pjmedia_snd_port_destroy(conf->snd_rec); 
     368                conf->snd_rec = NULL; 
     369            } 
     370            conf->snd_player = NULL; 
     371            return status; 
     372        } 
     373    } 
     374 
     375 
    312376    PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0")); 
    313377    return PJ_SUCCESS; 
     
    349413    conf->max_ports = max_ports; 
    350414    conf->clock_rate = clock_rate; 
     415    conf->channel_count = channel_count; 
    351416    conf->samples_per_frame = samples_per_frame; 
    352417    conf->bits_per_sample = bits_per_sample; 
     418 
     419     
     420    /* Create and initialize the master port interface. */ 
     421    conf->master_port = pj_pool_zalloc(pool, sizeof(pjmedia_port)); 
     422    PJ_ASSERT_RETURN(conf->master_port, PJ_ENOMEM); 
     423     
     424    conf->master_port->info.bits_per_sample = bits_per_sample; 
     425    conf->master_port->info.bytes_per_frame = samples_per_frame * 
     426                                              bits_per_sample / 8; 
     427    conf->master_port->info.channel_count = channel_count; 
     428    conf->master_port->info.encoding_name = pj_str("pcm"); 
     429    conf->master_port->info.has_info = 1; 
     430    conf->master_port->info.name = pj_str("master port"); 
     431    conf->master_port->info.need_info = 0; 
     432    conf->master_port->info.pt = 0xFF; 
     433    conf->master_port->info.sample_rate = clock_rate; 
     434    conf->master_port->info.samples_per_frame = samples_per_frame; 
     435    conf->master_port->info.signature = 0; 
     436    conf->master_port->info.type = PJMEDIA_TYPE_AUDIO; 
     437 
     438    conf->master_port->get_frame = &get_frame; 
     439    conf->master_port->put_frame = &put_frame; 
     440 
     441    conf->master_port->user_data = conf; 
    353442 
    354443 
     
    367456        return status; 
    368457 
     458    /* If sound device was created, connect sound device to the 
     459     * master port. 
     460     */ 
     461    if (conf->snd_player) { 
     462        status = pjmedia_snd_port_connect( conf->snd_player,  
     463                                           conf->master_port ); 
     464        if (status != PJ_SUCCESS) { 
     465            pjmedia_conf_destroy(conf); 
     466            return status; 
     467        } 
     468    } 
     469 
     470    if (conf->snd_rec) { 
     471        status = pjmedia_snd_port_connect( conf->snd_rec, 
     472                                           conf->master_port); 
     473        if (status != PJ_SUCCESS) { 
     474            pjmedia_conf_destroy(conf); 
     475            return status; 
     476        } 
     477    } 
     478 
    369479 
    370480    /* Done */ 
     
    377487 
    378488/* 
    379  * Create sound device 
    380  */ 
    381 static pj_status_t create_sound( pjmedia_conf *conf ) 
    382 { 
    383     pj_status_t status; 
    384  
    385     /* Open recorder only if mic is not disabled. */ 
    386     if ((conf->options & PJMEDIA_CONF_NO_MIC) == 0) { 
    387         status = pjmedia_snd_open_recorder(-1, conf->clock_rate, 1,  
    388                                       conf->samples_per_frame, 
    389                                       conf->bits_per_sample, 
    390                                       &rec_cb, conf, &conf->snd_rec); 
    391         if (status != PJ_SUCCESS) { 
    392             conf->snd_rec = NULL; 
    393             return status; 
    394         } 
    395     } 
    396  
    397     /* Open player */ 
    398     status = pjmedia_snd_open_player(-1, conf->clock_rate, 1, 
    399                                 conf->samples_per_frame, 
    400                                 conf->bits_per_sample,  
    401                                 &play_cb, conf, &conf->snd_player); 
    402     if (status != PJ_SUCCESS) { 
    403         if (conf->snd_rec) { 
    404             pjmedia_snd_stream_close(conf->snd_rec); 
    405             conf->snd_rec = NULL; 
    406         } 
    407         conf->snd_player = NULL; 
    408         return status; 
    409     } 
    410  
    411     return PJ_SUCCESS; 
    412 } 
    413  
    414 /* 
    415  * Destroy sound device 
    416  */ 
    417 static pj_status_t destroy_sound( pjmedia_conf *conf ) 
    418 { 
    419     if (conf->snd_rec) { 
    420         pjmedia_snd_stream_close(conf->snd_rec); 
    421         conf->snd_rec = NULL; 
    422     } 
    423     if (conf->snd_player) { 
    424         pjmedia_snd_stream_close(conf->snd_player); 
    425         conf->snd_player = NULL; 
    426     } 
    427     return PJ_SUCCESS; 
    428 } 
    429  
    430 /* 
    431  * Activate sound device. 
     489 * Pause sound device. 
     490 */ 
     491static pj_status_t pause_sound( pjmedia_conf *conf ) 
     492{ 
     493    /* Do nothing. */ 
     494    PJ_UNUSED_ARG(conf); 
     495    return PJ_SUCCESS; 
     496} 
     497 
     498/* 
     499 * Resume sound device. 
    432500 */ 
    433501static pj_status_t resume_sound( pjmedia_conf *conf ) 
    434502{ 
    435     char errmsg[PJ_ERR_MSG_SIZE]; 
    436     pj_status_t status; 
    437  
    438     if (conf->snd_player == NULL) { 
    439         status = create_sound(conf); 
    440         if (status != PJ_SUCCESS) 
    441             return status; 
    442     } 
    443  
    444     /* Start recorder. */ 
    445     if (conf->snd_rec) { 
    446         status = pjmedia_snd_stream_start(conf->snd_rec); 
    447         if (status != PJ_SUCCESS) 
    448             goto on_error; 
    449     } 
    450  
    451     /* Start player. */ 
    452     if (conf->snd_player) { 
    453         status = pjmedia_snd_stream_start(conf->snd_player); 
    454         if (status != PJ_SUCCESS) 
    455             goto on_error; 
    456     } 
    457  
    458     return PJ_SUCCESS; 
    459  
    460 on_error: 
    461     pj_strerror(status, errmsg, sizeof(errmsg)); 
    462     PJ_LOG(4,(THIS_FILE, "Error starting sound player/recorder: %s", 
    463               errmsg)); 
    464     return status; 
     503    /* Do nothing. */ 
     504    PJ_UNUSED_ARG(conf); 
     505    return PJ_SUCCESS; 
    465506} 
    466507 
     
    473514    PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL); 
    474515 
    475     //suspend_sound(conf); 
    476     destroy_sound(conf); 
     516    /* Destroy sound devices. */ 
     517    if (conf->snd_rec) { 
     518        pjmedia_snd_port_destroy(conf->snd_rec); 
     519        conf->snd_rec = NULL; 
     520    } 
     521    if (conf->snd_player) { 
     522        pjmedia_snd_port_destroy(conf->snd_player); 
     523        conf->snd_player = NULL; 
     524    } 
     525 
     526    /* Destroy mutex */ 
    477527    pj_mutex_destroy(conf->mutex); 
    478528 
    479529    return PJ_SUCCESS; 
     530} 
     531 
     532 
     533/* 
     534 * Get port zero interface. 
     535 */ 
     536PJ_DEF(pjmedia_port*) pjmedia_conf_get_master_port(pjmedia_conf *conf) 
     537{ 
     538    /* Sanity check. */ 
     539    PJ_ASSERT_RETURN(conf != NULL, NULL); 
     540 
     541    /* Can only return port interface when PJMEDIA_CONF_NO_DEVICE was 
     542     * present in the option. 
     543     */ 
     544    PJ_ASSERT_RETURN((conf->options & PJMEDIA_CONF_NO_DEVICE) != 0, NULL); 
     545     
     546    return conf->master_port; 
    480547} 
    481548 
     
    520587    pj_assert(index != conf->max_ports); 
    521588 
    522     /* Create port structure. */ 
     589    /* Create conf port structure. */ 
    523590    status = create_conf_port(pool, conf, strm_port, port_name, &conf_port); 
    524591    if (status != PJ_SUCCESS) { 
     
    575642PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, 
    576643                                               unsigned src_slot, 
    577                                                unsigned sink_slot ) 
     644                                               unsigned sink_slot, 
     645                                               int level ) 
    578646{ 
    579647    struct conf_port *src_port, *dst_port; 
     
    587655    PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL); 
    588656    PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL); 
     657 
     658    /* For now, level MUST be zero. */ 
     659    PJ_ASSERT_RETURN(level == 0, PJ_EINVAL); 
    589660 
    590661    pj_mutex_lock(conf->mutex); 
     
    659730 
    660731    if (conf->connect_cnt == 0) { 
    661         destroy_sound(conf); 
     732        pause_sound(conf); 
    662733    } 
    663734 
     
    724795    /* Stop sound if there's no connection. */ 
    725796    if (conf->connect_cnt == 0) { 
    726         destroy_sound(conf); 
     797        pause_sound(conf); 
    727798    } 
    728799 
     
    780851 
    781852 
     853/* 
     854 * Get signal level. 
     855 */ 
     856PJ_DEF(pj_status_t) pjmedia_conf_get_signal_level( pjmedia_conf *conf, 
     857                                                   unsigned slot, 
     858                                                   unsigned *tx_level, 
     859                                                   unsigned *rx_level) 
     860{ 
     861    struct conf_port *conf_port; 
     862 
     863    /* Check arguments */ 
     864    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 
     865 
     866    /* Port must be valid. */ 
     867    PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 
     868 
     869    conf_port = conf->ports[slot]; 
     870 
     871    if (tx_level != NULL) { 
     872        conf_port->need_tx_level = 1; 
     873        *tx_level = conf_port->tx_level; 
     874    } 
     875 
     876    if (rx_level != NULL)  
     877        *rx_level = conf_port->rx_level; 
     878 
     879    return PJ_SUCCESS; 
     880} 
     881 
     882 
     883/* 
     884 * Adjust RX level of individual port. 
     885 */ 
     886PJ_DEF(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf, 
     887                                                  unsigned slot, 
     888                                                  int adj_level ) 
     889{ 
     890    struct conf_port *conf_port; 
     891 
     892    /* Check arguments */ 
     893    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 
     894 
     895    /* Port must be valid. */ 
     896    PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 
     897 
     898    /* Value must be from -128 to +127 */ 
     899    PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); 
     900 
     901    conf_port = conf->ports[slot]; 
     902 
     903    /* Set normalized adjustment level. */ 
     904    conf_port->rx_adj_level = adj_level + 128; 
     905 
     906    return PJ_SUCCESS; 
     907} 
     908 
     909 
     910/* 
     911 * Adjust TX level of individual port. 
     912 */ 
     913PJ_DEF(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf, 
     914                                                  unsigned slot, 
     915                                                  int adj_level ) 
     916{ 
     917    struct conf_port *conf_port; 
     918 
     919    /* Check arguments */ 
     920    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 
     921 
     922    /* Port must be valid. */ 
     923    PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 
     924 
     925    /* Value must be from -128 to +127 */ 
     926    PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); 
     927 
     928    conf_port = conf->ports[slot]; 
     929 
     930    /* Set normalized adjustment level. */ 
     931    conf_port->tx_adj_level = adj_level + 128; 
     932 
     933    return PJ_SUCCESS; 
     934} 
     935 
     936 
    782937/* Convert signed 16bit pcm sample to unsigned 16bit sample */ 
    783938static pj_uint16_t pcm2unsigned(pj_int32_t pcm) 
     
    9251080            pjmedia_port_put_frame(cport->port, &frame); 
    9261081 
     1082        cport->tx_level = 0; 
    9271083        return PJ_SUCCESS; 
    9281084 
    9291085    } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) { 
     1086        cport->tx_level = 0; 
    9301087        return PJ_SUCCESS; 
    9311088    } 
     
    9341091     * to the mixed samples itself. This is possible because mixed sample 
    9351092     * is 32bit. 
     1093     * 
     1094     * In addition to this process, if we need to change the level of 
     1095     * TX signal, we adjust is here too. 
    9361096     */ 
    9371097    buf = (pj_int16_t*)cport->mix_buf; 
    938     for (j=0; j<conf->samples_per_frame; ++j) { 
    939         buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->sources); 
     1098 
     1099    if (cport->tx_adj_level != 128) { 
     1100 
     1101        unsigned adj_level = cport->tx_adj_level; 
     1102 
     1103        /* We need to adjust signal level. */ 
     1104        for (j=0; j<conf->samples_per_frame; ++j) { 
     1105            pj_int32_t itemp; 
     1106 
     1107            /* Calculate average level, and convert the sample to 
     1108             * 16bit signed integer. 
     1109             */ 
     1110            itemp = unsigned2pcm(cport->mix_buf[j] / cport->sources); 
     1111 
     1112            /* Adjust the level */ 
     1113            itemp = itemp * adj_level / 128; 
     1114 
     1115            /* Clip the signal if it's too loud */ 
     1116            if (itemp > 32767) itemp = 32767; 
     1117            else if (itemp < -32768) itemp = -32768; 
     1118 
     1119            /* Put back in the buffer. */ 
     1120            buf[j] = (pj_int16_t) itemp; 
     1121        } 
     1122 
     1123    } else { 
     1124        /* No need to adjust signal level. */ 
     1125        for (j=0; j<conf->samples_per_frame; ++j) { 
     1126            buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->sources); 
     1127        } 
     1128    } 
     1129 
     1130    /* Calculate TX level if we need to do so.  
     1131     * This actually is not the most correct place to calculate TX signal  
     1132     * level of the port; it should calculate the level of the actual 
     1133     * frame just before put_frame() is called. 
     1134     * But doing so would make the code more complicated than it is 
     1135     * necessary, since the purpose of level calculation mostly is just 
     1136     * for VU meter display. By doing it here, it should give the acceptable 
     1137     * indication of the signal level of the port. 
     1138     */ 
     1139    if (cport->need_tx_level) { 
     1140        pj_uint32_t level; 
     1141 
     1142        /* Get the signal level. */ 
     1143        level = pjmedia_calc_avg_signal(buf, conf->samples_per_frame); 
     1144 
     1145        /* Convert level to 8bit complement ulaw */ 
     1146        cport->tx_level = linear2ulaw(level) ^ 0xff; 
     1147 
     1148    } else { 
     1149        cport->tx_level = 0; 
    9401150    } 
    9411151 
     
    10131223 * Player callback. 
    10141224 */ 
    1015 static pj_status_t play_cb( /* in */  void *user_data, 
    1016                             /* in */  pj_uint32_t timestamp, 
    1017                             /* out */ void *output, 
    1018                             /* out */ unsigned size) 
    1019 { 
    1020     pjmedia_conf *conf = user_data; 
     1225static pj_status_t get_frame(pjmedia_port *this_port,  
     1226                             pjmedia_frame *frame) 
     1227{ 
     1228    pjmedia_conf *conf = this_port->user_data; 
    10211229    unsigned ci, cj, i, j; 
    10221230     
    1023     PJ_UNUSED_ARG(timestamp); 
    1024     PJ_UNUSED_ARG(size); 
    1025  
     1231    /* Check that correct size is specified. */ 
     1232    pj_assert(frame->size == conf->samples_per_frame * 
     1233                             conf->bits_per_sample / 8); 
     1234 
     1235    /* Must lock mutex (must we??) */ 
    10261236    pj_mutex_lock(conf->mutex); 
    10271237 
     
    10571267            continue; 
    10581268 
     1269        /* Var "ci" is to count how many ports have been visited so far. */ 
    10591270        ++ci; 
    10601271 
    10611272        /* Skip if we're not allowed to receive from this port. */ 
    10621273        if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) { 
     1274            conf_port->rx_level = 0; 
    10631275            continue; 
    10641276        } 
    10651277 
    10661278        /* Also skip if this port doesn't have listeners. */ 
    1067         if (conf_port->listener_cnt == 0) 
     1279        if (conf_port->listener_cnt == 0) { 
     1280            conf_port->rx_level = 0; 
    10681281            continue; 
     1282        } 
    10691283 
    10701284        /* Get frame from this port.  
     
    10831297            /* Skip if this port is muted/disabled. */ 
    10841298            if (conf_port->rx_setting != PJMEDIA_PORT_ENABLE) { 
     1299                conf_port->rx_level = 0; 
    10851300                continue; 
    10861301            } 
    10871302 
    1088  
    1089             /* Skip if no port is listening to the microphone */ 
    1090             if (conf_port->listener_cnt == 0) { 
    1091                 continue; 
    1092             } 
    1093  
    10941303            snd_buf = conf_port->snd_buf[conf_port->snd_read_pos]; 
    10951304            for (j=0; j<conf->samples_per_frame; ++j) { 
    1096                 ((pj_int16_t*)output)[j] = snd_buf[j]; 
     1305                ((pj_int16_t*)frame->buf)[j] = snd_buf[j]; 
    10971306            } 
    10981307            conf_port->snd_read_pos = (conf_port->snd_read_pos+1) % RX_BUF_COUNT; 
     
    11031312            pjmedia_frame_type frame_type; 
    11041313 
    1105             status = read_port(conf, conf_port, output,  
     1314            status = read_port(conf, conf_port, frame->buf,  
    11061315                               conf->samples_per_frame, &frame_type); 
    11071316             
     
    11171326        } 
    11181327 
    1119         /* Get the signal level. */ 
    1120         level = pjmedia_calc_avg_signal(output, conf->samples_per_frame); 
     1328        /* If we need to adjust the RX level from this port, adjust the level 
     1329         * and calculate the average level at the same time. 
     1330         * Otherwise just calculate the averate level. 
     1331         */ 
     1332        if (conf_port->rx_adj_level != 128) { 
     1333            pj_int16_t *input = frame->buf; 
     1334            pj_int32_t adj = conf_port->rx_adj_level; 
     1335 
     1336            level = 0; 
     1337            for (j=0; j<conf->samples_per_frame; ++j) { 
     1338                pj_int32_t itemp; 
     1339 
     1340                /* For the level adjustment, we need to store the sample to 
     1341                 * a temporary 32bit integer value to avoid overflowing the 
     1342                 * 16bit sample storage. 
     1343                 */ 
     1344                itemp = input[j]; 
     1345                itemp = itemp * adj / 128; 
     1346 
     1347                /* Clip the signal if it's too loud */ 
     1348                if (itemp > 32767) itemp = 32767; 
     1349                else if (itemp < -32768) itemp = -32768; 
     1350 
     1351                input[j] = (pj_int16_t) itemp; 
     1352                level += itemp; 
     1353            } 
     1354 
     1355            level /= conf->samples_per_frame; 
     1356 
     1357        } else { 
     1358            level = pjmedia_calc_avg_signal(frame->buf,  
     1359                                            conf->samples_per_frame); 
     1360        } 
    11211361 
    11221362        /* Convert level to 8bit complement ulaw */ 
    11231363        level = linear2ulaw(level) ^ 0xff; 
    11241364 
     1365        /* Put this level to port's last RX level. */ 
     1366        conf_port->rx_level = level; 
     1367 
    11251368        /* Convert the buffer to unsigned 16bit value */ 
    11261369        for (j=0; j<conf->samples_per_frame; ++j) 
    1127             conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)output)[j]); 
     1370            conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)frame->buf)[j]); 
    11281371 
    11291372        /* Add the signal to all listeners. */ 
     
    11431386                continue; 
    11441387 
     1388            /* Var "cj" is the number of listeners we have visited so far */ 
    11451389            ++cj; 
    11461390 
     
    11581402    } 
    11591403 
    1160     /* For all ports, calculate avg signal. */ 
     1404    /* Time for all ports to transmit whetever they have in their 
     1405     * buffer.  
     1406     */ 
    11611407    for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { 
    11621408        struct conf_port *conf_port = conf->ports[i]; 
     
    11661412            continue; 
    11671413 
     1414        /* Var "ci" is to count how many ports have been visited. */ 
    11681415        ++ci; 
    11691416 
    1170         status = write_port( conf, conf_port, timestamp); 
     1417        status = write_port( conf, conf_port, frame->timestamp.u32.lo); 
    11711418        if (status != PJ_SUCCESS) { 
    11721419            PJ_LOG(4,(THIS_FILE, "Port %.*s put_frame() returned %d. " 
     
    11821429    /* Return sound playback frame. */ 
    11831430    if (conf->ports[0]->sources) { 
    1184         copy_samples( output, (pj_int16_t*)conf->ports[0]->mix_buf,  
     1431        copy_samples( frame->buf, (pj_int16_t*)conf->ports[0]->mix_buf,  
    11851432                      conf->samples_per_frame); 
    11861433    } else { 
    1187         zero_samples( output, conf->samples_per_frame );  
     1434        zero_samples( frame->buf, conf->samples_per_frame );  
    11881435    } 
    11891436 
     
    11971444 * Recorder callback. 
    11981445 */ 
    1199 static pj_status_t rec_cb(  /* in */  void *user_data, 
    1200                             /* in */  pj_uint32_t timestamp, 
    1201                             /* in */  const void *input, 
    1202                             /* in */  unsigned size) 
    1203 { 
    1204     pjmedia_conf *conf = user_data; 
     1446static pj_status_t put_frame(pjmedia_port *this_port,  
     1447                             const pjmedia_frame *frame) 
     1448{ 
     1449    pjmedia_conf *conf = this_port->user_data; 
    12051450    struct conf_port *snd_port = conf->ports[0]; 
     1451    const pj_int16_t *input = frame->buf; 
    12061452    pj_int16_t *target_snd_buf; 
    12071453    unsigned i; 
    12081454 
    1209     PJ_UNUSED_ARG(timestamp); 
    1210      
    12111455    TRACE_(("r")); 
    12121456 
    1213     if (size != conf->samples_per_frame*2) { 
    1214         TRACE_(("rxerr ")); 
    1215     } 
     1457    /* Check for correct size. */ 
     1458    PJ_ASSERT_RETURN( frame->size == conf->samples_per_frame * 
     1459                                     conf->bits_per_sample / 8, 
     1460                      PJMEDIA_ENCSAMPLESPFRAME); 
    12161461 
    12171462    /* Skip if this port is muted/disabled. */ 
Note: See TracChangeset for help on using the changeset viewer.