[asterisk-commits] dvossel: trunk r308582 - in /trunk: ./ apps/ bridges/ channels/ codecs/ codec...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Feb 22 17:04:55 CST 2011
Author: dvossel
Date: Tue Feb 22 17:04:49 2011
New Revision: 308582
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=308582
Log:
Media Project Phase2: SILK 8khz-24khz, SLINEAR 8khz-192khz, SPEEX 32khz, hd audio ConfBridge, and other stuff
-Functional changes
1. Dynamic global format list build by codecs defined in codecs.conf
2. SILK 8khz, 12khz, 16khz, and 24khz with custom attributes defined in codecs.conf
3. Negotiation of SILK attributes in chan_sip.
4. SPEEX 32khz with translation
5. SLINEAR 8khz, 12khz, 24khz, 32khz, 44.1khz, 48khz, 96khz, 192khz with translation
using codec_resample.c
6. Various changes to RTP code required to properly handle the dynamic format list
and formats with attributes.
7. ConfBridge now dynamically jumps to the best possible sample rate. This allows
for conferences to take advantage of HD audio (Which sounds awesome)
8. Audiohooks are no longer limited to 8khz audio, and most effects have been
updated to take advantage of this such as Volume, DENOISE, PITCH_SHIFT.
9. codec_resample now uses its own code rather than depending on libresample.
-Organizational changes
Global format list is moved from frame.c to format.c
Various format specific functions moved from frame.c to format.c
Added:
trunk/codecs/speex/
trunk/codecs/speex/arch.h (with props)
trunk/codecs/speex/fixed_generic.h (with props)
trunk/codecs/speex/resample.c (with props)
trunk/codecs/speex/resample_sse.h (with props)
trunk/codecs/speex/speex_resampler.h (with props)
trunk/codecs/speex/stack_alloc.h (with props)
trunk/formats/format_attr_silk.c (with props)
trunk/include/asterisk/silk.h (with props)
Modified:
trunk/CHANGES
trunk/apps/app_chanspy.c
trunk/apps/app_jack.c
trunk/apps/app_mixmonitor.c
trunk/bridges/bridge_multiplexed.c
trunk/bridges/bridge_softmix.c
trunk/channels/chan_gtalk.c
trunk/channels/chan_iax2.c
trunk/channels/chan_jingle.c
trunk/channels/chan_sip.c
trunk/channels/chan_skinny.c
trunk/channels/iax2.h
trunk/codecs/Makefile
trunk/codecs/codec_resample.c
trunk/codecs/codec_speex.c
trunk/configs/codecs.conf.sample
trunk/funcs/func_pitchshift.c
trunk/funcs/func_speex.c
trunk/funcs/func_volume.c
trunk/include/asterisk/_private.h
trunk/include/asterisk/audiohook.h
trunk/include/asterisk/format.h
trunk/include/asterisk/format_cap.h
trunk/include/asterisk/frame.h
trunk/include/asterisk/rtp_engine.h
trunk/include/asterisk/slinfactory.h
trunk/include/asterisk/time.h
trunk/include/asterisk/translate.h
trunk/main/asterisk.c
trunk/main/audiohook.c
trunk/main/bridging.c
trunk/main/channel.c
trunk/main/data.c
trunk/main/format.c
trunk/main/format_cap.c
trunk/main/format_pref.c
trunk/main/frame.c
trunk/main/rtp_engine.c
trunk/main/slinfactory.c
trunk/main/translate.c
trunk/res/res_mutestream.c
trunk/res/res_rtp_asterisk.c
Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Tue Feb 22 17:04:49 2011
@@ -39,6 +39,11 @@
--------------------------
* The filter option in cdr_adaptive_odbc now supports negating the argument,
thus allowing records which do NOT match the specified filter.
+
+CODECS
+--------------------------
+ * Ability to define custom SILK formats in codecs.conf.
+ * Addition of speex32 audio format with translation.
Dialplan Variables
------------------
Modified: trunk/apps/app_chanspy.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_chanspy.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/apps/app_chanspy.c (original)
+++ trunk/apps/app_chanspy.c Tue Feb 22 17:04:49 2011
@@ -541,15 +541,15 @@
memset(&csth, 0, sizeof(csth));
ast_copy_flags(&csth.spy_audiohook, flags, AST_FLAGS_ALL);
- ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");
+ ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy", 0);
if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook)) {
ast_audiohook_destroy(&csth.spy_audiohook);
return 0;
}
- ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
- ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy");
+ ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy", 0);
+ ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy", 0);
if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook)) {
ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
}
Modified: trunk/apps/app_jack.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_jack.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/apps/app_jack.c (original)
+++ trunk/apps/app_jack.c Tue Feb 22 17:04:49 2011
@@ -885,7 +885,7 @@
goto return_error;
jack_data->has_audiohook = 1;
- ast_audiohook_init(&jack_data->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "JACK_HOOK");
+ ast_audiohook_init(&jack_data->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "JACK_HOOK", 0);
jack_data->audiohook.manipulate_callback = jack_hook_callback;
datastore->data = jack_data;
Modified: trunk/apps/app_mixmonitor.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_mixmonitor.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/apps/app_mixmonitor.c (original)
+++ trunk/apps/app_mixmonitor.c Tue Feb 22 17:04:49 2011
@@ -426,7 +426,7 @@
}
/* Setup the actual spy before creating our thread */
- if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
+ if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type, 0)) {
mixmonitor_free(mixmonitor);
return;
}
Modified: trunk/bridges/bridge_multiplexed.c
URL: http://svnview.digium.com/svn/asterisk/trunk/bridges/bridge_multiplexed.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/bridges/bridge_multiplexed.c (original)
+++ trunk/bridges/bridge_multiplexed.c Tue Feb 22 17:04:49 2011
@@ -219,6 +219,9 @@
winner = ast_waitfor_nandfds(multiplexed_thread->chans, multiplexed_thread->service_count, &fds, 1, NULL, &outfd, &to);
multiplexed_thread->waiting = 0;
ao2_lock(multiplexed_thread);
+ if (multiplexed_thread->thread == AST_PTHREADT_STOP) {
+ break;
+ }
if (outfd > -1) {
int nudge;
@@ -230,7 +233,21 @@
}
}
if (winner && winner->bridge) {
- ast_bridge_handle_trip(winner->bridge, NULL, winner, -1);
+ struct ast_bridge *bridge = winner->bridge;
+ int stop = 0;
+ ao2_unlock(multiplexed_thread);
+ while ((bridge = winner->bridge) && ao2_trylock(bridge)) {
+ sched_yield();
+ if (multiplexed_thread->thread == AST_PTHREADT_STOP) {
+ stop = 1;
+ break;
+ }
+ }
+ if (!stop && bridge) {
+ ast_bridge_handle_trip(bridge, NULL, winner, -1);
+ ao2_unlock(bridge);
+ }
+ ao2_lock(multiplexed_thread);
}
}
Modified: trunk/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/trunk/bridges/bridge_softmix.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/bridges/bridge_softmix.c (original)
+++ trunk/bridges/bridge_softmix.c Tue Feb 22 17:04:49 2011
@@ -52,14 +52,16 @@
#include "asterisk/astobj2.h"
#include "asterisk/timing.h"
+#define MAX_DATALEN 3840
+
/*! \brief Interval at which mixing will take place. Valid options are 10, 20, and 40. */
#define SOFTMIX_INTERVAL 20
/*! \brief Size of the buffer used for sample manipulation */
-#define SOFTMIX_DATALEN (160 * (SOFTMIX_INTERVAL / 10))
+#define SOFTMIX_DATALEN(rate) ((rate/50) * (SOFTMIX_INTERVAL / 10))
/*! \brief Number of samples we are dealing with */
-#define SOFTMIX_SAMPLES (SOFTMIX_DATALEN / 2)
+#define SOFTMIX_SAMPLES(rate) (SOFTMIX_DATALEN(rate) / 2)
/*! \brief Define used to turn on 16 kHz audio support */
/* #define SOFTMIX_16_SUPPORT */
@@ -77,40 +79,74 @@
/*! Bit used to indicate that a frame is available to be written out to the channel */
int have_frame:1;
/*! Buffer containing final mixed audio from all sources */
- short final_buf[SOFTMIX_DATALEN];
+ short final_buf[MAX_DATALEN];
/*! Buffer containing only the audio from the channel */
- short our_buf[SOFTMIX_DATALEN];
+ short our_buf[MAX_DATALEN];
+};
+
+struct softmix_bridge_data {
+ struct ast_timer *timer;
+ unsigned int internal_rate;
};
/*! \brief Function called when a bridge is created */
static int softmix_bridge_create(struct ast_bridge *bridge)
{
- struct ast_timer *timer;
-
- if (!(timer = ast_timer_open())) {
+ struct softmix_bridge_data *bridge_data;
+
+ if (!(bridge_data = ast_calloc(1, sizeof(*bridge_data)))) {
return -1;
}
-
- bridge->bridge_pvt = timer;
-
+ if (!(bridge_data->timer = ast_timer_open())) {
+ ast_free(bridge_data);
+ return -1;
+ }
+
+ /* start at 8khz, let it grow from there */
+ bridge_data->internal_rate = 8000;
+
+ bridge->bridge_pvt = bridge_data;
return 0;
}
/*! \brief Function called when a bridge is destroyed */
static int softmix_bridge_destroy(struct ast_bridge *bridge)
{
+ struct softmix_bridge_data *bridge_data = bridge->bridge_pvt;
if (!bridge->bridge_pvt) {
return -1;
}
- ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
-
- return 0;
+ ast_timer_close(bridge_data->timer);
+ ast_free(bridge_data);
+ return 0;
+}
+
+static void set_softmix_bridge_data(int rate, struct ast_bridge_channel *bridge_channel, int reset)
+{
+ struct softmix_channel *sc = bridge_channel->bridge_pvt;
+ if (reset) {
+ ast_slinfactory_destroy(&sc->factory);
+ }
+ /* Setup frame parameters */
+ sc->frame.frametype = AST_FRAME_VOICE;
+
+ ast_format_set(&sc->frame.subclass.format, ast_format_slin_by_rate(rate), 0);
+ sc->frame.data.ptr = sc->final_buf;
+ sc->frame.datalen = SOFTMIX_DATALEN(rate);
+ sc->frame.samples = SOFTMIX_SAMPLES(rate);
+
+ /* Setup smoother */
+ ast_slinfactory_init_with_format(&sc->factory, &sc->frame.subclass.format);
+
+ ast_set_read_format(bridge_channel->chan, &sc->frame.subclass.format);
+ ast_set_write_format(bridge_channel->chan, &sc->frame.subclass.format);
}
/*! \brief Function called when a channel is joined into the bridge */
static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
{
struct softmix_channel *sc = NULL;
+ struct softmix_bridge_data *bridge_data = bridge->bridge_pvt;
/* Create a new softmix_channel structure and allocate various things on it */
if (!(sc = ast_calloc(1, sizeof(*sc)))) {
@@ -120,22 +156,10 @@
/* Can't forget the lock */
ast_mutex_init(&sc->lock);
- /* Setup smoother */
- ast_slinfactory_init(&sc->factory);
-
- /* Setup frame parameters */
- sc->frame.frametype = AST_FRAME_VOICE;
-#ifdef SOFTMIX_16_SUPPORT
- ast_format_set(&sc->frame.subclass.format, AST_FORMAT_SLINEAR16, 0);
-#else
- ast_format_set(&sc->frame.subclass.format, AST_FORMAT_SLINEAR, 0);
-#endif
- sc->frame.data.ptr = sc->final_buf;
- sc->frame.datalen = SOFTMIX_DATALEN;
- sc->frame.samples = SOFTMIX_SAMPLES;
-
/* Can't forget to record our pvt structure within the bridged channel structure */
bridge_channel->bridge_pvt = sc;
+
+ set_softmix_bridge_data(bridge_data->internal_rate, bridge_channel, 0);
return 0;
}
@@ -170,11 +194,7 @@
ast_mutex_lock(&sc->lock);
/* If a frame was provided add it to the smoother */
-#ifdef SOFTMIX_16_SUPPORT
- if (frame->frametype == AST_FRAME_VOICE && frame->subclass.format.id == AST_FORMAT_SLINEAR16) {
-#else
- if (frame->frametype == AST_FRAME_VOICE && frame->subclass.format.id == AST_FORMAT_SLINEAR) {
-#endif
+ if (frame->frametype == AST_FRAME_VOICE && ast_format_is_slinear(&frame->subclass.format)) {
ast_slinfactory_feed(&sc->factory, frame);
}
@@ -210,29 +230,54 @@
/*! \brief Function which acts as the mixing thread */
static int softmix_bridge_thread(struct ast_bridge *bridge)
{
- struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
+ struct {
+ /*! Each index represents a sample rate used above the internal rate. */
+ unsigned int sample_rates[8];
+ /*! Each index represents the number of channels using the same index in the sample_rates array. */
+ unsigned int num_channels[8];
+ /*! the number of channels above the internal sample rate */
+ unsigned int num_above_internal_rate;
+ /*! the number of channels at the internal sample rate */
+ unsigned int num_at_internal_rate;
+ /*! the absolute highest sample rate supported by any channel in the bridge */
+ unsigned int highest_supported_rate;
+ } stats;
+ struct softmix_bridge_data *bridge_data = bridge->bridge_pvt;
+ struct ast_timer *timer = bridge_data->timer;
int timingfd = ast_timer_fd(timer);
+ int update_all_rates = 0; /* set this when the internal sample rate has changed */
+ int i;
ast_timer_set_rate(timer, (1000 / SOFTMIX_INTERVAL));
while (!bridge->stop && !bridge->refresh && bridge->array_num) {
struct ast_bridge_channel *bridge_channel = NULL;
- short buf[SOFTMIX_DATALEN] = {0, };
+ short buf[MAX_DATALEN] = {0, };
int timeout = -1;
+
+ /* these variables help determine if a rate change is required */
+ memset(&stats, 0, sizeof(stats));
+ stats.highest_supported_rate = 8000;
/* Go through pulling audio from each factory that has it available */
AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
struct softmix_channel *sc = bridge_channel->bridge_pvt;
+ int channel_native_rate;
ast_mutex_lock(&sc->lock);
+ if (update_all_rates) {
+ set_softmix_bridge_data(bridge_data->internal_rate, bridge_channel, 1);
+ }
+
/* Try to get audio from the factory if available */
- if (ast_slinfactory_available(&sc->factory) >= SOFTMIX_SAMPLES && ast_slinfactory_read(&sc->factory, sc->our_buf, SOFTMIX_SAMPLES)) {
+ if (ast_slinfactory_available(&sc->factory) >= SOFTMIX_SAMPLES(bridge_data->internal_rate) &&
+ ast_slinfactory_read(&sc->factory, sc->our_buf, SOFTMIX_SAMPLES(bridge_data->internal_rate))) {
short *data1, *data2;
int i;
/* Put into the local final buffer */
- for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
+ for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN(bridge_data->internal_rate); i++, data1++, data2++)
ast_slinear_saturated_add(data1, data2);
/* Yay we have our own audio */
sc->have_audio = 1;
@@ -240,6 +285,30 @@
/* Awww we don't have audio ;( */
sc->have_audio = 0;
}
+
+ /* Gather stats about channel sample rates. */
+ channel_native_rate = MAX(ast_format_rate(&bridge_channel->chan->rawwriteformat),
+ ast_format_rate(&bridge_channel->chan->rawreadformat));
+
+ if (channel_native_rate > stats.highest_supported_rate) {
+ stats.highest_supported_rate = channel_native_rate;
+ }
+ if (channel_native_rate > bridge_data->internal_rate) {
+ for (i = 0; i < ARRAY_LEN(stats.sample_rates); i++) {
+ if (stats.sample_rates[i] == channel_native_rate) {
+ stats.num_channels[i]++;
+ break;
+ } else if (!stats.sample_rates[i]) {
+ stats.sample_rates[i] = channel_native_rate;
+ stats.num_channels[i]++;
+ break;
+ }
+ }
+ stats.num_above_internal_rate++;
+ } else if (channel_native_rate == bridge_data->internal_rate) {
+ stats.num_at_internal_rate++;
+ }
+
ast_mutex_unlock(&sc->lock);
}
@@ -253,7 +322,7 @@
/* If we provided audio then take it out */
if (sc->have_audio) {
- for (i = 0; i < SOFTMIX_DATALEN; i++) {
+ for (i = 0; i < SOFTMIX_DATALEN(bridge_data->internal_rate); i++) {
ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
}
}
@@ -263,6 +332,44 @@
/* Poke bridged channel thread just in case */
pthread_kill(bridge_channel->thread, SIGURG);
+ }
+
+ /* Re-adjust the internal bridge sample rate if
+ * 1. two or more channels support a higher sample rate
+ * 2. no channels support the current sample rate or a higher rate
+ */
+ if (stats.num_above_internal_rate >= 2) {
+ /* the highest rate is just used as a starting point */
+ unsigned int best_rate = stats.highest_supported_rate;
+ int best_index = -1;
+
+ /* 1. pick the best sample rate two or more channels support
+ * 2. if two or more channels do not support the same rate, pick the
+ * lowest sample rate that is still above the internal rate. */
+ for (i = 0; ((i < ARRAY_LEN(stats.num_channels)) && stats.num_channels[i]); i++) {
+ if ((stats.num_channels[i] >= 2 && (best_index == -1)) ||
+ ((best_index != -1) &&
+ (stats.num_channels[i] >= 2) &&
+ (stats.sample_rates[best_index] < stats.sample_rates[i]))) {
+
+ best_rate = stats.sample_rates[i];
+ best_index = i;
+ } else if (best_index == -1) {
+ best_rate = MIN(best_rate, stats.sample_rates[i]);
+ }
+ }
+
+ ast_debug(1, " Bridge changed from %d To %d\n", bridge_data->internal_rate, best_rate);
+ bridge_data->internal_rate = best_rate;
+ update_all_rates = 1;
+ } else if (!stats.num_at_internal_rate && !stats.num_above_internal_rate) {
+ update_all_rates = 1;
+ /* in this case, the highest supported rate is actually lower than the internal rate */
+ bridge_data->internal_rate = stats.highest_supported_rate;
+ ast_debug(1, " Bridge changed from %d to %d\n", bridge_data->internal_rate, stats.highest_supported_rate);
+ update_all_rates = 1;
+ } else {
+ update_all_rates = 0;
}
ao2_unlock(bridge);
Modified: trunk/channels/chan_gtalk.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_gtalk.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/channels/chan_gtalk.c (original)
+++ trunk/channels/chan_gtalk.c Tue Feb 22 17:04:49 2011
@@ -285,7 +285,7 @@
static int add_codec_to_answer(const struct gtalk_pvt *p, struct ast_format *codec, iks *dcodecs)
{
int res = 0;
- char *format = ast_getformatname(codec);
+ const char *format = ast_getformatname(codec);
if (!strcasecmp("ulaw", format)) {
iks *payload_eg711u, *payload_pcmu;
Modified: trunk/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_iax2.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/channels/chan_iax2.c (original)
+++ trunk/channels/chan_iax2.c Tue Feb 22 17:04:49 2011
@@ -1668,7 +1668,7 @@
return ast_format_to_old_bitfield(&tmpfmt);
}
-char *iax2_getformatname(iax2_format format)
+const char *iax2_getformatname(iax2_format format)
{
struct ast_format tmpfmt;
if (!(ast_format_from_old_bitfield(&tmpfmt, format))) {
Modified: trunk/channels/chan_jingle.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_jingle.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/channels/chan_jingle.c (original)
+++ trunk/channels/chan_jingle.c Tue Feb 22 17:04:49 2011
@@ -257,7 +257,7 @@
static void add_codec_to_answer(const struct jingle_pvt *p, struct ast_format *codec, iks *dcodecs)
{
- char *format = ast_getformatname(codec);
+ const char *format = ast_getformatname(codec);
if (!strcasecmp("ulaw", format)) {
iks *payload_eg711u, *payload_pcmu;
Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Tue Feb 22 17:04:49 2011
@@ -8885,11 +8885,10 @@
}
ast_debug(4, "We have an owner, now see if we need to change this call\n");
-
- if (!(ast_format_cap_has_joint(p->owner->nativeformats, p->jointcaps)) && ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO)) {
+ if (ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO)) {
if (debug) {
char s1[SIPBUFSIZE], s2[SIPBUFSIZE];
- ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n",
+ ast_debug(1, "Setting native formats after processing SDP. peer joint formats %s, old nativeformats %s\n",
ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcaps),
ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats));
}
@@ -9109,13 +9108,12 @@
ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
}
} else if (sscanf(a, "fmtp: %30u %63s", &codec, fmtp_string) == 2) {
- struct ast_rtp_payload_type payload;
-
- payload = ast_rtp_codecs_payload_lookup(newaudiortp, codec);
- if (payload.format.id && payload.asterisk_format) {
+ struct ast_format *format;
+
+ if ((format = ast_rtp_codecs_get_payload_format(newaudiortp, codec))) {
unsigned int bit_rate;
- switch ((int) payload.format.id) {
+ switch ((int) format->id) {
case AST_FORMAT_SIREN7:
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 32000) {
@@ -9145,6 +9143,21 @@
found = TRUE;
}
}
+ break;
+ case AST_FORMAT_SILK:
+ {
+ int val = 0;
+ if (sscanf(fmtp_string, "maxaveragebitrate=%30u", &val) == 1) {
+ ast_format_append(format, SILK_ATTR_KEY_MAX_BITRATE, val, AST_FORMAT_ATTR_END);
+ }
+ if (sscanf(fmtp_string, "usedtx=%30u", &val) == 1) {
+ ast_format_append(format, SILK_ATTR_KEY_DTX, val ? 1 : 0, AST_FORMAT_ATTR_END);
+ }
+ if (sscanf(fmtp_string, "useinbandfec=%30u", &val) == 1) {
+ ast_format_append(format, SILK_ATTR_KEY_FEC, val ? 1 : 0, AST_FORMAT_ATTR_END);
+ }
+ break;
+ }
}
}
}
@@ -10505,6 +10518,20 @@
/* Indicate that we only expect 64Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code);
break;
+ case AST_FORMAT_SILK:
+ {
+ int val = 0;
+ if (!ast_format_get_value(format, SILK_ATTR_KEY_MAX_BITRATE, &val) && val > 5000 && val < 40000) {
+ ast_str_append(a_buf, 0, "a=fmtp:%d maxaveragebitrate=%u\r\n", rtp_code, val);
+ }
+ if (!ast_format_get_value(format, SILK_ATTR_KEY_DTX, &val)) {
+ ast_str_append(a_buf, 0, "a=fmtp:%d usedtx=%u\r\n", rtp_code, val ? 1 : 0);
+ }
+ if (!ast_format_get_value(format, SILK_ATTR_KEY_FEC, &val)) {
+ ast_str_append(a_buf, 0, "a=fmtp:%d useinbandfec=%u\r\n", rtp_code, val ? 1 : 0);
+ }
+ break;
+ }
}
if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size))
Modified: trunk/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_skinny.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/channels/chan_skinny.c (original)
+++ trunk/channels/chan_skinny.c Tue Feb 22 17:04:49 2011
@@ -1796,7 +1796,7 @@
}
}
-static int codec_ast2skinny(struct ast_format *astcodec)
+static int codec_ast2skinny(const struct ast_format *astcodec)
{
switch (astcodec->id) {
case AST_FORMAT_ALAW:
@@ -2289,7 +2289,7 @@
req->data.openreceivechannel.conferenceId = htolel(sub->callid);
req->data.openreceivechannel.partyId = htolel(sub->callid);
req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
- req->data.openreceivechannel.capability = htolel(codec_ast2skinny(ast_format_set(&tmpfmt, fmt.id, 0)));
+ req->data.openreceivechannel.capability = htolel(codec_ast2skinny(&fmt.format));
req->data.openreceivechannel.echo = htolel(0);
req->data.openreceivechannel.bitrate = htolel(0);
transmit_response(d, req);
@@ -2494,7 +2494,6 @@
static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, struct ast_format_list fmt)
{
struct skinny_req *req;
- struct ast_format tmpfmt;
if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
return;
@@ -2504,7 +2503,7 @@
req->data.startmedia.remoteIp = dest.sin_addr.s_addr;
req->data.startmedia.remotePort = htolel(ntohs(dest.sin_port));
req->data.startmedia.packetSize = htolel(fmt.cur_ms);
- req->data.startmedia.payloadType = htolel(codec_ast2skinny(ast_format_set(&tmpfmt, fmt.id, 0)));
+ req->data.startmedia.payloadType = htolel(codec_ast2skinny(&fmt.format));
req->data.startmedia.qualifier.precedence = htolel(127);
req->data.startmedia.qualifier.vad = htolel(0);
req->data.startmedia.qualifier.packets = htolel(0);
@@ -2986,7 +2985,7 @@
fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
if (skinnydebug)
- ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(ast_format_set(&tmpfmt, fmt.id, 0)), fmt.cur_ms);
+ ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);
if (!(l->directmedia) || (l->nat)){
ast_rtp_instance_get_local_address(rtp, &us_tmp);
@@ -5760,7 +5759,7 @@
fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
if (skinnydebug)
- ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(ast_format_set(&tmpfmt, fmt.id, 0)), fmt.cur_ms);
+ ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);
transmit_startmediatransmission(d, sub, us, fmt);
Modified: trunk/channels/iax2.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/iax2.h?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/channels/iax2.h (original)
+++ trunk/channels/iax2.h Tue Feb 22 17:04:49 2011
@@ -218,7 +218,7 @@
typedef int64_t iax2_format;
/*!\brief iax2 wrapper function for ast_getformatname */
-char *iax2_getformatname(iax2_format format);
+const char *iax2_getformatname(iax2_format format);
/*! Full frames are always delivered reliably */
struct ast_iax2_full_hdr {
Modified: trunk/codecs/Makefile
URL: http://svnview.digium.com/svn/asterisk/trunk/codecs/Makefile?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/codecs/Makefile (original)
+++ trunk/codecs/Makefile Tue Feb 22 17:04:49 2011
@@ -29,11 +29,13 @@
$(if $(filter codec_gsm,$(EMBEDDED_MODS)),modules.link,codec_gsm.so): gsm/lib/libgsm.a
endif
+
clean::
$(MAKE) -C gsm clean
$(MAKE) -C lpc10 clean
$(MAKE) -C ilbc clean
rm -f g722/*.[oa]
+ rm -f speex/*.[oa]
gsm/lib/libgsm.a:
@mkdir -p gsm/lib
@@ -47,7 +49,17 @@
$(LIBILBC):
@$(MAKE) -C ilbc all _ASTCFLAGS="$(filter-out -Wmissing-prototypes -Wmissing-declarations -Wshadow,$(_ASTCFLAGS)) $(AST_NO_STRICT_OVERFLOW)"
+
$(if $(filter codec_ilbc,$(EMBEDDED_MODS)),modules.link,codec_ilbc.so): $(LIBILBC)
$(if $(filter codec_g722,$(EMBEDDED_MODS)),modules.link,codec_g722.so): g722/g722_encode.o g722/g722_decode.o
g722/g722_encode.o g722/g722_decode.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,codec_g722)
+
+ifeq ($(BUILD_CPU),x86_64)
+SPEEX_RESAMPLE_CFLAGS:=-fPIC
+else
+SPEEX_RESAMPLE_CFLAGS:=
+endif
+
+$(if $(filter codec_resample,$(EMBEDDED_MODS)),modules.link,codec_resample.so): speex/resample.o
+speex/resample.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,codec_resample) $(SPEEX_RESAMPLE_CFLAGS)
Modified: trunk/codecs/codec_resample.c
URL: http://svnview.digium.com/svn/asterisk/trunk/codecs/codec_resample.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/codecs/codec_resample.c (original)
+++ trunk/codecs/codec_resample.c Tue Feb 22 17:04:49 2011
@@ -1,9 +1,10 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2007, Digium, Inc.
+ * Copyright (C) 2011, Digium, Inc.
*
* Russell Bryant <russell at digium.com>
+ * David Vossel <dvossel at digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -21,9 +22,6 @@
*
* \brief Resample slinear audio
*
- * \note To install libresample, check it out of the following repository:
- * <code>$ svn co http://svn.digium.com/svn/thirdparty/libresample/trunk</code>
- *
* \ingroup codecs
*/
@@ -32,170 +30,75 @@
***/
#include "asterisk.h"
+#include "speex/speex_resampler.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-/* These are for SHRT_MAX and FLT_MAX -- { */
-#if defined(__Darwin__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
-#include <float.h>
-#else
-#include <values.h>
-#endif
-#include <limits.h>
-/* } */
-
-#include <libresample.h>
-
#include "asterisk/module.h"
#include "asterisk/translate.h"
-
#include "asterisk/slin.h"
-
-#define RESAMPLER_QUALITY 1
#define OUTBUF_SIZE 8096
-struct slin16_to_slin8_pvt {
- void *resampler;
- float resample_factor;
+static struct ast_translator *translators;
+static int trans_size;
+static int id_list[] = {
+ AST_FORMAT_SLINEAR,
+ AST_FORMAT_SLINEAR12,
+ AST_FORMAT_SLINEAR16,
+ AST_FORMAT_SLINEAR24,
+ AST_FORMAT_SLINEAR32,
+ AST_FORMAT_SLINEAR44,
+ AST_FORMAT_SLINEAR48,
+ AST_FORMAT_SLINEAR96,
+ AST_FORMAT_SLINEAR192,
};
-struct slin8_to_slin16_pvt {
- void *resampler;
- float resample_factor;
-};
+static int resamp_new(struct ast_trans_pvt *pvt)
+{
+ int err;
-static int slin16_to_slin8_new(struct ast_trans_pvt *pvt)
-{
- struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
-
- resamp_pvt->resample_factor = 8000.0 / 16000.0;
-
- if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, resamp_pvt->resample_factor, resamp_pvt->resample_factor)))
+ if (!(pvt->pvt = speex_resampler_init(1, ast_format_rate(&pvt->t->src_format), ast_format_rate(&pvt->t->dst_format), 5, &err))) {
return -1;
+ }
return 0;
}
-static int slin8_to_slin16_new(struct ast_trans_pvt *pvt)
+static void resamp_destroy(struct ast_trans_pvt *pvt)
{
- struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
+ SpeexResamplerState *resamp_pvt = pvt->pvt;
+ speex_resampler_destroy(resamp_pvt);
+}
- resamp_pvt->resample_factor = 16000.0 / 8000.0;
+static int resamp_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+ SpeexResamplerState *resamp_pvt = pvt->pvt;
+ unsigned int out_samples = (OUTBUF_SIZE / sizeof(int16_t)) - pvt->samples;
+ unsigned int in_samples = f->samples;
- if (!(resamp_pvt->resampler = resample_open(RESAMPLER_QUALITY, resamp_pvt->resample_factor, resamp_pvt->resample_factor)))
- return -1;
+ speex_resampler_process_int(resamp_pvt,
+ 0,
+ f->data.ptr,
+ &in_samples,
+ pvt->outbuf.i16 + pvt->samples,
+ &out_samples);
+
+ pvt->samples += out_samples;
+ pvt->datalen += out_samples * 2;
return 0;
}
-static void slin16_to_slin8_destroy(struct ast_trans_pvt *pvt)
-{
- struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
-
- if (resamp_pvt->resampler)
- resample_close(resamp_pvt->resampler);
-}
-
-static void slin8_to_slin16_destroy(struct ast_trans_pvt *pvt)
-{
- struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
-
- if (resamp_pvt->resampler)
- resample_close(resamp_pvt->resampler);
-}
-
-static int resample_frame(struct ast_trans_pvt *pvt,
- void *resampler, float resample_factor, struct ast_frame *f)
-{
- int total_in_buf_used = 0;
- int total_out_buf_used = 0;
- int16_t *in_buf = (int16_t *) f->data.ptr;
- int16_t *out_buf = pvt->outbuf.i16 + pvt->samples;
- float in_buf_f[f->samples];
- float out_buf_f[2048];
- int res = 0;
- int i;
-
- for (i = 0; i < f->samples; i++)
- in_buf_f[i] = in_buf[i] * (FLT_MAX / SHRT_MAX);
-
- while (total_in_buf_used < f->samples) {
- int in_buf_used, out_buf_used;
-
- out_buf_used = resample_process(resampler, resample_factor,
- &in_buf_f[total_in_buf_used], f->samples - total_in_buf_used,
- 0, &in_buf_used,
- &out_buf_f[total_out_buf_used], ARRAY_LEN(out_buf_f) - total_out_buf_used);
-
- if (out_buf_used < 0)
- break;
-
- total_out_buf_used += out_buf_used;
- total_in_buf_used += in_buf_used;
-
- if (total_out_buf_used == ARRAY_LEN(out_buf_f)) {
- ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
- res = -1;
- break;
- }
- }
-
- for (i = 0; i < total_out_buf_used; i++)
- out_buf[i] = out_buf_f[i] * (SHRT_MAX / FLT_MAX);
-
- pvt->samples += total_out_buf_used;
- pvt->datalen += (total_out_buf_used * sizeof(int16_t));
-
- return res;
-}
-
-static int slin16_to_slin8_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
-{
- struct slin16_to_slin8_pvt *resamp_pvt = pvt->pvt;
- void *resampler = resamp_pvt->resampler;
- float resample_factor = resamp_pvt->resample_factor;
-
- return resample_frame(pvt, resampler, resample_factor, f);
-}
-
-static int slin8_to_slin16_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
-{
- struct slin8_to_slin16_pvt *resamp_pvt = pvt->pvt;
- void *resampler = resamp_pvt->resampler;
- float resample_factor = resamp_pvt->resample_factor;
-
- return resample_frame(pvt, resampler, resample_factor, f);
-}
-
-static struct ast_translator slin16_to_slin8 = {
- .name = "slin16_to_slin8",
- .newpvt = slin16_to_slin8_new,
- .destroy = slin16_to_slin8_destroy,
- .framein = slin16_to_slin8_framein,
- .sample = slin16_sample,
- .desc_size = sizeof(struct slin16_to_slin8_pvt),
- .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
- .buf_size = OUTBUF_SIZE,
-};
-
-static struct ast_translator slin8_to_slin16 = {
- .name = "slin8_to_slin16",
- .newpvt = slin8_to_slin16_new,
- .destroy = slin8_to_slin16_destroy,
- .framein = slin8_to_slin16_framein,
- .sample = slin8_sample,
- .desc_size = sizeof(struct slin8_to_slin16_pvt),
- .buffer_samples = (OUTBUF_SIZE / sizeof(int16_t)),
- .buf_size = OUTBUF_SIZE,
-};
-
static int unload_module(void)
{
int res = 0;
+ int idx;
- res |= ast_unregister_translator(&slin16_to_slin8);
- res |= ast_unregister_translator(&slin8_to_slin16);
+ for (idx = 0; idx < trans_size; idx++) {
+ res |= ast_unregister_translator(&translators[idx]);
+ }
+ ast_free(translators);
return res;
}
@@ -203,15 +106,33 @@
static int load_module(void)
{
int res = 0;
+ int x, y, idx = 0;
- ast_format_set(&slin16_to_slin8.src_format, AST_FORMAT_SLINEAR16, 0);
- ast_format_set(&slin16_to_slin8.dst_format, AST_FORMAT_SLINEAR, 0);
+ trans_size = ARRAY_LEN(id_list) * ARRAY_LEN(id_list);
+ if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
- ast_format_set(&slin8_to_slin16.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&slin8_to_slin16.dst_format, AST_FORMAT_SLINEAR16, 0);
+ for (x = 0; x < ARRAY_LEN(id_list); x++) {
+ for (y = 0; y < ARRAY_LEN(id_list); y++) {
+ if (x == y) {
+ continue;
+ }
+ translators[idx].newpvt = resamp_new;
+ translators[idx].destroy = resamp_destroy;
+ translators[idx].framein = resamp_framein;
+ translators[idx].desc_size = 0;
+ translators[idx].buffer_samples = (OUTBUF_SIZE / sizeof(int16_t));
+ translators[idx].buf_size = OUTBUF_SIZE;
+ ast_format_set(&translators[idx].src_format, id_list[x], 0);
+ ast_format_set(&translators[idx].dst_format, id_list[y], 0);
+ snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %dkhz -> %dkhz",
+ ast_format_rate(&translators[idx].src_format), ast_format_rate(&translators[idx].dst_format));
+ res |= ast_register_translator(&translators[idx]);
+ idx++;
+ }
- res |= ast_register_translator(&slin16_to_slin8);
- res |= ast_register_translator(&slin8_to_slin16);
+ }
return AST_MODULE_LOAD_SUCCESS;
}
Modified: trunk/codecs/codec_speex.c
URL: http://svnview.digium.com/svn/asterisk/trunk/codecs/codec_speex.c?view=diff&rev=308582&r1=308581&r2=308582
==============================================================================
--- trunk/codecs/codec_speex.c (original)
+++ trunk/codecs/codec_speex.c Tue Feb 22 17:04:49 2011
@@ -148,6 +148,11 @@
return speex_encoder_construct(pvt, &speex_wb_mode, 16000);
}
+static int lin32tospeexuwb_new(struct ast_trans_pvt *pvt)
+{
+ return speex_encoder_construct(pvt, &speex_uwb_mode, 32000);
+}
+
static int speex_decoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile)
{
struct speex_coder_pvt *tmp = pvt->pvt;
@@ -171,6 +176,11 @@
static int speexwbtolin16_new(struct ast_trans_pvt *pvt)
{
return speex_decoder_construct(pvt, &speex_wb_mode);
+}
+
+static int speexuwbtolin32_new(struct ast_trans_pvt *pvt)
+{
+ return speex_decoder_construct(pvt, &speex_uwb_mode);
}
/*! \brief convert and store into outbuf */
@@ -371,6 +381,28 @@
.frameout = lintospeex_frameout,
.destroy = lintospeex_destroy,
.sample = slin16_sample,
+ .desc_size = sizeof(struct speex_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
+};
+
+static struct ast_translator speexuwbtolin32 = {
+ .name = "speexuwbtolin32",
+ .newpvt = speexuwbtolin32_new,
+ .framein = speextolin_framein,
+ .destroy = speextolin_destroy,
+ .desc_size = sizeof(struct speex_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+ .native_plc = 1,
+};
+
+static struct ast_translator lin32tospeexuwb = {
+ .name = "lin32tospeexuwb",
+ .newpvt = lin32tospeexuwb_new,
+ .framein = lintospeex_framein,
+ .frameout = lintospeex_frameout,
+ .destroy = lintospeex_destroy,
.desc_size = sizeof(struct speex_coder_pvt),
.buffer_samples = BUFFER_SAMPLES,
.buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
@@ -486,6 +518,9 @@
res |= ast_unregister_translator(&lintospeex);
res |= ast_unregister_translator(&speexwbtolin16);
res |= ast_unregister_translator(&lin16tospeexwb);
+ res |= ast_unregister_translator(&speexuwbtolin32);
+ res |= ast_unregister_translator(&lin32tospeexuwb);
+
return res;
}
@@ -509,11 +544,20 @@
ast_format_set(&lin16tospeexwb.src_format, AST_FORMAT_SLINEAR16, 0);
ast_format_set(&lin16tospeexwb.dst_format, AST_FORMAT_SPEEX16, 0);
+
+ ast_format_set(&speexuwbtolin32.src_format, AST_FORMAT_SPEEX32, 0);
+ ast_format_set(&speexuwbtolin32.dst_format, AST_FORMAT_SLINEAR32, 0);
+
+ ast_format_set(&lin32tospeexuwb.src_format, AST_FORMAT_SLINEAR32, 0);
+ ast_format_set(&lin32tospeexuwb.dst_format, AST_FORMAT_SPEEX32, 0);
res |= ast_register_translator(&speextolin);
res |= ast_register_translator(&lintospeex);
res |= ast_register_translator(&speexwbtolin16);
res |= ast_register_translator(&lin16tospeexwb);
+ res |= ast_register_translator(&speexuwbtolin32);
+ res |= ast_register_translator(&lin32tospeexuwb);
+
return res;
}
Added: trunk/codecs/speex/arch.h
URL: http://svnview.digium.com/svn/asterisk/trunk/codecs/speex/arch.h?view=auto&rev=308582
==============================================================================
--- trunk/codecs/speex/arch.h (added)
+++ trunk/codecs/speex/arch.h Tue Feb 22 17:04:49 2011
@@ -1,0 +1,241 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+ @file arch.h
+ @brief Various architecture definitions Speex
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
[... 6399 lines stripped ...]
More information about the asterisk-commits
mailing list