diff options
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_alsa.c | 27 | ||||
-rw-r--r-- | channels/chan_bridge_media.c | 14 | ||||
-rw-r--r-- | channels/chan_console.c | 35 | ||||
-rw-r--r-- | channels/chan_dahdi.c | 129 | ||||
-rw-r--r-- | channels/chan_iax2.c | 505 | ||||
-rw-r--r-- | channels/chan_mgcp.c | 378 | ||||
-rw-r--r-- | channels/chan_misdn.c | 55 | ||||
-rw-r--r-- | channels/chan_motif.c | 185 | ||||
-rw-r--r-- | channels/chan_multicast_rtp.c | 36 | ||||
-rw-r--r-- | channels/chan_nbs.c | 56 | ||||
-rw-r--r-- | channels/chan_oss.c | 23 | ||||
-rw-r--r-- | channels/chan_phone.c | 208 | ||||
-rw-r--r-- | channels/chan_pjsip.c | 83 | ||||
-rw-r--r-- | channels/chan_sip.c | 791 | ||||
-rw-r--r-- | channels/chan_skinny.c | 362 | ||||
-rw-r--r-- | channels/chan_unistim.c | 165 | ||||
-rw-r--r-- | channels/chan_vpb.cc | 97 | ||||
-rw-r--r-- | channels/dahdi/bridge_native_dahdi.c | 13 | ||||
-rw-r--r-- | channels/iax2/codec_pref.c | 333 | ||||
-rw-r--r-- | channels/iax2/format_compatibility.c | 73 | ||||
-rw-r--r-- | channels/iax2/include/codec_pref.h | 123 | ||||
-rw-r--r-- | channels/iax2/include/format_compatibility.h | 55 | ||||
-rw-r--r-- | channels/iax2/parser.c | 15 | ||||
-rw-r--r-- | channels/iax2/provision.c | 9 | ||||
-rw-r--r-- | channels/pjsip/dialplan_functions.c | 46 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 2 |
26 files changed, 2319 insertions, 1499 deletions
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index 9d43ba139..f74e78fd6 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -63,6 +63,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/musiconhold.h" #include "asterisk/poll-compat.h" #include "asterisk/stasis_channels.h" +#include "asterisk/format_cache.h" /*! Global jitterbuffer configuration - by default, jb is disabled * \note Values shown here match the defaults shown in alsa.conf.sample */ @@ -511,7 +512,7 @@ static struct ast_frame *alsa_read(struct ast_channel *chan) } f.frametype = AST_FRAME_VOICE; - ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0); + f.subclass.format = ast_format_slin; f.samples = FRAME_SIZE; f.datalen = FRAME_SIZE * 2; f.data.ptr = buf; @@ -585,9 +586,9 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const st ast_channel_tech_set(tmp, &alsa_tech); ast_channel_set_fd(tmp, 0, readdev); - ast_format_set(ast_channel_readformat(tmp), AST_FORMAT_SLINEAR, 0); - ast_format_set(ast_channel_writeformat(tmp), AST_FORMAT_SLINEAR, 0); - ast_format_cap_add(ast_channel_nativeformats(tmp), ast_channel_writeformat(tmp)); + ast_channel_set_readformat(tmp, ast_format_slin); + ast_channel_set_writeformat(tmp, ast_format_slin); + ast_channel_nativeformats_set(tmp, alsa_tech.capabilities); ast_channel_tech_pvt_set(tmp, p); if (!ast_strlen_zero(p->context)) @@ -616,14 +617,11 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const st static struct ast_channel *alsa_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause) { - struct ast_format tmpfmt; - char buf[256]; struct ast_channel *tmp = NULL; - ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0); - - if (!(ast_format_cap_iscompatible(cap, &tmpfmt))) { - ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); + if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *codec_buf = ast_str_alloca(64); + ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_format_cap_get_names(cap, &codec_buf)); return NULL; } @@ -959,12 +957,11 @@ static int load_module(void) struct ast_config *cfg; struct ast_variable *v; struct ast_flags config_flags = { 0 }; - struct ast_format tmpfmt; - if (!(alsa_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(alsa_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add(alsa_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_format_cap_append(alsa_tech.capabilities, ast_format_slin, 0); /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); @@ -1042,7 +1039,9 @@ static int unload_module(void) if (alsa.owner) return -1; - alsa_tech.capabilities = ast_format_cap_destroy(alsa_tech.capabilities); + ao2_cleanup(alsa_tech.capabilities); + alsa_tech.capabilities = NULL; + return 0; } diff --git a/channels/chan_bridge_media.c b/channels/chan_bridge_media.c index ac15e7d70..6502b5c77 100644 --- a/channels/chan_bridge_media.c +++ b/channels/chan_bridge_media.c @@ -164,11 +164,13 @@ static struct ast_channel *record_request(const char *type, struct ast_format_ca static void cleanup_capabilities(void) { if (announce_tech.capabilities) { - announce_tech.capabilities = ast_format_cap_destroy(announce_tech.capabilities); + ao2_ref(announce_tech.capabilities, -1); + announce_tech.capabilities = NULL; } if (record_tech.capabilities) { - record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities); + ao2_ref(record_tech.capabilities, -1); + record_tech.capabilities = NULL; } } @@ -182,18 +184,18 @@ static int unload_module(void) static int load_module(void) { - announce_tech.capabilities = ast_format_cap_alloc(0); + announce_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!announce_tech.capabilities) { return AST_MODULE_LOAD_DECLINE; } - record_tech.capabilities = ast_format_cap_alloc(0); + record_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!record_tech.capabilities) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add_all(announce_tech.capabilities); - ast_format_cap_add_all(record_tech.capabilities); + ast_format_cap_append_by_type(announce_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_by_type(record_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); if (ast_channel_register(&announce_tech)) { ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n", diff --git a/channels/chan_console.c b/channels/chan_console.c index b1f5cdf7c..3aeda931a 100644 --- a/channels/chan_console.c +++ b/channels/chan_console.c @@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/callerid.h" #include "asterisk/astobj2.h" #include "asterisk/stasis_channels.h" +#include "asterisk/format_cache.h" /*! * \brief The sample rate to request from PortAudio @@ -270,12 +271,12 @@ static void *stream_monitor(void *data) PaError res; struct ast_frame f = { .frametype = AST_FRAME_VOICE, + .subclass.format = ast_format_slin16, .src = "console_stream_monitor", .data.ptr = buf, .datalen = sizeof(buf), .samples = sizeof(buf) / sizeof(int16_t), }; - ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0); for (;;) { pthread_testcancel(); @@ -421,19 +422,28 @@ static int stop_stream(struct console_pvt *pvt) */ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor) { + struct ast_format_cap *caps; struct ast_channel *chan; + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + return NULL; + } + if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL, ext, ctx, assignedids, requestor, 0, "Console/%s", pvt->name))) { + ao2_ref(caps, -1); return NULL; } ast_channel_stage_snapshot(chan); ast_channel_tech_set(chan, &console_tech); - ast_format_set(ast_channel_readformat(chan), AST_FORMAT_SLINEAR16, 0); - ast_format_set(ast_channel_writeformat(chan), AST_FORMAT_SLINEAR16, 0); - ast_format_cap_add(ast_channel_nativeformats(chan), ast_channel_readformat(chan)); + ast_channel_set_readformat(chan, ast_format_slin16); + ast_channel_set_writeformat(chan, ast_format_slin16); + ast_format_cap_append(caps, ast_format_slin16, 0); + ast_channel_nativeformats_set(chan, caps); + ao2_ref(caps, -1); ast_channel_tech_pvt_set(chan, ref_pvt(pvt)); pvt->owner = chan; @@ -462,15 +472,16 @@ static struct ast_channel *console_request(const char *type, struct ast_format_c { struct ast_channel *chan = NULL; struct console_pvt *pvt; - char buf[512]; if (!(pvt = find_pvt(data))) { ast_log(LOG_ERROR, "Console device '%s' not found\n", data); return NULL; } - if (!(ast_format_cap_has_joint(cap, console_tech.capabilities))) { - ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); + if (!(ast_format_cap_iscompatible(cap, console_tech.capabilities))) { + struct ast_str *cap_buf = ast_str_alloca(64); + ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n", + ast_format_cap_get_names(cap, &cap_buf)); goto return_unref; } @@ -1467,7 +1478,8 @@ static void stop_streams(void) static int unload_module(void) { - console_tech.capabilities = ast_format_cap_destroy(console_tech.capabilities); + ao2_ref(console_tech.capabilities, -1); + console_tech.capabilities = NULL; ast_channel_unregister(&console_tech); ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console)); @@ -1495,13 +1507,12 @@ static int unload_module(void) */ static int load_module(void) { - struct ast_format tmpfmt; PaError res; - if (!(console_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(console_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add(console_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0)); + ast_format_cap_append(console_tech.capabilities, ast_format_slin16, 0); init_pvt(&globals, NULL); @@ -1538,6 +1549,8 @@ return_error: if (pvts) ao2_ref(pvts, -1); pvts = NULL; + ao2_ref(console_tech.capabilities, -1); + console_tech.capabilities = NULL; pvt_destructor(&globals); return AST_MODULE_LOAD_DECLINE; diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 81242533e..c22833da5 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -129,6 +129,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/bridge.h" #include "asterisk/stasis_channels.h" #include "asterisk/parking.h" +#include "asterisk/format_cache.h" #include "chan_dahdi.h" #include "dahdi/bridge_native_dahdi.h" @@ -461,7 +462,7 @@ static struct ast_jb_conf global_jbconf; /*! \brief Typically, how many rings before we should send Caller*ID */ #define DEFAULT_CIDRINGS 1 -#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) +#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw) /*! \brief Signaling types that need to use MF detection should be placed in this macro */ @@ -1321,7 +1322,6 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e int res; unsigned char buf[256]; int flags; - struct ast_format tmpfmt; poller.fd = p->subs[SUB_REAL].dfd; poller.events = POLLPRI | POLLIN; @@ -1354,9 +1354,9 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e } if (p->cid_signalling == CID_SIG_V23_JP) { - res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p)); } else { - res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + res = callerid_feed(p->cs, buf, res, AST_LAW(p)); } if (res < 0) { /* @@ -1525,7 +1525,7 @@ static int restore_conference(struct dahdi_pvt *p); static int my_callwait(void *pvt) { struct dahdi_pvt *p = pvt; - struct ast_format tmpfmt; + p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; if (p->cidspill) { ast_log(LOG_WARNING, "Spill already exists?!?\n"); @@ -1542,11 +1542,11 @@ static int my_callwait(void *pvt) /* Silence */ memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); if (!p->callwaitrings && p->callwaitingcallerid) { - ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); p->callwaitcas = 1; p->cidlen = 2400 + 680 + READ_SIZE * 4; } else { - ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); p->callwaitcas = 0; p->cidlen = 2400 + READ_SIZE * 4; } @@ -1559,7 +1559,6 @@ static int my_callwait(void *pvt) static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller) { struct dahdi_pvt *p = pvt; - struct ast_format tmpfmt; ast_debug(2, "Starting cid spill\n"); @@ -1573,7 +1572,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle p->cidlen = ast_callerid_generate(p->cidspill, caller->id.name.str, caller->id.number.str, - ast_format_set(&tmpfmt, AST_LAW(p), 0)); + AST_LAW(p)); } else { ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", caller->id.name.str, caller->id.number.str); @@ -1582,7 +1581,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, caller->id.name.str, caller->id.number.str, - ast_format_set(&tmpfmt, AST_LAW(p), 0)); + AST_LAW(p)); p->cidlen += READ_SIZE * 4; } p->cidpos = 0; @@ -4965,14 +4964,12 @@ static int restore_conference(struct dahdi_pvt *p) static int send_cwcidspill(struct dahdi_pvt *p) { - struct ast_format tmpfmt; - p->callwaitcas = 0; p->cidcwexpire = 0; p->cid_suppress_expire = 0; if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) return -1; - p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); /* Make sure we account for the end */ p->cidlen += READ_SIZE * 4; p->cidpos = 0; @@ -5038,7 +5035,7 @@ static int send_callerid(struct dahdi_pvt *p) static int dahdi_callwait(struct ast_channel *ast) { struct dahdi_pvt *p = ast_channel_tech_pvt(ast); - struct ast_format tmpfmt; + p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; if (p->cidspill) { ast_log(LOG_WARNING, "Spill already exists?!?\n"); @@ -5055,11 +5052,11 @@ static int dahdi_callwait(struct ast_channel *ast) /* Silence */ memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); if (!p->callwaitrings && p->callwaitingcallerid) { - ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); p->callwaitcas = 1; p->cidlen = 2400 + 680 + READ_SIZE * 4; } else { - ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); p->callwaitcas = 0; p->cidlen = 2400 + READ_SIZE * 4; } @@ -8504,25 +8501,20 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) return f; } - if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) { + if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) { if (!p->subs[idx].linear) { p->subs[idx].linear = 1; res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); if (res) ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); } - } else if ((ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) || - (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ALAW)) { + } else { if (p->subs[idx].linear) { p->subs[idx].linear = 0; res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); if (res) ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); } - } else { - ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast_channel_rawreadformat(ast))); - ast_mutex_unlock(&p->lock); - return NULL; } readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; CHECK_BLOCKING(ast); @@ -8612,7 +8604,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) } p->subs[idx].f.frametype = AST_FRAME_VOICE; - ast_format_copy(&p->subs[idx].f.subclass.format, ast_channel_rawreadformat(ast)); + p->subs[idx].f.subclass.format = ast_channel_rawreadformat(ast); p->subs[idx].f.samples = READ_SIZE; p->subs[idx].f.mallocd = 0; p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; @@ -8795,12 +8787,6 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype); return 0; } - if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) && - (frame->subclass.format.id != AST_FORMAT_ULAW) && - (frame->subclass.format.id != AST_FORMAT_ALAW)) { - ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format)); - return -1; - } if (p->dialing) { ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast)); return 0; @@ -8818,7 +8804,7 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame) if (!frame->data.ptr || !frame->datalen) return 0; - if (frame->subclass.format.id == AST_FORMAT_SLINEAR) { + if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) { if (!p->subs[idx].linear) { p->subs[idx].linear = 1; res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); @@ -8826,7 +8812,8 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); } res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); - } else { + } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL + || ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) { /* x-law already */ if (p->subs[idx].linear) { p->subs[idx].linear = 0; @@ -8835,6 +8822,10 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); } res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); + } else { + ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", + ast_format_get_name(frame->subclass.format)); + return -1; } if (res < 0) { ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); @@ -9024,7 +9015,8 @@ static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid) { struct ast_channel *tmp; - struct ast_format deflaw; + struct ast_format_cap *caps; + struct ast_format *deflaw; int x; int features; struct ast_str *chan_name; @@ -9037,7 +9029,6 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb return NULL; } - ast_format_clear(&deflaw); #if defined(HAVE_PRI) /* * The dnid has been stuffed with the called-number[:subaddress] @@ -9051,9 +9042,16 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb return NULL; } + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_free(chan_name); + return NULL; + } + tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name)); ast_free(chan_name); if (!tmp) { + ao2_ref(caps, -1); return NULL; } @@ -9073,9 +9071,9 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb if (law) { i->law = law; if (law == DAHDI_LAW_ALAW) { - ast_format_set(&deflaw, AST_FORMAT_ALAW, 0); + deflaw = ast_format_alaw; } else { - ast_format_set(&deflaw, AST_FORMAT_ULAW, 0); + deflaw = ast_format_ulaw; } } else { switch (i->sig) { @@ -9089,18 +9087,20 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb break; } if (i->law_default == DAHDI_LAW_ALAW) { - ast_format_set(&deflaw, AST_FORMAT_ALAW, 0); + deflaw = ast_format_alaw; } else { - ast_format_set(&deflaw, AST_FORMAT_ULAW, 0); + deflaw = ast_format_ulaw; } } ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); - ast_format_cap_add(ast_channel_nativeformats(tmp), &deflaw); + ast_format_cap_append(caps, deflaw, 0); + ast_channel_nativeformats_set(tmp, caps); + ao2_ref(caps, -1); /* Start out assuming ulaw since it's smaller :) */ - ast_format_copy(ast_channel_rawreadformat(tmp), &deflaw); - ast_format_copy(ast_channel_readformat(tmp), &deflaw); - ast_format_copy(ast_channel_rawwriteformat(tmp), &deflaw); - ast_format_copy(ast_channel_writeformat(tmp), &deflaw); + ast_channel_set_rawreadformat(tmp, deflaw); + ast_channel_set_readformat(tmp, deflaw); + ast_channel_set_rawwriteformat(tmp, deflaw); + ast_channel_set_writeformat(tmp, deflaw); i->subs[idx].linear = 0; dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); features = 0; @@ -9397,7 +9397,6 @@ static void *analog_ss_thread(void *data) int len = 0; int res; int idx; - struct ast_format tmpfmt; RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup); const char *pickupexten; @@ -10114,9 +10113,9 @@ static void *analog_ss_thread(void *data) samples += res; if (p->cid_signalling == CID_SIG_V23_JP) { - res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); } else { - res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + res = callerid_feed(cs, buf, res, AST_LAW(p)); } if (res < 0) { /* @@ -10399,7 +10398,7 @@ static void *analog_ss_thread(void *data) } } samples += res; - res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); + res = callerid_feed(cs, buf, res, AST_LAW(p)); if (res < 0) { /* * The previous diagnostic message output likely @@ -10569,7 +10568,7 @@ struct mwi_thread_data { size_t len; }; -static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law) +static int calc_energy(const unsigned char *buf, int len, struct ast_format *law) { int x; int sum = 0; @@ -10578,7 +10577,7 @@ static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law return 0; for (x = 0; x < len; x++) - sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); + sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); return sum / len; } @@ -10594,13 +10593,12 @@ static void *mwi_thread(void *data) int i, res; unsigned int spill_done = 0; int spill_result = -1; - struct ast_format tmpfmt; if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { goto quit_no_clean; } - callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0)); + callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); bump_gains(mtd->pvt); @@ -10686,7 +10684,7 @@ static void *mwi_thread(void *data) } samples += res; if (!spill_done) { - if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) { + if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { /* * The previous diagnostic message output likely * explains why it failed. @@ -10744,7 +10742,6 @@ quit_no_clean: static int mwi_send_init(struct dahdi_pvt * pvt) { int x; - struct ast_format tmpfmt; #ifdef HAVE_DAHDI_LINEREVERSE_VMWI /* Determine how this spill is to be sent */ @@ -10786,8 +10783,8 @@ static int mwi_send_init(struct dahdi_pvt * pvt) #ifdef HAVE_DAHDI_LINEREVERSE_VMWI if (pvt->mwisend_fsk) { #endif - pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL, - ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0); + pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), + CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0); pvt->cidpos = 0; #ifdef HAVE_DAHDI_LINEREVERSE_VMWI } @@ -17314,7 +17311,8 @@ static int __unload_module(void) dahdi_native_unload(); - dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities); + ao2_cleanup(dahdi_tech.capabilities); + dahdi_tech.capabilities = NULL; STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type); return 0; } @@ -19496,7 +19494,6 @@ static const struct ast_data_entry dahdi_data_providers[] = { static int load_module(void) { int res; - struct ast_format tmpfmt; #if defined(HAVE_PRI) || defined(HAVE_SS7) int y; #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ @@ -19505,14 +19502,15 @@ static int load_module(void) return AST_MODULE_LOAD_FAILURE; } - if (!(dahdi_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(dahdi_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_FAILURE; } - ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); - ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + ast_format_cap_append(dahdi_tech.capabilities, ast_format_slin, 0); + ast_format_cap_append(dahdi_tech.capabilities, ast_format_ulaw, 0); + ast_format_cap_append(dahdi_tech.capabilities, ast_format_alaw, 0); if (dahdi_native_load(ast_module_info->self, &dahdi_tech)) { + ao2_ref(dahdi_tech.capabilities, -1); return AST_MODULE_LOAD_FAILURE; } @@ -19558,8 +19556,10 @@ static int load_module(void) #endif /* defined(HAVE_SS7) */ res = setup_dahdi(0); /* Make sure we can register our DAHDI channel type */ - if (res) + if (res) { + __unload_module(); return AST_MODULE_LOAD_DECLINE; + } if (ast_channel_register(&dahdi_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); __unload_module(); @@ -19652,10 +19652,9 @@ static int dahdi_sendtext(struct ast_channel *c, const char *text) return -1; mybuf = buf; if (p->mate) { - struct ast_format tmp; /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */ - struct ast_format *codec = &tmp; - ast_format_set(codec, AST_LAW(p), 0); + struct ast_format *codec = AST_LAW(p); + for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ PUT_CLID_MARKMS; } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 4beacfb22..be5b4c751 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -116,11 +116,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/stasis.h" #include "asterisk/stasis_system.h" #include "asterisk/stasis_channels.h" +#include "asterisk/format_cache.h" +#include "asterisk/format_compatibility.h" +#include "asterisk/format_cap.h" #include "iax2/include/iax2.h" #include "iax2/include/firmware.h" #include "iax2/include/parser.h" #include "iax2/include/provision.h" +#include "iax2/include/codec_pref.h" +#include "iax2/include/format_compatibility.h" + #include "jitterbuf.h" /*** DOCUMENTATION @@ -279,7 +285,7 @@ static int nochecksums = 0; /* Sample over last 100 units to determine historic jitter */ #define GAMMA (0.01) -static struct ast_codec_pref prefs; +static struct iax2_codec_pref prefs; static const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)"; @@ -347,22 +353,22 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL; #define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF /* T1, maybe ISDN */ #define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_SLINEAR) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_SLINEAR16) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_SIREN7) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_SIREN14) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_G719) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_ULAW) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_ALAW) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_G722)) + ~ast_format_compatibility_format2bitfield(ast_format_slin) & \ + ~ast_format_compatibility_format2bitfield(ast_format_slin16) & \ + ~ast_format_compatibility_format2bitfield(ast_format_siren7) & \ + ~ast_format_compatibility_format2bitfield(ast_format_siren14) & \ + ~ast_format_compatibility_format2bitfield(ast_format_g719) & \ + ~ast_format_compatibility_format2bitfield(ast_format_ulaw) & \ + ~ast_format_compatibility_format2bitfield(ast_format_alaw) & \ + ~ast_format_compatibility_format2bitfield(ast_format_g722)) /* A modem */ #define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_G726) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_G726_AAL2) & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_ADPCM)) + ~ast_format_compatibility_format2bitfield(ast_format_g726) & \ + ~ast_format_compatibility_format2bitfield(ast_format_g726_aal2) & \ + ~ast_format_compatibility_format2bitfield(ast_format_adpcm)) #define IAX_CAPABILITY_LOWFREE (IAX_CAPABILITY_LOWBANDWIDTH & \ - ~ast_format_id_to_old_bitfield(AST_FORMAT_G723_1)) + ~ast_format_compatibility_format2bitfield(ast_format_g723)) #define DEFAULT_MAXMS 2000 /* Must be faster than 2 seconds by default */ @@ -503,7 +509,7 @@ struct iax2_user { iax2_format capability; int maxauthreq; /*!< Maximum allowed outstanding AUTHREQs */ int curauthreq; /*!< Current number of outstanding AUTHREQs */ - struct ast_codec_pref prefs; + struct iax2_codec_pref prefs; struct ast_acl_list *acl; struct iax2_context *contexts; struct ast_variable *vars; @@ -532,7 +538,7 @@ struct iax2_peer { AST_STRING_FIELD(zonetag); /*!< Time Zone */ AST_STRING_FIELD(parkinglot); /*!< Default parkinglot for device */ ); - struct ast_codec_pref prefs; + struct iax2_codec_pref prefs; struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager */ struct ast_sockaddr addr; int formats; @@ -708,9 +714,9 @@ struct chan_iax2_pvt { /*! Peer Address */ struct ast_sockaddr addr; /*! Actual used codec preferences */ - struct ast_codec_pref prefs; + struct iax2_codec_pref prefs; /*! Requested codec preferences */ - struct ast_codec_pref rprefs; + struct iax2_codec_pref rprefs; /*! Our call number */ unsigned short callno; /*! Our callno_entry entry */ @@ -1809,17 +1815,18 @@ static iax2_format uncompress_subclass(unsigned char csub) return csub; } -static iax2_format iax2_codec_choose(struct ast_codec_pref *pref, iax2_format formats, int find_best) +static iax2_format iax2_codec_choose(struct iax2_codec_pref *pref, iax2_format formats, int find_best) { struct ast_format_cap *cap; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; iax2_format format = 0; - if ((cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) { - ast_format_clear(&tmpfmt); - ast_format_cap_from_old_bitfield(cap, formats); - ast_codec_choose(pref, cap, find_best, &tmpfmt); - format = ast_format_to_old_bitfield(&tmpfmt); - cap = ast_format_cap_destroy(cap); + + if ((cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { + iax2_format_compatibility_bitfield2cap(formats, cap); + tmpfmt = ast_format_cap_get_format(cap, 0); + format = ast_format_compatibility_format2bitfield(tmpfmt); + ao2_ref(tmpfmt, -1); + ao2_ref(cap, -1); } return format; @@ -1827,55 +1834,84 @@ static iax2_format iax2_codec_choose(struct ast_codec_pref *pref, iax2_format fo static iax2_format iax2_best_codec(iax2_format formats) { - struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - struct ast_format tmpfmt; + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + struct ast_format *tmpfmt; + iax2_format format; + if (!cap) { return 0; } - ast_format_clear(&tmpfmt); - ast_format_cap_from_old_bitfield(cap, formats); - ast_best_codec(cap, &tmpfmt); - cap = ast_format_cap_destroy(cap); - return ast_format_to_old_bitfield(&tmpfmt); + iax2_format_compatibility_bitfield2cap(formats, cap); + tmpfmt = ast_format_cap_get_format(cap, 0); + format = ast_format_compatibility_format2bitfield(tmpfmt); + ao2_ref(tmpfmt, -1); + ao2_ref(cap, -1); + + return format; } const char *iax2_getformatname(iax2_format format) { - struct ast_format tmpfmt; - if (!(ast_format_from_old_bitfield(&tmpfmt, format))) { + struct ast_format *tmpfmt; + + tmpfmt = ast_format_compatibility_bitfield2format(format); + if (!tmpfmt) { return "Unknown"; } - return ast_getformatname(&tmpfmt); + return ast_format_get_name(tmpfmt); } -static char *iax2_getformatname_multiple(char *codec_buf, size_t len, iax2_format format) +static const char *iax2_getformatname_multiple(iax2_format format, struct ast_str **codec_buf) { - struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!cap) { return "(Nothing)"; } - ast_format_cap_from_old_bitfield(cap, format); - ast_getformatname_multiple(codec_buf, len, cap); - cap = ast_format_cap_destroy(cap); + iax2_format_compatibility_bitfield2cap(format, cap); + ast_format_cap_get_names(cap, codec_buf); + ao2_ref(cap, -1); - return codec_buf; + return ast_str_buffer(*codec_buf); } -static int iax2_parse_allow_disallow(struct ast_codec_pref *pref, iax2_format *formats, const char *list, int allowing) +static int iax2_parse_allow_disallow(struct iax2_codec_pref *pref, iax2_format *formats, const char *list, int allowing) { - int res; - struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + int res, i; + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!cap) { return 1; } - ast_format_cap_from_old_bitfield(cap, *formats); - res = ast_parse_allow_disallow(pref, cap, list, allowing); - *formats = ast_format_cap_to_old_bitfield(cap); - cap = ast_format_cap_destroy(cap); + /* We want to add the formats to the cap in the preferred order */ + for (i = 0; i < IAX2_CODEC_PREF_SIZE; i++) { + uint64_t pref_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[i]); + + if (!pref_as_bitfield) { + break; + } + + if (iax2_format_compatibility_bitfield2cap(pref_as_bitfield, cap)) { + ao2_ref(cap, -1); + return 1; + } + } + + res = ast_format_cap_update_by_allow_disallow(cap, list, allowing); + *formats = iax2_format_compatibility_cap2bitfield(cap); + + iax2_codec_pref_remove_missing(pref, *formats); + + for (i = 0; i < ast_format_cap_count(cap); i++) { + struct ast_format *fmt = ast_format_cap_get_format(cap, i); + iax2_codec_pref_append(pref, fmt, ast_format_cap_get_format_framing(cap, fmt)); + ao2_ref(fmt, -1); + } + + ao2_ref(cap, -1); return res; } @@ -1883,13 +1919,13 @@ static int iax2_parse_allow_disallow(struct ast_codec_pref *pref, iax2_format *f static int iax2_data_add_codecs(struct ast_data *root, const char *node_name, iax2_format formats) { int res; - struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!cap) { return -1; } - ast_format_cap_from_old_bitfield(cap, formats); + iax2_format_compatibility_bitfield2cap(formats, cap); res = ast_data_add_codecs(root, node_name, cap); - cap = ast_format_cap_destroy(cap); + ao2_ref(cap, -1); return res; } @@ -3737,9 +3773,9 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct char status[30]; char cbuf[256]; struct iax2_peer *peer; - char codec_buf[512]; + struct ast_str *codec_buf = ast_str_alloca(64); struct ast_str *encmethods = ast_str_alloca(256); - int x = 0, load_realtime = 0; + int load_realtime = 0; switch (cmd) { case CLI_INIT: @@ -3789,23 +3825,13 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli(a->fd, " Defaddr->IP : %s Port %s\n", str_defaddr, str_defport); ast_cli(a->fd, " Username : %s\n", peer->username); ast_cli(a->fd, " Codecs : "); - iax2_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); - ast_cli(a->fd, "%s\n", codec_buf); + ast_cli(a->fd, "%s\n", iax2_getformatname_multiple(peer->capability, &codec_buf)); - ast_cli(a->fd, " Codec Order : ("); - for(x = 0; x < AST_CODEC_PREF_SIZE; x++) { - struct ast_format tmpfmt; - if(!(ast_codec_pref_index(&peer->prefs, x, &tmpfmt))) - break; - ast_cli(a->fd, "%s", ast_getformatname(&tmpfmt)); - if(x < 31 && ast_codec_pref_index(&peer->prefs, x+1, &tmpfmt)) - ast_cli(a->fd, "|"); + ast_cli(a->fd, " Codec Order : "); + if (iax2_codec_pref_string(&peer->prefs, cbuf, sizeof(cbuf)) != -1) { + ast_cli(a->fd, "%s\n", cbuf); } - if (!x) - ast_cli(a->fd, "none"); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, " Status : "); peer_status(peer, status, sizeof(status)); ast_cli(a->fd, "%s\n",status); @@ -4084,9 +4110,9 @@ static void __get_from_jb(const void *p) ms = ast_tvdiff_ms(now, pvt->rxcore); if(ms >= (next = jb_next(pvt->jb))) { - struct ast_format voicefmt; - ast_format_from_old_bitfield(&voicefmt, pvt->voiceformat); - ret = jb_get(pvt->jb, &frame, ms, ast_codec_interp_len(&voicefmt)); + struct ast_format *voicefmt; + voicefmt = ast_format_compatibility_bitfield2format(pvt->voiceformat); + ret = jb_get(pvt->jb, &frame, ms, ast_format_get_default_ms(voicefmt)); switch(ret) { case JB_OK: fr = frame.data; @@ -4100,8 +4126,8 @@ static void __get_from_jb(const void *p) /* create an interpolation frame */ af.frametype = AST_FRAME_VOICE; - ast_format_copy(&af.subclass.format, &voicefmt); - af.samples = frame.ms * (ast_format_rate(&voicefmt) / 1000); + af.subclass.format = voicefmt; + af.samples = frame.ms * (ast_format_get_sample_rate(voicefmt) / 1000); af.src = "IAX2 JB interpolation"; af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); af.offset = AST_FRIENDLY_OFFSET; @@ -4182,7 +4208,7 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr if(fr->af.frametype == AST_FRAME_VOICE) { type = JB_TYPE_VOICE; - len = ast_codec_get_samples(&fr->af) / (ast_format_rate(&fr->af.subclass.format) / 1000); + len = ast_codec_samples_count(&fr->af) / (ast_format_get_sample_rate(fr->af.subclass.format) / 1000); } else if(fr->af.frametype == AST_FRAME_CNG) { type = JB_TYPE_SILENCE; } @@ -4579,7 +4605,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s { struct iax2_peer *peer; int res = -1; - struct ast_codec_pref ourprefs; + struct iax2_codec_pref ourprefs; ast_clear_flag64(cai, IAX_SENDANI | IAX_TRUNK); cai->sockfd = defaultsockfd; @@ -4604,14 +4630,16 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s /* But move the calling channel's native codec to the top of the preference list */ memcpy(&ourprefs, &prefs, sizeof(ourprefs)); if (c) { - struct ast_format tmpfmt; - ast_format_cap_iter_start(ast_channel_nativeformats(c)); - while (!(ast_format_cap_iter_next(ast_channel_nativeformats(c), &tmpfmt))) { - ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1); + int i; + + for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) { + struct ast_format *format = ast_format_cap_get_format( + ast_channel_nativeformats(c), i); + iax2_codec_pref_prepend(&ourprefs, format, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), format), 1); + ao2_ref(format, -1); } - ast_format_cap_iter_end(ast_channel_nativeformats(c)); } - ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); + iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); return 0; } @@ -4635,15 +4663,16 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); /* Move the calling channel's native codec to the top of the preference list */ if (c) { - struct ast_format tmpfmt; - ast_format_cap_iter_start(ast_channel_nativeformats(c)); - while (!(ast_format_cap_iter_next(ast_channel_nativeformats(c), &tmpfmt))) { - ast_debug(1, "prepending %s to prefs\n", ast_getformatname(&tmpfmt)); - ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1); + int i; + + for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) { + struct ast_format *tmpfmt = ast_format_cap_get_format( + ast_channel_nativeformats(c), i); + iax2_codec_pref_prepend(&ourprefs, tmpfmt, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), tmpfmt), 1); + ao2_ref(tmpfmt, -1); } - ast_format_cap_iter_end(ast_channel_nativeformats(c)); } - ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); + iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); ast_copy_string(cai->context, peer->context, sizeof(cai->context)); ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); ast_copy_string(cai->username, peer->username, sizeof(cai->username)); @@ -5181,7 +5210,7 @@ static int iax2_call(struct ast_channel *c, const char *dest, int timeout) if (pds.password) ast_string_field_set(iaxs[callno], secret, pds.password); - iax2_tmpfmt = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(c)); + iax2_tmpfmt = iax2_format_compatibility_cap2bitfield(ast_channel_nativeformats(c)); iax_ie_append_int(&ied, IAX_IE_FORMAT, (int) iax2_tmpfmt); iax_ie_append_versioned_uint64(&ied, IAX_IE_FORMAT2, 0, iax2_tmpfmt); @@ -5551,11 +5580,13 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha return AST_BRIDGE_FAILED_NOWARN; } if (!(ast_format_cap_identical(ast_channel_nativeformats(c0), ast_channel_nativeformats(c1)))) { - char buf0[256]; - char buf1[256]; - ast_getformatname_multiple(buf0, sizeof(buf0), ast_channel_nativeformats(c0)); - ast_getformatname_multiple(buf1, sizeof(buf1), ast_channel_nativeformats(c1)); - ast_verb(3, "Operating with different codecs [%s] [%s] , can't native bridge...\n", buf0, buf1); + struct ast_str *c0_buf = ast_str_alloca(64); + struct ast_str *c1_buf = ast_str_alloca(64); + + ast_verb(3, "Operating with different codecs [%s] [%s] , can't native bridge...\n", + ast_format_cap_get_names(ast_channel_nativeformats(c0), &c0_buf), + ast_format_cap_get_names(ast_channel_nativeformats(c1), &c1_buf)); + /* Remove from native mode */ lock_both(callno0, callno1); if (iaxs[callno0]) @@ -5780,7 +5811,8 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab struct ast_channel *tmp; struct chan_iax2_pvt *i; struct ast_variable *v = NULL; - struct ast_format tmpfmt; + struct ast_format_cap *native; + struct ast_format *tmpfmt; struct ast_callid *callid; if (!(i = iaxs[callno])) { @@ -5788,6 +5820,11 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab return NULL; } + native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!native) { + return NULL; + } + /* Don't hold call lock */ ast_mutex_unlock(&iaxsl[callno]); tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno); @@ -5800,9 +5837,11 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab tmp = ast_channel_release(tmp); ast_mutex_lock(&iaxsl[callno]); } + ao2_ref(native, -1); return NULL; } if (!tmp) { + ao2_ref(native, -1); return NULL; } @@ -5813,14 +5852,19 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab } ast_channel_tech_set(tmp, &iax2_tech); + /* We can support any format by default, until we get restricted */ - ast_format_cap_from_old_bitfield(ast_channel_nativeformats(tmp), capability); - ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt); + iax2_format_compatibility_bitfield2cap(capability, native); + ast_channel_nativeformats_set(tmp, native); + tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0); - ast_format_copy(ast_channel_readformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); + ast_channel_set_readformat(tmp, tmpfmt); + ast_channel_set_rawreadformat(tmp, tmpfmt); + ast_channel_set_writeformat(tmp, tmpfmt); + ast_channel_set_rawwriteformat(tmp, tmpfmt); + + ao2_ref(tmpfmt, -1); + ao2_ref(native, -1); ast_channel_tech_pvt_set(tmp, CALLNO_TO_PTR(i->callno)); @@ -5971,7 +6015,7 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str int voice = 0; int genuine = 0; int adjust; - int rate = ast_format_rate(&f->subclass.format) / 1000; + int rate = 0; struct timeval *delivery = NULL; @@ -5983,6 +6027,7 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str */ if (f->frametype == AST_FRAME_VOICE) { voice = 1; + rate = ast_format_get_sample_rate(f->subclass.format) / 1000; delivery = &f->delivery; } else if (f->frametype == AST_FRAME_IAX) { genuine = 1; @@ -6092,8 +6137,9 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str } } p->lastsent = ms; - if (voice) + if (voice) { p->nextpred = p->nextpred + f->samples / rate; + } return ms; } @@ -6344,9 +6390,9 @@ static int decode_frame(ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh, memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); f->frametype = fh->type; if (f->frametype == AST_FRAME_VIDEO) { - ast_format_from_old_bitfield(&f->subclass.format, (uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1))); + f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1)); } else if (f->frametype == AST_FRAME_VOICE) { - ast_format_from_old_bitfield(&f->subclass.format, uncompress_subclass(fh->csub)); + f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub)); } else { f->subclass.integer = uncompress_subclass(fh->csub); } @@ -6487,7 +6533,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in /* High two bytes are the same on timestamp, or sending on a trunk */ && (f->frametype == AST_FRAME_VOICE) /* is a voice frame */ && - (f->subclass.format.id == ast_format_id_from_old_bitfield(pvt->svoiceformat)) + (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svoiceformat))) /* is the same type */ ) { /* Force immediate rather than delayed transmission */ now = 1; @@ -6501,7 +6547,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in * Otherwise send a mini video frame */ if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) && - ((f->subclass.format.id) == ast_format_id_from_old_bitfield(pvt->svideoformat)) + (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svideoformat))) ) { now = 1; sendmini = 1; @@ -6556,11 +6602,11 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in fh->type = fr->af.frametype & 0xFF; if (fr->af.frametype == AST_FRAME_VIDEO) { - iax2_format tmpfmt = ast_format_to_old_bitfield(&fr->af.subclass.format); - tmpfmt |= ast_format_get_video_mark(&fr->af.subclass.format) ? 0x1LL : 0; + iax2_format tmpfmt = ast_format_compatibility_format2bitfield(fr->af.subclass.format); + tmpfmt |= fr->af.subclass.frame_ending ? 0x1LL : 0; fh->csub = compress_subclass(tmpfmt | ((tmpfmt & 0x1LL) << 6)); } else if (fr->af.frametype == AST_FRAME_VOICE) { - fh->csub = compress_subclass(ast_format_to_old_bitfield(&fr->af.subclass.format)); + fh->csub = compress_subclass(ast_format_compatibility_format2bitfield(fr->af.subclass.format)); } else { fh->csub = compress_subclass(fr->af.subclass.integer); } @@ -6583,9 +6629,9 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in if ((f->frametype == AST_FRAME_IAX) && (f->subclass.integer == IAX_COMMAND_ACK)) fr->retries = -1; else if (f->frametype == AST_FRAME_VOICE) - pvt->svoiceformat = ast_format_to_old_bitfield(&f->subclass.format); + pvt->svoiceformat = ast_format_compatibility_format2bitfield(f->subclass.format); else if (f->frametype == AST_FRAME_VIDEO) - pvt->svideoformat = ast_format_to_old_bitfield(&f->subclass.format); + pvt->svideoformat = ast_format_compatibility_format2bitfield(f->subclass.format); if (ast_test_flag64(pvt, IAX_ENCRYPTED)) { if (ast_test_flag64(pvt, IAX_KEYPOPULATED)) { if (fr->transfer) @@ -6616,7 +6662,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in vh = (struct ast_iax2_video_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_video_hdr)); vh->zeros = 0; vh->callno = htons(0x8000 | fr->callno); - vh->ts = htons((fr->ts & 0x7FFF) | (ast_format_get_video_mark(&fr->af.subclass.format) ? 0x8000 : 0)); + vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass.frame_ending ? 0x8000 : 0)); fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); fr->data = vh; fr->retries = -1; @@ -7767,8 +7813,8 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i /* Use provided preferences until told otherwise for actual preferences */ if (ies->codec_prefs) { - ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); - ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); + iax2_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); + iax2_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); } if (!gotcapability) { @@ -9827,7 +9873,7 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n"); iax2_vnak(fr->callno); } else { - ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat); + f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat); f.datalen = len; if (f.datalen >= 0) { if (f.datalen) @@ -9847,7 +9893,7 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s f.mallocd = 0; f.offset = 0; if (f.datalen && (f.frametype == AST_FRAME_VOICE)) - f.samples = ast_codec_get_samples(&f); + f.samples = ast_codec_samples_count(&f); else f.samples = 0; fr->outoforder = 0; @@ -10004,7 +10050,7 @@ static int socket_process_helper(struct iax2_thread *thread) struct iax_frame *duped_fr; char host_pref_buf[128]; char caller_pref_buf[128]; - struct ast_codec_pref pref; + struct iax2_codec_pref pref; char *using_prefs = "mine"; /* allocate an iax_frame with 4096 bytes of data buffer */ @@ -10069,12 +10115,12 @@ static int socket_process_helper(struct iax2_thread *thread) /* Retrieve the type and subclass */ f.frametype = fh->type; if (f.frametype == AST_FRAME_VIDEO) { - ast_format_from_old_bitfield(&f.subclass.format, (uncompress_subclass(fh->csub & ~0x40))); + f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40)); if ((fh->csub >> 6) & 0x1) { - ast_format_set_video_mark(&f.subclass.format); + f.subclass.frame_ending = 1; } } else if (f.frametype == AST_FRAME_VOICE) { - ast_format_from_old_bitfield(&f.subclass.format, uncompress_subclass(fh->csub)); + f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub)); } else { f.subclass.integer = uncompress_subclass(fh->csub); } @@ -10498,22 +10544,21 @@ static int socket_process_helper(struct iax2_thread *thread) } if (f.frametype == AST_FRAME_VOICE) { - if (ast_format_to_old_bitfield(&f.subclass.format) != iaxs[fr->callno]->voiceformat) { - iaxs[fr->callno]->voiceformat = ast_format_to_old_bitfield(&f.subclass.format); - ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_getformatname(&f.subclass.format)); + if (ast_format_compatibility_format2bitfield(f.subclass.format) != iaxs[fr->callno]->voiceformat) { + iaxs[fr->callno]->voiceformat = ast_format_compatibility_format2bitfield(f.subclass.format); + ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_format_get_name(f.subclass.format)); if (iaxs[fr->callno]->owner) { iax2_lock_owner(fr->callno); if (iaxs[fr->callno]) { if (iaxs[fr->callno]->owner) { - struct ast_format_cap *orignative = ast_format_cap_dup(ast_channel_nativeformats(iaxs[fr->callno]->owner)); - struct ast_format_cap *native = ast_channel_nativeformats(iaxs[fr->callno]->owner); - if (orignative) { - ast_format_cap_set(native, &f.subclass.format); - if (ast_channel_readformat(iaxs[fr->callno]->owner)->id) { + struct ast_format_cap *native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (native) { + ast_format_cap_append(native, f.subclass.format, 0); + ast_channel_nativeformats_set(iaxs[fr->callno]->owner, native); + if (ast_channel_readformat(iaxs[fr->callno]->owner)) { ast_set_read_format(iaxs[fr->callno]->owner, ast_channel_readformat(iaxs[fr->callno]->owner)); } - ast_format_cap_copy(native, orignative); - orignative = ast_format_cap_destroy(orignative); + ao2_ref(native, -1); } ast_channel_unlock(iaxs[fr->callno]->owner); } @@ -10532,9 +10577,9 @@ static int socket_process_helper(struct iax2_thread *thread) } } if (f.frametype == AST_FRAME_VIDEO) { - if (f.subclass.format.id != ast_format_id_from_old_bitfield(iaxs[fr->callno]->videoformat)) { - ast_debug(1, "Ooh, video format changed to %s\n", ast_getformatname(&f.subclass.format)); - iaxs[fr->callno]->videoformat = ast_format_to_old_bitfield(&f.subclass.format); + if (ast_format_compatibility_format2bitfield(f.subclass.format) != iaxs[fr->callno]->videoformat) { + ast_debug(1, "Ooh, video format changed to %s\n", ast_format_get_name(f.subclass.format)); + iaxs[fr->callno]->videoformat = ast_format_compatibility_format2bitfield(f.subclass.format); } } if (f.frametype == AST_FRAME_IAX) { @@ -10697,12 +10742,12 @@ static int socket_process_helper(struct iax2_thread *thread) strcpy(caller_pref_buf, "disabled"); strcpy(host_pref_buf, "disabled"); } else { - struct ast_format tmpfmt; + struct ast_format *tmpfmt; using_prefs = "mine"; /* If the information elements are in here... use them */ if (ies.codec_prefs) - ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); - if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { + iax2_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); + if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { pref = iaxs[fr->callno]->rprefs; @@ -10714,8 +10759,8 @@ static int socket_process_helper(struct iax2_thread *thread) pref = iaxs[fr->callno]->prefs; format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); - ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); - ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); + iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); + iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); } if (!format) { if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) @@ -10729,18 +10774,21 @@ static int socket_process_helper(struct iax2_thread *thread) break; } if (authdebug) { - char tmp[256], tmp2[256], tmp3[256]; + struct ast_str *peer_buf = ast_str_alloca(64); + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *peer_form_buf = ast_str_alloca(64); + if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } else { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } } } else { @@ -10756,9 +10804,9 @@ static int socket_process_helper(struct iax2_thread *thread) strcpy(caller_pref_buf,"disabled"); strcpy(host_pref_buf,"disabled"); } else { - struct ast_format tmpfmt; + struct ast_format *tmpfmt; using_prefs = "mine"; - if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { + if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { /* Do the opposite of what we tried above. */ if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { pref = iaxs[fr->callno]->prefs; @@ -10773,11 +10821,14 @@ static int socket_process_helper(struct iax2_thread *thread) } if (!format) { - char tmp[256], tmp2[256], tmp3[256]; + struct ast_str *peer_buf = ast_str_alloca(64); + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *peer_form_buf = ast_str_alloca(64); + memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); - ast_log(LOG_ERROR, "No best format in '%s'???\n", iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability)); + ast_log(LOG_ERROR, "No best format in '%s'???\n", iax2_getformatname_multiple(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, &cap_buf)); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { break; @@ -10785,9 +10836,9 @@ static int socket_process_helper(struct iax2_thread *thread) if (authdebug) { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE); break; @@ -10935,7 +10986,7 @@ static int socket_process_helper(struct iax2_thread *thread) iaxs[fr->callno]->peerformat = ies.format; } else { if (iaxs[fr->callno]->owner) - iaxs[fr->callno]->peerformat = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner)); + iaxs[fr->callno]->peerformat = iax2_format_compatibility_cap2bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner)); else iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; } @@ -10950,28 +11001,36 @@ static int socket_process_helper(struct iax2_thread *thread) break; } if (authdebug) { - char tmp1[256], tmp2[256]; + struct ast_str *peer_buf = ast_str_alloca(64); + struct ast_str *cap_buf = ast_str_alloca(64); + ast_log(LOG_NOTICE, "Rejected call to %s, format %s incompatible with our capability %s.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } } else { + struct ast_format_cap *native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); iax2_lock_owner(fr->callno); - if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { - char tmp[256]; + if (iaxs[fr->callno] && iaxs[fr->callno]->owner && native) { + struct ast_str *cap_buf = ast_str_alloca(64); + /* Switch us to use a compatible format */ - ast_format_cap_from_old_bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner), iaxs[fr->callno]->peerformat); - ast_verb(3, "Format for call is %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(iaxs[fr->callno]->owner))); + iax2_format_compatibility_bitfield2cap(iaxs[fr->callno]->peerformat, native); + ast_channel_nativeformats_set(iaxs[fr->callno]->owner, native); + ast_verb(3, "Format for call is %s\n", ast_format_cap_get_names(ast_channel_nativeformats(iaxs[fr->callno]->owner), &cap_buf)); /* Setup read/write formats properly. */ - if (ast_channel_writeformat(iaxs[fr->callno]->owner)->id) + if (ast_channel_writeformat(iaxs[fr->callno]->owner)) ast_set_write_format(iaxs[fr->callno]->owner, ast_channel_writeformat(iaxs[fr->callno]->owner)); - if (ast_channel_readformat(iaxs[fr->callno]->owner)->id) + if (ast_channel_readformat(iaxs[fr->callno]->owner)) ast_set_read_format(iaxs[fr->callno]->owner, ast_channel_readformat(iaxs[fr->callno]->owner)); ast_channel_unlock(iaxs[fr->callno]->owner); } + + ao2_cleanup(native); } if (iaxs[fr->callno]) { AST_LIST_LOCK(&dpcache); @@ -11140,11 +11199,11 @@ static int socket_process_helper(struct iax2_thread *thread) strcpy(caller_pref_buf, "disabled"); strcpy(host_pref_buf, "disabled"); } else { - struct ast_format tmpfmt; + struct ast_format *tmpfmt; using_prefs = "mine"; if (ies.codec_prefs) - ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); - if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { + iax2_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); + if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { pref = iaxs[fr->callno]->rprefs; using_prefs = "caller"; @@ -11154,15 +11213,18 @@ static int socket_process_helper(struct iax2_thread *thread) } else /* if no codec_prefs IE do it the old way */ pref = iaxs[fr->callno]->prefs; format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); - ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); - ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); + iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); + iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); } if (!format) { - char tmp1[256], tmp2[256], tmp3[256]; + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *peer_buf = ast_str_alloca(64); + struct ast_str *peer_form_buf = ast_str_alloca(64); + if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) { ast_debug(1, "We don't do requested format %s, falling back to peer capability '%s'\n", iax2_getformatname(iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf)); format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; } if (!format) { @@ -11170,14 +11232,14 @@ static int socket_process_helper(struct iax2_thread *thread) if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } else { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } } memset(&ied0, 0, sizeof(ied0)); @@ -11201,9 +11263,9 @@ static int socket_process_helper(struct iax2_thread *thread) strcpy(caller_pref_buf,"disabled"); strcpy(host_pref_buf,"disabled"); } else { - struct ast_format tmpfmt; + struct ast_format *tmpfmt; using_prefs = "mine"; - if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { + if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) { /* Do the opposite of what we tried above. */ if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { pref = iaxs[fr->callno]->prefs; @@ -11217,21 +11279,24 @@ static int socket_process_helper(struct iax2_thread *thread) } } if (!format) { - char tmp1[256], tmp2[256], tmp3[256]; + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *peer_buf = ast_str_alloca(64); + struct ast_str *peer_form_buf = ast_str_alloca(64); + ast_log(LOG_ERROR, "No best format in %s???\n", - iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, &cap_buf)); if (authdebug) { if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } else { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf), + iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf)); } } memset(&ied0, 0, sizeof(ied0)); @@ -11338,11 +11403,11 @@ immediatedial: break; } } else { - char tmp[256]; + struct ast_str *cap_buf = ast_str_alloca(64); ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); ast_verb(3, "Accepting DIAL from %s, formats = %s\n", ast_sockaddr_stringify(&addr), - iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat)); + iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &cap_buf)); ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat, NULL, NULL, 1))) @@ -11662,9 +11727,9 @@ immediatedial: f.frametype = AST_FRAME_VIDEO; if (iaxs[fr->callno]->videoformat > 0) { if (ntohs(vh->ts) & 0x8000LL) { - ast_format_set_video_mark(&f.subclass.format); + f.subclass.frame_ending = 1; } - ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->videoformat); + f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->videoformat); } else { ast_log(LOG_WARNING, "Received mini frame before first full video frame\n"); iax2_vnak(fr->callno); @@ -11687,7 +11752,7 @@ immediatedial: /* A mini frame */ f.frametype = AST_FRAME_VOICE; if (iaxs[fr->callno]->voiceformat > 0) - ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat); + f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat); else { ast_debug(1, "Received mini frame before first full voice frame\n"); iax2_vnak(fr->callno); @@ -11795,9 +11860,9 @@ immediatedial: f.offset = 0; f.len = 0; if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { - f.samples = ast_codec_get_samples(&f); + f.samples = ast_codec_samples_count(&f); /* We need to byteswap incoming slinear samples from network byte order */ - if (f.subclass.format.id == AST_FORMAT_SLINEAR) + if (ast_format_cmp(f.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) ast_frame_byteswap_be(&f); } else f.samples = 0; @@ -12376,32 +12441,48 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap if (c) { struct ast_format_cap *joint; + struct ast_format *format; if (callid) { ast_channel_lock(c); ast_channel_callid_set(c, callid); ast_channel_unlock(c); } - /* Choose a format we can live with */ - if ((joint = ast_format_cap_joint(ast_channel_nativeformats(c), cap))) { - ast_format_cap_copy(ast_channel_nativeformats(c), joint); - joint = ast_format_cap_destroy(joint); - } else { - struct ast_format best_fmt_cap; - struct ast_format best_fmt_native; + joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!joint) { + ast_hangup(c); + return NULL; + } + + ast_format_cap_get_compatible(ast_channel_nativeformats(c), cap, joint); + + /* If there is no joint format find one through translation */ + if (!ast_format_cap_count(joint)) { + struct ast_format *best_fmt_cap = NULL; + struct ast_format *best_fmt_native = NULL; res = ast_translator_best_choice(cap, ast_channel_nativeformats(c), &best_fmt_cap, &best_fmt_native); if (res < 0) { - char tmp[256]; - char tmp2[256]; + struct ast_str *native_cap_buf = ast_str_alloca(64); + struct ast_str *cap_buf = ast_str_alloca(64); + ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", - ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(c)), ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_channel_name(c)); + ast_format_cap_get_names(ast_channel_nativeformats(c), &native_cap_buf), + ast_format_cap_get_names(cap, &cap_buf), + ast_channel_name(c)); ast_hangup(c); return NULL; } - ast_format_cap_set(ast_channel_nativeformats(c), &best_fmt_native); + ast_format_cap_append(joint, best_fmt_native, 0); + ao2_ref(best_fmt_cap, -1); + ao2_ref(best_fmt_native, -1); } - ast_best_codec(ast_channel_nativeformats(c), ast_channel_readformat(c)); - ast_format_copy(ast_channel_writeformat(c), ast_channel_readformat(c)); + ast_channel_nativeformats_set(c, joint); + format = ast_format_cap_get_format(ast_channel_nativeformats(c), 0); + ast_channel_set_readformat(c, format); + ast_channel_set_writeformat(c, format); + + ao2_ref(joint, -1); + ao2_ref(format, -1); } if (callid) { @@ -13355,7 +13436,7 @@ static int set_config(const char *config_file, int reload, int forced) ast_sockaddr_parse(&bindaddr, "0.0.0.0:0", 0); /* Reset global codec prefs */ - memset(&prefs, 0 , sizeof(struct ast_codec_pref)); + memset(&prefs, 0 , sizeof(struct iax2_codec_pref)); /* Reset Global Flags */ memset(&globalflags, 0, sizeof(globalflags)); @@ -14234,10 +14315,13 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat } else if (!strcasecmp(colname, "callerid_num")) { ast_copy_string(buf, peer->cid_num, len); } else if (!strcasecmp(colname, "codecs")) { - iax2_getformatname_multiple(buf, len -1, peer->capability); + struct ast_str *codec_buf; + + iax2_getformatname_multiple(peer->capability, &codec_buf); + ast_copy_string(buf, ast_str_buffer(codec_buf), len); } else if (!strncasecmp(colname, "codec[", 6)) { char *codecnum, *ptr; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; /* skip over "codec" to the '[' */ codecnum = colname + 5; @@ -14246,8 +14330,8 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat if ((ptr = strchr(codecnum, ']'))) { *ptr = '\0'; } - if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &tmpfmt))) { - ast_copy_string(buf, ast_getformatname(&tmpfmt), len); + if((iax2_codec_pref_index(&peer->prefs, atoi(codecnum), &tmpfmt))) { + ast_copy_string(buf, ast_format_get_name(tmpfmt), len); } else { buf[0] = '\0'; } @@ -14604,7 +14688,8 @@ static int __unload_module(void) ast_context_destroy(con, "IAX2"); ast_unload_realtime("iaxpeers"); - iax2_tech.capabilities = ast_format_cap_destroy(iax2_tech.capabilities); + ao2_ref(iax2_tech.capabilities, -1); + iax2_tech.capabilities = NULL; return 0; } @@ -14914,10 +14999,10 @@ static int load_module(void) int x = 0; struct iax2_registry *reg = NULL; - if (!(iax2_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(iax2_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_FAILURE; } - ast_format_cap_add_all(iax2_tech.capabilities); + ast_format_cap_append_by_type(iax2_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); if (load_objects()) { return AST_MODULE_LOAD_FAILURE; diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 2d0afe29d..6021b6c1d 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -86,6 +86,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/features_config.h" #include "asterisk/parking.h" #include "asterisk/stasis_channels.h" +#include "asterisk/format_cache.h" /* * Define to work around buggy dlink MGCP phone firmware which @@ -1199,9 +1200,20 @@ static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub) if (sub->owner) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE) { - if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format)) { - ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); - ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format); + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_format_cap *caps; + + ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format)); + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + ast_format_cap_append(caps, f->subclass.format, 0); + ast_channel_nativeformats_set(sub->owner, caps); + ao2_ref(caps, -1); + } else { + return &ast_null_frame; + } + ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner)); ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner)); } @@ -1239,7 +1251,6 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame) { struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); int res = 0; - char buf[256]; if (frame->frametype != AST_FRAME_VOICE) { if (frame->frametype == AST_FRAME_IMAGE) @@ -1249,12 +1260,14 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } } else { - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) { + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *cap_buf = ast_str_alloca(64); + ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(&frame->subclass.format), - ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)), - ast_getformatname(ast_channel_readformat(ast)), - ast_getformatname(ast_channel_writeformat(ast))); + ast_format_get_name(frame->subclass.format), + ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf), + ast_format_get_name(ast_channel_readformat(ast)), + ast_format_get_name(ast_channel_writeformat(ast))); /* return -1; */ } } @@ -1490,90 +1503,103 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor) { + struct ast_format_cap *caps = NULL; struct ast_channel *tmp; struct ast_variable *v = NULL; struct mgcp_endpoint *i = sub->parent; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_log(LOG_ERROR, "Format capabilities could not be created\n"); + return NULL; + } tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); - if (tmp) { - ast_channel_stage_snapshot(tmp); - ast_channel_tech_set(tmp, &mgcp_tech); - ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap); - if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) { - ast_format_cap_copy(ast_channel_nativeformats(tmp), global_capability); - } - if (sub->rtp) { - ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); - } - if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { - i->dsp = ast_dsp_new(); - ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); - /* this is to prevent clipping of dtmf tones during dsp processing */ - ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); - } else { - i->dsp = NULL; - } - if (state == AST_STATE_RING) - ast_channel_rings_set(tmp, 1); - - ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt); - ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_readformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); - ast_channel_tech_pvt_set(tmp, sub); - if (!ast_strlen_zero(i->language)) - ast_channel_language_set(tmp, i->language); - if (!ast_strlen_zero(i->accountcode)) - ast_channel_accountcode_set(tmp, i->accountcode); - if (i->amaflags) - ast_channel_amaflags_set(tmp, i->amaflags); - mgcp_set_owner(sub, tmp); - ast_module_ref(ast_module_info->self); - ast_channel_callgroup_set(tmp, i->callgroup); - ast_channel_pickupgroup_set(tmp, i->pickupgroup); - ast_channel_call_forward_set(tmp, i->call_forward); - ast_channel_context_set(tmp, i->context); - ast_channel_exten_set(tmp, i->exten); - - /* Don't use ast_set_callerid() here because it will - * generate a needless NewCallerID event */ - if (!ast_strlen_zero(i->cid_num)) { - ast_channel_caller(tmp)->ani.number.valid = 1; - ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num); - } - - if (!i->adsi) { - ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE); - } - ast_channel_priority_set(tmp, 1); + if (!tmp) { + ast_log(LOG_WARNING, "Channel could not be created\n"); + ao2_ref(caps, -1); + return NULL; + } - /* Set channel variables for this call from configuration */ - for (v = i->chanvars ; v ; v = v->next) { - char valuebuf[1024]; - pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf))); - } + ast_channel_stage_snapshot(tmp); + ast_channel_tech_set(tmp, &mgcp_tech); + if (ast_format_cap_count(i->cap)) { + ast_format_cap_append_from_cap(caps, i->cap, AST_MEDIA_TYPE_UNKNOWN); + } else { + ast_format_cap_append_from_cap(caps, global_capability, AST_MEDIA_TYPE_UNKNOWN); + } + ast_channel_nativeformats_set(tmp, caps); + ao2_ref(caps, -1); + if (sub->rtp) { + ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); + } + if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { + i->dsp = ast_dsp_new(); + ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); + /* this is to prevent clipping of dtmf tones during dsp processing */ + ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); + } else { + i->dsp = NULL; + } + if (state == AST_STATE_RING) { + ast_channel_rings_set(tmp, 1); + } + + tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0); + ast_channel_set_writeformat(tmp, tmpfmt); + ast_channel_set_rawwriteformat(tmp, tmpfmt); + ast_channel_set_readformat(tmp, tmpfmt); + ast_channel_set_rawreadformat(tmp, tmpfmt); + ao2_ref(tmpfmt, -1); + ast_channel_tech_pvt_set(tmp, sub); + if (!ast_strlen_zero(i->language)) + ast_channel_language_set(tmp, i->language); + if (!ast_strlen_zero(i->accountcode)) + ast_channel_accountcode_set(tmp, i->accountcode); + if (i->amaflags) + ast_channel_amaflags_set(tmp, i->amaflags); + mgcp_set_owner(sub, tmp); + ast_module_ref(ast_module_info->self); + ast_channel_callgroup_set(tmp, i->callgroup); + ast_channel_pickupgroup_set(tmp, i->pickupgroup); + ast_channel_call_forward_set(tmp, i->call_forward); + ast_channel_context_set(tmp, i->context); + ast_channel_exten_set(tmp, i->exten); + /* Don't use ast_set_callerid() here because it will + * generate a needless NewCallerID event */ + if (!ast_strlen_zero(i->cid_num)) { + ast_channel_caller(tmp)->ani.number.valid = 1; + ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num); + } + + if (!i->adsi) { + ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE); + } + ast_channel_priority_set(tmp, 1); + + /* Set channel variables for this call from configuration */ + for (v = i->chanvars ; v ; v = v->next) { + char valuebuf[1024]; + pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf))); + } - if (sub->rtp) { - ast_jb_configure(tmp, &global_jbconf); - } + if (sub->rtp) { + ast_jb_configure(tmp, &global_jbconf); + } - ast_channel_stage_snapshot_done(tmp); - ast_channel_unlock(tmp); + ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); - if (state != AST_STATE_DOWN) { - if (ast_pbx_start(tmp)) { - ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); - ast_hangup(tmp); - tmp = NULL; - } + if (state != AST_STATE_DOWN) { + if (ast_pbx_start(tmp)) { + ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); + ast_hangup(tmp); + tmp = NULL; } - ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", - ast_channel_name(tmp), ast_state2str(state)); - } else { - ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); } + ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", + ast_channel_name(tmp), ast_state2str(state)); + return tmp; } @@ -1973,7 +1999,9 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req) int codec, codec_count=0; int iterator; struct mgcp_endpoint *p = sub->parent; - char tmp1[256], tmp2[256], tmp3[256]; + struct ast_str *global_buf = ast_str_alloca(64); + struct ast_str *peer_buf = ast_str_alloca(64); + struct ast_str *pvt_buf = ast_str_alloca(64); /* Get codec and RTP info from SDP */ m = get_sdp(req, "m"); @@ -2030,20 +2058,20 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req) } /* Now gather all of the codecs that were asked for: */ - if (!(peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) { + if (!(peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return -1; } ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability); - ast_format_cap_joint_copy(global_capability, peercap, p->cap); + ast_format_cap_get_compatible(global_capability, peercap, p->cap); ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n", - ast_getformatname_multiple(tmp1, sizeof(tmp1), global_capability), - ast_getformatname_multiple(tmp2, sizeof(tmp2), peercap), - ast_getformatname_multiple(tmp3, sizeof(tmp3), p->cap)); - peercap = ast_format_cap_destroy(peercap); + ast_format_cap_get_names(global_capability, &global_buf), + ast_format_cap_get_names(peercap, &peer_buf), + ast_format_cap_get_names(p->cap, &pvt_buf)); + ao2_ref(peercap, -1); ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n", nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); - if (ast_format_cap_is_empty(p->cap)) { + if (!ast_format_cap_count(p->cap)) { ast_log(LOG_WARNING, "No compatible codecs!\n"); return -1; } @@ -2201,7 +2229,6 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc char m[256] = ""; char a[1024] = ""; int x; - struct ast_format tmpfmt; struct sockaddr_in dest = { 0, }; struct ast_sockaddr dest_tmp; struct mgcp_endpoint *p = sub->parent; @@ -2236,24 +2263,25 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc ast_copy_string(t, "t=0 0\r\n", sizeof(t)); snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); - ast_format_cap_iter_start(p->cap); - while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { - if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { - /* Audio is now discontiguous */ + for (x = 0; x < ast_format_cap_count(p->cap); x++) { + struct ast_format *format = ast_format_cap_get_format(p->cap, x); + + if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) { + ao2_ref(format, -1); continue; } - if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { - ast_debug(1, "Answering with capability %s\n", ast_getformatname(&tmpfmt)); - codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &tmpfmt, 0); - if (codec > -1) { - snprintf(costr, sizeof(costr), " %d", codec); - strncat(m, costr, sizeof(m) - strlen(m) - 1); - snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); - strncat(a, costr, sizeof(a) - strlen(a) - 1); - } + + ast_debug(1, "Answering with capability %s\n", ast_format_get_name(format)); + codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, format, 0); + if (codec > -1) { + snprintf(costr, sizeof(costr), " %d", codec); + strncat(m, costr, sizeof(m) - strlen(m) - 1); + snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, format, 0, 0)); + strncat(a, costr, sizeof(a) - strlen(a) - 1); } + + ao2_ref(format, -1); } - ast_format_cap_iter_end(p->cap); for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { if (p->nonCodecCapability & x) { @@ -2292,7 +2320,7 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_ char local[256]; char tmp[80]; struct mgcp_endpoint *p = sub->parent; - struct ast_format tmpfmt; + int i; struct ast_sockaddr sub_tmpdest_tmp; unsigned int oseq; @@ -2304,18 +2332,20 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_ return 0; } ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); - ast_format_cap_iter_start(p->cap); - while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { - if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { - /* Audio is now discontiguous */ + + for (i = 0; i < ast_format_cap_count(p->cap); i++) { + struct ast_format *format = ast_format_cap_get_format(p->cap, i); + + if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) { + ao2_ref(format, -1); continue; } - if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); - strncat(local, tmp, sizeof(local) - strlen(local) - 1); - } + + snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0)); + strncat(local, tmp, sizeof(local) - strlen(local) - 1); + + ao2_ref(format, -1); } - ast_format_cap_iter_end(p->cap); if (sub->gate) { if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { @@ -2351,7 +2381,7 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp struct mgcp_request resp; char local[256]; char tmp[80]; - struct ast_format tmpfmt; + int i; struct mgcp_endpoint *p = sub->parent; unsigned int oseq; @@ -2360,18 +2390,19 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); - ast_format_cap_iter_start(p->cap); - while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { - if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { - /* Audio is now discontiguous */ + for (i = 0; i < ast_format_cap_count(p->cap); i++) { + struct ast_format *format = ast_format_cap_get_format(p->cap, i); + + if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) { + ao2_ref(format, -1); continue; } - if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); - strncat(local, tmp, sizeof(local) - strlen(local) - 1); - } + + snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0)); + strncat(local, tmp, sizeof(local) - strlen(local) - 1); + + ao2_ref(format, -1); } - ast_format_cap_iter_end(p->cap); if (sub->gate) { if(sub->gate->state == GATE_ALLOCATED) { @@ -2447,22 +2478,23 @@ static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub) static int transmit_connect(struct mgcp_subchannel *sub) { struct mgcp_request resp; + int x; char local[256]; char tmp[80]; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; struct mgcp_endpoint *p = sub->parent; unsigned int oseq; ast_copy_string(local, "p:20, s:off, e:on", sizeof(local)); - ast_format_cap_iter_start(p->cap); - while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { - if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); - strncat(local, tmp, sizeof(local) - strlen(local) - 1); - } + for (x = 0; x < ast_format_cap_count(p->cap); x++) { + tmpfmt = ast_format_cap_get_format(p->cap, x); + + snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, tmpfmt, 0, 0)); + strncat(local, tmp, sizeof(local) - strlen(local) - 1); + + ao2_ref(tmpfmt, -1); } - ast_format_cap_iter_end(p->cap); ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); @@ -2557,7 +2589,7 @@ static int transmit_modify_request(struct mgcp_subchannel *sub) { struct mgcp_request resp; struct mgcp_endpoint *p = sub->parent; - struct ast_format tmpfmt; + int i; int fc = 1; char local[256]; char tmp[80]; @@ -2572,18 +2604,22 @@ static int transmit_modify_request(struct mgcp_subchannel *sub) p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); ast_copy_string(local, "", sizeof(local)); - ast_format_cap_iter_start(p->cap); - while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { + for (i = 0; i < ast_format_cap_count(p->cap); i++) { + struct ast_format *format = ast_format_cap_get_format(p->cap, i); + if (p->ncs && !fc) { - ast_format_cap_set(p->cap, &tmpfmt); /* sb5120e bug */ + ast_format_cap_remove_by_type(p->cap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(p->cap, format, 0); /* sb5120e bug */ + ao2_ref(format, -1); break; } else { fc = 0; - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); + snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0)); } strncat(local, tmp, sizeof(local) - strlen(local) - 1); + + ao2_ref(format, -1); } - ast_format_cap_iter_end(p->cap); if (!sub->sdpsent) { if (sub->gate) { @@ -3948,8 +3984,10 @@ static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap struct ast_channel *tmpc = NULL; char tmp[256]; - if (!(ast_format_cap_has_joint(cap, global_capability))) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); + if (!(ast_format_cap_iscompatible(cap, global_capability))) { + struct ast_str *cap_buf = ast_str_alloca(64); + ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", + ast_format_cap_get_names(cap, &cap_buf)); /*return NULL;*/ } ast_copy_string(tmp, dest, sizeof(tmp)); @@ -4185,7 +4223,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) ast_mutex_init(&e->lock); ast_mutex_init(&e->rqnt_queue_lock); ast_mutex_init(&e->cmd_queue_lock); - e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); ast_copy_string(e->name, v->value, sizeof(e->name)); e->needaudit = 1; } @@ -4210,7 +4248,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random()); e->msgstate = -1; e->amaflags = amaflags; - ast_format_cap_copy(e->cap, global_capability); + ast_format_cap_append_from_cap(e->cap, global_capability, AST_MEDIA_TYPE_UNKNOWN); e->parent = gw; e->ncs = ncs; e->dtmfmode = dtmfmode; @@ -4292,7 +4330,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) ast_mutex_init(&e->lock); ast_mutex_init(&e->rqnt_queue_lock); ast_mutex_init(&e->cmd_queue_lock); - e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); ast_copy_string(e->name, v->value, sizeof(e->name)); e->needaudit = 1; } @@ -4314,7 +4352,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) e->parent = gw; } e->amaflags = amaflags; - ast_format_cap_copy(e->cap, global_capability); + ast_format_cap_append_from_cap(e->cap, global_capability, AST_MEDIA_TYPE_UNKNOWN); e->dtmfmode = dtmfmode; e->ncs = ncs; e->pktcgatealloc = pktcgatealloc; @@ -4470,7 +4508,8 @@ static void mgcp_get_codec(struct ast_channel *chan, struct ast_format_cap *resu { struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan); struct mgcp_endpoint *p = sub->parent; - ast_format_cap_copy(result, p->cap); + + ast_format_cap_append_from_cap(result, p->cap, AST_MEDIA_TYPE_UNKNOWN); } static struct ast_rtp_glue mgcp_rtp_glue = { @@ -4556,7 +4595,7 @@ static void destroy_endpoint(struct mgcp_endpoint *e) ast_mutex_destroy(&e->lock); ast_mutex_destroy(&e->rqnt_queue_lock); ast_mutex_destroy(&e->cmd_queue_lock); - e->cap = ast_format_cap_destroy(e->cap); + ao2_ref(e->cap, -1); ast_free(e); } @@ -4654,7 +4693,6 @@ static int reload_config(int reload) char *cat; struct ast_hostent ahp; struct hostent *hp; - struct ast_format format; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; if (gethostname(ourhost, sizeof(ourhost)-1)) { @@ -4694,19 +4732,9 @@ static int reload_config(int reload) memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); } } else if (!strcasecmp(v->name, "allow")) { - ast_getformatbyname(v->value, &format); - if (!format.id) { - ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); - } else { - ast_format_cap_add(global_capability, &format); - } + ast_format_cap_update_by_allow_disallow(global_capability, v->value, 1); } else if (!strcasecmp(v->name, "disallow")) { - ast_getformatbyname(v->value, &format); - if (!format.id) { - ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); - } else { - ast_format_cap_remove(global_capability, &format); - } + ast_format_cap_update_by_allow_disallow(global_capability, v->value, 0); } else if (!strcasecmp(v->name, "tos")) { if (ast_str2tos(v->value, &qos.tos)) { ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); @@ -4831,36 +4859,44 @@ static int reload_config(int reload) */ static int load_module(void) { - struct ast_format tmpfmt; - - if (!(global_capability = ast_format_cap_alloc(0))) { + if (!(global_capability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_FAILURE; } - if (!(mgcp_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(mgcp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { + ao2_ref(global_capability, -1); return AST_MODULE_LOAD_FAILURE; } - ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + ast_format_cap_append(global_capability, ast_format_ulaw, 0); + ast_format_cap_append(mgcp_tech.capabilities, ast_format_ulaw, 0); + ast_format_cap_append(mgcp_tech.capabilities, ast_format_alaw, 0); if (!(sched = ast_sched_context_create())) { ast_log(LOG_WARNING, "Unable to create schedule context\n"); + ao2_ref(global_capability, -1); + ao2_ref(mgcp_tech.capabilities, -1); return AST_MODULE_LOAD_FAILURE; } if (!(io = io_context_create())) { ast_log(LOG_WARNING, "Unable to create I/O context\n"); ast_sched_context_destroy(sched); + ao2_ref(global_capability, -1); + ao2_ref(mgcp_tech.capabilities, -1); return AST_MODULE_LOAD_FAILURE; } - if (reload_config(0)) + if (reload_config(0)) { + ao2_ref(global_capability, -1); + ao2_ref(mgcp_tech.capabilities, -1); return AST_MODULE_LOAD_DECLINE; + } /* Make sure we can register our mgcp channel type */ if (ast_channel_register(&mgcp_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); io_context_destroy(io); ast_sched_context_destroy(sched); + ao2_ref(global_capability, -1); + ao2_ref(mgcp_tech.capabilities, -1); return AST_MODULE_LOAD_FAILURE; } @@ -4973,8 +5009,10 @@ static int unload_module(void) ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); ast_sched_context_destroy(sched); - global_capability = ast_format_cap_destroy(global_capability); - mgcp_tech.capabilities = ast_format_cap_destroy(mgcp_tech.capabilities); + ao2_ref(global_capability, -1); + global_capability = NULL; + ao2_ref(mgcp_tech.capabilities, -1); + mgcp_tech.capabilities = NULL; return 0; } diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 47d5947c3..0774e3c15 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -120,6 +120,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/features_config.h" #include "asterisk/bridge.h" #include "asterisk/pickup.h" +#include "asterisk/format_cache.h" #include "chan_misdn_config.h" #include "isdn_lib.h" @@ -691,9 +692,6 @@ static const char misdn_type[] = "mISDN"; static int tracing = 0; -/*! \brief Only alaw and mulaw is allowed for now */ -static struct ast_format prefformat; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */ - static int *misdn_debug; static int *misdn_debug_only; static int max_ports; @@ -7436,7 +7434,7 @@ static struct ast_frame *misdn_read(struct ast_channel *ast) } tmp->frame.frametype = AST_FRAME_VOICE; - ast_format_set(&tmp->frame.subclass.format, AST_FORMAT_ALAW, 0); + tmp->frame.subclass.format = ast_format_alaw; tmp->frame.datalen = len; tmp->frame.samples = len; tmp->frame.mallocd = 0; @@ -7501,13 +7499,14 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame) } - if (!frame->subclass.format.id) { + if (!frame->subclass.format) { chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n"); return 0; } - if (ast_format_cmp(&frame->subclass.format, &prefformat) == AST_FORMAT_CMP_NOT_EQUAL) { - chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(&frame->subclass.format)); + if (ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL) { + chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", + ast_format_get_name(frame->subclass.format)); return 0; } @@ -8174,12 +8173,18 @@ static void update_name(struct ast_channel *tmp, int port, int c) static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int port, int c) { + struct ast_format_cap *native; struct ast_channel *tmp; char *cid_name = NULL; char *cid_num = NULL; int chan_offset = 0; int tmp_port = misdn_cfg_get_next_port(0); - struct ast_format tmpfmt; + struct ast_format *tmpfmt; + + native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!native) { + return NULL; + } for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) { if (tmp_port == port) { @@ -8199,12 +8204,15 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char if (tmp) { chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid); - ast_best_codec(cap, &tmpfmt); - ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat); - ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_readformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); + tmpfmt = ast_format_cap_get_format(cap, 0); + ast_format_cap_append(native, ast_format_alaw, 0); + ast_channel_nativeformats_set(tmp, native); + ast_channel_set_writeformat(tmp, tmpfmt); + ast_channel_set_rawwriteformat(tmp, tmpfmt); + ast_channel_set_readformat(tmp, tmpfmt); + ast_channel_set_rawreadformat(tmp, tmpfmt); + + ao2_ref(tmpfmt, -1); /* Link the channel and private together */ chan_list_ref(chlist, "Give a reference to ast_channel"); @@ -8242,6 +8250,8 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char chan_misdn_log(-1, 0, "Unable to allocate channel structure\n"); } + ao2_ref(native, -1); + return tmp; } @@ -10207,14 +10217,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ch->addr = bc->addr; { - struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - struct ast_format tmpfmt; + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!(cap)) { return RESPONSE_ERR; } - ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + ast_format_cap_append(cap, ast_format_alaw, 0); chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, NULL, bc->port, bc->channel); - cap = ast_format_cap_destroy(cap); + ao2_ref(cap, -1); } if (!chan) { chan_list_unref(ch, "Failed to create a new channel"); @@ -10849,7 +10858,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) /* In Data Modes we queue frames */ memset(&frame, 0, sizeof(frame)); frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */ - ast_format_set(&frame.subclass.format, AST_FORMAT_ALAW, 0); + frame.subclass.format = ast_format_alaw; frame.datalen = bc->bframe_len; frame.samples = bc->bframe_len; frame.mallocd = 0; @@ -11287,7 +11296,8 @@ static int unload_module(void) #if defined(AST_MISDN_ENHANCEMENTS) misdn_cc_destroy(); #endif /* defined(AST_MISDN_ENHANCEMENTS) */ - misdn_tech.capabilities = ast_format_cap_destroy(misdn_tech.capabilities); + ao2_cleanup(misdn_tech.capabilities); + misdn_tech.capabilities = NULL; return 0; } @@ -11316,11 +11326,10 @@ static int load_module(void) }; - if (!(misdn_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(misdn_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - ast_format_set(&prefformat, AST_FORMAT_ALAW, 0); - ast_format_cap_add(misdn_tech.capabilities, &prefformat); + ast_format_cap_append(misdn_tech.capabilities, ast_format_alaw, 0); max_ports = misdn_lib_maxports_get(); diff --git a/channels/chan_motif.c b/channels/chan_motif.c index d853839ab..4b1d7d26b 100644 --- a/channels/chan_motif.c +++ b/channels/chan_motif.c @@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/abstract_jb.h" #include "asterisk/xmpp.h" #include "asterisk/stasis_channels.h" +#include "asterisk/format_cache.h" /*** DOCUMENTATION <configInfo name="chan_motif" language="en_US"> @@ -286,7 +287,6 @@ struct jingle_endpoint { iksrule *rule; /*!< Active matching rule */ unsigned int maxicecandidates; /*!< Maximum number of ICE candidates we will offer */ unsigned int maxpayloads; /*!< Maximum number of payloads we will offer */ - struct ast_codec_pref prefs; /*!< Codec preferences */ struct ast_format_cap *cap; /*!< Formats to use */ ast_group_t callgroup; /*!< Call group */ ast_group_t pickupgroup; /*!< Pickup group */ @@ -309,7 +309,6 @@ struct jingle_session { char remote_original[XMPP_MAX_JIDLEN];/*!< Identifier of the original remote party (remote may have changed due to redirect) */ char remote[XMPP_MAX_JIDLEN]; /*!< Identifier of the remote party */ iksrule *rule; /*!< Session matching rule */ - struct ast_codec_pref prefs; /*!< Codec preferences */ struct ast_channel *owner; /*!< Master Channel */ struct ast_rtp_instance *rtp; /*!< RTP audio session */ struct ast_rtp_instance *vrtp; /*!< RTP video session */ @@ -454,8 +453,7 @@ static void jingle_endpoint_destructor(void *obj) ast_xmpp_client_unref(endpoint->connection); } - ast_format_cap_destroy(endpoint->cap); - + ao2_cleanup(endpoint->cap); ao2_ref(endpoint->state, -1); ast_string_field_free_memory(endpoint); @@ -519,7 +517,7 @@ static void *jingle_endpoint_alloc(const char *cat) ast_string_field_set(endpoint, name, cat); - endpoint->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + endpoint->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); endpoint->transport = JINGLE_TRANSPORT_ICE_UDP; return endpoint; @@ -583,9 +581,9 @@ static void jingle_session_destructor(void *obj) ast_rtp_instance_destroy(session->vrtp); } - ast_format_cap_destroy(session->cap); - ast_format_cap_destroy(session->jointcap); - ast_format_cap_destroy(session->peercap); + ao2_cleanup(session->cap); + ao2_cleanup(session->jointcap); + ao2_cleanup(session->peercap); if (session->callid) { ast_callid_unref(session->callid); @@ -681,7 +679,7 @@ static void jingle_enable_video(struct jingle_session *session) } /* If there are no configured video codecs do not turn video support on, it just won't work */ - if (!ast_format_cap_has_type(session->cap, AST_FORMAT_TYPE_VIDEO)) { + if (!ast_format_cap_has_type(session->cap, AST_MEDIA_TYPE_VIDEO)) { return; } @@ -695,8 +693,8 @@ static void jingle_enable_video(struct jingle_session *session) ast_rtp_instance_set_channel_id(session->vrtp, ast_channel_uniqueid(session->owner)); ast_channel_set_fd(session->owner, 2, ast_rtp_instance_fd(session->vrtp, 0)); ast_channel_set_fd(session->owner, 3, ast_rtp_instance_fd(session->vrtp, 1)); - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->vrtp), session->vrtp, &session->prefs); - + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(session->vrtp), + ast_format_cap_get_framing(session->cap)); if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) { ice->stop(session->vrtp); } @@ -741,15 +739,15 @@ static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, con session->connection = endpoint->connection; session->transport = endpoint->transport; - if (!(session->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) || - !(session->jointcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) || - !(session->peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) || + if (!(session->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) || + !(session->jointcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) || + !(session->peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) || !session->callid) { ao2_ref(session, -1); return NULL; } - ast_format_cap_copy(session->cap, endpoint->cap); + ast_format_cap_append_from_cap(session->cap, endpoint->cap, AST_MEDIA_TYPE_UNKNOWN); /* While we rely on res_xmpp for communication we still need a temporary ast_sockaddr to tell the RTP engine * that we want IPv4 */ @@ -763,8 +761,6 @@ static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, con ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_DTMF, 1); - memcpy(&session->prefs, &endpoint->prefs, sizeof(session->prefs)); - session->maxicecandidates = endpoint->maxicecandidates; session->maxpayloads = endpoint->maxpayloads; @@ -776,13 +772,20 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j { struct ast_channel *chan; const char *str = S_OR(title, session->remote); - struct ast_format tmpfmt; + struct ast_format_cap *caps; + struct ast_format *tmpfmt; + + if (!ast_format_cap_count(session->cap)) { + return NULL; + } - if (ast_format_cap_is_empty(session->cap)) { + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { return NULL; } if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) { + ao2_ref(caps, -1); return NULL; } @@ -794,15 +797,17 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j ast_channel_callid_set(chan, session->callid); - ast_format_cap_copy(ast_channel_nativeformats(chan), session->cap); - ast_codec_choose(&session->prefs, session->cap, 1, &tmpfmt); + ast_format_cap_append_from_cap(caps, session->cap, AST_MEDIA_TYPE_UNKNOWN); + ast_channel_nativeformats_set(chan, caps); + ao2_ref(caps, -1); if (session->rtp) { struct ast_rtp_engine_ice *ice; ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(session->rtp, 0)); ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(session->rtp, 1)); - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->rtp), session->rtp, &session->prefs); + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(session->rtp), + ast_format_cap_get_framing(session->cap)); if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) && @@ -818,11 +823,12 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j ast_channel_adsicpe_set(chan, AST_ADSI_UNAVAILABLE); - ast_best_codec(ast_channel_nativeformats(chan), &tmpfmt); - ast_format_copy(ast_channel_writeformat(chan), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(chan), &tmpfmt); - ast_format_copy(ast_channel_readformat(chan), &tmpfmt); - ast_format_copy(ast_channel_rawreadformat(chan), &tmpfmt); + tmpfmt = ast_format_cap_get_format(session->cap, 0); + ast_channel_set_writeformat(chan, tmpfmt); + ast_channel_set_rawwriteformat(chan, tmpfmt); + ast_channel_set_readformat(chan, tmpfmt); + ast_channel_set_rawreadformat(chan, tmpfmt); + ao2_ref(tmpfmt, -1); ao2_lock(endpoint); @@ -1300,30 +1306,24 @@ static void jingle_send_transport_info(struct jingle_session *session, const cha } /*! \brief Internal helper function which adds payloads to a description */ -static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_format_type type) +static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_media_type type) { - struct ast_format format; int x = 0, i = 0, res = 0; - for (x = 0; (x < AST_CODEC_PREF_SIZE) && (i < (session->maxpayloads - 2)); x++) { + for (x = 0; (x < ast_format_cap_count(session->jointcap)) && (i < (session->maxpayloads - 2)); x++) { + struct ast_format *format = ast_format_cap_get_format(session->jointcap, x); int rtp_code; iks *payload; char tmp[32]; - if (!ast_codec_pref_index(&session->prefs, x, &format)) { - break; - } - - if (AST_FORMAT_GET_TYPE(format.id) != type) { - continue; - } - - if (!ast_format_cap_iscompatible(session->jointcap, &format)) { + if (ast_format_get_type(format) != type) { + ao2_ref(format, -1); continue; } - if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, &format, 0)) == -1) || + if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, format, 0)) == -1) || (!(payload = iks_new("payload-type")))) { + ao2_ref(format, -1); return -1; } @@ -1333,17 +1333,18 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st snprintf(tmp, sizeof(tmp), "%d", rtp_code); iks_insert_attrib(payload, "id", tmp); - iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, &format, 0, 0)); + iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, format, 0, 0)); iks_insert_attrib(payload, "channels", "1"); - if ((format.id == AST_FORMAT_G722) && ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) { + if ((ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) && + ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) { iks_insert_attrib(payload, "clockrate", "16000"); } else { - snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, &format, 0)); + snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, format, 0)); iks_insert_attrib(payload, "clockrate", tmp); } - if ((type == AST_FORMAT_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) { + if ((type == AST_MEDIA_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) { iks *parameter; /* Google requires these parameters to be set, but alas we can not give accurate values so use some safe defaults */ @@ -1366,9 +1367,11 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st iks_insert_node(description, payload); payloads[i++] = payload; + + ao2_ref(format, -1); } /* If this is for audio and there is room for RFC2833 add it in */ - if ((type == AST_FORMAT_TYPE_AUDIO) && (i < session->maxpayloads)) { + if ((type == AST_MEDIA_TYPE_AUDIO) && (i < session->maxpayloads)) { iks *payload; if ((payload = iks_new("payload-type"))) { @@ -1390,7 +1393,7 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st /*! \brief Helper function which adds content to a description */ static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *content, iks *description, iks *transport, - const char *name, enum ast_format_type type, struct ast_rtp_instance *rtp, iks **payloads) + const char *name, enum ast_media_type type, struct ast_rtp_instance *rtp, iks **payloads) { int res = 0; @@ -1400,9 +1403,9 @@ static int jingle_add_content(struct jingle_session *session, iks *jingle, iks * iks_insert_node(jingle, content); iks_insert_attrib(description, "xmlns", JINGLE_RTP_NS); - if (type == AST_FORMAT_TYPE_AUDIO) { + if (type == AST_MEDIA_TYPE_AUDIO) { iks_insert_attrib(description, "media", "audio"); - } else if (type == AST_FORMAT_TYPE_VIDEO) { + } else if (type == AST_MEDIA_TYPE_VIDEO) { iks_insert_attrib(description, "media", "video"); } else { return -1; @@ -1469,7 +1472,7 @@ static void jingle_send_session_action(struct jingle_session *session, const cha if (session->rtp && (audio = iks_new("content")) && (audio_description = iks_new("description")) && (audio_transport = iks_new("transport"))) { res = jingle_add_content(session, jingle, audio, audio_description, audio_transport, session->audio_name, - AST_FORMAT_TYPE_AUDIO, session->rtp, audio_payloads); + AST_MEDIA_TYPE_AUDIO, session->rtp, audio_payloads); } else { ast_log(LOG_ERROR, "Failed to allocate audio content stanzas for session '%s', hanging up\n", session->sid); res = -1; @@ -1479,7 +1482,7 @@ static void jingle_send_session_action(struct jingle_session *session, const cha if ((video = iks_new("content")) && (video_description = iks_new("description")) && (video_transport = iks_new("transport"))) { res = jingle_add_content(session, jingle, video, video_description, video_transport, session->video_name, - AST_FORMAT_TYPE_VIDEO, session->vrtp, video_payloads); + AST_MEDIA_TYPE_VIDEO, session->vrtp, video_payloads); } else { ast_log(LOG_ERROR, "Failed to allocate video content stanzas for session '%s', hanging up\n", session->sid); res = -1; @@ -1668,17 +1671,24 @@ static struct ast_frame *jingle_read(struct ast_channel *ast) } if (frame && frame->frametype == AST_FRAME_VOICE && - !ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format)) { - if (!ast_format_cap_iscompatible(session->jointcap, &frame->subclass.format)) { + ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + if (ast_format_cap_iscompatible_format(session->jointcap, frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n", - ast_getformatname(&frame->subclass.format), ast_channel_name(ast)); + ast_format_get_name(frame->subclass.format), ast_channel_name(ast)); ast_frfree(frame); frame = &ast_null_frame; } else { + struct ast_format_cap *caps; + ast_debug(1, "Oooh, format changed to %s\n", - ast_getformatname(&frame->subclass.format)); - ast_format_cap_remove_bytype(ast_channel_nativeformats(ast), AST_FORMAT_TYPE_AUDIO); - ast_format_cap_add(ast_channel_nativeformats(ast), &frame->subclass.format); + ast_format_get_name(frame->subclass.format)); + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + ast_format_cap_append(caps, frame->subclass.format, 0); + ast_channel_nativeformats_set(ast, caps); + ao2_ref(caps, -1); + } ast_set_read_format(ast, ast_channel_readformat(ast)); ast_set_write_format(ast, ast_channel_writeformat(ast)); } @@ -1692,17 +1702,18 @@ static int jingle_write(struct ast_channel *ast, struct ast_frame *frame) { struct jingle_session *session = ast_channel_tech_pvt(ast); int res = 0; - char buf[256]; switch (frame->frametype) { case AST_FRAME_VOICE: - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) { + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *codec_buf = ast_str_alloca(64); + ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(&frame->subclass.format), - ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)), - ast_getformatname(ast_channel_readformat(ast)), - ast_getformatname(ast_channel_writeformat(ast))); + ast_format_get_name(frame->subclass.format), + ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf), + ast_format_get_name(ast_channel_readformat(ast)), + ast_format_get_name(ast_channel_writeformat(ast))); return 0; } if (session && session->rtp) { @@ -1845,7 +1856,7 @@ static int jingle_call(struct ast_channel *ast, const char *dest, int timeout) ast_setstate(ast, AST_STATE_RING); /* Since we have no idea of the remote capabilities use ours for now */ - ast_format_cap_copy(session->jointcap, session->cap); + ast_format_cap_append_from_cap(session->jointcap, session->cap, AST_MEDIA_TYPE_UNKNOWN); /* We set up a hook so we can know when our session-initiate message was accepted or rejected */ session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session, @@ -1908,7 +1919,7 @@ static struct ast_channel *jingle_request(const char *type, struct ast_format_ca ); /* We require at a minimum one audio format to be requested */ - if (!ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO)) { + if (!ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO)) { ast_log(LOG_ERROR, "Motif channel driver requires an audio format when dialing a destination\n"); *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; return NULL; @@ -2001,7 +2012,7 @@ static struct ast_channel *jingle_request(const char *type, struct ast_format_ca } /* If video was requested try to enable it on the session */ - if (ast_format_cap_has_type(cap, AST_FORMAT_TYPE_VIDEO)) { + if (ast_format_cap_has_type(cap, AST_MEDIA_TYPE_VIDEO)) { jingle_enable_video(session); } @@ -2043,8 +2054,8 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des ast_string_field_set(session, audio_name, name); } *rtp = session->rtp; - ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_AUDIO); - ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_remove_by_type(session->peercap, AST_MEDIA_TYPE_AUDIO); + ast_format_cap_remove_by_type(session->jointcap, AST_MEDIA_TYPE_AUDIO); } else if (!strcasecmp(media, "video")) { if (!ast_strlen_zero(name)) { ast_string_field_set(session, video_name, name); @@ -2060,8 +2071,8 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des return -1; } - ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_VIDEO); - ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_VIDEO); + ast_format_cap_remove_by_type(session->peercap, AST_MEDIA_TYPE_VIDEO); + ast_format_cap_remove_by_type(session->jointcap, AST_MEDIA_TYPE_VIDEO); } else { /* Unknown media type */ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); @@ -2082,8 +2093,6 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des int rtp_id, rtp_clockrate; if (!ast_strlen_zero(id) && !ast_strlen_zero(name) && (sscanf(id, "%30d", &rtp_id) == 1)) { - ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, rtp_id); - if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) { ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, name, 0, rtp_clockrate); } else { @@ -2093,9 +2102,9 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des } ast_rtp_codecs_payload_formats(&codecs, session->peercap, &othercapability); - ast_format_cap_joint_append(session->cap, session->peercap, session->jointcap); + ast_format_cap_get_compatible(session->cap, session->peercap, session->jointcap); - if (ast_format_cap_is_empty(session->jointcap)) { + if (!ast_format_cap_count(session->jointcap)) { /* We have no compatible codecs, so terminate the session appropriately */ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); ast_rtp_codecs_payloads_destroy(&codecs); @@ -2355,12 +2364,20 @@ static int jingle_interpret_content(struct jingle_session *session, ikspak *pak) } if ((chan = jingle_session_lock_full(session))) { - struct ast_format fmt; + struct ast_format_cap *caps; + struct ast_format *fmt; + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + ast_format_cap_append_from_cap(caps, session->jointcap, AST_MEDIA_TYPE_UNKNOWN); + ast_channel_nativeformats_set(chan, caps); + ao2_ref(caps, -1); + } - ast_format_cap_copy(ast_channel_nativeformats(chan), session->jointcap); - ast_codec_choose(&session->prefs, session->jointcap, 1, &fmt); - ast_set_read_format(chan, &fmt); - ast_set_write_format(chan, &fmt); + fmt = ast_format_cap_get_format(session->jointcap, 0); + ast_set_read_format(chan, fmt); + ast_set_write_format(chan, fmt); + ao2_ref(fmt, -1); ast_channel_unlock(chan); ast_channel_unref(chan); @@ -2710,7 +2727,7 @@ static int custom_transport_handler(const struct aco_option *opt, struct ast_var */ static int load_module(void) { - if (!(jingle_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(jingle_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } @@ -2726,8 +2743,8 @@ static int load_module(void) aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass)); aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot)); aco_option_register(&cfg_info, "accountcode", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, accountcode)); - aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, prefs, cap)); - aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, prefs, cap)); + aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, cap)); + aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, cap)); aco_option_register_custom(&cfg_info, "connection", ACO_EXACT, endpoint_options, NULL, custom_connection_handler, 0); aco_option_register_custom(&cfg_info, "transport", ACO_EXACT, endpoint_options, NULL, custom_transport_handler, 0); aco_option_register(&cfg_info, "maxicecandidates", ACO_EXACT, endpoint_options, DEFAULT_MAX_ICE_CANDIDATES, OPT_UINT_T, PARSE_DEFAULT, @@ -2735,9 +2752,10 @@ static int load_module(void) aco_option_register(&cfg_info, "maxpayloads", ACO_EXACT, endpoint_options, DEFAULT_MAX_PAYLOADS, OPT_UINT_T, PARSE_DEFAULT, FLDSET(struct jingle_endpoint, maxpayloads), DEFAULT_MAX_PAYLOADS); - ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_append_by_type(jingle_tech.capabilities, AST_MEDIA_TYPE_AUDIO); if (aco_process_config(&cfg_info, 0)) { + ao2_ref(jingle_tech.capabilities, -1); ast_log(LOG_ERROR, "Unable to read config file motif.conf. Module loaded but not running.\n"); aco_info_destroy(&cfg_info); return AST_MODULE_LOAD_DECLINE; @@ -2763,6 +2781,7 @@ static int load_module(void) return 0; end: + ao2_cleanup(jingle_tech.capabilities); ast_rtp_glue_unregister(&jingle_rtp_glue); if (sched) { @@ -2784,7 +2803,7 @@ static int reload(void) static int unload_module(void) { ast_channel_unregister(&jingle_tech); - ast_format_cap_destroy(jingle_tech.capabilities); + ao2_cleanup(jingle_tech.capabilities); jingle_tech.capabilities = NULL; ast_rtp_glue_unregister(&jingle_rtp_glue); ast_sched_context_destroy(sched); diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c index 730b2f459..ae6022cb6 100644 --- a/channels/chan_multicast_rtp.c +++ b/channels/chan_multicast_rtp.c @@ -117,8 +117,10 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo struct ast_sockaddr control_address; struct ast_sockaddr destination_address; struct ast_channel *chan; - struct ast_format fmt; - ast_best_codec(cap, &fmt); + struct ast_format_cap *caps = NULL; + struct ast_format *fmt = NULL; + + fmt = ast_format_cap_get_format(cap, 0); ast_sockaddr_setnull(&control_address); @@ -145,6 +147,11 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo goto failure; } + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + goto failure; + } + if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, multicast_type))) { goto failure; } @@ -158,19 +165,25 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo ast_channel_tech_set(chan, &multicast_rtp_tech); - ast_format_cap_add(ast_channel_nativeformats(chan), &fmt); - ast_format_copy(ast_channel_writeformat(chan), &fmt); - ast_format_copy(ast_channel_rawwriteformat(chan), &fmt); - ast_format_copy(ast_channel_readformat(chan), &fmt); - ast_format_copy(ast_channel_rawreadformat(chan), &fmt); + ast_format_cap_append(caps, fmt, 0); + ast_channel_nativeformats_set(chan, caps); + ast_channel_set_writeformat(chan, fmt); + ast_channel_set_rawwriteformat(chan, fmt); + ast_channel_set_readformat(chan, fmt); + ast_channel_set_rawreadformat(chan, fmt); ast_channel_tech_pvt_set(chan, instance); ast_channel_unlock(chan); + ao2_ref(fmt, -1); + ao2_ref(caps, -1); + return chan; failure: + ao2_cleanup(fmt); + ao2_cleanup(caps); *cause = AST_CAUSE_FAILURE; return NULL; } @@ -178,12 +191,14 @@ failure: /*! \brief Function called when our module is loaded */ static int load_module(void) { - if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add_all(multicast_rtp_tech.capabilities); + ast_format_cap_append_by_type(multicast_rtp_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); if (ast_channel_register(&multicast_rtp_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n"); + ao2_ref(multicast_rtp_tech.capabilities, -1); + multicast_rtp_tech.capabilities = NULL; return AST_MODULE_LOAD_DECLINE; } @@ -194,7 +209,8 @@ static int load_module(void) static int unload_module(void) { ast_channel_unregister(&multicast_rtp_tech); - multicast_rtp_tech.capabilities = ast_format_cap_destroy(multicast_rtp_tech.capabilities); + ao2_ref(multicast_rtp_tech.capabilities, -1); + multicast_rtp_tech.capabilities = NULL; return 0; } diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c index cbfb6b3c4..1be9bffeb 100644 --- a/channels/chan_nbs.c +++ b/channels/chan_nbs.c @@ -47,12 +47,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/module.h" #include "asterisk/pbx.h" #include "asterisk/utils.h" +#include "asterisk/format_cache.h" static const char tdesc[] = "Network Broadcast Sound Driver"; -/* Only linear is allowed */ -static struct ast_format prefformat; - static char context[AST_MAX_EXTENSION] = "default"; static const char type[] = "NBS"; @@ -63,7 +61,6 @@ struct nbs_pvt { struct ast_channel *owner; /* Channel we belong to, possibly NULL */ char app[16]; /* Our app */ char stream[80]; /* Our stream */ - struct ast_frame fr; /* "null" frame */ struct ast_module_user *u; /*! for holding a reference to this module */ }; @@ -178,37 +175,14 @@ static int nbs_hangup(struct ast_channel *ast) static struct ast_frame *nbs_xread(struct ast_channel *ast) { - struct nbs_pvt *p = ast_channel_tech_pvt(ast); - - - /* Some nice norms */ - p->fr.datalen = 0; - p->fr.samples = 0; - p->fr.data.ptr = NULL; - p->fr.src = type; - p->fr.offset = 0; - p->fr.mallocd=0; - p->fr.delivery.tv_sec = 0; - p->fr.delivery.tv_usec = 0; - ast_debug(1, "Returning null frame on %s\n", ast_channel_name(ast)); - return &p->fr; + return &ast_null_frame; } static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame) { struct nbs_pvt *p = ast_channel_tech_pvt(ast); - /* Write a frame of (presumably voice) data */ - if (frame->frametype != AST_FRAME_VOICE) { - if (frame->frametype != AST_FRAME_IMAGE) - ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); - return 0; - } - if (frame->subclass.format.id != (AST_FORMAT_SLINEAR)) { - ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format)); - return 0; - } if (ast_channel_state(ast) != AST_STATE_UP) { /* Don't try tos end audio on-hook */ return 0; @@ -226,11 +200,11 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const struct as ast_channel_tech_set(tmp, &nbs_tech); ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs)); - ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat); - ast_format_copy(ast_channel_rawreadformat(tmp), &prefformat); - ast_format_copy(ast_channel_rawwriteformat(tmp), &prefformat); - ast_format_copy(ast_channel_writeformat(tmp), &prefformat); - ast_format_copy(ast_channel_readformat(tmp), &prefformat); + ast_channel_nativeformats_set(tmp, nbs_tech.capabilities); + ast_channel_set_rawreadformat(tmp, ast_format_slin); + ast_channel_set_rawwriteformat(tmp, ast_format_slin); + ast_channel_set_writeformat(tmp, ast_format_slin); + ast_channel_set_readformat(tmp, ast_format_slin); if (state == AST_STATE_RING) ast_channel_rings_set(tmp, 1); ast_channel_tech_pvt_set(tmp, i); @@ -257,9 +231,11 @@ static struct ast_channel *nbs_request(const char *type, struct ast_format_cap * struct nbs_pvt *p; struct ast_channel *tmp = NULL; - if (!(ast_format_cap_iscompatible(cap, &prefformat))) { - char tmp[256]; - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); + if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *cap_buf = ast_str_alloca(64); + + ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", + ast_format_cap_get_names(cap, &cap_buf)); return NULL; } p = nbs_alloc(data); @@ -275,17 +251,17 @@ static int unload_module(void) { /* First, take us out of the channel loop */ ast_channel_unregister(&nbs_tech); - nbs_tech.capabilities = ast_format_cap_destroy(nbs_tech.capabilities); + ao2_ref(nbs_tech.capabilities, -1); + nbs_tech.capabilities = NULL; return 0; } static int load_module(void) { - ast_format_set(&prefformat, AST_FORMAT_SLINEAR, 0); - if (!(nbs_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(nbs_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_FAILURE; } - ast_format_cap_add(nbs_tech.capabilities, &prefformat); + ast_format_cap_append(nbs_tech.capabilities, ast_format_slin, 0); /* Make sure we can register our channel type */ if (ast_channel_register(&nbs_tech)) { ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); diff --git a/channels/chan_oss.c b/channels/chan_oss.c index 4459b4b6f..46b751d7c 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -69,6 +69,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/musiconhold.h" #include "asterisk/app.h" #include "asterisk/bridge.h" +#include "asterisk/format_cache.h" #include "console_video.h" @@ -726,7 +727,7 @@ static struct ast_frame *oss_read(struct ast_channel *c) return f; /* ok we can build and deliver the frame to the caller */ f->frametype = AST_FRAME_VOICE; - ast_format_set(&f->subclass.format, AST_FORMAT_SLINEAR, 0); + f->subclass.format = ao2_bump(ast_format_slin); f->samples = FRAME_SIZE; f->datalen = FRAME_SIZE * 2; f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET; @@ -804,9 +805,9 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx, setformat(o, O_RDWR); ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */ - ast_format_set(ast_channel_readformat(c), AST_FORMAT_SLINEAR, 0); - ast_format_set(ast_channel_writeformat(c), AST_FORMAT_SLINEAR, 0); - ast_format_cap_add(ast_channel_nativeformats(c), ast_channel_readformat(c)); + ast_channel_set_readformat(c, ast_format_slin); + ast_channel_set_writeformat(c, ast_format_slin); + ast_channel_nativeformats_set(c, oss_tech.capabilities); /* if the console makes the call, add video to the offer */ /* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER @@ -851,8 +852,6 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap * AST_APP_ARG(flags); ); char *parse = ast_strdupa(data); - char buf[256]; - struct ast_format tmpfmt; AST_NONSTANDARD_APP_ARGS(args, parse, '/'); o = find_desc(args.name); @@ -863,8 +862,9 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap * /* XXX we could default to 'dsp' perhaps ? */ return NULL; } - if (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)))) { - ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); + if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *codec_buf = ast_str_alloca(64); + ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_format_cap_get_names(cap, &codec_buf)); return NULL; } if (o->owner) { @@ -1452,7 +1452,6 @@ static int load_module(void) struct ast_config *cfg = NULL; char *ctg = NULL; struct ast_flags config_flags = { 0 }; - struct ast_format tmpfmt; /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); @@ -1482,7 +1481,7 @@ static int load_module(void) if (!(oss_tech.capabilities = ast_format_cap_alloc(0))) { return AST_MODULE_LOAD_FAILURE; } - ast_format_cap_add(oss_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_format_cap_append(oss_tech.capabilities, ast_format_slin, 0); /* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER * add console_video_formats to oss_tech.capabilities once this occurs. */ @@ -1517,7 +1516,9 @@ static int unload_module(void) ast_free(o); o = next; } - oss_tech.capabilities = ast_format_cap_destroy(oss_tech.capabilities); + ao2_cleanup(oss_tech.capabilities); + oss_tech.capabilities = NULL; + return 0; } diff --git a/channels/chan_phone.c b/channels/chan_phone.c index 1e5e19d57..72f38291b 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -67,6 +67,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/causes.h" #include "asterisk/stringfields.h" #include "asterisk/musiconhold.h" +#include "asterisk/format_cache.h" +#include "asterisk/format_compatibility.h" #include "chan_phone.h" @@ -134,8 +136,8 @@ static struct phone_pvt { int fd; /* Raw file descriptor for this device */ struct ast_channel *owner; /* Channel we belong to, possibly NULL */ int mode; /* Is this in the */ - struct ast_format lastformat; /* Last output format */ - struct ast_format lastinput; /* Last input format */ + struct ast_format *lastformat; /* Last output format */ + struct ast_format *lastinput; /* Last input format */ int ministate; /* Miniature state, for dialtone mode */ char dev[256]; /* Device name */ struct phone_pvt *next; /* Next channel in list */ @@ -218,7 +220,8 @@ static int phone_indicate(struct ast_channel *chan, int condition, const void *d ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK); usleep(320000); ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK); - ast_format_clear(&p->lastformat); + ao2_cleanup(p->lastformat); + p->lastformat = NULL; res = 0; break; case AST_CONTROL_HOLD: @@ -282,7 +285,8 @@ static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int dur ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK); usleep(320000); ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK); - ast_format_clear(&p->lastformat); + ao2_cleanup(p->lastformat); + p->lastformat = NULL; return 0; default: ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit); @@ -290,7 +294,8 @@ static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int dur } ast_debug(1, "Dialed %d\n", outdigit); ioctl(p->fd, PHONE_PLAY_TONE, outdigit); - ast_format_clear(&p->lastformat); + ao2_cleanup(p->lastformat); + p->lastformat = NULL; return 0; } @@ -381,8 +386,10 @@ static int phone_hangup(struct ast_channel *ast) ioctl(p->fd, PHONE_BUSY); p->cpt = 1; } - ast_format_clear(&p->lastformat); - ast_format_clear(&p->lastinput); + ao2_cleanup(p->lastformat); + p->lastformat = NULL; + ao2_cleanup(p->lastinput); + p->lastinput = NULL; p->ministate = 0; p->obuflen = 0; p->dialtone = 0; @@ -402,38 +409,38 @@ static int phone_setup(struct ast_channel *ast) p = ast_channel_tech_pvt(ast); ioctl(p->fd, PHONE_CPT_STOP); /* Nothing to answering really, just start recording */ - if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_G729A) { + if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_g729) == AST_FORMAT_CMP_EQUAL) { /* Prefer g729 */ ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput.id != AST_FORMAT_G729A) { - ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0); + if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_g729) != AST_FORMAT_CMP_EQUAL)) { + ao2_replace(p->lastinput, ast_format_g729); if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { ast_log(LOG_WARNING, "Failed to set codec to g729\n"); return -1; } } - } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_G723_1) { + } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_g723) == AST_FORMAT_CMP_EQUAL) { ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput.id != AST_FORMAT_G723_1) { - ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0); + if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_g723) != AST_FORMAT_CMP_EQUAL)) { + ao2_replace(p->lastinput, ast_format_g723); if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) { ast_log(LOG_WARNING, "Failed to set codec to g723.1\n"); return -1; } } - } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) { + } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) { ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput.id != AST_FORMAT_SLINEAR) { - ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0); + if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) { + ao2_replace(p->lastinput, ast_format_slin); if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) { ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n"); return -1; } } - } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) { + } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) { ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput.id != AST_FORMAT_ULAW) { - ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0); + if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) { + ao2_replace(p->lastinput, ast_format_ulaw); if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) { ast_log(LOG_WARNING, "Failed to set codec to uLaw\n"); return -1; @@ -441,16 +448,16 @@ static int phone_setup(struct ast_channel *ast) } } else if (p->mode == MODE_FXS) { ioctl(p->fd, PHONE_REC_STOP); - if (ast_format_cmp(&p->lastinput, ast_channel_rawreadformat(ast)) == AST_FORMAT_CMP_NOT_EQUAL) { - ast_format_copy(&p->lastinput, ast_channel_rawreadformat(ast)); + if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_channel_rawreadformat(ast)) == AST_FORMAT_CMP_NOT_EQUAL)) { + ao2_replace(p->lastinput, ast_channel_rawreadformat(ast)); if (ioctl(p->fd, PHONE_REC_CODEC, ast_channel_rawreadformat(ast))) { ast_log(LOG_WARNING, "Failed to set codec to %s\n", - ast_getformatname(ast_channel_rawreadformat(ast))); + ast_format_get_name(ast_channel_rawreadformat(ast))); return -1; } } } else { - ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast_channel_rawreadformat(ast))); + ast_log(LOG_WARNING, "Can't do format %s\n", ast_format_get_name(ast_channel_rawreadformat(ast))); return -1; } if (ioctl(p->fd, PHONE_REC_START)) { @@ -601,13 +608,13 @@ static struct ast_frame *phone_read(struct ast_channel *ast) } p->fr.samples = 240; p->fr.datalen = res; - p->fr.frametype = AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_AUDIO ? - AST_FRAME_VOICE : AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_IMAGE ? + p->fr.frametype = ast_format_get_type(p->lastinput) == AST_MEDIA_TYPE_AUDIO ? + AST_FRAME_VOICE : ast_format_get_type(p->lastinput) == AST_MEDIA_TYPE_IMAGE ? AST_FRAME_IMAGE : AST_FRAME_VIDEO; - ast_format_copy(&p->fr.subclass.format, &p->lastinput); + p->fr.subclass.format = p->lastinput; p->fr.offset = AST_FRIENDLY_OFFSET; /* Byteswap from little-endian to native-endian */ - if (p->fr.subclass.format.id == AST_FORMAT_SLINEAR) + if (ast_format_cmp(p->fr.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) ast_frame_byteswap_le(&p->fr); return &p->fr; } @@ -669,14 +676,6 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype); return 0; } - if (!(frame->subclass.format.id == AST_FORMAT_G723_1 || - frame->subclass.format.id == AST_FORMAT_SLINEAR || - frame->subclass.format.id == AST_FORMAT_ULAW || - frame->subclass.format.id == AST_FORMAT_G729A) && - p->mode != MODE_FXS) { - ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format)); - return -1; - } #if 0 /* If we're not in up mode, go into up mode now */ if (ast->_state != AST_STATE_UP) { @@ -689,8 +688,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } #endif - if (frame->subclass.format.id == AST_FORMAT_G729A) { - if (p->lastformat.id != AST_FORMAT_G729A) { + if (ast_format_cmp(frame->subclass.format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) { + if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_g729) != AST_FORMAT_CMP_EQUAL)) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) { @@ -701,8 +700,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Unable to set G729 mode\n"); return -1; } - ast_format_set(&p->lastformat, AST_FORMAT_G729A, 0); - ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0); + ao2_replace(p->lastformat, ast_format_g729); + ao2_replace(p->lastinput, ast_format_g729); /* Reset output buffer */ p->obuflen = 0; codecset = 1; @@ -712,8 +711,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return -1; } maxfr = 80; - } else if (frame->subclass.format.id == AST_FORMAT_G723_1) { - if (p->lastformat.id != AST_FORMAT_G723_1) { + } else if (ast_format_cmp(frame->subclass.format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) { + if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_g723) != AST_FORMAT_CMP_EQUAL)) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) { @@ -724,8 +723,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Unable to set G723.1 mode\n"); return -1; } - ast_format_set(&p->lastformat, AST_FORMAT_G723_1, 0); - ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0); + ao2_replace(p->lastformat, ast_format_g723); + ao2_replace(p->lastinput, ast_format_g723); /* Reset output buffer */ p->obuflen = 0; codecset = 1; @@ -735,8 +734,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return -1; } maxfr = 24; - } else if (frame->subclass.format.id == AST_FORMAT_SLINEAR) { - if (p->lastformat.id != AST_FORMAT_SLINEAR) { + } else if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) { + if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) { @@ -747,15 +746,15 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n"); return -1; } - ast_format_set(&p->lastformat, AST_FORMAT_SLINEAR, 0); - ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0); + ao2_replace(p->lastformat, ast_format_slin); + ao2_replace(p->lastinput, ast_format_slin); codecset = 1; /* Reset output buffer */ p->obuflen = 0; } maxfr = 480; - } else if (frame->subclass.format.id == AST_FORMAT_ULAW) { - if (p->lastformat.id != AST_FORMAT_ULAW) { + } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) { + if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) { @@ -766,29 +765,29 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Unable to set uLaw mode\n"); return -1; } - ast_format_set(&p->lastformat, AST_FORMAT_ULAW, 0); - ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0); + ao2_replace(p->lastformat, ast_format_ulaw); + ao2_replace(p->lastinput, ast_format_ulaw); codecset = 1; /* Reset output buffer */ p->obuflen = 0; } maxfr = 240; } else { - if (ast_format_cmp(&p->lastformat, &frame->subclass.format) != AST_FORMAT_CMP_EQUAL) { + if (!p->lastformat || (ast_format_cmp(p->lastformat, frame->subclass.format) != AST_FORMAT_CMP_EQUAL)) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); - if (ioctl(p->fd, PHONE_PLAY_CODEC, (int) frame->subclass.format.id)) { + if (ioctl(p->fd, PHONE_PLAY_CODEC, ast_format_compatibility_format2bitfield(frame->subclass.format))) { ast_log(LOG_WARNING, "Unable to set %s mode\n", - ast_getformatname(&frame->subclass.format)); + ast_format_get_name(frame->subclass.format)); return -1; } - if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.format.id)) { + if (ioctl(p->fd, PHONE_REC_CODEC, ast_format_compatibility_format2bitfield(frame->subclass.format))) { ast_log(LOG_WARNING, "Unable to set %s mode\n", - ast_getformatname(&frame->subclass.format)); + ast_format_get_name(frame->subclass.format)); return -1; } - ast_format_copy(&p->lastformat, &frame->subclass.format); - ast_format_copy(&p->lastinput, &frame->subclass.format); + ao2_replace(p->lastformat, frame->subclass.format); + ao2_replace(p->lastinput, frame->subclass.format); codecset = 1; /* Reset output buffer */ p->obuflen = 0; @@ -857,11 +856,13 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor) { + struct ast_format_cap *caps = NULL; struct ast_channel *tmp; struct phone_codec_data queried_codec; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, assignedids, requestor, 0, "Phone/%s", i->dev + 5); - if (tmp) { + if (tmp && caps) { ast_channel_lock(tmp); ast_channel_tech_set(tmp, cur_tech); ast_channel_set_fd(tmp, 0, i->fd); @@ -869,18 +870,20 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, if (i->mode == MODE_FXS && ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) { if (queried_codec.type == LINEAR16) { - ast_format_cap_add(ast_channel_nativeformats(tmp), ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); + ast_format_cap_append(caps, ast_format_slin, 0); } else { - ast_format_cap_remove(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_format_cap_remove(prefcap, ast_format_slin); + ast_format_cap_append_from_cap(caps, prefcap, AST_MEDIA_TYPE_UNKNOWN); } } else { - ast_format_cap_copy(ast_channel_nativeformats(tmp), prefcap); - ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); + ast_format_cap_append_from_cap(caps, prefcap, AST_MEDIA_TYPE_UNKNOWN); } + tmpfmt = ast_format_cap_get_format(caps, 0); + ast_channel_nativeformats_set(tmp, caps); + ao2_ref(caps, -1); + ast_channel_set_rawreadformat(tmp, tmpfmt); + ast_channel_set_rawwriteformat(tmp, tmpfmt); + ao2_ref(tmpfmt, -1); /* no need to call ast_setstate: the channel_alloc already did its job */ if (state == AST_STATE_RING) ast_channel_rings_set(tmp, 1); @@ -913,8 +916,10 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, ast_hangup(tmp); } } - } else + } else { + ao2_cleanup(caps); ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); + } return tmp; } @@ -989,7 +994,8 @@ static void phone_check_exception(struct phone_pvt *i) ioctl(i->fd, PHONE_PLAY_STOP); ioctl(i->fd, PHONE_PLAY_CODEC, ULAW); ioctl(i->fd, PHONE_PLAY_START); - ast_format_clear(&i->lastformat); + ao2_cleanup(i->lastformat); + i->lastformat = NULL; } else if (i->mode == MODE_SIGMA) { ast_module_ref(ast_module_info->self); /* Reset the extension */ @@ -1010,7 +1016,8 @@ static void phone_check_exception(struct phone_pvt *i) ioctl(i->fd, PHONE_PLAY_STOP); ioctl(i->fd, PHONE_REC_STOP); i->dialtone = 0; - ast_format_clear(&i->lastformat); + ao2_cleanup(i->lastformat); + i->lastformat = NULL; } } if (phonee.bits.pstn_ring) { @@ -1222,8 +1229,10 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai flags = fcntl(tmp->fd, F_GETFL); fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); tmp->owner = NULL; - ast_format_clear(&tmp->lastformat); - ast_format_clear(&tmp->lastinput); + ao2_cleanup(tmp->lastformat); + tmp->lastformat = NULL; + ao2_cleanup(tmp->lastinput); + tmp->lastinput = NULL; tmp->ministate = 0; memset(tmp->ext, 0, sizeof(tmp->ext)); ast_copy_string(tmp->language, language, sizeof(tmp->language)); @@ -1256,7 +1265,7 @@ static struct ast_channel *phone_request(const char *type, struct ast_format_cap } p = iflist; while(p) { - if (p->mode == MODE_FXS || (ast_format_cap_has_joint(cap, phone_tech.capabilities))) { + if (p->mode == MODE_FXS || (ast_format_cap_iscompatible(cap, phone_tech.capabilities))) { size_t length = strlen(p->dev + 5); if (strncmp(name, p->dev + 5, length) == 0 && !isalnum(name[length])) { @@ -1272,9 +1281,10 @@ static struct ast_channel *phone_request(const char *type, struct ast_format_cap ast_mutex_unlock(&iflock); restart_monitor(); if (tmp == NULL) { - if (!(ast_format_cap_has_joint(cap, phone_tech.capabilities))) { - char buf[256]; - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); + if (!(ast_format_cap_iscompatible(cap, phone_tech.capabilities))) { + struct ast_str *codec_buf = ast_str_alloca(64); + ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", + ast_format_cap_get_names(cap, &codec_buf)); return NULL; } } @@ -1357,9 +1367,10 @@ static int __unload_module(void) return -1; } - phone_tech.capabilities = ast_format_cap_destroy(phone_tech.capabilities); - phone_tech_fxs.capabilities = ast_format_cap_destroy(phone_tech_fxs.capabilities); - prefcap = ast_format_cap_destroy(prefcap); + ao2_ref(phone_tech.capabilities, -1); + ao2_ref(phone_tech_fxs.capabilities, -1); + ao2_ref(prefcap, -1); + return 0; } @@ -1376,21 +1387,21 @@ static int load_module(void) int mode = MODE_IMMEDIATE; int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ struct ast_flags config_flags = { 0 }; - struct ast_format tmpfmt; - if (!(phone_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(phone_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0)); - ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); - ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0)); - if (!(prefcap = ast_format_cap_alloc(0))) { + ast_format_cap_append(phone_tech.capabilities, ast_format_g723, 0); + ast_format_cap_append(phone_tech.capabilities, ast_format_slin, 0); + ast_format_cap_append(phone_tech.capabilities, ast_format_ulaw, 0); + ast_format_cap_append(phone_tech.capabilities, ast_format_g729, 0); + + if (!(prefcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_copy(prefcap, phone_tech.capabilities); - if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc(0))) { + ast_format_cap_append_from_cap(prefcap, phone_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); + if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } @@ -1440,7 +1451,7 @@ static int load_module(void) mode = MODE_IMMEDIATE; else if (!strncasecmp(v->value, "fxs", 3)) { mode = MODE_FXS; - ast_format_cap_remove_bytype(prefcap, AST_FORMAT_TYPE_AUDIO); /* All non-voice */ + ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_AUDIO); /* All non-voice */ } else if (!strncasecmp(v->value, "fx", 2)) mode = MODE_FXO; @@ -1450,18 +1461,21 @@ static int load_module(void) ast_copy_string(context, v->value, sizeof(context)); } else if (!strcasecmp(v->name, "format")) { if (!strcasecmp(v->value, "g729")) { - ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0)); + ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(prefcap, ast_format_g729, 0); } else if (!strcasecmp(v->value, "g723.1")) { - ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0)); + ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(prefcap, ast_format_g723, 0); } else if (!strcasecmp(v->value, "slinear")) { - ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0); if (mode == MODE_FXS) { - ast_format_cap_add(prefcap, &tmpfmt); + ast_format_cap_append(prefcap, ast_format_slin, 0); } else { - ast_format_cap_set(prefcap, &tmpfmt); + ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(prefcap, ast_format_slin, 0); } } else if (!strcasecmp(v->value, "ulaw")) { - ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); + ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(prefcap, ast_format_ulaw, 0); } else ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); } else if (!strcasecmp(v->name, "echocancel")) { @@ -1485,7 +1499,7 @@ static int load_module(void) ast_mutex_unlock(&iflock); if (mode == MODE_FXS) { - ast_format_cap_copy(phone_tech_fxs.capabilities, prefcap); + ast_format_cap_append_from_cap(phone_tech_fxs.capabilities, prefcap, AST_MEDIA_TYPE_UNKNOWN); cur_tech = &phone_tech_fxs; } else cur_tech = (struct ast_channel_tech *) &phone_tech; diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 695211480..5812360c5 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/stasis_endpoints.h" #include "asterisk/stasis_channels.h" #include "asterisk/indications.h" +#include "asterisk/format_cache.h" #include "asterisk/threadstorage.h" #include "asterisk/features_config.h" #include "asterisk/pickup.h" @@ -210,7 +211,7 @@ static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap { struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan); - ast_format_cap_copy(result, channel->session->endpoint->media.codecs); + ast_format_cap_append_from_cap(result, channel->session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN); } static int send_direct_media_request(void *data) @@ -325,8 +326,9 @@ static int chan_pjsip_set_rtp_peer(struct ast_channel *chan, return 0; } - if (cap && !ast_format_cap_is_empty(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) { - ast_format_cap_copy(session->direct_media_cap, cap); + if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) { + ast_format_cap_remove_by_type(session->direct_media_cap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(session->direct_media_cap, cap, AST_MEDIA_TYPE_UNKNOWN); changed = 1; } @@ -355,7 +357,8 @@ static struct ast_rtp_glue chan_pjsip_rtp_glue = { static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int state, const char *exten, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name) { struct ast_channel *chan; - struct ast_format fmt; + struct ast_format_cap *caps; + struct ast_format *fmt; RAII_VAR(struct chan_pjsip_pvt *, pvt, NULL, ao2_cleanup); struct ast_sip_channel_pvt *channel; struct ast_variable *var; @@ -363,19 +366,21 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s if (!(pvt = ao2_alloc(sizeof(*pvt), chan_pjsip_pvt_dtor))) { return NULL; } + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + return NULL; + } - - chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), - session->endpoint->accountcode, "", "", assignedids, - requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint), - (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)); - if (!chan) { + if (!(chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), session->endpoint->accountcode, "", "", assignedids, requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint), + (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)))) { + ao2_ref(caps, -1); return NULL; } ast_channel_tech_set(chan, &chan_pjsip_tech); if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) { + ao2_ref(caps, -1); ast_channel_unlock(chan); ast_hangup(chan); return NULL; @@ -391,17 +396,21 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s ast_channel_tech_pvt_set(chan, channel); - if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) { - ast_format_cap_copy(ast_channel_nativeformats(chan), session->endpoint->media.codecs); + if (!ast_format_cap_count(session->req_caps) || + !ast_format_cap_iscompatible(session->req_caps, session->endpoint->media.codecs)) { + ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN); } else { - ast_format_cap_copy(ast_channel_nativeformats(chan), session->req_caps); + ast_format_cap_append_from_cap(caps, session->req_caps, AST_MEDIA_TYPE_UNKNOWN); } - ast_codec_choose(&session->endpoint->media.prefs, ast_channel_nativeformats(chan), 1, &fmt); - ast_format_copy(ast_channel_writeformat(chan), &fmt); - ast_format_copy(ast_channel_rawwriteformat(chan), &fmt); - ast_format_copy(ast_channel_readformat(chan), &fmt); - ast_format_copy(ast_channel_rawreadformat(chan), &fmt); + ast_channel_nativeformats_set(chan, caps); + fmt = ast_format_cap_get_format(caps, 0); + ast_channel_set_writeformat(chan, fmt); + ast_channel_set_rawwriteformat(chan, fmt); + ast_channel_set_readformat(chan, fmt); + ast_channel_set_rawreadformat(chan, fmt); + ao2_ref(fmt, -1); + ao2_ref(caps, -1); if (state == AST_STATE_RING) { ast_channel_rings_set(chan, 1); @@ -584,9 +593,18 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast) return f; } - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) { - ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); - ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format); + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_format_cap *caps; + + ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format)); + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + ast_format_cap_append(caps, f->subclass.format, 0); + ast_channel_nativeformats_set(ast, caps); + ao2_ref(caps, -1); + } + ast_set_read_format(ast, ast_channel_readformat(ast)); ast_set_write_format(ast, ast_channel_writeformat(ast)); } @@ -623,15 +641,15 @@ static int chan_pjsip_write(struct ast_channel *ast, struct ast_frame *frame) if (!media) { return 0; } - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) { - char buf[256]; + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *cap_buf = ast_str_alloca(64); ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(&frame->subclass.format), - ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)), - ast_getformatname(ast_channel_readformat(ast)), - ast_getformatname(ast_channel_writeformat(ast))); + ast_format_get_name(frame->subclass.format), + ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf), + ast_format_get_name(ast_channel_readformat(ast)), + ast_format_get_name(ast_channel_writeformat(ast))); return 0; } if (media->rtp) { @@ -1127,10 +1145,8 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi if (media && media->rtp) { /* FIXME: Only use this for VP8. Additional work would have to be done to * fully support other video codecs */ - struct ast_format_cap *fcap = ast_channel_nativeformats(ast); - struct ast_format vp8; - ast_format_set(&vp8, AST_FORMAT_VP8, 0); - if (ast_format_cap_iscompatible(fcap, &vp8)) { + + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp8) != AST_FORMAT_CMP_NOT_EQUAL) { /* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the * RTP engine would provide a way to externally write/schedule RTCP * packets */ @@ -2162,11 +2178,11 @@ static int load_module(void) { struct ao2_container *endpoints; - if (!(chan_pjsip_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(chan_pjsip_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add_all_by_type(chan_pjsip_tech.capabilities, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_append_by_type(chan_pjsip_tech.capabilities, AST_MEDIA_TYPE_AUDIO); ast_rtp_glue_register(&chan_pjsip_rtp_glue); @@ -2259,6 +2275,7 @@ static int unload_module(void) ast_custom_function_unregister(&chan_pjsip_dial_contacts_function); ast_channel_unregister(&chan_pjsip_tech); + ao2_ref(chan_pjsip_tech.capabilities, -1); ast_rtp_glue_unregister(&chan_pjsip_rtp_glue); return 0; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 095b5a763..44629dc3d 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -285,6 +285,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/stasis_channels.h" #include "asterisk/features_config.h" #include "asterisk/http_websocket.h" +#include "asterisk/format_cache.h" /*** DOCUMENTATION <application name="SIPDtmfMode" language="en_US"> @@ -747,7 +748,6 @@ static char default_mohsuggest[MAX_MUSICCLASS]; /*!< Global setting for moh c static char default_parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */ static char default_engine[256]; /*!< Default RTP engine */ static int default_maxcallbitrate; /*!< Maximum bitrate for call */ -static struct ast_codec_pref default_prefs; /*!< Default codec prefs */ static char default_zone[MAX_TONEZONE_COUNTRY]; /*!< Default tone zone for channels created from the SIP driver */ static unsigned int default_transports; /*!< Default Transports (enum ast_transport) that are acceptable */ static unsigned int default_primary_transport; /*!< Default primary Transport (enum ast_transport) for outbound connections to devices */ @@ -1295,7 +1295,6 @@ static int str2dtmfmode(const char *str) attribute_unused; static const char *insecure2str(int mode) attribute_const; static const char *allowoverlap2str(int mode) attribute_const; static void cleanup_stale_contexts(char *new, char *old); -static void print_codec_to_cli(int fd, struct ast_codec_pref *pref); static const char *domain_mode_to_text(const enum domain_mode mode); static char *sip_show_domains(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]); @@ -1764,7 +1763,7 @@ static void destroy_escs(void) { int i; for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) { - ao2_ref(event_state_compositors[i].compositor, -1); + ao2_cleanup(event_state_compositors[i].compositor); } } @@ -3385,7 +3384,7 @@ static void unlink_peers_from_tables(peer_unlink_flag_t flag) ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers"); ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, - match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers"); + match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers_by_ip"); } /* \brief Unlink all marked peers from ao2 containers */ @@ -5308,7 +5307,7 @@ static void sip_destroy_peer(struct sip_peer *peer) ast_string_field_free_memory(peer); - peer->caps = ast_format_cap_destroy(peer->caps); + ao2_cleanup(peer->caps); ast_rtp_dtls_cfg_free(&peer->dtls_cfg); @@ -5967,7 +5966,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog) } if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) || - (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) { + (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_MEDIA_TYPE_VIDEO)))) { if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { return -1; } @@ -6053,8 +6052,11 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); - ast_format_cap_copy(dialog->caps, peer->caps); - dialog->prefs = peer->prefs; + /* Take the peer's caps */ + if (peer->caps) { + ast_format_cap_remove_by_type(dialog->caps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(dialog->caps, peer->caps, AST_MEDIA_TYPE_UNKNOWN); + } dialog->amaflags = peer->amaflags; ast_string_field_set(dialog, engine, peer->engine); @@ -6078,8 +6080,8 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); /* Set Frame packetization */ - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs); dialog->autoframing = peer->autoframing; + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(dialog->rtp), ast_format_cap_get_framing(dialog->caps)); } /* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */ @@ -6456,7 +6458,7 @@ static int sip_call(struct ast_channel *ast, const char *dest, int timeout) p->jointnoncodeccapability = p->noncodeccapability; /* If there are no audio formats left to offer, punt */ - if (!(ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO))) { + if (!(ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_AUDIO))) { ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username); res = -1; } else { @@ -6721,11 +6723,11 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) p->named_callgroups = ast_unref_namedgroups(p->named_callgroups); p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups); - p->caps = ast_format_cap_destroy(p->caps); - p->jointcaps = ast_format_cap_destroy(p->jointcaps); - p->peercaps = ast_format_cap_destroy(p->peercaps); - p->redircaps = ast_format_cap_destroy(p->redircaps); - p->prefcaps = ast_format_cap_destroy(p->prefcaps); + ao2_cleanup(p->caps); + ao2_cleanup(p->jointcaps); + ao2_cleanup(p->peercaps); + ao2_cleanup(p->redircaps); + ao2_cleanup(p->prefcaps); ast_rtp_dtls_cfg_free(&p->dtls_cfg); @@ -7308,7 +7310,6 @@ static int sip_hangup(struct ast_channel *ast) /*! \brief Try setting the codecs suggested by the SIP_CODEC channel variable */ static void try_suggested_sip_codec(struct sip_pvt *p) { - struct ast_format fmt; const char *codec_list; char *codec_list_copy; struct ast_format_cap *original_jointcaps; @@ -7328,31 +7329,44 @@ static void try_suggested_sip_codec(struct sip_pvt *p) } codec_list_copy = ast_strdupa(codec_list); - original_jointcaps = ast_format_cap_dup(p->jointcaps); + + original_jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!original_jointcaps) { + return; + } + ast_format_cap_append_from_cap(original_jointcaps, p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); for (codec = strtok_r(codec_list_copy, ",", &strtok_ptr); codec; codec = strtok_r(NULL, ",", &strtok_ptr)) { + struct ast_format *fmt; + codec = ast_strip(codec); - if (!ast_getformatbyname(codec, &fmt)) { + fmt = ast_format_cache_get(codec); + if (!fmt) { ast_log(AST_LOG_NOTICE, "Ignoring ${SIP_CODEC*} variable because of unrecognized/not configured codec %s (check allow/disallow in sip.conf)\n", codec); continue; } - if (ast_format_cap_iscompatible(original_jointcaps, &fmt)) { + if (ast_format_cap_iscompatible_format(original_jointcaps, fmt) != AST_FORMAT_CMP_NOT_EQUAL) { if (first_codec) { ast_verb(4, "Set codec to '%s' for this call because of ${SIP_CODEC*} variable\n", codec); - ast_format_cap_set(p->jointcaps, &fmt); - ast_format_cap_set(p->caps, &fmt); + ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(p->jointcaps, fmt, 0); + ast_format_cap_remove_by_type(p->caps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(p->caps, fmt, 0); first_codec = 0; } else { ast_verb(4, "Add codec to '%s' for this call because of ${SIP_CODEC*} variable\n", codec); - ast_format_cap_add(p->jointcaps, &fmt); - ast_format_cap_add(p->caps, &fmt); + /* Add the format to the capabilities structure */ + ast_format_cap_append(p->jointcaps, fmt, 0); + ast_format_cap_append(p->caps, fmt, 0); } } else { ast_log(AST_LOG_NOTICE, "Ignoring ${SIP_CODEC*} variable because it is not shared by both ends: %s\n", codec); } + + ao2_ref(fmt, -1); } - ast_format_cap_destroy(original_jointcaps); + ao2_ref(original_jointcaps, -1); return; } @@ -7401,13 +7415,13 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame) switch (frame->frametype) { case AST_FRAME_VOICE: - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) { - char s1[512]; + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *codec_buf = ast_str_alloca(64); ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s read/write = %s/%s\n", - ast_getformatname(&frame->subclass.format), - ast_getformatname_multiple(s1, sizeof(s1), ast_channel_nativeformats(ast)), - ast_getformatname(ast_channel_readformat(ast)), - ast_getformatname(ast_channel_writeformat(ast))); + ast_format_get_name(frame->subclass.format), + ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf), + ast_format_get_name(ast_channel_readformat(ast)), + ast_format_get_name(ast_channel_writeformat(ast))); return 0; } if (p) { @@ -7929,10 +7943,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data if (p->vrtp && !p->novideo) { /* FIXME: Only use this for VP8. Additional work would have to be done to * fully support other video codecs */ - struct ast_format_cap *fcap = ast_channel_nativeformats(ast); - struct ast_format vp8; - ast_format_set(&vp8, AST_FORMAT_VP8, 0); - if (ast_format_cap_iscompatible(fcap, &vp8)) { + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp8) != AST_FORMAT_CMP_NOT_EQUAL) { /* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the * RTP engine would provide a way to externally write/schedule RTCP * packets */ @@ -8036,15 +8047,21 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data */ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid) { + struct ast_format_cap *caps; struct ast_channel *tmp; struct ast_variable *v = NULL; - struct ast_format fmt; + struct ast_format *fmt; struct ast_format_cap *what = NULL; /* SHALLOW COPY DO NOT DESTROY! */ + struct ast_str *codec_buf = ast_str_alloca(64); int needvideo = 0; int needtext = 0; - char buf[SIPBUFSIZE]; char *exten; + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + return NULL; + } + { const char *my_name; /* pick a good name */ @@ -8060,6 +8077,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit } if (!tmp) { ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n"); + ao2_ref(caps, -1); sip_pvt_lock(i); return NULL; } @@ -8068,6 +8086,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) { ast_channel_unlock(tmp); ast_channel_unref(tmp); + ao2_ref(caps, -1); sip_pvt_lock(i); return NULL; } @@ -8088,27 +8107,40 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit /* Select our native format based on codec preference until we receive something from another device to the contrary. */ - if (!(ast_format_cap_is_empty(i->jointcaps))) { /* The joint capabilities of us and peer */ + if (ast_format_cap_count(i->jointcaps)) { /* The joint capabilities of us and peer */ what = i->jointcaps; - } else if (!(ast_format_cap_is_empty(i->caps))) { /* Our configured capability for this peer */ + } else if (ast_format_cap_count(i->caps)) { /* Our configured capability for this peer */ what = i->caps; } else { what = sip_cfg.caps; } /* Set the native formats */ - ast_format_cap_copy(ast_channel_nativeformats(tmp), what); - /* choose and use only the best audio format for our native formats */ - ast_codec_choose(&i->prefs, ast_channel_nativeformats(tmp), 1, &fmt); /* get the best audio format */ - ast_format_cap_remove_bytype(ast_channel_nativeformats(tmp), AST_FORMAT_TYPE_AUDIO); /* remove only the other audio formats */ - ast_format_cap_add(ast_channel_nativeformats(tmp), &fmt); /* add our best choice back */ + ast_format_cap_append_from_cap(caps, what, AST_MEDIA_TYPE_UNKNOWN); + /* Use only the preferred audio format, which is stored at the '0' index */ + fmt = ast_format_cap_get_best_by_type(what, AST_MEDIA_TYPE_AUDIO); /* get the best audio format */ + if (fmt) { + ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); /* remove only the other audio formats */ + ast_format_cap_append(caps, fmt, 0); /* add our best choice back */ + } else { + /* If we don't have an audio format, try to get something */ + fmt = ast_format_cap_get_format(caps, 0); + if (!fmt) { + ast_log(LOG_WARNING, "No compatible formats could be found for %s\n", ast_channel_name(tmp)); + ao2_ref(caps, -1); + tmp = ast_channel_unref(tmp); + return NULL; + } + } + ast_channel_nativeformats_set(tmp, caps); + ao2_ref(caps, -1); - ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_channel_nativeformats(tmp))); - ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcaps)); - ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->caps)); - ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname(&fmt)); - if (!ast_format_cap_is_empty(i->prefcaps)) { - ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcaps)); + ast_debug(3, "*** Our native formats are %s \n", ast_format_cap_get_names(ast_channel_nativeformats(tmp), &codec_buf)); + ast_debug(3, "*** Joint capabilities are %s \n", ast_format_cap_get_names(i->jointcaps, &codec_buf)); + ast_debug(3, "*** Our capabilities are %s \n", ast_format_cap_get_names(i->caps, &codec_buf)); + ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_format_get_name(fmt)); + if (ast_format_cap_count(i->prefcaps)) { + ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_format_cap_get_names(i->prefcaps, &codec_buf)); } /* If we have a prefcodec setting, we have an inbound channel that set a @@ -8118,17 +8150,17 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit if (i->vrtp) { if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT)) needvideo = 1; - else if (!ast_format_cap_is_empty(i->prefcaps)) - needvideo = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_VIDEO); /* Outbound call */ + else if (ast_format_cap_count(i->prefcaps)) + needvideo = ast_format_cap_has_type(i->prefcaps, AST_MEDIA_TYPE_VIDEO); /* Outbound call */ else - needvideo = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_VIDEO); /* Inbound call */ + needvideo = ast_format_cap_has_type(i->jointcaps, AST_MEDIA_TYPE_VIDEO); /* Inbound call */ } if (i->trtp) { - if (!ast_format_cap_is_empty(i->prefcaps)) - needtext = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_TEXT); /* Outbound call */ + if (ast_format_cap_count(i->prefcaps)) + needtext = ast_format_cap_has_type(i->prefcaps, AST_MEDIA_TYPE_TEXT); /* Outbound call */ else - needtext = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_TEXT); /* Inbound call */ + needtext = ast_format_cap_has_type(i->jointcaps, AST_MEDIA_TYPE_TEXT); /* Inbound call */ } if (needvideo) { @@ -8156,8 +8188,8 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit if (i->rtp) { ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0)); ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1)); - ast_rtp_instance_set_write_format(i->rtp, &fmt); - ast_rtp_instance_set_read_format(i->rtp, &fmt); + ast_rtp_instance_set_write_format(i->rtp, fmt); + ast_rtp_instance_set_read_format(i->rtp, fmt); } if (needvideo && i->vrtp) { ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0)); @@ -8175,11 +8207,13 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit } ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE); - ast_format_copy(ast_channel_writeformat(tmp), &fmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &fmt); + ast_channel_set_writeformat(tmp, fmt); + ast_channel_set_rawwriteformat(tmp, fmt); + + ast_channel_set_readformat(tmp, fmt); + ast_channel_set_rawreadformat(tmp, fmt); - ast_format_copy(ast_channel_readformat(tmp), &fmt); - ast_format_copy(ast_channel_rawreadformat(tmp), &fmt); + ao2_ref(fmt, -1); ast_channel_tech_pvt_set(tmp, dialog_ref(i, "sip_new: set chan->tech_pvt to i")); @@ -8534,17 +8568,26 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p return f; } - if (f && !ast_format_cap_iscompatible(ast_channel_nativeformats(p->owner), &f->subclass.format)) { - if (!ast_format_cap_iscompatible(p->jointcaps, &f->subclass.format)) { + if (f && ast_format_cap_iscompatible_format(ast_channel_nativeformats(p->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_format_cap *caps; + + if (ast_format_cap_iscompatible_format(p->jointcaps, f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n", - ast_getformatname(&f->subclass.format), ast_channel_name(p->owner)); + ast_format_get_name(f->subclass.format), ast_channel_name(p->owner)); ast_frfree(f); return &ast_null_frame; } ast_debug(1, "Oooh, format changed to %s\n", - ast_getformatname(&f->subclass.format)); - ast_format_cap_remove_bytype(ast_channel_nativeformats(p->owner), AST_FORMAT_TYPE_AUDIO); - ast_format_cap_add(ast_channel_nativeformats(p->owner), &f->subclass.format); + ast_format_get_name(f->subclass.format)); + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(p->owner), AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); + ast_format_cap_append(caps, f->subclass.format, 0); + ast_channel_nativeformats_set(p->owner, caps); + ao2_ref(caps, -1); + } ast_set_read_format(p->owner, ast_channel_readformat(p->owner)); ast_set_write_format(p->owner, ast_channel_writeformat(p->owner)); } @@ -8796,18 +8839,18 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr, sip_pvt_callid_set(p, logger_callid); } - p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); - if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps) { - p->caps = ast_format_cap_destroy(p->caps); - p->jointcaps = ast_format_cap_destroy(p->jointcaps); - p->peercaps = ast_format_cap_destroy(p->peercaps); - p->redircaps = ast_format_cap_destroy(p->redircaps); - p->prefcaps = ast_format_cap_destroy(p->prefcaps); + if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps || !p->prefcaps) { + ao2_cleanup(p->caps); + ao2_cleanup(p->jointcaps); + ao2_cleanup(p->peercaps); + ao2_cleanup(p->redircaps); + ao2_cleanup(p->prefcaps); ao2_t_ref(p, -1, "Yuck, couldn't allocate format capabilities. Get rid o' p"); return NULL; } @@ -8857,7 +8900,6 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr, p->sessionversion_remote = -1; p->session_modify = TRUE; p->stimer = NULL; - p->prefs = default_prefs; /* Set default codecs for this call */ ast_copy_string(p->zone, default_zone, sizeof(p->zone)); p->maxforwards = sip_cfg.default_max_forwards; @@ -8909,7 +8951,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr, /* Assign default music on hold class */ ast_string_field_set(p, mohinterpret, default_mohinterpret); ast_string_field_set(p, mohsuggest, default_mohsuggest); - ast_format_cap_copy(p->caps, sip_cfg.caps); + ast_format_cap_append_from_cap(p->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN); p->allowtransfer = sip_cfg.allowtransfer; if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { @@ -10034,15 +10076,17 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action int udptlportno = -1; /*!< UDPTL image destination port number */ /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ - struct ast_format_cap *peercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - struct ast_format_cap *vpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - struct ast_format_cap *tpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + struct ast_format_cap *peercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + struct ast_format_cap *vpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + struct ast_format_cap *tpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); int peernoncodeccapability = 0, vpeernoncodeccapability = 0, tpeernoncodeccapability = 0; - struct ast_rtp_codecs newaudiortp = { 0, }, newvideortp = { 0, }, newtextrtp = { 0, }; - struct ast_format_cap *newjointcapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); /* Negotiated capability */ - struct ast_format_cap *newpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + struct ast_rtp_codecs newaudiortp = AST_RTP_CODECS_NULL_INIT; + struct ast_rtp_codecs newvideortp = AST_RTP_CODECS_NULL_INIT; + struct ast_rtp_codecs newtextrtp = AST_RTP_CODECS_NULL_INIT; + struct ast_format_cap *newjointcapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); /* Negotiated capability */ + struct ast_format_cap *newpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); int newnoncodeccapability; const char *codecs; @@ -10062,8 +10106,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action int debug = sip_debug_test_pvt(p); /* START UNKNOWN */ - char buf[SIPBUFSIZE]; - struct ast_format tmp_fmt; + struct ast_str *codec_buf = ast_str_alloca(64); + struct ast_format *tmp_fmt; /* END UNKNOWN */ /* Initial check */ @@ -10625,10 +10669,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action /* Ensure crypto lines are provided where necessary */ if (audio && secure_audio && !processed_crypto) { ast_log(LOG_WARNING, "Rejecting secure audio stream without encryption details: %s\n", m); - return -1; + res = -1; + goto process_sdp_cleanup; } else if (video && secure_video && !processed_crypto) { ast_log(LOG_WARNING, "Rejecting secure video stream without encryption details: %s\n", m); - return -1; + res = -1; + goto process_sdp_cleanup; } } @@ -10687,12 +10733,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_rtp_codecs_payload_formats(&newvideortp, vpeercapability, &vpeernoncodeccapability); ast_rtp_codecs_payload_formats(&newtextrtp, tpeercapability, &tpeernoncodeccapability); - ast_format_cap_append(newpeercapability, peercapability); - ast_format_cap_append(newpeercapability, vpeercapability); - ast_format_cap_append(newpeercapability, tpeercapability); + ast_format_cap_append_from_cap(newpeercapability, peercapability, AST_MEDIA_TYPE_AUDIO); + ast_format_cap_append_from_cap(newpeercapability, vpeercapability, AST_MEDIA_TYPE_VIDEO); + ast_format_cap_append_from_cap(newpeercapability, tpeercapability, AST_MEDIA_TYPE_TEXT); - ast_format_cap_joint_copy(p->caps, newpeercapability, newjointcapability); - if (ast_format_cap_is_empty(newjointcapability) && udptlportno == -1) { + ast_format_cap_get_compatible(p->caps, newpeercapability, newjointcapability); + if (!ast_format_cap_count(newjointcapability) && udptlportno == -1) { ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); /* Do NOT Change current setting */ res = -1; @@ -10703,14 +10749,18 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action if (debug) { /* shame on whoever coded this.... */ - char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE]; + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *peer_buf = ast_str_alloca(64); + struct ast_str *vpeer_buf = ast_str_alloca(64); + struct ast_str *tpeer_buf = ast_str_alloca(64); + struct ast_str *joint_buf = ast_str_alloca(64); ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n", - ast_getformatname_multiple(s1, SIPBUFSIZE, p->caps), - ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability), - ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability), - ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability), - ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability)); + ast_format_cap_get_names(p->caps, &cap_buf), + ast_format_cap_get_names(peercapability, &peer_buf), + ast_format_cap_get_names(vpeercapability, &vpeer_buf), + ast_format_cap_get_names(tpeercapability, &tpeer_buf), + ast_format_cap_get_names(newjointcapability, &joint_buf)); } if (debug) { struct ast_str *s1 = ast_str_alloca(SIPBUFSIZE); @@ -10726,14 +10776,21 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action if (portno != -1 || vportno != -1 || tportno != -1) { /* We are now ready to change the sip session and RTP structures with the offered codecs, since they are acceptable */ - ast_format_cap_copy(p->jointcaps, newjointcapability); /* Our joint codec profile for this call */ - ast_format_cap_copy(p->peercaps, newpeercapability); /* The other side's capability in latest offer */ + ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(p->jointcaps, newjointcapability, AST_MEDIA_TYPE_UNKNOWN); /* Our joint codec profile for this call */ + ast_format_cap_remove_by_type(p->peercaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(p->peercaps, newpeercapability, AST_MEDIA_TYPE_UNKNOWN); /* The other side's capability in latest offer */ p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ /* respond with single most preferred joint codec, limiting the other side's choice */ if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { - ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt); - ast_format_cap_set(p->jointcaps, &tmp_fmt); + unsigned int framing; + + tmp_fmt = ast_format_cap_get_format(p->jointcaps, 0); + framing = ast_format_cap_get_format_framing(p->jointcaps, tmp_fmt); + ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(p->jointcaps, tmp_fmt, framing); + ao2_ref(tmp_fmt, -1); } } @@ -10813,7 +10870,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_verbose("Peer T.140 RTP is at port %s\n", ast_sockaddr_stringify(tsa)); } - if (ast_format_cap_iscompatible(p->jointcaps, ast_format_set(&tmp_fmt, AST_FORMAT_T140RED, 0))) { + if (ast_format_cap_iscompatible_format(p->jointcaps, ast_format_t140_red) != AST_FORMAT_CMP_NOT_EQUAL) { p->red = 1; ast_rtp_red_init(p->trtp, 300, red_data_pt, 2); } else { @@ -10890,7 +10947,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action } /* Ok, we're going with this offer */ - ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcaps)); + ast_debug(2, "We're settling with these formats: %s\n", ast_format_cap_get_names(p->jointcaps, &codec_buf)); if (!p->owner) { /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */ res = 0; @@ -10898,19 +10955,30 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action } ast_debug(4, "We have an owner, now see if we need to change this call\n"); - if (ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO)) { + if (ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_AUDIO)) { + struct ast_format_cap *caps; + unsigned int framing; + if (debug) { - char s1[SIPBUFSIZE], s2[SIPBUFSIZE]; + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *joint_buf = ast_str_alloca(64); + 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, ast_channel_nativeformats(p->owner))); + ast_format_cap_get_names(p->jointcaps, &joint_buf), + ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &cap_buf)); } - ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt); - - ast_format_cap_set(ast_channel_nativeformats(p->owner), &tmp_fmt); - ast_format_cap_joint_append(p->caps, vpeercapability, ast_channel_nativeformats(p->owner)); - ast_format_cap_joint_append(p->caps, tpeercapability, ast_channel_nativeformats(p->owner)); + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + tmp_fmt = ast_format_cap_get_format(p->jointcaps, 0); + framing = ast_format_cap_get_format_framing(p->jointcaps, tmp_fmt); + ast_format_cap_append(caps, tmp_fmt, framing); + ast_format_cap_append_from_cap(caps, vpeercapability, AST_MEDIA_TYPE_VIDEO); + ast_format_cap_append_from_cap(caps, tpeercapability, AST_MEDIA_TYPE_TEXT); + ast_channel_nativeformats_set(p->owner, caps); + ao2_ref(caps, -1); + ao2_ref(tmp_fmt, -1); + } ast_set_read_format(p->owner, ast_channel_readformat(p->owner)); ast_set_write_format(p->owner, ast_channel_writeformat(p->owner)); @@ -10942,11 +11010,11 @@ process_sdp_cleanup: ast_rtp_codecs_payloads_destroy(&newtextrtp); ast_rtp_codecs_payloads_destroy(&newvideortp); ast_rtp_codecs_payloads_destroy(&newaudiortp); - ast_format_cap_destroy(peercapability); - ast_format_cap_destroy(vpeercapability); - ast_format_cap_destroy(tpeercapability); - ast_format_cap_destroy(newjointcapability); - ast_format_cap_destroy(newpeercapability); + ao2_cleanup(peercapability); + ao2_cleanup(vpeercapability); + ao2_cleanup(tpeercapability); + ao2_cleanup(newjointcapability); + ao2_cleanup(newpeercapability); return res; } @@ -11203,17 +11271,10 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ ast_debug(1, "Can't read framing from SDP: %s\n", a); } } + if (framing && p->autoframing) { - struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref; - int codec_n; - for (codec_n = 0; codec_n < AST_RTP_MAX_PT; codec_n++) { - struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n); - if (!format.asterisk_format) /* non-codec or not found */ - continue; - ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(&format.format), framing); - ast_codec_pref_setsize(pref, &format.format, framing); - } - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref); + ast_debug(1, "Setting framing to %ld\n", framing); + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), framing); } found = TRUE; } else if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) { @@ -11240,15 +11301,19 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ if ((format = ast_rtp_codecs_get_payload_format(newaudiortp, codec))) { unsigned int bit_rate; + struct ast_format *format_parsed; - if (!ast_format_sdp_parse(format, fmtp_string)) { + format_parsed = ast_format_parse_sdp_fmtp(format, fmtp_string); + if (format_parsed) { + ast_rtp_codecs_payload_replace_format(newaudiortp, codec, format_parsed); + ao2_replace(format, format_parsed); + ao2_ref(format_parsed, -1); found = TRUE; } else { ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec); } - switch ((int) format->id) { - case AST_FORMAT_SIREN7: + if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) { if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) { if (bit_rate != 32000) { ast_log(LOG_WARNING, "Got Siren7 offer at %u bps, but only 32000 bps supported; ignoring.\n", bit_rate); @@ -11257,8 +11322,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ found = TRUE; } } - break; - case AST_FORMAT_SIREN14: + } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) { if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) { if (bit_rate != 48000) { ast_log(LOG_WARNING, "Got Siren14 offer at %u bps, but only 48000 bps supported; ignoring.\n", bit_rate); @@ -11267,8 +11331,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ found = TRUE; } } - break; - case AST_FORMAT_G719: + } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) { if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) { if (bit_rate != 64000) { ast_log(LOG_WARNING, "Got G.719 offer at %u bps, but only 64000 bps supported; ignoring.\n", bit_rate); @@ -11277,8 +11340,8 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ found = TRUE; } } - break; } + ao2_ref(format, -1); } } @@ -11320,11 +11383,19 @@ static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_ struct ast_format *format; if ((format = ast_rtp_codecs_get_payload_format(newvideortp, codec))) { - if (!ast_format_sdp_parse(format, fmtp_string)) { + struct ast_format *format_parsed; + + format_parsed = ast_format_parse_sdp_fmtp(format, fmtp_string); + + if (format_parsed) { + ast_rtp_codecs_payload_replace_format(newvideortp, codec, format_parsed); + ao2_replace(format, format_parsed); + ao2_ref(format_parsed, -1); found = TRUE; } else { ast_rtp_codecs_payloads_unset(newvideortp, NULL, codec); } + ao2_ref(format, -1); } } @@ -12890,12 +12961,11 @@ static void add_codec_to_sdp(const struct sip_pvt *p, int *max_packet_size) { int rtp_code; - struct ast_format_list fmt; const char *mime; - unsigned int rate; + unsigned int rate, framing; if (debug) - ast_verbose("Adding codec %u (%s) to SDP\n", format->id, ast_getformatname(format)); + ast_verbose("Adding codec %s to SDP\n", ast_format_get_name(format)); if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, format, 0)) == -1) || !(mime = ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0)) || @@ -12903,63 +12973,54 @@ static void add_codec_to_sdp(const struct sip_pvt *p, return; } - if (p->rtp) { - struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref; - fmt = ast_codec_pref_getsize(pref, format); - } else /* I don't see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */ - return; ast_str_append(m_buf, 0, " %d", rtp_code); /* Opus mandates 2 channels in rtpmap */ - if ((int)format->id == AST_FORMAT_OPUS) { + if (ast_format_cmp(format, ast_format_opus) == AST_FORMAT_CMP_EQUAL) { ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u/2\r\n", rtp_code, mime, rate); } else { ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u\r\n", rtp_code, mime, rate); } - ast_format_sdp_generate(format, rtp_code, a_buf); + ast_format_generate_sdp_fmtp(format, rtp_code, a_buf); + + framing = ast_format_cap_get_format_framing(p->caps, format); - switch ((int) format->id) { - case AST_FORMAT_G729A: + if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) { /* Indicate that we don't support VAD (G.729 annex B) */ ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code); - break; - case AST_FORMAT_G723_1: + } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) { /* Indicate that we don't support VAD (G.723.1 annex A) */ ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code); - break; - case AST_FORMAT_ILBC: + } else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL) { /* Add information about us using only 20/30 ms packetization */ - ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms); - break; - case AST_FORMAT_SIREN7: + ast_str_append(a_buf, 0, "a=fmtp:%d mode=%u\r\n", rtp_code, framing); + } else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) { /* Indicate that we only expect 32Kbps */ ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=32000\r\n", rtp_code); - break; - case AST_FORMAT_SIREN14: + } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) { /* Indicate that we only expect 48Kbps */ ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=48000\r\n", rtp_code); - break; - case AST_FORMAT_G719: + } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) { /* Indicate that we only expect 64Kbps */ ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code); - break; } - if (max_packet_size && fmt.max_ms && (fmt.max_ms < *max_packet_size)) { - *max_packet_size = fmt.max_ms; + if (max_packet_size && ast_format_get_maximum_ms(format) && + (ast_format_get_maximum_ms(format) < *max_packet_size)) { + *max_packet_size = ast_format_get_maximum_ms(format); } - if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) { - *min_packet_size = fmt.cur_ms; + if (framing && (framing < *min_packet_size)) { + *min_packet_size = framing; } /* Our first codec packetization processed cannot be zero */ - if ((*min_packet_size) == 0 && fmt.cur_ms) { - *min_packet_size = fmt.cur_ms; + if ((*min_packet_size) == 0 && framing) { + *min_packet_size = framing; } - if ((*max_packet_size) == 0 && fmt.max_ms) { - *max_packet_size = fmt.max_ms; + if ((*max_packet_size) == 0 && ast_format_get_maximum_ms(format)) { + *max_packet_size = ast_format_get_maximum_ms(format); } } @@ -12977,7 +13038,7 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format return; if (debug) - ast_verbose("Adding video codec %u (%s) to SDP\n", format->id, ast_getformatname(format)); + ast_verbose("Adding video codec %s to SDP\n", ast_format_get_name(format)); if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, format, 0)) == -1) || !(subtype = ast_rtp_lookup_mime_subtype2(1, format, 0, 0)) || @@ -12988,11 +13049,11 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format ast_str_append(m_buf, 0, " %d", rtp_code); ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u\r\n", rtp_code, subtype, rate); /* VP8: add RTCP FIR support */ - if ((int)format->id == AST_FORMAT_VP8) { + if (ast_format_cmp(format, ast_format_vp8) == AST_FORMAT_CMP_EQUAL) { ast_str_append(a_buf, 0, "a=rtcp-fb:* ccm fir\r\n"); } - ast_format_sdp_generate(format, rtp_code, a_buf); + ast_format_generate_sdp_fmtp(format, rtp_code, a_buf); } /*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */ @@ -13006,7 +13067,7 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format return; if (debug) - ast_verbose("Adding text codec %u (%s) to SDP\n", format->id, ast_getformatname(format)); + ast_verbose("Adding text codec %s to SDP\n", ast_format_get_name(format)); if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, format, 0)) == -1) return; @@ -13017,9 +13078,8 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format ast_rtp_lookup_sample_rate2(1, format, 0)); /* Add fmtp code here */ - if (format->id == AST_FORMAT_T140RED) { - struct ast_format tmp_fmt; - int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_set(&tmp_fmt, AST_FORMAT_T140, 0), 0); + if (ast_format_cmp(format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) { + int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_t140, 0); ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code, t140code, t140code, @@ -13194,8 +13254,8 @@ static char *crypto_get_attrib(struct ast_sdp_srtp *srtp, int dtls_enabled, int */ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38) { - struct ast_format_cap *alreadysent = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - struct ast_format_cap *tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + struct ast_format_cap *alreadysent = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + struct ast_format_cap *tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); int res = AST_SUCCESS; int doing_directmedia = FALSE; struct ast_sockaddr addr = { {0,} }; @@ -13229,7 +13289,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int RAII_VAR(char *, t_a_crypto, NULL, ast_free); int x; - struct ast_format tmp_fmt; + struct ast_format *tmp_fmt; int needaudio = FALSE; int needvideo = FALSE; int needtext = FALSE; @@ -13239,8 +13299,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int int min_video_packet_size = 0; int min_text_packet_size = 0; - char codecbuf[SIPBUFSIZE]; - char buf[SIPBUFSIZE]; + struct ast_str *codec_buf = ast_str_alloca(64); /* Set the SDP session name */ snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); @@ -13268,11 +13327,24 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int } if (add_audio) { - doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && !(ast_format_cap_is_empty(p->redircaps))) ? TRUE : FALSE; + doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && (ast_format_cap_count(p->redircaps))) ? TRUE : FALSE; + + if (doing_directmedia) { + ast_format_cap_get_compatible(p->jointcaps, p->redircaps, tmpcap); + ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_format_cap_get_names(tmpcap, &codec_buf)); + } else { + ast_format_cap_append_from_cap(tmpcap, p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); + } + + /* Check if we need audio */ + if (ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_AUDIO) + || ast_format_cap_has_type(p->caps, AST_MEDIA_TYPE_AUDIO)) { + needaudio = TRUE; + } + /* Check if we need video in this call */ - if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_VIDEO)) && !p->novideo) { - ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap); - if (doing_directmedia && !ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_VIDEO)) { + if ((ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_VIDEO)) && !p->novideo) { + if (doing_directmedia && !ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_VIDEO)) { ast_debug(2, "This call needs video offers, but caller probably did not offer it!\n"); } else if (p->vrtp) { needvideo = TRUE; @@ -13281,8 +13353,9 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int ast_debug(2, "This call needs video offers, but there's no video support enabled!\n"); } } + /* Check if we need text in this call */ - if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_TEXT)) && !p->notext) { + if ((ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_TEXT)) && !p->notext) { if (sipdebug_text) ast_verbose("We think we can do text\n"); if (p->trtp) { @@ -13295,6 +13368,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n"); } } + + /* XXX note, Video and Text are negated - 'true' means 'no' */ + ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", + ast_format_cap_get_names(tmpcap, &codec_buf), + p->novideo ? "True" : "False", p->notext ? "True" : "False"); + ast_debug(1, "** Our prefcodec: %s \n", ast_format_cap_get_names(p->prefcaps, &codec_buf)); } get_our_media_address(p, needvideo, needtext, &addr, &vaddr, &taddr, &dest, &vdest, &tdest); @@ -13322,22 +13401,6 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int hold = "a=sendrecv\r\n"; } - ast_format_cap_copy(tmpcap, p->jointcaps); - - /* XXX note, Video and Text are negated - 'true' means 'no' */ - ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap), - p->novideo ? "True" : "False", p->notext ? "True" : "False"); - ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcaps)); - - if (doing_directmedia) { - ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap); - ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap)); - } - - /* Check if we need audio */ - if (ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_AUDIO)) - needaudio = TRUE; - if (debug) { ast_verbose("Audio is at %s\n", ast_sockaddr_stringify_port(&addr)); } @@ -13406,8 +13469,8 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int /* Now, start adding audio codecs. These are added in this order: - First what was requested by the calling channel + - Then our mutually shared capabilities, determined previous in tmpcap - Then preferences in order from sip.conf device config for this peer/user - - Then other codecs in capabilities, including video */ @@ -13415,57 +13478,62 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int * configured codecs. */ if (!ast_test_flag(&p->flags[2], SIP_PAGE3_IGNORE_PREFCAPS)) { - ast_format_cap_iter_start(p->prefcaps); - while (!(ast_format_cap_iter_next(p->prefcaps, &tmp_fmt))) { - if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO || - !ast_format_cap_iscompatible(tmpcap, &tmp_fmt)) { + for (x = 0; x < ast_format_cap_count(p->prefcaps); x++) { + tmp_fmt = ast_format_cap_get_format(p->prefcaps, x); + + if ((ast_format_get_type(tmp_fmt) != AST_MEDIA_TYPE_AUDIO) || + (ast_format_cap_iscompatible_format(tmpcap, tmp_fmt) == AST_FORMAT_CMP_NOT_EQUAL)) { + ao2_ref(tmp_fmt, -1); continue; } - add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size); - ast_format_cap_add(alreadysent, &tmp_fmt); + + add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size); + ast_format_cap_append(alreadysent, tmp_fmt, 0); + ao2_ref(tmp_fmt, -1); } - ast_format_cap_iter_end(p->prefcaps); } - /* Start by sending our preferred audio/video codecs */ - for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { - struct ast_format pref; - - if (!(ast_codec_pref_index(&p->prefs, x, &pref))) - break; - - if (!ast_format_cap_get_compatible_format(tmpcap, &pref, &tmp_fmt)) - continue; + /* Now send any other common codecs */ + for (x = 0; x < ast_format_cap_count(tmpcap); x++) { + tmp_fmt = ast_format_cap_get_format(tmpcap, x); - if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt)) + if (ast_format_cap_iscompatible_format(alreadysent, tmp_fmt) != AST_FORMAT_CMP_NOT_EQUAL) { + ao2_ref(tmp_fmt, -1); continue; + } - if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) { - add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size); - } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) { - add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size); - } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) { - add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size); + if (ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_AUDIO) { + add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size); + } else if (needvideo && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_VIDEO) { + add_vcodec_to_sdp(p, tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size); + } else if (needtext && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_TEXT) { + add_tcodec_to_sdp(p, tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size); } - ast_format_cap_add(alreadysent, &tmp_fmt); + ast_format_cap_append(alreadysent, tmp_fmt, 0); + ao2_ref(tmp_fmt, -1); } - /* Now send any other common audio and video codecs, and non-codec formats: */ - ast_format_cap_iter_start(tmpcap); - while (!(ast_format_cap_iter_next(tmpcap, &tmp_fmt))) { - if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt)) + /* Finally our remaining audio/video codecs */ + for (x = 0; x < ast_format_cap_count(p->caps); x++) { + tmp_fmt = ast_format_cap_get_format(p->caps, x); + + if (ast_format_cap_iscompatible_format(alreadysent, tmp_fmt) != AST_FORMAT_CMP_NOT_EQUAL) { + ao2_ref(tmp_fmt, -1); continue; + } - if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) { - add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size); - } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) { - add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size); - } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) { - add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size); + if (ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_AUDIO) { + add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size); + } else if (needvideo && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_VIDEO) { + add_vcodec_to_sdp(p, tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size); + } else if (needtext && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_TEXT) { + add_tcodec_to_sdp(p, tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size); } + + ast_format_cap_append(alreadysent, tmp_fmt, 0); + ao2_ref(tmp_fmt, -1); } - ast_format_cap_iter_end(tmpcap); /* Now add DTMF RFC2833 telephony-event as a codec */ for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { @@ -13677,14 +13745,15 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int ao2_t_link(dialogs_rtpcheck, p, "link pvt into dialogs_rtpcheck container"); ao2_unlock(dialogs_rtpcheck); - ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmpcap)); + ast_debug(3, "Done building SDP. Settling with this capability: %s\n", + ast_format_cap_get_names(tmpcap, &codec_buf)); add_sdp_cleanup: ast_free(a_text); ast_free(a_video); ast_free(a_audio); - alreadysent = ast_format_cap_destroy(alreadysent); - tmpcap = ast_format_cap_destroy(tmpcap); + ao2_cleanup(alreadysent); + ao2_cleanup(tmpcap); return res; } @@ -13792,7 +13861,7 @@ static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const if (p->rtp) { if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { ast_debug(1, "Setting framing from config on incoming call\n"); - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs); + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(p->caps)); } ast_rtp_instance_activate(p->rtp); try_suggested_sip_codec(p); @@ -18475,10 +18544,9 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of, peer->name, of, ast_sockaddr_stringify(&p->recv)); } - /* XXX what about p->prefs = peer->prefs; ? */ /* Set Frame packetization */ if (p->rtp) { - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs); + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(peer->caps)); p->autoframing = peer->autoframing; } @@ -18595,20 +18663,22 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of, p->named_callgroups = ast_ref_namedgroups(peer->named_callgroups); ast_unref_namedgroups(p->named_pickupgroups); p->named_pickupgroups = ast_ref_namedgroups(peer->named_pickupgroups); - ast_format_cap_copy(p->caps, peer->caps); - ast_format_cap_copy(p->jointcaps, peer->caps); - p->prefs = peer->prefs; + ast_format_cap_remove_by_type(p->caps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(p->caps, peer->caps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(p->jointcaps, peer->caps, AST_MEDIA_TYPE_UNKNOWN); ast_copy_string(p->zone, peer->zone, sizeof(p->zone)); if (peer->maxforwards > 0) { p->maxforwards = peer->maxforwards; } - if (!(ast_format_cap_is_empty(p->peercaps))) { - struct ast_format_cap *tmp = ast_format_cap_joint(p->jointcaps, p->peercaps); - struct ast_format_cap *tmp2; - if (tmp) { - tmp2 = p->jointcaps; - p->jointcaps = tmp; - ast_format_cap_destroy(tmp2); + if (ast_format_cap_count(p->peercaps)) { + struct ast_format_cap *joint; + + joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (joint) { + ast_format_cap_get_compatible(p->jointcaps, p->peercaps, joint); + ao2_ref(p->jointcaps, -1); + p->jointcaps = joint; } } p->maxcallbitrate = peer->maxcallbitrate; @@ -18623,7 +18693,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of, p->rtpkeepalive = peer->rtpkeepalive; if (!dialog_initialize_rtp(p)) { if (p->rtp) { - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs); + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(peer->caps)); p->autoframing = peer->autoframing; } } else { @@ -19959,25 +20029,6 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli return CLI_SUCCESS; } -/*! \brief Print codec list from preference to CLI/manager */ -static void print_codec_to_cli(int fd, struct ast_codec_pref *pref) -{ - int x; - struct ast_format codec; - - for(x = 0; x < AST_CODEC_PREF_SIZE; x++) { - if (!(ast_codec_pref_index(pref, x, &codec))) { - break; - } - ast_cli(fd, "%s", ast_getformatname(&codec)); - ast_cli(fd, ":%d", pref->framing[x]); - if (x < 31 && ast_codec_pref_index(pref, x + 1, &codec)) - ast_cli(fd, ","); - } - if (!x) - ast_cli(fd, "none"); -} - /*! \brief Print domain mode to cli */ static const char *domain_mode_to_text(const enum domain_mode mode) { @@ -20262,11 +20313,9 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct char status[30] = ""; char cbuf[256]; struct sip_peer *peer; - char codec_buf[512]; - struct ast_codec_pref *pref; + struct ast_str *codec_buf = ast_str_alloca(64); struct ast_variable *v; int x = 0, load_realtime; - struct ast_format codec; int realtimepeers; realtimepeers = ast_check_realtime("sippeers"); @@ -20415,12 +20464,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct ast_cli(fd, "(none)"); ast_cli(fd, "\n"); - ast_cli(fd, " Codecs : "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps); - ast_cli(fd, "%s\n", codec_buf); - ast_cli(fd, " Codec Order : ("); - print_codec_to_cli(fd, &peer->prefs); - ast_cli(fd, ")\n"); + ast_cli(fd, " Codecs : %s\n", ast_format_cap_get_names(peer->caps, &codec_buf)); ast_cli(fd, " Auto-Framing : %s\n", AST_CLI_YESNO(peer->autoframing)); ast_cli(fd, " Status : "); @@ -20523,21 +20567,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct astman_append(s, "Default-Username: %s\r\n", peer->username); if (!ast_strlen_zero(sip_cfg.regcontext)) astman_append(s, "RegExtension: %s\r\n", peer->regexten); - astman_append(s, "Codecs: "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps); - astman_append(s, "%s\r\n", codec_buf); - astman_append(s, "CodecOrder: "); - pref = &peer->prefs; - for(x = 0; x < AST_CODEC_PREF_SIZE ; x++) { - if (!(ast_codec_pref_index(pref, x, &codec))) { - break; - } - astman_append(s, "%s", ast_getformatname(&codec)); - if ((x < (AST_CODEC_PREF_SIZE - 1)) && ast_codec_pref_index(pref, x+1, &codec)) - astman_append(s, ","); - } - - astman_append(s, "\r\n"); + astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(peer->caps, &codec_buf)); astman_append(s, "Status: "); peer_status(peer, status, sizeof(status)); astman_append(s, "%s\r\n", status); @@ -20660,10 +20690,6 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se); ast_cli(a->fd, " RTP Engine : %s\n", user->engine); - ast_cli(a->fd, " Codec Order : ("); - print_codec_to_cli(a->fd, &user->prefs); - ast_cli(a->fd, ")\n"); - ast_cli(a->fd, " Auto-Framing: %s \n", AST_CLI_YESNO(user->autoframing)); if (user->chanvars) { ast_cli(a->fd, " Variables :\n"); @@ -20916,7 +20942,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_ { int realtimepeers; int realtimeregs; - char codec_buf[SIPBUFSIZE]; + struct ast_str *codec_buf = ast_str_alloca(64); const char *msg; /* temporary msg pointer */ struct sip_auth_container *credentials; @@ -21069,12 +21095,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_ } ast_cli(a->fd, "\nGlobal Signalling Settings:\n"); ast_cli(a->fd, "---------------------------\n"); - ast_cli(a->fd, " Codecs: "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, sip_cfg.caps); - ast_cli(a->fd, "%s\n", codec_buf); - ast_cli(a->fd, " Codec Order: "); - print_codec_to_cli(a->fd, &default_prefs); - ast_cli(a->fd, "\n"); + ast_cli(a->fd, " Codecs: %s\n", ast_format_cap_get_names(sip_cfg.caps, &codec_buf)); ast_cli(a->fd, " Relax DTMF: %s\n", AST_CLI_YESNO(global_relaxdtmf)); ast_cli(a->fd, " RFC2833 Compensation: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_RFC2833_COMPENSATE))); ast_cli(a->fd, " Symmetric RTP: %s\n", comedia_string(global_flags)); @@ -21233,12 +21254,12 @@ static int show_channels_cb(void *__cur, void *__arg, int flags) if (cur->subscribed == NONE && !arg->subscriptions) { /* set if SIP transfer in progress */ const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : ""; - char formatbuf[SIPBUFSIZE/2]; + struct ast_str *codec_buf = ast_str_alloca(64); ast_cli(arg->fd, FORMAT, ast_sockaddr_stringify_addr(dst), S_OR(cur->username, S_OR(cur->cid_num, "(None)")), cur->callid, - cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), ast_channel_nativeformats(cur->owner)) : "(nothing)", + cur->owner ? ast_format_cap_get_names(ast_channel_nativeformats(cur->owner), &codec_buf) : "(nothing)", AST_CLI_YESNO(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)), cur->needdestroy ? "(d)" : "", cur->lastmsg , @@ -21479,7 +21500,8 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a if (!strncasecmp(cur->callid, a->argv[3], len)) { struct ast_str *strbuf; - char formatbuf[SIPBUFSIZE/2]; + struct ast_str *codec_buf = ast_str_alloca(64); + ast_cli(a->fd, "\n"); if (cur->subscribed != NONE) { ast_cli(a->fd, " * Subscription (type: %s)\n", subscription_type2str(cur->subscribed)); @@ -21489,11 +21511,11 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a ast_cli(a->fd, " Curr. trans. direction: %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING) ? "Outgoing" : "Incoming"); ast_cli(a->fd, " Call-ID: %s\n", cur->callid); ast_cli(a->fd, " Owner channel ID: %s\n", cur->owner ? ast_channel_name(cur->owner) : "<none>"); - ast_cli(a->fd, " Our Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->caps)); + ast_cli(a->fd, " Our Codec Capability: %s\n", ast_format_cap_get_names(cur->caps, &codec_buf)); ast_cli(a->fd, " Non-Codec Capability (DTMF): %d\n", cur->noncodeccapability); - ast_cli(a->fd, " Their Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->peercaps)); - ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->jointcaps)); - ast_cli(a->fd, " Format: %s\n", cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), ast_channel_nativeformats(cur->owner)) : "(nothing)" ); + ast_cli(a->fd, " Their Codec Capability: %s\n", ast_format_cap_get_names(cur->peercaps, &codec_buf)); + ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_format_cap_get_names(cur->jointcaps, &codec_buf)); + ast_cli(a->fd, " Format: %s\n", cur->owner ? ast_format_cap_get_names(ast_channel_nativeformats(cur->owner), &codec_buf) : "(nothing)" ); ast_cli(a->fd, " T.38 support %s\n", AST_CLI_YESNO(cur->udptl != NULL)); ast_cli(a->fd, " Video support %s\n", AST_CLI_YESNO(cur->vrtp != NULL)); ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate); @@ -22437,7 +22459,9 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat } else if (!strcasecmp(colname, "callerid_num")) { ast_copy_string(buf, peer->cid_num, len); } else if (!strcasecmp(colname, "codecs")) { - ast_getformatname_multiple(buf, len -1, peer->caps); + struct ast_str *codec_buf = ast_str_alloca(64); + ast_format_cap_get_names(peer->caps, &codec_buf); + ast_copy_string(buf, ast_str_buffer(codec_buf), len); } else if (!strcasecmp(colname, "encryption")) { snprintf(buf, len, "%u", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP)); } else if (!strncasecmp(colname, "chanvar[", 8)) { @@ -22452,12 +22476,14 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat } } else if (!strncasecmp(colname, "codec[", 6)) { char *codecnum; - struct ast_format codec; + struct ast_format *codec; codecnum = colname + 6; /* move past the '[' */ codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */ - if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &codec))) { - ast_copy_string(buf, ast_getformatname(&codec), len); + codec = ast_format_cap_get_format(peer->caps, atoi(codecnum)); + if (codec) { + ast_copy_string(buf, ast_format_get_name(codec), len); + ao2_ref(codec, -1); } else { buf[0] = '\0'; } @@ -25476,7 +25502,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str } ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE); } else { - ast_format_cap_copy(p->jointcaps, p->caps); + ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(p->jointcaps, p->caps, AST_MEDIA_TYPE_UNKNOWN); ast_debug(1, "Hm.... No sdp for the moment\n"); /* Some devices signal they want to be put off hold by sending a re-invite *without* an SDP, which is supposed to mean "Go back to your state" @@ -25541,7 +25568,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str goto request_invite_cleanup; } } else { /* No SDP in invite, call control session */ - ast_format_cap_copy(p->jointcaps, p->caps); + ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(p->jointcaps, p->caps, AST_MEDIA_TYPE_UNKNOWN); ast_debug(2, "No SDP in Invite, third party call control\n"); } @@ -25855,7 +25883,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str if (p && (p->autokillid == -1)) { const char *msg; - if ((ast_format_cap_is_empty(p->jointcaps))) + if ((!ast_format_cap_count(p->jointcaps))) msg = "488 Not Acceptable Here (codec error)"; else { ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n"); @@ -29539,7 +29567,8 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_ struct ast_channel *tmpc = NULL; char *ext = NULL, *host; char tmp[256]; - char tmp2[256]; + struct ast_str *codec_buf = ast_str_alloca(64); + struct ast_str *cap_buf = ast_str_alloca(64); char *dnid; char *secret = NULL; char *md5secret = NULL; @@ -29562,14 +29591,14 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_ * configured from sip.conf, and sip_tech.capabilities, which is * hardwired to all audio formats. */ - if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) { + if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) { ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n", - ast_getformatname_multiple(tmp, sizeof(tmp), cap), - ast_getformatname_multiple(tmp2, sizeof(tmp2), sip_cfg.caps)); + ast_format_cap_get_names(cap, &codec_buf), + ast_format_cap_get_names(sip_cfg.caps, &cap_buf)); *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; /* Can't find codec to connect to host */ return NULL; } - ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); + ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_format_cap_get_names(cap, &codec_buf)); if (ast_strlen_zero(dest)) { ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n"); @@ -29739,8 +29768,8 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_ #if 0 printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host); #endif - ast_format_cap_append(p->prefcaps, cap); - ast_format_cap_joint_copy(cap, p->caps, p->jointcaps); + ast_format_cap_append_from_cap(p->prefcaps, cap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_get_compatible(cap, p->caps, p->jointcaps); sip_pvt_lock(p); @@ -30217,7 +30246,7 @@ static void set_peer_defaults(struct sip_peer *peer) ast_string_field_set(peer, engine, default_engine); ast_sockaddr_setnull(&peer->addr); ast_sockaddr_setnull(&peer->defaddr); - ast_format_cap_copy(peer->caps, sip_cfg.caps); + ast_format_cap_append_from_cap(peer->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN); peer->maxcallbitrate = default_maxcallbitrate; peer->rtptimeout = global_rtptimeout; peer->rtpholdtimeout = global_rtpholdtimeout; @@ -30243,7 +30272,6 @@ static void set_peer_defaults(struct sip_peer *peer) peer->pickupgroup = 0; peer->maxms = default_qualify; peer->keepalive = default_keepalive; - peer->prefs = default_prefs; ast_string_field_set(peer, zone, default_zone); peer->stimer.st_mode_oper = global_st_mode; /* Session-Timers */ peer->stimer.st_ref = global_st_refresher; @@ -30279,7 +30307,7 @@ static struct sip_peer *temp_peer(const char *name) return NULL; } - if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) { + if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer"); return NULL; } @@ -30291,7 +30319,6 @@ static struct sip_peer *temp_peer(const char *name) peer->selfdestruct = TRUE; peer->host_dynamic = TRUE; - peer->prefs = default_prefs; reg_source_db(peer); return peer; @@ -30384,7 +30411,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str if (!(peer->endpoint = ast_endpoint_create("SIP", name))) { return NULL; } - if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) { + if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer"); return NULL; } @@ -30705,12 +30732,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str } else if (!strcasecmp(v->name, "namedpickupgroup")) { peer->named_pickupgroups = ast_get_namedgroups(v->value); } else if (!strcasecmp(v->name, "allow")) { - int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, TRUE); + int error = ast_format_cap_update_by_allow_disallow(peer->caps, v->value, TRUE); if (error) { ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); } } else if (!strcasecmp(v->name, "disallow")) { - int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, FALSE); + int error = ast_format_cap_update_by_allow_disallow(peer->caps, v->value, FALSE); if (error) { ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); } @@ -31104,14 +31131,11 @@ static int peer_markall_autopeers_func(void *device, void *arg, int flags) */ static void sip_set_default_format_capabilities(struct ast_format_cap *cap) { - struct ast_format tmp_fmt; - - ast_format_cap_remove_all(cap); - ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_TESTLAW, 0)); - ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ALAW, 0)); - ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0)); - ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_H263, 0)); + ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append(cap, ast_format_ulaw, 0); + ast_format_cap_append(cap, ast_format_alaw, 0); + ast_format_cap_append(cap, ast_format_gsm, 0); + ast_format_cap_append(cap, ast_format_h263, 0); } static void display_nat_warning(const char *cat, int reason, struct ast_flags *flags) { @@ -31276,7 +31300,6 @@ static int reload_config(enum channelreloadreason reason) memset(&localaddr, 0, sizeof(localaddr)); memset(&externaddr, 0, sizeof(externaddr)); memset(&media_address, 0, sizeof(media_address)); - memset(&default_prefs, 0 , sizeof(default_prefs)); memset(&sip_cfg.outboundproxy, 0, sizeof(struct sip_proxy)); sip_cfg.outboundproxy.force = FALSE; /*!< Don't force proxy usage, use route: headers */ default_transports = AST_TRANSPORT_UDP; @@ -31768,12 +31791,12 @@ static int reload_config(enum channelreloadreason reason) ast_log(LOG_WARNING, "Invalid externtlsport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno); } } else if (!strcasecmp(v->name, "allow")) { - int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, TRUE); + int error = ast_format_cap_update_by_allow_disallow(sip_cfg.caps, v->value, TRUE); if (error) { ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); } } else if (!strcasecmp(v->name, "disallow")) { - int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, FALSE); + int error = ast_format_cap_update_by_allow_disallow(sip_cfg.caps, v->value, FALSE); if (error) { ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); } @@ -32565,8 +32588,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i memset(&p->tredirip, 0, sizeof(p->tredirip)); changed = 1; } - if (cap && !ast_format_cap_is_empty(cap) && !ast_format_cap_identical(p->redircaps, cap)) { - ast_format_cap_copy(p->redircaps, cap); + if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(cap, p->redircaps)) { + ast_format_cap_remove_by_type(p->redircaps, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_append_from_cap(p->redircaps, cap, AST_MEDIA_TYPE_UNKNOWN); changed = 1; } @@ -32603,7 +32627,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i static void sip_get_codec(struct ast_channel *chan, struct ast_format_cap *result) { struct sip_pvt *p = ast_channel_tech_pvt(chan); - ast_format_cap_append(result, ast_format_cap_is_empty(p->peercaps) ? p->caps : p->peercaps); + + ast_format_cap_append_from_cap(result, !ast_format_cap_count(p->peercaps) ? p->caps : p->peercaps, AST_MEDIA_TYPE_UNKNOWN); } static struct ast_rtp_glue sip_rtp_glue = { @@ -34217,6 +34242,8 @@ static const struct ast_sip_api_tech chan_sip_api_provider = { .sipinfo_send = sipinfo_send, }; +static int unload_module(void); + /*! * \brief Load the module * @@ -34232,14 +34259,17 @@ static int load_module(void) ast_verbose("SIP channel loading...\n"); if (STASIS_MESSAGE_TYPE_INIT(session_timeout_type)) { + unload_module(); return AST_MODULE_LOAD_FAILURE; } if (!(sip_tech.capabilities = ast_format_cap_alloc(0))) { + unload_module(); return AST_MODULE_LOAD_FAILURE; } if (ast_sip_api_provider_register(&chan_sip_api_provider)) { + unload_module(); return AST_MODULE_LOAD_FAILURE; } @@ -34254,24 +34284,28 @@ static int load_module(void) if (!peers || !peers_by_ip || !dialogs || !dialogs_needdestroy || !dialogs_rtpcheck || !threadt) { ast_log(LOG_ERROR, "Unable to create primary SIP container(s)\n"); + unload_module(); return AST_MODULE_LOAD_FAILURE; } - if (!(sip_cfg.caps = ast_format_cap_alloc(0))) { + if (!(sip_cfg.caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { + unload_module(); return AST_MODULE_LOAD_FAILURE; } - ast_format_cap_add_all_by_type(sip_tech.capabilities, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_append_by_type(sip_tech.capabilities, AST_MEDIA_TYPE_AUDIO); ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */ ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */ if (!(sched = ast_sched_context_create())) { ast_log(LOG_ERROR, "Unable to create scheduler context\n"); + unload_module(); return AST_MODULE_LOAD_FAILURE; } if (!(io = io_context_create())) { ast_log(LOG_ERROR, "Unable to create I/O context\n"); + unload_module(); return AST_MODULE_LOAD_FAILURE; } @@ -34279,15 +34313,14 @@ static int load_module(void) can_parse_xml = sip_is_xml_parsable(); if (reload_config(sip_reloadreason)) { /* Load the configuration from sip.conf */ - ast_sip_api_provider_unregister(); + unload_module(); return AST_MODULE_LOAD_DECLINE; } /* Initialize bogus peer. Can be done first after reload_config() */ if (!(bogus_peer = temp_peer("(bogus_peer)"))) { ast_log(LOG_ERROR, "Unable to create bogus_peer for authentication\n"); - io_context_destroy(io); - ast_sched_context_destroy(sched); + unload_module(); return AST_MODULE_LOAD_FAILURE; } /* Make sure the auth will always fail. */ @@ -34302,16 +34335,14 @@ static int load_module(void) memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin)); if (ast_msg_tech_register(&sip_msg_tech)) { - /* LOAD_FAILURE stops Asterisk, so cleanup is a moot point. */ + unload_module(); return AST_MODULE_LOAD_FAILURE; } /* Make sure we can register our sip channel type */ if (ast_channel_register(&sip_tech)) { ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n"); - ao2_t_ref(bogus_peer, -1, "unref the bogus_peer"); - io_context_destroy(io); - ast_sched_context_destroy(sched); + unload_module(); return AST_MODULE_LOAD_FAILURE; } @@ -34358,13 +34389,13 @@ static int load_module(void) initialize_escs(); if (sip_epa_register(&cc_epa_static_data)) { - ast_sip_api_provider_unregister(); + unload_module(); return AST_MODULE_LOAD_DECLINE; } if (sip_reqresp_parser_init() == -1) { ast_log(LOG_ERROR, "Unable to initialize the SIP request and response parser\n"); - ast_sip_api_provider_unregister(); + unload_module(); return AST_MODULE_LOAD_DECLINE; } @@ -34373,16 +34404,16 @@ static int load_module(void) * in incoming PUBLISH requests */ if (ast_cc_agent_register(&sip_cc_agent_callbacks)) { - ast_sip_api_provider_unregister(); + unload_module(); return AST_MODULE_LOAD_DECLINE; } } if (ast_cc_monitor_register(&sip_cc_monitor_callbacks)) { - ast_sip_api_provider_unregister(); + unload_module(); return AST_MODULE_LOAD_DECLINE; } if (!(sip_monitor_instances = ao2_container_alloc(37, sip_monitor_instance_hash_fn, sip_monitor_instance_cmp_fn))) { - ast_sip_api_provider_unregister(); + unload_module(); return AST_MODULE_LOAD_DECLINE; } @@ -34523,7 +34554,7 @@ static int unload_module(void) ast_mutex_lock(&authl_lock); if (authl) { - ao2_t_ref(authl, -1, "Removing global authentication"); + ao2_t_cleanup(authl, "Removing global authentication"); authl = NULL; } ast_mutex_unlock(&authl_lock); @@ -34568,15 +34599,15 @@ static int unload_module(void) ast_debug(2, "TCP/TLS thread container did not become empty :(\n"); } - ao2_t_ref(bogus_peer, -1, "unref the bogus_peer"); + ao2_t_cleanup(bogus_peer, "unref the bogus_peer"); - ao2_t_ref(peers, -1, "unref the peers table"); - ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table"); - ao2_t_ref(dialogs, -1, "unref the dialogs table"); - ao2_t_ref(dialogs_needdestroy, -1, "unref dialogs_needdestroy"); - ao2_t_ref(dialogs_rtpcheck, -1, "unref dialogs_rtpcheck"); - ao2_t_ref(threadt, -1, "unref the thread table"); - ao2_t_ref(sip_monitor_instances, -1, "unref the sip_monitor_instances table"); + ao2_t_cleanup(peers, "unref the peers table"); + ao2_t_cleanup(peers_by_ip, "unref the peers_by_ip table"); + ao2_t_cleanup(dialogs, "unref the dialogs table"); + ao2_t_cleanup(dialogs_needdestroy, "unref dialogs_needdestroy"); + ao2_t_cleanup(dialogs_rtpcheck, "unref dialogs_rtpcheck"); + ao2_t_cleanup(threadt, "unref the thread table"); + ao2_t_cleanup(sip_monitor_instances, "unref the sip_monitor_instances table"); clear_sip_domains(); sip_cfg.contact_acl = ast_free_acl_list(sip_cfg.contact_acl); @@ -34604,8 +34635,10 @@ static int unload_module(void) notify_types = NULL; } - ast_format_cap_destroy(sip_tech.capabilities); - sip_cfg.caps = ast_format_cap_destroy(sip_cfg.caps); + ao2_cleanup(sip_tech.capabilities); + sip_tech.capabilities = NULL; + ao2_cleanup(sip_cfg.caps); + sip_cfg.caps = NULL; STASIS_MESSAGE_TYPE_CLEANUP(session_timeout_type); diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 49ff8d548..e4882dbba 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -84,6 +84,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/bridge.h" #include "asterisk/parking.h" #include "asterisk/stasis_channels.h" +#include "asterisk/format_cache.h" /*** DOCUMENTATION <manager name="SKINNYdevices" language="en_US"> @@ -146,8 +147,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #ifdef AST_DEVMODE static int skinnydebug = 0; char dbgcli_buf[256]; -char dbgreg_buf[256]; -char dbgsub_buf[256]; #define DEBUG_GENERAL (1 << 1) #define DEBUG_SUB (1 << 2) #define DEBUG_PACKET (1 << 3) @@ -174,7 +173,6 @@ static const char tdesc[] = "Skinny Client Control Protocol (Skinny)"; static const char config[] = "skinny.conf"; static struct ast_format_cap *default_cap; -static struct ast_codec_pref default_prefs; enum skinny_codecs { SKINNY_CODEC_ALAW = 2, @@ -1454,8 +1452,6 @@ struct skinny_subchannel { int amaflags; \ int instance; \ int group; \ - struct ast_codec_pref confprefs; \ - struct ast_codec_pref prefs; \ int nonCodecCapability; \ int immediate; \ int nat; \ @@ -1568,7 +1564,6 @@ struct skinny_addon { int hookstate; \ int lastlineinstance; \ int lastcallreference; \ - struct ast_codec_pref confprefs; \ int earlyrtp; \ int transfer; \ int callwaiting; \ @@ -1679,11 +1674,11 @@ static struct skinny_line *skinny_line_alloc(void) return NULL; } - l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - l->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + l->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!l->cap || !l->confcap) { - l->cap = ast_format_cap_destroy(l->cap); - l->confcap = ast_format_cap_destroy(l->confcap); + ao2_cleanup(l->cap); + ao2_cleanup(l->confcap); ast_free(l); return NULL; } @@ -1691,8 +1686,8 @@ static struct skinny_line *skinny_line_alloc(void) } static struct skinny_line *skinny_line_destroy(struct skinny_line *l) { - l->cap = ast_format_cap_destroy(l->cap); - l->confcap = ast_format_cap_destroy(l->confcap); + ao2_ref(l->cap, -1); + ao2_ref(l->confcap, -1); l->named_callgroups = ast_unref_namedgroups(l->named_callgroups); l->named_pickupgroups = ast_unref_namedgroups(l->named_pickupgroups); ast_free(l->container); @@ -1706,12 +1701,12 @@ static struct skinny_device *skinny_device_alloc(const char *dname) return NULL; } - d->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - d->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); + d->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + d->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); d->endpoint = ast_endpoint_create("Skinny", dname); if (!d->cap || !d->confcap || !d->endpoint) { - d->cap = ast_format_cap_destroy(d->cap); - d->confcap = ast_format_cap_destroy(d->confcap); + ao2_cleanup(d->cap); + ao2_cleanup(d->confcap); ast_free(d); return NULL; } @@ -1722,8 +1717,8 @@ static struct skinny_device *skinny_device_alloc(const char *dname) } static struct skinny_device *skinny_device_destroy(struct skinny_device *d) { - d->cap = ast_format_cap_destroy(d->cap); - d->confcap = ast_format_cap_destroy(d->confcap); + ao2_ref(d->cap, -1); + ao2_ref(d->confcap, -1); ast_endpoint_shutdown(d->endpoint); ast_free(d); return NULL; @@ -2103,51 +2098,49 @@ static struct skinny_speeddial *find_speeddial_by_instance(struct skinny_device return sd; } -static struct ast_format *codec_skinny2ast(enum skinny_codecs skinnycodec, struct ast_format *result) +static struct ast_format *codec_skinny2ast(enum skinny_codecs skinnycodec) { switch (skinnycodec) { case SKINNY_CODEC_ALAW: - return ast_format_set(result, AST_FORMAT_ALAW, 0); + return ast_format_alaw; case SKINNY_CODEC_ULAW: - return ast_format_set(result, AST_FORMAT_ULAW, 0); + return ast_format_ulaw; case SKINNY_CODEC_G722: - return ast_format_set(result, AST_FORMAT_G722, 0); + return ast_format_g722; case SKINNY_CODEC_G723_1: - return ast_format_set(result, AST_FORMAT_G723_1, 0); + return ast_format_g723; case SKINNY_CODEC_G729A: - return ast_format_set(result, AST_FORMAT_G729A, 0); + return ast_format_g729; case SKINNY_CODEC_G726_32: - return ast_format_set(result, AST_FORMAT_G726_AAL2, 0); /* XXX Is this right? */ + return ast_format_g726; /* XXX Is this right? */ case SKINNY_CODEC_H261: - return ast_format_set(result, AST_FORMAT_H261, 0); + return ast_format_h261; case SKINNY_CODEC_H263: - return ast_format_set(result, AST_FORMAT_H263 ,0); + return ast_format_h263; default: - ast_format_clear(result); - return result; + return ast_format_none; } } static int codec_ast2skinny(const struct ast_format *astcodec) { - switch (astcodec->id) { - case AST_FORMAT_ALAW: + if (ast_format_cmp(astcodec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_ALAW; - case AST_FORMAT_ULAW: + } else if (ast_format_cmp(astcodec, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_ULAW; - case AST_FORMAT_G722: + } else if (ast_format_cmp(astcodec, ast_format_g722) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_G722; - case AST_FORMAT_G723_1: + } else if (ast_format_cmp(astcodec, ast_format_g723) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_G723_1; - case AST_FORMAT_G729A: + } else if (ast_format_cmp(astcodec, ast_format_g729) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_G729A; - case AST_FORMAT_G726_AAL2: /* XXX Is this right? */ + } else if (ast_format_cmp(astcodec, ast_format_g726) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_G726_32; - case AST_FORMAT_H261: + } else if (ast_format_cmp(astcodec, ast_format_h261) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_H261; - case AST_FORMAT_H263: + } else if (ast_format_cmp(astcodec, ast_format_h263) == AST_FORMAT_CMP_EQUAL) { return SKINNY_CODEC_H263; - default: + } else { return 0; } } @@ -2312,13 +2305,8 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s) instance++; } AST_LIST_TRAVERSE(&d->lines, l, list) { - ast_format_cap_joint_copy(l->confcap, d->cap, l->cap); - l->prefs = l->confprefs; - if (!l->prefs.order[0]) { - l->prefs = d->confprefs; - } - /* l->capability = d->capability; - l->prefs = d->prefs; */ + ast_format_cap_get_compatible(l->confcap, d->cap, l->cap); + /* l->capability = d->capability; */ l->instance = instance; l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL); set_callforwards(l, NULL, SKINNY_CFWD_ALL|SKINNY_CFWD_BUSY|SKINNY_CFWD_NOANSWER); @@ -2656,23 +2644,27 @@ static void transmit_connect(struct skinny_device *d, struct skinny_subchannel * { struct skinny_req *req; struct skinny_line *l = sub->line; - struct ast_format_list fmt; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; + unsigned int framing; if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE))) return; - ast_best_codec(l->cap, &tmpfmt); - fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt); + + tmpfmt = ast_format_cap_get_format(l->cap, 0); + framing = ast_format_cap_get_format_framing(l->cap, tmpfmt); 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(&fmt.format)); + req->data.openreceivechannel.packets = htolel(framing); + req->data.openreceivechannel.capability = htolel(codec_ast2skinny(tmpfmt)); req->data.openreceivechannel.echo = htolel(0); req->data.openreceivechannel.bitrate = htolel(0); SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting OPEN_RECEIVE_CHANNEL_MESSAGE to %s, confid %u, partyid %u, ms %d, fmt %d, echo %d, brate %d\n", - d->name, sub->callid, sub->callid, fmt.cur_ms, codec_ast2skinny(&fmt.format), 0, 0); + d->name, sub->callid, sub->callid, framing, codec_ast2skinny(tmpfmt), 0, 0); + + ao2_ref(tmpfmt, -1); + transmit_response(d, req); } @@ -3033,7 +3025,8 @@ static void transmit_stopmediatransmission(struct skinny_device *d, struct skinn transmit_response(d, req); } -static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, struct ast_format_list fmt) +static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, + struct ast_format *format, unsigned int framing) { struct skinny_req *req; @@ -3044,8 +3037,8 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin req->data.startmedia_ip4.passThruPartyId = htolel(sub->callid); req->data.startmedia_ip4.remoteIp = dest.sin_addr.s_addr; req->data.startmedia_ip4.remotePort = htolel(ntohs(dest.sin_port)); - req->data.startmedia_ip4.packetSize = htolel(fmt.cur_ms); - req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(&fmt.format)); + req->data.startmedia_ip4.packetSize = htolel(framing); + req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(format)); req->data.startmedia_ip4.qualifier.precedence = htolel(127); req->data.startmedia_ip4.qualifier.vad = htolel(0); req->data.startmedia_ip4.qualifier.packets = htolel(0); @@ -3057,8 +3050,8 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin req->data.startmedia_ip6.passThruPartyId = htolel(sub->callid); memcpy(req->data.startmedia_ip6.remoteIp, &dest.sin_addr.s_addr, sizeof(dest.sin_addr.s_addr)); req->data.startmedia_ip6.remotePort = htolel(ntohs(dest.sin_port)); - req->data.startmedia_ip6.packetSize = htolel(fmt.cur_ms); - req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(&fmt.format)); + req->data.startmedia_ip6.packetSize = htolel(framing); + req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(format)); req->data.startmedia_ip6.qualifier.precedence = htolel(127); req->data.startmedia_ip6.qualifier.vad = htolel(0); req->data.startmedia_ip6.qualifier.packets = htolel(0); @@ -3066,7 +3059,7 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin } SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting START_MEDIA_TRANSMISSION_MESSAGE to %s, callid %u, passthrupartyid %u, ip %s:%d, ms %d, fmt %d, prec 127\n", - d->name, sub->callid, sub->callid, ast_inet_ntoa(dest.sin_addr), dest.sin_port, fmt.cur_ms, codec_ast2skinny(&fmt.format)); + d->name, sub->callid, sub->callid, ast_inet_ntoa(dest.sin_addr), dest.sin_port, framing, codec_ast2skinny(format)); transmit_response(d, req); } @@ -3643,7 +3636,6 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r struct skinny_subchannel *sub; struct skinny_line *l; struct skinny_device *d; - struct ast_format_list fmt; struct sockaddr_in us = { 0, }; struct sockaddr_in them = { 0, }; struct ast_sockaddr them_tmp; @@ -3662,7 +3654,8 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r d = l->device; if (rtp){ - struct ast_format tmpfmt; + struct ast_format *tmpfmt; + unsigned int framing; ast_rtp_instance_get_remote_address(rtp, &them_tmp); ast_sockaddr_to_sin(&them_tmp, &them); @@ -3671,20 +3664,22 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r SKINNY_DEBUG(DEBUG_AUDIO, 4, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port)); - ast_best_codec(l->cap, &tmpfmt); - fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt); + tmpfmt = ast_format_cap_get_format(l->cap, 0); + framing = ast_format_cap_get_format_framing(l->cap, tmpfmt); - SKINNY_DEBUG(DEBUG_AUDIO, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms); + SKINNY_DEBUG(DEBUG_AUDIO, 4, "Setting payloadType to '%s' (%d ms)\n", ast_format_get_name(tmpfmt), framing); if (!(l->directmedia) || (l->nat)){ ast_rtp_instance_get_local_address(rtp, &us_tmp); ast_sockaddr_to_sin(&us_tmp, &us); us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr; - transmit_startmediatransmission(d, sub, us, fmt); + transmit_startmediatransmission(d, sub, us, tmpfmt, framing); } else { - transmit_startmediatransmission(d, sub, them, fmt); + transmit_startmediatransmission(d, sub, them, tmpfmt, framing); } + ao2_ref(tmpfmt, -1); + return 0; } /* Need a return here to break the bridge */ @@ -4067,25 +4062,6 @@ static char *device2str(int type) } } -/*! \brief Print codec list from preference to CLI/manager */ -static void print_codec_to_cli(int fd, struct ast_codec_pref *pref) -{ - int x; - struct ast_format tmpfmt; - - for(x = 0; x < 32 ; x++) { - ast_codec_pref_index(pref, x, &tmpfmt); - if (!tmpfmt.id) - break; - ast_cli(fd, "%s", ast_getformatname(&tmpfmt)); - ast_cli(fd, ":%d", pref->framing[x]); - if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt)) - ast_cli(fd, ","); - } - if (!x) - ast_cli(fd, "none"); -} - static char *_skinny_show_devices(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char * const *argv) { struct skinny_device *d; @@ -4204,7 +4180,7 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s struct skinny_speeddial *sd; struct skinny_addon *sa; struct skinny_serviceurl *surl; - char codec_buf[512]; + struct ast_str *codec_buf = ast_str_alloca(64); if (argc < 4) { return CLI_SHOWUSAGE; @@ -4238,12 +4214,8 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s ast_cli(fd, "Ip address: %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown")); ast_cli(fd, "Port: %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0)); ast_cli(fd, "Device Type: %s\n", device2str(d->type)); - ast_cli(fd, "Conf Codecs:"); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->confcap); - ast_cli(fd, "%s\n", codec_buf); - ast_cli(fd, "Neg Codecs: "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->cap); - ast_cli(fd, "%s\n", codec_buf); + ast_cli(fd, "Conf Codecs: %s\n", ast_format_cap_get_names(d->confcap, &codec_buf)); + ast_cli(fd, "Neg Codecs: %s\n", ast_format_cap_get_names(d->cap, &codec_buf)); ast_cli(fd, "Registered: %s\n", (d->session ? "Yes" : "No")); ast_cli(fd, "Lines: %d\n", numlines); AST_LIST_TRAVERSE(&d->lines, l, list) { @@ -4270,12 +4242,8 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s astman_append(s, "Ipaddress: %s\r\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown")); astman_append(s, "Port: %d\r\n", (d->session ? ntohs(d->session->sin.sin_port) : 0)); astman_append(s, "DeviceType: %s\r\n", device2str(d->type)); - astman_append(s, "Codecs: "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->confcap); - astman_append(s, "%s\r\n", codec_buf); - astman_append(s, "CodecOrder: "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->cap); - astman_append(s, "%s\r\n", codec_buf); + astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(d->confcap, &codec_buf)); + astman_append(s, "CodecOrder: %s\r\n", ast_format_cap_get_names(d->cap, &codec_buf)); astman_append(s, "Devicestatus: %s\r\n", (d->session?"registered":"unregistered")); astman_append(s, "NumberOfLines: %d\r\n", numlines); AST_LIST_TRAVERSE(&d->lines, l, list) { @@ -4468,9 +4436,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str struct skinny_device *d; struct skinny_line *l; struct skinny_subline *subline; - struct ast_codec_pref *pref; - int x = 0; - char codec_buf[512]; + struct ast_str *codec_buf = ast_str_alloca(64); char group_buf[256]; char cbuf[256]; @@ -4536,15 +4502,8 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str ast_cli(fd, "immediate: %s\n", (l->immediate ? "Yes" : "No")); ast_cli(fd, "Group: %d\n", l->group); ast_cli(fd, "Parkinglot: %s\n", S_OR(l->parkinglot, "<not set>")); - ast_cli(fd, "Conf Codecs: "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap); - ast_cli(fd, "%s\n", codec_buf); - ast_cli(fd, "Neg Codecs: "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->cap); - ast_cli(fd, "%s\n", codec_buf); - ast_cli(fd, "Codec Order: ("); - print_codec_to_cli(fd, &l->prefs); - ast_cli(fd, ")\n"); + ast_cli(fd, "Conf Codecs: %s\n", ast_format_cap_get_names(l->confcap, &codec_buf)); + ast_cli(fd, "Neg Codecs: %s\n", ast_format_cap_get_names(l->cap, &codec_buf)); if (AST_LIST_FIRST(&l->sublines)) { ast_cli(fd, "Sublines:\n"); AST_LIST_TRAVERSE(&l->sublines, subline, list) { @@ -4592,19 +4551,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No")); astman_append(s, "Group: %d\r\n", l->group); astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>")); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap); - astman_append(s, "Codecs: %s\r\n", codec_buf); - astman_append(s, "CodecOrder: "); - pref = &l->prefs; - for(x = 0; x < 32 ; x++) { - struct ast_format tmpfmt; - ast_codec_pref_index(pref, x, &tmpfmt); - if (!tmpfmt.id) - break; - astman_append(s, "%s", ast_getformatname(&tmpfmt)); - if (x < 31 && ast_codec_pref_index(pref, x+1, &tmpfmt)) - astman_append(s, ","); - } + astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(l->confcap, &codec_buf)); astman_append(s, "\r\n"); } } @@ -4802,7 +4749,7 @@ static void start_rtp(struct skinny_subchannel *sub) struct ast_sockaddr bindaddr_tmp; skinny_locksub(sub); - /* Allocate the RTP */ + SKINNY_DEBUG(DEBUG_AUDIO, 3, "Sub %u - Starting RTP\n", sub->callid); ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL); if (hasvideo) @@ -4828,14 +4775,14 @@ static void start_rtp(struct skinny_subchannel *sub) if (sub->rtp) { ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP"); ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat); + /* Set frame packetization */ + ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(sub->rtp), + ast_format_cap_get_framing(l->cap)); } if (sub->vrtp) { ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP"); ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat); } - /* Set Frame packetization */ - if (sub->rtp) - ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs); /* Create the RTP connection */ transmit_connect(d, sub); @@ -5097,9 +5044,17 @@ static struct ast_frame *skinny_rtp_read(struct skinny_subchannel *sub) if (ast) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE) { - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) { - ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); - ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format); + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_format_cap *caps; + + ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format)); + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + ast_format_cap_append(caps, f->subclass.format, 0); + ast_channel_nativeformats_set(ast, caps); + ao2_ref(caps, -1); + } ast_set_read_format(ast, ast_channel_readformat(ast)); ast_set_write_format(ast, ast_channel_writeformat(ast)); } @@ -5130,13 +5085,13 @@ static int skinny_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } } else { - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) { - char buf[256]; + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *codec_buf = ast_str_alloca(64); ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(&frame->subclass.format), - ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)), - ast_getformatname(ast_channel_readformat(ast)), - ast_getformatname(ast_channel_writeformat(ast))); + ast_format_get_name(frame->subclass.format), + ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf), + ast_format_get_name(ast_channel_readformat(ast)), + ast_format_get_name(ast_channel_writeformat(ast))); return -1; } } @@ -5403,23 +5358,33 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli struct skinny_subchannel *sub; struct skinny_device *d = l->device; struct ast_variable *v = NULL; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; + struct ast_format_cap *caps; if (!l->device || !l->device->session) { ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name); return NULL; } + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + return NULL; + } + tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, assignedids, requestor, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums); if (!tmp) { ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); + ao2_ref(caps, -1); return NULL; } else { + struct ast_str *codec_buf = ast_str_alloca(64); + sub = ast_calloc(1, sizeof(*sub)); if (!sub) { ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n"); ast_channel_unlock(tmp); ast_channel_unref(tmp); + ao2_ref(caps, -1); return NULL; } else { skinny_set_owner(sub, tmp); @@ -5452,25 +5417,28 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli ast_channel_stage_snapshot(tmp); ast_channel_tech_set(tmp, &skinny_tech); ast_channel_tech_pvt_set(tmp, sub); - ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap); - if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) { - // Should throw an error - ast_format_cap_copy(ast_channel_nativeformats(tmp), default_cap); + if (!ast_format_cap_count(l->cap)) { + ast_format_cap_append_from_cap(caps, l->cap, AST_MEDIA_TYPE_UNKNOWN); + } else { + ast_format_cap_append_from_cap(caps, default_cap, AST_MEDIA_TYPE_UNKNOWN); } - ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt); + ast_channel_nativeformats_set(tmp, caps); + ao2_ref(caps, -1); + tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0); SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_new: tmp->nativeformats=%s fmt=%s\n", - ast_getformatname_multiple(dbgsub_buf, sizeof(dbgsub_buf), ast_channel_nativeformats(tmp)), - ast_getformatname(&tmpfmt)); + ast_format_cap_get_names(ast_channel_nativeformats(tmp), &codec_buf), + ast_format_get_name(tmpfmt)); if (sub->rtp) { ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); } if (state == AST_STATE_RING) { ast_channel_rings_set(tmp, 1); } - ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_readformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); + ast_channel_set_writeformat(tmp, tmpfmt); + ast_channel_set_rawwriteformat(tmp, tmpfmt); + ast_channel_set_readformat(tmp, tmpfmt); + ast_channel_set_rawreadformat(tmp, tmpfmt); + ao2_ref(tmpfmt, -1); if (!ast_strlen_zero(l->language)) ast_channel_language_set(tmp, l->language); @@ -6676,7 +6644,8 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny struct skinny_device *d = s->device; struct skinny_line *l; uint32_t count = 0; - struct ast_format_cap *codecs = ast_format_cap_alloc(0); + struct ast_format_cap *codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + struct ast_str *codec_buf = ast_str_alloca(64); int i; if (!codecs) { @@ -6690,23 +6659,23 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny } for (i = 0; i < count; i++) { - struct ast_format acodec; + struct ast_format *acodec; int scodec = 0; scodec = letohl(req->data.caps.caps[i].codec); - codec_skinny2ast(scodec, &acodec); - SKINNY_DEBUG(DEBUG_AUDIO, 4, "Adding codec capability %s (%d)\n", ast_getformatname(&acodec), scodec); - ast_format_cap_add(codecs, &acodec); + acodec = codec_skinny2ast(scodec); + SKINNY_DEBUG(DEBUG_AUDIO, 4, "Adding codec capability %s (%d)\n", ast_format_get_name(acodec), scodec); + ast_format_cap_append(codecs, acodec, 0); } - ast_format_cap_joint_copy(d->confcap, codecs, d->cap); - SKINNY_DEBUG(DEBUG_AUDIO, 4, "Device capability set to '%s'\n", ast_getformatname_multiple(dbgreg_buf, sizeof(dbgreg_buf), d->cap)); + ast_format_cap_get_compatible(d->confcap, codecs, d->cap); + SKINNY_DEBUG(DEBUG_AUDIO, 4, "Device capability set to '%s'\n", ast_format_cap_get_names(d->cap, &codec_buf)); AST_LIST_TRAVERSE(&d->lines, l, list) { ast_mutex_lock(&l->lock); - ast_format_cap_joint_copy(l->confcap, d->cap, l->cap); + ast_format_cap_get_compatible(l->confcap, d->cap, l->cap); ast_mutex_unlock(&l->lock); } - codecs = ast_format_cap_destroy(codecs); + ao2_ref(codecs, -1); return 1; } @@ -6877,16 +6846,16 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc struct skinny_device *d = s->device; struct skinny_line *l; struct skinny_subchannel *sub; - struct ast_format_list fmt; struct sockaddr_in sin = { 0, }; struct sockaddr_in us = { 0, }; struct ast_sockaddr sin_tmp; struct ast_sockaddr us_tmp; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; uint32_t addr; int port; int status; int callid; + unsigned int framing; status = (d->protocolversion<17) ? letohl(req->data.openreceivechannelack_ip4.status) : letohl(req->data.openreceivechannelack_ip6.status); @@ -6937,12 +6906,14 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc SKINNY_DEBUG(DEBUG_PACKET, 4, "device ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); SKINNY_DEBUG(DEBUG_PACKET, 4, "asterisk ipaddr = %s:%d\n", ast_inet_ntoa(us.sin_addr), ntohs(us.sin_port)); - ast_best_codec(l->cap, &tmpfmt); - fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt); + tmpfmt = ast_format_cap_get_format(l->cap, 0); + framing = ast_format_cap_get_format_framing(l->cap, tmpfmt); - SKINNY_DEBUG(DEBUG_PACKET, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms); + SKINNY_DEBUG(DEBUG_PACKET, 4, "Setting payloadType to '%s' (%d ms)\n", ast_format_get_name(tmpfmt), framing); - transmit_startmediatransmission(d, sub, us, fmt); + transmit_startmediatransmission(d, sub, us, tmpfmt, framing); + + ao2_ref(tmpfmt, -1); return 1; } @@ -7496,8 +7467,8 @@ static void skinny_session_cleanup(void *data) if (l->device != d) { continue; } - ast_format_cap_remove_all(l->cap); - ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0); + ast_format_cap_remove_by_type(l->cap, AST_MEDIA_TYPE_UNKNOWN); + ast_format_cap_update_by_allow_disallow(l->cap, "all", 0); l->instance = 0; unregister_exten(l); ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name); @@ -7713,8 +7684,9 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca struct ast_channel *tmpc = NULL; char tmp[256]; - if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); + if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) { + struct ast_str *codec_buf = ast_str_alloca(64); + ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf)); return NULL; } @@ -7870,10 +7842,10 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp } continue; } else if (!strcasecmp(v->name, "allow")) { - ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 1); + ast_format_cap_update_by_allow_disallow(default_cap, v->value, 1); continue; } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 0); + ast_format_cap_update_by_allow_disallow(default_cap, v->value, 0); continue; } } @@ -8080,20 +8052,20 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp } } else if (!strcasecmp(v->name, "allow")) { if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) { - ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 1); + ast_format_cap_update_by_allow_disallow(CDEV->confcap, v->value, 1); continue; } if (type & (TYPE_DEF_LINE | TYPE_LINE)) { - ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 1); + ast_format_cap_update_by_allow_disallow(CLINE->confcap, v->value, 1); continue; } } else if (!strcasecmp(v->name, "disallow")) { if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) { - ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 0); + ast_format_cap_update_by_allow_disallow(CDEV->confcap, v->value, 0); continue; } if (type & (TYPE_DEF_LINE | TYPE_LINE)) { - ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 0); + ast_format_cap_update_by_allow_disallow(CLINE->confcap, v->value, 0); continue; } } else if (!strcasecmp(v->name, "version")) { @@ -8303,7 +8275,7 @@ static struct skinny_line *config_line(const char *lname, struct ast_variable *v memcpy(l, default_line, sizeof(*default_line)); ast_mutex_init(&l->lock); ast_copy_string(l->name, lname, sizeof(l->name)); - ast_format_cap_copy(l->confcap, default_cap); + ast_format_cap_append_from_cap(l->confcap, default_cap, AST_MEDIA_TYPE_UNKNOWN); AST_LIST_INSERT_TAIL(&lines, l, all); ast_mutex_lock(&l->lock); @@ -8362,7 +8334,7 @@ static struct skinny_device *config_device(const char *dname, struct ast_variabl memcpy(d, default_device, sizeof(*default_device)); ast_mutex_init(&d->lock); ast_copy_string(d->name, dname, sizeof(d->name)); - ast_format_cap_copy(d->confcap, default_cap); + ast_format_cap_append_from_cap(d->confcap, default_cap, AST_MEDIA_TYPE_UNKNOWN); AST_LIST_INSERT_TAIL(&devices, d, list); ast_mutex_lock(&d->lock); @@ -8453,7 +8425,6 @@ static int config_load(void) } memset(&bindaddr, 0, sizeof(bindaddr)); - memset(&default_prefs, 0, sizeof(default_prefs)); immed_dialchar = '\0'; memset(&vmexten, '\0', sizeof(vmexten)); @@ -8482,7 +8453,6 @@ static int config_load(void) bindaddr.sin_family = AF_INET; /* load the lines sections */ - default_line->confprefs = default_prefs; config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines")); cat = ast_category_browse(cfg, "lines"); while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) { @@ -8491,7 +8461,6 @@ static int config_load(void) } /* load the devices sections */ - default_device->confprefs = default_prefs; config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices")); cat = ast_category_browse(cfg, "devices"); while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) { @@ -8678,17 +8647,18 @@ int skinny_reload(void) static int load_module(void) { int res = 0; - struct ast_format tmpfmt; - if (!(default_cap = ast_format_cap_alloc(0))) { + + if (!(default_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return AST_MODULE_LOAD_DECLINE; } - if (!(skinny_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(skinny_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { + ao2_ref(default_cap, -1); return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add_all_by_type(skinny_tech.capabilities, AST_FORMAT_TYPE_AUDIO); - ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + ast_format_cap_append_by_type(skinny_tech.capabilities, AST_MEDIA_TYPE_AUDIO); + ast_format_cap_append(default_cap, ast_format_ulaw, 0); + ast_format_cap_append(default_cap, ast_format_alaw, 0); for (; res < ARRAY_LEN(soft_key_template_default); res++) { soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent); @@ -8696,11 +8666,23 @@ static int load_module(void) /* load and parse config */ res = config_load(); if (res == -1) { + ao2_ref(skinny_tech.capabilities, -1); + ao2_ref(default_cap, -1); return AST_MODULE_LOAD_DECLINE; } + sched = ast_sched_context_create(); + if (!sched) { + ao2_ref(skinny_tech.capabilities, -1); + ao2_ref(default_cap, -1); + ast_log(LOG_WARNING, "Unable to create schedule context\n"); + return AST_MODULE_LOAD_FAILURE; + } + /* Make sure we can register our skinny channel type */ if (ast_channel_register(&skinny_tech)) { + ao2_ref(default_cap, -1); + ao2_ref(skinny_tech.capabilities, -1); ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n"); return -1; } @@ -8713,14 +8695,12 @@ static int load_module(void) ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines); ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line); - sched = ast_sched_context_create(); - if (!sched) { - ast_log(LOG_WARNING, "Unable to create schedule context\n"); - return AST_MODULE_LOAD_FAILURE; - } if (ast_sched_start_thread(sched)) { ast_sched_context_destroy(sched); sched = NULL; + ast_channel_unregister(&skinny_tech); + ao2_ref(default_cap, -1); + ao2_ref(skinny_tech.capabilities, -1); return AST_MODULE_LOAD_FAILURE; } @@ -8738,6 +8718,7 @@ static int unload_module(void) ast_rtp_glue_unregister(&skinny_rtp_glue); ast_channel_unregister(&skinny_tech); + ao2_cleanup(skinny_tech.capabilities); ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny)); ast_manager_unregister("SKINNYdevices"); @@ -8797,8 +8778,7 @@ static int unload_module(void) if (con) ast_context_destroy(con, "Skinny"); - default_cap = ast_format_cap_destroy(default_cap); - skinny_tech.capabilities = ast_format_cap_destroy(skinny_tech.capabilities); + ao2_ref(default_cap, -1); return 0; } diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index 7525f3921..3f6fd01c8 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -78,6 +78,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/features_config.h" #include "asterisk/bridge.h" #include "asterisk/stasis_channels.h" +#include "asterisk/format_cache.h" #define DEFAULTCONTEXT "default" #define DEFAULTCALLERID "Unknown" @@ -1933,7 +1934,7 @@ static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src struct ast_format_cap *tmp = src->cap; memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */ src->cap = tmp; - ast_format_cap_copy(src->cap, dst->cap); + ast_format_cap_append_from_cap(src->cap, dst->cap, AST_MEDIA_TYPE_UNKNOWN); } static struct unistim_line *unistim_line_destroy(struct unistim_line *l) @@ -1941,7 +1942,7 @@ static struct unistim_line *unistim_line_destroy(struct unistim_line *l) if (!l) { return NULL; } - l->cap = ast_format_cap_destroy(l->cap); + ao2_ref(l->cap, -1); ast_free(l); return NULL; } @@ -1953,7 +1954,7 @@ static struct unistim_line *unistim_line_alloc(void) return NULL; } - if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) { + if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { ast_free(l); return NULL; } @@ -2699,15 +2700,15 @@ static void send_start_rtp(struct unistim_subchannel *sub) if (unistimdebug) { ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n", ast_inet_ntoa(us.sin_addr), - htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner))); + htons(us.sin_port), ast_format_get_name(ast_channel_readformat(sub->owner))); ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n", ast_inet_ntoa(public.sin_addr)); } pte = sub->parent->parent->session; codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0); - if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) || - (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) { + if ((ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) || + (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_alaw) == AST_FORMAT_CMP_EQUAL)) { if (unistimdebug) { ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec); } @@ -2804,17 +2805,17 @@ static void send_start_rtp(struct unistim_subchannel *sub) /* Codec */ buffsend[40] = codec; buffsend[41] = codec; - if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) { + if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) { buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */ - } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) { + } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_alaw) == AST_FORMAT_CMP_EQUAL) { buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */ - } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) { + } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_g723) == AST_FORMAT_CMP_EQUAL) { buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */ - } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) { + } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_g729) == AST_FORMAT_CMP_EQUAL) { buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */ } else { ast_log(LOG_WARNING, "Unsupported codec %s!\n", - ast_getformatname(ast_channel_readformat(sub->owner))); + ast_format_get_name(ast_channel_readformat(sub->owner))); } /* Source port for transmit RTP and Destination port for receiving RTP */ buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8; @@ -2883,18 +2884,20 @@ static void start_rtp(struct unistim_subchannel *sub) sin.sin_port = htons(find_rtp_port(sub)); ast_sockaddr_from_sin(&sin_tmp, &sin); ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp); - if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) { - struct ast_format tmpfmt; - char tmp[256]; - ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt); + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner)) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_format *tmpfmt; + struct ast_str *cap_buf = ast_str_alloca(64); + + tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(sub->owner), 0); ast_log(LOG_WARNING, "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n", - ast_getformatname(ast_channel_readformat(sub->owner)), - ast_getformatname(&tmpfmt), - ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner))); + ast_format_get_name(ast_channel_readformat(sub->owner)), + ast_format_get_name(tmpfmt), + ast_format_cap_get_names(ast_channel_nativeformats(sub->owner), &cap_buf)); - ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt); - ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt); + ast_channel_set_readformat(sub->owner, tmpfmt); + ast_channel_set_writeformat(sub->owner, tmpfmt); + ao2_ref(tmpfmt, -1); } send_start_rtp(sub); ast_mutex_unlock(&sub->lock); @@ -5132,14 +5135,21 @@ static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast, if (sub->owner) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE) { - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format))) { - char tmp[256]; + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_format_cap *caps; + ast_debug(1, "Oooh, format changed from %s to %s\n", - ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)), - ast_getformatname(&f->subclass.format)); - - ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format); + ast_format_cap_get_names(ast_channel_nativeformats(sub->owner), &cap_buf), + ast_format_get_name(f->subclass.format)); + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (caps) { + ast_format_cap_append(caps, f->subclass.format, 0); + ast_channel_nativeformats_set(sub->owner, caps); + ao2_ref(caps, -1); + } ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner)); ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner)); } @@ -5175,14 +5185,15 @@ static int unistim_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } } else { - if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) { - char tmp[256]; + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + struct ast_str *cap_buf = ast_str_alloca(64); + ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n", - ast_getformatname(&frame->subclass.format), - ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(ast)), - ast_getformatname(ast_channel_readformat(ast)), - ast_getformatname(ast_channel_writeformat(ast))); + ast_format_get_name(frame->subclass.format), + ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf), + ast_format_get_name(ast_channel_readformat(ast)), + ast_format_get_name(ast_channel_writeformat(ast))); return -1; } } @@ -5661,9 +5672,10 @@ static int unistim_send_mwi_to_peer(struct unistim_line *peer, unsigned int tick /* called from unistim_request (calls from the pbx ) */ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor) { + struct ast_format_cap *caps; struct ast_channel *tmp; struct unistim_line *l; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; if (!sub) { ast_log(LOG_WARNING, "subchannel null in unistim_new\n"); @@ -5673,6 +5685,12 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state ast_log(LOG_WARNING, "no line for subchannel %p\n", sub); return NULL; } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + return NULL; + } + l = sub->parent; tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten, l->parent->context, assignedids, requestor, l->amaflags, "USTM/%s@%s-%p", l->name, l->parent->name, sub); @@ -5681,24 +5699,32 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state } if (!tmp) { ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); + ao2_ref(caps, -1); return NULL; } ast_channel_stage_snapshot(tmp); - ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap); - if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) { - ast_format_cap_copy(ast_channel_nativeformats(tmp), global_cap); + if (ast_format_cap_count(l->cap)) { + ast_format_cap_append_from_cap(caps, l->cap, AST_MEDIA_TYPE_UNKNOWN); + } else { + ast_format_cap_append_from_cap(caps, global_cap, AST_MEDIA_TYPE_UNKNOWN); } - ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt); + ast_channel_nativeformats_set(tmp, caps); + ao2_ref(caps, -1); + + tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0); if (unistimdebug) { - char tmp1[256], tmp2[256], tmp3[256]; + struct ast_str *native_buf = ast_str_alloca(64); + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *global_buf = ast_str_alloca(64); + ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n", - ast_getformatname(&tmpfmt), - ast_getformatname_multiple(tmp1, sizeof(tmp1), ast_channel_nativeformats(tmp)), - ast_getformatname_multiple(tmp2, sizeof(tmp2), l->cap), - ast_getformatname_multiple(tmp3, sizeof(tmp3), global_cap)); + ast_format_get_name(tmpfmt), + ast_format_cap_get_names(ast_channel_nativeformats(tmp), &native_buf), + ast_format_cap_get_names(l->cap, &cap_buf), + ast_format_cap_get_names(global_cap, &global_buf)); } if ((sub->rtp) && (sub->subtype == 0)) { if (unistimdebug) { @@ -5716,10 +5742,13 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state ast_channel_rings_set(tmp, 1); } ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE); - ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_readformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); + + ast_channel_set_writeformat(tmp, tmpfmt); + ast_channel_set_rawwriteformat(tmp, tmpfmt); + ast_channel_set_readformat(tmp, tmpfmt); + ast_channel_set_rawreadformat(tmp, tmpfmt); + ao2_ref(tmpfmt, -1); + ast_channel_tech_pvt_set(tmp, sub); ast_channel_tech_set(tmp, &unistim_tech); @@ -5900,12 +5929,14 @@ static struct ast_channel *unistim_request(const char *type, struct ast_format_c struct unistim_device *d; struct ast_channel *tmpc = NULL; char tmp[256]; - char tmp2[256]; - if (!(ast_format_cap_has_joint(cap, global_cap))) { + if (!(ast_format_cap_iscompatible(cap, global_cap))) { + struct ast_str *cap_buf = ast_str_alloca(64); + struct ast_str *global_buf = ast_str_alloca(64); ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n", - ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_getformatname_multiple(tmp, sizeof(tmp), global_cap)); + ast_format_cap_get_names(cap, &cap_buf), + ast_format_cap_get_names(global_cap, &global_buf)); return NULL; } @@ -5956,7 +5987,8 @@ static struct ast_channel *unistim_request(const char *type, struct ast_format_c } sub->subtype = SUB_RING; sub->softkey = -1; - ast_format_cap_copy(sub->parent->cap, cap); + + ast_format_cap_append_from_cap(sub->parent->cap, cap, AST_MEDIA_TYPE_UNKNOWN); tmpc = unistim_new(sub, AST_STATE_DOWN, assignedids, requestor); if (!tmpc) { ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); @@ -5975,6 +6007,7 @@ static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_ struct unistim_line *line; struct unistim_subchannel *sub; struct unistimsession *s; + struct ast_str *cap_buf = ast_str_alloca(64); switch (cmd) { case CLI_INIT: @@ -6005,11 +6038,10 @@ static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_ device, device->selected, device->height); AST_LIST_LOCK(&device->lines); AST_LIST_TRAVERSE(&device->lines,line,list) { - char tmp2[256]; ast_cli(a->fd, "->name=%s fullname=%s exten=%s callid=%s cap=%s line=%p\n", line->name, line->fullname, line->exten, line->cid_num, - ast_getformatname_multiple(tmp2, sizeof(tmp2), line->cap), line); + ast_format_cap_get_names(line->cap, &cap_buf), line); } AST_LIST_UNLOCK(&device->lines); @@ -6595,7 +6627,7 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name); } } - ast_format_cap_copy(l->cap, global_cap); + ast_format_cap_append_from_cap(l->cap, global_cap, AST_MEDIA_TYPE_UNKNOWN); l->parent = d; linecnt++; AST_LIST_LOCK(&d->lines); @@ -7011,17 +7043,18 @@ static struct ast_rtp_glue unistim_rtp_glue = { int load_module(void) { int res; - struct ast_format tmpfmt; - if (!(global_cap = ast_format_cap_alloc(0))) { + + if (!(global_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { goto buff_failed; } - if (!(unistim_tech.capabilities = ast_format_cap_alloc(0))) { + if (!(unistim_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { goto buff_failed; } - ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); - ast_format_cap_copy(unistim_tech.capabilities, global_cap); + ast_format_cap_append(global_cap, ast_format_ulaw, 0); + ast_format_cap_append(global_cap, ast_format_alaw, 0); + ast_format_cap_append_from_cap(unistim_tech.capabilities, global_cap, AST_MEDIA_TYPE_AUDIO); + if (!(buff = ast_malloc(SIZE_PAGE))) { goto buff_failed; } @@ -7040,6 +7073,10 @@ int load_module(void) res = reload_config(); if (res) { + ao2_ref(unistim_tech.capabilities, -1); + ao2_ref(global_cap, -1); + ast_sched_context_destroy(sched); + io_context_destroy(io); return AST_MODULE_LOAD_DECLINE; } /* Make sure we can register our unistim channel type */ @@ -7066,9 +7103,11 @@ sched_failed: io_failed: ast_free(buff); buff = NULL; - global_cap = ast_format_cap_destroy(global_cap); - unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities); buff_failed: + ao2_cleanup(global_cap); + global_cap = NULL; + ao2_cleanup(unistim_tech.capabilities); + unistim_tech.capabilities = NULL; return AST_MODULE_LOAD_FAILURE; } @@ -7082,6 +7121,7 @@ static int unload_module(void) ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli)); ast_channel_unregister(&unistim_tech); + ao2_cleanup(unistim_tech.capabilities); ast_rtp_glue_unregister(&unistim_rtp_glue); ast_mutex_lock(&monlock); @@ -7099,8 +7139,7 @@ static int unload_module(void) if (unistimsock > -1) { close(unistimsock); } - global_cap = ast_format_cap_destroy(global_cap); - unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities); + ao2_ref(global_cap, -1); return 0; } diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc index f1a45ab63..181e50aee 100644 --- a/channels/chan_vpb.cc +++ b/channels/chan_vpb.cc @@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/dsp.h" #include "asterisk/features.h" #include "asterisk/musiconhold.h" +#include "asterisk/format_cache.h" } #include <sys/socket.h> @@ -766,11 +767,10 @@ static void get_callerid_ast(struct vpb_pvt *p) #endif vpb_record_buf_start(p->handle, VPB_MULAW); while ((rc == 0) && (sam_count < 8000 * 3)) { - struct ast_format tmpfmt; vrc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf)); if (vrc != VPB_OK) ast_log(LOG_ERROR, "%s: Caller ID couldn't read audio buffer!\n", p->dev); - rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); + rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), ast_format_ulaw); #ifdef ANALYSE_CID vpb_wave_write(ws, (char *)buf, sizeof(buf)); #endif @@ -2070,46 +2070,41 @@ static struct ast_frame *vpb_read(struct ast_channel *ast) static inline AudioCompress ast2vpbformat(struct ast_format *format) { - switch (format->id) { - case AST_FORMAT_ALAW: + if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) { return VPB_ALAW; - case AST_FORMAT_SLINEAR: + } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) { return VPB_LINEAR; - case AST_FORMAT_ULAW: + } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) { return VPB_MULAW; - case AST_FORMAT_ADPCM: + } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) { return VPB_OKIADPCM; - default: + } else { return VPB_RAW; } } static inline const char * ast2vpbformatname(struct ast_format *format) { - switch(format->id) { - case AST_FORMAT_ALAW: + if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) { return "AST_FORMAT_ALAW:VPB_ALAW"; - case AST_FORMAT_SLINEAR: + } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) { return "AST_FORMAT_SLINEAR:VPB_LINEAR"; - case AST_FORMAT_ULAW: + } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) { return "AST_FORMAT_ULAW:VPB_MULAW"; - case AST_FORMAT_ADPCM: + } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) { return "AST_FORMAT_ADPCM:VPB_OKIADPCM"; - default: + } else { return "UNKN:UNKN"; } } static inline int astformatbits(struct ast_format *format) { - switch (format->id) { - case AST_FORMAT_SLINEAR: + if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) { return 16; - case AST_FORMAT_ADPCM: + } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) { return 4; - case AST_FORMAT_ALAW: - case AST_FORMAT_ULAW: - default: + } else { return 8; } } @@ -2146,7 +2141,8 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame) /* ast_mutex_unlock(&p->lock); */ return 0; } else if (ast_channel_state(ast) != AST_STATE_UP) { - ast_verb(4, "%s: vpb_write: Attempt to Write frame type[%d]subclass[%s] on not up chan(state[%d])\n", ast_channel_name(ast), frame->frametype, ast_getformatname(&frame->subclass.format), ast_channel_state(ast)); + ast_verb(4, "%s: vpb_write: Attempt to Write frame type[%d]subclass[%s] on not up chan(state[%d])\n", + ast_channel_name(ast), frame->frametype, ast_format_get_name(frame->subclass.format), ast_channel_state(ast)); p->lastoutput = -1; /* ast_mutex_unlock(&p->lock); */ return 0; @@ -2154,9 +2150,10 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame) /* ast_debug(1, "%s: vpb_write: Checked frame type..\n", p->dev); */ - fmt = ast2vpbformat(&frame->subclass.format); + fmt = ast2vpbformat(frame->subclass.format); if (fmt < 0) { - ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast_channel_name(ast), ast_getformatname(&frame->subclass.format)); + ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast_channel_name(ast), + ast_format_get_name(frame->subclass.format)); return -1; } @@ -2180,7 +2177,7 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame) /* Check if we have set up the play_buf */ if (p->lastoutput == -1) { vpb_play_buf_start(p->handle, fmt); - ast_verb(2, "%s: vpb_write: Starting play mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(&frame->subclass.format)); + ast_verb(2, "%s: vpb_write: Starting play mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(frame->subclass.format)); p->lastoutput = fmt; ast_mutex_unlock(&p->play_lock); return 0; @@ -2230,7 +2227,7 @@ static void *do_chanreads(void *pvt) struct ast_frame *fr = &p->fr; char *readbuf = ((char *)p->buf) + AST_FRIENDLY_OFFSET; int bridgerec = 0; - struct ast_format tmpfmt; + struct ast_format *tmpfmt; int readlen, res, trycnt=0; AudioCompress fmt; int ignore_dtmf; @@ -2315,22 +2312,22 @@ static void *do_chanreads(void *pvt) ast_mutex_unlock(&p->play_dtmf_lock); if (p->owner) { - ast_format_copy(&tmpfmt, ast_channel_rawreadformat(p->owner)); + tmpfmt = ast_channel_rawreadformat(p->owner); } else { - ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0); + tmpfmt = ast_format_slin; } - fmt = ast2vpbformat(&tmpfmt); + fmt = ast2vpbformat(tmpfmt); if (fmt < 0) { - ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_getformatname(&tmpfmt)); + ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_format_get_name(tmpfmt)); return NULL; } - readlen = VPB_SAMPLES * astformatbits(&tmpfmt) / 8; + readlen = VPB_SAMPLES * astformatbits(tmpfmt) / 8; if (p->lastinput == -1) { vpb_record_buf_start(p->handle, fmt); /* vpb_reset_record_fifo_alarm(p->handle); */ p->lastinput = fmt; - ast_verb(2, "%s: Starting record mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(&tmpfmt)); + ast_verb(2, "%s: Starting record mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(tmpfmt)); continue; } else if (p->lastinput != fmt) { vpb_record_buf_finish(p->handle); @@ -2349,7 +2346,7 @@ static void *do_chanreads(void *pvt) a_gain_vector(p->rxswgain - MAX_VPB_GAIN, (short *)readbuf, readlen / sizeof(short)); ast_verb(6, "%s: chanreads: applied gain\n", p->dev); - ast_format_copy(&fr->subclass.format, &tmpfmt); + fr->subclass.format = tmpfmt; fr->data.ptr = readbuf; fr->datalen = readlen; fr->frametype = AST_FRAME_VOICE; @@ -2429,7 +2426,6 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st struct ast_channel *tmp; char cid_num[256]; char cid_name[256]; - struct ast_format tmpfmt; if (me->owner) { ast_log(LOG_WARNING, "Called vpb_new on owned channel (%s) ?!\n", me->dev); @@ -2452,9 +2448,9 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st * they are all converted to/from linear in the vpb code. Best for us to use * linear since we can then adjust volume in this modules. */ - ast_format_cap_add(ast_channel_nativeformats(tmp), ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); - ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); - ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); + ast_channel_nativeformats_set(tmp, vpb_tech.capabilities); + ast_channel_set_rawreadformat(tmp, ast_format_slin); + ast_channel_set_rawwriteformat(tmp, ast_format_slin); if (state == AST_STATE_RING) { ast_channel_rings_set(tmp, 1); cid_name[0] = '\0'; @@ -2508,13 +2504,17 @@ static struct ast_channel *vpb_request(const char *type, struct ast_format_cap * char *sepstr, *name; const char *s; int group = -1; - struct ast_format slin; - ast_format_set(&slin, AST_FORMAT_SLINEAR, 0); + if (!(ast_format_cap_iscompatible_format(cap, ast_format_slin))) { + struct ast_str *buf; - if (!(ast_format_cap_iscompatible(cap, &slin))) { - char tmp[256]; - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); + buf = ast_str_create(256); + if (!buf) { + return NULL; + } + ast_log(LOG_NOTICE, "Asked to create a channel for unsupported formats: %s\n", + ast_format_cap_get_names(cap, &buf)); + ast_free(buf); return NULL; } @@ -2636,8 +2636,10 @@ static int unload_module(void) ast_free(bridges); } - ast_format_cap_destroy(vpb_tech.capabilities); - ast_format_cap_destroy(vpb_tech_indicate.capabilities); + ao2_cleanup(vpb_tech.capabilities); + vpb_tech.capabilities = NULL; + ao2_cleanup(vpb_tech_indicate.capabilities); + vpb_tech_indicate.capabilities = NULL; return 0; } @@ -2671,19 +2673,18 @@ static enum ast_module_load_result load_module() int bal2 = -1; int bal3 = -1; char * callerid = NULL; - struct ast_format tmpfmt; int num_cards = 0; - vpb_tech.capabilities = ast_format_cap_alloc((enum ast_format_cap_flags) 0); + vpb_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!vpb_tech.capabilities) { return AST_MODULE_LOAD_DECLINE; } - vpb_tech_indicate.capabilities = ast_format_cap_alloc((enum ast_format_cap_flags) 0); + vpb_tech_indicate.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!vpb_tech_indicate.capabilities) { return AST_MODULE_LOAD_DECLINE; } - ast_format_cap_add(vpb_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); - ast_format_cap_add(vpb_tech_indicate.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_format_cap_append(vpb_tech.capabilities, ast_format_slin, 0); + ast_format_cap_append(vpb_tech_indicate.capabilities, ast_format_slin, 0); try { num_cards = vpb_get_num_cards(); } catch (std::exception e) { diff --git a/channels/dahdi/bridge_native_dahdi.c b/channels/dahdi/bridge_native_dahdi.c index 2f4fd170e..85cb4bfef 100644 --- a/channels/dahdi/bridge_native_dahdi.c +++ b/channels/dahdi/bridge_native_dahdi.c @@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/bridge.h" #include "asterisk/bridge_technology.h" #include "asterisk/frame.h" +#include "asterisk/format_cache.h" /* ------------------------------------------------------------------- */ @@ -892,7 +893,7 @@ static struct ast_bridge_technology native_bridge = { void dahdi_native_unload(void) { ast_bridge_technology_unregister(&native_bridge); - ast_format_cap_destroy(native_bridge.format_capabilities); + ao2_cleanup(native_bridge.format_capabilities); } /*! @@ -905,11 +906,9 @@ void dahdi_native_unload(void) */ int dahdi_native_load(struct ast_module *mod, const struct ast_channel_tech *tech) { - struct ast_format format; - dahdi_tech = tech; - native_bridge.format_capabilities = ast_format_cap_alloc(0); + native_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!native_bridge.format_capabilities) { return -1; } @@ -918,9 +917,9 @@ int dahdi_native_load(struct ast_module *mod, const struct ast_channel_tech *tec * This is used to make channels compatible with the bridge * itself not with each other. */ - ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_SLINEAR, 0)); - ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_ALAW, 0)); + ast_format_cap_append(native_bridge.format_capabilities, ast_format_slin, 0); + ast_format_cap_append(native_bridge.format_capabilities, ast_format_ulaw, 0); + ast_format_cap_append(native_bridge.format_capabilities, ast_format_alaw, 0); return __ast_bridge_technology_register(&native_bridge, mod); } diff --git a/channels/iax2/codec_pref.c b/channels/iax2/codec_pref.c new file mode 100644 index 000000000..903dca4cc --- /dev/null +++ b/channels/iax2/codec_pref.c @@ -0,0 +1,333 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Media Format Bitfield Compatibility API + * + * \author Joshua Colp <jcolp@digium.com> + */ + +/*** MODULEINFO + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/logger.h" +#include "asterisk/astobj2.h" +#include "asterisk/codec.h" +#include "asterisk/format.h" +#include "asterisk/format_compatibility.h" +#include "asterisk/format_cache.h" +#include "asterisk/format_cap.h" + +#include "include/codec_pref.h" +#include "include/format_compatibility.h" + +void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right) +{ + static int differential = (int) 'A'; + int x; + + if (right) { + for (x = 0; x < IAX2_CODEC_PREF_SIZE && x < size; x++) { + if (!pref->order[x]) { + break; + } + + buf[x] = pref->order[x] + differential; + } + + buf[x] = '\0'; + } else { + for (x = 0; x < IAX2_CODEC_PREF_SIZE && x < size; x++) { + if (buf[x] == '\0') { + break; + } + + pref->order[x] = buf[x] - differential; + } + + if (x < size) { + pref->order[x] = 0; + } + } +} + +struct ast_format *iax2_codec_pref_index(struct iax2_codec_pref *pref, int idx, struct ast_format **result) +{ + if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->order[idx]) { + *result = ast_format_compatibility_bitfield2format(pref->order[idx]); + } else { + *result = NULL; + } + + return *result; +} + +void iax2_codec_pref_to_cap(struct iax2_codec_pref *pref, struct ast_format_cap *cap) +{ + int idx; + + for (idx = 0; idx < sizeof(pref->order); idx++) { + if (!pref->order[idx]) { + break; + } + ast_format_cap_append(cap, ast_format_compatibility_bitfield2format(pref->order[idx]), pref->framing[idx]); + } +} + +int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size) +{ + int x; + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + size_t total_len; + char *cur; + + if (!cap) { + return -1; + } + + /* This function is useless if you have less than a 6 character buffer. + * '(...)' is six characters. */ + if (size < 6) { + return -1; + } + + /* Convert the preferences into a format cap so that we can read the formst names */ + for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) { + uint64_t bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]); + if (!bitfield) { + break; + } + + iax2_format_compatibility_bitfield2cap(bitfield, cap); + } + + /* We know that at a minimum, 3 characters are used - (, ), and \0 */ + total_len = size - 3; + + memset(buf, 0, size); + + /* This character has already been accounted for total_len purposes */ + buf[0] = '('; + cur = buf + 1; + + /* Loop through the formats and write as many into the buffer as we can */ + for (x = 0; x < ast_format_cap_count(cap); x++) { + size_t name_len; + struct ast_format *fmt = ast_format_cap_get_format(cap, x); + const char *name = ast_format_get_name(fmt); + + name_len = strlen(name); + + /* all entries after the first need a delimiter character */ + if (x) { + name_len++; + } + + /* Terminate the list early if we don't have room for the entry. + * If it's not the last entry in the list, save enough room to write '...'. + */ + if (((x == ast_format_cap_count(cap) - 1) && (total_len < name_len)) || + ((x < ast_format_cap_count(cap) - 1) && (total_len < name_len + 3))) { + strcpy(cur, "..."); + cur += 3; + total_len -= 3; + ao2_ref(fmt, -1); + break; + } + + sprintf(cur, "%s%s", x ? "|" : "", name); + cur += name_len; + total_len -= name_len; + + ao2_ref(fmt, -1); + } + ao2_ref(cap, -1); + + /* These two characters have already been accounted for total_len purposes */ + cur[0] = ')'; + cur[1] = '\0'; + + return size - total_len; +} + +static void codec_pref_remove_index(struct iax2_codec_pref *pref, int codec_pref_index) +{ + int x; + + for (x = codec_pref_index; x < IAX2_CODEC_PREF_SIZE; x++) { + pref->order[x] = pref->order[x + 1]; + pref->framing[x] = pref->framing[x + 1]; + if (!pref->order[x]) { + return; + } + } +} + +/*! \brief Remove codec from pref list */ +static void codec_pref_remove(struct iax2_codec_pref *pref, int format_index) +{ + int x; + + if (!pref->order[0]) { + return; + } + + for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) { + if (!pref->order[x]) { + break; + } + + if (pref->order[x] == format_index) { + codec_pref_remove_index(pref, x); + break; + } + } +} + +void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield) +{ + int x; + + if (!pref->order[0]) { + return; + } + + for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) { + uint64_t format_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]); + if (!pref->order[x]) { + break; + } + + /* If this format isn't in the bitfield, remove it from the prefs. */ + if (!(format_as_bitfield & bitfield)) { + codec_pref_remove_index(pref, x); + } + } +} + +uint64_t iax2_codec_pref_order_value_to_format_bitfield(uint64_t order_value) +{ + if (!order_value) { + return 0; + } + + return 1 << (order_value - 1); +} + +uint64_t iax2_codec_pref_format_bitfield_to_order_value(uint64_t bitfield) +{ + int format_index = 1; + + if (!bitfield) { + return 0; + } + + while (bitfield > 1) { + bitfield = bitfield >> 1; + format_index++; + } + + return format_index; +} + +/*! \brief Append codec to list */ +int iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing) +{ + uint64_t bitfield = ast_format_compatibility_format2bitfield(format); + int format_index = iax2_codec_pref_format_bitfield_to_order_value(bitfield); + int x; + + codec_pref_remove(pref, format_index); + + for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) { + if (!pref->order[x]) { + pref->order[x] = format_index; + pref->framing[x] = framing; + break; + } + } + + return x; +} + +/*! \brief Prepend codec to list */ +void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing, + int only_if_existing) +{ + uint64_t bitfield = ast_format_compatibility_format2bitfield(format); + int x; + + /* Now find any existing occurrence, or the end */ + for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) { + if (!pref->order[x] || pref->order[x] == bitfield) + break; + } + + /* If we failed to find any occurrence, set to the end */ + if (x == IAX2_CODEC_PREF_SIZE) { + --x; + } + + if (only_if_existing && !pref->order[x]) { + return; + } + + /* Move down to make space to insert - either all the way to the end, + or as far as the existing location (which will be overwritten) */ + for (; x > 0; x--) { + pref->order[x] = pref->order[x - 1]; + pref->framing[x] = pref->framing[x - 1]; + } + + /* And insert the new entry */ + pref->order[0] = bitfield; + pref->framing[0] = framing; +} + +unsigned int iax2_codec_pref_getsize(struct iax2_codec_pref *pref, int idx) +{ + if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->order[idx]) { + return pref->framing[idx]; + } else { + return 0; + } +} + +int iax2_codec_pref_setsize(struct iax2_codec_pref *pref, struct ast_format *format, int framems) +{ + int idx; + + for (idx = 0; idx < sizeof(pref->order); idx++) { + if (!pref->order[idx]) { + break; + } else if (ast_format_cmp(ast_format_compatibility_bitfield2format(pref->order[idx]), + format) != AST_FORMAT_CMP_EQUAL) { + continue; + } + pref->framing[idx] = framems; + return 0; + } + + return -1; +} diff --git a/channels/iax2/format_compatibility.c b/channels/iax2/format_compatibility.c new file mode 100644 index 000000000..8085c2c26 --- /dev/null +++ b/channels/iax2/format_compatibility.c @@ -0,0 +1,73 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Media Format Bitfield Compatibility API + * + * \author Joshua Colp <jcolp@digium.com> + */ + +/*** MODULEINFO + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/logger.h" +#include "asterisk/astobj2.h" +#include "asterisk/codec.h" +#include "asterisk/format.h" +#include "asterisk/format_compatibility.h" +#include "asterisk/format_cache.h" +#include "asterisk/format_cap.h" + +#include "include/format_compatibility.h" + +uint64_t iax2_format_compatibility_cap2bitfield(const struct ast_format_cap *cap) +{ + uint64_t bitfield = 0; + int x; + + for (x = 0; x < ast_format_cap_count(cap); x++) { + struct ast_format *format = ast_format_cap_get_format(cap, x); + + bitfield |= ast_format_compatibility_format2bitfield(format); + + ao2_ref(format, -1); + } + + return bitfield; +} + +int iax2_format_compatibility_bitfield2cap(uint64_t bitfield, struct ast_format_cap *cap) +{ + int x; + + for (x = 0; x < 64; x++) { + uint64_t tmp = (1ULL << x); + + if ((tmp & bitfield) && ast_format_cap_append(cap, ast_format_compatibility_bitfield2format(tmp), 0)) { + return -1; + } + } + + return 0; +} diff --git a/channels/iax2/include/codec_pref.h b/channels/iax2/include/codec_pref.h new file mode 100644 index 000000000..bfb889164 --- /dev/null +++ b/channels/iax2/include/codec_pref.h @@ -0,0 +1,123 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Media Format Bitfield Compatibility API + * + * \author Joshua Colp <jcolp@digium.com> + */ + +#ifndef _IAX2_CODEC_PREF_H_ +#define _IAX2_CODEC_PREF_H_ + +struct ast_format; +struct ast_codec; +struct ast_format_cap; + +#define IAX2_CODEC_PREF_SIZE 64 +struct iax2_codec_pref { + /*! This array is ordered by preference and contains the codec bitfield. */ + uint64_t order[IAX2_CODEC_PREF_SIZE]; + /*! Framing size of the codec */ + unsigned int framing[IAX2_CODEC_PREF_SIZE]; +}; + +/*! + * \brief Convert an iax2_codec_pref order value into a format bitfield + * + * \param order_value value being converted + * + * \return the bitfield value of the order_value format + */ +uint64_t iax2_codec_pref_order_value_to_format_bitfield(uint64_t order_value); + +/*! + * \brief Convert a format bitfield into an iax2_codec_pref order value + * + * \param bitfield value being converted + * + * \return the iax2_codec_pref order value of the most significant format + * in the bitfield. + * + * \note This is really meant to be used on single format bitfields. + * It will work with multiformat bitfields, but it can only return the + * index of the most significant one if that is the case. + */ +uint64_t iax2_codec_pref_format_bitfield_to_order_value(uint64_t bitfield); + +/*! + * \brief Codec located at a particular place in the preference index. + * \param pref preference structure to get the codec out of + * \param index to retrieve from + * \param result ast_format structure to store the index value in + * \return pointer to input ast_format on success, NULL on failure +*/ +struct ast_format *iax2_codec_pref_index(struct iax2_codec_pref *pref, int index, struct ast_format **result); + +/*! \brief Convert a preference structure to a capabilities structure */ +void iax2_codec_pref_to_cap(struct iax2_codec_pref *pref, struct ast_format_cap *cap); + +/*! \brief Removes format from the pref list that aren't in the bitfield */ +void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield); + +/*! + * \brief Dump audio codec preference list into a string + * + * \param pref preference structure to dump string representation of order for + * \param buf character buffer to put string into + * \param size size of the character buffer + * + * \return -1 on error. Otherwise returns the remaining spaaaaaace in the buffer. + * + * \note Format is (codec1|codec2|codec3|...) -- if the list is too long for the + * size of the buffer, codecs will be written until they exceed the length + * remaining in which case the list will be closed with '...)' after the last + * writable codec. + */ +int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size); + +/*! \brief Append a audio codec to a preference list, removing it first if it was already there +*/ +int iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing); + +/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there +*/ +void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing, + int only_if_existing); + +/*! \brief Get packet size for codec +*/ +unsigned int iax2_codec_pref_getsize(struct iax2_codec_pref *pref, int index); + +/*! \brief Set packet size for codec +*/ +int iax2_codec_pref_setsize(struct iax2_codec_pref *pref, struct ast_format *format, int framems); + +/*! \brief Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string + * \note Due to a misunderstanding in how codec preferences are stored, this + * list starts at 'B', not 'A'. For backwards compatibility reasons, this + * cannot change. + * \param pref A codec preference list structure + * \param buf A string denoting codec preference, appropriate for use in line transmission + * \param size Size of \a buf + * \param right Boolean: if 0, convert from \a buf to \a pref; if 1, convert from \a pref to \a buf. + */ +void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right); + +#endif /* _IAX2_CODEC_PREF_H_ */ diff --git a/channels/iax2/include/format_compatibility.h b/channels/iax2/include/format_compatibility.h new file mode 100644 index 000000000..aa29cfa2c --- /dev/null +++ b/channels/iax2/include/format_compatibility.h @@ -0,0 +1,55 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Media Format Bitfield Compatibility API + * + * \author Joshua Colp <jcolp@digium.com> + */ + +#ifndef _IAX2_FORMAT_COMPATIBILITY_H_ +#define _IAX2_FORMAT_COMPATIBILITY_H_ + +struct ast_format; +struct ast_format_cap; + +/*! + * \brief Convert a format capabilities structure to a bitfield + * + * \param cap Capabilities structure containing formats + * + * \retval non-zero success + * \retval zero no formats present or no formats supported + */ +uint64_t iax2_format_compatibility_cap2bitfield(const struct ast_format_cap *cap); + +/*! + * \brief Convert a bitfield to a format capabilities structure + * + * \param bitfield The bitfield for the media formats + * \param cap Capabilities structure to place formats into + * + * \retval non-NULL success + * \retval NULL failure + * + * \note If failure occurs the capabilities structure may contain a partial set of formats + */ +int iax2_format_compatibility_bitfield2cap(uint64_t bitfield, struct ast_format_cap *cap); + +#endif /* _IAX2_FORMAT_COMPATIBILITY_H */ diff --git a/channels/iax2/parser.c b/channels/iax2/parser.c index f5c7ba05d..f1fc8f82d 100644 --- a/channels/iax2/parser.c +++ b/channels/iax2/parser.c @@ -42,10 +42,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/lock.h" #include "asterisk/threadstorage.h" #include "asterisk/netsock2.h" +#include "asterisk/format_cache.h" +#include "asterisk/format_compatibility.h" #include "include/iax2.h" #include "include/parser.h" #include "include/provision.h" +#include "include/codec_pref.h" static int frames = 0; static int iframes = 0; @@ -124,7 +127,7 @@ static void dump_string(char *output, int maxlen, void *value, int len) static void dump_prefs(char *output, int maxlen, void *value, int len) { - struct ast_codec_pref pref; + struct iax2_codec_pref pref; int total_len = 0; maxlen--; @@ -136,9 +139,9 @@ static void dump_prefs(char *output, int maxlen, void *value, int len) strncpy(output, value, maxlen); output[maxlen] = '\0'; - ast_codec_pref_convert(&pref, output, total_len, 0); + iax2_codec_pref_convert(&pref, output, total_len, 0); memset(output,0,total_len); - ast_codec_pref_string(&pref, output, total_len); + iax2_codec_pref_string(&pref, output, total_len); } static void dump_int(char *output, int maxlen, void *value, int len) @@ -1180,7 +1183,8 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f) { fr->af.frametype = f->frametype; - ast_format_copy(&fr->af.subclass.format, &f->subclass.format); + fr->af.subclass.format = f->subclass.format; + fr->af.subclass.integer = f->subclass.integer; fr->af.mallocd = 0; /* Our frame is static relative to the container */ fr->af.datalen = f->datalen; fr->af.samples = f->samples; @@ -1199,7 +1203,8 @@ void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f) } #if __BYTE_ORDER == __LITTLE_ENDIAN /* We need to byte-swap slinear samples from network byte order */ - if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.format.id == AST_FORMAT_SLINEAR)) { + if ((fr->af.frametype == AST_FRAME_VOICE) && + (ast_format_cmp(fr->af.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) { /* 2 bytes / sample for SLINEAR */ ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2); } else diff --git a/channels/iax2/provision.c b/channels/iax2/provision.c index 78e0b1b3d..85dfe9448 100644 --- a/channels/iax2/provision.c +++ b/channels/iax2/provision.c @@ -45,6 +45,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/astdb.h" #include "asterisk/utils.h" #include "asterisk/acl.h" +#include "asterisk/format_cache.h" +#include "asterisk/format_compatibility.h" #include "include/iax2.h" #include "include/provision.h" @@ -345,9 +347,10 @@ static int iax_template_parse(struct iax_template *cur, struct ast_config *cfg, } else ast_log(LOG_WARNING, "Ignoring invalid %s '%s' for '%s' at line %d\n", v->name, v->value, s, v->lineno); } else if (!strcasecmp(v->name, "codec")) { - struct ast_format tmpfmt; - if ((ast_getformatbyname(v->value, &tmpfmt)) > 0) { - cur->format = ast_format_to_old_bitfield(&tmpfmt); + struct ast_format *tmpfmt; + if ((tmpfmt = ast_format_cache_get(v->value))) { + cur->format = ast_format_compatibility_format2bitfield(tmpfmt); + ao2_ref(tmpfmt, -1); } else ast_log(LOG_WARNING, "Ignoring invalid codec '%s' for '%s' at line %d\n", v->value, s, v->lineno); } else if (!strcasecmp(v->name, "tos")) { diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c index c50dbf3fc..054552b5a 100644 --- a/channels/pjsip/dialplan_functions.c +++ b/channels/pjsip/dialplan_functions.c @@ -806,35 +806,32 @@ int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char } static int media_offer_read_av(struct ast_sip_session *session, char *buf, - size_t len, enum ast_format_type media_type) + size_t len, enum ast_media_type media_type) { int i, size = 0; - struct ast_format fmt; - const char *name; - for (i = 0; ast_codec_pref_index(&session->override_prefs, i, &fmt); ++i) { - if (AST_FORMAT_GET_TYPE(fmt.id) != media_type) { - continue; - } + for (i = 0; i < ast_format_cap_count(session->req_caps); i++) { + struct ast_format *fmt = ast_format_cap_get_format(session->req_caps, i); - name = ast_getformatname(&fmt); - - if (ast_strlen_zero(name)) { - ast_log(LOG_WARNING, "PJSIP_MEDIA_OFFER unrecognized format %s\n", name); + if (ast_format_get_type(fmt) != media_type) { + ao2_ref(fmt, -1); continue; } /* add one since we'll include a comma */ - size = strlen(name) + 1; + size = strlen(ast_format_get_name(fmt)) + 1; len -= size; if ((len) < 0) { + ao2_ref(fmt, -1); break; } /* no reason to use strncat here since we have already ensured buf has enough space, so strcat can be safely used */ - strcat(buf, name); + strcat(buf, ast_format_get_name(fmt)); strcat(buf, ","); + + ao2_ref(fmt, -1); } if (size) { @@ -846,23 +843,16 @@ static int media_offer_read_av(struct ast_sip_session *session, char *buf, struct media_offer_data { struct ast_sip_session *session; - enum ast_format_type media_type; + enum ast_media_type media_type; const char *value; }; static int media_offer_write_av(void *obj) { struct media_offer_data *data = obj; - int i; - struct ast_format fmt; - /* remove all of the given media type first */ - for (i = 0; ast_codec_pref_index(&data->session->override_prefs, i, &fmt); ++i) { - if (AST_FORMAT_GET_TYPE(fmt.id) == data->media_type) { - ast_codec_pref_remove(&data->session->override_prefs, &fmt); - } - } - ast_format_cap_remove_bytype(data->session->req_caps, data->media_type); - ast_parse_allow_disallow(&data->session->override_prefs, data->session->req_caps, data->value, 1); + + ast_format_cap_remove_by_type(data->session->req_caps, data->media_type); + ast_format_cap_update_by_allow_disallow(data->session->req_caps, data->value, 1); return 0; } @@ -879,9 +869,9 @@ int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char * channel = ast_channel_tech_pvt(chan); if (!strcmp(data, "audio")) { - return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_AUDIO); + return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_AUDIO); } else if (!strcmp(data, "video")) { - return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_VIDEO); + return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_VIDEO); } return 0; @@ -903,9 +893,9 @@ int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char mdata.session = channel->session; if (!strcmp(data, "audio")) { - mdata.media_type = AST_FORMAT_TYPE_AUDIO; + mdata.media_type = AST_MEDIA_TYPE_AUDIO; } else if (!strcmp(data, "video")) { - mdata.media_type = AST_FORMAT_TYPE_VIDEO; + mdata.media_type = AST_MEDIA_TYPE_VIDEO; } return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata); diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 11078d5b7..8ce63ee9d 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -1082,7 +1082,6 @@ struct sip_pvt { int timer_b; /*!< SIP timer B, ms */ unsigned int sipoptions; /*!< Supported SIP options on the other end */ unsigned int reqsipoptions; /*!< Required SIP options on the other end */ - struct ast_codec_pref prefs; /*!< codec prefs */ struct ast_format_cap *caps; /*!< Special capability (codec) */ struct ast_format_cap *jointcaps; /*!< Supported capability at both ends (codecs) */ struct ast_format_cap *peercaps; /*!< Supported peer capability */ @@ -1310,7 +1309,6 @@ struct sip_peer { int busy_level; /*!< Level of active channels where we signal busy */ int maxforwards; /*!< SIP Loop prevention */ enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */ - struct ast_codec_pref prefs; /*!< codec prefs */ int lastmsgssent; /*!< The last known VM message counts (new/old) */ unsigned int sipoptions; /*!< Supported SIP options */ struct ast_flags flags[3]; /*!< SIP_ flags */ |