]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
stereo refactoring
authorAnthony Minessale <anthm@freeswitch.org>
Fri, 13 Jun 2014 05:49:10 +0000 (01:49 -0400)
committerAnthony Minessale <anthm@freeswitch.org>
Fri, 13 Jun 2014 05:49:16 +0000 (01:49 -0400)
src/include/switch_core_media.h
src/include/switch_frame.h
src/include/switch_loadable_module.h
src/mod/codecs/mod_opus/mod_opus.c
src/mod/endpoints/mod_loopback/mod_loopback.c
src/mod/endpoints/mod_verto/mod_verto.c
src/switch_core_io.c
src/switch_core_media.c
src/switch_ivr_async.c
src/switch_loadable_module.c

index 312937756e03aaf092f3804cd59952e8a240b9ce..0de6a288597d3e9b1cf3cab33b344f4d36380040 100644 (file)
@@ -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);
 
 
index bbbca0917be6754d24b2510afa80e6d69a8f5a2b..51800df6c137afa41016817974eaecc86cdf4c70 100644 (file)
@@ -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 */
index ef27e75758afd1b78ec4a7e1fc73d9f6aaa689d3..644887a931910869d50b71256f8882664e8da01e 100644 (file)
@@ -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
index af10ca337111164de7f67e5508a4223411ee99bc..62ab8dbcbca3be7d30340cc2278bc652f8c4ab7a 100644 (file)
@@ -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;
index 8c0dd8c92eb0249900f286b96f021ded5df17ce6..b0cde67f07d2bd236de23650ad3c5c53aac01de4 100644 (file)
@@ -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);
                }
                
        }
index 7d30e7dc8492257b787616daacddf7656fd18ca8..748c98067c6c966a1d34871d2537655319f08846 100644 (file)
@@ -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);
index 430993df1f8f19311af27b575c518aabe39ef4a2..bb99c3eb397dc168e0ec6f99e9318948f41f01b9 100644 (file)
@@ -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;
                                        }
index 2c4da7c4cd639e410ebcd0df63a3e06ed634c3ae..0bbef216b428c72a47d81eddf1a21ef0527be637 100644 (file)
@@ -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);
index ea034e8e508aebf283b96a9a98a32e00f28c1220..ff87e35ed69ee0e8ab910bb137221435f843ab07 100644 (file)
@@ -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;
 
index bd49e877a00cd3eee4fe8f4d533a89cbcb6a6cb6..f9bda289f2ccdefff6bc924232ff4ea019d0b8fa 100644 (file)
@@ -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;