diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 312937756e..0de6a28859 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -264,7 +264,8 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se switch_sdp_type_t sdp_type, uint32_t pt, uint32_t rate, - uint32_t ptime, + uint32_t ptime, + uint32_t channels, uint8_t negotiated); diff --git a/src/include/switch_frame.h b/src/include/switch_frame.h index bbbca0917b..51800df6c1 100644 --- a/src/include/switch_frame.h +++ b/src/include/switch_frame.h @@ -61,6 +61,8 @@ SWITCH_BEGIN_EXTERN_C uint32_t samples; /*! the rate of the frame */ uint32_t rate; + /*! the number of channels in the frame */ + uint32_t channels; /*! the payload of the frame */ switch_payload_t payload; /*! the timestamp of the frame */ diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index ef27e75758..644887a931 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -117,7 +117,7 @@ SWITCH_DECLARE(switch_endpoint_interface_t *) switch_loadable_module_get_endpoin */ SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_interface(const char *name); -SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit); +SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit, uint32_t *channels); /*! \brief Retrieve the dialplan interface by it's registered name diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index af10ca3371..62ab8dbcbc 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -266,6 +266,8 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag switch_opus_fmtp_parse(codec->fmtp_in, &codec_fmtp); codec->fmtp_out = gen_fmtp(&opus_codec_settings, codec->memory_pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OPUS init %d %d\n", codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels); + if (encoding) { /* come up with a way to specify these */ int bitrate_bps = OPUS_AUTO; @@ -472,6 +474,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) settings.maxptime = settings.ptime; settings.minptime = settings.ptime; settings.samplerate = rate; + settings.stereo = 0; dft_fmtp = gen_fmtp(&settings, pool); switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ @@ -493,8 +496,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) switch_opus_destroy); /* deinitalize a codec handle using this implementation */ settings.stereo = 1; + if (x < 2) { dft_fmtp = gen_fmtp(&settings, pool); - switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ 116, /* the IANA code number */ "opus",/* the IANA code name */ @@ -512,7 +515,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) switch_opus_encode, /* function to encode raw data into encoded data */ switch_opus_decode, /* function to decode encoded data into raw data */ switch_opus_destroy); /* deinitalize a codec handle using this implementation */ - + } bytes *= 2; samples *= 2; mss *= 2; diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c index 8c0dd8c92e..b0cde67f07 100644 --- a/src/mod/endpoints/mod_loopback/mod_loopback.c +++ b/src/mod/endpoints/mod_loopback/mod_loopback.c @@ -140,8 +140,8 @@ static switch_status_t tech_init(loopback_private_t *tech_pvt, switch_core_sessi if ((var = switch_channel_get_variable(channel, "loopback_initial_codec"))) { char *dup = switch_core_session_strdup(session, var); - uint32_t bit; - iananame = switch_parse_codec_buf(dup, &interval, &rate, &bit); + uint32_t bit, channels; + iananame = switch_parse_codec_buf(dup, &interval, &rate, &bit, &channels); } } diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index 7d30e7dc84..748c98067c 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -1441,10 +1441,12 @@ static switch_status_t verto_connect(switch_core_session_t *session, const char verto_set_media_options(tech_pvt, jsock->profile); - switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); + switch_channel_set_variable(tech_pvt->channel, "verto_profile_name", jsock->profile->name); if (!switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) { + switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); + if ((status = switch_core_media_choose_ports(tech_pvt->session, SWITCH_TRUE, SWITCH_TRUE)) != SWITCH_STATUS_SUCCESS) { //if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 430993df1f..bb99c3eb39 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -405,6 +405,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi tmp_frame.codec = (*frame)->codec; tmp_frame.datalen = (*frame)->codec->implementation->encoded_bytes_per_packet; tmp_frame.samples = (*frame)->codec->implementation->samples_per_packet; + tmp_frame.channels = (*frame)->codec->implementation->number_of_channels; tmp_frame.data = data; switch_core_gen_encoded_silence(data, (*frame)->codec->implementation, tmp_frame.datalen); @@ -510,7 +511,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi session->raw_read_frame.timestamp = 0; session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; - session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); + session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels; + session->raw_read_frame.channels = read_frame->codec->implementation->number_of_channels; read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; } else { @@ -547,7 +549,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; - session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); + session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels; + session->raw_read_frame.channels = session->read_impl.number_of_channels; memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen); status = SWITCH_STATUS_SUCCESS; } else { @@ -632,7 +635,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi } } case SWITCH_STATUS_SUCCESS: - session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); + session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels; + session->raw_read_frame.channels = session->read_impl.number_of_channels; session->raw_read_frame.rate = read_frame->rate; if (read_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->raw_read_frame.timestamp = 0; @@ -670,7 +674,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi case SWITCH_STATUS_BREAK: memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; - session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); + session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels; + session->raw_read_frame.channels = session->read_impl.number_of_channels; session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.rate = read_frame->rate; session->raw_read_frame.ssrc = read_frame->ssrc; @@ -820,6 +825,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2 / session->read_resampler->channels); memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2 * session->read_resampler->channels); read_frame->samples = session->read_resampler->to_len; + read_frame->channels = session->read_resampler->channels; read_frame->datalen = session->read_resampler->to_len * 2 * session->read_resampler->channels; read_frame->rate = session->read_resampler->to_rate; switch_mutex_unlock(session->resample_mutex); @@ -872,7 +878,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi case SWITCH_STATUS_RESAMPLE: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 1\n"); case SWITCH_STATUS_SUCCESS: - session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t); + session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t) / session->read_impl.number_of_channels; + session->enc_read_frame.channels = session->read_impl.number_of_channels; if (perfect) { if (enc_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->enc_read_frame.timestamp = 0; @@ -889,6 +896,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi break; case SWITCH_STATUS_NOOP: session->raw_read_frame.samples = enc_frame->codec->implementation->samples_per_packet; + session->raw_read_frame.channels = enc_frame->codec->implementation->number_of_channels; session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode; session->raw_read_frame.m = read_frame->m; @@ -1251,7 +1259,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess } break; case SWITCH_STATUS_SUCCESS: - session->raw_write_frame.samples = session->raw_write_frame.datalen / sizeof(int16_t); + session->raw_write_frame.samples = session->raw_write_frame.datalen / sizeof(int16_t) / session->write_impl.number_of_channels; + session->raw_write_frame.channels = session->write_impl.number_of_channels; session->raw_write_frame.timestamp = frame->timestamp; session->raw_write_frame.rate = frame->rate; session->raw_write_frame.m = frame->m; @@ -1317,7 +1326,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2 * session->write_resampler->channels); write_frame->samples = session->write_resampler->to_len; - + write_frame->channels = session->write_resampler->channels; write_frame->datalen = write_frame->samples * 2 * session->write_resampler->channels; write_frame->rate = session->write_resampler->to_rate; @@ -1431,7 +1440,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 2\n"); */ case SWITCH_STATUS_SUCCESS: session->enc_write_frame.codec = session->write_codec; - session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); + session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels; + session->enc_write_frame.channels = session->write_impl.number_of_channels; if (frame->codec->implementation->samples_per_packet != session->write_impl.samples_per_packet) { session->enc_write_frame.timestamp = 0; } else { @@ -1446,7 +1456,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess break; case SWITCH_STATUS_NOOP: enc_frame->codec = session->write_codec; - enc_frame->samples = enc_frame->datalen / sizeof(int16_t); + enc_frame->samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels; + enc_frame->channels = session->write_impl.number_of_channels; enc_frame->timestamp = frame->timestamp; enc_frame->m = frame->m; enc_frame->seq = frame->seq; @@ -1534,7 +1545,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess case SWITCH_STATUS_RESAMPLE: resample++; session->enc_write_frame.codec = session->write_codec; - session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); + session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels; + session->enc_write_frame.channels = session->write_impl.number_of_channels; session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.payload = session->write_impl.ianacode; @@ -1567,7 +1579,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess break; case SWITCH_STATUS_SUCCESS: session->enc_write_frame.codec = session->write_codec; - session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); + session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels; + session->enc_write_frame.channels = session->write_impl.number_of_channels; session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.payload = session->write_impl.ianacode; @@ -1595,7 +1608,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess } enc_frame->codec = session->write_codec; - enc_frame->samples = enc_frame->datalen / sizeof(int16_t); + enc_frame->samples = enc_frame->datalen / sizeof(int16_t) / session->read_impl.number_of_channels; + enc_frame->channels = session->read_impl.number_of_channels; enc_frame->m = frame->m; enc_frame->ssrc = frame->ssrc; enc_frame->payload = enc_frame->codec->implementation->ianacode; @@ -1620,6 +1634,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess switch_resample_process(session->read_resampler, data, write_frame->datalen / 2 / session->read_resampler->channels); memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2 * session->read_resampler->channels); write_frame->samples = session->read_resampler->to_len; + write_frame->channels = session->read_resampler->channels; write_frame->datalen = session->read_resampler->to_len * 2 * session->read_resampler->channels; write_frame->rate = session->read_resampler->to_rate; } diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 2c4da7c4cd..0bbef216b4 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -577,7 +577,8 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se switch_sdp_type_t sdp_type, uint32_t pt, uint32_t rate, - uint32_t ptime, + uint32_t ptime, + uint32_t channels, uint8_t negotiated) { payload_map_t *pmap; @@ -628,6 +629,7 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se pmap->iananame = switch_core_strdup(session->pool, name); pmap->rm_encoding = pmap->iananame; pmap->hash = switch_ci_hashfunc_default(pmap->iananame, &hlen); + pmap->channels = 1; } pmap->sdp_type = sdp_type; @@ -640,6 +642,10 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se pmap->rate = rate; } + if (channels) { + pmap->channels = channels; + } + if (!zstr(fmtp) && (zstr(pmap->rm_fmtp) || strcmp(pmap->rm_fmtp, fmtp))) { pmap->rm_fmtp = switch_core_strdup(session->pool, fmtp); } @@ -2310,8 +2316,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_ switch_channel_set_variable(session->channel, "rtp_use_codec_fmtp", a_engine->cur_payload_map->rm_fmtp); switch_channel_set_variable_printf(session->channel, "rtp_use_codec_rate", "%d", a_engine->cur_payload_map->rm_rate); switch_channel_set_variable_printf(session->channel, "rtp_use_codec_ptime", "%d", a_engine->cur_payload_map->codec_ms); - switch_channel_set_variable_printf(session->channel, "rtp_last_audio_codec_string", "%s@%dh@%di", - a_engine->cur_payload_map->iananame, a_engine->cur_payload_map->rm_rate, a_engine->cur_payload_map->codec_ms); + switch_channel_set_variable_printf(session->channel, "rtp_use_codec_channels", "%d", a_engine->cur_payload_map->channels); + switch_channel_set_variable_printf(session->channel, "rtp_last_audio_codec_string", "%s@%dh@%di@%dc", + a_engine->cur_payload_map->iananame, a_engine->cur_payload_map->rm_rate, a_engine->cur_payload_map->codec_ms, a_engine->cur_payload_map->channels); switch_assert(a_engine->read_codec.implementation); switch_assert(a_engine->write_codec.implementation); @@ -2345,7 +2352,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_ a_engine->cur_payload_map->codec_ms, a_engine->read_impl.samples_per_packet, a_engine->read_impl.bits_per_second); a_engine->read_frame.codec = &a_engine->read_codec; - + a_engine->read_frame.channels = a_engine->read_impl.number_of_channels; a_engine->write_codec.agreed_pt = a_engine->cur_payload_map->agreed_pt; a_engine->read_codec.agreed_pt = a_engine->cur_payload_map->agreed_pt; @@ -3066,6 +3073,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s reneg = 0; } + if (switch_channel_test_flag(session->channel, CF_RECOVERING)) { + reneg = 0; + } + if (!reneg && smh->num_negotiated_codecs) { codec_array = smh->negotiated_codecs; total_codecs = smh->num_negotiated_codecs; @@ -3520,6 +3531,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s matches[j].map->rm_pt, matches[j].imp->samples_per_second, matches[j].imp->microseconds_per_packet / 1000, + matches[j].imp->number_of_channels, SWITCH_TRUE); mimp = matches[j].imp; mmap = matches[j].map; @@ -3789,6 +3801,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s matches[j].map->rm_pt, matches[j].imp->samples_per_second, matches[j].imp->microseconds_per_packet / 1000, + matches[j].imp->number_of_channels, SWITCH_TRUE); if (j == 0) { v_engine->cur_payload_map = pmap; @@ -6137,7 +6150,6 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess smh->ianacodes[i] = (switch_payload_t)smh->payload_space++; } } - switch_core_media_add_payload_map(session, imp->codec_type == SWITCH_CODEC_TYPE_AUDIO ? SWITCH_MEDIA_TYPE_AUDIO : SWITCH_MEDIA_TYPE_VIDEO, @@ -6147,6 +6159,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess smh->ianacodes[i], imp->samples_per_second, imp->microseconds_per_packet / 1000, + imp->number_of_channels, SWITCH_FALSE); } @@ -8125,7 +8138,7 @@ SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size_t buflen) { int codec_ms = ptime; - uint32_t map_bit_rate = 0; + uint32_t map_bit_rate = 0, map_channels = 1; char ptstr[20] = ""; char ratestr[20] = ""; char bitstr[20] = ""; @@ -8135,6 +8148,7 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt); } + map_channels = map->rm_params ? atoi(map->rm_params) : 1; map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt); if (!ptime && !strcasecmp(map->rm_encoding, "g723")) { @@ -8172,6 +8186,10 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate); } + if (map_channels > 1) { + switch_snprintf(bitstr, sizeof(bitstr), "@%dc", map_channels); + } + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr); } @@ -8257,6 +8275,7 @@ static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *sess map->rm_pt, map->rm_rate, ptime, + map->rm_params ? atoi(map->rm_params) : 1, SWITCH_FALSE); } } @@ -8355,6 +8374,7 @@ static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *sess } for (i = 0; i < num_codecs; i++) { const switch_codec_implementation_t *imp = codecs[i]; + int channels; if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO || imp->ianacode > 127 || already_did[imp->ianacode]) { continue; @@ -8381,11 +8401,12 @@ static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *sess } if (match) { + channels = map->rm_params ? atoi(map->rm_params) : 1; if (ptime > 0) { - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate, - ptime); + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di@%dc", imp->iananame, (unsigned int) map->rm_rate, + ptime, channels); } else { - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate); + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%dc", imp->iananame, (unsigned int) map->rm_rate, channels); } already_did[imp->ianacode] = 1; break; @@ -8611,6 +8632,10 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s a_engine->cur_payload_map->codec_ms = atoi(tmp); } + if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_channels"))) { + a_engine->cur_payload_map->channels = atoi(tmp); + } + if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_pt"))) { a_engine->cur_payload_map->pt = a_engine->cur_payload_map->agreed_pt = (switch_payload_t)atoi(tmp); } @@ -8618,8 +8643,8 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s if ((tmp = switch_channel_get_variable(session->channel, "rtp_audio_recv_pt"))) { a_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp); } - - switch_core_media_set_codec(session, 1, smh->mparams->codec_flags); + + switch_core_media_set_codec(session, 0, smh->mparams->codec_flags); a_engine->adv_sdp_ip = smh->mparams->extrtpip = (char *) ip; a_engine->adv_sdp_port = a_engine->local_sdp_port = (switch_port_t)atoi(port); diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index ea034e8e50..ff87e35ed6 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -761,7 +761,7 @@ static switch_bool_t write_displace_callback(switch_media_bug_t *bug, void *user len = rframe->samples; if (dh->mux) { - int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE / 2]; + int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE]; int16_t *fp = rframe->data; uint32_t x; @@ -775,13 +775,12 @@ static switch_bool_t write_displace_callback(switch_media_bug_t *bug, void *user } else { st = switch_core_file_read(&dh->fh, rframe->data, &len); if (len < rframe->samples) { - memset((char *)rframe->data + len * 2, 0, rframe->datalen - len * 2); + memset((char *)rframe->data + len * 2 * dh->fh.channels, 0, (rframe->datalen - len) * 2 * dh->fh.channels); } } rframe->datalen = rframe->samples * 2 * dh->fh.channels; - if (st != SWITCH_STATUS_SUCCESS || len == 0) { if (dh->loop) { uint32_t pos = 0; @@ -845,7 +844,7 @@ static switch_bool_t read_displace_callback(switch_media_bug_t *bug, void *user_ len = rframe->samples; if (dh->mux) { - int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE / 2]; + int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE]; int16_t *fp = rframe->data; uint32_t x; diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index bd49e877a0..f9bda289f2 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -2230,12 +2230,14 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs(const switch_codec_impleme } -SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit) +SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit, uint32_t *channels) { char *cur, *next = NULL, *name, *p; name = next = cur = buf; + *channels = 1; + for (;;) { if (!next) { break; @@ -2253,8 +2255,10 @@ SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uin *rate = atoi(cur); } else if (strchr(cur, 'b')) { *bit = atoi(cur); + } else if (strchr(cur, 'c')) { + *channels = atoi(cur); } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad syntax for codec string. Missing qualifier [h|k|i|b] for part [%s]!\n", cur); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad syntax for codec string. Missing qualifier [h|k|i|b|c] for part [%s]!\n", cur); } } cur = next; @@ -2273,15 +2277,15 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ for (x = 0; x < preflen; x++) { char *name, buf[256], jbuf[256]; - uint32_t interval = 0, rate = 0, bit = 0; + uint32_t interval = 0, rate = 0, bit = 0, channels = 1; switch_copy_string(buf, prefs[x], sizeof(buf)); - name = switch_parse_codec_buf(buf, &interval, &rate, &bit); + name = switch_parse_codec_buf(buf, &interval, &rate, &bit, &channels); for(j = 0; j < x; j++) { char *jname; - uint32_t jinterval = 0, jrate = 0, jbit = 0; - uint32_t ointerval = interval, orate = rate; + uint32_t jinterval = 0, jrate = 0, jbit = 0, jchannels = 1; + uint32_t ointerval = interval, orate = rate, ochannels = channels; if (ointerval == 0) { ointerval = switch_default_ptime(name, 0); @@ -2291,8 +2295,12 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ orate = switch_default_rate(name, 0); } + if (ochannels == 0) { + ochannels = 1; + } + switch_copy_string(jbuf, prefs[j], sizeof(jbuf)); - jname = switch_parse_codec_buf(jbuf, &jinterval, &jrate, &jbit); + jname = switch_parse_codec_buf(jbuf, &jinterval, &jrate, &jbit, &jchannels); if (jinterval == 0) { jinterval = switch_default_ptime(jname, 0); @@ -2302,7 +2310,11 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ jrate = switch_default_rate(jname, 0); } - if (!strcasecmp(name, jname) && ointerval == jinterval && orate == jrate) { + if (jchannels == 0) { + jchannels = 1; + } + + if (!strcasecmp(name, jname) && ointerval == jinterval && orate == jrate && ochannels == jchannels) { goto next_x; } } @@ -2320,7 +2332,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ (interval && (uint32_t) (imp->microseconds_per_packet / 1000) != interval)) { continue; } - + if (((!rate && crate != default_rate) || (rate && (uint32_t) imp->actual_samples_per_second != rate))) { continue; } @@ -2329,6 +2341,9 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ continue; } + if (channels && imp->number_of_channels != channels) { + continue; + } } @@ -2353,7 +2368,10 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_ if (bit && (uint32_t) imp->bits_per_second != bit) { continue; } - + + if (channels && imp->number_of_channels != channels) { + continue; + } } array[i++] = imp;