Changeset 323 for pjproject/trunk/pjmedia/src/pjmedia/conference.c
- Timestamp:
- Mar 17, 2006 12:16:01 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/conference.c
r322 r323 22 22 #include <pjmedia/resample.h> 23 23 #include <pjmedia/silencedet.h> 24 #include <pjmedia/sound .h>24 #include <pjmedia/sound_port.h> 25 25 #include <pjmedia/stream.h> 26 26 #include <pj/assert.h> … … 47 47 * 48 48 * 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. 50 52 */ 51 53 … … 68 70 unsigned samples_per_frame; /**< Port's samples per frame. */ 69 71 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 70 83 /* Resample, for converting clock rate, if they're different. */ 71 84 pjmedia_resample *rx_resample; … … 74 87 /* RX buffer is temporary buffer to be used when there is mismatch 75 88 * 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. 78 95 * 79 96 * This buffer contains samples at port's clock rate. … … 86 103 87 104 /* 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. 89 109 * 90 110 * This buffer contains samples at bridge's clock rate. … … 98 118 /* Tx buffer is a temporary buffer to be used when there's mismatch 99 119 * 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. 102 126 * 103 127 * This buffer contains samples at port's clock rate. … … 109 133 unsigned tx_buf_count; /**< # of samples in the buffer. */ 110 134 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. 113 137 * 114 138 * There are multiple numbers of this buffer, because we can not expect … … 132 156 unsigned port_cnt; /**< Current number of ports. */ 133 157 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. */ 136 161 pj_mutex_t *mutex; /**< Conference mutex. */ 137 162 struct conf_port **ports; /**< Array of ports. */ … … 148 173 149 174 /* 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); 175 static pj_status_t put_frame(pjmedia_port *this_port, 176 const pjmedia_frame *frame); 177 static pj_status_t get_frame(pjmedia_port *this_port, 178 pjmedia_frame *frame); 179 158 180 159 181 /* … … 179 201 conf_port->rx_setting = PJMEDIA_PORT_ENABLE; 180 202 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; 181 207 182 208 /* Create transmit flag array */ … … 310 336 conf->port_cnt++; 311 337 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 312 376 PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0")); 313 377 return PJ_SUCCESS; … … 349 413 conf->max_ports = max_ports; 350 414 conf->clock_rate = clock_rate; 415 conf->channel_count = channel_count; 351 416 conf->samples_per_frame = samples_per_frame; 352 417 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; 353 442 354 443 … … 367 456 return status; 368 457 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 369 479 370 480 /* Done */ … … 377 487 378 488 /* 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 */ 491 static 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. 432 500 */ 433 501 static pj_status_t resume_sound( pjmedia_conf *conf ) 434 502 { 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; 465 506 } 466 507 … … 473 514 PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL); 474 515 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 */ 477 527 pj_mutex_destroy(conf->mutex); 478 528 479 529 return PJ_SUCCESS; 530 } 531 532 533 /* 534 * Get port zero interface. 535 */ 536 PJ_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; 480 547 } 481 548 … … 520 587 pj_assert(index != conf->max_ports); 521 588 522 /* Create port structure. */589 /* Create conf port structure. */ 523 590 status = create_conf_port(pool, conf, strm_port, port_name, &conf_port); 524 591 if (status != PJ_SUCCESS) { … … 575 642 PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, 576 643 unsigned src_slot, 577 unsigned sink_slot ) 644 unsigned sink_slot, 645 int level ) 578 646 { 579 647 struct conf_port *src_port, *dst_port; … … 587 655 PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL); 588 656 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); 589 660 590 661 pj_mutex_lock(conf->mutex); … … 659 730 660 731 if (conf->connect_cnt == 0) { 661 destroy_sound(conf);732 pause_sound(conf); 662 733 } 663 734 … … 724 795 /* Stop sound if there's no connection. */ 725 796 if (conf->connect_cnt == 0) { 726 destroy_sound(conf);797 pause_sound(conf); 727 798 } 728 799 … … 780 851 781 852 853 /* 854 * Get signal level. 855 */ 856 PJ_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 */ 886 PJ_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 */ 913 PJ_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 782 937 /* Convert signed 16bit pcm sample to unsigned 16bit sample */ 783 938 static pj_uint16_t pcm2unsigned(pj_int32_t pcm) … … 925 1080 pjmedia_port_put_frame(cport->port, &frame); 926 1081 1082 cport->tx_level = 0; 927 1083 return PJ_SUCCESS; 928 1084 929 1085 } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) { 1086 cport->tx_level = 0; 930 1087 return PJ_SUCCESS; 931 1088 } … … 934 1091 * to the mixed samples itself. This is possible because mixed sample 935 1092 * 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. 936 1096 */ 937 1097 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; 940 1150 } 941 1151 … … 1013 1223 * Player callback. 1014 1224 */ 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; 1225 static pj_status_t get_frame(pjmedia_port *this_port, 1226 pjmedia_frame *frame) 1227 { 1228 pjmedia_conf *conf = this_port->user_data; 1021 1229 unsigned ci, cj, i, j; 1022 1230 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??) */ 1026 1236 pj_mutex_lock(conf->mutex); 1027 1237 … … 1057 1267 continue; 1058 1268 1269 /* Var "ci" is to count how many ports have been visited so far. */ 1059 1270 ++ci; 1060 1271 1061 1272 /* Skip if we're not allowed to receive from this port. */ 1062 1273 if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) { 1274 conf_port->rx_level = 0; 1063 1275 continue; 1064 1276 } 1065 1277 1066 1278 /* 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; 1068 1281 continue; 1282 } 1069 1283 1070 1284 /* Get frame from this port. … … 1083 1297 /* Skip if this port is muted/disabled. */ 1084 1298 if (conf_port->rx_setting != PJMEDIA_PORT_ENABLE) { 1299 conf_port->rx_level = 0; 1085 1300 continue; 1086 1301 } 1087 1302 1088 1089 /* Skip if no port is listening to the microphone */1090 if (conf_port->listener_cnt == 0) {1091 continue;1092 }1093 1094 1303 snd_buf = conf_port->snd_buf[conf_port->snd_read_pos]; 1095 1304 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]; 1097 1306 } 1098 1307 conf_port->snd_read_pos = (conf_port->snd_read_pos+1) % RX_BUF_COUNT; … … 1103 1312 pjmedia_frame_type frame_type; 1104 1313 1105 status = read_port(conf, conf_port, output,1314 status = read_port(conf, conf_port, frame->buf, 1106 1315 conf->samples_per_frame, &frame_type); 1107 1316 … … 1117 1326 } 1118 1327 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 } 1121 1361 1122 1362 /* Convert level to 8bit complement ulaw */ 1123 1363 level = linear2ulaw(level) ^ 0xff; 1124 1364 1365 /* Put this level to port's last RX level. */ 1366 conf_port->rx_level = level; 1367 1125 1368 /* Convert the buffer to unsigned 16bit value */ 1126 1369 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]); 1128 1371 1129 1372 /* Add the signal to all listeners. */ … … 1143 1386 continue; 1144 1387 1388 /* Var "cj" is the number of listeners we have visited so far */ 1145 1389 ++cj; 1146 1390 … … 1158 1402 } 1159 1403 1160 /* For all ports, calculate avg signal. */ 1404 /* Time for all ports to transmit whetever they have in their 1405 * buffer. 1406 */ 1161 1407 for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { 1162 1408 struct conf_port *conf_port = conf->ports[i]; … … 1166 1412 continue; 1167 1413 1414 /* Var "ci" is to count how many ports have been visited. */ 1168 1415 ++ci; 1169 1416 1170 status = write_port( conf, conf_port, timestamp);1417 status = write_port( conf, conf_port, frame->timestamp.u32.lo); 1171 1418 if (status != PJ_SUCCESS) { 1172 1419 PJ_LOG(4,(THIS_FILE, "Port %.*s put_frame() returned %d. " … … 1182 1429 /* Return sound playback frame. */ 1183 1430 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, 1185 1432 conf->samples_per_frame); 1186 1433 } else { 1187 zero_samples( output, conf->samples_per_frame );1434 zero_samples( frame->buf, conf->samples_per_frame ); 1188 1435 } 1189 1436 … … 1197 1444 * Recorder callback. 1198 1445 */ 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; 1446 static pj_status_t put_frame(pjmedia_port *this_port, 1447 const pjmedia_frame *frame) 1448 { 1449 pjmedia_conf *conf = this_port->user_data; 1205 1450 struct conf_port *snd_port = conf->ports[0]; 1451 const pj_int16_t *input = frame->buf; 1206 1452 pj_int16_t *target_snd_buf; 1207 1453 unsigned i; 1208 1454 1209 PJ_UNUSED_ARG(timestamp);1210 1211 1455 TRACE_(("r")); 1212 1456 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); 1216 1461 1217 1462 /* Skip if this port is muted/disabled. */
Note: See TracChangeset
for help on using the changeset viewer.