#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 */
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);
* 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,
}
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)
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)
{
struct mbl_pvt *pvt;
char *dest_dev = NULL;
char *dest_num = NULL;
- format_t oldformat;
int group = -1;
if (!data) {
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;
}
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;
if (sdp_session)
sdp_close(sdp_session);
+ mbl_tech.capabilities = ast_format_cap_destroy(mbl_tech.capabilities);
return 0;
}
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);
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);
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);
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,
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;
unsigned inUse;
char accountcode[20];
int amaflags;
- format_t capability;
+ struct ast_format_cap *cap;
struct ast_codec_pref prefs;
int dtmfmode;
int dtmfcodec;
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;
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;
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,
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));
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);
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);
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);
/*
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)
{
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;
}
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;
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;
}
- 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);
}
- 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; */
}
-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) {
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)) {
}
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);
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");
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) {
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)) {
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");
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;
}
}
- 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);
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);
if(peer->url) free(peer->url);
if(peer->e164) free(peer->e164);
+ peer->cap = ast_format_cap_destroy(peer->cap);
free(peer);
}
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;
} 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")) {
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));
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);
struct ooh323_peer *peer = NULL;
char *cat;
const char *utype;
+ struct ast_format tmpfmt;
if (gH323Debug)
ast_verbose("--- reload_config\n");
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;
} 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;
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);
/*! \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)
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);
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) {
int res;
struct ooAliases * pNewAlias = NULL;
struct ooh323_peer *peer = NULL;
+ struct ast_format tmpfmt;
OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
OOH323CALLBACKS h323Callbacks = {
.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;
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;
}
ast_mutex_unlock(&cur->lock);
ast_mutex_destroy(&cur->lock);
-
+ cur->cap = ast_format_cap_destroy(cur->cap);
ast_free(cur);
}
free(prev->rtpmask);
}
}
+ prev->cap = ast_format_cap_destroy(prev->cap);
free(prev);
if (cur == userl.users) {
break;
ast_verbose("+++ ooh323 unload_module \n");
}
+ gCap = ast_format_cap_destroy(gCap);
+ ooh323_tech.capabilities = ast_format_cap_destroy(ooh323_tech.capabilities);
return 0;
}
(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:
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;
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");
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");
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);
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);
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);
#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"
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);
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;
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,
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]");
}
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");
&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");
&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");
&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");
}
- if(format & AST_FORMAT_G726)
+ if(tmpfmt.id == AST_FORMAT_G726)
{
if(gH323Debug)
ast_verbose("\tAdding g726 capability to H323 endpoint\n");
}
- if(format & AST_FORMAT_G726_AAL2)
+ if(tmpfmt.id == AST_FORMAT_G726_AAL2)
{
if(gH323Debug)
ast_verbose("\tAdding g726aal2 capability to H323 endpoint\n");
}
- if(format & AST_FORMAT_H263)
+ if(tmpfmt.id == AST_FORMAT_H263)
{
if(gH323Debug)
ast_verbose("\tAdding h263 capability to H323 endpoint\n");
}
- if(format & AST_FORMAT_GSM)
+ if(tmpfmt.id == AST_FORMAT_GSM)
{
if(gH323Debug)
ast_verbose("\tAdding gsm capability to H323 endpoint\n");
}
#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");
#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");
}
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);
&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",
&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",
&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",
}
- 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",
}
- if(format & AST_FORMAT_G729A)
+ if(tmpfmt.id == AST_FORMAT_G729A)
{
txframes = (prefs->framing[x])/10;
}
- 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",
}
- if(format & AST_FORMAT_H263)
+ if(tmpfmt.id == AST_FORMAT_H263)
{
if(gH323Debug)
ast_verbose("\tAdding h263 capability to call (%s, %s)\n",
}
- if(format & AST_FORMAT_GSM)
+ if(tmpfmt.id == AST_FORMAT_GSM)
{
if(gH323Debug)
ast_verbose("\tAdding gsm capability to call(%s, %s)\n",
}
#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",
}
#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",
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",
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",
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;
}
#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)
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
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;
/* 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;
}
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;
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)) {
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", "");
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 */
{
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) {
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);
.volume = '#',
.exit = '\0',
};
- int oldwf = 0;
+ struct ast_format oldwf;
int volfactor = 0;
int res;
char *mailbox = NULL;
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;
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;
}
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)) {
.volume = '#',
.exit = '\0',
};
- int oldwf = 0;
+ struct ast_format oldwf;
int volfactor = 0;
int res;
char *mailbox = NULL;
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);
}
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;
}
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;
.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);
}
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;
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;
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;
}
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);
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;
int ffactor = 320 * 80,
res = 0,
done = 0,
- oldr = 0,
lastop = 0,
samples = 0,
speed = 1,
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)) {
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;
}
ast_frfree(f);
}
}
- if (oldr) {
- ast_set_read_format(chan, oldr);
+ if (oldr.id) {
+ ast_set_read_format(chan, &oldr);
}
return 0;
}
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,
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);
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);
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;
*/
};
+ 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
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;
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");
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);
}
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;
.f = { 0, },
};
+ ast_format_clear(&owriteformat);
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
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;
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;
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;
}
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),
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;
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]);
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;
}
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;
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;
}
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;
}
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);
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))) {
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;
conf_map[confno_int] = 1;
cnfout:
+ cap_slin = ast_format_cap_destroy(cap_slin);
if (cnf)
ast_atomic_fetchadd_int(&cnf->refcount, refcount);
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 */
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;
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;
}
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);
}
}
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;
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;
)) {
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;
}
}
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);
ao2_ref(user, -1);
AST_LIST_UNLOCK(&confs);
+
+conf_run_cleanup:
+ cap_slin = ast_format_cap_destroy(cap_slin);
+
return ret;
}
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
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);
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;
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) {
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;
.f = { 0, },
};
+ ast_format_clear(&owriteformat);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
return -1;
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;
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;
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;
}
int fds[2];
int ms = -1;
int pid = -1;
- int owriteformat;
+ struct ast_format owriteformat;
struct timeval next;
struct ast_frame *f;
struct myframe {
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;
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;
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;
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;
}
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");
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 {
break;
}
}
-
+ cap_slin = ast_format_cap_destroy(cap_slin);
ast_autoservice_stop(chan);
return res;
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);
);
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);
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, "/");
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);
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),
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);
ast_stopstream(dchan);
ast_hangup(dchan);
-
+
+parkcleanup:
+ cap_slin = ast_format_cap_destroy(cap_slin);
+
return res;
}
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;
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");
/* 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");
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)
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);
return(NULL);
}
-
static void rpt_mutex_spew(void)
{
struct by_lightning lock_ring_copy[32];
#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
*/
char decimals[MAXREMSTR];
char mystr[200];
struct dahdi_params par;
-
+struct ast_format_cap *cap = NULL;
/* get a pointer to myrpt */
myrpt = mytele->rpt;
/* 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");
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");
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");
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){
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);
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);
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);
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
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);
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;
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);
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)
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);
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");
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");
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");
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);
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");
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");
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");
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)) {
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);
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);
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);
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");
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);
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 */
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;
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");
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;
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
+ ast_format_clear(&oldreadformat);
if (speech == NULL)
return -1;
}
/* 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)) {
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;
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);
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;
}
}
- 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;
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);
} 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) {
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;
}
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]);
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;
}
}
/* 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");
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;
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;
}
}
- 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;
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;
}
.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,
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;
}
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);
}
}
/* 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;
}
.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);
}
/* 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;
/* 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);
}
.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,
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);
}
#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)
} 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);
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,
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",
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;
}
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 */
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;
}
/*! \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;
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)
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) {
*/
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");
ast_free(p);
}
AST_LIST_UNLOCK(&agents);
+
+ agent_tech.capabilities = ast_format_cap_destroy(agent_tech.capabilities);
return 0;
}
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);
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,
}
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;
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));
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;
}
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));
if (alsa.owner)
return -1;
+ alsa_tech.capabilities = ast_format_cap_destroy(alsa_tech.capabilities);
return 0;
}
#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,
}
/*! \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)))) {
/* 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;
}
/*! \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");
static int unload_module(void)
{
ast_channel_unregister(&bridge_tech);
+ bridge_tech.capabilities = ast_format_cap_destroy(bridge_tech.capabilities);
return 0;
}
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);
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,
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();
}
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;
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];
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;
}
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));
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)))
}
-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);
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,
int res;
unsigned char buf[256];
int flags;
+ struct ast_format tmpfmt;
poller.fd = p->subs[SUB_REAL].dfd;
poller.events = POLLPRI | POLLIN;
}
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) {
/*
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");
/* 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;
}
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");
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);
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;
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;
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");
/* 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;
}
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);
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;
}
}
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;
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) {
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);
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;
return NULL;
}
+ ast_format_clear(&deflaw);
#if defined(HAVE_PRI)
/*
* The dnid has been stuffed with the called-number[:subaddress]
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) {
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;
int len = 0;
int res;
int idx;
+ struct ast_format tmpfmt;
ast_mutex_lock(&ss_thread_lock);
ss_thread_count++;
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) {
/*
}
}
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
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;
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;
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);
}
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.
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 */
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
}
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;
}
#endif /* defined(HAVE_SS7) */
ast_cond_destroy(&ss_thread_complete);
+
+ dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
return 0;
}
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++) {
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;
}
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;
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 */
};
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 */
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);
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,
static void gtalk_member_destroy(struct gtalk *obj)
{
+ obj->cap = ast_format_cap_destroy(obj->cap);
ast_free(obj);
}
}
-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);
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);
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 */
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;
}
/* 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);
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));
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;
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;
/* 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));
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;
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);
}
}
/* 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;
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);
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) {
}
/*!\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;
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");
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"))
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;
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")) {
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));
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,
{
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 */
}
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;
}
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
#ifdef __cplusplus
}
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;
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 */
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);
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,
/*! \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)
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 */
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)) {
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;
}
}
{
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;
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
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) {
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;
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;
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");
/* 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);
break;
}
ast_channel_unlock(pvt->owner);
+ pvt_native = ast_format_cap_destroy(pvt_native);
}
else {
if (pvt->options.progress_audio)
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) {
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);
}
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:
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;
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");
{
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) {
ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
ASTOBJ_CONTAINER_DESTROY(&aliasl);
+ oh323_tech.capabilities = ast_format_cap_destroy(oh323_tech.capabilities);
return 0;
}
#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 */
#define DONT_RESCHEDULE -2
-static format_t iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH;
+static iax2_format iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH;
static int iaxdebug = 0;
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;
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 */
/*! 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 */
/*! 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 */
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);
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,
return 0;
}
-static unsigned char compress_subclass(format_t subclass)
+static unsigned char compress_subclass(iax2_format subclass)
{
int x;
int power=-1;
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) {
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
*/
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:
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, "|");
}
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;
/* 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;
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;
}
}
struct create_addr_info {
- format_t capability;
+ iax2_format capability;
uint64_t flags;
int maxtime;
int encmethods;
/* 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;
}
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));
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);
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);
}
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);
}
/*! \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);
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))
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;
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);
}
/* 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;
* 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;
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);
}
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)
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;
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:",
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)
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;
/* 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);
}
}
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");
}
}
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) {
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;
} 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);
}
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 {
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;
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);
}
}
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;
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;
"%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,
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");
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);
}
}
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";
}
} 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);
}
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));
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;
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));
"%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,
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)))
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);
/* 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);
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;
}
}
-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;
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;
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;
} 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];
}
}
} 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) {
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;
} 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")) {
} 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';
}
if (con)
ast_context_destroy(con, "IAX2");
ast_unload_realtime("iaxpeers");
+
+ iax2_tech.capabilities = ast_format_cap_destroy(iax2_tech.capabilities);
return 0;
}
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);
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));
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;
}
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;
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 */
};
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 */
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);
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,
static void jingle_member_destroy(struct jingle *obj)
{
+ obj->cap = ast_format_cap_destroy(obj->cap);
ast_free(obj);
}
}
-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);
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");
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");
iks_delete(jingle);
iks_delete(iq);
}
+ alreadysent = ast_format_cap_destroy(alreadysent);
return 1;
}
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;
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) {
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)
/* 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;
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));
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;
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);
}
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);
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) {
}
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,
}
/*! \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;
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");
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
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"))
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));
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,
{
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 */
}
ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
ASTOBJ_CONTAINER_DESTROY(&jingle_list);
+
+ global_capability = ast_format_cap_destroy(global_capability);
return 0;
}
.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);
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,
*/
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 */
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;
}
*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
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;
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;
}
/*! \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);
}
/*! \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;
}
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));
ao2_iterator_destroy(&it);
ao2_ref(locals, -1);
+ ast_format_cap_destroy(local_tech.capabilities);
return 0;
}
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];
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 */
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);
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);
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,
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)) {
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; */
}
}
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));
}
}
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);
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;
}
/* 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;
}
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;
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,
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) {
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) {
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",
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) {
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);
{
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];
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) {
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));
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;
}
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;
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;
}
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;
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 = {
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);
}
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)) {
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)) {
/*! \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;
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;
}
#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"
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);
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;
}
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;
}
- 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;
}
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] = "";
}
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);
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,
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,
}
}
-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;
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) {
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");
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) {
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);
/* 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;
#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;
}
.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) {
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,
}
/*! \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);
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;
/*! \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;
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;
}
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";
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,
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) {
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;
}
-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);
{
/* 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);
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);
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,
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;
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))
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;
);
char *parse = ast_strdupa(data);
char buf[256];
+ struct ast_format tmpfmt;
AST_NONSTANDARD_APP_ARGS(args, parse, '/');
o = find_desc(args.name);
/* 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) {
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));
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");
ast_free(o);
o = next;
}
+ oss_tech.capabilities = ast_format_cap_destroy(oss_tech.capabilities);
return 0;
}
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);
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 */
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);
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,
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;
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);
}
ast_debug(1, "Dialed %d\n", outdigit);
ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
- p->lastformat = -1;
+ ast_format_clear(&p->lastformat);
return 0;
}
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;
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;
}
} 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)) {
}
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;
}
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
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)) {
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;
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)) {
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;
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)) {
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)) {
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;
{
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;
/* 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)
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 */
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) {
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));
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;
}
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) {
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;
}
}
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;
}
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);
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;
} 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")) {
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;
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);
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,
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);
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) */
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);
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) */
}
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;
}
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] */
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 {
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
/*! \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"))) {
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
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) {
{
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;
/* 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) {
}
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");
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) {
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. */
/* 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))
*/
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;
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;
/* 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 */
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) */
/* 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)) {
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);
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);
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);
/* 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) {
}
/* 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) {
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),
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 */
}
/* 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);
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 {
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)) {
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)
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);
}
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) {
}
/*! \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);
/*! \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)
{
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)
{
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,
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);
}
*/
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,} };
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;
/* 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 */
}
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");
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) {
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) {
/* 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) {
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 */
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))
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)
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");
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);
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, ",");
}
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);
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 ,
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);
} 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)) {
}
} 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';
}
}
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"
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");
}
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");
* 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;
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);
* 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");
#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)
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;
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;
} 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);
}
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
/* 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;
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);
}
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;
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)) {
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 = {
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);
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");
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 */
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;
}
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 {
#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];
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; \
.instance = 0,
.directmedia = 0,
.nat = 0,
- .confcapability = AST_FORMAT_ULAW | AST_FORMAT_ALAW,
- .capability = 0,
.getforward = 0,
.needdestroy = 0,
.prune = 0,
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; \
.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;
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);
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,
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;
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:
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;
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);
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);
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;
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);
}
-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;
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);
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);
/*! \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)
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);
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);
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];
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);
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");
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);
}
}
}
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;
}
}
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);
}
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));
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))
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;
}
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;
}
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;
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);
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;
}
}
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;
}
}
}
} 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")) {
}
}
- 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;
}
}
- 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;
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");
}
/* 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");
/* 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))) {
/* 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);
free(a);
}
AST_LIST_REMOVE_CURRENT(list);
- free(d);
+ d = skinny_device_destroy(d);
}
AST_LIST_TRAVERSE_SAFE_END;
AST_LIST_UNLOCK(&devices);
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;
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);
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;
}
#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"
#define SUB_THREEWAY 1
#define MAX_SUBS 2
+struct ast_format_cap *global_cap;
+
enum autoprovision {
AUTOPROVISIONING_NO = 0,
AUTOPROVISIONING_YES,
/*! 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;
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);
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,
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;
}
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;
}
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;
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 */
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;
/* 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);
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);
}
}
}
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;
}
}
{
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");
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)
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))
/*--- 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;
}
*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);
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)
}
}
+
static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
{
struct unistim_device *d;
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;
}
"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;
}
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;
}
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);
}
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);
}
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;
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;
}
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;
}
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);
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,
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;
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))
}
/*
*/
-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);
/* 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) {
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;
/* XXX what about the thread ? */
/* XXX what about the memory allocated ? */
}
+
+ usbradio_tech.capabilities = ast_format_cap_destroy(usbradio_tech.capabilities);
return 0;
}
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);
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);
static struct ast_channel_tech vpb_tech = {
type: "vpb",
description: tdesc,
- capabilities: AST_FORMAT_SLINEAR,
+ capabilities: NULL,
properties: 0,
requester: vpb_request,
devicestate: NULL,
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,
#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
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:
}
}
-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:
}
}
-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:
/* 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;
/* 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;
}
/* 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;
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;
}
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);
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;
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);
* 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';
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;
}
ast_free(bridges);
}
+ ast_format_cap_destroy(vpb_tech.capabilities);
+ ast_format_cap_destroy(vpb_tech_indicate.capabilities);
return 0;
}
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) {
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;
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
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
#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
#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 {
int progress_audio;
int dtmfcodec[2];
int dtmfmode;
- format_t capability;
+ h323_format capability;
int bridge;
int nat;
int tunnelOptions;
{
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);
}
{
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 */
}
{
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 */
}
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;
}
#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
#include "asterisk/linkedlists.h"
#include "asterisk/crypto.h"
-#include "asterisk/frame_defs.h"
+#include "iax2.h"
struct iax_ies {
char *called_number;
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;
unsigned short serverport;
unsigned int altserver;
unsigned int flags;
- unsigned int format;
+ iax2_format format;
unsigned int tos;
AST_LIST_ENTRY(iax_template) list;
};
} 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")) {
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++;
}
#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 */
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
#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
/*@}*/
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) */
};
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 */
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 */
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,
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,
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));
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),
static struct ast_translator lintoadpcm = {
.name = "lintoadpcm",
- .srcfmt = AST_FORMAT_SLINEAR,
- .dstfmt = AST_FORMAT_ADPCM,
.framein = lintoadpcm_framein,
.frameout = lintoadpcm_frameout,
.sample = slin8_sample,
{
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);
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,
static struct ast_translator lintoalaw = {
"lintoalaw",
- .srcfmt = AST_FORMAT_SLINEAR,
- .dstfmt = AST_FORMAT_ALAW,
.framein = lintoalaw_framein,
.sample = slin8_sample,
.buffer_samples = BUFFER_SAMPLES,
{
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);
{
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;
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;
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;
{
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;
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;
}
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;
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;
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)) {
* 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;
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;
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)
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;
{
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;
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);
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,
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,
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,
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,
{
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);
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,
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,
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,
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,
{
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);
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,
static struct ast_translator lintogsm = {
.name = "lintogsm",
- .srcfmt = AST_FORMAT_SLINEAR,
- .dstfmt = AST_FORMAT_GSM,
.newpvt = gsm_new,
.framein = lintogsm_framein,
.frameout = lintogsm_frameout,
{
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);
static struct ast_translator ilbctolin = {
.name = "ilbctolin",
- .srcfmt = AST_FORMAT_ILBC,
- .dstfmt = AST_FORMAT_SLINEAR,
.newpvt = ilbctolin_new,
.framein = ilbctolin_framein,
.sample = ilbc_sample,
static struct ast_translator lintoilbc = {
.name = "lintoilbc",
- .srcfmt = AST_FORMAT_SLINEAR,
- .dstfmt = AST_FORMAT_ILBC,
.newpvt = lintoilbc_new,
.framein = lintoilbc_framein,
.frameout = lintoilbc_frameout,
{
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);
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,
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,
{
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);
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,
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,
{
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);
static struct ast_translator speextolin = {
.name = "speextolin",
- .srcfmt = AST_FORMAT_SPEEX,
- .dstfmt = AST_FORMAT_SLINEAR,
.newpvt = speextolin_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
static struct ast_translator lintospeex = {
.name = "lintospeex",
- .srcfmt = AST_FORMAT_SLINEAR,
- .dstfmt = AST_FORMAT_SPEEX,
.newpvt = lintospeex_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
static struct ast_translator speexwbtolin16 = {
.name = "speexwbtolin16",
- .srcfmt = AST_FORMAT_SPEEX16,
- .dstfmt = AST_FORMAT_SLINEAR16,
.newpvt = speexwbtolin16_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
static struct ast_translator lin16tospeexwb = {
.name = "lin16tospeexwb",
- .srcfmt = AST_FORMAT_SLINEAR16,
- .dstfmt = AST_FORMAT_SPEEX16,
.newpvt = lin16tospeexwb_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
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);
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,
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,
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,
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,
{
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);
{
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,
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_adpcm,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_ADPCM, 0);
return &f;
}
{
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,
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_alaw,
};
-
+ ast_format_set(&f.subclass.format, AST_FORMAT_ALAW, 0);
return &f;
}
{
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,
.data.ptr = ex_g722,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_G722, 0);
+
return &f;
}
{
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,
.data.ptr = ex_g726,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_G726, 0);
+
return &f;
}
{
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,
.data.ptr = ex_gsm,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_GSM, 0);
return &f;
}
{
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?? */
.data.ptr = ex_lpc10,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_LPC10, 0);
+
return &f;
}
{
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,
.data.ptr = ex_speex,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX, 0);
+
return &f;
}
{
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,
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_speex16,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX16, 0);
return &f;
}
{
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,
.data.ptr = ex_ulaw,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_ULAW, 0);
return &f;
}
/* 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) {
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) {
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,
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",
}
/* 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) {
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;
}
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,
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",
/* 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;
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]) {
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,
{
.name = "g726-32",
.exts = "g726-32",
- .format = AST_FORMAT_G726,
.open = g726_32_open,
.rewrite = g726_32_rewrite,
.write = g726_write,
{
.name = "g726-24",
.exts = "g726-24",
- .format = AST_FORMAT_G726,
.open = g726_24_open,
.rewrite = g726_24_rewrite,
.write = g726_write,
{
.name = "g726-16",
.exts = "g726-16",
- .format = AST_FORMAT_G726,
.open = g726_16_open,
.rewrite = g726_16_rewrite,
.write = g726_write,
.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;
}
{
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);
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);
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) {
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,
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",
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) {
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)) {
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,
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",
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;
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) {
}
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)) {
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);
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,
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",
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;
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) {
}
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)) {
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);
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,
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",
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) {
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) {
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,
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",
}
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;
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;
}
.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,
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;
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)
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 */
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,
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",
/* 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) {
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;
}
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);
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;
}
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;
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,
#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,
.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,
.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,
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",
/* 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) {
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) {
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,
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;
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)",
/* 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) {
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) {
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,
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;
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)",
/* 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) {
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) {
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,
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)",
/* 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) {
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) {
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,
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;
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)",
/* 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) {
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) {
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,
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",
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;
}
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;
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);
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;
}
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,
.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,
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)",
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;
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
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,
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)",
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);
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")) {
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);
}
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;
}
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;
#include <sys/time.h>
-#include "asterisk/frame_defs.h"
+#include "asterisk/format.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
/*! \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. */
*/
#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
*/
#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);
/*@} */
/* 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 {
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 */
* \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
* 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
*
* 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
*
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 */
/*! 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. */
#ifndef _ASTERISK_CALLERID_H
#define _ASTERISK_CALLERID_H
-#include "asterisk/frame_defs.h"
+#include "asterisk/format.h"
#define MAX_CALLERID_SIZE 32000
/*! 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;
* \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
* \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
* \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
* \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
* \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
* \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...
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 */
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 */
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;
* \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
* \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
* \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
* \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);
/*!
* \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)
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
*/
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);
/*!
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.
* \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)
}
* \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);
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
#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 ?
union ast_frame_subclass {
int integer;
- format_t codec;
+ struct ast_format format;
};
/*! \brief Data structure associated with a single frame of data
/*! 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 */
/*! \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 */
#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
* 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
*/
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;
}
/*!
/*!
* \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:
-/*
- * 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 */
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 */
* \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
* 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.
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)
*/
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;
/*! 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;
* \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
* \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)
}
#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" {
/*! 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
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 */
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 */
/*! 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 */
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;
};
*/
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;
};
/*!
* \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
*
* \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
* 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
* 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
*
* \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
* 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
* 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
* \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
{
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,
.data.ptr = ex_slin8,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
return &f;
}
{
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,
.data.ptr = ex_slin16,
};
+ ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0);
return &f;
}
#ifndef _ASTERISK_SLINFACTORY_H
#define _ASTERISK_SLINFACTORY_H
+#include "asterisk/format.h"
+
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
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 */
};
/*!
/*! Current state of structure */
int state;
/*! Expected write format */
- int format;
+ struct ast_format format;
/*! Data for speech engine */
void *data;
/*! Cached results */
/*! 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 */
/*! 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;
};
/*! \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 */
#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
#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.
*
*/
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 */
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 */
};
* \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
* \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
* \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
* \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
*/
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
}
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);
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));
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)) {
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) {
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);
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;
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;
}
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);
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", "");
#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"
#include "asterisk/poll-compat.h"
#include "asterisk/ccss.h"
#include "asterisk/test.h"
+#include "asterisk/format.h"
#include "asterisk/aoc.h"
#include "../defaults.h"
}
#endif
+ if (ast_translate_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
ast_aoc_cli_init();
ast_makesocket();
astobj2_init();
+ ast_format_attr_init();
+
ast_autoservice_init();
if (ast_timing_init()) {
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);
* 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 */
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);
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;
}
* 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;
}
* 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;
}
struct ast_audiohook_translate {
struct ast_trans_pvt *trans_pvt;
- format_t format;
+ struct ast_format format;
};
struct ast_audiohook_list {
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))
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);
* \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;
}
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;
/* ---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))) {
}
/*! \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;
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;
/* 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;
}
return bridge;
}
-int ast_bridge_check(format_t capabilities)
+int ast_bridge_check(uint32_t capabilities)
{
struct ast_bridge_technology *bridge_technology = NULL;
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;
/*! \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,
/* 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;
}
/*! \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();
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);
}
}
#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;
}
}
-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;
}
}
-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;
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;
}
-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;
}
-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];
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;
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;
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);
}
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);
}
}
- 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");
(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",
}
/*! \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,
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 = {
/* 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
*/
ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
}
+
+ chan->nativeformats = ast_format_cap_destroy(chan->nativeformats);
}
/*! \brief Free a dummy channel structure */
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)
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;
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;
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)) {
#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;
/* 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))
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;
#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;
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);
}
}
/* 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
} 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)
}
}
-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;
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);
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;
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);
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;
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)
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;
}
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;
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");
/*! \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 */
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;
}
* 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;
*/
int ast_do_masquerade(struct ast_channel *original)
{
- format_t x;
- int i;
+ int x, i;
int res=0;
int origstate;
int visible_indication;
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
}
/* 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;
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);
}
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 */
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;
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;
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;
ast_poll_channel_del(c0, c1);
+ ast_format_cap_destroy(o0nativeformats);
+ ast_format_cap_destroy(o1nativeformats);
+
return res;
}
{
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;
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)) {
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) {
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);
}
}
- 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);
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;
}
int v1_2;
int v2_2;
int v3_2;
- format_t origwfmt;
+ struct ast_format origwfmt;
int pos;
int duration;
int modulate;
struct tonepair_state *ts = params;
if (chan)
- ast_set_write_format(chan, ts->origwfmt);
+ ast_set_write_format(chan, &ts->origwfmt);
ast_free(ts);
}
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;
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;
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));
};
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)
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;
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);
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;
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",
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;
}
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;
{
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)";
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;
}
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;
}
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;
}
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;
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;
}
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:
for (x = 0; x < len; x++) {
odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
}
+ /* fall through */
+ default:
break;
}
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);
/*!
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;
/* 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);
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. */
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);
*/
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;
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:
}
} 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;
}
chan = NULL;
}
+ tmp_cap = ast_format_cap_destroy(tmp_cap);
+
if (outstate)
*outstate = state;
*/
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) {
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);
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) {
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");
}
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");
} 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;
/* 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);
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;
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);
};
/*!
+ * \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 */
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 */
}
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;
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:
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 */
}
}
- 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:
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) {
}
/* 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;
}
}
* 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;
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;
/* 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 = "";
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;
}
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));
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;
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;
{
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);
/* 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);
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)
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))
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;
}
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;
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;
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;
{
#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) {
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);
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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));
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+}
+
+
struct ast_smoother {
int size;
- format_t format;
+ struct ast_format format;
int flags;
float samplesperbyte;
unsigned int opt_needs_swap:1;
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) {
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;
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 */
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;
}
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;
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;
}
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;
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;
}
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:
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 {
}
}
- 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;
}
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:
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;
}
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");
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, ","))) {
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));
}
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;
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;
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)
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)
}
}
-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];
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;
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);
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);
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];
struct playtones_state *ps = params;
if (chan) {
- ast_set_write_format(chan, ps->origwfmt);
+ ast_set_write_format(chan, &ps->origwfmt);
}
if (ps->items) {
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;
}
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;
/*! 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];
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);
if (chan) {
ast_channel_unlock(chan);
}
+ in->cap = ast_format_cap_destroy(in->cap);
ast_free(in);
return NULL;
}
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));
}
}
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);
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 {
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) {
} else {
astman_send_error(s, m, "Originate failed");
}
+
+fast_orig_cleanup:
+ ast_format_cap_destroy(cap);
return 0;
}
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;
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)
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)
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;
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)
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;
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},
};
/*!
* 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)
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);
}
}
}
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);
}
}
}
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);
}
}
}
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);
}
}
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;
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);
}
}
}
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;
}
}
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;
}
}
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)");
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;
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);
}
/* 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);
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);
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 */
} 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 */
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);
*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) ||
ast_poll_channel_del(c0, c1);
+remote_bridge_cleanup:
+ ast_format_cap_destroy(oldcap0);
+ ast_format_cap_destroy(oldcap1);
+
return res;
}
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)) {
}
/* 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;
}
} 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);
}
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);
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 */
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);
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 */
}
/* Make sure we have matching codecs */
- if (!(codec0 & codec1)) {
+ if (!ast_format_cap_has_joint(cap0, cap1)) {
goto 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);
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;
}
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);
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 */
}
/* 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>");
}
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);
}
}
-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;
}
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)
{
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)
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;
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))) {
#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.
* 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.
*/
{
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;
{
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;
}
/*! \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);
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;
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 */
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);
}
}
/* 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;
}
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);
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;
}
}
*/
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;
+ }
}
}
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);
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) {
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, "-");
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")
};
/*! \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;
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;
}
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;
/* 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);
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);
{
AST_RWLIST_WRLOCK(&translators);
t->active = 1;
- rebuild_matrix(0);
+ matrix_rebuild(0);
AST_RWLIST_UNLOCK(&translators);
}
{
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");
}
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;
}
/* 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;
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;
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;
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;
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 */
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;
ast_variables_destroy(o->vars);
}
ast_string_field_free_memory(o);
+ o->capabilities = ast_format_cap_destroy(o->capabilities);
ast_free(o);
}
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")) {
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) {
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) */
*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;
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;
*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;
}
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)) {
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;
}
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) {
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;
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) {
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 */
}
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;
}
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);
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;
}
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;
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;
}
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;
}
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");
char *chantech;
char *chandata;
int reason = 0;
+ struct ast_format_cap *cap;
+ struct ast_format tmpfmt;
if (ast_strlen_zero(app))
return CLI_SHOWUSAGE;
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;
}
char *exten = NULL;
char *context = NULL;
int reason = 0;
+ struct ast_format_cap *cap;
+ struct ast_format tmpfmt;
chandata = ast_strdupa(chan);
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;
}
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 */
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);
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);
}
} else {
expected_frametype = AST_FRAME_MODEM;
- expected_framesubclass.codec = AST_MODEM_T38;
+ expected_framesubclass.integer = AST_MODEM_T38;
}
if (fax->debug_info) {
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;
* 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);
}
}
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);
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;
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;
struct mohdata {
int pipe[2];
- format_t origwfmt;
+ struct ast_format origwfmt;
struct mohclass *parent;
struct ast_frame f;
AST_LIST_ENTRY(mohdata) list;
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;
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) {
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");
{
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);
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);
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;
}
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);
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;
}
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);
}
}
}
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);
}
}
}
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);
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). */
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)
}
/* 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;
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;
}
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;
}
}
}
} 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;
{
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);
}
/* 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;
/* 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:
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));
}
}
}
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) {
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);
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);
}
} 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;
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,} };
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;
}
/* 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",
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;
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);
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);
*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;
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;
}
}
- 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;
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)
}
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;
}
/* 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;
}
}
/*! \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))))
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;
--- /dev/null
+/*
+ * 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");