diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c index 29d14e036fe1edc2affc810e00d6acc137b06de4..dd48f933eb05aae7d5ea8a2f59bf54a4f52a0acb 100644 --- a/addons/chan_mobile.c +++ b/addons/chan_mobile.c @@ -71,7 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define DEVICE_FRAME_FORMAT AST_FORMAT_SLINEAR #define CHANNEL_FRAME_SIZE 320 -static format_t prefformat = DEVICE_FRAME_FORMAT; +static struct ast_format prefformat; static int discovery_interval = 60; /* The device discovery interval, default 60 seconds. */ static pthread_t discovery_thread = AST_PTHREADT_NULL; /* The discovery thread */ @@ -196,7 +196,7 @@ static char *mblsendsms_desc = static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num, const struct ast_channel *requestor); -static struct ast_channel *mbl_request(const char *type, format_t format, +static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int mbl_call(struct ast_channel *ast, char *dest, int timeout); static int mbl_hangup(struct ast_channel *ast); @@ -450,10 +450,9 @@ static struct msg_queue_entry *msg_queue_head(struct mbl_pvt *pvt); * channel stuff */ -static const struct ast_channel_tech mbl_tech = { +static struct ast_channel_tech mbl_tech = { .type = "Mobile", .description = "Bluetooth Mobile Device Channel Driver", - .capabilities = AST_FORMAT_SLINEAR, .requester = mbl_request, .call = mbl_call, .hangup = mbl_hangup, @@ -844,11 +843,11 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num } chn->tech = &mbl_tech; - chn->nativeformats = prefformat; - chn->rawreadformat = prefformat; - chn->rawwriteformat = prefformat; - chn->writeformat = prefformat; - chn->readformat = prefformat; + ast_format_cap_add(chn->nativeformats, &prefformat); + ast_format_copy(&chn->rawreadformat, &prefformat); + ast_format_copy(&chn->rawwriteformat, &prefformat); + ast_format_copy(&chn->writeformat, &prefformat); + ast_format_copy(&chn->readformat, &prefformat); chn->tech_pvt = pvt; if (state == AST_STATE_RING) @@ -867,7 +866,7 @@ e_return: return NULL; } -static struct ast_channel *mbl_request(const char *type, format_t format, +static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { @@ -875,7 +874,6 @@ static struct ast_channel *mbl_request(const char *type, format_t format, struct mbl_pvt *pvt; char *dest_dev = NULL; char *dest_num = NULL; - format_t oldformat; int group = -1; if (!data) { @@ -884,10 +882,9 @@ static struct ast_channel *mbl_request(const char *type, format_t format, return NULL; } - oldformat = format; - format &= (AST_FORMAT_SLINEAR); - if (!format) { - ast_log(LOG_WARNING, "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_WARNING, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); *cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED; return NULL; } @@ -1099,7 +1096,7 @@ static struct ast_frame *mbl_read(struct ast_channel *ast) memset(&pvt->fr, 0x00, sizeof(struct ast_frame)); pvt->fr.frametype = AST_FRAME_VOICE; - pvt->fr.subclass.codec = DEVICE_FRAME_FORMAT; + ast_format_set(&pvt->fr.subclass.format, DEVICE_FRAME_FORMAT, 0); pvt->fr.src = "Mobile"; pvt->fr.offset = AST_FRIENDLY_OFFSET; pvt->fr.mallocd = 0; @@ -4534,6 +4531,7 @@ static int unload_module(void) if (sdp_session) sdp_close(sdp_session); + mbl_tech.capabilities = ast_format_cap_destroy(mbl_tech.capabilities); return 0; } @@ -4542,6 +4540,11 @@ static int load_module(void) int dev_id, s; + if (!(mbl_tech.capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_set(&prefformat, DEVICE_FRAME_FORMAT, 0); + ast_format_cap_add(mbl_tech.capabilities, &prefformat); /* Check if we have Bluetooth, no point loading otherwise... */ dev_id = hci_get_route(NULL); s = hci_open_dev(dev_id); diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c index a49e3a882cd2f27fe7c37f48fff6189fbdb0d4ff..df4965bbda60e237051b8f18623259f95bcf0696 100644 --- a/addons/chan_ooh323.c +++ b/addons/chan_ooh323.c @@ -66,7 +66,7 @@ static struct ast_jb_conf default_jbconf = static struct ast_jb_conf global_jbconf; /* Channel Definition */ -static struct ast_channel *ooh323_request(const char *type, format_t format, +static struct ast_channel *ooh323_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); static int ooh323_digit_begin(struct ast_channel *ast, char digit); static int ooh323_digit_end(struct ast_channel *ast, char digit, unsigned int duration); @@ -82,7 +82,7 @@ static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp); static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp); static int ooh323_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); + struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active); static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan); static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl); @@ -92,10 +92,9 @@ static void print_codec_to_cli(int fd, struct ast_codec_pref *pref); struct ooh323_peer *find_friend(const char *name, int port); -static const struct ast_channel_tech ooh323_tech = { +static struct ast_channel_tech ooh323_tech = { .type = type, .description = tdesc, - .capabilities = -1, .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER, .requester = ooh323_request, .send_digit_begin = ooh323_digit_begin, @@ -172,9 +171,9 @@ static struct ooh323_pvt { char callee_url[AST_MAX_EXTENSION]; int port; - format_t readformat; /* negotiated read format */ - format_t writeformat; /* negotiated write format */ - format_t capability; + struct ast_format readformat; /* negotiated read format */ + struct ast_format writeformat; /* negotiated write format */ + struct ast_format_cap *cap; struct ast_codec_pref prefs; int dtmfmode; int dtmfcodec; @@ -204,7 +203,7 @@ struct ooh323_user{ unsigned inUse; char accountcode[20]; int amaflags; - format_t capability; + struct ast_format_cap *cap; struct ast_codec_pref prefs; int dtmfmode; int dtmfcodec; @@ -225,7 +224,7 @@ struct ooh323_peer{ char name[256]; unsigned outgoinglimit; unsigned outUse; - format_t capability; + struct ast_format_cap *cap; struct ast_codec_pref prefs; char accountcode[20]; int amaflags; @@ -286,7 +285,7 @@ static int gPort = 1720; static char gIP[20]; static char gCallerID[AST_MAX_EXTENSION] = ""; static struct ooAliases *gAliasList; -static format_t gCapability = AST_FORMAT_ULAW; +static struct ast_format_cap *gCap; static struct ast_codec_pref gPrefs; static int gDTMFMode = H323_DTMF_RFC2833; static int gDTMFCodec = 101; @@ -337,14 +336,14 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL; static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, - const char *host, int capability, const char *linkedid) + const char *host, struct ast_format_cap *cap, const char *linkedid) { struct ast_channel *ch = NULL; - int fmt = 0; + struct ast_format tmpfmt; if (gH323Debug) - ast_verbose("--- ooh323_new - %s, %d\n", host, capability); - + ast_verbose("--- ooh323_new - %s\n", host); + ast_format_clear(&tmpfmt); /* Don't hold a h323 pvt lock while we allocate a channel */ ast_mutex_unlock(&i->lock); ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, @@ -360,12 +359,14 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, ast_channel_lock(ch); ch->tech = &ooh323_tech; - if (capability) - fmt = ast_best_codec(capability); - if (!fmt) - fmt = ast_codec_pref_index(&i->prefs, 0); + if (cap) + ast_best_codec(cap, &tmpfmt); + if (!tmpfmt.id) + ast_codec_pref_index(&i->prefs, 0, &tmpfmt); - ch->nativeformats = ch->rawwriteformat = ch->rawreadformat = fmt; + ast_format_cap_add(ch->nativeformats, &tmpfmt); + ast_format_copy(&ch->rawwriteformat, &tmpfmt); + ast_format_copy(&ch->rawreadformat, &tmpfmt); ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(i->rtp, 0)); ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(i->rtp, 1)); @@ -377,8 +378,8 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, ch->rings = 1; ch->adsicpe = AST_ADSI_UNAVAILABLE; - ast_set_write_format(ch, fmt); - ast_set_read_format(ch, fmt); + ast_set_write_format(ch, &tmpfmt); + ast_set_read_format(ch, &tmpfmt); ch->tech_pvt = i; i->owner = ch; ast_module_ref(myself); @@ -472,6 +473,11 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n"); return NULL; } + if (!(pvt->cap = ast_format_cap_alloc_nolock())) { + ast_free(pvt); + ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n"); + return NULL; + } ast_mutex_init(&pvt->lock); ast_mutex_lock(&pvt->lock); @@ -529,7 +535,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode)); pvt->amaflags = gAMAFLAGS; - pvt->capability = gCapability; + ast_format_cap_copy(pvt->cap, gCap); memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs)); ast_mutex_unlock(&pvt->lock); @@ -549,7 +555,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) /* Possible data values - peername, exten/peername, exten@ip */ -static struct ast_channel *ooh323_request(const char *type, format_t format, +static struct ast_channel *ooh323_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause) { @@ -560,17 +566,14 @@ static struct ast_channel *ooh323_request(const char *type, format_t format, char *ext = NULL; char tmp[256]; char formats[FORMAT_STRING_SIZE]; - int oldformat; int port = 0; if (gH323Debug) ast_verbose("--- ooh323_request - data %s format %s\n", (char*)data, - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,format)); + ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap)); - oldformat = format; - format &= AST_FORMAT_AUDIO_MASK; - if (!format) { - ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%lld'\n", (long long) 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(formats,FORMAT_STRING_SIZE,cap)); return NULL; } @@ -633,7 +636,7 @@ static struct ast_channel *ooh323_request(const char *type, format_t format, if (ext) ast_copy_string(p->exten, ext, sizeof(p->exten)); - p->capability = peer->capability; + ast_format_cap_copy(p->cap, peer->cap); memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref)); p->dtmfmode |= peer->dtmfmode; p->dtmfcodec = peer->dtmfcodec; @@ -667,7 +670,7 @@ static struct ast_channel *ooh323_request(const char *type, format_t format, p->dtmfcodec = gDTMFCodec; p->t38support = gT38Support; p->rtptimeout = gRTPTimeout; - p->capability = gCapability; + ast_format_cap_copy(p->cap, gCap); p->rtdrinterval = gRTDRInterval; p->rtdrcount = gRTDRCount; p->faststart = gFastStart; @@ -686,7 +689,7 @@ static struct ast_channel *ooh323_request(const char *type, format_t format, } - chan = ooh323_new(p, AST_STATE_DOWN, p->username, format, + chan = ooh323_new(p, AST_STATE_DOWN, p->username, cap, requestor ? requestor->linkedid : NULL); ast_mutex_unlock(&p->lock); @@ -1140,16 +1143,16 @@ static int ooh323_write(struct ast_channel *ast, struct ast_frame *f) } - if (!(f->subclass.codec & ast->nativeformats)) { - if (ast->nativeformats != 0) { + if (!(ast_format_cap_iscompatible(ast->nativeformats, &f->subclass.format))) { + if (!(ast_format_cap_is_empty(ast->nativeformats))) { ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", - ast_getformatname(f->subclass.codec), + ast_getformatname(&f->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)); - ast_set_write_format(ast, f->subclass.codec); + ast_set_write_format(ast, &f->subclass.format); } else { /* ast_set_write_format(ast, f->subclass); ast->nativeformats = f->subclass; */ @@ -1409,14 +1412,14 @@ static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan } -void ooh323_set_write_format(ooCallData *call, int fmt, int txframes) +void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes) { struct ooh323_pvt *p = NULL; char formats[FORMAT_STRING_SIZE]; if (gH323Debug) ast_verbose("--- ooh323_update_writeformat %s/%d\n", - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, fmt), txframes); + ast_getformatname(fmt), txframes); p = find_call(call); if (!p) { @@ -1426,7 +1429,7 @@ void ooh323_set_write_format(ooCallData *call, int fmt, int txframes) ast_mutex_lock(&p->lock); - p->writeformat = fmt; + ast_format_copy(&p->writeformat, fmt); if (p->owner) { while (p->owner && ast_channel_trylock(p->owner)) { @@ -1440,8 +1443,8 @@ void ooh323_set_write_format(ooCallData *call, int fmt, int txframes) } if (gH323Debug) ast_verbose("Writeformat before update %s/%s\n", - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, p->owner->writeformat), - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, p->owner->nativeformats)); + ast_getformatname(&p->owner->writeformat), + ast_getformatname_multiple(formats, sizeof(formats), p->owner->nativeformats)); if (txframes) ast_codec_pref_setsize(&p->prefs, fmt, txframes); ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs); @@ -1454,9 +1457,9 @@ void ooh323_set_write_format(ooCallData *call, int fmt, int txframes) p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0); } - p->owner->nativeformats = fmt; - ast_set_write_format(p->owner, p->owner->writeformat); - ast_set_read_format(p->owner, p->owner->readformat); + ast_format_cap_set(p->owner->nativeformats, fmt); + ast_set_write_format(p->owner, &p->owner->writeformat); + ast_set_read_format(p->owner, &p->owner->readformat); ast_channel_unlock(p->owner); } else ast_log(LOG_ERROR, "No owner found\n"); @@ -1468,14 +1471,13 @@ void ooh323_set_write_format(ooCallData *call, int fmt, int txframes) ast_verbose("+++ ooh323_update_writeformat\n"); } -void ooh323_set_read_format(ooCallData *call, int fmt) +void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt) { struct ooh323_pvt *p = NULL; - char formats[FORMAT_STRING_SIZE]; if (gH323Debug) ast_verbose("--- ooh323_update_readformat %s\n", - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, fmt)); + ast_getformatname(fmt)); p = find_call(call); if (!p) { @@ -1485,8 +1487,7 @@ void ooh323_set_read_format(ooCallData *call, int fmt) ast_mutex_lock(&p->lock); - p->readformat = fmt; - + ast_format_copy(&p->readformat, fmt); if (p->owner) { while (p->owner && ast_channel_trylock(p->owner)) { @@ -1501,9 +1502,9 @@ void ooh323_set_read_format(ooCallData *call, int fmt) if (gH323Debug) ast_verbose("Readformat before update %s\n", - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, p->owner->readformat)); - p->owner->nativeformats = fmt; - ast_set_read_format(p->owner, p->owner->readformat); + ast_getformatname(&p->owner->readformat)); + ast_format_cap_set(p->owner->nativeformats, fmt); + ast_set_read_format(p->owner, &p->owner->readformat); ast_channel_unlock(p->owner); } else ast_log(LOG_ERROR, "No owner found\n"); @@ -1760,7 +1761,7 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg) ast_copy_string(p->context, user->context, sizeof(p->context)); ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode)); p->amaflags = user->amaflags; - p->capability = user->capability; + ast_format_cap_copy(p->cap, user->cap); memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref)); p->dtmfmode |= user->dtmfmode; p->dtmfcodec = user->dtmfcodec; @@ -1804,7 +1805,7 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg) } } - ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode, p->dtmfcodec, + ooh323c_set_capability_for_call(call, &p->prefs, p->cap, p->dtmfmode, p->dtmfcodec, p->t38support); configure_local_rtp(p, call); @@ -1971,7 +1972,7 @@ int onNewCallCreated(ooCallData *call) p->username?p->username:"NULL", call->callToken, prefsBuf); } - ooh323c_set_capability_for_call(call, &p->prefs, p->capability, + ooh323c_set_capability_for_call(call, &p->prefs, p->cap, p->dtmfmode, p->dtmfcodec, p->t38support); configure_local_rtp(p, call); @@ -2157,6 +2158,7 @@ void ooh323_delete_peer(struct ooh323_peer *peer) if(peer->url) free(peer->url); if(peer->e164) free(peer->e164); + peer->cap = ast_format_cap_destroy(peer->cap); free(peer); } @@ -2176,10 +2178,14 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v) user = ast_calloc(1,sizeof(struct ooh323_user)); if (user) { + if (!(user->cap = ast_format_cap_alloc_nolock())) { + ast_free(user); + return NULL; + } memset(user, 0, sizeof(struct ooh323_user)); ast_mutex_init(&user->lock); ast_copy_string(user->name, name, sizeof(user->name)); - user->capability = gCapability; + ast_format_cap_copy(user->cap, gCap); memcpy(&user->prefs, &gPrefs, sizeof(user->prefs)); user->rtptimeout = gRTPTimeout; user->dtmfmode = gDTMFMode; @@ -2223,14 +2229,14 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v) } else user->rtpmask = NULL; } else if (!strcasecmp(v->name, "disallow")) { ast_parse_allow_disallow(&user->prefs, - &user->capability, v->value, 0); + user->cap, v->value, 0); } else if (!strcasecmp(v->name, "allow")) { const char* tcodecs = v->value; if (!strcasecmp(v->value, "all")) { tcodecs = "ulaw,alaw,g729,g723,gsm"; } ast_parse_allow_disallow(&user->prefs, - &user->capability, tcodecs, 1); + user->cap, tcodecs, 1); } else if (!strcasecmp(v->name, "amaflags")) { user->amaflags = ast_cdr_amaflags2int(v->value); } else if (!strcasecmp(v->name, "ip")) { @@ -2285,10 +2291,14 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, peer = ast_calloc(1, sizeof(*peer)); if (peer) { + if (!(peer->cap = ast_format_cap_alloc_nolock())) { + ast_free(peer); + return NULL; + } memset(peer, 0, sizeof(struct ooh323_peer)); ast_mutex_init(&peer->lock); ast_copy_string(peer->name, name, sizeof(peer->name)); - peer->capability = gCapability; + ast_format_cap_copy(peer->cap, gCap); memcpy(&peer->prefs, &gPrefs, sizeof(peer->prefs)); peer->rtptimeout = gRTPTimeout; ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode)); @@ -2362,14 +2372,14 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, sizeof(peer->rtpmaskstr)); } else peer->rtpmask = NULL; } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&peer->prefs, &peer->capability, + ast_parse_allow_disallow(&peer->prefs, peer->cap, v->value, 0); } else if (!strcasecmp(v->name, "allow")) { const char* tcodecs = v->value; if (!strcasecmp(v->value, "all")) { tcodecs = "ulaw,alaw,g729,g723,gsm"; } - ast_parse_allow_disallow(&peer->prefs, &peer->capability, + ast_parse_allow_disallow(&peer->prefs, peer->cap, tcodecs, 1); } else if (!strcasecmp(v->name, "amaflags")) { peer->amaflags = ast_cdr_amaflags2int(v->value); @@ -2475,6 +2485,7 @@ int reload_config(int reload) struct ooh323_peer *peer = NULL; char *cat; const char *utype; + struct ast_format tmpfmt; if (gH323Debug) ast_verbose("--- reload_config\n"); @@ -2509,7 +2520,7 @@ int reload_config(int reload) gPort = 1720; gIP[0] = '\0'; strcpy(gCallerID, DEFAULT_H323ID); - gCapability = AST_FORMAT_ALAW; + ast_format_cap_set(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); memset(&gPrefs, 0, sizeof(struct ast_codec_pref)); gDTMFMode = H323_DTMF_RFC2833; gDTMFCodec = 101; @@ -2678,13 +2689,13 @@ int reload_config(int reload) } else if (!strcasecmp(v->name, "accountcode")) { ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode)); } else if (!strcasecmp(v->name, "disallow")) { - ast_parse_allow_disallow(&gPrefs, &gCapability, v->value, 0); + ast_parse_allow_disallow(&gPrefs, gCap, v->value, 0); } else if (!strcasecmp(v->name, "allow")) { const char* tcodecs = v->value; if (!strcasecmp(v->value, "all")) { tcodecs = "ulaw,alaw,g729,g723,gsm"; } - ast_parse_allow_disallow(&gPrefs, &gCapability, tcodecs, 1); + ast_parse_allow_disallow(&gPrefs, gCap, tcodecs, 1); } else if (!strcasecmp(v->name, "dtmfmode")) { if (!strcasecmp(v->value, "inband")) gDTMFMode = H323_DTMF_INBAND; @@ -2893,7 +2904,7 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, stru ast_cli(a->fd, FORMAT, peer->name, peer->accountcode, ip_port, - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,peer->capability)); + ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,peer->cap)); prev = peer; peer = peer->next; ast_mutex_unlock(&prev->lock); @@ -2907,15 +2918,15 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, stru /*! \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) @@ -3038,7 +3049,7 @@ static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, stru ast_mutex_lock(&user->lock); ast_cli(a->fd, FORMAT1, user->name, user->accountcode, user->context, - ast_getformatname_multiple(formats, FORMAT_STRING_SIZE, user->capability)); + ast_getformatname_multiple(formats, FORMAT_STRING_SIZE, user->cap)); prev = user; user = user->next; ast_mutex_unlock(&prev->lock); @@ -3137,7 +3148,7 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str ast_cli(a->fd, "%-20s%s\n", "Context:", gContext); ast_cli(a->fd, "%-20s%s\n", "Capability:", - ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCapability)); + ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap)); ast_cli(a->fd, "%-20s", "DTMF Mode: "); if (gDTMFMode & H323_DTMF_CISCO) { @@ -3207,6 +3218,7 @@ static int load_module(void) int res; struct ooAliases * pNewAlias = NULL; struct ooh323_peer *peer = NULL; + struct ast_format tmpfmt; OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0}; OOH323CALLBACKS h323Callbacks = { @@ -3221,6 +3233,14 @@ static int load_module(void) .onReceivedDTMF = ooh323_onReceivedDigit, .onModeChanged = onModeChanged }; + if (!(gCap = ast_format_cap_alloc())) { + return 1; + } + if (!(ooh323_tech.capabilities = ast_format_cap_alloc())) { + return 1; + } + ast_format_cap_add(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); + ast_format_cap_add_all(ooh323_tech.capabilities); myself = ast_module_info->self; @@ -3334,7 +3354,7 @@ static int load_module(void) ooH323EpSetH323Callbacks(h323Callbacks); /* Add endpoint capabilities */ - if (ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode, gDTMFCodec) < 0) { + if (ooh323c_set_capability(&gPrefs, gCap, gDTMFMode, gDTMFCodec) < 0) { ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n"); return 1; } @@ -3558,7 +3578,7 @@ int ooh323_destroy(struct ooh323_pvt *p) ast_mutex_unlock(&cur->lock); ast_mutex_destroy(&cur->lock); - + cur->cap = ast_format_cap_destroy(cur->cap); ast_free(cur); } @@ -3623,6 +3643,7 @@ int delete_users() free(prev->rtpmask); } } + prev->cap = ast_format_cap_destroy(prev->cap); free(prev); if (cur == userl.users) { break; @@ -3751,6 +3772,8 @@ static int unload_module(void) ast_verbose("+++ ooh323 unload_module \n"); } + gCap = ast_format_cap_destroy(gCap); + ooh323_tech.capabilities = ast_format_cap_destroy(ooh323_tech.capabilities); return 0; } @@ -3802,22 +3825,23 @@ int ooh323_update_capPrefsOrderForCall (ooCallData *call, struct ast_codec_pref *prefs) { int i = 0; - int codec = ast_codec_pref_index(prefs, i); + struct ast_format tmpfmt; + + ast_codec_pref_index(prefs, i, &tmpfmt); ooResetCapPrefs(call); - while (codec) { - ooAppendCapToCapPrefs(call, ooh323_convertAsteriskCapToH323Cap(codec)); - codec = ast_codec_pref_index(prefs, ++i); + while (tmpfmt.id) { + ooAppendCapToCapPrefs(call, ooh323_convertAsteriskCapToH323Cap(&tmpfmt)); + ast_codec_pref_index(prefs, ++i, &tmpfmt); } return 0; } -int ooh323_convertAsteriskCapToH323Cap(format_t cap) +int ooh323_convertAsteriskCapToH323Cap(struct ast_format *format) { - char formats[FORMAT_STRING_SIZE]; - switch (cap) { + switch (format->id) { case AST_FORMAT_ULAW: return OO_G711ULAW64K; case AST_FORMAT_ALAW: @@ -3845,14 +3869,13 @@ int ooh323_convertAsteriskCapToH323Cap(format_t cap) case AST_FORMAT_H263: return OO_H263VIDEO; default: - ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", - ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap)); + ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_getformatname(format)); return -1; } } static int ooh323_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) + struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *cap, int nat_active) { /* XXX Deal with Video */ struct ooh323_pvt *p; @@ -3868,7 +3891,7 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance return 0; } - mode = ooh323_convertAsteriskCapToH323Cap(chan->writeformat); + mode = ooh323_convertAsteriskCapToH323Cap(&chan->writeformat); p = (struct ooh323_pvt *) chan->tech_pvt; if (!p) { ast_log(LOG_ERROR, "No Private Structure, this is bad\n"); @@ -3890,7 +3913,9 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call) struct ast_sockaddr tmp; ooMediaInfo mediaInfo; int x; - format_t format = 0; + struct ast_format tmpfmt; + + ast_format_clear(&tmpfmt); if (gH323Debug) ast_verbose("--- configure_local_rtp\n"); @@ -3929,9 +3954,9 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call) ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP)); mediaInfo.lMediaPort = ntohs(us.sin_port); mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1; - for (x = 0; 0 != (format = ast_codec_pref_index(&p->prefs, x)); x++) { + for (x = 0; ast_codec_pref_index(&p->prefs, x, &tmpfmt); x++) { strcpy(mediaInfo.dir, "transmit"); - mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format); + mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(&tmpfmt); ooAddMediaInfo(call, mediaInfo); strcpy(mediaInfo.dir, "receive"); ooAddMediaInfo(call, mediaInfo); @@ -3995,7 +4020,7 @@ void setup_rtp_connection(ooCallData *call, const char *remoteIp, ast_sockaddr_from_sin(&tmp, &them); ast_rtp_instance_set_remote_address(p->rtp, &tmp); - if (p->writeformat & AST_FORMAT_G726_AAL2) + if (p->writeformat.id == AST_FORMAT_G726_AAL2) ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, 2, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD); @@ -4237,16 +4262,16 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p) if (p->owner) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE && !p->faxmode) { - if (f->subclass.codec != p->owner->nativeformats) { - ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(f->subclass.codec)); - p->owner->nativeformats = 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, voice format changed to %s\n", ast_getformatname(&f->subclass.format)); + ast_format_cap_set(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 ((p->dtmfmode & H323_DTMF_INBAND) && p->vad && - (f->subclass.codec == AST_FORMAT_SLINEAR || f->subclass.codec == AST_FORMAT_ALAW || - f->subclass.codec == AST_FORMAT_ULAW)) { + (f->subclass.format.id == AST_FORMAT_SLINEAR || f->subclass.format.id == AST_FORMAT_ALAW || + f->subclass.format.id == AST_FORMAT_ULAW)) { f = ast_dsp_process(p->owner, p->vad, f); if (f && (f->frametype == AST_FRAME_DTMF)) ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer); diff --git a/addons/chan_ooh323.h b/addons/chan_ooh323.h index 65eefb7c604fa13418c14f9bce4d6ec34a9894e3..2fb9039175a3cfc8addd19a2fa77de4ec9ebe048 100644 --- a/addons/chan_ooh323.h +++ b/addons/chan_ooh323.h @@ -61,7 +61,8 @@ #include "asterisk/manager.h" #include "asterisk/dsp.h" #include "asterisk/stringfields.h" -#include "asterisk/frame_defs.h" +#include "asterisk/format.h" +#include "asterisk/format_cap.h" #include "asterisk/udptl.h" #include "ootypes.h" @@ -99,13 +100,13 @@ void close_rtp_connection(ooCallData *call); struct ast_frame *ooh323_rtp_read (struct ast_channel *ast, struct ooh323_pvt *p); -void ooh323_set_write_format(ooCallData *call, int fmt, int txframes); -void ooh323_set_read_format(ooCallData *call, int fmt); +void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes); +void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt); int ooh323_update_capPrefsOrderForCall (ooCallData *call, struct ast_codec_pref *prefs); -int ooh323_convertAsteriskCapToH323Cap(format_t cap); +int ooh323_convertAsteriskCapToH323Cap(struct ast_format *format); int ooh323_convert_hangupcause_asteriskToH323(int cause); int ooh323_convert_hangupcause_h323ToAsterisk(int cause); diff --git a/addons/format_mp3.c b/addons/format_mp3.c index ceb1accbbb3311a11b003815d74ec226e9eb2581..d59411d6cbea696b0ebdf57c1a408bf461598368 100644 --- a/addons/format_mp3.c +++ b/addons/format_mp3.c @@ -224,7 +224,7 @@ static struct ast_frame *mp3_read(struct ast_filestream *s, int *whennext) p->offset += p->buflen; delay = p->buflen/2; s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_SLINEAR, 0); AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, p->buflen); s->fr.mallocd = 0; s->fr.samples = delay; @@ -293,10 +293,9 @@ static char *mp3_getcomment(struct ast_filestream *s) return NULL; } -static const struct ast_format mp3_f = { +static struct ast_format_def mp3_f = { .name = "mp3", .exts = "mp3", - .format = AST_FORMAT_SLINEAR, .open = mp3_open, .write = mp3_write, .rewrite = mp3_rewrite, @@ -313,13 +312,14 @@ static const struct ast_format mp3_f = { static int load_module(void) { + ast_format_set(&mp3_f.format, AST_FORMAT_SLINEAR, 0); InitMP3Constants(); - return ast_format_register(&mp3_f); + return ast_format_def_register(&mp3_f); } static int unload_module(void) { - return ast_format_unregister(name); + return ast_format_def_unregister(name); } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "MP3 format [Any rate but 8000hz mono is optimal]"); diff --git a/addons/ooh323cDriver.c b/addons/ooh323cDriver.c index dd07bb4b017d240c4e7aa8a68a403c94d468237c..604336c211c747b394b4ba3286a77c5b55c904f1 100644 --- a/addons/ooh323cDriver.c +++ b/addons/ooh323cDriver.c @@ -226,15 +226,16 @@ int ooh323c_stop_stack_thread(void) } int ooh323c_set_capability - (struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec) + (struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec) { - int ret = 0, x, format=0; + int ret = 0, x; + struct ast_format tmpfmt; if(gH323Debug) ast_verbose("\tAdding capabilities to H323 endpoint\n"); - for(x=0; 0 != (format=ast_codec_pref_index(prefs, x)); x++) + for(x=0; ast_codec_pref_index(prefs, x, &tmpfmt); x++) { - if(format & AST_FORMAT_ULAW) + if(tmpfmt.id == AST_FORMAT_ULAW) { if(gH323Debug) ast_verbose("\tAdding g711 ulaw capability to H323 endpoint\n"); @@ -244,7 +245,7 @@ int ooh323c_set_capability &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); } - if(format & AST_FORMAT_ALAW) + if(tmpfmt.id == AST_FORMAT_ALAW) { if(gH323Debug) ast_verbose("\tAdding g711 alaw capability to H323 endpoint\n"); @@ -255,7 +256,7 @@ int ooh323c_set_capability &ooh323c_stop_transmit_channel); } - if(format & AST_FORMAT_G729A) + if(tmpfmt.id == AST_FORMAT_G729A) { if(gH323Debug) ast_verbose("\tAdding g729A capability to H323 endpoint\n"); @@ -281,7 +282,7 @@ int ooh323c_set_capability &ooh323c_stop_transmit_channel); } - if(format & AST_FORMAT_G723_1) + if(tmpfmt.id == AST_FORMAT_G723_1) { if(gH323Debug) ast_verbose("\tAdding g7231 capability to H323 endpoint\n"); @@ -293,7 +294,7 @@ int ooh323c_set_capability } - if(format & AST_FORMAT_G726) + if(tmpfmt.id == AST_FORMAT_G726) { if(gH323Debug) ast_verbose("\tAdding g726 capability to H323 endpoint\n"); @@ -305,7 +306,7 @@ int ooh323c_set_capability } - if(format & AST_FORMAT_G726_AAL2) + if(tmpfmt.id == AST_FORMAT_G726_AAL2) { if(gH323Debug) ast_verbose("\tAdding g726aal2 capability to H323 endpoint\n"); @@ -317,7 +318,7 @@ int ooh323c_set_capability } - if(format & AST_FORMAT_H263) + if(tmpfmt.id == AST_FORMAT_H263) { if(gH323Debug) ast_verbose("\tAdding h263 capability to H323 endpoint\n"); @@ -329,7 +330,7 @@ int ooh323c_set_capability } - if(format & AST_FORMAT_GSM) + if(tmpfmt.id == AST_FORMAT_GSM) { if(gH323Debug) ast_verbose("\tAdding gsm capability to H323 endpoint\n"); @@ -342,7 +343,7 @@ int ooh323c_set_capability } #ifdef AST_FORMAT_AMRNB - if(format & AST_FORMAT_AMRNB) + if(tmpfmt.id == AST_FORMAT_AMRNB) { if(gH323Debug) ast_verbose("\tAdding amr nb capability to H323 endpoint\n"); @@ -356,7 +357,7 @@ int ooh323c_set_capability #endif #ifdef AST_FORMAT_SPEEX - if(format & AST_FORMAT_SPEEX) + if(tmpfmt.id == AST_FORMAT_SPEEX) { if(gH323Debug) ast_verbose("\tAdding speex capability to H323 endpoint\n"); @@ -384,11 +385,11 @@ int ooh323c_set_capability } int ooh323c_set_capability_for_call - (ooCallData *call, struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec, + (ooCallData *call, struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec, int t38support) { int ret = 0, x, txframes; - int format=0; + struct ast_format tmpfmt; if(gH323Debug) ast_verbose("\tAdding capabilities to call(%s, %s)\n", call->callType, call->callToken); @@ -409,9 +410,9 @@ int ooh323c_set_capability_for_call &ooh323c_stop_transmit_datachannel, 0); - for(x=0; 0 !=(format=ast_codec_pref_index(prefs, x)); x++) + for(x=0; ast_codec_pref_index(prefs, x, &tmpfmt); x++) { - if(format & AST_FORMAT_ULAW) + if(tmpfmt.id == AST_FORMAT_ULAW) { if(gH323Debug) ast_verbose("\tAdding g711 ulaw capability to call(%s, %s)\n", @@ -424,7 +425,7 @@ int ooh323c_set_capability_for_call &ooh323c_stop_receive_channel, &ooh323c_stop_transmit_channel); } - if(format & AST_FORMAT_ALAW) + if(tmpfmt.id == AST_FORMAT_ALAW) { if(gH323Debug) ast_verbose("\tAdding g711 alaw capability to call(%s, %s)\n", @@ -438,7 +439,7 @@ int ooh323c_set_capability_for_call &ooh323c_stop_transmit_channel); } - if(format & AST_FORMAT_G726) + if(tmpfmt.id == AST_FORMAT_G726) { if(gH323Debug) ast_verbose("\tAdding g726 capability to call (%s, %s)\n", @@ -452,7 +453,7 @@ int ooh323c_set_capability_for_call } - if(format & AST_FORMAT_G726_AAL2) + if(tmpfmt.id == AST_FORMAT_G726_AAL2) { if(gH323Debug) ast_verbose("\tAdding g726aal2 capability to call (%s, %s)\n", @@ -466,7 +467,7 @@ int ooh323c_set_capability_for_call } - if(format & AST_FORMAT_G729A) + if(tmpfmt.id == AST_FORMAT_G729A) { txframes = (prefs->framing[x])/10; @@ -497,7 +498,7 @@ int ooh323c_set_capability_for_call } - if(format & AST_FORMAT_G723_1) + if(tmpfmt.id == AST_FORMAT_G723_1) { if(gH323Debug) ast_verbose("\tAdding g7231 capability to call (%s, %s)\n", @@ -510,7 +511,7 @@ int ooh323c_set_capability_for_call } - if(format & AST_FORMAT_H263) + if(tmpfmt.id == AST_FORMAT_H263) { if(gH323Debug) ast_verbose("\tAdding h263 capability to call (%s, %s)\n", @@ -523,7 +524,7 @@ int ooh323c_set_capability_for_call } - if(format & AST_FORMAT_GSM) + if(tmpfmt.id == AST_FORMAT_GSM) { if(gH323Debug) ast_verbose("\tAdding gsm capability to call(%s, %s)\n", @@ -536,7 +537,7 @@ int ooh323c_set_capability_for_call } #ifdef AST_FORMAT_AMRNB - if(format & AST_FORMAT_AMRNB) + if(tmpfmt.id == AST_FORMAT_AMRNB) { if(gH323Debug) ast_verbose("\tAdding AMR capability to call(%s, %s)\n", @@ -549,7 +550,7 @@ int ooh323c_set_capability_for_call } #endif #ifdef AST_FORMAT_SPEEX - if(format & AST_FORMAT_SPEEX) + if(tmpfmt.id == AST_FORMAT_SPEEX) { if(gH323Debug) ast_verbose("\tAdding Speex capability to call(%s, %s)\n", @@ -594,9 +595,9 @@ int ooh323c_set_aliases(ooAliases * aliases) int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel) { - format_t fmt=-1; - fmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap); - if(fmt>0) { + struct ast_format tmpfmt; + convertH323CapToAsteriskCap(pChannel->chanCap->cap, &tmpfmt); + if(tmpfmt.id) { /* ooh323_set_read_format(call, fmt); */ }else{ ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n", @@ -608,19 +609,19 @@ int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel) int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel) { - format_t fmt; - fmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap); - if(fmt>0) { - switch (fmt) { + struct ast_format tmpfmt; + convertH323CapToAsteriskCap(pChannel->chanCap->cap, &tmpfmt); + if(tmpfmt.id) { + switch (tmpfmt.id) { case AST_FORMAT_ALAW: case AST_FORMAT_ULAW: - ooh323_set_write_format(call, fmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes); + ooh323_set_write_format(call, &tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes); break; case AST_FORMAT_G729A: - ooh323_set_write_format(call, fmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10); + ooh323_set_write_format(call, &tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10); break; default: - ooh323_set_write_format(call, fmt, 0); + ooh323_set_write_format(call, &tmpfmt, 0); } }else{ ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n", @@ -665,47 +666,47 @@ int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChann return 1; } -format_t convertH323CapToAsteriskCap(int cap) +struct ast_format *convertH323CapToAsteriskCap(int cap, struct ast_format *result) { - + ast_format_clear(result); switch(cap) { case OO_G711ULAW64K: - return AST_FORMAT_ULAW; + return ast_format_set(result, AST_FORMAT_ULAW, 0); case OO_G711ALAW64K: - return AST_FORMAT_ALAW; + return ast_format_set(result, AST_FORMAT_ALAW, 0); case OO_GSMFULLRATE: - return AST_FORMAT_GSM; + return ast_format_set(result, AST_FORMAT_GSM, 0); #ifdef AST_FORMAT_AMRNB case OO_AMRNB: - return AST_FORMAT_AMRNB; + return ast_format_set(result, AST_FORMAT_AMRNB, 0); #endif #ifdef AST_FORMAT_SPEEX case OO_SPEEX: - return AST_FORMAT_SPEEX; + return ast_format_set(result, AST_FORMAT_SPEEX, 0); #endif case OO_G729: - return AST_FORMAT_G729A; + return ast_format_set(result, AST_FORMAT_G729A, 0); case OO_G729A: - return AST_FORMAT_G729A; + return ast_format_set(result, AST_FORMAT_G729A, 0); case OO_G729B: - return AST_FORMAT_G729A; + return ast_format_set(result, AST_FORMAT_G729A, 0); case OO_G7231: - return AST_FORMAT_G723_1; + return ast_format_set(result, AST_FORMAT_G723_1, 0); case OO_G726: - return AST_FORMAT_G726; + return ast_format_set(result, AST_FORMAT_G726, 0); case OO_G726AAL2: - return AST_FORMAT_G726_AAL2; + return ast_format_set(result, AST_FORMAT_G726_AAL2, 0); case OO_H263VIDEO: - return AST_FORMAT_H263; + return ast_format_set(result, AST_FORMAT_H263, 0); default: ast_debug(1, "Cap %d is not supported by driver yet\n", cap); - return -1; + return NULL; } - return -1; + return NULL; } diff --git a/addons/ooh323cDriver.h b/addons/ooh323cDriver.h index 269c56a719c37ce79ca4ecabaf183657c3fa2545..f16b8af2425699c191d8b32dbaa65e62ab084679 100644 --- a/addons/ooh323cDriver.h +++ b/addons/ooh323cDriver.h @@ -22,7 +22,7 @@ #include "ooCalls.h" #include "ooCapability.h" #include "ooStackCmds.h" -#include "asterisk/frame_defs.h" +#include "asterisk/format.h" #define H323_DTMF_RFC2833 (1 << 0) #define H323_DTMF_Q931 (1 << 1) #define H323_DTMF_H245ALPHANUMERIC (1 << 2) @@ -37,9 +37,9 @@ int ooh323c_stop_stack_thread(void); int ooh323c_start_call_thread(ooCallData *call); int ooh323c_stop_call_thread(ooCallData *call); int ooh323c_set_capability - (struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec); -format_t convertH323CapToAsteriskCap(int cap); + (struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec); +struct ast_format *convertH323CapToAsteriskCap(int cap, struct ast_format *format); int ooh323c_set_capability_for_call - (ooCallData *call, struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec, + (ooCallData *call, struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec, int t38support); #endif diff --git a/apps/app_alarmreceiver.c b/apps/app_alarmreceiver.c index 952ef722e01ad154840417435688716aeffacd24..6936cb5a0d5ad7bd468c6cb78ff089aaf3054899 100644 --- a/apps/app_alarmreceiver.c +++ b/apps/app_alarmreceiver.c @@ -191,7 +191,7 @@ static int send_tone_burst(struct ast_channel *chan, float freq, int duration, i if (f->frametype == AST_FRAME_VOICE) { wf.frametype = AST_FRAME_VOICE; - wf.subclass.codec = AST_FORMAT_ULAW; + ast_format_set(&wf.subclass.format, AST_FORMAT_ULAW, 0); wf.offset = AST_FRIENDLY_OFFSET; wf.mallocd = 0; wf.data.ptr = tone_block.buf; @@ -578,12 +578,12 @@ static int alarmreceiver_exec(struct ast_channel *chan, const char *data) /* Set write and read formats to ULAW */ ast_verb(4, "AlarmReceiver: Setting read and write formats to ULAW\n"); - if (ast_set_write_format(chan,AST_FORMAT_ULAW)) { + if (ast_set_write_format_by_id(chan,AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name); return -1; } - if (ast_set_read_format(chan,AST_FORMAT_ULAW)) { + if (ast_set_read_format_by_id(chan,AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name); return -1; } diff --git a/apps/app_amd.c b/apps/app_amd.c index c978ce0f41291643c9d5a41e9bba3cfc2ad93e54..60c13fd956f4c0334c8bc77ebd1e5f076c417dfc 100644 --- a/apps/app_amd.c +++ b/apps/app_amd.c @@ -148,7 +148,8 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data) int res = 0; struct ast_frame *f = NULL; struct ast_dsp *silenceDetector = NULL; - int dspsilence = 0, readFormat, framelength = 0; + int dspsilence = 0, framelength = 0; + struct ast_format readFormat; int inInitialSilence = 1; int inGreeting = 0; int voiceDuration = 0; @@ -188,10 +189,11 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data) AST_APP_ARG(argMaximumWordLength); ); + ast_format_clear(&readFormat); ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", chan->name, S_COR(chan->caller.ani.number.valid, chan->caller.ani.number.str, "(N/A)"), S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "(N/A)"), - ast_getformatname(chan->readformat)); + ast_getformatname(&chan->readformat)); /* Lets parse the arguments. */ if (!ast_strlen_zero(parse)) { @@ -240,8 +242,8 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data) minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold, maximumWordLength); /* Set read format to signed linear so we get signed linear frames in */ - readFormat = chan->readformat; - if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0 ) { + ast_format_copy(&readFormat, &chan->readformat); + if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0 ) { ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", chan->name ); pbx_builtin_setvar_helper(chan , "AMDSTATUS", ""); pbx_builtin_setvar_helper(chan , "AMDCAUSE", ""); @@ -399,7 +401,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data) pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause); /* Restore channel read format */ - if (readFormat && ast_set_read_format(chan, readFormat)) + if (readFormat.id && ast_set_read_format(chan, &readFormat)) ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name); /* Free the DSP used to detect silence */ diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 4b671df266bb4764fd30607383a1323069ae9bdb..1fc544afb58390157c9c51fb881c975b0b470845 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -427,6 +427,9 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl { struct chanspy_translation_helper *csth = data; struct ast_frame *f, *cur; + struct ast_format format_slin; + + ast_format_set(&format_slin, AST_FORMAT_SLINEAR, 0); ast_audiohook_lock(&csth->spy_audiohook); if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) { @@ -437,9 +440,9 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl if (ast_test_flag(&csth->spy_audiohook, OPTION_READONLY)) { /* Option 'o' was set, so don't mix channel audio */ - f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_READ, AST_FORMAT_SLINEAR); + f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_READ, &format_slin); } else { - f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR); + f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, &format_slin); } ast_audiohook_unlock(&csth->spy_audiohook); @@ -1006,7 +1009,7 @@ static int chanspy_exec(struct ast_channel *chan, const char *data) .volume = '#', .exit = '\0', }; - int oldwf = 0; + struct ast_format oldwf; int volfactor = 0; int res; char *mailbox = NULL; @@ -1019,6 +1022,7 @@ static int chanspy_exec(struct ast_channel *chan, const char *data) char *parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); + ast_format_clear(&oldwf); if (args.spec && !strcmp(args.spec, "all")) args.spec = NULL; @@ -1082,8 +1086,8 @@ static int chanspy_exec(struct ast_channel *chan, const char *data) ast_clear_flag(&flags, AST_FLAGS_ALL); } - oldwf = chan->writeformat; - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { + ast_format_copy(&oldwf, &chan->writeformat); + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); return -1; } @@ -1103,7 +1107,7 @@ static int chanspy_exec(struct ast_channel *chan, const char *data) if (fd) close(fd); - if (oldwf && ast_set_write_format(chan, oldwf) < 0) + if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0) ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); if (ast_test_flag(&flags, OPTION_EXITONHANGUP)) { @@ -1125,7 +1129,7 @@ static int extenspy_exec(struct ast_channel *chan, const char *data) .volume = '#', .exit = '\0', }; - int oldwf = 0; + struct ast_format oldwf; int volfactor = 0; int res; char *mailbox = NULL; @@ -1137,12 +1141,13 @@ static int extenspy_exec(struct ast_channel *chan, const char *data) char *parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); + ast_format_clear(&oldwf); + if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) { exten = args.context; *ptr++ = '\0'; args.context = ptr; } - if (ast_strlen_zero(args.context)) args.context = ast_strdupa(chan->context); @@ -1206,7 +1211,7 @@ static int extenspy_exec(struct ast_channel *chan, const char *data) } oldwf = chan->writeformat; - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); return -1; } @@ -1227,7 +1232,7 @@ static int extenspy_exec(struct ast_channel *chan, const char *data) if (fd) close(fd); - if (oldwf && ast_set_write_format(chan, oldwf) < 0) + if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0) ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); return res; @@ -1242,12 +1247,12 @@ static int dahdiscan_exec(struct ast_channel *chan, const char *data) .volume = '\0', .exit = '*', }; - int oldwf = 0; + struct ast_format oldwf; int res; char *mygroup = NULL; ast_clear_flag(&flags, AST_FLAGS_ALL); - + ast_format_clear(&oldwf); if (!ast_strlen_zero(data)) { mygroup = ast_strdupa(data); } @@ -1255,15 +1260,15 @@ static int dahdiscan_exec(struct ast_channel *chan, const char *data) ast_set_flag(&flags, OPTION_DTMF_CYCLE); ast_set_flag(&flags, OPTION_DAHDI_SCAN); - oldwf = chan->writeformat; - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { + ast_format_copy(&oldwf, &chan->writeformat); + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); return -1; } res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL); - if (oldwf && ast_set_write_format(chan, oldwf) < 0) + if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0) ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); return res; diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 71608d42601584dce71269b3c301140209570113..e533c80e7d322ac9de16100aaa7dc01a2e2c35a6 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -568,11 +568,18 @@ static int play_sound_file(struct conference_bridge *conference_bridge, const ch if (!(conference_bridge->playback_chan)) { int cause; - - if (!(conference_bridge->playback_chan = ast_request("Bridge", AST_FORMAT_SLINEAR, NULL, "", &cause))) { + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + struct ast_format tmpfmt; + if (!cap) { + return -1; + } + ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + if (!(conference_bridge->playback_chan = ast_request("Bridge", cap, NULL, "", &cause))) { ast_mutex_unlock(&conference_bridge->playback_lock); + cap = ast_format_cap_destroy(cap); return -1; } + cap = ast_format_cap_destroy(cap); conference_bridge->playback_chan->bridge = conference_bridge->bridge; diff --git a/apps/app_dahdibarge.c b/apps/app_dahdibarge.c index d9dd59054df07316506c54389956b7f8ba4af57e..082405e80ec7cb502d449116db34491977b9e52e 100644 --- a/apps/app_dahdibarge.c +++ b/apps/app_dahdibarge.c @@ -113,13 +113,13 @@ static int conf_run(struct ast_channel *chan, int confno, int confflags) char *buf = __buf + AST_FRIENDLY_OFFSET; /* Set it into U-law mode (write) */ - if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name); goto outrun; } /* Set it into U-law mode (read) */ - if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) { + if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); goto outrun; } @@ -214,11 +214,11 @@ dahdiretry: break; } else if (fd != chan->fds[0]) { if (f->frametype == AST_FRAME_VOICE) { - if (f->subclass.codec == AST_FORMAT_ULAW) { + if (f->subclass.format.id == AST_FORMAT_ULAW) { /* Carefully write */ careful_write(fd, f->data.ptr, f->datalen); } else - ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%s) frame in the conference\n", ast_getformatname(f->subclass.codec)); + ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%s) frame in the conference\n", ast_getformatname(&f->subclass.format)); } } ast_frfree(f); @@ -227,7 +227,7 @@ dahdiretry: if (res > 0) { memset(&fr, 0, sizeof(fr)); fr.frametype = AST_FRAME_VOICE; - fr.subclass.codec = AST_FORMAT_ULAW; + ast_format_set(&fr.subclass.format, AST_FORMAT_ULAW, 0); fr.datalen = res; fr.samples = res; fr.data.ptr = buf; diff --git a/apps/app_dictate.c b/apps/app_dictate.c index e9e5f0d53d288f60ad5e9ac6fd9e347609187466..5bf439d1609b923fde876b584fd4e022d3d6e0cb 100644 --- a/apps/app_dictate.c +++ b/apps/app_dictate.c @@ -97,7 +97,6 @@ static int dictate_exec(struct ast_channel *chan, const char *data) int ffactor = 320 * 80, res = 0, done = 0, - oldr = 0, lastop = 0, samples = 0, speed = 1, @@ -105,6 +104,8 @@ static int dictate_exec(struct ast_channel *chan, const char *data) len = 0, maxlen = 0, mode = 0; + struct ast_format oldr; + ast_format_clear(&oldr); snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR); if (!ast_strlen_zero(data)) { @@ -121,8 +122,8 @@ static int dictate_exec(struct ast_channel *chan, const char *data) if (args.argc > 1 && args.filename) { filename = args.filename; } - oldr = chan->readformat; - if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) { + ast_format_copy(&oldr, &chan->readformat); + if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) { ast_log(LOG_WARNING, "Unable to set to linear mode.\n"); return -1; } @@ -330,8 +331,8 @@ static int dictate_exec(struct ast_channel *chan, const char *data) ast_frfree(f); } } - if (oldr) { - ast_set_read_format(chan, oldr); + if (oldr.id) { + ast_set_read_format(chan, &oldr); } return 0; } diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c index feaeda29e7df646d752877dd247bea9e98a62185..47888935bbfd7692ca631aef53c9de670f1d8afe 100644 --- a/apps/app_dumpchan.c +++ b/apps/app_dumpchan.c @@ -126,10 +126,10 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size) c->_state, c->rings, ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->nativeformats), - ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->writeformat), - ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->readformat), - ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->rawwriteformat), - ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->rawreadformat), + ast_getformatname(&c->writeformat), + ast_getformatname(&c->readformat), + ast_getformatname(&c->rawwriteformat), + ast_getformatname(&c->rawreadformat), c->fds[0], c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)c->whentohangup.tv_sec, hour, diff --git a/apps/app_echo.c b/apps/app_echo.c index 1c721106075b7ffc75a3658c9356cb0e34f6817b..ab991427ddc3c8b5e9f9ccd4430100e8fdede206 100644 --- a/apps/app_echo.c +++ b/apps/app_echo.c @@ -51,11 +51,11 @@ static const char app[] = "Echo"; static int echo_exec(struct ast_channel *chan, const char *data) { int res = -1; - format_t format; + struct ast_format format; - format = ast_best_codec(chan->nativeformats); - ast_set_write_format(chan, format); - ast_set_read_format(chan, format); + ast_best_codec(chan->nativeformats, &format); + ast_set_write_format(chan, &format); + ast_set_read_format(chan, &format); while (ast_waitfor(chan, -1) > -1) { struct ast_frame *f = ast_read(chan); diff --git a/apps/app_fax.c b/apps/app_fax.c index 54d22db1695da46d443e5dfa6e9e0f3ed6b259b3..ce8541910159d859e39c499e29d2ce5657df5d00 100644 --- a/apps/app_fax.c +++ b/apps/app_fax.c @@ -329,9 +329,9 @@ static int fax_generator_generate(struct ast_channel *chan, void *data, int len, struct ast_frame outf = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .src = __FUNCTION__, }; + ast_format_set(&outf.subclass.format, AST_FORMAT_SLINEAR, 0); if (samples > MAX_SAMPLES) { ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples); @@ -362,8 +362,8 @@ static struct ast_generator generator = { static int transmit_audio(fax_session *s) { int res = -1; - int original_read_fmt = AST_FORMAT_SLINEAR; - int original_write_fmt = AST_FORMAT_SLINEAR; + struct ast_format original_read_fmt; + struct ast_format original_write_fmt; fax_state_t fax; t30_state_t *t30state; struct ast_frame *inf = NULL; @@ -383,6 +383,9 @@ static int transmit_audio(fax_session *s) */ }; + ast_format_clear(&original_read_fmt); + ast_format_clear(&original_write_fmt); + /* if in called party mode, try to use T.38 */ if (s->caller_mode == FALSE) { /* check if we are already in T.38 mode (unlikely), or if we can request @@ -455,18 +458,18 @@ static int transmit_audio(fax_session *s) t30state = &fax.t30_state; #endif - original_read_fmt = s->chan->readformat; - if (original_read_fmt != AST_FORMAT_SLINEAR) { - res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR); + ast_format_copy(&original_read_fmt, &s->chan->readformat); + if (original_read_fmt.id != AST_FORMAT_SLINEAR) { + res = ast_set_read_format_by_id(s->chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n"); goto done; } } - original_write_fmt = s->chan->writeformat; - if (original_write_fmt != AST_FORMAT_SLINEAR) { - res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR); + ast_format_copy(&original_write_fmt, &s->chan->writeformat); + if (original_write_fmt.id != AST_FORMAT_SLINEAR) { + res = ast_set_write_format_by_id(s->chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n"); goto done; @@ -523,12 +526,12 @@ static int transmit_audio(fax_session *s) break; } - ast_debug(10, "frame %d/%llu, len=%d\n", inf->frametype, (unsigned long long) inf->subclass.codec, inf->datalen); + ast_debug(10, "frame %d/%u, len=%d\n", inf->frametype, (unsigned int) inf->subclass.format.id, inf->datalen); /* Check the frame type. Format also must be checked because there is a chance that a frame in old format was already queued before we set channel format to slinear so it will still be received by ast_read */ - if (inf->frametype == AST_FRAME_VOICE && inf->subclass.codec == AST_FORMAT_SLINEAR) { + if (inf->frametype == AST_FRAME_VOICE && inf->subclass.format.id == AST_FORMAT_SLINEAR) { if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) { /* I know fax_rx never returns errors. The check here is for good style only */ ast_log(LOG_WARNING, "fax_rx returned error\n"); @@ -582,13 +585,13 @@ static int transmit_audio(fax_session *s) fax_release(&fax); done: - if (original_write_fmt != AST_FORMAT_SLINEAR) { - if (ast_set_write_format(s->chan, original_write_fmt) < 0) + if (original_write_fmt.id != AST_FORMAT_SLINEAR) { + if (ast_set_write_format(s->chan, &original_write_fmt) < 0) ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name); } - if (original_read_fmt != AST_FORMAT_SLINEAR) { - if (ast_set_read_format(s->chan, original_read_fmt) < 0) + if (original_read_fmt.id != AST_FORMAT_SLINEAR) { + if (ast_set_read_format(s->chan, &original_read_fmt) < 0) ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name); } diff --git a/apps/app_festival.c b/apps/app_festival.c index ef8827adb1245fb9bdee74cddda2ef5259f7e7c2..f6f3734cac83e276c11efc45a703e8c5ac3f8201 100644 --- a/apps/app_festival.c +++ b/apps/app_festival.c @@ -165,7 +165,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in int fds[2]; int pid = -1; int needed = 0; - int owriteformat; + struct ast_format owriteformat; struct ast_frame *f; struct myframe { struct ast_frame f; @@ -175,6 +175,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in .f = { 0, }, }; + ast_format_clear(&owriteformat); if (pipe(fds)) { ast_log(LOG_WARNING, "Unable to create pipe\n"); return -1; @@ -186,8 +187,8 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in ast_stopstream(chan); ast_indicate(chan, -1); - owriteformat = chan->writeformat; - res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); + ast_format_copy(&owriteformat, &chan->writeformat); + res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); return -1; @@ -229,7 +230,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in res = read(fds[0], myf.frdata, needed); if (res > 0) { myf.f.frametype = AST_FRAME_VOICE; - myf.f.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0); myf.f.datalen = res; myf.f.samples = res / 2; myf.f.offset = AST_FRIENDLY_OFFSET; @@ -261,8 +262,8 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in if (pid > -1) kill(pid, SIGKILL); #endif - if (!res && owriteformat) - ast_set_write_format(chan, owriteformat); + if (!res && owriteformat.id) + ast_set_write_format(chan, &owriteformat); return res; } diff --git a/apps/app_followme.c b/apps/app_followme.c index 95b1ceafbed5af0049a8d3dc5348e67db9350f46..8b9f1061b998315bc23fbfde4d9c21d59a3859bb 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -848,7 +848,7 @@ static void findmeexec(struct fm_args *tpargs) return; } - outbound = ast_request("Local", ast_best_codec(caller->nativeformats), caller, dialarg, &dg); + outbound = ast_request("Local", caller->nativeformats, caller, dialarg, &dg); if (outbound) { ast_set_callerid(outbound, S_COR(caller->caller.id.number.valid, caller->caller.id.number.str, NULL), diff --git a/apps/app_ices.c b/apps/app_ices.c index f2b9498a6fa8a17e7645c42ec79298aa52f0c9c2..b7eea944cfd584c2df4d475fd5e3c8d7dfc521a2 100644 --- a/apps/app_ices.c +++ b/apps/app_ices.c @@ -111,12 +111,13 @@ static int ices_exec(struct ast_channel *chan, const char *data) int ms = -1; int pid = -1; int flags; - int oreadformat; + struct ast_format oreadformat; struct timeval last; struct ast_frame *f; char filename[256]=""; char *c; + ast_format_clear(&oreadformat); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n"); return -1; @@ -143,8 +144,8 @@ static int ices_exec(struct ast_channel *chan, const char *data) return -1; } - oreadformat = chan->readformat; - res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); + ast_format_copy(&oreadformat, &chan->readformat); + res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { close(fds[0]); close(fds[1]); @@ -195,8 +196,8 @@ static int ices_exec(struct ast_channel *chan, const char *data) if (pid > -1) kill(pid, SIGKILL); - if (!res && oreadformat) - ast_set_read_format(chan, oreadformat); + if (!res && oreadformat.id) + ast_set_read_format(chan, &oreadformat); return res; } diff --git a/apps/app_jack.c b/apps/app_jack.c index 2f263b6936a060b150a410801c495c2eb872ace3..d073451a8ac1db713bce141815d1240b73a17970 100644 --- a/apps/app_jack.c +++ b/apps/app_jack.c @@ -604,12 +604,12 @@ static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_d short buf[160]; struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .src = "JACK", .data.ptr = buf, .datalen = sizeof(buf), .samples = ARRAY_LEN(buf), }; + ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0); for (;;) { size_t res, read_len; @@ -754,12 +754,12 @@ static int jack_exec(struct ast_channel *chan, const char *data) return -1; } - if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { + if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) { destroy_jack_data(jack_data); return -1; } - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) { destroy_jack_data(jack_data); return -1; } @@ -823,9 +823,9 @@ static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channe if (frame->frametype != AST_FRAME_VOICE) return 0; - if (frame->subclass.codec != AST_FORMAT_SLINEAR) { + if (frame->subclass.format.id != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Expected frame in SLINEAR for the audiohook, but got format %s\n", - ast_getformatname(frame->subclass.codec)); + ast_getformatname(&frame->subclass.format)); return 0; } diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 18b1e11003e30be8a79f8f01160f536674e4e971..ae60cfb905e40c8499e94318dde02fa8bbfe5ca9 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -1189,6 +1189,8 @@ static struct ast_conference *build_conf(const char *confno, const char *pin, struct ast_conference *cnf; struct dahdi_confinfo dahdic = { 0, }; int confno_int = 0; + struct ast_format_cap *cap_slin = ast_format_cap_alloc_nolock(); + struct ast_format tmp_fmt; AST_LIST_LOCK(&confs); @@ -1197,9 +1199,10 @@ static struct ast_conference *build_conf(const char *confno, const char *pin, break; } - if (cnf || (!make && !dynamic)) + if (cnf || (!make && !dynamic) || !cap_slin) goto cnfout; + ast_format_cap_add(cap_slin, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0)); /* Make a new one */ if (!(cnf = ast_calloc(1, sizeof(*cnf))) || !(cnf->usercontainer = ao2_container_alloc(1, NULL, user_no_cmp))) { @@ -1245,10 +1248,10 @@ static struct ast_conference *build_conf(const char *confno, const char *pin, cnf->dahdiconf = dahdic.confno; /* Setup a new channel for playback of audio files */ - cnf->chan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL); + cnf->chan = ast_request("DAHDI", cap_slin, chan, "pseudo", NULL); if (cnf->chan) { - ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); - ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(cnf->chan, AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(cnf->chan, AST_FORMAT_SLINEAR); dahdic.chan = 0; dahdic.confno = cnf->dahdiconf; dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; @@ -1284,6 +1287,7 @@ static struct ast_conference *build_conf(const char *confno, const char *pin, conf_map[confno_int] = 1; cnfout: + cap_slin = ast_format_cap_destroy(cap_slin); if (cnf) ast_atomic_fetchadd_int(&cnf->refcount, refcount); @@ -2260,9 +2264,16 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc int setusercount = 0; int confsilence = 0, totalsilence = 0; char *mailbox, *context; + struct ast_format_cap *cap_slin = ast_format_cap_alloc_nolock(); + struct ast_format tmpfmt; + + if (!cap_slin) { + goto conf_run_cleanup; + } + ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); if (!(user = ao2_alloc(sizeof(*user), NULL))) { - return ret; + goto conf_run_cleanup; } /* Possible timeout waiting for marked user */ @@ -2372,9 +2383,9 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc ast_mutex_lock(&conf->recordthreadlock); if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && - ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { - ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); - ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); + ((conf->lchan = ast_request("DAHDI", cap_slin, chan, "pseudo", NULL)))) { + ast_set_read_format_by_id(conf->lchan, AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(conf->lchan, AST_FORMAT_SLINEAR); dahdic.chan = 0; dahdic.confno = conf->dahdiconf; dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; @@ -2601,12 +2612,12 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc ast_indicate(chan, -1); } - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); goto outrun; } - if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { + if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); goto outrun; } @@ -3167,7 +3178,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc dtmfstr[1] = '\0'; } - if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.codec == AST_FORMAT_SLINEAR)) { + if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) { if (user->talk.actual) { ast_frame_adjust_volume(f, user->talk.actual); } @@ -3339,9 +3350,9 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc } ast_mutex_lock(&conf->recordthreadlock); - if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { - ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); - ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); + if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", cap_slin, chan, "pseudo", NULL)))) { + ast_set_read_format_by_id(conf->lchan, AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(conf->lchan, AST_FORMAT_SLINEAR); dahdic.chan = 0; dahdic.confno = conf->dahdiconf; dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; @@ -3627,7 +3638,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc if (res > 0) { memset(&fr, 0, sizeof(fr)); fr.frametype = AST_FRAME_VOICE; - fr.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&fr.subclass.format, AST_FORMAT_SLINEAR, 0); fr.datalen = res; fr.samples = res / 2; fr.data.ptr = buf; @@ -3639,7 +3650,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc )) { int idx; for (idx = 0; idx < AST_FRAME_BITS; idx++) { - if (chan->rawwriteformat & (1 << idx)) { + if (ast_format_to_old_bitfield(&chan->rawwriteformat) & (1 << idx)) { break; } } @@ -3654,7 +3665,11 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc mohtempstopped = 1; } if (!conf->transpath[idx]) { - conf->transpath[idx] = ast_translator_build_path((1 << idx), AST_FORMAT_SLINEAR); + struct ast_format src; + struct ast_format dst; + ast_format_set(&src, AST_FORMAT_SLINEAR, 0); + ast_format_from_old_bitfield(&dst, (1 << idx)); + conf->transpath[idx] = ast_translator_build_path(&dst, &src); } if (conf->transpath[idx]) { conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0); @@ -3821,6 +3836,10 @@ bailoutandtrynormal: ao2_ref(user, -1); AST_LIST_UNLOCK(&confs); + +conf_run_cleanup: + cap_slin = ast_format_cap_destroy(cap_slin); + return ret; } diff --git a/apps/app_milliwatt.c b/apps/app_milliwatt.c index 24137606d3191eb116432978e60914fa3a327fd0..26cba3c40f0e101c8b3f580015b8cc3e22c15afd 100644 --- a/apps/app_milliwatt.c +++ b/apps/app_milliwatt.c @@ -78,10 +78,10 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int int i, *indexp = (int *) data; struct ast_frame wf = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_ULAW, .offset = AST_FRIENDLY_OFFSET, .src = __FUNCTION__, }; + ast_format_set(&wf.subclass.format, AST_FORMAT_ULAW, 0); wf.data.ptr = buf + AST_FRIENDLY_OFFSET; /* Instead of len, use samples, because channel.c generator_force @@ -120,8 +120,8 @@ static struct ast_generator milliwattgen = { static int old_milliwatt_exec(struct ast_channel *chan) { - ast_set_write_format(chan, AST_FORMAT_ULAW); - ast_set_read_format(chan, AST_FORMAT_ULAW); + ast_set_write_format_by_id(chan, AST_FORMAT_ULAW); + ast_set_read_format_by_id(chan, AST_FORMAT_ULAW); if (chan->_state != AST_STATE_UP) { ast_answer(chan); diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index ca3a23991b8ad05b63f4946bef73e0946ea084cf..8e6adead194757f6565e2dd0c05788177f745978 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -281,7 +281,9 @@ static void *mixmonitor_thread(void *obj) unsigned int oflags; char *ext; int errflag = 0; + struct ast_format format_slin; + ast_format_set(&format_slin, AST_FORMAT_SLINEAR, 0); ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name); fs = &mixmonitor->mixmonitor_ds->fs; @@ -291,7 +293,7 @@ static void *mixmonitor_thread(void *obj) while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) { struct ast_frame *fr = NULL; - if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR))) { + if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, &format_slin))) { ast_audiohook_trigger_wait(&mixmonitor->audiohook); if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) { diff --git a/apps/app_mp3.c b/apps/app_mp3.c index f8e42a12c75a0a5d9bc23f026fb8340f67934bfc..f8c5a05781f98b8230d30461c29269ac78a02390 100644 --- a/apps/app_mp3.c +++ b/apps/app_mp3.c @@ -137,7 +137,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data) int fds[2]; int ms = -1; int pid = -1; - int owriteformat; + struct ast_format owriteformat; int timeout = 2000; struct timeval next; struct ast_frame *f; @@ -149,6 +149,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data) .f = { 0, }, }; + ast_format_clear(&owriteformat); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n"); return -1; @@ -161,8 +162,8 @@ static int mp3_exec(struct ast_channel *chan, const char *data) ast_stopstream(chan); - owriteformat = chan->writeformat; - res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); + ast_format_copy(&owriteformat, &chan->writeformat); + res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); return -1; @@ -185,7 +186,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data) res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); if (res > 0) { myf.f.frametype = AST_FRAME_VOICE; - myf.f.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0); myf.f.datalen = res; myf.f.samples = res / 2; myf.f.mallocd = 0; @@ -234,8 +235,8 @@ static int mp3_exec(struct ast_channel *chan, const char *data) if (pid > -1) kill(pid, SIGKILL); - if (!res && owriteformat) - ast_set_write_format(chan, owriteformat); + if (!res && owriteformat.id) + ast_set_write_format(chan, &owriteformat); return res; } diff --git a/apps/app_nbscat.c b/apps/app_nbscat.c index dd7637a83b763bfd0a716c444035ac0e3ffdda45..2bbde630e1060879e1d207a54370c521b5becb05 100644 --- a/apps/app_nbscat.c +++ b/apps/app_nbscat.c @@ -111,7 +111,7 @@ static int NBScat_exec(struct ast_channel *chan, const char *data) int fds[2]; int ms = -1; int pid = -1; - int owriteformat; + struct ast_format owriteformat; struct timeval next; struct ast_frame *f; struct myframe { @@ -119,7 +119,8 @@ static int NBScat_exec(struct ast_channel *chan, const char *data) char offset[AST_FRIENDLY_OFFSET]; short frdata[160]; } myf; - + + ast_format_clear(&owriteformat); if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) { ast_log(LOG_WARNING, "Unable to create socketpair\n"); return -1; @@ -127,8 +128,8 @@ static int NBScat_exec(struct ast_channel *chan, const char *data) ast_stopstream(chan); - owriteformat = chan->writeformat; - res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); + ast_format_copy(&owriteformat, &chan->writeformat); + res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); return -1; @@ -148,7 +149,7 @@ static int NBScat_exec(struct ast_channel *chan, const char *data) res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata)); if (res > 0) { myf.f.frametype = AST_FRAME_VOICE; - myf.f.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0); myf.f.datalen = res; myf.f.samples = res / 2; myf.f.mallocd = 0; @@ -197,8 +198,8 @@ static int NBScat_exec(struct ast_channel *chan, const char *data) if (pid > -1) kill(pid, SIGKILL); - if (!res && owriteformat) - ast_set_write_format(chan, owriteformat); + if (!res && owriteformat.id) + ast_set_write_format(chan, &owriteformat); return res; } diff --git a/apps/app_originate.c b/apps/app_originate.c index 659ea2949f02c05bb0bb72972b520497ce112a44..94ac3596cdb45539f2808ce3d888d5867fdc176d 100644 --- a/apps/app_originate.c +++ b/apps/app_originate.c @@ -105,8 +105,14 @@ static int originate_exec(struct ast_channel *chan, const char *data) int outgoing_status = 0; static const unsigned int timeout = 30; static const char default_exten[] = "s"; + struct ast_format tmpfmt; + struct ast_format_cap *cap_slin = ast_format_cap_alloc_nolock(); ast_autoservice_start(chan); + if (!cap_slin) { + goto return_cleanup; + } + ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); if (ast_strlen_zero(data)) { ast_log(LOG_ERROR, "Originate() requires arguments\n"); @@ -148,14 +154,14 @@ static int originate_exec(struct ast_channel *chan, const char *data) ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n", chantech, chandata, args.arg1, exten, priority); - outgoing_res = ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata, + outgoing_res = ast_pbx_outgoing_exten(chantech, cap_slin, chandata, timeout * 1000, args.arg1, exten, priority, &outgoing_status, 0, NULL, NULL, NULL, NULL, NULL); } else if (!strcasecmp(args.type, "app")) { ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n", chantech, chandata, args.arg1, S_OR(args.arg2, "")); - outgoing_res = ast_pbx_outgoing_app(chantech, AST_FORMAT_SLINEAR, chandata, + outgoing_res = ast_pbx_outgoing_app(chantech, cap_slin, chandata, timeout * 1000, args.arg1, args.arg2, &outgoing_status, 0, NULL, NULL, NULL, NULL, NULL); } else { @@ -194,7 +200,7 @@ return_cleanup: break; } } - + cap_slin = ast_format_cap_destroy(cap_slin); ast_autoservice_stop(chan); return res; diff --git a/apps/app_parkandannounce.c b/apps/app_parkandannounce.c index 5bb8b659465dc3164c727c47480a0681ed2e546f..fb3e713e13bd558c8e75e46470ebd691678cc495 100644 --- a/apps/app_parkandannounce.c +++ b/apps/app_parkandannounce.c @@ -96,6 +96,9 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data) struct ast_channel *dchan; struct outgoing_helper oh = { 0, }; int outstate; + struct ast_format tmpfmt; + struct ast_format_cap *cap_slin = ast_format_cap_alloc_nolock(); + AST_DECLARE_APP_ARGS(args, AST_APP_ARG(template); AST_APP_ARG(timeout); @@ -104,9 +107,15 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data) ); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n"); - return -1; + res = -1; + goto parkcleanup; + } + if (!cap_slin) { + res = -1; + goto parkcleanup; } - + ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + s = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, s); @@ -115,7 +124,8 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data) if (ast_strlen_zero(args.dial)) { ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or DAHDI/g1/5551212\n"); - return -1; + res = -1; + goto parkcleanup; } dialtech = strsep(&args.dial, "/"); @@ -138,8 +148,9 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data) before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */ res = ast_masq_park_call(chan, NULL, timeout, &lot); - if (res == -1) - return res; + if (res == -1) { + goto parkcleanup; + } ast_verb(3, "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, args.return_context); @@ -148,7 +159,7 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data) snprintf(buf, sizeof(buf), "%d", lot); oh.parent_channel = chan; oh.vars = ast_variable_new("_PARKEDAT", buf, ""); - dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, chan, args.dial, 30000, + dchan = __ast_request_and_dial(dialtech, cap_slin, chan, args.dial, 30000, &outstate, S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL), S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL), @@ -160,11 +171,13 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data) ast_verb(4, "Channel %s was never answered.\n", dchan->name); ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name); ast_hangup(dchan); - return -1; + res = -1; + goto parkcleanup; } } else { ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n"); - return -1; + res = -1; + goto parkcleanup; } ast_stopstream(dchan); @@ -197,7 +210,10 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data) ast_stopstream(dchan); ast_hangup(dchan); - + +parkcleanup: + cap_slin = ast_format_cap_destroy(cap_slin); + return res; } diff --git a/apps/app_record.c b/apps/app_record.c index 64e635018b6e9a1d5328eb3b7b08baca0e52491f..a192b1adc1fd46191b6fb7bab64c0d8022f864e7 100644 --- a/apps/app_record.c +++ b/apps/app_record.c @@ -154,7 +154,7 @@ static int record_exec(struct ast_channel *chan, const char *data) int maxduration = 0; /* max duration of recording in milliseconds */ int gottimeout = 0; /* did we timeout for maxduration exceeded? */ int terminator = '#'; - int rfmt = 0; + struct ast_format rfmt; int ioflags; int waitres; struct ast_silence_generator *silgen = NULL; @@ -165,7 +165,8 @@ static int record_exec(struct ast_channel *chan, const char *data) AST_APP_ARG(maxduration); AST_APP_ARG(options); ); - + + ast_format_clear(&rfmt); /* The next few lines of code parse out the filename and header from the input string */ if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */ ast_log(LOG_WARNING, "Record requires an argument (filename)\n"); @@ -286,8 +287,8 @@ static int record_exec(struct ast_channel *chan, const char *data) /* The end of beep code. Now the recording starts */ if (silence > 0) { - rfmt = chan->readformat; - res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); + ast_format_copy(&rfmt, &chan->readformat); + res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR"); @@ -408,8 +409,8 @@ static int record_exec(struct ast_channel *chan, const char *data) ast_channel_stop_silence_generator(chan, silgen); out: - if ((silence > 0) && rfmt) { - res = ast_set_read_format(chan, rfmt); + if ((silence > 0) && rfmt.id) { + res = ast_set_read_format(chan, &rfmt); if (res) ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); if (sildet) diff --git a/apps/app_rpt.c b/apps/app_rpt.c index a4d350d32eb3286977055e104d3499578048b421..765f73184b8714162e478256b071af78920cade7 100644 --- a/apps/app_rpt.c +++ b/apps/app_rpt.c @@ -882,6 +882,7 @@ static int setrem(struct rpt *myrpt); static int setrtx_check(struct rpt *myrpt); static int channel_revert(struct rpt *myrpt); static int channel_steer(struct rpt *myrpt, char *data); +static struct ast_format_cap *get_slin_cap(struct ast_format_cap *cap); AST_MUTEX_DEFINE_STATIC(nodeloglock); @@ -951,7 +952,6 @@ int i; return(NULL); } - static void rpt_mutex_spew(void) { struct by_lightning lock_ring_copy[32]; @@ -1070,6 +1070,18 @@ pthread_t id; #endif /* APP_RPT_LOCK_DEBUG */ +static struct ast_format_cap *get_slin_cap(struct ast_format_cap *cap) +{ + struct ast_format tmp; + cap = ast_format_cap_alloc_nolock(); + if (!cap) { + return NULL; + } + ast_format_cap_add(cap, ast_format_set(&tmp, AST_FORMAT_SLINEAR, 0)); + + return cap; +} + /* * Return 1 if rig is multimode capable */ @@ -3961,7 +3973,7 @@ char mhz[MAXREMSTR]; char decimals[MAXREMSTR]; char mystr[200]; struct dahdi_params par; - +struct ast_format_cap *cap = NULL; /* get a pointer to myrpt */ myrpt = mytele->rpt; @@ -4004,7 +4016,8 @@ struct dahdi_params par; /* allocate a pseudo-channel thru asterisk */ - mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + mychannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!mychannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -5288,10 +5301,12 @@ struct rpt *myrpt = (struct rpt *)this; int res; int stopped,congstarted,dialtimer,lastcidx,aborted; struct ast_channel *mychannel,*genchannel; +struct ast_format_cap *cap = NULL; myrpt->mydtmf = 0; /* allocate a pseudo-channel thru asterisk */ - mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + mychannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!mychannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -5317,7 +5332,8 @@ struct ast_channel *mychannel,*genchannel; pthread_exit(NULL); } /* allocate a pseudo-channel thru asterisk */ - genchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + genchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!genchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -5689,6 +5705,7 @@ static int connect_link(struct rpt *myrpt, char* node, int mode, int perma) int reconnects = 0; int i,n; struct dahdi_confinfo ci; /* conference info */ + struct ast_format_cap *cap = NULL; val = node_lookup(myrpt,node); if (!val){ @@ -5792,10 +5809,11 @@ static int connect_link(struct rpt *myrpt, char* node, int mode, int perma) return -1; } *tele++ = 0; - l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL); + l->chan = ast_request(deststr, get_slin_cap(cap), NULL, tele, NULL); + cap = ast_format_cap_destroy(cap); if (l->chan){ - ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); - ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(l->chan, AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(l->chan, AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (l->chan->cdr) ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -5827,15 +5845,16 @@ static int connect_link(struct rpt *myrpt, char* node, int mode, int perma) return -1; } /* allocate a pseudo-channel thru asterisk */ - l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + l->pchan = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!l->pchan){ ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n"); ast_hangup(l->chan); ast_free(l); return -1; } - ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR); - ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(l->pchan, AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(l->pchan, AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (l->pchan->cdr) ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -10341,6 +10360,7 @@ static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l) char *val, *s, *s1, *s2, *tele; char tmp[300], deststr[300] = ""; char sx[320],*sy; + struct ast_format_cap *cap = NULL; val = node_lookup(myrpt,l->name); @@ -10376,10 +10396,11 @@ static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l) l->connecttime = 0; l->thisconnected = 0; l->newkey = 0; - l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL); + l->chan = ast_request(deststr, get_slin_cap(cap), NULL, tele, NULL); + cap = ast_format_cap_destroy(cap); if (l->chan){ - ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); - ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(l->chan, AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(l->chan, AST_FORMAT_SLINEAR); #ifndef NEW_ASTERISK l->chan->whentohangup = 0; #endif @@ -10743,6 +10764,7 @@ time_t t; struct rpt_link *l,*m; struct rpt_tele *telem; char tmpstr[300],lstr[MAXLINKLIST]; +struct ast_format_cap *cap = NULL; if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600); @@ -10795,7 +10817,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; pthread_exit(NULL); } *tele++ = 0; - myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL); + myrpt->rxchannel = ast_request(tmpstr, get_slin_cap(cap), NULL, tele, NULL); + cap = ast_format_cap_destroy(cap); myrpt->dahdirxchannel = NULL; if (!strcasecmp(tmpstr,"DAHDI")) myrpt->dahdirxchannel = myrpt->rxchannel; @@ -10809,8 +10832,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; myrpt->rpt_thread = AST_PTHREADT_STOP; pthread_exit(NULL); } - ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->rxchannel->cdr) ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -10853,7 +10876,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; pthread_exit(NULL); } *tele++ = 0; - myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL); + myrpt->txchannel = ast_request(tmpstr, get_slin_cap(cap), NULL, tele, NULL); + cap = ast_format_cap_destroy(cap); if (!strcasecmp(tmpstr,"DAHDI")) myrpt->dahditxchannel = myrpt->txchannel; if (myrpt->txchannel) @@ -10867,8 +10891,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; myrpt->rpt_thread = AST_PTHREADT_STOP; pthread_exit(NULL); } - ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->txchannel->cdr) ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -10909,7 +10933,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY); ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); /* allocate a pseudo-channel thru asterisk */ - myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + myrpt->pchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!myrpt->pchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -10928,7 +10953,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; if (!myrpt->dahditxchannel) { /* allocate a pseudo-channel thru asterisk */ - myrpt->dahditxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + myrpt->dahditxchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!myrpt->dahditxchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -10939,15 +10965,16 @@ char tmpstr[300],lstr[MAXLINKLIST]; myrpt->rpt_thread = AST_PTHREADT_STOP; pthread_exit(NULL); } - ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->dahditxchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->dahditxchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->dahditxchannel->cdr) ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED); #endif } /* allocate a pseudo-channel thru asterisk */ - myrpt->monchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + myrpt->monchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!myrpt->monchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -10958,8 +10985,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; myrpt->rpt_thread = AST_PTHREADT_STOP; pthread_exit(NULL); } - ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->monchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->monchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->monchannel->cdr) ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -11042,7 +11069,8 @@ char tmpstr[300],lstr[MAXLINKLIST]; pthread_exit(NULL); } /* allocate a pseudo-channel thru asterisk */ - myrpt->parrotchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + myrpt->parrotchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!myrpt->parrotchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -11053,14 +11081,15 @@ char tmpstr[300],lstr[MAXLINKLIST]; myrpt->rpt_thread = AST_PTHREADT_STOP; pthread_exit(NULL); } - ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->parrotchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->parrotchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->parrotchannel->cdr) ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED); #endif /* allocate a pseudo-channel thru asterisk */ - myrpt->voxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + myrpt->voxchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!myrpt->voxchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -11071,14 +11100,15 @@ char tmpstr[300],lstr[MAXLINKLIST]; myrpt->rpt_thread = AST_PTHREADT_STOP; pthread_exit(NULL); } - ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->voxchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->voxchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->voxchannel->cdr) ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED); #endif /* allocate a pseudo-channel thru asterisk */ - myrpt->txpchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + myrpt->txpchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!myrpt->txpchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -13146,6 +13176,7 @@ static int rpt_exec(struct ast_channel *chan, const char *data) struct dahdi_radio_param z; struct rpt_tele *telem; int numlinks; + struct ast_format_cap *cap = NULL; nullfd = open("/dev/null",O_RDWR); if (ast_strlen_zero(data)) { @@ -13631,17 +13662,18 @@ static int rpt_exec(struct ast_channel *chan, const char *data) l->lastf2 = NULL; l->dtmfed = 0; voxinit_link(l,1); - ast_set_read_format(l->chan,AST_FORMAT_SLINEAR); - ast_set_write_format(l->chan,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(l->chan,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(l->chan,AST_FORMAT_SLINEAR); /* allocate a pseudo-channel thru asterisk */ - l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + l->pchan = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!l->pchan) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); pthread_exit(NULL); } - ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR); - ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(l->pchan,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(l->pchan,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (l->pchan->cdr) ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -13778,14 +13810,15 @@ static int rpt_exec(struct ast_channel *chan, const char *data) pthread_exit(NULL); } *tele++ = 0; - myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL); + myrpt->rxchannel = ast_request(myrpt->rxchanname, get_slin_cap(cap), NULL, tele, NULL); + cap = ast_format_cap_destroy(cap); myrpt->dahdirxchannel = NULL; if (!strcasecmp(myrpt->rxchanname,"DAHDI")) myrpt->dahdirxchannel = myrpt->rxchannel; if (myrpt->rxchannel) { - ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->rxchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->rxchannel->cdr) ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -13821,13 +13854,14 @@ static int rpt_exec(struct ast_channel *chan, const char *data) pthread_exit(NULL); } *tele++ = 0; - myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL); + myrpt->txchannel = ast_request(myrpt->txchanname, get_slin_cap(cap), NULL, tele, NULL); + cap = ast_format_cap_destroy(cap); if (!strncasecmp(myrpt->txchanname,"DAHDI",3)) myrpt->dahditxchannel = myrpt->txchannel; if (myrpt->txchannel) { - ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->txchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->txchannel->cdr) ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -13860,7 +13894,8 @@ static int rpt_exec(struct ast_channel *chan, const char *data) myrpt->dahditxchannel = myrpt->rxchannel; } /* allocate a pseudo-channel thru asterisk */ - myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL); + myrpt->pchannel = ast_request("DAHDI", get_slin_cap(cap), NULL, "pseudo", NULL); + cap = ast_format_cap_destroy(cap); if (!myrpt->pchannel) { fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); @@ -13870,8 +13905,8 @@ static int rpt_exec(struct ast_channel *chan, const char *data) ast_hangup(myrpt->rxchannel); pthread_exit(NULL); } - ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR); - ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(myrpt->pchannel,AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(myrpt->pchannel,AST_FORMAT_SLINEAR); #ifdef AST_CDR_FLAG_POST_DISABLED if (myrpt->pchannel->cdr) ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED); @@ -13987,8 +14022,8 @@ static int rpt_exec(struct ast_channel *chan, const char *data) myrpt->tele.prev = &myrpt->tele; myrpt->newkey = 0; rpt_mutex_unlock(&myrpt->lock); - ast_set_write_format(chan, AST_FORMAT_SLINEAR); - ast_set_read_format(chan, AST_FORMAT_SLINEAR); + ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR); + ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); rem_rx = 0; remkeyed = 0; /* if we are on 2w loop and are a remote, turn EC on */ diff --git a/apps/app_sms.c b/apps/app_sms.c index b5c471b8eea6a6487da3ece12eb8f8c7af457482..07af71d1cd0b69ce707391a68582d27496893bc4 100644 --- a/apps/app_sms.c +++ b/apps/app_sms.c @@ -1603,7 +1603,7 @@ static int sms_generate(struct ast_channel *chan, void *data, int len, int sampl buf = alloca(len); f.frametype = AST_FRAME_VOICE; - f.subclass.codec = __OUT_FMT; + ast_format_set(&f.subclass.format, __OUT_FMT, 0); f.datalen = samples * sizeof(*buf); f.offset = AST_FRIENDLY_OFFSET; f.mallocd = 0; @@ -2001,9 +2001,9 @@ static int sms_exec(struct ast_channel *chan, const char *data) sms_messagetx(&h); } - res = ast_set_write_format(chan, __OUT_FMT); + res = ast_set_write_format_by_id(chan, __OUT_FMT); if (res >= 0) { - res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); + res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); } if (res < 0) { ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n"); diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c index 0323f7c47100d709a1fb0611fed4627c51e5fe75..fe99157e95ae66a5f5989170e843c48e3dc42d5d 100644 --- a/apps/app_speech_utils.c +++ b/apps/app_speech_utils.c @@ -642,7 +642,7 @@ static int speech_background(struct ast_channel *chan, const char *data) int res = 0, done = 0, started = 0, quieted = 0, max_dtmf_len = 0; struct ast_speech *speech = find_speech(chan); struct ast_frame *f = NULL; - int oldreadformat = AST_FORMAT_SLINEAR; + struct ast_format oldreadformat; char dtmf[AST_MAX_EXTENSION] = ""; struct timeval start = { 0, 0 }, current; struct ast_datastore *datastore = NULL; @@ -658,6 +658,7 @@ static int speech_background(struct ast_channel *chan, const char *data) parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); + ast_format_clear(&oldreadformat); if (speech == NULL) return -1; @@ -673,10 +674,10 @@ static int speech_background(struct ast_channel *chan, const char *data) } /* Record old read format */ - oldreadformat = chan->readformat; + ast_format_copy(&oldreadformat, &chan->readformat); /* Change read format to be signed linear */ - if (ast_set_read_format(chan, speech->format)) + if (ast_set_read_format(chan, &speech->format)) return -1; if (!ast_strlen_zero(args.soundfile)) { @@ -881,7 +882,7 @@ static int speech_background(struct ast_channel *chan, const char *data) ast_channel_datastore_remove(chan, datastore); } else { /* Channel is okay so restore read format */ - ast_set_read_format(chan, oldreadformat); + ast_set_read_format(chan, &oldreadformat); } return 0; diff --git a/apps/app_talkdetect.c b/apps/app_talkdetect.c index 615929e9430079674421143a75fa1cf5037f12c2..545261c72f2b30d59889fdeb6aff263291d2563f 100644 --- a/apps/app_talkdetect.c +++ b/apps/app_talkdetect.c @@ -87,7 +87,7 @@ static int background_detect_exec(struct ast_channel *chan, const char *data) int analysistime = -1; int continue_analysis = 1; int x; - int origrformat = 0; + struct ast_format origrformat; struct ast_dsp *dsp = NULL; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(filename); @@ -96,7 +96,8 @@ static int background_detect_exec(struct ast_channel *chan, const char *data) AST_APP_ARG(max); AST_APP_ARG(analysistime); ); - + + ast_format_clear(&origrformat); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n"); return -1; @@ -126,8 +127,8 @@ static int background_detect_exec(struct ast_channel *chan, const char *data) } } - origrformat = chan->readformat; - if ((ast_set_read_format(chan, AST_FORMAT_SLINEAR))) { + ast_format_copy(&origrformat, &chan->readformat); + if ((ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR))) { ast_log(LOG_WARNING, "Unable to set read format to linear!\n"); res = -1; break; @@ -182,7 +183,7 @@ static int background_detect_exec(struct ast_channel *chan, const char *data) ast_frfree(fr); break; } - } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass.codec == AST_FORMAT_SLINEAR) && continue_analysis) { + } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass.format.id == AST_FORMAT_SLINEAR) && continue_analysis) { int totalsilence; int ms; res = ast_dsp_silence(dsp, fr, &totalsilence); @@ -228,9 +229,9 @@ static int background_detect_exec(struct ast_channel *chan, const char *data) } while (0); if (res > -1) { - if (origrformat && ast_set_read_format(chan, origrformat)) { + if (origrformat.id && ast_set_read_format(chan, &origrformat)) { ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", - chan->name, ast_getformatname(origrformat)); + chan->name, ast_getformatname(&origrformat)); } } if (dsp) { diff --git a/apps/app_test.c b/apps/app_test.c index a7aa7b65707e4060f1d39db4501399b9cab2dec3..7d0214a59a28d26d611566e3de4b2795a2a72046 100644 --- a/apps/app_test.c +++ b/apps/app_test.c @@ -87,9 +87,10 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who) short *foo; struct timeval start; struct ast_frame *f; - int rformat; - rformat = chan->readformat; - if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { + struct ast_format rformat; + + ast_format_copy(&rformat, &chan->readformat); + if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) { ast_log(LOG_NOTICE, "Unable to set to linear mode!\n"); return -1; } @@ -106,7 +107,7 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who) res = -1; break; } - if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.codec == AST_FORMAT_SLINEAR)) { + if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) { foo = (short *)f->data.ptr; for (x=0;x<f->samples;x++) { noise += abs(foo[x]); @@ -116,8 +117,8 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who) ast_frfree(f); } - if (rformat) { - if (ast_set_read_format(chan, rformat)) { + if (rformat.id) { + if (ast_set_read_format(chan, &rformat)) { ast_log(LOG_NOTICE, "Unable to restore original format!\n"); return -1; } diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 166df4c94ae497ebce406c34168bfeec9c62a390..f7882c20da88c5ea0796bec9b97b50035cc9f729 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -12347,11 +12347,11 @@ AST_TEST_DEFINE(test_voicemail_vmsayname) } /* normally this is done in the channel driver */ - test_channel1->nativeformats = AST_FORMAT_GSM; - test_channel1->writeformat = AST_FORMAT_GSM; - test_channel1->rawwriteformat = AST_FORMAT_GSM; - test_channel1->readformat = AST_FORMAT_GSM; - test_channel1->rawreadformat = AST_FORMAT_GSM; + ast_format_set(&test_channel1->writeformat, AST_FORMAT_GSM, 0); + ast_format_cap_add(test_channel1->nativeformats, &test_channel1->writeformat); + ast_format_set(&test_channel1->rawwriteformat, AST_FORMAT_GSM, 0); + ast_format_set(&test_channel1->readformat, AST_FORMAT_GSM, 0); + ast_format_set(&test_channel1->rawreadformat, AST_FORMAT_GSM, 0); test_channel1->tech = &fake_tech; ast_test_status_update(test, "Test playing of extension when greeting is not available...\n"); diff --git a/apps/app_waitforsilence.c b/apps/app_waitforsilence.c index fb76f913486c4d3b408442abb814e64e732d9ed8..fe4b1e14dca41b57e6118c19273b294e77e642fd 100644 --- a/apps/app_waitforsilence.c +++ b/apps/app_waitforsilence.c @@ -125,7 +125,7 @@ static char *app_noise = "WaitForNoise"; static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) { struct ast_frame *f = NULL; int dsptime = 0; - int rfmt = 0; + struct ast_format rfmt; int res = 0; struct ast_dsp *sildet; /* silence detector dsp */ time_t now; @@ -134,8 +134,8 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) = wait_for_silence ? ast_dsp_silence : ast_dsp_noise; - rfmt = chan->readformat; /* Set to linear mode */ - if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) { + ast_format_copy(&rfmt, &chan->readformat); /* Set to linear mode */ + if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) { ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n"); return -1; } @@ -195,8 +195,8 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, } - if (rfmt && ast_set_read_format(chan, rfmt)) { - ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); + if (rfmt.id && ast_set_read_format(chan, &rfmt)) { + ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(&rfmt), chan->name); } ast_dsp_free(sildet); return res; diff --git a/bridges/bridge_multiplexed.c b/bridges/bridge_multiplexed.c index 5206731341346ef7336b21110269f1c72fd3e539..0d2b3e254c335f54be59a94b9943ea47de625274 100644 --- a/bridges/bridge_multiplexed.c +++ b/bridges/bridge_multiplexed.c @@ -306,7 +306,9 @@ static int multiplexed_bridge_join(struct ast_bridge *bridge, struct ast_bridge_ return 0; } - if (((c0->writeformat == c1->readformat) && (c0->readformat == c1->writeformat) && (c0->nativeformats == c1->nativeformats))) { + if ((ast_format_cmp(&c0->writeformat, &c1->readformat) == AST_FORMAT_CMP_EQUAL) && + (ast_format_cmp(&c0->readformat, &c1->writeformat) == AST_FORMAT_CMP_EQUAL) && + (ast_format_cap_identical(c0->nativeformats, c1->nativeformats))) { return 0; } @@ -373,7 +375,6 @@ static struct ast_bridge_technology multiplexed_bridge = { .name = "multiplexed_bridge", .capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX, .preference = AST_BRIDGE_PREFERENCE_HIGH, - .formats = AST_FORMAT_AUDIO_MASK | AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK, .create = multiplexed_bridge_create, .destroy = multiplexed_bridge_destroy, .join = multiplexed_bridge_join, @@ -388,6 +389,7 @@ static int unload_module(void) int res = ast_bridge_technology_unregister(&multiplexed_bridge); ao2_ref(multiplexed_threads, -1); + multiplexed_bridge.format_capabilities = ast_format_cap_destroy(multiplexed_bridge.format_capabilities); return res; } @@ -397,7 +399,12 @@ static int load_module(void) if (!(multiplexed_threads = ao2_container_alloc(MULTIPLEXED_BUCKETS, NULL, NULL))) { return AST_MODULE_LOAD_DECLINE; } - + if (!(multiplexed_bridge.format_capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_add_all_by_type(multiplexed_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_add_all_by_type(multiplexed_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO); + ast_format_cap_add_all_by_type(multiplexed_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT); return ast_bridge_technology_register(&multiplexed_bridge); } diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c index 0dbcd25d2fdb73afb85862b3d796cbe9acdf5f74..72b91087adfda9885e644249cc7907d1834b5b14 100644 --- a/bridges/bridge_simple.c +++ b/bridges/bridge_simple.c @@ -51,7 +51,9 @@ static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chann } /* See if we need to make these compatible */ - if (((c0->writeformat == c1->readformat) && (c0->readformat == c1->writeformat) && (c0->nativeformats == c1->nativeformats))) { + if ((ast_format_cmp(&c0->writeformat, &c1->readformat) == AST_FORMAT_CMP_EQUAL) && + (ast_format_cmp(&c0->readformat, &c1->writeformat) == AST_FORMAT_CMP_EQUAL) && + (ast_format_cap_identical(c0->nativeformats, c1->nativeformats))) { return 0; } @@ -85,18 +87,25 @@ static struct ast_bridge_technology simple_bridge = { .name = "simple_bridge", .capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_THREAD, .preference = AST_BRIDGE_PREFERENCE_MEDIUM, - .formats = AST_FORMAT_AUDIO_MASK | AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK, .join = simple_bridge_join, .write = simple_bridge_write, }; static int unload_module(void) { + ast_format_cap_destroy(simple_bridge.format_capabilities); return ast_bridge_technology_unregister(&simple_bridge); } static int load_module(void) { + if (!(simple_bridge.format_capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } + ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO); + ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT); + return ast_bridge_technology_register(&simple_bridge); } diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c index 69d13a2b6aabe872f550e5d919b78b9515a9478f..b25ab99fa82606d1063ba6d82e7f7df0cddf3e6b 100644 --- a/bridges/bridge_softmix.c +++ b/bridges/bridge_softmix.c @@ -126,9 +126,9 @@ static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan /* Setup frame parameters */ sc->frame.frametype = AST_FRAME_VOICE; #ifdef SOFTMIX_16_SUPPORT - sc->frame.subclass.codec = AST_FORMAT_SLINEAR16; + ast_format_set(&sc->frame.subclass.format, AST_FORMAT_SLINEAR16, 0); #else - sc->frame.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&sc->frame.subclass.format, AST_FORMAT_SLINEAR, 0); #endif sc->frame.data.ptr = sc->final_buf; sc->frame.datalen = SOFTMIX_DATALEN; @@ -171,9 +171,9 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid /* If a frame was provided add it to the smoother */ #ifdef SOFTMIX_16_SUPPORT - if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR16) { + if (frame->frametype == AST_FRAME_VOICE && frame->subclass.format.id == AST_FORMAT_SLINEAR16) { #else - if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR) { + if (frame->frametype == AST_FRAME_VOICE && frame->subclass.format.id == AST_FORMAT_SLINEAR) { #endif ast_slinfactory_feed(&sc->factory, frame); } @@ -282,11 +282,6 @@ static struct ast_bridge_technology softmix_bridge = { .name = "softmix", .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED, .preference = AST_BRIDGE_PREFERENCE_LOW, -#ifdef SOFTMIX_16_SUPPORT - .formats = AST_FORMAT_SLINEAR16, -#else - .formats = AST_FORMAT_SLINEAR, -#endif .create = softmix_bridge_create, .destroy = softmix_bridge_destroy, .join = softmix_bridge_join, @@ -298,11 +293,21 @@ static struct ast_bridge_technology softmix_bridge = { static int unload_module(void) { + ast_format_cap_destroy(softmix_bridge.format_capabilities); return ast_bridge_technology_unregister(&softmix_bridge); } static int load_module(void) { + struct ast_format tmp; + if (!(softmix_bridge.format_capabilities = ast_format_cap_alloc())) { + return AST_MODULE_LOAD_DECLINE; + } +#ifdef SOFTMIX_16_SUPPORT + ast_format_cap_add(softmix_bridge.format_capabilities, ast_format_set(&tmp, AST_FORMAT_SLINEAR16, 0)); +#else + ast_format_cap_add(softmix_bridge.format_capabilities, ast_format_set(&tmp, AST_FORMAT_SLINEAR, 0)); +#endif return ast_bridge_technology_register(&softmix_bridge); } diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 7cf5e69d76c541e5cf2c9cf02ba9853a7f26667a..9e1dfed9edbc827b953893c32fd2707cc55ad851 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 120987ae4e549f6ff9e1ad4851f659547435f92a..58382881e7237e74ac74edc24265063a5542edaa 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 8218bdceb9a2f22a68aee540e4ec3b9171366ee2..a58cfcc59b34a51421ffedd5b36c58b45f5dfce1 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 64c1b87fcdf3ada4b9b9211db6521f663fbc87d3..eb961b6825d141ad06c55a02a703555143ad5689 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 09f4612590b950e80e4ec1850d738ec646472570..b5f398fdf388b6cd1563b6940b57fdc9a4c565d4 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 280cac4b55556ead008954d724b2bafaa589a3df..3bbf161928eb18377eea09dc62962ec7c49f88ba 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 e549d429907c0e3240607554e8e5cf88a19bdb96..ccc034872c51df067d83e546784c37a6579ad323 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 5de2c4a23a2c76be345bd75ae32230e460b7562e..49434d6785274e302e8904091dcdc6379d64c7e7 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 fd84f1f27b914872f7b4c4ecffbd9182208c45e4..93d81d954bd63337ec76eb4961a86f43057ab98d 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 e80722c239e7a20c94b9ea7d3f107e56b2764bb1..fbe1e530e04a06260021ea31136923829d189191 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 723849785abef5401ba1507d010be8f9eb54d631..32886a6a7b07befd6371446410e93a10d618f099 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 97eaba942957356cd908d2c580654026f41fe2db..91bcf87035b333b65dfdff4e80579984c1a75f92 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 55b757567fc926a07b9df9112b7647d7b0284d01..b398abb21375ebc616724f5b94c6960e7d87a5d3 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 882258f00ffda4f7f405803860bb6f813e2f71b1..1cd3d75fb3edf643ae255e2b34f32fa904426f89 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 3c4f2c943ee8a39960d41544c790e62495929d1a..10b0ed0fd52d89cfebc551fe76ad6e42e220aeae 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 531b95cb56af5c0da639d686d60dbca2006dd1d0..4897775cc41dca6dc0d451e29878354a1ffdb6f5 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 d5ee01345e8dda973597e86281ff8debcf049c90..e80f387cc99e5a7f399ba6ffbf940948a16ff138 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 0d75888bab30d4423143a7b11e7040bffefe17f8..3eb76820c9391d743f645323c09287199943d5d3 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 15589025012379aeceafd6d4c67b9744606e5066..4cb5dd71aecae7985725b28b4f5a712291706837 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 eca7760ab196e8b5aedf1ab975f1d5d4522e4414..73995dd074b7478e3641dc2d980cd73cb3f5a009 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 6a268bdb3239ea3dffb4eec5fa3c50b43c9b8e0d..0215ab82f5a4596973ff91e2e48144d52f37155a 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 c068389f8cab61b2a29e2525f6fc895bfc53c17b..b8f3aaaee20b06ed771ba793c5f88ab66f97215b 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 2ae2c84c49835831d5c77e618f3b6336345b2915..ddabb669ac088cf47de8f183a1a9cc35cd6a5a9c 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 094651e7097d3a412e328d7afdc68498b0efb4d9..ce9af244d8ca158a4937cfa6fd7d7ae17ee42dfc 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 f25aaa3b7ade0b32de2f8bbff619a652abe420e0..978ca0d2a43247a493152bd27071961483bb1fc2 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 c7af9f324e8abfbc8b5c3c68c5e0d849e61b622e..a95098236c167844d03776d6b80133ce1dc4969d 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 825efb8cb28409a19d07e06639fafffed8508993..d579ed8aad7b8174e53e7aa6bd4e18a12ddf9c9b 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 0bd2f4d2d1c8315ea29b1c3cd81283e33702434a..d7c9f13d0893f093eb31a9083fa7543696aad64e 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 57c155e141c42e0337a5cac37ceee8b2d7151a91..e5d8205e58644228638476c89b92865e4d154649 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 */ diff --git a/codecs/codec_a_mu.c b/codecs/codec_a_mu.c index 9b2e408500e8fa4b6f583f5877a61ad78ca5b42e..a7d86e2c4cc7fd7ff698af2ddca047e03c28fb53 100644 --- a/codecs/codec_a_mu.c +++ b/codecs/codec_a_mu.c @@ -76,8 +76,6 @@ static int ulawtoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) static struct ast_translator alawtoulaw = { .name = "alawtoulaw", - .srcfmt = AST_FORMAT_ALAW, - .dstfmt = AST_FORMAT_ULAW, .framein = alawtoulaw_framein, .sample = alaw_sample, .buffer_samples = BUFFER_SAMPLES, @@ -86,8 +84,6 @@ static struct ast_translator alawtoulaw = { static struct ast_translator ulawtoalaw = { .name = "ulawtoalaw", - .srcfmt = AST_FORMAT_ULAW, - .dstfmt = AST_FORMAT_ALAW, .framein = ulawtoalaw_framein, .sample = ulaw_sample, .buffer_samples = BUFFER_SAMPLES, @@ -111,6 +107,12 @@ static int load_module(void) int res; int x; + ast_format_set(&alawtoulaw.src_format, AST_FORMAT_ALAW, 0); + ast_format_set(&alawtoulaw.dst_format, AST_FORMAT_ULAW, 0); + + ast_format_set(&ulawtoalaw.src_format, AST_FORMAT_ULAW, 0); + ast_format_set(&ulawtoalaw.dst_format, AST_FORMAT_ALAW, 0); + for (x=0;x<256;x++) { mu2a[x] = AST_LIN2A(AST_MULAW(x)); a2mu[x] = AST_LIN2MU(AST_ALAW(x)); diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c index a1b0680a518a8ff073cf762833e2121234ecfca0..63745c17041927481111e4ddd887cbef8493159f 100644 --- a/codecs/codec_adpcm.c +++ b/codecs/codec_adpcm.c @@ -286,8 +286,6 @@ static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt) static struct ast_translator adpcmtolin = { .name = "adpcmtolin", - .srcfmt = AST_FORMAT_ADPCM, - .dstfmt = AST_FORMAT_SLINEAR, .framein = adpcmtolin_framein, .sample = adpcm_sample, .desc_size = sizeof(struct adpcm_decoder_pvt), @@ -297,8 +295,6 @@ static struct ast_translator adpcmtolin = { static struct ast_translator lintoadpcm = { .name = "lintoadpcm", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_ADPCM, .framein = lintoadpcm_framein, .frameout = lintoadpcm_frameout, .sample = slin8_sample, @@ -327,6 +323,12 @@ static int load_module(void) { int res; + ast_format_set(&adpcmtolin.src_format, AST_FORMAT_ADPCM, 0); + ast_format_set(&adpcmtolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintoadpcm.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintoadpcm.dst_format, AST_FORMAT_ADPCM, 0); + res = ast_register_translator(&adpcmtolin); if (!res) res = ast_register_translator(&lintoadpcm); diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c index bb749d003f43d03b065839430390ff5a0abfeb6c..3d2fc92aec3871f8d7f2041853a9767a5773a293 100644 --- a/codecs/codec_alaw.c +++ b/codecs/codec_alaw.c @@ -73,8 +73,6 @@ static int lintoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) static struct ast_translator alawtolin = { .name = "alawtolin", - .srcfmt = AST_FORMAT_ALAW, - .dstfmt = AST_FORMAT_SLINEAR, .framein = alawtolin_framein, .sample = alaw_sample, .buffer_samples = BUFFER_SAMPLES, @@ -83,8 +81,6 @@ static struct ast_translator alawtolin = { static struct ast_translator lintoalaw = { "lintoalaw", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_ALAW, .framein = lintoalaw_framein, .sample = slin8_sample, .buffer_samples = BUFFER_SAMPLES, @@ -112,6 +108,12 @@ static int load_module(void) { int res; + ast_format_set(&lintoalaw.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintoalaw.dst_format, AST_FORMAT_ALAW, 0); + + ast_format_set(&alawtolin.src_format, AST_FORMAT_ALAW, 0); + ast_format_set(&alawtolin.dst_format, AST_FORMAT_SLINEAR, 0); + res = ast_register_translator(&alawtolin); if (!res) res = ast_register_translator(&lintoalaw); diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c index 64b73cdc1001e78055afdff85bce50815f94d418..960a594f7884ba08075865137dc3d118b30399e1 100644 --- a/codecs/codec_dahdi.c +++ b/codecs/codec_dahdi.c @@ -179,7 +179,7 @@ static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) { struct codec_dahdi_pvt *dahdip = pvt->pvt; - if (!f->subclass.codec) { + if (!f->subclass.format.id) { /* We're just faking a return for calculation purposes. */ dahdip->fake = 2; pvt->samples = f->samples; @@ -227,7 +227,7 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt) if (2 == dahdip->fake) { dahdip->fake = 1; pvt->f.frametype = AST_FRAME_VOICE; - pvt->f.subclass.codec = 0; + ast_format_clear(&pvt->f.subclass.format); pvt->f.samples = dahdip->required_samples; pvt->f.data.ptr = NULL; pvt->f.offset = 0; @@ -255,7 +255,7 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt) pvt->f.datalen = res; pvt->f.samples = dahdip->required_samples; pvt->f.frametype = AST_FRAME_VOICE; - pvt->f.subclass.codec = 1 << (pvt->t->dstfmt); + ast_format_copy(&pvt->f.subclass.format, &pvt->t->dst_format); pvt->f.mallocd = 0; pvt->f.offset = AST_FRIENDLY_OFFSET; pvt->f.src = pvt->t->name; @@ -274,7 +274,7 @@ static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) { struct codec_dahdi_pvt *dahdip = pvt->pvt; - if (!f->subclass.codec) { + if (!f->subclass.format.id) { /* We're just faking a return for calculation purposes. */ dahdip->fake = 2; pvt->samples = f->samples; @@ -300,7 +300,7 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt) if (2 == dahdip->fake) { dahdip->fake = 1; pvt->f.frametype = AST_FRAME_VOICE; - pvt->f.subclass.codec = 0; + ast_format_clear(&pvt->f.subclass.format); pvt->f.samples = dahdip->required_samples; pvt->f.data.ptr = NULL; pvt->f.offset = 0; @@ -338,7 +338,7 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt) } pvt->datalen = 0; pvt->f.frametype = AST_FRAME_VOICE; - pvt->f.subclass.codec = 1 << (pvt->t->dstfmt); + ast_format_copy(&pvt->f.subclass.format, &pvt->t->dst_format); pvt->f.mallocd = 0; pvt->f.offset = AST_FRIENDLY_OFFSET; pvt->f.src = pvt->t->name; @@ -371,7 +371,7 @@ static void dahdi_destroy(struct ast_trans_pvt *pvt) close(dahdip->fd); } -static int dahdi_translate(struct ast_trans_pvt *pvt, int dest, int source) +static int dahdi_translate(struct ast_trans_pvt *pvt, struct ast_format *dst_format, struct ast_format *src_format) { /* Request translation through zap if possible */ int fd; @@ -385,10 +385,10 @@ static int dahdi_translate(struct ast_trans_pvt *pvt, int dest, int source) return -1; } - dahdip->fmts.srcfmt = (1 << source); - dahdip->fmts.dstfmt = (1 << dest); + dahdip->fmts.srcfmt = ast_format_to_old_bitfield(src_format); + dahdip->fmts.dstfmt = ast_format_to_old_bitfield(dst_format); - ast_debug(1, "Opening transcoder channel from %d to %d.\n", source, dest); + ast_debug(1, "Opening transcoder channel from %s to %s.\n", ast_getformatname(src_format), ast_getformatname(dst_format)); retry: if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) { @@ -401,14 +401,14 @@ retry: * support for ULAW instead of signed linear and then * we'll just convert from ulaw to signed linear in * software. */ - if (AST_FORMAT_SLINEAR == dahdip->fmts.srcfmt) { + if (AST_FORMAT_SLINEAR == ast_format_id_from_old_bitfield(dahdip->fmts.srcfmt)) { ast_debug(1, "Using soft_slin support on source\n"); dahdip->softslin = 1; - dahdip->fmts.srcfmt = AST_FORMAT_ULAW; - } else if (AST_FORMAT_SLINEAR == dahdip->fmts.dstfmt) { + dahdip->fmts.srcfmt = ast_format_id_to_old_bitfield(AST_FORMAT_ULAW); + } else if (AST_FORMAT_SLINEAR == ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) { ast_debug(1, "Using soft_slin support on destination\n"); dahdip->softslin = 1; - dahdip->fmts.dstfmt = AST_FORMAT_ULAW; + dahdip->fmts.dstfmt = ast_format_id_to_old_bitfield(AST_FORMAT_ULAW); } tried_once = 1; goto retry; @@ -427,9 +427,9 @@ retry: dahdip->fd = fd; - dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt)&AST_FORMAT_G723_1) ? G723_SAMPLES : G729_SAMPLES; + dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (ast_format_id_to_old_bitfield(AST_FORMAT_G723_1))) ? G723_SAMPLES : G729_SAMPLES; - switch (dahdip->fmts.dstfmt) { + switch (ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) { case AST_FORMAT_G729A: ast_atomic_fetchadd_int(&channels.encoders, +1); break; @@ -446,7 +446,9 @@ retry: static int dahdi_new(struct ast_trans_pvt *pvt) { - return dahdi_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt); + return dahdi_translate(pvt, + &pvt->t->dst_format, + &pvt->t->src_format); } static struct ast_frame *fakesrc_sample(void) @@ -463,7 +465,9 @@ static struct ast_frame *fakesrc_sample(void) static int is_encoder(struct translator *zt) { - if (zt->t.srcfmt&(AST_FORMAT_ULAW|AST_FORMAT_ALAW|AST_FORMAT_SLINEAR)) { + if ((zt->t.src_format.id == AST_FORMAT_ULAW) || + (zt->t.src_format.id == AST_FORMAT_ALAW) || + (zt->t.src_format.id == AST_FORMAT_SLINEAR)) { return 1; } else { return 0; @@ -474,15 +478,20 @@ static int register_translator(int dst, int src) { struct translator *zt; int res; + struct ast_format dst_format; + struct ast_format src_format; + + ast_format_from_old_bitfield(&dst_format, (1 << dst)); + ast_format_from_old_bitfield(&src_format, (1 << src)); if (!(zt = ast_calloc(1, sizeof(*zt)))) { return -1; } snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", - ast_getformatname((1 << src)), ast_getformatname((1 << dst))); - zt->t.srcfmt = (1 << src); - zt->t.dstfmt = (1 << dst); + ast_getformatname(&src_format), ast_getformatname(&dst_format)); + ast_format_copy(&zt->t.src_format, &src_format); + ast_format_copy(&zt->t.dst_format, &dst_format); zt->t.buf_size = BUFFER_SIZE; if (is_encoder(zt)) { zt->t.framein = dahdi_encoder_framein; @@ -518,10 +527,10 @@ static void drop_translator(int dst, int src) AST_LIST_LOCK(&translators); AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) { - if (cur->t.srcfmt != src) + if (cur->t.src_format.id != ast_format_id_from_old_bitfield((1 << src))) continue; - if (cur->t.dstfmt != dst) + if (cur->t.dst_format.id != ast_format_id_from_old_bitfield((1 << dst))) continue; AST_LIST_REMOVE_CURRENT(entry); diff --git a/codecs/codec_g722.c b/codecs/codec_g722.c index 22196da011114e58785ba8250e6222a46a2c35bc..9c3a018468280b5e0a144464509c3b0145d7d95a 100644 --- a/codecs/codec_g722.c +++ b/codecs/codec_g722.c @@ -134,8 +134,6 @@ static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) static struct ast_translator g722tolin = { .name = "g722tolin", - .srcfmt = AST_FORMAT_G722, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = g722tolin_new, /* same for both directions */ .framein = g722tolin_framein, .sample = g722_sample, @@ -146,8 +144,6 @@ static struct ast_translator g722tolin = { static struct ast_translator lintog722 = { .name = "lintog722", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_G722, .newpvt = lintog722_new, /* same for both directions */ .framein = lintog722_framein, .sample = slin8_sample, @@ -158,8 +154,6 @@ static struct ast_translator lintog722 = { static struct ast_translator g722tolin16 = { .name = "g722tolin16", - .srcfmt = AST_FORMAT_G722, - .dstfmt = AST_FORMAT_SLINEAR16, .newpvt = g722tolin16_new, /* same for both directions */ .framein = g722tolin_framein, .sample = g722_sample, @@ -170,8 +164,6 @@ static struct ast_translator g722tolin16 = { static struct ast_translator lin16tog722 = { .name = "lin16tog722", - .srcfmt = AST_FORMAT_SLINEAR16, - .dstfmt = AST_FORMAT_G722, .newpvt = lin16tog722_new, /* same for both directions */ .framein = lintog722_framein, .sample = slin16_sample, @@ -201,6 +193,18 @@ static int load_module(void) { int res = 0; + ast_format_set(&g722tolin.src_format, AST_FORMAT_G722, 0); + ast_format_set(&g722tolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintog722.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintog722.dst_format, AST_FORMAT_G722, 0); + + ast_format_set(&g722tolin16.src_format, AST_FORMAT_G722, 0); + ast_format_set(&g722tolin16.dst_format, AST_FORMAT_SLINEAR16, 0); + + ast_format_set(&lin16tog722.src_format, AST_FORMAT_SLINEAR16, 0); + ast_format_set(&lin16tog722.dst_format, AST_FORMAT_G722, 0); + res |= ast_register_translator(&g722tolin); res |= ast_register_translator(&lintog722); res |= ast_register_translator(&g722tolin16); diff --git a/codecs/codec_g726.c b/codecs/codec_g726.c index cc9b1cb31e5864a3d646640396ab6c80f13666e8..f8a57f740eb92d0a62b75929217874f581032e7c 100644 --- a/codecs/codec_g726.c +++ b/codecs/codec_g726.c @@ -771,8 +771,6 @@ static int lintog726_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) static struct ast_translator g726tolin = { .name = "g726tolin", - .srcfmt = AST_FORMAT_G726, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = lintog726_new, /* same for both directions */ .framein = g726tolin_framein, .sample = g726_sample, @@ -783,8 +781,6 @@ static struct ast_translator g726tolin = { static struct ast_translator lintog726 = { .name = "lintog726", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_G726, .newpvt = lintog726_new, /* same for both directions */ .framein = lintog726_framein, .sample = slin8_sample, @@ -795,8 +791,6 @@ static struct ast_translator lintog726 = { static struct ast_translator g726aal2tolin = { .name = "g726aal2tolin", - .srcfmt = AST_FORMAT_G726_AAL2, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = lintog726_new, /* same for both directions */ .framein = g726aal2tolin_framein, .sample = g726_sample, @@ -807,8 +801,6 @@ static struct ast_translator g726aal2tolin = { static struct ast_translator lintog726aal2 = { .name = "lintog726aal2", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_G726_AAL2, .newpvt = lintog726_new, /* same for both directions */ .framein = lintog726aal2_framein, .sample = slin8_sample, @@ -839,6 +831,18 @@ static int load_module(void) { int res = 0; + ast_format_set(&g726tolin.src_format, AST_FORMAT_G726, 0); + ast_format_set(&g726tolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintog726.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintog726.dst_format, AST_FORMAT_G726, 0); + + ast_format_set(&g726aal2tolin.src_format, AST_FORMAT_G726_AAL2, 0); + ast_format_set(&g726aal2tolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintog726aal2.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintog726aal2.dst_format, AST_FORMAT_G726_AAL2, 0); + res |= ast_register_translator(&g726tolin); res |= ast_register_translator(&lintog726); diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c index ab28154457aa86421cb83276a7d91346334e6f7c..46c1c84fb88c2ddd8d560b131f147eb2e8dc98b4 100644 --- a/codecs/codec_gsm.c +++ b/codecs/codec_gsm.c @@ -168,8 +168,6 @@ static void gsm_destroy_stuff(struct ast_trans_pvt *pvt) static struct ast_translator gsmtolin = { .name = "gsmtolin", - .srcfmt = AST_FORMAT_GSM, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = gsm_new, .framein = gsmtolin_framein, .destroy = gsm_destroy_stuff, @@ -181,8 +179,6 @@ static struct ast_translator gsmtolin = { static struct ast_translator lintogsm = { .name = "lintogsm", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_GSM, .newpvt = gsm_new, .framein = lintogsm_framein, .frameout = lintogsm_frameout, @@ -213,6 +209,12 @@ static int load_module(void) { int res; + ast_format_set(&gsmtolin.src_format, AST_FORMAT_GSM, 0); + ast_format_set(&gsmtolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintogsm.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintogsm.dst_format, AST_FORMAT_GSM, 0); + res = ast_register_translator(&gsmtolin); if (!res) res=ast_register_translator(&lintogsm); diff --git a/codecs/codec_ilbc.c b/codecs/codec_ilbc.c index 3227dc80e34ef76b7f7eb0c88b023536207683b8..bbd0019deb94fecde78d11bb16c1690157e17365 100644 --- a/codecs/codec_ilbc.c +++ b/codecs/codec_ilbc.c @@ -166,8 +166,6 @@ static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt) static struct ast_translator ilbctolin = { .name = "ilbctolin", - .srcfmt = AST_FORMAT_ILBC, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = ilbctolin_new, .framein = ilbctolin_framein, .sample = ilbc_sample, @@ -178,8 +176,6 @@ static struct ast_translator ilbctolin = { static struct ast_translator lintoilbc = { .name = "lintoilbc", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_ILBC, .newpvt = lintoilbc_new, .framein = lintoilbc_framein, .frameout = lintoilbc_frameout, @@ -202,6 +198,13 @@ static int load_module(void) { int res; + ast_format_set(&ilibctolin.src_format, AST_FORMAT_ILBC, 0); + ast_format_set(&ilibctolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintoilbc.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintoilbc.dst_format, AST_FORMAT_ILBC, 0); + + res = ast_register_translator(&ilbctolin); if (!res) res=ast_register_translator(&lintoilbc); diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c index d61729c9547248553197cd0e765d12b0c41738c2..7d1739203f42e410d8c1a36a3e71fa2d5e661201 100644 --- a/codecs/codec_lpc10.c +++ b/codecs/codec_lpc10.c @@ -193,8 +193,6 @@ static void lpc10_destroy(struct ast_trans_pvt *arg) static struct ast_translator lpc10tolin = { .name = "lpc10tolin", - .srcfmt = AST_FORMAT_LPC10, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = lpc10_dec_new, .framein = lpc10tolin_framein, .destroy = lpc10_destroy, @@ -206,8 +204,6 @@ static struct ast_translator lpc10tolin = { static struct ast_translator lintolpc10 = { .name = "lintolpc10", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_LPC10, .newpvt = lpc10_enc_new, .framein = lintolpc10_framein, .frameout = lintolpc10_frameout, @@ -238,6 +234,12 @@ static int load_module(void) { int res; + ast_format_set(&lpc10tolin.src_format, AST_FORMAT_LPC10, 0); + ast_format_set(&lpc10tolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintolpc10.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintolpc10.dst_format, AST_FORMAT_LPC10, 0); + res = ast_register_translator(&lpc10tolin); if (!res) res = ast_register_translator(&lintolpc10); diff --git a/codecs/codec_resample.c b/codecs/codec_resample.c index 834fb46ba7c63c43eb1c17ff31353fc7ff83da66..80823bb7c8ecb911d2e44799fd48544876e74135 100644 --- a/codecs/codec_resample.c +++ b/codecs/codec_resample.c @@ -170,8 +170,6 @@ static int slin8_to_slin16_framein(struct ast_trans_pvt *pvt, struct ast_frame * static struct ast_translator slin16_to_slin8 = { .name = "slin16_to_slin8", - .srcfmt = AST_FORMAT_SLINEAR16, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = slin16_to_slin8_new, .destroy = slin16_to_slin8_destroy, .framein = slin16_to_slin8_framein, @@ -183,8 +181,6 @@ static struct ast_translator slin16_to_slin8 = { static struct ast_translator slin8_to_slin16 = { .name = "slin8_to_slin16", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_SLINEAR16, .newpvt = slin8_to_slin16_new, .destroy = slin8_to_slin16_destroy, .framein = slin8_to_slin16_framein, @@ -208,6 +204,12 @@ static int load_module(void) { int res = 0; + ast_format_set(&slin16_to_slin8.src_format, AST_FORMAT_SLINEAR16, 0); + ast_format_set(&slin16_to_slin8.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&slin8_to_slin16.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&slin8_to_slin16.dst_format, AST_FORMAT_SLINEAR16, 0); + res |= ast_register_translator(&slin16_to_slin8); res |= ast_register_translator(&slin8_to_slin16); diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c index 2bfdec228163675e26c32c936744116b01030f29..aaaa1bea25d72cfaf629306d3fec6fe079288e4b 100644 --- a/codecs/codec_speex.c +++ b/codecs/codec_speex.c @@ -330,8 +330,6 @@ static void lintospeex_destroy(struct ast_trans_pvt *arg) static struct ast_translator speextolin = { .name = "speextolin", - .srcfmt = AST_FORMAT_SPEEX, - .dstfmt = AST_FORMAT_SLINEAR, .newpvt = speextolin_new, .framein = speextolin_framein, .destroy = speextolin_destroy, @@ -344,8 +342,6 @@ static struct ast_translator speextolin = { static struct ast_translator lintospeex = { .name = "lintospeex", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_SPEEX, .newpvt = lintospeex_new, .framein = lintospeex_framein, .frameout = lintospeex_frameout, @@ -358,8 +354,6 @@ static struct ast_translator lintospeex = { static struct ast_translator speexwbtolin16 = { .name = "speexwbtolin16", - .srcfmt = AST_FORMAT_SPEEX16, - .dstfmt = AST_FORMAT_SLINEAR16, .newpvt = speexwbtolin16_new, .framein = speextolin_framein, .destroy = speextolin_destroy, @@ -372,8 +366,6 @@ static struct ast_translator speexwbtolin16 = { static struct ast_translator lin16tospeexwb = { .name = "lin16tospeexwb", - .srcfmt = AST_FORMAT_SLINEAR16, - .dstfmt = AST_FORMAT_SPEEX16, .newpvt = lin16tospeexwb_new, .framein = lintospeex_framein, .frameout = lintospeex_frameout, @@ -505,6 +497,19 @@ static int load_module(void) if (parse_config(0)) return AST_MODULE_LOAD_DECLINE; + + ast_format_set(&speextolin.src_format, AST_FORMAT_SPEEX, 0); + ast_format_set(&speextolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&lintospeex.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintospeex.dst_format, AST_FORMAT_SPEEX, 0); + + ast_format_set(&speexwbtolin16.src_format, AST_FORMAT_SPEEX16, 0); + ast_format_set(&speexwbtolin16.dst_format, AST_FORMAT_SLINEAR16, 0); + + ast_format_set(&lin16tospeexwb.src_format, AST_FORMAT_SLINEAR16, 0); + ast_format_set(&lin16tospeexwb.dst_format, AST_FORMAT_SPEEX16, 0); + res |= ast_register_translator(&speextolin); res |= ast_register_translator(&lintospeex); res |= ast_register_translator(&speexwbtolin16); diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c index 07f5da39ddf772d3199328d69f271228f1ef80e3..b5211a585aaee453883b7160e9a5f2ce2ece4a3f 100644 --- a/codecs/codec_ulaw.c +++ b/codecs/codec_ulaw.c @@ -78,8 +78,6 @@ static int lintoulaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) static struct ast_translator ulawtolin = { .name = "ulawtolin", - .srcfmt = AST_FORMAT_ULAW, - .dstfmt = AST_FORMAT_SLINEAR, .framein = ulawtolin_framein, .sample = ulaw_sample, .buffer_samples = BUFFER_SAMPLES, @@ -88,8 +86,6 @@ static struct ast_translator ulawtolin = { static struct ast_translator testlawtolin = { .name = "testlawtolin", - .srcfmt = AST_FORMAT_TESTLAW, - .dstfmt = AST_FORMAT_SLINEAR, .framein = ulawtolin_framein, .sample = ulaw_sample, .buffer_samples = BUFFER_SAMPLES, @@ -102,8 +98,6 @@ static struct ast_translator testlawtolin = { static struct ast_translator lintoulaw = { .name = "lintoulaw", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_ULAW, .framein = lintoulaw_framein, .sample = slin8_sample, .buf_size = BUFFER_SAMPLES, @@ -112,8 +106,6 @@ static struct ast_translator lintoulaw = { static struct ast_translator lintotestlaw = { .name = "lintotestlaw", - .srcfmt = AST_FORMAT_SLINEAR, - .dstfmt = AST_FORMAT_TESTLAW, .framein = lintoulaw_framein, .sample = slin8_sample, .buf_size = BUFFER_SAMPLES, @@ -141,6 +133,18 @@ static int load_module(void) { int res; + ast_format_set(&lintoulaw.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintoulaw.dst_format, AST_FORMAT_ULAW, 0); + + ast_format_set(&lintotestlaw.src_format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&lintotestlaw.dst_format, AST_FORMAT_TESTLAW, 0); + + ast_format_set(&ulawtolin.src_format, AST_FORMAT_ULAW, 0); + ast_format_set(&ulawtolin.dst_format, AST_FORMAT_SLINEAR, 0); + + ast_format_set(&testlawtolin.src_format, AST_FORMAT_TESTLAW, 0); + ast_format_set(&testlawtolin.dst_format, AST_FORMAT_SLINEAR, 0); + res = ast_register_translator(&ulawtolin); if (!res) { res = ast_register_translator(&lintoulaw); diff --git a/codecs/ex_adpcm.h b/codecs/ex_adpcm.h index 8a1a5eea9462cbdef78858df041e31855e478e6b..96b7c51f8a7caa804e92e40979c43615a7f62987 100644 --- a/codecs/ex_adpcm.h +++ b/codecs/ex_adpcm.h @@ -19,7 +19,6 @@ static struct ast_frame *adpcm_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_ADPCM, .datalen = sizeof(ex_adpcm), .samples = ARRAY_LEN(ex_adpcm) * 2, .mallocd = 0, @@ -27,6 +26,7 @@ static struct ast_frame *adpcm_sample(void) .src = __PRETTY_FUNCTION__, .data.ptr = ex_adpcm, }; + ast_format_set(&f.subclass.format, AST_FORMAT_ADPCM, 0); return &f; } diff --git a/codecs/ex_alaw.h b/codecs/ex_alaw.h index 5a03111fa90b90edb77ab65baf9d334f9f319bc3..bbf8ad982e43274fb39b843d26b30bad028214fb 100644 --- a/codecs/ex_alaw.h +++ b/codecs/ex_alaw.h @@ -24,7 +24,6 @@ static struct ast_frame *alaw_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_ALAW, .datalen = sizeof(ex_alaw), .samples = ARRAY_LEN(ex_alaw), .mallocd = 0, @@ -32,6 +31,6 @@ static struct ast_frame *alaw_sample(void) .src = __PRETTY_FUNCTION__, .data.ptr = ex_alaw, }; - + ast_format_set(&f.subclass.format, AST_FORMAT_ALAW, 0); return &f; } diff --git a/codecs/ex_g722.h b/codecs/ex_g722.h index 61146909e5da43d2ecdef45afaa145fa9168c93d..0e9f22686860c72da3d419708c3d3be3c6bf7c77 100644 --- a/codecs/ex_g722.h +++ b/codecs/ex_g722.h @@ -34,7 +34,6 @@ static struct ast_frame *g722_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_G722, .datalen = sizeof(ex_g722), .samples = ARRAY_LEN(ex_g722), .mallocd = 0, @@ -43,5 +42,7 @@ static struct ast_frame *g722_sample(void) .data.ptr = ex_g722, }; + ast_format_set(&f.subclass.format, AST_FORMAT_G722, 0); + return &f; } diff --git a/codecs/ex_g726.h b/codecs/ex_g726.h index 622418a27a05642f0da106f4345be8809d2ef1be..d5438c91a38fca382478a89c9fbdd1b6c2e5765d 100644 --- a/codecs/ex_g726.h +++ b/codecs/ex_g726.h @@ -19,7 +19,6 @@ static struct ast_frame *g726_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_G726, .datalen = sizeof(ex_g726), .samples = ARRAY_LEN(ex_g726) * 2, /* 2 samples per byte */ .mallocd = 0, @@ -28,5 +27,7 @@ static struct ast_frame *g726_sample(void) .data.ptr = ex_g726, }; + ast_format_set(&f.subclass.format, AST_FORMAT_G726, 0); + return &f; } diff --git a/codecs/ex_gsm.h b/codecs/ex_gsm.h index 0e4cffab079cfaf122b8391a7dcbfa31294f38e6..8f8b4f9fec4a976425f7f866d7dbe7d73eb007ca 100644 --- a/codecs/ex_gsm.h +++ b/codecs/ex_gsm.h @@ -18,7 +18,6 @@ static struct ast_frame *gsm_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_GSM, .datalen = sizeof(ex_gsm), /* All frames are 20 ms long */ .samples = GSM_SAMPLES, @@ -28,5 +27,6 @@ static struct ast_frame *gsm_sample(void) .data.ptr = ex_gsm, }; + ast_format_set(&f.subclass.format, AST_FORMAT_GSM, 0); return &f; } diff --git a/codecs/ex_lpc10.h b/codecs/ex_lpc10.h index 9c2ded88bb6a0550aa48e676aa20f043d54dbbce..a36e06addbccfcde24426fb907a522ff0142ab0c 100644 --- a/codecs/ex_lpc10.h +++ b/codecs/ex_lpc10.h @@ -15,7 +15,6 @@ static struct ast_frame *lpc10_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_LPC10, .datalen = sizeof(ex_lpc10), /* All frames are 22 ms long (maybe a little more -- why did he choose LPC10_SAMPLES_PER_FRAME sample frames anyway?? */ @@ -26,5 +25,7 @@ static struct ast_frame *lpc10_sample(void) .data.ptr = ex_lpc10, }; + ast_format_set(&f.subclass.format, AST_FORMAT_LPC10, 0); + return &f; } diff --git a/codecs/ex_speex.h b/codecs/ex_speex.h index 60ccf092e0f51f71228e1b176cca5b8fd31c3147..e9411e5d7b5faf2598c198f7abce41913df24e6f 100644 --- a/codecs/ex_speex.h +++ b/codecs/ex_speex.h @@ -18,7 +18,6 @@ static struct ast_frame *speex_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SPEEX, .datalen = sizeof(ex_speex), /* All frames are 20 ms long */ .samples = SPEEX_SAMPLES, @@ -28,6 +27,8 @@ static struct ast_frame *speex_sample(void) .data.ptr = ex_speex, }; + ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX, 0); + return &f; } @@ -49,7 +50,6 @@ static struct ast_frame *speex16_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SPEEX16, .datalen = sizeof(ex_speex16), /* All frames are 20 ms long */ .samples = SPEEX_SAMPLES, @@ -58,6 +58,7 @@ static struct ast_frame *speex16_sample(void) .src = __PRETTY_FUNCTION__, .data.ptr = ex_speex16, }; + ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX16, 0); return &f; } diff --git a/codecs/ex_ulaw.h b/codecs/ex_ulaw.h index b3970f5f8142ef477e5ae6d46ecc9155ebdf3cc9..2ab9222fbb19730bbf16466dd6c621f527680741 100644 --- a/codecs/ex_ulaw.h +++ b/codecs/ex_ulaw.h @@ -24,7 +24,6 @@ static struct ast_frame *ulaw_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_ULAW, .datalen = sizeof(ex_ulaw), .samples = ARRAY_LEN(ex_ulaw), .mallocd = 0, @@ -33,5 +32,6 @@ static struct ast_frame *ulaw_sample(void) .data.ptr = ex_ulaw, }; + ast_format_set(&f.subclass.format, AST_FORMAT_ULAW, 0); return &f; } diff --git a/formats/format_g719.c b/formats/format_g719.c index c5fc8efaace11cb3bd16d2a6f64a9c5c1c97da7a..b679122f87cf0a0ad1cc4f63f8670d3245eff332 100644 --- a/formats/format_g719.c +++ b/formats/format_g719.c @@ -41,7 +41,7 @@ static struct ast_frame *g719read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_G719; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_G719, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { @@ -61,8 +61,8 @@ static int g719write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_G719) { - ast_log(LOG_WARNING, "Asked to write non-G.719 frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_G719) { + ast_log(LOG_WARNING, "Asked to write non-G.719 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) { @@ -110,10 +110,9 @@ static off_t g719tell(struct ast_filestream *fs) return BYTES_TO_SAMPLES(ftello(fs->f)); } -static const struct ast_format g719_f = { +static struct ast_format_def g719_f = { .name = "g719", .exts = "g719", - .format = AST_FORMAT_G719, .write = g719write, .seek = g719seek, .trunc = g719trunc, @@ -124,15 +123,15 @@ static const struct ast_format g719_f = { static int load_module(void) { - if (ast_format_register(&g719_f)) + ast_format_set(&g719_f.format, AST_FORMAT_G719, 0); + if (ast_format_def_register(&g719_f)) return AST_MODULE_LOAD_DECLINE; - return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(g719_f.name); + return ast_format_def_unregister(g719_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ITU G.719", diff --git a/formats/format_g723.c b/formats/format_g723.c index 109811609c2409ec3a3d3f4e476a2848165216c1..6dab66a8603f1ac2834c4b38b2069cfe38a51661 100644 --- a/formats/format_g723.c +++ b/formats/format_g723.c @@ -61,7 +61,7 @@ static struct ast_frame *g723_read(struct ast_filestream *s, int *whennext) } /* Read the data into the buffer */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_G723_1; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_G723_1, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, size); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != size) { @@ -82,7 +82,7 @@ static int g723_write(struct ast_filestream *s, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_G723_1) { + if (f->subclass.format.id != AST_FORMAT_G723_1) { ast_log(LOG_WARNING, "Asked to write non-g723 frame!\n"); return -1; } @@ -125,10 +125,9 @@ static off_t g723_tell(struct ast_filestream *fs) return -1; } -static const struct ast_format g723_1_f = { +static struct ast_format_def g723_1_f = { .name = "g723sf", .exts = "g723|g723sf", - .format = AST_FORMAT_G723_1, .write = g723_write, .seek = g723_seek, .trunc = g723_trunc, @@ -139,14 +138,16 @@ static const struct ast_format g723_1_f = { static int load_module(void) { - if (ast_format_register(&g723_1_f)) + ast_format_set(&g723_1_f.format, AST_FORMAT_G723_1, 0); + + if (ast_format_def_register(&g723_1_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(g723_1_f.name); + return ast_format_def_unregister(g723_1_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "G.723.1 Simple Timestamp File Format", diff --git a/formats/format_g726.c b/formats/format_g726.c index 3c5697f5d6bb53221afa82cbe9f8ce8f6f303154..73a57c8eef5413b5d027a3d883cc998711b1ad81 100644 --- a/formats/format_g726.c +++ b/formats/format_g726.c @@ -119,7 +119,7 @@ static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_G726; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_G726, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, frame_size[fs->rate]); s->fr.samples = 8 * FRAME_TIME; @@ -141,9 +141,9 @@ static int g726_write(struct ast_filestream *s, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_G726) { + if (f->subclass.format.id != AST_FORMAT_G726) { ast_log(LOG_WARNING, "Asked to write non-G726 frame (%s)!\n", - ast_getformatname(f->subclass.codec)); + ast_getformatname(&f->subclass.format)); return -1; } if (f->datalen % frame_size[fs->rate]) { @@ -174,11 +174,10 @@ static off_t g726_tell(struct ast_filestream *fs) return -1; } -static const struct ast_format f[] = { +static struct ast_format_def f[] = { { .name = "g726-40", .exts = "g726-40", - .format = AST_FORMAT_G726, .open = g726_40_open, .rewrite = g726_40_rewrite, .write = g726_write, @@ -192,7 +191,6 @@ static const struct ast_format f[] = { { .name = "g726-32", .exts = "g726-32", - .format = AST_FORMAT_G726, .open = g726_32_open, .rewrite = g726_32_rewrite, .write = g726_write, @@ -206,7 +204,6 @@ static const struct ast_format f[] = { { .name = "g726-24", .exts = "g726-24", - .format = AST_FORMAT_G726, .open = g726_24_open, .rewrite = g726_24_rewrite, .write = g726_write, @@ -220,7 +217,6 @@ static const struct ast_format f[] = { { .name = "g726-16", .exts = "g726-16", - .format = AST_FORMAT_G726, .open = g726_16_open, .rewrite = g726_16_rewrite, .write = g726_write, @@ -231,15 +227,16 @@ static const struct ast_format f[] = { .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, .desc_size = sizeof(struct g726_desc), }, - { .format = 0 } /* terminator */ + { .desc_size = 0 } /* terminator */ }; static int load_module(void) { int i; - for (i = 0; f[i].format ; i++) { - if (ast_format_register(&f[i])) { /* errors are fatal */ + for (i = 0; f[i].desc_size ; i++) { + ast_format_set(&f[i].format, AST_FORMAT_G726, 0); + if (ast_format_def_register(&f[i])) { /* errors are fatal */ ast_log(LOG_WARNING, "Failed to register format %s.\n", f[i].name); return AST_MODULE_LOAD_FAILURE; } @@ -251,8 +248,8 @@ static int unload_module(void) { int i; - for (i = 0; f[i].format ; i++) { - if (ast_format_unregister(f[i].name)) + for (i = 0; f[i].desc_size ; i++) { + if (ast_format_def_unregister(f[i].name)) ast_log(LOG_WARNING, "Failed to unregister format %s.\n", f[i].name); } return(0); diff --git a/formats/format_g729.c b/formats/format_g729.c index ad7d7fee7db3cea8cfa06a6d5597235ee3b52834..22b3c3282d595a147488b7e2efe58fe19a87b9bf 100644 --- a/formats/format_g729.c +++ b/formats/format_g729.c @@ -46,7 +46,7 @@ static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext) int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_G729A; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_G729A, 0); s->fr.mallocd = 0; s->fr.samples = G729A_SAMPLES; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); @@ -66,8 +66,8 @@ static int g729_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_G729A) { - ast_log(LOG_WARNING, "Asked to write non-G729 frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_G729A) { + ast_log(LOG_WARNING, "Asked to write non-G729 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if (f->datalen % 10) { @@ -121,10 +121,9 @@ static off_t g729_tell(struct ast_filestream *fs) return (offset/BUF_SIZE)*G729A_SAMPLES; } -static const struct ast_format g729_f = { +static struct ast_format_def g729_f = { .name = "g729", .exts = "g729", - .format = AST_FORMAT_G729A, .write = g729_write, .seek = g729_seek, .trunc = g729_trunc, @@ -135,14 +134,15 @@ static const struct ast_format g729_f = { static int load_module(void) { - if (ast_format_register(&g729_f)) + ast_format_set(&g729_f.format, AST_FORMAT_G729A, 0); + if (ast_format_def_register(&g729_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(g729_f.name); + return ast_format_def_unregister(g729_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw G.729 data", diff --git a/formats/format_gsm.c b/formats/format_gsm.c index 2b0b3413e81e6a822c06ae0f66c1bebbd1ed5caa..26257c39fb73bfd3e2d83545df2ec77cc0266010 100644 --- a/formats/format_gsm.c +++ b/formats/format_gsm.c @@ -53,7 +53,7 @@ static struct ast_frame *gsm_read(struct ast_filestream *s, int *whennext) int res; s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_GSM; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_GSM, 0); AST_FRAME_SET_BUFFER(&(s->fr), s->buf, AST_FRIENDLY_OFFSET, GSM_FRAME_SIZE) s->fr.mallocd = 0; if ((res = fread(s->fr.data.ptr, 1, GSM_FRAME_SIZE, s->f)) != GSM_FRAME_SIZE) { @@ -74,8 +74,8 @@ static int gsm_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_GSM) { - ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_GSM) { + ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if (!(f->datalen % 65)) { @@ -145,10 +145,9 @@ static off_t gsm_tell(struct ast_filestream *fs) return (offset/GSM_FRAME_SIZE)*GSM_SAMPLES; } -static const struct ast_format gsm_f = { +static struct ast_format_def gsm_f = { .name = "gsm", .exts = "gsm", - .format = AST_FORMAT_GSM, .write = gsm_write, .seek = gsm_seek, .trunc = gsm_trunc, @@ -159,14 +158,15 @@ static const struct ast_format gsm_f = { static int load_module(void) { - if (ast_format_register(&gsm_f)) + ast_format_set(&gsm_f.format, AST_FORMAT_GSM, 0); + if (ast_format_def_register(&gsm_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(gsm_f.name); + return ast_format_def_unregister(gsm_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw GSM data", diff --git a/formats/format_h263.c b/formats/format_h263.c index 12c9d017075bb78321fff4b220db0d9c076f0a16..76555a67c927fc7f1735dd85f8e48cb97625b1fe 100644 --- a/formats/format_h263.c +++ b/formats/format_h263.c @@ -64,7 +64,7 @@ static int h263_open(struct ast_filestream *s) static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext) { int res; - format_t mark; + uint32_t mark; unsigned short len; unsigned int ts; struct h263_desc *fs = (struct h263_desc *)s->_private; @@ -80,7 +80,7 @@ static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext) return NULL; } s->fr.frametype = AST_FRAME_VIDEO; - s->fr.subclass.codec = AST_FORMAT_H263; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_H263, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, len); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { @@ -90,7 +90,9 @@ static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext) } s->fr.samples = fs->lastts; /* XXX what ? */ s->fr.datalen = len; - s->fr.subclass.codec |= mark; + if (mark) { + ast_format_set_video_mark(&s->fr.subclass.format); + } s->fr.delivery.tv_sec = 0; s->fr.delivery.tv_usec = 0; if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) { @@ -106,18 +108,14 @@ static int h263_write(struct ast_filestream *fs, struct ast_frame *f) int res; unsigned int ts; unsigned short len; - format_t subclass; - format_t mark=0; + uint32_t mark = 0; if (f->frametype != AST_FRAME_VIDEO) { ast_log(LOG_WARNING, "Asked to write non-video frame!\n"); return -1; } - subclass = f->subclass.codec; - if (subclass & 0x1) - mark=0x8000; - subclass &= ~0x1; - if (subclass != AST_FORMAT_H263) { - ast_log(LOG_WARNING, "Asked to write non-h263 frame (%s)!\n", ast_getformatname(f->subclass.codec)); + mark = ast_format_get_video_mark(&f->subclass.format) ? 0x8000 : 0; + if (f->subclass.format.id != AST_FORMAT_H263) { + ast_log(LOG_WARNING, "Asked to write non-h263 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } ts = htonl(f->samples); @@ -157,10 +155,9 @@ static off_t h263_tell(struct ast_filestream *fs) return offset; /* XXX totally bogus, needs fixing */ } -static const struct ast_format h263_f = { +static struct ast_format_def h263_f = { .name = "h263", .exts = "h263", - .format = AST_FORMAT_H263, .open = h263_open, .write = h263_write, .seek = h263_seek, @@ -173,14 +170,15 @@ static const struct ast_format h263_f = { static int load_module(void) { - if (ast_format_register(&h263_f)) + ast_format_set(&h263_f.format, AST_FORMAT_H263, 0); + if (ast_format_def_register(&h263_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(h263_f.name); + return ast_format_def_unregister(h263_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw H.263 data", diff --git a/formats/format_h264.c b/formats/format_h264.c index f8fe75c427e1106c06f42de6674ed3e083bab11c..ea82454f3569b2c7e491125ad00b1dde1495584e 100644 --- a/formats/format_h264.c +++ b/formats/format_h264.c @@ -56,7 +56,7 @@ static int h264_open(struct ast_filestream *s) static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext) { int res; - int mark=0; + int mark = 0; unsigned short len; unsigned int ts; struct h264_desc *fs = (struct h264_desc *)s->_private; @@ -72,7 +72,7 @@ static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext) len = BUF_SIZE; /* XXX truncate */ } s->fr.frametype = AST_FRAME_VIDEO; - s->fr.subclass.codec = AST_FORMAT_H264; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_H264, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, len); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { @@ -82,7 +82,9 @@ static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext) } s->fr.samples = fs->lastts; s->fr.datalen = len; - s->fr.subclass.codec |= mark; + if (mark) { + ast_format_set_video_mark(&s->fr.subclass.format); + } s->fr.delivery.tv_sec = 0; s->fr.delivery.tv_usec = 0; if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) { @@ -104,9 +106,9 @@ static int h264_write(struct ast_filestream *s, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-video frame!\n"); return -1; } - mark = (f->subclass.codec & 0x1) ? 0x8000 : 0; - if ((f->subclass.codec & ~0x1) != AST_FORMAT_H264) { - ast_log(LOG_WARNING, "Asked to write non-h264 frame (%s)!\n", ast_getformatname(f->subclass.codec)); + mark = ast_format_get_video_mark(&f->subclass.format) ? 0x8000 : 0; + if (f->subclass.format.id != AST_FORMAT_H264) { + ast_log(LOG_WARNING, "Asked to write non-h264 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } ts = htonl(f->samples); @@ -146,10 +148,9 @@ static off_t h264_tell(struct ast_filestream *fs) return offset; /* XXX totally bogus, needs fixing */ } -static const struct ast_format h264_f = { +static struct ast_format_def h264_f = { .name = "h264", .exts = "h264", - .format = AST_FORMAT_H264, .open = h264_open, .write = h264_write, .seek = h264_seek, @@ -162,14 +163,15 @@ static const struct ast_format h264_f = { static int load_module(void) { - if (ast_format_register(&h264_f)) + ast_format_set(&h264_f.format, AST_FORMAT_H264, 0); + if (ast_format_def_register(&h264_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(h264_f.name); + return ast_format_def_unregister(h264_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw H.264 data", diff --git a/formats/format_ilbc.c b/formats/format_ilbc.c index 40bda2639382d24c683ff6ec3637bbb08f38e2a9..a60b585d7186a26a6c3d83c4d2de32c0e4c054e0 100644 --- a/formats/format_ilbc.c +++ b/formats/format_ilbc.c @@ -45,7 +45,7 @@ static struct ast_frame *ilbc_read(struct ast_filestream *s, int *whennext) int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_ILBC; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_ILBC, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, ILBC_BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { @@ -64,8 +64,8 @@ static int ilbc_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_ILBC) { - ast_log(LOG_WARNING, "Asked to write non-iLBC frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_ILBC) { + ast_log(LOG_WARNING, "Asked to write non-iLBC frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if (f->datalen % 50) { @@ -119,10 +119,9 @@ static off_t ilbc_tell(struct ast_filestream *fs) return (offset/ILBC_BUF_SIZE)*ILBC_SAMPLES; } -static const struct ast_format ilbc_f = { +static struct ast_format_def ilbc_f = { .name = "iLBC", .exts = "ilbc", - .format = AST_FORMAT_ILBC, .write = ilbc_write, .seek = ilbc_seek, .trunc = ilbc_trunc, @@ -133,14 +132,15 @@ static const struct ast_format ilbc_f = { static int load_module(void) { - if (ast_format_register(&ilbc_f)) + ast_format_set(&ilbc_f.format, AST_FORMAT_ILBC, 0); + if (ast_format_def_register(&ilbc_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(ilbc_f.name); + return ast_format_def_unregister(ilbc_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw iLBC data", diff --git a/formats/format_jpeg.c b/formats/format_jpeg.c index 9b1fb99652d96b6d72e0cc918359454467a12216..99de8dac1b4496ad38b8eaace2ee2f09e27f916e 100644 --- a/formats/format_jpeg.c +++ b/formats/format_jpeg.c @@ -48,7 +48,7 @@ static struct ast_frame *jpeg_read_image(int fd, int len) } memset(&fr, 0, sizeof(fr)); fr.frametype = AST_FRAME_IMAGE; - fr.subclass.codec = AST_FORMAT_JPEG; + ast_format_set(&fr.subclass.format, AST_FORMAT_JPEG, 0); fr.data.ptr = buf; fr.src = "JPEG Read"; fr.datalen = len; @@ -74,7 +74,7 @@ static int jpeg_write_image(int fd, struct ast_frame *fr) ast_log(LOG_WARNING, "Not an image\n"); return -1; } - if (fr->subclass.codec != AST_FORMAT_JPEG) { + if (fr->subclass.format.id != AST_FORMAT_JPEG) { ast_log(LOG_WARNING, "Not a jpeg image\n"); return -1; } @@ -92,7 +92,6 @@ static struct ast_imager jpeg_format = { .name = "jpg", .desc = "JPEG (Joint Picture Experts Group)", .exts = "jpg|jpeg", - .format = AST_FORMAT_JPEG, .read_image = jpeg_read_image, .identify = jpeg_identify, .write_image = jpeg_write_image, @@ -100,6 +99,7 @@ static struct ast_imager jpeg_format = { static int load_module(void) { + ast_format_set(&jpeg_format.format, AST_FORMAT_JPEG, 0); if (ast_image_register(&jpeg_format)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; diff --git a/formats/format_ogg_vorbis.c b/formats/format_ogg_vorbis.c index d2a08736084bfe4946014988e184fa175b1205c7..949a13f78b3823a91adedf8807ad88634ee56296 100644 --- a/formats/format_ogg_vorbis.c +++ b/formats/format_ogg_vorbis.c @@ -291,9 +291,9 @@ static int ogg_vorbis_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_SLINEAR) { + if (f->subclass.format.id != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%s)!\n", - ast_getformatname(f->subclass.codec)); + ast_getformatname(&f->subclass.format)); return -1; } if (!f->datalen) @@ -438,7 +438,7 @@ static struct ast_frame *ogg_vorbis_read(struct ast_filestream *fs, short *buf; /* SLIN data buffer */ fs->fr.frametype = AST_FRAME_VOICE; - fs->fr.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&fs->fr.subclass.format, AST_FORMAT_SLINEAR, 0); fs->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); buf = (short *)(fs->fr.data.ptr); /* SLIN data buffer */ @@ -528,10 +528,9 @@ static off_t ogg_vorbis_tell(struct ast_filestream *s) return -1; } -static const struct ast_format vorbis_f = { +static struct ast_format_def vorbis_f = { .name = "ogg_vorbis", .exts = "ogg", - .format = AST_FORMAT_SLINEAR, .open = ogg_vorbis_open, .rewrite = ogg_vorbis_rewrite, .write = ogg_vorbis_write, @@ -546,14 +545,15 @@ static const struct ast_format vorbis_f = { static int load_module(void) { - if (ast_format_register(&vorbis_f)) + ast_format_set(&vorbis_f.format, AST_FORMAT_SLINEAR, 0); + if (ast_format_def_register(&vorbis_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(vorbis_f.name); + return ast_format_def_unregister(vorbis_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "OGG/Vorbis audio", diff --git a/formats/format_pcm.c b/formats/format_pcm.c index 76eb9c6af19dc6686156411dd4a3ae849196f58c..ec628c5b3043ca0d1d7736c18d7f3195e122bb3d 100644 --- a/formats/format_pcm.c +++ b/formats/format_pcm.c @@ -80,7 +80,7 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = s->fmt->format; + ast_format_copy(&s->fr.subclass.format, &s->fmt->format); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { @@ -89,7 +89,7 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext) return NULL; } s->fr.datalen = res; - if (s->fmt->format == AST_FORMAT_G722) + if (s->fmt->format.id == AST_FORMAT_G722) *whennext = s->fr.samples = res * 2; else *whennext = s->fr.samples = res; @@ -126,7 +126,7 @@ static int pcm_seek(struct ast_filestream *fs, off_t sample_offset, int whence) } if (whence == SEEK_FORCECUR && offset > max) { /* extend the file */ size_t left = offset - max; - const char *src = (fs->fmt->format == AST_FORMAT_ALAW) ? alaw_silence : ulaw_silence; + const char *src = (fs->fmt->format.id == AST_FORMAT_ALAW) ? alaw_silence : ulaw_silence; while (left) { size_t written = fwrite(src, 1, (left > BUF_SIZE) ? BUF_SIZE : left, fs->f); @@ -163,8 +163,8 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != fs->fmt->format) { - ast_log(LOG_WARNING, "Asked to write incompatible format frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) == AST_FORMAT_CMP_NOT_EQUAL) { + ast_log(LOG_WARNING, "Asked to write incompatible format frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } @@ -373,7 +373,7 @@ static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence) off_t min, max, cur; long offset = 0, bytes; - if (fs->fmt->format == AST_FORMAT_G722) + if (fs->fmt->format.id == AST_FORMAT_G722) bytes = sample_offset / 2; else bytes = sample_offset; @@ -413,10 +413,9 @@ static off_t au_tell(struct ast_filestream *fs) return offset - AU_HEADER_SIZE; } -static const struct ast_format alaw_f = { +static struct ast_format_def alaw_f = { .name = "alaw", .exts = "alaw|al|alw", - .format = AST_FORMAT_ALAW, .write = pcm_write, .seek = pcm_seek, .trunc = pcm_trunc, @@ -430,10 +429,9 @@ static const struct ast_format alaw_f = { #endif }; -static const struct ast_format pcm_f = { +static struct ast_format_def pcm_f = { .name = "pcm", .exts = "pcm|ulaw|ul|mu|ulw", - .format = AST_FORMAT_ULAW, .write = pcm_write, .seek = pcm_seek, .trunc = pcm_trunc, @@ -442,10 +440,9 @@ static const struct ast_format pcm_f = { .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, }; -static const struct ast_format g722_f = { +static struct ast_format_def g722_f = { .name = "g722", .exts = "g722", - .format = AST_FORMAT_G722, .write = pcm_write, .seek = pcm_seek, .trunc = pcm_trunc, @@ -454,10 +451,9 @@ static const struct ast_format g722_f = { .buf_size = (BUF_SIZE * 2) + AST_FRIENDLY_OFFSET, }; -static const struct ast_format au_f = { +static struct ast_format_def au_f = { .name = "au", .exts = "au", - .format = AST_FORMAT_ULAW, .open = au_open, .rewrite = au_rewrite, .write = pcm_write, @@ -478,20 +474,24 @@ static int load_module(void) for (i = 0; i < ARRAY_LEN(alaw_silence); i++) alaw_silence[i] = AST_LIN2A(0); - if ( ast_format_register(&pcm_f) - || ast_format_register(&alaw_f) - || ast_format_register(&au_f) - || ast_format_register(&g722_f) ) + ast_format_set(&pcm_f.format, AST_FORMAT_ULAW, 0); + ast_format_set(&alaw_f.format, AST_FORMAT_ALAW, 0); + ast_format_set(&au_f.format, AST_FORMAT_ULAW, 0); + ast_format_set(&g722_f.format, AST_FORMAT_G722, 0); + if ( ast_format_def_register(&pcm_f) + || ast_format_def_register(&alaw_f) + || ast_format_def_register(&au_f) + || ast_format_def_register(&g722_f) ) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(pcm_f.name) - || ast_format_unregister(alaw_f.name) - || ast_format_unregister(au_f.name) - || ast_format_unregister(g722_f.name); + return ast_format_def_unregister(pcm_f.name) + || ast_format_def_unregister(alaw_f.name) + || ast_format_def_unregister(au_f.name) + || ast_format_def_unregister(g722_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw/Sun uLaw/ALaw 8KHz (PCM,PCMA,AU), G.722 16Khz", diff --git a/formats/format_siren14.c b/formats/format_siren14.c index 0b8526bde63ff53643b62791c3eb8cfc9dda0b90..53c9ea92211066017f3b450c757ed94b85b67fd8 100644 --- a/formats/format_siren14.c +++ b/formats/format_siren14.c @@ -41,7 +41,7 @@ static struct ast_frame *siren14read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_SIREN14; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_SIREN14, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { @@ -61,8 +61,8 @@ static int siren14write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_SIREN14) { - ast_log(LOG_WARNING, "Asked to write non-Siren14 frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_SIREN14) { + ast_log(LOG_WARNING, "Asked to write non-Siren14 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) { @@ -110,10 +110,9 @@ static off_t siren14tell(struct ast_filestream *fs) return BYTES_TO_SAMPLES(ftello(fs->f)); } -static const struct ast_format siren14_f = { +static struct ast_format_def siren14_f = { .name = "siren14", .exts = "siren14", - .format = AST_FORMAT_SIREN14, .write = siren14write, .seek = siren14seek, .trunc = siren14trunc, @@ -124,7 +123,8 @@ static const struct ast_format siren14_f = { static int load_module(void) { - if (ast_format_register(&siren14_f)) + ast_format_set(&siren14_f.format, AST_FORMAT_SIREN14, 0); + if (ast_format_def_register(&siren14_f)) return AST_MODULE_LOAD_DECLINE; return AST_MODULE_LOAD_SUCCESS; @@ -132,7 +132,7 @@ static int load_module(void) static int unload_module(void) { - return ast_format_unregister(siren14_f.name); + return ast_format_def_unregister(siren14_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ITU G.722.1 Annex C (Siren14, licensed from Polycom)", diff --git a/formats/format_siren7.c b/formats/format_siren7.c index 5c7919307b4beab24f064832e28fbd8f7b57a6d7..16eca5df59d9235185c8ef8b864ad6d157ac9ad5 100644 --- a/formats/format_siren7.c +++ b/formats/format_siren7.c @@ -41,7 +41,7 @@ static struct ast_frame *siren7read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_SIREN7; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_SIREN7, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { @@ -61,8 +61,8 @@ static int siren7write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_SIREN7) { - ast_log(LOG_WARNING, "Asked to write non-Siren7 frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_SIREN7) { + ast_log(LOG_WARNING, "Asked to write non-Siren7 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) { @@ -110,10 +110,9 @@ static off_t siren7tell(struct ast_filestream *fs) return BYTES_TO_SAMPLES(ftello(fs->f)); } -static const struct ast_format siren7_f = { +static struct ast_format_def siren7_f = { .name = "siren7", .exts = "siren7", - .format = AST_FORMAT_SIREN7, .write = siren7write, .seek = siren7seek, .trunc = siren7trunc, @@ -124,7 +123,8 @@ static const struct ast_format siren7_f = { static int load_module(void) { - if (ast_format_register(&siren7_f)) + ast_format_set(&siren7_f.format, AST_FORMAT_SIREN7, 0); + if (ast_format_def_register(&siren7_f)) return AST_MODULE_LOAD_DECLINE; return AST_MODULE_LOAD_SUCCESS; @@ -132,7 +132,7 @@ static int load_module(void) static int unload_module(void) { - return ast_format_unregister(siren7_f.name); + return ast_format_def_unregister(siren7_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ITU G.722.1 (Siren7, licensed from Polycom)", diff --git a/formats/format_sln.c b/formats/format_sln.c index 578e64c7baabba9513969e343d62a4d9def0a89b..0cb27949d6883e8de3eaee0317466c56a25fb1a0 100644 --- a/formats/format_sln.c +++ b/formats/format_sln.c @@ -39,7 +39,7 @@ static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_SLINEAR, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { @@ -59,8 +59,8 @@ static int slinear_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_SLINEAR) { - ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_SLINEAR) { + ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) { @@ -103,10 +103,9 @@ static off_t slinear_tell(struct ast_filestream *fs) return ftello(fs->f) / 2; } -static const struct ast_format slin_f = { +static struct ast_format_def slin_f = { .name = "sln", .exts = "sln|raw", - .format = AST_FORMAT_SLINEAR, .write = slinear_write, .seek = slinear_seek, .trunc = slinear_trunc, @@ -117,14 +116,15 @@ static const struct ast_format slin_f = { static int load_module(void) { - if (ast_format_register(&slin_f)) + ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR, 0); + if (ast_format_def_register(&slin_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(slin_f.name); + return ast_format_def_unregister(slin_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear Audio support (SLN)", diff --git a/formats/format_sln16.c b/formats/format_sln16.c index 1e324941204218d01d0f348a029ec5a29a3a1782..cac019615a8f18f1d08fb914812563003da9fb99 100644 --- a/formats/format_sln16.c +++ b/formats/format_sln16.c @@ -40,7 +40,7 @@ static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_SLINEAR16; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_SLINEAR16, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { @@ -61,8 +61,8 @@ static int slinear_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_SLINEAR16) { - ast_log(LOG_WARNING, "Asked to write non-slinear16 frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_SLINEAR16) { + ast_log(LOG_WARNING, "Asked to write non-slinear16 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) { @@ -110,10 +110,9 @@ static off_t slinear_tell(struct ast_filestream *fs) return ftello(fs->f) / 2; } -static const struct ast_format slin_f = { +static struct ast_format_def slin_f = { .name = "sln16", .exts = "sln16", - .format = AST_FORMAT_SLINEAR16, .write = slinear_write, .seek = slinear_seek, .trunc = slinear_trunc, @@ -124,7 +123,8 @@ static const struct ast_format slin_f = { static int load_module(void) { - if (ast_format_register(&slin_f)) + ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR16, 0); + if (ast_format_def_register(&slin_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; @@ -132,7 +132,7 @@ static int load_module(void) static int unload_module(void) { - return ast_format_unregister(slin_f.name); + return ast_format_def_unregister(slin_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear 16KHz Audio support (SLN16)", diff --git a/formats/format_vox.c b/formats/format_vox.c index c13dd7ac5042ec6f16843c34e54557fac98c9e64..05ecdeeaff6343f1a4678aa627595419b9051a80 100644 --- a/formats/format_vox.c +++ b/formats/format_vox.c @@ -41,7 +41,7 @@ static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext) /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_ADPCM; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_ADPCM, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { @@ -61,8 +61,8 @@ static int vox_write(struct ast_filestream *s, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_ADPCM) { - ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_ADPCM) { + ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) { @@ -108,10 +108,9 @@ static off_t vox_tell(struct ast_filestream *fs) return offset; } -static const struct ast_format vox_f = { +static struct ast_format_def vox_f = { .name = "vox", .exts = "vox", - .format = AST_FORMAT_ADPCM, .write = vox_write, .seek = vox_seek, .trunc = vox_trunc, @@ -122,14 +121,15 @@ static const struct ast_format vox_f = { static int load_module(void) { - if (ast_format_register(&vox_f)) + ast_format_set(&vox_f.format, AST_FORMAT_ADPCM, 0); + if (ast_format_def_register(&vox_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(vox_f.name); + return ast_format_def_unregister(vox_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Dialogic VOX (ADPCM) File Format", diff --git a/formats/format_wav.c b/formats/format_wav.c index 91a309ef4c116bc546f400ca2274891e10ec2ff9..74c14f21c8af8bd32523f8c37d5c23d76cbdd19c 100644 --- a/formats/format_wav.c +++ b/formats/format_wav.c @@ -319,7 +319,7 @@ static int wav_open(struct ast_filestream *s) if we did, it would go here. We also might want to check and be sure it's a valid file. */ struct wav_desc *tmp = (struct wav_desc *)s->_private; - if ((tmp->maxlen = check_header(s->f, (s->fmt->format == AST_FORMAT_SLINEAR16 ? 16000 : 8000))) < 0) + if ((tmp->maxlen = check_header(s->f, (s->fmt->format.id == AST_FORMAT_SLINEAR16 ? 16000 : 8000))) < 0) return -1; return 0; } @@ -331,7 +331,7 @@ static int wav_rewrite(struct ast_filestream *s, const char *comment) and be sure it's a valid file. */ struct wav_desc *tmp = (struct wav_desc *)s->_private; - tmp->hz = (s->fmt->format == AST_FORMAT_SLINEAR16 ? 16000 : 8000); + tmp->hz = (s->fmt->format.id == AST_FORMAT_SLINEAR16 ? 16000 : 8000); if (write_header(s->f,tmp->hz)) return -1; return 0; @@ -376,7 +376,7 @@ static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext) bytes = 0; /* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = (fs->hz == 16000 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR); + ast_format_set(&s->fr.subclass.format, (fs->hz == 16000 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR), 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes); @@ -412,11 +412,11 @@ static int wav_write(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if ((f->subclass.codec != AST_FORMAT_SLINEAR) && (f->subclass.codec != AST_FORMAT_SLINEAR16)) { - ast_log(LOG_WARNING, "Asked to write non-SLINEAR%s frame (%s)!\n", s->hz == 16000 ? "16" : "", ast_getformatname(f->subclass.codec)); + if ((f->subclass.format.id != AST_FORMAT_SLINEAR) && (f->subclass.format.id != AST_FORMAT_SLINEAR16)) { + ast_log(LOG_WARNING, "Asked to write non-SLINEAR%s frame (%s)!\n", s->hz == 16000 ? "16" : "", ast_getformatname(&f->subclass.format)); return -1; } - if (f->subclass.codec != fs->fmt->format) { + if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) == AST_FORMAT_CMP_NOT_EQUAL) { ast_log(LOG_WARNING, "Can't change SLINEAR frequency during write\n"); return -1; } @@ -486,10 +486,9 @@ static off_t wav_tell(struct ast_filestream *fs) return (offset - 44)/2; } -static const struct ast_format wav16_f = { +static struct ast_format_def wav16_f = { .name = "wav16", .exts = "wav16", - .format = AST_FORMAT_SLINEAR16, .open = wav_open, .rewrite = wav_rewrite, .write = wav_write, @@ -502,10 +501,9 @@ static const struct ast_format wav16_f = { .desc_size = sizeof(struct wav_desc), }; -static const struct ast_format wav_f = { +static struct ast_format_def wav_f = { .name = "wav", .exts = "wav", - .format = AST_FORMAT_SLINEAR, .open = wav_open, .rewrite = wav_rewrite, .write = wav_write, @@ -520,16 +518,18 @@ static const struct ast_format wav_f = { static int load_module(void) { - if (ast_format_register(&wav_f) - || ast_format_register(&wav16_f)) + ast_format_set(&wav_f.format, AST_FORMAT_SLINEAR, 0); + ast_format_set(&wav16_f.format, AST_FORMAT_SLINEAR16, 0); + if (ast_format_def_register(&wav_f) + || ast_format_def_register(&wav16_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(wav_f.name) - || ast_format_unregister(wav16_f.name); + return ast_format_def_unregister(wav_f.name) + || ast_format_def_unregister(wav16_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV/WAV16 format (8kHz/16kHz Signed Linear)", diff --git a/formats/format_wav_gsm.c b/formats/format_wav_gsm.c index f864f281409c9c319c0ac5492c34976b8e7ae422..ae1f11ed8df7a506d5f3d589b4b8dbb4b2cf700b 100644 --- a/formats/format_wav_gsm.c +++ b/formats/format_wav_gsm.c @@ -395,7 +395,7 @@ static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext) struct wavg_desc *fs = (struct wavg_desc *)s->_private; s->fr.frametype = AST_FRAME_VOICE; - s->fr.subclass.codec = AST_FORMAT_GSM; + ast_format_set(&s->fr.subclass.format, AST_FORMAT_GSM, 0); s->fr.offset = AST_FRIENDLY_OFFSET; s->fr.samples = GSM_SAMPLES; s->fr.mallocd = 0; @@ -432,8 +432,8 @@ static int wav_write(struct ast_filestream *s, struct ast_frame *f) ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } - if (f->subclass.codec != AST_FORMAT_GSM) { - ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(f->subclass.codec)); + if (f->subclass.format.id != AST_FORMAT_GSM) { + ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } /* XXX this might fail... if the input is a multiple of MSGSM_FRAME_SIZE @@ -521,10 +521,9 @@ static off_t wav_tell(struct ast_filestream *fs) return (offset - MSGSM_DATA_OFFSET)/MSGSM_FRAME_SIZE*MSGSM_SAMPLES; } -static const struct ast_format wav49_f = { +static struct ast_format_def wav49_f = { .name = "wav49", .exts = "WAV|wav49", - .format = AST_FORMAT_GSM, .open = wav_open, .rewrite = wav_rewrite, .write = wav_write, @@ -538,14 +537,15 @@ static const struct ast_format wav49_f = { static int load_module(void) { - if (ast_format_register(&wav49_f)) + ast_format_set(&wav49_f.format, AST_FORMAT_GSM, 0); + if (ast_format_def_register(&wav49_f)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) { - return ast_format_unregister(wav49_f.name); + return ast_format_def_unregister(wav49_f.name); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV format (Proprietary GSM)", diff --git a/funcs/func_channel.c b/funcs/func_channel.c index c0f85d372b79ba2639c7db9cf068a366de5a7707..548d0590f040561c9d0fc976c399ce2763230608 100644 --- a/funcs/func_channel.c +++ b/funcs/func_channel.c @@ -265,27 +265,30 @@ static int func_channel_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) { int ret = 0; + char tmp[512]; + struct ast_format_cap *tmpcap; - if (!strcasecmp(data, "audionativeformat")) - /* use the _multiple version when chan->nativeformats holds multiple formats */ - /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */ - ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len); - else if (!strcasecmp(data, "videonativeformat")) - /* use the _multiple version when chan->nativeformats holds multiple formats */ - /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */ - ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len); - else if (!strcasecmp(data, "audioreadformat")) - ast_copy_string(buf, ast_getformatname(chan->readformat), len); - else if (!strcasecmp(data, "audiowriteformat")) - ast_copy_string(buf, ast_getformatname(chan->writeformat), len); + if (!strcasecmp(data, "audionativeformat")) { + if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_AUDIO))) { + ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len); + tmpcap = ast_format_cap_destroy(tmpcap); + } + } else if (!strcasecmp(data, "videonativeformat")) { + if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_VIDEO))) { + ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len); + tmpcap = ast_format_cap_destroy(tmpcap); + } + } else if (!strcasecmp(data, "audioreadformat")) { + ast_copy_string(buf, ast_getformatname(&chan->readformat), len); + } else if (!strcasecmp(data, "audiowriteformat")) { + ast_copy_string(buf, ast_getformatname(&chan->writeformat), len); #ifdef CHANNEL_TRACE - else if (!strcasecmp(data, "trace")) { + } else if (!strcasecmp(data, "trace")) { ast_channel_lock(chan); ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len); ast_channel_unlock(chan); - } #endif - else if (!strcasecmp(data, "tonezone") && chan->zone) + } else if (!strcasecmp(data, "tonezone") && chan->zone) locked_copy_string(chan, buf, chan->zone->country, len); else if (!strcasecmp(data, "language")) locked_copy_string(chan, buf, chan->language, len); @@ -349,9 +352,9 @@ static int func_channel_read(struct ast_channel *chan, const char *function, ast_channel_unlock(chan); } else if (!strcasecmp(data, "uniqueid")) { locked_copy_string(chan, buf, chan->uniqueid, len); - } else if (!strcasecmp(data, "transfercapability")) + } else if (!strcasecmp(data, "transfercapability")) { locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len); - else if (!strcasecmp(data, "callgroup")) { + } else if (!strcasecmp(data, "callgroup")) { char groupbuf[256]; locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len); } else if (!strcasecmp(data, "amaflags")) { diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c index c4c8d397885e7a0962acfd7856ca692bde1dc5c3..5863b27e8ffc7c5b54f0af92d6dd84ee3ee54454 100644 --- a/funcs/func_frame_trace.c +++ b/funcs/func_frame_trace.c @@ -209,14 +209,14 @@ static void print_frame(struct ast_frame *frame) break; case AST_FRAME_VOICE: ast_verbose("FrameType: VOICE\n"); - ast_verbose("Codec: %s\n", ast_getformatname(frame->subclass.codec)); + ast_verbose("Codec: %s\n", ast_getformatname(&frame->subclass.format)); ast_verbose("MS: %ld\n", frame->len); ast_verbose("Samples: %d\n", frame->samples); ast_verbose("Bytes: %d\n", frame->datalen); break; case AST_FRAME_VIDEO: ast_verbose("FrameType: VIDEO\n"); - ast_verbose("Codec: %s\n", ast_getformatname(frame->subclass.codec)); + ast_verbose("Codec: %s\n", ast_getformatname(&frame->subclass.format)); ast_verbose("MS: %ld\n", frame->len); ast_verbose("Samples: %d\n", frame->samples); ast_verbose("Bytes: %d\n", frame->datalen); diff --git a/funcs/func_pitchshift.c b/funcs/func_pitchshift.c index 7b7c9a2caf45e4f078d87db2c491676049f742a0..36fa2f6c4c674bc04a1b7daf330f254924dae1cc 100644 --- a/funcs/func_pitchshift.c +++ b/funcs/func_pitchshift.c @@ -170,8 +170,8 @@ static int pitchshift_cb(struct ast_audiohook *audiohook, struct ast_channel *ch } if ((audiohook->status == AST_AUDIOHOOK_STATUS_DONE) || (f->frametype != AST_FRAME_VOICE) || - ((f->subclass.codec != AST_FORMAT_SLINEAR) && - (f->subclass.codec != AST_FORMAT_SLINEAR16))) { + ((f->subclass.format.id != AST_FORMAT_SLINEAR) && + (f->subclass.format.id != AST_FORMAT_SLINEAR16))) { return -1; } @@ -481,7 +481,7 @@ static int pitch_shift(struct ast_frame *f, float amount, struct fft_data *fft) return 0; } for (samples = 0; samples < f->samples; samples += 32) { - smb_pitch_shift(amount, 32, MAX_FRAME_LENGTH, 32, ast_format_rate(f->subclass.codec), fun+samples, fun+samples, fft); + smb_pitch_shift(amount, 32, MAX_FRAME_LENGTH, 32, ast_format_rate(&f->subclass.format), fun+samples, fun+samples, fft); } return 0; diff --git a/include/asterisk/abstract_jb.h b/include/asterisk/abstract_jb.h index 4efa924b8f70d33444a779813e9df045d1d5cc47..d51554b663f30f8f27f16eb8705c546ada3148f9 100644 --- a/include/asterisk/abstract_jb.h +++ b/include/asterisk/abstract_jb.h @@ -32,7 +32,7 @@ #include <sys/time.h> -#include "asterisk/frame_defs.h" +#include "asterisk/format.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -97,7 +97,7 @@ struct ast_jb /*! \brief The time the next frame should be played. */ long next; /*! \brief Voice format of the last frame in. */ - format_t last_format; + struct ast_format last_format; /*! \brief File for frame timestamp tracing. */ FILE *logfile; /*! \brief Jitterbuffer internal state flags. */ diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index ff35599caec85aa2ae513c6db7b5ae876601b49a..bf8dd42baec9602d58086a613abab4b57a1e07aa 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -771,18 +771,20 @@ int ao2_container_count(struct ao2_container *c); */ #ifdef REF_DEBUG -#define ao2_t_link(arg1, arg2, arg3) __ao2_link_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_link(arg1, arg2) __ao2_link_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_t_link(arg1, arg2, arg3) __ao2_link_debug((arg1), (arg2), 0, (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_link(arg1, arg2) __ao2_link_debug((arg1), (arg2), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_link_nolock(arg1, arg2) __ao2_link_debug((arg1), (arg2), OBJ_NOLOCK, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) #else -#define ao2_t_link(arg1, arg2, arg3) __ao2_link((arg1), (arg2)) -#define ao2_link(arg1, arg2) __ao2_link((arg1), (arg2)) +#define ao2_t_link(arg1, arg2, arg3) __ao2_link((arg1), (arg2), 0) +#define ao2_link(arg1, arg2) __ao2_link((arg1), (arg2), 0) +#define ao2_link_nolock(arg1, arg2) __ao2_link((arg1), (arg2), OBJ_NOLOCK) #endif -void *__ao2_link_debug(struct ao2_container *c, void *new_obj, char *tag, char *file, int line, const char *funcname); -void *__ao2_link(struct ao2_container *c, void *newobj); +void *__ao2_link_debug(struct ao2_container *c, void *new_obj, int flags, char *tag, char *file, int line, const char *funcname); +void *__ao2_link(struct ao2_container *c, void *newobj, int flags); /*! * \brief Remove an object from a container @@ -803,18 +805,20 @@ void *__ao2_link(struct ao2_container *c, void *newobj); */ #ifdef REF_DEBUG -#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_unlink(arg1, arg2) __ao2_unlink_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink_debug((arg1), (arg2), 0, (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_unlink(arg1, arg2) __ao2_unlink_debug((arg1), (arg2), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_unlink_nolock(arg1, arg2) __ao2_unlink_debug((arg1), (arg2), OBJ_NOLOCK, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) #else -#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink((arg1), (arg2)) -#define ao2_unlink(arg1, arg2) __ao2_unlink((arg1), (arg2)) +#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink((arg1), (arg2), 0) +#define ao2_unlink(arg1, arg2) __ao2_unlink((arg1), (arg2), 0) +#define ao2_unlink_nolock(arg1, arg2) __ao2_unlink((arg1), (arg2), OBJ_NOLOCK) #endif -void *__ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *file, int line, const char *funcname); -void *__ao2_unlink(struct ao2_container *c, void *obj); +void *__ao2_unlink_debug(struct ao2_container *c, void *obj, int flags, char *tag, char *file, int line, const char *funcname); +void *__ao2_unlink(struct ao2_container *c, void *obj, int flags); /*@} */ diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h index abf6ca34574dfe7ecd089d2ca5afbeca4fd591b1..75e2c876370c606127a855cf1024e4244e77792a 100644 --- a/include/asterisk/audiohook.h +++ b/include/asterisk/audiohook.h @@ -30,7 +30,6 @@ extern "C" { /* these two are used in struct ast_audiohook */ #include "asterisk/lock.h" #include "asterisk/linkedlists.h" -#include "asterisk/frame_defs.h" #include "asterisk/slinfactory.h" enum ast_audiohook_type { @@ -104,7 +103,7 @@ struct ast_audiohook { struct ast_slinfactory write_factory; /*!< Factory where frames written to the channel will go through */ struct timeval read_time; /*!< Last time read factory was fed */ struct timeval write_time; /*!< Last time write factory was fed */ - int format; /*!< Format translation path is setup as */ + struct ast_format format; /*!< Format translation path is setup as */ struct ast_trans_pvt *trans_pvt; /*!< Translation path for reading frames */ ast_audiohook_manipulate_callback manipulate_callback; /*!< Manipulation callback */ struct ast_audiohook_options options; /*!< Applicable options */ @@ -142,7 +141,7 @@ int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohoo * \param format Format of frame remote side wants back * \return Returns frame on success, NULL on failure */ -struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, format_t format); +struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format); /*! \brief Attach audiohook to channel * \param chan Channel diff --git a/include/asterisk/bridging.h b/include/asterisk/bridging.h index 3e34760022bf853296f8b46e2dbecf3438103e7d..810bc3705d57ded424c9721420b55d557144c32f 100644 --- a/include/asterisk/bridging.h +++ b/include/asterisk/bridging.h @@ -193,7 +193,7 @@ struct ast_bridge { * This creates a simple two party bridge that will be destroyed once one of * the channels hangs up. */ -struct ast_bridge *ast_bridge_new(format_t capabilities, int flags); +struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags); /*! \brief See if it is possible to create a bridge * @@ -211,7 +211,7 @@ struct ast_bridge *ast_bridge_new(format_t capabilities, int flags); * This sees if it is possible to create a bridge capable of bridging two channels * together. */ -int ast_bridge_check(format_t capabilities); +int ast_bridge_check(uint32_t capabilities); /*! \brief Destroy a bridge * diff --git a/include/asterisk/bridging_technology.h b/include/asterisk/bridging_technology.h index 0659abd779be03f6c6bb6ffddd7e9b9a9c98cdf4..c3e22975c28f07b04bb2e1216fdceb6d68141a71 100644 --- a/include/asterisk/bridging_technology.h +++ b/include/asterisk/bridging_technology.h @@ -44,8 +44,9 @@ enum ast_bridge_preference { struct ast_bridge_technology { /*! Unique name to this bridge technology */ const char *name; - /*! The capabilities that this bridge technology is capable of */ - format_t capabilities; + /*! The capabilities that this bridge technology is capable of. This has nothing to do with + * format capabilities. */ + uint32_t capabilities; /*! Preference level that should be used when determining whether to use this bridge technology or not */ enum ast_bridge_preference preference; /*! Callback for when a bridge is being created */ @@ -71,7 +72,7 @@ struct ast_bridge_technology { /*! Callback for poking a bridge thread */ int (*poke)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); /*! Formats that the bridge technology supports */ - format_t formats; + struct ast_format_cap *format_capabilities; /*! Bit to indicate whether the bridge technology is currently suspended or not */ unsigned int suspended:1; /*! Module this bridge technology belongs to. Is used for reference counting when creating/destroying a bridge. */ diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h index e052f64781625a5a511d43cb06e3088747dedff9..c047632b999ba390f063bc86ad160e79225c3e4a 100644 --- a/include/asterisk/callerid.h +++ b/include/asterisk/callerid.h @@ -45,7 +45,7 @@ #ifndef _ASTERISK_CALLERID_H #define _ASTERISK_CALLERID_H -#include "asterisk/frame_defs.h" +#include "asterisk/format.h" #define MAX_CALLERID_SIZE 32000 @@ -75,8 +75,8 @@ /*! MWI MDMF format -- generate name, callerid, date and MWI fields */ #define CID_MWI_TYPE_MDMF_FULL 0x02 -#define AST_LIN2X(a) ((codec == AST_FORMAT_ALAW) ? (AST_LIN2A(a)) : (AST_LIN2MU(a))) -#define AST_XLAW(a) ((codec == AST_FORMAT_ALAW) ? (AST_ALAW(a)) : (AST_MULAW(a))) +#define AST_LIN2X(a) ((codec->id == AST_FORMAT_ALAW) ? (AST_LIN2A(a)) : (AST_LIN2MU(a))) +#define AST_XLAW(a) ((codec->id == AST_FORMAT_ALAW) ? (AST_ALAW(a)) : (AST_MULAW(a))) struct callerid_state; @@ -101,7 +101,7 @@ void callerid_init(void); * \return It returns the size * (in bytes) of the data (if it returns a size of 0, there is probably an error) */ -int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, format_t codec); +int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec); /*! \brief Create a callerID state machine * \param cid_signalling Type of signalling in use @@ -124,7 +124,7 @@ struct callerid_state *callerid_new(int cid_signalling); * \retval 0 for "needs more samples" * \retval 1 if the CallerID spill reception is complete. */ -int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, format_t codec); +int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec); /*! \brief Read samples into the state machine. * \param cid Which state machine to act upon @@ -138,7 +138,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, * \retval 0 for "needs more samples" * \retval 1 if the CallerID spill reception is complete. */ -int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, format_t codec); +int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec); /*! \brief Extract info out of callerID state machine. Flags are listed above * \param cid Callerid state machine to act upon @@ -177,7 +177,7 @@ void callerid_free(struct callerid_state *cid); * \details * Acts like callerid_generate except uses an asterisk format callerid string. */ -int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, format_t codec); +int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec); /*! * \brief Generate message waiting indicator @@ -192,13 +192,13 @@ int ast_callerid_generate(unsigned char *buf, const char *name, const char *numb * \see callerid_generate() for more info as it uses the same encoding * \version 1.6.1 changed mdmf parameter to type, added name, number and flags for caller id message generation */ -int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, format_t codec, const char *name, +int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name, const char *number, int flags); /*! \brief Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm) * \see ast_callerid_generate() for other details */ -int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, format_t codec); +int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec); /*! \brief Destructively parse inbuf into name and location (or number) * \details @@ -223,7 +223,7 @@ int ast_callerid_parse(char *instr, char **name, char **location); * \param codec Which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW) * \return Returns -1 on error (if len is less than 2400), 0 on success. */ -int ast_gen_cas(unsigned char *outbuf, int sas, int len, format_t codec); +int ast_gen_cas(unsigned char *outbuf, int sas, int len, struct ast_format *codec); /*! * \brief Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s... diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index c9156daf1a92e556b4e11a98d4a336ce882f7237..f58ffc76750127b80ba78d04aeecac774f94475f 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -507,12 +507,12 @@ struct ast_channel_tech { const char * const type; const char * const description; - format_t capabilities; /*!< Bitmap of formats this channel can handle */ + struct ast_format_cap *capabilities; /*!< format capabilities this channel can handle */ int properties; /*!< Technology Properties */ /*! \brief Requester - to set up call data structures (pvt's) */ - struct ast_channel *(* const requester)(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); + struct ast_channel *(* const requester)(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause); int (* const devicestate)(void *data); /*!< Devicestate call back */ @@ -824,7 +824,7 @@ struct ast_channel { int fdno; /*!< Which fd had an event detected on */ int streamid; /*!< For streaming playback, the schedule ID */ int vstreamid; /*!< For streaming video playback, the schedule ID */ - format_t oldwriteformat; /*!< Original writer format */ + struct ast_format oldwriteformat; /*!< Original writer format */ int timingfd; /*!< Timing fd */ enum ast_channel_state _state; /*!< State of line -- Don't write directly, use ast_setstate() */ int rings; /*!< Number of rings so far */ @@ -839,11 +839,11 @@ struct ast_channel { int hangupcause; /*!< Why is the channel hanged up. See causes.h */ unsigned int flags; /*!< channel flags of AST_FLAG_ type */ int alertpipe[2]; - format_t nativeformats; /*!< Kinds of data this channel can natively handle */ - format_t readformat; /*!< Requested read format (after translation) */ - format_t writeformat; /*!< Requested write format (after translation) */ - format_t rawreadformat; /*!< Raw read format (before translation) */ - format_t rawwriteformat; /*!< Raw write format (before translation) */ + struct ast_format_cap *nativeformats; /*!< Kinds of data this channel can natively handle */ + struct ast_format readformat; /*!< Requested read format (after translation) */ + struct ast_format writeformat; /*!< Requested write format (after translation) */ + struct ast_format rawreadformat; /*!< Raw read format (before translation) */ + struct ast_format rawwriteformat; /*!< Raw write format (before translation) */ unsigned int emulate_dtmf_duration; /*!< Number of ms left to emulate DTMF for */ #ifdef HAVE_EPOLL int epfd; @@ -1252,7 +1252,7 @@ struct ast_channel *ast_channel_release(struct ast_channel *chan); * \brief Requests a channel * * \param type type of channel to request - * \param format requested channel format (codec) + * \param format capabilities for requested channel * \param requestor channel asking for data * \param data data to pass to the channel requester * \param status status @@ -1264,14 +1264,14 @@ struct ast_channel *ast_channel_release(struct ast_channel *chan); * \retval NULL failure * \retval non-NULL channel on success */ -struct ast_channel *ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status); +struct ast_channel *ast_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *status); /*! * \brief Request a channel of a given type, with data as optional information used * by the low level module and attempt to place a call on it * * \param type type of channel to request - * \param format requested channel format + * \param format capabilities for requested channel * \param requestor channel asking for data * \param data data to pass to the channel requester * \param timeout maximum amount of time to wait for an answer @@ -1282,14 +1282,14 @@ struct ast_channel *ast_request(const char *type, format_t format, const struct * \return Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state * to know if the call was answered or not. */ -struct ast_channel *ast_request_and_dial(const char *type, format_t format, const struct ast_channel *requestor, void *data, +struct ast_channel *ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int timeout, int *reason, const char *cid_num, const char *cid_name); /*! * \brief Request a channel of a given type, with data as optional information used * by the low level module and attempt to place a call on it * \param type type of channel to request - * \param format requested channel format + * \param format capabilities for requested channel * \param requestor channel requesting data * \param data data to pass to the channel requester * \param timeout maximum amount of time to wait for an answer @@ -1300,7 +1300,7 @@ struct ast_channel *ast_request_and_dial(const char *type, format_t format, cons * \return Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state * to know if the call was answered or not. */ -struct ast_channel *__ast_request_and_dial(const char *type, format_t format, const struct ast_channel *requestor, void *data, +struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int timeout, int *reason, const char *cid_num, const char *cid_name, struct outgoing_helper *oh); /*! @@ -1308,12 +1308,12 @@ struct ast_channel *__ast_request_and_dial(const char *type, format_t format, co * \param caller in channel that requested orig * \param orig channel being replaced by the call forward channel * \param timeout maximum amount of time to wait for setup of new forward channel - * \param format requested channel format + * \param format capabilities for requested channel * \param oh outgoing helper used with original channel * \param outstate reason why unsuccessful (if uncuccessful) * \return Returns the forwarded call's ast_channel on success or NULL on failure */ -struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, format_t format, struct outgoing_helper *oh, int *outstate); +struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, struct ast_format_cap *cap, struct outgoing_helper *oh, int *outstate); /*! * \brief Register a channel technology (a new channel driver) @@ -1743,22 +1743,54 @@ int ast_write_text(struct ast_channel *chan, struct ast_frame *frame); int ast_prod(struct ast_channel *chan); /*! - * \brief Sets read format on channel chan + * \brief Sets read format on channel chan from capabilities * Set read format for channel to whichever component of "format" is best. * \param chan channel to change - * \param format format to change to + * \param formats new formats to pick from for reading + * \return Returns 0 on success, -1 on failure + */ +int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap *formats); + +/*! + * \brief Sets read format on channel chan + * \param chan channel to change + * \param formats, format to set for reading * \return Returns 0 on success, -1 on failure */ -int ast_set_read_format(struct ast_channel *chan, format_t format); +int ast_set_read_format(struct ast_channel *chan, struct ast_format *format); + +/*! + * \brief Sets read format on channel chan by id + * \param chan channel to change + * \param format id to set for reading, only used for formats without attributes + * \return Returns 0 on success, -1 on failure + */ +int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id); /*! * \brief Sets write format on channel chan * Set write format for channel to whichever component of "format" is best. * \param chan channel to change - * \param format new format for writing + * \param formats new formats to pick from for writing * \return Returns 0 on success, -1 on failure */ -int ast_set_write_format(struct ast_channel *chan, format_t format); +int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_cap *formats); + +/*! + * \brief Sets write format on channel chan + * \param chan channel to change + * \param formats, format to set for writing + * \return Returns 0 on success, -1 on failure + */ +int ast_set_write_format(struct ast_channel *chan, struct ast_format *format); + +/*! + * \brief Sets write format on channel chan + * \param chan channel to change + * \param format id to set for writing, only used for formats without attributes + * \return Returns 0 on success, -1 on failure + */ +int ast_set_write_format_by_id(struct ast_channel *chan, enum ast_format_id id); /*! * \brief Sends text to a channel @@ -2023,9 +2055,15 @@ char *ast_transfercapability2str(int transfercapability) attribute_const; */ int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block); -/*! Pick the best codec - * Choose the best codec... Uhhh... Yah. */ -format_t ast_best_codec(format_t fmts); +/*! + * \brief Pick the best codec + * + * \param capabilities to pick best codec out of + * \param result stucture to store the best codec in. + * \retval on success, pointer to result structure + * \retval on failure, NULL + */ +struct ast_format *ast_best_codec(struct ast_format_cap *cap, struct ast_format *result); /*! diff --git a/include/asterisk/data.h b/include/asterisk/data.h index 6851bd511f48a4db5b728fa53e258246d62f94e2..e3253377e798326ce6aba97a95ef390470285f73 100644 --- a/include/asterisk/data.h +++ b/include/asterisk/data.h @@ -799,6 +799,16 @@ static inline struct in_addr ast_data_retrieve_ipaddr(struct ast_data *tree, con return ret.value.AST_DATA_IPADDR; } +/*! + * \brief Add the codec in the root node based on the format parameter. + * \param[in] root The astdata root node where to add the codec node. + * \param[in] node_name The name of the node where we are going to add the codec. + * \param[in] format The codec allowed. + * \return < 0 on error. + * \return 0 on success. + */ +int ast_data_add_codec(struct ast_data *root, const char *node_name, struct ast_format *format); + /*! * \brief Add the list of codecs in the root node based on the capability parameter. * \param[in] root The astdata root node where to add the codecs node. @@ -808,7 +818,7 @@ static inline struct in_addr ast_data_retrieve_ipaddr(struct ast_data *tree, con * \return < 0 on error. * \return 0 on success. */ -int ast_data_add_codecs(struct ast_data *root, const char *node_name, format_t capability); +int ast_data_add_codecs(struct ast_data *root, const char *node_name, struct ast_format_cap *capability); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/asterisk/file.h b/include/asterisk/file.h index 69de811652abc41ccc6ace7b44e7fd8ddc916f29..4b032510111629ee8cb92b80da4b322c869b2e61 100644 --- a/include/asterisk/file.h +++ b/include/asterisk/file.h @@ -90,7 +90,8 @@ int ast_stopstream(struct ast_channel *c); * \param fmt the format you wish to check (the extension) * \param preflang (the preferred language you wisht to find the file in) * See if a given file exists in a given format. If fmt is NULL, any format is accepted. - * \return 0 if file does not exist, non-zero positive otherwise. + * \retval 0, false. The file does not exist + * \retval 1, true. The file does exist. */ int ast_fileexists(const char *filename, const char *fmt, const char *preflang); diff --git a/include/asterisk/format.h b/include/asterisk/format.h new file mode 100644 index 0000000000000000000000000000000000000000..09212abc8167b0e56169397abcee8a9426d4ff67 --- /dev/null +++ b/include/asterisk/format.h @@ -0,0 +1,310 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2010, Digium, Inc. + * + * David Vossel <dvossel@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format API + * + * \author David Vossel <dvossel@digium.com> + */ + +#ifndef _AST_FORMAT_H_ +#define _AST_FORMAT_H_ + +#define AST_FORMAT_ATTR_SIZE 128 + +#define AST_FORMAT_INC 100000 + +/*! This is the value that ends a var list of format attribute + * key value pairs. */ +#define AST_FORMAT_ATTR_END -1 + +/* \brief Format Categories*/ +enum ast_format_type { + AST_FORMAT_TYPE_AUDIO = 1 * AST_FORMAT_INC, + AST_FORMAT_TYPE_VIDEO = 2 * AST_FORMAT_INC, + AST_FORMAT_TYPE_IMAGE = 3 * AST_FORMAT_INC, + AST_FORMAT_TYPE_TEXT = 4 * AST_FORMAT_INC, +}; + +enum ast_format_id { + /*! G.723.1 compression */ + AST_FORMAT_G723_1 = 1 + AST_FORMAT_TYPE_AUDIO, + /*! GSM compression */ + AST_FORMAT_GSM = 2 + AST_FORMAT_TYPE_AUDIO, + /*! Raw mu-law data (G.711) */ + AST_FORMAT_ULAW = 3 + AST_FORMAT_TYPE_AUDIO, + /*! Raw A-law data (G.711) */ + AST_FORMAT_ALAW = 4 + AST_FORMAT_TYPE_AUDIO, + /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */ + AST_FORMAT_G726_AAL2 = 5 + AST_FORMAT_TYPE_AUDIO, + /*! ADPCM (IMA) */ + AST_FORMAT_ADPCM = 6 + AST_FORMAT_TYPE_AUDIO, + /*! Raw 16-bit Signed Linear (8000 Hz) PCM */ + AST_FORMAT_SLINEAR = 7 + AST_FORMAT_TYPE_AUDIO, + /*! LPC10, 180 samples/frame */ + AST_FORMAT_LPC10 = 8 + AST_FORMAT_TYPE_AUDIO, + /*! G.729A audio */ + AST_FORMAT_G729A = 9 + AST_FORMAT_TYPE_AUDIO, + /*! SpeeX Free Compression */ + AST_FORMAT_SPEEX = 10 + AST_FORMAT_TYPE_AUDIO, + /*! iLBC Free Compression */ + AST_FORMAT_ILBC = 11 + AST_FORMAT_TYPE_AUDIO, + /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */ + AST_FORMAT_G726 = 12 + AST_FORMAT_TYPE_AUDIO, + /*! G.722 */ + AST_FORMAT_G722 = 13 + AST_FORMAT_TYPE_AUDIO, + /*! G.722.1 (also known as Siren7, 32kbps assumed) */ + AST_FORMAT_SIREN7 = 14 + AST_FORMAT_TYPE_AUDIO, + /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */ + AST_FORMAT_SIREN14 = 15 + AST_FORMAT_TYPE_AUDIO, + /*! Raw 16-bit Signed Linear (16000 Hz) PCM */ + AST_FORMAT_SLINEAR16 = 16 + AST_FORMAT_TYPE_AUDIO, + /*! G.719 (64 kbps assumed) */ + AST_FORMAT_G719 = 17 + AST_FORMAT_TYPE_AUDIO, + /*! SpeeX Wideband (16kHz) Free Compression */ + AST_FORMAT_SPEEX16 = 18 + AST_FORMAT_TYPE_AUDIO, + /*! Raw mu-law data (G.711) */ + AST_FORMAT_TESTLAW = 19 + AST_FORMAT_TYPE_AUDIO, + + /*! H.261 Video */ + AST_FORMAT_H261 = 1 + AST_FORMAT_TYPE_VIDEO, + /*! H.263 Video */ + AST_FORMAT_H263 = 2 + AST_FORMAT_TYPE_VIDEO, + /*! H.263+ Video */ + AST_FORMAT_H263_PLUS = 3 + AST_FORMAT_TYPE_VIDEO, + /*! H.264 Video */ + AST_FORMAT_H264 = 4 + AST_FORMAT_TYPE_VIDEO, + /*! MPEG4 Video */ + AST_FORMAT_MP4_VIDEO = 5 + AST_FORMAT_TYPE_VIDEO, + + /*! JPEG Images */ + AST_FORMAT_JPEG = 1 + AST_FORMAT_TYPE_IMAGE, + /*! PNG Images */ + AST_FORMAT_PNG = 2 + AST_FORMAT_TYPE_IMAGE, + + /*! T.140 RED Text format RFC 4103 */ + AST_FORMAT_T140RED = 1 + AST_FORMAT_TYPE_TEXT, + /*! T.140 Text format - ITU T.140, RFC 4103 */ + AST_FORMAT_T140 = 2 + AST_FORMAT_TYPE_TEXT, +}; + +/*! Determine what type of media a ast_format_id is. */ +#define AST_FORMAT_GET_TYPE(id) (((int) (id / AST_FORMAT_INC)) * AST_FORMAT_INC) + +/*! \brief This structure contains the buffer used for format attributes */ +struct ast_format_attr { + /*! The buffer formats can use to represent attributes */ + uint8_t format_attr[AST_FORMAT_ATTR_SIZE]; + /*! If a format's payload needs to pass through that a new marker is required + * for RTP, this variable will be set. */ + uint8_t rtp_marker_bit; +}; + +/*! \brief Represents a media format within Asterisk. */ +struct ast_format { + /*! The unique id representing this format from all the other formats. */ + enum ast_format_id id; + /*! Attribute structure used to associate attributes with a format. */ + struct ast_format_attr fattr; +}; + +enum ast_format_cmp_res { + /*! structure 1 is identical to structure 2. */ + AST_FORMAT_CMP_EQUAL = 0, + /*! structure 1 contains elements not in structure 2. */ + AST_FORMAT_CMP_NOT_EQUAL, + /*! structure 1 is a proper subset of the elements in structure 2.*/ + AST_FORMAT_CMP_SUBSET, +}; + +/*! \brief A format must register an attribute interface if it requires the use of the format attributes void pointer */ +struct ast_format_attr_interface { + /*! format type */ + enum ast_format_id id; + + /*! \brief Determine if format_attr 1 is a subset of format_attr 2. + * + * \retval ast_format_cmp_res representing the result of comparing fattr1 and fattr2. + */ + enum ast_format_cmp_res (* const format_attr_cmp)(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2); + + /*! \brief Get joint attributes of same format type if they exist. + * + * \retval 0 if joint attributes exist + * \retval -1 if no joint attributes are present + */ + int (* const format_attr_get_joint)(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result); + + /*! \brief Set format capabilities from a list of key value pairs ending with AST_FORMAT_ATTR_END. + * \note This function does not need to call va_end of the va_list. */ + void (* const format_attr_set)(struct ast_format_attr *format_attr, va_list ap); +}; + +/*! + * \brief This function is used to set an ast_format object to represent a media format + * with optional format attributes represented by format specific key value pairs. + * + * \param format to set + * \param id, format id to set on format + * \param set_attributes, are there attributes to set on this format. 0 == false, 1 == True. + * \param var list of attribute key value pairs, must end with AST_FORMAT_ATTR_END; + * + * \details Example usage. + * ast_format_set(format, AST_FORMAT_ULAW, 0); // no capability attributes are needed for ULAW + * + * ast_format_set(format, AST_FORMAT_SILK, 1, // SILK has capability attributes. + * AST_FORMAT_SILK_ATTR_RATE, 24000, + * AST_FORMAT_SILK_ATTR_RATE, 16000, + * AST_FORMAT_SILK_ATTR_RATE, 12000, + * AST_FORMAT_SILK_ATTR_RATE, 8000, + * AST_FORMAT_ATTR_END); + * + * \note This function will initialize the ast_format structure. + * + * \return Pointer to ast_format object, same pointer that is passed in + * by the first argument. + */ +struct ast_format *ast_format_set(struct ast_format *format, enum ast_format_id id, int set_attributes, ... ); + +/*! + * \brief After ast_format_set has been used on a function, this function can be used to + * set additional format attributes to the structure. + * + * \param format to set + * \param var list of attribute key value pairs, must end with AST_FORMAT_ATTR_END; + * + * \details Example usage. + * ast_format_set(format, AST_FORMAT_SILK, 0); + * ast_format_append(format, // SILK has capability attributes. + * AST_FORMAT_SILK_ATTR_RATE, 24000, + * AST_FORMAT_SILK_ATTR_RATE, 16000, + * AST_FORMAT_SILK_ATTR_RATE, 12000, + * AST_FORMAT_SILK_ATTR_RATE, 8000, + * AST_FORMAT_ATTR_END); + * + * \return Pointer to ast_format object, same pointer that is passed in + * by the first argument. + */ +struct ast_format *ast_format_append(struct ast_format *format, ... ); + +/*! + * \brief Clears the format stucture. + */ +void ast_format_clear(struct ast_format *format); + +/*! + * \brief This function is used to set an ast_format object to represent a media format + * with optional capability attributes represented by format specific key value pairs. + * + * \details Example usage. Is this SILK format capable of 8khz + * is_8khz = ast_format_isset(format, AST_FORMAT_SILK_CAP_RATE, 8000); + * + * \return 0, The format key value pairs are within the capabilities defined in this structure. + * \return -1, The format key value pairs are _NOT_ within the capabilities of this structure. + */ +int ast_format_isset(struct ast_format *format, ... ); + +/*! + * \brief Compare ast_formats structures + * + * \retval ast_format_cmp_res representing the result of comparing format1 and format2. + */ +enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2); + +/*! + * \brief Find joint format attributes of two ast_format + * structures containing the same uid and return the intersection in the + * result structure. + * + * retval 0, joint attribute capabilities exist. + * retval -1, no joint attribute capabilities exist. + */ +int ast_format_joint(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result); + +/*! + * \brief copy format src into format dst. + */ +void ast_format_copy(struct ast_format *dst, const struct ast_format *src); + +/*! + * \brief Set the rtp mark value on the format to indicate to the interface + * writing this format's payload that a new RTP marker is necessary. + */ +void ast_format_set_video_mark(struct ast_format *format); + +/*! + * \brief Determine of the marker bit is set or not on this format. + * + * \retval 1, true + * \retval 0, false + */ +int ast_format_get_video_mark(const struct ast_format *format); + +/*! + * \brief ast_format to old bitfield format represenatation + * + * \note This is only to be used for IAX2 compatibility + * + * \retval iax2 representation of ast_format + * \retval 0, if no representation existis for iax2 + */ +uint64_t ast_format_to_old_bitfield(const struct ast_format *format); + +/*! + * \brief ast_format_id to old bitfield format represenatation + * + */ +uint64_t ast_format_id_to_old_bitfield(enum ast_format_id id); + +/*! + * \brief convert old bitfield format to ast_format represenatation + * \note This is only to be used for IAX2 compatibility + * + * \retval on success, pointer to the dst format in the input parameters + * \retval on failure, NULL + */ +struct ast_format *ast_format_from_old_bitfield(struct ast_format *dst, uint64_t src); + +/*! + * \brief convert old bitfield format to ast_format_id value + */ +enum ast_format_id ast_format_id_from_old_bitfield(uint64_t src); + +/*! + * \brief register ast_format_attr_interface with core. + * + * \retval 0 success + * \retval -1 failure + */ +int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interface); + +/*! + * \brief unregister format_attr interface with core. + * + * \retval 0 success + * \retval -1 failure + */ +int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *interface); + +/*! + * \brief Init the ast_format attribute interface register container. + */ +int ast_format_attr_init(void); + +#endif /* _AST_FORMAT_H */ diff --git a/include/asterisk/format_cap.h b/include/asterisk/format_cap.h new file mode 100644 index 0000000000000000000000000000000000000000..301ec1471e442368bfe1544ac0a028cb517319b0 --- /dev/null +++ b/include/asterisk/format_cap.h @@ -0,0 +1,273 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2010, Digium, Inc. + * + * David Vossel <dvossel@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format Capability API + * + * \author David Vossel <dvossel@digium.com> + */ + +#ifndef _AST_FORMATCAP_H_ +#define _AST_FORMATCAP_H_ + +/*! Capabilities are represented by an opaque structure statically defined in format_capability.c */ +struct ast_format_cap; + +/*! + * \brief Allocate a new ast_format_cap structure. + * + * \note Allocation of this object assumes locking + * is already occuring and that the point of contention + * is above this capabilities structure. For example, + * a tech_pvt object referencing a capabilities structure + * can use this function as long as it always holds the + * tech_pvt lock while accessing its capabilities. + * + * \retval ast_format_cap object on success. + * \retval NULL on failure. + */ +struct ast_format_cap *ast_format_cap_alloc_nolock(void); + +/*! + * \brief Allocate a new ast_format_cap structure with locking + * + * \note If no other form of locking is taking place, use this function. + * This function makes most sense for globally accessible capabilities structures + * that have no other means of locking. + * + * \retval ast_format_cap object on success. + * \retval NULL on failure. + */ +struct ast_format_cap *ast_format_cap_alloc(void); + +/*! + * \brief Destroy an ast_format_cap structure. + * + * \return NULL + */ +void *ast_format_cap_destroy(struct ast_format_cap *cap); + +/*! + * \brief Add format capability to capabilities structure. + * + * \note A copy of the input format is made and that copy is + * what is placed in the ast_format_cap structure. The actual + * input format ptr is not stored. + */ +void ast_format_cap_add(struct ast_format_cap *cap, struct ast_format *format); + +/*! + * \brief Add all formats Asterisk knows about for a specific type to + * the capabilities structure. Formats with attributes are set, but their + * attributes are initilized to 0's. An attribute structure of 0's should + * indicate to the format attribute interface that the format has full + * capabilities. + * + * \note A copy of the input format is made and that copy is + * what is placed in the ast_format_cap structure. The actual + * input format ptr is not stored. + */ +void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type); + +/*! + * \brief Add all known formats to the capabilities structure using default format attribute. */ +void ast_format_cap_add_all(struct ast_format_cap *cap); + +/*! + * \brief Append the formats in src to dst + */ +void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src); + +/*! + * \brief Copy all items in src to dst. + * \note any items in dst will be removed before copying + */ +void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src); + +/*! + * \brief create a deep copy of an ast_format_cap structure + * + * \retval cap on success + * \retval NULL on failure + */ +struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *src); + +/*! + * \brief determine if a capabilities structure is empty or not + * + * \retval 1, true is empty + * \retval 0, false, not empty + */ +int ast_format_cap_is_empty(const struct ast_format_cap *cap); + +/*! + * \brief Remove format capability from capability structure. + * + * \Note format must match Exactly to format in ast_format_cap object in order + * to be removed. + * + * \retval 0, remove was successful + * \retval -1, remove failed. Could not find format to remove + */ +int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format); + +/*! + * \brief Remove all format capabilities from capability + * structure for a specific format id. + * + * \Note This will remove _ALL_ formats matching the format id from the + * capabilities structure. + * + * \retval 0, remove was successful + * \retval -1, remove failed. Could not find formats to remove + */ +int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id); + +/*! + * \brief Remove all formats matching a specific format type. + */ +void ast_format_cap_remove_bytype(struct ast_format_cap *cap, enum ast_format_type type); + +/*! + * \brief Remove all format capabilities from capability structure + */ +void ast_format_cap_remove_all(struct ast_format_cap *cap); + +/*! + * \brief Remove all previous formats and set a single new format. + */ +void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format); + +/*! + * \brief Find if ast_format is within the capabilities of the ast_format_cap object. + * + * retval 1 format is compatible with formats held in ast_format_cap object. + * retval 0 format is not compatible with any formats in ast_format_cap object. + */ +int ast_format_cap_iscompatible(const struct ast_format_cap *cap, const struct ast_format *format); + +/*! + * \brief is cap1 identical to cap2 + * + * retval 1 true, identical + * retval 0 false, not identical + */ +int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2); + +/*! + * \brief Get joint capability structure. + * + * \note returns an ast_format_cap object containing the joint capabilities on success. This new + * capabilities structure is allocated with _NO_ locking enabled. If a joint structure requires + * locking, allocate it and use the ast_format_cap_joint_copy function to fill it with the joint + * capabilities. + * + * \retval !NULL success, joint capabilties structure with _NO_ locking enabled. + * \retval NULL failure + */ +struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2); + +/*! + * \brief Get joint capability structure, copy into result capabilities structure + * + * \retval 1, joint capabilities exist + * \retval 0, joint capabilities do not exist + */ +int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result); + +/*! + * \brief Find out if capability structures have any joint capabilities without + * returning those capabilities. + * + * \retval 1 true, has joint capabilities + * \retval 0 false, failure + */ +int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2); + +/*! + * \brief Get all capabilities for a specific media type + * + * \retval !NULL success, new capabilities structure with _NO_ locking enabled on the new structure. + * \retval NULL failure + */ +struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype); + +/*! + * \brief Find out if the capabilities structure has any formats + * of a specific type. + * + * \retval 1 true + * \retval 0 false, no formats of specific type. + */ +int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type); + +/*! \brief Start iterating formats */ +void ast_format_cap_iter_start(struct ast_format_cap *cap); + +/*! + * \brief Next format in interation + * + * \details + * Here is how to use the ast_format_cap iterator. + * + * 1. call ast_format_cap_iter_start + * 2. call ast_format_cap_iter_next in a loop until it returns -1 + * 3. call ast_format_cap_iter_end to terminate the iterator. + * + * example: + * + * ast_format_cap_iter_start(cap); + * while (!ast_format_cap_iter_next(cap, &format)) { + * + * } + * ast_format_cap_iter_end(Cap); + * + * \Note Unless the container was alloced using no_lock, the container + * will be locked during the entire iteration until ast_format_cap_iter_end + * is called. XXX Remember this, and do not attempt to lock any containers + * within this iteration that will violate locking order. + * + * \retval 0 on success, new format is copied into input format struct + * \retval -1, no more formats are present. + */ +int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format); + +/*! + * \brief Ends ast_format_cap iteration. + * \note this must be call after every ast_format_cap_iter_start + */ +void ast_format_cap_iter_end(struct ast_format_cap *cap); + +/*! + * \brief ast_format_cap to old bitfield format represenatation + * + * \note This is only to be used for IAX2 compatibility + * + * \retval old bitfield representation of ast_format_cap + * \retval 0, if no old bitfield capabilities are present in ast_format_cap + */ +uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap); + +/*! + * \brief convert old bitfield format to ast_format_cap represenatation + * \note This is only to be used for IAX2 compatibility + */ +void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src); + +#endif /* _AST_FORMATCAP_H */ diff --git a/include/asterisk/format_pref.h b/include/asterisk/format_pref.h new file mode 100644 index 0000000000000000000000000000000000000000..73a0bdc45231450c4ebffdaf47b21ff48c248a23 --- /dev/null +++ b/include/asterisk/format_pref.h @@ -0,0 +1,114 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2010, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format Preference API + */ + +#ifndef _AST_FORMATPREF_H_ +#define _AST_FORMATPREF_H_ + +#include "asterisk/format.h" +#include "asterisk/format_cap.h" + +#define AST_CODEC_PREF_SIZE 64 +struct ast_codec_pref { + /*! This array represents the each format in the pref list */ + struct ast_format formats[AST_CODEC_PREF_SIZE]; + /*! This array represents the format id's index in the global format list. */ + char order[AST_CODEC_PREF_SIZE]; + /*! This array represents the format's framing size if present. */ + char framing[AST_CODEC_PREF_SIZE]; +}; + +/*! \page AudioCodecPref Audio Codec Preferences + + In order to negotiate audio codecs in the order they are configured + in \<channel\>.conf for a device, we set up codec preference lists + in addition to the codec capabilities setting. The capabilities + setting is a bitmask of audio and video codecs with no internal + order. This will reflect the offer given to the other side, where + the prefered codecs will be added to the top of the list in the + order indicated by the "allow" lines in the device configuration. + + Video codecs are not included in the preference lists since they + can't be transcoded and we just have to pick whatever is supported +*/ + +/*! + *\brief Initialize an audio codec preference to "no preference". + * \arg \ref AudioCodecPref +*/ +void ast_codec_pref_init(struct ast_codec_pref *pref); + +/*! + * \brief Codec located at a particular place in the preference index. + * \param preference structure to get the codec out of + * \param index to retrieve from + * \param retult ast_format structure to store the index value in + * \return pointer to input ast_format on success, NULL on failure +*/ +struct ast_format *ast_codec_pref_index(struct ast_codec_pref *pref, int index, struct ast_format *result); + +/*! \brief Remove audio a codec from a preference list */ +void ast_codec_pref_remove(struct ast_codec_pref *pref, struct ast_format *format); + +/*! \brief Append a audio codec to a preference list, removing it first if it was already there +*/ +int ast_codec_pref_append(struct ast_codec_pref *pref, struct ast_format *format); + +/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there +*/ +void ast_codec_pref_prepend(struct ast_codec_pref *pref, struct ast_format *format, int only_if_existing); + +/*! \brief Select the best audio format according to preference list from supplied options. + * Best audio format is returned in the result format. + * + * \note If "find_best" is non-zero then if nothing is found, the "Best" format of + * the format list is selected and returned in the result structure, otherwise + * NULL is returned + * + * \retval ptr to result struture. + * \retval NULL, best codec was not found + */ +struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result); + +/*! \brief Set packet size for codec +*/ +int ast_codec_pref_setsize(struct ast_codec_pref *pref, struct ast_format *format, int framems); + +/*! \brief Get packet size for codec +*/ +struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format); + +/*! \brief Dump audio codec preference list into a string */ +int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size); + +/*! \brief Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string + * \note Due to a misunderstanding in how codec preferences are stored, this + * list starts at 'B', not 'A'. For backwards compatibility reasons, this + * cannot change. + * \param pref A codec preference list structure + * \param buf A string denoting codec preference, appropriate for use in line transmission + * \param size Size of \a buf + * \param right Boolean: if 0, convert from \a buf to \a pref; if 1, convert from \a pref to \a buf. + */ +void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right); + +#endif /* _AST_FORMATPREF_H */ diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index 0d8fc0b22ba5aa3bc5921c919c2924588d14a2ed..fc7c1a07b2b2a2d2236f9ccb4dc99852de24f5b7 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -31,15 +31,11 @@ extern "C" { #include <sys/time.h> -#include "asterisk/frame_defs.h" +#include "asterisk/format_pref.h" +#include "asterisk/format.h" #include "asterisk/endian.h" #include "asterisk/linkedlists.h" -struct ast_codec_pref { - char order[sizeof(format_t) * 8]; - char framing[sizeof(format_t) * 8]; -}; - /*! * \page Def_Frame AST Multimedia and signalling frames * \section Def_AstFrame What is an ast_frame ? @@ -134,7 +130,7 @@ enum { union ast_frame_subclass { int integer; - format_t codec; + struct ast_format format; }; /*! \brief Data structure associated with a single frame of data @@ -237,78 +233,6 @@ extern struct ast_frame ast_null_frame; /*! Reject link request */ #define AST_HTML_LINKREJECT 20 -/* Data formats for capabilities and frames alike */ -/*! G.723.1 compression */ -#define AST_FORMAT_G723_1 (1ULL << 0) -/*! GSM compression */ -#define AST_FORMAT_GSM (1ULL << 1) -/*! Raw mu-law data (G.711) */ -#define AST_FORMAT_ULAW (1ULL << 2) -/*! Raw A-law data (G.711) */ -#define AST_FORMAT_ALAW (1ULL << 3) -/*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */ -#define AST_FORMAT_G726_AAL2 (1ULL << 4) -/*! ADPCM (IMA) */ -#define AST_FORMAT_ADPCM (1ULL << 5) -/*! Raw 16-bit Signed Linear (8000 Hz) PCM */ -#define AST_FORMAT_SLINEAR (1ULL << 6) -/*! LPC10, 180 samples/frame */ -#define AST_FORMAT_LPC10 (1ULL << 7) -/*! G.729A audio */ -#define AST_FORMAT_G729A (1ULL << 8) -/*! SpeeX Free Compression */ -#define AST_FORMAT_SPEEX (1ULL << 9) -/*! iLBC Free Compression */ -#define AST_FORMAT_ILBC (1ULL << 10) -/*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */ -#define AST_FORMAT_G726 (1ULL << 11) -/*! G.722 */ -#define AST_FORMAT_G722 (1ULL << 12) -/*! G.722.1 (also known as Siren7, 32kbps assumed) */ -#define AST_FORMAT_SIREN7 (1ULL << 13) -/*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */ -#define AST_FORMAT_SIREN14 (1ULL << 14) -/*! Raw 16-bit Signed Linear (16000 Hz) PCM */ -#define AST_FORMAT_SLINEAR16 (1ULL << 15) -/*! Maximum audio mask */ -#define AST_FORMAT_AUDIO_MASK 0xFFFF0000FFFFULL -/*! JPEG Images */ -#define AST_FORMAT_JPEG (1ULL << 16) -/*! PNG Images */ -#define AST_FORMAT_PNG (1ULL << 17) -/*! H.261 Video */ -#define AST_FORMAT_H261 (1ULL << 18) -/*! H.263 Video */ -#define AST_FORMAT_H263 (1ULL << 19) -/*! H.263+ Video */ -#define AST_FORMAT_H263_PLUS (1ULL << 20) -/*! H.264 Video */ -#define AST_FORMAT_H264 (1ULL << 21) -/*! MPEG4 Video */ -#define AST_FORMAT_MP4_VIDEO (1ULL << 22) -#define AST_FORMAT_VIDEO_MASK ((((1ULL << 25)-1) & ~(AST_FORMAT_AUDIO_MASK)) | 0x7FFF000000000000ULL) -/*! T.140 RED Text format RFC 4103 */ -#define AST_FORMAT_T140RED (1ULL << 26) -/*! T.140 Text format - ITU T.140, RFC 4103 */ -#define AST_FORMAT_T140 (1ULL << 27) -/*! Maximum text mask */ -#define AST_FORMAT_MAX_TEXT (1ULL << 28) -#define AST_FORMAT_TEXT_MASK (((1ULL << 30)-1) & ~(AST_FORMAT_AUDIO_MASK) & ~(AST_FORMAT_VIDEO_MASK)) -/*! G.719 (64 kbps assumed) */ -#define AST_FORMAT_G719 (1ULL << 32) -/*! SpeeX Wideband (16kHz) Free Compression */ -#define AST_FORMAT_SPEEX16 (1ULL << 33) -/*! Raw mu-law data (G.711) */ -#define AST_FORMAT_TESTLAW (1ULL << 47) -/*! Reserved bit - do not use - * \warning We use this bit internally for iteration. Additionally, using this - * bit will severely break the implementation of codec prefs within IAX2, as we - * rely on the equivalence of UTF-8 and ASCII. The codec represented by this - * bit should use the first two-byte encoding of UTF-8, which is not presently - * accounted for. Hence, we reserve this bit as unused. - */ -#define AST_FORMAT_RESERVED (1ULL << 63) - enum ast_control_frame_type { AST_CONTROL_HANGUP = 1, /*!< Other end has hungup */ AST_CONTROL_RING = 2, /*!< Local ring */ @@ -505,7 +429,7 @@ struct ast_option_header { /*! \brief Definition of supported media formats (codecs) */ struct ast_format_list { - format_t bits; /*!< bitmask value */ + enum ast_format_id id; /*!< The format unique id */ char *name; /*!< short name */ int samplespersecond; /*!< Number of samples per second (8000/16000) */ char *desc; /*!< Description */ @@ -573,12 +497,18 @@ void ast_swapcopy_samples(void *dst, const void *src, int samples); #define ast_frame_byteswap_be(fr) do { ; } while(0) #endif +/*! \brief Parse an "allow" or "deny" line in a channel or device configuration + and update the capabilities and pref if provided. + Video codecs are not added to codec preference lists, since we can not transcode + \return Returns number of errors encountered during parsing + */ +int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing); /*! \brief Get the name of a format * \param format id of format * \return A static string containing the name of the format or "unknown" if unknown. */ -char* ast_getformatname(format_t format); +char* ast_getformatname(struct ast_format *format); /*! \brief Get the names of a set of formats * \param buf a buffer for the output string @@ -588,21 +518,22 @@ char* ast_getformatname(format_t format); * ex: for format=AST_FORMAT_GSM|AST_FORMAT_SPEEX|AST_FORMAT_ILBC it will return "0x602 (GSM|SPEEX|ILBC)" * \return The return value is buf. */ -char* ast_getformatname_multiple(char *buf, size_t size, format_t format); +char* ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap); /*! * \brief Gets a format from a name. * \param name string of format - * \return This returns the form of the format in binary on success, 0 on error. + * \param format structure to return the format in. + * \return This returns the format pointer given to it on success and NULL on failure */ -format_t ast_getformatbyname(const char *name); +struct ast_format *ast_getformatbyname(const char *name, struct ast_format *format); /*! \brief Get a name from a format * Gets a name from a format - * \param codec codec number (1,2,4,8,16,etc.) + * \param format to get name of * \return This returns a static string identifying the format on success, 0 on error. */ -char *ast_codec2str(format_t codec); +char *ast_codec2str(struct ast_format *format); /*! \name AST_Smoother */ @@ -654,91 +585,20 @@ const struct ast_format_list *ast_get_format_list_index(int index); const struct ast_format_list *ast_get_format_list(size_t *size); void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix); -/*! \page AudioCodecPref Audio Codec Preferences - - In order to negotiate audio codecs in the order they are configured - in \<channel\>.conf for a device, we set up codec preference lists - in addition to the codec capabilities setting. The capabilities - setting is a bitmask of audio and video codecs with no internal - order. This will reflect the offer given to the other side, where - the prefered codecs will be added to the top of the list in the - order indicated by the "allow" lines in the device configuration. - - Video codecs are not included in the preference lists since they - can't be transcoded and we just have to pick whatever is supported -*/ - -/*! - *\brief Initialize an audio codec preference to "no preference". - * \arg \ref AudioCodecPref -*/ -void ast_codec_pref_init(struct ast_codec_pref *pref); - -/*! - * \brief Codec located at a particular place in the preference index. - * \arg \ref AudioCodecPref -*/ -format_t ast_codec_pref_index(struct ast_codec_pref *pref, int index); - -/*! \brief Remove audio a codec from a preference list */ -void ast_codec_pref_remove(struct ast_codec_pref *pref, format_t format); - -/*! \brief Append a audio codec to a preference list, removing it first if it was already there -*/ -int ast_codec_pref_append(struct ast_codec_pref *pref, format_t format); - -/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there -*/ -void ast_codec_pref_prepend(struct ast_codec_pref *pref, format_t format, int only_if_existing); - -/*! \brief Select the best audio format according to preference list from supplied options. - If "find_best" is non-zero then if nothing is found, the "Best" format of - the format list is selected, otherwise 0 is returned. */ -format_t ast_codec_choose(struct ast_codec_pref *pref, format_t formats, int find_best); - -/*! \brief Set packet size for codec -*/ -int ast_codec_pref_setsize(struct ast_codec_pref *pref, format_t format, int framems); - -/*! \brief Get packet size for codec -*/ -struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, format_t format); - -/*! \brief Parse an "allow" or "deny" line in a channel or device configuration - and update the capabilities mask and pref if provided. - Video codecs are not added to codec preference lists, since we can not transcode - \return Returns number of errors encountered during parsing - */ -int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing); - -/*! \brief Dump audio codec preference list into a string */ -int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size); - -/*! \brief Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string - * \note Due to a misunderstanding in how codec preferences are stored, this - * list starts at 'B', not 'A'. For backwards compatibility reasons, this - * cannot change. - * \param pref A codec preference list structure - * \param buf A string denoting codec preference, appropriate for use in line transmission - * \param size Size of \a buf - * \param right Boolean: if 0, convert from \a buf to \a pref; if 1, convert from \a pref to \a buf. - */ -void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right); - /*! \brief Returns the number of samples contained in the frame */ int ast_codec_get_samples(struct ast_frame *f); /*! \brief Returns the number of bytes for the number of samples of the given format */ -int ast_codec_get_len(format_t format, int samples); +int ast_codec_get_len(struct ast_format *format, int samples); /*! \brief Appends a frame to the end of a list of frames, truncating the maximum length of the list */ struct ast_frame *ast_frame_enqueue(struct ast_frame *head, struct ast_frame *f, int maxlen, int dupe); /*! \brief Gets duration in ms of interpolation frame for a format */ -static inline int ast_codec_interp_len(format_t format) +static inline int ast_codec_interp_len(struct ast_format *format) { - return (format == AST_FORMAT_ILBC) ? 30 : 20; + return (format->id == AST_FORMAT_ILBC) ? 30 : 20; } /*! @@ -763,9 +623,9 @@ int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2); /*! * \brief Get the sample rate for a given format. */ -static force_inline int ast_format_rate(format_t format) +static force_inline int ast_format_rate(struct ast_format *format) { - switch (format) { + switch (format->id) { case AST_FORMAT_G722: case AST_FORMAT_SLINEAR16: case AST_FORMAT_SIREN7: diff --git a/include/asterisk/frame_defs.h b/include/asterisk/frame_defs.h index 829572d197f0401fa2a7e6e05dfee549b48d3f1b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/include/asterisk/frame_defs.h +++ b/include/asterisk/frame_defs.h @@ -1,38 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 1999 - 2009, Digium, Inc. - * - * Mark Spencer <markster@digium.com> - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! \file - * \brief Asterisk internal frame definitions. - * \arg For an explanation of frames, see \ref Def_Frame - * \arg Frames are send of Asterisk channels, see \ref Def_Channel - */ - -#ifndef _ASTERISK_FRAME_DEFS_H -#define _ASTERISK_FRAME_DEFS_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -typedef int64_t format_t; - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* _ASTERISK_FRAME_DEFS_H */ diff --git a/include/asterisk/image.h b/include/asterisk/image.h index a3e2e015e0eae0d883beb55c7b24af0c97cf246c..302f09e852ddec4b123ebb87dc74188ee0ba536e 100644 --- a/include/asterisk/image.h +++ b/include/asterisk/image.h @@ -28,7 +28,7 @@ struct ast_imager { char *name; /*!< Name */ char *desc; /*!< Description */ char *exts; /*!< Extension(s) (separated by '|' ) */ - int format; /*!< Image format */ + struct ast_format format; /*!< Image format */ struct ast_frame *(*read_image)(int fd, int len); /*!< Read an image from a file descriptor */ int (*identify)(int fd); /*!< Identify if this is that type of file */ int (*write_image)(int fd, struct ast_frame *frame); /*!< Returns length written */ @@ -57,12 +57,12 @@ int ast_send_image(struct ast_channel *chan, const char *filename); * \brief Make an image * \param filename filename of image to prepare * \param preflang preferred language to get the image...? - * \param format the format of the file + * \param format the format of the file, NULL for any image format * Make an image from a filename ??? No estoy positivo * \retval an ast_frame on success * \retval NULL on failure */ -struct ast_frame *ast_read_image(const char *filename, const char *preflang, int format); +struct ast_frame *ast_read_image(const char *filename, const char *preflang, struct ast_format *format); /*! * \brief Register image format diff --git a/include/asterisk/mod_format.h b/include/asterisk/mod_format.h index 08ee4cc42db44b0edae33ca52c3e9383bcbdd1f4..ff3ab7bbf587d1f6e19f393c5ec8d23ff3cacbe5 100644 --- a/include/asterisk/mod_format.h +++ b/include/asterisk/mod_format.h @@ -37,14 +37,14 @@ extern "C" { * Not all are necessary, the support routine implement default * values for some of them. * A handler typically fills a structure initializing the desired - * fields, and then calls ast_format_register() with the (readonly) + * fields, and then calls ast_format_def_register() with the (readonly) * structure as an argument. */ -struct ast_format { +struct ast_format_def { char name[80]; /*!< Name of format */ char exts[80]; /*!< Extensions (separated by | if more than one) this format can read. First is assumed for writing (e.g. .mp3) */ - format_t format; /*!< Format of frames it uses/provides (one only) */ + struct ast_format format; /*!< Format of frames it uses/provides (one only) */ /*! * \brief Prepare an input stream for playback. * \return 0 on success, -1 on error. @@ -76,7 +76,7 @@ struct ast_format { void (*close)(struct ast_filestream *); char * (*getcomment)(struct ast_filestream *); /*!< Retrieve file comment */ - AST_LIST_ENTRY(ast_format) list; /*!< Link */ + AST_LIST_ENTRY(ast_format_def) list; /*!< Link */ /*! * If the handler needs a buffer (for read, typically) @@ -99,7 +99,7 @@ struct ast_format { */ struct ast_filestream { /*! Everybody reserves a block of AST_RESERVED_POINTERS pointers for us */ - struct ast_format *fmt; /* need to write to the lock and usecnt */ + struct ast_format_def *fmt; /* need to write to the lock and usecnt */ int flags; mode_t mode; char *open_filename; @@ -110,7 +110,7 @@ struct ast_filestream { /*! Transparently translate from another format -- just once */ struct ast_trans_pvt *trans; struct ast_tranlator_pvt *tr; - int lastwriteformat; + struct ast_format lastwriteformat; int lasttimeout; struct ast_channel *owner; FILE *f; @@ -127,8 +127,8 @@ struct ast_filestream { * \retval 0 on success * \retval -1 on failure */ -int __ast_format_register(const struct ast_format *f, struct ast_module *mod); -#define ast_format_register(f) __ast_format_register(f, ast_module_info->self) +int __ast_format_def_register(const struct ast_format_def *f, struct ast_module *mod); +#define ast_format_def_register(f) __ast_format_def_register(f, ast_module_info->self) /*! * \brief Unregisters a file format @@ -137,7 +137,7 @@ int __ast_format_register(const struct ast_format *f, struct ast_module *mod); * \retval 0 on success * \retval -1 on failure to unregister */ -int ast_format_unregister(const char *name); +int ast_format_def_unregister(const char *name); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index e80a303f605474a7095b071bc45332654a67129a..429e6053722ce333c466d1345d151cdc1a30c3be 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -30,7 +30,7 @@ #include "asterisk/hashtab.h" #include "asterisk/stringfields.h" #include "asterisk/xmldoc.h" -#include "asterisk/frame_defs.h" +#include "asterisk/format.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -887,11 +887,11 @@ int ast_async_goto_by_name(const char *chan, const char *context, const char *ex /*! Synchronously or asynchronously make an outbound call and send it to a particular extension */ -int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel); +int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel); /*! Synchronously or asynchronously make an outbound call and send it to a particular application with given extension */ -int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel); +int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel); /*! * \brief Evaluate a condition diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h index cd9179be123b91f7ad91e34a8e59a6b29e2aaf28..f13538321de5a1c4f67a43cc92bc51fb09a85d53 100644 --- a/include/asterisk/rtp_engine.h +++ b/include/asterisk/rtp_engine.h @@ -227,8 +227,12 @@ enum ast_rtp_instance_stat { struct ast_rtp_payload_type { /*! Is this an Asterisk value */ int asterisk_format; - /*! Actual internal value of the payload */ - format_t code; + /*! If asterisk_format is set, this is the internal + * asterisk format represented by the payload */ + struct ast_format format; + /*! Actual internal RTP specific value of the payload */ + int rtp_code; + }; /*! Structure that represents statistics from an RTP instance */ @@ -335,8 +339,8 @@ struct ast_rtp_engine { void *(*extended_prop_get)(struct ast_rtp_instance *instance, int property); /*! Callback for setting an RTP property */ void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value); - /*! Callback for setting a payload */ - void (*payload_set)(struct ast_rtp_instance *instance, int payload, int astformat, format_t format); + /*! Callback for setting a payload. If asterisk is to be used, asterisk_format will be set, otherwise value in code is used. */ + void (*payload_set)(struct ast_rtp_instance *instance, int payload, int asterisk_format, struct ast_format *format, int code); /*! Callback for setting packetization preferences */ void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref); /*! Callback for setting the remote address that RTP is to be sent to */ @@ -360,9 +364,9 @@ struct ast_rtp_engine { /*! Callback to locally bridge two RTP instances */ int (*local_bridge)(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1); /*! Callback to set the read format */ - int (*set_read_format)(struct ast_rtp_instance *instance, format_t format); + int (*set_read_format)(struct ast_rtp_instance *instance, struct ast_format *format); /*! Callback to set the write format */ - int (*set_write_format)(struct ast_rtp_instance *instance, format_t format); + int (*set_write_format)(struct ast_rtp_instance *instance, struct ast_format *format); /*! Callback to make two instances compatible */ int (*make_compatible)(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1); /*! Callback to see if two instances are compatible with DTMF */ @@ -371,8 +375,8 @@ struct ast_rtp_engine { int (*activate)(struct ast_rtp_instance *instance); /*! Callback to request that the RTP engine send a STUN BIND request */ void (*stun_request)(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username); - /*! Callback to get the transcodeable formats supported */ - int (*available_formats)(struct ast_rtp_instance *instance, format_t to_endpoint, format_t to_asterisk); + /*! Callback to get the transcodeable formats supported. result returned in ast_format_cap *result */ + void (*available_formats)(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result); /*! Linked list information */ AST_RWLIST_ENTRY(ast_rtp_engine) entry; }; @@ -407,9 +411,9 @@ struct ast_rtp_glue { */ enum ast_rtp_glue_result (*get_trtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance); /*! Callback for updating the destination that the remote side should send RTP to */ - int (*update_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); - /*! Callback for retrieving codecs that the channel can do */ - format_t (*get_codec)(struct ast_channel *chan); + int (*update_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); + /*! Callback for retrieving codecs that the channel can do. Result returned in result_cap*/ + void (*get_codec)(struct ast_channel *chan, struct ast_format_cap *result_cap); /*! Linked list information */ AST_RWLIST_ENTRY(ast_rtp_glue) entry; }; @@ -1046,27 +1050,29 @@ struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs /*! * \brief Get the sample rate associated with known RTP payload types * - * \param asterisk_format True if the value in the 'code' parameter is an AST_FORMAT value - * \param code Format code, either from AST_FORMAT list or from AST_RTP list + * \param asterisk_format True if the value in format is to be used. + * \param An asterisk format + * \param code from AST_RTP list * * \return the sample rate if the format was found, zero if it was not found * * \since 1.8 */ -unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, format_t code); +unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, struct ast_format *format, int code); /*! * \brief Retrieve all formats that were found * * \param codecs Codecs structure to look in - * \param astformats An integer to put the Asterisk formats in + * \param astformats A capabilities structure to put the Asterisk formats in. * \param nonastformats An integer to put the non-Asterisk formats in * * Example usage: * * \code - * int astformats, nonastformats; - * ast_rtp_codecs_payload_Formats(&codecs, &astformats, &nonastformats); + * struct ast_format_cap *astformats = ast_format_cap_alloc_nolock() + * int nonastformats; + * ast_rtp_codecs_payload_formats(&codecs, &astformats, &nonastformats); * \endcode * * This retrieves all the formats known about in the codecs structure and puts the Asterisk ones in the integer @@ -1074,13 +1080,14 @@ unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, format_t code); * * \since 1.8 */ -void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, format_t *astformats, int *nonastformats); +void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats); /*! * \brief Retrieve a payload based on whether it is an Asterisk format and the code * * \param codecs Codecs structure to look in - * \param asterisk_format Non-zero if the given code is an Asterisk format value + * \param asterisk_format Non-zero if the given Asterisk format is present + * \param format Asterisk format to look for * \param code The format to look for * * \retval Numerical payload @@ -1088,20 +1095,21 @@ void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, format_t *ast * Example usage: * * \code - * int payload = ast_rtp_codecs_payload_code(&codecs, 1, AST_FORMAT_ULAW); + * int payload = ast_rtp_codecs_payload_code(&codecs, 1, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0), 0); * \endcode * * This looks for the numerical payload for ULAW in the codecs structure. * * \since 1.8 */ -int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const format_t code); +int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code); /*! * \brief Retrieve mime subtype information on a payload * - * \param asterisk_format Non-zero if the given code is an Asterisk format value - * \param code Format to look up + * \param asterisk_format Non-zero to look up using Asterisk format + * \param format Asterisk format to look up + * \param code RTP code to look up * \param options Additional options that may change the result * * \retval Mime subtype success @@ -1110,21 +1118,22 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asteris * Example usage: * * \code - * const char *subtype = ast_rtp_lookup_mime_subtype2(1, AST_FORMAT_ULAW, 0); + * const char *subtype = ast_rtp_lookup_mime_subtype2(1, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0), 0, 0); * \endcode * * This looks up the mime subtype for the ULAW format. * * \since 1.8 */ -const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const format_t code, enum ast_rtp_options options); +const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_format *format, int code, enum ast_rtp_options options); /*! * \brief Convert formats into a string and put them into a buffer * * \param buf Buffer to put the mime output into - * \param capability Formats that we are looking up - * \param asterisk_format Non-zero if the given capability are Asterisk format capabilities + * \param ast_format_capability Asterisk Formats we are looking up. + * \param rtp_capability RTP codes that we are looking up + * \param asterisk_format Non-zero if the ast_format_capability structure is to be used, 0 if rtp_capability is to be used * \param options Additional options that may change the result * * \retval non-NULL success @@ -1134,14 +1143,19 @@ const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const format * * \code * char buf[256] = ""; - * char *mime = ast_rtp_lookup_mime_multiple2(&buf, sizeof(buf), AST_FORMAT_ULAW | AST_FORMAT_ALAW, 1, 0); + * struct ast_format tmp_fmt; + * struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + * 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_GSM, 0)); + * char *mime = ast_rtp_lookup_mime_multiple2(&buf, sizeof(buf), cap, 0, 1, 0); + * ast_format_cap_destroy(cap); * \endcode * * This returns the mime values for ULAW and ALAW in the buffer pointed to by buf. * * \since 1.8 */ -char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, const format_t capability, const int asterisk_format, enum ast_rtp_options options); +char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *ast_format_capability, int rtp_capability, const int asterisk_format, enum ast_rtp_options options); /*! * \brief Set codec packetization preferences @@ -1535,14 +1549,15 @@ char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_r * Example usage: * * \code - * ast_rtp_instance_set_read_format(instance, AST_FORMAT_ULAW); + * struct ast_format tmp_fmt; + * ast_rtp_instance_set_read_format(instance, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0)); * \endcode * * This requests that the RTP engine provide audio frames in the ULAW format. * * \since 1.8 */ -int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, format_t format); +int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, struct ast_format *format); /*! * \brief Tell underlying RTP engine that audio frames will be provided in a specific format @@ -1556,14 +1571,15 @@ int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, format_t * Example usage: * * \code - * ast_rtp_instance_set_write_format(instance, AST_FORMAT_ULAW); + * struct ast_format tmp_fmt; + * ast_rtp_instance_set_write_format(instance, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0)); * \endcode * * This tells the underlying RTP engine that audio frames will be provided to it in ULAW format. * * \since 1.8 */ -int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, format_t format); +int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, struct ast_format *format); /*! * \brief Request that the underlying RTP engine make two RTP instances compatible with eachother @@ -1592,20 +1608,19 @@ int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_in * \param instance The RTP instance * \param to_endpoint Formats being sent/received towards the endpoint * \param to_asterisk Formats being sent/received towards Asterisk - * - * \retval supported formats + * \param result capabilities structure to store and return supported formats in. * * Example usage: * * \code - * ast_rtp_instance_available_formats(instance, AST_FORMAT_ULAW, AST_FORMAT_SLINEAR); + * ast_rtp_instance_available_formats(instance, to_capabilities, from_capabilities, result_capabilities); * \endcode * * This sees if it is possible to have ulaw communicated to the endpoint but signed linear received into Asterisk. * * \since 1.8 */ -format_t ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, format_t to_endpoint, format_t to_asterisk); +void ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result); /*! * \brief Indicate to the RTP engine that packets are now expected to be sent/received on the RTP instance diff --git a/include/asterisk/slin.h b/include/asterisk/slin.h index 7abfe7fd8fa0179574ef4112531294c6f0e802db..ab7d843abe9647649e363430664e1d08f747882a 100644 --- a/include/asterisk/slin.h +++ b/include/asterisk/slin.h @@ -62,7 +62,6 @@ static inline struct ast_frame *slin8_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .datalen = sizeof(ex_slin8) * 2, .samples = ARRAY_LEN(ex_slin8), .mallocd = 0, @@ -71,6 +70,7 @@ static inline struct ast_frame *slin8_sample(void) .data.ptr = ex_slin8, }; + ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0); return &f; } @@ -78,7 +78,6 @@ static inline struct ast_frame *slin16_sample(void) { static struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR16, .datalen = sizeof(ex_slin16) * 2, .samples = ARRAY_LEN(ex_slin16), .mallocd = 0, @@ -87,5 +86,6 @@ static inline struct ast_frame *slin16_sample(void) .data.ptr = ex_slin16, }; + ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0); return &f; } diff --git a/include/asterisk/slinfactory.h b/include/asterisk/slinfactory.h index 78d4321935cee6e61f36ee630c6fa454ac3c08b1..003c6ac282f4cf83587a85e106b88fcdd82e8c46 100644 --- a/include/asterisk/slinfactory.h +++ b/include/asterisk/slinfactory.h @@ -24,6 +24,8 @@ #ifndef _ASTERISK_SLINFACTORY_H #define _ASTERISK_SLINFACTORY_H +#include "asterisk/format.h" + #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif @@ -37,8 +39,8 @@ struct ast_slinfactory { short *offset; /*!< Offset into the hold where audio begins */ size_t holdlen; /*!< Number of samples currently in the hold */ unsigned int size; /*!< Number of samples currently in the factory */ - format_t format; /*!< Current format the translation path is converting from */ - format_t output_format; /*!< The output format desired */ + struct ast_format format; /*!< Current format the translation path is converting from */ + struct ast_format output_format; /*!< The output format desired */ }; /*! diff --git a/include/asterisk/speech.h b/include/asterisk/speech.h index cb167d5b529daa796bfcb1e007e3d306c422b36e..5397d8aaadf407969f42e7876a92bb1578b9ffa8 100644 --- a/include/asterisk/speech.h +++ b/include/asterisk/speech.h @@ -58,7 +58,7 @@ struct ast_speech { /*! Current state of structure */ int state; /*! Expected write format */ - int format; + struct ast_format format; /*! Data for speech engine */ void *data; /*! Cached results */ @@ -74,7 +74,7 @@ struct ast_speech_engine { /*! Name of speech engine */ char *name; /*! Set up the speech structure within the engine */ - int (*create)(struct ast_speech *speech, int format); + int (*create)(struct ast_speech *speech, struct ast_format *format); /*! Destroy any data set on the speech structure by the engine */ int (*destroy)(struct ast_speech *speech); /*! Load a local grammar on the speech structure */ @@ -98,7 +98,7 @@ struct ast_speech_engine { /*! Try to get results */ struct ast_speech_result *(*get)(struct ast_speech *speech); /*! Accepted formats by the engine */ - int formats; + struct ast_format_cap *formats; AST_LIST_ENTRY(ast_speech_engine) list; }; @@ -131,7 +131,7 @@ int ast_speech_results_free(struct ast_speech_result *result); /*! \brief Indicate to the speech engine that audio is now going to start being written */ void ast_speech_start(struct ast_speech *speech); /*! \brief Create a new speech structure */ -struct ast_speech *ast_speech_new(const char *engine_name, int formats); +struct ast_speech *ast_speech_new(const char *engine_name, const struct ast_format_cap *formats); /*! \brief Destroy a speech structure */ int ast_speech_destroy(struct ast_speech *speech); /*! \brief Write audio to the speech engine */ diff --git a/include/asterisk/translate.h b/include/asterisk/translate.h index 821463bf19865d3315cdf9aae4b35636a8f080ea..7e73cd1b199906e9e4f930b42acf222dad8a7c7c 100644 --- a/include/asterisk/translate.h +++ b/include/asterisk/translate.h @@ -24,9 +24,6 @@ #ifndef _ASTERISK_TRANSLATE_H #define _ASTERISK_TRANSLATE_H -#define MAX_AUDIO_FORMAT 47 /* Do not include video here */ -#define MAX_FORMAT 64 /* Do include video here */ - #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif @@ -35,11 +32,78 @@ extern "C" { #include "asterisk/frame.h" #include "asterisk/plc.h" #include "asterisk/linkedlists.h" -// XXX #include "asterisk/module.h" #endif struct ast_trans_pvt; /* declared below */ +/*! + * \brief Translator Cost Table definition. + * + * \note The defined values in this table must be used to set + * the translator's table_cost value. + * + * \note The cost value of the first two values must always add + * up to be greater than the largest value defined in this table. + * This is done to guarantee a direct translation will always + * have precedence over a multi step translation. + * + * \details This table is built in a way that allows translation + * paths to be built that guarantee the best possible balance + * between performance and quality. With this table direct + * translation paths between two formats will always take precedence + * over multi step paths, lossless intermediate steps will always + * be chosen over lossy intermediate steps, and preservation of + * sample rate across the translation will always have precedence + * over a path that involves any re-sampling. + */ +enum ast_trans_cost_table { + + /* Lossless Source Translation Costs */ + + /*! [lossless -> lossless] original sampling */ + AST_TRANS_COST_LL_LL_ORIGSAMP = 400000, + /*! [lossless -> lossy] original sampling */ + AST_TRANS_COST_LL_LY_ORIGSAMP = 600000, + + /*! [lossless -> lossless] up sample */ + AST_TRANS_COST_LL_LL_UPSAMP = 800000, + /*! [lossless -> lossy] up sample */ + AST_TRANS_COST_LL_LY_UPSAMP = 825000, + + /*! [lossless -> lossless] down sample */ + AST_TRANS_COST_LL_LL_DOWNSAMP = 850000, + /*! [lossless -> lossy] down sample */ + AST_TRANS_COST_LL_LY_DOWNSAMP = 875000, + + /*! [lossless -> unknown] unknown. + * This value is for a lossless source translation + * with an unknown destination and or sample rate conversion. */ + AST_TRANS_COST_LL_UNKNOWN = 885000, + + /* Lossy Source Translation Costs */ + + /*! [lossy -> lossless] original sampling */ + AST_TRANS_COST_LY_LL_ORIGSAMP = 900000, + /*! [lossy -> lossy] original sampling */ + AST_TRANS_COST_LY_LY_ORIGSAMP = 915000, + + /*! [lossy -> lossless] up sample */ + AST_TRANS_COST_LY_LL_UPSAMP = 930000, + /*! [lossy -> lossy] up sample */ + AST_TRANS_COST_LY_LY_UPSAMP = 945000, + + /*! [lossy -> lossless] down sample */ + AST_TRANS_COST_LY_LL_DOWNSAMP = 960000, + /*! [lossy -> lossy] down sample */ + AST_TRANS_COST_LY_LY_DOWNSAMP = 975000, + + /*! [lossy -> unknown] unknown. + * This value is for a lossy source translation + * with an unknown destination and or sample rate conversion. */ + AST_TRANS_COST_LY_UNKNOWN = 985000, + +}; + /*! \brief * Descriptor of a translator. * @@ -70,10 +134,14 @@ struct ast_trans_pvt; /* declared below */ */ struct ast_translator { const char name[80]; /*!< Name of translator */ - format_t srcfmt; /*!< Source format (note: bit position, - * converted to index during registration) */ - format_t dstfmt; /*!< Destination format (note: bit position, - * converted to index during registration) */ + struct ast_format src_format; /*!< Source format */ + struct ast_format dst_format; /*!< Destination format */ + + int table_cost; /*!< Cost value associated with this translator based + * on translation cost table. */ + int comp_cost; /*!< Cost value associated with this translator based + * on computation time. This cost value is computed based + * on the time required to translate sample data. */ int (*newpvt)(struct ast_trans_pvt *); /*!< initialize private data * associated with the translator */ @@ -109,8 +177,9 @@ struct ast_translator { struct ast_module *module; /*!< opaque reference to the parent module */ - int cost; /*!< Cost in milliseconds for encoding/decoding 1 second of sound */ int active; /*!< Whether this translator should be used or not */ + int src_fmt_index; /*!< index of the source format in the matrix table */ + int dst_fmt_index; /*!< index of the destination format in the matrix table */ AST_LIST_ENTRY(ast_translator) list; /*!< link field */ }; @@ -199,11 +268,20 @@ void ast_translator_deactivate(struct ast_translator *t); * \brief Chooses the best translation path * * Given a list of sources, and a designed destination format, which should - * I choose? - * \return Returns 0 on success, -1 if no path could be found. - * \note Modifies dests and srcs in place + * I choose? + * + * \param destination capabilities + * \param source capabilities + * \param destination format chosen out of destination capabilities + * \param source format chosen out of source capabilities + * \return Returns 0 on success, -1 if no path could be found. + * + * \note dst_cap and src_cap are not mondified. */ -format_t ast_translator_best_choice(format_t *dsts, format_t *srcs); +int ast_translator_best_choice(struct ast_format_cap *dst_cap, + struct ast_format_cap *src_cap, + struct ast_format *dst_fmt_out, + struct ast_format *src_fmt_out); /*! * \brief Builds a translator path @@ -212,7 +290,7 @@ format_t ast_translator_best_choice(format_t *dsts, format_t *srcs); * \param source source format * \return ast_trans_pvt on success, NULL on failure * */ -struct ast_trans_pvt *ast_translator_build_path(format_t dest, format_t source); +struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dest, struct ast_format *source); /*! * \brief Frees a translator path @@ -238,12 +316,14 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, i * \param src source format * \return the number of translation steps required, or -1 if no path is available */ -unsigned int ast_translate_path_steps(format_t dest, format_t src); +unsigned int ast_translate_path_steps(struct ast_format *dest, struct ast_format *src); /*! - * \brief Mask off unavailable formats from a format bitmask + * \brief Find available formats * \param dest possible destination formats * \param src source formats + * \param result capabilities structure to store available formats in + * * \return the destination formats that are available in the source or translatable * * The result will include all formats from 'dest' that are either present @@ -252,7 +332,7 @@ unsigned int ast_translate_path_steps(format_t dest, format_t src); * \note Only a single audio format and a single video format can be * present in 'src', or the function will produce unexpected results. */ -format_t ast_translate_available_formats(format_t dest, format_t src); +void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result); /*! * \brief Puts a string representation of the translation path into outbuf @@ -262,6 +342,13 @@ format_t ast_translate_available_formats(format_t dest, format_t src); */ const char *ast_translate_path_to_str(struct ast_trans_pvt *t, struct ast_str **str); +/*! + * \brief Initialize the translation matrix and index to format conversion table. + * \retval 0 on success + * \retval -1 on failure + */ +int ast_translate_init(void); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/main/abstract_jb.c b/main/abstract_jb.c index 4cd5ccb0d7acaf732d5f98c8361f8b953d6ca168..5ff1c4b2a85c4ed7eebd1a94ff0b490ba3442608 100644 --- a/main/abstract_jb.c +++ b/main/abstract_jb.c @@ -398,7 +398,7 @@ static void jb_get_and_deliver(struct ast_channel *chan) } while (now >= jb->next) { - interpolation_len = ast_codec_interp_len(jb->last_format); + interpolation_len = ast_codec_interp_len(&jb->last_format); res = jbimpl->get(jbobj, &f, now, interpolation_len); @@ -409,13 +409,13 @@ static void jb_get_and_deliver(struct ast_channel *chan) case JB_IMPL_DROP: jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n", now, jb_get_actions[res], f->ts, f->len); - jb->last_format = f->subclass.codec; + ast_format_copy(&jb->last_format, &f->subclass.format); ast_frfree(f); break; case JB_IMPL_INTERP: /* interpolate a frame */ f = &finterp; - f->subclass.codec = jb->last_format; + ast_format_copy(&f->subclass.format, &jb->last_format); f->samples = interpolation_len * 8; f->src = "JB interpolation"; f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000)); @@ -476,7 +476,7 @@ static int create_jb(struct ast_channel *chan, struct ast_frame *frr) jb->next = jbimpl->next(jbobj); /* Init last format for a first time. */ - jb->last_format = frr->subclass.codec; + ast_format_copy(&jb->last_format, &frr->subclass.format); /* Create a frame log file */ if (ast_test_flag(jbconf, AST_JB_LOG)) { diff --git a/main/app.c b/main/app.c index 0054c4cdeb95f4f95c5fca0c76951e9e0a658cba..27858a29b9af891942dd5e01018a5759c5831f8e 100644 --- a/main/app.c +++ b/main/app.c @@ -445,15 +445,15 @@ struct linear_state { int fd; int autoclose; int allowoverride; - int origwfmt; + struct ast_format origwfmt; }; static void linear_release(struct ast_channel *chan, void *params) { struct linear_state *ls = params; - if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) { - ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt); + if (ls->origwfmt.id && ast_set_write_format(chan, &ls->origwfmt)) { + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt.id); } if (ls->autoclose) { @@ -469,12 +469,13 @@ static int linear_generator(struct ast_channel *chan, void *data, int len, int s struct linear_state *ls = data; struct ast_frame f = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .data.ptr = buf + AST_FRIENDLY_OFFSET / 2, .offset = AST_FRIENDLY_OFFSET, }; int res; + ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0); + len = samples * 2; if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) { ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len); @@ -507,9 +508,9 @@ static void *linear_alloc(struct ast_channel *chan, void *params) ast_clear_flag(chan, AST_FLAG_WRITE_INT); } - ls->origwfmt = chan->writeformat; + ast_format_copy(&ls->origwfmt, &chan->writeformat); - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) { ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name); ast_free(ls); ls = params = NULL; @@ -741,10 +742,11 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, int totalsilence = 0; int dspsilence = 0; int olddspsilence = 0; - int rfmt = 0; + struct ast_format rfmt; struct ast_silence_generator *silgen = NULL; char prependfile[80]; + ast_format_clear(&rfmt); if (silencethreshold < 0) { silencethreshold = global_silence_threshold; } @@ -815,8 +817,8 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, return -1; } ast_dsp_set_threshold(sildet, silencethreshold); - rfmt = chan->readformat; - res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); + ast_format_copy(&rfmt, &chan->readformat); + res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); ast_dsp_free(sildet); @@ -1005,8 +1007,8 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, ast_filedelete(prependfile, sfmt[x]); } } - if (rfmt && ast_set_read_format(chan, rfmt)) { - ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); + if (rfmt.id && ast_set_read_format(chan, &rfmt)) { + ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(&rfmt), chan->name); } if (outmsg == 2) { ast_stream_and_wait(chan, "auth-thankyou", ""); diff --git a/main/asterisk.c b/main/asterisk.c index 8d81b5eedc765b8c35acb51e226a23fa7b238bd2..7f8b6a285aa7f2407b99089cff474afb41ec3c25 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -111,6 +111,7 @@ int daemon(int, int); /* defined in libresolv of all places */ #include "asterisk/network.h" #include "asterisk/cli.h" #include "asterisk/channel.h" +#include "asterisk/translate.h" #include "asterisk/features.h" #include "asterisk/ulaw.h" #include "asterisk/alaw.h" @@ -142,6 +143,7 @@ int daemon(int, int); /* defined in libresolv of all places */ #include "asterisk/poll-compat.h" #include "asterisk/ccss.h" #include "asterisk/test.h" +#include "asterisk/format.h" #include "asterisk/aoc.h" #include "../defaults.h" @@ -3669,6 +3671,11 @@ int main(int argc, char *argv[]) } #endif + if (ast_translate_init()) { + printf("%s", term_quit()); + exit(1); + } + ast_aoc_cli_init(); ast_makesocket(); @@ -3700,6 +3707,8 @@ int main(int argc, char *argv[]) astobj2_init(); + ast_format_attr_init(); + ast_autoservice_init(); if (ast_timing_init()) { diff --git a/main/astobj2.c b/main/astobj2.c index ccfbf5388f59d0768d3d882c7bc7524ece6d9f70..6391844fe82ffaf002b12a2399bb116f532060b7 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -137,7 +137,7 @@ enum ao2_callback_type { static int internal_ao2_ref(void *user_data, const int delta); static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn); -static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func); +static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *user_data, int flags, const char *file, int line, const char *func); static void *internal_ao2_callback(struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname); @@ -471,7 +471,7 @@ struct bucket_entry { * link an object to a container */ -static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func) +static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *user_data, int flags, const char *file, int line, const char *func) { int i; /* create a new list entry */ @@ -490,7 +490,9 @@ static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *use i = abs(c->hash_fn(user_data, OBJ_POINTER)); - ao2_lock(c); + if (!(flags & OBJ_NOLOCK)) { + ao2_lock(c); + } i %= c->n_buckets; p->astobj = obj; p->version = ast_atomic_fetchadd_int(&c->version, 1); @@ -501,24 +503,28 @@ static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *use return p; } -void *__ao2_link_debug(struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname) +void *__ao2_link_debug(struct ao2_container *c, void *user_data, int flags, char *tag, char *file, int line, const char *funcname) { - struct bucket_entry *p = internal_ao2_link(c, user_data, file, line, funcname); + struct bucket_entry *p = internal_ao2_link(c, user_data, flags, file, line, funcname); if (p) { __ao2_ref_debug(user_data, +1, tag, file, line, funcname); - ao2_unlock(c); + if (!(flags & OBJ_NOLOCK)) { + ao2_unlock(c); + } } return p; } -void *__ao2_link(struct ao2_container *c, void *user_data) +void *__ao2_link(struct ao2_container *c, void *user_data, int flags) { - struct bucket_entry *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__); + struct bucket_entry *p = internal_ao2_link(c, user_data, flags, __FILE__, __LINE__, __PRETTY_FUNCTION__); if (p) { __ao2_ref(user_data, +1); - ao2_unlock(c); + if (!(flags & OBJ_NOLOCK)) { + ao2_unlock(c); + } } return p; } @@ -535,23 +541,26 @@ int ao2_match_by_addr(void *user_data, void *arg, int flags) * Unlink an object from the container * and destroy the associated * bucket_entry structure. */ -void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, char *tag, +void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags, char *tag, char *file, int line, const char *funcname) { if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ return NULL; - __ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname); + flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA); + + __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, funcname); return NULL; } -void *__ao2_unlink(struct ao2_container *c, void *user_data) +void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags) { if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ return NULL; - __ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data); + flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA); + __ao2_callback(c, flags, ao2_match_by_addr, user_data); return NULL; } @@ -696,7 +705,7 @@ static void *internal_ao2_callback(struct ao2_container *c, * link the object into the container that will hold the results. */ if (ret && (multi_container != NULL)) { - __ao2_link(multi_container, ret); + __ao2_link(multi_container, ret, flags); ret = NULL; } diff --git a/main/audiohook.c b/main/audiohook.c index ad977ecbc60f31f85350bc508de0b0eaab7e6876..23650a79f83c45908751898db72c4abe08aeefdf 100644 --- a/main/audiohook.c +++ b/main/audiohook.c @@ -40,7 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") struct ast_audiohook_translate { struct ast_trans_pvt *trans_pvt; - format_t format; + struct ast_format format; }; struct ast_audiohook_list { @@ -185,11 +185,11 @@ static struct ast_frame *audiohook_read_frame_single(struct ast_audiohook *audio short buf[samples]; struct ast_frame frame = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .data.ptr = buf, .datalen = sizeof(buf), .samples = samples, }; + ast_format_set(&frame.subclass.format, AST_FORMAT_SLINEAR, 0); /* Ensure the factory is able to give us the samples we want */ if (samples > ast_slinfactory_available(factory)) @@ -212,11 +212,11 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL; struct ast_frame frame = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .data.ptr = NULL, .datalen = sizeof(buf1), .samples = samples, }; + ast_format_set(&frame.subclass.format, AST_FORMAT_SLINEAR, 0); /* Make sure both factories have the required samples */ usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0); @@ -304,23 +304,24 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho * \param format Format of frame remote side wants back * \return Returns frame on success, NULL on failure */ -struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, format_t format) +struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format) { struct ast_frame *read_frame = NULL, *final_frame = NULL; + struct ast_format tmp_fmt; if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ? audiohook_read_frame_both(audiohook, samples) : audiohook_read_frame_single(audiohook, samples, direction)))) return NULL; /* If they don't want signed linear back out, we'll have to send it through the translation path */ - if (format != AST_FORMAT_SLINEAR) { + if (format->id != AST_FORMAT_SLINEAR) { /* Rebuild translation path if different format then previously */ - if (audiohook->format != format) { + if (ast_format_cmp(format, &audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) { if (audiohook->trans_pvt) { ast_translator_free_path(audiohook->trans_pvt); audiohook->trans_pvt = NULL; } /* Setup new translation path for this format... if we fail we can't very well return signed linear so free the frame and return nothing */ - if (!(audiohook->trans_pvt = ast_translator_build_path(format, AST_FORMAT_SLINEAR))) { + if (!(audiohook->trans_pvt = ast_translator_build_path(format, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0)))) { ast_frfree(read_frame); return NULL; } @@ -619,17 +620,18 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]); struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame; struct ast_audiohook *audiohook = NULL; + struct ast_format tmp_fmt; int samples = frame->samples; /* ---Part_1. translate start_frame to SLINEAR if necessary. */ /* If the frame coming in is not signed linear we have to send it through the in_translate path */ - if (frame->subclass.codec != AST_FORMAT_SLINEAR) { - if (in_translate->format != frame->subclass.codec) { + if (frame->subclass.format.id != AST_FORMAT_SLINEAR) { + if (ast_format_cmp(&frame->subclass.format, &in_translate->format) == AST_FORMAT_CMP_NOT_EQUAL) { if (in_translate->trans_pvt) ast_translator_free_path(in_translate->trans_pvt); - if (!(in_translate->trans_pvt = ast_translator_build_path(AST_FORMAT_SLINEAR, frame->subclass.codec))) + if (!(in_translate->trans_pvt = ast_translator_build_path(ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0), &frame->subclass.format))) return frame; - in_translate->format = frame->subclass.codec; + ast_format_copy(&in_translate->format, &frame->subclass.format); } if (!(middle_frame = ast_translate(in_translate->trans_pvt, frame, 0))) return frame; @@ -707,16 +709,16 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */ if (middle_frame == end_frame) { /* Middle frame was modified and became the end frame... let's see if we need to transcode */ - if (end_frame->subclass.codec != start_frame->subclass.codec) { - if (out_translate->format != start_frame->subclass.codec) { + if (ast_format_cmp(&end_frame->subclass.format, &start_frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + if (ast_format_cmp(&out_translate->format, &start_frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { if (out_translate->trans_pvt) ast_translator_free_path(out_translate->trans_pvt); - if (!(out_translate->trans_pvt = ast_translator_build_path(start_frame->subclass.codec, AST_FORMAT_SLINEAR))) { + if (!(out_translate->trans_pvt = ast_translator_build_path(&start_frame->subclass.format, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0)))) { /* We can't transcode this... drop our middle frame and return the original */ ast_frfree(middle_frame); return start_frame; } - out_translate->format = start_frame->subclass.codec; + ast_format_copy(&out_translate->format, &start_frame->subclass.format); } /* Transcode from our middle (signed linear) frame to new format of the frame that came in */ if (!(end_frame = ast_translate(out_translate->trans_pvt, middle_frame, 0))) { diff --git a/main/bridging.c b/main/bridging.c index a256cf038a2d05a06d656de6f53559c3f9378947..9de02aa346961ea5be37db8971316d8c16b72c92 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -382,16 +382,12 @@ static void *bridge_thread(void *data) } /*! \brief Helper function used to find the "best" bridge technology given a specified capabilities */ -static struct ast_bridge_technology *find_best_technology(format_t capabilities) +static struct ast_bridge_technology *find_best_technology(uint32_t capabilities) { struct ast_bridge_technology *current = NULL, *best = NULL; AST_RWLIST_RDLOCK(&bridge_technologies); AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) { - char tmp1[256], tmp2[256]; - ast_debug(1, "Bridge technology %s has capabilities %s and we want %s\n", current->name, - ast_getformatname_multiple(tmp1, sizeof(tmp1), current->capabilities), - ast_getformatname_multiple(tmp2, sizeof(tmp2), capabilities)); if (current->suspended) { ast_debug(1, "Bridge technology %s is suspended. Skipping.\n", current->name); continue; @@ -448,7 +444,7 @@ static void destroy_bridge(void *obj) return; } -struct ast_bridge *ast_bridge_new(format_t capabilities, int flags) +struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags) { struct ast_bridge *bridge = NULL; struct ast_bridge_technology *bridge_technology = NULL; @@ -470,9 +466,6 @@ struct ast_bridge *ast_bridge_new(format_t capabilities, int flags) /* If no bridge technology was found we can't possibly do bridging so fail creation of the bridge */ if (!bridge_technology) { - char codec_buf[256]; - ast_debug(1, "Failed to find a bridge technology to satisfy capabilities %s\n", - ast_getformatname_multiple(codec_buf, sizeof(codec_buf), capabilities)); return NULL; } @@ -503,7 +496,7 @@ struct ast_bridge *ast_bridge_new(format_t capabilities, int flags) return bridge; } -int ast_bridge_check(format_t capabilities) +int ast_bridge_check(uint32_t capabilities) { struct ast_bridge_technology *bridge_technology = NULL; @@ -542,47 +535,51 @@ int ast_bridge_destroy(struct ast_bridge *bridge) static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) { - format_t formats[2] = {bridge_channel->chan->readformat, bridge_channel->chan->writeformat}; + struct ast_format formats[2]; + ast_format_copy(&formats[0], &bridge_channel->chan->readformat); + ast_format_copy(&formats[1], &bridge_channel->chan->writeformat); /* Are the formats currently in use something ths bridge can handle? */ - if (!(bridge->technology->formats & bridge_channel->chan->readformat)) { - format_t best_format = ast_best_codec(bridge->technology->formats); + if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, &bridge_channel->chan->readformat)) { + struct ast_format best_format; + ast_best_codec(bridge->technology->format_capabilities, &best_format); /* Read format is a no go... */ if (option_debug) { char codec_buf[512]; ast_debug(1, "Bridge technology %s wants to read any of formats %s but channel has %s\n", bridge->technology->name, - ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats), - ast_getformatname(formats[0])); + ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->format_capabilities), + ast_getformatname(&formats[0])); } /* Switch read format to the best one chosen */ - if (ast_set_read_format(bridge_channel->chan, best_format)) { - ast_log(LOG_WARNING, "Failed to set channel %s to read format %s\n", bridge_channel->chan->name, ast_getformatname(best_format)); + if (ast_set_read_format(bridge_channel->chan, &best_format)) { + ast_log(LOG_WARNING, "Failed to set channel %s to read format %s\n", bridge_channel->chan->name, ast_getformatname(&best_format)); return -1; } - ast_debug(1, "Bridge %p put channel %s into read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format)); + ast_debug(1, "Bridge %p put channel %s into read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(&best_format)); } else { - ast_debug(1, "Bridge %p is happy that channel %s already has read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[0])); + ast_debug(1, "Bridge %p is happy that channel %s already has read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(&formats[0])); } - if (!(bridge->technology->formats & formats[1])) { - int best_format = ast_best_codec(bridge->technology->formats); + if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, &formats[1])) { + struct ast_format best_format; + ast_best_codec(bridge->technology->format_capabilities, &best_format); /* Write format is a no go... */ if (option_debug) { char codec_buf[512]; ast_debug(1, "Bridge technology %s wants to write any of formats %s but channel has %s\n", bridge->technology->name, - ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats), - ast_getformatname(formats[1])); + ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->format_capabilities), + ast_getformatname(&formats[1])); } /* Switch write format to the best one chosen */ - if (ast_set_write_format(bridge_channel->chan, best_format)) { - ast_log(LOG_WARNING, "Failed to set channel %s to write format %s\n", bridge_channel->chan->name, ast_getformatname(best_format)); + if (ast_set_write_format(bridge_channel->chan, &best_format)) { + ast_log(LOG_WARNING, "Failed to set channel %s to write format %s\n", bridge_channel->chan->name, ast_getformatname(&best_format)); return -1; } - ast_debug(1, "Bridge %p put channel %s into write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format)); + ast_debug(1, "Bridge %p put channel %s into write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(&best_format)); } else { - ast_debug(1, "Bridge %p is happy that channel %s already has write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[1])); + ast_debug(1, "Bridge %p is happy that channel %s already has write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(&formats[1])); } return 0; @@ -591,7 +588,7 @@ static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_c /*! \brief Perform the smart bridge operation. Basically sees if a new bridge technology should be used instead of the current one. */ static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int count) { - format_t new_capabilities = 0; + uint32_t new_capabilities = 0; struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology; struct ast_bridge temp_bridge = { .technology = bridge->technology, @@ -621,9 +618,6 @@ static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_c /* Attempt to find a new bridge technology to satisfy the capabilities */ if (!(new_technology = find_best_technology(new_capabilities))) { - char codec_buf[256]; - ast_debug(1, "Smart bridge operation was unable to find new bridge technology with capabilities %s to satisfy bridge %p\n", - ast_getformatname_multiple(codec_buf, sizeof(codec_buf), new_capabilities), bridge); return -1; } @@ -873,8 +867,10 @@ static void bridge_channel_dtmf_stream(struct ast_bridge *bridge, struct ast_bri /*! \brief Join a channel to a bridge and handle anything the bridge may want us to do */ static enum ast_bridge_channel_state bridge_channel_join(struct ast_bridge_channel *bridge_channel) { - int formats[2] = { bridge_channel->chan->readformat, bridge_channel->chan->writeformat }; + struct ast_format formats[2]; enum ast_bridge_channel_state state; + ast_format_copy(&formats[0], &bridge_channel->chan->readformat); + ast_format_copy(&formats[1], &bridge_channel->chan->writeformat); /* Record the thread that will be the owner of us */ bridge_channel->thread = pthread_self(); @@ -975,16 +971,16 @@ static enum ast_bridge_channel_state bridge_channel_join(struct ast_bridge_chann ao2_unlock(bridge_channel->bridge); /* Restore original formats of the channel as they came in */ - if (bridge_channel->chan->readformat != formats[0]) { - ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]); - if (ast_set_read_format(bridge_channel->chan, formats[0])) { - ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]); + if (ast_format_cmp(&bridge_channel->chan->readformat, &formats[0]) == AST_FORMAT_CMP_NOT_EQUAL) { + ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(&formats[0]), formats[0].id); + if (ast_set_read_format(bridge_channel->chan, &formats[0])) { + ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(&formats[0]), formats[0].id); } } - if (bridge_channel->chan->writeformat != formats[1]) { - ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]); - if (ast_set_write_format(bridge_channel->chan, formats[1])) { - ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]); + if (ast_format_cmp(&bridge_channel->chan->writeformat, &formats[1]) == AST_FORMAT_CMP_NOT_EQUAL) { + ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(&formats[1]), formats[1].id); + if (ast_set_write_format(bridge_channel->chan, &formats[1])) { + ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(&formats[1]), formats[1].id); } } diff --git a/main/callerid.c b/main/callerid.c index ac8fbde8b17541efde2620ec54d028e09ca845be..aa53eb83e0eac802efe72883207dac048722fbe9 100644 --- a/main/callerid.c +++ b/main/callerid.c @@ -71,7 +71,7 @@ float casdr1, casdi1, casdr2, casdi2; #define AST_CALLERID_UNKNOWN "<unknown>" -static inline void gen_tones(unsigned char *buf, int len, format_t codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2) +static inline void gen_tones(unsigned char *buf, int len, struct ast_format *codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2) { int x; float t; @@ -93,7 +93,7 @@ static inline void gen_tones(unsigned char *buf, int len, format_t codec, float } } -static inline void gen_tone(unsigned char *buf, int len, format_t codec, float ddr1, float ddi1, float *cr1, float *ci1) +static inline void gen_tone(unsigned char *buf, int len, struct ast_format *codec, float ddr1, float ddi1, float *cr1, float *ci1) { int x; float t; @@ -255,7 +255,7 @@ void callerid_get_dtmf(char *cidstring, char *number, int *flags) } } -int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, format_t codec) +int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, struct ast_format *codec) { int pos = 0; int saslen = 2400; @@ -300,7 +300,7 @@ static unsigned short calc_crc(unsigned short crc, unsigned char data) return crc; } -int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, format_t codec) +int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec) { int mylen = len; int olen; @@ -539,7 +539,7 @@ int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, f } -int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, format_t codec) +int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec) { int mylen = len; int olen; @@ -791,7 +791,7 @@ static int callerid_genmsg(char *msg, int size, const char *number, const char * } -int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, format_t codec, +int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char* name, const char* number, int flags) { char msg[256]; @@ -879,7 +879,7 @@ int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, format_ return bytes; } -int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, format_t codec) +int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec) { int bytes = 0; int x, sum; @@ -1038,7 +1038,7 @@ int ast_callerid_parse(char *instr, char **name, char **location) return 0; } -static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, format_t codec) +static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, struct ast_format *codec) { if (ast_strlen_zero(name)) name = NULL; @@ -1047,12 +1047,12 @@ static int __ast_callerid_generate(unsigned char *buf, const char *name, const c return callerid_generate(buf, number, name, 0, callwaiting, codec); } -int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, format_t codec) +int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec) { return __ast_callerid_generate(buf, name, number, 0, codec); } -int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, format_t codec) +int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec) { return __ast_callerid_generate(buf, name, number, 1, codec); } diff --git a/main/ccss.c b/main/ccss.c index 3583e8472b2afa818879808e1775b71f35663220..fc79a01ddbf0265e06924ba0ec04ab1744a35de2 100644 --- a/main/ccss.c +++ b/main/ccss.c @@ -2482,19 +2482,30 @@ static void *generic_recall(void *data) struct ast_channel *chan; const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params); unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000; + struct ast_format tmp_fmt; + struct ast_format_cap *tmp_cap = ast_format_cap_alloc_nolock(); + + if (!tmp_cap) { + return NULL; + } tech = interface; if ((target = strchr(interface, '/'))) { *target++ = '\0'; } - if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) { + + ast_format_cap_add(tmp_cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0)); + if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) { /* Hmm, no channel. Sucks for you, bud. */ ast_log_dynamic_level(cc_logger_level, "Core %d: Failed to call back %s for reason %d\n", agent->core_id, agent->device_name, reason); ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target); + ast_format_cap_destroy(tmp_cap); return NULL; } + ast_format_cap_destroy(tmp_cap); + if (!ast_strlen_zero(callback_macro)) { ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback macro configured for agent %s\n", agent->core_id, agent->device_name); diff --git a/main/channel.c b/main/channel.c index 0cabf2d7e073cc6500505646f73687d2712cc1ba..796dc8b011748ef3d7c0ac6f0086282a7f4ae02d 100644 --- a/main/channel.c +++ b/main/channel.c @@ -372,12 +372,12 @@ int ast_channel_data_add_structure(struct ast_data *tree, } } - ast_data_add_codecs(tree, "oldwriteformat", chan->oldwriteformat); + ast_data_add_codec(tree, "oldwriteformat", &chan->oldwriteformat); + ast_data_add_codec(tree, "readformat", &chan->readformat); + ast_data_add_codec(tree, "writeformat", &chan->writeformat); + ast_data_add_codec(tree, "rawreadformat", &chan->rawreadformat); + ast_data_add_codec(tree, "rawwriteformat", &chan->rawwriteformat); ast_data_add_codecs(tree, "nativeformats", chan->nativeformats); - ast_data_add_codecs(tree, "readformat", chan->readformat); - ast_data_add_codecs(tree, "writeformat", chan->writeformat); - ast_data_add_codecs(tree, "rawreadformat", chan->rawreadformat); - ast_data_add_codecs(tree, "rawwriteformat", chan->rawwriteformat); /* state */ enum_node = ast_data_add_node(tree, "state"); @@ -593,7 +593,7 @@ static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd, (cl->tech->devicestate) ? "yes" : "no", (cl->tech->indicate) ? "yes" : "no", (cl->tech->transfer) ? "yes" : "no", - ast_getformatname_multiple(buf, sizeof(buf), (cl->tech->capabilities) ? cl->tech->capabilities : -1), + ast_getformatname_multiple(buf, sizeof(buf), cl->tech->capabilities), (cl->tech->send_digit_begin) ? "yes" : "no", (cl->tech->send_digit_end) ? "yes" : "no", (cl->tech->send_html) ? "yes" : "no", @@ -989,12 +989,11 @@ char *ast_transfercapability2str(int transfercapability) } /*! \brief Pick the best audio codec */ -format_t ast_best_codec(format_t fmts) +struct ast_format *ast_best_codec(struct ast_format_cap *cap, struct ast_format *result) { /* This just our opinion, expressed in code. We are asked to choose the best codec to use, given no information */ - int x; - static const format_t prefs[] = + static const enum ast_format_id prefs[] = { /*! Okay, ulaw is used by all telephony equipment, so start with it */ AST_FORMAT_ULAW, @@ -1032,19 +1031,19 @@ format_t ast_best_codec(format_t fmts) AST_FORMAT_G723_1, }; char buf[512]; + int x; - /* Strip out video */ - fmts &= AST_FORMAT_AUDIO_MASK; - /* Find the first preferred codec in the format given */ for (x = 0; x < ARRAY_LEN(prefs); x++) { - if (fmts & prefs[x]) - return prefs[x]; + if (ast_format_cap_iscompatible(cap, ast_format_set(result, prefs[x], 0))) { + return result; + } } - ast_log(LOG_WARNING, "Don't know any of %s formats\n", ast_getformatname_multiple(buf, sizeof(buf), fmts)); + ast_format_clear(result); + ast_log(LOG_WARNING, "Don't know any of %s formats\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); - return 0; + return NULL; } static const struct ast_channel_tech null_tech = { @@ -1087,6 +1086,11 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char /* Channel structure allocation failure. */ return NULL; } + if (!(tmp->nativeformats = ast_format_cap_alloc())) { + ao2_ref(tmp, -1); + /* format capabilities structure allocation failure */ + return NULL; + } /* * Init file descriptors to unopened state so @@ -2426,6 +2430,8 @@ static void ast_channel_destructor(void *obj) */ ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name); } + + chan->nativeformats = ast_format_cap_destroy(chan->nativeformats); } /*! \brief Free a dummy channel structure */ @@ -2658,8 +2664,15 @@ static void free_translation(struct ast_channel *clonechan) ast_translator_free_path(clonechan->readtrans); clonechan->writetrans = NULL; clonechan->readtrans = NULL; - clonechan->rawwriteformat = clonechan->nativeformats; - clonechan->rawreadformat = clonechan->nativeformats; + if (ast_format_cap_is_empty(clonechan->nativeformats)) { + ast_format_clear(&clonechan->rawwriteformat); + ast_format_clear(&clonechan->rawreadformat); + } else { + struct ast_format tmpfmt; + ast_best_codec(clonechan->nativeformats, &tmpfmt); + ast_format_copy(&clonechan->rawwriteformat, &tmpfmt); + ast_format_copy(&clonechan->rawreadformat, &tmpfmt); + } } void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force) @@ -2987,7 +3000,7 @@ static int generator_force(const void *data) if (!tmp || !generate) return 0; - res = generate(chan, tmp, 0, ast_format_rate(chan->writeformat & AST_FORMAT_AUDIO_MASK) / 50); + res = generate(chan, tmp, 0, ast_format_rate(&chan->writeformat) / 50); chan->generatordata = tmp; @@ -3548,9 +3561,9 @@ static void ast_read_generator_actions(struct ast_channel *chan, struct ast_fram chan->generatordata = NULL; /* reset, to let writes go through */ - if (f->subclass.codec != chan->writeformat) { + if (ast_format_cmp(&f->subclass.format, &chan->writeformat) == AST_FORMAT_CMP_NOT_EQUAL) { float factor; - factor = ((float) ast_format_rate(chan->writeformat)) / ((float) ast_format_rate(f->subclass.codec)); + factor = ((float) ast_format_rate(&chan->writeformat)) / ((float) ast_format_rate(&f->subclass.format)); samples = (int) ( ((float) f->samples) * factor ); } else { samples = f->samples; @@ -4066,11 +4079,11 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) ast_frfree(f); f = &ast_null_frame; } - } else if ((f->frametype == AST_FRAME_VOICE) && !(f->subclass.codec & chan->nativeformats)) { + } else if ((f->frametype == AST_FRAME_VOICE) && !ast_format_cap_iscompatible(chan->nativeformats, &f->subclass.format)) { /* This frame is not one of the current native formats -- drop it on the floor */ char to[200]; ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", - chan->name, ast_getformatname(f->subclass.codec), ast_getformatname_multiple(to, sizeof(to), chan->nativeformats)); + chan->name, ast_getformatname(&f->subclass.format), ast_getformatname_multiple(to, sizeof(to), chan->nativeformats)); ast_frfree(f); f = &ast_null_frame; } else if ((f->frametype == AST_FRAME_VOICE)) { @@ -4086,7 +4099,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) #ifndef MONITOR_CONSTANT_DELAY int jump = chan->outsmpl - chan->insmpl - 4 * f->samples; if (jump >= 0) { - jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); + jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(&f->subclass.format), ast_format_rate(&chan->monitor->read_stream->fmt->format)); if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1) ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); chan->insmpl += (chan->outsmpl - chan->insmpl) + f->samples; @@ -4557,7 +4570,7 @@ int ast_prod(struct ast_channel *chan) /* Send an empty audio frame to get things moving */ if (chan->_state != AST_STATE_UP) { ast_debug(1, "Prodding channel '%s'\n", chan->name); - a.subclass.codec = chan->rawwriteformat; + ast_format_copy(&a.subclass.format, &chan->rawwriteformat); a.data.ptr = nothing + AST_FRIENDLY_OFFSET; a.src = "ast_prod"; /* this better match check in ast_write */ if (ast_write(chan, &a)) @@ -4808,12 +4821,12 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) if (chan->tech->write == NULL) break; /*! \todo XXX should return 0 maybe ? */ - if (ast_opt_generic_plc && fr->subclass.codec == AST_FORMAT_SLINEAR) { + if (ast_opt_generic_plc && fr->subclass.format.id == AST_FORMAT_SLINEAR) { apply_plc(chan, fr); } /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */ - if (fr->subclass.codec == chan->rawwriteformat) + if (ast_format_cmp(&fr->subclass.format, &chan->rawwriteformat) != AST_FORMAT_CMP_NOT_EQUAL) f = fr; else f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr; @@ -4880,7 +4893,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) #ifndef MONITOR_CONSTANT_DELAY int jump = chan->insmpl - chan->outsmpl - 4 * cur->samples; if (jump >= 0) { - jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); + jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(&f->subclass.format), ast_format_rate(&chan->monitor->read_stream->fmt->format)); if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1) ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); chan->outsmpl += (chan->insmpl - chan->outsmpl) + cur->samples; @@ -4967,26 +4980,33 @@ done: return res; } -static int set_format(struct ast_channel *chan, format_t fmt, format_t *rawformat, format_t *format, - struct ast_trans_pvt **trans, const int direction) +static int set_format(struct ast_channel *chan, + struct ast_format_cap *cap_set, + struct ast_format *rawformat, + struct ast_format *format, + struct ast_trans_pvt **trans, + const int direction) { - format_t native, native_fmt = ast_best_codec(fmt); + struct ast_format_cap *cap_native = chan->nativeformats; + struct ast_format best_set_fmt; + struct ast_format best_native_fmt; int res; char from[200], to[200]; - - /* Make sure we only consider audio */ - fmt &= AST_FORMAT_AUDIO_MASK; - - native = chan->nativeformats; - if (!fmt || !native) /* No audio requested */ - return 0; /* Let's try a call without any sounds (video, text) */ + ast_best_codec(cap_set, &best_set_fmt); /* See if the underlying channel driver is capable of performing transcoding for us */ - if (!ast_channel_setoption(chan, direction ? AST_OPTION_FORMAT_WRITE : AST_OPTION_FORMAT_READ, &native_fmt, sizeof(int*), 0)) { + if (!ast_channel_setoption(chan, direction ? AST_OPTION_FORMAT_WRITE : AST_OPTION_FORMAT_READ, &best_set_fmt, sizeof(best_set_fmt), 0)) { ast_debug(1, "Channel driver natively set channel %s to %s format %s\n", chan->name, - direction ? "write" : "read", ast_getformatname(native_fmt)); - chan->nativeformats = *rawformat = *format = native_fmt; + direction ? "write" : "read", ast_getformatname(&best_set_fmt)); + + ast_format_copy(format, &best_set_fmt); + ast_format_copy(rawformat, &best_set_fmt); + + ast_channel_lock(chan); + ast_format_cap_set(chan->nativeformats, &best_set_fmt); + ast_channel_unlock(chan); + if (*trans) { ast_translator_free_path(*trans); } @@ -4995,39 +5015,44 @@ static int set_format(struct ast_channel *chan, format_t fmt, format_t *rawforma } /* Find a translation path from the native format to one of the desired formats */ - if (!direction) + if (!direction) { /* reading */ - res = ast_translator_best_choice(&fmt, &native); - else + res = ast_translator_best_choice(cap_set, cap_native, &best_set_fmt, &best_native_fmt); + } else { /* writing */ - res = ast_translator_best_choice(&native, &fmt); + res = ast_translator_best_choice(cap_native, cap_set, &best_native_fmt, &best_set_fmt); + } if (res < 0) { ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n", - ast_getformatname_multiple(from, sizeof(from), native), - ast_getformatname_multiple(to, sizeof(to), fmt)); + ast_getformatname_multiple(from, sizeof(from), cap_native), + ast_getformatname_multiple(to, sizeof(to), cap_set)); return -1; } - + /* Now we have a good choice for both. */ ast_channel_lock(chan); - if ((*rawformat == native) && (*format == fmt) && ((*rawformat == *format) || (*trans))) { + if ((ast_format_cmp(rawformat, &best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) && + (ast_format_cmp(format, &best_set_fmt) != AST_FORMAT_CMP_NOT_EQUAL) && + ((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || (*trans))) { /* the channel is already in these formats, so nothing to do */ ast_channel_unlock(chan); return 0; } - *rawformat = native; + ast_format_copy(rawformat, &best_native_fmt); /* User perspective is fmt */ - *format = fmt; + ast_format_copy(format, &best_set_fmt); + /* Free any read translation we have right now */ if (*trans) { ast_translator_free_path(*trans); *trans = NULL; } + /* Build a translation path from the raw format to the desired format */ - if (*format == *rawformat) { + if (ast_format_cmp(format, rawformat) != AST_FORMAT_CMP_NOT_EQUAL) { /* * If we were able to swap the native format to the format that * has been requested, then there is no need to try to build @@ -5037,29 +5062,122 @@ static int set_format(struct ast_channel *chan, format_t fmt, format_t *rawforma } else { if (!direction) { /* reading */ - *trans = ast_translator_build_path(*format, *rawformat); + *trans = ast_translator_build_path(format, rawformat); } else { /* writing */ - *trans = ast_translator_build_path(*rawformat, *format); + *trans = ast_translator_build_path(rawformat, format); } res = *trans ? 0 : -1; } ast_channel_unlock(chan); - ast_debug(1, "Set channel %s to %s format %s\n", chan->name, - direction ? "write" : "read", ast_getformatname(fmt)); + + ast_debug(1, "Set channel %s to %s format %s\n", + chan->name, + direction ? "write" : "read", + ast_getformatname(&best_set_fmt)); + return res; +} + +int ast_set_read_format(struct ast_channel *chan, struct ast_format *format) +{ + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + int res; + if (!cap) { + return -1; + } + ast_format_cap_add(cap, format); + + res = set_format(chan, + cap, + &chan->rawreadformat, + &chan->readformat, + &chan->readtrans, + 0); + + ast_format_cap_destroy(cap); return res; } -int ast_set_read_format(struct ast_channel *chan, format_t fmt) +int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id) { - return set_format(chan, fmt, &chan->rawreadformat, &chan->readformat, - &chan->readtrans, 0); + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + struct ast_format tmp_format; + int res; + if (!cap) { + return -1; + } + ast_format_cap_add(cap, ast_format_set(&tmp_format, id, 0)); + + res = set_format(chan, + cap, + &chan->rawreadformat, + &chan->readformat, + &chan->readtrans, + 0); + + ast_format_cap_destroy(cap); + return res; } -int ast_set_write_format(struct ast_channel *chan, format_t fmt) +int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap) { - return set_format(chan, fmt, &chan->rawwriteformat, &chan->writeformat, - &chan->writetrans, 1); + return set_format(chan, + cap, + &chan->rawreadformat, + &chan->readformat, + &chan->readtrans, + 0); +} + +int ast_set_write_format(struct ast_channel *chan, struct ast_format *format) +{ + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + int res; + if (!cap) { + return -1; + } + ast_format_cap_add(cap, format); + + res = set_format(chan, + cap, + &chan->rawwriteformat, + &chan->writeformat, + &chan->writetrans, + 1); + + ast_format_cap_destroy(cap); + return res; +} + +int ast_set_write_format_by_id(struct ast_channel *chan, enum ast_format_id id) +{ + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + struct ast_format tmp_format; + int res; + if (!cap) { + return -1; + } + ast_format_cap_add(cap, ast_format_set(&tmp_format, id, 0)); + + res = set_format(chan, + cap, + &chan->rawwriteformat, + &chan->writeformat, + &chan->writetrans, + 1); + + ast_format_cap_destroy(cap); + return res; +} + +int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap) +{ + return set_format(chan, + cap, + &chan->rawwriteformat, + &chan->writeformat, + &chan->writetrans, + 1); } const char *ast_channel_reason2str(int reason) @@ -5098,7 +5216,7 @@ static void handle_cause(int cause, int *outstate) } } -struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, format_t format, struct outgoing_helper *oh, int *outstate) +struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, struct ast_format_cap *cap, struct outgoing_helper *oh, int *outstate) { char tmpchan[256]; struct ast_channel *new = NULL; @@ -5121,7 +5239,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan data = tmpchan; type = "Local"; } - if (!(new = ast_request(type, format, orig, data, &cause))) { + if (!(new = ast_request(type, cap, orig, data, &cause))) { ast_log(LOG_NOTICE, "Unable to create channel for call forward to '%s/%s' (cause = %d)\n", type, data, cause); handle_cause(cause, outstate); ast_hangup(orig); @@ -5179,7 +5297,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan return new; } -struct ast_channel *__ast_request_and_dial(const char *type, format_t format, const struct ast_channel *requestor, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh) +struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh) { int dummy_outstate; int cause = 0; @@ -5193,7 +5311,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, format_t format, co else outstate = &dummy_outstate; /* make outstate always a valid pointer */ - chan = ast_request(type, format, requestor, data, &cause); + chan = ast_request(type, cap, requestor, data, &cause); if (!chan) { ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); handle_cause(cause, outstate); @@ -5245,7 +5363,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, format_t format, co if (timeout > -1) timeout = res; if (!ast_strlen_zero(chan->call_forward)) { - if (!(chan = ast_call_forward(NULL, chan, NULL, format, oh, outstate))) { + if (!(chan = ast_call_forward(NULL, chan, NULL, cap, oh, outstate))) { return NULL; } continue; @@ -5338,9 +5456,9 @@ struct ast_channel *__ast_request_and_dial(const char *type, format_t format, co return chan; } -struct ast_channel *ast_request_and_dial(const char *type, format_t format, const struct ast_channel *requestor, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname) +struct ast_channel *ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname) { - return __ast_request_and_dial(type, format, requestor, data, timeout, outstate, cidnum, cidname, NULL); + return __ast_request_and_dial(type, cap, requestor, data, timeout, outstate, cidnum, cidname, NULL); } static int set_security_requirements(const struct ast_channel *requestor, struct ast_channel *out) @@ -5383,16 +5501,12 @@ static int set_security_requirements(const struct ast_channel *requestor, struct return 0; } -struct ast_channel *ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) +struct ast_channel *ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_channel *requestor, void *data, int *cause) { struct chanlist *chan; struct ast_channel *c; - format_t capabilities; - format_t fmt; int res; int foo; - format_t videoformat = format & AST_FORMAT_VIDEO_MASK; - format_t textformat = format & AST_FORMAT_TEXT_MASK; if (!cause) cause = &foo; @@ -5404,21 +5518,27 @@ struct ast_channel *ast_request(const char *type, format_t format, const struct } AST_RWLIST_TRAVERSE(&backends, chan, list) { + struct ast_format_cap *tmp_cap; + struct ast_format tmp_fmt; + struct ast_format best_audio_fmt; + struct ast_format_cap *joint_cap; + if (strcasecmp(type, chan->tech->type)) continue; - capabilities = chan->tech->capabilities; - fmt = format & AST_FORMAT_AUDIO_MASK; - if (fmt) { + ast_format_clear(&best_audio_fmt); + /* find the best audio format to use */ + if ((tmp_cap = ast_format_cap_get_type(request_cap, AST_FORMAT_TYPE_AUDIO))) { /* We have audio - is it possible to connect the various calls to each other? (Avoid this check for calls without audio, like text+video calls) */ - res = ast_translator_best_choice(&fmt, &capabilities); + res = ast_translator_best_choice(tmp_cap, chan->tech->capabilities, &tmp_fmt, &best_audio_fmt); + ast_format_cap_destroy(tmp_cap); if (res < 0) { char tmp1[256], tmp2[256]; ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %s) to %s\n", type, ast_getformatname_multiple(tmp1, sizeof(tmp1), chan->tech->capabilities), - ast_getformatname_multiple(tmp2, sizeof(tmp2), format)); + ast_getformatname_multiple(tmp2, sizeof(tmp2), request_cap)); *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; AST_RWLIST_UNLOCK(&backends); return NULL; @@ -5428,8 +5548,21 @@ struct ast_channel *ast_request(const char *type, format_t format, const struct if (!chan->tech->requester) return NULL; - if (!(c = chan->tech->requester(type, capabilities | videoformat | textformat, requestor, data, cause))) + /* XXX Only the audio format calculated as being the best for translation + * purposes is used for the request. This needs to be re-evaluated. It may be + * a better choice to send all the audio formats capable of being translated + * during the request and allow the channel drivers to pick the best one. */ + if (!(joint_cap = ast_format_cap_dup(request_cap))) { return NULL; + } + ast_format_cap_remove_bytype(joint_cap, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_add(joint_cap, &best_audio_fmt); + + if (!(c = chan->tech->requester(type, joint_cap, requestor, data, cause))) { + ast_format_cap_destroy(joint_cap); + return NULL; + } + joint_cap = ast_format_cap_destroy(joint_cap); if (set_security_requirements(requestor, c)) { ast_log(LOG_WARNING, "Setting security requirements failed\n"); @@ -5610,7 +5743,10 @@ int ast_channel_sendurl(struct ast_channel *chan, const char *url) /*! \brief Set up translation from one channel to another */ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct ast_channel *to) { - format_t src, dst; + struct ast_format_cap *src_cap = from->nativeformats; /* shallow copy, do not destroy */ + struct ast_format_cap *dst_cap = to->nativeformats; /* shallow copy, do not destroy */ + struct ast_format best_src_fmt; + struct ast_format best_dst_fmt; int use_slin; /* See if the channel driver can natively make these two channels compatible */ @@ -5619,20 +5755,17 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a return 0; } - if (from->readformat == to->writeformat && from->writeformat == to->readformat) { + if ((ast_format_cmp(&from->readformat, &to->writeformat) != AST_FORMAT_CMP_NOT_EQUAL) && + (ast_format_cmp(&to->readformat, &from->writeformat) != AST_FORMAT_CMP_NOT_EQUAL)) { /* Already compatible! Moving on ... */ return 0; } - /* Set up translation from the 'from' channel to the 'to' channel */ - src = from->nativeformats; - dst = to->nativeformats; - /* If there's no audio in this call, don't bother with trying to find a translation path */ - if ((src & AST_FORMAT_AUDIO_MASK) == 0 || (dst & AST_FORMAT_AUDIO_MASK) == 0) + if (!ast_format_cap_has_type(src_cap, AST_FORMAT_TYPE_AUDIO) || !ast_format_cap_has_type(dst_cap, AST_FORMAT_TYPE_AUDIO)) return 0; - if (ast_translator_best_choice(&dst, &src) < 0) { + if (ast_translator_best_choice(dst_cap, src_cap, &best_src_fmt, &best_dst_fmt) < 0) { ast_log(LOG_WARNING, "No path to translate from %s to %s\n", from->name, to->name); return -1; } @@ -5643,16 +5776,20 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a * no direct conversion available. If generic PLC is * desired, then transcoding via SLINEAR is a requirement */ - use_slin = (src == AST_FORMAT_SLINEAR || dst == AST_FORMAT_SLINEAR); - if ((src != dst) && (ast_opt_generic_plc || ast_opt_transcode_via_slin) && - (ast_translate_path_steps(dst, src) != 1 || use_slin)) - dst = AST_FORMAT_SLINEAR; - if (ast_set_read_format(from, dst) < 0) { - ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n", from->name, ast_getformatname(dst)); + use_slin = (best_src_fmt.id == AST_FORMAT_SLINEAR || best_dst_fmt.id == AST_FORMAT_SLINEAR); + if ((ast_format_cmp(&best_src_fmt, &best_dst_fmt) == AST_FORMAT_CMP_NOT_EQUAL) && + (ast_opt_generic_plc || ast_opt_transcode_via_slin) && + (ast_translate_path_steps(&best_dst_fmt, &best_src_fmt) != 1 || use_slin)) { + + ast_format_set(&best_dst_fmt, AST_FORMAT_SLINEAR, 0); + } + + if (ast_set_read_format(from, &best_dst_fmt) < 0) { + ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n", from->name, ast_getformatname(&best_dst_fmt)); return -1; } - if (ast_set_write_format(to, dst) < 0) { - ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n", to->name, ast_getformatname(dst)); + if (ast_set_write_format(to, &best_dst_fmt) < 0) { + ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n", to->name, ast_getformatname(&best_dst_fmt)); return -1; } return 0; @@ -6199,8 +6336,7 @@ static void masquerade_colp_transfer(struct ast_channel *transferee, struct xfer */ int ast_do_masquerade(struct ast_channel *original) { - format_t x; - int i; + int x, i; int res=0; int origstate; int visible_indication; @@ -6218,13 +6354,17 @@ int ast_do_masquerade(struct ast_channel *original) struct ast_cdr *cdr; struct ast_datastore *xfer_ds; struct xfer_masquerade_ds *xfer_colp; - format_t rformat = original->readformat; - format_t wformat = original->writeformat; + struct ast_format rformat; + struct ast_format wformat; + struct ast_format tmp_format; char newn[AST_CHANNEL_NAME]; char orig[AST_CHANNEL_NAME]; char masqn[AST_CHANNEL_NAME]; char zombn[AST_CHANNEL_NAME]; + ast_format_copy(&rformat, &original->readformat); + ast_format_copy(&wformat, &original->writeformat); + /* XXX This operation is a bit odd. We're essentially putting the guts of * the clone channel into the original channel. Start by killing off the * original channel's backend. While the features are nice, which is the @@ -6383,12 +6523,13 @@ int ast_do_masquerade(struct ast_channel *original) } /* Swap the raw formats */ - x = original->rawreadformat; - original->rawreadformat = clonechan->rawreadformat; - clonechan->rawreadformat = x; - x = original->rawwriteformat; - original->rawwriteformat = clonechan->rawwriteformat; - clonechan->rawwriteformat = x; + ast_format_copy(&tmp_format, &original->rawreadformat); + ast_format_copy(&original->rawreadformat, &clonechan->rawreadformat); + ast_format_copy(&clonechan->rawreadformat, &tmp_format); + + ast_format_copy(&tmp_format, &original->rawwriteformat); + ast_format_copy(&original->rawwriteformat, &clonechan->rawwriteformat); + ast_format_copy(&clonechan->rawwriteformat, &tmp_format); clonechan->_softhangup = AST_SOFTHANGUP_DEV; @@ -6486,16 +6627,16 @@ int ast_do_masquerade(struct ast_channel *original) ast_channel_set_fd(original, AST_TIMING_FD, original->timingfd); /* Our native formats are different now */ - original->nativeformats = clonechan->nativeformats; + ast_format_cap_copy(original->nativeformats, clonechan->nativeformats); /* Context, extension, priority, app data, jump table, remain the same */ /* pvt switches. pbx stays the same, as does next */ /* Set the write format */ - ast_set_write_format(original, wformat); + ast_set_write_format(original, &wformat); /* Set the read format */ - ast_set_read_format(original, rformat); + ast_set_read_format(original, &rformat); /* Copy the music class */ ast_string_field_set(original, musicclass, clonechan->musicclass); @@ -6509,7 +6650,7 @@ int ast_do_masquerade(struct ast_channel *original) } ast_debug(1, "Putting channel %s in %s/%s formats\n", original->name, - ast_getformatname(wformat), ast_getformatname(rformat)); + ast_getformatname(&wformat), ast_getformatname(&rformat)); /* Okay. Last thing is to let the channel driver know about all this mess, so he can fix up everything as best as possible */ @@ -6753,8 +6894,8 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct struct ast_channel *cs[3]; struct ast_frame *f; enum ast_bridge_result res = AST_BRIDGE_COMPLETE; - format_t o0nativeformats; - format_t o1nativeformats; + struct ast_format_cap *o0nativeformats; + struct ast_format_cap *o1nativeformats; int watch_c0_dtmf; int watch_c1_dtmf; void *pvt0, *pvt1; @@ -6762,13 +6903,20 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct int frame_put_in_jb = 0; int jb_in_use; int to; - + + o0nativeformats = ast_format_cap_dup(c0->nativeformats); + o1nativeformats = ast_format_cap_dup(c1->nativeformats); + + if (!o0nativeformats || !o1nativeformats) { + ast_format_cap_destroy(o0nativeformats); /* NULL safe */ + ast_format_cap_destroy(o1nativeformats); /* NULL safe */ + return AST_BRIDGE_FAILED; + } + cs[0] = c0; cs[1] = c1; pvt0 = c0->tech_pvt; pvt1 = c1->tech_pvt; - o0nativeformats = c0->nativeformats; - o1nativeformats = c1->nativeformats; watch_c0_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_0; watch_c1_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_1; @@ -6790,8 +6938,8 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct struct ast_channel *who, *other; if ((c0->tech_pvt != pvt0) || (c1->tech_pvt != pvt1) || - (o0nativeformats != c0->nativeformats) || - (o1nativeformats != c1->nativeformats)) { + (!ast_format_cap_identical(o0nativeformats, c0->nativeformats)) || + (!ast_format_cap_identical(o1nativeformats, c1->nativeformats))) { /* Check for Masquerade, codec changes, etc */ res = AST_BRIDGE_RETRY; break; @@ -6941,6 +7089,9 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct ast_poll_channel_del(c0, c1); + ast_format_cap_destroy(o0nativeformats); + ast_format_cap_destroy(o1nativeformats); + return res; } @@ -7050,8 +7201,8 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha { struct ast_channel *chans[2] = { c0, c1 }; enum ast_bridge_result res = AST_BRIDGE_COMPLETE; - format_t o0nativeformats; - format_t o1nativeformats; + struct ast_format_cap *o0nativeformats; + struct ast_format_cap *o1nativeformats; long time_left_ms=0; char caller_warning = 0; char callee_warning = 0; @@ -7072,6 +7223,16 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) return -1; + o0nativeformats = ast_format_cap_dup(c0->nativeformats); + o1nativeformats = ast_format_cap_dup(c1->nativeformats); + if (!o0nativeformats || !o1nativeformats) { + ast_format_cap_destroy(o0nativeformats); + ast_format_cap_destroy(o1nativeformats); + ast_log(LOG_WARNING, "failed to copy native formats\n"); + return -1; + } + + *fo = NULL; if (ast_tvzero(config->start_time)) { @@ -7092,9 +7253,6 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha ast_set_owners_and_peers(c0, c1); - o0nativeformats = c0->nativeformats; - o1nativeformats = c1->nativeformats; - if (config->feature_timer && !ast_tvzero(config->nexteventts)) { config->nexteventts = ast_tvadd(config->feature_start_time, ast_samp2tv(config->feature_timer, 1000)); } else if (config->timelimit) { @@ -7245,6 +7403,8 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha c0->_bridge = NULL; c1->_bridge = NULL; + ast_format_cap_destroy(o0nativeformats); + ast_format_cap_destroy(o1nativeformats); return res; } else { ast_clear_flag(c0, AST_FLAG_NBRIDGE); @@ -7264,16 +7424,21 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha } } - if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || - (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && + if (((ast_format_cmp(&c1->readformat, &c0->writeformat) == AST_FORMAT_CMP_NOT_EQUAL) || + (ast_format_cmp(&c0->readformat, &c1->writeformat) == AST_FORMAT_CMP_NOT_EQUAL) || + !ast_format_cap_identical(c0->nativeformats, o0nativeformats) || + !ast_format_cap_identical(c1->nativeformats, o1nativeformats)) && !(c0->generator || c1->generator)) { if (ast_channel_make_compatible(c0, c1)) { ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); manager_bridge_event(0, 1, c0, c1); + ast_format_cap_destroy(o0nativeformats); + ast_format_cap_destroy(o1nativeformats); return AST_BRIDGE_FAILED; } - o0nativeformats = c0->nativeformats; - o1nativeformats = c1->nativeformats; + + ast_format_cap_copy(o0nativeformats, c0->nativeformats); + ast_format_cap_copy(o1nativeformats, c1->nativeformats); } update_bridge_vars(c0, c1); @@ -7310,6 +7475,8 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "<unknown>")); ast_debug(1, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name); + ast_format_cap_destroy(o0nativeformats); + ast_format_cap_destroy(o1nativeformats); return res; } @@ -7356,7 +7523,7 @@ struct tonepair_state { int v1_2; int v2_2; int v3_2; - format_t origwfmt; + struct ast_format origwfmt; int pos; int duration; int modulate; @@ -7370,7 +7537,7 @@ static void tonepair_release(struct ast_channel *chan, void *params) struct tonepair_state *ts = params; if (chan) - ast_set_write_format(chan, ts->origwfmt); + ast_set_write_format(chan, &ts->origwfmt); ast_free(ts); } @@ -7381,8 +7548,8 @@ static void *tonepair_alloc(struct ast_channel *chan, void *params) if (!(ts = ast_calloc(1, sizeof(*ts)))) return NULL; - ts->origwfmt = chan->writeformat; - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { + ast_format_copy(&ts->origwfmt, &chan->writeformat); + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) { ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name); tonepair_release(NULL, ts); ts = NULL; @@ -7436,7 +7603,7 @@ static int tonepair_generator(struct ast_channel *chan, void *data, int len, int ts->data[x] = ts->v3_1 + ts->v3_2; } ts->f.frametype = AST_FRAME_VOICE; - ts->f.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&ts->f.subclass.format, AST_FORMAT_SLINEAR, 0); ts->f.datalen = len; ts->f.samples = samples; ts->f.offset = AST_FRIENDLY_OFFSET; @@ -7778,11 +7945,11 @@ static int silence_generator_generate(struct ast_channel *chan, void *data, int short buf[samples]; struct ast_frame frame = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .data.ptr = buf, .samples = samples, .datalen = sizeof(buf), }; + ast_format_set(&frame.subclass.format, AST_FORMAT_SLINEAR, 0); memset(buf, 0, sizeof(buf)); @@ -7799,7 +7966,7 @@ static struct ast_generator silence_generator = { }; struct ast_silence_generator { - int old_write_format; + struct ast_format old_write_format; }; struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan) @@ -7810,9 +7977,9 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha return NULL; } - state->old_write_format = chan->writeformat; + ast_format_copy(&state->old_write_format, &chan->writeformat); - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n"); ast_free(state); return NULL; @@ -7834,7 +8001,7 @@ void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_sil ast_debug(1, "Stopped silence generator on '%s'\n", chan->name); - if (ast_set_write_format(chan, state->old_write_format) < 0) + if (ast_set_write_format(chan, &state->old_write_format) < 0) ast_log(LOG_ERROR, "Could not return write format to its original state\n"); ast_free(state); diff --git a/main/cli.c b/main/cli.c index 7f4c1791fd76fb2bd883806e869b5163ebccad22..671a2bac77ee3055c3b9942e1aecc21df20c7727 100644 --- a/main/cli.c +++ b/main/cli.c @@ -1387,7 +1387,7 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar struct timeval now; struct ast_str *out = ast_str_thread_get(&ast_str_thread_global_buf, 16); char cdrtime[256]; - char nf[256], wf[256], rf[256]; + char nf[256]; struct ast_str *write_transpath = ast_str_alloca(256); struct ast_str *read_transpath = ast_str_alloca(256); long elapsed_seconds=0; @@ -1469,9 +1469,9 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar S_OR(c->dialed.number.str, "(N/A)"), c->language, ast_state2str(c->_state), c->_state, c->rings, - ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats), - ast_getformatname_multiple(wf, sizeof(wf), c->writeformat), - ast_getformatname_multiple(rf, sizeof(rf), c->readformat), + ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats), + ast_getformatname(&c->writeformat), + ast_getformatname(&c->readformat), c->writetrans ? "Yes" : "No", ast_translate_path_to_str(c->writetrans, &write_transpath), c->readtrans ? "Yes" : "No", diff --git a/main/data.c b/main/data.c index 3b2c124abcf24f0d62f8f23a46a4f07567e6dff3..3ca2f7c27d154d668714189a928428ea2d0a7c1a 100644 --- a/main/data.c +++ b/main/data.c @@ -3100,7 +3100,7 @@ static int manager_data_get(struct mansession *s, const struct message *m) return RESULT_SUCCESS; } -int ast_data_add_codecs(struct ast_data *root, const char *node_name, format_t capability) +int ast_data_add_codec(struct ast_data *root, const char *node_name, struct ast_format *format) { struct ast_data *codecs, *codec; size_t fmlist_size; @@ -3113,7 +3113,36 @@ int ast_data_add_codecs(struct ast_data *root, const char *node_name, format_t c } fmlist = ast_get_format_list(&fmlist_size); for (x = 0; x < fmlist_size; x++) { - if (fmlist[x].bits & capability) { + if (fmlist[x].id == format->id) { + codec = ast_data_add_node(codecs, "codec"); + if (!codec) { + return -1; + } + ast_data_add_str(codec, "name", fmlist[x].name); + ast_data_add_int(codec, "samplespersecond", fmlist[x].samplespersecond); + ast_data_add_str(codec, "description", fmlist[x].desc); + ast_data_add_int(codec, "frame_length", fmlist[x].fr_len); + } + } + + return 0; +} + +int ast_data_add_codecs(struct ast_data *root, const char *node_name, struct ast_format_cap *cap) +{ + struct ast_data *codecs, *codec; + size_t fmlist_size; + const struct ast_format_list *fmlist; + struct ast_format tmp_fmt; + int x; + + codecs = ast_data_add_node(root, node_name); + if (!codecs) { + return -1; + } + fmlist = ast_get_format_list(&fmlist_size); + for (x = 0; x < fmlist_size; x++) { + if (ast_format_cap_iscompatible(cap, ast_format_set(&tmp_fmt, fmlist[x].id, 0))) { codec = ast_data_add_node(codecs, "codec"); if (!codec) { return -1; diff --git a/main/dial.c b/main/dial.c index ba1a2bb53cf3d2c54c54dd5b0b7f9422b5bb74a8..5c30e287dc4ce44cab72dc0d822b8e998dffd1d6 100644 --- a/main/dial.c +++ b/main/dial.c @@ -248,13 +248,27 @@ static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_chann { char numsubst[AST_MAX_EXTENSION]; int res = 1; + struct ast_format_cap *cap_all_audio = NULL; + struct ast_format_cap *cap_request; /* Copy device string over */ ast_copy_string(numsubst, channel->device, sizeof(numsubst)); + if (chan) { + cap_request = chan->nativeformats; + } else { + cap_all_audio = ast_format_cap_alloc_nolock(); + ast_format_cap_add_all_by_type(cap_all_audio, AST_FORMAT_TYPE_AUDIO); + cap_request = cap_all_audio; + } + /* If we fail to create our owner channel bail out */ - if (!(channel->owner = ast_request(channel->tech, chan ? chan->nativeformats : AST_FORMAT_AUDIO_MASK, chan, numsubst, &channel->cause))) + if (!(channel->owner = ast_request(channel->tech, cap_request, chan, numsubst, &channel->cause))) { + cap_all_audio = ast_format_cap_destroy(cap_all_audio); return -1; + } + cap_request = NULL; + cap_all_audio = ast_format_cap_destroy(cap_all_audio); channel->owner->appl = "AppDial2"; channel->owner->data = "(Outgoing Line)"; diff --git a/main/dsp.c b/main/dsp.c index cba01b5f1798b02eb73b845d4e7063b398d71647..69989afe8530d930adde1da20a1b7027038f0053 100644 --- a/main/dsp.c +++ b/main/dsp.c @@ -1106,7 +1106,7 @@ int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf) ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); return 0; } - if (inf->subclass.codec != AST_FORMAT_SLINEAR) { + if (inf->subclass.format.id != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); return 0; } @@ -1280,7 +1280,7 @@ int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence) ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); return 0; } - if (f->subclass.codec != AST_FORMAT_SLINEAR) { + if (f->subclass.format.id != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); return 0; } @@ -1298,7 +1298,7 @@ int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise) ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); return 0; } - if (f->subclass.codec != AST_FORMAT_SLINEAR) { + if (f->subclass.format.id != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); return 0; } @@ -1329,7 +1329,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, odata = af->data.ptr; len = af->datalen; /* Make sure we have short data */ - switch (af->subclass.codec) { + switch (af->subclass.format.id) { case AST_FORMAT_SLINEAR: shortdata = af->data.ptr; len = af->datalen / 2; @@ -1350,7 +1350,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, default: /*Display warning only once. Otherwise you would get hundreds of warnings every second */ if (dsp->display_inband_dtmf_warning) - ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec)); + ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(&af->subclass.format)); dsp->display_inband_dtmf_warning = 0; return af; } @@ -1479,7 +1479,7 @@ done: memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start)); } - switch (af->subclass.codec) { + switch (af->subclass.format.id) { case AST_FORMAT_SLINEAR: break; case AST_FORMAT_ULAW: @@ -1491,6 +1491,8 @@ done: for (x = 0; x < len; x++) { odata[x] = AST_LIN2A((unsigned short) shortdata[x]); } + /* fall through */ + default: break; } diff --git a/main/features.c b/main/features.c index 413f8170a94175fda70f3088f1bc67165e136fa9..f35a2475a8544b0e11e18c073b3974309ae420a1 100644 --- a/main/features.c +++ b/main/features.c @@ -743,7 +743,7 @@ static void check_goto_on_transfer(struct ast_channel *chan) static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, const char *caller_name, struct ast_channel *requestor, - struct ast_channel *transferee, const char *type, format_t format, void *data, + struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data, int timeout, int *outstate, const char *language); /*! @@ -1315,17 +1315,20 @@ static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *origina static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech) { struct ast_channel *test_channel1; + struct ast_format tmp_fmt; if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, 0, 0, "TestChannel1"))) { return NULL; } /* normally this is done in the channel driver */ - test_channel1->nativeformats = AST_FORMAT_GSM; - test_channel1->writeformat = AST_FORMAT_GSM; - test_channel1->rawwriteformat = AST_FORMAT_GSM; - test_channel1->readformat = AST_FORMAT_GSM; - test_channel1->rawreadformat = AST_FORMAT_GSM; + ast_format_cap_add(test_channel1->nativeformats, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0)); + + ast_format_set(&test_channel1->writeformat, AST_FORMAT_GSM, 0); + ast_format_set(&test_channel1->rawwriteformat, AST_FORMAT_GSM, 0); + ast_format_set(&test_channel1->readformat, AST_FORMAT_GSM, 0); + ast_format_set(&test_channel1->rawreadformat, AST_FORMAT_GSM, 0); + test_channel1->tech = fake_tech; return test_channel1; @@ -2136,7 +2139,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st /* Dial party C */ newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer, - transferee, "Local", ast_best_codec(transferer->nativeformats), xferto, + transferee, "Local", transferer->nativeformats, xferto, atxfernoanswertimeout, &outstate, transferer->language); ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate); @@ -2243,14 +2246,13 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st transferer_tech, transferer_name); newchan = feature_request_and_dial(transferer, transferer_name_orig, transferee, transferee, transferer_tech, - ast_best_codec(transferee->nativeformats), transferer_name, + transferee->nativeformats, transferer_name, atxfernoanswertimeout, &outstate, transferer->language); ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n", !!newchan, outstate); if (newchan || ast_check_hangup(transferee)) { break; } - ++tries; if (atxfercallbackretries <= tries) { /* No more callback tries remaining. */ @@ -2272,7 +2274,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto); newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer, transferee, "Local", - ast_best_codec(transferee->nativeformats), xferto, + transferee->nativeformats, xferto, atxfernoanswertimeout, &outstate, transferer->language); ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate); @@ -2980,7 +2982,7 @@ static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, */ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, const char *caller_name, struct ast_channel *requestor, - struct ast_channel *transferee, const char *type, format_t format, void *data, + struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data, int timeout, int *outstate, const char *language) { int state = 0; @@ -2996,12 +2998,21 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, struct timeval started; int x, len = 0; char *disconnect_code = NULL, *dialed_code = NULL; + struct ast_format_cap *tmp_cap; + struct ast_format best_audio_fmt; struct ast_frame *f; AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames; + tmp_cap = ast_format_cap_alloc_nolock(); + if (!tmp_cap) { + return NULL; + } + ast_best_codec(cap, &best_audio_fmt); + ast_format_cap_add(tmp_cap, &best_audio_fmt); + caller_hungup = ast_check_hangup(caller); - if (!(chan = ast_request(type, format, requestor, data, &cause))) { + if (!(chan = ast_request(type, tmp_cap, requestor, data, &cause))) { ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); switch (cause) { case AST_CAUSE_BUSY: @@ -3119,8 +3130,7 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, } } else if (chan == active_channel) { if (!ast_strlen_zero(chan->call_forward)) { - state = 0; - chan = ast_call_forward(caller, chan, NULL, format, NULL, &state); + chan = ast_call_forward(caller, chan, NULL, tmp_cap, NULL, &state); if (!chan) { break; } @@ -3252,6 +3262,8 @@ done: chan = NULL; } + tmp_cap = ast_format_cap_destroy(tmp_cap); + if (outstate) *outstate = state; diff --git a/main/file.c b/main/file.c index c2ab096cd004bd98483c10e2f7ff5710dfad831d..57bf1570c0316c405dcd70268ff057e134cc6af8 100644 --- a/main/file.c +++ b/main/file.c @@ -59,11 +59,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") */ int ast_language_is_prefix = 1; -static AST_RWLIST_HEAD_STATIC(formats, ast_format); +static AST_RWLIST_HEAD_STATIC(formats, ast_format_def); -int __ast_format_register(const struct ast_format *f, struct ast_module *mod) +int __ast_format_def_register(const struct ast_format_def *f, struct ast_module *mod) { - struct ast_format *tmp; + struct ast_format_def *tmp; AST_RWLIST_WRLOCK(&formats); AST_RWLIST_TRAVERSE(&formats, tmp, list) { @@ -98,9 +98,9 @@ int __ast_format_register(const struct ast_format *f, struct ast_module *mod) return 0; } -int ast_format_unregister(const char *name) +int ast_format_def_unregister(const char *name) { - struct ast_format *tmp; + struct ast_format_def *tmp; int res = -1; AST_RWLIST_WRLOCK(&formats); @@ -130,8 +130,8 @@ int ast_stopstream(struct ast_channel *tmp) if (tmp->stream) { ast_closestream(tmp->stream); tmp->stream = NULL; - if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat)) - ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_getformatname(tmp->oldwriteformat)); + if (tmp->oldwriteformat.id && ast_set_write_format(tmp, &tmp->oldwriteformat)) + ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_getformatname(&tmp->oldwriteformat)); } /* Stop the video stream too */ if (tmp->vstream != NULL) { @@ -149,10 +149,10 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f) int res = -1; int alt = 0; if (f->frametype == AST_FRAME_VIDEO) { - if (fs->fmt->format & AST_FORMAT_AUDIO_MASK) { + if (AST_FORMAT_GET_TYPE(fs->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) { /* This is the audio portion. Call the video one... */ if (!fs->vfs && fs->filename) { - const char *type = ast_getformatname(f->subclass.codec & ~0x1); + const char *type = ast_getformatname(&f->subclass.format); fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode); ast_debug(1, "Opened video output file\n"); } @@ -168,7 +168,7 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f) ast_log(LOG_WARNING, "Tried to write non-voice frame\n"); return -1; } - if (((fs->fmt->format | alt) & f->subclass.codec) == f->subclass.codec) { + if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) != AST_FORMAT_CMP_NOT_EQUAL) { res = fs->fmt->write(fs, f); if (res < 0) ast_log(LOG_WARNING, "Natural write failed\n"); @@ -177,18 +177,18 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f) } else { /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't the one we've setup a translator for, we do the "wrong thing" XXX */ - if (fs->trans && f->subclass.codec != fs->lastwriteformat) { + if (fs->trans && (ast_format_cmp(&f->subclass.format, &fs->lastwriteformat) != AST_FORMAT_CMP_EQUAL)) { ast_translator_free_path(fs->trans); fs->trans = NULL; } if (!fs->trans) - fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass.codec); + fs->trans = ast_translator_build_path(&fs->fmt->format, &f->subclass.format); if (!fs->trans) ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", - fs->fmt->name, ast_getformatname(f->subclass.codec)); + fs->fmt->name, ast_getformatname(&f->subclass.format)); else { struct ast_frame *trf; - fs->lastwriteformat = f->subclass.codec; + ast_format_copy(&fs->lastwriteformat, &f->subclass.format); /* Get the translated frame but don't consume the original in case they're using it on another stream */ if ((trf = ast_translate(fs->trans, f, 0))) { struct ast_frame *cur; @@ -296,7 +296,7 @@ static void filestream_destructor(void *arg) /* Stop a running stream if there is one */ if (f->owner) { - if (f->fmt->format < AST_FORMAT_AUDIO_MASK) { + if (AST_FORMAT_GET_TYPE(f->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) { f->owner->stream = NULL; AST_SCHED_DEL(f->owner->sched, f->owner->streamid); ast_settimeout(f->owner, 0, NULL, NULL); @@ -335,7 +335,7 @@ static void filestream_destructor(void *arg) ast_module_unref(f->fmt->module); } -static struct ast_filestream *get_filestream(struct ast_format *fmt, FILE *bfile) +static struct ast_filestream *get_filestream(struct ast_format_def *fmt, FILE *bfile) { struct ast_filestream *s; @@ -361,7 +361,7 @@ enum wrap_fn { WRAP_OPEN, WRAP_REWRITE }; static int fn_wrapper(struct ast_filestream *s, const char *comment, enum wrap_fn mode) { - struct ast_format *f = s->fmt; + struct ast_format_def *f = s->fmt; int ret = -1; int (*openfn)(struct ast_filestream *s); @@ -396,18 +396,20 @@ enum file_action { }; /*! + * \internal * \brief perform various actions on a file. Second argument - * arg2 depends on the command: - * unused for EXISTS and DELETE + * \note arg2 depends on the command: + * unused for DELETE + * optional ast_format_cap holding all the formats found for a file, for EXISTS. * destination file name (const char *) for COPY and RENAME * struct ast_channel * for OPEN * if fmt is NULL, OPEN will return the first matching entry, * whereas other functions will run on all matching entries. */ -static format_t ast_filehelper(const char *filename, const void *arg2, const char *fmt, const enum file_action action) +static int filehelper(const char *filename, const void *arg2, const char *fmt, const enum file_action action) { - struct ast_format *f; - format_t res = (action == ACTION_EXISTS) ? 0 : -1; + struct ast_format_def *f; + int res = (action == ACTION_EXISTS) ? 0 : -1; AST_RWLIST_RDLOCK(&formats); /* Check for a specific format */ @@ -441,9 +443,9 @@ static format_t ast_filehelper(const char *filename, const void *arg2, const cha FILE *bfile; struct ast_filestream *s; - if ( !(chan->writeformat & f->format) && - !((f->format & AST_FORMAT_AUDIO_MASK && fmt) || - (f->format & AST_FORMAT_VIDEO_MASK && fmt))) { + if ((ast_format_cmp(&chan->writeformat, &f->format) == AST_FORMAT_CMP_NOT_EQUAL) && + !(((AST_FORMAT_GET_TYPE(f->format.id) == AST_FORMAT_TYPE_AUDIO) && fmt) || + ((AST_FORMAT_GET_TYPE(f->format.id) == AST_FORMAT_TYPE_VIDEO) && fmt))) { ast_free(fn); continue; /* not a supported format */ } @@ -471,7 +473,7 @@ static format_t ast_filehelper(const char *filename, const void *arg2, const cha s->fmt = f; s->trans = NULL; s->filename = NULL; - if (s->fmt->format & AST_FORMAT_AUDIO_MASK) { + if (AST_FORMAT_GET_TYPE(s->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) { if (chan->stream) ast_closestream(chan->stream); chan->stream = s; @@ -488,7 +490,12 @@ static format_t ast_filehelper(const char *filename, const void *arg2, const cha break; /* will never get here */ case ACTION_EXISTS: /* return the matching format */ - res |= f->format; + /* if arg2 is present, it is a format capabilities structure. + * Add this format to the set of formats this file can be played in */ + if (arg2) { + ast_format_cap_add((struct ast_format_cap *) arg2, &f->format); + } + res = 1; /* file does exist and format it exists in is returned in arg2 */ break; case ACTION_DELETE: @@ -527,11 +534,17 @@ static int is_absolute_path(const char *filename) return filename[0] == '/'; } -static format_t fileexists_test(const char *filename, const char *fmt, const char *lang, - char *buf, int buflen) +/*! + * \brief test if a file exists for a given format. + * \note result_cap is OPTIONAL + * \retval 1, true and result_cap represents format capabilities file exists in. + * \retval 0, false + */ +static int fileexists_test(const char *filename, const char *fmt, const char *lang, + char *buf, int buflen, struct ast_format_cap *result_cap) { if (buf == NULL) { - return -1; + return 0; } if (ast_language_is_prefix && !is_absolute_path(filename)) { /* new layout */ @@ -550,25 +563,36 @@ static format_t fileexists_test(const char *filename, const char *fmt, const cha } } - return ast_filehelper(buf, NULL, fmt, ACTION_EXISTS); + return filehelper(buf, result_cap, fmt, ACTION_EXISTS); } /*! * \brief helper routine to locate a file with a given format * and language preference. - * Try preflang, preflang with stripped '_' suffices, or NULL. + * + * \note Try preflang, preflang with stripped '_' suffices, or NULL. * - * The last parameter(s) point to a buffer of sufficient size, + * \note The last parameter(s) point to a buffer of sufficient size, * which on success is filled with the matching filename. + * + * \param filename, name of the file. + * \param fmt, format to look for the file in. OPTIONAL + * \param preflang, the perfered language + * \param buf, returns the matching filename + * \param buflen, size of the buf + * \param result_cap, OPTIONAL format capabilities result structure + * returns what formats the file was found in. + * + * \retval 1, true. file exists and result format is set + * \retval 0, false. file does not exist. */ -static format_t fileexists_core(const char *filename, const char *fmt, const char *preflang, - char *buf, int buflen) +static int fileexists_core(const char *filename, const char *fmt, const char *preflang, + char *buf, int buflen, struct ast_format_cap *result_cap) { - format_t res = -1; char *lang; if (buf == NULL) { - return -1; + return 0; } /* We try languages in the following order: @@ -584,8 +608,8 @@ static format_t fileexists_core(const char *filename, const char *fmt, const cha while (!ast_strlen_zero(lang)) { char *end; - if ((res = fileexists_test(filename, fmt, lang, buf, buflen)) > 0) { - return res; + if (fileexists_test(filename, fmt, lang, buf, buflen, result_cap)) { + return 1; } if ((end = strrchr(lang, '_')) != NULL) { @@ -597,14 +621,14 @@ static format_t fileexists_core(const char *filename, const char *fmt, const cha } /* Try without any language */ - if ((res = fileexists_test(filename, fmt, NULL, buf, buflen)) > 0) { - return res; + if (fileexists_test(filename, fmt, NULL, buf, buflen, result_cap)) { + return 1; } /* Finally try the default language unless it was already tried before */ if ((ast_strlen_zero(preflang) || strcmp(preflang, DEFAULT_LANGUAGE)) && (ast_strlen_zero(lang) || strcmp(lang, DEFAULT_LANGUAGE))) { - if ((res = fileexists_test(filename, fmt, DEFAULT_LANGUAGE, buf, buflen)) > 0) { - return res; + if ((fileexists_test(filename, fmt, DEFAULT_LANGUAGE, buf, buflen, result_cap)) > 0) { + return 1; } } @@ -623,7 +647,8 @@ struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char * language and format, set up a suitable translator, * and open the stream. */ - format_t fmts, res; + struct ast_format_cap *file_fmt_cap; + int res; int buflen; char *buf; @@ -639,20 +664,29 @@ struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char buf = alloca(buflen); if (buf == NULL) return NULL; - fmts = fileexists_core(filename, NULL, preflang, buf, buflen); - if (fmts > 0) - fmts &= AST_FORMAT_AUDIO_MASK; - if (fmts < 1) { + + if (!(file_fmt_cap = ast_format_cap_alloc_nolock())) { + return NULL; + } + if (!fileexists_core(filename, NULL, preflang, buf, buflen, file_fmt_cap) || + !ast_format_cap_has_type(file_fmt_cap, AST_FORMAT_TYPE_AUDIO)) { + ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename); + file_fmt_cap = ast_format_cap_destroy(file_fmt_cap); return NULL; } - chan->oldwriteformat = chan->writeformat; - /* Set the channel to a format we can work with */ - res = ast_set_write_format(chan, fmts); + + /* Set the channel to a format we can work with and save off the previous format. */ + ast_format_copy(&chan->oldwriteformat, &chan->writeformat); + /* Set the channel to the best format that exists for the file. */ + res = ast_set_write_format_from_cap(chan, file_fmt_cap); + /* don't need this anymore now that the channel's write format is set. */ + file_fmt_cap = ast_format_cap_destroy(file_fmt_cap); + if (res == -1) { /* No format available that works with this channel */ return NULL; } - res = ast_filehelper(buf, chan, NULL, ACTION_OPEN); + res = filehelper(buf, chan, NULL, ACTION_OPEN); if (res >= 0) return chan->stream; return NULL; @@ -663,9 +697,12 @@ struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *fil /* As above, but for video. But here we don't have translators * so we must enforce a format. */ - format_t format; + struct ast_format tmp_fmt; + struct ast_format_cap *tmp_cap; char *buf; int buflen; + const char *fmt; + int fd; if (preflang == NULL) preflang = ""; @@ -674,20 +711,39 @@ struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *fil if (buf == NULL) return NULL; - for (format = AST_FORMAT_AUDIO_MASK + 1; format <= AST_FORMAT_VIDEO_MASK; format = format << 1) { - int fd; - const char *fmt; + /* is the channel capable of video without translation ?*/ + if (!ast_format_cap_has_type(chan->nativeformats, AST_FORMAT_TYPE_VIDEO)) { + return NULL; + } + if (!(tmp_cap = ast_format_cap_alloc_nolock())) { + return NULL; + } + /* Video is supported, so see what video formats exist for this file */ + if (!fileexists_core(filename, NULL, preflang, buf, buflen, tmp_cap)) { + tmp_cap = ast_format_cap_destroy(tmp_cap); + return NULL; + } - if (!(chan->nativeformats & format)) + /* iterate over file formats and pick the first one compatible with the channel's native formats */ + ast_format_cap_iter_start(tmp_cap); + while (!ast_format_cap_iter_next(tmp_cap, &tmp_fmt)) { + fmt = ast_getformatname(&tmp_fmt); + if ((AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_VIDEO) || + !ast_format_cap_iscompatible(chan->nativeformats, &tmp_fmt)) { continue; - fmt = ast_getformatname(format); - if ( fileexists_core(filename, fmt, preflang, buf, buflen) < 1) /* no valid format */ - continue; - fd = ast_filehelper(buf, chan, fmt, ACTION_OPEN); - if (fd >= 0) + } + + fd = filehelper(buf, chan, fmt, ACTION_OPEN); + if (fd >= 0) { + ast_format_cap_iter_end(tmp_cap); + tmp_cap = ast_format_cap_destroy(tmp_cap); return chan->vstream; + } ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename); } + ast_format_cap_iter_end(tmp_cap); + tmp_cap = ast_format_cap_destroy(tmp_cap); + return NULL; } @@ -759,7 +815,7 @@ static enum fsread_res ast_readaudio_callback(struct ast_filestream *s) if (whennext != s->lasttimeout) { if (s->owner->timingfd > -1) { - float samp_rate = (float) ast_format_rate(s->fmt->format); + float samp_rate = (float) ast_format_rate(&s->fmt->format); unsigned int rate; rate = (unsigned int) roundf(samp_rate / ((float) whennext)); @@ -767,7 +823,7 @@ static enum fsread_res ast_readaudio_callback(struct ast_filestream *s) ast_settimeout(s->owner, rate, ast_fsread_audio, s); } else { s->owner->streamid = ast_sched_add(s->owner->sched, - whennext / (ast_format_rate(s->fmt->format) / 1000), ast_fsread_audio, s); + whennext / (ast_format_rate(&s->fmt->format) / 1000), ast_fsread_audio, s); } s->lasttimeout = whennext; return FSREAD_SUCCESS_NOSCHED; @@ -818,7 +874,7 @@ static enum fsread_res ast_readvideo_callback(struct ast_filestream *s) if (whennext != s->lasttimeout) { s->owner->vstreamid = ast_sched_add(s->owner->sched, - whennext / (ast_format_rate(s->fmt->format) / 1000), + whennext / (ast_format_rate(&s->fmt->format) / 1000), ast_fsread_video, s); s->lasttimeout = whennext; return FSREAD_SUCCESS_NOSCHED; @@ -850,7 +906,7 @@ int ast_playstream(struct ast_filestream *s) { enum fsread_res res; - if (s->fmt->format & AST_FORMAT_AUDIO_MASK) + if (AST_FORMAT_GET_TYPE(s->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) res = ast_readaudio_callback(s); else res = ast_readvideo_callback(s); @@ -892,7 +948,7 @@ int ast_closestream(struct ast_filestream *f) /* Stop a running stream if there is one */ if (f->owner) { - if (f->fmt->format < AST_FORMAT_AUDIO_MASK) { + if (AST_FORMAT_GET_TYPE(f->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) { f->owner->stream = NULL; AST_SCHED_DEL(f->owner->sched, f->owner->streamid); ast_settimeout(f->owner, 0, NULL, NULL); @@ -921,22 +977,22 @@ int ast_fileexists(const char *filename, const char *fmt, const char *preflang) buf = alloca(buflen); if (buf == NULL) return 0; - return fileexists_core(filename, fmt, preflang, buf, buflen); + return fileexists_core(filename, fmt, preflang, buf, buflen, NULL) ? 1 : 0; } int ast_filedelete(const char *filename, const char *fmt) { - return ast_filehelper(filename, NULL, fmt, ACTION_DELETE); + return filehelper(filename, NULL, fmt, ACTION_DELETE); } int ast_filerename(const char *filename, const char *filename2, const char *fmt) { - return ast_filehelper(filename, filename2, fmt, ACTION_RENAME); + return filehelper(filename, filename2, fmt, ACTION_RENAME); } int ast_filecopy(const char *filename, const char *filename2, const char *fmt) { - return ast_filehelper(filename, filename2, fmt, ACTION_COPY); + return filehelper(filename, filename2, fmt, ACTION_COPY); } int ast_streamfile(struct ast_channel *chan, const char *filename, const char *preflang) @@ -966,7 +1022,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p vfs = ast_openvstream(chan, filename, preflang); if (vfs) { - ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format)); + ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(&vfs->fmt->format)); } if (ast_test_flag(chan, AST_FLAG_MASQ_NOSTREAM)) @@ -978,7 +1034,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p res = ast_playstream(fs); if (!res && vfs) res = ast_playstream(vfs); - ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", chan->name, filename, ast_getformatname(chan->writeformat), preflang ? preflang : "default"); + ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", chan->name, filename, ast_getformatname(&chan->writeformat), preflang ? preflang : "default"); return res; } @@ -986,7 +1042,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p struct ast_filestream *ast_readfile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode) { FILE *bfile; - struct ast_format *f; + struct ast_format_def *f; struct ast_filestream *fs = NULL; char *fn; int format_found = 0; @@ -1036,7 +1092,7 @@ struct ast_filestream *ast_writefile(const char *filename, const char *type, con int fd, myflags = 0; /* compiler claims this variable can be used before initialization... */ FILE *bfile = NULL; - struct ast_format *f; + struct ast_format_def *f; struct ast_filestream *fs = NULL; char *buf = NULL; size_t size = 0; @@ -1359,8 +1415,8 @@ int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char * char *ast_format_str_reduce(char *fmts) { - struct ast_format *f; - struct ast_format *fmts_ptr[AST_MAX_FORMATS]; + struct ast_format_def *f; + struct ast_format_def *fmts_ptr[AST_MAX_FORMATS]; char *fmts_str[AST_MAX_FORMATS]; char *stringp, *type; char *orig = fmts; @@ -1437,7 +1493,7 @@ static char *handle_cli_core_show_file_formats(struct ast_cli_entry *e, int cmd, { #define FORMAT "%-10s %-10s %-20s\n" #define FORMAT2 "%-10s %-10s %-20s\n" - struct ast_format *f; + struct ast_format_def *f; int count_fmt = 0; switch (cmd) { @@ -1459,7 +1515,7 @@ static char *handle_cli_core_show_file_formats(struct ast_cli_entry *e, int cmd, AST_RWLIST_RDLOCK(&formats); AST_RWLIST_TRAVERSE(&formats, f, list) { - ast_cli(a->fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts); + ast_cli(a->fd, FORMAT2, ast_getformatname(&f->format), f->name, f->exts); count_fmt++; } AST_RWLIST_UNLOCK(&formats); diff --git a/main/format.c b/main/format.c new file mode 100644 index 0000000000000000000000000000000000000000..d77d244a644d4239f10bb304c2470898ce734122 --- /dev/null +++ b/main/format.c @@ -0,0 +1,558 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2010, Digium, Inc. + * + * David Vossel <dvossel@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format API + * + * \author David Vossel <dvossel@digium.com> + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); + +#include "asterisk/_private.h" +#include "asterisk/version.h" +#include "asterisk/format.h" +#include "asterisk/astobj2.h" +#include "asterisk/lock.h" + +/*! This is the container for all the format attribute interfaces. + * An ao2 container was chosen for fast lookup. */ +static struct ao2_container *interfaces; + +/*! This is the lock used to protect the interfaces container. Yes, ao2_containers + * do have their own locking, but we need the capability of performing read/write + * locks on this specific container. */ +static ast_rwlock_t ilock; + +/*! a wrapper is used put interfaces into the ao2 container. */ +struct interface_ao2_wrapper { + enum ast_format_id id; + const struct ast_format_attr_interface *interface; + /*! a read write lock must be used to protect the wrapper instead + * of the ao2 lock. */ + ast_rwlock_t wraplock; +}; + +static int interface_cmp_cb(void *obj, void *arg, int flags) +{ + struct interface_ao2_wrapper *wrapper1 = obj; + struct interface_ao2_wrapper *wrapper2 = arg; + + return (wrapper2->id == wrapper1->id) ? CMP_MATCH | CMP_STOP : 0; +} + +static int interface_hash_cb(const void *obj, const int flags) +{ + const struct interface_ao2_wrapper *wrapper = obj; + return wrapper->id; +} + +static void interface_destroy_cb(void *obj) +{ + struct interface_ao2_wrapper *wrapper = obj; + ast_rwlock_destroy(&wrapper->wraplock); +} + +void ast_format_copy(struct ast_format *dst, const struct ast_format *src) +{ + memcpy(dst, src, sizeof(struct ast_format)); +} + +void ast_format_set_video_mark(struct ast_format *format) +{ + format->fattr.rtp_marker_bit = 1; +} + +int ast_format_get_video_mark(const struct ast_format *format) +{ + return format->fattr.rtp_marker_bit; +} + +static struct interface_ao2_wrapper *find_interface(const struct ast_format *format) +{ + struct interface_ao2_wrapper *wrapper; + struct interface_ao2_wrapper tmp_wrapper = { + .id = format->id, + }; + + ast_rwlock_rdlock(&ilock); + if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) { + ast_rwlock_unlock(&ilock); + return NULL; + } + ast_rwlock_unlock(&ilock); + + return wrapper; +} + +/*! \internal + * \brief set format attributes using an interface + */ +static int format_set_helper(struct ast_format *format, va_list ap) +{ + struct interface_ao2_wrapper *wrapper; + + if (!(wrapper = find_interface(format))) { + ast_log(LOG_WARNING, "Could not find format interface to set.\n"); + return -1; + } + + ast_rwlock_rdlock(&wrapper->wraplock); + if (!wrapper->interface || !wrapper->interface->format_attr_set) { + ast_rwlock_unlock(&wrapper->wraplock); + ao2_ref(wrapper, -1); + return -1; + } + + wrapper->interface->format_attr_set(&format->fattr, ap); + + ast_rwlock_unlock(&wrapper->wraplock); + ao2_ref(wrapper, -1); + + return 0; +} + +struct ast_format *ast_format_append(struct ast_format *format, ... ) +{ + va_list ap; + va_start(ap, format); + format_set_helper(format, ap); + va_end(ap); + + return format; +} + +struct ast_format *ast_format_set(struct ast_format *format, enum ast_format_id id, int set_attributes, ... ) +{ + /* initialize the structure before setting it. */ + ast_format_clear(format); + + format->id = id; + + if (set_attributes) { + va_list ap; + va_start(ap, set_attributes); + format_set_helper(format, ap); + va_end(ap); + } + + return format; +} + +void ast_format_clear(struct ast_format *format) +{ + format->id = 0; + memset(&format->fattr, 0, sizeof(format->fattr)); +} + +/*! \internal + * \brief determine if a list of attribute key value pairs are set on a format + */ +static int format_isset_helper(struct ast_format *format, va_list ap) +{ + int res; + struct interface_ao2_wrapper *wrapper; + struct ast_format tmp = { + .id = format->id, + .fattr = { { 0, }, }, + }; + + if (!(wrapper = find_interface(format))) { + return -1; + } + + ast_rwlock_rdlock(&wrapper->wraplock); + if (!wrapper->interface || + !wrapper->interface->format_attr_set || + !wrapper->interface->format_attr_cmp) { + + ast_rwlock_unlock(&wrapper->wraplock); + ao2_ref(wrapper, -1); + return -1; + } + + wrapper->interface->format_attr_set(&tmp.fattr, ap); + + /* use our tmp structure to tell if the attributes are set or not */ + res = wrapper->interface->format_attr_cmp(&tmp.fattr, &format->fattr); + + ast_rwlock_unlock(&wrapper->wraplock); + ao2_ref(wrapper, -1); + + return (res == AST_FORMAT_CMP_NOT_EQUAL) ? -1 : 0; +} + +int ast_format_isset(struct ast_format *format, ... ) +{ + va_list ap; + int res; + + va_start(ap, format); + res = format_isset_helper(format, ap); + va_end(ap); + return res; +} + + +/*! \internal + * \brief cmp format attributes using an interface + */ +static enum ast_format_cmp_res format_cmp_helper(const struct ast_format *format1, const struct ast_format *format2) +{ + enum ast_format_cmp_res res = AST_FORMAT_CMP_EQUAL; + struct interface_ao2_wrapper *wrapper; + + if (!(wrapper = find_interface(format1))) { + return res; + } + + ast_rwlock_rdlock(&wrapper->wraplock); + if (!wrapper->interface || !wrapper->interface->format_attr_cmp) { + ast_rwlock_unlock(&wrapper->wraplock); + ao2_ref(wrapper, -1); + return res; + } + + res = wrapper->interface->format_attr_cmp(&format1->fattr, &format2->fattr); + + ast_rwlock_unlock(&wrapper->wraplock); + ao2_ref(wrapper, -1); + + return res; +} + +enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2) +{ + if (format1->id != format2->id) { + return AST_FORMAT_CMP_NOT_EQUAL; + } + + return format_cmp_helper(format1, format2); +} + +/*! \internal + * \brief get joint format attributes using an interface + */ +static int format_joint_helper(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result) +{ + int res = 0; + struct interface_ao2_wrapper *wrapper; + + if (!(wrapper = find_interface(format1))) { + /* if no interface is present, we assume formats are joint by id alone */ + return res; + } + + ast_rwlock_rdlock(&wrapper->wraplock); + if (wrapper->interface && wrapper->interface->format_attr_get_joint) { + res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr); + } + ast_rwlock_unlock(&wrapper->wraplock); + + ao2_ref(wrapper, -1); + + return res; +} + +int ast_format_joint(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result) +{ + if (format1->id != format2->id) { + return -1; + } + result->id = format1->id; + return format_joint_helper(format1, format2, result); +} + + +uint64_t ast_format_id_to_old_bitfield(enum ast_format_id id) +{ + switch (id) { + /*! G.723.1 compression */ + case AST_FORMAT_G723_1: + return (1ULL << 0); + /*! GSM compression */ + case AST_FORMAT_GSM: + return (1ULL << 1); + /*! Raw mu-law data (G.711) */ + case AST_FORMAT_ULAW: + return (1ULL << 2); + /*! Raw A-law data (G.711) */ + case AST_FORMAT_ALAW: + return (1ULL << 3); + /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */ + case AST_FORMAT_G726_AAL2: + return (1ULL << 4); + /*! ADPCM (IMA) */ + case AST_FORMAT_ADPCM: + return (1ULL << 5); + /*! Raw 16-bit Signed Linear (8000 Hz) PCM */ + case AST_FORMAT_SLINEAR: + return (1ULL << 6); + /*! LPC10, 180 samples/frame */ + case AST_FORMAT_LPC10: + return (1ULL << 7); + /*! G.729A audio */ + case AST_FORMAT_G729A: + return (1ULL << 8); + /*! SpeeX Free Compression */ + case AST_FORMAT_SPEEX: + return (1ULL << 9); + /*! iLBC Free Compression */ + case AST_FORMAT_ILBC: + return (1ULL << 10); + /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */ + case AST_FORMAT_G726: + return (1ULL << 11); + /*! G.722 */ + case AST_FORMAT_G722: + return (1ULL << 12); + /*! G.722.1 (also known as Siren7, 32kbps assumed) */ + case AST_FORMAT_SIREN7: + return (1ULL << 13); + /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */ + case AST_FORMAT_SIREN14: + return (1ULL << 14); + /*! Raw 16-bit Signed Linear (16000 Hz) PCM */ + case AST_FORMAT_SLINEAR16: + return (1ULL << 15); + /*! G.719 (64 kbps assumed) */ + case AST_FORMAT_G719: + return (1ULL << 32); + /*! SpeeX Wideband (16kHz) Free Compression */ + case AST_FORMAT_SPEEX16: + return (1ULL << 33); + /*! Raw mu-law data (G.711) */ + case AST_FORMAT_TESTLAW: + return (1ULL << 47); + + /*! H.261 Video */ + case AST_FORMAT_H261: + return (1ULL << 18); + /*! H.263 Video */ + case AST_FORMAT_H263: + return (1ULL << 19); + /*! H.263+ Video */ + case AST_FORMAT_H263_PLUS: + return (1ULL << 20); + /*! H.264 Video */ + case AST_FORMAT_H264: + return (1ULL << 21); + /*! MPEG4 Video */ + case AST_FORMAT_MP4_VIDEO: + return (1ULL << 22); + + /*! JPEG Images */ + case AST_FORMAT_JPEG: + return (1ULL << 16); + /*! PNG Images */ + case AST_FORMAT_PNG: + return (1ULL << 17); + + /*! T.140 RED Text format RFC 4103 */ + case AST_FORMAT_T140RED: + return (1ULL << 26); + /*! T.140 Text format - ITU T.140, RFC 4103 */ + case AST_FORMAT_T140: + return (1ULL << 27); + } + + return 0; + +} +uint64_t ast_format_to_old_bitfield(const struct ast_format *format) +{ + return ast_format_id_to_old_bitfield(format->id); +} + +struct ast_format *ast_format_from_old_bitfield(struct ast_format *dst, uint64_t src) +{ + switch (src) { + /*! G.723.1 compression */ + case (1ULL << 0): + return ast_format_set(dst, AST_FORMAT_G723_1, 0); + /*! GSM compression */ + case (1ULL << 1): + return ast_format_set(dst, AST_FORMAT_GSM, 0); + /*! Raw mu-law data (G.711) */ + case (1ULL << 2): + return ast_format_set(dst, AST_FORMAT_ULAW, 0); + /*! Raw A-law data (G.711) */ + case (1ULL << 3): + return ast_format_set(dst, AST_FORMAT_ALAW, 0); + /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */ + case (1ULL << 4): + return ast_format_set(dst, AST_FORMAT_G726_AAL2, 0); + /*! ADPCM (IMA) */ + case (1ULL << 5): + return ast_format_set(dst, AST_FORMAT_ADPCM, 0); + /*! Raw 16-bit Signed Linear (8000 Hz) PCM */ + case (1ULL << 6): + return ast_format_set(dst, AST_FORMAT_SLINEAR, 0); + /*! LPC10, 180 samples/frame */ + case (1ULL << 7): + return ast_format_set(dst, AST_FORMAT_LPC10, 0); + /*! G.729A audio */ + case (1ULL << 8): + return ast_format_set(dst, AST_FORMAT_G729A, 0); + /*! SpeeX Free Compression */ + case (1ULL << 9): + return ast_format_set(dst, AST_FORMAT_SPEEX, 0); + /*! iLBC Free Compression */ + case (1ULL << 10): + return ast_format_set(dst, AST_FORMAT_ILBC, 0); + /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */ + case (1ULL << 11): + return ast_format_set(dst, AST_FORMAT_G726, 0); + /*! G.722 */ + case (1ULL << 12): + return ast_format_set(dst, AST_FORMAT_G722, 0); + /*! G.722.1 (also known as Siren7, 32kbps assumed) */ + case (1ULL << 13): + return ast_format_set(dst, AST_FORMAT_SIREN7, 0); + /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */ + case (1ULL << 14): + return ast_format_set(dst, AST_FORMAT_SIREN14, 0); + /*! Raw 16-bit Signed Linear (16000 Hz) PCM */ + case (1ULL << 15): + return ast_format_set(dst, AST_FORMAT_SLINEAR16, 0); + /*! G.719 (64 kbps assumed) */ + case (1ULL << 32): + return ast_format_set(dst, AST_FORMAT_G719, 0); + /*! SpeeX Wideband (16kHz) Free Compression */ + case (1ULL << 33): + return ast_format_set(dst, AST_FORMAT_SPEEX16, 0); + /*! Raw mu-law data (G.711) */ + case (1ULL << 47): + return ast_format_set(dst, AST_FORMAT_TESTLAW, 0); + + /*! H.261 Video */ + case (1ULL << 18): + return ast_format_set(dst, AST_FORMAT_H261, 0); + /*! H.263 Video */ + case (1ULL << 19): + return ast_format_set(dst, AST_FORMAT_H263, 0); + /*! H.263+ Video */ + case (1ULL << 20): + return ast_format_set(dst, AST_FORMAT_H263_PLUS, 0); + /*! H.264 Video */ + case (1ULL << 21): + return ast_format_set(dst, AST_FORMAT_H264, 0); + /*! MPEG4 Video */ + case (1ULL << 22): + return ast_format_set(dst, AST_FORMAT_MP4_VIDEO, 0); + + /*! JPEG Images */ + case (1ULL << 16): + return ast_format_set(dst, AST_FORMAT_JPEG, 0); + /*! PNG Images */ + case (1ULL << 17): + return ast_format_set(dst, AST_FORMAT_PNG, 0); + + /*! T.140 RED Text format RFC 4103 */ + case (1ULL << 26): + return ast_format_set(dst, AST_FORMAT_T140RED, 0); + /*! T.140 Text format - ITU T.140, RFC 4103 */ + case (1ULL << 27): + return ast_format_set(dst, AST_FORMAT_T140, 0); + } + ast_format_clear(dst); + return NULL; +} + +enum ast_format_id ast_format_id_from_old_bitfield(uint64_t src) +{ + struct ast_format dst; + if (ast_format_from_old_bitfield(&dst, src)) { + return dst.id; + } + return 0; +} + +int ast_format_attr_init() +{ + if (ast_rwlock_init(&ilock)) { + return -1; + } + if (!(interfaces = ao2_container_alloc(283, interface_hash_cb, interface_cmp_cb))) { + ast_rwlock_destroy(&ilock); + return -1; + } + return 0; +} + +int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interface) +{ + struct interface_ao2_wrapper *wrapper; + struct interface_ao2_wrapper tmp_wrapper = { + .id = interface->id, + }; + + /* check for duplicates first*/ + ast_rwlock_wrlock(&ilock); + if ((wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) { + ast_rwlock_unlock(&ilock); + ast_log(LOG_WARNING, "Can not register attribute interface for format id %d, interface already exists.\n", interface->id); + ao2_ref(wrapper, -1); + return -1; + } + ast_rwlock_unlock(&ilock); + + if (!(wrapper = ao2_alloc(sizeof(*wrapper), interface_destroy_cb))) { + return -1; + } + + wrapper->interface = interface; + wrapper->id = interface->id; + ast_rwlock_init(&wrapper->wraplock); + + /* use the write lock whenever the interface container is modified */ + ast_rwlock_wrlock(&ilock); + ao2_link(interfaces, wrapper); + ast_rwlock_unlock(&ilock); + + ao2_ref(wrapper, -1); + + return 0; +} + +int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *interface) +{ + struct interface_ao2_wrapper *wrapper; + struct interface_ao2_wrapper tmp_wrapper = { + .id = interface->id, + }; + + /* use the write lock whenever the interface container is modified */ + ast_rwlock_wrlock(&ilock); + if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_UNLINK | OBJ_NOLOCK)))) { + ast_rwlock_unlock(&ilock); + return -1; + } + ast_rwlock_unlock(&ilock); + + ast_rwlock_wrlock(&wrapper->wraplock); + wrapper->interface = NULL; + ast_rwlock_unlock(&wrapper->wraplock); + + ao2_ref(wrapper, -1); + + return 0; +} diff --git a/main/format_cap.c b/main/format_cap.c new file mode 100644 index 0000000000000000000000000000000000000000..1d566050f7fd22372e97be9d0ff7f31c3bb12b84 --- /dev/null +++ b/main/format_cap.c @@ -0,0 +1,545 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2010, Digium, Inc. + * + * David Vossel <dvossel@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format Capability API + * + * \author David Vossel <dvossel@digium.com> + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); + +#include "asterisk/_private.h" +#include "asterisk/version.h" +#include "asterisk/format.h" +#include "asterisk/format_cap.h" +#include "asterisk/frame.h" +#include "asterisk/astobj2.h" +#include "asterisk/utils.h" + + +struct ast_format_cap { + /* The capabilities structure is just an ao2 container of ast_formats */ + struct ao2_container *formats; + struct ao2_iterator it; + int nolock; +}; + +/*! format exists within capabilities structure if it is identical to + * another format, or if the format is a proper subset of another format. */ +static int cmp_cb(void *obj, void *arg, int flags) +{ + struct ast_format *format1 = arg; + struct ast_format *format2 = obj; + enum ast_format_cmp_res res = ast_format_cmp(format1, format2); + + return ((res == AST_FORMAT_CMP_EQUAL) || + (res == AST_FORMAT_CMP_SUBSET)) ? + CMP_MATCH | CMP_STOP : + 0; +} + +static int hash_cb(const void *obj, const int flags) +{ + const struct ast_format *format = obj; + return format->id; +} + +static struct ast_format_cap *cap_alloc_helper(int nolock) +{ + struct ast_format_cap *cap = ast_calloc(1, sizeof(*cap)); + + if (!cap) { + return NULL; + } + cap->nolock = nolock ? OBJ_NOLOCK : 0; + if (!(cap->formats = ao2_container_alloc(283, hash_cb, cmp_cb))) { + ast_free(cap); + return NULL; + } + + return cap; +} + +struct ast_format_cap *ast_format_cap_alloc_nolock(void) +{ + return cap_alloc_helper(1); +} + +struct ast_format_cap *ast_format_cap_alloc(void) +{ + return cap_alloc_helper(0); +} + +void *ast_format_cap_destroy(struct ast_format_cap *cap) +{ + if (!cap) { + return NULL; + } + ao2_ref(cap->formats, -1); + ast_free(cap); + return NULL; +} + +void ast_format_cap_add(struct ast_format_cap *cap, struct ast_format *format) +{ + struct ast_format *fnew; + + if (!format || !format->id) { + return; + } + if (!(fnew = ao2_alloc(sizeof(struct ast_format), NULL))) { + return; + } + ast_format_copy(fnew, format); + if (cap->nolock) { + ao2_link_nolock(cap->formats, fnew); + } else { + ao2_link(cap->formats, fnew); + } + ao2_ref(fnew, -1); +} + +void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type) +{ + int x; + size_t f_len = 0; + struct ast_format tmp_fmt; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + for (x = 0; x < f_len; x++) { + if (AST_FORMAT_GET_TYPE(f_list[x].id) == type) { + ast_format_cap_add(cap, ast_format_set(&tmp_fmt, f_list[x].id, 0)); + } + } +} + +void ast_format_cap_add_all(struct ast_format_cap *cap) +{ + int x; + size_t f_len = 0; + struct ast_format tmp_fmt; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + for (x = 0; x < f_len; x++) { + ast_format_cap_add(cap, ast_format_set(&tmp_fmt, f_list[x].id, 0)); + } +} + +static int append_cb(void *obj, void *arg, int flag) +{ + struct ast_format_cap *result = (struct ast_format_cap *) arg; + struct ast_format *format = (struct ast_format *) obj; + + if (!ast_format_cap_iscompatible(result, format)) { + ast_format_cap_add(result, format); + } + + return 0; +} + +void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src) +{ + ao2_callback(src->formats, OBJ_NODATA | src->nolock, append_cb, dst); +} + +static int copy_cb(void *obj, void *arg, int flag) +{ + struct ast_format_cap *result = (struct ast_format_cap *) arg; + struct ast_format *format = (struct ast_format *) obj; + + ast_format_cap_add(result, format); + return 0; +} + +void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src) +{ + ast_format_cap_remove_all(dst); + ao2_callback(src->formats, OBJ_NODATA | src->nolock, copy_cb, dst); +} + +struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *cap) +{ + struct ast_format_cap *dst; + if (cap->nolock) { + dst = ast_format_cap_alloc_nolock(); + } else { + dst = ast_format_cap_alloc(); + } + if (!dst) { + return NULL; + } + ao2_callback(cap->formats, OBJ_NODATA | cap->nolock, copy_cb, dst); + return dst; +} + +int ast_format_cap_is_empty(const struct ast_format_cap *cap) +{ + if (!cap) { + return 1; + } + return ao2_container_count(cap->formats) == 0 ? 1 : 0; +} + +static int find_exact_cb(void *obj, void *arg, int flag) +{ + struct ast_format *format1 = (struct ast_format *) arg; + struct ast_format *format2 = (struct ast_format *) obj; + + return (ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL) ? CMP_MATCH : 0; +} + +int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format) +{ + struct ast_format *fremove; + fremove = ao2_callback(cap->formats, OBJ_POINTER | OBJ_UNLINK | cap->nolock, find_exact_cb, format); + + if (fremove) { + ao2_ref(fremove, -1); + return 0; + } + + return -1; +} + +struct multiple_by_id_data { + struct ast_format *format; + int match_found; +}; + +static int multiple_by_id_cb(void *obj, void *arg, int flag) +{ + struct multiple_by_id_data *data = arg; + struct ast_format *format = obj; + int res; + + res = (format->id == data->format->id) ? CMP_MATCH : 0; + if (res) { + data->match_found = 1; + } + + return res; +} + +int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id) +{ + struct ast_format format = { + .id = id, + }; + struct multiple_by_id_data data = { + .format = &format, + .match_found = 0, + }; + + ao2_callback(cap->formats, + OBJ_NODATA | cap->nolock | OBJ_MULTIPLE | OBJ_UNLINK, + multiple_by_id_cb, + &data); + + /* match_found will be set if at least one item was removed */ + if (data.match_found) { + return 0; + } + + return -1; +} + +static int multiple_by_type_cb(void *obj, void *arg, int flag) +{ + int *type = arg; + struct ast_format *format = obj; + return ((AST_FORMAT_GET_TYPE(format->id)) == *type) ? CMP_MATCH : 0; +} + +void ast_format_cap_remove_bytype(struct ast_format_cap *cap, enum ast_format_type type) +{ + ao2_callback(cap->formats, + OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE | cap->nolock, + multiple_by_type_cb, + &type); +} + +void ast_format_cap_remove_all(struct ast_format_cap *cap) +{ + ao2_callback(cap->formats, OBJ_NODATA | cap->nolock | OBJ_MULTIPLE | OBJ_UNLINK, NULL, NULL); +} + +void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format) +{ + ast_format_cap_remove_all(cap); + ast_format_cap_add(cap, format); +} + +int ast_format_cap_iscompatible(const struct ast_format_cap *cap, const struct ast_format *format) +{ + struct ast_format *f; + struct ast_format_cap *tmp_cap = (struct ast_format_cap *) cap; + f = ao2_find(tmp_cap->formats, (struct ast_format *) format, OBJ_POINTER | tmp_cap->nolock); + + if (f) { + ao2_ref(f, -1); + return 1; + } + + return 0; +} + +/*! \internal + * \brief this struct is just used for the ast_format_cap_joint function so we can provide + * both a format and a result ast_format_cap structure as arguments to the find_joint_cb + * ao2 callback function. + */ +struct find_joint_data { + /*! format to compare to for joint capabilities */ + struct ast_format *format; + /*! if joint formmat exists with above format, add it to the result container */ + struct ast_format_cap *joint_cap; + int joint_found; +}; + +static int find_joint_cb(void *obj, void *arg, int flag) +{ + struct ast_format *format = obj; + struct find_joint_data *data = arg; + + struct ast_format tmp = { 0, }; + if (!ast_format_joint(format, data->format, &tmp)) { + if (data->joint_cap) { + ast_format_cap_add(data->joint_cap, &tmp); + } + data->joint_found++; + } + + return 0; +} + +int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) +{ + struct ao2_iterator it; + struct ast_format *tmp; + struct find_joint_data data = { + .joint_found = 0, + .joint_cap = NULL, + }; + + it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); + while ((tmp = ao2_iterator_next(&it))) { + data.format = tmp; + ao2_callback(cap2->formats, + OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, + find_joint_cb, + &data); + ao2_ref(tmp, -1); + } + ao2_iterator_destroy(&it); + + return data.joint_found ? 1 : 0; +} + +int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) +{ + struct ao2_iterator it; + struct ast_format *tmp; + + if (ao2_container_count(cap1->formats) != ao2_container_count(cap2->formats)) { + return 0; /* if they are not the same size, they are not identical */ + } + + it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); + while ((tmp = ao2_iterator_next(&it))) { + if (!ast_format_cap_iscompatible(cap2, tmp)) { + ao2_ref(tmp, -1); + ao2_iterator_destroy(&it); + return 0; + } + ao2_ref(tmp, -1); + } + ao2_iterator_destroy(&it); + + return 1; +} + +struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) +{ + struct ao2_iterator it; + struct ast_format_cap *result = ast_format_cap_alloc_nolock(); + struct ast_format *tmp; + struct find_joint_data data = { + .joint_found = 0, + .joint_cap = result, + }; + if (!result) { + return NULL; + } + + it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); + while ((tmp = ao2_iterator_next(&it))) { + data.format = tmp; + ao2_callback(cap2->formats, + OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, + find_joint_cb, + &data); + ao2_ref(tmp, -1); + } + ao2_iterator_destroy(&it); + + if (ao2_container_count(result->formats)) { + return result; + } + + result = ast_format_cap_destroy(result); + return NULL; +} + +int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result) +{ + struct ao2_iterator it; + struct ast_format *tmp; + struct find_joint_data data = { + .joint_cap = result, + .joint_found = 0, + }; + + ast_format_cap_remove_all(result); + it = ao2_iterator_init(cap1->formats, cap2->nolock ? AO2_ITERATOR_DONTLOCK : 0); + while ((tmp = ao2_iterator_next(&it))) { + data.format = tmp; + ao2_callback(cap2->formats, + OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, + find_joint_cb, + &data); + ao2_ref(tmp, -1); + } + ao2_iterator_destroy(&it); + + return ao2_container_count(result->formats) ? 1 : 0; +} + +struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype) +{ + struct ao2_iterator it; + struct ast_format_cap *result = ast_format_cap_alloc_nolock(); + struct ast_format *tmp; + + if (!result) { + return NULL; + } + + /* for each format in cap1, see if that format is + * compatible with cap2. If so copy it to the result */ + it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); + while ((tmp = ao2_iterator_next(&it))) { + if (AST_FORMAT_GET_TYPE(tmp->id) == ftype) { + /* copy format */ + ast_format_cap_add(result, tmp); + } + ao2_ref(tmp, -1); + } + ao2_iterator_destroy(&it); + + if (ao2_container_count(result->formats)) { + return result; + } + result = ast_format_cap_destroy(result); + + /* Remember to always free the NULL before returning it. */ + ast_free(NULL); + return NULL; +} + + +int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type) +{ + struct ao2_iterator it; + struct ast_format *tmp; + + it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); + while ((tmp = ao2_iterator_next(&it))) { + if (AST_FORMAT_GET_TYPE(tmp->id) == type) { + ao2_ref(tmp, -1); + ao2_iterator_destroy(&it); + return 1; + } + ao2_ref(tmp, -1); + } + ao2_iterator_destroy(&it); + + return 0; +} + +void ast_format_cap_iter_start(struct ast_format_cap *cap) +{ + if (!cap->nolock) { + ao2_lock(cap->formats); + } + cap->it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); +} + +void ast_format_cap_iter_end(struct ast_format_cap *cap) +{ + ao2_iterator_destroy(&cap->it); + if (!cap->nolock) { + ao2_unlock(cap->formats); + } +} + +int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format) +{ + struct ast_format *tmp = ao2_iterator_next(&cap->it); + + if (!tmp) { + return -1; + } + ast_format_copy(format, tmp); + ao2_ref(tmp, -1); + + return 0; +} + +uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap) +{ + uint64_t res = 0; + struct ao2_iterator it; + struct ast_format *tmp; + + it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); + while ((tmp = ao2_iterator_next(&it))) { + res |= ast_format_to_old_bitfield(tmp); + ao2_ref(tmp, -1); + } + ao2_iterator_destroy(&it); + return res; +} + +void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src) +{ + uint64_t tmp = 0; + int x; + struct ast_format tmp_format = { 0, }; + + ast_format_cap_remove_all(dst); + for (x = 0; x < 64; x++) { + tmp = (1ULL << x); + if (tmp & src) { + ast_format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp)); + } + } +} diff --git a/main/format_pref.c b/main/format_pref.c new file mode 100644 index 0000000000000000000000000000000000000000..26801b648d0268068f03c34cbc3c2f5bc3d78ec4 --- /dev/null +++ b/main/format_pref.c @@ -0,0 +1,320 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2010, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format Preference API + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); + +#include "asterisk/_private.h" +#include "asterisk/version.h" +#include "asterisk/frame.h" +#include "asterisk/channel.h" +#include "asterisk/utils.h" + +void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right) +{ + size_t f_len; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + int x, differential = (int) 'A', mem; + char *from, *to; + + /* TODO re-evaluate this function. It is using the order of the formats specified + * in the global format list in a way that may not be safe. */ + if (right) { + from = pref->order; + to = buf; + mem = size; + } else { + to = pref->order; + from = buf; + mem = AST_CODEC_PREF_SIZE; + } + + memset(to, 0, mem); + for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { + if (!from[x]) { + break; + } + to[x] = right ? (from[x] + differential) : (from[x] - differential); + if (!right && to[x] && (to[x] < f_len)) { + ast_format_set(&pref->formats[x], f_list[to[x]-1].id , 0); + } + } +} + +int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size) +{ + int x; + struct ast_format format; + size_t total_len, slen; + char *formatname; + + memset(buf, 0, size); + total_len = size; + buf[0] = '('; + total_len--; + for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { + if (total_len <= 0) + break; + if (!(ast_codec_pref_index(pref, x, &format))) + break; + if ((formatname = ast_getformatname(&format))) { + slen = strlen(formatname); + if (slen > total_len) + break; + strncat(buf, formatname, total_len - 1); /* safe */ + total_len -= slen; + } + if (total_len && x < AST_CODEC_PREF_SIZE - 1 && ast_codec_pref_index(pref, x + 1, &format)) { + strncat(buf, "|", total_len - 1); /* safe */ + total_len--; + } + } + if (total_len) { + strncat(buf, ")", total_len - 1); /* safe */ + total_len--; + } + + return size - total_len; +} + +struct ast_format *ast_codec_pref_index(struct ast_codec_pref *pref, int idx, struct ast_format *result) +{ + if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->formats[idx].id) { + ast_format_copy(result, &pref->formats[idx]); + } else { + ast_format_clear(result); + return NULL; + } + + return result; +} + +/*! \brief Remove codec from pref list */ +void ast_codec_pref_remove(struct ast_codec_pref *pref, struct ast_format *format) +{ + struct ast_codec_pref oldorder; + int x, y = 0; + size_t f_len = 0; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + if (!pref->order[0]) + return; + + memcpy(&oldorder, pref, sizeof(oldorder)); + memset(pref, 0, sizeof(*pref)); + + for (x = 0; x < f_len; x++) { + if (!oldorder.order[x]) + break; + if (f_list[oldorder.order[x]-1].id != format->id) { + pref->order[y] = oldorder.order[x]; + ast_format_copy(&pref->formats[y], &oldorder.formats[x]); + pref->framing[y++] = oldorder.framing[x]; + } + } +} + +/*! \brief Append codec to list */ +int ast_codec_pref_append(struct ast_codec_pref *pref, struct ast_format *format) +{ + int x, newindex = 0; + size_t f_len = 0; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + ast_codec_pref_remove(pref, format); + + for (x = 0; x < f_len; x++) { + if (f_list[x].id == format->id) { + newindex = x + 1; + break; + } + } + + if (newindex) { + for (x = 0; x < f_len; x++) { + if (!pref->order[x]) { + pref->order[x] = newindex; + ast_format_copy(&pref->formats[x], format); + break; + } + } + } + + return x; +} + +/*! \brief Prepend codec to list */ +void ast_codec_pref_prepend(struct ast_codec_pref *pref, struct ast_format *format, int only_if_existing) +{ + int x, newindex = 0; + size_t f_len = 0; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + /* First step is to get the codecs "index number" */ + for (x = 0; x < f_len; x++) { + if (f_list[x].id == format->id) { + newindex = x + 1; + break; + } + } + /* Done if its unknown */ + if (!newindex) + return; + + /* Now find any existing occurrence, or the end */ + for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { + if (!pref->order[x] || pref->order[x] == newindex) + break; + } + + if (only_if_existing && !pref->order[x]) + return; + + /* Move down to make space to insert - either all the way to the end, + or as far as the existing location (which will be overwritten) */ + for (; x > 0; x--) { + pref->order[x] = pref->order[x - 1]; + pref->framing[x] = pref->framing[x - 1]; + ast_format_copy(&pref->formats[x], &pref->formats[x - 1]); + } + + /* And insert the new entry */ + pref->order[0] = newindex; + pref->framing[0] = 0; /* ? */ + ast_format_copy(&pref->formats[0], format); +} + +/*! \brief Set packet size for codec */ +int ast_codec_pref_setsize(struct ast_codec_pref *pref, struct ast_format *format, int framems) +{ + int x, idx = -1; + size_t f_len = 0; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + for (x = 0; x < f_len; x++) { + if (f_list[x].id == format->id) { + idx = x; + break; + } + } + + if (idx < 0) + return -1; + + /* size validation */ + if (!framems) + framems = f_list[idx].def_ms; + + if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms) /* avoid division by zero */ + framems -= framems % f_list[idx].inc_ms; + + if (framems < f_list[idx].min_ms) + framems = f_list[idx].min_ms; + + if (framems > f_list[idx].max_ms) + framems = f_list[idx].max_ms; + + for (x = 0; x < f_len; x++) { + if (pref->order[x] == (idx + 1)) { + pref->framing[x] = framems; + break; + } + } + + return x; +} + +/*! \brief Get packet size for codec */ +struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format) +{ + int x, idx = -1, framems = 0; + struct ast_format_list fmt = { 0, }; + size_t f_len = 0; + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + for (x = 0; x < f_len; x++) { + if (f_list[x].id == format->id) { + fmt = f_list[x]; + idx = x; + break; + } + } + + for (x = 0; x < f_len; x++) { + if (pref->order[x] == (idx + 1)) { + framems = pref->framing[x]; + break; + } + } + + /* size validation */ + if (!framems) + framems = f_list[idx].def_ms; + + if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms) /* avoid division by zero */ + framems -= framems % f_list[idx].inc_ms; + + if (framems < f_list[idx].min_ms) + framems = f_list[idx].min_ms; + + if (framems > f_list[idx].max_ms) + framems = f_list[idx].max_ms; + + fmt.cur_ms = framems; + + return fmt; +} + +/*! \brief Pick a codec */ +struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result) +{ + int x, slot, found; + size_t f_len = 0; + struct ast_format tmp_fmt; + + const struct ast_format_list *f_list = ast_get_format_list(&f_len); + + ast_format_clear(result); + + for (x = 0; x < f_len; x++) { + slot = pref->order[x]; + + if (!slot) + break; + if (ast_format_cap_iscompatible(cap, ast_format_set(&tmp_fmt, f_list[slot-1].id, 0))) { + found = 1; /*format is found and stored in tmp_fmt */ + break; + } + } + if (found && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO)) { + ast_format_copy(result, &tmp_fmt); + return result; + } + + ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec"); + + return find_best ? ast_best_codec(cap, result) : NULL; +} + + diff --git a/main/frame.c b/main/frame.c index 9f599a9917937062e3e381861ca186598f2bbba7..840fa4b75da4e78654a28941ec90b9acf5a501e4 100644 --- a/main/frame.c +++ b/main/frame.c @@ -80,7 +80,7 @@ enum frame_type { struct ast_smoother { int size; - format_t format; + struct ast_format format; int flags; float samplesperbyte; unsigned int opt_needs_swap:1; @@ -207,12 +207,12 @@ int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap) ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n"); return -1; } - if (!s->format) { - s->format = f->subclass.codec; + if (!s->format.id) { + ast_format_copy(&s->format, &f->subclass.format); s->samplesperbyte = (float)f->samples / (float)f->datalen; - } else if (s->format != f->subclass.codec) { + } else if (ast_format_cmp(&s->format, &f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { ast_log(LOG_WARNING, "Smoother was working on %s format frames, now trying to feed %s?\n", - ast_getformatname(s->format), ast_getformatname(f->subclass.codec)); + ast_getformatname(&s->format), ast_getformatname(&f->subclass.format)); return -1; } if (s->len + f->datalen > SMOOTHER_SIZE) { @@ -263,7 +263,7 @@ struct ast_frame *ast_smoother_read(struct ast_smoother *s) len = s->len; /* Make frame */ s->f.frametype = AST_FRAME_VOICE; - s->f.subclass.codec = s->format; + ast_format_copy(&s->f.subclass.format, &s->format); s->f.data.ptr = s->framedata + AST_FRIENDLY_OFFSET; s->f.offset = AST_FRIENDLY_OFFSET; s->f.datalen = len; @@ -280,7 +280,7 @@ struct ast_frame *ast_smoother_read(struct ast_smoother *s) memmove(s->data, s->data + len, s->len); if (!ast_tvzero(s->delivery)) { /* If we have delivery time, increment it, otherwise, leave it at 0 */ - s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, ast_format_rate(s->format))); + s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, ast_format_rate(&s->format))); } } /* Return frame */ @@ -408,7 +408,7 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr) return NULL; } out->frametype = fr->frametype; - out->subclass.codec = fr->subclass.codec; + ast_format_copy(&out->subclass.format, &fr->subclass.format); out->datalen = fr->datalen; out->samples = fr->samples; out->offset = fr->offset; @@ -515,7 +515,7 @@ struct ast_frame *ast_frdup(const struct ast_frame *f) } out->frametype = f->frametype; - out->subclass.codec = f->subclass.codec; + ast_format_copy(&out->subclass.format, &f->subclass.format); out->datalen = f->datalen; out->samples = f->samples; out->delivery = f->delivery; @@ -566,12 +566,12 @@ const struct ast_format_list *ast_get_format_list(size_t *size) return AST_FORMAT_LIST; } -char* ast_getformatname(format_t format) +char* ast_getformatname(struct ast_format *format) { int x; char *ret = "unknown"; for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (AST_FORMAT_LIST[x].bits == format) { + if (AST_FORMAT_LIST[x].id == format->id) { ret = AST_FORMAT_LIST[x].name; break; } @@ -579,21 +579,23 @@ char* ast_getformatname(format_t format) return ret; } -char *ast_getformatname_multiple(char *buf, size_t size, format_t format) +char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap) { int x; unsigned len; char *start, *end = buf; + struct ast_format tmp_fmt; if (!size) return buf; - snprintf(end, size, "0x%llx (", (unsigned long long) format); + snprintf(end, size, "("); len = strlen(end); end += len; size -= len; start = end; for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (AST_FORMAT_LIST[x].bits & format) { + ast_format_set(&tmp_fmt, AST_FORMAT_LIST[x].id, 0); + if (ast_format_cap_iscompatible(cap, &tmp_fmt)) { snprintf(end, size, "%s|", AST_FORMAT_LIST[x].name); len = strlen(end); end += len; @@ -629,31 +631,28 @@ static const char *ast_expand_codec_alias(const char *in) return in; } -format_t ast_getformatbyname(const char *name) +struct ast_format *ast_getformatbyname(const char *name, struct ast_format *result) { - int x, all; - format_t format = 0; + int x; - all = strcasecmp(name, "all") ? 0 : 1; for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (all || - !strcasecmp(AST_FORMAT_LIST[x].name,name) || - !strcasecmp(AST_FORMAT_LIST[x].name, ast_expand_codec_alias(name))) { - format |= AST_FORMAT_LIST[x].bits; - if (!all) - break; + if (!strcasecmp(AST_FORMAT_LIST[x].name,name) || + !strcasecmp(AST_FORMAT_LIST[x].name, ast_expand_codec_alias(name))) { + + ast_format_set(result, AST_FORMAT_LIST[x].id, 0); + return result; } } - return format; + return NULL; } -char *ast_codec2str(format_t codec) +char *ast_codec2str(struct ast_format *format) { int x; char *ret = "unknown"; for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (AST_FORMAT_LIST[x].bits == codec) { + if (AST_FORMAT_LIST[x].id == format->id) { ret = AST_FORMAT_LIST[x].desc; break; } @@ -663,8 +662,7 @@ char *ast_codec2str(format_t codec) static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - int i, found=0; - char hex[25]; + int x, found=0; switch (cmd) { case CLI_INIT: @@ -684,25 +682,25 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args * ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n" "\tIt does not indicate anything about your configuration.\n"); - ast_cli(a->fd, "%19s %9s %20s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESCRIPTION"); + ast_cli(a->fd, "%19s %8s %8s %s\n","ID","TYPE","NAME","DESCRIPTION"); ast_cli(a->fd, "-----------------------------------------------------------------------------------\n"); - for (i = 0; i < 63; i++) { + for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { if (a->argc == 4) { if (!strcasecmp(a->argv[3], "audio")) { - if (!((1LL << i) & AST_FORMAT_AUDIO_MASK)) { + if (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) != AST_FORMAT_TYPE_AUDIO) { continue; } } else if (!strcasecmp(a->argv[3], "video")) { - if (!((1LL << i) & AST_FORMAT_VIDEO_MASK)) { + if (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) != AST_FORMAT_TYPE_VIDEO) { continue; } } else if (!strcasecmp(a->argv[3], "image")) { - if (i != 16 && i != 17) { + if (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) != AST_FORMAT_TYPE_IMAGE) { continue; } } else if (!strcasecmp(a->argv[3], "text")) { - if (!((1LL << i) & AST_FORMAT_TEXT_MASK)) { + if (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) != AST_FORMAT_TYPE_TEXT) { continue; } } else { @@ -710,14 +708,15 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args * } } - snprintf(hex, sizeof(hex), "(0x%llx)", 1LL << i); - ast_cli(a->fd, "%19llu (1 << %2d) %20s %5s %8s (%s)\n", 1LL << i, i, hex, - ((1LL << i) & AST_FORMAT_AUDIO_MASK) ? "audio" : - i == 16 || i == 17 ? "image" : - ((1LL << i) & AST_FORMAT_VIDEO_MASK) ? "video" : - ((1LL << i) & AST_FORMAT_TEXT_MASK) ? "text" : + ast_cli(a->fd, "%19u %5s %8s (%s)\n", + AST_FORMAT_LIST[x].id, + (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) == AST_FORMAT_TYPE_AUDIO) ? "audio" : + (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) == AST_FORMAT_TYPE_TEXT) ? "image" : + (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) == AST_FORMAT_TYPE_VIDEO) ? "video" : + (AST_FORMAT_GET_TYPE(AST_FORMAT_LIST[x].id) == AST_FORMAT_TYPE_TEXT) ? "text" : "(unk)", - ast_getformatname(1LL << i), ast_codec2str(1LL << i)); + AST_FORMAT_LIST[x].name, + AST_FORMAT_LIST[x].desc); found = 1; } @@ -730,9 +729,9 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args * static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - format_t codec; - int i, found = 0; - long long type_punned_codec; + enum ast_format_id format_id; + int x, found = 0; + int type_punned_codec; switch (cmd) { case CLI_INIT: @@ -748,19 +747,21 @@ static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args if (a->argc != 4) return CLI_SHOWUSAGE; - if (sscanf(a->argv[3], "%30lld", &type_punned_codec) != 1) { + if (sscanf(a->argv[3], "%30d", &type_punned_codec) != 1) { return CLI_SHOWUSAGE; } - codec = type_punned_codec; + format_id = type_punned_codec; - for (i = 0; i < 63; i++) - if (codec & (1LL << i)) { + for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { + if (AST_FORMAT_LIST[x].id == format_id) { found = 1; - ast_cli(a->fd, "%11llu (1 << %2d) %s\n", 1LL << i, i, ast_codec2str(1LL << i)); + ast_cli(a->fd, "%11u %s\n", (unsigned int) format_id, AST_FORMAT_LIST[x].desc); + break; } + } if (!found) - ast_cli(a->fd, "Codec %lld not found\n", (long long) codec); + ast_cli(a->fd, "Codec %d not found\n", format_id); return CLI_SUCCESS; } @@ -896,7 +897,7 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix) break; case AST_FRAME_IMAGE: strcpy(ftype, "Image"); - snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass.codec)); + snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(&f->subclass.format)); break; case AST_FRAME_HTML: strcpy(ftype, "HTML"); @@ -984,271 +985,11 @@ int init_framer(void) return 0; } -void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right) -{ - int x, differential = (int) 'A', mem; - char *from, *to; - - if (right) { - from = pref->order; - to = buf; - mem = size; - } else { - to = pref->order; - from = buf; - mem = sizeof(format_t) * 8; - } - - memset(to, 0, mem); - for (x = 0; x < sizeof(format_t) * 8; x++) { - if (!from[x]) - break; - to[x] = right ? (from[x] + differential) : (from[x] - differential); - } -} - -int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size) -{ - int x; - format_t codec; - size_t total_len, slen; - char *formatname; - - memset(buf, 0, size); - total_len = size; - buf[0] = '('; - total_len--; - for (x = 0; x < sizeof(format_t) * 8; x++) { - if (total_len <= 0) - break; - if (!(codec = ast_codec_pref_index(pref,x))) - break; - if ((formatname = ast_getformatname(codec))) { - slen = strlen(formatname); - if (slen > total_len) - break; - strncat(buf, formatname, total_len - 1); /* safe */ - total_len -= slen; - } - if (total_len && x < sizeof(format_t) * 8 - 1 && ast_codec_pref_index(pref, x + 1)) { - strncat(buf, "|", total_len - 1); /* safe */ - total_len--; - } - } - if (total_len) { - strncat(buf, ")", total_len - 1); /* safe */ - total_len--; - } - - return size - total_len; -} - -format_t ast_codec_pref_index(struct ast_codec_pref *pref, int idx) -{ - int slot = 0; - - if ((idx >= 0) && (idx < sizeof(pref->order))) { - slot = pref->order[idx]; - } - - return slot ? AST_FORMAT_LIST[slot - 1].bits : 0; -} - -/*! \brief Remove codec from pref list */ -void ast_codec_pref_remove(struct ast_codec_pref *pref, format_t format) -{ - struct ast_codec_pref oldorder; - int x, y = 0; - int slot; - int size; - - if (!pref->order[0]) - return; - - memcpy(&oldorder, pref, sizeof(oldorder)); - memset(pref, 0, sizeof(*pref)); - - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - slot = oldorder.order[x]; - size = oldorder.framing[x]; - if (! slot) - break; - if (AST_FORMAT_LIST[slot-1].bits != format) { - pref->order[y] = slot; - pref->framing[y++] = size; - } - } -} - -/*! \brief Append codec to list */ -int ast_codec_pref_append(struct ast_codec_pref *pref, format_t format) -{ - int x, newindex = 0; - - ast_codec_pref_remove(pref, format); - - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (AST_FORMAT_LIST[x].bits == format) { - newindex = x + 1; - break; - } - } - - if (newindex) { - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (!pref->order[x]) { - pref->order[x] = newindex; - break; - } - } - } - - return x; -} - -/*! \brief Prepend codec to list */ -void ast_codec_pref_prepend(struct ast_codec_pref *pref, format_t format, int only_if_existing) +int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing) { - int x, newindex = 0; - - /* First step is to get the codecs "index number" */ - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (AST_FORMAT_LIST[x].bits == format) { - newindex = x + 1; - break; - } - } - /* Done if its unknown */ - if (!newindex) - return; - - /* Now find any existing occurrence, or the end */ - for (x = 0; x < sizeof(format_t) * 8; x++) { - if (!pref->order[x] || pref->order[x] == newindex) - break; - } - - if (only_if_existing && !pref->order[x]) - return; - - /* Move down to make space to insert - either all the way to the end, - or as far as the existing location (which will be overwritten) */ - for (; x > 0; x--) { - pref->order[x] = pref->order[x - 1]; - pref->framing[x] = pref->framing[x - 1]; - } - - /* And insert the new entry */ - pref->order[0] = newindex; - pref->framing[0] = 0; /* ? */ -} - -/*! \brief Set packet size for codec */ -int ast_codec_pref_setsize(struct ast_codec_pref *pref, format_t format, int framems) -{ - int x, idx = -1; - - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (AST_FORMAT_LIST[x].bits == format) { - idx = x; - break; - } - } - - if (idx < 0) - return -1; - - /* size validation */ - if (!framems) - framems = AST_FORMAT_LIST[idx].def_ms; - - if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms) /* avoid division by zero */ - framems -= framems % AST_FORMAT_LIST[idx].inc_ms; - - if (framems < AST_FORMAT_LIST[idx].min_ms) - framems = AST_FORMAT_LIST[idx].min_ms; - - if (framems > AST_FORMAT_LIST[idx].max_ms) - framems = AST_FORMAT_LIST[idx].max_ms; - - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (pref->order[x] == (idx + 1)) { - pref->framing[x] = framems; - break; - } - } - - return x; -} - -/*! \brief Get packet size for codec */ -struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, format_t format) -{ - int x, idx = -1, framems = 0; - struct ast_format_list fmt = { 0, }; - - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (AST_FORMAT_LIST[x].bits == format) { - fmt = AST_FORMAT_LIST[x]; - idx = x; - break; - } - } - - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - if (pref->order[x] == (idx + 1)) { - framems = pref->framing[x]; - break; - } - } - - /* size validation */ - if (!framems) - framems = AST_FORMAT_LIST[idx].def_ms; - - if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms) /* avoid division by zero */ - framems -= framems % AST_FORMAT_LIST[idx].inc_ms; - - if (framems < AST_FORMAT_LIST[idx].min_ms) - framems = AST_FORMAT_LIST[idx].min_ms; - - if (framems > AST_FORMAT_LIST[idx].max_ms) - framems = AST_FORMAT_LIST[idx].max_ms; - - fmt.cur_ms = framems; - - return fmt; -} - -/*! \brief Pick a codec */ -format_t ast_codec_choose(struct ast_codec_pref *pref, format_t formats, int find_best) -{ - int x, slot; - format_t ret = 0; - - for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) { - slot = pref->order[x]; - - if (!slot) - break; - if (formats & AST_FORMAT_LIST[slot-1].bits) { - ret = AST_FORMAT_LIST[slot-1].bits; - break; - } - } - if (ret & AST_FORMAT_AUDIO_MASK) - return ret; - - ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec"); - - return find_best ? ast_best_codec(formats) : 0; -} - -int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing) -{ - int errors = 0, framems = 0; + int errors = 0, framems = 0, all = 0; char *parse = NULL, *this = NULL, *psize = NULL; - format_t format = 0; + struct ast_format format; parse = ast_strdupa(list); while ((this = strsep(&parse, ","))) { @@ -1263,30 +1004,38 @@ int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this); } } - if (!(format = ast_getformatbyname(this))) { + all = strcasecmp(this, "all") ? 0 : 1; + + if (!all && !ast_getformatbyname(this, &format)) { ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this); errors++; continue; } - if (mask) { - if (allowing) - *mask |= format; - else - *mask &= ~format; + if (cap) { + if (allowing) { + if (all) { + ast_format_cap_add_all(cap); + } else { + ast_format_cap_add(cap, &format); + } + } else { + if (all) { + ast_format_cap_remove_all(cap); + } else { + ast_format_cap_remove(cap, &format); + } + } } - /* Set up a preference list for audio. Do not include video in preferences - since we can not transcode video and have to use whatever is offered - */ - if (pref && (format & AST_FORMAT_AUDIO_MASK)) { - if (strcasecmp(this, "all")) { + if (pref) { + if (!all) { if (allowing) { - ast_codec_pref_append(pref, format); - ast_codec_pref_setsize(pref, format, framems); + ast_codec_pref_append(pref, &format); + ast_codec_pref_setsize(pref, &format, framems); + } else { + ast_codec_pref_remove(pref, &format); } - else - ast_codec_pref_remove(pref, format); } else if (!allowing) { memset(pref, 0, sizeof(*pref)); } @@ -1445,9 +1194,8 @@ static int speex_samples(unsigned char *data, int len) int ast_codec_get_samples(struct ast_frame *f) { int samples = 0; - char tmp[64]; - switch (f->subclass.codec) { + switch (f->subclass.format.id) { case AST_FORMAT_SPEEX: samples = speex_samples(f->data.ptr, f->datalen); break; @@ -1499,17 +1247,17 @@ int ast_codec_get_samples(struct ast_frame *f) samples = (int) f->datalen * ((float) 48000 / 8000); break; default: - ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), f->subclass.codec)); + ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format)); } return samples; } -int ast_codec_get_len(format_t format, int samples) +int ast_codec_get_len(struct ast_format *format, int samples) { int len = 0; /* XXX Still need speex, and lpc10 XXX */ - switch(format) { + switch(format->id) { case AST_FORMAT_G723_1: len = (samples / 240) * 20; break; @@ -1562,7 +1310,7 @@ int ast_frame_adjust_volume(struct ast_frame *f, int adjustment) short *fdata = f->data.ptr; short adjust_value = abs(adjustment); - if ((f->frametype != AST_FRAME_VOICE) || (f->subclass.codec != AST_FORMAT_SLINEAR)) + if ((f->frametype != AST_FRAME_VOICE) || (f->subclass.format.id != AST_FORMAT_SLINEAR)) return -1; if (!adjustment) @@ -1584,10 +1332,10 @@ int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2) int count; short *data1, *data2; - if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass.codec != AST_FORMAT_SLINEAR)) + if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass.format.id != AST_FORMAT_SLINEAR)) return -1; - if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass.codec != AST_FORMAT_SLINEAR)) + if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass.format.id != AST_FORMAT_SLINEAR)) return -1; if (f1->samples != f2->samples) diff --git a/main/image.c b/main/image.c index 5da07ce069c7ae3f03e36f5c2251eb6be5494000..3aa22665327a7089a7f88cb8a2fd763617aa4bef 100644 --- a/main/image.c +++ b/main/image.c @@ -96,7 +96,7 @@ static void make_filename(char *buf, int len, const char *filename, const char * } } -struct ast_frame *ast_read_image(const char *filename, const char *preflang, int format) +struct ast_frame *ast_read_image(const char *filename, const char *preflang, struct ast_format *format) { struct ast_imager *i; char buf[256]; @@ -109,7 +109,8 @@ struct ast_frame *ast_read_image(const char *filename, const char *preflang, int AST_RWLIST_RDLOCK(&imagers); AST_RWLIST_TRAVERSE(&imagers, i, list) { - if (i->format & format) { + /* if NULL image format, just pick the first one, otherwise match it. */ + if (!format || (ast_format_cmp(&i->format, format) == AST_FORMAT_CMP_EQUAL)) { char *stringp=NULL; ast_copy_string(tmp, i->exts, sizeof(tmp)); stringp = tmp; @@ -157,7 +158,7 @@ int ast_send_image(struct ast_channel *chan, const char *filename) struct ast_frame *f; int res = -1; if (chan->tech->send_image) { - f = ast_read_image(filename, chan->language, -1); + f = ast_read_image(filename, chan->language, NULL); if (f) { res = chan->tech->send_image(chan, f); ast_frfree(f); @@ -189,7 +190,7 @@ static char *handle_core_show_image_formats(struct ast_cli_entry *e, int cmd, st ast_cli(a->fd, FORMAT, "----", "----------", "-----------", "------"); AST_RWLIST_RDLOCK(&imagers); AST_RWLIST_TRAVERSE(&imagers, i, list) { - ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format)); + ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(&i->format)); count_fmt++; } AST_RWLIST_UNLOCK(&imagers); diff --git a/main/indications.c b/main/indications.c index dcd597ac7a0e65888a7860aa0f18c9825ae61881..f93239380a922e2639acc32e6928ef9d3ac824f4 100644 --- a/main/indications.c +++ b/main/indications.c @@ -116,7 +116,7 @@ struct playtones_state { int npos; int oldnpos; int pos; - int origwfmt; + struct ast_format origwfmt; struct ast_frame f; unsigned char offset[AST_FRIENDLY_OFFSET]; short data[4000]; @@ -127,7 +127,7 @@ static void playtones_release(struct ast_channel *chan, void *params) struct playtones_state *ps = params; if (chan) { - ast_set_write_format(chan, ps->origwfmt); + ast_set_write_format(chan, &ps->origwfmt); } if (ps->items) { @@ -147,9 +147,9 @@ static void *playtones_alloc(struct ast_channel *chan, void *params) return NULL; } - ps->origwfmt = chan->writeformat; + ast_format_copy(&ps->origwfmt, &chan->writeformat); - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) { ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name); playtones_release(NULL, ps); ps = NULL; @@ -223,7 +223,7 @@ static int playtones_generator(struct ast_channel *chan, void *data, int len, in } ps->f.frametype = AST_FRAME_VOICE; - ps->f.subclass.codec = AST_FORMAT_SLINEAR; + ast_format_set(&ps->f.subclass.format, AST_FORMAT_SLINEAR, 0); ps->f.datalen = len; ps->f.samples = samples; ps->f.offset = AST_FRIENDLY_OFFSET; diff --git a/main/manager.c b/main/manager.c index 40804bf31187d924cefda6622df50d8a865e8eea..27fa6d8dd0fc4a41ebef4da2ec1e74a8949cd21a 100644 --- a/main/manager.c +++ b/main/manager.c @@ -3506,7 +3506,7 @@ struct fast_originate_helper { /*! data can contain a channel name, extension number, username, password, etc. */ char data[512]; int timeout; - format_t format; /*!< Codecs used for a call */ + struct ast_format_cap *cap; /*!< Codecs used for a call */ char app[AST_MAX_APP]; char appdata[AST_MAX_EXTENSION]; char cid_name[AST_MAX_EXTENSION]; @@ -3528,12 +3528,12 @@ static void *fast_originate(void *data) char requested_channel[AST_CHANNEL_NAME]; if (!ast_strlen_zero(in->app)) { - res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1, + res = ast_pbx_outgoing_app(in->tech, in->cap, in->data, in->timeout, in->app, in->appdata, &reason, 1, S_OR(in->cid_num, NULL), S_OR(in->cid_name, NULL), in->vars, in->account, &chan); } else { - res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, + res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, S_OR(in->cid_num, NULL), S_OR(in->cid_name, NULL), in->vars, in->account, &chan); @@ -3565,6 +3565,7 @@ static void *fast_originate(void *data) if (chan) { ast_channel_unlock(chan); } + in->cap = ast_format_cap_destroy(in->cap); ast_free(in); return NULL; } @@ -3822,29 +3823,39 @@ static int action_originate(struct mansession *s, const struct message *m) int reason = 0; char tmp[256]; char tmp2[256]; - format_t format = AST_FORMAT_SLINEAR; - + struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); + struct ast_format tmp_fmt; pthread_t th; + + if (!cap) { + astman_send_error(s, m, "Internal Error. Memory allocation failure."); + } + ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0)); + if (ast_strlen_zero(name)) { astman_send_error(s, m, "Channel not specified"); - return 0; + res = 0; + goto fast_orig_cleanup; } if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { astman_send_error(s, m, "Invalid priority"); - return 0; + res = 0; + goto fast_orig_cleanup; } } if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) { astman_send_error(s, m, "Invalid timeout"); - return 0; + res = 0; + goto fast_orig_cleanup; } ast_copy_string(tmp, name, sizeof(tmp)); tech = tmp; data = strchr(tmp, '/'); if (!data) { astman_send_error(s, m, "Invalid channel"); - return 0; + res = 0; + goto fast_orig_cleanup; } *data++ = '\0'; ast_copy_string(tmp2, callerid, sizeof(tmp2)); @@ -3861,8 +3872,8 @@ static int action_originate(struct mansession *s, const struct message *m) } } if (!ast_strlen_zero(codecs)) { - format = 0; - ast_parse_allow_disallow(NULL, &format, codecs, 1); + ast_format_cap_remove_all(cap); + ast_parse_allow_disallow(NULL, cap, codecs, 1); } /* Allocate requested channel variables */ vars = astman_get_variables(m); @@ -3888,10 +3899,12 @@ static int action_originate(struct mansession *s, const struct message *m) ast_copy_string(fast->context, context, sizeof(fast->context)); ast_copy_string(fast->exten, exten, sizeof(fast->exten)); ast_copy_string(fast->account, account, sizeof(fast->account)); - fast->format = format; + fast->cap = cap; + cap = NULL; /* transfered originate helper the capabilities structure. It is now responsible for freeing it. */ fast->timeout = to; fast->priority = pi; if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) { + ast_format_cap_destroy(fast->cap); ast_free(fast); res = -1; } else { @@ -3912,18 +3925,20 @@ static int action_originate(struct mansession *s, const struct message *m) strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ )) { astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); - return 0; + res = 0; + goto fast_orig_cleanup; } - res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); + res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); } else { if (exten && context && pi) { - res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); + res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); } else { astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); if (vars) { ast_variables_destroy(vars); } - return 0; + res = 0; + goto fast_orig_cleanup; } } if (!res) { @@ -3931,6 +3946,9 @@ static int action_originate(struct mansession *s, const struct message *m) } else { astman_send_error(s, m, "Originate failed"); } + +fast_orig_cleanup: + ast_format_cap_destroy(cap); return 0; } diff --git a/main/pbx.c b/main/pbx.c index bceceb00f3a47c3fff2c429e5225a9dfdac872f5..1d8324e6e898be77266aa056a0c6d97a90eaeafb 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -8503,7 +8503,7 @@ static int ast_pbx_outgoing_cdr_failed(void) return 0; /* success */ } -int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) +int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) { struct ast_channel *chan; struct async_stat *as; @@ -8520,7 +8520,7 @@ int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int ti oh.vars = vars; oh.parent_channel = NULL; - chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); + chan = __ast_request_and_dial(type, cap, NULL, data, timeout, reason, cid_num, cid_name, &oh); if (channel) { *channel = chan; if (chan) @@ -8610,7 +8610,7 @@ int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int ti res = -1; goto outgoing_exten_cleanup; } - chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); + chan = ast_request_and_dial(type, cap, NULL, data, timeout, reason, cid_num, cid_name); if (channel) { *channel = chan; if (chan) @@ -8669,7 +8669,7 @@ static void *ast_pbx_run_app(void *data) return NULL; } -int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) +int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) { struct ast_channel *chan; struct app_tmp *tmp; @@ -8687,7 +8687,7 @@ int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int time goto outgoing_app_cleanup; } if (synchronous) { - chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); + chan = __ast_request_and_dial(type, cap, NULL, data, timeout, reason, cid_num, cid_name, &oh); if (chan) { ast_set_variables(chan, vars); if (account) @@ -8752,7 +8752,7 @@ int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int time res = -1; goto outgoing_app_cleanup; } - chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); + chan = __ast_request_and_dial(type, cap, NULL, data, timeout, reason, cid_num, cid_name, &oh); if (!chan) { ast_free(as); res = -1; diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 4a4dbf5955103b7876d3bbc90f449b2611154eb6..738b58faeb978fc5c223024e353e981303c804e4 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -89,43 +89,43 @@ static const struct ast_rtp_mime_type { char *subtype; unsigned int sample_rate; } ast_rtp_mime_types[] = { - {{1, AST_FORMAT_G723_1}, "audio", "G723", 8000}, - {{1, AST_FORMAT_GSM}, "audio", "GSM", 8000}, - {{1, AST_FORMAT_ULAW}, "audio", "PCMU", 8000}, - {{1, AST_FORMAT_ULAW}, "audio", "G711U", 8000}, - {{1, AST_FORMAT_ALAW}, "audio", "PCMA", 8000}, - {{1, AST_FORMAT_ALAW}, "audio", "G711A", 8000}, - {{1, AST_FORMAT_G726}, "audio", "G726-32", 8000}, - {{1, AST_FORMAT_ADPCM}, "audio", "DVI4", 8000}, - {{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000}, - {{1, AST_FORMAT_SLINEAR16}, "audio", "L16", 16000}, - {{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000}, - {{1, AST_FORMAT_G729A}, "audio", "G729", 8000}, - {{1, AST_FORMAT_G729A}, "audio", "G729A", 8000}, - {{1, AST_FORMAT_G729A}, "audio", "G.729", 8000}, - {{1, AST_FORMAT_SPEEX}, "audio", "speex", 8000}, - {{1, AST_FORMAT_SPEEX16}, "audio", "speex", 16000}, - {{1, AST_FORMAT_ILBC}, "audio", "iLBC", 8000}, + {{1, {.id = AST_FORMAT_G723_1}, 0}, "audio", "G723", 8000}, + {{1, {.id = AST_FORMAT_GSM}, 0}, "audio", "GSM", 8000}, + {{1, {.id = AST_FORMAT_ULAW}, 0}, "audio", "PCMU", 8000}, + {{1, {.id = AST_FORMAT_ULAW}, 0}, "audio", "G711U", 8000}, + {{1, {.id = AST_FORMAT_ALAW}, 0}, "audio", "PCMA", 8000}, + {{1, {.id = AST_FORMAT_ALAW}, 0}, "audio", "G711A", 8000}, + {{1, {.id = AST_FORMAT_G726}, 0}, "audio", "G726-32", 8000}, + {{1, {.id = AST_FORMAT_ADPCM}, 0}, "audio", "DVI4", 8000}, + {{1, {.id = AST_FORMAT_SLINEAR}, 0}, "audio", "L16", 8000}, + {{1, {.id = AST_FORMAT_SLINEAR16}, 0}, "audio", "L16", 16000}, + {{1, {.id = AST_FORMAT_LPC10}, 0}, "audio", "LPC", 8000}, + {{1, {.id = AST_FORMAT_G729A}, 0}, "audio", "G729", 8000}, + {{1, {.id = AST_FORMAT_G729A}, 0}, "audio", "G729A", 8000}, + {{1, {.id = AST_FORMAT_G729A}, 0}, "audio", "G.729", 8000}, + {{1, {.id = AST_FORMAT_SPEEX}, 0}, "audio", "speex", 8000}, + {{1, {.id = AST_FORMAT_SPEEX16}, 0}, "audio", "speex", 16000}, + {{1, {.id = AST_FORMAT_ILBC}, 0}, "audio", "iLBC", 8000}, /* this is the sample rate listed in the RTP profile for the G.722 codec, *NOT* the actual sample rate of the media stream */ - {{1, AST_FORMAT_G722}, "audio", "G722", 8000}, - {{1, AST_FORMAT_G726_AAL2}, "audio", "AAL2-G726-32", 8000}, - {{0, AST_RTP_DTMF}, "audio", "telephone-event", 8000}, - {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event", 8000}, - {{0, AST_RTP_CN}, "audio", "CN", 8000}, - {{1, AST_FORMAT_JPEG}, "video", "JPEG", 90000}, - {{1, AST_FORMAT_PNG}, "video", "PNG", 90000}, - {{1, AST_FORMAT_H261}, "video", "H261", 90000}, - {{1, AST_FORMAT_H263}, "video", "H263", 90000}, - {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998", 90000}, - {{1, AST_FORMAT_H264}, "video", "H264", 90000}, - {{1, AST_FORMAT_MP4_VIDEO}, "video", "MP4V-ES", 90000}, - {{1, AST_FORMAT_T140RED}, "text", "RED", 1000}, - {{1, AST_FORMAT_T140}, "text", "T140", 1000}, - {{1, AST_FORMAT_SIREN7}, "audio", "G7221", 16000}, - {{1, AST_FORMAT_SIREN14}, "audio", "G7221", 32000}, - {{1, AST_FORMAT_G719}, "audio", "G719", 48000}, + {{1, {.id = AST_FORMAT_G722}, 0}, "audio", "G722", 8000}, + {{1, {.id = AST_FORMAT_G726_AAL2}, 0}, "audio", "AAL2-G726-32", 8000}, + {{0, {.id = 0}, AST_RTP_DTMF}, "audio", "telephone-event", 8000}, + {{0, {.id = 0}, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event", 8000}, + {{0, {.id = 0}, AST_RTP_CN}, "audio", "CN", 8000}, + {{1, {.id = AST_FORMAT_JPEG}, 0}, "video", "JPEG", 90000}, + {{1, {.id = AST_FORMAT_PNG}, 0}, "video", "PNG", 90000}, + {{1, {.id = AST_FORMAT_H261}, 0}, "video", "H261", 90000}, + {{1, {.id = AST_FORMAT_H263}, 0}, "video", "H263", 90000}, + {{1, {.id = AST_FORMAT_H263_PLUS}, 0}, "video", "h263-1998", 90000}, + {{1, {.id = AST_FORMAT_H264}, 0}, "video", "H264", 90000}, + {{1, {.id = AST_FORMAT_MP4_VIDEO}, 0}, "video", "MP4V-ES", 90000}, + {{1, {.id = AST_FORMAT_T140RED}, 0}, "text", "RED", 1000}, + {{1, {.id = AST_FORMAT_T140}, 0}, "text", "T140", 1000}, + {{1, {.id = AST_FORMAT_SIREN7}, 0}, "audio", "G7221", 16000}, + {{1, {.id = AST_FORMAT_SIREN14}, 0}, "audio", "G7221", 32000}, + {{1, {.id = AST_FORMAT_G719}, 0}, "audio", "G719", 48000}, }; /*! @@ -139,44 +139,44 @@ static const struct ast_rtp_mime_type { * assigned values */ static const struct ast_rtp_payload_type static_RTP_PT[AST_RTP_MAX_PT] = { - [0] = {1, AST_FORMAT_ULAW}, + [0] = {1, {.id = AST_FORMAT_ULAW}, 0}, #ifdef USE_DEPRECATED_G726 - [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */ + [2] = {1, {.id = AST_FORMAT_G726}, 0},/* Technically this is G.721, but if Cisco can do it, so can we... */ #endif - [3] = {1, AST_FORMAT_GSM}, - [4] = {1, AST_FORMAT_G723_1}, - [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */ - [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */ - [7] = {1, AST_FORMAT_LPC10}, - [8] = {1, AST_FORMAT_ALAW}, - [9] = {1, AST_FORMAT_G722}, - [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */ - [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */ - [13] = {0, AST_RTP_CN}, - [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */ - [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */ - [18] = {1, AST_FORMAT_G729A}, - [19] = {0, AST_RTP_CN}, /* Also used for CN */ - [26] = {1, AST_FORMAT_JPEG}, - [31] = {1, AST_FORMAT_H261}, - [34] = {1, AST_FORMAT_H263}, - [97] = {1, AST_FORMAT_ILBC}, - [98] = {1, AST_FORMAT_H263_PLUS}, - [99] = {1, AST_FORMAT_H264}, - [101] = {0, AST_RTP_DTMF}, - [102] = {1, AST_FORMAT_SIREN7}, - [103] = {1, AST_FORMAT_H263_PLUS}, - [104] = {1, AST_FORMAT_MP4_VIDEO}, - [105] = {1, AST_FORMAT_T140RED}, /* Real time text chat (with redundancy encoding) */ - [106] = {1, AST_FORMAT_T140}, /* Real time text chat */ - [110] = {1, AST_FORMAT_SPEEX}, - [111] = {1, AST_FORMAT_G726}, - [112] = {1, AST_FORMAT_G726_AAL2}, - [115] = {1, AST_FORMAT_SIREN14}, - [116] = {1, AST_FORMAT_G719}, - [117] = {1, AST_FORMAT_SPEEX16}, - [118] = {1, AST_FORMAT_SLINEAR16}, /* 16 Khz signed linear */ - [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */ + [3] = {1, {.id = AST_FORMAT_GSM}, 0}, + [4] = {1, {.id = AST_FORMAT_G723_1}, 0}, + [5] = {1, {.id = AST_FORMAT_ADPCM}, 0},/* 8 kHz */ + [6] = {1, {.id = AST_FORMAT_ADPCM}, 0}, /* 16 kHz */ + [7] = {1, {.id = AST_FORMAT_LPC10}, 0}, + [8] = {1, {.id = AST_FORMAT_ALAW}, 0}, + [9] = {1, {.id = AST_FORMAT_G722}, 0}, + [10] = {1, {.id = AST_FORMAT_SLINEAR}, 0}, /* 2 channels */ + [11] = {1, {.id = AST_FORMAT_SLINEAR}, 0}, /* 1 channel */ + [13] = {0, {.id = 0}, AST_RTP_CN}, + [16] = {1, {.id = AST_FORMAT_ADPCM}, 0}, /* 11.025 kHz */ + [17] = {1, {.id = AST_FORMAT_ADPCM}, 0}, /* 22.050 kHz */ + [18] = {1, {.id = AST_FORMAT_G729A}, 0}, + [19] = {0, {.id = 0}, AST_RTP_CN}, /* Also used for CN */ + [26] = {1, {.id = AST_FORMAT_JPEG}, 0}, + [31] = {1, {.id = AST_FORMAT_H261}, 0}, + [34] = {1, {.id = AST_FORMAT_H263}, 0}, + [97] = {1, {.id = AST_FORMAT_ILBC}, 0}, + [98] = {1, {.id = AST_FORMAT_H263_PLUS}, 0}, + [99] = {1, {.id = AST_FORMAT_H264}, 0}, + [101] = {0, {.id = 0}, AST_RTP_DTMF}, + [102] = {1, {.id = AST_FORMAT_SIREN7}, 0}, + [103] = {1, {.id = AST_FORMAT_H263_PLUS}, 0}, + [104] = {1, {.id = AST_FORMAT_MP4_VIDEO}, 0}, + [105] = {1, {.id = AST_FORMAT_T140RED}, 0}, /* Real time text chat (with redundancy encoding) */ + [106] = {1, {.id = AST_FORMAT_T140}, 0}, /* Real time text chat */ + [110] = {1, {.id = AST_FORMAT_SPEEX}, 0}, + [111] = {1, {.id = AST_FORMAT_G726}, 0}, + [112] = {1, {.id = AST_FORMAT_G726_AAL2}, 0}, + [115] = {1, {.id = AST_FORMAT_SIREN14}, 0}, + [116] = {1, {.id = AST_FORMAT_G719}, 0}, + [117] = {1, {.id = AST_FORMAT_SPEEX16}, 0}, + [118] = {1, {.id = AST_FORMAT_SLINEAR16}, 0}, /* 16 Khz signed linear */ + [121] = {0, {.id = 0}, AST_RTP_CISCO_DTMF}, /* Must be type 121 */ }; int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module) @@ -485,9 +485,10 @@ void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp for (i = 0; i < AST_RTP_MAX_PT; i++) { codecs->payloads[i].asterisk_format = 0; - codecs->payloads[i].code = 0; + codecs->payloads[i].rtp_code = 0; + ast_format_clear(&codecs->payloads[i].format); if (instance && instance->engine && instance->engine->payload_set) { - instance->engine->payload_set(instance, i, 0, 0); + instance->engine->payload_set(instance, i, 0, NULL, 0); } } } @@ -497,11 +498,13 @@ void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_r int i; for (i = 0; i < AST_RTP_MAX_PT; i++) { - if (static_RTP_PT[i].code) { + if (static_RTP_PT[i].rtp_code || static_RTP_PT[i].asterisk_format) { + codecs->payloads[i].asterisk_format = static_RTP_PT[i].asterisk_format; - codecs->payloads[i].code = static_RTP_PT[i].code; + codecs->payloads[i].rtp_code = static_RTP_PT[i].rtp_code; + ast_format_copy(&codecs->payloads[i].format, &static_RTP_PT[i].format); if (instance && instance->engine && instance->engine->payload_set) { - instance->engine->payload_set(instance, i, codecs->payloads[i].asterisk_format, codecs->payloads[i].code); + instance->engine->payload_set(instance, i, codecs->payloads[i].asterisk_format, &codecs->payloads[i].format, codecs->payloads[i].rtp_code); } } } @@ -512,12 +515,13 @@ void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_cod int i; for (i = 0; i < AST_RTP_MAX_PT; i++) { - if (src->payloads[i].code) { + if (src->payloads[i].rtp_code || src->payloads[i].asterisk_format) { ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest); dest->payloads[i].asterisk_format = src->payloads[i].asterisk_format; - dest->payloads[i].code = src->payloads[i].code; + dest->payloads[i].rtp_code = src->payloads[i].rtp_code; + ast_format_copy(&dest->payloads[i].format, &src->payloads[i].format); if (instance && instance->engine && instance->engine->payload_set) { - instance->engine->payload_set(instance, i, dest->payloads[i].asterisk_format, dest->payloads[i].code); + instance->engine->payload_set(instance, i, dest->payloads[i].asterisk_format, &dest->payloads[i].format, dest->payloads[i].rtp_code); } } } @@ -525,17 +529,18 @@ void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_cod void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload) { - if (payload < 0 || payload >= AST_RTP_MAX_PT || !static_RTP_PT[payload].code) { + if (payload < 0 || payload >= AST_RTP_MAX_PT || (!static_RTP_PT[payload].rtp_code && !static_RTP_PT[payload].asterisk_format)) { return; } codecs->payloads[payload].asterisk_format = static_RTP_PT[payload].asterisk_format; - codecs->payloads[payload].code = static_RTP_PT[payload].code; + codecs->payloads[payload].rtp_code = static_RTP_PT[payload].rtp_code; + ast_format_copy(&codecs->payloads[payload].format, &static_RTP_PT[payload].format); ast_debug(1, "Setting payload %d based on m type on %p\n", payload, codecs); if (instance && instance->engine && instance->engine->payload_set) { - instance->engine->payload_set(instance, payload, codecs->payloads[payload].asterisk_format, codecs->payloads[payload].code); + instance->engine->payload_set(instance, payload, codecs->payloads[payload].asterisk_format, &codecs->payloads[payload].format, codecs->payloads[payload].rtp_code); } } @@ -572,14 +577,12 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, found = 1; codecs->payloads[pt] = t->payload_type; - if ((t->payload_type.code == AST_FORMAT_G726) && - t->payload_type.asterisk_format && - (options & AST_RTP_OPT_G726_NONSTANDARD)) { - codecs->payloads[pt].code = AST_FORMAT_G726_AAL2; + if ((t->payload_type.format.id == AST_FORMAT_G726) && t->payload_type.asterisk_format && (options & AST_RTP_OPT_G726_NONSTANDARD)) { + ast_format_set(&codecs->payloads[pt].format, AST_FORMAT_G726_AAL2, 0); } if (instance && instance->engine && instance->engine->payload_set) { - instance->engine->payload_set(instance, pt, codecs->payloads[i].asterisk_format, codecs->payloads[i].code); + instance->engine->payload_set(instance, pt, codecs->payloads[i].asterisk_format, &codecs->payloads[i].format, codecs->payloads[i].rtp_code); } break; @@ -602,10 +605,11 @@ void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs); codecs->payloads[payload].asterisk_format = 0; - codecs->payloads[payload].code = 0; + codecs->payloads[payload].rtp_code = 0; + ast_format_clear(&codecs->payloads[payload].format); if (instance && instance->engine && instance->engine->payload_set) { - instance->engine->payload_set(instance, payload, 0, 0); + instance->engine->payload_set(instance, payload, 0, NULL, 0); } } @@ -618,45 +622,55 @@ struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs } result.asterisk_format = codecs->payloads[payload].asterisk_format; - result.code = codecs->payloads[payload].code; + result.rtp_code = codecs->payloads[payload].rtp_code; + ast_format_copy(&result.format, &codecs->payloads[payload].format); - if (!result.code) { + if (!result.rtp_code && !result.asterisk_format) { result = static_RTP_PT[payload]; } return result; } -void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, format_t *astformats, int *nonastformats) +void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats) { int i; - *astformats = *nonastformats = 0; + ast_format_cap_remove_all(astformats); + *nonastformats = 0; for (i = 0; i < AST_RTP_MAX_PT; i++) { - if (codecs->payloads[i].code) { + if (codecs->payloads[i].rtp_code || codecs->payloads[i].asterisk_format) { ast_debug(1, "Incorporating payload %d on %p\n", i, codecs); } if (codecs->payloads[i].asterisk_format) { - *astformats |= codecs->payloads[i].code; + ast_format_cap_add(astformats, &codecs->payloads[i].format); } else { - *nonastformats |= codecs->payloads[i].code; + *nonastformats |= codecs->payloads[i].rtp_code; } } } -int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const format_t code) +int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code) { int i; for (i = 0; i < AST_RTP_MAX_PT; i++) { - if (codecs->payloads[i].asterisk_format == asterisk_format && codecs->payloads[i].code == code) { + if (codecs->payloads[i].asterisk_format && asterisk_format && format && + (ast_format_cmp(format, &codecs->payloads[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) { + return i; + } else if (!codecs->payloads[i].asterisk_format && !asterisk_format && + (codecs->payloads[i].rtp_code == code)) { return i; } } for (i = 0; i < AST_RTP_MAX_PT; i++) { - if (static_RTP_PT[i].asterisk_format == asterisk_format && static_RTP_PT[i].code == code) { + if (static_RTP_PT[i].asterisk_format && asterisk_format && format && + (ast_format_cmp(format, &static_RTP_PT[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) { + return i; + } else if (!static_RTP_PT[i].asterisk_format && !asterisk_format && + (static_RTP_PT[i].rtp_code == code)) { return i; } } @@ -664,29 +678,38 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asteris return -1; } -const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const format_t code, enum ast_rtp_options options) +const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_format *format, int code, enum ast_rtp_options options) { int i; for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); i++) { - if (ast_rtp_mime_types[i].payload_type.code == code && ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format) { - if (asterisk_format && (code == AST_FORMAT_G726_AAL2) && (options & AST_RTP_OPT_G726_NONSTANDARD)) { + if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format && + (ast_format_cmp(format, &ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) { + if ((format->id == AST_FORMAT_G726_AAL2) && (options & AST_RTP_OPT_G726_NONSTANDARD)) { return "G726-32"; } else { return ast_rtp_mime_types[i].subtype; } + } else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format && + ast_rtp_mime_types[i].payload_type.rtp_code == code) { + + return ast_rtp_mime_types[i].subtype; } } return ""; } -unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, format_t code) +unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, struct ast_format *format, int code) { unsigned int i; for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); ++i) { - if ((ast_rtp_mime_types[i].payload_type.code == code) && (ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format)) { + if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format && + (ast_format_cmp(format, &ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) { + return ast_rtp_mime_types[i].sample_rate; + } else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format && + ast_rtp_mime_types[i].payload_type.rtp_code == code) { return ast_rtp_mime_types[i].sample_rate; } } @@ -694,23 +717,35 @@ unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, format_t code) return 0; } -char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, const format_t capability, const int asterisk_format, enum ast_rtp_options options) +char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *ast_format_capability, int rtp_capability, const int asterisk_format, enum ast_rtp_options options) { - format_t format; int found = 0; - + const char *name; if (!buf) { return NULL; } - ast_str_append(&buf, 0, "0x%llx (", (unsigned long long) capability); - for (format = 1; format < AST_RTP_MAX; format <<= 1) { - if (capability & format) { - const char *name = ast_rtp_lookup_mime_subtype2(asterisk_format, format, options); + if (asterisk_format) { + struct ast_format tmp_fmt; + ast_format_cap_iter_start(ast_format_capability); + while (!ast_format_cap_iter_next(ast_format_capability, &tmp_fmt)) { + name = ast_rtp_lookup_mime_subtype2(asterisk_format, &tmp_fmt, 0, options); ast_str_append(&buf, 0, "%s|", name); found = 1; } + ast_format_cap_iter_end(ast_format_capability); + + } else { + int x; + ast_str_append(&buf, 0, "0x%x (", (unsigned int) rtp_capability); + for (x = 1; x < AST_RTP_MAX; x <<= 1) { + if (rtp_capability & x) { + name = ast_rtp_lookup_mime_subtype2(asterisk_format, NULL, x, options); + ast_str_append(&buf, 0, "%s|", name); + found = 1; + } + } } ast_str_append(&buf, 0, "%s", found ? ")" : "nothing)"); @@ -842,7 +877,8 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a cs[2] = NULL; for (;;) { /* If the underlying formats have changed force this bridge to break */ - if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) { + if ((ast_format_cmp(&c0->rawreadformat, &c1->rawwriteformat) == AST_FORMAT_CMP_NOT_EQUAL) || + (ast_format_cmp(&c1->rawreadformat, &c0->rawwriteformat) == AST_FORMAT_CMP_NOT_EQUAL)) { ast_debug(1, "rtp-engine-local-bridge: Oooh, formats changed, backing out\n"); res = AST_BRIDGE_FAILED_NOWARN; break; @@ -969,20 +1005,40 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a return res; } -static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1, - struct ast_rtp_instance *vinstance0, struct ast_rtp_instance *vinstance1, struct ast_rtp_instance *tinstance0, - struct ast_rtp_instance *tinstance1, struct ast_rtp_glue *glue0, struct ast_rtp_glue *glue1, format_t codec0, format_t codec1, int timeoutms, - int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1) +static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, + struct ast_channel *c1, + struct ast_rtp_instance *instance0, + struct ast_rtp_instance *instance1, + struct ast_rtp_instance *vinstance0, + struct ast_rtp_instance *vinstance1, + struct ast_rtp_instance *tinstance0, + struct ast_rtp_instance *tinstance1, + struct ast_rtp_glue *glue0, + struct ast_rtp_glue *glue1, + struct ast_format_cap *cap0, + struct ast_format_cap *cap1, + int timeoutms, + int flags, + struct ast_frame **fo, + struct ast_channel **rc, + void *pvt0, + void *pvt1) { enum ast_bridge_result res = AST_BRIDGE_FAILED; struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, }; - format_t oldcodec0 = codec0, oldcodec1 = codec1; + struct ast_format_cap *oldcap0 = ast_format_cap_dup(cap0); + struct ast_format_cap *oldcap1 = ast_format_cap_dup(cap1); struct ast_sockaddr ac1 = {{0,}}, vac1 = {{0,}}, tac1 = {{0,}}, ac0 = {{0,}}, vac0 = {{0,}}, tac0 = {{0,}}; struct ast_sockaddr t1 = {{0,}}, vt1 = {{0,}}, tt1 = {{0,}}, t0 = {{0,}}, vt0 = {{0,}}, tt0 = {{0,}}; struct ast_frame *fr = NULL; + if (!oldcap0 || !oldcap1) { + ast_channel_unlock(c0); + ast_channel_unlock(c1); + goto remote_bridge_cleanup; + } /* Test the first channel */ - if (!(glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0))) { + if (!(glue0->update_peer(c0, instance1, vinstance1, tinstance1, cap1, 0))) { ast_rtp_instance_get_remote_address(instance1, &ac1); if (vinstance1) { ast_rtp_instance_get_remote_address(vinstance1, &vac1); @@ -995,7 +1051,7 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct } /* Test the second channel */ - if (!(glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0))) { + if (!(glue1->update_peer(c1, instance0, vinstance0, tinstance0, cap0, 0))) { ast_rtp_instance_get_remote_address(instance0, &ac0); if (vinstance0) { ast_rtp_instance_get_remote_address(instance0, &vac0); @@ -1039,7 +1095,8 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_rtp_instance_get_remote_address(tinstance1, &tt1); } if (glue1->get_codec) { - codec1 = glue1->get_codec(c1); + ast_format_cap_remove_all(cap1); + glue1->get_codec(c1, cap1); } ast_rtp_instance_get_remote_address(instance0, &t0); @@ -1050,63 +1107,66 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_rtp_instance_get_remote_address(tinstance0, &tt0); } if (glue0->get_codec) { - codec0 = glue0->get_codec(c0); + ast_format_cap_remove_all(cap0); + glue0->get_codec(c0, cap0); } if ((ast_sockaddr_cmp(&t1, &ac1)) || (vinstance1 && ast_sockaddr_cmp(&vt1, &vac1)) || (tinstance1 && ast_sockaddr_cmp(&tt1, &tac1)) || - (codec1 != oldcodec1)) { + (!ast_format_cap_identical(cap1, oldcap1))) { + char tmp_buf[512] = { 0, }; ast_debug(1, "Oooh, '%s' changed end address to %s (format %s)\n", c1->name, ast_sockaddr_stringify(&t1), - ast_getformatname(codec1)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), cap1)); ast_debug(1, "Oooh, '%s' changed end vaddress to %s (format %s)\n", c1->name, ast_sockaddr_stringify(&vt1), - ast_getformatname(codec1)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), cap1)); ast_debug(1, "Oooh, '%s' changed end taddress to %s (format %s)\n", c1->name, ast_sockaddr_stringify(&tt1), - ast_getformatname(codec1)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), cap1)); ast_debug(1, "Oooh, '%s' was %s/(format %s)\n", c1->name, ast_sockaddr_stringify(&ac1), - ast_getformatname(oldcodec1)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), oldcap1)); ast_debug(1, "Oooh, '%s' was %s/(format %s)\n", c1->name, ast_sockaddr_stringify(&vac1), - ast_getformatname(oldcodec1)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), oldcap1)); ast_debug(1, "Oooh, '%s' was %s/(format %s)\n", c1->name, ast_sockaddr_stringify(&tac1), - ast_getformatname(oldcodec1)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), oldcap1)); if (glue0->update_peer(c0, ast_sockaddr_isnull(&t1) ? NULL : instance1, ast_sockaddr_isnull(&vt1) ? NULL : vinstance1, ast_sockaddr_isnull(&tt1) ? NULL : tinstance1, - codec1, 0)) { + cap1, 0)) { ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); } ast_sockaddr_copy(&ac1, &t1); ast_sockaddr_copy(&vac1, &vt1); ast_sockaddr_copy(&tac1, &tt1); - oldcodec1 = codec1; + ast_format_cap_copy(oldcap1, cap1); } if ((ast_sockaddr_cmp(&t0, &ac0)) || (vinstance0 && ast_sockaddr_cmp(&vt0, &vac0)) || (tinstance0 && ast_sockaddr_cmp(&tt0, &tac0)) || - (codec0 != oldcodec0)) { + (!ast_format_cap_identical(cap0, oldcap0))) { + char tmp_buf[512] = { 0, }; ast_debug(1, "Oooh, '%s' changed end address to %s (format %s)\n", c0->name, ast_sockaddr_stringify(&t0), - ast_getformatname(codec0)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), cap0)); ast_debug(1, "Oooh, '%s' was %s/(format %s)\n", c0->name, ast_sockaddr_stringify(&ac0), - ast_getformatname(oldcodec0)); + ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), oldcap0)); if (glue1->update_peer(c1, t0.len ? instance0 : NULL, vt0.len ? vinstance0 : NULL, tt0.len ? tinstance0 : NULL, - codec0, 0)) { + cap0, 0)) { ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); } ast_sockaddr_copy(&ac0, &t0); ast_sockaddr_copy(&vac0, &vt0); ast_sockaddr_copy(&tac0, &tt0); - oldcodec0 = codec0; + ast_format_cap_copy(oldcap0, cap0); } /* Wait for frame to come in on the channels */ @@ -1148,9 +1208,9 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct } else if (fr->subclass.integer == AST_CONTROL_UNHOLD) { /* If they went off hold they should go back to being direct */ if (who == c0) { - glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0); + glue1->update_peer(c1, instance0, vinstance0, tinstance0, cap0, 0); } else { - glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0); + glue0->update_peer(c0, instance1, vinstance1, tinstance1, cap1, 0); } } /* Update local address information */ @@ -1160,10 +1220,17 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_sockaddr_copy(&ac1, &t1); /* Update codec information */ if (glue0->get_codec && c0->tech_pvt) { - oldcodec0 = codec0 = glue0->get_codec(c0); + ast_format_cap_remove_all(cap0); + ast_format_cap_remove_all(oldcap0); + glue0->get_codec(c0, cap0); + ast_format_cap_append(oldcap0, cap0); + } if (glue1->get_codec && c1->tech_pvt) { - oldcodec1 = codec1 = glue1->get_codec(c1); + ast_format_cap_remove_all(cap1); + ast_format_cap_remove_all(oldcap1); + glue0->get_codec(c1, cap1); + ast_format_cap_append(oldcap1, cap1); } ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); ast_frfree(fr); @@ -1181,7 +1248,8 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct *fo = fr; *rc = who; ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass.integer, who->name); - return AST_BRIDGE_COMPLETE; + res = AST_BRIDGE_COMPLETE; + goto remote_bridge_cleanup; } } else { if ((fr->frametype == AST_FRAME_DTMF_BEGIN) || @@ -1214,6 +1282,10 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_poll_channel_del(c0, c1); +remote_bridge_cleanup: + ast_format_cap_destroy(oldcap0); + ast_format_cap_destroy(oldcap1); + return res; } @@ -1238,9 +1310,15 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID; enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID; enum ast_bridge_result res = AST_BRIDGE_FAILED; - format_t codec0 = 0, codec1 = 0; + struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock(); + struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock(); int unlock_chans = 1; + if (!cap0 || !cap1) { + unlock_chans = 0; + goto done; + } + /* Lock both channels so we can look for the glue that binds them together */ ast_channel_lock(c0); while (ast_channel_trylock(c1)) { @@ -1311,10 +1389,18 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as } /* Make sure that codecs match */ - codec0 = glue0->get_codec ? glue0->get_codec(c0) : 0; - codec1 = glue1->get_codec ? glue1->get_codec(c1) : 0; - if (codec0 && codec1 && !(codec0 & codec1)) { - ast_debug(1, "Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n", ast_getformatname(codec0), ast_getformatname(codec1)); + if (glue0->get_codec){ + glue0->get_codec(c0, cap0); + } + if (glue1->get_codec) { + glue1->get_codec(c1, cap1); + } + if (!ast_format_cap_is_empty(cap0) && !ast_format_cap_is_empty(cap1) && !ast_format_cap_has_joint(cap0, cap1)) { + char tmp0[256] = { 0, }; + char tmp1[256] = { 0, }; + ast_debug(1, "Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n", + ast_getformatname_multiple(tmp0, sizeof(tmp0), cap0), + ast_getformatname_multiple(tmp1, sizeof(tmp1), cap1)); res = AST_BRIDGE_FAILED_NOWARN; goto done; } @@ -1331,7 +1417,7 @@ enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct as } else { ast_verbose(VERBOSE_PREFIX_3 "Remotely bridging %s and %s\n", c0->name, c1->name); res = remote_bridge_loop(c0, c1, instance0, instance1, vinstance0, vinstance1, - tinstance0, tinstance1, glue0, glue1, codec0, codec1, timeoutms, flags, + tinstance0, tinstance1, glue0, glue1, cap0, cap1, timeoutms, flags, fo, rc, c0->tech_pvt, c1->tech_pvt); } @@ -1347,6 +1433,8 @@ done: ast_channel_unlock(c0); ast_channel_unlock(c1); } + ast_format_cap_destroy(cap1); + ast_format_cap_destroy(cap0); unref_instance_cond(&instance0); unref_instance_cond(&instance1); @@ -1371,7 +1459,8 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struc struct ast_rtp_glue *glue0, *glue1; enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID; enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID; - format_t codec0 = 0, codec1 = 0; + struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock(); + struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock(); int res = 0; /* Lock both channels so we can look for the glue that binds them together */ @@ -1382,6 +1471,10 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struc ast_channel_lock(c0); } + if (!cap1 || !cap0) { + goto done; + } + /* Grab glue that binds each channel to something using the RTP engine */ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) { ast_debug(1, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name); @@ -1404,10 +1497,10 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struc audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID; } if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec) { - codec0 = glue0->get_codec(c0); + glue0->get_codec(c0, cap0); } if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec) { - codec1 = glue1->get_codec(c1); + glue1->get_codec(c1, cap1); } /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */ @@ -1416,7 +1509,7 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struc } /* Make sure we have matching codecs */ - if (!(codec0 & codec1)) { + if (!ast_format_cap_has_joint(cap0, cap1)) { goto done; } @@ -1435,6 +1528,9 @@ done: ast_channel_unlock(c0); ast_channel_unlock(c1); + ast_format_cap_destroy(cap0); + ast_format_cap_destroy(cap1); + unref_instance_cond(&instance0); unref_instance_cond(&instance1); unref_instance_cond(&vinstance0); @@ -1455,11 +1551,14 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1 struct ast_rtp_glue *glue0, *glue1; enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID; enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID; - format_t codec0 = 0, codec1 = 0; + struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock(); + struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock(); int res = 0; /* If there is no second channel just immediately bail out, we are of no use in that scenario */ if (!c1) { + ast_format_cap_destroy(cap0); + ast_format_cap_destroy(cap1); return -1; } @@ -1471,6 +1570,10 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1 ast_channel_lock(c0); } + if (!cap1 || !cap0) { + goto done; + } + /* Grab glue that binds each channel to something using the RTP engine */ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) { ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name); @@ -1492,11 +1595,11 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1 if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) { audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID; } - if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec(c0)) { - codec0 = glue0->get_codec(c0); + if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec) { + glue0->get_codec(c0, cap0); } - if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec(c1)) { - codec1 = glue1->get_codec(c1); + if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec) { + glue1->get_codec(c1, cap1); } /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */ @@ -1505,12 +1608,12 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1 } /* Make sure we have matching codecs */ - if (!(codec0 & codec1)) { + if (!ast_format_cap_has_joint(cap0, cap1)) { goto done; } /* Bridge media early */ - if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0)) { + if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, cap1, 0)) { ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); } @@ -1520,6 +1623,9 @@ done: ast_channel_unlock(c0); ast_channel_unlock(c1); + ast_format_cap_destroy(cap0); + ast_format_cap_destroy(cap1); + unref_instance_cond(&instance0); unref_instance_cond(&instance1); unref_instance_cond(&vinstance0); @@ -1623,12 +1729,12 @@ void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_in } } -int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, format_t format) +int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, struct ast_format *format) { return instance->engine->set_read_format ? instance->engine->set_read_format(instance, format) : -1; } -int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, format_t format) +int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, struct ast_format *format) { return instance->engine->set_write_format ? instance->engine->set_write_format(instance, format) : -1; } @@ -1669,15 +1775,16 @@ int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_in return res; } -format_t ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, format_t to_endpoint, format_t to_asterisk) +void ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result) { - format_t formats; - - if (instance->engine->available_formats && (formats = instance->engine->available_formats(instance, to_endpoint, to_asterisk))) { - return formats; + if (instance->engine->available_formats) { + instance->engine->available_formats(instance, to_endpoint, to_asterisk, result); + if (!ast_format_cap_is_empty(result)) { + return; + } } - return ast_translate_available_formats(to_endpoint, to_asterisk); + ast_translate_available_formats(to_endpoint, to_asterisk, result); } int ast_rtp_instance_activate(struct ast_rtp_instance *instance) diff --git a/main/slinfactory.c b/main/slinfactory.c index 4da443af5810eac3ca7ef81ba85d48c27a96cf18..f7363ab4bdaf6793c3bb8416823fd644c1bf32f2 100644 --- a/main/slinfactory.c +++ b/main/slinfactory.c @@ -36,7 +36,7 @@ void ast_slinfactory_init(struct ast_slinfactory *sf) { memset(sf, 0, sizeof(*sf)); sf->offset = sf->hold; - sf->output_format = AST_FORMAT_SLINEAR; + ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR, 0); } int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_rate) @@ -45,10 +45,10 @@ int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_ra sf->offset = sf->hold; switch (sample_rate) { case 8000: - sf->output_format = AST_FORMAT_SLINEAR; + ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR, 0); break; case 16000: - sf->output_format = AST_FORMAT_SLINEAR16; + ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR16, 0); break; default: return -1; @@ -85,19 +85,19 @@ int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f) return 0; } - if (f->subclass.codec != sf->output_format) { - if (sf->trans && f->subclass.codec != sf->format) { + if (ast_format_cmp(&f->subclass.format, &sf->output_format) == AST_FORMAT_CMP_NOT_EQUAL) { + if (sf->trans && (ast_format_cmp(&f->subclass.format, &sf->format) == AST_FORMAT_CMP_NOT_EQUAL)) { ast_translator_free_path(sf->trans); sf->trans = NULL; } if (!sf->trans) { - if (!(sf->trans = ast_translator_build_path(sf->output_format, f->subclass.codec))) { - ast_log(LOG_WARNING, "Cannot build a path from %s to %s\n", ast_getformatname(f->subclass.codec), - ast_getformatname(sf->output_format)); + if (!(sf->trans = ast_translator_build_path(&sf->output_format, &f->subclass.format))) { + ast_log(LOG_WARNING, "Cannot build a path from %s to %s\n", ast_getformatname(&f->subclass.format), + ast_getformatname(&sf->output_format)); return 0; } - sf->format = f->subclass.codec; + ast_format_copy(&sf->format, &f->subclass.format); } if (!(begin_frame = ast_translate(sf->trans, f, 0))) { diff --git a/main/translate.c b/main/translate.c index 61b4a4686d83065aa83c0ba7eb053e896a00adcf..553e70cde2dc16de3feba5d90fcc1c8493c453f5 100644 --- a/main/translate.c +++ b/main/translate.c @@ -40,31 +40,26 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/cli.h" #include "asterisk/term.h" -#define MAX_RECALC 1000 /* max sample recalc */ +/*! \todo + * TODO: sample frames for each supported input format. + * We build this on the fly, by taking an SLIN frame and using + * the existing converter to play with it. + */ + +/*! max sample recalc */ +#define MAX_RECALC 1000 /*! \brief the list of translators */ static AST_RWLIST_HEAD_STATIC(translators, ast_translator); - -/*! \brief these values indicate how a translation path will affect the sample rate - * - * \note These must stay in this order. They are ordered by most optimal selection first. - */ -enum path_samp_change { - RATE_CHANGE_NONE = 0, /*!< path uses the same sample rate consistently */ - RATE_CHANGE_UPSAMP = 1, /*!< path will up the sample rate during a translation */ - RATE_CHANGE_DOWNSAMP = 2, /*!< path will have to down the sample rate during a translation. */ - RATE_CHANGE_UPSAMP_DOWNSAMP = 3, /*!< path will both up and down the sample rate during translation */ -}; - struct translator_path { - struct ast_translator *step; /*!< Next step translator */ - unsigned int cost; /*!< Complete cost to destination */ - unsigned int multistep; /*!< Multiple conversions required for this translation */ - enum path_samp_change rate_change; /*!< does this path require a sample rate change, if so what kind. */ + struct ast_translator *step; /*!< Next step translator */ + uint32_t table_cost; /*!< Complete table cost to destination */ + uint8_t multistep; /*!< Multiple conversions required for this translation */ }; -/*! \brief a matrix that, for any pair of supported formats, +/*! + * \brief a matrix that, for any pair of supported formats, * indicates the total cost of translation and the first step. * The full path can be reconstricted iterating on the matrix * until step->dstfmt == desired_format. @@ -74,27 +69,202 @@ struct translator_path { * Note: the lock in the 'translators' list is also used to protect * this structure. */ -static struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT]; +static struct translator_path **__matrix; -/*! \todo - * TODO: sample frames for each supported input format. - * We build this on the fly, by taking an SLIN frame and using - * the existing converter to play with it. +/*! + * \brief table for converting index to format id values. + * + * \note this table is protected by the table_lock. */ +static int *__indextable; + +/*! protects the __indextable for resizing */ +static ast_rwlock_t tablelock; + +/* index size starts at this*/ +#define INIT_INDEX 32 +/* index size grows by this as necessary */ +#define GROW_INDEX 16 + +/*! the current largest index used by the __matrix and __indextable arrays*/ +static int cur_max_index; +/*! the largest index that can be used in either the __indextable or __matrix before resize must occur */ +static int index_size; + +static void matrix_rebuild(int samples); -/*! \brief returns the index of the lowest bit set */ -static force_inline int powerof(format_t d) +/*! + * \internal + * \brief converts format id to index value. + */ +static int format2index(enum ast_format_id id) { - int x = ffsll(d); + int x; + + ast_rwlock_rdlock(&tablelock); + for (x = 0; x < cur_max_index; x++) { + if (__indextable[x] == id) { + /* format already exists in index2format table */ + ast_rwlock_unlock(&tablelock); + return x; + } + } + ast_rwlock_unlock(&tablelock); + return -1; /* not found */ +} - if (x) - return x - 1; +/*! + * \internal + * \brief add a new format to the matrix and index table structures. + * + * \note it is perfectly safe to call this on formats already indexed. + * + * \retval 0, success + * \retval -1, matrix and index table need to be resized + */ +static int add_format2index(enum ast_format_id id) +{ + if (format2index(id) != -1) { + /* format is already already indexed */ + return 0; + } + + ast_rwlock_wrlock(&tablelock); + if (cur_max_index == (index_size)) { + ast_rwlock_unlock(&tablelock); + return -1; /* hit max length */ + } + __indextable[cur_max_index] = id; + cur_max_index++; + ast_rwlock_unlock(&tablelock); + + return 0; +} - ast_log(LOG_WARNING, "No bits set? %llu\n", (unsigned long long) d); +/*! + * \internal + * \brief converts index value back to format id + */ +static enum ast_format_id index2format(int index) +{ + enum ast_format_id format_id; + + if (index >= cur_max_index) { + return 0; + } + ast_rwlock_rdlock(&tablelock); + format_id = __indextable[index]; + ast_rwlock_unlock(&tablelock); + + return format_id; +} + +/*! + * \internal + * \brief resize both the matrix and index table so they can represent + * more translators + * + * \note _NO_ locks can be held prior to calling this function + * + * \retval 0, success + * \retval -1, failure. Old matrix and index table can still be used though + */ +static int matrix_resize(int init) +{ + struct translator_path **tmp_matrix = NULL; + int *tmp_table = NULL; + int old_index; + int x; + + AST_RWLIST_WRLOCK(&translators); + ast_rwlock_wrlock(&tablelock); + + old_index = index_size; + if (init) { + index_size += INIT_INDEX; + } else { + index_size += GROW_INDEX; + } + + /* make new 2d array of translator_path structures */ + if (!(tmp_matrix = ast_calloc(1, sizeof(struct translator_path *) * (index_size)))) { + goto resize_cleanup; + } + + for (x = 0; x < index_size; x++) { + if (!(tmp_matrix[x] = ast_calloc(1, sizeof(struct translator_path) * (index_size)))) { + goto resize_cleanup; + } + } + + /* make new index table */ + if (!(tmp_table = ast_calloc(1, sizeof(int) * index_size))) { + goto resize_cleanup; + } + + /* if everything went well this far, free the old and use the new */ + if (!init) { + for (x = 0; x < old_index; x++) { + ast_free(__matrix[x]); + } + ast_free(__matrix); + + memcpy(tmp_table, __indextable, sizeof(int) * old_index); + ast_free(__indextable); + } + + /* now copy them over */ + __matrix = tmp_matrix; + __indextable = tmp_table; + + matrix_rebuild(0); + ast_rwlock_unlock(&tablelock); + AST_RWLIST_UNLOCK(&translators); + + return 0; + +resize_cleanup: + ast_rwlock_unlock(&tablelock); + AST_RWLIST_UNLOCK(&translators); + if (tmp_matrix) { + for (x = 0; x < index_size; x++) { + ast_free(tmp_matrix[x]); + } + ast_free(tmp_matrix); + } + ast_free(tmp_table); return -1; } +/*! + * \internal + * \brief reinitialize the __matrix during matrix rebuild + * + * \note must be protected by the translators list lock + */ +static void matrix_clear(void) +{ + int x; + for (x = 0; x < index_size; x++) { + memset(__matrix[x], '\0', sizeof(struct translator_path) * (index_size)); + } +} + +/*! + * \internal + * \brief get a matrix entry + * + * \note This function must be protected by the translators list lock + */ +static struct translator_path *matrix_get(unsigned int x, unsigned int y) +{ + if (!(x >= 0 && y >= 0)) { + return NULL; + } + return __matrix[x] + y; +} + /* * wrappers around the translator routines. */ @@ -151,7 +321,7 @@ static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f) { int ret; int samples = pvt->samples; /* initial value */ - + /* Copy the last in jb timing info to the pvt */ ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO); pvt->f.ts = f->ts; @@ -193,23 +363,23 @@ struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt, { struct ast_frame *f = &pvt->f; - if (samples) + if (samples) { f->samples = samples; - else { + } else { if (pvt->samples == 0) return NULL; f->samples = pvt->samples; pvt->samples = 0; } - if (datalen) + if (datalen) { f->datalen = datalen; - else { + } else { f->datalen = pvt->datalen; pvt->datalen = 0; } f->frametype = AST_FRAME_VOICE; - f->subclass.codec = 1LL << (pvt->t->dstfmt); + ast_format_copy(&f->subclass.format, &pvt->t->dst_format); f->mallocd = 0; f->offset = AST_FRIENDLY_OFFSET; f->src = pvt->t->name; @@ -235,45 +405,56 @@ void ast_translator_free_path(struct ast_trans_pvt *p) } /*! \brief Build a chain of translators based upon the given source and dest formats */ -struct ast_trans_pvt *ast_translator_build_path(format_t dest, format_t source) +struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct ast_format *src) { struct ast_trans_pvt *head = NULL, *tail = NULL; - - source = powerof(source); - dest = powerof(dest); + int src_index, dst_index; + struct ast_format tmp_fmt1; + struct ast_format tmp_fmt2; + + src_index = format2index(src->id); + dst_index = format2index(dst->id); - if (source == -1 || dest == -1) { - ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending"); + if (src_index == -1 || dst_index == -1) { + ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index == -1 ? "starting" : "ending"); return NULL; } AST_RWLIST_RDLOCK(&translators); - while (source != dest) { + while (src_index != dst_index) { struct ast_trans_pvt *cur; - struct ast_translator *t = tr_matrix[source][dest].step; + struct ast_translator *t = matrix_get(src_index, dst_index)->step; if (!t) { - ast_log(LOG_WARNING, "No translator path from %s to %s\n", - ast_getformatname(source), ast_getformatname(dest)); + int src_id = index2format(src_index); + int dst_id = index2format(dst_index); + ast_log(LOG_WARNING, "No translator path from %s to %s\n", + ast_getformatname(ast_format_set(&tmp_fmt1, src_id, 0)), + ast_getformatname(ast_format_set(&tmp_fmt2, dst_id, 0))); AST_RWLIST_UNLOCK(&translators); return NULL; } if (!(cur = newpvt(t))) { + int src_id = index2format(src_index); + int dst_id = index2format(dst_index); ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n", - ast_getformatname(source), ast_getformatname(dest)); - if (head) - ast_translator_free_path(head); + ast_getformatname(ast_format_set(&tmp_fmt1, src_id, 0)), + ast_getformatname(ast_format_set(&tmp_fmt2, dst_id, 0))); + if (head) { + ast_translator_free_path(head); + } AST_RWLIST_UNLOCK(&translators); return NULL; } - if (!head) + if (!head) { head = cur; - else + } else { tail->next = cur; + } tail = cur; cur->nextin = cur->nextout = ast_tv(0, 0); /* Keep going if this isn't the final destination */ - source = cur->t->dstfmt; + src_index = cur->t->dst_fmt_index; } AST_RWLIST_UNLOCK(&translators); @@ -284,7 +465,7 @@ struct ast_trans_pvt *ast_translator_build_path(format_t dest, format_t source) struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume) { struct ast_trans_pvt *p = path; - struct ast_frame *out = f; + struct ast_frame *out; struct timeval delivery; int has_timing_info; long ts; @@ -296,7 +477,6 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, len = f->len; seqno = f->seqno; - /* XXX hmmm... check this below */ if (!ast_tvzero(f->delivery)) { if (!ast_tvzero(path->nextin)) { /* Make sure this is in line with what we were expecting */ @@ -316,31 +496,35 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, path->nextout = f->delivery; } /* Predict next incoming sample */ - path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass.codec))); + path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(&f->subclass.format))); } delivery = f->delivery; - for ( ; out && p ; p = p->next) { + for (out = f; out && p ; p = p->next) { framein(p, out); - if (out != f) + if (out != f) { ast_frfree(out); + } out = p->t->frameout(p); } - if (consume) + if (consume) { ast_frfree(f); - if (out == NULL) + } + if (out == NULL) { return NULL; + } /* we have a frame, play with times */ if (!ast_tvzero(delivery)) { /* Regenerate prediction after a discontinuity */ - if (ast_tvzero(path->nextout)) + if (ast_tvzero(path->nextout)) { path->nextout = ast_tvnow(); + } /* Use next predicted outgoing timestamp */ out->delivery = path->nextout; - + /* Predict next outgoing timestamp from samples in this frame. */ - path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass.codec))); + path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(&out->subclass.format))); } else { out->delivery = ast_tv(0, 0); ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO); @@ -351,35 +535,45 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, } } /* Invalidate prediction if we're entering a silence period */ - if (out->frametype == AST_FRAME_CNG) + if (out->frametype == AST_FRAME_CNG) { path->nextout = ast_tv(0, 0); + } return out; } -/*! \brief compute the cost of a single translation step */ -static void calc_cost(struct ast_translator *t, int seconds) +/*! + * \internal + * \brief Compute the computational cost of a single translation step. + * + * \note This function is only used to decide which translation path to + * use between two translators with identical src and dst formats. Computational + * cost acts only as a tie breaker. This is done so hardware translators + * can naturally have precedence over software translators. + */ +static void generate_computational_cost(struct ast_translator *t, int seconds) { int num_samples = 0; struct ast_trans_pvt *pvt; struct rusage start; struct rusage end; int cost; - int out_rate = ast_format_rate(t->dstfmt); + int out_rate = ast_format_rate(&t->dst_format); - if (!seconds) + if (!seconds) { seconds = 1; - + } + /* If they don't make samples, give them a terrible score */ if (!t->sample) { ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); - t->cost = 999999; + t->comp_cost = 999999; return; } pvt = newpvt(t); if (!pvt) { ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); - t->cost = 999999; + t->comp_cost = 999999; return; } @@ -391,7 +585,7 @@ static void calc_cost(struct ast_translator *t, int seconds) if (!f) { ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); destroy(pvt); - t->cost = 999999; + t->comp_cost = 999999; return; } framein(pvt, f); @@ -409,72 +603,127 @@ static void calc_cost(struct ast_translator *t, int seconds) destroy(pvt); - t->cost = cost / seconds; + t->comp_cost = cost / seconds; - if (!t->cost) - t->cost = 1; + if (!t->comp_cost) { + t->comp_cost = 1; + } } -static enum path_samp_change get_rate_change_result(format_t src, format_t dst) +/*! + * \internal + * + * \brief If no table cost value was pre set by the translator. An attempt is made to + * automatically generate that cost value from the cost table based on our src and + * dst formats. + * + * \note This function allows older translators built before the translation cost + * changed away from using onely computational time to continue to be registered + * correctly. It is expected that translators built after the introduction of this + * function will manually assign their own table cost value. + * + * \note This function is safe to use on any audio formats that used to be defined in the + * first 64 bits of the old bit field codec representation. + * + * \retval Table Cost value greater than 0. + * \retval 0 on error. + */ +static int generate_table_cost(struct ast_format *src, struct ast_format *dst) { int src_rate = ast_format_rate(src); + int src_ll = 0; int dst_rate = ast_format_rate(dst); + int dst_ll = 0; - /* if src rate is less than dst rate, a sample upgrade is required */ - if (src_rate < dst_rate) { - return RATE_CHANGE_UPSAMP; + if ((AST_FORMAT_GET_TYPE(src->id) != AST_FORMAT_TYPE_AUDIO) || (AST_FORMAT_GET_TYPE(dst->id) != AST_FORMAT_TYPE_AUDIO)) { + /* This method of generating table cost is limited to audio. + * Translators for media other than audio must manually set their + * table cost. */ + return 0; } - - /* if src rate is larger than dst rate, a downgrade is required */ - if (src_rate > dst_rate) { - return RATE_CHANGE_DOWNSAMP; + if ((src->id == AST_FORMAT_SLINEAR) || (src->id == AST_FORMAT_SLINEAR16)) { + src_ll = 1; + } + if ((dst->id == AST_FORMAT_SLINEAR) || (dst->id == AST_FORMAT_SLINEAR16)) { + dst_ll = 1; } - return RATE_CHANGE_NONE; + if (src_ll) { + if (dst_ll && (src_rate == dst_rate)) { + return AST_TRANS_COST_LL_LL_ORIGSAMP; + } else if (!dst_ll && (src_rate == dst_rate)) { + return AST_TRANS_COST_LL_LY_ORIGSAMP; + } else if (dst_ll && (src_rate < dst_rate)) { + return AST_TRANS_COST_LL_LL_UPSAMP; + } else if (!dst_ll && (src_rate < dst_rate)) { + return AST_TRANS_COST_LL_LY_UPSAMP; + } else if (dst_ll && (src_rate > dst_rate)) { + return AST_TRANS_COST_LL_LL_DOWNSAMP; + } else if (!dst_ll && (src_rate > dst_rate)) { + return AST_TRANS_COST_LL_LY_DOWNSAMP; + } else { + return AST_TRANS_COST_LL_UNKNOWN; + } + } else { + if (dst_ll && (src_rate == dst_rate)) { + return AST_TRANS_COST_LY_LL_ORIGSAMP; + } else if (!dst_ll && (src_rate == dst_rate)) { + return AST_TRANS_COST_LY_LY_ORIGSAMP; + } else if (dst_ll && (src_rate < dst_rate)) { + return AST_TRANS_COST_LY_LL_UPSAMP; + } else if (!dst_ll && (src_rate < dst_rate)) { + return AST_TRANS_COST_LY_LY_UPSAMP; + } else if (dst_ll && (src_rate > dst_rate)) { + return AST_TRANS_COST_LY_LL_DOWNSAMP; + } else if (!dst_ll && (src_rate > dst_rate)) { + return AST_TRANS_COST_LY_LY_DOWNSAMP; + } else { + return AST_TRANS_COST_LY_UNKNOWN; + } + } } /*! * \brief rebuild a translation matrix. * \note This function expects the list of translators to be locked */ -static void rebuild_matrix(int samples) +static void matrix_rebuild(int samples) { struct ast_translator *t; - int new_rate_change; - int newcost; + int newtablecost; int x; /* source format index */ int y; /* intermediate format index */ int z; /* destination format index */ ast_debug(1, "Resetting translation matrix\n"); - memset(tr_matrix, '\0', sizeof(tr_matrix)); + matrix_clear(); /* first, compute all direct costs */ AST_RWLIST_TRAVERSE(&translators, t, list) { - if (!t->active) + if (!t->active) { continue; + } - x = t->srcfmt; - z = t->dstfmt; - - if (samples) - calc_cost(t, samples); + x = t->src_fmt_index; + z = t->dst_fmt_index; - new_rate_change = get_rate_change_result(1LL << t->srcfmt, 1LL << t->dstfmt); + if (samples) { + generate_computational_cost(t, samples); + } - /* this translator is the best choice if any of the below are true. + /* This new translator is the best choice if any of the below are true. * 1. no translation path is set between x and z yet. - * 2. the new translation costs less and sample rate is no worse than old one. - * 3. the new translation has a better sample rate conversion than the old one. + * 2. the new table cost is less. + * 3. the new computational cost is less. Computational cost is only used + * to break a tie between two identical translation paths. */ - if (!tr_matrix[x][z].step || - ((t->cost < tr_matrix[x][z].cost) && (new_rate_change <= tr_matrix[x][z].rate_change)) || - (new_rate_change < tr_matrix[x][z].rate_change)) { + if (!matrix_get(x, z)->step || + (t->table_cost < matrix_get(x, z)->step->table_cost) || + (t->comp_cost < matrix_get(x, z)->step->comp_cost)) { - tr_matrix[x][z].step = t; - tr_matrix[x][z].cost = t->cost; - tr_matrix[x][z].rate_change = new_rate_change; + matrix_get(x, z)->step = t; + matrix_get(x, z)->table_cost = t->table_cost; } } @@ -486,81 +735,43 @@ static void rebuild_matrix(int samples) */ for (;;) { int changed = 0; - int better_choice = 0; - for (x = 0; x < MAX_FORMAT; x++) { /* source format */ - for (y = 0; y < MAX_FORMAT; y++) { /* intermediate format */ - if (x == y) /* skip ourselves */ + for (x = 0; x < cur_max_index; x++) { /* source format */ + for (y = 0; y < cur_max_index; y++) { /* intermediate format */ + if (x == y) { /* skip ourselves */ continue; - for (z = 0; z < MAX_FORMAT; z++) { /* dst format */ - if (z == x || z == y) /* skip null conversions */ - continue; - if (!tr_matrix[x][y].step) /* no path from x to y */ - continue; - if (!tr_matrix[y][z].step) /* no path from y to z */ - continue; - - /* Does x->y->z result in a less optimal sample rate change? - * Never downgrade the sample rate conversion quality regardless - * of any cost improvements */ - if (tr_matrix[x][z].step && - ((tr_matrix[x][z].rate_change < tr_matrix[x][y].rate_change) || - (tr_matrix[x][z].rate_change < tr_matrix[y][z].rate_change))) { + } + for (z = 0; z < cur_max_index; z++) { /* dst format */ + if ((z == x || z == y) || /* skip null conversions */ + !matrix_get(x, y)->step || /* no path from x to y */ + !matrix_get(y, z)->step) { /* no path from y to z */ continue; } - /* is x->y->z a better sample rate confersion that the current x->z? */ - new_rate_change = tr_matrix[x][y].rate_change + tr_matrix[y][z].rate_change; - - /* calculate cost from x->y->z */ - newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; - - /* Is x->y->z a better choice than x->z? - * There are three conditions for x->y->z to be a better choice than x->z - * 1. if there is no step directly between x->z then x->y->z is the best and only current option. - * 2. if x->y->z costs less and the sample rate conversion is no less optimal. - * 3. if x->y->z results in a more optimal sample rate conversion. */ - if (!tr_matrix[x][z].step) { - better_choice = 1; - } else if ((newcost < tr_matrix[x][z].cost) && (new_rate_change <= tr_matrix[x][z].rate_change)) { - better_choice = 1; - } else if (new_rate_change < tr_matrix[x][z].rate_change) { - better_choice = 1; - } else { - better_choice = 0; + /* calculate table cost from x->y->z */ + newtablecost = matrix_get(x, y)->table_cost + matrix_get(y, z)->table_cost; + + /* if no step already exists between x and z OR the new cost of using the intermediate + * step is cheaper, use this step. */ + if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) { + struct ast_format tmpx; + struct ast_format tmpy; + struct ast_format tmpz; + matrix_get(x, z)->step = matrix_get(x, y)->step; + matrix_get(x, z)->table_cost = newtablecost; + matrix_get(x, z)->multistep = 1; + changed++; + ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", + matrix_get(x, z)->table_cost, + ast_getformatname(ast_format_set(&tmpx, index2format(x), 0)), + ast_getformatname(ast_format_set(&tmpy, index2format(z), 0)), + ast_getformatname(ast_format_set(&tmpz, index2format(y), 0))); } - - if (!better_choice) { - continue; - } - /* ok, we can get from x to z via y with a cost that - is the sum of the transition from x to y and from y to z */ - tr_matrix[x][z].step = tr_matrix[x][y].step; - tr_matrix[x][z].cost = newcost; - tr_matrix[x][z].multistep = 1; - - /* now calculate what kind of sample rate change is required for this multi-step path - * - * if both paths require a change in rate, and they are not in the same direction - * then this is a up sample down sample conversion scenario. */ - if ((tr_matrix[x][y].rate_change > RATE_CHANGE_NONE) && - (tr_matrix[y][z].rate_change > RATE_CHANGE_NONE) && - (tr_matrix[x][y].rate_change != tr_matrix[y][z].rate_change)) { - - tr_matrix[x][z].rate_change = RATE_CHANGE_UPSAMP_DOWNSAMP; - } else { - /* else just set the rate change to whichever is worse */ - tr_matrix[x][z].rate_change = tr_matrix[x][y].rate_change > tr_matrix[y][z].rate_change - ? tr_matrix[x][y].rate_change : tr_matrix[y][z].rate_change; - } - - ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost, - ast_getformatname(1LL << x), ast_getformatname(1LL << z), ast_getformatname(1LL << y)); - changed++; } } } - if (!changed) + if (!changed) { break; + } } } @@ -572,11 +783,11 @@ const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str ** return ""; } - ast_str_set(str, 0, "%s", ast_getformatname(1LL << p->t->srcfmt)); + ast_str_set(str, 0, "%s", ast_getformatname(&p->t->src_format)); while ( (p = pn) ) { pn = p->next; - ast_str_append(str, 0, "->%s", ast_getformatname(1LL << p->t->dstfmt)); + ast_str_append(str, 0, "->%s", ast_getformatname(&p->t->dst_format)); } return ast_str_buffer(*str); @@ -592,7 +803,7 @@ static char *complete_trans_path_choice(const char *line, const char *word, int const struct ast_format_list *format_list = ast_get_format_list(&len); for (i = 0; i < len; i++) { - if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) { + if (AST_FORMAT_GET_TYPE(format_list[i].id) != AST_FORMAT_TYPE_AUDIO) { continue; } if (!strncasecmp(word, format_list[i].name, wordlen) && ++which > state) { @@ -603,165 +814,81 @@ static char *complete_trans_path_choice(const char *line, const char *word, int return ret; } -static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +static void handle_cli_recalc(struct ast_cli_args *a) { -#define SHOW_TRANS 64 - static const char * const option1[] = { "recalc", "paths", NULL }; - int x, y, z; - int curlen = 0, longest = 0, magnitude[SHOW_TRANS] = { 0, }; + int time = a->argv[4] ? atoi(a->argv[4]) : 1; - switch (cmd) { - case CLI_INIT: - e->command = "core show translation"; - e->usage = - "Usage: 'core show translation' can be used in two ways.\n" - " 1. 'core show translation [recalc [<recalc seconds>]]\n" - " Displays known codec translators and the cost associated\n" - " with each conversion. If the argument 'recalc' is supplied along\n" - " with optional number of seconds to test a new test will be performed\n" - " as the chart is being displayed.\n" - " 2. 'core show translation paths [codec]'\n" - " This will display all the translation paths associated with a codec\n"; - return NULL; - case CLI_GENERATE: - if (a->pos == 3) { - return ast_cli_complete(a->word, option1, a->n); - } - if (a->pos == 4 && !strcasecmp(a->argv[3], option1[1])) { - return complete_trans_path_choice(a->line, a->word, a->pos, a->n); - } - return NULL; + if (time <= 0) { + ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n"); + time = 1; } - if (a->argc > 5) - return CLI_SHOWUSAGE; - - if (a->argv[3] && !strcasecmp(a->argv[3], option1[1]) && a->argc == 5) { - format_t input_src = 0; - format_t src = 0; - size_t len = 0; - int dst; - int i; - const struct ast_format_list *format_list = ast_get_format_list(&len); - struct ast_str *str = ast_str_alloca(256); - struct ast_translator *step; - - for (i = 0; i < len; i++) { - if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) { - continue; - } - if (!strncasecmp(format_list[i].name, a->argv[4], strlen(format_list[i].name))) { - input_src = format_list[i].bits; - } - } - - if (!input_src) { - ast_cli(a->fd, "Source codec \"%s\" is not found.\n", a->argv[4]); - return CLI_FAILURE; - } - - AST_RWLIST_RDLOCK(&translators); - ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %d ---\n", a->argv[4], ast_format_rate(input_src)); - for (i = 0; i < len; i++) { - if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK) || (format_list[i].bits == input_src)) { - continue; - } - dst = powerof(format_list[i].bits); - src = powerof(input_src); - ast_str_reset(str); - if (tr_matrix[src][dst].step) { - ast_str_append(&str, 0, "%s", ast_getformatname(1LL << tr_matrix[src][dst].step->srcfmt)); - while (src != dst) { - step = tr_matrix[src][dst].step; - if (!step) { - ast_str_reset(str); - break; - } - ast_str_append(&str, 0, "->%s", ast_getformatname(1LL << step->dstfmt)); - src = step->dstfmt; - } - } - - if (ast_strlen_zero(ast_str_buffer(str))) { - ast_str_set(&str, 0, "No Translation Path"); - } - - ast_cli(a->fd, "\t%-10.10s To %-10.10s: %-60.60s\n", a->argv[4], format_list[i].name, ast_str_buffer(str)); - } - AST_RWLIST_UNLOCK(&translators); - - return CLI_SUCCESS; - } else if (a->argv[3] && !strcasecmp(a->argv[3], "recalc")) { - z = a->argv[4] ? atoi(a->argv[4]) : 1; - - if (z <= 0) { - ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n"); - z = 1; - } - - if (z > MAX_RECALC) { - ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); - z = MAX_RECALC; - } - ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); - AST_RWLIST_WRLOCK(&translators); - rebuild_matrix(z); - AST_RWLIST_UNLOCK(&translators); - } else if (a->argc > 3) - return CLI_SHOWUSAGE; + if (time > MAX_RECALC) { + ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", time - MAX_RECALC, MAX_RECALC); + time = MAX_RECALC; + } + ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", time); + AST_RWLIST_WRLOCK(&translators); + matrix_rebuild(time); + AST_RWLIST_UNLOCK(&translators); +} +static char *handle_show_translation_table(struct ast_cli_args *a) +{ + int x, y; + int curlen = 0, longest = 0; + struct ast_format tmp_fmt; AST_RWLIST_RDLOCK(&translators); - ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n"); ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n"); + /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ - for (x = 0; x < SHOW_TRANS; x++) { + for (x = 0; x < cur_max_index; x++) { /* translation only applies to audio right now. */ - if (!(AST_FORMAT_AUDIO_MASK & (1LL << (x)))) + if (AST_FORMAT_GET_TYPE(index2format(x)) != AST_FORMAT_TYPE_AUDIO) continue; - curlen = strlen(ast_getformatname(1LL << (x))); - if (curlen > longest) + curlen = strlen(ast_getformatname(ast_format_set(&tmp_fmt, index2format(x), 0))); + if (curlen > longest) { longest = curlen; - for (y = 0; y < SHOW_TRANS; y++) { - if (!(AST_FORMAT_AUDIO_MASK & (1LL << (y)))) - continue; - if (tr_matrix[x][y].cost > pow(10, magnitude[x])) { - magnitude[y] = floor(log10(tr_matrix[x][y].cost)); - } } } - for (x = -1; x < SHOW_TRANS; x++) { + + for (x = -1; x < cur_max_index; x++) { struct ast_str *out = ast_str_alloca(256); /* translation only applies to audio right now. */ - if (x >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (x)))) + if (x >= 0 && (AST_FORMAT_GET_TYPE(index2format(x)) != AST_FORMAT_TYPE_AUDIO)) { continue; + } /*Go ahead and move to next iteration if dealing with an unknown codec*/ - if(x >= 0 && !strcmp(ast_getformatname(1LL << (x)), "unknown")) + if (x >= 0 && !strcmp(ast_getformatname(ast_format_set(&tmp_fmt, index2format(x), 0)), "unknown")) { continue; + } ast_str_set(&out, -1, " "); - for (y = -1; y < SHOW_TRANS; y++) { + for (y = -1; y < cur_max_index; y++) { /* translation only applies to audio right now. */ - if (y >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (y)))) + if (y >= 0 && (AST_FORMAT_GET_TYPE(index2format(y)) != AST_FORMAT_TYPE_AUDIO)) { continue; + } /*Go ahead and move to next iteration if dealing with an unknown codec*/ - if (y >= 0 && !strcmp(ast_getformatname(1LL << (y)), "unknown")) + if (y >= 0 && !strcmp(ast_getformatname(ast_format_set(&tmp_fmt, index2format(y), 0)), "unknown")) { continue; - if (y >= 0) - curlen = strlen(ast_getformatname(1LL << (y))); - if (y >= 0 && magnitude[y] + 1 > curlen) { - curlen = magnitude[y] + 1; } - if (curlen < 5) + if (y >= 0) { + curlen = strlen(ast_getformatname(ast_format_set(&tmp_fmt, index2format(y), 0))); + } + if (curlen < 5) { curlen = 5; - if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { + } + + if (x >= 0 && y >= 0 && matrix_get(x, y)->step) { /* Actual codec output */ - ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost); + ast_str_append(&out, -1, "%*d", curlen + 1, (matrix_get(x, y)->table_cost/100)); } else if (x == -1 && y >= 0) { /* Top row - use a dynamic size */ - ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1LL << (y)) ); + ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(ast_format_set(&tmp_fmt, index2format(y), 0))); } else if (y == -1 && x >= 0) { /* Left column - use a static size. */ - ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1LL << (x)) ); + ast_str_append(&out, -1, "%*s", longest, ast_getformatname(ast_format_set(&tmp_fmt, index2format(x), 0))); } else if (x >= 0 && y >= 0) { /* Codec not supported */ ast_str_append(&out, -1, "%*s", curlen + 1, "-"); @@ -777,6 +904,106 @@ static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, return CLI_SUCCESS; } +static char *handle_show_translation_path(struct ast_cli_args *a) +{ + struct ast_format input_src_format; + size_t len = 0; + int i; + const struct ast_format_list *format_list = ast_get_format_list(&len); + struct ast_str *str = ast_str_alloca(256); + struct ast_translator *step; + + ast_format_clear(&input_src_format); + + for (i = 0; i < len; i++) { + if (AST_FORMAT_GET_TYPE(format_list[i].id) != AST_FORMAT_TYPE_AUDIO) { + continue; + } + if (!strncasecmp(format_list[i].name, a->argv[4], strlen(format_list[i].name))) { + ast_format_set(&input_src_format, format_list[i].id, 0); + } + } + + if (!input_src_format.id) { + ast_cli(a->fd, "Source codec \"%s\" is not found.\n", a->argv[4]); + return CLI_FAILURE; + } + + AST_RWLIST_RDLOCK(&translators); + ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %d ---\n", a->argv[4], ast_format_rate(&input_src_format)); + for (i = 0; i < len; i++) { + int src; + int dst; + if ((AST_FORMAT_GET_TYPE(format_list[i].id) != AST_FORMAT_TYPE_AUDIO) || (format_list[i].id == input_src_format.id)) { + continue; + } + dst = format2index(format_list[i].id); + src = format2index(input_src_format.id); + ast_str_reset(str); + if ((len >= cur_max_index) && (src != -1) && (dst != -1) && matrix_get(src, dst)->step) { + ast_str_append(&str, 0, "%s", ast_getformatname(&matrix_get(src, dst)->step->src_format)); + while (src != dst) { + step = matrix_get(src, dst)->step; + if (!step) { + ast_str_reset(str); + break; + } + ast_str_append(&str, 0, "->%s", ast_getformatname(&step->dst_format)); + src = step->dst_fmt_index; + } + } + + if (ast_strlen_zero(ast_str_buffer(str))) { + ast_str_set(&str, 0, "No Translation Path"); + } + ast_cli(a->fd, "\t%-10.10s To %-10.10s: %-60.60s\n", a->argv[4], format_list[i].name, ast_str_buffer(str)); + } + AST_RWLIST_UNLOCK(&translators); + + return CLI_SUCCESS; +} + +static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + static const char * const option[] = { "recalc", "paths", NULL }; + + switch (cmd) { + case CLI_INIT: + e->command = "core show translation"; + e->usage = + "Usage: 'core show translation' can be used in two ways.\n" + " 1. 'core show translation [recalc [<recalc seconds>]]\n" + " Displays known codec translators and the cost associated\n" + " with each conversion. If the argument 'recalc' is supplied along\n" + " with optional number of seconds to test a new test will be performed\n" + " as the chart is being displayed.\n" + " 2. 'core show translation paths [codec]'\n" + " This will display all the translation paths associated with a codec\n"; + return NULL; + case CLI_GENERATE: + if (a->pos == 3) { + return ast_cli_complete(a->word, option, a->n); + } + if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) { + return complete_trans_path_choice(a->line, a->word, a->pos, a->n); + } + return NULL; + } + + if (a->argc > 5) + return CLI_SHOWUSAGE; + + if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */ + return handle_show_translation_path(a); + } else if (a->argv[3] && !strcasecmp(a->argv[3], option[0])) { /* recalc and then fall through to show table */ + handle_cli_recalc(a); + } else if (a->argc > 3) { /* wrong input */ + return CLI_SHOWUSAGE; + } + + return handle_show_translation_table(a); +} + static struct ast_cli_entry cli_translate[] = { AST_CLI_DEFINE(handle_cli_core_show_translation, "Display translation matrix") }; @@ -784,10 +1011,18 @@ static struct ast_cli_entry cli_translate[] = { /*! \brief register codec translator */ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod) { - static int added_cli = 0; struct ast_translator *u; char tmp[80]; + if (add_format2index(t->src_format.id) || add_format2index(t->dst_format.id)) { + if (matrix_resize(0)) { + ast_log(LOG_WARNING, "Translator matrix can not represent any more translators. Out of resources.\n"); + return -1; + } + add_format2index(t->src_format.id); + add_format2index(t->dst_format.id); + } + if (!mod) { ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); return -1; @@ -797,24 +1032,28 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod) ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); return -1; } + if (!t->table_cost && !(t->table_cost = generate_table_cost(&t->src_format, &t->dst_format))) { + ast_log(LOG_WARNING, "Table cost could not be generated for %s, " + "Please set table_cost variable on translator.\n", t->name); + return -1; + } t->module = mod; - - t->srcfmt = powerof(t->srcfmt); - t->dstfmt = powerof(t->dstfmt); + t->src_fmt_index = format2index(t->src_format.id); + t->dst_fmt_index = format2index(t->dst_format.id); t->active = 1; - if (t->srcfmt == -1 || t->dstfmt == -1) { - ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending"); + if (t->src_fmt_index == -1 || t->dst_fmt_index == -1) { + ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->src_fmt_index == -1 ? "starting" : "ending"); return -1; } - if (t->srcfmt >= MAX_FORMAT) { - ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); + if (t->src_fmt_index >= cur_max_index) { + ast_log(LOG_WARNING, "Source format %s is larger than cur_max_index\n", ast_getformatname(&t->src_format)); return -1; } - if (t->dstfmt >= MAX_FORMAT) { - ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); + if (t->dst_fmt_index >= cur_max_index) { + ast_log(LOG_WARNING, "Destination format %s is larger than cur_max_index\n", ast_getformatname(&t->dst_format)); return -1; } @@ -829,28 +1068,24 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod) t->buf_size = ((t->buf_size + align - 1) / align) * align; } - if (t->frameout == NULL) + if (t->frameout == NULL) { t->frameout = default_frameout; - - calc_cost(t, 1); + } - ast_verb(2, "Registered translator '%s' from format %s to %s, cost %d\n", - term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), - ast_getformatname(1LL << t->srcfmt), ast_getformatname(1LL << t->dstfmt), t->cost); + generate_computational_cost(t, 1); - if (!added_cli) { - ast_cli_register_multiple(cli_translate, ARRAY_LEN(cli_translate)); - added_cli++; - } + ast_verb(2, "Registered translator '%s' from format %s to %s, table cost, %d, computational cost %d\n", + term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), + ast_getformatname(&t->src_format), ast_getformatname(&t->dst_format), t->table_cost, t->comp_cost); AST_RWLIST_WRLOCK(&translators); /* find any existing translators that provide this same srcfmt/dstfmt, - and put this one in order based on cost */ + and put this one in order based on computational cost */ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { - if ((u->srcfmt == t->srcfmt) && - (u->dstfmt == t->dstfmt) && - (u->cost > t->cost)) { + if ((u->src_fmt_index == t->src_fmt_index) && + (u->dst_fmt_index == t->dst_fmt_index) && + (u->comp_cost > t->comp_cost)) { AST_RWLIST_INSERT_BEFORE_CURRENT(t, list); t = NULL; break; @@ -860,10 +1095,11 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod) /* if no existing translator was found for this format combination, add it to the beginning of the list */ - if (t) + if (t) { AST_RWLIST_INSERT_HEAD(&translators, t, list); + } - rebuild_matrix(0); + matrix_rebuild(0); AST_RWLIST_UNLOCK(&translators); @@ -881,15 +1117,19 @@ int ast_unregister_translator(struct ast_translator *t) AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { if (u == t) { AST_RWLIST_REMOVE_CURRENT(list); - ast_verb(2, "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1LL << t->srcfmt), ast_getformatname(1LL << t->dstfmt)); + ast_verb(2, "Unregistered translator '%s' from format %s to %s\n", + term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), + ast_getformatname(&t->src_format), + ast_getformatname(&t->dst_format)); found = 1; break; } } AST_RWLIST_TRAVERSE_SAFE_END; - if (found) - rebuild_matrix(0); + if (found) { + matrix_rebuild(0); + } AST_RWLIST_UNLOCK(&translators); @@ -900,7 +1140,7 @@ void ast_translator_activate(struct ast_translator *t) { AST_RWLIST_WRLOCK(&translators); t->active = 1; - rebuild_matrix(0); + matrix_rebuild(0); AST_RWLIST_UNLOCK(&translators); } @@ -908,93 +1148,93 @@ void ast_translator_deactivate(struct ast_translator *t) { AST_RWLIST_WRLOCK(&translators); t->active = 0; - rebuild_matrix(0); + matrix_rebuild(0); AST_RWLIST_UNLOCK(&translators); } /*! \brief Calculate our best translator source format, given costs, and a desired destination */ -format_t ast_translator_best_choice(format_t *dst, format_t *srcs) +int ast_translator_best_choice(struct ast_format_cap *dst_cap, + struct ast_format_cap *src_cap, + struct ast_format *dst_fmt_out, + struct ast_format *src_fmt_out) { - int x,y; - int better = 0; - int besttime = INT_MAX; - int beststeps = INT_MAX; - unsigned int best_rate_change = INT_MAX; - format_t best = -1; - format_t bestdst = 0; - format_t cur, cursrc; - format_t common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */ - - if (common) { /* yes, pick one and return */ - for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { - if (!(cur & common)) { - continue; - } - + unsigned int besttablecost = INT_MAX; + unsigned int beststeps = INT_MAX; + struct ast_format best; + struct ast_format bestdst; + struct ast_format_cap *joint_cap = ast_format_cap_joint(dst_cap, src_cap); + ast_format_clear(&best); + ast_format_clear(&bestdst); + + if (joint_cap) { /* yes, pick one and return */ + struct ast_format tmp_fmt; + ast_format_cap_iter_start(joint_cap); + while (!ast_format_cap_iter_next(joint_cap, &tmp_fmt)) { /* We are guaranteed to find one common format. */ - if (best == -1) { - best = cur; + if (!best.id) { + ast_format_copy(&best, &tmp_fmt); continue; } /* If there are multiple common formats, pick the one with the highest sample rate */ - if (ast_format_rate(best) < ast_format_rate(cur)) { - best = cur; + if (ast_format_rate(&best) < ast_format_rate(&tmp_fmt)) { + ast_format_copy(&best, &tmp_fmt); continue; } + } + ast_format_cap_iter_end(joint_cap); + /* We are done, this is a common format to both. */ - *srcs = *dst = best; + ast_format_copy(dst_fmt_out, &best); + ast_format_copy(src_fmt_out, &best); + ast_format_cap_destroy(joint_cap); return 0; } else { /* No, we will need to translate */ + struct ast_format cur_dst; + struct ast_format cur_src; AST_RWLIST_RDLOCK(&translators); - for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { - if (! (cur & *dst)) { - continue; - } - for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) { - if (!(*srcs & cursrc) || !tr_matrix[x][y].step) { - continue; - } - /* This is a better choice if any of the following are true. - * 1. The sample rate conversion is better than the current pick. - * 2. the sample rate conversion is no worse than the current pick and the cost or multistep is better - */ - better = 0; - if (tr_matrix[x][y].rate_change < best_rate_change) { - better = 1; /* this match has a better rate conversion */ + ast_format_cap_iter_start(dst_cap); + while (!ast_format_cap_iter_next(dst_cap, &cur_dst)) { + ast_format_cap_iter_start(src_cap); + while (!ast_format_cap_iter_next(src_cap, &cur_src)) { + int x = format2index(cur_src.id); + int y = format2index(cur_dst.id); + if (x < 0 || y < 0) { + continue; } - if ((tr_matrix[x][y].rate_change <= best_rate_change) && - (tr_matrix[x][y].cost < besttime || tr_matrix[x][y].multistep < beststeps)) { - better = 1; /* this match has no worse rate conversion and the conversion cost is less */ + if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) { + continue; } - if (better) { + if (((matrix_get(x, y)->table_cost < besttablecost) || (matrix_get(x, y)->multistep < beststeps))) { /* better than what we have so far */ - best = cursrc; - bestdst = cur; - besttime = tr_matrix[x][y].cost; - beststeps = tr_matrix[x][y].multistep; - best_rate_change = tr_matrix[x][y].rate_change; + ast_format_copy(&best, &cur_src); + ast_format_copy(&bestdst, &cur_dst); + besttablecost = matrix_get(x, y)->table_cost; + beststeps = matrix_get(x, y)->multistep; } } + ast_format_cap_iter_end(src_cap); } + + ast_format_cap_iter_end(dst_cap); AST_RWLIST_UNLOCK(&translators); - if (best > -1) { - *srcs = best; - *dst = bestdst; - best = 0; + if (best.id) { + ast_format_copy(dst_fmt_out, &bestdst); + ast_format_copy(src_fmt_out, &best); + return 0; } - return best; + return -1; } } -unsigned int ast_translate_path_steps(format_t dest, format_t src) +unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_format *src_format) { unsigned int res = -1; - + int src, dest; /* convert bitwise format numbers into array indices */ - src = powerof(src); - dest = powerof(dest); + src = format2index(src_format->id); + dest = format2index(dst_format->id); if (src == -1 || dest == -1) { ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending"); @@ -1002,97 +1242,123 @@ unsigned int ast_translate_path_steps(format_t dest, format_t src) } AST_RWLIST_RDLOCK(&translators); - if (tr_matrix[src][dest].step) - res = tr_matrix[src][dest].multistep + 1; + if (matrix_get(src, dest)->step) { + res = matrix_get(src, dest)->multistep + 1; + } AST_RWLIST_UNLOCK(&translators); return res; } -format_t ast_translate_available_formats(format_t dest, format_t src) +void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result) { - format_t res = dest; - format_t x; - format_t src_audio = src & AST_FORMAT_AUDIO_MASK; - format_t src_video = src & AST_FORMAT_VIDEO_MASK; + struct ast_format tmp_fmt; + struct ast_format cur_src; + int src_audio = 0; + int src_video = 0; + int index; + + ast_format_cap_copy(result, dest); /* if we don't have a source format, we just have to try all possible destination formats */ - if (!src) - return dest; + if (!src) { + return; + } - /* If we have a source audio format, get its format index */ - if (src_audio) - src_audio = powerof(src_audio); + ast_format_cap_iter_start(src); + while (!ast_format_cap_iter_next(src, &cur_src)) { + /* If we have a source audio format, get its format index */ + if (AST_FORMAT_GET_TYPE(cur_src.id) == AST_FORMAT_TYPE_AUDIO) { + src_audio = format2index(cur_src.id); + } - /* If we have a source video format, get its format index */ - if (src_video) - src_video = powerof(src_video); + /* If we have a source video format, get its format index */ + if (AST_FORMAT_GET_TYPE(cur_src.id) == AST_FORMAT_TYPE_VIDEO) { + src_video = format2index(cur_src.id); + } - AST_RWLIST_RDLOCK(&translators); + AST_RWLIST_RDLOCK(&translators); - /* For a given source audio format, traverse the list of - known audio formats to determine whether there exists - a translation path from the source format to the - destination format. */ - for (x = 1LL; src_audio && x > 0; x <<= 1) { - if (!(x & AST_FORMAT_AUDIO_MASK)) { - continue; - } + /* For a given source audio format, traverse the list of + known audio formats to determine whether there exists + a translation path from the source format to the + destination format. */ + for (index = 0; (src_audio >= 0) && index < cur_max_index; index++) { + ast_format_set(&tmp_fmt, index2format(index), 0); - /* if this is not a desired format, nothing to do */ - if (!(dest & x)) - continue; + if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO) { + continue; + } - /* if the source is supplying this format, then - we can leave it in the result */ - if (src & x) - continue; + /* if this is not a desired format, nothing to do */ + if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) { + continue; + } - /* if we don't have a translation path from the src - to this format, remove it from the result */ - if (!tr_matrix[src_audio][powerof(x)].step) { - res &= ~x; - continue; - } + /* if the source is supplying this format, then + we can leave it in the result */ + if (ast_format_cap_iscompatible(src, &tmp_fmt)) { + continue; + } - /* now check the opposite direction */ - if (!tr_matrix[powerof(x)][src_audio].step) - res &= ~x; - } + /* if we don't have a translation path from the src + to this format, remove it from the result */ + if (!matrix_get(src_audio, index)->step) { + ast_format_cap_remove_byid(result, tmp_fmt.id); + continue; + } - /* For a given source video format, traverse the list of - known video formats to determine whether there exists - a translation path from the source format to the - destination format. */ - for (x = 1LL; src_video && x > 0; x <<= 1) { - if (!(x & AST_FORMAT_VIDEO_MASK)) { - continue; + /* now check the opposite direction */ + if (!matrix_get(index, src_audio)->step) { + ast_format_cap_remove_byid(result, tmp_fmt.id); + } } - /* if this is not a desired format, nothing to do */ - if (!(dest & x)) - continue; + /* For a given source video format, traverse the list of + known video formats to determine whether there exists + a translation path from the source format to the + destination format. */ + for (index = 0; (src_video >= 0) && index < cur_max_index; index++) { + ast_format_set(&tmp_fmt, index2format(index), 0); + if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_VIDEO) { + continue; + } - /* if the source is supplying this format, then - we can leave it in the result */ - if (src & x) - continue; + /* if this is not a desired format, nothing to do */ + if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) { + continue; + } - /* if we don't have a translation path from the src - to this format, remove it from the result */ - if (!tr_matrix[src_video][powerof(x)].step) { - res &= ~x; - continue; - } + /* if the source is supplying this format, then + we can leave it in the result */ + if (ast_format_cap_iscompatible(src, &tmp_fmt)) { + continue; + } - /* now check the opposite direction */ - if (!tr_matrix[powerof(x)][src_video].step) - res &= ~x; - } + /* if we don't have a translation path from the src + to this format, remove it from the result */ + if (!matrix_get(src_video, index)->step) { + ast_format_cap_remove_byid(result, tmp_fmt.id); + continue; + } - AST_RWLIST_UNLOCK(&translators); + /* now check the opposite direction */ + if (!matrix_get(index, src_video)->step) { + ast_format_cap_remove_byid(result, tmp_fmt.id); + } + } + AST_RWLIST_UNLOCK(&translators); + } + ast_format_cap_iter_end(src); +} +int ast_translate_init(void) +{ + int res = 0; + ast_rwlock_init(&tablelock); + res = matrix_resize(1); + res |= ast_cli_register_multiple(cli_translate, ARRAY_LEN(cli_translate)); return res; } diff --git a/main/udptl.c b/main/udptl.c index 1845ca8823c59047130adb4d5e85cdb8f6350dfd..f5abbb900bd8145ef964d73f1b38606f27a9840e 100644 --- a/main/udptl.c +++ b/main/udptl.c @@ -379,7 +379,7 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len) /* Decode the secondary IFP packet */ //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); s->f[ifp_no].frametype = AST_FRAME_MODEM; - s->f[ifp_no].subclass.codec = AST_MODEM_T38; + s->f[ifp_no].subclass.integer = AST_MODEM_T38; s->f[ifp_no].mallocd = 0; s->f[ifp_no].seqno = seq_no - i; @@ -481,7 +481,7 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len) if (repaired[l]) { //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); s->f[ifp_no].frametype = AST_FRAME_MODEM; - s->f[ifp_no].subclass.codec = AST_MODEM_T38; + s->f[ifp_no].subclass.integer = AST_MODEM_T38; s->f[ifp_no].mallocd = 0; s->f[ifp_no].seqno = j; @@ -502,7 +502,7 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len) if (seq_no >= s->rx_seq_no) { /* Decode the primary IFP packet */ s->f[ifp_no].frametype = AST_FRAME_MODEM; - s->f[ifp_no].subclass.codec = AST_MODEM_T38; + s->f[ifp_no].subclass.integer = AST_MODEM_T38; s->f[ifp_no].mallocd = 0; s->f[ifp_no].seqno = seq_no; @@ -1057,7 +1057,7 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f) return 0; if ((f->frametype != AST_FRAME_MODEM) || - (f->subclass.codec != AST_MODEM_T38)) { + (f->subclass.integer != AST_MODEM_T38)) { ast_log(LOG_WARNING, "(%s): UDPTL can only send T.38 data.\n", LOG_TAG(s)); return -1; diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c index d285af54bb20e1cc53a02a76b1fc7ad71a7a0eb2..bc832309b872c74e5cd80ead0b3421329c868498 100644 --- a/pbx/pbx_spool.c +++ b/pbx/pbx_spool.c @@ -74,7 +74,7 @@ struct outgoing { int retrytime; /*!< How long to wait between retries (in seconds) */ int waittime; /*!< How long to wait for an answer */ long callingpid; /*!< PID which is currently calling */ - format_t format; /*!< Formats (codecs) for this call */ + struct ast_format_cap *capabilities; /*!< Formats (codecs) for this call */ AST_DECLARE_STRING_FIELDS ( AST_STRING_FIELD(fn); /*!< File name of call file */ AST_STRING_FIELD(tech); /*!< Which channel technology to use for outgoing call */ @@ -99,10 +99,16 @@ static void queue_file(const char *filename, time_t when); static int init_outgoing(struct outgoing *o) { + struct ast_format tmpfmt; o->priority = 1; o->retrytime = 300; o->waittime = 45; - o->format = AST_FORMAT_SLINEAR; + + if (!(o->capabilities = ast_format_cap_alloc_nolock())) { + return -1; + } + ast_format_cap_add(o->capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE); if (ast_string_field_init(o, 128)) { return -1; @@ -116,6 +122,7 @@ static void free_outgoing(struct outgoing *o) ast_variables_destroy(o->vars); } ast_string_field_free_memory(o); + o->capabilities = ast_format_cap_destroy(o->capabilities); ast_free(o); } @@ -189,7 +196,7 @@ static int apply_outgoing(struct outgoing *o, const char *fn, FILE *f) o->maxretries = 0; } } else if (!strcasecmp(buf, "codecs")) { - ast_parse_allow_disallow(NULL, &o->format, c, 1); + ast_parse_allow_disallow(NULL, o->capabilities, c, 1); } else if (!strcasecmp(buf, "context")) { ast_string_field_set(o, context, c); } else if (!strcasecmp(buf, "extension")) { @@ -338,11 +345,11 @@ static void *attempt_thread(void *data) int res, reason; if (!ast_strlen_zero(o->app)) { ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries); - res = ast_pbx_outgoing_app(o->tech, o->format, (void *) o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL); + res = ast_pbx_outgoing_app(o->tech, o->capabilities, (void *) o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL); o->vars = NULL; } else { ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries); - res = ast_pbx_outgoing_exten(o->tech, o->format, (void *) o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL); + res = ast_pbx_outgoing_exten(o->tech, o->capabilities, (void *) o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL); o->vars = NULL; } if (res) { diff --git a/res/res_adsi.c b/res/res_adsi.c index 226105d87b29f5ab51f4646d108eb2a5d0133761..0a1f623a5af31966c57fdddce80d784d3c6c11b9 100644 --- a/res/res_adsi.c +++ b/res/res_adsi.c @@ -69,7 +69,7 @@ static char speeddial[ADSI_MAX_SPEED_DIAL][3][SPEEDDIAL_MAX_LEN]; static int alignment = 0; -static int adsi_generate(unsigned char *buf, int msgtype, unsigned char *msg, int msglen, int msgnum, int last, format_t codec) +static int adsi_generate(unsigned char *buf, int msgtype, unsigned char *msg, int msglen, int msgnum, int last, struct ast_format *codec) { int sum, x, bytes = 0; /* Initial carrier (imaginary) */ @@ -139,7 +139,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l *remain = *remain - amt; } outf.frametype = AST_FRAME_VOICE; - outf.subclass.codec = AST_FORMAT_ULAW; + ast_format_set(&outf.subclass.format, AST_FORMAT_ULAW, 0); outf.data.ptr = buf; outf.datalen = amt; outf.samples = amt; @@ -170,7 +170,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l continue; } - if (inf->subclass.codec != AST_FORMAT_ULAW) { + if (inf->subclass.format.id != AST_FORMAT_ULAW) { ast_log(LOG_WARNING, "Channel not in ulaw?\n"); ast_frfree(inf); return -1; @@ -182,7 +182,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l *remain = inf->datalen - amt; } outf.frametype = AST_FRAME_VOICE; - outf.subclass.codec = AST_FORMAT_ULAW; + ast_format_set(&outf.subclass.format, AST_FORMAT_ULAW, 0); outf.data.ptr = buf; outf.datalen = amt; outf.samples = amt; @@ -214,9 +214,11 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms } while (retries < maxretries) { + struct ast_format tmpfmt; if (!(chan->adsicpe & ADSI_FLAG_DATAMODE)) { /* Generate CAS (no SAS) */ - ast_gen_cas(buf, 0, 680, AST_FORMAT_ULAW); + ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0); + ast_gen_cas(buf, 0, 680, &tmpfmt); /* Send CAS */ if (adsi_careful_send(chan, buf, 680, NULL)) { @@ -275,7 +277,7 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms def= ast_channel_defer_dtmf(chan); #endif while ((x < 6) && msg[x]) { - if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], AST_FORMAT_ULAW)) < 0) { + if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], ast_format_set(&tmpfmt, AST_FORMAT_ULAW,0))) < 0) { ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, chan->name); return -1; } @@ -361,7 +363,12 @@ int AST_OPTIONAL_API_NAME(ast_adsi_end_download)(struct ast_channel *chan) int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message_full)(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait) { unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL }; - int msglens[5], msgtypes[5], newdatamode = (chan->adsicpe & ADSI_FLAG_DATAMODE), res, x, writeformat = chan->writeformat, readformat = chan->readformat, waitforswitch = 0; + int msglens[5], msgtypes[5], newdatamode = (chan->adsicpe & ADSI_FLAG_DATAMODE), res, x, waitforswitch = 0; + struct ast_format writeformat; + struct ast_format readformat; + + ast_format_copy(&writeformat, &chan->writeformat); + ast_format_copy(&readformat, &chan->readformat); for (x = 0; x < msglen; x += (msg[x+1]+2)) { if (msg[x] == ADSI_SWITCH_TO_DATA) { @@ -388,16 +395,16 @@ int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message_full)(struct ast_channel *ch ast_stopstream(chan); - if (ast_set_write_format(chan, AST_FORMAT_ULAW)) { + if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "Unable to set write format to ULAW\n"); return -1; } - if (ast_set_read_format(chan, AST_FORMAT_ULAW)) { + if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "Unable to set read format to ULAW\n"); - if (writeformat) { - if (ast_set_write_format(chan, writeformat)) { - ast_log(LOG_WARNING, "Unable to restore write format to %d\n", writeformat); + if (writeformat.id) { + if (ast_set_write_format(chan, &writeformat)) { + ast_log(LOG_WARNING, "Unable to restore write format to %s\n", ast_getformatname(&writeformat)); } } return -1; @@ -416,11 +423,11 @@ int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message_full)(struct ast_channel *ch chan->adsicpe = (chan->adsicpe & ~ADSI_FLAG_DATAMODE) | newdatamode; } - if (writeformat) { - ast_set_write_format(chan, writeformat); + if (writeformat.id) { + ast_set_write_format(chan, &writeformat); } - if (readformat) { - ast_set_read_format(chan, readformat); + if (readformat.id) { + ast_set_read_format(chan, &readformat); } if (!res) { diff --git a/res/res_agi.c b/res/res_agi.c index 7dc2d20c9c581680c07e8397d9751ac661aad468..09cdc396691296bcc36bd9f1e4b0909ce8d3033e 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -2146,7 +2146,8 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const int silence = 0; /* amount of silence to allow */ int gotsilence = 0; /* did we timeout for silence? */ char *silencestr = NULL; - int rfmt = 0; + struct ast_format rfmt; + ast_format_clear(&rfmt); /* XXX EAGI FIXME XXX */ @@ -2176,8 +2177,8 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const } if (silence > 0) { - rfmt = chan->readformat; - res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); + ast_format_copy(&rfmt, &chan->readformat); + res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); return -1; @@ -2299,7 +2300,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const } if (silence > 0) { - res = ast_set_read_format(chan, rfmt); + res = ast_set_read_format(chan, &rfmt); if (res) ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); ast_dsp_free(sildet); @@ -2650,16 +2651,25 @@ static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const c static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[]) { + struct ast_format_cap *cap; + struct ast_format tmpfmt; + /* If a structure already exists, return an error */ - if (agi->speech) { + if (agi->speech) { ast_agi_send(agi->fd, chan, "200 result=0\n"); return RESULT_SUCCESS; } - if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR))) + if (!(cap = ast_format_cap_alloc_nolock())) { + return RESULT_FAILURE; + } + ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + if ((agi->speech = ast_speech_new(argv[2], cap))) { ast_agi_send(agi->fd, chan, "200 result=1\n"); - else + } else { ast_agi_send(agi->fd, chan, "200 result=0\n"); + } + cap = ast_format_cap_destroy(cap); return RESULT_SUCCESS; } @@ -2791,7 +2801,8 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, struct ast_speech *speech = agi->speech; const char *prompt; char dtmf = 0, tmp[4096] = "", *buf = tmp; - int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0; + int timeout = 0, offset = 0, res = 0, i = 0; + struct ast_format old_read_format; long current_offset = 0; const char *reason = NULL; struct ast_frame *fr = NULL; @@ -2815,8 +2826,8 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, offset = atoi(argv[4]); /* We want frames coming in signed linear */ - old_read_format = chan->readformat; - if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { + ast_format_copy(&old_read_format, &chan->readformat); + if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) { ast_agi_send(agi->fd, chan, "200 result=0\n"); return RESULT_SUCCESS; } @@ -3759,21 +3770,22 @@ static int agi_exec(struct ast_channel *chan, const char *data) static int eagi_exec(struct ast_channel *chan, const char *data) { - int readformat, res; + int res; + struct ast_format readformat; if (ast_check_hangup(chan)) { ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n"); return 0; } - readformat = chan->readformat; - if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { + ast_format_copy(&readformat, &chan->readformat); + if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) { ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name); return -1; } res = agi_exec_full(chan, data, 1, 0); if (!res) { - if (ast_set_read_format(chan, readformat)) { - ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat)); + if (ast_set_read_format(chan, &readformat)) { + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(&readformat)); } } return res; diff --git a/res/res_calendar.c b/res/res_calendar.c index d5c716025be24d991226888c61f8ad2492601a2b..af81c183f87acab4abd81334c7b346b06fb640c6 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -702,8 +702,12 @@ static void *do_notify(void *data) } chan->tech = &null_tech; - chan->nativeformats = chan->writeformat = chan->rawwriteformat = - chan->readformat = chan->rawreadformat = AST_FORMAT_SLINEAR; + ast_format_set(&chan->writeformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&chan->readformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&chan->rawwriteformat, AST_FORMAT_SLINEAR, 0); + ast_format_set(&chan->rawreadformat, AST_FORMAT_SLINEAR, 0); + /* clear native formats and set to slinear. write format is signlear so just use that to set it */ + ast_format_cap_set(chan->nativeformats, &chan->writeformat); if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) { ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n"); diff --git a/res/res_clioriginate.c b/res/res_clioriginate.c index 01cf9f7b75b2218ccd03acf0b032d7f0b87eeb4b..f244c165dc492733cb5d8081b101d1b0bd3bda28 100644 --- a/res/res_clioriginate.c +++ b/res/res_clioriginate.c @@ -52,6 +52,8 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app char *chantech; char *chandata; int reason = 0; + struct ast_format_cap *cap; + struct ast_format tmpfmt; if (ast_strlen_zero(app)) return CLI_SHOWUSAGE; @@ -64,7 +66,12 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app return CLI_SHOWUSAGE; } - ast_pbx_outgoing_app(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL); + if (!(cap = ast_format_cap_alloc_nolock())) { + return CLI_FAILURE; + } + ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL); + cap = ast_format_cap_destroy(cap); return CLI_SUCCESS; } @@ -84,6 +91,8 @@ static char *orig_exten(int fd, const char *chan, const char *data) char *exten = NULL; char *context = NULL; int reason = 0; + struct ast_format_cap *cap; + struct ast_format tmpfmt; chandata = ast_strdupa(chan); @@ -102,8 +111,12 @@ static char *orig_exten(int fd, const char *chan, const char *data) exten = "s"; if (ast_strlen_zero(context)) context = "default"; - - ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL); + if (!(cap = ast_format_cap_alloc_nolock())) { + return CLI_FAILURE; + } + ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); + ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL); + cap = ast_format_cap_destroy(cap); return CLI_SUCCESS; } diff --git a/res/res_fax.c b/res/res_fax.c index 2ec7d2e3a2cb74b226728c1ee8b1c1c3237b9bb5..1191658ca0fe1594d9f11bf22afef4fd2a895b75 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -1095,8 +1095,11 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det struct ast_fax_session *fax = NULL; struct ast_frame *frame = NULL; struct ast_channel *c = chan; - unsigned int orig_write_format = 0, orig_read_format = 0; + struct ast_format orig_write_format; + struct ast_format orig_read_format; + ast_format_clear(&orig_write_format); + ast_format_clear(&orig_read_format); chancount = 1; /* create the FAX session */ @@ -1121,9 +1124,9 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det if (details->caps & AST_FAX_TECH_AUDIO) { expected_frametype = AST_FRAME_VOICE;; - expected_framesubclass.codec = AST_FORMAT_SLINEAR; - orig_write_format = chan->writeformat; - if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { + ast_format_set(&expected_framesubclass.format, AST_FORMAT_SLINEAR, 0); + ast_format_copy(&orig_write_format, &chan->writeformat); + if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name); ao2_lock(faxregistry.container); ao2_unlink(faxregistry.container, fax); @@ -1132,8 +1135,8 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det ast_channel_unlock(chan); return -1; } - orig_read_format = chan->readformat; - if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { + ast_format_copy(&orig_read_format, &chan->readformat); + if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name); ao2_lock(faxregistry.container); ao2_unlink(faxregistry.container, fax); @@ -1151,7 +1154,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det } } else { expected_frametype = AST_FRAME_MODEM; - expected_framesubclass.codec = AST_MODEM_T38; + expected_framesubclass.integer = AST_MODEM_T38; } if (fax->debug_info) { @@ -1226,7 +1229,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det fax->tech->switch_to_t38(fax); details->caps &= ~AST_FAX_TECH_AUDIO; expected_frametype = AST_FRAME_MODEM; - expected_framesubclass.codec = AST_MODEM_T38; + expected_framesubclass.integer = AST_MODEM_T38; if (fax->smoother) { ast_smoother_free(fax->smoother); fax->smoother = NULL; @@ -1327,11 +1330,11 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det * restore them now */ if (chancount) { - if (orig_read_format) { - ast_set_read_format(chan, orig_read_format); + if (orig_read_format.id) { + ast_set_read_format(chan, &orig_read_format); } - if (orig_write_format) { - ast_set_write_format(chan, orig_write_format); + if (orig_write_format.id) { + ast_set_write_format(chan, &orig_write_format); } } diff --git a/res/res_fax_spandsp.c b/res/res_fax_spandsp.c index 6b2f103a7464b45580ffa44c872662321ebe83ac..21b4b496c016a422bf1bcacb4f19af998f1a62f4 100644 --- a/res/res_fax_spandsp.c +++ b/res/res_fax_spandsp.c @@ -492,11 +492,10 @@ static struct ast_frame *spandsp_fax_read(struct ast_fax_session *s) struct ast_frame fax_frame = { .frametype = AST_FRAME_VOICE, - .subclass.codec = AST_FORMAT_SLINEAR, .src = "res_fax_spandsp_g711", }; - struct ast_frame *f = &fax_frame; + ast_format_set(&fax_frame.subclass.format, AST_FORMAT_SLINEAR, 0); ast_timer_ack(p->timer, 1); diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 45280bf746f12f3b6e6602e487aeb8d61ff6090a..1d7aeadb55835195793516614eb2aa2ec9ac734e 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -152,7 +152,7 @@ static int respawn_time = 20; struct moh_files_state { struct mohclass *class; char name[MAX_MUSICCLASS]; - format_t origwfmt; + struct ast_format origwfmt; int samples; int sample_queue; int pos; @@ -188,7 +188,7 @@ struct mohclass { int total_files; unsigned int flags; /*! The format from the MOH source, not applicable to "files" mode */ - format_t format; + struct ast_format format; /*! The pid of the external application delivering MOH */ int pid; time_t start; @@ -206,7 +206,7 @@ struct mohclass { struct mohdata { int pipe[2]; - format_t origwfmt; + struct ast_format origwfmt; struct mohclass *parent; struct ast_frame f; AST_LIST_ENTRY(mohdata) list; @@ -267,8 +267,8 @@ static void moh_files_release(struct ast_channel *chan, void *data) ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name); } - if (state->origwfmt && ast_set_write_format(chan, state->origwfmt)) { - ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", chan->name, ast_getformatname(state->origwfmt)); + if (state->origwfmt.id && ast_set_write_format(chan, &state->origwfmt)) { + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", chan->name, ast_getformatname(&state->origwfmt)); } state->save_pos = state->pos; @@ -666,7 +666,7 @@ static void *monmp3thread(void *data) if ((strncasecmp(class->dir, "http://", 7) && strcasecmp(class->dir, "nodir")) && AST_LIST_EMPTY(&class->members)) continue; /* Read mp3 audio */ - len = ast_codec_get_len(class->format, res); + len = ast_codec_get_len(&class->format, res); if ((res2 = read(class->srcfd, sbuf, len)) != len) { if (!res2) { @@ -869,7 +869,7 @@ static struct mohdata *mohalloc(struct mohclass *cl) fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK); moh->f.frametype = AST_FRAME_VOICE; - moh->f.subclass.codec = cl->format; + ast_format_copy(&moh->f.subclass.format, &cl->format); moh->f.offset = AST_FRIENDLY_OFFSET; moh->parent = mohclass_ref(cl, "Reffing music class for mohdata parent"); @@ -885,7 +885,7 @@ static void moh_release(struct ast_channel *chan, void *data) { struct mohdata *moh = data; struct mohclass *class = moh->parent; - format_t oldwfmt; + struct ast_format oldwfmt; ao2_lock(class); AST_LIST_REMOVE(&moh->parent->members, moh, list); @@ -894,16 +894,16 @@ static void moh_release(struct ast_channel *chan, void *data) close(moh->pipe[0]); close(moh->pipe[1]); - oldwfmt = moh->origwfmt; + ast_format_copy(&oldwfmt, &moh->origwfmt); moh->parent = class = mohclass_unref(class, "unreffing moh->parent upon deactivation of generator"); ast_free(moh); if (chan) { - if (oldwfmt && ast_set_write_format(chan, oldwfmt)) { + if (oldwfmt.id && ast_set_write_format(chan, &oldwfmt)) { ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", - chan->name, ast_getformatname(oldwfmt)); + chan->name, ast_getformatname(&oldwfmt)); } ast_verb(3, "Stopped music on hold on %s\n", chan->name); @@ -930,8 +930,8 @@ static void *moh_alloc(struct ast_channel *chan, void *params) if ((res = mohalloc(class))) { res->origwfmt = chan->writeformat; - if (ast_set_write_format(chan, class->format)) { - ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", chan->name, ast_codec2str(class->format)); + if (ast_set_write_format(chan, &class->format)) { + ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", chan->name, ast_codec2str(&class->format)); moh_release(NULL, res); res = NULL; } @@ -946,7 +946,7 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl short buf[1280 + AST_FRIENDLY_OFFSET / 2]; int res; - len = ast_codec_get_len(moh->parent->format, samples); + len = ast_codec_get_len(&moh->parent->format, samples); if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) { ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, chan->name); @@ -1276,7 +1276,7 @@ static struct mohclass *_moh_class_malloc(const char *file, int line, const char ao2_alloc(sizeof(*class), moh_class_destructor) #endif )) { - class->format = AST_FORMAT_SLINEAR; + ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0); class->srcfd = -1; } @@ -1354,10 +1354,10 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "alpha")) ast_set_flag(mohclass, MOH_SORTALPHA); else if (!strcasecmp(tmp->name, "format")) { - mohclass->format = ast_getformatbyname(tmp->value); - if (!mohclass->format) { + ast_getformatbyname(tmp->value, &mohclass->format); + if (!mohclass->format.id) { ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value); - mohclass->format = AST_FORMAT_SLINEAR; + ast_format_set(&mohclass->format, AST_FORMAT_SLINEAR, 0); } } } @@ -1683,10 +1683,10 @@ static int load_moh_classes(int reload) else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "alpha")) ast_set_flag(class, MOH_SORTALPHA); else if (!strcasecmp(var->name, "format")) { - class->format = ast_getformatbyname(var->value); - if (!class->format) { + ast_getformatbyname(var->value, &class->format); + if (!class->format.id) { ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value); - class->format = AST_FORMAT_SLINEAR; + ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0); } } } @@ -1819,7 +1819,7 @@ static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struc ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>")); } if (strcasecmp(class->mode, "files")) { - ast_cli(a->fd, "\tFormat: %s\n", ast_getformatname(class->format)); + ast_cli(a->fd, "\tFormat: %s\n", ast_getformatname(&class->format)); } } ao2_iterator_destroy(&i); diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 785b4040d8d1942249fd7ec5cf28ad15de336731..f91cdb117ae618a2ddc1b332440a51d277c0b338 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -130,8 +130,8 @@ struct ast_rtp { unsigned int cycles; /*!< Shifted count of sequence number cycles */ double rxjitter; /*!< Interarrival jitter at the moment */ double rxtransit; /*!< Relative transit time for previous packet */ - format_t lasttxformat; - format_t lastrxformat; + struct ast_format lasttxformat; + struct ast_format lastrxformat; int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */ int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */ @@ -368,9 +368,9 @@ static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, return __rtp_sendto(instance, buf, size, flags, sa, 0); } -static int rtp_get_rate(format_t subclass) +static int rtp_get_rate(struct ast_format *format) { - return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass); + return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format); } static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp) @@ -560,7 +560,7 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit) } /* Grab the payload that they expect the RFC2833 packet to be received in */ - payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF); + payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_DTMF); rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); rtp->send_duration = 160; @@ -675,7 +675,7 @@ static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, cha rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); - if (duration > 0 && (measured_samples = duration * rtp_get_rate(rtp->f.subclass.codec) / 1000) > rtp->send_duration) { + if (duration > 0 && (measured_samples = duration * rtp_get_rate(&rtp->f.subclass.format) / 1000) > rtp->send_duration) { ast_debug(2, "Adjusting final end duration from %u to %u\n", rtp->send_duration, measured_samples); rtp->send_duration = measured_samples; } @@ -1037,9 +1037,9 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame int pred, mark = 0; unsigned int ms = calc_txstamp(rtp, &frame->delivery); struct ast_sockaddr remote_address = { {0,} }; - int rate = rtp_get_rate(frame->subclass.codec) / 1000; + int rate = rtp_get_rate(&frame->subclass.format) / 1000; - if (frame->subclass.codec == AST_FORMAT_G722) { + if (frame->subclass.format.id == AST_FORMAT_G722) { frame->samples /= 2; } @@ -1063,7 +1063,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame } } } else if (frame->frametype == AST_FRAME_VIDEO) { - mark = frame->subclass.codec & 0x1; + mark = ast_format_get_video_mark(&frame->subclass.format); pred = rtp->lastovidtimestamp + frame->samples; /* Re-calculate last TS */ rtp->lastts = rtp->lastts + ms * 90; @@ -1195,7 +1195,8 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr { struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); struct ast_sockaddr remote_address = { {0,} }; - format_t codec, subclass; + struct ast_format subclass; + int codec; ast_rtp_instance_get_remote_address(instance, &remote_address); @@ -1225,19 +1226,17 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr } /* Grab the subclass and look up the payload we are going to use */ - subclass = frame->subclass.codec; - if (frame->frametype == AST_FRAME_VIDEO) { - subclass &= ~0x1LL; - } - if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) { - ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass.codec)); + ast_format_copy(&subclass, &frame->subclass.format); + if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &subclass, 0)) < 0) { + ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(&frame->subclass.format)); return -1; } /* Oh dear, if the format changed we will have to set up a new smoother */ - if (rtp->lasttxformat != subclass) { - ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); + if (ast_format_cmp(&rtp->lasttxformat, &subclass) == AST_FORMAT_CMP_NOT_EQUAL) { + ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(&rtp->lasttxformat), ast_getformatname(&subclass)); rtp->lasttxformat = subclass; + ast_format_copy(&rtp->lasttxformat, &subclass); if (rtp->smoother) { ast_smoother_free(rtp->smoother); rtp->smoother = NULL; @@ -1246,9 +1245,9 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr /* If no smoother is present see if we have to set one up */ if (!rtp->smoother) { - struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass); + struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, &subclass); - switch (subclass) { + switch (subclass.id) { case AST_FORMAT_SPEEX: case AST_FORMAT_SPEEX16: case AST_FORMAT_G723_1: @@ -1261,13 +1260,13 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr default: if (fmt.inc_ms) { if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) { - ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); + ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); return -1; } if (fmt.flags) { ast_smoother_set_flags(rtp->smoother, fmt.flags); } - ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); + ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms)); } } } @@ -1315,7 +1314,7 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t double d; double dtv; double prog; - int rate = rtp_get_rate(rtp->f.subclass.codec); + int rate = rtp_get_rate(&rtp->f.subclass.format); double normdev_rxjitter_current; if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) { @@ -1478,7 +1477,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha if ((rtp->lastevent != seqno) && rtp->resp) { rtp->dtmf_duration = new_duration; f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0)); - f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0)); + f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0)); rtp->resp = 0; rtp->dtmf_duration = rtp->dtmf_timeout = 0; AST_LIST_INSERT_TAIL(frames, f, frame_list); @@ -1489,7 +1488,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha if (rtp->resp && rtp->resp != resp) { /* Another digit already began. End it */ f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0)); - f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0)); + f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0)); rtp->resp = 0; rtp->dtmf_duration = rtp->dtmf_timeout = 0; AST_LIST_INSERT_TAIL(frames, f, frame_list); @@ -1586,10 +1585,10 @@ static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, u } } else if ((rtp->resp == resp) && !power) { f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)); - f->samples = rtp->dtmfsamples * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8); + f->samples = rtp->dtmfsamples * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8); rtp->resp = 0; } else if (rtp->resp == resp) - rtp->dtmfsamples += 20 * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8); + rtp->dtmfsamples += 20 * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8); rtp->dtmf_timeout = 0; @@ -1604,7 +1603,7 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u totally help us out becuase we don't have an engine to keep it going and we are not guaranteed to have it every 20ms or anything */ if (rtpdebug) - ast_debug(0, "- RTP 3389 Comfort noise event: Level %" PRId64 " (len = %d)\n", rtp->lastrxformat, len); + ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", (int) rtp->lastrxformat.id, len); if (ast_test_flag(rtp, FLAG_3389_WARNING)) { struct ast_sockaddr remote_address = { {0,} }; @@ -1924,10 +1923,11 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload); /* Otherwise adjust bridged payload to match */ - bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code); + bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, &payload_type.format, payload_type.rtp_code); /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */ - if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) { + if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].rtp_code) && + !(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].asterisk_format)) { return -1; } @@ -2176,15 +2176,15 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */ if (!payload.asterisk_format) { struct ast_frame *f = NULL; - if (payload.code == AST_RTP_DTMF) { + if (payload.rtp_code == AST_RTP_DTMF) { /* process_dtmf_rfc2833 may need to return multiple frames. We do this * by passing the pointer to the frame list to it so that the method * can append frames to the list as needed. */ process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames); - } else if (payload.code == AST_RTP_CISCO_DTMF) { + } else if (payload.rtp_code == AST_RTP_CISCO_DTMF) { f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark); - } else if (payload.code == AST_RTP_CN) { + } else if (payload.rtp_code == AST_RTP_CN) { f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark); } else { ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", @@ -2204,8 +2204,9 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc return &ast_null_frame; } - rtp->lastrxformat = rtp->f.subclass.codec = payload.code; - rtp->f.frametype = (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT; + ast_format_copy(&rtp->lastrxformat, &payload.format); + ast_format_copy(&rtp->f.subclass.format, &payload.format); + rtp->f.frametype = (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) ? AST_FRAME_VOICE : (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) ? AST_FRAME_VIDEO : AST_FRAME_TEXT; rtp->rxseqno = seqno; @@ -2215,7 +2216,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc if (rtp->resp) { struct ast_frame *f; f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0); - f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0)); + f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0)); rtp->resp = 0; rtp->dtmf_timeout = rtp->dtmf_duration = 0; AST_LIST_INSERT_TAIL(&frames, f, frame_list); @@ -2232,7 +2233,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; rtp->f.seqno = seqno; - if (rtp->f.subclass.codec == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { + if (rtp->f.subclass.format.id == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) { unsigned char *data = rtp->f.data.ptr; memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen); @@ -2242,7 +2243,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc *data = 0xBD; } - if (rtp->f.subclass.codec == AST_FORMAT_T140RED) { + if (rtp->f.subclass.format.id == AST_FORMAT_T140RED) { unsigned char *data = rtp->f.data.ptr; unsigned char *header_end; int num_generations; @@ -2251,7 +2252,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ int x; - rtp->f.subclass.codec = AST_FORMAT_T140; + ast_format_set(&rtp->f.subclass.format, AST_FORMAT_T140, 0); header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); if (header_end == NULL) { return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; @@ -2289,17 +2290,17 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc } } - if (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) { + if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) { rtp->f.samples = ast_codec_get_samples(&rtp->f); - if ((rtp->f.subclass.codec == AST_FORMAT_SLINEAR) || (rtp->f.subclass.codec == AST_FORMAT_SLINEAR16)) { + if ((rtp->f.subclass.format.id == AST_FORMAT_SLINEAR) || (rtp->f.subclass.format.id == AST_FORMAT_SLINEAR16)) { ast_frame_byteswap_be(&rtp->f); } calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); - rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass.codec) / 1000); - rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass.codec) / 1000)); - } else if (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) { + rtp->f.ts = timestamp / (rtp_get_rate(&rtp->f.subclass.format) / 1000); + rtp->f.len = rtp->f.samples / ((ast_format_rate(&rtp->f.subclass.format) / 1000)); + } else if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) { /* Video -- samples is # of samples vs. 90000 */ if (!rtp->lastividtimestamp) rtp->lastividtimestamp = timestamp; @@ -2307,13 +2308,8 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc rtp->lastividtimestamp = timestamp; rtp->f.delivery.tv_sec = 0; rtp->f.delivery.tv_usec = 0; - /* Pass the RTP marker bit as bit 0 in the subclass field. - * This is ok because subclass is actually a bitmask, and - * the low bits represent audio formats, that are not - * involved here since we deal with video. - */ - if (mark) - rtp->f.subclass.codec |= 0x1; + /* Pass the RTP marker bit as bit */ + ast_format_set_video_mark(&rtp->f.subclass.format); } else { /* TEXT -- samples is # of samples vs. 1000 */ if (!rtp->lastitexttimestamp) @@ -2440,7 +2436,7 @@ static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int } rtp->red->t140.frametype = AST_FRAME_TEXT; - rtp->red->t140.subclass.codec = AST_FORMAT_T140RED; + ast_format_set(&rtp->red->t140.subclass.format, AST_FORMAT_T140RED, 0); rtp->red->t140.data.ptr = &rtp->red->buf_data; rtp->red->t140.ts = 0; diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c index 4ec71f26e4e4c56661716e9cd96fa10caa15d6ff..0e930d61f3504ec15efec649c52b262290eaf150 100644 --- a/res/res_rtp_multicast.c +++ b/res/res_rtp_multicast.c @@ -213,7 +213,7 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra } /* Grab the actual payload number for when we create the RTP packet */ - if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) { + if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &frame->subclass.format, 0)) < 0) { return -1; } diff --git a/res/res_speech.c b/res/res_speech.c index 46a846f0399c2edf2b22d7a1458fbf19ca93c60b..7a8d17e5aa8bdd370b32d6f7d4bf643d84239db8 100644 --- a/res/res_speech.c +++ b/res/res_speech.c @@ -169,23 +169,26 @@ int ast_speech_change(struct ast_speech *speech, const char *name, const char *v } /*! \brief Create a new speech structure using the engine specified */ -struct ast_speech *ast_speech_new(const char *engine_name, int formats) +struct ast_speech *ast_speech_new(const char *engine_name, const struct ast_format_cap *cap) { struct ast_speech_engine *engine = NULL; struct ast_speech *new_speech = NULL; - int format = AST_FORMAT_SLINEAR; + struct ast_format_cap *joint = NULL; + struct ast_format best; + + ast_format_set(&best, AST_FORMAT_SLINEAR, 0); /* Try to find the speech recognition engine that was requested */ if (!(engine = find_engine(engine_name))) return NULL; /* Before even allocating the memory below do some codec negotiation, we choose the best codec possible and fall back to signed linear if possible */ - if ((format = (engine->formats & formats))) - format = ast_best_codec(format); - else if ((engine->formats & AST_FORMAT_SLINEAR)) - format = AST_FORMAT_SLINEAR; - else + if ((joint = ast_format_cap_joint(engine->formats, cap))) { + ast_best_codec(joint, &best); + joint = ast_format_cap_destroy(joint); + } else if (!ast_format_cap_iscompatible(engine->formats, &best)) { return NULL; + } /* Allocate our own speech structure, and try to allocate a structure from the engine too */ if (!(new_speech = ast_calloc(1, sizeof(*new_speech)))) @@ -201,13 +204,13 @@ struct ast_speech *ast_speech_new(const char *engine_name, int formats) new_speech->engine = engine; /* Can't forget the format audio is going to be in */ - new_speech->format = format; + ast_format_copy(&new_speech->format, &best); /* We are not ready to accept audio yet */ ast_speech_change_state(new_speech, AST_SPEECH_STATE_NOT_READY); /* Pass ourselves to the engine so they can set us up some more and if they error out then do not create a structure */ - if (engine->create(new_speech, format)) { + if (engine->create(new_speech, &best)) { ast_mutex_destroy(&new_speech->lock); ast_free(new_speech); new_speech = NULL; diff --git a/tests/test_format_api.c b/tests/test_format_api.c new file mode 100644 index 0000000000000000000000000000000000000000..dc27725a55f7d2f33f441f6a505b752091735a8c --- /dev/null +++ b/tests/test_format_api.c @@ -0,0 +1,859 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2010, Digium, Inc. + * + * David Vossel <dvossel@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Tests for the ast_event API + * + * \author David Vossel <dvossel@digium.com> + * + * \ingroup tests + * + */ + +/*** MODULEINFO + <depend>TEST_FRAMEWORK</depend> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/module.h" +#include "asterisk/test.h" +#include "asterisk/format.h" +#include "asterisk/format_cap.h" +#include "asterisk/strings.h" + +/*! These are the keys for accessing attributes */ +enum test_attr_keys { + TEST_ATTR_KEY_SAMP_RATE, + TEST_ATTR_KEY_STRING, +}; + +/*! These are the values for the TEST_ATTR_KEY_SAMP_RATE key */ +enum test_attr_vals_samp { + TEST_ATTR_VAL_SAMP_8KHZ = (1 << 0), + TEST_ATTR_VAL_SAMP_12KHZ = (1 << 1), + TEST_ATTR_VAL_SAMP_16KHZ = (1 << 2), + TEST_ATTR_VAL_SAMP_32KHZ = (1 << 3), + TEST_ATTR_VAL_SAMP_48KHZ = (1 << 4), +}; + +/*! This is the attribute structure used for our test interface. */ +struct test_attr { + enum test_attr_vals_samp samp_flags; + char string[32]; +}; + +static enum ast_format_cmp_res test_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2) +{ + struct test_attr *attr1 = (struct test_attr *) fattr1; + struct test_attr *attr2 = (struct test_attr *) fattr2; + + if ((attr1->samp_flags == attr2->samp_flags) && + !(strcmp(attr1->string, attr2->string))) { + return AST_FORMAT_CMP_EQUAL; + } + if ((attr1->samp_flags != (attr1->samp_flags & attr2->samp_flags)) || + (!ast_strlen_zero(attr1->string) && strcmp(attr1->string, attr2->string))) { + return AST_FORMAT_CMP_NOT_EQUAL; + } + return AST_FORMAT_CMP_SUBSET; +} + +static int test_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result) +{ + struct test_attr *attr1 = (struct test_attr *) fattr1; + struct test_attr *attr2 = (struct test_attr *) fattr2; + struct test_attr *attr_res = (struct test_attr *) result; + int joint = -1; + + attr_res->samp_flags = (attr1->samp_flags & attr2->samp_flags); + + if (attr_res->samp_flags) { + joint = 0; + } + + if (!strcmp(attr1->string, attr2->string)) { + ast_copy_string(attr_res->string, attr1->string, sizeof(attr_res->string)); + joint = 0; + } + + return joint; +} + +static void test_set(struct ast_format_attr *fattr, va_list ap) +{ + enum test_attr_keys key; + struct test_attr *attr = (struct test_attr *) fattr; + char *string; + + for (key = va_arg(ap, int); + key != AST_FORMAT_ATTR_END; + key = va_arg(ap, int)) + { + switch (key) { + case TEST_ATTR_KEY_SAMP_RATE: + attr->samp_flags = (va_arg(ap, int) | attr->samp_flags); + break; + case TEST_ATTR_KEY_STRING: + string = va_arg(ap, char *); + if (!ast_strlen_zero(string)) { + ast_copy_string(attr->string, string, sizeof(attr->string)); + } + break; + default: + ast_log(LOG_WARNING, "unknown attribute type %d\n", key); + } + } +} + +/*! uLaw does not actually have any attributes associated with it. + * This is just for the purpose of testing. We are guaranteed there + * will never exist a interface for uLaw already. */ +static struct ast_format_attr_interface test_interface = { + .id = AST_FORMAT_TESTLAW, + .format_attr_cmp = test_cmp, + .format_attr_get_joint = test_getjoint, + .format_attr_set = test_set +}; + +/*! + * \internal + */ +AST_TEST_DEFINE(format_test1) +{ + struct ast_format format1 = { 0, }; + struct ast_format format2 = { 0, }; + struct ast_format joint = { 0, }; + + switch (cmd) { + case TEST_INIT: + info->name = "ast_format_test1"; + info->category = "/main/format/"; + info->summary = "Test ast_format with attributes."; + info->description = + "This test exercises the Ast Format API by creating and registering " + "a custom ast_format_attr_interface and performing various function " + "calls on ast_formats using the interface. "; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_format_attr_reg_interface(&test_interface)) { + ast_test_status_update(test, "test_interface failed to register.\n"); + return AST_TEST_FAIL; + } + + /* set a format with a single attribute. */ + ast_format_set(&format1, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + AST_FORMAT_ATTR_END); + if (ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) { + ast_test_status_update(test, "format1 did not set number attribute correctly.\n"); + return AST_TEST_FAIL; + } + if (!ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, AST_FORMAT_ATTR_END)) { + ast_test_status_update(test, "format1 did not determine isset on number correctly. \n"); + return AST_TEST_FAIL; + } + + /* append the string attribute to a format with previous attributes already set */ + ast_format_append(&format1, + TEST_ATTR_KEY_STRING,"String", + AST_FORMAT_ATTR_END); + if (ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "String", AST_FORMAT_ATTR_END)) { + ast_test_status_update(test, "format1 did not set string attribute correctly.\n"); + return AST_TEST_FAIL; + } + if (!ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "Not a string", AST_FORMAT_ATTR_END)) { + ast_test_status_update(test, "format1 did not determine isset on string correctly. \n"); + return AST_TEST_FAIL; + } + + /* set format2 with both STRING and NUMBER at the same time */ + ast_format_set(&format2, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_STRING, "MOOOoo", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + AST_FORMAT_ATTR_END); + /* perform isset with multiple key value pairs. */ + + if (ast_format_isset(&format2, + TEST_ATTR_KEY_STRING, "MOOOoo", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + AST_FORMAT_ATTR_END)) { + + ast_test_status_update(test, "format2 did not set attributes correctly.\n"); + return AST_TEST_FAIL; + } + if (!ast_format_isset(&format2, + TEST_ATTR_KEY_STRING, "WRONG", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + AST_FORMAT_ATTR_END)) { + + ast_test_status_update(test, "format2 did not deterine isset correctly.\n"); + return AST_TEST_FAIL; + } + + /* get joint attributes between format1 and format2. */ + if (ast_format_joint(&format1, &format2, &joint)) { + ast_test_status_update(test, "failed to get joint attributes.\n"); + return AST_TEST_FAIL; + } + if (ast_format_isset(&joint, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) { + ast_test_status_update(test, "joint attribute was not what we expected.\n"); + return AST_TEST_FAIL; + } + + /* exercise compare functions */ + if (ast_format_cmp(&format1, &format2) != AST_FORMAT_CMP_NOT_EQUAL) { + ast_test_status_update(test, "cmp 1 failed.\n"); + return AST_TEST_FAIL; + } + if (ast_format_cmp(&format1, &format1) != AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "cmp 2 failed.\n"); + return AST_TEST_FAIL; + } + if (ast_format_cmp(&joint, &format1) != AST_FORMAT_CMP_SUBSET) { + ast_test_status_update(test, "cmp 3 failed.\n"); + return AST_TEST_FAIL; + } + + /* unregister interface */ + if (ast_format_attr_unreg_interface(&test_interface)) { + ast_test_status_update(test, "test_interface failed to unregister.\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +/*! + * \internal + */ +AST_TEST_DEFINE(format_test2) +{ + struct ast_format format = { 0, }; + + switch (cmd) { + case TEST_INIT: + info->name = "ast_format_test2"; + info->category = "/main/format/"; + info->summary = "Test ast_format unique id and category system"; + info->description = + "This test exercises the Ast Format unique id and category " + "system by creating formats of various types and verifying " + "their category matches what we expect."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + ast_format_set(&format, AST_FORMAT_ULAW, 0); + if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_AUDIO) { + ast_test_status_update(test, "audio type failed\n"); + return AST_TEST_FAIL; + } + + ast_format_set(&format, AST_FORMAT_H264, 0); + if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_VIDEO) { + ast_test_status_update(test, "video type failed\n"); + return AST_TEST_FAIL; + } + + ast_format_set(&format, AST_FORMAT_JPEG, 0); + if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_IMAGE) { + ast_test_status_update(test, "image type failed\n"); + return AST_TEST_FAIL; + } + + ast_format_set(&format, AST_FORMAT_T140, 0); + if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_TEXT) { + ast_test_status_update(test, "text type failed\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +static int container_test1_helper(struct ast_format_cap *cap1, struct ast_format_cap *cap2, struct ast_test *test) +{ + + int res = AST_TEST_PASS; + struct ast_format_cap *cap_joint; + struct ast_format tmpformat; + + if (ast_format_attr_reg_interface(&test_interface)) { + ast_test_status_update(test, "test_interface failed to register.\n"); + ast_format_cap_destroy(cap1); + ast_format_cap_destroy(cap2); + return AST_TEST_FAIL; + } + + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_G722, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H263, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)); + ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_STRING, "testing caps hooray", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, + AST_FORMAT_ATTR_END)); + + /* Test is compatible */ + if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || + !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || + !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || + !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || + !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || + !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { + ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 1.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* Test things that are not compatible */ + if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX, 0)) || + ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX16, 0)) || + ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H261, 0))) { + ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 2.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* Test compatiblity with format with attributes. */ + if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_STRING, "testing caps hooray", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + AST_FORMAT_ATTR_END))) { + + ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 3.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + AST_FORMAT_ATTR_END))) { + + ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 4.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, /* 48khz was not compatible, so this should fail iscompatible check */ + AST_FORMAT_ATTR_END))) { + + ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 5.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* Lets start testing the functions that compare ast_format_cap objects. + * Genreate the cap2 object to contain some similar formats as cap1 + * and some different formats as well. */ + ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); + ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); + ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)); + ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_H261, 0)); + ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); + ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_STRING, "testing caps hooray", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, + AST_FORMAT_ATTR_END)); + + + /* find joint formats between cap1 and cap2 */ + cap_joint = ast_format_cap_joint(cap1, cap2); + + if (!cap_joint) { + ast_test_status_update(test, "failed to create joint capabilities correctly.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + /* determine if cap_joint is what we think it should be */ + if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || + !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || + !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)) || + !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_STRING, "testing caps hooray", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + AST_FORMAT_ATTR_END))) { + + ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + /* make sure joint cap does not have formats that should not be there */ + if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)) || + ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, + TEST_ATTR_KEY_STRING, "testing caps hooray", + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, + TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, + AST_FORMAT_ATTR_END))) { + + ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* Lets test removing a capability */ + if (ast_format_cap_remove(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { + ast_test_status_update(test, "ast_format_cap_remove failed. \n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + /* Lets make sure what we just removed does not still exist */ + if (ast_format_cap_iscompatible(cap_joint, &tmpformat)) { + ast_test_status_update(test, "ast_format_cap_remove failed 2. \n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + /* Lets test removing a capability by id.*/ + if (ast_format_cap_remove_byid(cap_joint, AST_FORMAT_GSM)) { + ast_test_status_update(test, "ast_format_cap_remove failed 3. \n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + /* Lets make sure what we just removed does not still exist */ + if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0))) { + ast_test_status_update(test, "ast_format_cap_remove failed 4. \n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* lets test getting joint formats by type */ + ast_format_cap_destroy(cap_joint); + if (!(cap_joint = ast_format_cap_get_type(cap1, AST_FORMAT_TYPE_VIDEO))) { + ast_test_status_update(test, "ast_format_cap_get_type failed.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + /* lets make sure our joint capability structure has what we expect */ + if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || + !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H263, 0))) { + ast_test_status_update(test, "get_type failed 2.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + /* now make sure joint does not have anything but video */ + if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || + ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || + ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || + ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || + ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { + ast_test_status_update(test, "get_type failed 3.\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* now lets remove everythign from cap_joint */ + ast_format_cap_remove_all(cap_joint); + if (!ast_format_cap_is_empty(cap_joint)) { + ast_test_status_update(test, "failed to remove all\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* now lets add all by type */ + ast_format_cap_add_all_by_type(cap_joint, AST_FORMAT_TYPE_AUDIO); + if (ast_format_cap_is_empty(cap_joint)) { + ast_test_status_update(test, "failed to add all by type AUDIO\n"); + res = AST_TEST_FAIL; + } + ast_format_cap_iter_start(cap_joint); + while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { + if (AST_FORMAT_GET_TYPE(tmpformat.id) != AST_FORMAT_TYPE_AUDIO) { + ast_test_status_update(test, "failed to add all by type AUDIO\n"); + res = AST_TEST_FAIL; + ast_format_cap_iter_end(cap_joint); + goto test3_cleanup; + } + } + ast_format_cap_iter_end(cap_joint); + + /* test append */ + ast_format_cap_append(cap_joint, cap1); + ast_format_cap_iter_start(cap1); + while (!(ast_format_cap_iter_next(cap1, &tmpformat))) { + if (!ast_format_cap_iscompatible(cap_joint, &tmpformat)) { + ast_test_status_update(test, "failed to append format capabilities.\n"); + res = AST_TEST_FAIL; + ast_format_cap_iter_end(cap1); + goto test3_cleanup; + } + } + ast_format_cap_iter_end(cap1); + + /* test copy */ + cap1 = ast_format_cap_destroy(cap1); + cap1 = ast_format_cap_dup(cap_joint); + if (!ast_format_cap_identical(cap_joint, cap1)) { + ast_test_status_update(test, "failed to copy capabilities\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + + /* test remove by type */ + ast_format_cap_remove_bytype(cap_joint, AST_FORMAT_TYPE_AUDIO); + if (ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_AUDIO)) { + ast_test_status_update(test, "failed to remove all by type audio\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + if (!ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_TEXT)) { /* it should still have text */ + ast_test_status_update(test, "failed to remove all by type audio\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + ast_format_cap_iter_start(cap_joint); + while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { + if (AST_FORMAT_GET_TYPE(tmpformat.id) == AST_FORMAT_TYPE_AUDIO) { + ast_test_status_update(test, "failed to remove all by type audio\n"); + res = AST_TEST_FAIL; + ast_format_cap_iter_end(cap_joint); + goto test3_cleanup; + } + } + ast_format_cap_iter_end(cap_joint); + + /* test add all */ + ast_format_cap_remove_all(cap_joint); + ast_format_cap_add_all(cap_joint); + { + int video = 0, audio = 0, text = 0, image = 0; + ast_format_cap_iter_start(cap_joint); + while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { + switch (AST_FORMAT_GET_TYPE(tmpformat.id)) { + case AST_FORMAT_TYPE_AUDIO: + audio++; + break; + case AST_FORMAT_TYPE_VIDEO: + video++; + break; + case AST_FORMAT_TYPE_TEXT: + text++; + break; + case AST_FORMAT_TYPE_IMAGE: + image++; + break; + } + } + ast_format_cap_iter_end(cap_joint); + if (!video || !audio || !text || !image) { + ast_test_status_update(test, "failed to add all\n"); + res = AST_TEST_FAIL; + ast_format_cap_iter_end(cap_joint); + goto test3_cleanup; + } + } + + /* test copy2 */ + ast_format_cap_copy(cap2, cap_joint); + if (!ast_format_cap_identical(cap2, cap_joint)) { + ast_test_status_update(test, "ast_format_cap_copy failed\n"); + res = AST_TEST_FAIL; + goto test3_cleanup; + } + +test3_cleanup: + ast_format_cap_destroy(cap1); + ast_format_cap_destroy(cap2); + ast_format_cap_destroy(cap_joint); + + /* unregister interface */ + if (ast_format_attr_unreg_interface(&test_interface)) { + ast_test_status_update(test, "test_interface failed to unregister.\n"); + res = AST_TEST_FAIL; + } + + return res; +} + +/*! + * \internal + */ +AST_TEST_DEFINE(container_test1_nolock) +{ + struct ast_format_cap *cap1; + struct ast_format_cap *cap2; + + switch (cmd) { + case TEST_INIT: + info->name = "container_test_1_no_locking"; + info->category = "/main/format/"; + info->summary = "Test ast_format and ast_format_cap structures, no locking"; + info->description = + "This test exercises the Ast Format Capability API by creating " + "capability structures and performing various API calls on them."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + cap1 = ast_format_cap_alloc_nolock(); + cap2 = ast_format_cap_alloc_nolock(); + + if (!cap1 || !cap2) { + ast_test_status_update(test, "cap alloc failed.\n"); + return AST_TEST_FAIL; + } + return container_test1_helper(cap1, cap2, test); +} + + +/*! + * \internal + */ +AST_TEST_DEFINE(container_test1_withlock) +{ + struct ast_format_cap *cap1; + struct ast_format_cap *cap2; + + switch (cmd) { + case TEST_INIT: + info->name = "container_test1_with_locking"; + info->category = "/main/format/"; + info->summary = "Test ast_format and ast_format_cap structures, with locking"; + info->description = + "This test exercises the Ast Format Capability API by creating " + "capability structures and performing various API calls on them."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + cap1 = ast_format_cap_alloc(); + cap2 = ast_format_cap_alloc(); + + if (!cap1 || !cap2) { + ast_test_status_update(test, "cap alloc failed.\n"); + return AST_TEST_FAIL; + } + return container_test1_helper(cap1, cap2, test); +} + +static int container_test2_no_locking_helper(struct ast_format_cap *cap, struct ast_test *test) +{ + int num = 0; + struct ast_format tmpformat = { 0, }; + + ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); + ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); + ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_G722, 0)); + + ast_format_cap_iter_start(cap); + while (!ast_format_cap_iter_next(cap, &tmpformat)) { + num++; + } + ast_format_cap_iter_end(cap); + + ast_format_cap_iter_start(cap); + while (!ast_format_cap_iter_next(cap, &tmpformat)) { + num++; + } + ast_format_cap_iter_end(cap); + + ast_format_cap_destroy(cap); + ast_test_status_update(test, "%d items iterated over\n", num); + return (num == 6) ? AST_TEST_PASS : AST_TEST_FAIL; + +} + +/*! + * \internal + */ +AST_TEST_DEFINE(container_test2_no_locking) +{ + struct ast_format_cap *cap; + + switch (cmd) { + case TEST_INIT: + info->name = "container_test2_no_locking"; + info->category = "/main/format/"; + info->summary = "Test ast_format_cap iterator, no locking"; + info->description = + "This test exercises the Ast Capability API iterators."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + cap = ast_format_cap_alloc_nolock(); + if (!cap) { + ast_test_status_update(test, "alloc failed\n"); + return AST_TEST_FAIL; + } + return container_test2_no_locking_helper(cap, test); +} + +/*! + * \internal + */ +AST_TEST_DEFINE(container_test2_with_locking) +{ + struct ast_format_cap *cap; + + switch (cmd) { + case TEST_INIT: + info->name = "container_test2_with_locking"; + info->category = "/main/format/"; + info->summary = "Test ast_format_cap iterator, with locking"; + info->description = + "This test exercises the Ast Capability API iterators."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + cap = ast_format_cap_alloc(); + if (!cap) { + ast_test_status_update(test, "alloc failed\n"); + return AST_TEST_FAIL; + } + return container_test2_no_locking_helper(cap, test); +} + + +static int container_test3_helper(int nolocking, struct ast_test *test) +{ + int x; + int res = AST_TEST_PASS; + struct ast_format_cap *cap1; + struct ast_format_cap *cap2; + struct ast_format_cap *joint; + + for (x = 0; x < 2000; x++) { + if (nolocking) { + cap1 = ast_format_cap_alloc_nolock(); + cap2 = ast_format_cap_alloc_nolock(); + joint = ast_format_cap_alloc_nolock(); + } else { + cap1 = ast_format_cap_alloc(); + cap2 = ast_format_cap_alloc(); + joint = ast_format_cap_alloc(); + } + if (!cap1 || !cap2 || !joint) { + ast_test_status_update(test, "cap alloc fail\n"); + return AST_TEST_FAIL; + } + ast_format_cap_add_all(cap1); + ast_format_cap_add_all_by_type(cap2, AST_FORMAT_TYPE_AUDIO); + ast_format_cap_joint_copy(cap1, cap2, joint); + if (!(ast_format_cap_identical(cap2, joint))) { + ast_test_status_update(test, "failed identical test\n"); + res = AST_TEST_FAIL; + cap1 = ast_format_cap_destroy(cap1); + cap2 = ast_format_cap_destroy(cap2); + joint = ast_format_cap_destroy(joint); + break; + } + cap1 = ast_format_cap_destroy(cap1); + cap2 = ast_format_cap_destroy(cap2); + joint = ast_format_cap_destroy(joint); + } + return res; +} + +/*! + * \internal + */ +AST_TEST_DEFINE(container_test3_nolock) +{ + switch (cmd) { + case TEST_INIT: + info->name = "container_test3_no_locking"; + info->category = "/main/format/"; + info->summary = "Load Test ast_format_cap no locking."; + info->description = + "This test exercises the Ast Capability API and its iterators for the purpose " + "of measuring performance."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + return container_test3_helper(1, test); +} + +/*! + * \internal + */ +AST_TEST_DEFINE(container_test3_withlock) +{ + switch (cmd) { + case TEST_INIT: + info->name = "container_test3_with_locking"; + info->category = "/main/format/"; + info->summary = "Load Test ast_format_cap with locking."; + info->description = + "This test exercises the Ast Capability API and its iterators for the purpose " + "of measuring performance."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + return container_test3_helper(0, test); +} + +static int unload_module(void) +{ + AST_TEST_UNREGISTER(format_test1); + AST_TEST_UNREGISTER(format_test2); + AST_TEST_UNREGISTER(container_test1_nolock); + AST_TEST_UNREGISTER(container_test1_withlock); + AST_TEST_UNREGISTER(container_test2_no_locking); + AST_TEST_UNREGISTER(container_test2_with_locking); + AST_TEST_UNREGISTER(container_test3_nolock); + AST_TEST_UNREGISTER(container_test3_withlock); + + return 0; +} + +static int load_module(void) +{ + AST_TEST_REGISTER(format_test1); + AST_TEST_REGISTER(format_test2); + AST_TEST_REGISTER(container_test1_nolock); + AST_TEST_REGISTER(container_test1_withlock); + AST_TEST_REGISTER(container_test2_no_locking); + AST_TEST_REGISTER(container_test2_with_locking); + AST_TEST_REGISTER(container_test3_nolock); + AST_TEST_REGISTER(container_test3_withlock); + + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_format API Tests");