diff options
Diffstat (limited to 'channels')
29 files changed, 1957 insertions, 1251 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 7cf5e69d7..9e1dfed9e 100644 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -297,19 +297,19 @@ static AST_LIST_HEAD_STATIC(agents, agent_pvt); /*!< Holds the list of agents (l #define CHECK_FORMATS(ast, p) do { \ if (p->chan) {\ - if (ast->nativeformats != p->chan->nativeformats) { \ + if (!(ast_format_cap_identical(ast->nativeformats, p->chan->nativeformats))) { \ char tmp1[256], tmp2[256]; \ ast_debug(1, "Native formats changing from '%s' to '%s'\n", ast_getformatname_multiple(tmp1, sizeof(tmp1), ast->nativeformats), ast_getformatname_multiple(tmp2, sizeof(tmp2), p->chan->nativeformats)); \ /* Native formats changed, reset things */ \ - ast->nativeformats = p->chan->nativeformats; \ - ast_debug(1, "Resetting read to '%s' and write to '%s'\n", ast_getformatname_multiple(tmp1, sizeof(tmp1), ast->readformat), ast_getformatname_multiple(tmp2, sizeof(tmp2), ast->writeformat));\ - ast_set_read_format(ast, ast->readformat); \ - ast_set_write_format(ast, ast->writeformat); \ + ast_format_cap_copy(ast->nativeformats, p->chan->nativeformats); \ + ast_debug(1, "Resetting read to '%s' and write to '%s'\n", ast_getformatname(&ast->readformat), ast_getformatname(&ast->writeformat));\ + ast_set_read_format(ast, &ast->readformat); \ + ast_set_write_format(ast, &ast->writeformat); \ } \ - if (p->chan->readformat != ast->rawreadformat && !p->chan->generator) \ - ast_set_read_format(p->chan, ast->rawreadformat); \ - if (p->chan->writeformat != ast->rawwriteformat && !p->chan->generator) \ - ast_set_write_format(p->chan, ast->rawwriteformat); \ + if ((ast_format_cmp(&p->chan->readformat, &ast->rawreadformat) != AST_FORMAT_CMP_EQUAL) && !p->chan->generator) \ + ast_set_read_format(p->chan, &ast->rawreadformat); \ + if ((ast_format_cmp(&p->chan->writeformat, &ast->rawwriteformat) != AST_FORMAT_CMP_EQUAL) && !p->chan->generator) \ + ast_set_write_format(p->chan, &ast->rawwriteformat); \ } \ } while(0) @@ -329,7 +329,7 @@ static AST_LIST_HEAD_STATIC(agents, agent_pvt); /*!< Holds the list of agents (l } while(0) /*--- Forward declarations */ -static struct ast_channel *agent_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *agent_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int agent_devicestate(void *data); static int agent_digit_begin(struct ast_channel *ast, char digit); static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration); @@ -349,10 +349,9 @@ static int agent_set_base_channel(struct ast_channel *chan, struct ast_channel * static int agent_logoff(const char *agent, int soft); /*! \brief Channel interface description for PBX integration */ -static const struct ast_channel_tech agent_tech = { +static struct ast_channel_tech agent_tech = { .type = "Agent", .description = tdesc, - .capabilities = -1, .requester = agent_request, .devicestate = agent_devicestate, .send_digit_begin = agent_digit_begin, @@ -695,7 +694,7 @@ static int agent_write(struct ast_channel *ast, struct ast_frame *f) else { if ((f->frametype != AST_FRAME_VOICE) || (f->frametype != AST_FRAME_VIDEO) || - (f->subclass.codec == p->chan->writeformat)) { + (ast_format_cmp(&f->subclass.format, &p->chan->writeformat) != AST_FORMAT_CMP_NOT_EQUAL)) { res = ast_write(p->chan, f); } else { ast_debug(1, "Dropping one incompatible %s frame on '%s' to '%s'\n", @@ -799,10 +798,11 @@ static int agent_call(struct ast_channel *ast, char *dest, int timeout) ast_debug(3, "Waited for stream, result '%d'\n", res); } if (!res) { - res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats)); + struct ast_format tmpfmt; + res = ast_set_read_format_from_cap(p->chan, p->chan->nativeformats); ast_debug(3, "Set read format, result '%d'\n", res); if (res) - ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); + ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(&tmpfmt)); } else { /* Agent hung-up */ p->chan = NULL; @@ -810,10 +810,11 @@ static int agent_call(struct ast_channel *ast, char *dest, int timeout) } if (!res) { - res = ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats)); + struct ast_format tmpfmt; + res = ast_set_write_format_from_cap(p->chan, p->chan->nativeformats); ast_debug(3, "Set write format, result '%d'\n", res); if (res) - ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); + ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(&tmpfmt)); } if(!res) { /* Call is immediately up, or might need ack */ @@ -1047,21 +1048,21 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state, const char tmp->tech = &agent_tech; if (p->chan) { - tmp->nativeformats = p->chan->nativeformats; - tmp->writeformat = p->chan->writeformat; - tmp->rawwriteformat = p->chan->writeformat; - tmp->readformat = p->chan->readformat; - tmp->rawreadformat = p->chan->readformat; + ast_format_cap_copy(tmp->nativeformats, p->chan->nativeformats); + ast_format_copy(&tmp->writeformat, &p->chan->writeformat); + ast_format_copy(&tmp->rawwriteformat, &p->chan->writeformat); + ast_format_copy(&tmp->readformat, &p->chan->readformat); + ast_format_copy(&tmp->rawreadformat, &p->chan->readformat); ast_string_field_set(tmp, language, p->chan->language); ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context)); ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten)); /* XXX Is this really all we copy form the originating channel?? */ } else { - tmp->nativeformats = AST_FORMAT_SLINEAR; - tmp->writeformat = AST_FORMAT_SLINEAR; - tmp->rawwriteformat = AST_FORMAT_SLINEAR; - tmp->readformat = AST_FORMAT_SLINEAR; - tmp->rawreadformat = AST_FORMAT_SLINEAR; + ast_format_set(&tmp->writeformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&tmp->rawwriteformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&tmp->readformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&tmp->rawreadformat, AST_FORMAT_SLINEAR, 0); + ast_format_cap_add(tmp->nativeformats, &tmp->writeformat); } /* Safe, agentlock already held */ tmp->tech_pvt = p; @@ -1374,7 +1375,7 @@ static int check_beep(struct agent_pvt *newlyavailable, int needlock) } /*! \brief Part of the Asterisk PBX interface */ -static struct ast_channel *agent_request(const char *type, format_t format, const struct ast_channel* requestor, void *data, int *cause) +static struct ast_channel *agent_request(const char *type, struct ast_format_cap *cap, const struct ast_channel* requestor, void *data, int *cause) { struct agent_pvt *p; struct ast_channel *chan = NULL; @@ -1997,14 +1998,18 @@ static int login_exec(struct ast_channel *chan, const char *data) AST_LIST_LOCK(&agents); ast_mutex_lock(&p->lock); if (!res) { - res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); - if (res) - ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(chan->nativeformats))); + struct ast_format tmpfmt; + res = ast_set_read_format_from_cap(chan, chan->nativeformats); + if (res) { + ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(&tmpfmt)); + } } if (!res) { - res = ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); - if (res) - ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(chan->nativeformats))); + struct ast_format tmpfmt; + res = ast_set_write_format_from_cap(chan, chan->nativeformats); + if (res) { + ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(&tmpfmt)); + } } /* Check once more just in case */ if (p->chan) @@ -2024,7 +2029,7 @@ static int login_exec(struct ast_channel *chan, const char *data) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name); ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", p->agent, - ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat)); + ast_getformatname(&chan->readformat), ast_getformatname(&chan->writeformat)); /* Login this channel and wait for it to go away */ p->chan = chan; if (p->ackcall) { @@ -2418,6 +2423,11 @@ static const struct ast_data_entry agents_data_providers[] = { */ static int load_module(void) { + if (!(agent_tech.capabilities = ast_format_cap_alloc())) { + ast_log(LOG_ERROR, "ast_format_cap_alloc_nolock fail.\n"); + return AST_MODULE_LOAD_FAILURE; + } + ast_format_cap_add_all(agent_tech.capabilities); /* Make sure we can register our agent channel type */ if (ast_channel_register(&agent_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'Agent'\n"); @@ -2477,6 +2487,8 @@ static int unload_module(void) ast_free(p); } AST_LIST_UNLOCK(&agents); + + agent_tech.capabilities = ast_format_cap_destroy(agent_tech.capabilities); return 0; } diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index 120987ae4..58382881e 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -133,7 +133,7 @@ static int autoanswer = 1; static int mute = 0; static int noaudiocapture = 0; -static struct ast_channel *alsa_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *alsa_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration); static int alsa_text(struct ast_channel *c, const char *text); static int alsa_hangup(struct ast_channel *c); @@ -144,10 +144,9 @@ static int alsa_write(struct ast_channel *chan, struct ast_frame *f); static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen); static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); -static const struct ast_channel_tech alsa_tech = { +static struct ast_channel_tech alsa_tech = { .type = "Console", .description = tdesc, - .capabilities = AST_FORMAT_SLINEAR, .requester = alsa_request, .send_digit_end = alsa_digit, .send_text = alsa_text, @@ -502,7 +501,7 @@ static struct ast_frame *alsa_read(struct ast_channel *chan) } f.frametype = AST_FRAME_VOICE; - f.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0); f.samples = FRAME_SIZE; f.datalen = FRAME_SIZE * 2; f.data.ptr = buf; @@ -572,9 +571,10 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const ch tmp->tech = &alsa_tech; ast_channel_set_fd(tmp, 0, readdev); - tmp->nativeformats = AST_FORMAT_SLINEAR; - tmp->readformat = AST_FORMAT_SLINEAR; - tmp->writeformat = AST_FORMAT_SLINEAR; + ast_format_set(&tmp->readformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&tmp->writeformat, AST_FORMAT_SLINEAR, 0); + ast_format_cap_add(tmp->nativeformats, &tmp->writeformat); + tmp->tech_pvt = p; if (!ast_strlen_zero(p->context)) ast_copy_string(tmp->context, p->context, sizeof(tmp->context)); @@ -596,14 +596,16 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const ch return tmp; } -static struct ast_channel *alsa_request(const char *type, format_t fmt, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *alsa_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat = fmt; + struct ast_format tmpfmt; char buf[256]; struct ast_channel *tmp = NULL; - if (!(fmt &= AST_FORMAT_SLINEAR)) { - ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), oldformat)); + 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)); return NULL; } @@ -929,6 +931,12 @@ 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())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_add(alsa_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); @@ -1006,6 +1014,7 @@ static int unload_module(void) if (alsa.owner) return -1; + alsa_tech.capabilities = ast_format_cap_destroy(alsa_tech.capabilities); return 0; } diff --git a/channels/chan_bridge.c b/channels/chan_bridge.c index 8218bdceb..a58cfcc59 100644 --- a/channels/chan_bridge.c +++ b/channels/chan_bridge.c @@ -46,17 +46,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/app.h" #include "asterisk/bridging.h" -static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *bridge_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int bridge_call(struct ast_channel *ast, char *dest, int timeout); static int bridge_hangup(struct ast_channel *ast); static struct ast_frame *bridge_read(struct ast_channel *ast); static int bridge_write(struct ast_channel *ast, struct ast_frame *f); static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge); -static const struct ast_channel_tech bridge_tech = { +static struct ast_channel_tech bridge_tech = { .type = "Bridge", .description = "Bridge Interaction Channel", - .capabilities = -1, .requester = bridge_request, .call = bridge_call, .hangup = bridge_hangup, @@ -189,9 +188,10 @@ static int bridge_hangup(struct ast_channel *ast) } /*! \brief Called when we want to place a call somewhere, but not actually call it... yet */ -static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *bridge_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct bridge_pvt *p = NULL; + struct ast_format slin; /* Try to allocate memory for our very minimal pvt structure */ if (!(p = ast_calloc(1, sizeof(*p)))) { @@ -215,11 +215,19 @@ static struct ast_channel *bridge_request(const char *type, format_t format, con /* Setup parameters on both new channels */ p->input->tech = p->output->tech = &bridge_tech; p->input->tech_pvt = p->output->tech_pvt = p; - p->input->nativeformats = p->output->nativeformats = AST_FORMAT_SLINEAR; - p->input->readformat = p->output->readformat = AST_FORMAT_SLINEAR; - p->input->rawreadformat = p->output->rawreadformat = AST_FORMAT_SLINEAR; - p->input->writeformat = p->output->writeformat = AST_FORMAT_SLINEAR; - p->input->rawwriteformat = p->output->rawwriteformat = AST_FORMAT_SLINEAR; + + ast_format_set(&slin, AST_FORMAT_SLINEAR, 0); + + ast_format_cap_add(p->input->nativeformats, &slin); + ast_format_cap_add(p->output->nativeformats, &slin); + ast_format_copy(&p->input->readformat, &slin); + ast_format_copy(&p->output->readformat, &slin); + ast_format_copy(&p->input->rawreadformat, &slin); + ast_format_copy(&p->output->rawreadformat, &slin); + ast_format_copy(&p->input->writeformat, &slin); + ast_format_copy(&p->output->writeformat, &slin); + ast_format_copy(&p->input->rawwriteformat, &slin); + ast_format_copy(&p->output->rawwriteformat, &slin); return p->input; } @@ -227,6 +235,11 @@ static struct ast_channel *bridge_request(const char *type, format_t format, con /*! \brief Load module into PBX, register channel */ static int load_module(void) { + if (!(bridge_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } + + ast_format_cap_add_all(bridge_tech.capabilities); /* Make sure we can register our channel type */ if (ast_channel_register(&bridge_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'Bridge'\n"); @@ -239,6 +252,7 @@ static int load_module(void) static int unload_module(void) { ast_channel_unregister(&bridge_tech); + bridge_tech.capabilities = ast_format_cap_destroy(bridge_tech.capabilities); return 0; } diff --git a/channels/chan_console.c b/channels/chan_console.c index 64c1b87fc..eb961b682 100644 --- a/channels/chan_console.c +++ b/channels/chan_console.c @@ -183,7 +183,7 @@ static struct ast_jb_conf default_jbconf = { static struct ast_jb_conf global_jbconf; /*! Channel Technology Callbacks @{ */ -static struct ast_channel *console_request(const char *type, format_t format, +static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int console_digit_begin(struct ast_channel *c, char digit); static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration); @@ -198,15 +198,9 @@ static int console_indicate(struct ast_channel *chan, int cond, static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); /*! @} */ -/*! - * \brief Formats natively supported by this module. - */ -#define SUPPORTED_FORMATS ( AST_FORMAT_SLINEAR16 ) - -static const struct ast_channel_tech console_tech = { +static struct ast_channel_tech console_tech = { .type = "Console", .description = "Console Channel Driver", - .capabilities = SUPPORTED_FORMATS, .requester = console_request, .send_digit_begin = console_digit_begin, .send_digit_end = console_digit_end, @@ -265,12 +259,12 @@ static void *stream_monitor(void *data) PaError res; struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR16, .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(); @@ -424,9 +418,9 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, } chan->tech = &console_tech; - chan->nativeformats = AST_FORMAT_SLINEAR16; - chan->readformat = AST_FORMAT_SLINEAR16; - chan->writeformat = AST_FORMAT_SLINEAR16; + ast_format_set(&chan->readformat, AST_FORMAT_SLINEAR16, 0); + ast_format_set(&chan->writeformat, AST_FORMAT_SLINEAR16, 0); + ast_format_cap_add(chan->nativeformats, &chan->readformat); chan->tech_pvt = ref_pvt(pvt); pvt->owner = chan; @@ -448,9 +442,8 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, return chan; } -static struct ast_channel *console_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat = format; struct ast_channel *chan = NULL; struct console_pvt *pvt; char buf[512]; @@ -460,9 +453,8 @@ static struct ast_channel *console_request(const char *type, format_t format, co return NULL; } - format &= SUPPORTED_FORMATS; - if (!format) { - ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), oldformat)); + 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)); goto return_unref; } @@ -1457,6 +1449,7 @@ static void stop_streams(void) static int unload_module(void) { + console_tech.capabilities = ast_format_cap_destroy(console_tech.capabilities); ast_channel_unregister(&console_tech); ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console)); @@ -1474,8 +1467,14 @@ static int unload_module(void) static int load_module(void) { + struct ast_format tmpfmt; PaError res; + if (!(console_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_add(console_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0)); + init_pvt(&globals, NULL); if (!(pvts = ao2_container_alloc(NUM_PVT_BUCKETS, pvt_hash_cb, pvt_cmp_cb))) diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 09f461259..b5f398fdf 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -1471,7 +1471,7 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void) } -static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int dahdi_digit_begin(struct ast_channel *ast, char digit); static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration); static int dahdi_sendtext(struct ast_channel *c, const char *text); @@ -1490,10 +1490,9 @@ static int dahdi_func_write(struct ast_channel *chan, const char *function, char static int dahdi_devicestate(void *data); static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback); -static const struct ast_channel_tech dahdi_tech = { +static struct ast_channel_tech dahdi_tech = { .type = "DAHDI", .description = tdesc, - .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW, .requester = dahdi_request, .send_digit_begin = dahdi_digit_begin, .send_digit_end = dahdi_digit_end, @@ -1679,6 +1678,7 @@ 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; @@ -1714,9 +1714,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_LAW(p)); + res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); } else { - res = callerid_feed(p->cs, buf, res, AST_LAW(p)); + res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); } if (res < 0) { /* @@ -1885,6 +1885,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"); @@ -1901,11 +1902,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_LAW(p)); + ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0)); p->callwaitcas = 1; p->cidlen = 2400 + 680 + READ_SIZE * 4; } else { - ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); + ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0)); p->callwaitcas = 0; p->cidlen = 2400 + READ_SIZE * 4; } @@ -1918,6 +1919,7 @@ 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"); @@ -1931,7 +1933,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_LAW(p)); + ast_format_set(&tmpfmt, AST_LAW(p), 0)); } else { ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", caller->id.name.str, caller->id.number.str); @@ -1940,7 +1942,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_LAW(p)); + ast_format_set(&tmpfmt, AST_LAW(p), 0)); p->cidlen += READ_SIZE * 4; } p->cidpos = 0; @@ -5106,12 +5108,14 @@ 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_LAW(p)); + p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0)); /* Make sure we account for the end */ p->cidlen += READ_SIZE * 4; p->cidpos = 0; @@ -5186,6 +5190,7 @@ static int send_callerid(struct dahdi_pvt *p) static int dahdi_callwait(struct ast_channel *ast) { struct dahdi_pvt *p = ast->tech_pvt; + struct ast_format tmpfmt; p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; if (p->cidspill) { ast_log(LOG_WARNING, "Spill already exists?!?\n"); @@ -5202,11 +5207,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_LAW(p)); + ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0)); p->callwaitcas = 1; p->cidlen = 2400 + 680 + READ_SIZE * 4; } else { - ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); + ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0)); p->callwaitcas = 0; p->cidlen = 2400 + READ_SIZE * 4; } @@ -8823,15 +8828,15 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) return &p->subs[idx].f; } - if (ast->rawreadformat == AST_FORMAT_SLINEAR) { + if (ast->rawreadformat.id == AST_FORMAT_SLINEAR) { 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->rawreadformat == AST_FORMAT_ULAW) || - (ast->rawreadformat == AST_FORMAT_ALAW)) { + } else if ((ast->rawreadformat.id == AST_FORMAT_ULAW) || + (ast->rawreadformat.id == AST_FORMAT_ALAW)) { if (p->subs[idx].linear) { p->subs[idx].linear = 0; res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); @@ -8839,7 +8844,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) 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->rawreadformat)); + ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(&ast->rawreadformat)); ast_mutex_unlock(&p->lock); return NULL; } @@ -8931,7 +8936,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) } p->subs[idx].f.frametype = AST_FRAME_VOICE; - p->subs[idx].f.subclass.codec = ast->rawreadformat; + ast_format_copy(&p->subs[idx].f.subclass.format, &ast->rawreadformat); p->subs[idx].f.samples = READ_SIZE; p->subs[idx].f.mallocd = 0; p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; @@ -9101,10 +9106,10 @@ 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 '%d'\n", frame->frametype); return 0; } - if ((frame->subclass.codec != AST_FORMAT_SLINEAR) && - (frame->subclass.codec != AST_FORMAT_ULAW) && - (frame->subclass.codec != AST_FORMAT_ALAW)) { - ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); + 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) { @@ -9124,7 +9129,7 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame) if (!frame->data.ptr || !frame->datalen) return 0; - if (frame->subclass.codec == AST_FORMAT_SLINEAR) { + if (frame->subclass.format.id == AST_FORMAT_SLINEAR) { if (!p->subs[idx].linear) { p->subs[idx].linear = 1; res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); @@ -9316,7 +9321,7 @@ static struct ast_str *create_channel_name(struct dahdi_pvt *i) static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid) { struct ast_channel *tmp; - format_t deflaw; + struct ast_format deflaw; int x; int features; struct ast_str *chan_name; @@ -9327,6 +9332,7 @@ 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] @@ -9354,9 +9360,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) { - deflaw = AST_FORMAT_ALAW; + ast_format_set(&deflaw, AST_FORMAT_ALAW, 0); } else { - deflaw = AST_FORMAT_ULAW; + ast_format_set(&deflaw, AST_FORMAT_ULAW, 0); } } else { switch (i->sig) { @@ -9370,18 +9376,18 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb break; } if (i->law_default == DAHDI_LAW_ALAW) { - deflaw = AST_FORMAT_ALAW; + ast_format_set(&deflaw, AST_FORMAT_ALAW, 0); } else { - deflaw = AST_FORMAT_ULAW; + ast_format_set(&deflaw, AST_FORMAT_ULAW, 0); } } ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); - tmp->nativeformats = deflaw; + ast_format_cap_add(tmp->nativeformats, &deflaw); /* Start out assuming ulaw since it's smaller :) */ - tmp->rawreadformat = deflaw; - tmp->readformat = deflaw; - tmp->rawwriteformat = deflaw; - tmp->writeformat = deflaw; + ast_format_copy(&tmp->rawreadformat, &deflaw); + ast_format_copy(&tmp->readformat, &deflaw); + ast_format_copy(&tmp->rawwriteformat, &deflaw); + ast_format_copy(&tmp->writeformat, &deflaw); i->subs[idx].linear = 0; dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); features = 0; @@ -9619,6 +9625,7 @@ static void *analog_ss_thread(void *data) int len = 0; int res; int idx; + struct ast_format tmpfmt; ast_mutex_lock(&ss_thread_lock); ss_thread_count++; @@ -10279,9 +10286,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_LAW(p)); + res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); } else { - res = callerid_feed(cs, buf, res, AST_LAW(p)); + res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); } if (res < 0) { /* @@ -10550,7 +10557,7 @@ static void *analog_ss_thread(void *data) } } samples += res; - res = callerid_feed(cs, buf, res, AST_LAW(p)); + res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0)); if (res < 0) { /* * The previous diagnostic message output likely @@ -10718,7 +10725,7 @@ struct mwi_thread_data { size_t len; }; -static int calc_energy(const unsigned char *buf, int len, format_t law) +static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law) { int x; int sum = 0; @@ -10743,6 +10750,7 @@ 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))) { mtd->pvt->mwimonitoractive = 0; @@ -10750,7 +10758,7 @@ static void *mwi_thread(void *data) return NULL; } - callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); + callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0)); bump_gains(mtd->pvt); @@ -10832,7 +10840,7 @@ static void *mwi_thread(void *data) } samples += res; if (!spill_done) { - if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { + if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) { /* * The previous diagnostic message output likely * explains why it failed. @@ -10891,6 +10899,7 @@ quit_no_clean: static int mwi_send_init(struct dahdi_pvt * pvt) { int x, res; + struct ast_format tmpfmt; #ifdef HAVE_DAHDI_LINEREVERSE_VMWI /* Determine how this spill is to be sent */ @@ -10933,7 +10942,7 @@ static int mwi_send_init(struct dahdi_pvt * pvt) if (pvt->mwisend_fsk) { #endif 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); + ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0); pvt->cidpos = 0; #ifdef HAVE_DAHDI_LINEREVERSE_VMWI } @@ -13295,7 +13304,7 @@ static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi return p; } -static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { int callwait = 0; struct dahdi_pvt *p; @@ -16285,6 +16294,8 @@ static int __unload_module(void) } #endif /* defined(HAVE_SS7) */ ast_cond_destroy(&ss_thread_complete); + + dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities); return 0; } @@ -18034,10 +18045,18 @@ 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) */ + if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) { + 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)); + #ifdef HAVE_PRI memset(pris, 0, sizeof(pris)); for (y = 0; y < NUM_SPANS; y++) { @@ -18146,7 +18165,10 @@ static int dahdi_sendtext(struct ast_channel *c, const char *text) return -1; mybuf = buf; if (p->mate) { - int codec = AST_LAW(p); + 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); for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ PUT_CLID_MARKMS; } diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index 280cac4b5..3bbf16192 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -111,7 +111,6 @@ struct gtalk_pvt { iksrule *ringrule; /*!< Rule for matching RING request */ int initiator; /*!< If we're the initiator */ int alreadygone; - int capability; struct ast_codec_pref prefs; struct gtalk_candidate *theircandidates; struct gtalk_candidate *ourcandidates; @@ -121,8 +120,9 @@ struct gtalk_pvt { struct ast_channel *owner; /*!< Master Channel */ struct ast_rtp_instance *rtp; /*!< RTP audio session */ struct ast_rtp_instance *vrtp; /*!< RTP video session */ - format_t jointcapability; /*!< Supported capability at both ends (codecs ) */ - format_t peercapability; + struct ast_format_cap *cap; + struct ast_format_cap *jointcap; /*!< Supported capability at both ends (codecs ) */ + struct ast_format_cap *peercap; struct gtalk_pvt *next; /* Next entity */ }; @@ -152,7 +152,7 @@ struct gtalk { char context[AST_MAX_CONTEXT]; char parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */ char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */ - format_t capability; + struct ast_format_cap *cap; ast_group_t callgroup; /*!< Call group */ ast_group_t pickupgroup; /*!< Pickup group */ int callingpres; /*!< Calling presentation */ @@ -169,12 +169,12 @@ static const char desc[] = "Gtalk Channel"; static const char DEFAULT_CONTEXT[] = "default"; static const int DEFAULT_ALLOWGUEST = 1; -static format_t global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263; +static struct ast_format_cap *global_capability; AST_MUTEX_DEFINE_STATIC(gtalklock); /*!< Protect the interface list (of gtalk_pvt's) */ /* Forward declarations */ -static struct ast_channel *gtalk_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *gtalk_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); /*static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration);*/ static int gtalk_sendtext(struct ast_channel *ast, const char *text); static int gtalk_digit_begin(struct ast_channel *ast, char digit); @@ -200,10 +200,9 @@ static int gtalk_parser(void *data, ikspak *pak); static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, char *sid, char *from, char *to); /*! \brief PBX interface structure for channel registration */ -static const struct ast_channel_tech gtalk_tech = { +static struct ast_channel_tech gtalk_tech = { .type = "Gtalk", .description = "Gtalk Channel Driver", - .capabilities = AST_FORMAT_AUDIO_MASK, .requester = gtalk_request, .send_text = gtalk_sendtext, .send_digit_begin = gtalk_digit_begin, @@ -247,6 +246,7 @@ static struct gtalk_container gtalk_list; static void gtalk_member_destroy(struct gtalk *obj) { + obj->cap = ast_format_cap_destroy(obj->cap); ast_free(obj); } @@ -282,7 +282,7 @@ static struct gtalk *find_gtalk(char *name, char *connection) } -static int add_codec_to_answer(const struct gtalk_pvt *p, int codec, iks *dcodecs) +static int add_codec_to_answer(const struct gtalk_pvt *p, struct ast_format *codec, iks *dcodecs) { int res = 0; char *format = ast_getformatname(codec); @@ -392,17 +392,17 @@ static int gtalk_invite(struct gtalk_pvt *p, char *to, char *from, char *sid, in struct gtalk *client = p->parent; iks *iq, *gtalk, *dcodecs, *payload_telephone, *transport; int x; - int pref_codec = 0; - int alreadysent = 0; + struct ast_format_cap *alreadysent; int codecs_num = 0; char *lowerto = NULL; + struct ast_format tmpfmt; iq = iks_new("iq"); gtalk = iks_new("session"); dcodecs = iks_new("description"); transport = iks_new("transport"); payload_telephone = iks_new("payload-type"); - if (!(iq && gtalk && dcodecs && transport && payload_telephone)){ + if (!(iq && gtalk && dcodecs && transport && payload_telephone)) { iks_delete(iq); iks_delete(gtalk); iks_delete(dcodecs); @@ -415,16 +415,23 @@ static int gtalk_invite(struct gtalk_pvt *p, char *to, char *from, char *sid, in iks_insert_attrib(dcodecs, "xmlns", GOOGLE_AUDIO_NS); iks_insert_attrib(dcodecs, "xml:lang", "en"); - for (x = 0; x < 64; x++) { - if (!(pref_codec = ast_codec_pref_index(&client->prefs, x))) + if (!(alreadysent = ast_format_cap_alloc_nolock())) { + return 0; + } + for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { + if (!(ast_codec_pref_index(&client->prefs, x, &tmpfmt))) { break; - if (!(client->capability & pref_codec)) + } + if (!(ast_format_cap_iscompatible(client->cap, &tmpfmt))) { continue; - if (alreadysent & pref_codec) + } + if (ast_format_cap_iscompatible(alreadysent, &tmpfmt)) { continue; - codecs_num = add_codec_to_answer(p, pref_codec, dcodecs); - alreadysent |= pref_codec; + } + codecs_num = add_codec_to_answer(p, &tmpfmt, dcodecs); + ast_format_cap_add(alreadysent, &tmpfmt); } + alreadysent = ast_format_cap_destroy(alreadysent); if (codecs_num) { /* only propose DTMF within an audio session */ @@ -544,13 +551,15 @@ static enum ast_rtp_glue_result gtalk_get_rtp_peer(struct ast_channel *chan, str return res; } -static format_t gtalk_get_codec(struct ast_channel *chan) +static void gtalk_get_codec(struct ast_channel *chan, struct ast_format_cap *result) { struct gtalk_pvt *p = chan->tech_pvt; - return p->peercapability; + ast_mutex_lock(&p->lock); + ast_format_cap_copy(result, p->peercap); + ast_mutex_unlock(&p->lock); } -static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active) +static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *cap, int nat_active) { struct gtalk_pvt *p; @@ -658,15 +667,15 @@ static int gtalk_is_answered(struct gtalk *client, ikspak *pak) } /* Now gather all of the codecs that we are asked for */ - ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(tmp->rtp), &tmp->peercapability, &peernoncodeccapability); + ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(tmp->rtp), tmp->peercap, &peernoncodeccapability); - /* at this point, we received an awser from the remote Gtalk client, + /* at this point, we received an answer from the remote Gtalk client, which allows us to compare capabilities */ - tmp->jointcapability = tmp->capability & tmp->peercapability; - if (!tmp->jointcapability) { - ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->capability), - ast_getformatname_multiple(s2, BUFSIZ, tmp->peercapability), - ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcapability)); + ast_format_cap_joint_copy(tmp->cap, tmp->peercap, tmp->jointcap); + if (ast_format_cap_is_empty(tmp->jointcap)) { + ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->cap), + ast_getformatname_multiple(s2, BUFSIZ, tmp->peercap), + ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcap)); /* close session if capabilities don't match */ ast_queue_hangup(tmp->owner); @@ -1018,6 +1027,16 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { return NULL; } + tmp->cap = ast_format_cap_alloc_nolock(); + tmp->jointcap = ast_format_cap_alloc_nolock(); + tmp->peercap = ast_format_cap_alloc_nolock(); + if (!tmp->jointcap || !tmp->peercap || !tmp->cap) { + tmp->cap = ast_format_cap_destroy(tmp->cap); + tmp->jointcap = ast_format_cap_destroy(tmp->jointcap); + tmp->peercap = ast_format_cap_destroy(tmp->peercap); + ast_free(tmp); + return NULL; + } memcpy(&tmp->prefs, &client->prefs, sizeof(struct ast_codec_pref)); @@ -1046,10 +1065,10 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp); /* add user configured codec capabilites */ - if (client->capability) { - tmp->capability = client->capability; - } else if (global_capability) { - tmp->capability = global_capability; + if (!(ast_format_cap_is_empty(client->cap))) { + ast_format_cap_copy(tmp->cap, client->cap); + } else if (!(ast_format_cap_is_empty(global_capability))) { + ast_format_cap_copy(tmp->cap, global_capability); } tmp->parent = client; @@ -1081,9 +1100,9 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i, int state, const char *title, const char *linkedid) { struct ast_channel *tmp; - int fmt; - int what; const char *n2; + struct ast_format_cap *what; /* used as SHALLOW COPY DO NOT DESTROY */ + struct ast_format tmpfmt; if (title) n2 = title; @@ -1098,20 +1117,29 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i, /* Select our native format based on codec preference until we receive something from another device to the contrary. */ - if (i->jointcapability) - what = i->jointcapability; - else if (i->capability) - what = i->capability; - else + if (!(ast_format_cap_is_empty(i->jointcap))) { + what = i->jointcap; + } else if (i->cap) { + what = i->cap; + } else { what = global_capability; + } /* Set Frame packetization */ if (i->rtp) { ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs); } - tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK); - fmt = ast_best_codec(tmp->nativeformats); + ast_codec_choose(&i->prefs, what, 1, &tmpfmt); + ast_format_cap_add(tmp->nativeformats, &tmpfmt); + + ast_format_cap_iter_start(i->jointcap); + while (!(ast_format_cap_iter_next(i->jointcap, &tmpfmt))) { + if (AST_FORMAT_GET_TYPE(tmpfmt.id) == AST_FORMAT_TYPE_VIDEO) { + ast_format_cap_add(tmp->nativeformats, &tmpfmt); + } + } + ast_format_cap_iter_end(i->jointcap); if (i->rtp) { ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0)); @@ -1124,10 +1152,12 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i, if (state == AST_STATE_RING) tmp->rings = 1; tmp->adsicpe = AST_ADSI_UNAVAILABLE; - tmp->writeformat = fmt; - tmp->rawwriteformat = fmt; - tmp->readformat = fmt; - tmp->rawreadformat = fmt; + + ast_best_codec(tmp->nativeformats, &tmpfmt); + ast_format_copy(&tmp->writeformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + ast_format_copy(&tmp->readformat, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); tmp->tech_pvt = i; tmp->callgroup = client->callgroup; @@ -1240,6 +1270,9 @@ static void gtalk_free_pvt(struct gtalk *client, struct gtalk_pvt *p) if (p->vrtp) ast_rtp_instance_destroy(p->vrtp); gtalk_free_candidates(p->theircandidates); + p->cap = ast_format_cap_destroy(p->cap); + p->jointcap = ast_format_cap_destroy(p->jointcap); + p->peercap = ast_format_cap_destroy(p->peercap); ast_free(p); } @@ -1341,15 +1374,15 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) } /* Now gather all of the codecs that we are asked for */ - ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(p->rtp), &p->peercapability, &peernoncodeccapability); - p->jointcapability = p->capability & p->peercapability; + ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(p->rtp), p->peercap, &peernoncodeccapability); + ast_format_cap_joint_copy(p->cap, p->peercap, p->jointcap); ast_mutex_unlock(&p->lock); ast_setstate(chan, AST_STATE_RING); - if (!p->jointcapability) { - ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->capability), - ast_getformatname_multiple(s2, BUFSIZ, p->peercapability), - ast_getformatname_multiple(s3, BUFSIZ, p->jointcapability)); + if (ast_format_cap_is_empty(p->jointcap)) { + ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->cap), + ast_getformatname_multiple(s2, BUFSIZ, p->peercap), + ast_getformatname_multiple(s3, BUFSIZ, p->jointcap)); /* close session if capabilities don't match */ gtalk_action(client, p, "reject"); p->alreadygone = 1; @@ -1572,12 +1605,12 @@ static struct ast_frame *gtalk_rtp_read(struct ast_channel *ast, struct gtalk_pv if (p->owner) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE) { - if (f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { - ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec)); - p->owner->nativeformats = - (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass.codec; - ast_set_read_format(p->owner, p->owner->readformat); - ast_set_write_format(p->owner, p->owner->writeformat); + if (!ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format)) { + ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_remove_bytype(p->owner->nativeformats, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_add(p->owner->nativeformats, &f->subclass.format); + ast_set_read_format(p->owner, &p->owner->readformat); + ast_set_write_format(p->owner, &p->owner->writeformat); } /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { f = ast_dsp_process(p->owner, p->vad, f); @@ -1609,13 +1642,13 @@ static int gtalk_write(struct ast_channel *ast, struct ast_frame *frame) switch (frame->frametype) { case AST_FRAME_VOICE: - if (!(frame->subclass.codec & ast->nativeformats)) { + if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(frame->subclass.codec), + ast_getformatname(&frame->subclass.format), ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), - ast_getformatname(ast->readformat), - ast_getformatname(ast->writeformat)); + ast_getformatname(&ast->readformat), + ast_getformatname(&ast->writeformat)); return 0; } if (p) { @@ -1845,7 +1878,7 @@ static int gtalk_hangup(struct ast_channel *ast) } /*!\brief Part of PBX interface */ -static struct ast_channel *gtalk_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *gtalk_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct gtalk_pvt *p = NULL; struct gtalk *client = NULL; @@ -1937,8 +1970,8 @@ static char *gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cl chan->name, jid, resource, - ast_getformatname(chan->readformat), - ast_getformatname(chan->writeformat) + ast_getformatname(&chan->readformat), + ast_getformatname(&chan->writeformat) ); else ast_log(LOG_WARNING, "No available channel\n"); @@ -2067,9 +2100,9 @@ static int gtalk_create_member(char *label, struct ast_variable *var, int allowg if (!strcasecmp(var->name, "username")) ast_copy_string(member->user, var->value, sizeof(member->user)); else if (!strcasecmp(var->name, "disallow")) - ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 0); else if (!strcasecmp(var->name, "allow")) - ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 1); else if (!strcasecmp(var->name, "context")) ast_copy_string(member->context, var->value, sizeof(member->context)); else if (!strcasecmp(var->name, "parkinglot")) @@ -2122,6 +2155,7 @@ static int gtalk_load_config(void) memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); /* set defaults */ + memset(&prefs, 0, sizeof(prefs)); memset(&stunaddr, 0, sizeof(stunaddr)); global_stunaddr = 0; global_allowguest = DEFAULT_ALLOWGUEST; @@ -2138,9 +2172,9 @@ static int gtalk_load_config(void) if (!strcasecmp(var->name, "allowguest")) { global_allowguest = (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; } else if (!strcasecmp(var->name, "disallow")) { - ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0); + ast_parse_allow_disallow(&prefs, global_capability, var->value, 0); } else if (!strcasecmp(var->name, "allow")) { - ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1); + ast_parse_allow_disallow(&prefs, global_capability, var->value, 1); } else if (!strcasecmp(var->name, "context")) { ast_copy_string(global_context, var->value, sizeof(global_context)); } else if (!strcasecmp(var->name, "externip")) { @@ -2167,6 +2201,7 @@ static int gtalk_load_config(void) member = ast_calloc(1, sizeof(*member)); ASTOBJ_INIT(member); ASTOBJ_WRLOCK(member); + member->cap = ast_format_cap_alloc_nolock(); if (!strcasecmp(cat, "guest")) { ast_copy_string(member->name, "guest", sizeof(member->name)); ast_copy_string(member->user, "guest", sizeof(member->user)); @@ -2176,10 +2211,10 @@ static int gtalk_load_config(void) member->prefs = prefs; while (var) { if (!strcasecmp(var->name, "disallow")) { - ast_parse_allow_disallow(&member->prefs, &member->capability, + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 0); } else if (!strcasecmp(var->name, "allow")) { - ast_parse_allow_disallow(&member->prefs, &member->capability, + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 1); } else if (!strcasecmp(var->name, "context")) { ast_copy_string(member->context, var->value, @@ -2229,8 +2264,22 @@ static int load_module(void) { struct ast_sockaddr bindaddr_tmp; struct ast_sockaddr ourip_tmp; - char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); + struct ast_format tmpfmt; + + if (!(gtalk_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(global_capability = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + + ast_format_cap_add_all_by_type(gtalk_tech.capabilities, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0)); + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_H263, 0)); + free(jabber_loaded); if (!jabber_loaded) { /* If embedded, check for a different module name */ @@ -2313,6 +2362,8 @@ static int unload_module(void) } ASTOBJ_CONTAINER_DESTROYALL(>alk_list, gtalk_member_destroy); ASTOBJ_CONTAINER_DESTROY(>alk_list); + global_capability = ast_format_cap_destroy(global_capability); + gtalk_tech.capabilities = ast_format_cap_destroy(gtalk_tech.capabilities); return 0; } diff --git a/channels/chan_h323.c b/channels/chan_h323.c index e549d4299..ccc034872 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -85,6 +85,8 @@ extern "C" { #include "asterisk/stringfields.h" #include "asterisk/abstract_jb.h" #include "asterisk/astobj.h" +#include "asterisk/format.h" +#include "asterisk/format_cap.h" #ifdef __cplusplus } @@ -129,7 +131,13 @@ static const char config[] = "h323.conf"; static char default_context[AST_MAX_CONTEXT] = "default"; static struct sockaddr_in bindaddr; -#define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261) +#define GLOBAL_CAPABILITY (ast_format_id_to_old_bitfield(AST_FORMAT_G723_1) | \ + ast_format_id_to_old_bitfield(AST_FORMAT_GSM) | \ + 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_G729A) | \ + ast_format_id_to_old_bitfield(AST_FORMAT_G726_AAL2) | \ + ast_format_id_to_old_bitfield(AST_FORMAT_H261)) \ /** H.323 configuration values */ static int h323_signalling_port = 1720; @@ -173,9 +181,9 @@ static struct oh323_pvt { int newcontrol; /*!< Pending control to send */ int newdigit; /*!< Pending DTMF digit to send */ int newduration; /*!< Pending DTMF digit duration to send */ - format_t pref_codec; /*!< Preferred codec */ - format_t peercapability; /*!< Capabilities learned from peer */ - format_t jointcapability; /*!< Common capabilities for local and remote side */ + h323_format pref_codec; /*!< Preferred codec */ + h323_format peercapability; /*!< Capabilities learned from peer */ + h323_format jointcapability; /*!< Common capabilities for local and remote side */ struct ast_codec_pref peer_prefs; /*!< Preferenced list of codecs which remote side supports */ int dtmf_pt[2]; /*!< Payload code used for RFC2833/CISCO messages */ int curDTMF; /*!< DTMF tone being generated to Asterisk side */ @@ -231,7 +239,7 @@ static void delete_users(void); static void delete_aliases(void); static void prune_peers(void); -static struct ast_channel *oh323_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *oh323_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int oh323_digit_begin(struct ast_channel *c, char digit); static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration); static int oh323_call(struct ast_channel *c, char *dest, int timeout); @@ -242,10 +250,9 @@ static int oh323_write(struct ast_channel *c, struct ast_frame *frame); static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen); static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); -static const struct ast_channel_tech oh323_tech = { +static struct ast_channel_tech oh323_tech = { .type = "H323", .description = tdesc, - .capabilities = AST_FORMAT_AUDIO_MASK, .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, .requester = oh323_request, .send_digit_begin = oh323_digit_begin, @@ -331,12 +338,13 @@ static int oh323_simulate_dtmf_end(const void *data) /*! \brief Channel and private structures should be already locked */ static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt) { - if (c->nativeformats != pvt->nativeformats) { + h323_format chan_nativeformats_bits = ast_format_cap_to_old_bitfield(c->nativeformats); + if (chan_nativeformats_bits != pvt->nativeformats) { if (h323debug) ast_debug(1, "Preparing %s for new native format\n", c->name); - c->nativeformats = pvt->nativeformats; - ast_set_read_format(c, c->readformat); - ast_set_write_format(c, c->writeformat); + ast_format_cap_from_old_bitfield(c->nativeformats, pvt->nativeformats); + ast_set_read_format(c, &c->readformat); + ast_set_write_format(c, &c->writeformat); } if (pvt->needhangup) { if (h323debug) @@ -764,18 +772,20 @@ static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt) if (pvt->owner) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE) { - if (f->subclass.codec != pvt->owner->nativeformats) { + if (!ast_format_cap_iscompatible(pvt->owner->nativeformats, &f->subclass.format)) { /* Try to avoid deadlock */ if (ast_channel_trylock(pvt->owner)) { ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n"); return &ast_null_frame; } if (h323debug) - ast_debug(1, "Oooh, format changed to '%s'\n", ast_getformatname(f->subclass.codec)); - pvt->owner->nativeformats = f->subclass.codec; - pvt->nativeformats = f->subclass.codec; - ast_set_read_format(pvt->owner, pvt->owner->readformat); - ast_set_write_format(pvt->owner, pvt->owner->writeformat); + ast_debug(1, "Oooh, format changed to '%s'\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_set(pvt->owner->nativeformats, &f->subclass.format); + + pvt->nativeformats = ast_format_to_old_bitfield(&f->subclass.format); + + ast_set_read_format(pvt->owner, &pvt->owner->readformat); + ast_set_write_format(pvt->owner, &pvt->owner->writeformat); ast_channel_unlock(pvt->owner); } /* Do in-band DTMF detection */ @@ -788,7 +798,7 @@ static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt) else ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n"); } else if (pvt->nativeformats && !pvt->noInbandDtmf) { - ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass.codec)); + ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(&f->subclass.format)); pvt->noInbandDtmf = 1; } if (f &&(f->frametype == AST_FRAME_DTMF)) { @@ -838,10 +848,10 @@ static int oh323_write(struct ast_channel *c, struct ast_frame *frame) return 0; } } else { - if (!(frame->subclass.codec & c->nativeformats)) { + if (!(ast_format_cap_iscompatible(c->nativeformats, &frame->subclass.format))) { char tmp[256]; ast_log(LOG_WARNING, "Asked to transmit frame type '%s', while native formats is '%s' (read/write = %s/%s)\n", - ast_getformatname(frame->subclass.codec), ast_getformatname_multiple(tmp, sizeof(tmp), c->nativeformats), ast_getformatname(c->readformat), ast_getformatname(c->writeformat)); + ast_getformatname(&frame->subclass.format), ast_getformatname_multiple(tmp, sizeof(tmp), c->nativeformats), ast_getformatname(&c->readformat), ast_getformatname(&c->writeformat)); return 0; } } @@ -1011,7 +1021,8 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c { struct ast_channel *ch; char *cid_num, *cid_name; - int fmt; + h323_format fmt; + struct ast_format tmpfmt; if (!ast_strlen_zero(pvt->options.cid_num)) cid_num = pvt->options.cid_num; @@ -1033,13 +1044,18 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c ch->tech = &oh323_tech; if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability)) fmt = global_options.capability; - ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/; - pvt->nativeformats = ch->nativeformats; - fmt = ast_best_codec(ch->nativeformats); - ch->writeformat = fmt; - ch->rawwriteformat = fmt; - ch->readformat = fmt; - ch->rawreadformat = fmt; + + ast_format_cap_from_old_bitfield(ch->nativeformats, fmt); + ast_codec_choose(&pvt->options.prefs, ch->nativeformats, 1, &tmpfmt)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/; + + ast_format_cap_set(ch->nativeformats, &tmpfmt); + + pvt->nativeformats = ast_format_cap_to_old_bitfield(ch->nativeformats); + ast_best_codec(ch->nativeformats, &tmpfmt); + ast_format_copy(&ch->writeformat, &tmpfmt); + ast_format_copy(&ch->rawwriteformat, &tmpfmt); + ast_format_copy(&ch->readformat, &tmpfmt); + ast_format_copy(&ch->rawreadformat, &tmpfmt); if (!pvt->rtp) __oh323_rtp_create(pvt); #if 0 @@ -1264,17 +1280,33 @@ static struct oh323_alias *realtime_alias(const char *alias) return a; } +static int h323_parse_allow_disallow(struct ast_codec_pref *pref, h323_format *formats, const char *list, int allowing) +{ + int res; + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + 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); + return res; + +} + static int update_common_options(struct ast_variable *v, struct call_options *options) { int tmp = 0; char *val, *opt; if (!strcasecmp(v->name, "allow")) { - ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1); + h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1); } else if (!strcasecmp(v->name, "autoframing")) { options->autoframing = ast_true(v->value); } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0); + h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0); } else if (!strcasecmp(v->name, "dtmfmode")) { val = ast_strdupa(v->value); if ((opt = strchr(val, ':')) != (char *)NULL) { @@ -1745,9 +1777,8 @@ static int create_addr(struct oh323_pvt *pvt, char *opeer) return 0; } } -static struct ast_channel *oh323_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *oh323_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat; struct oh323_pvt *pvt; struct ast_channel *tmpc = NULL; char *dest = (char *)data; @@ -1756,17 +1787,15 @@ static struct ast_channel *oh323_request(const char *type, format_t format, cons char tmp[256], tmp1[256]; if (h323debug) - ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), format), (char *)data); + ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), cap), (char *)data); pvt = oh323_alloc(0); if (!pvt) { ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data); return NULL; } - oldformat = format; - format &= AST_FORMAT_AUDIO_MASK; - if (!format) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format)); + 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)); oh323_destroy(pvt); if (cause) *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION; @@ -2020,11 +2049,11 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, nativeformats_changed = 0; if (pt != 128 && pvt->rtp) { /* Payload type is invalid, so try to use previously decided */ struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt); - if (h323debug) - ast_debug(1, "Native format is set to %llu from %d by RTP payload type %d\n", (unsigned long long) rtptype.code, pvt->nativeformats, pt); - if (pvt->nativeformats != rtptype.code) { - pvt->nativeformats = rtptype.code; - nativeformats_changed = 1; + if (rtptype.asterisk_format) { + if (pvt->nativeformats != ast_format_to_old_bitfield(&rtptype.format)) { + pvt->nativeformats = ast_format_to_old_bitfield(&rtptype.format); + nativeformats_changed = 1; + } } } else if (h323debug) ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n"); @@ -2032,15 +2061,18 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, /* Don't try to lock the channel if nothing changed */ if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) { if (pvt->owner && !ast_channel_trylock(pvt->owner)) { + struct ast_format_cap *pvt_native = ast_format_cap_alloc_nolock(); + ast_format_cap_from_old_bitfield(pvt_native, pvt->nativeformats); + /* Re-build translation path only if native format(s) has been changed */ - if (pvt->owner->nativeformats != pvt->nativeformats) { + if (!(ast_format_cap_identical(pvt->owner->nativeformats, pvt_native))) { if (h323debug) { char tmp[256], tmp2[256]; - ast_debug(1, "Native format changed to '%s' from '%s', read format is %s, write format is %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), pvt->nativeformats), ast_getformatname_multiple(tmp2, sizeof(tmp2), pvt->owner->nativeformats), ast_getformatname(pvt->owner->readformat), ast_getformatname(pvt->owner->writeformat)); + ast_debug(1, "Native format changed to '%s' from '%s', read format is %s, write format is %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), pvt_native), ast_getformatname_multiple(tmp2, sizeof(tmp2), pvt->owner->nativeformats), ast_getformatname(&pvt->owner->readformat), ast_getformatname(&pvt->owner->writeformat)); } - pvt->owner->nativeformats = pvt->nativeformats; - ast_set_read_format(pvt->owner, pvt->owner->readformat); - ast_set_write_format(pvt->owner, pvt->owner->writeformat); + ast_format_cap_copy(pvt->owner->nativeformats, pvt_native); + ast_set_read_format(pvt->owner, &pvt->owner->readformat); + ast_set_write_format(pvt->owner, &pvt->owner->writeformat); } if (pvt->options.progress_audio) ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS); @@ -2055,6 +2087,7 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, break; } ast_channel_unlock(pvt->owner); + pvt_native = ast_format_cap_destroy(pvt_native); } else { if (pvt->options.progress_audio) @@ -2491,7 +2524,7 @@ static void set_peer_capabilities(unsigned call_reference, const char *token, in for (i = 0; i < 32; ++i) { if (!prefs->order[i]) break; - ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]); + ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(&prefs->formats[i]) : "<none>"), prefs->framing[i]); } } if (pvt->rtp) { @@ -2531,7 +2564,7 @@ static void set_local_capabilities(unsigned call_reference, const char *token) for (i = 0; i < 32; i++) { if (!prefs.order[i]) break; - ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]); + ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(&prefs.formats[i]) : "<none>"), prefs.framing[i]); } ast_debug(1, "Capabilities for connection %s is set\n", token); } @@ -3191,9 +3224,9 @@ static enum ast_rtp_glue_result oh323_get_rtp_peer(struct ast_channel *chan, str return res; } -static char *convertcap(format_t cap) +static char *convertcap(struct ast_format *format) { - switch (cap) { + switch (format->id) { case AST_FORMAT_G723_1: return "G.723"; case AST_FORMAT_GSM: @@ -3213,12 +3246,12 @@ static char *convertcap(format_t cap) case AST_FORMAT_ILBC: return "ILBC"; default: - ast_log(LOG_NOTICE, "Don't know how to deal with mode %" PRId64 "\n", cap); + ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_getformatname(format)); return NULL; } } -static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active) +static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active) { /* XXX Deal with Video */ struct oh323_pvt *pvt; @@ -3230,7 +3263,7 @@ static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance return 0; } - mode = convertcap(chan->writeformat); + mode = convertcap(&chan->writeformat); pvt = (struct oh323_pvt *) chan->tech_pvt; if (!pvt) { ast_log(LOG_ERROR, "No Private Structure, this is bad\n"); @@ -3260,6 +3293,11 @@ static enum ast_module_load_result load_module(void) { int res; + if (!(oh323_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } + ast_format_cap_add_all_by_type(oh323_tech.capabilities, AST_FORMAT_TYPE_AUDIO); + h323debug = 0; sched = ast_sched_context_create(); if (!sched) { @@ -3430,6 +3468,7 @@ static int unload_module(void) ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias); ASTOBJ_CONTAINER_DESTROY(&aliasl); + oh323_tech.capabilities = ast_format_cap_destroy(oh323_tech.capabilities); return 0; } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 5de2c4a23..49434d678 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -317,22 +317,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_SLINEAR & \ - ~AST_FORMAT_SLINEAR16 & \ - ~AST_FORMAT_SIREN7 & \ - ~AST_FORMAT_SIREN14 & \ - ~AST_FORMAT_G719 & \ - ~AST_FORMAT_ULAW & \ - ~AST_FORMAT_ALAW & \ - ~AST_FORMAT_G722) + ~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)) /* A modem */ #define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \ - ~AST_FORMAT_G726 & \ - ~AST_FORMAT_G726_AAL2 & \ - ~AST_FORMAT_ADPCM) + ~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)) #define IAX_CAPABILITY_LOWFREE (IAX_CAPABILITY_LOWBANDWIDTH & \ - ~AST_FORMAT_G723_1) + ~ast_format_id_to_old_bitfield(AST_FORMAT_G723_1)) #define DEFAULT_MAXMS 2000 /* Must be faster than 2 seconds by default */ @@ -361,7 +361,7 @@ static struct ast_sched_context *sched; #define DONT_RESCHEDULE -2 -static format_t iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH; +static iax2_format iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH; static int iaxdebug = 0; @@ -470,7 +470,7 @@ struct iax2_user { int amaflags; int adsi; uint64_t flags; - format_t capability; + iax2_format capability; int maxauthreq; /*!< Maximum allowed outstanding AUTHREQs */ int curauthreq; /*!< Current number of outstanding AUTHREQs */ struct ast_codec_pref prefs; @@ -517,7 +517,7 @@ struct iax2_peer { int expire; /*!< Schedule entry for expiry */ int expiry; /*!< How soon to expire */ - format_t capability; /*!< Capability */ + iax2_format capability; /*!< Capability */ /* Qualification */ int callno; /*!< Call number of POKE request */ @@ -648,15 +648,15 @@ struct chan_iax2_pvt { /*! Socket to send/receive on for this call */ int sockfd; /*! Last received voice format */ - format_t voiceformat; + iax2_format voiceformat; /*! Last received video format */ - format_t videoformat; + iax2_format videoformat; /*! Last sent voice format */ - format_t svoiceformat; + iax2_format svoiceformat; /*! Last sent video format */ - format_t svideoformat; + iax2_format svideoformat; /*! What we are capable of sending */ - format_t capability; + iax2_format capability; /*! Last received timestamp */ unsigned int last; /*! Last sent timestamp - never send the same timestamp twice in a single call */ @@ -690,11 +690,11 @@ struct chan_iax2_pvt { /*! Negotiated format, this is only used to remember what format was chosen for an unauthenticated call so that the channel can get created later using the right format */ - format_t chosenformat; + iax2_format chosenformat; /*! Peer selected format */ - format_t peerformat; + iax2_format peerformat; /*! Peer capability */ - format_t peercapability; + iax2_format peercapability; /*! timeval that we base our transmission on */ struct timeval offset; /*! timeval that we base our delivery on */ @@ -1191,7 +1191,7 @@ static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, c static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int); static int send_command_locked(unsigned short callno, char, int, unsigned int, const unsigned char *, int, int); static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int); -static struct ast_channel *iax2_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *iax2_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static struct ast_frame *iax2_read(struct ast_channel *c); static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly); static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly); @@ -1211,10 +1211,9 @@ static int replace_callno(const void *obj); static void sched_delay_remove(struct sockaddr_in *sin, struct callno_entry *callno_entry); static void network_change_event_cb(const struct ast_event *, void *); -static const struct ast_channel_tech iax2_tech = { +static struct ast_channel_tech iax2_tech = { .type = "IAX2", .description = tdesc, - .capabilities = IAX_CAPABILITY_FULLBANDWIDTH, .properties = AST_CHAN_TP_WANTSJITTER, .requester = iax2_request, .devicestate = iax2_devicestate, @@ -1604,7 +1603,7 @@ static int send_lagrq(const void *data) return 0; } -static unsigned char compress_subclass(format_t subclass) +static unsigned char compress_subclass(iax2_format subclass) { int x; int power=-1; @@ -1624,7 +1623,7 @@ static unsigned char compress_subclass(format_t subclass) return power | IAX_FLAG_SC_LOG; } -static format_t uncompress_subclass(unsigned char csub) +static iax2_format uncompress_subclass(unsigned char csub) { /* If the SC_LOG flag is set, return 2^csub otherwise csub */ if (csub & IAX_FLAG_SC_LOG) { @@ -1638,6 +1637,90 @@ static format_t uncompress_subclass(unsigned char csub) return csub; } +static iax2_format iax2_codec_choose(struct ast_codec_pref *pref, iax2_format formats, int find_best) +{ + struct ast_format_cap *cap; + struct ast_format tmpfmt; + iax2_format format = 0; + if ((cap = ast_format_cap_alloc_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); + } + + return format; +} + +static iax2_format iax2_best_codec(iax2_format formats) +{ + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + struct ast_format tmpfmt; + 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); +} + +char *iax2_getformatname(iax2_format format) +{ + struct ast_format tmpfmt; + if (!(ast_format_from_old_bitfield(&tmpfmt, format))) { + return "Unknown"; + } + + return ast_getformatname(&tmpfmt); +} + +static char *iax2_getformatname_multiple(char *codec_buf, size_t len, iax2_format format) +{ + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + + 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); + + return codec_buf; +} + +static int iax2_parse_allow_disallow(struct ast_codec_pref *pref, iax2_format *formats, const char *list, int allowing) +{ + int res; + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + 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); + + return res; +} + +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_nolock(); + if (!cap) { + return -1; + } + ast_format_cap_from_old_bitfield(cap, formats); + res = ast_data_add_codecs(root, node_name, cap); + cap = ast_format_cap_destroy(cap); + return res; +} + /*! * \note The only member of the peer passed here guaranteed to be set is the name field */ @@ -3727,7 +3810,7 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct struct iax2_peer *peer; char codec_buf[512]; struct ast_str *encmethods = ast_str_alloca(256); - int x = 0, codec = 0, load_realtime = 0; + int x = 0, load_realtime = 0; switch (cmd) { case CLI_INIT: @@ -3772,16 +3855,16 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli(a->fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); ast_cli(a->fd, " Username : %s\n", peer->username); ast_cli(a->fd, " Codecs : "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); + iax2_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); ast_cli(a->fd, "%s\n", codec_buf); ast_cli(a->fd, " Codec Order : ("); - for(x = 0; x < 32 ; x++) { - codec = ast_codec_pref_index(&peer->prefs,x); - if(!codec) + 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(codec)); - if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) + ast_cli(a->fd, "%s", ast_getformatname(&tmpfmt)); + if(x < 31 && ast_codec_pref_index(&peer->prefs, x+1, &tmpfmt)) ast_cli(a->fd, "|"); } @@ -4067,7 +4150,9 @@ static void __get_from_jb(const void *p) ms = ast_tvdiff_ms(now, pvt->rxcore); if(ms >= (next = jb_next(pvt->jb))) { - ret = jb_get(pvt->jb,&frame,ms,ast_codec_interp_len(pvt->voiceformat)); + struct ast_format voicefmt; + ast_format_from_old_bitfield(&voicefmt, pvt->voiceformat); + ret = jb_get(pvt->jb, &frame, ms, ast_codec_interp_len(&voicefmt)); switch(ret) { case JB_OK: fr = frame.data; @@ -4081,8 +4166,8 @@ static void __get_from_jb(const void *p) /* create an interpolation frame */ af.frametype = AST_FRAME_VOICE; - af.subclass.codec = pvt->voiceformat; - af.samples = frame.ms * (ast_format_rate(pvt->voiceformat) / 1000); + ast_format_copy(&af.subclass.format, &voicefmt); + af.samples = frame.ms * (ast_format_rate(&voicefmt) / 1000); af.src = "IAX2 JB interpolation"; af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); af.offset = AST_FRIENDLY_OFFSET; @@ -4154,7 +4239,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.codec) / 1000); + len = ast_codec_get_samples(&fr->af) / (ast_format_rate(&fr->af.subclass.format) / 1000); } else if(fr->af.frametype == AST_FRAME_CNG) { type = JB_TYPE_SILENCE; } @@ -4511,7 +4596,7 @@ static void realtime_update_peer(const char *peername, struct ast_sockaddr *sock } struct create_addr_info { - format_t capability; + iax2_format capability; uint64_t flags; int maxtime; int encmethods; @@ -4557,8 +4642,14 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka /* use global iax prefs for unknown peer/user */ /* But move the calling channel's native codec to the top of the preference list */ memcpy(&ourprefs, &prefs, sizeof(ourprefs)); - if (c) - ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); + if (c) { + struct ast_format tmpfmt; + ast_format_cap_iter_start(c->nativeformats); + while (!(ast_format_cap_iter_next(c->nativeformats, &tmpfmt))) { + ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1); + } + ast_format_cap_iter_end(c->nativeformats); + } ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); return 0; } @@ -4585,8 +4676,13 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); /* Move the calling channel's native codec to the top of the preference list */ if (c) { - ast_debug(1, "prepending %llx to prefs\n", (unsigned long long) c->nativeformats); - ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); + struct ast_format tmpfmt; + ast_format_cap_iter_start(c->nativeformats); + while (!(ast_format_cap_iter_next(c->nativeformats, &tmpfmt))) { + ast_debug(1, "prepending %s to prefs\n", ast_getformatname(&tmpfmt)); + ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1); + } + ast_format_cap_iter_end(c->nativeformats); } ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); ast_copy_string(cai->context, peer->context, sizeof(cai->context)); @@ -4995,6 +5091,7 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout) unsigned char osp_block_index; unsigned int osp_block_length; unsigned char osp_buffer[256]; + iax2_format iax2_tmpfmt; if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); @@ -5121,8 +5218,10 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout) if (pds.password) ast_string_field_set(iaxs[callno], secret, pds.password); - iax_ie_append_int(&ied, IAX_IE_FORMAT, (int) c->nativeformats); - iax_ie_append_versioned_uint64(&ied, IAX_IE_FORMAT2, 0, c->nativeformats); + iax2_tmpfmt = ast_format_cap_to_old_bitfield(c->nativeformats); + iax_ie_append_int(&ied, IAX_IE_FORMAT, (int) iax2_tmpfmt); + iax_ie_append_versioned_uint64(&ied, IAX_IE_FORMAT2, 0, iax2_tmpfmt); + iax_ie_append_int(&ied, IAX_IE_CAPABILITY, (int) iaxs[callno]->capability); iax_ie_append_versioned_uint64(&ied, IAX_IE_CAPABILITY2, 0, iaxs[callno]->capability); iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); @@ -5471,7 +5570,7 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha } return AST_BRIDGE_FAILED_NOWARN; } - if (c0->nativeformats != c1->nativeformats) { + if (!(ast_format_cap_identical(c0->nativeformats, c1->nativeformats))) { char buf0[256]; char buf1[256]; ast_getformatname_multiple(buf0, sizeof(buf0), c0->nativeformats); @@ -5676,11 +5775,12 @@ static int iax2_getpeertrunk(struct sockaddr_in sin) } /*! \brief Create new call, interface with the PBX core */ -static struct ast_channel *ast_iax2_new(int callno, int state, format_t capability, const char *linkedid) +static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capability, const char *linkedid) { struct ast_channel *tmp; struct chan_iax2_pvt *i; struct ast_variable *v = NULL; + struct ast_format tmpfmt; if (!(i = iaxs[callno])) { ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); @@ -5705,9 +5805,14 @@ static struct ast_channel *ast_iax2_new(int callno, int state, format_t capabili return NULL; tmp->tech = &iax2_tech; /* We can support any format by default, until we get restricted */ - tmp->nativeformats = capability; - tmp->readformat = tmp->rawreadformat = ast_best_codec(capability); - tmp->writeformat = tmp->rawwriteformat = ast_best_codec(capability); + ast_format_cap_from_old_bitfield(tmp->nativeformats, capability); + ast_best_codec(tmp->nativeformats, &tmpfmt); + + ast_format_copy(&tmp->readformat, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); + ast_format_copy(&tmp->writeformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + tmp->tech_pvt = CALLNO_TO_PTR(i->callno); if (!ast_strlen_zero(i->parkinglot)) @@ -5848,7 +5953,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.codec) / 1000; + int rate = ast_format_rate(&f->subclass.format) / 1000; struct timeval *delivery = NULL; @@ -6221,9 +6326,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) { - f->subclass.codec = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); + ast_format_from_old_bitfield(&f->subclass.format, (uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1))); } else if (f->frametype == AST_FRAME_VOICE) { - f->subclass.codec = uncompress_subclass(fh->csub); + ast_format_from_old_bitfield(&f->subclass.format, uncompress_subclass(fh->csub)); } else { f->subclass.integer = uncompress_subclass(fh->csub); } @@ -6366,7 +6471,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.codec == pvt->svoiceformat) + (f->subclass.format.id == ast_format_id_from_old_bitfield(pvt->svoiceformat)) /* is the same type */ ) { /* Force immediate rather than delayed transmission */ now = 1; @@ -6380,7 +6485,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.codec & ~0x1LL) == pvt->svideoformat) + ((f->subclass.format.id) == ast_format_id_from_old_bitfield(pvt->svideoformat)) ) { now = 1; sendmini = 1; @@ -6435,9 +6540,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) { - fh->csub = compress_subclass(fr->af.subclass.codec & ~0x1LL) | ((fr->af.subclass.codec & 0x1LL) << 6); + iax2_format tmpfmt = ast_format_to_old_bitfield(&fr->af.subclass.format); + tmpfmt |= ast_format_get_video_mark(&fr->af.subclass.format) ? 0x1LL : 0; + fh->csub = compress_subclass(tmpfmt | ((tmpfmt & 0x1LL) << 6)); } else if (fr->af.frametype == AST_FRAME_VOICE) { - fh->csub = compress_subclass(fr->af.subclass.codec); + fh->csub = compress_subclass(ast_format_to_old_bitfield(&fr->af.subclass.format)); } else { fh->csub = compress_subclass(fr->af.subclass.integer); } @@ -6460,9 +6567,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 = f->subclass.codec; + pvt->svoiceformat = ast_format_to_old_bitfield(&f->subclass.format); else if (f->frametype == AST_FRAME_VIDEO) - pvt->svideoformat = f->subclass.codec & ~0x1LL; + pvt->svideoformat = ast_format_to_old_bitfield(&f->subclass.format); if (ast_test_flag64(pvt, IAX_ENCRYPTED)) { if (ast_test_flag64(pvt, IAX_KEYPOPULATED)) { if (fr->transfer) @@ -6493,7 +6600,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) | (fr->af.subclass.codec & 0x1LL ? 0x8000 : 0)); + vh->ts = htons((fr->ts & 0x7FFF) | (ast_format_get_video_mark(&fr->af.subclass.format) ? 0x8000 : 0)); fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); fr->data = vh; fr->retries = -1; @@ -7167,7 +7274,7 @@ static char *handle_cli_iax2_show_channels(struct ast_cli_entry *e, int cmd, str lag, jitter, localdelay, - ast_getformatname(iaxs[x]->voiceformat), + iax2_getformatname(iaxs[x]->voiceformat), (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", first_message, (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", @@ -9659,7 +9766,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 { - f.subclass.codec = iaxs[fr->callno]->voiceformat; + ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat); f.datalen = len; if (f.datalen >= 0) { if (f.datalen) @@ -9806,7 +9913,7 @@ static int socket_process(struct iax2_thread *thread) struct iax2_peer *peer; struct iax_ies ies; struct iax_ie_data ied0, ied1; - format_t format; + iax2_format format; int fd; int exists; int minivid = 0; @@ -9877,9 +9984,12 @@ static int socket_process(struct iax2_thread *thread) /* Retrieve the type and subclass */ f.frametype = fh->type; if (f.frametype == AST_FRAME_VIDEO) { - f.subclass.codec = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); + ast_format_from_old_bitfield(&f.subclass.format, (uncompress_subclass(fh->csub & ~0x40))); + if ((fh->csub >> 6) & 0x1) { + ast_format_set_video_mark(&f.subclass.format); + } } else if (f.frametype == AST_FRAME_VOICE) { - f.subclass.codec = uncompress_subclass(fh->csub); + ast_format_from_old_bitfield(&f.subclass.format, uncompress_subclass(fh->csub)); } else { f.subclass.integer = uncompress_subclass(fh->csub); } @@ -10250,21 +10360,24 @@ static int socket_process(struct iax2_thread *thread) } if (f.frametype == AST_FRAME_VOICE) { - if (f.subclass.codec != iaxs[fr->callno]->voiceformat) { - iaxs[fr->callno]->voiceformat = f.subclass.codec; - ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_getformatname(f.subclass.codec)); + 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 (iaxs[fr->callno]->owner) { iax2_lock_owner(fr->callno); if (iaxs[fr->callno]) { if (iaxs[fr->callno]->owner) { - format_t orignative; - - orignative = iaxs[fr->callno]->owner->nativeformats; - iaxs[fr->callno]->owner->nativeformats = f.subclass.codec; - if (iaxs[fr->callno]->owner->readformat) - ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); - iaxs[fr->callno]->owner->nativeformats = orignative; - ast_channel_unlock(iaxs[fr->callno]->owner); + struct ast_format_cap *orignative = ast_format_cap_dup(iaxs[fr->callno]->owner->nativeformats); + struct ast_format_cap *native = iaxs[fr->callno]->owner->nativeformats; + if (orignative) { + ast_format_cap_set(native, &f.subclass.format); + if (iaxs[fr->callno]->owner->readformat.id) { + ast_set_read_format(iaxs[fr->callno]->owner, &iaxs[fr->callno]->owner->readformat); + } + ast_format_cap_copy(native, orignative); + ast_channel_unlock(iaxs[fr->callno]->owner); + orignative = ast_format_cap_destroy(orignative); + } } } else { ast_debug(1, "Neat, somebody took away the channel at a magical time but i found it!\n"); @@ -10281,9 +10394,9 @@ static int socket_process(struct iax2_thread *thread) } } if (f.frametype == AST_FRAME_VIDEO) { - if (f.subclass.codec != iaxs[fr->callno]->videoformat) { - ast_debug(1, "Ooh, video format changed to %s\n", ast_getformatname(f.subclass.codec & ~0x1LL)); - iaxs[fr->callno]->videoformat = f.subclass.codec & ~0x1LL; + 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 (f.frametype == AST_FRAME_CONTROL && iaxs[fr->callno]->owner) { @@ -10471,11 +10584,12 @@ static int socket_process(struct iax2_thread *thread) strcpy(caller_pref_buf, "disabled"); strcpy(host_pref_buf, "disabled"); } else { + 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)) { + if (ast_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; @@ -10486,7 +10600,7 @@ static int socket_process(struct iax2_thread *thread) } else pref = iaxs[fr->callno]->prefs; - format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); + 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); } @@ -10506,14 +10620,14 @@ static int socket_process(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_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat), + iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); } else { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", ast_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - ast_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + 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)); } } } else { @@ -10525,12 +10639,13 @@ static int socket_process(struct iax2_thread *thread) if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { using_prefs = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; memset(&pref, 0, sizeof(pref)); - format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); + format = iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); strcpy(caller_pref_buf,"disabled"); strcpy(host_pref_buf,"disabled"); } else { + struct ast_format tmpfmt; using_prefs = "mine"; - if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { + if (ast_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; @@ -10538,9 +10653,9 @@ static int socket_process(struct iax2_thread *thread) pref = iaxs[fr->callno]->rprefs; using_prefs = "caller"; } - format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); + format = iax2_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); } else /* if no codec_prefs IE do it the old way */ - format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); + format = iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); } } @@ -10549,7 +10664,7 @@ static int socket_process(struct iax2_thread *thread) 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", ast_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(tmp, sizeof(tmp), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability)); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { break; @@ -10557,9 +10672,9 @@ static int socket_process(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_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - ast_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + 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)); } ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE); break; @@ -10582,11 +10697,11 @@ static int socket_process(struct iax2_thread *thread) "%spriority = %s\n", ast_inet_ntoa(sin.sin_addr), VERBOSE_PREFIX_4, - ast_getformatname(iaxs[fr->callno]->peerformat), + iax2_getformatname(iaxs[fr->callno]->peerformat), VERBOSE_PREFIX_4, caller_pref_buf, VERBOSE_PREFIX_4, - ast_getformatname(format), + iax2_getformatname(format), VERBOSE_PREFIX_4, host_pref_buf, VERBOSE_PREFIX_4, @@ -10730,11 +10845,11 @@ static int socket_process(struct iax2_thread *thread) iaxs[fr->callno]->peerformat = ies.format; } else { if (iaxs[fr->callno]->owner) - iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; + iaxs[fr->callno]->peerformat = ast_format_cap_to_old_bitfield(iaxs[fr->callno]->owner->nativeformats); else iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; } - ast_verb(3, "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat)); + ast_verb(3, "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iax2_getformatname(iaxs[fr->callno]->peerformat)); if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); @@ -10747,22 +10862,23 @@ static int socket_process(struct iax2_thread *thread) char tmp1[256], tmp2[256]; ast_log(LOG_NOTICE, "Rejected call to %s, format %s incompatible with our capability %s.\n", ast_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), + iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); } } else { 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]; /* Switch us to use a compatible format */ - iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; - ast_verb(3, "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); + ast_format_cap_from_old_bitfield(iaxs[fr->callno]->owner->nativeformats, iaxs[fr->callno]->peerformat); + ast_verb(3, "Format for call is %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->owner->nativeformats)); /* Setup read/write formats properly. */ - if (iaxs[fr->callno]->owner->writeformat) - ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); - if (iaxs[fr->callno]->owner->readformat) - ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); + if (iaxs[fr->callno]->owner->writeformat.id) + ast_set_write_format(iaxs[fr->callno]->owner, &iaxs[fr->callno]->owner->writeformat); + if (iaxs[fr->callno]->owner->readformat.id) + ast_set_read_format(iaxs[fr->callno]->owner, &iaxs[fr->callno]->owner->readformat); ast_channel_unlock(iaxs[fr->callno]->owner); } } @@ -10921,10 +11037,11 @@ static int socket_process(struct iax2_thread *thread) strcpy(caller_pref_buf, "disabled"); strcpy(host_pref_buf, "disabled"); } else { + 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)) { + if (ast_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"; @@ -10933,7 +11050,7 @@ static int socket_process(struct iax2_thread *thread) } } else /* if no codec_prefs IE do it the old way */ pref = iaxs[fr->callno]->prefs; - format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); + 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); } @@ -10941,22 +11058,22 @@ static int socket_process(struct iax2_thread *thread) char tmp1[256], tmp2[256], tmp3[256]; 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", - ast_getformatname(iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability)); + iax2_getformatname(iaxs[fr->callno]->peerformat), + iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability)); format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; } if (!format) { 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_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), + iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); } else { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", ast_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - ast_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + 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)); } } memset(&ied0, 0, sizeof(ied0)); @@ -10976,12 +11093,13 @@ static int socket_process(struct iax2_thread *thread) using_prefs = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; memset(&pref, 0, sizeof(pref)); format = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ? - iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); + iaxs[fr->callno]->peerformat : iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); strcpy(caller_pref_buf,"disabled"); strcpy(host_pref_buf,"disabled"); } else { + struct ast_format tmpfmt; using_prefs = "mine"; - if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { + if (ast_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; @@ -10989,27 +11107,27 @@ static int socket_process(struct iax2_thread *thread) pref = iaxs[fr->callno]->rprefs; using_prefs = "caller"; } - format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); + format = iax2_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); } else /* if no codec_prefs IE do it the old way */ - format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); + format = iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); } } if (!format) { char tmp1[256], tmp2[256], tmp3[256]; ast_log(LOG_ERROR, "No best format in %s???\n", - ast_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability)); 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_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); + iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), + iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability)); } else { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", ast_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat), - ast_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability), - ast_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability)); + 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)); } } memset(&ied0, 0, sizeof(ied0)); @@ -11038,11 +11156,11 @@ static int socket_process(struct iax2_thread *thread) "%spriority = %s\n", ast_inet_ntoa(sin.sin_addr), VERBOSE_PREFIX_4, - ast_getformatname(iaxs[fr->callno]->peerformat), + iax2_getformatname(iaxs[fr->callno]->peerformat), VERBOSE_PREFIX_4, caller_pref_buf, VERBOSE_PREFIX_4, - ast_getformatname(format), + iax2_getformatname(format), VERBOSE_PREFIX_4, host_pref_buf, VERBOSE_PREFIX_4, @@ -11117,7 +11235,7 @@ immediatedial: ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); ast_verb(3, "Accepting DIAL from %s, formats = %s\n", ast_inet_ntoa(sin.sin_addr), - ast_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat)); + iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat)); 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))) @@ -11396,9 +11514,12 @@ immediatedial: send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); } else if (minivid) { f.frametype = AST_FRAME_VIDEO; - if (iaxs[fr->callno]->videoformat > 0) - f.subclass.codec = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000LL ? 1 : 0); - else { + if (iaxs[fr->callno]->videoformat > 0) { + if (ntohs(vh->ts) & 0x8000LL) { + ast_format_set_video_mark(&f.subclass.format); + } + ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->videoformat); + } else { ast_log(LOG_WARNING, "Received mini frame before first full video frame\n"); iax2_vnak(fr->callno); ast_variables_destroy(ies.vars); @@ -11420,7 +11541,7 @@ immediatedial: /* A mini frame */ f.frametype = AST_FRAME_VOICE; if (iaxs[fr->callno]->voiceformat > 0) - f.subclass.codec = iaxs[fr->callno]->voiceformat; + ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat); else { ast_debug(1, "Received mini frame before first full voice frame\n"); iax2_vnak(fr->callno); @@ -11492,7 +11613,7 @@ immediatedial: if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { f.samples = ast_codec_get_samples(&f); /* We need to byteswap incoming slinear samples from network byte order */ - if (f.subclass.codec == AST_FORMAT_SLINEAR) + if (f.subclass.format.id == AST_FORMAT_SLINEAR) ast_frame_byteswap_be(&f); } else f.samples = 0; @@ -11982,11 +12103,10 @@ static void free_context(struct iax2_context *con) } } -static struct ast_channel *iax2_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *iax2_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { int callno; int res; - format_t fmt, native; struct sockaddr_in sin; struct ast_channel *c; struct parsed_dial_string pds; @@ -12001,12 +12121,11 @@ static struct ast_channel *iax2_request(const char *type, format_t format, const ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); return NULL; } - memset(&cai, 0, sizeof(cai)); cai.capability = iax2_capability; ast_copy_flags64(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE); - + /* Populate our address from the given */ if (create_addr(pds.peer, NULL, &sin, &cai)) { *cause = AST_CAUSE_UNREGISTERED; @@ -12039,23 +12158,28 @@ static struct ast_channel *iax2_request(const char *type, format_t format, const ast_mutex_unlock(&iaxsl[callno]); if (c) { + struct ast_format_cap *joint; + /* Choose a format we can live with */ - if (c->nativeformats & format) - c->nativeformats &= format; - else { - native = c->nativeformats; - fmt = format; - res = ast_translator_best_choice(&fmt, &native); + if ((joint = ast_format_cap_joint(c->nativeformats, cap))) { + ast_format_cap_copy(c->nativeformats, joint); + joint = ast_format_cap_destroy(joint); + } else { + struct ast_format best_fmt_cap; + struct ast_format best_fmt_native; + res = ast_translator_best_choice(cap, c->nativeformats, &best_fmt_cap, &best_fmt_native); if (res < 0) { + char tmp[256]; + char tmp2[256]; ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", - ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); + ast_getformatname_multiple(tmp, sizeof(tmp), c->nativeformats), ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), c->name); ast_hangup(c); return NULL; } - c->nativeformats = native; + ast_format_cap_set(c->nativeformats, &best_fmt_native); } - c->readformat = ast_best_codec(c->nativeformats); - c->writeformat = c->readformat; + ast_best_codec(c->nativeformats, &c->readformat); + ast_format_copy(&c->writeformat, &c->readformat); } return c; @@ -12429,9 +12553,9 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st } else if (!strcasecmp(v->name, "username")) { ast_string_field_set(peer, username, v->value); } else if (!strcasecmp(v->name, "allow")) { - ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); + iax2_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); + iax2_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); } else if (!strcasecmp(v->name, "callerid")) { if (!ast_strlen_zero(v->value)) { char name2[80]; @@ -12641,9 +12765,9 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st } } } else if (!strcasecmp(v->name, "allow")) { - ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); + iax2_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); + iax2_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); } else if (!strcasecmp(v->name, "trunk")) { ast_set2_flag64(user, ast_true(v->value), IAX_TRUNK); if (ast_test_flag64(user, IAX_TRUNK) && !timer) { @@ -12903,7 +13027,7 @@ static void set_config_destroy(void) static int set_config(const char *config_file, int reload) { struct ast_config *cfg, *ucfg; - format_t capability = iax2_capability; + iax2_format capability = iax2_capability; struct ast_variable *v; char *cat; const char *utype; @@ -13164,9 +13288,9 @@ static int set_config(const char *config_file, int reload) } else ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); } else if (!strcasecmp(v->name, "allow")) { - ast_parse_allow_disallow(&prefs, &capability, v->value, 1); + iax2_parse_allow_disallow(&prefs, &capability, v->value, 1); } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&prefs, &capability, v->value, 0); + iax2_parse_allow_disallow(&prefs, &capability, v->value, 0); } else if (!strcasecmp(v->name, "register")) { iax2_register(v->value, v->lineno); } else if (!strcasecmp(v->name, "iaxcompat")) { @@ -13802,19 +13926,18 @@ 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")) { - ast_getformatname_multiple(buf, len -1, peer->capability); + iax2_getformatname_multiple(buf, len -1, peer->capability); } else if (!strncasecmp(colname, "codec[", 6)) { char *codecnum, *ptr; - int codec = 0; - + struct ast_format tmpfmt; codecnum = strchr(colname, '['); *codecnum = '\0'; codecnum++; if ((ptr = strchr(codecnum, ']'))) { *ptr = '\0'; } - if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { - ast_copy_string(buf, ast_getformatname(codec), len); + if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &tmpfmt))) { + ast_copy_string(buf, ast_getformatname(&tmpfmt), len); } else { buf[0] = '\0'; } @@ -14273,6 +14396,8 @@ static int __unload_module(void) if (con) ast_context_destroy(con, "IAX2"); ast_unload_realtime("iaxpeers"); + + iax2_tech.capabilities = ast_format_cap_destroy(iax2_tech.capabilities); return 0; } @@ -14436,7 +14561,7 @@ static int peers_data_provider_get(const struct ast_data_search *search, ast_data_add_structure(iax2_peer, data_peer, peer); - ast_data_add_codecs(data_peer, "codecs", peer->capability); + iax2_data_add_codecs(data_peer, "codecs", peer->capability); peer_status(peer, status, sizeof(status)); ast_data_add_str(data_peer, "status", status); @@ -14500,7 +14625,7 @@ static int users_data_provider_get(const struct ast_data_search *search, ast_data_add_structure(iax2_user, data_user, user); - ast_data_add_codecs(data_user, "codecs", user->capability); + iax2_data_add_codecs(data_user, "codecs", user->capability); if (!ast_strlen_zero(user->secret)) { ast_copy_string(auth, user->secret, sizeof(auth)); @@ -14576,6 +14701,11 @@ static int load_module(void) int x = 0; struct iax2_registry *reg = NULL; + if (!(iax2_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } + ast_format_cap_add_all(iax2_tech.capabilities); + if (load_objects()) { return AST_MODULE_LOAD_FAILURE; } diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c index fd84f1f27..93d81d954 100644 --- a/channels/chan_jingle.c +++ b/channels/chan_jingle.c @@ -104,7 +104,6 @@ struct jingle_pvt { iksrule *ringrule; /*!< Rule for matching RING request */ int initiator; /*!< If we're the initiator */ int alreadygone; - format_t capability; struct ast_codec_pref prefs; struct jingle_candidate *theircandidates; struct jingle_candidate *ourcandidates; @@ -116,8 +115,9 @@ struct jingle_pvt { struct ast_rtp_instance *rtp; /*!< RTP audio session */ char video_content_name[100]; /*!< name attribute of content tag */ struct ast_rtp_instance *vrtp; /*!< RTP video session */ - format_t jointcapability; /*!< Supported capability at both ends (codecs ) */ - format_t peercapability; + struct ast_format_cap *cap; + struct ast_format_cap *jointcap; /*!< Supported capability at both ends (codecs ) */ + struct ast_format_cap *peercap; struct jingle_pvt *next; /* Next entity */ }; @@ -147,7 +147,7 @@ struct jingle { char user[100]; char context[100]; char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */ - format_t capability; + struct ast_format_cap *cap; ast_group_t callgroup; /*!< Call group */ ast_group_t pickupgroup; /*!< Pickup group */ int callingpres; /*!< Calling presentation */ @@ -164,12 +164,12 @@ struct jingle_container { static const char desc[] = "Jingle Channel"; static const char channel_type[] = "Jingle"; -static format_t global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263; +static struct ast_format_cap *global_capability; AST_MUTEX_DEFINE_STATIC(jinglelock); /*!< Protect the interface list (of jingle_pvt's) */ /* Forward declarations */ -static struct ast_channel *jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *jingle_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int jingle_sendtext(struct ast_channel *ast, const char *text); static int jingle_digit_begin(struct ast_channel *ast, char digit); static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration); @@ -187,10 +187,9 @@ static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_c static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); /*! \brief PBX interface structure for channel registration */ -static const struct ast_channel_tech jingle_tech = { +static struct ast_channel_tech jingle_tech = { .type = "Jingle", .description = "Jingle Channel Driver", - .capabilities = AST_FORMAT_AUDIO_MASK, .requester = jingle_request, .send_text = jingle_sendtext, .send_digit_begin = jingle_digit_begin, @@ -226,6 +225,7 @@ static struct jingle_container jingle_list; static void jingle_member_destroy(struct jingle *obj) { + obj->cap = ast_format_cap_destroy(obj->cap); ast_free(obj); } @@ -255,7 +255,7 @@ static struct jingle *find_jingle(char *name, char *connection) } -static void add_codec_to_answer(const struct jingle_pvt *p, int codec, iks *dcodecs) +static void add_codec_to_answer(const struct jingle_pvt *p, struct ast_format *codec, iks *dcodecs) { char *format = ast_getformatname(codec); @@ -301,10 +301,10 @@ static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p) struct aji_client *c = client->connection; iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn; int x; - format_t pref_codec = 0; - int alreadysent = 0; + struct ast_format pref_codec; + struct ast_format_cap *alreadysent = ast_format_cap_alloc_nolock(); - if (p->initiator) + if (p->initiator || !alreadysent) return 1; iq = iks_new("iq"); @@ -313,15 +313,15 @@ static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p) if (iq && jingle && dcodecs) { iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS); - for (x = 0; x < 64; x++) { - if (!(pref_codec = ast_codec_pref_index(&client->prefs, x))) + for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { + if (!(ast_codec_pref_index(&client->prefs, x, &pref_codec))) break; - if (!(client->capability & pref_codec)) + if (!(ast_format_cap_iscompatible(client->cap, &pref_codec))) continue; - if (alreadysent & pref_codec) + if ((ast_format_cap_iscompatible(alreadysent, &pref_codec))) continue; - add_codec_to_answer(p, pref_codec, dcodecs); - alreadysent |= pref_codec; + add_codec_to_answer(p, &pref_codec, dcodecs); + ast_format_cap_add(alreadysent, &pref_codec); } payload_red = iks_new("payload-type"); iks_insert_attrib(payload_red, "id", "117"); @@ -358,6 +358,7 @@ static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p) iks_delete(jingle); iks_delete(iq); } + alreadysent = ast_format_cap_destroy(alreadysent); return 1; } @@ -405,13 +406,15 @@ static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, st return res; } -static format_t jingle_get_codec(struct ast_channel *chan) +static void jingle_get_codec(struct ast_channel *chan, struct ast_format_cap *result) { struct jingle_pvt *p = chan->tech_pvt; - return p->peercapability; + ast_mutex_lock(&p->lock); + ast_format_cap_copy(result, p->peercap); + ast_mutex_unlock(&p->lock); } -static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, format_t codecs, int nat_active) +static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, int nat_active) { struct jingle_pvt *p; @@ -772,6 +775,16 @@ static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, return NULL; } + tmp->cap = ast_format_cap_alloc_nolock(); + tmp->jointcap = ast_format_cap_alloc_nolock(); + tmp->peercap = ast_format_cap_alloc_nolock(); + if (!tmp->cap || !tmp->jointcap || !tmp->peercap) { + tmp->cap = ast_format_cap_destroy(tmp->cap); + tmp->jointcap = ast_format_cap_destroy(tmp->jointcap); + tmp->peercap = ast_format_cap_destroy(tmp->peercap); + ast_free(tmp); + return NULL; + } memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs)); if (sid) { @@ -803,8 +816,8 @@ static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid) { struct ast_channel *tmp; - int fmt; - int what; + struct ast_format_cap *what; /* SHALLOW COPY DO NOT DESTROY */ + struct ast_format tmpfmt; const char *str; if (title) @@ -820,10 +833,10 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt * /* Select our native format based on codec preference until we receive something from another device to the contrary. */ - if (i->jointcapability) - what = i->jointcapability; - else if (i->capability) - what = i->capability; + if (!ast_format_cap_is_empty(i->jointcap)) + what = i->jointcap; + else if (!(ast_format_cap_is_empty(i->cap))) + what = i->cap; else what = global_capability; @@ -831,8 +844,16 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt * if (i->rtp) ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs); - tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK); - fmt = ast_best_codec(tmp->nativeformats); + ast_codec_choose(&i->prefs, what, 1, &tmpfmt); + ast_format_cap_add(tmp->nativeformats, &tmpfmt); + + ast_format_cap_iter_start(i->jointcap); + while (!(ast_format_cap_iter_next(i->jointcap, &tmpfmt))) { + if (AST_FORMAT_GET_TYPE(tmpfmt.id) == AST_FORMAT_TYPE_VIDEO) { + ast_format_cap_add(tmp->nativeformats, &tmpfmt); + } + } + ast_format_cap_iter_end(i->jointcap); if (i->rtp) { ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0)); @@ -845,10 +866,13 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt * if (state == AST_STATE_RING) tmp->rings = 1; tmp->adsicpe = AST_ADSI_UNAVAILABLE; - tmp->writeformat = fmt; - tmp->rawwriteformat = fmt; - tmp->readformat = fmt; - tmp->rawreadformat = fmt; + + + ast_best_codec(tmp->nativeformats, &tmpfmt); + ast_format_copy(&tmp->writeformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + ast_format_copy(&tmp->readformat, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); tmp->tech_pvt = i; tmp->callgroup = client->callgroup; @@ -955,6 +979,10 @@ static void jingle_free_pvt(struct jingle *client, struct jingle_pvt *p) if (p->vrtp) ast_rtp_instance_destroy(p->vrtp); jingle_free_candidates(p->theircandidates); + p->cap = ast_format_cap_destroy(p->cap); + p->jointcap = ast_format_cap_destroy(p->jointcap); + p->peercap = ast_format_cap_destroy(p->peercap); + ast_free(p); } @@ -1185,12 +1213,12 @@ static struct ast_frame *jingle_rtp_read(struct ast_channel *ast, struct jingle_ if (p->owner) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE) { - if (f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { - ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec)); - p->owner->nativeformats = - (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass.codec; - ast_set_read_format(p->owner, p->owner->readformat); - ast_set_write_format(p->owner, p->owner->writeformat); + if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) { + ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_remove_bytype(p->owner->nativeformats, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_add(p->owner->nativeformats, &f->subclass.format); + ast_set_read_format(p->owner, &p->owner->readformat); + ast_set_write_format(p->owner, &p->owner->writeformat); } /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { f = ast_dsp_process(p->owner, p->vad, f); @@ -1222,13 +1250,13 @@ static int jingle_write(struct ast_channel *ast, struct ast_frame *frame) switch (frame->frametype) { case AST_FRAME_VOICE: - if (!(frame->subclass.codec & ast->nativeformats)) { + if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(frame->subclass.codec), + ast_getformatname(&frame->subclass.format), ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), - ast_getformatname(ast->readformat), - ast_getformatname(ast->writeformat)); + ast_getformatname(&ast->readformat), + ast_getformatname(&ast->writeformat)); return 0; } if (p) { @@ -1464,7 +1492,7 @@ static int jingle_call(struct ast_channel *ast, char *dest, int timeout) } ast_setstate(ast, AST_STATE_RING); - p->jointcapability = p->capability; + ast_format_cap_copy(p->jointcap, p->cap); if (!p->ringrule) { ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring)); p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p, @@ -1498,7 +1526,7 @@ static int jingle_hangup(struct ast_channel *ast) } /*! \brief Part of PBX interface */ -static struct ast_channel *jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *jingle_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct jingle_pvt *p = NULL; struct jingle *client = NULL; @@ -1588,8 +1616,8 @@ static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_c chan->name, jid, resource, - ast_getformatname(chan->readformat), - ast_getformatname(chan->writeformat) + ast_getformatname(&chan->readformat), + ast_getformatname(&chan->writeformat) ); else ast_log(LOG_WARNING, "No available channel\n"); @@ -1717,9 +1745,9 @@ static int jingle_create_member(char *label, struct ast_variable *var, int allow if (!strcasecmp(var->name, "username")) ast_copy_string(member->user, var->value, sizeof(member->user)); else if (!strcasecmp(var->name, "disallow")) - ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 0); else if (!strcasecmp(var->name, "allow")) - ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 1); else if (!strcasecmp(var->name, "context")) ast_copy_string(member->context, var->value, sizeof(member->context)); #if 0 @@ -1787,9 +1815,9 @@ static int jingle_load_config(void) allowguest = (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; else if (!strcasecmp(var->name, "disallow")) - ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0); + ast_parse_allow_disallow(&prefs, global_capability, var->value, 0); else if (!strcasecmp(var->name, "allow")) - ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1); + ast_parse_allow_disallow(&prefs, global_capability, var->value, 1); else if (!strcasecmp(var->name, "context")) ast_copy_string(context, var->value, sizeof(context)); else if (!strcasecmp(var->name, "externip")) @@ -1818,6 +1846,7 @@ static int jingle_load_config(void) member = ast_calloc(1, sizeof(*member)); ASTOBJ_INIT(member); ASTOBJ_WRLOCK(member); + member->cap = ast_format_cap_alloc_nolock(); if (!strcasecmp(cat, "guest")) { ast_copy_string(member->name, "guest", sizeof(member->name)); ast_copy_string(member->user, "guest", sizeof(member->user)); @@ -1826,10 +1855,10 @@ static int jingle_load_config(void) member->prefs = prefs; while (var) { if (!strcasecmp(var->name, "disallow")) - ast_parse_allow_disallow(&member->prefs, &member->capability, + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 0); else if (!strcasecmp(var->name, "allow")) - ast_parse_allow_disallow(&member->prefs, &member->capability, + ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 1); else if (!strcasecmp(var->name, "context")) ast_copy_string(member->context, var->value, @@ -1884,8 +1913,23 @@ static int load_module(void) { struct ast_sockaddr ourip_tmp; struct ast_sockaddr bindaddr_tmp; + struct ast_format tmpfmt; char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); + + if (!(jingle_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + + ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO); + if (!(global_capability = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0)); + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_H263, 0)); + free(jabber_loaded); if (!jabber_loaded) { /* Dependency module has a different name, if embedded */ @@ -1965,6 +2009,8 @@ static int unload_module(void) } ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy); ASTOBJ_CONTAINER_DESTROY(&jingle_list); + + global_capability = ast_format_cap_destroy(global_capability); return 0; } diff --git a/channels/chan_local.c b/channels/chan_local.c index e80722c23..fbe1e530e 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -88,7 +88,7 @@ static struct ast_jb_conf g_jb_conf = { .target_extra = -1, }; -static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int local_digit_begin(struct ast_channel *ast, char digit); static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration); static int local_call(struct ast_channel *ast, char *dest, int timeout); @@ -106,10 +106,9 @@ static int local_queryoption(struct ast_channel *ast, int option, void *data, in static int local_setoption(struct ast_channel *chan, int option, void *data, int datalen); /* PBX interface structure for channel registration */ -static const struct ast_channel_tech local_tech = { +static struct ast_channel_tech local_tech = { .type = "Local", .description = tdesc, - .capabilities = -1, .requester = local_request, .send_digit_begin = local_digit_begin, .send_digit_end = local_digit_end, @@ -138,15 +137,15 @@ static const struct ast_channel_tech local_tech = { */ struct local_pvt { - unsigned int flags; /*!< Private flags */ - char context[AST_MAX_CONTEXT]; /*!< Context to call */ - char exten[AST_MAX_EXTENSION]; /*!< Extension to call */ - format_t reqformat; /*!< Requested format */ - struct ast_jb_conf jb_conf; /*!< jitterbuffer configuration for this local channel */ - struct ast_channel *owner; /*!< Master Channel - Bridging happens here */ - struct ast_channel *chan; /*!< Outbound channel - PBX is run here */ - struct ast_module_user *u_owner; /*!< reference to keep the module loaded while in use */ - struct ast_module_user *u_chan; /*!< reference to keep the module loaded while in use */ + unsigned int flags; /*!< Private flags */ + char context[AST_MAX_CONTEXT]; /*!< Context to call */ + char exten[AST_MAX_EXTENSION]; /*!< Extension to call */ + struct ast_format_cap *reqcap; /*!< Requested format capabilities */ + struct ast_jb_conf jb_conf; /*!< jitterbuffer configuration for this local channel */ + struct ast_channel *owner; /*!< Master Channel - Bridging happens here */ + struct ast_channel *chan; /*!< Outbound channel - PBX is run here */ + struct ast_module_user *u_owner;/*!< reference to keep the module loaded while in use */ + struct ast_module_user *u_chan; /*!< reference to keep the module loaded while in use */ }; #define LOCAL_ALREADY_MASQED (1 << 0) /*!< Already masqueraded */ @@ -954,13 +953,23 @@ static int local_hangup(struct ast_channel *ast) return 0; } +static void local_destroy(void *obj) +{ + struct local_pvt *pvt = obj; + pvt->reqcap = ast_format_cap_destroy(pvt->reqcap); +} + /*! \brief Create a call structure */ -static struct local_pvt *local_alloc(const char *data, format_t format) +static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *cap) { struct local_pvt *tmp = NULL; char *c = NULL, *opts = NULL; - if (!(tmp = ao2_alloc(sizeof(*tmp), NULL))) { + if (!(tmp = ao2_alloc(sizeof(*tmp), local_destroy))) { + return NULL; + } + if (!(tmp->reqcap = ast_format_cap_dup(cap))) { + ao2_ref(tmp, -1); return NULL; } @@ -995,9 +1004,6 @@ static struct local_pvt *local_alloc(const char *data, format_t format) *c++ = '\0'; ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context)); - - tmp->reqformat = format; - #if 0 /* We can't do this check here, because we don't know the CallerID yet, and * the CallerID could potentially affect what step is actually taken (or @@ -1019,7 +1025,8 @@ static struct local_pvt *local_alloc(const char *data, format_t format) static struct ast_channel *local_new(struct local_pvt *p, int state, const char *linkedid) { struct ast_channel *tmp = NULL, *tmp2 = NULL; - int randnum = ast_random() & 0xffff, fmt = 0; + int randnum = ast_random() & 0xffff; + struct ast_format fmt; const char *t; int ama; @@ -1045,19 +1052,19 @@ static struct ast_channel *local_new(struct local_pvt *p, int state, const char tmp2->tech = tmp->tech = &local_tech; - tmp->nativeformats = p->reqformat; - tmp2->nativeformats = p->reqformat; + ast_format_cap_copy(tmp->nativeformats, p->reqcap); + ast_format_cap_copy(tmp2->nativeformats, p->reqcap); /* Determine our read/write format and set it on each channel */ - fmt = ast_best_codec(p->reqformat); - tmp->writeformat = fmt; - tmp2->writeformat = fmt; - tmp->rawwriteformat = fmt; - tmp2->rawwriteformat = fmt; - tmp->readformat = fmt; - tmp2->readformat = fmt; - tmp->rawreadformat = fmt; - tmp2->rawreadformat = fmt; + ast_best_codec(p->reqcap, &fmt); + ast_format_copy(&tmp->writeformat, &fmt); + ast_format_copy(&tmp2->writeformat, &fmt); + ast_format_copy(&tmp->rawwriteformat, &fmt); + ast_format_copy(&tmp2->rawwriteformat, &fmt); + ast_format_copy(&tmp->readformat, &fmt); + ast_format_copy(&tmp2->readformat, &fmt); + ast_format_copy(&tmp->rawreadformat, &fmt); + ast_format_copy(&tmp2->rawreadformat, &fmt); tmp->tech_pvt = p; tmp2->tech_pvt = p; @@ -1079,13 +1086,13 @@ static struct ast_channel *local_new(struct local_pvt *p, int state, const char } /*! \brief Part of PBX interface */ -static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct local_pvt *p = NULL; struct ast_channel *chan = NULL; /* Allocate a new private structure and then Asterisk channel */ - if ((p = local_alloc(data, format))) { + if ((p = local_alloc(data, cap))) { if (!(chan = local_new(p, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL))) { ao2_unlink(locals, p); } @@ -1197,7 +1204,13 @@ static int locals_cmp_cb(void *obj, void *arg, int flags) /*! \brief Load module into PBX, register channel */ static int load_module(void) { + if (!(local_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } + ast_format_cap_add_all(local_tech.capabilities); + if (!(locals = ao2_container_alloc(BUCKET_SIZE, NULL, locals_cmp_cb))) { + ast_format_cap_destroy(local_tech.capabilities); return AST_MODULE_LOAD_FAILURE; } @@ -1205,6 +1218,7 @@ static int load_module(void) if (ast_channel_register(&local_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n"); ao2_ref(locals, -1); + ast_format_cap_destroy(local_tech.capabilities); return AST_MODULE_LOAD_FAILURE; } ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry)); @@ -1234,6 +1248,7 @@ static int unload_module(void) ao2_iterator_destroy(&it); ao2_ref(locals, -1); + ast_format_cap_destroy(local_tech.capabilities); return 0; } diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 723849785..32886a6a7 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -222,7 +222,7 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL; static int restart_monitor(void); -static format_t capability = AST_FORMAT_ULAW; +static struct ast_format_cap *global_capability; static int nonCodecCapability = AST_RTP_DTMF; static char ourhost[MAXHOSTNAMELEN]; @@ -361,7 +361,7 @@ struct mgcp_endpoint { int iseq; /*!< Not used? */ int lastout; /*!< tracking this on the subchannels. Is it needed here? */ int needdestroy; /*!< Not used? */ - format_t capability; + struct ast_format_cap *cap; int nonCodecCapability; int onhooktime; int msgstate; /*!< voicemail message state */ @@ -429,7 +429,7 @@ static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone); static int transmit_modify_request(struct mgcp_subchannel *sub); static int transmit_connect(struct mgcp_subchannel *sub); static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername); -static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, format_t codecs); +static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs); static int transmit_connection_del(struct mgcp_subchannel *sub); static int transmit_audit_endpoint(struct mgcp_endpoint *p); static void start_rtp(struct mgcp_subchannel *sub); @@ -439,7 +439,7 @@ static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); static int reload_config(int reload); -static struct ast_channel *mgcp_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int mgcp_call(struct ast_channel *ast, char *dest, int timeout); static int mgcp_hangup(struct ast_channel *ast); static int mgcp_answer(struct ast_channel *ast); @@ -458,10 +458,9 @@ static int acf_channel_read(struct ast_channel *chan, const char *funcname, char static struct ast_variable *add_var(const char *buf, struct ast_variable *list); static struct ast_variable *copy_vars(struct ast_variable *src); -static const struct ast_channel_tech mgcp_tech = { +static struct ast_channel_tech mgcp_tech = { .type = "MGCP", .description = tdesc, - .capabilities = AST_FORMAT_ULAW | AST_FORMAT_ALAW, .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, .requester = mgcp_request, .devicestate = mgcp_devicestate, @@ -1208,11 +1207,11 @@ 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 (f->subclass.codec != sub->owner->nativeformats) { - ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec)); - sub->owner->nativeformats = f->subclass.codec; - ast_set_read_format(sub->owner, sub->owner->readformat); - ast_set_write_format(sub->owner, sub->owner->writeformat); + if (!ast_format_cap_iscompatible(sub->owner->nativeformats, &f->subclass.format)) { + ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_set(sub->owner->nativeformats, &f->subclass.format); + ast_set_read_format(sub->owner, &sub->owner->readformat); + ast_set_write_format(sub->owner, &sub->owner->writeformat); } /* Courtesy fearnor aka alex@pilosoft.com */ if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { @@ -1251,12 +1250,12 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } } else { - if (!(frame->subclass.codec & ast->nativeformats)) { + if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(frame->subclass.codec), + ast_getformatname(&frame->subclass.format), ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), - ast_getformatname(ast->readformat), - ast_getformatname(ast->writeformat)); + ast_getformatname(&ast->readformat), + ast_getformatname(&ast->writeformat)); /* return -1; */ } } @@ -1489,16 +1488,15 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons struct ast_channel *tmp; struct ast_variable *v = NULL; struct mgcp_endpoint *i = sub->parent; - int fmt; + struct ast_format tmpfmt; tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); if (tmp) { tmp->tech = &mgcp_tech; - tmp->nativeformats = i->capability; - if (!tmp->nativeformats) { - tmp->nativeformats = capability; + ast_format_cap_copy(tmp->nativeformats, i->cap); + if (ast_format_cap_is_empty(tmp->nativeformats)) { + ast_format_cap_copy(tmp->nativeformats, global_capability); } - fmt = ast_best_codec(tmp->nativeformats); if (sub->rtp) { ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); } @@ -1512,10 +1510,12 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons } if (state == AST_STATE_RING) tmp->rings = 1; - tmp->writeformat = fmt; - tmp->rawwriteformat = fmt; - tmp->readformat = fmt; - tmp->rawreadformat = fmt; + + ast_best_codec(tmp->nativeformats, &tmpfmt); + ast_format_copy(&tmp->writeformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + ast_format_copy(&tmp->readformat, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); tmp->tech_pvt = sub; if (!ast_strlen_zero(i->language)) ast_string_field_set(tmp, language, i->language); @@ -1954,7 +1954,7 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req) char host[258]; int len; int portno; - format_t peercapability; + struct ast_format_cap *peercap; int peerNonCodecCapability; struct sockaddr_in sin; struct ast_sockaddr sin_tmp; @@ -2020,15 +2020,20 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req) } /* Now gather all of the codecs that were asked for: */ - ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability); - p->capability = capability & peercapability; + if (!(peercap = ast_format_cap_alloc_nolock())) { + 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_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n", - ast_getformatname_multiple(tmp1, sizeof(tmp1), capability), - ast_getformatname_multiple(tmp2, sizeof(tmp2), peercapability), - ast_getformatname_multiple(tmp3, sizeof(tmp3), p->capability)); + 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_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n", nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); - if (!p->capability) { + if (ast_format_cap_is_empty(p->cap)) { ast_log(LOG_WARNING, "No compatible codecs!\n"); return -1; } @@ -2181,7 +2186,8 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc char t[256]; char m[256] = ""; char a[1024] = ""; - format_t x; + int x; + struct ast_format tmpfmt; struct sockaddr_in dest = { 0, }; struct ast_sockaddr dest_tmp; struct mgcp_endpoint *p = sub->parent; @@ -2215,30 +2221,34 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); ast_copy_string(t, "t=0 0\r\n", sizeof(t)); snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); - for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { - if (!(x & AST_FORMAT_AUDIO_MASK)) { + + 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 */ continue; } - if (p->capability & x) { - ast_debug(1, "Answering with capability %s\n", ast_getformatname(x)); - codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, x); + 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, x, 0)); + 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_format_cap_iter_end(p->cap); + for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { if (p->nonCodecCapability & x) { ast_debug(1, "Answering with non-codec capability %d\n", (int) x); - codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, x); + codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, NULL, x); 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(0, x, 0)); + snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, NULL, x, 0)); strncat(a, costr, sizeof(a) - strlen(a) - 1); if (x == AST_RTP_DTMF) { /* Indicate we support DTMF... Not sure about 16, @@ -2262,13 +2272,13 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc return 0; } -static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, format_t codecs) +static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs) { struct mgcp_request resp; char local[256]; char tmp[80]; struct mgcp_endpoint *p = sub->parent; - format_t x; + struct ast_format tmpfmt; struct ast_sockaddr sub_tmpdest_tmp; if (ast_strlen_zero(sub->cxident) && rtp) { @@ -2279,16 +2289,18 @@ 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)); - for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { - if (!(x & AST_FORMAT_AUDIO_MASK)) { - /* No longer contiguous */ + 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 */ continue; } - if (p->capability & x) { - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); + 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); } } + ast_format_cap_iter_end(p->cap); if (sub->gate) { if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { @@ -2324,7 +2336,7 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp struct mgcp_request resp; char local[256]; char tmp[80]; - int x; + struct ast_format tmpfmt; struct mgcp_endpoint *p = sub->parent; ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", @@ -2332,16 +2344,18 @@ 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)); - for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { - if (!(x & AST_FORMAT_AUDIO_MASK)) { - /* No longer contiguous */ + 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 */ continue; } - if (p->capability & x) { - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); + 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); } } + ast_format_cap_iter_end(p->cap); if (sub->gate) { if(sub->gate->state == GATE_ALLOCATED) { @@ -2419,17 +2433,19 @@ static int transmit_connect(struct mgcp_subchannel *sub) struct mgcp_request resp; char local[256]; char tmp[80]; - format_t x; + struct ast_format tmpfmt; struct mgcp_endpoint *p = sub->parent; ast_copy_string(local, "p:20, s:off, e:on", sizeof(local)); - for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { - if (p->capability & x) { - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); + 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); } } + 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); @@ -2522,7 +2538,7 @@ static int transmit_modify_request(struct mgcp_subchannel *sub) { struct mgcp_request resp; struct mgcp_endpoint *p = sub->parent; - format_t x; + struct ast_format tmpfmt; int fc = 1; char local[256]; char tmp[80]; @@ -2536,18 +2552,18 @@ 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)); - for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { - if (p->capability & x) { - if (p->ncs && !fc) { - p->capability = x; /* sb5120e bug */ - break; - } else { - fc = 0; - snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); - } - strncat(local, tmp, sizeof(local) - strlen(local) - 1); + ast_format_cap_iter_start(p->cap); + while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { + if (p->ncs && !fc) { + ast_format_cap_set(p->cap, &tmpfmt); /* sb5120e bug */ + break; + } else { + fc = 0; + snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); } + strncat(local, tmp, sizeof(local) - strlen(local) - 1); } + ast_format_cap_iter_end(p->cap); if (!sub->sdpsent) { if (sub->gate) { @@ -3899,18 +3915,15 @@ static int restart_monitor(void) return 0; } -static struct ast_channel *mgcp_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat; struct mgcp_subchannel *sub; struct ast_channel *tmpc = NULL; char tmp[256]; char *dest = data; - oldformat = format; - format &= capability; - if (!format) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format)); + 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)); /*return NULL;*/ } ast_copy_string(tmp, dest, sizeof(tmp)); @@ -4138,6 +4151,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_nolock(); ast_copy_string(e->name, v->value, sizeof(e->name)); e->needaudit = 1; } @@ -4167,7 +4181,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); e->msgstate = -1; e->amaflags = amaflags; - e->capability = capability; + ast_format_cap_copy(e->cap, global_capability); e->parent = gw; e->ncs = ncs; e->dtmfmode = dtmfmode; @@ -4249,6 +4263,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_nolock(); ast_copy_string(e->name, v->value, sizeof(e->name)); e->needaudit = 1; } @@ -4270,7 +4285,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) e->parent = gw; } e->amaflags = amaflags; - e->capability = capability; + ast_format_cap_copy(e->cap, global_capability); e->dtmfmode = dtmfmode; e->ncs = ncs; e->pktcgatealloc = pktcgatealloc; @@ -4410,23 +4425,23 @@ static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, stru return AST_RTP_GLUE_RESULT_LOCAL; } -static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active) +static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *cap, int nat_active) { /* XXX Is there such thing as video support with MGCP? XXX */ struct mgcp_subchannel *sub; sub = chan->tech_pvt; if (sub && !sub->alreadygone) { - transmit_modify_with_sdp(sub, rtp, codecs); + transmit_modify_with_sdp(sub, rtp, cap); return 0; } return -1; } -static format_t mgcp_get_codec(struct ast_channel *chan) +static void mgcp_get_codec(struct ast_channel *chan, struct ast_format_cap *result) { struct mgcp_subchannel *sub = chan->tech_pvt; struct mgcp_endpoint *p = sub->parent; - return p->capability; + ast_format_cap_copy(result, p->cap); } static struct ast_rtp_glue mgcp_rtp_glue = { @@ -4511,6 +4526,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); ast_free(e); } @@ -4608,7 +4624,7 @@ static int reload_config(int reload) char *cat; struct ast_hostent ahp; struct hostent *hp; - int format; + struct ast_format format; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; if (gethostname(ourhost, sizeof(ourhost)-1)) { @@ -4648,18 +4664,18 @@ static int reload_config(int reload) memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); } } else if (!strcasecmp(v->name, "allow")) { - format = ast_getformatbyname(v->value); - if (format < 1) { + ast_getformatbyname(v->value, &format); + if (!format.id) { ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); } else { - capability |= format; + ast_format_cap_add(global_capability, &format); } } else if (!strcasecmp(v->name, "disallow")) { - format = ast_getformatbyname(v->value); - if (format < 1) { - ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value); + ast_getformatbyname(v->value, &format); + if (!format.id) { + ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); } else { - capability &= ~format; + ast_format_cap_remove(global_capability, &format); } } else if (!strcasecmp(v->name, "tos")) { if (ast_str2tos(v->value, &qos.tos)) { @@ -4776,6 +4792,17 @@ static int reload_config(int reload) /*! \brief load_module: PBX load module - initialization ---*/ static int load_module(void) { + struct ast_format tmpfmt; + + if (!(global_capability = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } + if (!(mgcp_tech.capabilities = ast_format_cap_alloc())) { + 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)); if (!(sched = ast_sched_context_create())) { ast_log(LOG_WARNING, "Unable to create schedule context\n"); return AST_MODULE_LOAD_FAILURE; @@ -4907,6 +4934,9 @@ 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); + return 0; } diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 97eaba942..91bcf8703 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -90,6 +90,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/stringfields.h" #include "asterisk/abstract_jb.h" #include "asterisk/causes.h" +#include "asterisk/format.h" +#include "asterisk/format_cap.h" #include "chan_misdn_config.h" #include "isdn_lib.h" @@ -645,7 +647,7 @@ static int *misdn_ports; static void chan_misdn_log(int level, int port, char *tmpl, ...) __attribute__((format(printf, 3, 4))); -static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, const char *linkedid, int port, int c); +static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, struct ast_format_cap *cap, const char *linkedid, int port, int c); static void send_digit_to_chan(struct chan_list *cl, char digit); static int pbx_start_chan(struct chan_list *ch); @@ -661,7 +663,7 @@ static const char misdn_type[] = "mISDN"; static int tracing = 0; /*! \brief Only alaw and mulaw is allowed for now */ -static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */ +static struct ast_format prefformat; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */ static int *misdn_debug; static int *misdn_debug_only; @@ -7346,7 +7348,7 @@ static struct ast_frame *misdn_read(struct ast_channel *ast) } tmp->frame.frametype = AST_FRAME_VOICE; - tmp->frame.subclass.codec = AST_FORMAT_ALAW; + ast_format_set(&tmp->frame.subclass.format, AST_FORMAT_ALAW, 0); tmp->frame.datalen = len; tmp->frame.samples = len; tmp->frame.mallocd = 0; @@ -7412,13 +7414,13 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame) } - if (!frame->subclass.codec) { + if (!frame->subclass.format.id) { chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n"); return 0; } - if (!(frame->subclass.codec & prefformat)) { - chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(frame->subclass.codec)); + 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)); return 0; } @@ -7756,7 +7758,7 @@ static struct chan_list *chan_list_init(int orig) return cl; } -static struct ast_channel *misdn_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *misdn_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct ast_channel *ast; char group[BUFFERSIZE + 1] = ""; @@ -7982,7 +7984,7 @@ static struct ast_channel *misdn_request(const char *type, format_t format, cons } cl->bc = newbc; - ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, format, requestor ? requestor->linkedid : NULL, port, channel); + ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, cap, requestor ? requestor->linkedid : NULL, port, channel); if (!ast) { chan_list_unref(cl, "Failed to create a new channel"); ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str); @@ -8025,7 +8027,6 @@ static int misdn_send_text(struct ast_channel *chan, const char *text) static struct ast_channel_tech misdn_tech = { .type = misdn_type, .description = "Channel driver for mISDN Support (Bri/Pri)", - .capabilities = AST_FORMAT_ALAW , .requester = misdn_request, .send_digit_begin = misdn_digit_begin, .send_digit_end = misdn_digit_end, @@ -8044,7 +8045,6 @@ static struct ast_channel_tech misdn_tech = { static struct ast_channel_tech misdn_tech_wo_bridge = { .type = misdn_type, .description = "Channel driver for mISDN Support (Bri/Pri)", - .capabilities = AST_FORMAT_ALAW , .requester = misdn_request, .send_digit_begin = misdn_digit_begin, .send_digit_end = misdn_digit_end, @@ -8086,7 +8086,7 @@ 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, int format, const char *linkedid, 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 char *linkedid, int port, int c) { struct ast_channel *tmp; char *cid_name = NULL; @@ -8094,6 +8094,7 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char int chan_offset = 0; int tmp_port = misdn_cfg_get_next_port(0); int bridging; + struct ast_format tmpfmt; for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) { if (tmp_port == port) { @@ -8113,12 +8114,12 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char if (tmp) { chan_misdn_log(2, 0, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid); - tmp->nativeformats = prefformat; - - tmp->readformat = format; - tmp->rawreadformat = format; - tmp->writeformat = format; - tmp->rawwriteformat = format; + ast_best_codec(cap, &tmpfmt); + ast_format_cap_add(tmp->nativeformats, &prefformat); + ast_format_copy(&tmp->writeformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + ast_format_copy(&tmp->readformat, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); /* Link the channel and private together */ chan_list_ref(chlist, "Give a reference to ast_channel"); @@ -8128,8 +8129,6 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging)); tmp->tech = bridging ? &misdn_tech : &misdn_tech_wo_bridge; - tmp->writeformat = format; - tmp->readformat = format; tmp->priority = 1; if (exten) { @@ -10116,7 +10115,16 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ch->l3id = bc->l3_id; ch->addr = bc->addr; - chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, AST_FORMAT_ALAW, NULL, bc->port, bc->channel); + { + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + struct ast_format tmpfmt; + if (!(cap)) { + return RESPONSE_ERR; + } + ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, bc->port, bc->channel); + cap = ast_format_cap_destroy(cap); + } if (!chan) { chan_list_unref(ch, "Failed to create a new channel"); misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); @@ -10723,7 +10731,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 */ - frame.subclass.codec = AST_FORMAT_ALAW; + ast_format_set(&frame.subclass.format, AST_FORMAT_ALAW, 0); frame.datalen = bc->bframe_len; frame.samples = bc->bframe_len; frame.mallocd = 0; @@ -11145,6 +11153,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); + misdn_tech_wo_bridge.capabilities = ast_format_cap_destroy(misdn_tech_wo_bridge.capabilities); return 0; } @@ -11162,6 +11172,17 @@ static int load_module(void) .cb_jb_empty = chan_misdn_jb_empty, }; + + if (!(misdn_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(misdn_tech_wo_bridge.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_set(&prefformat, AST_FORMAT_ALAW, 0); + ast_format_cap_add(misdn_tech.capabilities, &prefformat); + ast_format_cap_add(misdn_tech_wo_bridge.capabilities, &prefformat); + max_ports = misdn_lib_maxports_get(); if (max_ports <= 0) { diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c index 55b757567..b398abb21 100644 --- a/channels/chan_multicast_rtp.c +++ b/channels/chan_multicast_rtp.c @@ -52,17 +52,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") static const char tdesc[] = "Multicast RTP Paging Channel Driver"; /* Forward declarations */ -static struct ast_channel *multicast_rtp_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *multicast_rtp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int multicast_rtp_call(struct ast_channel *ast, char *dest, int timeout); static int multicast_rtp_hangup(struct ast_channel *ast); static struct ast_frame *multicast_rtp_read(struct ast_channel *ast); static int multicast_rtp_write(struct ast_channel *ast, struct ast_frame *f); /* Channel driver declaration */ -static const struct ast_channel_tech multicast_rtp_tech = { +static struct ast_channel_tech multicast_rtp_tech = { .type = "MulticastRTP", .description = tdesc, - .capabilities = -1, .requester = multicast_rtp_request, .call = multicast_rtp_call, .hangup = multicast_rtp_hangup, @@ -107,14 +106,15 @@ static int multicast_rtp_hangup(struct ast_channel *ast) } /*! \brief Function called when we should prepare to call the destination */ -static struct ast_channel *multicast_rtp_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *multicast_rtp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { char *tmp = ast_strdupa(data), *multicast_type = tmp, *destination, *control; struct ast_rtp_instance *instance; struct ast_sockaddr control_address; struct ast_sockaddr destination_address; struct ast_channel *chan; - format_t fmt = ast_best_codec(format); + struct ast_format fmt; + ast_best_codec(cap, &fmt); ast_sockaddr_setnull(&control_address); @@ -153,11 +153,13 @@ static struct ast_channel *multicast_rtp_request(const char *type, format_t form ast_rtp_instance_set_remote_address(instance, &destination_address); chan->tech = &multicast_rtp_tech; - chan->nativeformats = fmt; - chan->writeformat = fmt; - chan->readformat = fmt; - chan->rawwriteformat = fmt; - chan->rawreadformat = fmt; + + ast_format_cap_add(chan->nativeformats, &fmt); + ast_format_copy(&chan->writeformat, &fmt); + ast_format_copy(&chan->rawwriteformat, &fmt); + ast_format_copy(&chan->readformat, &fmt); + ast_format_copy(&chan->rawreadformat, &fmt); + chan->tech_pvt = instance; return chan; @@ -170,6 +172,10 @@ failure: /*! \brief Function called when our module is loaded */ static int load_module(void) { + if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_add_all(multicast_rtp_tech.capabilities); if (ast_channel_register(&multicast_rtp_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n"); return AST_MODULE_LOAD_DECLINE; @@ -182,6 +188,7 @@ 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); return 0; } diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c index 882258f00..1cd3d75fb 100644 --- a/channels/chan_nbs.c +++ b/channels/chan_nbs.c @@ -50,7 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") static const char tdesc[] = "Network Broadcast Sound Driver"; /* Only linear is allowed */ -static format_t prefformat = AST_FORMAT_SLINEAR; +static struct ast_format prefformat; static char context[AST_MAX_EXTENSION] = "default"; static const char type[] = "NBS"; @@ -66,16 +66,15 @@ struct nbs_pvt { struct ast_module_user *u; /*! for holding a reference to this module */ }; -static struct ast_channel *nbs_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *nbs_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int nbs_call(struct ast_channel *ast, char *dest, int timeout); static int nbs_hangup(struct ast_channel *ast); static struct ast_frame *nbs_xread(struct ast_channel *ast); static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame); -static const struct ast_channel_tech nbs_tech = { +static struct ast_channel_tech nbs_tech = { .type = type, .description = tdesc, - .capabilities = AST_FORMAT_SLINEAR, .requester = nbs_request, .call = nbs_call, .hangup = nbs_hangup, @@ -205,9 +204,8 @@ static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame) ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); return 0; } - if (!(frame->subclass.codec & - (AST_FORMAT_SLINEAR))) { - ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); + 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->_state != AST_STATE_UP) { @@ -226,11 +224,12 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *lin if (tmp) { tmp->tech = &nbs_tech; ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs)); - tmp->nativeformats = prefformat; - tmp->rawreadformat = prefformat; - tmp->rawwriteformat = prefformat; - tmp->writeformat = prefformat; - tmp->readformat = prefformat; + + ast_format_cap_add(tmp->nativeformats, &prefformat); + ast_format_copy(&tmp->rawreadformat, &prefformat); + ast_format_copy(&tmp->rawwriteformat, &prefformat); + ast_format_copy(&tmp->writeformat, &prefformat); + ast_format_copy(&tmp->readformat, &prefformat); if (state == AST_STATE_RING) tmp->rings = 1; tmp->tech_pvt = i; @@ -251,16 +250,14 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *lin } -static struct ast_channel *nbs_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *nbs_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat; struct nbs_pvt *p; struct ast_channel *tmp = NULL; - - oldformat = format; - format &= (AST_FORMAT_SLINEAR); - if (!format) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname(oldformat)); + + 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)); return NULL; } p = nbs_alloc(data); @@ -276,11 +273,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); return 0; } static int load_module(void) { + ast_format_set(&prefformat, AST_FORMAT_SLINEAR, 0); + if (!(nbs_tech.capabilities == ast_format_cap_alloc())) { + return -1; + } + ast_format_cap_add(nbs_tech.capabilities, &prefformat); /* 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 3c4f2c943..10b0ed0fd 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -326,7 +326,7 @@ static struct chan_oss_pvt oss_default = { static int setformat(struct chan_oss_pvt *o, int mode); -static struct ast_channel *oss_request(const char *type, format_t format, const struct ast_channel *requestor, +static struct ast_channel *oss_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int oss_digit_begin(struct ast_channel *c, char digit); static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration); @@ -344,7 +344,6 @@ static char tdesc[] = "OSS Console Channel Driver"; static struct ast_channel_tech oss_tech = { .type = "Console", .description = tdesc, - .capabilities = AST_FORMAT_SLINEAR, /* overwritten later */ .requester = oss_request, .send_digit_begin = oss_digit_begin, .send_digit_end = oss_digit_end, @@ -719,7 +718,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; - f->subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&f->subclass.format, AST_FORMAT_SLINEAR, 0); f->samples = FRAME_SIZE; f->datalen = FRAME_SIZE * 2; f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET; @@ -794,13 +793,15 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx, if (o->sounddev < 0) setformat(o, O_RDWR); ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */ - c->nativeformats = AST_FORMAT_SLINEAR; + + ast_format_set(&c->readformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&c->writeformat, AST_FORMAT_SLINEAR, 0); + ast_format_cap_add(c->nativeformats, &c->readformat); + /* if the console makes the call, add video to the offer */ - if (state == AST_STATE_RINGING) - c->nativeformats |= console_video_formats; + /* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER + c->nativeformats |= console_video_formats; */ - c->readformat = AST_FORMAT_SLINEAR; - c->writeformat = AST_FORMAT_SLINEAR; c->tech_pvt = o; if (!ast_strlen_zero(o->language)) @@ -830,7 +831,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx, return c; } -static struct ast_channel *oss_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *oss_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct ast_channel *c; struct chan_oss_pvt *o; @@ -840,6 +841,7 @@ static struct ast_channel *oss_request(const char *type, format_t format, const ); char *parse = ast_strdupa(data); char buf[256]; + struct ast_format tmpfmt; AST_NONSTANDARD_APP_ARGS(args, parse, '/'); o = find_desc(args.name); @@ -850,8 +852,8 @@ static struct ast_channel *oss_request(const char *type, format_t format, const /* XXX we could default to 'dsp' perhaps ? */ return NULL; } - if ((format & AST_FORMAT_SLINEAR) == 0) { - ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), format)); + 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)); return NULL; } if (o->owner) { @@ -1437,6 +1439,7 @@ 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)); @@ -1463,7 +1466,13 @@ static int load_module(void) return AST_MODULE_LOAD_FAILURE; } - oss_tech.capabilities |= console_video_formats; + if (!(oss_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } + ast_format_cap_add(oss_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + + /* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER + * add console_video_formats to oss_tech.capabilities once this occurs. */ if (ast_channel_register(&oss_tech)) { ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n"); @@ -1495,6 +1504,7 @@ static int unload_module(void) ast_free(o); o = next; } + oss_tech.capabilities = ast_format_cap_destroy(oss_tech.capabilities); return 0; } diff --git a/channels/chan_phone.c b/channels/chan_phone.c index 531b95cb5..4897775cc 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -94,7 +94,7 @@ static int echocancel = AEC_OFF; static int silencesupression = 0; -static format_t prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW; +static struct ast_format_cap *prefcap; /* Protect the interface list (of phone_pvt's) */ AST_MUTEX_DEFINE_STATIC(iflock); @@ -125,8 +125,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 */ - format_t lastformat; /* Last output format */ - format_t 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 */ @@ -150,7 +150,7 @@ static struct phone_pvt { static char cid_num[AST_MAX_EXTENSION]; static char cid_name[AST_MAX_EXTENSION]; -static struct ast_channel *phone_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *phone_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int phone_digit_begin(struct ast_channel *ast, char digit); static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration); static int phone_call(struct ast_channel *ast, char *dest, int timeout); @@ -163,10 +163,9 @@ static int phone_send_text(struct ast_channel *ast, const char *text); static int phone_fixup(struct ast_channel *old, struct ast_channel *new); static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen); -static const struct ast_channel_tech phone_tech = { +static struct ast_channel_tech phone_tech = { .type = "Phone", .description = tdesc, - .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A, .requester = phone_request, .send_digit_begin = phone_digit_begin, .send_digit_end = phone_digit_end, @@ -210,9 +209,9 @@ 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); - p->lastformat = -1; - res = 0; - break; + ast_format_clear(&p->lastformat); + res = 0; + break; case AST_CONTROL_HOLD: ast_moh_start(chan, data, NULL); break; @@ -272,7 +271,7 @@ 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); - p->lastformat = -1; + ast_format_clear(&p->lastformat); return 0; default: ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit); @@ -280,7 +279,7 @@ 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); - p->lastformat = -1; + ast_format_clear(&p->lastformat); return 0; } @@ -373,8 +372,8 @@ static int phone_hangup(struct ast_channel *ast) ioctl(p->fd, PHONE_BUSY); p->cpt = 1; } - p->lastformat = -1; - p->lastinput = -1; + ast_format_clear(&p->lastformat); + ast_format_clear(&p->lastinput); p->ministate = 0; p->obuflen = 0; p->dialtone = 0; @@ -394,38 +393,38 @@ static int phone_setup(struct ast_channel *ast) p = ast->tech_pvt; ioctl(p->fd, PHONE_CPT_STOP); /* Nothing to answering really, just start recording */ - if (ast->rawreadformat == AST_FORMAT_G729A) { + if (ast->rawreadformat.id == AST_FORMAT_G729A) { /* Prefer g729 */ ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput != AST_FORMAT_G729A) { - p->lastinput = AST_FORMAT_G729A; + if (p->lastinput.id != AST_FORMAT_G729A) { + ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0); if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { ast_log(LOG_WARNING, "Failed to set codec to g729\n"); return -1; } } - } else if (ast->rawreadformat == AST_FORMAT_G723_1) { + } else if (ast->rawreadformat.id == AST_FORMAT_G723_1) { ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput != AST_FORMAT_G723_1) { - p->lastinput = AST_FORMAT_G723_1; + if (p->lastinput.id != AST_FORMAT_G723_1) { + ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0); 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->rawreadformat == AST_FORMAT_SLINEAR) { + } else if (ast->rawreadformat.id == AST_FORMAT_SLINEAR) { ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput != AST_FORMAT_SLINEAR) { - p->lastinput = AST_FORMAT_SLINEAR; + if (p->lastinput.id != AST_FORMAT_SLINEAR) { + ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0); 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->rawreadformat == AST_FORMAT_ULAW) { + } else if (ast->rawreadformat.id == AST_FORMAT_ULAW) { ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput != AST_FORMAT_ULAW) { - p->lastinput = AST_FORMAT_ULAW; + if (p->lastinput.id != AST_FORMAT_ULAW) { + ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0); if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) { ast_log(LOG_WARNING, "Failed to set codec to uLaw\n"); return -1; @@ -433,16 +432,16 @@ static int phone_setup(struct ast_channel *ast) } } else if (p->mode == MODE_FXS) { ioctl(p->fd, PHONE_REC_STOP); - if (p->lastinput != ast->rawreadformat) { - p->lastinput = ast->rawreadformat; - if (ioctl(p->fd, PHONE_REC_CODEC, ast->rawreadformat)) { + if (ast_format_cmp(&p->lastinput, &ast->rawreadformat) == AST_FORMAT_CMP_NOT_EQUAL) { + ast_format_copy(&p->lastinput, &ast->rawreadformat); + if (ioctl(p->fd, PHONE_REC_CODEC, &ast->rawreadformat)) { ast_log(LOG_WARNING, "Failed to set codec to %s\n", - ast_getformatname(ast->rawreadformat)); + ast_getformatname(&ast->rawreadformat)); return -1; } } } else { - ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast->rawreadformat)); + ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(&ast->rawreadformat)); return -1; } if (ioctl(p->fd, PHONE_REC_START)) { @@ -593,14 +592,13 @@ static struct ast_frame *phone_read(struct ast_channel *ast) } p->fr.samples = 240; p->fr.datalen = res; - p->fr.frametype = p->lastinput <= AST_FORMAT_AUDIO_MASK ? - AST_FRAME_VOICE : - p->lastinput <= AST_FORMAT_PNG ? AST_FRAME_IMAGE - : AST_FRAME_VIDEO; - p->fr.subclass.codec = p->lastinput; + 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 ? + AST_FRAME_IMAGE : AST_FRAME_VIDEO; + ast_format_copy(&p->fr.subclass.format, &p->lastinput); p->fr.offset = AST_FRIENDLY_OFFSET; /* Byteswap from little-endian to native-endian */ - if (p->fr.subclass.codec == AST_FORMAT_SLINEAR) + if (p->fr.subclass.format.id == AST_FORMAT_SLINEAR) ast_frame_byteswap_le(&p->fr); return &p->fr; } @@ -662,10 +660,12 @@ 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 '%d'\n", frame->frametype); return 0; } - if (!(frame->subclass.codec & - (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A)) && + 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.codec)); + ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format)); return -1; } #if 0 @@ -680,8 +680,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } #endif - if (frame->subclass.codec == AST_FORMAT_G729A) { - if (p->lastformat != AST_FORMAT_G729A) { + if (frame->subclass.format.id == AST_FORMAT_G729A) { + if (p->lastformat.id != AST_FORMAT_G729A) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) { @@ -692,8 +692,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; } - p->lastformat = AST_FORMAT_G729A; - p->lastinput = AST_FORMAT_G729A; + ast_format_set(&p->lastformat, AST_FORMAT_G729A, 0); + ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0); /* Reset output buffer */ p->obuflen = 0; codecset = 1; @@ -703,8 +703,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return -1; } maxfr = 80; - } else if (frame->subclass.codec == AST_FORMAT_G723_1) { - if (p->lastformat != AST_FORMAT_G723_1) { + } else if (frame->subclass.format.id == AST_FORMAT_G723_1) { + if (p->lastformat.id != AST_FORMAT_G723_1) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) { @@ -715,8 +715,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; } - p->lastformat = AST_FORMAT_G723_1; - p->lastinput = AST_FORMAT_G723_1; + ast_format_set(&p->lastformat, AST_FORMAT_G723_1, 0); + ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0); /* Reset output buffer */ p->obuflen = 0; codecset = 1; @@ -726,8 +726,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return -1; } maxfr = 24; - } else if (frame->subclass.codec == AST_FORMAT_SLINEAR) { - if (p->lastformat != AST_FORMAT_SLINEAR) { + } else if (frame->subclass.format.id == AST_FORMAT_SLINEAR) { + if (p->lastformat.id != AST_FORMAT_SLINEAR) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) { @@ -738,15 +738,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; } - p->lastformat = AST_FORMAT_SLINEAR; - p->lastinput = AST_FORMAT_SLINEAR; + ast_format_set(&p->lastformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0); codecset = 1; /* Reset output buffer */ p->obuflen = 0; } maxfr = 480; - } else if (frame->subclass.codec == AST_FORMAT_ULAW) { - if (p->lastformat != AST_FORMAT_ULAW) { + } else if (frame->subclass.format.id == AST_FORMAT_ULAW) { + if (p->lastformat.id != AST_FORMAT_ULAW) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) { @@ -757,29 +757,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; } - p->lastformat = AST_FORMAT_ULAW; - p->lastinput = AST_FORMAT_ULAW; + ast_format_set(&p->lastformat, AST_FORMAT_ULAW, 0); + ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0); codecset = 1; /* Reset output buffer */ p->obuflen = 0; } maxfr = 240; } else { - if (p->lastformat != frame->subclass.codec) { + if (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.codec)) { + if (ioctl(p->fd, PHONE_PLAY_CODEC, (int) frame->subclass.format.id)) { ast_log(LOG_WARNING, "Unable to set %s mode\n", - ast_getformatname(frame->subclass.codec)); + ast_getformatname(&frame->subclass.format)); return -1; } - if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.codec)) { + if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.format.id)) { ast_log(LOG_WARNING, "Unable to set %s mode\n", - ast_getformatname(frame->subclass.codec)); + ast_getformatname(&frame->subclass.format)); return -1; } - p->lastformat = frame->subclass.codec; - p->lastinput = frame->subclass.codec; + ast_format_copy(&p->lastformat, &frame->subclass.format); + ast_format_copy(&p->lastinput, &frame->subclass.format); codecset = 1; /* Reset output buffer */ p->obuflen = 0; @@ -850,6 +850,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, { struct ast_channel *tmp; struct phone_codec_data queried_codec; + struct ast_format tmpfmt; tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, linkedid, 0, "Phone/%s", i->dev + 5); if (tmp) { tmp->tech = cur_tech; @@ -857,22 +858,18 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, /* XXX Switching formats silently causes kernel panics XXX */ if (i->mode == MODE_FXS && ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) { - if (queried_codec.type == LINEAR16) - tmp->nativeformats = - tmp->rawreadformat = - tmp->rawwriteformat = - AST_FORMAT_SLINEAR; - else { - tmp->nativeformats = - tmp->rawreadformat = - tmp->rawwriteformat = - prefformat & ~AST_FORMAT_SLINEAR; + if (queried_codec.type == LINEAR16) { + ast_format_cap_add(tmp->nativeformats, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + } else { + ast_format_cap_remove(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); } - } - else { - tmp->nativeformats = prefformat; - tmp->rawreadformat = prefformat; - tmp->rawwriteformat = prefformat; + } else { + ast_format_cap_copy(tmp->nativeformats, prefcap); + ast_best_codec(tmp->nativeformats, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); } /* no need to call ast_setstate: the channel_alloc already did its job */ if (state == AST_STATE_RING) @@ -981,7 +978,7 @@ 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); - i->lastformat = -1; + ast_format_clear(&i->lastformat); } else if (i->mode == MODE_SIGMA) { ast_module_ref(ast_module_info->self); /* Reset the extension */ @@ -1002,7 +999,7 @@ static void phone_check_exception(struct phone_pvt *i) ioctl(i->fd, PHONE_PLAY_STOP); ioctl(i->fd, PHONE_REC_STOP); i->dialtone = 0; - i->lastformat = -1; + ast_format_clear(&i->lastformat); } } if (phonee.bits.pstn_ring) { @@ -1214,8 +1211,8 @@ 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; - tmp->lastformat = -1; - tmp->lastinput = -1; + ast_format_clear(&tmp->lastformat); + ast_format_clear(&tmp->lastinput); tmp->ministate = 0; memset(tmp->ext, 0, sizeof(tmp->ext)); ast_copy_string(tmp->language, language, sizeof(tmp->language)); @@ -1235,9 +1232,8 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai return tmp; } -static struct ast_channel *phone_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *phone_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat; struct phone_pvt *p; struct ast_channel *tmp = NULL; char *name = data; @@ -1249,9 +1245,8 @@ static struct ast_channel *phone_request(const char *type, format_t format, cons } p = iflist; while(p) { - if (p->mode == MODE_FXS || - format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) { - size_t length = strlen(p->dev + 5); + if (p->mode == MODE_FXS || (ast_format_cap_has_joint(cap, phone_tech.capabilities))) { + size_t length = strlen(p->dev + 5); if (strncmp(name, p->dev + 5, length) == 0 && !isalnum(name[length])) { if (!p->owner) { @@ -1266,11 +1261,9 @@ static struct ast_channel *phone_request(const char *type, format_t format, cons ast_mutex_unlock(&iflock); restart_monitor(); if (tmp == NULL) { - oldformat = format; - format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW); - if (!format) { + 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), oldformat)); + ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); return NULL; } } @@ -1352,7 +1345,10 @@ static int __unload_module(void) ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 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); return 0; } @@ -1369,6 +1365,23 @@ 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())) { + 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())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_copy(prefcap, phone_tech.capabilities); + if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) { ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); @@ -1416,7 +1429,7 @@ static int load_module(void) mode = MODE_IMMEDIATE; else if (!strncasecmp(v->value, "fxs", 3)) { mode = MODE_FXS; - prefformat = 0x01ff0000; /* All non-voice */ + ast_format_cap_remove_bytype(prefcap, AST_FORMAT_TYPE_AUDIO); /* All non-voice */ } else if (!strncasecmp(v->value, "fx", 2)) mode = MODE_FXO; @@ -1425,16 +1438,20 @@ static int load_module(void) } else if (!strcasecmp(v->name, "context")) { ast_copy_string(context, v->value, sizeof(context)); } else if (!strcasecmp(v->name, "format")) { + struct ast_format tmpfmt; if (!strcasecmp(v->value, "g729")) { - prefformat = AST_FORMAT_G729A; - } else if (!strcasecmp(v->value, "g723.1")) { - prefformat = AST_FORMAT_G723_1; + ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0)); + } else if (!strcasecmp(v->value, "g723.1")) { + ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0)); } else if (!strcasecmp(v->value, "slinear")) { - if (mode == MODE_FXS) - prefformat |= AST_FORMAT_SLINEAR; - else prefformat = AST_FORMAT_SLINEAR; + ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0); + if (mode == MODE_FXS) { + ast_format_cap_add(prefcap, &tmpfmt); + } else { + ast_format_cap_set(prefcap, &tmpfmt); + } } else if (!strcasecmp(v->value, "ulaw")) { - prefformat = AST_FORMAT_ULAW; + ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); } else ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); } else if (!strcasecmp(v->name, "echocancel")) { @@ -1458,7 +1475,7 @@ static int load_module(void) ast_mutex_unlock(&iflock); if (mode == MODE_FXS) { - phone_tech_fxs.capabilities = prefformat; + ast_format_cap_copy(phone_tech_fxs.capabilities, prefcap); cur_tech = &phone_tech_fxs; } else cur_tech = (struct ast_channel_tech *) &phone_tech; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index d5ee01345..e80f387cc 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1199,7 +1199,7 @@ static struct ast_config *notify_types = NULL; /*!< The list of manual NOTIFY in coming releases. */ /*--- PBX interface functions */ -static struct ast_channel *sip_request_call(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *sip_request_call(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int sip_devicestate(void *data); static int sip_sendtext(struct ast_channel *ast, const char *text); static int sip_call(struct ast_channel *ast, char *dest, int timeout); @@ -1291,7 +1291,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec); static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec); static int process_sdp_a_image(const char *a, struct sip_pvt *p); -static void add_codec_to_sdp(const struct sip_pvt *p, format_t codec, +static void add_codec_to_sdp(const struct sip_pvt *p, struct ast_format *codec, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size); static void add_noncodec_to_sdp(const struct sip_pvt *p, int format, @@ -1565,7 +1565,7 @@ static enum st_mode st_get_mode(struct sip_pvt *); static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p); /*------- RTP Glue functions -------- */ -static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, format_t codecs, int nat_active); +static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active); /*!--- SIP MWI Subscription support */ static int sip_subscribe_mwi(const char *value, int lineno); @@ -1575,10 +1575,9 @@ static int sip_subscribe_mwi_do(const void *data); static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi); /*! \brief Definition of this channel for PBX channel registration */ -const struct ast_channel_tech sip_tech = { +struct ast_channel_tech sip_tech = { .type = "SIP", .description = "Session Initiation Protocol (SIP)", - .capabilities = AST_FORMAT_AUDIO_MASK, /* all audio formats */ .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, .requester = sip_request_call, /* called with chan unlocked */ .devicestate = sip_devicestate, /* called with chan unlocked (not chan-specific) */ @@ -4038,10 +4037,10 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d switch (option) { case AST_OPTION_FORMAT_READ: - res = ast_rtp_instance_set_read_format(p->rtp, *(int *) data); + res = ast_rtp_instance_set_read_format(p->rtp, (struct ast_format *) data); break; case AST_OPTION_FORMAT_WRITE: - res = ast_rtp_instance_set_write_format(p->rtp, *(int *) data); + res = ast_rtp_instance_set_write_format(p->rtp, (struct ast_format *) data); break; case AST_OPTION_MAKE_COMPATIBLE: res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data); @@ -4385,6 +4384,8 @@ static void sip_destroy_peer(struct sip_peer *peer) ast_cc_config_params_destroy(peer->cc_params); ast_string_field_free_memory(peer); + + peer->caps = ast_format_cap_destroy(peer->caps); } /*! \brief Update peer data in database (if used) */ @@ -4826,7 +4827,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) && (dialog->capability & AST_FORMAT_VIDEO_MASK))) { + (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) { if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { return -1; } @@ -4887,7 +4888,7 @@ 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); - dialog->capability = peer->capability; + ast_format_cap_append(dialog->caps, peer->caps); dialog->prefs = peer->prefs; if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) { /* t38pt_udptl was enabled in the peer and not in [general] */ @@ -5253,11 +5254,11 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout) return res; } p->callingpres = ast_party_id_presentation(&ast->caller.id); - p->jointcapability = ast_rtp_instance_available_formats(p->rtp, p->capability, p->prefcodec); + ast_rtp_instance_available_formats(p->rtp, p->caps, p->prefcaps, p->jointcaps); p->jointnoncodeccapability = p->noncodeccapability; /* If there are no audio formats left to offer, punt */ - if (!(p->jointcapability & AST_FORMAT_AUDIO_MASK)) { + if (!(ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO))) { ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username); res = -1; } else { @@ -5463,6 +5464,11 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) ao2_ref(p->socket.tcptls_session, -1); p->socket.tcptls_session = NULL; } + 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); } /*! \brief update_call_counter: Handle call_limit for SIP devices @@ -6025,9 +6031,11 @@ static int sip_hangup(struct ast_channel *ast) /*! \brief Try setting codec suggested by the SIP_CODEC channel variable */ static void try_suggested_sip_codec(struct sip_pvt *p) { - format_t fmt; + struct ast_format fmt; const char *codec; + ast_format_clear(&fmt); + if (p->outgoing_call) { codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC_OUTBOUND"); } else if (!(codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC_INBOUND"))) { @@ -6037,12 +6045,12 @@ static void try_suggested_sip_codec(struct sip_pvt *p) if (!codec) return; - fmt = ast_getformatbyname(codec); - if (fmt) { + ast_getformatbyname(codec, &fmt); + if (fmt.id) { ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC} variable\n", codec); - if (p->jointcapability & fmt) { - p->jointcapability &= fmt; - p->capability &= fmt; + if (ast_format_cap_iscompatible(p->jointcaps, &fmt)) { + ast_format_cap_set(p->jointcaps, &fmt); + ast_format_cap_set(p->caps, &fmt); } else ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because it is not shared by both ends.\n"); } else @@ -6079,13 +6087,13 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame) switch (frame->frametype) { case AST_FRAME_VOICE: - if (!(frame->subclass.codec & ast->nativeformats)) { - char s1[512], s2[512], s3[512]; + if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { + char s1[512]; ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s read/write = %s/%s\n", - ast_getformatname(frame->subclass.codec), - ast_getformatname_multiple(s1, sizeof(s1), ast->nativeformats & AST_FORMAT_AUDIO_MASK), - ast_getformatname_multiple(s2, sizeof(s2), ast->readformat), - ast_getformatname_multiple(s3, sizeof(s3), ast->writeformat)); + ast_getformatname(&frame->subclass.format), + ast_getformatname_multiple(s1, sizeof(s1), ast->nativeformats), + ast_getformatname(&ast->readformat), + ast_getformatname(&ast->writeformat)); return 0; } if (p) { @@ -6538,11 +6546,9 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit { struct ast_channel *tmp; struct ast_variable *v = NULL; - format_t fmt; - format_t what; - format_t video; - format_t text; - format_t needvideo = 0; + struct ast_format fmt; + struct ast_format_cap *what = NULL; /* SHALLOW COPY DO NOT DESTROY! */ + int needvideo = 0; int needtext = 0; char buf[SIPBUFSIZE]; char *decoded_exten; @@ -6575,51 +6581,47 @@ 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 (i->jointcapability) { /* The joint capabilities of us and peer */ - what = i->jointcapability; - video = i->jointcapability & AST_FORMAT_VIDEO_MASK; - text = i->jointcapability & AST_FORMAT_TEXT_MASK; - } else if (i->capability) { /* Our configured capability for this peer */ - what = i->capability; - video = i->capability & AST_FORMAT_VIDEO_MASK; - text = i->capability & AST_FORMAT_TEXT_MASK; + if (!(ast_format_cap_is_empty(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 */ + what = i->caps; } else { - what = sip_cfg.capability; /* Global codec support */ - video = sip_cfg.capability & AST_FORMAT_VIDEO_MASK; - text = sip_cfg.capability & AST_FORMAT_TEXT_MASK; + what = sip_cfg.caps; } - /* Set the native formats for audio and merge in video */ - tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text; + /* Set the native formats */ + ast_format_cap_copy(tmp->nativeformats, what); + /* choose and use only the best audio format for our native formats */ + ast_codec_choose(&i->prefs, tmp->nativeformats, 1, &fmt); /* get the best audio format */ + ast_format_cap_remove_bytype(tmp->nativeformats, AST_FORMAT_TYPE_AUDIO); /* remove only the other audio formats */ + ast_format_cap_add(tmp->nativeformats, &fmt); /* add our best choice back */ + ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmp->nativeformats)); - ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcapability)); - ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->capability)); - ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_codec_choose(&i->prefs, what, 1))); - if (i->prefcodec) { - ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcodec)); + 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)); } - /* XXX Why are we choosing a codec from the native formats?? */ - fmt = ast_best_codec(tmp->nativeformats); - /* If we have a prefcodec setting, we have an inbound channel that set a preferred format for this call. Otherwise, we check the jointcapability We also check for vrtp. If it's not there, we are not allowed do any video anyway. */ if (i->vrtp) { if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT)) - needvideo = AST_FORMAT_VIDEO_MASK; - else if (i->prefcodec) - needvideo = i->prefcodec & AST_FORMAT_VIDEO_MASK; /* Outbound call */ + 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 - needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK; /* Inbound call */ + needvideo = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_VIDEO); /* Inbound call */ } if (i->trtp) { - if (i->prefcodec) - needtext = i->prefcodec & AST_FORMAT_TEXT_MASK; /* Outbound call */ + if (!ast_format_cap_is_empty(i->prefcaps)) + needtext = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_TEXT); /* Outbound call */ else - needtext = i->jointcapability & AST_FORMAT_TEXT_MASK; /* Inbound call */ + needtext = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_TEXT); /* Inbound call */ } if (needvideo) { @@ -6662,13 +6664,13 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit } tmp->adsicpe = AST_ADSI_UNAVAILABLE; - tmp->writeformat = fmt; - tmp->rawwriteformat = fmt; - ast_rtp_instance_set_write_format(i->rtp, fmt); + ast_format_copy(&tmp->writeformat, &fmt); + ast_format_copy(&tmp->rawwriteformat, &fmt); + ast_rtp_instance_set_write_format(i->rtp, &fmt); - tmp->readformat = fmt; - tmp->rawreadformat = fmt; - ast_rtp_instance_set_read_format(i->rtp, fmt); + ast_format_copy(&tmp->readformat, &fmt); + ast_format_copy(&tmp->rawreadformat, &fmt); + ast_rtp_instance_set_read_format(i->rtp, &fmt); tmp->tech_pvt = dialog_ref(i, "sip_new: set chan->tech_pvt to i"); @@ -6976,17 +6978,18 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p return f; } - if (f && f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { - if (!(f->subclass.codec & p->jointcapability)) { + if (f && !ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format)) { + if (!ast_format_cap_iscompatible(p->jointcaps, &f->subclass.format)) { ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n", - ast_getformatname(f->subclass.codec), p->owner->name); + ast_getformatname(&f->subclass.format), p->owner->name); return &ast_null_frame; } ast_debug(1, "Oooh, format changed to %s\n", - ast_getformatname(f->subclass.codec)); - p->owner->nativeformats = (p->owner->nativeformats & (AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK)) | f->subclass.codec; - ast_set_read_format(p->owner, p->owner->readformat); - ast_set_write_format(p->owner, p->owner->writeformat); + ast_getformatname(&f->subclass.format)); + ast_format_cap_remove_bytype(p->owner->nativeformats, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_add(p->owner->nativeformats, &f->subclass.format); + ast_set_read_format(p->owner, &p->owner->readformat); + ast_set_write_format(p->owner, &p->owner->writeformat); } if (f && p->dsp) { @@ -7149,6 +7152,22 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr, ao2_t_ref(p, -1, "Yuck, couldn't allocate cc_params struct. Get rid o' p"); return NULL; } + p->caps = ast_format_cap_alloc_nolock(); + p->jointcaps = ast_format_cap_alloc_nolock(); + p->peercaps = ast_format_cap_alloc_nolock(); + p->redircaps = ast_format_cap_alloc_nolock(); + p->prefcaps = ast_format_cap_alloc_nolock(); + + 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); + ao2_t_ref(p, -1, "Yuck, couldn't allocate cc_params struct. Get rid o' p"); + return NULL; + } + /* If this dialog is created as a result of a request or response, lets store * some information about it in the dialog. */ @@ -7255,7 +7274,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); - p->capability = sip_cfg.capability; + ast_format_cap_append(p->caps, sip_cfg.caps); 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)) @@ -8262,6 +8281,8 @@ static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_ty */ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action) { + int res = 0; + /* Iterators for SDP parsing */ int start = req->sdp_start; int next = start; @@ -8284,18 +8305,21 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action struct ast_sockaddr *vsa = NULL; /*!< RTP video host IP */ struct ast_sockaddr *tsa = NULL; /*!< RTP text host IP */ struct ast_sockaddr *isa = NULL; /*!< UDPTL host ip */ - int portno = -1; /*!< RTP Audio port number */ - int vportno = -1; /*!< RTP Video port number */ + int portno = -1; /*!< RTP Audio port number */ + int vportno = -1; /*!< RTP Video port number */ int tportno = -1; /*!< RTP Text port number */ int udptlportno = -1; /*!< UDPTL Image port number */ /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ - format_t peercapability = 0, vpeercapability = 0, tpeercapability = 0; + struct ast_format_cap *peercapability = ast_format_cap_alloc_nolock(); + struct ast_format_cap *vpeercapability = ast_format_cap_alloc_nolock(); + struct ast_format_cap *tpeercapability = ast_format_cap_alloc_nolock(); + int peernoncodeccapability = 0, vpeernoncodeccapability = 0, tpeernoncodeccapability = 0; struct ast_rtp_codecs newaudiortp, newvideortp, newtextrtp; - format_t newjointcapability; /* Negotiated capability */ - format_t newpeercapability; + struct ast_format_cap *newjointcapability = ast_format_cap_alloc_nolock(); /* Negotiated capability */ + struct ast_format_cap *newpeercapability = ast_format_cap_alloc_nolock(); int newnoncodeccapability; const char *codecs; @@ -8318,12 +8342,18 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action /* START UNKNOWN */ char buf[SIPBUFSIZE]; + struct ast_format tmp_fmt; /* END UNKNOWN */ /* Initial check */ if (!p->rtp) { ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n"); - return -1; + res = -1; + goto process_sdp_cleanup; + } + if (!peercapability || !vpeercapability || !tpeercapability || !newpeercapability || !newjointcapability) { + res = -1; + goto process_sdp_cleanup; } /* Make sure that the codec structures are all cleared out */ @@ -8353,7 +8383,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action nextm = get_sdp_iterate(&next, req, "m"); if (ast_strlen_zero(nextm)) { ast_log(LOG_WARNING, "Insufficient information for SDP (m= not found)\n"); - return -1; + res = -1; + goto process_sdp_cleanup; } /* Scan session level SDP parameters (lines before first media stream) */ @@ -8364,8 +8395,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action /* If we end up receiving SDP that doesn't actually modify the session we don't want to treat this as a fatal * error. We just want to ignore the SDP and let the rest of the packet be handled as normal. */ - if (!process_sdp_o(value, p)) - return (p->session_modify == FALSE) ? 0 : -1; + if (!process_sdp_o(value, p)) { + res = (p->session_modify == FALSE) ? 0 : -1; + goto process_sdp_cleanup; + } break; case 'c': if (process_sdp_c(value, &sessionsa)) { @@ -8433,7 +8466,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); - return -1; + res = -1; + goto process_sdp_cleanup; } if (debug) ast_verbose("Found RTP audio format %d\n", codec); @@ -8461,7 +8495,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); - return -1; + res = -1; + goto process_sdp_cleanup; } if (debug) ast_verbose("Found RTP video format %d\n", codec); @@ -8482,7 +8517,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); - return -1; + res = -1; + goto process_sdp_cleanup; } if (debug) ast_verbose("Found RTP text format %d\n", codec); @@ -8587,45 +8623,53 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action /* Sanity checks */ if (!sa && !vsa && !tsa && !isa) { ast_log(LOG_WARNING, "Insufficient information in SDP (c=)...\n"); - return -1; + res = -1; + goto process_sdp_cleanup; } if (portno == -1 && vportno == -1 && udptlportno == -1 && tportno == -1) { /* No acceptable offer found in SDP - we have no ports */ /* Do not change RTP or VRTP if this is a re-invite */ ast_log(LOG_WARNING, "Failing due to no acceptable offer found\n"); - return -2; + res = -2; + goto process_sdp_cleanup; } if (numberofmediastreams > 3) { /* We have too many fax, audio and/or video and/or text media streams, fail this offer */ ast_log(LOG_WARNING, "Faling due to too many media streams\n"); - return -3; + res = -3; + goto process_sdp_cleanup; } if (secure_audio && !(p->srtp && (ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)))) { ast_log(LOG_WARNING, "Can't provide secure audio requested in SDP offer\n"); - return -4; + res = -4; + goto process_sdp_cleanup; } if (!secure_audio && p->srtp) { ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n"); - return -4; + res = -4; + goto process_sdp_cleanup; } if (secure_video && !(p->vsrtp && (ast_test_flag(p->vsrtp, SRTP_CRYPTO_OFFER_OK)))) { ast_log(LOG_WARNING, "Can't provide secure video requested in SDP offer\n"); - return -4; + res = -4; + goto process_sdp_cleanup; } if (!p->novideo && !secure_video && p->vsrtp) { ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n"); - return -4; + res = -4; + goto process_sdp_cleanup; } if (!(secure_audio || secure_video) && ast_test_flag(&p->flags[1], SIP_PAGE2_USE_SRTP)) { ast_log(LOG_WARNING, "Matched device setup to use SRTP, but request was not!\n"); - return -4; + res = -4; + goto process_sdp_cleanup; } if (udptlportno == -1) { @@ -8633,12 +8677,22 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action } /* Now gather all of the codecs that we are asked for: */ - ast_rtp_codecs_payload_formats(&newaudiortp, &peercapability, &peernoncodeccapability); - ast_rtp_codecs_payload_formats(&newvideortp, &vpeercapability, &vpeernoncodeccapability); - ast_rtp_codecs_payload_formats(&newtextrtp, &tpeercapability, &tpeernoncodeccapability); + ast_rtp_codecs_payload_formats(&newaudiortp, peercapability, &peernoncodeccapability); + 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_joint_copy(p->caps, newpeercapability, newjointcapability); + if (ast_format_cap_is_empty(newjointcapability) && (portno != -1)) { + ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); + /* Do NOT Change current setting */ + res = -1; + goto process_sdp_cleanup; + } - newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability); - newpeercapability = (peercapability | vpeercapability | tpeercapability); newnoncodeccapability = p->noncodeccapability & peernoncodeccapability; if (debug) { @@ -8646,7 +8700,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE]; ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n", - ast_getformatname_multiple(s1, SIPBUFSIZE, p->capability), + 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), @@ -8658,14 +8712,9 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action struct ast_str *s3 = ast_str_alloca(SIPBUFSIZE); ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n", - ast_rtp_lookup_mime_multiple2(s1, p->noncodeccapability, 0, 0), - ast_rtp_lookup_mime_multiple2(s2, peernoncodeccapability, 0, 0), - ast_rtp_lookup_mime_multiple2(s3, newnoncodeccapability, 0, 0)); - } - if (!newjointcapability && (portno != -1)) { - ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); - /* Do NOT Change current setting */ - return -1; + ast_rtp_lookup_mime_multiple2(s1, NULL, p->noncodeccapability, 0, 0), + ast_rtp_lookup_mime_multiple2(s2, NULL, peernoncodeccapability, 0, 0), + ast_rtp_lookup_mime_multiple2(s3, NULL, newnoncodeccapability, 0, 0)); } /* Setup audio address and port */ @@ -8679,12 +8728,13 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action } /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since they are acceptable */ - p->jointcapability = newjointcapability; /* Our joint codec profile for this call */ - p->peercapability = newpeercapability; /* The other sides capability in latest offer */ + ast_format_cap_copy(p->jointcaps, newjointcapability); /* Our joint codec profile for this call */ + ast_format_cap_copy(p->peercaps, newpeercapability); /* The other sides capability in latest offer */ p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { /* respond with single most preferred joint codec, limiting the other side's choice */ - p->jointcapability = ast_codec_choose(&p->prefs, p->jointcapability, 1); + ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt); + ast_format_cap_set(p->jointcaps, &tmp_fmt); } ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp); @@ -8737,7 +8787,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 ((p->jointcapability & AST_FORMAT_T140RED)) { + if (ast_format_cap_iscompatible(p->jointcaps, ast_format_set(&tmp_fmt, AST_FORMAT_T140RED, 0))) { p->red = 1; ast_rtp_red_init(p->trtp, 300, red_data_pt, 2); } else { @@ -8807,27 +8857,36 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action if ((portno == -1) && (p->t38.state != T38_DISABLED)) { ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n"); - return 0; - } + res = 0; + goto process_sdp_cleanup; + } /* Ok, we're going with this offer */ - ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcapability)); + ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcaps)); - if (!p->owner) /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */ - return 0; + 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; + goto process_sdp_cleanup; + } ast_debug(4, "We have an owner, now see if we need to change this call\n"); - if (!(p->owner->nativeformats & p->jointcapability) && (p->jointcapability & AST_FORMAT_AUDIO_MASK)) { + if (!(ast_format_cap_has_joint(p->owner->nativeformats, p->jointcaps)) && ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO)) { if (debug) { char s1[SIPBUFSIZE], s2[SIPBUFSIZE]; ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n", - ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability), + ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcaps), ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats)); } - p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability); - ast_set_read_format(p->owner, p->owner->readformat); - ast_set_write_format(p->owner, p->owner->writeformat); + + ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt); + + ast_format_cap_set(p->owner->nativeformats, &tmp_fmt); + ast_format_cap_joint_copy(p->caps, vpeercapability, p->owner->nativeformats); + ast_format_cap_joint_copy(p->caps, tpeercapability, p->owner->nativeformats); + + ast_set_read_format(p->owner, &p->owner->readformat); + ast_set_write_format(p->owner, &p->owner->writeformat); } if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && (!ast_sockaddr_isnull(sa) || !ast_sockaddr_isnull(vsa) || !ast_sockaddr_isnull(tsa) || !ast_sockaddr_isnull(isa)) && (!sendonly || sendonly == -1)) { @@ -8846,8 +8905,14 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_queue_frame(p->owner, &ast_null_frame); change_hold_state(p, req, TRUE, sendonly); } - - return 0; + +process_sdp_cleanup: + 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); + return res; } static int process_sdp_o(const char *o, struct sip_pvt *p) @@ -9001,10 +9066,10 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ 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 || !format.code) /* non-codec or not found */ + if (!format.asterisk_format) /* non-codec or not found */ continue; - ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(format.code), framing); - ast_codec_pref_setsize(pref, format.code, framing); + 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); } @@ -9032,10 +9097,10 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_ struct ast_rtp_payload_type payload; payload = ast_rtp_codecs_payload_lookup(newaudiortp, codec); - if (payload.code && payload.asterisk_format) { + if (payload.format.id && payload.asterisk_format) { unsigned int bit_rate; - switch (payload.code) { + switch ((int) payload.format.id) { case AST_FORMAT_SIREN7: if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) { if (bit_rate != 32000) { @@ -10373,31 +10438,34 @@ static int add_vidupdate(struct sip_request *req) } /*! \brief Add codec offer to SDP offer/answer body in INVITE or 200 OK */ -static void add_codec_to_sdp(const struct sip_pvt *p, format_t codec, - struct ast_str **m_buf, struct ast_str **a_buf, - int debug, int *min_packet_size) +static void add_codec_to_sdp(const struct sip_pvt *p, + struct ast_format *format, + struct ast_str **m_buf, + struct ast_str **a_buf, + int debug, + int *min_packet_size) { int rtp_code; struct ast_format_list fmt; if (debug) - ast_verbose("Adding codec 0x%" PRIx64 " (%s) to SDP\n", codec, ast_getformatname(codec)); - if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, codec)) == -1) + ast_verbose("Adding codec %d (%s) to SDP\n", format->id, ast_getformatname(format)); + if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, format, 0)) == -1) return; if (p->rtp) { struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref; - fmt = ast_codec_pref_getsize(pref, codec); + 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); - ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, - ast_rtp_lookup_mime_subtype2(1, codec, - ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0), - ast_rtp_lookup_sample_rate2(1, codec)); + ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", + rtp_code, + ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0), + ast_rtp_lookup_sample_rate2(1, format, 0)); - switch (codec) { + switch ((int) format->id) { case AST_FORMAT_G729A: /* 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); @@ -10434,7 +10502,7 @@ static void add_codec_to_sdp(const struct sip_pvt *p, format_t codec, /*! \brief Add video codec offer to SDP offer/answer body in INVITE or 200 OK */ /* This is different to the audio one now so we can add more caps later */ -static void add_vcodec_to_sdp(const struct sip_pvt *p, format_t codec, +static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size) { @@ -10444,20 +10512,20 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, format_t codec, return; if (debug) - ast_verbose("Adding video codec 0x%" PRIx64 " (%s) to SDP\n", codec, ast_getformatname(codec)); + ast_verbose("Adding video codec %d (%s) to SDP\n", format->id, ast_getformatname(format)); - if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, codec)) == -1) + if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, format, 0)) == -1) return; ast_str_append(m_buf, 0, " %d", rtp_code); ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, - ast_rtp_lookup_mime_subtype2(1, codec, 0), - ast_rtp_lookup_sample_rate2(1, codec)); + ast_rtp_lookup_mime_subtype2(1, format, 0, 0), + ast_rtp_lookup_sample_rate2(1, format, 0)); /* Add fmtp code here */ } /*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */ -static void add_tcodec_to_sdp(const struct sip_pvt *p, int codec, +static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size) { @@ -10467,19 +10535,20 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, int codec, return; if (debug) - ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); + ast_verbose("Adding text codec %d (%s) to SDP\n", format->id, ast_getformatname(format)); - if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, codec)) == -1) + if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, format, 0)) == -1) return; ast_str_append(m_buf, 0, " %d", rtp_code); ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, - ast_rtp_lookup_mime_subtype2(1, codec, 0), - ast_rtp_lookup_sample_rate2(1, codec)); + ast_rtp_lookup_mime_subtype2(1, format, 0, 0), + ast_rtp_lookup_sample_rate2(1, format, 0)); /* Add fmtp code here */ - if (codec == AST_FORMAT_T140RED) { - int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, AST_FORMAT_T140); + 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); ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code, t140code, t140code, @@ -10518,14 +10587,14 @@ static void add_noncodec_to_sdp(const struct sip_pvt *p, int format, int rtp_code; if (debug) - ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, format, 0)); - if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, format)) == -1) + ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, NULL, format, 0)); + if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, NULL, format)) == -1) return; ast_str_append(m_buf, 0, " %d", rtp_code); ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, - ast_rtp_lookup_mime_subtype2(0, format, 0), - ast_rtp_lookup_sample_rate2(0, format)); + ast_rtp_lookup_mime_subtype2(0, NULL, format, 0), + ast_rtp_lookup_sample_rate2(0, NULL, format)); if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */ ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code); } @@ -10651,9 +10720,10 @@ static void get_crypto_attrib(struct sip_srtp *srtp, const char **a_crypto) */ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38) { - format_t alreadysent = 0; + struct ast_format_cap *alreadysent = ast_format_cap_alloc_nolock(); + struct ast_format_cap *tmpcap = ast_format_cap_alloc_nolock(); + int res = AST_SUCCESS; int doing_directmedia = FALSE; - struct ast_sockaddr addr = { {0,} }; struct ast_sockaddr vaddr = { {0,} }; struct ast_sockaddr taddr = { {0,} }; @@ -10683,8 +10753,8 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int const char *v_a_crypto = NULL; const char *t_a_crypto = NULL; - format_t x; - format_t capability = 0; + int x; + struct ast_format tmp_fmt; int needaudio = FALSE; int needvideo = FALSE; int needtext = FALSE; @@ -10700,9 +10770,15 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int /* Set the SDP session name */ snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); + if (!alreadysent || !tmpcap) { + res = AST_FAILURE; + goto add_sdp_cleanup; + } if (!p->rtp) { ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); - return AST_FAILURE; + res = AST_FAILURE; + goto add_sdp_cleanup; + } /* XXX We should not change properties in the SIP dialog until we have acceptance of the offer if this is a re-invite */ @@ -10717,9 +10793,9 @@ 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) && p->redircodecs) ? TRUE : FALSE; + doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && !(ast_format_cap_is_empty(p->redircaps))) ? TRUE : FALSE; /* Check if we need video in this call */ - if ((p->jointcapability & AST_FORMAT_VIDEO_MASK) && !p->novideo) { + if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_VIDEO)) && !p->novideo) { if (p->vrtp) { needvideo = TRUE; ast_debug(2, "This call needs video offers!\n"); @@ -10727,7 +10803,7 @@ 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 ((p->jointcapability & AST_FORMAT_TEXT_MASK) && !p->notext) { + if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_TEXT)) && !p->notext) { if (sipdebug_text) ast_verbose("We think we can do text\n"); if (p->trtp) { @@ -10767,20 +10843,20 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int hold = "a=sendrecv\r\n"; } - capability = p->jointcapability; + 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), capability), + 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->prefcodec)); + ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcaps)); if (doing_directmedia) { - capability &= p->redircodecs; - ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability)); + 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 (capability & AST_FORMAT_AUDIO_MASK) + if (ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_AUDIO)) needaudio = TRUE; if (debug) { @@ -10833,45 +10909,55 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int /* Prefer the audio codec we were requested to use, first, no matter what Note that p->prefcodec can include video codecs, so mask them out */ - if (capability & p->prefcodec) { - format_t codec = p->prefcodec & AST_FORMAT_AUDIO_MASK; - - add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size); - alreadysent |= codec; + if (ast_format_cap_has_joint(tmpcap, p->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) { + continue; + } + add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size); + ast_format_cap_add(alreadysent, &tmp_fmt); + } + ast_format_cap_iter_end(p->prefcaps); } /* Start by sending our preferred audio/video codecs */ - for (x = 0; x < 64; x++) { - format_t codec; - - if (!(codec = ast_codec_pref_index(&p->prefs, x))) + for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { + if (!(ast_codec_pref_index(&p->prefs, x, &tmp_fmt))) break; - if (!(capability & codec)) + if (!(ast_format_cap_iscompatible(tmpcap, &tmp_fmt))) continue; - if (alreadysent & codec) + if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt)) continue; - add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size); - alreadysent |= codec; + 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); + } 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); + } + + ast_format_cap_add(alreadysent, &tmp_fmt); } /* Now send any other common audio and video codecs, and non-codec formats: */ - for (x = 1ULL; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) { - if (!(capability & x)) /* Codec not requested */ + ast_format_cap_iter_start(tmpcap); + while (!(ast_format_cap_iter_next(tmpcap, &tmp_fmt))) { + if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt)) continue; - if (alreadysent & x) /* Already added to SDP */ - continue; - - if (x & AST_FORMAT_AUDIO_MASK) - add_codec_to_sdp(p, x, &m_audio, &a_audio, debug, &min_audio_packet_size); - else if (x & AST_FORMAT_VIDEO_MASK) - add_vcodec_to_sdp(p, x, &m_video, &a_video, debug, &min_video_packet_size); - else if (x & AST_FORMAT_TEXT_MASK) - add_tcodec_to_sdp(p, x, &m_text, &a_text, debug, &min_text_packet_size); + 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); + } 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); + } } + ast_format_cap_iter_end(tmpcap); /* Now add DTMF RFC2833 telephony-event as a codec */ for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { @@ -11024,9 +11110,13 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int ao2_t_unlink(dialogs_rtpcheck, p, "unlink pvt into dialogs_rtpcheck container"); ao2_t_link(dialogs_rtpcheck, p, "link pvt into dialogs_rtpcheck container"); - ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, capability)); + ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmpcap)); - return AST_SUCCESS; +add_sdp_cleanup: + alreadysent = ast_format_cap_destroy(alreadysent); + tmpcap = ast_format_cap_destroy(tmpcap); + + return res; } /*! \brief Used for 200 OK and 183 early media */ @@ -15257,14 +15347,21 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of, p->amaflags = peer->amaflags; p->callgroup = peer->callgroup; p->pickupgroup = peer->pickupgroup; - p->capability = peer->capability; + ast_format_cap_copy(p->caps, peer->caps); + ast_format_cap_copy(p->jointcaps, peer->caps); p->prefs = peer->prefs; - p->jointcapability = peer->capability; if (peer->maxforwards > 0) { p->maxforwards = peer->maxforwards; } - if (p->peercapability) - p->jointcapability &= p->peercapability; + 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); + } + } p->maxcallbitrate = peer->maxcallbitrate; if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) @@ -16333,15 +16430,15 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli static void print_codec_to_cli(int fd, struct ast_codec_pref *pref) { int x; - format_t codec; + struct ast_format codec; - for(x = 0; x < 64 ; x++) { - codec = ast_codec_pref_index(pref, x); - if (!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, "%s", ast_getformatname(&codec)); ast_cli(fd, ":%d", pref->framing[x]); - if (x < 31 && ast_codec_pref_index(pref, x + 1)) + if (x < 31 && ast_codec_pref_index(pref, x + 1, &codec)) ast_cli(fd, ","); } if (!x) @@ -16529,7 +16626,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct struct ast_variable *v; struct sip_auth *auth; int x = 0, load_realtime; - format_t codec = 0; + struct ast_format codec; int realtimepeers; realtimepeers = ast_check_realtime("sippeers"); @@ -16644,7 +16741,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct ast_cli(fd, "\n"); ast_cli(fd, " Codecs : "); - ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); + 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); @@ -16738,16 +16835,16 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct 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->capability); + 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 < 64 ; x++) { - codec = ast_codec_pref_index(pref, x); - if (!codec) + 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 < 63 && ast_codec_pref_index(pref, x+1)) + } + 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, ","); } @@ -17243,7 +17340,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.capability); + 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); @@ -17400,7 +17497,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags) ast_cli(arg->fd, FORMAT, ast_sockaddr_stringify_addr(dst), S_OR(cur->username, S_OR(cur->cid_num, "(None)")), cur->callid, - ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0), + cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner->nativeformats) : "(nothing)", AST_CLI_YESNO(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)), cur->needdestroy ? "(d)" : "", cur->lastmsg , @@ -17649,11 +17746,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 ? cur->owner->name : "<none>"); - ast_cli(a->fd, " Our Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->capability)); + ast_cli(a->fd, " Our Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->caps)); 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->peercapability)); - ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->jointcapability)); - ast_cli(a->fd, " Format: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0) ); + 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), cur->owner->nativeformats) : "(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); @@ -18558,13 +18655,13 @@ 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->capability); + ast_getformatname_multiple(buf, len -1, peer->caps); } else if (!strcasecmp(colname, "encryption")) { snprintf(buf, len, "%d", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP)); } else if (!strncasecmp(colname, "chanvar[", 8)) { char *chanvar=colname + 8; struct ast_variable *v; - + chanvar = strsep(&chanvar, "]"); for (v = peer->chanvars ; v ; v = v->next) { if (!strcasecmp(v->name, chanvar)) { @@ -18573,12 +18670,12 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat } } else if (!strncasecmp(colname, "codec[", 6)) { char *codecnum; - format_t codec = 0; - + struct ast_format codec; + codecnum = colname + 6; /* move past the '[' */ codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */ - if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { - ast_copy_string(buf, ast_getformatname(codec), len); + if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &codec))) { + ast_copy_string(buf, ast_getformatname(&codec), len); } else { buf[0] = '\0'; } @@ -21484,7 +21581,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int } ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE); } else { - p->jointcapability = p->capability; + ast_format_cap_copy(p->jointcaps, p->caps); 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" @@ -21566,7 +21663,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int goto request_invite_cleanup; } } else { /* No SDP in invite, call control session */ - p->jointcapability = p->capability; + ast_format_cap_copy(p->jointcaps, p->caps); ast_debug(2, "No SDP in Invite, third party call control\n"); } @@ -21968,7 +22065,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int if (p && (p->autokillid == -1)) { const char *msg; - if (!p->jointcapability) + if ((ast_format_cap_is_empty(p->jointcaps))) msg = "488 Not Acceptable Here (codec error)"; else { ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n"); @@ -25309,12 +25406,13 @@ static int sip_devicestate(void *data) * or SIP/host!dnid * \endverbatim */ -static struct ast_channel *sip_request_call(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *sip_request_call(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct sip_pvt *p; struct ast_channel *tmpc = NULL; char *ext = NULL, *host; char tmp[256]; + char tmp2[256]; char *dest = data; char *dnid; char *secret = NULL; @@ -25325,7 +25423,6 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c char *remote_address; enum sip_transport transport = 0; struct ast_sockaddr remote_address_sa = { {0,} }; - format_t oldformat = format; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(peerorhost); AST_APP_ARG(exten); @@ -25339,13 +25436,14 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c * configured from sip.conf, and sip_tech.capabilities, which is * hardwired to all audio formats. */ - format &= AST_FORMAT_AUDIO_MASK; - if (!format) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n", ast_getformatname(oldformat), ast_getformatname(sip_cfg.capability)); + if (!(ast_format_cap_has_type(cap, AST_FORMAT_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)); *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), oldformat)); + ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); if (ast_strlen_zero(dest)) { ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n"); @@ -25488,8 +25586,9 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c #if 0 printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host); #endif - p->prefcodec = oldformat; /* Format for this call */ - p->jointcapability = oldformat & p->capability; + ast_format_cap_append(p->prefcaps, cap); + ast_format_cap_joint_copy(cap, p->caps, p->jointcaps); + sip_pvt_lock(p); tmpc = sip_new(p, AST_STATE_DOWN, host, requestor ? requestor->linkedid : NULL); /* Place the call */ if (sip_cfg.callevents) @@ -25915,7 +26014,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); - peer->capability = sip_cfg.capability; + ast_format_cap_copy(peer->caps, sip_cfg.caps); peer->maxcallbitrate = default_maxcallbitrate; peer->rtptimeout = global_rtptimeout; peer->rtpholdtimeout = global_rtpholdtimeout; @@ -26063,9 +26162,13 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str if (!(peer->the_mark)) firstpass = 0; } else { - if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) + if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) { return NULL; - + } + if (!(peer->caps = ast_format_cap_alloc_nolock())) { + ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer"); + return NULL; + } if (ast_string_field_init(peer, 512)) { ao2_t_ref(peer, -1, "failed to string_field_init, drop peer"); return NULL; @@ -26356,12 +26459,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str } else if (!strcasecmp(v->name, "pickupgroup")) { peer->pickupgroup = ast_get_group(v->value); } else if (!strcasecmp(v->name, "allow")) { - int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE); + int error = ast_parse_allow_disallow(&peer->prefs, 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->capability, v->value, FALSE); + int error = ast_parse_allow_disallow(&peer->prefs, 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); } @@ -26697,6 +26800,22 @@ static int peer_markall_func(void *device, void *arg, int flags) return 0; } +/*! + * \internal + * \brief If no default formats are set in config, these are used + */ +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)); +} + /*! \brief Re-read SIP.conf config file \note This function reloads all config data, except for active peers (with registrations). They will only @@ -26852,7 +26971,7 @@ static int reload_config(enum channelreloadreason reason) /* Reset channel settings to default before re-configuring */ sip_cfg.allow_external_domains = DEFAULT_ALLOW_EXT_DOM; /* Allow external invites */ sip_cfg.regcontext[0] = '\0'; - sip_cfg.capability = DEFAULT_CAPABILITY; + sip_set_default_format_capabilities(sip_cfg.caps); sip_cfg.regextenonqualify = DEFAULT_REGEXTENONQUALIFY; sip_cfg.notifyringing = DEFAULT_NOTIFYRINGING; sip_cfg.notifycid = DEFAULT_NOTIFYCID; @@ -27258,12 +27377,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.capability, v->value, TRUE); + int error = ast_parse_allow_disallow(&default_prefs, 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.capability, v->value, FALSE); + int error = ast_parse_allow_disallow(&default_prefs, 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); } @@ -27918,7 +28037,7 @@ static enum ast_rtp_glue_result sip_get_trtp_peer(struct ast_channel *chan, stru return res; } -static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, format_t codecs, int nat_active) +static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active) { struct sip_pvt *p; int changed = 0; @@ -27966,8 +28085,8 @@ 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 (codecs && (p->redircodecs != codecs)) { - p->redircodecs = codecs; + if (cap && !(ast_format_cap_is_empty(cap) && !(ast_format_cap_identical(p->redircaps, cap)))) { + ast_format_cap_copy(p->redircaps, cap); changed = 1; } if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { @@ -27990,10 +28109,10 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i return 0; } -static format_t sip_get_codec(struct ast_channel *chan) +static void sip_get_codec(struct ast_channel *chan, struct ast_format_cap *result) { struct sip_pvt *p = chan->tech_pvt; - return p->peercapability ? p->peercapability : p->capability; + ast_format_cap_append(result, ast_format_cap_is_empty(p->peercaps) ? p->caps : p->peercaps); } static struct ast_rtp_glue sip_rtp_glue = { @@ -28955,7 +29074,7 @@ static int peers_data_provider_get(const struct ast_data_search *search, ast_data_add_str(enum_node, "text", ast_describe_caller_presentation(peer->callingpres)); /* codecs */ - ast_data_add_codecs(data_peer, "codecs", peer->capability); + ast_data_add_codecs(data_peer, "codecs", peer->caps); if (!ast_data_search_match(search, data_peer)) { ast_data_remove_node(data_root, data_peer); @@ -28982,6 +29101,10 @@ static const struct ast_data_entry sip_data_providers[] = { static int load_module(void) { ast_verbose("SIP channel loading...\n"); + + if (!(sip_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } /* the fact that ao2_containers can't resize automatically is a major worry! */ /* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */ peers = ao2_t_container_alloc(HASH_PEER_SIZE, peer_hash_cb, peer_cmp_cb, "allocate peers"); @@ -28990,7 +29113,12 @@ static int load_module(void) dialogs_needdestroy = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs_needdestroy"); dialogs_rtpcheck = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs for rtpchecks"); threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table"); - + + if (!(sip_cfg.caps = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_FAILURE; + } + ast_format_cap_add_all_by_type(sip_tech.capabilities, AST_FORMAT_TYPE_AUDIO); + ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */ ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */ @@ -29257,6 +29385,9 @@ static int unload_module(void) sip_reqresp_parser_exit(); sip_unregister_tests(); + ast_format_cap_destroy(sip_tech.capabilities); + sip_cfg.caps = ast_format_cap_destroy(sip_cfg.caps); + return 0; } diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 0d75888ba..3eb76820c 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -148,7 +148,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") static const char tdesc[] = "Skinny Client Control Protocol (Skinny)"; static const char config[] = "skinny.conf"; -static format_t default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW; +static struct ast_format_cap *default_cap; static struct ast_codec_pref default_prefs; enum skinny_codecs { @@ -296,7 +296,7 @@ struct onhook_message { #define CAPABILITIES_RES_MESSAGE 0x0010 struct station_capabilities { - uint32_t codec; + uint32_t codec; /* skinny codec, not ast codec */ uint32_t frames; union { char res[8]; @@ -1244,9 +1244,9 @@ struct skinny_subchannel { int instance; \ int group; \ int needdestroy; \ - format_t confcapability; \ + struct ast_format_cap *confcap; \ struct ast_codec_pref confprefs; \ - format_t capability; \ + struct ast_format_cap *cap; \ struct ast_codec_pref prefs; \ int nonCodecCapability; \ int onhooktime; \ @@ -1282,8 +1282,6 @@ static struct skinny_line_options{ .instance = 0, .directmedia = 0, .nat = 0, - .confcapability = AST_FORMAT_ULAW | AST_FORMAT_ALAW, - .capability = 0, .getforward = 0, .needdestroy = 0, .prune = 0, @@ -1324,9 +1322,9 @@ struct skinny_addon { int registered; \ int lastlineinstance; \ int lastcallreference; \ - format_t confcapability; \ + struct ast_format_cap *confcap; \ struct ast_codec_pref confprefs; \ - format_t capability; \ + struct ast_format_cap *cap; \ int earlyrtp; \ int transfer; \ int callwaiting; \ @@ -1358,8 +1356,6 @@ static struct skinny_device_options { .callwaiting = 1, .mwiblink = 0, .dnd = 0, - .confcapability = AST_FORMAT_ULAW | AST_FORMAT_ALAW, - .capability = 0, .prune = 0, }; static struct skinny_device_options *default_device = &default_device_struct; @@ -1386,7 +1382,7 @@ struct skinnysession { AST_LIST_ENTRY(skinnysession) list; }; -static struct ast_channel *skinny_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *skinny_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static AST_LIST_HEAD_STATIC(sessions, skinnysession); static int skinny_devicestate(void *data); @@ -1402,10 +1398,9 @@ static int skinny_senddigit_end(struct ast_channel *ast, char digit, unsigned in static void mwi_event_cb(const struct ast_event *event, void *userdata); static int skinny_reload(void); -static const struct ast_channel_tech skinny_tech = { +static struct ast_channel_tech skinny_tech = { .type = "Skinny", .description = tdesc, - .capabilities = AST_FORMAT_AUDIO_MASK, .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, .requester = skinny_request, .devicestate = skinny_devicestate, @@ -1424,6 +1419,55 @@ static const struct ast_channel_tech skinny_tech = { static int skinny_extensionstate_cb(char *context, char* exten, int state, void *data); static int skinny_transfer(struct skinny_subchannel *sub); +static struct skinny_line *skinny_line_alloc(void) +{ + struct skinny_line *l; + if (!(l = ast_calloc(1, sizeof(*l)))) { + return NULL; + } + + l->cap = ast_format_cap_alloc_nolock(); + l->confcap = ast_format_cap_alloc_nolock(); + if (!l->cap || !l->confcap) { + l->cap = ast_format_cap_destroy(l->cap); + l->confcap = ast_format_cap_destroy(l->confcap); + ast_free(l); + return NULL; + } + return l; +} +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); + ast_free(l); + return NULL; +} +static struct skinny_device *skinny_device_alloc(void) +{ + struct skinny_device *d; + if (!(d = ast_calloc(1, sizeof(*d)))) { + return NULL; + } + + d->cap = ast_format_cap_alloc_nolock(); + d->confcap = ast_format_cap_alloc_nolock(); + if (!d->cap || !d->confcap) { + d->cap = ast_format_cap_destroy(d->cap); + d->confcap = ast_format_cap_destroy(d->confcap); + ast_free(d); + return NULL; + } + return d; +} +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); + ast_free(d); + return NULL; +} + static void *get_button_template(struct skinnysession *s, struct button_definition_template *btn) { struct skinny_device *d = s->device; @@ -1729,31 +1773,32 @@ static struct skinny_speeddial *find_speeddial_by_instance(struct skinny_device return sd; } -static format_t codec_skinny2ast(enum skinny_codecs skinnycodec) +static struct ast_format *codec_skinny2ast(enum skinny_codecs skinnycodec, struct ast_format *result) { switch (skinnycodec) { case SKINNY_CODEC_ALAW: - return AST_FORMAT_ALAW; + return ast_format_set(result, AST_FORMAT_ALAW, 0); case SKINNY_CODEC_ULAW: - return AST_FORMAT_ULAW; + return ast_format_set(result, AST_FORMAT_ULAW, 0); case SKINNY_CODEC_G723_1: - return AST_FORMAT_G723_1; + return ast_format_set(result, AST_FORMAT_G723_1, 0); case SKINNY_CODEC_G729A: - return AST_FORMAT_G729A; + return ast_format_set(result, AST_FORMAT_G729A, 0); case SKINNY_CODEC_G726_32: - return AST_FORMAT_G726_AAL2; /* XXX Is this right? */ + return ast_format_set(result, AST_FORMAT_G726_AAL2, 0); /* XXX Is this right? */ case SKINNY_CODEC_H261: - return AST_FORMAT_H261; + return ast_format_set(result, AST_FORMAT_H261, 0); case SKINNY_CODEC_H263: - return AST_FORMAT_H263; + return ast_format_set(result, AST_FORMAT_H263 ,0); default: - return 0; + ast_format_clear(result); + return result; } } -static int codec_ast2skinny(format_t astcodec) +static int codec_ast2skinny(struct ast_format *astcodec) { - switch (astcodec) { + switch (astcodec->id) { case AST_FORMAT_ALAW: return SKINNY_CODEC_ALAW; case AST_FORMAT_ULAW: @@ -1924,7 +1969,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s) ast_verb(1, "Line %s already connected to %s. Not connecting to %s.\n", l->name, l->device->name, d->name); } else { l->device = d; - l->capability = l->confcapability & d->capability; + ast_format_cap_joint_copy(l->confcap, d->cap, l->cap); l->prefs = l->confprefs; if (!l->prefs.order[0]) { l->prefs = d->confprefs; @@ -1971,8 +2016,8 @@ static int skinny_unregister(struct skinny_req *req, struct skinnysession *s) AST_LIST_TRAVERSE(&d->lines, l, list) { if (l->device == d) { l->device = NULL; - l->capability = 0; - ast_parse_allow_disallow(&l->prefs, &l->capability, "all", 0); + ast_format_cap_remove_all(l->cap); + ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0); l->instance = 0; manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name); unregister_exten(l); @@ -2234,16 +2279,17 @@ static void transmit_connect(struct skinny_device *d, struct skinny_subchannel * struct skinny_req *req; struct skinny_line *l = sub->parent; struct ast_format_list fmt; + struct ast_format tmpfmt; if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE))) return; - - fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability)); + ast_best_codec(l->cap, &tmpfmt); + fmt = ast_codec_pref_getsize(&l->prefs, &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.bits)); + req->data.openreceivechannel.capability = htolel(codec_ast2skinny(ast_format_set(&tmpfmt, fmt.id, 0))); req->data.openreceivechannel.echo = htolel(0); req->data.openreceivechannel.bitrate = htolel(0); transmit_response(d, req); @@ -2448,6 +2494,7 @@ static void transmit_stopmediatransmission(struct skinny_device *d, struct skinn static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, struct ast_format_list fmt) { struct skinny_req *req; + struct ast_format tmpfmt; if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE))) return; @@ -2457,7 +2504,7 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin req->data.startmedia.remoteIp = dest.sin_addr.s_addr; req->data.startmedia.remotePort = htolel(ntohs(dest.sin_port)); req->data.startmedia.packetSize = htolel(fmt.cur_ms); - req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits)); + req->data.startmedia.payloadType = htolel(codec_ast2skinny(ast_format_set(&tmpfmt, fmt.id, 0))); req->data.startmedia.qualifier.precedence = htolel(127); req->data.startmedia.qualifier.vad = htolel(0); req->data.startmedia.qualifier.packets = htolel(0); @@ -2901,7 +2948,7 @@ static enum ast_rtp_glue_result skinny_get_rtp_peer(struct ast_channel *c, struc } -static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active) +static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active) { struct skinny_subchannel *sub; struct skinny_line *l; @@ -2925,6 +2972,7 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r d = l->device; if (rtp){ + struct ast_format tmpfmt; ast_rtp_instance_get_remote_address(rtp, &them_tmp); ast_sockaddr_to_sin(&them_tmp, &them); @@ -2934,10 +2982,11 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r if (skinnydebug) ast_verb(1, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port)); - fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability)); + ast_best_codec(l->cap, &tmpfmt); + fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt); if (skinnydebug) - ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms); + ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(ast_format_set(&tmpfmt, fmt.id, 0)), fmt.cur_ms); if (!(l->directmedia) || (l->nat)){ ast_rtp_instance_get_local_address(rtp, &us_tmp); @@ -3195,15 +3244,16 @@ 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, codec; + int x; + struct ast_format tmpfmt; for(x = 0; x < 32 ; x++) { - codec = ast_codec_pref_index(pref, x); - if (!codec) + ast_codec_pref_index(pref, x, &tmpfmt); + if (!tmpfmt.id) break; - ast_cli(fd, "%s", ast_getformatname(codec)); + ast_cli(fd, "%s", ast_getformatname(&tmpfmt)); ast_cli(fd, ":%d", pref->framing[x]); - if (x < 31 && ast_codec_pref_index(pref, x + 1)) + if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt)) ast_cli(fd, ","); } if (!x) @@ -3358,10 +3408,10 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s 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->confcapability); + 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->capability); + ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->cap); ast_cli(fd, "%s\n", codec_buf); ast_cli(fd, "Registered: %s\n", (d->registered ? "Yes" : "No")); ast_cli(fd, "Lines: %d\n", numlines); @@ -3392,10 +3442,10 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s 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->confcapability); + 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->capability); + ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->cap); astman_append(s, "%s\r\n", codec_buf); astman_append(s, "Devicestatus: %s\r\n", (d->registered?"registered":"unregistered")); astman_append(s, "NumberOfLines: %d\r\n", numlines); @@ -3587,7 +3637,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str struct skinny_device *d; struct skinny_line *l; struct ast_codec_pref *pref; - int x = 0, codec = 0; + int x = 0; char codec_buf[512]; char group_buf[256]; char cbuf[256]; @@ -3648,10 +3698,10 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str 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->confcapability); + 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->capability); + 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); @@ -3693,16 +3743,17 @@ 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->confcapability); + 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++) { - codec = ast_codec_pref_index(pref, x); - if (!codec) + struct ast_format tmpfmt; + ast_codec_pref_index(pref, x, &tmpfmt); + if (!tmpfmt.id) break; - astman_append(s, "%s", ast_getformatname(codec)); - if (x < 31 && ast_codec_pref_index(pref, x+1)) + astman_append(s, "%s", ast_getformatname(&tmpfmt)); + if (x < 31 && ast_codec_pref_index(pref, x+1, &tmpfmt)) astman_append(s, ","); } astman_append(s, "\r\n"); @@ -4221,11 +4272,11 @@ 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 (f->subclass.codec != ast->nativeformats) { - ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec)); - ast->nativeformats = f->subclass.codec; - ast_set_read_format(ast, ast->readformat); - ast_set_write_format(ast, ast->writeformat); + if (!(ast_format_cap_iscompatible(ast->nativeformats, &f->subclass.format))) { + ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_set(ast->nativeformats, &f->subclass.format); + ast_set_read_format(ast, &ast->readformat); + ast_set_write_format(ast, &ast->writeformat); } } } @@ -4254,13 +4305,13 @@ static int skinny_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } } else { - if (!(frame->subclass.codec & ast->nativeformats)) { + if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { char buf[256]; ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(frame->subclass.codec), + ast_getformatname(&frame->subclass.format), ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), - ast_getformatname(ast->readformat), - ast_getformatname(ast->writeformat)); + ast_getformatname(&ast->readformat), + ast_getformatname(&ast->writeformat)); return -1; } } @@ -4586,7 +4637,7 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch struct skinny_subchannel *sub; struct skinny_device *d = l->device; struct ast_variable *v = NULL; - int fmt; + struct ast_format tmpfmt; if (!l->device) { ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name); @@ -4622,16 +4673,17 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch } tmp->tech = &skinny_tech; tmp->tech_pvt = sub; - tmp->nativeformats = l->capability; - if (!tmp->nativeformats) + ast_format_cap_copy(tmp->nativeformats, l->cap); + if (ast_format_cap_is_empty(tmp->nativeformats)) { // Should throw an error - tmp->nativeformats = default_capability; - fmt = ast_best_codec(tmp->nativeformats); + ast_format_cap_copy(tmp->nativeformats, default_cap); + } + ast_best_codec(tmp->nativeformats, &tmpfmt); if (skinnydebug) { char buf[256]; ast_verb(1, "skinny_new: tmp->nativeformats=%s fmt=%s\n", ast_getformatname_multiple(buf, sizeof(buf), tmp->nativeformats), - ast_getformatname(fmt)); + ast_getformatname(&tmpfmt)); } if (sub->rtp) { ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); @@ -4639,10 +4691,11 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch if (state == AST_STATE_RING) { tmp->rings = 1; } - tmp->writeformat = fmt; - tmp->rawwriteformat = fmt; - tmp->readformat = fmt; - tmp->rawreadformat = fmt; + ast_format_copy(&tmp->writeformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + ast_format_copy(&tmp->readformat, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); + if (!ast_strlen_zero(l->language)) ast_string_field_set(tmp, language, l->language); if (!ast_strlen_zero(l->accountcode)) @@ -5469,10 +5522,14 @@ 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; - format_t codecs = 0; + struct ast_format_cap *codecs = ast_format_cap_alloc(); int i; char buf[256]; + if (!codecs) { + return 0; + } + count = letohl(req->data.caps.count); if (count > SKINNY_MAX_CAPABILITIES) { count = SKINNY_MAX_CAPABILITIES; @@ -5480,23 +5537,24 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny } for (i = 0; i < count; i++) { - format_t acodec = 0; + struct ast_format acodec; int scodec = 0; scodec = letohl(req->data.caps.caps[i].codec); - acodec = codec_skinny2ast(scodec); + codec_skinny2ast(scodec, &acodec); if (skinnydebug) - ast_verb(1, "Adding codec capability '%" PRId64 " (%d)'\n", acodec, scodec); - codecs |= acodec; + ast_verb(1, "Adding codec capability %s (%d)'\n", ast_getformatname(&acodec), scodec); + ast_format_cap_add(codecs, &acodec); } - d->capability = d->confcapability & codecs; - ast_verb(0, "Device capability set to '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), d->capability)); + ast_format_cap_joint_copy(d->confcap, codecs, d->cap); + ast_verb(0, "Device capability set to '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), d->cap)); AST_LIST_TRAVERSE(&d->lines, l, list) { ast_mutex_lock(&l->lock); - l->capability = l->confcapability & d->capability; + ast_format_cap_joint_copy(l->confcap, d->cap, l->cap); ast_mutex_unlock(&l->lock); } + codecs = ast_format_cap_destroy(codecs); return 1; } @@ -5658,6 +5716,7 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc struct sockaddr_in us = { 0, }; struct ast_sockaddr sin_tmp; struct ast_sockaddr us_tmp; + struct ast_format tmpfmt; uint32_t addr; int port; int status; @@ -5698,11 +5757,11 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc ast_verb(1, "device ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); ast_verb(1, "asterisk ipaddr = %s:%d\n", ast_inet_ntoa(us.sin_addr), ntohs(us.sin_port)); } - - fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability)); + ast_best_codec(l->cap, &tmpfmt); + fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt); if (skinnydebug) - ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms); + ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(ast_format_set(&tmpfmt, fmt.id, 0)), fmt.cur_ms); transmit_startmediatransmission(d, sub, us, fmt); @@ -6546,19 +6605,15 @@ static int skinny_devicestate(void *data) return get_devicestate(l); } -static struct ast_channel *skinny_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *skinny_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat; - struct skinny_line *l; struct ast_channel *tmpc = NULL; char tmp[256]; char *dest = data; - oldformat = format; - - if (!(format &= AST_FORMAT_AUDIO_MASK)) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format)); + 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)); return NULL; } @@ -6670,10 +6725,10 @@ static struct ast_channel *skinny_request(const char *type, format_t format, con } continue; } else if (!strcasecmp(v->name, "allow")) { - ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1); + ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 1); continue; } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0); + ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 0); continue; } } @@ -6860,20 +6915,20 @@ static struct ast_channel *skinny_request(const char *type, format_t format, con } } else if (!strcasecmp(v->name, "allow")) { if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) { - ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 1); + ast_parse_allow_disallow(&CDEV_OPTS->confprefs, CDEV_OPTS->confcap, v->value, 1); continue; } if (type & (TYPE_DEF_LINE | TYPE_LINE)) { - ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 1); + ast_parse_allow_disallow(&CLINE_OPTS->confprefs, CLINE_OPTS->confcap, v->value, 1); continue; } } else if (!strcasecmp(v->name, "disallow")) { if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) { - ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 0); + ast_parse_allow_disallow(&CDEV_OPTS->confprefs, CDEV_OPTS->confcap, v->value, 0); continue; } if (type & (TYPE_DEF_LINE | TYPE_LINE)) { - ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 0); + ast_parse_allow_disallow(&CLINE_OPTS->confprefs, CLINE_OPTS->confcap, v->value, 0); continue; } } else if (!strcasecmp(v->name, "version")) { @@ -6982,7 +7037,7 @@ static struct ast_channel *skinny_request(const char *type, format_t format, con } } - if (!(l=ast_calloc(1, sizeof(*l)))) { + if (!(l = skinny_line_alloc())) { ast_verb(1, "Unable to allocate memory for line %s.\n", lname); AST_LIST_UNLOCK(&lines); return NULL; @@ -7040,7 +7095,7 @@ static struct ast_channel *skinny_request(const char *type, format_t format, con } } - if (!(d = ast_calloc(1, sizeof(*d)))) { + if (!(d = skinny_device_alloc())) { ast_verb(1, "Unable to allocate memory for device %s.\n", dname); AST_LIST_UNLOCK(&devices); return NULL; @@ -7162,7 +7217,7 @@ static struct ast_channel *skinny_request(const char *type, format_t format, con bindaddr.sin_family = AF_INET; /* load the lines sections */ - default_line->confcapability = default_capability; + ast_format_cap_copy(default_line->confcap, default_cap); default_line->confprefs = default_prefs; config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines")); cat = ast_category_browse(cfg, "lines"); @@ -7172,7 +7227,7 @@ static struct ast_channel *skinny_request(const char *type, format_t format, con } /* load the devices sections */ - default_device->confcapability = default_capability; + ast_format_cap_copy(default_device->confcap, default_cap); default_device->confprefs = default_prefs; config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices")); cat = ast_category_browse(cfg, "devices"); @@ -7243,7 +7298,7 @@ static void delete_devices(void) /* Delete all lines for this device */ while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) { AST_LIST_REMOVE(&lines, l, all); - free(l); + l = skinny_line_destroy(l); } /* Delete all speeddials for this device */ while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) { @@ -7252,8 +7307,8 @@ static void delete_devices(void) /* Delete all addons for this device */ while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) { free(a); - } - free(d); + } + d = skinny_device_destroy(d); } AST_LIST_UNLOCK(&lines); AST_LIST_UNLOCK(&devices); @@ -7310,7 +7365,7 @@ int skinny_reload(void) free(a); } AST_LIST_REMOVE_CURRENT(list); - free(d); + d = skinny_device_destroy(d); } AST_LIST_TRAVERSE_SAFE_END; AST_LIST_UNLOCK(&devices); @@ -7319,7 +7374,7 @@ int skinny_reload(void) AST_LIST_TRAVERSE_SAFE_BEGIN(&lines, l, all) { if (l->prune) { AST_LIST_REMOVE_CURRENT(all); - free(l); + l = skinny_line_destroy(l); } } AST_LIST_TRAVERSE_SAFE_END; @@ -7344,6 +7399,33 @@ int skinny_reload(void) static int load_module(void) { int res = 0; + struct ast_format tmpfmt; + if (!(default_cap = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(skinny_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(default_line->confcap = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(default_line->cap = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(default_device->confcap = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(default_device->cap = ast_format_cap_alloc())) { + 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_add(default_line->confcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); + ast_format_cap_add(default_line->confcap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); + ast_format_cap_add(default_device->confcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); + ast_format_cap_add(default_device->confcap, ast_format_set(&tmpfmt, 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); @@ -7456,7 +7538,13 @@ static int unload_module(void) con = ast_context_find(used_context); 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); + default_line->confcap = ast_format_cap_destroy(default_line->confcap); + default_line->cap = ast_format_cap_destroy(default_line->cap); + default_device->confcap = ast_format_cap_destroy(default_device->confcap); + default_device->cap = ast_format_cap_destroy(default_device->cap); return 0; } diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index 155890250..4cb5dd71a 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -71,7 +71,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/indications.h" /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */ -#define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */ #define DEFAULTCONTEXT "default" #define DEFAULTCALLERID "Unknown" @@ -102,6 +101,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define SUB_THREEWAY 1 #define MAX_SUBS 2 +struct ast_format_cap *global_cap; + enum autoprovision { AUTOPROVISIONING_NO = 0, AUTOPROVISIONING_YES, @@ -409,7 +410,7 @@ struct unistim_line { /*! AMA flags (for billing) */ int amaflags; /*! Codec supported */ - format_t capability; + struct ast_format_cap *cap; /*! Parkinglot */ char parkinglot[AST_MAX_CONTEXT]; struct unistim_line *next; @@ -679,7 +680,7 @@ static int reload(void); static int unload_module(void); static int reload_config(void); static void show_main_page(struct unistimsession *pte); -static struct ast_channel *unistim_request(const char *type, format_t format, const struct ast_channel *requestor, +static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int unistim_call(struct ast_channel *ast, char *dest, int timeout); static int unistim_hangup(struct ast_channel *ast); @@ -698,10 +699,9 @@ static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1); static void change_callerid(struct unistimsession *pte, int type, char *callerid); -static const struct ast_channel_tech unistim_tech = { +static struct ast_channel_tech unistim_tech = { .type = channel_type, .description = tdesc, - .capabilities = CAPABILITY, .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, .requester = unistim_request, .call = unistim_call, @@ -1483,6 +1483,38 @@ static int unistim_register(struct unistimsession *s) return 1; } +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); +} + +static struct unistim_line *unistim_line_destroy(struct unistim_line *l) +{ + if (!l) { + return NULL; + } + l->cap = ast_format_cap_destroy(l->cap); + ast_free(l); + return NULL; +} + +static struct unistim_line *unistim_line_alloc(void) +{ + struct unistim_line *l; + if (!(l = ast_calloc(1, sizeof(*l)))) { + return NULL; + } + + if (!(l->cap = ast_format_cap_alloc_nolock())) { + ast_free(l); + return NULL; + } + return l; +} + static int alloc_sub(struct unistim_line *l, int x) { struct unistim_subchannel *sub; @@ -1554,16 +1586,16 @@ static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf) } memcpy(newd, d, sizeof(*newd)); - if (!(newl = ast_malloc(sizeof(*newl)))) { + if (!(newl = unistim_line_alloc())) { ast_free(newd); ast_mutex_unlock(&devicelock); return; } - memcpy(newl, d->lines, sizeof(*newl)); + unistim_line_copy(d->lines, newl); if (!alloc_sub(newl, SUB_REAL)) { ast_free(newd); - ast_free(newl); + unistim_line_destroy(newl); ast_mutex_unlock(&devicelock); return; } @@ -2038,7 +2070,7 @@ static void start_rtp(struct unistim_subchannel *sub) struct sockaddr_in us = { 0, }; struct sockaddr_in public = { 0, }; struct sockaddr_in sin = { 0, }; - format_t codec; + int codec; struct sockaddr_in sout = { 0, }; struct ast_sockaddr us_tmp; struct ast_sockaddr sin_tmp; @@ -2093,19 +2125,19 @@ static void start_rtp(struct unistim_subchannel *sub) sin.sin_port = htons(sub->parent->parent->rtp_port); ast_sockaddr_from_sin(&sin_tmp, &sin); ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp); - if (!(sub->owner->nativeformats & sub->owner->readformat)) { - format_t fmt; + if (!(ast_format_cap_iscompatible(sub->owner->nativeformats, &sub->owner->readformat))) { + struct ast_format tmpfmt; char tmp[256]; - fmt = ast_best_codec(sub->owner->nativeformats); + ast_best_codec(sub->owner->nativeformats, &tmpfmt); ast_log(LOG_WARNING, "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n", - ast_getformatname(sub->owner->readformat), - ast_getformatname(fmt), + ast_getformatname(&sub->owner->readformat), + ast_getformatname(&tmpfmt), ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats)); - sub->owner->readformat = fmt; - sub->owner->writeformat = fmt; + ast_format_copy(&sub->owner->readformat, &tmpfmt); + ast_format_copy(&sub->owner->writeformat, &tmpfmt); } - codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat); + codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &sub->owner->readformat, 0); /* Setting up RTP of the phone */ if (public_ip.sin_family == 0) /* NAT IP override ? */ memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */ @@ -2114,14 +2146,14 @@ static void 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(sub->owner->readformat)); + htons(us.sin_port), ast_getformatname(&sub->owner->readformat)); ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n", ast_inet_ntoa(public.sin_addr)); } - if ((sub->owner->readformat == AST_FORMAT_ULAW) || - (sub->owner->readformat == AST_FORMAT_ALAW)) { + if ((sub->owner->readformat.id == AST_FORMAT_ULAW) || + (sub->owner->readformat.id == AST_FORMAT_ALAW)) { if (unistimdebug) - ast_verb(0, "Sending packet_send_rtp_packet_size for codec %s\n", ast_getformatname(codec)); + ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec); memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size, sizeof(packet_send_rtp_packet_size)); buffsend[10] = (int) codec & 0xffffffffLL; @@ -2214,17 +2246,17 @@ static void start_rtp(struct unistim_subchannel *sub) /* Codec */ buffsend[40] = codec; buffsend[41] = codec; - if (sub->owner->readformat == AST_FORMAT_ULAW) + if (sub->owner->readformat.id == AST_FORMAT_ULAW) buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */ - else if (sub->owner->readformat == AST_FORMAT_ALAW) + else if (sub->owner->readformat.id == AST_FORMAT_ALAW) buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */ - else if (sub->owner->readformat == AST_FORMAT_G723_1) + else if (sub->owner->readformat.id == AST_FORMAT_G723_1) buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */ - else if (sub->owner->readformat == AST_FORMAT_G729A) + else if (sub->owner->readformat.id == AST_FORMAT_G729A) buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */ else ast_log(LOG_WARNING, "Unsupported codec %s!\n", - ast_getformatname(sub->owner->readformat)); + ast_getformatname(&sub->owner->readformat)); /* Source port for transmit RTP and Destination port for receiving RTP */ buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8; buffsend[46] = (htons(sin.sin_port) & 0x00ff); @@ -4005,15 +4037,16 @@ 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 (f->subclass.codec != sub->owner->nativeformats) { + if (!(ast_format_cap_iscompatible(sub->owner->nativeformats, &f->subclass.format))) { + char tmp[256]; ast_debug(1, "Oooh, format changed from %s to %s\n", - ast_getformatname(sub->owner->nativeformats), - ast_getformatname(f->subclass.codec)); + ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats), + ast_getformatname(&f->subclass.format)); - sub->owner->nativeformats = f->subclass.codec; - ast_set_read_format(sub->owner, sub->owner->readformat); - ast_set_write_format(sub->owner, sub->owner->writeformat); + ast_format_cap_set(sub->owner->nativeformats, &f->subclass.format); + ast_set_read_format(sub->owner, &sub->owner->readformat); + ast_set_write_format(sub->owner, &sub->owner->writeformat); } } } @@ -4047,14 +4080,14 @@ static int unistim_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } } else { - if (!(frame->subclass.codec & ast->nativeformats)) { + if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { char tmp[256]; ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n", - ast_getformatname(frame->subclass.codec), + ast_getformatname(&frame->subclass.format), ast_getformatname_multiple(tmp, sizeof(tmp), ast->nativeformats), - ast_getformatname(ast->readformat), - ast_getformatname(ast->writeformat)); + ast_getformatname(&ast->readformat), + ast_getformatname(&ast->writeformat)); return -1; } } @@ -4499,7 +4532,7 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state { struct ast_channel *tmp; struct unistim_line *l; - int fmt; + struct ast_format tmpfmt; if (!sub) { ast_log(LOG_WARNING, "subchannel null in unistim_new\n"); @@ -4519,17 +4552,17 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state return NULL; } - tmp->nativeformats = l->capability; - if (!tmp->nativeformats) - tmp->nativeformats = CAPABILITY; - fmt = ast_best_codec(tmp->nativeformats); + ast_format_cap_copy(tmp->nativeformats, l->cap); + if (ast_format_cap_is_empty(tmp->nativeformats)) + ast_format_cap_copy(tmp->nativeformats, global_cap); + ast_best_codec(tmp->nativeformats, &tmpfmt); if (unistimdebug) { char tmp1[256], tmp2[256], tmp3[256]; ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n", - ast_getformatname(fmt), + ast_getformatname(&tmpfmt), ast_getformatname_multiple(tmp1, sizeof(tmp1), tmp->nativeformats), - ast_getformatname_multiple(tmp2, sizeof(tmp2), l->capability), - ast_getformatname_multiple(tmp3, sizeof(tmp3), CAPABILITY)); + ast_getformatname_multiple(tmp2, sizeof(tmp2), l->cap), + ast_getformatname_multiple(tmp3, sizeof(tmp3), global_cap)); } if ((sub->rtp) && (sub->subtype == 0)) { if (unistimdebug) @@ -4545,10 +4578,10 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state if (state == AST_STATE_RING) tmp->rings = 1; tmp->adsicpe = AST_ADSI_UNAVAILABLE; - tmp->writeformat = fmt; - tmp->rawwriteformat = fmt; - tmp->readformat = fmt; - tmp->rawreadformat = fmt; + ast_format_copy(&tmp->writeformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); + ast_format_copy(&tmp->readformat, &tmpfmt); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); tmp->tech_pvt = sub; tmp->tech = &unistim_tech; if (!ast_strlen_zero(l->language)) @@ -4699,26 +4732,19 @@ static int restart_monitor(void) /*--- unistim_request: PBX interface function ---*/ /* UNISTIM calls initiated by the PBX arrive here */ -static struct ast_channel *unistim_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, +static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { - format_t oldformat; struct unistim_subchannel *sub; struct ast_channel *tmpc = NULL; char tmp[256]; + char tmp2[256]; char *dest = data; - oldformat = format; - format &= CAPABILITY; - ast_log(LOG_NOTICE, - "Asked to get a channel of format %s while capability is %s result : %s\n", - ast_getformatname(oldformat), - ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY), - ast_getformatname(format)); - if (!format) { + if (!(ast_format_cap_has_joint(cap, global_cap))) { ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n", - ast_getformatname(oldformat), ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY)); + ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_getformatname_multiple(tmp, sizeof(tmp), global_cap)); return NULL; } @@ -4743,7 +4769,7 @@ static struct ast_channel *unistim_request(const char *type, format_t format, co *cause = AST_CAUSE_BUSY; return NULL; } - sub->parent->capability = format; + ast_format_cap_copy(sub->parent->cap, cap); tmpc = unistim_new(sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL); if (!tmpc) ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); @@ -4786,10 +4812,11 @@ static char *unistim_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args device); line = device->lines; while (line) { + char tmp2[256]; ast_cli(a->fd, - "->name=%s fullname=%s exten=%s callid=%s cap=%" PRId64 " device=%p line=%p\n", + "->name=%s fullname=%s exten=%s callid=%s cap=%s device=%p line=%p\n", line->name, line->fullname, line->exten, line->cid_num, - line->capability, line->parent, line); + ast_getformatname_multiple(tmp2, sizeof(tmp2), line->cap), line->parent, line); for (i = 0; i < MAX_SUBS; i++) { sub = line->subs[i]; if (!sub) @@ -5080,6 +5107,7 @@ static void finish_bookmark(void) } } + static struct unistim_device *build_device(const char *cat, const struct ast_variable *v) { struct unistim_device *d; @@ -5115,7 +5143,7 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var if (!(d = ast_calloc(1, sizeof(*d)))) return NULL; - if (!(l = ast_calloc(1, sizeof(*l)))) { + if (!(l = unistim_line_alloc())) { ast_free(d); return NULL; } @@ -5232,7 +5260,7 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var "You must use bookmark AFTER line=>. Only one line is supported in this version\n"); if (create) { ast_free(d); - ast_free(l); + unistim_line_destroy(l); } return NULL; } @@ -5277,13 +5305,13 @@ 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); } - l->capability = CAPABILITY; + ast_format_cap_copy(l->cap, global_cap); l->parent = d; if (create) { if (!alloc_sub(l, SUB_REAL)) { ast_mutex_destroy(&l->lock); - ast_free(l); + unistim_line_destroy(l); ast_free(d); return NULL; } @@ -5311,7 +5339,7 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var if (!d->lines) { ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n"); ast_mutex_destroy(&l->lock); - ast_free(l); + unistim_line_destroy(l); if (d->tz) { d->tz = ast_tone_zone_unref(d->tz); } @@ -5331,7 +5359,7 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var if (strcmp(d->name, "template")) { ast_log(LOG_ERROR, "You must specify the mac address with device=\n"); ast_mutex_destroy(&l->lock); - ast_free(l); + unistim_line_destroy(l); if (d->tz) { d->tz = ast_tone_zone_unref(d->tz); } @@ -5635,7 +5663,17 @@ 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())) { + goto buff_failed; + } + if (!(unistim_tech.capabilities = ast_format_cap_alloc())) { + 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); if (!(buff = ast_malloc(SIZE_PAGE))) goto buff_failed; @@ -5679,6 +5717,8 @@ 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: return AST_MODULE_LOAD_FAILURE; } @@ -5709,6 +5749,9 @@ 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); + return 0; } diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c index eca7760ab..73995dd07 100644 --- a/channels/chan_usbradio.c +++ b/channels/chan_usbradio.c @@ -661,7 +661,7 @@ static char *usbradio_active; /* the active device */ static int setformat(struct chan_usbradio_pvt *o, int mode); -static struct ast_channel *usbradio_request(const char *type, format_t format, +static struct ast_channel *usbradio_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int usbradio_digit_begin(struct ast_channel *c, char digit); @@ -682,10 +682,11 @@ static int RxTestIt(struct chan_usbradio_pvt *o); static char tdesc[] = "USB (CM108) Radio Channel Driver"; -static const struct ast_channel_tech usbradio_tech = { +static struct ast_format slin; + +static struct ast_channel_tech usbradio_tech = { .type = "Radio", .description = tdesc, - .capabilities = AST_FORMAT_SLINEAR, .requester = usbradio_request, .send_digit_begin = usbradio_digit_begin, .send_digit_end = usbradio_digit_end, @@ -2060,7 +2061,7 @@ static struct ast_frame *usbradio_read(struct ast_channel *c) return f; /* ok we can build and deliver the frame to the caller */ f->frametype = AST_FRAME_VOICE; - f->subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&f->subclass.format, AST_FORMAT_SLINEAR, 0); f->samples = FRAME_SIZE; f->datalen = FRAME_SIZE * 2; f->data.ptr = o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET; @@ -2177,9 +2178,9 @@ static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, if (o->sounddev < 0) setformat(o, O_RDWR); c->fds[0] = o->sounddev; /* -1 if device closed, override later */ - c->nativeformats = AST_FORMAT_SLINEAR; - c->readformat = AST_FORMAT_SLINEAR; - c->writeformat = AST_FORMAT_SLINEAR; + ast_format_cap_add(c->nativeformats, &slin); + ast_format_set(&c->readformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&c->writeformat, AST_FORMAT_SLINEAR, 0); c->tech_pvt = o; if (!ast_strlen_zero(o->language)) @@ -2211,7 +2212,7 @@ static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, } /* */ -static struct ast_channel *usbradio_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +static struct ast_channel *usbradio_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { struct ast_channel *c; struct chan_usbradio_pvt *o = find_desc(data); @@ -2227,8 +2228,7 @@ static struct ast_channel *usbradio_request(const char *type, format_t format, c /* XXX we could default to 'dsp' perhaps ? */ return NULL; } - if ((format & AST_FORMAT_SLINEAR) == 0) { - ast_log(LOG_NOTICE, "Format 0x%" PRIx64 " unsupported\n", format); + if (!(ast_format_cap_iscompatible(cap, &slin))) { return NULL; } if (o->owner) { @@ -3932,6 +3932,11 @@ static int load_module(void) struct ast_flags zeroflag = {0}; #endif + if (!(usbradio_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_add(usbradio_tech.capabilities, ast_format_set(&slin, AST_FORMAT_SLINEAR, 0)); + if (hid_device_mklist()) { ast_log(LOG_NOTICE, "Unable to make hid list\n"); return AST_MODULE_LOAD_DECLINE; @@ -4016,6 +4021,8 @@ static int unload_module(void) /* XXX what about the thread ? */ /* XXX what about the memory allocated ? */ } + + usbradio_tech.capabilities = ast_format_cap_destroy(usbradio_tech.capabilities); return 0; } diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc index 6a268bdb3..0215ab82f 100644 --- a/channels/chan_vpb.cc +++ b/channels/chan_vpb.cc @@ -101,8 +101,6 @@ static char language[MAX_LANGUAGE] = ""; static int gruntdetect_timeout = 3600000; /* Grunt detect timeout is 1hr. */ -static const int prefformat = AST_FORMAT_SLINEAR; - /* Protect the interface list (of vpb_pvt's) */ AST_MUTEX_DEFINE_STATIC(iflock); @@ -331,7 +329,7 @@ static struct vpb_pvt { static struct ast_channel *vpb_new(struct vpb_pvt *i, enum ast_channel_state state, const char *context, const char *linkedid); static void *do_chanreads(void *pvt); -static struct ast_channel *vpb_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); +static struct ast_channel *vpb_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int vpb_digit_begin(struct ast_channel *ast, char digit); static int vpb_digit_end(struct ast_channel *ast, char digit, unsigned int duration); static int vpb_call(struct ast_channel *ast, char *dest, int timeout); @@ -346,7 +344,7 @@ static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); static struct ast_channel_tech vpb_tech = { type: "vpb", description: tdesc, - capabilities: AST_FORMAT_SLINEAR, + capabilities: NULL, properties: 0, requester: vpb_request, devicestate: NULL, @@ -380,7 +378,7 @@ static struct ast_channel_tech vpb_tech = { static struct ast_channel_tech vpb_tech_indicate = { type: "vpb", description: tdesc, - capabilities: AST_FORMAT_SLINEAR, + capabilities: NULL, properties: 0, requester: vpb_request, devicestate: NULL, @@ -755,10 +753,11 @@ 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_ULAW); + rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); #ifdef ANALYSE_CID vpb_wave_write(ws, (char *)buf, sizeof(buf)); #endif @@ -2096,9 +2095,9 @@ static struct ast_frame *vpb_read(struct ast_channel *ast) return &f; } -static inline AudioCompress ast2vpbformat(format_t ast_format) +static inline AudioCompress ast2vpbformat(struct ast_format *format) { - switch (ast_format) { + switch (format->id) { case AST_FORMAT_ALAW: return VPB_ALAW; case AST_FORMAT_SLINEAR: @@ -2112,9 +2111,9 @@ static inline AudioCompress ast2vpbformat(format_t ast_format) } } -static inline const char * ast2vpbformatname(format_t ast_format) +static inline const char * ast2vpbformatname(struct ast_format *format) { - switch(ast_format) { + switch(format->id) { case AST_FORMAT_ALAW: return "AST_FORMAT_ALAW:VPB_ALAW"; case AST_FORMAT_SLINEAR: @@ -2128,9 +2127,9 @@ static inline const char * ast2vpbformatname(format_t ast_format) } } -static inline int astformatbits(format_t ast_format) +static inline int astformatbits(struct ast_format *format) { - switch (ast_format) { + switch (format->id) { case AST_FORMAT_SLINEAR: return 16; case AST_FORMAT_ADPCM: @@ -2174,7 +2173,7 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame) /* ast_mutex_unlock(&p->lock); */ return 0; } else if (ast->_state != 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->name, frame->frametype, ast_getformatname(frame->subclass.codec), ast->_state); + ast_verb(4, "%s: vpb_write: Attempt to Write frame type[%d]subclass[%s] on not up chan(state[%d])\n", ast->name, frame->frametype, ast_getformatname(&frame->subclass.format), ast->_state); p->lastoutput = -1; /* ast_mutex_unlock(&p->lock); */ return 0; @@ -2182,9 +2181,9 @@ 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.codec); + fmt = ast2vpbformat(&frame->subclass.format); if (fmt < 0) { - ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast->name, ast_getformatname(frame->subclass.codec)); + ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast->name, ast_getformatname(&frame->subclass.format)); return -1; } @@ -2208,7 +2207,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.codec)); + 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; @@ -2258,7 +2257,7 @@ static void *do_chanreads(void *pvt) struct ast_frame *fr = &p->fr; char *readbuf = ((char *)p->buf) + AST_FRIENDLY_OFFSET; int bridgerec = 0; - format_t afmt; + struct ast_format tmpfmt; int readlen, res, trycnt=0; AudioCompress fmt; int ignore_dtmf; @@ -2353,26 +2352,23 @@ static void *do_chanreads(void *pvt) } ast_mutex_unlock(&p->play_dtmf_lock); -/* afmt = (p->owner) ? p->owner->rawreadformat : AST_FORMAT_SLINEAR; */ if (p->owner) { - afmt = p->owner->rawreadformat; -/* ast_debug(1,"%s: Record using owner format [%s]\n", p->dev, ast2vpbformatname(afmt)); */ + ast_format_copy(&tmpfmt, &p->owner->rawreadformat); } else { - afmt = AST_FORMAT_SLINEAR; -/* ast_debug(1,"%s: Record using default format [%s]\n", p->dev, ast2vpbformatname(afmt)); */ + ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0); } - fmt = ast2vpbformat(afmt); + fmt = ast2vpbformat(&tmpfmt); if (fmt < 0) { - ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_getformatname(afmt)); + ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_getformatname(&tmpfmt)); return NULL; } - readlen = VPB_SAMPLES * astformatbits(afmt) / 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(afmt)); + 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); @@ -2391,7 +2387,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); - fr->subclass.codec = afmt; + ast_format_copy(&fr->subclass.format, &tmpfmt); fr->data.ptr = readbuf; fr->datalen = readlen; fr->frametype = AST_FRAME_VOICE; @@ -2471,6 +2467,7 @@ 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); @@ -2493,9 +2490,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. */ - tmp->nativeformats = prefformat; - tmp->rawreadformat = AST_FORMAT_SLINEAR; - tmp->rawwriteformat = AST_FORMAT_SLINEAR; + ast_format_cap_add(tmp->nativeformats, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_format_copy(&tmp->rawreadformat, &tmpfmt); + ast_format_copy(&tmp->rawwriteformat, &tmpfmt); if (state == AST_STATE_RING) { tmp->rings = 1; cid_name[0] = '\0'; @@ -2541,19 +2538,20 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st return tmp; } -static struct ast_channel *vpb_request(const char *type, format_t format, const struct ast_channel *requestor, void *vdata, int *cause) +static struct ast_channel *vpb_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *vdata, int *cause) { - format_t oldformat; struct vpb_pvt *p; struct ast_channel *tmp = NULL; char *sepstr, *data = (char *)vdata, *name; const char *s; int group = -1; + struct ast_format slin; + + ast_format_set(&slin, AST_FORMAT_SLINEAR, 0); - oldformat = format; - format &= prefformat; - if (!format) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname(oldformat)); + 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)); return NULL; } @@ -2675,6 +2673,8 @@ static int unload_module(void) ast_free(bridges); } + ast_format_cap_destroy(vpb_tech.capabilities); + ast_format_cap_destroy(vpb_tech_indicate.capabilities); return 0; } @@ -2698,8 +2698,17 @@ 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; + + if (!(vpb_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + if (!(vpb_tech_indicate.capabilities = ast_format_cap_alloc())) { + 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)); try { num_cards = vpb_get_num_cards(); } catch (std::exception e) { diff --git a/channels/h323/ast_h323.cxx b/channels/h323/ast_h323.cxx index c068389f8..b8f3aaaee 100644 --- a/channels/h323/ast_h323.cxx +++ b/channels/h323/ast_h323.cxx @@ -1770,20 +1770,21 @@ PBoolean MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remo if ((subType == codecs[x].h245_cap) && (!codecs[x].formatName || (!strcmp(codecs[x].formatName, (const char *)remoteCapabilities[i].GetFormatName())))) { int ast_codec = codecs[x].asterisk_codec; int ms = 0; - if (!(peer_capabilities & ast_codec)) { + struct ast_format tmpfmt; + if (!(peer_capabilities & ast_format_id_to_old_bitfield((enum ast_format_id) ast_codec))) { struct ast_format_list format; - ast_codec_pref_append(&prefs, ast_codec); - format = ast_codec_pref_getsize(&prefs, ast_codec); + ast_codec_pref_append(&prefs, ast_format_set(&tmpfmt, (enum ast_format_id) ast_codec, 0)); + format = ast_codec_pref_getsize(&prefs, &tmpfmt); if ((ast_codec == AST_FORMAT_ALAW) || (ast_codec == AST_FORMAT_ULAW)) { ms = remoteCapabilities[i].GetTxFramesInPacket(); } else ms = remoteCapabilities[i].GetTxFramesInPacket() * format.inc_ms; - ast_codec_pref_setsize(&prefs, ast_codec, ms); + ast_codec_pref_setsize(&prefs, &tmpfmt, ms); } if (h323debug) { cout << "Found peer capability " << remoteCapabilities[i] << ", Asterisk code is " << ast_codec << ", frame size (in ms) is " << ms << endl; } - peer_capabilities |= ast_codec; + peer_capabilities |= ast_format_id_to_old_bitfield((enum ast_format_id) ast_codec); } } break; @@ -1846,12 +1847,7 @@ PBoolean MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remo break; } } - if (h323debug) { - char caps_str[1024], caps2_str[1024]; - ast_codec_pref_string(&prefs, caps2_str, sizeof(caps2_str)); - cout << "Peer capabilities = " << ast_getformatname_multiple(caps_str, sizeof(caps_str), peer_capabilities) - << ", ordered list is " << caps2_str << endl; - } + #if 0 redir_capabilities &= peer_capabilities; #endif @@ -1897,38 +1893,37 @@ void MyH323Connection::SetCapabilities(int caps, int dtmf_mode, void *_prefs, in int alreadysent = 0; int codec; int x, y; - char caps_str[1024]; struct ast_codec_pref *prefs = (struct ast_codec_pref *)_prefs; struct ast_format_list format; int frames_per_packet; + struct ast_format tmpfmt; H323Capability *cap; localCapabilities.RemoveAll(); - if (h323debug) { - cout << "Setting capabilities to " << ast_getformatname_multiple(caps_str, sizeof(caps_str), caps) << endl; - ast_codec_pref_string(prefs, caps_str, sizeof(caps_str)); - cout << "Capabilities in preference order is " << caps_str << endl; - } /* Add audio codecs in preference order first, then audio codecs without preference as allowed by mask */ for (y = 0, x = -1; x < 32 + 32; ++x) { + ast_format_clear(&tmpfmt); if (x < 0) codec = pref_codec; - else if (y || (!(codec = ast_codec_pref_index(prefs, x)))) { + else if (y || (!(ast_codec_pref_index(prefs, x, &tmpfmt)))) { if (!y) y = 1; else y <<= 1; codec = y; } - if (!(caps & codec) || (alreadysent & codec) || !(codec & AST_FORMAT_AUDIO_MASK)) + if (tmpfmt.id) { + codec = ast_format_to_old_bitfield(&tmpfmt); + } + if (!(caps & codec) || (alreadysent & codec) || (AST_FORMAT_GET_TYPE(ast_format_id_from_old_bitfield(codec)) != AST_FORMAT_TYPE_AUDIO)) continue; alreadysent |= codec; /* format.cur_ms will be set to default if packetization is not explicitly set */ - format = ast_codec_pref_getsize(prefs, codec); + format = ast_codec_pref_getsize(prefs, ast_format_from_old_bitfield(&tmpfmt, codec)); frames_per_packet = (format.inc_ms ? format.cur_ms / format.inc_ms : format.cur_ms); - switch(codec) { + switch(ast_format_id_from_old_bitfield(codec)) { #if 0 case AST_FORMAT_SPEEX: /* Not real sure if Asterisk acutally supports all diff --git a/channels/h323/chan_h323.h b/channels/h323/chan_h323.h index 2ae2c84c4..ddabb669a 100644 --- a/channels/h323/chan_h323.h +++ b/channels/h323/chan_h323.h @@ -30,7 +30,7 @@ #define CHAN_H323_H #include <arpa/inet.h> -#include "asterisk/frame_defs.h" +#include "asterisk/format.h" /* * Enable support for sending/reception of tunnelled Q.SIG messages and @@ -47,6 +47,8 @@ #define H323_HOLD_Q931ONLY (1 << 1) #define H323_HOLD_H450 (1 << 2) +typedef int64_t h323_format; + /** call_option struct holds various bits * of information for each call */ typedef struct call_options { @@ -65,7 +67,7 @@ typedef struct call_options { int progress_audio; int dtmfcodec[2]; int dtmfmode; - format_t capability; + h323_format capability; int bridge; int nat; int tunnelOptions; diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index 094651e70..ce9af244d 100644 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -218,9 +218,9 @@ static void dump_versioned_codec(char *output, int maxlen, void *value, int len) { char *version = (char *) value; if (version[0] == 0) { - if (len == (int) (sizeof(format_t) + sizeof(char))) { - format_t codec = ntohll(get_unaligned_uint64(value + 1)); - ast_copy_string(output, ast_getformatname(codec), maxlen); + if (len == (int) (sizeof(iax2_format) + sizeof(char))) { + iax2_format codec = ntohll(get_unaligned_uint64(value + 1)); + ast_copy_string(output, iax2_getformatname(codec), maxlen); } else { ast_copy_string(output, "Invalid length!", maxlen); } @@ -804,11 +804,11 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) { int version = data[2]; if (version == 0) { - if (len != (int)sizeof(char) + sizeof(format_t)) { - snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(format_t) + sizeof(char)), len); + if (len != (int)sizeof(char) + sizeof(iax2_format)) { + snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len); errorf(tmp); } else { - ies->capability = (format_t) ntohll(get_unaligned_uint64(data + 3)); + ies->capability = (iax2_format) ntohll(get_unaligned_uint64(data + 3)); } } /* else unknown version */ } @@ -825,11 +825,11 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) { int version = data[2]; if (version == 0) { - if (len != (int)sizeof(char) + sizeof(format_t)) { - snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(format_t) + sizeof(char)), len); + if (len != (int)sizeof(char) + sizeof(iax2_format)) { + snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len); errorf(tmp); } else { - ies->format = (format_t) ntohll(get_unaligned_uint64(data + 3)); + ies->format = (iax2_format) ntohll(get_unaligned_uint64(data + 3)); } } /* else unknown version */ } @@ -1138,7 +1138,7 @@ 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; - fr->af.subclass.codec = f->subclass.codec; + ast_format_copy(&fr->af.subclass.format, &f->subclass.format); fr->af.mallocd = 0; /* Our frame is static relative to the container */ fr->af.datalen = f->datalen; fr->af.samples = f->samples; @@ -1157,7 +1157,7 @@ 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.codec == AST_FORMAT_SLINEAR)) { + if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.format.id == AST_FORMAT_SLINEAR)) { /* 2 bytes / sample for SLINEAR */ ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2); } else diff --git a/channels/iax2-parser.h b/channels/iax2-parser.h index f25aaa3b7..978ca0d2a 100644 --- a/channels/iax2-parser.h +++ b/channels/iax2-parser.h @@ -20,7 +20,7 @@ #include "asterisk/linkedlists.h" #include "asterisk/crypto.h" -#include "asterisk/frame_defs.h" +#include "iax2.h" struct iax_ies { char *called_number; @@ -33,8 +33,8 @@ struct iax_ies { char *called_context; char *username; char *password; - format_t capability; - format_t format; + iax2_format capability; + iax2_format format; char *codec_prefs; char *language; int version; diff --git a/channels/iax2-provision.c b/channels/iax2-provision.c index c7af9f324..a95098236 100644 --- a/channels/iax2-provision.c +++ b/channels/iax2-provision.c @@ -59,7 +59,7 @@ struct iax_template { unsigned short serverport; unsigned int altserver; unsigned int flags; - unsigned int format; + iax2_format format; unsigned int tos; AST_LIST_ENTRY(iax_template) list; }; @@ -340,8 +340,9 @@ 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")) { - if ((x = ast_getformatbyname(v->value)) > 0) { - cur->format = x; + struct ast_format tmpfmt; + if ((ast_getformatbyname(v->value, &tmpfmt)) > 0) { + cur->format = ast_format_to_old_bitfield(&tmpfmt); } 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")) { @@ -468,7 +469,7 @@ static char *iax_show_provisioning(struct ast_cli_entry *e, int cmd, struct ast_ ast_cli(a->fd, "Server Port: %d\n", cur->serverport); ast_cli(a->fd, "Alternate: %s\n", alternate); ast_cli(a->fd, "Flags: %s\n", iax_provflags2str(flags, sizeof(flags), cur->flags)); - ast_cli(a->fd, "Format: %s\n", ast_getformatname(cur->format)); + ast_cli(a->fd, "Format: %s\n", iax2_getformatname(cur->format)); ast_cli(a->fd, "TOS: 0x%x\n", cur->tos); found++; } diff --git a/channels/iax2.h b/channels/iax2.h index 825efb8cb..d579ed8aa 100644 --- a/channels/iax2.h +++ b/channels/iax2.h @@ -214,6 +214,12 @@ enum iax_frame_subclass { #define IAX_DPSTATUS_IGNOREPAT (1 << 14) #define IAX_DPSTATUS_MATCHMORE (1 << 15) +/*! iax2 format bit field for handling codecs the old way */ +typedef int64_t iax2_format; + +/*!\brief iax2 wrapper function for ast_getformatname */ +char *iax2_getformatname(iax2_format format); + /*! Full frames are always delivered reliably */ struct ast_iax2_full_hdr { unsigned short scallno; /*!< Source call number -- high bit must be 1 */ diff --git a/channels/sip/include/globals.h b/channels/sip/include/globals.h index 0bd2f4d2d..d7c9f13d0 100644 --- a/channels/sip/include/globals.h +++ b/channels/sip/include/globals.h @@ -28,7 +28,7 @@ extern struct ast_sockaddr bindaddr; /*!< UDP: The address we bind to */ extern struct ast_sched_context *sched; /*!< The scheduling context */ /*! \brief Definition of this channel for PBX channel registration */ -extern const struct ast_channel_tech sip_tech; +extern struct ast_channel_tech sip_tech; /*! \brief This version of the sip channel tech has no send_digit_begin * callback so that the core knows that the channel does not want diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 57c155e14..e5d8205e5 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -216,7 +216,6 @@ #define DEFAULT_SDPSESSION "Asterisk PBX" /*!< Default SDP session name, (s=) header unless re-defined in sip.conf */ #define DEFAULT_SDPOWNER "root" /*!< Default SDP username field in (o=) header unless re-defined in sip.conf */ #define DEFAULT_ENGINE "asterisk" /*!< Default RTP engine to use for sessions */ -#define DEFAULT_CAPABILITY (AST_FORMAT_ULAW | AST_FORMAT_TESTLAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263); #endif /*@}*/ @@ -695,7 +694,7 @@ struct sip_settings { char default_context[AST_MAX_CONTEXT]; char default_subscribecontext[AST_MAX_CONTEXT]; struct ast_ha *contact_ha; /*! \brief Global list of addresses dynamic peers are not allowed to use */ - format_t capability; /*!< Supported codecs */ + struct ast_format_cap *caps; /*!< Supported codecs */ int tcp_enabled; int default_max_forwards; /*!< Default max forwards (SIP Anti-loop) */ }; @@ -995,13 +994,13 @@ struct sip_pvt { 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 */ - format_t capability; /*!< Special capability (codec) */ - format_t jointcapability; /*!< Supported capability at both ends (codecs) */ - format_t peercapability; /*!< Supported peer capability */ - format_t prefcodec; /*!< Preferred codec (outbound only) */ + 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 */ + struct ast_format_cap *redircaps; /*!< Redirect codecs */ + struct ast_format_cap *prefcaps; /*!< Preferred codec (outbound only) */ int noncodeccapability; /*!< DTMF RFC2833 telephony-event */ int jointnoncodeccapability; /*!< Joint Non codec capability */ - format_t redircodecs; /*!< Redirect codecs */ int maxcallbitrate; /*!< Maximum Call Bitrate for Video Calls */ int t38_maxdatagram; /*!< T.38 FaxMaxDatagram override */ int request_queue_sched_id; /*!< Scheduler ID of any scheduled action to process queued requests */ @@ -1217,7 +1216,7 @@ struct sip_peer { int maxcallbitrate; /*!< Maximum Bitrate for a video call */ int expire; /*!< When to expire this peer registration */ - format_t capability; /*!< Codec capability */ + struct ast_format_cap *caps; /*!< Codec capability */ int rtptimeout; /*!< RTP timeout */ int rtpholdtimeout; /*!< RTP Hold Timeout */ int rtpkeepalive; /*!< Send RTP packets for keepalive */ |