summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UPGRADE.txt26
-rw-r--r--addons/chan_mobile.c34
-rw-r--r--addons/chan_ooh323.c365
-rw-r--r--addons/chan_ooh323.h4
-rw-r--r--addons/format_mp3.c6
-rw-r--r--addons/ooh323cDriver.c159
-rw-r--r--addons/ooh323cDriver.h6
-rw-r--r--apps/app_agent_pool.c4
-rw-r--r--apps/app_alarmreceiver.c13
-rw-r--r--apps/app_amd.c20
-rw-r--r--apps/app_chanspy.c38
-rw-r--r--apps/app_confbridge.c21
-rw-r--r--apps/app_dictate.c14
-rw-r--r--apps/app_dumpchan.c12
-rw-r--r--apps/app_echo.c5
-rw-r--r--apps/app_fax.c49
-rw-r--r--apps/app_festival.c26
-rw-r--r--apps/app_ices.c14
-rw-r--r--apps/app_jack.c29
-rw-r--r--apps/app_meetme.c43
-rw-r--r--apps/app_milliwatt.c15
-rw-r--r--apps/app_mixmonitor.c10
-rw-r--r--apps/app_mp3.c31
-rw-r--r--apps/app_nbscat.c32
-rw-r--r--apps/app_originate.c25
-rw-r--r--apps/app_record.c13
-rw-r--r--apps/app_sms.c17
-rw-r--r--apps/app_speech_utils.c9
-rw-r--r--apps/app_talkdetect.c16
-rw-r--r--apps/app_test.c17
-rw-r--r--apps/app_voicemail.c29
-rw-r--r--apps/app_waitforsilence.c11
-rw-r--r--apps/confbridge/conf_chan_record.c21
-rw-r--r--bridges/bridge_holding.c18
-rw-r--r--bridges/bridge_native_rtp.c33
-rw-r--r--bridges/bridge_simple.c11
-rw-r--r--bridges/bridge_softmix.c74
-rw-r--r--channels/chan_alsa.c27
-rw-r--r--channels/chan_bridge_media.c14
-rw-r--r--channels/chan_console.c35
-rw-r--r--channels/chan_dahdi.c129
-rw-r--r--channels/chan_iax2.c505
-rw-r--r--channels/chan_mgcp.c378
-rw-r--r--channels/chan_misdn.c55
-rw-r--r--channels/chan_motif.c185
-rw-r--r--channels/chan_multicast_rtp.c36
-rw-r--r--channels/chan_nbs.c56
-rw-r--r--channels/chan_oss.c23
-rw-r--r--channels/chan_phone.c208
-rw-r--r--channels/chan_pjsip.c83
-rw-r--r--channels/chan_sip.c791
-rw-r--r--channels/chan_skinny.c362
-rw-r--r--channels/chan_unistim.c165
-rw-r--r--channels/chan_vpb.cc97
-rw-r--r--channels/dahdi/bridge_native_dahdi.c13
-rw-r--r--channels/iax2/codec_pref.c333
-rw-r--r--channels/iax2/format_compatibility.c73
-rw-r--r--channels/iax2/include/codec_pref.h123
-rw-r--r--channels/iax2/include/format_compatibility.h55
-rw-r--r--channels/iax2/parser.c15
-rw-r--r--channels/iax2/provision.c9
-rw-r--r--channels/pjsip/dialplan_functions.c46
-rw-r--r--channels/sip/include/sip.h2
-rw-r--r--codecs/codec_a_mu.c40
-rw-r--r--codecs/codec_adpcm.c48
-rw-r--r--codecs/codec_alaw.c49
-rw-r--r--codecs/codec_dahdi.c399
-rw-r--r--codecs/codec_g722.c62
-rw-r--r--codecs/codec_g726.c62
-rw-r--r--codecs/codec_gsm.c53
-rw-r--r--codecs/codec_ilbc.c44
-rw-r--r--codecs/codec_lpc10.c50
-rw-r--r--codecs/codec_resample.c76
-rw-r--r--codecs/codec_speex.c103
-rw-r--r--codecs/codec_ulaw.c77
-rw-r--r--codecs/ex_adpcm.h3
-rw-r--r--codecs/ex_alaw.h2
-rw-r--r--codecs/ex_g722.h2
-rw-r--r--codecs/ex_g726.h2
-rw-r--r--codecs/ex_gsm.h3
-rw-r--r--codecs/ex_ilbc.h3
-rw-r--r--codecs/ex_lpc10.h2
-rw-r--r--codecs/ex_speex.h5
-rw-r--r--codecs/ex_ulaw.h3
-rw-r--r--formats/format_g719.c15
-rw-r--r--formats/format_g723.c14
-rw-r--r--formats/format_g726.c15
-rw-r--r--formats/format_g729.c15
-rw-r--r--formats/format_gsm.c14
-rw-r--r--formats/format_h263.c26
-rw-r--r--formats/format_h264.c26
-rw-r--r--formats/format_ilbc.c14
-rw-r--r--formats/format_jpeg.c13
-rw-r--r--formats/format_ogg_vorbis.c16
-rw-r--r--formats/format_pcm.c31
-rw-r--r--formats/format_siren14.c14
-rw-r--r--formats/format_siren7.c14
-rw-r--r--formats/format_sln.c78
-rw-r--r--formats/format_vox.c14
-rw-r--r--formats/format_wav.c26
-rw-r--r--formats/format_wav_gsm.c15
-rw-r--r--funcs/func_channel.c24
-rw-r--r--funcs/func_frame_trace.c4
-rw-r--r--funcs/func_pitchshift.c6
-rw-r--r--funcs/func_speex.c4
-rw-r--r--funcs/func_talkdetect.c2
-rw-r--r--include/asterisk/_private.h10
-rw-r--r--include/asterisk/abstract_jb.h2
-rw-r--r--include/asterisk/audiohook.h2
-rw-r--r--include/asterisk/bridge_channel.h4
-rw-r--r--include/asterisk/callerid.h4
-rw-r--r--include/asterisk/channel.h34
-rw-r--r--include/asterisk/codec.h186
-rw-r--r--include/asterisk/config_options.h9
-rw-r--r--include/asterisk/data.h1
-rw-r--r--include/asterisk/file.h2
-rw-r--r--include/asterisk/format.h553
-rw-r--r--include/asterisk/format_cache.h301
-rw-r--r--include/asterisk/format_cap.h377
-rw-r--r--include/asterisk/format_compatibility.h129
-rw-r--r--include/asterisk/format_pref.h117
-rw-r--r--include/asterisk/frame.h80
-rw-r--r--include/asterisk/image.h2
-rw-r--r--include/asterisk/mod_format.h10
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--include/asterisk/res_pjsip_session.h2
-rw-r--r--include/asterisk/rtp_engine.h127
-rw-r--r--include/asterisk/slin.h6
-rw-r--r--include/asterisk/slinfactory.h6
-rw-r--r--include/asterisk/smoother.h89
-rw-r--r--include/asterisk/speech.h2
-rw-r--r--include/asterisk/translate.h19
-rw-r--r--include/asterisk/vector.h104
-rw-r--r--main/abstract_jb.c21
-rw-r--r--main/app.c37
-rw-r--r--main/asterisk.c24
-rw-r--r--main/audiohook.c67
-rw-r--r--main/bridge.c50
-rw-r--r--main/bridge_basic.c11
-rw-r--r--main/bridge_channel.c26
-rw-r--r--main/callerid.c1
-rw-r--r--main/ccss.c10
-rw-r--r--main/channel.c434
-rw-r--r--main/channel_internal_api.c48
-rw-r--r--main/cli.c8
-rw-r--r--main/codec.c381
-rw-r--r--main/codec_builtin.c845
-rw-r--r--main/config_options.c6
-rw-r--r--main/core_local.c13
-rw-r--r--main/core_unreal.c41
-rw-r--r--main/data.c82
-rw-r--r--main/dial.c10
-rw-r--r--main/dsp.c86
-rw-r--r--main/file.c123
-rw-r--r--main/format.c1473
-rw-r--r--main/format_cache.c519
-rw-r--r--main/format_cap.c937
-rw-r--r--main/format_compatibility.c274
-rw-r--r--main/format_pref.c380
-rw-r--r--main/frame.c583
-rw-r--r--main/image.c4
-rw-r--r--main/indications.c17
-rw-r--r--main/manager.c22
-rw-r--r--main/media_index.c17
-rw-r--r--main/rtp_engine.c687
-rw-r--r--main/slinfactory.c34
-rw-r--r--main/smoother.c227
-rw-r--r--main/sorcery.c8
-rw-r--r--main/sounds_index.c16
-rw-r--r--main/translate.c775
-rw-r--r--main/utils.c4
-rw-r--r--pbx/pbx_spool.c11
-rw-r--r--res/ari/resource_bridges.c12
-rw-r--r--res/ari/resource_channels.c6
-rw-r--r--res/ari/resource_sounds.c19
-rw-r--r--res/parking/parking_applications.c8
-rw-r--r--res/res_adsi.c54
-rw-r--r--res/res_agi.c34
-rw-r--r--res/res_calendar.c21
-rw-r--r--res/res_clioriginate.c15
-rw-r--r--res/res_fax.c131
-rw-r--r--res/res_fax_spandsp.c21
-rw-r--r--res/res_format_attr_celt.c205
-rw-r--r--res/res_format_attr_h263.c349
-rw-r--r--res/res_format_attr_h264.c400
-rw-r--r--res/res_format_attr_opus.c256
-rw-r--r--res/res_format_attr_silk.c228
-rw-r--r--res/res_musiconhold.c88
-rw-r--r--res/res_pjsip/pjsip_configuration.c10
-rw-r--r--res/res_pjsip_sdp_rtp.c245
-rw-r--r--res/res_pjsip_session.c24
-rw-r--r--res/res_rtp_asterisk.c187
-rw-r--r--res/res_rtp_multicast.c8
-rw-r--r--res/res_speech.c36
-rw-r--r--res/res_stasis.c8
-rw-r--r--res/res_stasis_snoop.c31
-rw-r--r--tests/test_abstract_jb.c3
-rw-r--r--tests/test_cel.c11
-rw-r--r--tests/test_config.c35
-rw-r--r--tests/test_core_codec.c369
-rw-r--r--tests/test_core_format.c975
-rw-r--r--tests/test_format_api.c859
-rw-r--r--tests/test_format_cache.c281
-rw-r--r--tests/test_format_cap.c1479
-rw-r--r--tests/test_voicemail_api.c11
205 files changed, 13946 insertions, 9541 deletions
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 84b3e8d5a..535782a86 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -208,6 +208,32 @@ chan_sip:
progress indications into a 180 Ringing (if a 180 has not yet been
transmitted) if 'progressinband=never'.
+ - The codec preference order in an SDP during an offer is slightly different
+ than previous releases. Prior to Asterisk 13, the preference order of
+ codecs used to be:
+ (1) Our preferred codec
+ (2) Our configured codecs
+ (3) Any non-audio joint codecs
+
+ One of the ways the new media format architecture in Asterisk 13 improves
+ performance is by reference counting formats, such that they can be reused
+ in many places without additional allocation. To not require a large
+ amount of locking, an instance of a format is immutable by convention.
+ This works well except for formats with attributes. Since a media format
+ with an attribute is a different object than the same format without an
+ attribute, we have to carry over the formats with attributes from an
+ inbound offer so that the correct attributes are offered in an outgoing
+ INVITE request. This requires some subtle tweaks to the preference order
+ to ensure that the media format with attributes is offered to a remote
+ peer, as opposed to the same media format (but without attributes) that
+ may be stored in the peer object.
+
+ All of this means that our offer offer list will now be:
+ (1) Our preferred codec
+ (2) Any joint codecs offered by the inbound offer
+ (3) All other codecs that are not the preferred codec and not a joint
+ codec offered by the inbound offer
+
CLI commands:
- "core show settings" now lists the current console verbosity in addition
to the root console verbosity.
diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c
index a7cbc00e2..75db0fad8 100644
--- a/addons/chan_mobile.c
+++ b/addons/chan_mobile.c
@@ -73,16 +73,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/io.h"
+#include "asterisk/smoother.h"
+#include "asterisk/format_cache.h"
#define MBL_CONFIG "chan_mobile.conf"
#define MBL_CONFIG_OLD "mobile.conf"
#define DEVICE_FRAME_SIZE 48
-#define DEVICE_FRAME_FORMAT AST_FORMAT_SLINEAR
+#define DEVICE_FRAME_FORMAT ast_format_slin
#define CHANNEL_FRAME_SIZE 320
-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 sdp_session_t *sdp_session;
@@ -840,7 +840,6 @@ e_return:
static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num,
const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
-
struct ast_channel *chn;
pvt->answered = 0;
@@ -862,11 +861,11 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num
}
ast_channel_tech_set(chn, &mbl_tech);
- ast_format_cap_add(ast_channel_nativeformats(chn), &prefformat);
- ast_format_copy(ast_channel_rawreadformat(chn), &prefformat);
- ast_format_copy(ast_channel_rawwriteformat(chn), &prefformat);
- ast_format_copy(ast_channel_writeformat(chn), &prefformat);
- ast_format_copy(ast_channel_readformat(chn), &prefformat);
+ ast_channel_nativeformats_set(chn, mbl_tech.capabilities);
+ ast_channel_set_rawreadformat(chn, DEVICE_FRAME_FORMAT);
+ ast_channel_set_rawwriteformat(chn, DEVICE_FRAME_FORMAT);
+ ast_channel_set_writeformat(chn, DEVICE_FRAME_FORMAT);
+ ast_channel_set_readformat(chn, DEVICE_FRAME_FORMAT);
ast_channel_tech_pvt_set(chn, pvt);
if (state == AST_STATE_RING)
@@ -902,9 +901,9 @@ static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *
return NULL;
}
- 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));
+ if (ast_format_cap_iscompatible_format(cap, DEVICE_FRAME_FORMAT) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
*cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED;
return NULL;
}
@@ -1116,7 +1115,7 @@ static struct ast_frame *mbl_read(struct ast_channel *ast)
memset(&pvt->fr, 0x00, sizeof(struct ast_frame));
pvt->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&pvt->fr.subclass.format, DEVICE_FRAME_FORMAT, 0);
+ pvt->fr.subclass.format = DEVICE_FRAME_FORMAT;
pvt->fr.src = "Mobile";
pvt->fr.offset = AST_FRIENDLY_OFFSET;
pvt->fr.mallocd = 0;
@@ -4697,7 +4696,8 @@ static int unload_module(void)
if (sdp_session)
sdp_close(sdp_session);
- mbl_tech.capabilities = ast_format_cap_destroy(mbl_tech.capabilities);
+ ao2_ref(mbl_tech.capabilities, -1);
+ mbl_tech.capabilities = NULL;
return 0;
}
@@ -4706,11 +4706,11 @@ static int load_module(void)
int dev_id, s;
- if (!(mbl_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(mbl_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_set(&prefformat, DEVICE_FRAME_FORMAT, 0);
- ast_format_cap_add(mbl_tech.capabilities, &prefformat);
+
+ ast_format_cap_append(mbl_tech.capabilities, DEVICE_FRAME_FORMAT, 0);
/* Check if we have Bluetooth, no point loading otherwise... */
dev_id = hci_get_route(NULL);
s = hci_open_dev(dev_id);
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 8f1ae76bc..f02002f60 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -92,8 +92,6 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance
static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *result);
void setup_rtp_remote(ooCallData *call, const char *remoteIp, int remotePort);
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref);
-
struct ooh323_peer *find_friend(const char *name, int port);
@@ -174,10 +172,9 @@ static struct ooh323_pvt {
char callee_url[AST_MAX_EXTENSION];
int port;
- struct ast_format readformat; /* negotiated read format */
- struct ast_format writeformat; /* negotiated write format */
+ 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;
char exten[AST_MAX_EXTENSION]; /* Requested extension */
@@ -212,7 +209,6 @@ struct ooh323_user{
char accountcode[20];
int amaflags;
struct ast_format_cap *cap;
- struct ast_codec_pref prefs;
int dtmfmode;
int dtmfcodec;
int faxdetect;
@@ -239,7 +235,6 @@ struct ooh323_peer{
unsigned outgoinglimit;
unsigned outUse;
struct ast_format_cap *cap;
- struct ast_codec_pref prefs;
char accountcode[20];
int amaflags;
int dtmfmode;
@@ -307,7 +302,6 @@ int v6mode = 0;
static char gCallerID[AST_MAX_EXTENSION] = "";
static struct ooAliases *gAliasList;
static struct ast_format_cap *gCap;
-static struct ast_codec_pref gPrefs;
static int gDTMFMode = H323_DTMF_RFC2833;
static int gDTMFCodec = 101;
static int gFAXdetect = FAXDETECT_CNG;
@@ -366,15 +360,17 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
const char *host, struct ast_format_cap *cap,
const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps = NULL;
struct ast_channel *ch = NULL;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt = NULL;
int features = 0;
if (gH323Debug) {
ast_verb(0, "--- ooh323_new - %s\n", host);
}
- ast_format_clear(&tmpfmt);
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+
/* Don't hold a h323 pvt lock while we allocate a channel */
ast_mutex_unlock(&i->lock);
ast_mutex_lock(&ooh323c_cn_lock);
@@ -386,17 +382,25 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_mutex_lock(&i->lock);
- if (ch) {
+ if (ch && caps) {
ast_channel_tech_set(ch, &ooh323_tech);
- if (cap)
- ast_best_codec(cap, &tmpfmt);
- if (!tmpfmt.id)
- ast_codec_pref_index(&i->prefs, 0, &tmpfmt);
+ if (cap) {
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ }
+ if (!tmpfmt) {
+ tmpfmt = ast_format_cap_get_format(i->cap, 0);
+ }
+
+ ast_format_cap_append(caps, tmpfmt, 0);
+ ast_channel_nativeformats_set(ch, caps);
+ ao2_ref(caps, -1);
- ast_format_cap_add(ast_channel_nativeformats(ch), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(ch), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(ch), &tmpfmt);
+ ast_channel_set_rawwriteformat(ch, tmpfmt);
+ ast_channel_set_rawreadformat(ch, tmpfmt);
+ ast_set_write_format(ch, tmpfmt);
+ ast_set_read_format(ch, tmpfmt);
+ ao2_ref(tmpfmt, -1);
ast_jb_configure(ch, &global_jbconf);
@@ -404,8 +408,6 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_channel_rings_set(ch, 1);
ast_channel_adsicpe_set(ch, AST_ADSI_UNAVAILABLE);
- ast_set_write_format(ch, &tmpfmt);
- ast_set_read_format(ch, &tmpfmt);
ast_channel_tech_pvt_set(ch, i);
i->owner = ch;
ast_module_ref(myself);
@@ -485,8 +487,10 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_publish_channel_state(ch);
}
- } else
+ } else {
+ ao2_cleanup(caps);
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ }
if(ch) ast_channel_unlock(ch);
@@ -512,7 +516,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
return NULL;
}
- if (!(pvt->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(pvt->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_free(pvt);
ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
return NULL;
@@ -546,8 +550,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode));
pvt->amaflags = gAMAFLAGS;
- ast_format_cap_copy(pvt->cap, gCap);
- memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs));
+ ast_format_cap_append_from_cap(pvt->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
pvt->aniasdni = gANIasDNI;
@@ -573,21 +576,21 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_channel *chan = NULL;
struct ooh323_pvt *p = NULL;
struct ooh323_peer *peer = NULL;
char *dest = NULL;
char *ext = NULL;
char tmp[256];
- char formats[FORMAT_STRING_SIZE];
int port = 0;
- if (gH323Debug)
- ast_verb(0, "--- ooh323_request - data %s format %s\n", data,
- ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
+ if (gH323Debug) {
+ ast_verb(0, "--- ooh323_request - data %s format %s\n", data, ast_format_cap_get_names(cap, &codec_buf));
+ }
- 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));
+ if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
@@ -651,8 +654,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
if (ext)
ast_copy_string(p->exten, ext, sizeof(p->exten));
- ast_format_cap_copy(p->cap, peer->cap);
- memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref));
+ ast_format_cap_append_from_cap(p->cap, peer->cap, AST_MEDIA_TYPE_UNKNOWN);
p->g729onlyA = peer->g729onlyA;
p->dtmfmode |= peer->dtmfmode;
p->dtmfcodec = peer->dtmfcodec;
@@ -697,7 +699,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
p->t38support = gT38Support;
p->rtptimeout = gRTPTimeout;
p->nat = gNat;
- ast_format_cap_copy(p->cap, gCap);
+ ast_format_cap_append_from_cap(p->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
p->rtdrinterval = gRTDRInterval;
p->rtdrcount = gRTDRCount;
p->faststart = gFastStart;
@@ -705,7 +707,6 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
p->directrtp = gDirectRTP;
p->earlydirect = gEarlyDirect;
- memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
p->username = strdup(dest);
p->host = strdup(dest);
@@ -1164,7 +1165,6 @@ static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
{
struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
int res = 0;
- char buf[256];
if (p) {
ast_mutex_lock(&p->lock);
@@ -1190,16 +1190,17 @@ static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
}
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
- if (!(ast_format_cap_is_empty(ast_channel_nativeformats(ast)))) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cap_count(ast_channel_nativeformats(ast))) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&f->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(f->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
- ast_set_write_format(ast, &f->subclass.format);
+ ast_set_write_format(ast, f->subclass.format);
} else {
/* ast_set_write_format(ast, f->subclass);
ast->nativeformats = f->subclass; */
@@ -1508,11 +1509,10 @@ static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan
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_verb(0, "--- ooh323_update_writeformat %s/%d\n",
- ast_getformatname(fmt), txframes);
+ ast_format_get_name(fmt), txframes);
p = find_call(call);
if (!p) {
@@ -1522,9 +1522,17 @@ void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txfra
ast_mutex_lock(&p->lock);
- ast_format_copy(&(p->writeformat), fmt);
+ ao2_replace(p->writeformat, fmt);
if (p->owner) {
+ struct ast_format_cap *caps;
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
+ return;
+ }
+
while (p->owner && ast_channel_trylock(p->owner)) {
ast_debug(1,"Failed to grab lock, trying again\n");
DEADLOCK_AVOIDANCE(&p->lock);
@@ -1532,15 +1540,16 @@ void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txfra
if (!p->owner) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
+ ao2_ref(caps, -1);
return;
}
- if (gH323Debug)
- ast_verb(0, "Writeformat before update %s/%s\n",
- ast_getformatname(ast_channel_writeformat(p->owner)),
- ast_getformatname_multiple(formats, sizeof(formats), ast_channel_nativeformats(p->owner)));
- 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);
+ if (gH323Debug) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_verb(0, "Writeformat before update %s/%s\n",
+ ast_format_get_name(ast_channel_writeformat(p->owner)),
+ ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &codec_buf));
+ }
+
if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
@@ -1550,7 +1559,12 @@ void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txfra
p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
}
- ast_format_cap_set(ast_channel_nativeformats(p->owner), fmt);
+ if (txframes) {
+ ast_format_cap_set_framing(caps, txframes);
+ }
+ ast_format_cap_append(caps, fmt, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_channel_unlock(p->owner);
@@ -1570,7 +1584,7 @@ void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
if (gH323Debug)
ast_verb(0, "--- ooh323_update_readformat %s\n",
- ast_getformatname(fmt));
+ ast_format_get_name(fmt));
p = find_call(call);
if (!p) {
@@ -1580,9 +1594,17 @@ void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
ast_mutex_lock(&p->lock);
- ast_format_copy(&(p->readformat), fmt);
+ ao2_replace(p->readformat, fmt);
if (p->owner) {
+ struct ast_format_cap *caps;
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
+ return;
+ }
+
while (p->owner && ast_channel_trylock(p->owner)) {
ast_debug(1,"Failed to grab lock, trying again\n");
DEADLOCK_AVOIDANCE(&p->lock);
@@ -1590,14 +1612,18 @@ void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
if (!p->owner) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
+ ao2_ref(caps, -1);
return;
}
- if (gH323Debug)
- ast_verb(0, "Readformat before update %s\n",
- ast_getformatname(ast_channel_readformat(p->owner)));
- ast_format_cap_set(ast_channel_nativeformats(p->owner), fmt);
- ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
+ if (gH323Debug) {
+ ast_verb(0, "Readformat before update %s\n",
+ ast_format_get_name(ast_channel_readformat(p->owner)));
+ }
+ ast_format_cap_append(caps, fmt, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_channel_unlock(p->owner);
} else
ast_log(LOG_ERROR, "No owner found\n");
@@ -1854,9 +1880,8 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
ast_copy_string(p->context, user->context, sizeof(p->context));
ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
p->amaflags = user->amaflags;
- ast_format_cap_copy(p->cap, user->cap);
+ ast_format_cap_append_from_cap(p->cap, user->cap, AST_MEDIA_TYPE_UNKNOWN);
p->g729onlyA = user->g729onlyA;
- memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
p->dtmfmode |= user->dtmfmode;
p->dtmfcodec = user->dtmfcodec;
p->faxdetect = user->faxdetect;
@@ -1914,7 +1939,7 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
}
}
- ooh323c_set_capability_for_call(call, &p->prefs, p->cap, p->dtmfmode, p->dtmfcodec,
+ ooh323c_set_capability_for_call(call, p->cap, p->dtmfmode, p->dtmfcodec,
p->t38support, p->g729onlyA);
/* Incoming call */
c = ooh323_new(p, AST_STATE_RING, p->username, 0, NULL, NULL);
@@ -2088,13 +2113,14 @@ int onNewCallCreated(ooCallData *call)
}
if (gH323Debug) {
- char prefsBuf[256];
- ast_codec_pref_string(&p->prefs, prefsBuf, sizeof(prefsBuf));
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
ast_verb(0, " Outgoing call %s(%s) - Codec prefs - %s\n",
- p->username?p->username:"NULL", call->callToken, prefsBuf);
+ p->username?p->username:"NULL", call->callToken,
+ ast_format_cap_get_names(p->cap, &codec_buf));
}
- ooh323c_set_capability_for_call(call, &p->prefs, p->cap,
+ ooh323c_set_capability_for_call(call, p->cap,
p->dtmfmode, p->dtmfcodec, p->t38support, p->g729onlyA);
configure_local_rtp(p, call);
@@ -2284,7 +2310,7 @@ void ooh323_delete_peer(struct ooh323_peer *peer)
if(peer->url) free(peer->url);
if(peer->e164) free(peer->e164);
- peer->cap = ast_format_cap_destroy(peer->cap);
+ ao2_cleanup(peer->cap);
free(peer);
}
@@ -2311,8 +2337,7 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
}
ast_mutex_init(&user->lock);
ast_copy_string(user->name, name, sizeof(user->name));
- ast_format_cap_copy(user->cap, gCap);
- memcpy(&user->prefs, &gPrefs, sizeof(user->prefs));
+ ast_format_cap_append_from_cap(user->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
user->rtptimeout = gRTPTimeout;
user->nat = gNat;
user->dtmfmode = gDTMFMode;
@@ -2367,15 +2392,13 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
sizeof(user->rtpmaskstr));
} else user->rtpmask = NULL;
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&user->prefs,
- user->cap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(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->cap, tcodecs, 1);
+ ast_format_cap_update_by_allow_disallow(user->cap, tcodecs, 1);
} else if (!strcasecmp(v->name, "amaflags")) {
user->amaflags = ast_channel_string2amaflag(v->value);
} else if (!strcasecmp(v->name, "ip") || !strcasecmp(v->name, "host")) {
@@ -2461,8 +2484,7 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v,
}
ast_mutex_init(&peer->lock);
ast_copy_string(peer->name, name, sizeof(peer->name));
- ast_format_cap_copy(peer->cap, gCap);
- memcpy(&peer->prefs, &gPrefs, sizeof(peer->prefs));
+ ast_format_cap_append_from_cap(peer->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
peer->rtptimeout = gRTPTimeout;
peer->nat = gNat;
ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode));
@@ -2565,15 +2587,13 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v,
sizeof(peer->rtpmaskstr));
} else peer->rtpmask = NULL;
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&peer->prefs, peer->cap,
- v->value, 0);
+ ast_format_cap_update_by_allow_disallow(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->cap,
- tcodecs, 1);
+ ast_format_cap_update_by_allow_disallow(peer->cap, tcodecs, 1);
} else if (!strcasecmp(v->name, "amaflags")) {
peer->amaflags = ast_channel_string2amaflag(v->value);
} else if (!strcasecmp(v->name, "roundtrip")) {
@@ -2754,7 +2774,6 @@ int reload_config(int reload)
struct ooh323_peer *peer = NULL;
char *cat;
const char *utype;
- struct ast_format tmpfmt;
if (gH323Debug)
ast_verb(0, "--- reload_config\n");
@@ -2790,8 +2809,8 @@ int reload_config(int reload)
gPort = 1720;
gIP[0] = '\0';
strcpy(gCallerID, DEFAULT_H323ID);
- ast_format_cap_set(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
- memset(&gPrefs, 0, sizeof(struct ast_codec_pref));
+ ast_format_cap_remove_by_type(gCap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(gCap, ast_format_ulaw, 0);
gDTMFMode = H323_DTMF_RFC2833;
gDTMFCodec = 101;
gFAXdetect = FAXDETECT_CNG;
@@ -2992,13 +3011,13 @@ int reload_config(int reload)
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode));
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&gPrefs, gCap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(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, gCap, tcodecs, 1);
+ ast_format_cap_update_by_allow_disallow(gCap, tcodecs, 1);
} else if (!strcasecmp(v->name, "dtmfmode")) {
if (!strcasecmp(v->value, "inband"))
gDTMFMode = H323_DTMF_INBAND;
@@ -3150,9 +3169,6 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc
peer->h245tunneling?"yes":"no");
ast_cli(a->fd, "%-15s%s\n", "DirectRTP", peer->directrtp ? "yes" : "no");
ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", peer->earlydirect ? "yes" : "no");
- ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
- print_codec_to_cli(a->fd, &peer->prefs);
- ast_cli(a->fd, ")\n");
ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
if (peer->dtmfmode & H323_DTMF_CISCO) {
ast_cli(a->fd, "%s\n", "cisco");
@@ -3214,7 +3230,7 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc
static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ooh323_peer *prev = NULL, *peer = NULL;
- char formats[FORMAT_STRING_SIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
char ip_port[30];
#define FORMAT "%-15.15s %-15.15s %-23.23s %-s\n"
@@ -3239,10 +3255,10 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, stru
while (peer) {
ast_mutex_lock(&peer->lock);
snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
- ast_cli(a->fd, FORMAT, peer->name,
+ ast_cli(a->fd, FORMAT, peer->name,
peer->accountcode,
ip_port,
- ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,peer->cap));
+ ast_format_cap_get_names(peer->cap, &codec_buf));
prev = peer;
peer = peer->next;
ast_mutex_unlock(&prev->lock);
@@ -3253,24 +3269,6 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, stru
return CLI_SUCCESS;
}
-/*! \brief Print codec list from preference to CLI/manager */
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
-{
- int x;
- struct ast_format tmpfmt;
- for (x = 0; x < 32; x++) {
- ast_codec_pref_index(pref, x, &tmpfmt);
- if (!tmpfmt.id)
- break;
- ast_cli(fd, "%s", ast_getformatname(&tmpfmt));
- ast_cli(fd, ":%d", pref->framing[x]);
- if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt))
- ast_cli(fd, ",");
- }
- if (!x)
- ast_cli(fd, "none");
-}
-
static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ooh323_user *prev = NULL, *user = NULL;
@@ -3309,9 +3307,6 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc
user->h245tunneling?"yes":"no");
ast_cli(a->fd, "%-15s%s\n", "DirectRTP", user->directrtp ? "yes" : "no");
ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", user->earlydirect ? "yes" : "no");
- ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
- print_codec_to_cli(a->fd, &user->prefs);
- ast_cli(a->fd, ")\n");
ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
if (user->dtmfmode & H323_DTMF_CISCO) {
ast_cli(a->fd, "%s\n", "cisco");
@@ -3374,7 +3369,7 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc
static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ooh323_user *prev = NULL, *user = NULL;
- char formats[FORMAT_STRING_SIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
#define FORMAT1 "%-15.15s %-15.15s %-15.15s %-s\n"
switch (cmd) {
@@ -3401,7 +3396,7 @@ static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, stru
ast_mutex_lock(&user->lock);
ast_cli(a->fd, FORMAT1, user->name,
user->accountcode, user->context,
- ast_getformatname_multiple(formats, FORMAT_STRING_SIZE, user->cap));
+ ast_format_cap_get_names(user->cap, &codec_buf));
prev = user;
user = user->next;
ast_mutex_unlock(&prev->lock);
@@ -3508,6 +3503,7 @@ static char *handle_cli_ooh323_show_gk(struct ast_cli_entry *e, int cmd, struct
static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char value[FORMAT_STRING_SIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
ooAliases *pAlias = NULL, *pAliasNext = NULL;;
switch (cmd) {
@@ -3556,7 +3552,7 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str
ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile);
ast_cli(a->fd, "%-20s%s\n", "Context:", gContext);
ast_cli(a->fd, "%-20s%s\n", "Capability:",
- ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap));
+ ast_format_cap_get_names(gCap, &codec_buf));
ast_cli(a->fd, "%-20s", "DTMF Mode: ");
if (gDTMFMode & H323_DTMF_CISCO) {
ast_cli(a->fd, "%s\n", "cisco");
@@ -3737,7 +3733,6 @@ static int load_module(void)
{
struct ooAliases * pNewAlias = NULL;
struct ooh323_peer *peer = NULL;
- struct ast_format tmpfmt;
OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
OOH323CALLBACKS h323Callbacks = {
@@ -3753,14 +3748,16 @@ static int load_module(void)
.onModeChanged = onModeChanged,
.onMediaChanged = (cb_OnMediaChanged) setup_rtp_remote,
};
- if (!(gCap = ast_format_cap_alloc(0))) {
+ if (!(gCap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- if (!(ooh323_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(ooh323_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ ao2_ref(gCap, -1);
+ gCap = NULL;
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add_all(ooh323_tech.capabilities);
+ ast_format_cap_append(gCap, ast_format_ulaw, 0);
+ ast_format_cap_append_by_type(ooh323_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
myself = ast_module_info->self;
@@ -3789,12 +3786,20 @@ static int load_module(void)
if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) {
ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-"
"OOH323 Disabled\n");
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure we can register our OOH323 channel type */
if (ast_channel_register(&ooh323_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return AST_MODULE_LOAD_FAILURE;
}
ast_rtp_glue_register(&ooh323_rtp);
@@ -3876,8 +3881,12 @@ static int load_module(void)
ooH323EpSetH323Callbacks(h323Callbacks);
/* Add endpoint capabilities */
- if (ooh323c_set_capability(&gPrefs, gCap, gDTMFMode, gDTMFCodec) < 0) {
+ if (ooh323c_set_capability(gCap, gDTMFMode, gDTMFCodec) < 0) {
ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 1;
}
@@ -3887,6 +3896,10 @@ static int load_module(void)
"OOH323 DISABLED\n");
ooH323EpDestroy();
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 1;
}
@@ -3894,6 +3907,10 @@ static int load_module(void)
ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. "
"OOH323 DISABLED\n");
ooH323EpDestroy();
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 1;
}
/* And start the monitor for the first time */
@@ -4142,7 +4159,9 @@ int ooh323_destroy(struct ooh323_pvt *p)
ast_mutex_unlock(&cur->lock);
ast_mutex_destroy(&cur->lock);
- cur->cap = ast_format_cap_destroy(cur->cap);
+ ao2_cleanup(cur->writeformat);
+ ao2_cleanup(cur->readformat);
+ ao2_cleanup(cur->cap);
ast_free(cur);
}
@@ -4207,7 +4226,7 @@ int delete_users()
free(prev->rtpmask);
}
}
- prev->cap = ast_format_cap_destroy(prev->cap);
+ ao2_cleanup(prev->cap);
free(prev);
if (cur == userl.users) {
break;
@@ -4335,8 +4354,10 @@ static int unload_module(void)
ast_verb(0, "+++ ooh323 unload_module \n");
}
- gCap = ast_format_cap_destroy(gCap);
- ooh323_tech.capabilities = ast_format_cap_destroy(ooh323_tech.capabilities);
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 0;
}
@@ -4348,8 +4369,11 @@ static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *re
}
if (p) {
- ast_format_cap_append(result, ast_format_cap_is_empty(ast_channel_nativeformats(chan)) ?
- (ast_format_cap_is_empty(p->cap) ? NULL : p->cap) : ast_channel_nativeformats(chan));
+ if (ast_format_cap_count(ast_channel_nativeformats(chan))) {
+ ast_format_cap_append_from_cap(result, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_UNKNOWN);
+ } else if (ast_format_cap_count(p->cap)) {
+ ast_format_cap_append_from_cap(result, p->cap, AST_MEDIA_TYPE_UNKNOWN);
+ }
}
if (gH323Debug) {
@@ -4423,56 +4447,28 @@ static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, s
return res;
}
-
-int ooh323_update_capPrefsOrderForCall
- (ooCallData *call, struct ast_codec_pref *prefs)
-{
- int i = 0;
- struct ast_format tmpfmt;
-
- ast_codec_pref_index(prefs, i, &tmpfmt);
-
- ooResetCapPrefs(call);
- while (tmpfmt.id) {
- ooAppendCapToCapPrefs(call, ooh323_convertAsteriskCapToH323Cap(&tmpfmt));
- ast_codec_pref_index(prefs, ++i, &tmpfmt);
- }
-
- return 0;
-}
-
-
int ooh323_convertAsteriskCapToH323Cap(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_ULAW:
+ if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return OO_G711ULAW64K;
- case AST_FORMAT_ALAW:
+ } else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return OO_G711ALAW64K;
- case AST_FORMAT_GSM:
+ } else if (ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL) {
return OO_GSMFULLRATE;
-
-#ifdef AST_FORMAT_AMRNB
- case AST_FORMAT_AMRNB:
- return OO_AMRNB;
-#endif
-#ifdef AST_FORMAT_SPEEX
- case AST_FORMAT_SPEEX:
+ } else if (ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL) {
return OO_SPEEX;
-#endif
-
- case AST_FORMAT_G729A:
+ } else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
return OO_G729A;
- case AST_FORMAT_G726:
+ } else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
return OO_G726;
- case AST_FORMAT_G726_AAL2:
+ } else if (ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
return OO_G726AAL2;
- case AST_FORMAT_G723_1:
+ } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
return OO_G7231;
- case AST_FORMAT_H263:
+ } else if (ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
return OO_H263VIDEO;
- default:
- ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_getformatname(format));
+ } else {
+ ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_format_get_name(format));
return -1;
}
}
@@ -4551,9 +4547,6 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
struct ast_sockaddr tmp;
ooMediaInfo mediaInfo;
int x;
- struct ast_format tmpfmt;
-
- ast_format_clear(&tmpfmt);
if (gH323Debug)
ast_verb(0, "--- configure_local_rtp\n");
@@ -4599,7 +4592,10 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
ast_channel_unlock(p->owner);
if (p->rtp) {
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ if (p->cap) {
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp),
+ ast_format_cap_get_framing(p->cap));
+ }
if (p->nat) {
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, 1);
}
@@ -4636,9 +4632,11 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
mediaInfo.lMediaPort = lport;
mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort + 1;
- for (x = 0; ast_codec_pref_index(&p->prefs, x, &tmpfmt); x++) {
+ for (x = 0; x < ast_format_cap_count(p->cap); x++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, x);
+
strcpy(mediaInfo.dir, "transmit");
- mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(&tmpfmt);
+ mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format);
ooAddMediaInfo(call, mediaInfo);
strcpy(mediaInfo.dir, "receive");
ooAddMediaInfo(call, mediaInfo);
@@ -4655,6 +4653,8 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
strcpy(mediaInfo.dir, "receive");
ooAddMediaInfo(call, mediaInfo);
}
+
+ ao2_ref(format, -1);
}
if (p->udptl) {
@@ -4738,7 +4738,7 @@ void setup_rtp_connection(ooCallData *call, const char *remoteIp, int remotePort
ast_sockaddr_set_port(&tmp, remotePort);
ast_rtp_instance_set_remote_address(p->rtp, &tmp);
- if (p->writeformat.id == AST_FORMAT_G726_AAL2) {
+ if (ast_format_cmp(p->writeformat, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
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);
}
@@ -4955,15 +4955,24 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p)
if (f && p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) {
/* We already hold the channel lock */
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(p->owner), &f->subclass.format))) {
- ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(p->owner), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(p->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, voice format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
}
if (((p->dtmfmode & H323_DTMF_INBAND) || (p->faxdetect & FAXDETECT_CNG)) && p->vad &&
- (f->subclass.format.id == AST_FORMAT_SLINEAR || f->subclass.format.id == AST_FORMAT_ALAW ||
- f->subclass.format.id == AST_FORMAT_ULAW)) {
+ ((ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(f->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL))) {
dfr = ast_frdup(f);
dfr = ast_dsp_process(p->owner, p->vad, dfr);
}
diff --git a/addons/chan_ooh323.h b/addons/chan_ooh323.h
index 689adced2..89caaff63 100644
--- a/addons/chan_ooh323.h
+++ b/addons/chan_ooh323.h
@@ -65,6 +65,7 @@
#include "asterisk/format_cap.h"
#include "asterisk/udptl.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
#include "ootypes.h"
#include "ooUtils.h"
@@ -104,9 +105,6 @@ struct ast_frame *ooh323_rtp_read
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(struct ast_format *format);
int ooh323_convert_hangupcause_asteriskToH323(int cause);
diff --git a/addons/format_mp3.c b/addons/format_mp3.c
index 78fcc28c5..4c98789ab 100644
--- a/addons/format_mp3.c
+++ b/addons/format_mp3.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/mod_format.h"
#include "asterisk/logger.h"
+#include "asterisk/format_cache.h"
#define MP3_BUFLEN 320
#define MP3_SCACHE 16384
@@ -229,10 +230,7 @@ static struct ast_frame *mp3_read(struct ast_filestream *s, int *whennext)
p->offset += p->buflen;
delay = p->buflen / 2;
- s->fr.frametype = AST_FRAME_VOICE;
- 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;
*whennext = delay;
return &s->fr;
@@ -318,7 +316,7 @@ static struct ast_format_def mp3_f = {
static int load_module(void)
{
- ast_format_set(&mp3_f.format, AST_FORMAT_SLINEAR, 0);
+ mp3_f.format = ast_format_slin;
InitMP3Constants();
return ast_format_def_register(&mp3_f);
}
diff --git a/addons/ooh323cDriver.c b/addons/ooh323cDriver.c
index dd127a499..bceb07745 100644
--- a/addons/ooh323cDriver.c
+++ b/addons/ooh323cDriver.c
@@ -225,17 +225,17 @@ int ooh323c_stop_stack_thread(void)
}
int ooh323c_set_capability
- (struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec)
+ (struct ast_format_cap *cap, int dtmf, int dtmfcodec)
{
int ret = 0, x;
- struct ast_format tmpfmt;
if (gH323Debug) {
ast_verb(0, "\tAdding capabilities to H323 endpoint\n");
}
- for(x=0; ast_codec_pref_index(prefs, x, &tmpfmt); x++)
+ for(x=0; x<ast_format_cap_count(cap); x++)
{
- if(tmpfmt.id == AST_FORMAT_ULAW)
+ struct ast_format *format = ast_format_cap_get_format(cap, x);
+ if(ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 ulaw capability to H323 endpoint\n");
@@ -246,7 +246,7 @@ int ooh323c_set_capability
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_ALAW)
+ if(ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 alaw capability to H323 endpoint\n");
@@ -258,7 +258,7 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_G729A)
+ if(ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g729A capability to H323 endpoint\n");
@@ -287,7 +287,7 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_G723_1)
+ if(ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g7231 capability to H323 endpoint\n");
@@ -300,7 +300,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_G726)
+ if(ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726 capability to H323 endpoint\n");
@@ -313,7 +313,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_G726_AAL2)
+ if(ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726aal2 capability to H323 endpoint\n");
@@ -326,7 +326,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_H263)
+ if(ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding h263 capability to H323 endpoint\n");
@@ -339,7 +339,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_GSM)
+ if(ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding gsm capability to H323 endpoint\n");
@@ -351,24 +351,8 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
-
-#ifdef AST_FORMAT_AMRNB
- if(tmpfmt.id == AST_FORMAT_AMRNB)
- {
- if (gH323Debug) {
- ast_verb(0, "\tAdding amr nb capability to H323 endpoint\n");
- }
- ret = ooH323EpAddAMRNBCapability(OO_AMRNB, 4, 4, FALSE,
- OORXANDTX, &ooh323c_start_receive_channel,
- &ooh323c_start_transmit_channel,
- &ooh323c_stop_receive_channel,
- &ooh323c_stop_transmit_channel);
-
- }
-#endif
-#ifdef AST_FORMAT_SPEEX
- if(tmpfmt.id == AST_FORMAT_SPEEX)
+ if(ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding speex capability to H323 endpoint\n");
@@ -380,8 +364,8 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
-#endif
-
+
+ ao2_ref(format, -1);
}
if(dtmf & H323_DTMF_CISCO)
@@ -397,11 +381,10 @@ int ooh323c_set_capability
}
int ooh323c_set_capability_for_call
- (ooCallData *call, struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
+ (ooCallData *call, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
int t38support, int g729onlyA)
{
int ret = 0, x, txframes;
- struct ast_format tmpfmt;
if (gH323Debug) {
ast_verb(0, "\tAdding capabilities to call(%s, %s)\n", call->callType,
call->callToken);
@@ -423,15 +406,16 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_transmit_datachannel,
0);
- for(x=0; ast_codec_pref_index(prefs, x, &tmpfmt); x++)
+ for(x=0; x<ast_format_cap_count(cap); x++)
{
- if(tmpfmt.id == AST_FORMAT_ULAW)
+ struct ast_format *format = ast_format_cap_get_format(cap, x);
+ if(ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 ulaw capability to call(%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret= ooCallAddG711Capability(call, OO_G711ULAW64K, txframes,
txframes, OORXANDTX,
&ooh323c_start_receive_channel,
@@ -439,13 +423,13 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_ALAW)
+ if(ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 alaw capability to call(%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret= ooCallAddG711Capability(call, OO_G711ALAW64K, txframes,
txframes, OORXANDTX,
&ooh323c_start_receive_channel,
@@ -454,13 +438,13 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_G726)
+ if(ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726 capability to call (%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret = ooCallAddG726Capability(call, OO_G726, txframes, grxframes, FALSE,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
@@ -469,13 +453,13 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_G726_AAL2)
+ if(ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726aal2 capability to call (%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret = ooCallAddG726Capability(call, OO_G726AAL2, txframes, grxframes, FALSE,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
@@ -484,10 +468,10 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_G729A)
+ if(ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL)
{
- txframes = (prefs->framing[x])/10;
+ txframes = (ast_format_cap_get_format_framing(cap, format))/10;
if (gH323Debug) {
ast_verb(0, "\tAdding g729A capability to call(%s, %s)\n",
call->callType, call->callToken);
@@ -520,7 +504,7 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_G723_1)
+ if(ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g7231 capability to call (%s, %s)\n",
@@ -534,7 +518,7 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_H263)
+ if(ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding h263 capability to call (%s, %s)\n",
@@ -548,7 +532,7 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_GSM)
+ if(ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding gsm capability to call(%s, %s)\n",
@@ -561,22 +545,7 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_transmit_channel);
}
-#ifdef AST_FORMAT_AMRNB
- if(tmpfmt.id == AST_FORMAT_AMRNB)
- {
- if (gH323Debug) {
- ast_verb(0, "\tAdding AMR capability to call(%s, %s)\n",
- call->callType, call->callToken);
- }
- ret = ooCallAddAMRNBCapability(call, OO_AMRNB, 4, 4, FALSE,
- OORXANDTX, &ooh323c_start_receive_channel,
- &ooh323c_start_transmit_channel,
- &ooh323c_stop_receive_channel,
- &ooh323c_stop_transmit_channel);
- }
-#endif
-#ifdef AST_FORMAT_SPEEX
- if(tmpfmt.id == AST_FORMAT_SPEEX)
+ if(ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding Speex capability to call(%s, %s)\n",
@@ -588,7 +557,8 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
-#endif
+
+ ao2_ref(format, -1);
}
return ret;
}
@@ -622,9 +592,9 @@ int ooh323c_set_aliases(ooAliases * aliases)
int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel)
{
- struct ast_format tmpfmt;
- convertH323CapToAsteriskCap(pChannel->chanCap->cap, &tmpfmt);
- if(tmpfmt.id) {
+ struct ast_format *tmpfmt = NULL;
+ tmpfmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
+ if(tmpfmt) {
/* ooh323_set_read_format(call, fmt); */
}else{
ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
@@ -636,19 +606,17 @@ int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel)
int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel)
{
- 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, &tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes);
- break;
- case AST_FORMAT_G729A:
- ooh323_set_write_format(call, &tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10);
- break;
- default:
- ooh323_set_write_format(call, &tmpfmt, 0);
+ struct ast_format *tmpfmt = NULL;
+ tmpfmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
+
+ if (tmpfmt) {
+ if ((ast_format_cmp(tmpfmt, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(tmpfmt, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)) {
+ ooh323_set_write_format(call, tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes);
+ } else if (ast_format_cmp(tmpfmt, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
+ ooh323_set_write_format(call, tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10);
+ } else {
+ ooh323_set_write_format(call, tmpfmt, 0);
}
}else{
ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
@@ -693,41 +661,32 @@ int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChann
return 1;
}
-struct ast_format *convertH323CapToAsteriskCap(int cap, struct ast_format *result)
+struct ast_format *convertH323CapToAsteriskCap(int cap)
{
- ast_format_clear(result);
switch(cap)
{
case OO_G711ULAW64K:
- return ast_format_set(result, AST_FORMAT_ULAW, 0);
+ return ast_format_ulaw;
case OO_G711ALAW64K:
- return ast_format_set(result, AST_FORMAT_ALAW, 0);
+ return ast_format_alaw;
case OO_GSMFULLRATE:
- return ast_format_set(result, AST_FORMAT_GSM, 0);
-
-#ifdef AST_FORMAT_AMRNB
- case OO_AMRNB:
- return ast_format_set(result, AST_FORMAT_AMRNB, 0);
-#endif
-#ifdef AST_FORMAT_SPEEX
+ return ast_format_gsm;
case OO_SPEEX:
- return ast_format_set(result, AST_FORMAT_SPEEX, 0);
-#endif
-
+ return ast_format_speex;
case OO_G729:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case OO_G729A:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case OO_G729B:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case OO_G7231:
- return ast_format_set(result, AST_FORMAT_G723_1, 0);
+ return ast_format_g723;
case OO_G726:
- return ast_format_set(result, AST_FORMAT_G726, 0);
+ return ast_format_g726;
case OO_G726AAL2:
- return ast_format_set(result, AST_FORMAT_G726_AAL2, 0);
+ return ast_format_g726_aal2;
case OO_H263VIDEO:
- return ast_format_set(result, AST_FORMAT_H263, 0);
+ return ast_format_h263;
default:
ast_debug(1, "Cap %d is not supported by driver yet\n", cap);
return NULL;
diff --git a/addons/ooh323cDriver.h b/addons/ooh323cDriver.h
index af03eeaea..98198019a 100644
--- a/addons/ooh323cDriver.h
+++ b/addons/ooh323cDriver.h
@@ -37,9 +37,9 @@ int ooh323c_stop_stack_thread(void);
int ooh323c_start_call_thread(ooCallData *call);
int ooh323c_stop_call_thread(ooCallData *call);
int ooh323c_set_capability
- (struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec);
-struct ast_format *convertH323CapToAsteriskCap(int cap, struct ast_format *format);
+ (struct ast_format_cap *cap, int dtmf, int dtmfcodec);
+struct ast_format *convertH323CapToAsteriskCap(int cap);
int ooh323c_set_capability_for_call
- (ooCallData *call, struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
+ (ooCallData *call, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
int t38support, int g729onlyA);
#endif
diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c
index 5095001cf..f531c1613 100644
--- a/apps/app_agent_pool.c
+++ b/apps/app_agent_pool.c
@@ -2136,8 +2136,8 @@ static int agent_login_exec(struct ast_channel *chan, const char *data)
}
ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
- ast_getformatname(ast_channel_readformat(chan)),
- ast_getformatname(ast_channel_writeformat(chan)));
+ ast_format_get_name(ast_channel_readformat(chan)),
+ ast_format_get_name(ast_channel_writeformat(chan)));
ast_channel_lock(chan);
send_agent_login(chan, agent->username);
ast_channel_unlock(chan);
diff --git a/apps/app_alarmreceiver.c b/apps/app_alarmreceiver.c
index 9063e1a60..4f9de364d 100644
--- a/apps/app_alarmreceiver.c
+++ b/apps/app_alarmreceiver.c
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
#include "asterisk/indications.h"
+#include "asterisk/format_cache.h"
#define ALMRCV_CONFIG "alarmreceiver.conf"
#define UNKNOWN_FORMAT "UNKNOWN_FORMAT"
@@ -798,19 +799,19 @@ static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
char signalling_type[64] = "";
event_node_t *event_head = NULL;
- if (ast_channel_writeformat(chan)->id != AST_FORMAT_ALAW
- && ast_channel_writeformat(chan)->id != AST_FORMAT_ULAW) {
+ if ((ast_format_cmp(ast_channel_writeformat(chan), ast_format_ulaw) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ (ast_format_cmp(ast_channel_writeformat(chan), ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL)) {
ast_verb(4, "AlarmReceiver: Setting write format to Mu-law\n");
- if (ast_set_write_format_by_id(chan,AST_FORMAT_ULAW)) {
+ if (ast_set_write_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan));
return -1;
}
}
- if (ast_channel_readformat(chan)->id != AST_FORMAT_ALAW
- && ast_channel_readformat(chan)->id != AST_FORMAT_ULAW) {
+ if ((ast_format_cmp(ast_channel_readformat(chan), ast_format_ulaw) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ (ast_format_cmp(ast_channel_readformat(chan), ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL)) {
ast_verb(4, "AlarmReceiver: Setting read format to Mu-law\n");
- if (ast_set_read_format_by_id(chan,AST_FORMAT_ULAW)) {
+ if (ast_set_read_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan));
return -1;
}
diff --git a/apps/app_amd.c b/apps/app_amd.c
index d8f26b49b..3dd8cc617 100644
--- a/apps/app_amd.c
+++ b/apps/app_amd.c
@@ -52,6 +52,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="AMD" language="en_US">
@@ -163,7 +164,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
struct ast_frame *f = NULL;
struct ast_dsp *silenceDetector = NULL;
int dspsilence = 0, framelength = 0;
- struct ast_format readFormat;
+ RAII_VAR(struct ast_format *, readFormat, NULL, ao2_cleanup);
int inInitialSilence = 1;
int inGreeting = 0;
int voiceDuration = 0;
@@ -202,11 +203,10 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
AST_APP_ARG(argMaximumWordLength);
);
- ast_format_clear(&readFormat);
ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", ast_channel_name(chan),
S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, "(N/A)"),
S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "(N/A)"),
- ast_getformatname(ast_channel_readformat(chan)));
+ ast_format_get_name(ast_channel_readformat(chan)));
/* Lets parse the arguments. */
if (!ast_strlen_zero(parse)) {
@@ -255,8 +255,8 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold, maximumWordLength);
/* Set read format to signed linear so we get signed linear frames in */
- ast_format_copy(&readFormat, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0 ) {
+ readFormat = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin) < 0 ) {
ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", ast_channel_name(chan));
pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
@@ -289,7 +289,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) {
/* If the total time exceeds the analysis time then give up as we are not too sure */
if (f->frametype == AST_FRAME_VOICE) {
- framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
+ framelength = (ast_codec_samples_count(f) / DEFAULT_SAMPLES_PER_MS);
} else {
framelength = 2 * maxWaitTimeForFrame;
}
@@ -412,7 +412,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause);
/* Restore channel read format */
- if (readFormat.id && ast_set_read_format(chan, &readFormat))
+ if (readFormat && ast_set_read_format(chan, readFormat))
ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", ast_channel_name(chan));
/* Free the DSP used to detect silence */
@@ -510,10 +510,10 @@ static int unload_module(void)
*/
static int load_module(void)
{
- if (load_config(0))
+ if (load_config(0) || ast_register_application_xml(app, amd_exec)) {
return AST_MODULE_LOAD_DECLINE;
- if (ast_register_application_xml(app, amd_exec))
- return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c
index 47f755e5f..af69be303 100644
--- a/apps/app_chanspy.c
+++ b/apps/app_chanspy.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/autochan.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
#define AST_NAME_STRLEN 256
#define NUM_SPYGROUPS 128
@@ -451,9 +452,6 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
{
struct chanspy_translation_helper *csth = data;
struct ast_frame *f, *cur;
- struct ast_format format_slin;
-
- ast_format_set(&format_slin, AST_FORMAT_SLINEAR, 0);
ast_audiohook_lock(&csth->spy_audiohook);
if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
@@ -464,9 +462,9 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
if (ast_test_flag(&csth->flags, 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, &format_slin);
+ f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_READ, ast_format_slin);
} else {
- f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, &format_slin);
+ f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, ast_format_slin);
}
ast_audiohook_unlock(&csth->spy_audiohook);
@@ -1181,7 +1179,7 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
.volume = '#',
.exit = '\0',
};
- struct ast_format oldwf;
+ RAII_VAR(struct ast_format *, oldwf, NULL, ao2_cleanup);
int volfactor = 0;
int res;
char *mailbox = NULL;
@@ -1194,7 +1192,6 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
char *parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_format_clear(&oldwf);
if (args.spec && !strcmp(args.spec, "all"))
args.spec = NULL;
@@ -1258,8 +1255,8 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
ast_clear_flag(&flags, AST_FLAGS_ALL);
}
- ast_format_copy(&oldwf, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ oldwf = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return -1;
}
@@ -1279,7 +1276,7 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
if (fd)
close(fd);
- if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
+ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
if (ast_test_flag(&flags, OPTION_EXITONHANGUP)) {
@@ -1301,7 +1298,7 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
.volume = '#',
.exit = '\0',
};
- struct ast_format oldwf;
+ RAII_VAR(struct ast_format *, oldwf, NULL, ao2_cleanup);
int volfactor = 0;
int res;
char *mailbox = NULL;
@@ -1313,7 +1310,6 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
char *parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_format_clear(&oldwf);
if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
exten = args.context;
@@ -1383,8 +1379,8 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
ast_clear_flag(&flags, AST_FLAGS_ALL);
}
- ast_format_copy(&oldwf, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ oldwf = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return -1;
}
@@ -1405,7 +1401,7 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
if (fd)
close(fd);
- if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
+ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return res;
@@ -1420,13 +1416,13 @@ static int dahdiscan_exec(struct ast_channel *chan, const char *data)
.volume = '\0',
.exit = '*',
};
- struct ast_format oldwf;
+ struct ast_format *oldwf;
int res;
char *mygroup = NULL;
/* Coverity - This uninit_use should be ignored since this macro initializes the flags */
ast_clear_flag(&flags, AST_FLAGS_ALL);
- ast_format_clear(&oldwf);
+
if (!ast_strlen_zero(data)) {
mygroup = ast_strdupa(data);
}
@@ -1434,16 +1430,18 @@ static int dahdiscan_exec(struct ast_channel *chan, const char *data)
ast_set_flag(&flags, OPTION_DTMF_CYCLE);
ast_set_flag(&flags, OPTION_DAHDI_SCAN);
- ast_format_copy(&oldwf, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ oldwf = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
+ ao2_cleanup(oldwf);
return -1;
}
res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
- if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
+ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
+ ao2_cleanup(oldwf);
return res;
}
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 9a704ac93..445b196d4 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="ConfBridge" language="en_US">
@@ -676,7 +677,6 @@ static int conf_stop_record_thread(struct confbridge_conference *conference)
static int conf_start_record(struct confbridge_conference *conference)
{
struct ast_format_cap *cap;
- struct ast_format format;
if (conference->record_state != CONF_RECORD_STOP) {
return -1;
@@ -687,16 +687,16 @@ static int conf_start_record(struct confbridge_conference *conference)
return -1;
}
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
conference->record_chan = ast_request("CBRec", cap, NULL, NULL,
conference->name, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
if (!conference->record_chan) {
return -1;
}
@@ -1374,16 +1374,15 @@ static void leave_conference(struct confbridge_user *user)
static int alloc_playback_chan(struct confbridge_conference *conference)
{
struct ast_format_cap *cap;
- struct ast_format format;
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
conference->name, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
if (!conference->playback_chan) {
return -1;
}
@@ -3238,7 +3237,7 @@ void conf_remove_user_waiting(struct confbridge_conference *conference, struct c
static void unregister_channel_tech(struct ast_channel_tech *tech)
{
ast_channel_unregister(tech);
- tech->capabilities = ast_format_cap_destroy(tech->capabilities);
+ ao2_cleanup(tech->capabilities);
}
/*!
@@ -3253,11 +3252,11 @@ static void unregister_channel_tech(struct ast_channel_tech *tech)
*/
static int register_channel_tech(struct ast_channel_tech *tech)
{
- tech->capabilities = ast_format_cap_alloc(0);
+ tech->capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!tech->capabilities) {
return -1;
}
- ast_format_cap_add_all(tech->capabilities);
+ ast_format_cap_append_by_type(tech->capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (ast_channel_register(tech)) {
ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
tech->type, tech->description);
diff --git a/apps/app_dictate.c b/apps/app_dictate.c
index 1820a1f83..8f229f2a9 100644
--- a/apps/app_dictate.c
+++ b/apps/app_dictate.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Dictate" language="en_US">
@@ -108,8 +109,7 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
len = 0,
maxlen = 0,
mode = 0;
- struct ast_format oldr;
- ast_format_clear(&oldr);
+ struct ast_format *oldr;
snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
if (!ast_strlen_zero(data)) {
@@ -126,9 +126,10 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
if (args.argc > 1 && args.filename) {
filename = args.filename;
}
- ast_format_copy(&oldr, ast_channel_readformat(chan));
- if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) {
+ oldr = ao2_bump(ast_channel_readformat(chan));
+ if ((res = ast_set_read_format(chan, ast_format_slin)) < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
+ ao2_cleanup(oldr);
return -1;
}
@@ -335,8 +336,9 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
ast_frfree(f);
}
}
- if (oldr.id) {
- ast_set_read_format(chan, &oldr);
+ if (oldr) {
+ ast_set_read_format(chan, oldr);
+ ao2_ref(oldr, -1);
}
return 0;
}
diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c
index 5c5be18af..1794c2565 100644
--- a/apps/app_dumpchan.c
+++ b/apps/app_dumpchan.c
@@ -72,7 +72,7 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
{
long elapsed_seconds = 0;
int hour = 0, min = 0, sec = 0;
- char nf[256];
+ struct ast_str *format_buf = ast_str_alloca(64);
char cgrp[256];
char pgrp[256];
struct ast_str *write_transpath = ast_str_alloca(256);
@@ -143,11 +143,11 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
ast_state2str(ast_channel_state(c)),
ast_channel_state(c),
ast_channel_rings(c),
- ast_getformatname_multiple(nf, sizeof(nf), ast_channel_nativeformats(c)),
- ast_getformatname(ast_channel_writeformat(c)),
- ast_getformatname(ast_channel_readformat(c)),
- ast_getformatname(ast_channel_rawwriteformat(c)),
- ast_getformatname(ast_channel_rawreadformat(c)),
+ ast_format_cap_get_names(ast_channel_nativeformats(c), &format_buf),
+ ast_format_get_name(ast_channel_writeformat(c)),
+ ast_format_get_name(ast_channel_readformat(c)),
+ ast_format_get_name(ast_channel_rawwriteformat(c)),
+ ast_format_get_name(ast_channel_rawreadformat(c)),
ast_channel_writetrans(c) ? "Yes" : "No",
ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath),
ast_channel_readtrans(c) ? "Yes" : "No",
diff --git a/apps/app_echo.c b/apps/app_echo.c
index df5a914f1..d8b207967 100644
--- a/apps/app_echo.c
+++ b/apps/app_echo.c
@@ -58,11 +58,6 @@ static const char app[] = "Echo";
static int echo_exec(struct ast_channel *chan, const char *data)
{
int res = -1;
- struct ast_format format;
-
- ast_best_codec(ast_channel_nativeformats(chan), &format);
- ast_set_write_format(chan, &format);
- ast_set_read_format(chan, &format);
while (ast_waitfor(chan, -1) > -1) {
struct ast_frame *f = ast_read(chan);
diff --git a/apps/app_fax.c b/apps/app_fax.c
index e23ac431e..ceff38fef 100644
--- a/apps/app_fax.c
+++ b/apps/app_fax.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="SendFAX" language="en_US" module="app_fax">
@@ -332,9 +333,9 @@ static int fax_generator_generate(struct ast_channel *chan, void *data, int len,
struct ast_frame outf = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin,
.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);
@@ -365,8 +366,8 @@ static struct ast_generator generator = {
static int transmit_audio(fax_session *s)
{
int res = -1;
- struct ast_format original_read_fmt;
- struct ast_format original_write_fmt;
+ struct ast_format *original_read_fmt;
+ struct ast_format *original_write_fmt = NULL;
fax_state_t fax;
t30_state_t *t30state;
struct ast_frame *inf = NULL;
@@ -386,9 +387,6 @@ static int transmit_audio(fax_session *s)
*/
};
- ast_format_clear(&original_read_fmt);
- ast_format_clear(&original_write_fmt);
-
/* if in called party mode, try to use T.38 */
if (s->caller_mode == FALSE) {
/* check if we are already in T.38 mode (unlikely), or if we can request
@@ -461,22 +459,18 @@ static int transmit_audio(fax_session *s)
t30state = &fax.t30_state;
#endif
- ast_format_copy(&original_read_fmt, ast_channel_readformat(s->chan));
- 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_read_fmt = ao2_bump(ast_channel_readformat(s->chan));
+ res = ast_set_read_format(s->chan, ast_format_slin);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
+ goto done;
}
- ast_format_copy(&original_write_fmt, ast_channel_writeformat(s->chan));
- 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;
- }
+ original_write_fmt = ao2_bump(ast_channel_writeformat(s->chan));
+ res = ast_set_write_format(s->chan, ast_format_slin);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
+ goto done;
}
/* Initialize T30 terminal */
@@ -529,12 +523,13 @@ static int transmit_audio(fax_session *s)
break;
}
- ast_debug(10, "frame %d/%u, len=%d\n", inf->frametype, (unsigned int) inf->subclass.format.id, inf->datalen);
+ ast_debug(10, "frame %d/%s, len=%d\n", inf->frametype, ast_format_get_name(inf->subclass.format), 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.format.id == AST_FORMAT_SLINEAR) {
+ if (inf->frametype == AST_FRAME_VOICE &&
+ (ast_format_cmp(inf->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
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");
@@ -588,14 +583,16 @@ static int transmit_audio(fax_session *s)
fax_release(&fax);
done:
- if (original_write_fmt.id != AST_FORMAT_SLINEAR) {
- if (ast_set_write_format(s->chan, &original_write_fmt) < 0)
+ if (original_write_fmt) {
+ if (ast_set_write_format(s->chan, original_write_fmt) < 0)
ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", ast_channel_name(s->chan));
+ ao2_ref(original_write_fmt, -1);
}
- if (original_read_fmt.id != AST_FORMAT_SLINEAR) {
- if (ast_set_read_format(s->chan, &original_read_fmt) < 0)
+ if (original_read_fmt) {
+ if (ast_set_read_format(s->chan, original_read_fmt) < 0)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(s->chan));
+ ao2_ref(original_read_fmt, -1);
}
return res;
diff --git a/apps/app_festival.c b/apps/app_festival.c
index 3ccacb195..3626563c6 100644
--- a/apps/app_festival.c
+++ b/apps/app_festival.c
@@ -63,6 +63,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define FESTIVAL_CONFIG "festival.conf"
#define MAXLEN 180
@@ -177,7 +178,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
int res = 0;
int fds[2];
int needed = 0;
- struct ast_format owriteformat;
+ struct ast_format *owriteformat;
struct ast_frame *f;
struct myframe {
struct ast_frame f;
@@ -187,7 +188,6 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
.f = { 0, },
};
- ast_format_clear(&owriteformat);
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
@@ -199,12 +199,19 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
ast_stopstream(chan);
ast_indicate(chan, -1);
- ast_format_copy(&owriteformat, ast_channel_writeformat(chan));
- res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ owriteformat = ao2_bump(ast_channel_writeformat(chan));
+ res = ast_set_write_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
+ ao2_cleanup(owriteformat);
return -1;
}
+
+ myf.f.frametype = AST_FRAME_VOICE;
+ myf.f.subclass.format = ast_format_slin;
+ myf.f.offset = AST_FRIENDLY_OFFSET;
+ myf.f.src = __PRETTY_FUNCTION__;
+ myf.f.data.ptr = myf.frdata;
res = send_waveform_to_fd(waveform, length, fds[1]);
if (res >= 0) {
@@ -240,13 +247,8 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
}
res = read(fds[0], myf.frdata, needed);
if (res > 0) {
- myf.f.frametype = AST_FRAME_VOICE;
- 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;
- myf.f.src = __PRETTY_FUNCTION__;
- myf.f.data.ptr = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
ast_frfree(f);
@@ -269,8 +271,10 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
close(fds[0]);
close(fds[1]);
- if (!res && owriteformat.id)
- ast_set_write_format(chan, &owriteformat);
+ if (!res && owriteformat)
+ ast_set_write_format(chan, owriteformat);
+ ao2_cleanup(owriteformat);
+
return res;
}
diff --git a/apps/app_ices.c b/apps/app_ices.c
index bdccff43f..3122273c7 100644
--- a/apps/app_ices.c
+++ b/apps/app_ices.c
@@ -48,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="ICES" language="en_US">
@@ -115,12 +116,11 @@ static int ices_exec(struct ast_channel *chan, const char *data)
int ms = -1;
int pid = -1;
int flags;
- struct ast_format oreadformat;
+ struct ast_format *oreadformat;
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;
@@ -145,12 +145,13 @@ static int ices_exec(struct ast_channel *chan, const char *data)
return -1;
}
- ast_format_copy(&oreadformat, ast_channel_readformat(chan));
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ oreadformat = ao2_bump(ast_channel_readformat(chan));
+ res = ast_set_read_format(chan, ast_format_slin);
if (res < 0) {
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
+ ao2_cleanup(oreadformat);
return -1;
}
if (((char *)data)[0] == '/')
@@ -197,8 +198,9 @@ static int ices_exec(struct ast_channel *chan, const char *data)
if (pid > -1)
kill(pid, SIGKILL);
- if (!res && oreadformat.id)
- ast_set_read_format(chan, &oreadformat);
+ if (!res && oreadformat)
+ ast_set_read_format(chan, oreadformat);
+ ao2_cleanup(oreadformat);
return res;
}
diff --git a/apps/app_jack.c b/apps/app_jack.c
index 9c59ceaf4..8adfbc4cb 100644
--- a/apps/app_jack.c
+++ b/apps/app_jack.c
@@ -58,6 +58,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/audiohook.h"
+#include "asterisk/format_cache.h"
#define RESAMPLE_QUALITY 1
@@ -129,7 +130,7 @@ struct jack_data {
jack_port_t *output_port;
jack_ringbuffer_t *input_rb;
jack_ringbuffer_t *output_rb;
- enum ast_format_id audiohook_format_id;
+ struct ast_format *audiohook_format;
unsigned int audiohook_rate;
unsigned int frame_datalen;
void *output_resampler;
@@ -394,7 +395,6 @@ static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
jack_status_t status = 0;
jack_options_t jack_options = JackNullOption;
- struct ast_format format_slin;
unsigned int channel_rate;
unsigned int ringbuffer_size;
@@ -402,19 +402,17 @@ static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
/* Deducing audiohook sample rate from channel format
ATTENTION: Might be problematic, if channel has different sampling than used by audiohook!
*/
- channel_rate = ast_format_rate(ast_channel_readformat(chan));
- jack_data->audiohook_format_id = ast_format_slin_by_rate(channel_rate);
-
- ast_format_set(&format_slin, jack_data->audiohook_format_id, 0);
- jack_data->audiohook_rate = ast_format_rate(&format_slin);
+ channel_rate = ast_format_get_sample_rate(ast_channel_readformat(chan));
+ jack_data->audiohook_format = ast_format_cache_get_slin_by_rate(channel_rate);
+ jack_data->audiohook_rate = ast_format_get_sample_rate(jack_data->audiohook_format);
/* Guessing frame->datalen assuming a ptime of 20ms */
jack_data->frame_datalen = jack_data->audiohook_rate / 50;
ringbuffer_size = jack_data->frame_datalen * RINGBUFFER_FRAME_CAPACITY;
- ast_debug(1, "Audiohook parameters: slin-format:%d, rate:%d, frame-len:%d, ringbuffer_size: %d\n",
- jack_data->audiohook_format_id, jack_data->audiohook_rate, jack_data->frame_datalen, ringbuffer_size);
+ ast_debug(1, "Audiohook parameters: slin-format:%s, rate:%d, frame-len:%d, ringbuffer_size: %d\n",
+ ast_format_get_name(jack_data->audiohook_format), jack_data->audiohook_rate, jack_data->frame_datalen, ringbuffer_size);
if (!ast_strlen_zero(jack_data->client_name)) {
client_name = jack_data->client_name;
@@ -628,12 +626,12 @@ static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_d
short buf[jack_data->frame_datalen];
struct ast_frame f = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = jack_data->audiohook_format,
.src = "JACK",
.data.ptr = buf,
.datalen = sizeof(buf),
.samples = ARRAY_LEN(buf),
};
- ast_format_set(&f.subclass.format, jack_data->audiohook_format_id, 0);
for (;;) {
size_t res, read_len;
@@ -778,12 +776,12 @@ static int jack_exec(struct ast_channel *chan, const char *data)
return -1;
}
- if (ast_set_read_format_by_id(chan, jack_data->audiohook_format_id)) {
+ if (ast_set_read_format(chan, jack_data->audiohook_format)) {
destroy_jack_data(jack_data);
return -1;
}
- if (ast_set_write_format_by_id(chan, jack_data->audiohook_format_id)) {
+ if (ast_set_write_format(chan, jack_data->audiohook_format)) {
destroy_jack_data(jack_data);
return -1;
}
@@ -859,9 +857,10 @@ static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channe
jack_data = datastore->data;
- if (frame->subclass.format.id != jack_data->audiohook_format_id) {
- ast_log(LOG_WARNING, "Expected frame in SLINEAR with id %d for the audiohook, but got format %s\n",
- jack_data->audiohook_format_id, ast_getformatname(&frame->subclass.format));
+ if (ast_format_cmp(frame->subclass.format, jack_data->audiohook_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_log(LOG_WARNING, "Expected frame in %s for the audiohook, but got format %s\n",
+ ast_format_get_name(jack_data->audiohook_format),
+ ast_format_get_name(frame->subclass.format));
ast_channel_unlock(chan);
return 0;
}
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index 1a780e6ff..6d0b5ac1b 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/json.h"
+#include "asterisk/format_compatibility.h"
#include "enter.h"
#include "leave.h"
@@ -1606,8 +1607,7 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
struct ast_conference *cnf;
struct dahdi_confinfo dahdic = { 0, };
int confno_int = 0;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_fmt;
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
AST_LIST_LOCK(&confs);
@@ -1619,7 +1619,7 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
if (cnf || (!make && !dynamic) || !cap_slin)
goto cnfout;
- ast_format_cap_add(cap_slin, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
/* Make a new one */
if (!(cnf = ast_calloc(1, sizeof(*cnf))) ||
!(cnf->usercontainer = ao2_container_alloc(1, NULL, user_no_cmp))) {
@@ -1667,8 +1667,8 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
/* Setup a new channel for playback of audio files */
cnf->chan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL);
if (cnf->chan) {
- ast_set_read_format_by_id(cnf->chan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(cnf->chan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(cnf->chan, ast_format_slin);
+ ast_set_write_format(cnf->chan, ast_format_slin);
dahdic.chan = 0;
dahdic.confno = cnf->dahdiconf;
dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
@@ -1704,7 +1704,7 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
conf_map[confno_int] = 1;
cnfout:
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
if (cnf)
ast_atomic_fetchadd_int(&cnf->refcount, refcount);
@@ -3089,8 +3089,8 @@ static void meetme_menu_admin_extended(enum menu_modes *menu_mode, int *dtmf,
if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL)))) {
struct dahdi_confinfo dahdic;
- ast_set_read_format_by_id(conf->lchan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(conf->lchan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(conf->lchan, ast_format_slin);
+ ast_set_write_format(conf->lchan, ast_format_slin);
dahdic.chan = 0;
dahdic.confno = conf->dahdiconf;
dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
@@ -3217,13 +3217,12 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
int setusercount = 0;
int confsilence = 0, totalsilence = 0;
char *mailbox, *context;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmpfmt;
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap_slin) {
goto conf_run_cleanup;
}
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
if (!(user = ao2_alloc(sizeof(*user), NULL))) {
goto conf_run_cleanup;
@@ -3345,8 +3344,8 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
ast_mutex_lock(&conf->recordthreadlock);
if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) &&
((conf->lchan = ast_request("DAHDI", cap_slin, NULL, 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);
+ ast_set_read_format(conf->lchan, ast_format_slin);
+ ast_set_write_format(conf->lchan, ast_format_slin);
dahdic.chan = 0;
dahdic.confno = conf->dahdiconf;
dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
@@ -3572,12 +3571,12 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
ast_indicate(chan, -1);
}
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", ast_channel_name(chan));
goto outrun;
}
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ if (ast_set_read_format(chan, ast_format_slin) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", ast_channel_name(chan));
goto outrun;
}
@@ -4131,7 +4130,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
dtmfstr[1] = '\0';
}
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) {
+ if ((f->frametype == AST_FRAME_VOICE) && (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
if (user->talk.actual) {
ast_frame_adjust_volume(f, user->talk.actual);
}
@@ -4289,7 +4288,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
if (res > 0) {
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&fr.subclass.format, AST_FORMAT_SLINEAR, 0);
+ fr.subclass.format = ast_format_slin;
fr.datalen = res;
fr.samples = res / 2;
fr.data.ptr = buf;
@@ -4301,7 +4300,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
)) {
int idx;
for (idx = 0; idx < AST_FRAME_BITS; idx++) {
- if (ast_format_to_old_bitfield(ast_channel_rawwriteformat(chan)) & (1 << idx)) {
+ if (ast_format_compatibility_format2bitfield(ast_channel_rawwriteformat(chan)) & (1 << idx)) {
break;
}
}
@@ -4319,11 +4318,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
mohtempstopped = 1;
}
if (!conf->transpath[idx]) {
- 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);
+ conf->transpath[idx] = ast_translator_build_path(ast_channel_rawwriteformat(chan), ast_format_slin);
}
if (conf->transpath[idx]) {
conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0);
@@ -4485,7 +4480,7 @@ bailoutandtrynormal:
conf_run_cleanup:
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
return ret;
}
diff --git a/apps/app_milliwatt.c b/apps/app_milliwatt.c
index a4adc08c5..a3509581d 100644
--- a/apps/app_milliwatt.c
+++ b/apps/app_milliwatt.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/indications.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Milliwatt" language="en_US">
@@ -79,13 +80,14 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
{
unsigned char buf[AST_FRIENDLY_OFFSET + 640];
const int maxsamples = ARRAY_LEN(buf) - (AST_FRIENDLY_OFFSET / sizeof(buf[0]));
- int i, *indexp = (int *) data;
+ int i, *indexp = (int *) data, res;
struct ast_frame wf = {
.frametype = AST_FRAME_VOICE,
.offset = AST_FRIENDLY_OFFSET,
.src = __FUNCTION__,
};
- ast_format_set(&wf.subclass.format, AST_FORMAT_ULAW, 0);
+
+ wf.subclass.format = ast_format_ulaw;
wf.data.ptr = buf + AST_FRIENDLY_OFFSET;
/* Instead of len, use samples, because channel.c generator_force
@@ -108,7 +110,10 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
*indexp &= 7;
}
- if (ast_write(chan,&wf) < 0) {
+ res = ast_write(chan, &wf);
+ ast_frfree(&wf);
+
+ if (res < 0) {
ast_log(LOG_WARNING,"Failed to write frame to '%s': %s\n",ast_channel_name(chan),strerror(errno));
return -1;
}
@@ -124,8 +129,8 @@ static struct ast_generator milliwattgen = {
static int old_milliwatt_exec(struct ast_channel *chan)
{
- ast_set_write_format_by_id(chan, AST_FORMAT_ULAW);
- ast_set_read_format_by_id(chan, AST_FORMAT_ULAW);
+ ast_set_write_format(chan, ast_format_ulaw);
+ ast_set_read_format(chan, ast_format_ulaw);
if (ast_channel_state(chan) != AST_STATE_UP) {
ast_answer(chan);
diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index ab1d0bad1..1e7833cea 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h"
#include "asterisk/test.h"
#include "asterisk/mixmonitor.h"
+#include "asterisk/format_cache.h"
#include "asterisk/beep.h"
/*** DOCUMENTATION
@@ -616,7 +617,7 @@ static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename,
*errflag = 1;
} else {
struct ast_filestream *tmp = *fs;
- mixmonitor->mixmonitor_ds->samp_rate = MAX(mixmonitor->mixmonitor_ds->samp_rate, ast_format_rate(&tmp->fmt->format));
+ mixmonitor->mixmonitor_ds->samp_rate = MAX(mixmonitor->mixmonitor_ds->samp_rate, ast_format_get_sample_rate(tmp->fmt->format));
}
}
}
@@ -635,7 +636,7 @@ static void *mixmonitor_thread(void *obj)
unsigned int oflags;
int errflag = 0;
- struct ast_format format_slin;
+ struct ast_format *format_slin;
/* Keep callid association before any log messages */
if (mixmonitor->callid) {
@@ -653,11 +654,10 @@ static void *mixmonitor_thread(void *obj)
mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag, &fs_read_ext);
mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag, &fs_write_ext);
- ast_format_set(&format_slin, ast_format_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate), 0);
+ format_slin = ast_format_cache_get_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate);
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
-
/* The audiohook must enter and exit the loop locked */
ast_audiohook_lock(&mixmonitor->audiohook);
while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
@@ -665,7 +665,7 @@ static void *mixmonitor_thread(void *obj)
struct ast_frame *fr_read = NULL;
struct ast_frame *fr_write = NULL;
- if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, &format_slin,
+ if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, format_slin,
&fr_read, &fr_write))) {
ast_audiohook_trigger_wait(&mixmonitor->audiohook);
diff --git a/apps/app_mp3.c b/apps/app_mp3.c
index 463a91906..7e4e8e490 100644
--- a/apps/app_mp3.c
+++ b/apps/app_mp3.c
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
#define MPG_123 "/usr/bin/mpg123"
@@ -143,7 +144,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
int fds[2];
int ms = -1;
int pid = -1;
- struct ast_format owriteformat;
+ RAII_VAR(struct ast_format *, owriteformat, NULL, ao2_cleanup);
int timeout = 2000;
struct timeval next;
struct ast_frame *f;
@@ -155,7 +156,6 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
.f = { 0, },
};
- ast_format_clear(&owriteformat);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
return -1;
@@ -168,12 +168,21 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
ast_stopstream(chan);
- ast_format_copy(&owriteformat, ast_channel_writeformat(chan));
- res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ owriteformat = ao2_bump(ast_channel_writeformat(chan));
+ res = ast_set_write_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
return -1;
}
+
+ myf.f.frametype = AST_FRAME_VOICE;
+ myf.f.subclass.format = ast_format_slin;
+ myf.f.mallocd = 0;
+ myf.f.offset = AST_FRIENDLY_OFFSET;
+ myf.f.src = __PRETTY_FUNCTION__;
+ myf.f.delivery.tv_sec = 0;
+ myf.f.delivery.tv_usec = 0;
+ myf.f.data.ptr = myf.frdata;
res = mp3play(data, fds[1]);
if (!strncasecmp(data, "http://", 7)) {
@@ -191,16 +200,8 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
if (ms <= 0) {
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
if (res > 0) {
- myf.f.frametype = AST_FRAME_VOICE;
- ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0);
myf.f.datalen = res;
myf.f.samples = res / 2;
- myf.f.mallocd = 0;
- myf.f.offset = AST_FRIENDLY_OFFSET;
- myf.f.src = __PRETTY_FUNCTION__;
- myf.f.delivery.tv_sec = 0;
- myf.f.delivery.tv_usec = 0;
- myf.f.data.ptr = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
@@ -241,8 +242,10 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
if (pid > -1)
kill(pid, SIGKILL);
- if (!res && owriteformat.id)
- ast_set_write_format(chan, &owriteformat);
+ if (!res && owriteformat)
+ ast_set_write_format(chan, owriteformat);
+
+ ast_frfree(&myf.f);
return res;
}
diff --git a/apps/app_nbscat.c b/apps/app_nbscat.c
index 8cf02b369..435af8a29 100644
--- a/apps/app_nbscat.c
+++ b/apps/app_nbscat.c
@@ -46,6 +46,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="NBScat" language="en_US">
@@ -115,7 +116,7 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
int fds[2];
int ms = -1;
int pid = -1;
- struct ast_format owriteformat;
+ struct ast_format *owriteformat;
struct timeval next;
struct ast_frame *f;
struct myframe {
@@ -124,7 +125,6 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
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;
@@ -132,12 +132,22 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
ast_stopstream(chan);
- ast_format_copy(&owriteformat, ast_channel_writeformat(chan));
- res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ owriteformat = ao2_bump(ast_channel_writeformat(chan));
+ res = ast_set_write_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
+ ao2_cleanup(owriteformat);
return -1;
}
+
+ myf.f.frametype = AST_FRAME_VOICE;
+ myf.f.subclass.format = ast_format_slin;
+ myf.f.mallocd = 0;
+ myf.f.offset = AST_FRIENDLY_OFFSET;
+ myf.f.src = __PRETTY_FUNCTION__;
+ myf.f.delivery.tv_sec = 0;
+ myf.f.delivery.tv_usec = 0;
+ myf.f.data.ptr = myf.frdata;
res = NBScatplay(fds[1]);
/* Wait 1000 ms first */
@@ -152,16 +162,8 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
if (ms <= 0) {
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
if (res > 0) {
- myf.f.frametype = AST_FRAME_VOICE;
- ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0);
myf.f.datalen = res;
myf.f.samples = res / 2;
- myf.f.mallocd = 0;
- myf.f.offset = AST_FRIENDLY_OFFSET;
- myf.f.src = __PRETTY_FUNCTION__;
- myf.f.delivery.tv_sec = 0;
- myf.f.delivery.tv_usec = 0;
- myf.f.data.ptr = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
@@ -199,11 +201,13 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
}
close(fds[0]);
close(fds[1]);
+ ast_frfree(&myf.f);
if (pid > -1)
kill(pid, SIGKILL);
- if (!res && owriteformat.id)
- ast_set_write_format(chan, &owriteformat);
+ if (!res && owriteformat)
+ ast_set_write_format(chan, owriteformat);
+ ao2_cleanup(owriteformat);
return res;
}
diff --git a/apps/app_originate.c b/apps/app_originate.c
index 9fceb0849..15898b240 100644
--- a/apps/app_originate.c
+++ b/apps/app_originate.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
static const char app_originate[] = "Originate";
@@ -112,22 +113,22 @@ static int originate_exec(struct ast_channel *chan, const char *data)
int outgoing_status = 0;
unsigned int timeout = 30;
static const char default_exten[] = "s";
- struct ast_format tmpfmt;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
ast_autoservice_start(chan);
if (!cap_slin) {
goto return_cleanup;
}
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR12, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR24, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR32, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR44, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR48, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR96, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR192, 0));
+
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin12, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin16, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin24, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin32, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin44, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin48, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin96, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin192, 0);
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "Originate() requires arguments\n");
@@ -222,7 +223,7 @@ return_cleanup:
break;
}
}
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
ast_autoservice_stop(chan);
return res;
diff --git a/apps/app_record.c b/apps/app_record.c
index 45f1d8602..4008fc012 100644
--- a/apps/app_record.c
+++ b/apps/app_record.c
@@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h" /* use dsp routines for silence detection */
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Record" language="en_US">
@@ -196,7 +197,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
int maxduration = 0; /* max duration of recording in milliseconds */
int gottimeout = 0; /* did we timeout for maxduration exceeded? */
int terminator = '#';
- struct ast_format rfmt;
+ RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
int ioflags;
struct ast_silence_generator *silgen = NULL;
struct ast_flags flags = { 0, };
@@ -209,8 +210,6 @@ static int record_exec(struct ast_channel *chan, const char *data)
int ms;
struct timeval start;
- 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");
@@ -331,8 +330,8 @@ static int record_exec(struct ast_channel *chan, const char *data)
/* The end of beep code. Now the recording starts */
if (silence > 0) {
- ast_format_copy(&rfmt, ast_channel_readformat(chan));
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ rfmt = ao2_bump(ast_channel_readformat(chan));
+ res = ast_set_read_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
@@ -459,8 +458,8 @@ static int record_exec(struct ast_channel *chan, const char *data)
ast_channel_stop_silence_generator(chan, silgen);
out:
- if ((silence > 0) && rfmt.id) {
- res = ast_set_read_format(chan, &rfmt);
+ if ((silence > 0) && rfmt) {
+ res = ast_set_read_format(chan, rfmt);
if (res) {
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
}
diff --git a/apps/app_sms.c b/apps/app_sms.c
index b7d247818..266f8abdc 100644
--- a/apps/app_sms.c
+++ b/apps/app_sms.c
@@ -56,6 +56,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="SMS" language="en_US">
@@ -140,11 +141,11 @@ static const signed short wave[] = {
static unsigned char wavea[80];
typedef unsigned char output_t;
static const output_t *wave_out = wavea; /* outgoing samples */
-#define __OUT_FMT AST_FORMAT_ALAW;
+#define __OUT_FMT ast_format_alaw
#else
typedef signed short output_t;
static const output_t *wave_out = wave; /* outgoing samples */
-#define __OUT_FMT AST_FORMAT_SLINEAR
+#define __OUT_FMT ast_format_slin
#endif
#define OSYNC_BITS 80 /* initial sync bits */
@@ -1599,7 +1600,7 @@ static int sms_generate(struct ast_channel *chan, void *data, int len, int sampl
#define MAXSAMPLES (800)
output_t *buf;
sms_t *h = data;
- int i;
+ int i, res;
if (samples > MAXSAMPLES) {
ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
@@ -1610,7 +1611,7 @@ static int sms_generate(struct ast_channel *chan, void *data, int len, int sampl
buf = ast_alloca(len);
f.frametype = AST_FRAME_VOICE;
- ast_format_set(&f.subclass.format, __OUT_FMT, 0);
+ f.subclass.format = __OUT_FMT;
f.datalen = samples * sizeof(*buf);
f.offset = AST_FRIENDLY_OFFSET;
f.mallocd = 0;
@@ -1660,7 +1661,9 @@ static int sms_generate(struct ast_channel *chan, void *data, int len, int sampl
}
}
}
- if (ast_write(chan, &f) < 0) {
+ res = ast_write(chan, &f);
+ ast_frfree(&f);
+ if (res < 0) {
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
return -1;
}
@@ -2012,9 +2015,9 @@ static int sms_exec(struct ast_channel *chan, const char *data)
sms_messagetx(&h);
}
- res = ast_set_write_format_by_id(chan, __OUT_FMT);
+ res = ast_set_write_format(chan, __OUT_FMT);
if (res >= 0) {
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ res = ast_set_read_format(chan, ast_format_slin);
}
if (res < 0) {
ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c
index e9ca63ea9..e52425d6a 100644
--- a/apps/app_speech_utils.c
+++ b/apps/app_speech_utils.c
@@ -672,7 +672,7 @@ static int speech_background(struct ast_channel *chan, const char *data)
int res = 0, done = 0, started = 0, quieted = 0, max_dtmf_len = 0;
struct ast_speech *speech = find_speech(chan);
struct ast_frame *f = NULL;
- struct ast_format oldreadformat;
+ RAII_VAR(struct ast_format *, oldreadformat, NULL, ao2_cleanup);
char dtmf[AST_MAX_EXTENSION] = "";
struct timeval start = { 0, 0 }, current;
struct ast_datastore *datastore = NULL;
@@ -688,7 +688,6 @@ static int speech_background(struct ast_channel *chan, const char *data)
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_format_clear(&oldreadformat);
if (speech == NULL)
return -1;
@@ -704,10 +703,10 @@ static int speech_background(struct ast_channel *chan, const char *data)
}
/* Record old read format */
- ast_format_copy(&oldreadformat, ast_channel_readformat(chan));
+ oldreadformat = ao2_bump(ast_channel_readformat(chan));
/* 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)) {
@@ -912,7 +911,7 @@ static int speech_background(struct ast_channel *chan, const char *data)
ast_channel_datastore_remove(chan, datastore);
} else {
/* Channel is okay so restore read format */
- ast_set_read_format(chan, &oldreadformat);
+ ast_set_read_format(chan, oldreadformat);
}
return 0;
diff --git a/apps/app_talkdetect.c b/apps/app_talkdetect.c
index 5ef80c33c..5ccf2607e 100644
--- a/apps/app_talkdetect.c
+++ b/apps/app_talkdetect.c
@@ -42,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="BackgroundDetect" language="en_US">
@@ -91,7 +93,7 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
int analysistime = -1;
int continue_analysis = 1;
int x;
- struct ast_format origrformat;
+ RAII_VAR(struct ast_format *, origrformat, NULL, ao2_cleanup);
struct ast_dsp *dsp = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
@@ -101,7 +103,6 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
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;
@@ -131,8 +132,8 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
}
}
- ast_format_copy(&origrformat, ast_channel_readformat(chan));
- if ((ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR))) {
+ origrformat = ao2_bump(ast_channel_readformat(chan));
+ if ((ast_set_read_format(chan, ast_format_slin))) {
ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
res = -1;
break;
@@ -187,7 +188,8 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
ast_frfree(fr);
break;
}
- } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass.format.id == AST_FORMAT_SLINEAR) && continue_analysis) {
+ } else if ((fr->frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) && continue_analysis) {
int totalsilence;
int ms;
res = ast_dsp_silence(dsp, fr, &totalsilence);
@@ -233,9 +235,9 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
} while (0);
if (res > -1) {
- if (origrformat.id && ast_set_read_format(chan, &origrformat)) {
+ if (origrformat && ast_set_read_format(chan, origrformat)) {
ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
- ast_channel_name(chan), ast_getformatname(&origrformat));
+ ast_channel_name(chan), ast_format_get_name(origrformat));
}
}
if (dsp) {
diff --git a/apps/app_test.c b/apps/app_test.c
index 5b7b979e6..54139ba80 100644
--- a/apps/app_test.c
+++ b/apps/app_test.c
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="TestServer" language="en_US">
@@ -91,11 +92,12 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who)
short *foo;
struct timeval start;
struct ast_frame *f;
- struct ast_format rformat;
+ struct ast_format *rformat;
- ast_format_copy(&rformat, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ rformat = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin)) {
ast_log(LOG_NOTICE, "Unable to set to linear mode!\n");
+ ao2_cleanup(rformat);
return -1;
}
start = ast_tvnow();
@@ -111,7 +113,8 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who)
res = -1;
break;
}
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) {
+ if ((f->frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
foo = (short *)f->data.ptr;
for (x=0;x<f->samples;x++) {
noise += abs(foo[x]);
@@ -121,11 +124,13 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who)
ast_frfree(f);
}
- if (rformat.id) {
- if (ast_set_read_format(chan, &rformat)) {
+ if (rformat) {
+ if (ast_set_read_format(chan, rformat)) {
ast_log(LOG_NOTICE, "Unable to restore original format!\n");
+ ao2_ref(rformat, -1);
return -1;
}
+ ao2_ref(rformat, -1);
}
if (res < 0)
return res;
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 9c8a4b8ad..8a9c0f3ca 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -135,6 +135,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.h"
+#include "asterisk/format_cache.h"
#ifdef ODBC_STORAGE
#include "asterisk/res_odbc.h"
@@ -6112,13 +6113,16 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata)
if ((recording_fs = ast_readfile(recdata->recording_file, recdata->recording_ext, NULL, 0, 0, VOICEMAIL_DIR_MODE))) {
if (!ast_seekstream(recording_fs, 0, SEEK_END)) {
long framelength = ast_tellstream(recording_fs);
- struct ast_format result = {0,};
+ struct ast_format *result;
/* XXX This use of ast_getformatbyname seems incorrect here. The file extension does not necessarily correspond
* to the name of the format. For instance, if "raw" were passed in, I don't think ast_getformatbyname would
* find the slinear format
*/
- ast_getformatbyname(recdata->recording_ext, &result);
- duration = (int) (framelength / ast_format_rate(&result));
+ result = ast_format_cache_get(recdata->recording_ext);
+ if (result) {
+ duration = (int) (framelength / ast_format_get_sample_rate(result));
+ ao2_ref(result, -1);
+ }
}
}
@@ -14026,7 +14030,7 @@ AST_TEST_DEFINE(test_voicemail_vmsayname)
struct ast_channel *test_channel1 = NULL;
int res = -1;
- struct ast_format_cap *nativeformats;
+ struct ast_format_cap *capabilities;
static const struct ast_channel_tech fake_tech = {
.write = fake_write,
@@ -14051,12 +14055,17 @@ AST_TEST_DEFINE(test_voicemail_vmsayname)
}
/* normally this is done in the channel driver */
- ast_format_set(ast_channel_writeformat(test_channel1), AST_FORMAT_GSM, 0);
- nativeformats = ast_channel_nativeformats(test_channel1);
- ast_format_cap_add(nativeformats, ast_channel_writeformat(test_channel1));
- ast_format_set(ast_channel_rawwriteformat(test_channel1), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_readformat(test_channel1), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_rawreadformat(test_channel1), AST_FORMAT_GSM, 0);
+ capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!capabilities) {
+ goto exit_vmsayname_test;
+ }
+ ast_format_cap_append(capabilities, ast_format_gsm, 0);
+ ast_channel_nativeformats_set(test_channel1, capabilities);
+ ao2_ref(capabilities, -1);
+ ast_channel_set_writeformat(test_channel1, ast_format_gsm);
+ ast_channel_set_rawwriteformat(test_channel1, ast_format_gsm);
+ ast_channel_set_readformat(test_channel1, ast_format_gsm);
+ ast_channel_set_rawreadformat(test_channel1, ast_format_gsm);
ast_channel_tech_set(test_channel1, &fake_tech);
ast_channel_unlock(test_channel1);
diff --git a/apps/app_waitforsilence.c b/apps/app_waitforsilence.c
index 53870df30..f2111d720 100644
--- a/apps/app_waitforsilence.c
+++ b/apps/app_waitforsilence.c
@@ -51,6 +51,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/dsp.h"
#include "asterisk/module.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="WaitForSilence" language="en_US">
@@ -129,7 +130,7 @@ static char *app_noise = "WaitForNoise";
static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) {
struct ast_frame *f = NULL;
int dsptime = 0;
- struct ast_format rfmt;
+ RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
int res = 0;
struct ast_dsp *sildet; /* silence detector dsp */
time_t now;
@@ -138,8 +139,8 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart,
int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) =
wait_for_silence ? ast_dsp_silence : ast_dsp_noise;
- ast_format_copy(&rfmt, ast_channel_readformat(chan)); /* Set to linear mode */
- if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) {
+ rfmt = ao2_bump(ast_channel_readformat(chan));
+ if ((res = ast_set_read_format(chan, ast_format_slin)) < 0) {
ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
return -1;
}
@@ -199,8 +200,8 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart,
}
- 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), ast_channel_name(chan));
+ if (rfmt && ast_set_read_format(chan, rfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
}
ast_dsp_free(sildet);
return res;
diff --git a/apps/confbridge/conf_chan_record.c b/apps/confbridge/conf_chan_record.c
index 34de5af3b..0e298e78d 100644
--- a/apps/confbridge/conf_chan_record.c
+++ b/apps/confbridge/conf_chan_record.c
@@ -33,6 +33,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
+#include "asterisk/format_cache.h"
#include "include/confbridge.h"
/* ------------------------------------------------------------------- */
@@ -56,8 +57,14 @@ static int rec_write(struct ast_channel *ast, struct ast_frame *f)
static struct ast_channel *rec_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
struct ast_channel *chan;
- struct ast_format format;
const char *conf_name = data;
+ RAII_VAR(struct ast_format_cap *, capabilities, NULL, ao2_cleanup);
+
+ capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!capabilities) {
+ return NULL;
+ }
+ ast_format_cap_append_by_type(capabilities, AST_MEDIA_TYPE_UNKNOWN);
chan = ast_channel_alloc(1, AST_STATE_UP, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0,
"CBRec/conf-%s-uid-%d",
@@ -70,13 +77,13 @@ static struct ast_channel *rec_request(const char *type, struct ast_format_cap *
ast_channel_release(chan);
return NULL;
}
- ast_format_set(&format, AST_FORMAT_SLINEAR, 0);
+
ast_channel_tech_set(chan, conf_record_get_tech());
- ast_format_cap_add_all(ast_channel_nativeformats(chan));
- ast_format_copy(ast_channel_writeformat(chan), &format);
- ast_format_copy(ast_channel_rawwriteformat(chan), &format);
- ast_format_copy(ast_channel_readformat(chan), &format);
- ast_format_copy(ast_channel_rawreadformat(chan), &format);
+ ast_channel_nativeformats_set(chan, capabilities);
+ ast_channel_set_writeformat(chan, ast_format_slin);
+ ast_channel_set_rawwriteformat(chan, ast_format_slin);
+ ast_channel_set_readformat(chan, ast_format_slin);
+ ast_channel_set_rawreadformat(chan, ast_format_slin);
ast_channel_unlock(chan);
return chan;
}
diff --git a/bridges/bridge_holding.c b/bridges/bridge_holding.c
index 5eeb4708d..c343cc624 100644
--- a/bridges/bridge_holding.c
+++ b/bridges/bridge_holding.c
@@ -48,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge_technology.h"
#include "asterisk/frame.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
enum holding_roles {
HOLDING_ROLE_PARTICIPANT,
@@ -180,7 +181,7 @@ static void participant_reaction_announcer_join(struct ast_bridge_channel *bridg
chan = bridge_channel->chan;
participant_entertainment_stop(bridge_channel);
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Could not make participant %s compatible.\n", ast_channel_name(chan));
}
}
@@ -233,7 +234,7 @@ static void handle_participant_join(struct ast_bridge_channel *bridge_channel, s
}
/* We need to get compatible with the announcer. */
- if (ast_set_write_format_by_id(us, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(us, ast_format_slin)) {
ast_log(LOG_WARNING, "Could not make participant %s compatible.\n", ast_channel_name(us));
}
}
@@ -270,7 +271,7 @@ static int holding_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan
hc->role = HOLDING_ROLE_ANNOUNCER;
/* The announcer should always be made compatible with signed linear */
- if (ast_set_read_format_by_id(us, AST_FORMAT_SLINEAR)) {
+ if (ast_set_read_format(us, ast_format_slin)) {
ast_log(LOG_ERROR, "Could not make announcer %s compatible.\n", ast_channel_name(us));
}
@@ -427,18 +428,19 @@ static void deferred_action(struct ast_bridge_channel *bridge_channel, const voi
static int unload_module(void)
{
- ast_format_cap_destroy(holding_bridge.format_capabilities);
+ ao2_cleanup(holding_bridge.format_capabilities);
+ holding_bridge.format_capabilities = NULL;
return ast_bridge_technology_unregister(&holding_bridge);
}
static int load_module(void)
{
- if (!(holding_bridge.format_capabilities = ast_format_cap_alloc(0))) {
+ if (!(holding_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(holding_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add_all_by_type(holding_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO);
- ast_format_cap_add_all_by_type(holding_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT);
+ ast_format_cap_append_by_type(holding_bridge.format_capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_by_type(holding_bridge.format_capabilities, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_by_type(holding_bridge.format_capabilities, AST_MEDIA_TYPE_TEXT);
return ast_bridge_technology_register(&holding_bridge);
}
diff --git a/bridges/bridge_native_rtp.c b/bridges/bridge_native_rtp.c
index 2362ad296..4655efeae 100644
--- a/bridges/bridge_native_rtp.c
+++ b/bridges/bridge_native_rtp.c
@@ -137,8 +137,8 @@ static void native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channe
RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, tinstance0, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, tinstance1, NULL, ao2_cleanup);
- RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
+ RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
if (c0 == c1) {
return;
@@ -316,8 +316,8 @@ static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
- RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
+ RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
int read_ptime0, read_ptime1, write_ptime0, write_ptime1;
/* We require two channels before even considering native bridging */
@@ -374,19 +374,18 @@ static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
if (glue1->get_codec) {
glue1->get_codec(c1->chan, 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, }, tmp1[256] = { 0, };
-
+ if (ast_format_cap_count(cap0) != 0 && ast_format_cap_count(cap1) != 0 && !ast_format_cap_iscompatible(cap0, cap1)) {
+ struct ast_str *codec_buf0 = ast_str_alloca(64);
+ struct ast_str *codec_buf1 = ast_str_alloca(64);
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));
+ ast_format_cap_get_names(cap0, &codec_buf0), ast_format_cap_get_names(cap1, &codec_buf1));
return 0;
}
- read_ptime0 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance0)->pref, ast_channel_rawreadformat(c0->chan))).cur_ms;
- read_ptime1 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance1)->pref, ast_channel_rawreadformat(c1->chan))).cur_ms;
- write_ptime0 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance0)->pref, ast_channel_rawwriteformat(c0->chan))).cur_ms;
- write_ptime1 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance1)->pref, ast_channel_rawwriteformat(c1->chan))).cur_ms;
+ read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(c0->chan));
+ read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(c1->chan));
+ write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(c0->chan));
+ write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(c1->chan));
if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
ast_debug(1, "Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
@@ -518,7 +517,7 @@ static struct ast_bridge_technology native_rtp_bridge = {
static int unload_module(void)
{
- ast_format_cap_destroy(native_rtp_bridge.format_capabilities);
+ ao2_t_ref(native_rtp_bridge.format_capabilities, -1, "Dispose of capabilities in module unload");
return ast_bridge_technology_unregister(&native_rtp_bridge);
}
@@ -527,9 +526,9 @@ static int load_module(void)
if (!(native_rtp_bridge.format_capabilities = ast_format_cap_alloc(0))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO);
- ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT);
+ ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_TEXT);
return ast_bridge_technology_register(&native_rtp_bridge);
}
diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c
index 4a03dbe10..1626a3993 100644
--- a/bridges/bridge_simple.c
+++ b/bridges/bridge_simple.c
@@ -76,18 +76,19 @@ static struct ast_bridge_technology simple_bridge = {
static int unload_module(void)
{
- ast_format_cap_destroy(simple_bridge.format_capabilities);
+ ao2_cleanup(simple_bridge.format_capabilities);
+ simple_bridge.format_capabilities = NULL;
return ast_bridge_technology_unregister(&simple_bridge);
}
static int load_module(void)
{
- if (!(simple_bridge.format_capabilities = ast_format_cap_alloc(0))) {
+ if (!(simple_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
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);
+ ast_format_cap_append_by_type(simple_bridge.format_capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_by_type(simple_bridge.format_capabilities, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_by_type(simple_bridge.format_capabilities, AST_MEDIA_TYPE_TEXT);
return ast_bridge_technology_register(&simple_bridge);
}
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index 3f743550c..f5f4c2b16 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -163,14 +163,14 @@ struct softmix_mixing_array {
struct softmix_translate_helper_entry {
int num_times_requested; /*!< Once this entry is no longer requested, free the trans_pvt
and re-init if it was usable. */
- struct ast_format dst_format; /*!< The destination format for this helper */
+ struct ast_format *dst_format; /*!< The destination format for this helper */
struct ast_trans_pvt *trans_pvt; /*!< the translator for this slot. */
struct ast_frame *out_frame; /*!< The output frame from the last translation */
AST_LIST_ENTRY(softmix_translate_helper_entry) entry;
};
struct softmix_translate_helper {
- struct ast_format slin_src; /*!< the source format expected for all the translators */
+ struct ast_format *slin_src; /*!< the source format expected for all the translators */
AST_LIST_HEAD_NOLOCK(, softmix_translate_helper_entry) entries;
};
@@ -180,12 +180,14 @@ static struct softmix_translate_helper_entry *softmix_translate_helper_entry_all
if (!(entry = ast_calloc(1, sizeof(*entry)))) {
return NULL;
}
- ast_format_copy(&entry->dst_format, dst);
+ entry->dst_format = ao2_bump(dst);
return entry;
}
static void *softmix_translate_helper_free_entry(struct softmix_translate_helper_entry *entry)
{
+ ao2_cleanup(entry->dst_format);
+
if (entry->trans_pvt) {
ast_translator_free_path(entry->trans_pvt);
}
@@ -199,7 +201,7 @@ static void *softmix_translate_helper_free_entry(struct softmix_translate_helper
static void softmix_translate_helper_init(struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
{
memset(trans_helper, 0, sizeof(*trans_helper));
- ast_format_set(&trans_helper->slin_src, ast_format_slin_by_rate(sample_rate), 0);
+ trans_helper->slin_src = ast_format_cache_get_slin_by_rate(sample_rate);
}
static void softmix_translate_helper_destroy(struct softmix_translate_helper *trans_helper)
@@ -215,11 +217,11 @@ static void softmix_translate_helper_change_rate(struct softmix_translate_helper
{
struct softmix_translate_helper_entry *entry;
- ast_format_set(&trans_helper->slin_src, ast_format_slin_by_rate(sample_rate), 0);
+ trans_helper->slin_src = ast_format_cache_get_slin_by_rate(sample_rate);
AST_LIST_TRAVERSE_SAFE_BEGIN(&trans_helper->entries, entry, entry) {
if (entry->trans_pvt) {
ast_translator_free_path(entry->trans_pvt);
- if (!(entry->trans_pvt = ast_translator_build_path(&entry->dst_format, &trans_helper->slin_src))) {
+ if (!(entry->trans_pvt = ast_translator_build_path(entry->dst_format, trans_helper->slin_src))) {
AST_LIST_REMOVE_CURRENT(entry);
entry = softmix_translate_helper_free_entry(entry);
}
@@ -274,19 +276,19 @@ static void softmix_process_write_audio(struct softmix_translate_helper *trans_h
}
AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
- if (ast_format_cmp(&entry->dst_format, raw_write_fmt) == AST_FORMAT_CMP_EQUAL) {
+ if (ast_format_cmp(entry->dst_format, raw_write_fmt) == AST_FORMAT_CMP_EQUAL) {
entry->num_times_requested++;
} else {
continue;
}
if (!entry->trans_pvt && (entry->num_times_requested > 1)) {
- entry->trans_pvt = ast_translator_build_path(&entry->dst_format, &trans_helper->slin_src);
+ entry->trans_pvt = ast_translator_build_path(entry->dst_format, trans_helper->slin_src);
}
if (entry->trans_pvt && !entry->out_frame) {
entry->out_frame = ast_translate(entry->trans_pvt, &sc->write_frame, 0);
}
if (entry->out_frame && (entry->out_frame->datalen < MAX_DATALEN)) {
- ast_format_copy(&sc->write_frame.subclass.format, &entry->out_frame->subclass.format);
+ ao2_replace(sc->write_frame.subclass.format, entry->out_frame->subclass.format);
memcpy(sc->final_buf, entry->out_frame->data.ptr, entry->out_frame->datalen);
sc->write_frame.datalen = entry->out_frame->datalen;
sc->write_frame.samples = entry->out_frame->samples;
@@ -316,32 +318,45 @@ static void softmix_translate_helper_cleanup(struct softmix_translate_helper *tr
static void set_softmix_bridge_data(int rate, int interval, struct ast_bridge_channel *bridge_channel, int reset)
{
struct softmix_channel *sc = bridge_channel->tech_pvt;
- unsigned int channel_read_rate = ast_format_rate(ast_channel_rawreadformat(bridge_channel->chan));
+ unsigned int channel_read_rate = ast_format_get_sample_rate(ast_channel_rawreadformat(bridge_channel->chan));
ast_mutex_lock(&sc->lock);
if (reset) {
ast_slinfactory_destroy(&sc->factory);
ast_dsp_free(sc->dsp);
}
- /* Setup read/write frame parameters */
+
+ /* Setup write frame parameters */
sc->write_frame.frametype = AST_FRAME_VOICE;
- ast_format_set(&sc->write_frame.subclass.format, ast_format_slin_by_rate(rate), 0);
+ ao2_cleanup(sc->write_frame.subclass.format);
+ /*
+ * NOTE: The format is bumped here because translation could
+ * be needed and the format changed to the translated format
+ * for the channel. The translated format may not be a
+ * static cached format.
+ */
+ sc->write_frame.subclass.format = ao2_bump(ast_format_cache_get_slin_by_rate(rate));
sc->write_frame.data.ptr = sc->final_buf;
sc->write_frame.datalen = SOFTMIX_DATALEN(rate, interval);
sc->write_frame.samples = SOFTMIX_SAMPLES(rate, interval);
+ /* Setup read frame parameters */
sc->read_frame.frametype = AST_FRAME_VOICE;
- ast_format_set(&sc->read_frame.subclass.format, ast_format_slin_by_rate(channel_read_rate), 0);
+ /*
+ * NOTE: The format is not bumbed here because it will always
+ * be a signed linear format.
+ */
+ sc->read_frame.subclass.format = ast_format_cache_get_slin_by_rate(channel_read_rate);
sc->read_frame.data.ptr = sc->our_buf;
sc->read_frame.datalen = SOFTMIX_DATALEN(channel_read_rate, interval);
sc->read_frame.samples = SOFTMIX_SAMPLES(channel_read_rate, interval);
/* Setup smoother */
- ast_slinfactory_init_with_format(&sc->factory, &sc->write_frame.subclass.format);
+ ast_slinfactory_init_with_format(&sc->factory, sc->write_frame.subclass.format);
/* set new read and write formats on channel. */
- ast_set_read_format(bridge_channel->chan, &sc->read_frame.subclass.format);
- ast_set_write_format(bridge_channel->chan, &sc->write_frame.subclass.format);
+ ast_set_read_format(bridge_channel->chan, sc->read_frame.subclass.format);
+ ast_set_write_format(bridge_channel->chan, sc->write_frame.subclass.format);
/* set up new DSP. This is on the read side only right before the read frame enters the smoother. */
sc->dsp = ast_dsp_new_with_rate(channel_read_rate);
@@ -446,6 +461,9 @@ static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch
/* Drop the factory */
ast_slinfactory_destroy(&sc->factory);
+ /* Drop any formats on the frames */
+ ao2_cleanup(sc->write_frame.subclass.format);
+
/* Drop the DSP */
ast_dsp_free(sc->dsp);
@@ -500,7 +518,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri
ast_mutex_lock(&sc->lock);
ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan,
sc->video_talker.energy_average,
- ast_format_get_video_mark(&frame->subclass.format));
+ frame->subclass.frame_ending);
ast_mutex_unlock(&sc->lock);
video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
if (video_src_priority == 1) {
@@ -575,8 +593,7 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
/* If a frame was provided add it to the smoother, unless drop silence is enabled and this frame
* is not determined to be talking. */
- if (!(bridge_channel->tech_args.drop_silence && !sc->talking) &&
- (frame->frametype == AST_FRAME_VOICE && ast_format_is_slinear(&frame->subclass.format))) {
+ if (!(bridge_channel->tech_args.drop_silence && !sc->talking)) {
ast_slinfactory_feed(&sc->factory, frame);
}
@@ -680,8 +697,8 @@ static void gather_softmix_stats(struct softmix_stats *stats,
int channel_native_rate;
int i;
/* Gather stats about channel sample rates. */
- channel_native_rate = MAX(ast_format_rate(ast_channel_rawwriteformat(bridge_channel->chan)),
- ast_format_rate(ast_channel_rawreadformat(bridge_channel->chan)));
+ channel_native_rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(bridge_channel->chan)),
+ ast_format_get_sample_rate(ast_channel_rawreadformat(bridge_channel->chan)));
if (channel_native_rate > stats->highest_supported_rate) {
stats->highest_supported_rate = channel_native_rate;
@@ -845,7 +862,7 @@ static int softmix_mixing_loop(struct ast_bridge *bridge)
while (!softmix_data->stop && bridge->num_active) {
struct ast_bridge_channel *bridge_channel;
int timeout = -1;
- enum ast_format_id cur_slin_id = ast_format_slin_by_rate(softmix_data->internal_rate);
+ struct ast_format *cur_slin = ast_format_cache_get_slin_by_rate(softmix_data->internal_rate);
unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
unsigned int softmix_datalen = SOFTMIX_DATALEN(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
@@ -927,9 +944,8 @@ static int softmix_mixing_loop(struct ast_bridge *bridge)
ast_mutex_lock(&sc->lock);
/* Make SLINEAR write frame from local buffer */
- if (sc->write_frame.subclass.format.id != cur_slin_id) {
- ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
- }
+ ao2_t_replace(sc->write_frame.subclass.format, cur_slin,
+ "Replace softmix channel slin format");
sc->write_frame.datalen = softmix_datalen;
sc->write_frame.samples = softmix_samples;
memcpy(sc->final_buf, buf, softmix_datalen);
@@ -1144,17 +1160,17 @@ static struct ast_bridge_technology softmix_bridge = {
static int unload_module(void)
{
- ast_format_cap_destroy(softmix_bridge.format_capabilities);
+ ao2_cleanup(softmix_bridge.format_capabilities);
+ softmix_bridge.format_capabilities = NULL;
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(0))) {
+ if (!(softmix_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(softmix_bridge.format_capabilities, ast_format_set(&tmp, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(softmix_bridge.format_capabilities, ast_format_slin, 0);
return ast_bridge_technology_register(&softmix_bridge);
}
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index 9d43ba139..f74e78fd6 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -63,6 +63,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/musiconhold.h"
#include "asterisk/poll-compat.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*! Global jitterbuffer configuration - by default, jb is disabled
* \note Values shown here match the defaults shown in alsa.conf.sample */
@@ -511,7 +512,7 @@ static struct ast_frame *alsa_read(struct ast_channel *chan)
}
f.frametype = AST_FRAME_VOICE;
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ f.subclass.format = ast_format_slin;
f.samples = FRAME_SIZE;
f.datalen = FRAME_SIZE * 2;
f.data.ptr = buf;
@@ -585,9 +586,9 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const st
ast_channel_tech_set(tmp, &alsa_tech);
ast_channel_set_fd(tmp, 0, readdev);
- ast_format_set(ast_channel_readformat(tmp), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_writeformat(tmp), AST_FORMAT_SLINEAR, 0);
- ast_format_cap_add(ast_channel_nativeformats(tmp), ast_channel_writeformat(tmp));
+ ast_channel_set_readformat(tmp, ast_format_slin);
+ ast_channel_set_writeformat(tmp, ast_format_slin);
+ ast_channel_nativeformats_set(tmp, alsa_tech.capabilities);
ast_channel_tech_pvt_set(tmp, p);
if (!ast_strlen_zero(p->context))
@@ -616,14 +617,11 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const st
static struct ast_channel *alsa_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
- struct ast_format tmpfmt;
- char buf[256];
struct ast_channel *tmp = NULL;
- ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0);
-
- if (!(ast_format_cap_iscompatible(cap, &tmpfmt))) {
- ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
@@ -959,12 +957,11 @@ static int load_module(void)
struct ast_config *cfg;
struct ast_variable *v;
struct ast_flags config_flags = { 0 };
- struct ast_format tmpfmt;
- if (!(alsa_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(alsa_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(alsa_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(alsa_tech.capabilities, ast_format_slin, 0);
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
@@ -1042,7 +1039,9 @@ static int unload_module(void)
if (alsa.owner)
return -1;
- alsa_tech.capabilities = ast_format_cap_destroy(alsa_tech.capabilities);
+ ao2_cleanup(alsa_tech.capabilities);
+ alsa_tech.capabilities = NULL;
+
return 0;
}
diff --git a/channels/chan_bridge_media.c b/channels/chan_bridge_media.c
index ac15e7d70..6502b5c77 100644
--- a/channels/chan_bridge_media.c
+++ b/channels/chan_bridge_media.c
@@ -164,11 +164,13 @@ static struct ast_channel *record_request(const char *type, struct ast_format_ca
static void cleanup_capabilities(void)
{
if (announce_tech.capabilities) {
- announce_tech.capabilities = ast_format_cap_destroy(announce_tech.capabilities);
+ ao2_ref(announce_tech.capabilities, -1);
+ announce_tech.capabilities = NULL;
}
if (record_tech.capabilities) {
- record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities);
+ ao2_ref(record_tech.capabilities, -1);
+ record_tech.capabilities = NULL;
}
}
@@ -182,18 +184,18 @@ static int unload_module(void)
static int load_module(void)
{
- announce_tech.capabilities = ast_format_cap_alloc(0);
+ announce_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!announce_tech.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- record_tech.capabilities = ast_format_cap_alloc(0);
+ record_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!record_tech.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all(announce_tech.capabilities);
- ast_format_cap_add_all(record_tech.capabilities);
+ ast_format_cap_append_by_type(announce_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_by_type(record_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (ast_channel_register(&announce_tech)) {
ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
diff --git a/channels/chan_console.c b/channels/chan_console.c
index b1f5cdf7c..3aeda931a 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*!
* \brief The sample rate to request from PortAudio
@@ -270,12 +271,12 @@ static void *stream_monitor(void *data)
PaError res;
struct ast_frame f = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin16,
.src = "console_stream_monitor",
.data.ptr = buf,
.datalen = sizeof(buf),
.samples = sizeof(buf) / sizeof(int16_t),
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0);
for (;;) {
pthread_testcancel();
@@ -421,19 +422,28 @@ static int stop_stream(struct console_pvt *pvt)
*/
static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps;
struct ast_channel *chan;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL,
ext, ctx, assignedids, requestor, 0, "Console/%s", pvt->name))) {
+ ao2_ref(caps, -1);
return NULL;
}
ast_channel_stage_snapshot(chan);
ast_channel_tech_set(chan, &console_tech);
- ast_format_set(ast_channel_readformat(chan), AST_FORMAT_SLINEAR16, 0);
- ast_format_set(ast_channel_writeformat(chan), AST_FORMAT_SLINEAR16, 0);
- ast_format_cap_add(ast_channel_nativeformats(chan), ast_channel_readformat(chan));
+ ast_channel_set_readformat(chan, ast_format_slin16);
+ ast_channel_set_writeformat(chan, ast_format_slin16);
+ ast_format_cap_append(caps, ast_format_slin16, 0);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
ast_channel_tech_pvt_set(chan, ref_pvt(pvt));
pvt->owner = chan;
@@ -462,15 +472,16 @@ static struct ast_channel *console_request(const char *type, struct ast_format_c
{
struct ast_channel *chan = NULL;
struct console_pvt *pvt;
- char buf[512];
if (!(pvt = find_pvt(data))) {
ast_log(LOG_ERROR, "Console device '%s' not found\n", data);
return NULL;
}
- if (!(ast_format_cap_has_joint(cap, console_tech.capabilities))) {
- ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (!(ast_format_cap_iscompatible(cap, console_tech.capabilities))) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n",
+ ast_format_cap_get_names(cap, &cap_buf));
goto return_unref;
}
@@ -1467,7 +1478,8 @@ static void stop_streams(void)
static int unload_module(void)
{
- console_tech.capabilities = ast_format_cap_destroy(console_tech.capabilities);
+ ao2_ref(console_tech.capabilities, -1);
+ console_tech.capabilities = NULL;
ast_channel_unregister(&console_tech);
ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
@@ -1495,13 +1507,12 @@ static int unload_module(void)
*/
static int load_module(void)
{
- struct ast_format tmpfmt;
PaError res;
- if (!(console_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(console_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(console_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0));
+ ast_format_cap_append(console_tech.capabilities, ast_format_slin16, 0);
init_pvt(&globals, NULL);
@@ -1538,6 +1549,8 @@ return_error:
if (pvts)
ao2_ref(pvts, -1);
pvts = NULL;
+ ao2_ref(console_tech.capabilities, -1);
+ console_tech.capabilities = NULL;
pvt_destructor(&globals);
return AST_MODULE_LOAD_DECLINE;
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 81242533e..c22833da5 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -129,6 +129,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/parking.h"
+#include "asterisk/format_cache.h"
#include "chan_dahdi.h"
#include "dahdi/bridge_native_dahdi.h"
@@ -461,7 +462,7 @@ static struct ast_jb_conf global_jbconf;
/*! \brief Typically, how many rings before we should send Caller*ID */
#define DEFAULT_CIDRINGS 1
-#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
+#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
/*! \brief Signaling types that need to use MF detection should be placed in this macro */
@@ -1321,7 +1322,6 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e
int res;
unsigned char buf[256];
int flags;
- struct ast_format tmpfmt;
poller.fd = p->subs[SUB_REAL].dfd;
poller.events = POLLPRI | POLLIN;
@@ -1354,9 +1354,9 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e
}
if (p->cid_signalling == CID_SIG_V23_JP) {
- res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
} else {
- res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed(p->cs, buf, res, AST_LAW(p));
}
if (res < 0) {
/*
@@ -1525,7 +1525,7 @@ static int restore_conference(struct dahdi_pvt *p);
static int my_callwait(void *pvt)
{
struct dahdi_pvt *p = pvt;
- struct ast_format tmpfmt;
+
p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
if (p->cidspill) {
ast_log(LOG_WARNING, "Spill already exists?!?\n");
@@ -1542,11 +1542,11 @@ static int my_callwait(void *pvt)
/* Silence */
memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
if (!p->callwaitrings && p->callwaitingcallerid) {
- ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
p->callwaitcas = 1;
p->cidlen = 2400 + 680 + READ_SIZE * 4;
} else {
- ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
p->callwaitcas = 0;
p->cidlen = 2400 + READ_SIZE * 4;
}
@@ -1559,7 +1559,6 @@ static int my_callwait(void *pvt)
static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
{
struct dahdi_pvt *p = pvt;
- struct ast_format tmpfmt;
ast_debug(2, "Starting cid spill\n");
@@ -1573,7 +1572,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle
p->cidlen = ast_callerid_generate(p->cidspill,
caller->id.name.str,
caller->id.number.str,
- ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ AST_LAW(p));
} else {
ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
caller->id.name.str, caller->id.number.str);
@@ -1582,7 +1581,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle
p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
caller->id.name.str,
caller->id.number.str,
- ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ AST_LAW(p));
p->cidlen += READ_SIZE * 4;
}
p->cidpos = 0;
@@ -4965,14 +4964,12 @@ static int restore_conference(struct dahdi_pvt *p)
static int send_cwcidspill(struct dahdi_pvt *p)
{
- struct ast_format tmpfmt;
-
p->callwaitcas = 0;
p->cidcwexpire = 0;
p->cid_suppress_expire = 0;
if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
return -1;
- p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
/* Make sure we account for the end */
p->cidlen += READ_SIZE * 4;
p->cidpos = 0;
@@ -5038,7 +5035,7 @@ static int send_callerid(struct dahdi_pvt *p)
static int dahdi_callwait(struct ast_channel *ast)
{
struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
- struct ast_format tmpfmt;
+
p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
if (p->cidspill) {
ast_log(LOG_WARNING, "Spill already exists?!?\n");
@@ -5055,11 +5052,11 @@ static int dahdi_callwait(struct ast_channel *ast)
/* Silence */
memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
if (!p->callwaitrings && p->callwaitingcallerid) {
- ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
p->callwaitcas = 1;
p->cidlen = 2400 + 680 + READ_SIZE * 4;
} else {
- ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
p->callwaitcas = 0;
p->cidlen = 2400 + READ_SIZE * 4;
}
@@ -8504,25 +8501,20 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
return f;
}
- if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
if (!p->subs[idx].linear) {
p->subs[idx].linear = 1;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
}
- } else if ((ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) ||
- (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ALAW)) {
+ } else {
if (p->subs[idx].linear) {
p->subs[idx].linear = 0;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
}
- } else {
- ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
- ast_mutex_unlock(&p->lock);
- return NULL;
}
readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
CHECK_BLOCKING(ast);
@@ -8612,7 +8604,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
}
p->subs[idx].f.frametype = AST_FRAME_VOICE;
- ast_format_copy(&p->subs[idx].f.subclass.format, ast_channel_rawreadformat(ast));
+ p->subs[idx].f.subclass.format = ast_channel_rawreadformat(ast);
p->subs[idx].f.samples = READ_SIZE;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
@@ -8795,12 +8787,6 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
return 0;
}
- if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
- (frame->subclass.format.id != AST_FORMAT_ULAW) &&
- (frame->subclass.format.id != AST_FORMAT_ALAW)) {
- ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
- return -1;
- }
if (p->dialing) {
ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
return 0;
@@ -8818,7 +8804,7 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
if (!frame->data.ptr || !frame->datalen)
return 0;
- if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
if (!p->subs[idx].linear) {
p->subs[idx].linear = 1;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
@@ -8826,7 +8812,8 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
}
res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
- } else {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL
+ || ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
/* x-law already */
if (p->subs[idx].linear) {
p->subs[idx].linear = 0;
@@ -8835,6 +8822,10 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
}
res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
+ } else {
+ ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
+ ast_format_get_name(frame->subclass.format));
+ return -1;
}
if (res < 0) {
ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
@@ -9024,7 +9015,8 @@ static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state
static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid)
{
struct ast_channel *tmp;
- struct ast_format deflaw;
+ struct ast_format_cap *caps;
+ struct ast_format *deflaw;
int x;
int features;
struct ast_str *chan_name;
@@ -9037,7 +9029,6 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
return NULL;
}
- ast_format_clear(&deflaw);
#if defined(HAVE_PRI)
/*
* The dnid has been stuffed with the called-number[:subaddress]
@@ -9051,9 +9042,16 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
return NULL;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_free(chan_name);
+ return NULL;
+ }
+
tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
ast_free(chan_name);
if (!tmp) {
+ ao2_ref(caps, -1);
return NULL;
}
@@ -9073,9 +9071,9 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
if (law) {
i->law = law;
if (law == DAHDI_LAW_ALAW) {
- ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
+ deflaw = ast_format_alaw;
} else {
- ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
+ deflaw = ast_format_ulaw;
}
} else {
switch (i->sig) {
@@ -9089,18 +9087,20 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
break;
}
if (i->law_default == DAHDI_LAW_ALAW) {
- ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
+ deflaw = ast_format_alaw;
} else {
- ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
+ deflaw = ast_format_ulaw;
}
}
ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
- ast_format_cap_add(ast_channel_nativeformats(tmp), &deflaw);
+ ast_format_cap_append(caps, deflaw, 0);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
/* Start out assuming ulaw since it's smaller :) */
- ast_format_copy(ast_channel_rawreadformat(tmp), &deflaw);
- ast_format_copy(ast_channel_readformat(tmp), &deflaw);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &deflaw);
- ast_format_copy(ast_channel_writeformat(tmp), &deflaw);
+ ast_channel_set_rawreadformat(tmp, deflaw);
+ ast_channel_set_readformat(tmp, deflaw);
+ ast_channel_set_rawwriteformat(tmp, deflaw);
+ ast_channel_set_writeformat(tmp, deflaw);
i->subs[idx].linear = 0;
dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
features = 0;
@@ -9397,7 +9397,6 @@ static void *analog_ss_thread(void *data)
int len = 0;
int res;
int idx;
- struct ast_format tmpfmt;
RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
const char *pickupexten;
@@ -10114,9 +10113,9 @@ static void *analog_ss_thread(void *data)
samples += res;
if (p->cid_signalling == CID_SIG_V23_JP) {
- res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
} else {
- res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed(cs, buf, res, AST_LAW(p));
}
if (res < 0) {
/*
@@ -10399,7 +10398,7 @@ static void *analog_ss_thread(void *data)
}
}
samples += res;
- res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed(cs, buf, res, AST_LAW(p));
if (res < 0) {
/*
* The previous diagnostic message output likely
@@ -10569,7 +10568,7 @@ struct mwi_thread_data {
size_t len;
};
-static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
+static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
{
int x;
int sum = 0;
@@ -10578,7 +10577,7 @@ static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law
return 0;
for (x = 0; x < len; x++)
- sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
+ sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
return sum / len;
}
@@ -10594,13 +10593,12 @@ static void *mwi_thread(void *data)
int i, res;
unsigned int spill_done = 0;
int spill_result = -1;
- struct ast_format tmpfmt;
if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
goto quit_no_clean;
}
- callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
+ callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
bump_gains(mtd->pvt);
@@ -10686,7 +10684,7 @@ static void *mwi_thread(void *data)
}
samples += res;
if (!spill_done) {
- if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
+ if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
/*
* The previous diagnostic message output likely
* explains why it failed.
@@ -10744,7 +10742,6 @@ quit_no_clean:
static int mwi_send_init(struct dahdi_pvt * pvt)
{
int x;
- struct ast_format tmpfmt;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
/* Determine how this spill is to be sent */
@@ -10786,8 +10783,8 @@ static int mwi_send_init(struct dahdi_pvt * pvt)
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
if (pvt->mwisend_fsk) {
#endif
- pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
- ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
+ pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt),
+ CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
pvt->cidpos = 0;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
}
@@ -17314,7 +17311,8 @@ static int __unload_module(void)
dahdi_native_unload();
- dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
+ ao2_cleanup(dahdi_tech.capabilities);
+ dahdi_tech.capabilities = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
return 0;
}
@@ -19496,7 +19494,6 @@ static const struct ast_data_entry dahdi_data_providers[] = {
static int load_module(void)
{
int res;
- struct ast_format tmpfmt;
#if defined(HAVE_PRI) || defined(HAVE_SS7)
int y;
#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
@@ -19505,14 +19502,15 @@ static int load_module(void)
return AST_MODULE_LOAD_FAILURE;
}
- if (!(dahdi_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(dahdi_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(dahdi_tech.capabilities, ast_format_slin, 0);
+ ast_format_cap_append(dahdi_tech.capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(dahdi_tech.capabilities, ast_format_alaw, 0);
if (dahdi_native_load(ast_module_info->self, &dahdi_tech)) {
+ ao2_ref(dahdi_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
@@ -19558,8 +19556,10 @@ static int load_module(void)
#endif /* defined(HAVE_SS7) */
res = setup_dahdi(0);
/* Make sure we can register our DAHDI channel type */
- if (res)
+ if (res) {
+ __unload_module();
return AST_MODULE_LOAD_DECLINE;
+ }
if (ast_channel_register(&dahdi_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
__unload_module();
@@ -19652,10 +19652,9 @@ static int dahdi_sendtext(struct ast_channel *c, const char *text)
return -1;
mybuf = buf;
if (p->mate) {
- struct ast_format tmp;
/* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
- struct ast_format *codec = &tmp;
- ast_format_set(codec, AST_LAW(p), 0);
+ struct ast_format *codec = AST_LAW(p);
+
for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
PUT_CLID_MARKMS;
}
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 4beacfb22..be5b4c751 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -116,11 +116,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis.h"
#include "asterisk/stasis_system.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cap.h"
#include "iax2/include/iax2.h"
#include "iax2/include/firmware.h"
#include "iax2/include/parser.h"
#include "iax2/include/provision.h"
+#include "iax2/include/codec_pref.h"
+#include "iax2/include/format_compatibility.h"
+
#include "jitterbuf.h"
/*** DOCUMENTATION
@@ -279,7 +285,7 @@ static int nochecksums = 0;
/* Sample over last 100 units to determine historic jitter */
#define GAMMA (0.01)
-static struct ast_codec_pref prefs;
+static struct iax2_codec_pref prefs;
static const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)";
@@ -347,22 +353,22 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF
/* T1, maybe ISDN */
#define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SLINEAR) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SLINEAR16) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SIREN7) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SIREN14) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G719) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_ULAW) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_ALAW) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G722))
+ ~ast_format_compatibility_format2bitfield(ast_format_slin) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_slin16) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_siren7) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_siren14) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_g719) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_ulaw) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_alaw) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_g722))
/* A modem */
#define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G726) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G726_AAL2) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_ADPCM))
+ ~ast_format_compatibility_format2bitfield(ast_format_g726) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_g726_aal2) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_adpcm))
#define IAX_CAPABILITY_LOWFREE (IAX_CAPABILITY_LOWBANDWIDTH & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G723_1))
+ ~ast_format_compatibility_format2bitfield(ast_format_g723))
#define DEFAULT_MAXMS 2000 /* Must be faster than 2 seconds by default */
@@ -503,7 +509,7 @@ struct iax2_user {
iax2_format capability;
int maxauthreq; /*!< Maximum allowed outstanding AUTHREQs */
int curauthreq; /*!< Current number of outstanding AUTHREQs */
- struct ast_codec_pref prefs;
+ struct iax2_codec_pref prefs;
struct ast_acl_list *acl;
struct iax2_context *contexts;
struct ast_variable *vars;
@@ -532,7 +538,7 @@ struct iax2_peer {
AST_STRING_FIELD(zonetag); /*!< Time Zone */
AST_STRING_FIELD(parkinglot); /*!< Default parkinglot for device */
);
- struct ast_codec_pref prefs;
+ struct iax2_codec_pref prefs;
struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager */
struct ast_sockaddr addr;
int formats;
@@ -708,9 +714,9 @@ struct chan_iax2_pvt {
/*! Peer Address */
struct ast_sockaddr addr;
/*! Actual used codec preferences */
- struct ast_codec_pref prefs;
+ struct iax2_codec_pref prefs;
/*! Requested codec preferences */
- struct ast_codec_pref rprefs;
+ struct iax2_codec_pref rprefs;
/*! Our call number */
unsigned short callno;
/*! Our callno_entry entry */
@@ -1809,17 +1815,18 @@ static iax2_format uncompress_subclass(unsigned char csub)
return csub;
}
-static iax2_format iax2_codec_choose(struct ast_codec_pref *pref, iax2_format formats, int find_best)
+static iax2_format iax2_codec_choose(struct iax2_codec_pref *pref, iax2_format formats, int find_best)
{
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
iax2_format format = 0;
- if ((cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
- ast_format_clear(&tmpfmt);
- ast_format_cap_from_old_bitfield(cap, formats);
- ast_codec_choose(pref, cap, find_best, &tmpfmt);
- format = ast_format_to_old_bitfield(&tmpfmt);
- cap = ast_format_cap_destroy(cap);
+
+ if ((cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ iax2_format_compatibility_bitfield2cap(formats, cap);
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ format = ast_format_compatibility_format2bitfield(tmpfmt);
+ ao2_ref(tmpfmt, -1);
+ ao2_ref(cap, -1);
}
return format;
@@ -1827,55 +1834,84 @@ static iax2_format iax2_codec_choose(struct ast_codec_pref *pref, iax2_format fo
static iax2_format iax2_best_codec(iax2_format formats)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmpfmt;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format *tmpfmt;
+ iax2_format format;
+
if (!cap) {
return 0;
}
- ast_format_clear(&tmpfmt);
- ast_format_cap_from_old_bitfield(cap, formats);
- ast_best_codec(cap, &tmpfmt);
- cap = ast_format_cap_destroy(cap);
- return ast_format_to_old_bitfield(&tmpfmt);
+ iax2_format_compatibility_bitfield2cap(formats, cap);
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ format = ast_format_compatibility_format2bitfield(tmpfmt);
+ ao2_ref(tmpfmt, -1);
+ ao2_ref(cap, -1);
+
+ return format;
}
const char *iax2_getformatname(iax2_format format)
{
- struct ast_format tmpfmt;
- if (!(ast_format_from_old_bitfield(&tmpfmt, format))) {
+ struct ast_format *tmpfmt;
+
+ tmpfmt = ast_format_compatibility_bitfield2format(format);
+ if (!tmpfmt) {
return "Unknown";
}
- return ast_getformatname(&tmpfmt);
+ return ast_format_get_name(tmpfmt);
}
-static char *iax2_getformatname_multiple(char *codec_buf, size_t len, iax2_format format)
+static const char *iax2_getformatname_multiple(iax2_format format, struct ast_str **codec_buf)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return "(Nothing)";
}
- ast_format_cap_from_old_bitfield(cap, format);
- ast_getformatname_multiple(codec_buf, len, cap);
- cap = ast_format_cap_destroy(cap);
+ iax2_format_compatibility_bitfield2cap(format, cap);
+ ast_format_cap_get_names(cap, codec_buf);
+ ao2_ref(cap, -1);
- return codec_buf;
+ return ast_str_buffer(*codec_buf);
}
-static int iax2_parse_allow_disallow(struct ast_codec_pref *pref, iax2_format *formats, const char *list, int allowing)
+static int iax2_parse_allow_disallow(struct iax2_codec_pref *pref, iax2_format *formats, const char *list, int allowing)
{
- int res;
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ int res, i;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+
if (!cap) {
return 1;
}
- ast_format_cap_from_old_bitfield(cap, *formats);
- res = ast_parse_allow_disallow(pref, cap, list, allowing);
- *formats = ast_format_cap_to_old_bitfield(cap);
- cap = ast_format_cap_destroy(cap);
+ /* We want to add the formats to the cap in the preferred order */
+ for (i = 0; i < IAX2_CODEC_PREF_SIZE; i++) {
+ uint64_t pref_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[i]);
+
+ if (!pref_as_bitfield) {
+ break;
+ }
+
+ if (iax2_format_compatibility_bitfield2cap(pref_as_bitfield, cap)) {
+ ao2_ref(cap, -1);
+ return 1;
+ }
+ }
+
+ res = ast_format_cap_update_by_allow_disallow(cap, list, allowing);
+ *formats = iax2_format_compatibility_cap2bitfield(cap);
+
+ iax2_codec_pref_remove_missing(pref, *formats);
+
+ for (i = 0; i < ast_format_cap_count(cap); i++) {
+ struct ast_format *fmt = ast_format_cap_get_format(cap, i);
+ iax2_codec_pref_append(pref, fmt, ast_format_cap_get_format_framing(cap, fmt));
+ ao2_ref(fmt, -1);
+ }
+
+ ao2_ref(cap, -1);
return res;
}
@@ -1883,13 +1919,13 @@ static int iax2_parse_allow_disallow(struct ast_codec_pref *pref, iax2_format *f
static int iax2_data_add_codecs(struct ast_data *root, const char *node_name, iax2_format formats)
{
int res;
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return -1;
}
- ast_format_cap_from_old_bitfield(cap, formats);
+ iax2_format_compatibility_bitfield2cap(formats, cap);
res = ast_data_add_codecs(root, node_name, cap);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return res;
}
@@ -3737,9 +3773,9 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct
char status[30];
char cbuf[256];
struct iax2_peer *peer;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_str *encmethods = ast_str_alloca(256);
- int x = 0, load_realtime = 0;
+ int load_realtime = 0;
switch (cmd) {
case CLI_INIT:
@@ -3789,23 +3825,13 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct
ast_cli(a->fd, " Defaddr->IP : %s Port %s\n", str_defaddr, str_defport);
ast_cli(a->fd, " Username : %s\n", peer->username);
ast_cli(a->fd, " Codecs : ");
- iax2_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
- ast_cli(a->fd, "%s\n", codec_buf);
+ ast_cli(a->fd, "%s\n", iax2_getformatname_multiple(peer->capability, &codec_buf));
- ast_cli(a->fd, " Codec Order : (");
- for(x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- struct ast_format tmpfmt;
- if(!(ast_codec_pref_index(&peer->prefs, x, &tmpfmt)))
- break;
- ast_cli(a->fd, "%s", ast_getformatname(&tmpfmt));
- if(x < 31 && ast_codec_pref_index(&peer->prefs, x+1, &tmpfmt))
- ast_cli(a->fd, "|");
+ ast_cli(a->fd, " Codec Order : ");
+ if (iax2_codec_pref_string(&peer->prefs, cbuf, sizeof(cbuf)) != -1) {
+ ast_cli(a->fd, "%s\n", cbuf);
}
- if (!x)
- ast_cli(a->fd, "none");
- ast_cli(a->fd, ")\n");
-
ast_cli(a->fd, " Status : ");
peer_status(peer, status, sizeof(status));
ast_cli(a->fd, "%s\n",status);
@@ -4084,9 +4110,9 @@ static void __get_from_jb(const void *p)
ms = ast_tvdiff_ms(now, pvt->rxcore);
if(ms >= (next = jb_next(pvt->jb))) {
- struct ast_format voicefmt;
- ast_format_from_old_bitfield(&voicefmt, pvt->voiceformat);
- ret = jb_get(pvt->jb, &frame, ms, ast_codec_interp_len(&voicefmt));
+ struct ast_format *voicefmt;
+ voicefmt = ast_format_compatibility_bitfield2format(pvt->voiceformat);
+ ret = jb_get(pvt->jb, &frame, ms, ast_format_get_default_ms(voicefmt));
switch(ret) {
case JB_OK:
fr = frame.data;
@@ -4100,8 +4126,8 @@ static void __get_from_jb(const void *p)
/* create an interpolation frame */
af.frametype = AST_FRAME_VOICE;
- ast_format_copy(&af.subclass.format, &voicefmt);
- af.samples = frame.ms * (ast_format_rate(&voicefmt) / 1000);
+ af.subclass.format = voicefmt;
+ af.samples = frame.ms * (ast_format_get_sample_rate(voicefmt) / 1000);
af.src = "IAX2 JB interpolation";
af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
af.offset = AST_FRIENDLY_OFFSET;
@@ -4182,7 +4208,7 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
if(fr->af.frametype == AST_FRAME_VOICE) {
type = JB_TYPE_VOICE;
- len = ast_codec_get_samples(&fr->af) / (ast_format_rate(&fr->af.subclass.format) / 1000);
+ len = ast_codec_samples_count(&fr->af) / (ast_format_get_sample_rate(fr->af.subclass.format) / 1000);
} else if(fr->af.frametype == AST_FRAME_CNG) {
type = JB_TYPE_SILENCE;
}
@@ -4579,7 +4605,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
{
struct iax2_peer *peer;
int res = -1;
- struct ast_codec_pref ourprefs;
+ struct iax2_codec_pref ourprefs;
ast_clear_flag64(cai, IAX_SENDANI | IAX_TRUNK);
cai->sockfd = defaultsockfd;
@@ -4604,14 +4630,16 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
/* But move the calling channel's native codec to the top of the preference list */
memcpy(&ourprefs, &prefs, sizeof(ourprefs));
if (c) {
- struct ast_format tmpfmt;
- ast_format_cap_iter_start(ast_channel_nativeformats(c));
- while (!(ast_format_cap_iter_next(ast_channel_nativeformats(c), &tmpfmt))) {
- ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1);
+ int i;
+
+ for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) {
+ struct ast_format *format = ast_format_cap_get_format(
+ ast_channel_nativeformats(c), i);
+ iax2_codec_pref_prepend(&ourprefs, format, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), format), 1);
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(ast_channel_nativeformats(c));
}
- ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
+ iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
return 0;
}
@@ -4635,15 +4663,16 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
/* Move the calling channel's native codec to the top of the preference list */
if (c) {
- struct ast_format tmpfmt;
- ast_format_cap_iter_start(ast_channel_nativeformats(c));
- while (!(ast_format_cap_iter_next(ast_channel_nativeformats(c), &tmpfmt))) {
- ast_debug(1, "prepending %s to prefs\n", ast_getformatname(&tmpfmt));
- ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1);
+ int i;
+
+ for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) {
+ struct ast_format *tmpfmt = ast_format_cap_get_format(
+ ast_channel_nativeformats(c), i);
+ iax2_codec_pref_prepend(&ourprefs, tmpfmt, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), tmpfmt), 1);
+ ao2_ref(tmpfmt, -1);
}
- ast_format_cap_iter_end(ast_channel_nativeformats(c));
}
- ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
+ iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
ast_copy_string(cai->context, peer->context, sizeof(cai->context));
ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
ast_copy_string(cai->username, peer->username, sizeof(cai->username));
@@ -5181,7 +5210,7 @@ static int iax2_call(struct ast_channel *c, const char *dest, int timeout)
if (pds.password)
ast_string_field_set(iaxs[callno], secret, pds.password);
- iax2_tmpfmt = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(c));
+ iax2_tmpfmt = iax2_format_compatibility_cap2bitfield(ast_channel_nativeformats(c));
iax_ie_append_int(&ied, IAX_IE_FORMAT, (int) iax2_tmpfmt);
iax_ie_append_versioned_uint64(&ied, IAX_IE_FORMAT2, 0, iax2_tmpfmt);
@@ -5551,11 +5580,13 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha
return AST_BRIDGE_FAILED_NOWARN;
}
if (!(ast_format_cap_identical(ast_channel_nativeformats(c0), ast_channel_nativeformats(c1)))) {
- char buf0[256];
- char buf1[256];
- ast_getformatname_multiple(buf0, sizeof(buf0), ast_channel_nativeformats(c0));
- ast_getformatname_multiple(buf1, sizeof(buf1), ast_channel_nativeformats(c1));
- ast_verb(3, "Operating with different codecs [%s] [%s] , can't native bridge...\n", buf0, buf1);
+ struct ast_str *c0_buf = ast_str_alloca(64);
+ struct ast_str *c1_buf = ast_str_alloca(64);
+
+ ast_verb(3, "Operating with different codecs [%s] [%s] , can't native bridge...\n",
+ ast_format_cap_get_names(ast_channel_nativeformats(c0), &c0_buf),
+ ast_format_cap_get_names(ast_channel_nativeformats(c1), &c1_buf));
+
/* Remove from native mode */
lock_both(callno0, callno1);
if (iaxs[callno0])
@@ -5780,7 +5811,8 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
struct ast_channel *tmp;
struct chan_iax2_pvt *i;
struct ast_variable *v = NULL;
- struct ast_format tmpfmt;
+ struct ast_format_cap *native;
+ struct ast_format *tmpfmt;
struct ast_callid *callid;
if (!(i = iaxs[callno])) {
@@ -5788,6 +5820,11 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
return NULL;
}
+ native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!native) {
+ return NULL;
+ }
+
/* Don't hold call lock */
ast_mutex_unlock(&iaxsl[callno]);
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
@@ -5800,9 +5837,11 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
tmp = ast_channel_release(tmp);
ast_mutex_lock(&iaxsl[callno]);
}
+ ao2_ref(native, -1);
return NULL;
}
if (!tmp) {
+ ao2_ref(native, -1);
return NULL;
}
@@ -5813,14 +5852,19 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
}
ast_channel_tech_set(tmp, &iax2_tech);
+
/* We can support any format by default, until we get restricted */
- ast_format_cap_from_old_bitfield(ast_channel_nativeformats(tmp), capability);
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
+ iax2_format_compatibility_bitfield2cap(capability, native);
+ ast_channel_nativeformats_set(tmp, native);
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+
+ ao2_ref(tmpfmt, -1);
+ ao2_ref(native, -1);
ast_channel_tech_pvt_set(tmp, CALLNO_TO_PTR(i->callno));
@@ -5971,7 +6015,7 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
int voice = 0;
int genuine = 0;
int adjust;
- int rate = ast_format_rate(&f->subclass.format) / 1000;
+ int rate = 0;
struct timeval *delivery = NULL;
@@ -5983,6 +6027,7 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
*/
if (f->frametype == AST_FRAME_VOICE) {
voice = 1;
+ rate = ast_format_get_sample_rate(f->subclass.format) / 1000;
delivery = &f->delivery;
} else if (f->frametype == AST_FRAME_IAX) {
genuine = 1;
@@ -6092,8 +6137,9 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
}
}
p->lastsent = ms;
- if (voice)
+ if (voice) {
p->nextpred = p->nextpred + f->samples / rate;
+ }
return ms;
}
@@ -6344,9 +6390,9 @@ static int decode_frame(ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh,
memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
f->frametype = fh->type;
if (f->frametype == AST_FRAME_VIDEO) {
- ast_format_from_old_bitfield(&f->subclass.format, (uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1)));
+ f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1));
} else if (f->frametype == AST_FRAME_VOICE) {
- ast_format_from_old_bitfield(&f->subclass.format, uncompress_subclass(fh->csub));
+ f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub));
} else {
f->subclass.integer = uncompress_subclass(fh->csub);
}
@@ -6487,7 +6533,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
/* High two bytes are the same on timestamp, or sending on a trunk */ &&
(f->frametype == AST_FRAME_VOICE)
/* is a voice frame */ &&
- (f->subclass.format.id == ast_format_id_from_old_bitfield(pvt->svoiceformat))
+ (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svoiceformat)))
/* is the same type */ ) {
/* Force immediate rather than delayed transmission */
now = 1;
@@ -6501,7 +6547,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
* Otherwise send a mini video frame
*/
if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
- ((f->subclass.format.id) == ast_format_id_from_old_bitfield(pvt->svideoformat))
+ (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svideoformat)))
) {
now = 1;
sendmini = 1;
@@ -6556,11 +6602,11 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
fh->type = fr->af.frametype & 0xFF;
if (fr->af.frametype == AST_FRAME_VIDEO) {
- iax2_format tmpfmt = ast_format_to_old_bitfield(&fr->af.subclass.format);
- tmpfmt |= ast_format_get_video_mark(&fr->af.subclass.format) ? 0x1LL : 0;
+ iax2_format tmpfmt = ast_format_compatibility_format2bitfield(fr->af.subclass.format);
+ tmpfmt |= fr->af.subclass.frame_ending ? 0x1LL : 0;
fh->csub = compress_subclass(tmpfmt | ((tmpfmt & 0x1LL) << 6));
} else if (fr->af.frametype == AST_FRAME_VOICE) {
- fh->csub = compress_subclass(ast_format_to_old_bitfield(&fr->af.subclass.format));
+ fh->csub = compress_subclass(ast_format_compatibility_format2bitfield(fr->af.subclass.format));
} else {
fh->csub = compress_subclass(fr->af.subclass.integer);
}
@@ -6583,9 +6629,9 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
if ((f->frametype == AST_FRAME_IAX) && (f->subclass.integer == IAX_COMMAND_ACK))
fr->retries = -1;
else if (f->frametype == AST_FRAME_VOICE)
- pvt->svoiceformat = ast_format_to_old_bitfield(&f->subclass.format);
+ pvt->svoiceformat = ast_format_compatibility_format2bitfield(f->subclass.format);
else if (f->frametype == AST_FRAME_VIDEO)
- pvt->svideoformat = ast_format_to_old_bitfield(&f->subclass.format);
+ pvt->svideoformat = ast_format_compatibility_format2bitfield(f->subclass.format);
if (ast_test_flag64(pvt, IAX_ENCRYPTED)) {
if (ast_test_flag64(pvt, IAX_KEYPOPULATED)) {
if (fr->transfer)
@@ -6616,7 +6662,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
vh = (struct ast_iax2_video_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_video_hdr));
vh->zeros = 0;
vh->callno = htons(0x8000 | fr->callno);
- vh->ts = htons((fr->ts & 0x7FFF) | (ast_format_get_video_mark(&fr->af.subclass.format) ? 0x8000 : 0));
+ vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass.frame_ending ? 0x8000 : 0));
fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
fr->data = vh;
fr->retries = -1;
@@ -7767,8 +7813,8 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i
/* Use provided preferences until told otherwise for actual preferences */
if (ies->codec_prefs) {
- ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
- ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
+ iax2_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
+ iax2_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
}
if (!gotcapability) {
@@ -9827,7 +9873,7 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s
ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n");
iax2_vnak(fr->callno);
} else {
- ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat);
+ f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat);
f.datalen = len;
if (f.datalen >= 0) {
if (f.datalen)
@@ -9847,7 +9893,7 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s
f.mallocd = 0;
f.offset = 0;
if (f.datalen && (f.frametype == AST_FRAME_VOICE))
- f.samples = ast_codec_get_samples(&f);
+ f.samples = ast_codec_samples_count(&f);
else
f.samples = 0;
fr->outoforder = 0;
@@ -10004,7 +10050,7 @@ static int socket_process_helper(struct iax2_thread *thread)
struct iax_frame *duped_fr;
char host_pref_buf[128];
char caller_pref_buf[128];
- struct ast_codec_pref pref;
+ struct iax2_codec_pref pref;
char *using_prefs = "mine";
/* allocate an iax_frame with 4096 bytes of data buffer */
@@ -10069,12 +10115,12 @@ static int socket_process_helper(struct iax2_thread *thread)
/* Retrieve the type and subclass */
f.frametype = fh->type;
if (f.frametype == AST_FRAME_VIDEO) {
- ast_format_from_old_bitfield(&f.subclass.format, (uncompress_subclass(fh->csub & ~0x40)));
+ f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40));
if ((fh->csub >> 6) & 0x1) {
- ast_format_set_video_mark(&f.subclass.format);
+ f.subclass.frame_ending = 1;
}
} else if (f.frametype == AST_FRAME_VOICE) {
- ast_format_from_old_bitfield(&f.subclass.format, uncompress_subclass(fh->csub));
+ f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub));
} else {
f.subclass.integer = uncompress_subclass(fh->csub);
}
@@ -10498,22 +10544,21 @@ static int socket_process_helper(struct iax2_thread *thread)
}
if (f.frametype == AST_FRAME_VOICE) {
- if (ast_format_to_old_bitfield(&f.subclass.format) != iaxs[fr->callno]->voiceformat) {
- iaxs[fr->callno]->voiceformat = ast_format_to_old_bitfield(&f.subclass.format);
- ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_getformatname(&f.subclass.format));
+ if (ast_format_compatibility_format2bitfield(f.subclass.format) != iaxs[fr->callno]->voiceformat) {
+ iaxs[fr->callno]->voiceformat = ast_format_compatibility_format2bitfield(f.subclass.format);
+ ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_format_get_name(f.subclass.format));
if (iaxs[fr->callno]->owner) {
iax2_lock_owner(fr->callno);
if (iaxs[fr->callno]) {
if (iaxs[fr->callno]->owner) {
- struct ast_format_cap *orignative = ast_format_cap_dup(ast_channel_nativeformats(iaxs[fr->callno]->owner));
- struct ast_format_cap *native = ast_channel_nativeformats(iaxs[fr->callno]->owner);
- if (orignative) {
- ast_format_cap_set(native, &f.subclass.format);
- if (ast_channel_readformat(iaxs[fr->callno]->owner)->id) {
+ struct ast_format_cap *native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (native) {
+ ast_format_cap_append(native, f.subclass.format, 0);
+ ast_channel_nativeformats_set(iaxs[fr->callno]->owner, native);
+ if (ast_channel_readformat(iaxs[fr->callno]->owner)) {
ast_set_read_format(iaxs[fr->callno]->owner, ast_channel_readformat(iaxs[fr->callno]->owner));
}
- ast_format_cap_copy(native, orignative);
- orignative = ast_format_cap_destroy(orignative);
+ ao2_ref(native, -1);
}
ast_channel_unlock(iaxs[fr->callno]->owner);
}
@@ -10532,9 +10577,9 @@ static int socket_process_helper(struct iax2_thread *thread)
}
}
if (f.frametype == AST_FRAME_VIDEO) {
- if (f.subclass.format.id != ast_format_id_from_old_bitfield(iaxs[fr->callno]->videoformat)) {
- ast_debug(1, "Ooh, video format changed to %s\n", ast_getformatname(&f.subclass.format));
- iaxs[fr->callno]->videoformat = ast_format_to_old_bitfield(&f.subclass.format);
+ if (ast_format_compatibility_format2bitfield(f.subclass.format) != iaxs[fr->callno]->videoformat) {
+ ast_debug(1, "Ooh, video format changed to %s\n", ast_format_get_name(f.subclass.format));
+ iaxs[fr->callno]->videoformat = ast_format_compatibility_format2bitfield(f.subclass.format);
}
}
if (f.frametype == AST_FRAME_IAX) {
@@ -10697,12 +10742,12 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf, "disabled");
strcpy(host_pref_buf, "disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
/* If the information elements are in here... use them */
if (ies.codec_prefs)
- ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ iax2_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
/* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->rprefs;
@@ -10714,8 +10759,8 @@ static int socket_process_helper(struct iax2_thread *thread)
pref = iaxs[fr->callno]->prefs;
format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
- ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
- ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
}
if (!format) {
if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP))
@@ -10729,18 +10774,21 @@ static int socket_process_helper(struct iax2_thread *thread)
break;
}
if (authdebug) {
- char tmp[256], tmp2[256], tmp3[256];
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
} else {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
}
} else {
@@ -10756,9 +10804,9 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf,"disabled");
strcpy(host_pref_buf,"disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
/* Do the opposite of what we tried above. */
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->prefs;
@@ -10773,11 +10821,14 @@ static int socket_process_helper(struct iax2_thread *thread)
}
if (!format) {
- char tmp[256], tmp2[256], tmp3[256];
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
- ast_log(LOG_ERROR, "No best format in '%s'???\n", iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability));
+ ast_log(LOG_ERROR, "No best format in '%s'???\n", iax2_getformatname_multiple(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, &cap_buf));
send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
if (!iaxs[fr->callno]) {
break;
@@ -10785,9 +10836,9 @@ static int socket_process_helper(struct iax2_thread *thread)
if (authdebug) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
break;
@@ -10935,7 +10986,7 @@ static int socket_process_helper(struct iax2_thread *thread)
iaxs[fr->callno]->peerformat = ies.format;
} else {
if (iaxs[fr->callno]->owner)
- iaxs[fr->callno]->peerformat = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner));
+ iaxs[fr->callno]->peerformat = iax2_format_compatibility_cap2bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner));
else
iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability;
}
@@ -10950,28 +11001,36 @@ static int socket_process_helper(struct iax2_thread *thread)
break;
}
if (authdebug) {
- char tmp1[256], tmp2[256];
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_NOTICE, "Rejected call to %s, format %s incompatible with our capability %s.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
} else {
+ struct ast_format_cap *native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
iax2_lock_owner(fr->callno);
- if (iaxs[fr->callno] && iaxs[fr->callno]->owner) {
- char tmp[256];
+ if (iaxs[fr->callno] && iaxs[fr->callno]->owner && native) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
/* Switch us to use a compatible format */
- ast_format_cap_from_old_bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner), iaxs[fr->callno]->peerformat);
- ast_verb(3, "Format for call is %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(iaxs[fr->callno]->owner)));
+ iax2_format_compatibility_bitfield2cap(iaxs[fr->callno]->peerformat, native);
+ ast_channel_nativeformats_set(iaxs[fr->callno]->owner, native);
+ ast_verb(3, "Format for call is %s\n", ast_format_cap_get_names(ast_channel_nativeformats(iaxs[fr->callno]->owner), &cap_buf));
/* Setup read/write formats properly. */
- if (ast_channel_writeformat(iaxs[fr->callno]->owner)->id)
+ if (ast_channel_writeformat(iaxs[fr->callno]->owner))
ast_set_write_format(iaxs[fr->callno]->owner, ast_channel_writeformat(iaxs[fr->callno]->owner));
- if (ast_channel_readformat(iaxs[fr->callno]->owner)->id)
+ if (ast_channel_readformat(iaxs[fr->callno]->owner))
ast_set_read_format(iaxs[fr->callno]->owner, ast_channel_readformat(iaxs[fr->callno]->owner));
ast_channel_unlock(iaxs[fr->callno]->owner);
}
+
+ ao2_cleanup(native);
}
if (iaxs[fr->callno]) {
AST_LIST_LOCK(&dpcache);
@@ -11140,11 +11199,11 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf, "disabled");
strcpy(host_pref_buf, "disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
if (ies.codec_prefs)
- ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ iax2_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->rprefs;
using_prefs = "caller";
@@ -11154,15 +11213,18 @@ static int socket_process_helper(struct iax2_thread *thread)
} else /* if no codec_prefs IE do it the old way */
pref = iaxs[fr->callno]->prefs;
format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
- ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
- ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
}
if (!format) {
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_debug(1, "We don't do requested format %s, falling back to peer capability '%s'\n",
iax2_getformatname(iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf));
format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
}
if (!format) {
@@ -11170,14 +11232,14 @@ static int socket_process_helper(struct iax2_thread *thread)
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
} else {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
}
memset(&ied0, 0, sizeof(ied0));
@@ -11201,9 +11263,9 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf,"disabled");
strcpy(host_pref_buf,"disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
/* Do the opposite of what we tried above. */
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->prefs;
@@ -11217,21 +11279,24 @@ static int socket_process_helper(struct iax2_thread *thread)
}
}
if (!format) {
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
ast_log(LOG_ERROR, "No best format in %s???\n",
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, &cap_buf));
if (authdebug) {
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
} else {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
}
memset(&ied0, 0, sizeof(ied0));
@@ -11338,11 +11403,11 @@ immediatedial:
break;
}
} else {
- char tmp[256];
+ struct ast_str *cap_buf = ast_str_alloca(64);
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
ast_verb(3, "Accepting DIAL from %s, formats = %s\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &cap_buf));
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat, NULL, NULL, 1)))
@@ -11662,9 +11727,9 @@ immediatedial:
f.frametype = AST_FRAME_VIDEO;
if (iaxs[fr->callno]->videoformat > 0) {
if (ntohs(vh->ts) & 0x8000LL) {
- ast_format_set_video_mark(&f.subclass.format);
+ f.subclass.frame_ending = 1;
}
- ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->videoformat);
+ f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->videoformat);
} else {
ast_log(LOG_WARNING, "Received mini frame before first full video frame\n");
iax2_vnak(fr->callno);
@@ -11687,7 +11752,7 @@ immediatedial:
/* A mini frame */
f.frametype = AST_FRAME_VOICE;
if (iaxs[fr->callno]->voiceformat > 0)
- ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat);
+ f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat);
else {
ast_debug(1, "Received mini frame before first full voice frame\n");
iax2_vnak(fr->callno);
@@ -11795,9 +11860,9 @@ immediatedial:
f.offset = 0;
f.len = 0;
if (f.datalen && (f.frametype == AST_FRAME_VOICE)) {
- f.samples = ast_codec_get_samples(&f);
+ f.samples = ast_codec_samples_count(&f);
/* We need to byteswap incoming slinear samples from network byte order */
- if (f.subclass.format.id == AST_FORMAT_SLINEAR)
+ if (ast_format_cmp(f.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
ast_frame_byteswap_be(&f);
} else
f.samples = 0;
@@ -12376,32 +12441,48 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
if (c) {
struct ast_format_cap *joint;
+ struct ast_format *format;
if (callid) {
ast_channel_lock(c);
ast_channel_callid_set(c, callid);
ast_channel_unlock(c);
}
- /* Choose a format we can live with */
- if ((joint = ast_format_cap_joint(ast_channel_nativeformats(c), cap))) {
- ast_format_cap_copy(ast_channel_nativeformats(c), joint);
- joint = ast_format_cap_destroy(joint);
- } else {
- struct ast_format best_fmt_cap;
- struct ast_format best_fmt_native;
+ joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!joint) {
+ ast_hangup(c);
+ return NULL;
+ }
+
+ ast_format_cap_get_compatible(ast_channel_nativeformats(c), cap, joint);
+
+ /* If there is no joint format find one through translation */
+ if (!ast_format_cap_count(joint)) {
+ struct ast_format *best_fmt_cap = NULL;
+ struct ast_format *best_fmt_native = NULL;
res = ast_translator_best_choice(cap, ast_channel_nativeformats(c), &best_fmt_cap, &best_fmt_native);
if (res < 0) {
- char tmp[256];
- char tmp2[256];
+ struct ast_str *native_cap_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(c)), ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_channel_name(c));
+ ast_format_cap_get_names(ast_channel_nativeformats(c), &native_cap_buf),
+ ast_format_cap_get_names(cap, &cap_buf),
+ ast_channel_name(c));
ast_hangup(c);
return NULL;
}
- ast_format_cap_set(ast_channel_nativeformats(c), &best_fmt_native);
+ ast_format_cap_append(joint, best_fmt_native, 0);
+ ao2_ref(best_fmt_cap, -1);
+ ao2_ref(best_fmt_native, -1);
}
- ast_best_codec(ast_channel_nativeformats(c), ast_channel_readformat(c));
- ast_format_copy(ast_channel_writeformat(c), ast_channel_readformat(c));
+ ast_channel_nativeformats_set(c, joint);
+ format = ast_format_cap_get_format(ast_channel_nativeformats(c), 0);
+ ast_channel_set_readformat(c, format);
+ ast_channel_set_writeformat(c, format);
+
+ ao2_ref(joint, -1);
+ ao2_ref(format, -1);
}
if (callid) {
@@ -13355,7 +13436,7 @@ static int set_config(const char *config_file, int reload, int forced)
ast_sockaddr_parse(&bindaddr, "0.0.0.0:0", 0);
/* Reset global codec prefs */
- memset(&prefs, 0 , sizeof(struct ast_codec_pref));
+ memset(&prefs, 0 , sizeof(struct iax2_codec_pref));
/* Reset Global Flags */
memset(&globalflags, 0, sizeof(globalflags));
@@ -14234,10 +14315,13 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat
} else if (!strcasecmp(colname, "callerid_num")) {
ast_copy_string(buf, peer->cid_num, len);
} else if (!strcasecmp(colname, "codecs")) {
- iax2_getformatname_multiple(buf, len -1, peer->capability);
+ struct ast_str *codec_buf;
+
+ iax2_getformatname_multiple(peer->capability, &codec_buf);
+ ast_copy_string(buf, ast_str_buffer(codec_buf), len);
} else if (!strncasecmp(colname, "codec[", 6)) {
char *codecnum, *ptr;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
/* skip over "codec" to the '[' */
codecnum = colname + 5;
@@ -14246,8 +14330,8 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat
if ((ptr = strchr(codecnum, ']'))) {
*ptr = '\0';
}
- if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &tmpfmt))) {
- ast_copy_string(buf, ast_getformatname(&tmpfmt), len);
+ if((iax2_codec_pref_index(&peer->prefs, atoi(codecnum), &tmpfmt))) {
+ ast_copy_string(buf, ast_format_get_name(tmpfmt), len);
} else {
buf[0] = '\0';
}
@@ -14604,7 +14688,8 @@ static int __unload_module(void)
ast_context_destroy(con, "IAX2");
ast_unload_realtime("iaxpeers");
- iax2_tech.capabilities = ast_format_cap_destroy(iax2_tech.capabilities);
+ ao2_ref(iax2_tech.capabilities, -1);
+ iax2_tech.capabilities = NULL;
return 0;
}
@@ -14914,10 +14999,10 @@ static int load_module(void)
int x = 0;
struct iax2_registry *reg = NULL;
- if (!(iax2_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(iax2_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add_all(iax2_tech.capabilities);
+ ast_format_cap_append_by_type(iax2_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (load_objects()) {
return AST_MODULE_LOAD_FAILURE;
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 2d0afe29d..6021b6c1d 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -86,6 +86,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/features_config.h"
#include "asterisk/parking.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*
* Define to work around buggy dlink MGCP phone firmware which
@@ -1199,9 +1200,20 @@ static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
if (sub->owner) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
- if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format)) {
- ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(sub->owner, caps);
+ ao2_ref(caps, -1);
+ } else {
+ return &ast_null_frame;
+ }
+
ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
}
@@ -1239,7 +1251,6 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
{
struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
int res = 0;
- char buf[256];
if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype == AST_FRAME_IMAGE)
@@ -1249,12 +1260,14 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
} else {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
/* return -1; */
}
}
@@ -1490,90 +1503,103 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps = NULL;
struct ast_channel *tmp;
struct ast_variable *v = NULL;
struct mgcp_endpoint *i = sub->parent;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Format capabilities could not be created\n");
+ return NULL;
+ }
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
- if (tmp) {
- ast_channel_stage_snapshot(tmp);
- ast_channel_tech_set(tmp, &mgcp_tech);
- ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
- ast_format_cap_copy(ast_channel_nativeformats(tmp), global_capability);
- }
- if (sub->rtp) {
- ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
- }
- if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
- i->dsp = ast_dsp_new();
- ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
- /* this is to prevent clipping of dtmf tones during dsp processing */
- ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
- } else {
- i->dsp = NULL;
- }
- if (state == AST_STATE_RING)
- ast_channel_rings_set(tmp, 1);
-
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_channel_tech_pvt_set(tmp, sub);
- if (!ast_strlen_zero(i->language))
- ast_channel_language_set(tmp, i->language);
- if (!ast_strlen_zero(i->accountcode))
- ast_channel_accountcode_set(tmp, i->accountcode);
- if (i->amaflags)
- ast_channel_amaflags_set(tmp, i->amaflags);
- mgcp_set_owner(sub, tmp);
- ast_module_ref(ast_module_info->self);
- ast_channel_callgroup_set(tmp, i->callgroup);
- ast_channel_pickupgroup_set(tmp, i->pickupgroup);
- ast_channel_call_forward_set(tmp, i->call_forward);
- ast_channel_context_set(tmp, i->context);
- ast_channel_exten_set(tmp, i->exten);
-
- /* Don't use ast_set_callerid() here because it will
- * generate a needless NewCallerID event */
- if (!ast_strlen_zero(i->cid_num)) {
- ast_channel_caller(tmp)->ani.number.valid = 1;
- ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
- }
-
- if (!i->adsi) {
- ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
- }
- ast_channel_priority_set(tmp, 1);
+ if (!tmp) {
+ ast_log(LOG_WARNING, "Channel could not be created\n");
+ ao2_ref(caps, -1);
+ return NULL;
+ }
- /* Set channel variables for this call from configuration */
- for (v = i->chanvars ; v ; v = v->next) {
- char valuebuf[1024];
- pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
- }
+ ast_channel_stage_snapshot(tmp);
+ ast_channel_tech_set(tmp, &mgcp_tech);
+ if (ast_format_cap_count(i->cap)) {
+ ast_format_cap_append_from_cap(caps, i->cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append_from_cap(caps, global_capability, AST_MEDIA_TYPE_UNKNOWN);
+ }
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+ if (sub->rtp) {
+ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
+ }
+ if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
+ i->dsp = ast_dsp_new();
+ ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
+ /* this is to prevent clipping of dtmf tones during dsp processing */
+ ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
+ } else {
+ i->dsp = NULL;
+ }
+ if (state == AST_STATE_RING) {
+ ast_channel_rings_set(tmp, 1);
+ }
+
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
+ ast_channel_tech_pvt_set(tmp, sub);
+ if (!ast_strlen_zero(i->language))
+ ast_channel_language_set(tmp, i->language);
+ if (!ast_strlen_zero(i->accountcode))
+ ast_channel_accountcode_set(tmp, i->accountcode);
+ if (i->amaflags)
+ ast_channel_amaflags_set(tmp, i->amaflags);
+ mgcp_set_owner(sub, tmp);
+ ast_module_ref(ast_module_info->self);
+ ast_channel_callgroup_set(tmp, i->callgroup);
+ ast_channel_pickupgroup_set(tmp, i->pickupgroup);
+ ast_channel_call_forward_set(tmp, i->call_forward);
+ ast_channel_context_set(tmp, i->context);
+ ast_channel_exten_set(tmp, i->exten);
+ /* Don't use ast_set_callerid() here because it will
+ * generate a needless NewCallerID event */
+ if (!ast_strlen_zero(i->cid_num)) {
+ ast_channel_caller(tmp)->ani.number.valid = 1;
+ ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
+ }
+
+ if (!i->adsi) {
+ ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
+ }
+ ast_channel_priority_set(tmp, 1);
+
+ /* Set channel variables for this call from configuration */
+ for (v = i->chanvars ; v ; v = v->next) {
+ char valuebuf[1024];
+ pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
+ }
- if (sub->rtp) {
- ast_jb_configure(tmp, &global_jbconf);
- }
+ if (sub->rtp) {
+ ast_jb_configure(tmp, &global_jbconf);
+ }
- ast_channel_stage_snapshot_done(tmp);
- ast_channel_unlock(tmp);
+ ast_channel_stage_snapshot_done(tmp);
+ ast_channel_unlock(tmp);
- if (state != AST_STATE_DOWN) {
- if (ast_pbx_start(tmp)) {
- ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
- ast_hangup(tmp);
- tmp = NULL;
- }
+ if (state != AST_STATE_DOWN) {
+ if (ast_pbx_start(tmp)) {
+ ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
+ ast_hangup(tmp);
+ tmp = NULL;
}
- ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
- ast_channel_name(tmp), ast_state2str(state));
- } else {
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
}
+ ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
+ ast_channel_name(tmp), ast_state2str(state));
+
return tmp;
}
@@ -1973,7 +1999,9 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
int codec, codec_count=0;
int iterator;
struct mgcp_endpoint *p = sub->parent;
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *global_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *pvt_buf = ast_str_alloca(64);
/* Get codec and RTP info from SDP */
m = get_sdp(req, "m");
@@ -2030,20 +2058,20 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
}
/* Now gather all of the codecs that were asked for: */
- if (!(peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return -1;
}
ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability);
- ast_format_cap_joint_copy(global_capability, peercap, p->cap);
+ ast_format_cap_get_compatible(global_capability, peercap, p->cap);
ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n",
- ast_getformatname_multiple(tmp1, sizeof(tmp1), global_capability),
- ast_getformatname_multiple(tmp2, sizeof(tmp2), peercap),
- ast_getformatname_multiple(tmp3, sizeof(tmp3), p->cap));
- peercap = ast_format_cap_destroy(peercap);
+ ast_format_cap_get_names(global_capability, &global_buf),
+ ast_format_cap_get_names(peercap, &peer_buf),
+ ast_format_cap_get_names(p->cap, &pvt_buf));
+ ao2_ref(peercap, -1);
ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n",
nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
- if (ast_format_cap_is_empty(p->cap)) {
+ if (!ast_format_cap_count(p->cap)) {
ast_log(LOG_WARNING, "No compatible codecs!\n");
return -1;
}
@@ -2201,7 +2229,6 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
char m[256] = "";
char a[1024] = "";
int x;
- struct ast_format tmpfmt;
struct sockaddr_in dest = { 0, };
struct ast_sockaddr dest_tmp;
struct mgcp_endpoint *p = sub->parent;
@@ -2236,24 +2263,25 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
ast_copy_string(t, "t=0 0\r\n", sizeof(t));
snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
- /* Audio is now discontiguous */
+ for (x = 0; x < ast_format_cap_count(p->cap); x++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, x);
+
+ if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(format, -1);
continue;
}
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- ast_debug(1, "Answering with capability %s\n", ast_getformatname(&tmpfmt));
- codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &tmpfmt, 0);
- if (codec > -1) {
- snprintf(costr, sizeof(costr), " %d", codec);
- strncat(m, costr, sizeof(m) - strlen(m) - 1);
- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(a, costr, sizeof(a) - strlen(a) - 1);
- }
+
+ ast_debug(1, "Answering with capability %s\n", ast_format_get_name(format));
+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, format, 0);
+ if (codec > -1) {
+ snprintf(costr, sizeof(costr), " %d", codec);
+ strncat(m, costr, sizeof(m) - strlen(m) - 1);
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
+ strncat(a, costr, sizeof(a) - strlen(a) - 1);
}
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
if (p->nonCodecCapability & x) {
@@ -2292,7 +2320,7 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_
char local[256];
char tmp[80];
struct mgcp_endpoint *p = sub->parent;
- struct ast_format tmpfmt;
+ int i;
struct ast_sockaddr sub_tmpdest_tmp;
unsigned int oseq;
@@ -2304,18 +2332,20 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_
return 0;
}
ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
- /* Audio is now discontiguous */
+
+ for (i = 0; i < ast_format_cap_count(p->cap); i++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, i);
+
+ if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(format, -1);
continue;
}
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
+
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
if (sub->gate) {
if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
@@ -2351,7 +2381,7 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
struct mgcp_request resp;
char local[256];
char tmp[80];
- struct ast_format tmpfmt;
+ int i;
struct mgcp_endpoint *p = sub->parent;
unsigned int oseq;
@@ -2360,18 +2390,19 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
- /* Audio is now discontiguous */
+ for (i = 0; i < ast_format_cap_count(p->cap); i++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, i);
+
+ if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(format, -1);
continue;
}
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
+
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
if (sub->gate) {
if(sub->gate->state == GATE_ALLOCATED) {
@@ -2447,22 +2478,23 @@ static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub)
static int transmit_connect(struct mgcp_subchannel *sub)
{
struct mgcp_request resp;
+ int x;
char local[256];
char tmp[80];
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
struct mgcp_endpoint *p = sub->parent;
unsigned int oseq;
ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
+ for (x = 0; x < ast_format_cap_count(p->cap); x++) {
+ tmpfmt = ast_format_cap_get_format(p->cap, x);
+
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, tmpfmt, 0, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(tmpfmt, -1);
}
- ast_format_cap_iter_end(p->cap);
ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
@@ -2557,7 +2589,7 @@ static int transmit_modify_request(struct mgcp_subchannel *sub)
{
struct mgcp_request resp;
struct mgcp_endpoint *p = sub->parent;
- struct ast_format tmpfmt;
+ int i;
int fc = 1;
char local[256];
char tmp[80];
@@ -2572,18 +2604,22 @@ static int transmit_modify_request(struct mgcp_subchannel *sub)
p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
ast_copy_string(local, "", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
+ for (i = 0; i < ast_format_cap_count(p->cap); i++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, i);
+
if (p->ncs && !fc) {
- ast_format_cap_set(p->cap, &tmpfmt); /* sb5120e bug */
+ ast_format_cap_remove_by_type(p->cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->cap, format, 0); /* sb5120e bug */
+ ao2_ref(format, -1);
break;
} else {
fc = 0;
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
}
strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
if (!sub->sdpsent) {
if (sub->gate) {
@@ -3948,8 +3984,10 @@ static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap
struct ast_channel *tmpc = NULL;
char tmp[256];
- if (!(ast_format_cap_has_joint(cap, global_capability))) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ if (!(ast_format_cap_iscompatible(cap, global_capability))) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
+ ast_format_cap_get_names(cap, &cap_buf));
/*return NULL;*/
}
ast_copy_string(tmp, dest, sizeof(tmp));
@@ -4185,7 +4223,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
ast_mutex_init(&e->lock);
ast_mutex_init(&e->rqnt_queue_lock);
ast_mutex_init(&e->cmd_queue_lock);
- e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
ast_copy_string(e->name, v->value, sizeof(e->name));
e->needaudit = 1;
}
@@ -4210,7 +4248,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
e->msgstate = -1;
e->amaflags = amaflags;
- ast_format_cap_copy(e->cap, global_capability);
+ ast_format_cap_append_from_cap(e->cap, global_capability, AST_MEDIA_TYPE_UNKNOWN);
e->parent = gw;
e->ncs = ncs;
e->dtmfmode = dtmfmode;
@@ -4292,7 +4330,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
ast_mutex_init(&e->lock);
ast_mutex_init(&e->rqnt_queue_lock);
ast_mutex_init(&e->cmd_queue_lock);
- e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
ast_copy_string(e->name, v->value, sizeof(e->name));
e->needaudit = 1;
}
@@ -4314,7 +4352,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
e->parent = gw;
}
e->amaflags = amaflags;
- ast_format_cap_copy(e->cap, global_capability);
+ ast_format_cap_append_from_cap(e->cap, global_capability, AST_MEDIA_TYPE_UNKNOWN);
e->dtmfmode = dtmfmode;
e->ncs = ncs;
e->pktcgatealloc = pktcgatealloc;
@@ -4470,7 +4508,8 @@ static void mgcp_get_codec(struct ast_channel *chan, struct ast_format_cap *resu
{
struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
struct mgcp_endpoint *p = sub->parent;
- ast_format_cap_copy(result, p->cap);
+
+ ast_format_cap_append_from_cap(result, p->cap, AST_MEDIA_TYPE_UNKNOWN);
}
static struct ast_rtp_glue mgcp_rtp_glue = {
@@ -4556,7 +4595,7 @@ static void destroy_endpoint(struct mgcp_endpoint *e)
ast_mutex_destroy(&e->lock);
ast_mutex_destroy(&e->rqnt_queue_lock);
ast_mutex_destroy(&e->cmd_queue_lock);
- e->cap = ast_format_cap_destroy(e->cap);
+ ao2_ref(e->cap, -1);
ast_free(e);
}
@@ -4654,7 +4693,6 @@ static int reload_config(int reload)
char *cat;
struct ast_hostent ahp;
struct hostent *hp;
- struct ast_format format;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
if (gethostname(ourhost, sizeof(ourhost)-1)) {
@@ -4694,19 +4732,9 @@ static int reload_config(int reload)
memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
}
} else if (!strcasecmp(v->name, "allow")) {
- ast_getformatbyname(v->value, &format);
- if (!format.id) {
- ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
- } else {
- ast_format_cap_add(global_capability, &format);
- }
+ ast_format_cap_update_by_allow_disallow(global_capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
- ast_getformatbyname(v->value, &format);
- if (!format.id) {
- ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
- } else {
- ast_format_cap_remove(global_capability, &format);
- }
+ ast_format_cap_update_by_allow_disallow(global_capability, v->value, 0);
} else if (!strcasecmp(v->name, "tos")) {
if (ast_str2tos(v->value, &qos.tos)) {
ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
@@ -4831,36 +4859,44 @@ static int reload_config(int reload)
*/
static int load_module(void)
{
- struct ast_format tmpfmt;
-
- if (!(global_capability = ast_format_cap_alloc(0))) {
+ if (!(global_capability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- if (!(mgcp_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(mgcp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ ao2_ref(global_capability, -1);
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(global_capability, ast_format_ulaw, 0);
+ ast_format_cap_append(mgcp_tech.capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(mgcp_tech.capabilities, ast_format_alaw, 0);
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
if (!(io = io_context_create())) {
ast_log(LOG_WARNING, "Unable to create I/O context\n");
ast_sched_context_destroy(sched);
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
- if (reload_config(0))
+ if (reload_config(0)) {
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_DECLINE;
+ }
/* Make sure we can register our mgcp channel type */
if (ast_channel_register(&mgcp_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
io_context_destroy(io);
ast_sched_context_destroy(sched);
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
@@ -4973,8 +5009,10 @@ static int unload_module(void)
ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
ast_sched_context_destroy(sched);
- global_capability = ast_format_cap_destroy(global_capability);
- mgcp_tech.capabilities = ast_format_cap_destroy(mgcp_tech.capabilities);
+ ao2_ref(global_capability, -1);
+ global_capability = NULL;
+ ao2_ref(mgcp_tech.capabilities, -1);
+ mgcp_tech.capabilities = NULL;
return 0;
}
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 47d5947c3..0774e3c15 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -120,6 +120,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/pickup.h"
+#include "asterisk/format_cache.h"
#include "chan_misdn_config.h"
#include "isdn_lib.h"
@@ -691,9 +692,6 @@ static const char misdn_type[] = "mISDN";
static int tracing = 0;
-/*! \brief Only alaw and mulaw is allowed for now */
-static struct ast_format prefformat; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
-
static int *misdn_debug;
static int *misdn_debug_only;
static int max_ports;
@@ -7436,7 +7434,7 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
}
tmp->frame.frametype = AST_FRAME_VOICE;
- ast_format_set(&tmp->frame.subclass.format, AST_FORMAT_ALAW, 0);
+ tmp->frame.subclass.format = ast_format_alaw;
tmp->frame.datalen = len;
tmp->frame.samples = len;
tmp->frame.mallocd = 0;
@@ -7501,13 +7499,14 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
}
- if (!frame->subclass.format.id) {
+ if (!frame->subclass.format) {
chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
return 0;
}
- if (ast_format_cmp(&frame->subclass.format, &prefformat) == AST_FORMAT_CMP_NOT_EQUAL) {
- chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(&frame->subclass.format));
+ if (ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL) {
+ chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n",
+ ast_format_get_name(frame->subclass.format));
return 0;
}
@@ -8174,12 +8173,18 @@ static void update_name(struct ast_channel *tmp, int port, int c)
static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int port, int c)
{
+ struct ast_format_cap *native;
struct ast_channel *tmp;
char *cid_name = NULL;
char *cid_num = NULL;
int chan_offset = 0;
int tmp_port = misdn_cfg_get_next_port(0);
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+
+ native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!native) {
+ return NULL;
+ }
for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
if (tmp_port == port) {
@@ -8199,12 +8204,15 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char
if (tmp) {
chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
- ast_best_codec(cap, &tmpfmt);
- ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ ast_format_cap_append(native, ast_format_alaw, 0);
+ ast_channel_nativeformats_set(tmp, native);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+
+ ao2_ref(tmpfmt, -1);
/* Link the channel and private together */
chan_list_ref(chlist, "Give a reference to ast_channel");
@@ -8242,6 +8250,8 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char
chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
}
+ ao2_ref(native, -1);
+
return tmp;
}
@@ -10207,14 +10217,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ch->addr = bc->addr;
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmpfmt;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!(cap)) {
return RESPONSE_ERR;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(cap, ast_format_alaw, 0);
chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, NULL, bc->port, bc->channel);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
}
if (!chan) {
chan_list_unref(ch, "Failed to create a new channel");
@@ -10849,7 +10858,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
/* In Data Modes we queue frames */
memset(&frame, 0, sizeof(frame));
frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
- ast_format_set(&frame.subclass.format, AST_FORMAT_ALAW, 0);
+ frame.subclass.format = ast_format_alaw;
frame.datalen = bc->bframe_len;
frame.samples = bc->bframe_len;
frame.mallocd = 0;
@@ -11287,7 +11296,8 @@ static int unload_module(void)
#if defined(AST_MISDN_ENHANCEMENTS)
misdn_cc_destroy();
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
- misdn_tech.capabilities = ast_format_cap_destroy(misdn_tech.capabilities);
+ ao2_cleanup(misdn_tech.capabilities);
+ misdn_tech.capabilities = NULL;
return 0;
}
@@ -11316,11 +11326,10 @@ static int load_module(void)
};
- if (!(misdn_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(misdn_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_set(&prefformat, AST_FORMAT_ALAW, 0);
- ast_format_cap_add(misdn_tech.capabilities, &prefformat);
+ ast_format_cap_append(misdn_tech.capabilities, ast_format_alaw, 0);
max_ports = misdn_lib_maxports_get();
diff --git a/channels/chan_motif.c b/channels/chan_motif.c
index d853839ab..4b1d7d26b 100644
--- a/channels/chan_motif.c
+++ b/channels/chan_motif.c
@@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/abstract_jb.h"
#include "asterisk/xmpp.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<configInfo name="chan_motif" language="en_US">
@@ -286,7 +287,6 @@ struct jingle_endpoint {
iksrule *rule; /*!< Active matching rule */
unsigned int maxicecandidates; /*!< Maximum number of ICE candidates we will offer */
unsigned int maxpayloads; /*!< Maximum number of payloads we will offer */
- struct ast_codec_pref prefs; /*!< Codec preferences */
struct ast_format_cap *cap; /*!< Formats to use */
ast_group_t callgroup; /*!< Call group */
ast_group_t pickupgroup; /*!< Pickup group */
@@ -309,7 +309,6 @@ struct jingle_session {
char remote_original[XMPP_MAX_JIDLEN];/*!< Identifier of the original remote party (remote may have changed due to redirect) */
char remote[XMPP_MAX_JIDLEN]; /*!< Identifier of the remote party */
iksrule *rule; /*!< Session matching rule */
- struct ast_codec_pref prefs; /*!< Codec preferences */
struct ast_channel *owner; /*!< Master Channel */
struct ast_rtp_instance *rtp; /*!< RTP audio session */
struct ast_rtp_instance *vrtp; /*!< RTP video session */
@@ -454,8 +453,7 @@ static void jingle_endpoint_destructor(void *obj)
ast_xmpp_client_unref(endpoint->connection);
}
- ast_format_cap_destroy(endpoint->cap);
-
+ ao2_cleanup(endpoint->cap);
ao2_ref(endpoint->state, -1);
ast_string_field_free_memory(endpoint);
@@ -519,7 +517,7 @@ static void *jingle_endpoint_alloc(const char *cat)
ast_string_field_set(endpoint, name, cat);
- endpoint->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ endpoint->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
return endpoint;
@@ -583,9 +581,9 @@ static void jingle_session_destructor(void *obj)
ast_rtp_instance_destroy(session->vrtp);
}
- ast_format_cap_destroy(session->cap);
- ast_format_cap_destroy(session->jointcap);
- ast_format_cap_destroy(session->peercap);
+ ao2_cleanup(session->cap);
+ ao2_cleanup(session->jointcap);
+ ao2_cleanup(session->peercap);
if (session->callid) {
ast_callid_unref(session->callid);
@@ -681,7 +679,7 @@ static void jingle_enable_video(struct jingle_session *session)
}
/* If there are no configured video codecs do not turn video support on, it just won't work */
- if (!ast_format_cap_has_type(session->cap, AST_FORMAT_TYPE_VIDEO)) {
+ if (!ast_format_cap_has_type(session->cap, AST_MEDIA_TYPE_VIDEO)) {
return;
}
@@ -695,8 +693,8 @@ static void jingle_enable_video(struct jingle_session *session)
ast_rtp_instance_set_channel_id(session->vrtp, ast_channel_uniqueid(session->owner));
ast_channel_set_fd(session->owner, 2, ast_rtp_instance_fd(session->vrtp, 0));
ast_channel_set_fd(session->owner, 3, ast_rtp_instance_fd(session->vrtp, 1));
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->vrtp), session->vrtp, &session->prefs);
-
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(session->vrtp),
+ ast_format_cap_get_framing(session->cap));
if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
ice->stop(session->vrtp);
}
@@ -741,15 +739,15 @@ static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, con
session->connection = endpoint->connection;
session->transport = endpoint->transport;
- if (!(session->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
- !(session->jointcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
- !(session->peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
+ if (!(session->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(session->jointcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(session->peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
!session->callid) {
ao2_ref(session, -1);
return NULL;
}
- ast_format_cap_copy(session->cap, endpoint->cap);
+ ast_format_cap_append_from_cap(session->cap, endpoint->cap, AST_MEDIA_TYPE_UNKNOWN);
/* While we rely on res_xmpp for communication we still need a temporary ast_sockaddr to tell the RTP engine
* that we want IPv4 */
@@ -763,8 +761,6 @@ static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, con
ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_RTCP, 1);
ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_DTMF, 1);
- memcpy(&session->prefs, &endpoint->prefs, sizeof(session->prefs));
-
session->maxicecandidates = endpoint->maxicecandidates;
session->maxpayloads = endpoint->maxpayloads;
@@ -776,13 +772,20 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
{
struct ast_channel *chan;
const char *str = S_OR(title, session->remote);
- struct ast_format tmpfmt;
+ struct ast_format_cap *caps;
+ struct ast_format *tmpfmt;
+
+ if (!ast_format_cap_count(session->cap)) {
+ return NULL;
+ }
- if (ast_format_cap_is_empty(session->cap)) {
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
return NULL;
}
if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) {
+ ao2_ref(caps, -1);
return NULL;
}
@@ -794,15 +797,17 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
ast_channel_callid_set(chan, session->callid);
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->cap);
- ast_codec_choose(&session->prefs, session->cap, 1, &tmpfmt);
+ ast_format_cap_append_from_cap(caps, session->cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
if (session->rtp) {
struct ast_rtp_engine_ice *ice;
ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(session->rtp, 0));
ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(session->rtp, 1));
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->rtp), session->rtp, &session->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(session->rtp),
+ ast_format_cap_get_framing(session->cap));
if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
(session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
@@ -818,11 +823,12 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
ast_channel_adsicpe_set(chan, AST_ADSI_UNAVAILABLE);
- ast_best_codec(ast_channel_nativeformats(chan), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(chan), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &tmpfmt);
- ast_format_copy(ast_channel_readformat(chan), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(session->cap, 0);
+ ast_channel_set_writeformat(chan, tmpfmt);
+ ast_channel_set_rawwriteformat(chan, tmpfmt);
+ ast_channel_set_readformat(chan, tmpfmt);
+ ast_channel_set_rawreadformat(chan, tmpfmt);
+ ao2_ref(tmpfmt, -1);
ao2_lock(endpoint);
@@ -1300,30 +1306,24 @@ static void jingle_send_transport_info(struct jingle_session *session, const cha
}
/*! \brief Internal helper function which adds payloads to a description */
-static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_format_type type)
+static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_media_type type)
{
- struct ast_format format;
int x = 0, i = 0, res = 0;
- for (x = 0; (x < AST_CODEC_PREF_SIZE) && (i < (session->maxpayloads - 2)); x++) {
+ for (x = 0; (x < ast_format_cap_count(session->jointcap)) && (i < (session->maxpayloads - 2)); x++) {
+ struct ast_format *format = ast_format_cap_get_format(session->jointcap, x);
int rtp_code;
iks *payload;
char tmp[32];
- if (!ast_codec_pref_index(&session->prefs, x, &format)) {
- break;
- }
-
- if (AST_FORMAT_GET_TYPE(format.id) != type) {
- continue;
- }
-
- if (!ast_format_cap_iscompatible(session->jointcap, &format)) {
+ if (ast_format_get_type(format) != type) {
+ ao2_ref(format, -1);
continue;
}
- if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, &format, 0)) == -1) ||
+ if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, format, 0)) == -1) ||
(!(payload = iks_new("payload-type")))) {
+ ao2_ref(format, -1);
return -1;
}
@@ -1333,17 +1333,18 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st
snprintf(tmp, sizeof(tmp), "%d", rtp_code);
iks_insert_attrib(payload, "id", tmp);
- iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, &format, 0, 0));
+ iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
iks_insert_attrib(payload, "channels", "1");
- if ((format.id == AST_FORMAT_G722) && ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
+ if ((ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) &&
+ ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
iks_insert_attrib(payload, "clockrate", "16000");
} else {
- snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, &format, 0));
+ snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, format, 0));
iks_insert_attrib(payload, "clockrate", tmp);
}
- if ((type == AST_FORMAT_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
+ if ((type == AST_MEDIA_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
iks *parameter;
/* Google requires these parameters to be set, but alas we can not give accurate values so use some safe defaults */
@@ -1366,9 +1367,11 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st
iks_insert_node(description, payload);
payloads[i++] = payload;
+
+ ao2_ref(format, -1);
}
/* If this is for audio and there is room for RFC2833 add it in */
- if ((type == AST_FORMAT_TYPE_AUDIO) && (i < session->maxpayloads)) {
+ if ((type == AST_MEDIA_TYPE_AUDIO) && (i < session->maxpayloads)) {
iks *payload;
if ((payload = iks_new("payload-type"))) {
@@ -1390,7 +1393,7 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st
/*! \brief Helper function which adds content to a description */
static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *content, iks *description, iks *transport,
- const char *name, enum ast_format_type type, struct ast_rtp_instance *rtp, iks **payloads)
+ const char *name, enum ast_media_type type, struct ast_rtp_instance *rtp, iks **payloads)
{
int res = 0;
@@ -1400,9 +1403,9 @@ static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *
iks_insert_node(jingle, content);
iks_insert_attrib(description, "xmlns", JINGLE_RTP_NS);
- if (type == AST_FORMAT_TYPE_AUDIO) {
+ if (type == AST_MEDIA_TYPE_AUDIO) {
iks_insert_attrib(description, "media", "audio");
- } else if (type == AST_FORMAT_TYPE_VIDEO) {
+ } else if (type == AST_MEDIA_TYPE_VIDEO) {
iks_insert_attrib(description, "media", "video");
} else {
return -1;
@@ -1469,7 +1472,7 @@ static void jingle_send_session_action(struct jingle_session *session, const cha
if (session->rtp && (audio = iks_new("content")) && (audio_description = iks_new("description")) &&
(audio_transport = iks_new("transport"))) {
res = jingle_add_content(session, jingle, audio, audio_description, audio_transport, session->audio_name,
- AST_FORMAT_TYPE_AUDIO, session->rtp, audio_payloads);
+ AST_MEDIA_TYPE_AUDIO, session->rtp, audio_payloads);
} else {
ast_log(LOG_ERROR, "Failed to allocate audio content stanzas for session '%s', hanging up\n", session->sid);
res = -1;
@@ -1479,7 +1482,7 @@ static void jingle_send_session_action(struct jingle_session *session, const cha
if ((video = iks_new("content")) && (video_description = iks_new("description")) &&
(video_transport = iks_new("transport"))) {
res = jingle_add_content(session, jingle, video, video_description, video_transport, session->video_name,
- AST_FORMAT_TYPE_VIDEO, session->vrtp, video_payloads);
+ AST_MEDIA_TYPE_VIDEO, session->vrtp, video_payloads);
} else {
ast_log(LOG_ERROR, "Failed to allocate video content stanzas for session '%s', hanging up\n", session->sid);
res = -1;
@@ -1668,17 +1671,24 @@ static struct ast_frame *jingle_read(struct ast_channel *ast)
}
if (frame && frame->frametype == AST_FRAME_VOICE &&
- !ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format)) {
- if (!ast_format_cap_iscompatible(session->jointcap, &frame->subclass.format)) {
+ ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cap_iscompatible_format(session->jointcap, frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
- ast_getformatname(&frame->subclass.format), ast_channel_name(ast));
+ ast_format_get_name(frame->subclass.format), ast_channel_name(ast));
ast_frfree(frame);
frame = &ast_null_frame;
} else {
+ struct ast_format_cap *caps;
+
ast_debug(1, "Oooh, format changed to %s\n",
- ast_getformatname(&frame->subclass.format));
- ast_format_cap_remove_bytype(ast_channel_nativeformats(ast), AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(ast_channel_nativeformats(ast), &frame->subclass.format);
+ ast_format_get_name(frame->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, frame->subclass.format, 0);
+ ast_channel_nativeformats_set(ast, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(ast, ast_channel_readformat(ast));
ast_set_write_format(ast, ast_channel_writeformat(ast));
}
@@ -1692,17 +1702,18 @@ static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
{
struct jingle_session *session = ast_channel_tech_pvt(ast);
int res = 0;
- char buf[256];
switch (frame->frametype) {
case AST_FRAME_VOICE:
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return 0;
}
if (session && session->rtp) {
@@ -1845,7 +1856,7 @@ static int jingle_call(struct ast_channel *ast, const char *dest, int timeout)
ast_setstate(ast, AST_STATE_RING);
/* Since we have no idea of the remote capabilities use ours for now */
- ast_format_cap_copy(session->jointcap, session->cap);
+ ast_format_cap_append_from_cap(session->jointcap, session->cap, AST_MEDIA_TYPE_UNKNOWN);
/* We set up a hook so we can know when our session-initiate message was accepted or rejected */
session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
@@ -1908,7 +1919,7 @@ static struct ast_channel *jingle_request(const char *type, struct ast_format_ca
);
/* We require at a minimum one audio format to be requested */
- if (!ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO)) {
+ if (!ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO)) {
ast_log(LOG_ERROR, "Motif channel driver requires an audio format when dialing a destination\n");
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
return NULL;
@@ -2001,7 +2012,7 @@ static struct ast_channel *jingle_request(const char *type, struct ast_format_ca
}
/* If video was requested try to enable it on the session */
- if (ast_format_cap_has_type(cap, AST_FORMAT_TYPE_VIDEO)) {
+ if (ast_format_cap_has_type(cap, AST_MEDIA_TYPE_VIDEO)) {
jingle_enable_video(session);
}
@@ -2043,8 +2054,8 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
ast_string_field_set(session, audio_name, name);
}
*rtp = session->rtp;
- ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_remove_by_type(session->peercap, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_remove_by_type(session->jointcap, AST_MEDIA_TYPE_AUDIO);
} else if (!strcasecmp(media, "video")) {
if (!ast_strlen_zero(name)) {
ast_string_field_set(session, video_name, name);
@@ -2060,8 +2071,8 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
return -1;
}
- ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_VIDEO);
- ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_VIDEO);
+ ast_format_cap_remove_by_type(session->peercap, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_remove_by_type(session->jointcap, AST_MEDIA_TYPE_VIDEO);
} else {
/* Unknown media type */
jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
@@ -2082,8 +2093,6 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
int rtp_id, rtp_clockrate;
if (!ast_strlen_zero(id) && !ast_strlen_zero(name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
- ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, rtp_id);
-
if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) {
ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, name, 0, rtp_clockrate);
} else {
@@ -2093,9 +2102,9 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
}
ast_rtp_codecs_payload_formats(&codecs, session->peercap, &othercapability);
- ast_format_cap_joint_append(session->cap, session->peercap, session->jointcap);
+ ast_format_cap_get_compatible(session->cap, session->peercap, session->jointcap);
- if (ast_format_cap_is_empty(session->jointcap)) {
+ if (!ast_format_cap_count(session->jointcap)) {
/* We have no compatible codecs, so terminate the session appropriately */
jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
ast_rtp_codecs_payloads_destroy(&codecs);
@@ -2355,12 +2364,20 @@ static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
}
if ((chan = jingle_session_lock_full(session))) {
- struct ast_format fmt;
+ struct ast_format_cap *caps;
+ struct ast_format *fmt;
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append_from_cap(caps, session->jointcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
+ }
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->jointcap);
- ast_codec_choose(&session->prefs, session->jointcap, 1, &fmt);
- ast_set_read_format(chan, &fmt);
- ast_set_write_format(chan, &fmt);
+ fmt = ast_format_cap_get_format(session->jointcap, 0);
+ ast_set_read_format(chan, fmt);
+ ast_set_write_format(chan, fmt);
+ ao2_ref(fmt, -1);
ast_channel_unlock(chan);
ast_channel_unref(chan);
@@ -2710,7 +2727,7 @@ static int custom_transport_handler(const struct aco_option *opt, struct ast_var
*/
static int load_module(void)
{
- if (!(jingle_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(jingle_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -2726,8 +2743,8 @@ static int load_module(void)
aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass));
aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot));
aco_option_register(&cfg_info, "accountcode", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, accountcode));
- aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, prefs, cap));
- aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, prefs, cap));
+ aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, cap));
+ aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, cap));
aco_option_register_custom(&cfg_info, "connection", ACO_EXACT, endpoint_options, NULL, custom_connection_handler, 0);
aco_option_register_custom(&cfg_info, "transport", ACO_EXACT, endpoint_options, NULL, custom_transport_handler, 0);
aco_option_register(&cfg_info, "maxicecandidates", ACO_EXACT, endpoint_options, DEFAULT_MAX_ICE_CANDIDATES, OPT_UINT_T, PARSE_DEFAULT,
@@ -2735,9 +2752,10 @@ static int load_module(void)
aco_option_register(&cfg_info, "maxpayloads", ACO_EXACT, endpoint_options, DEFAULT_MAX_PAYLOADS, OPT_UINT_T, PARSE_DEFAULT,
FLDSET(struct jingle_endpoint, maxpayloads), DEFAULT_MAX_PAYLOADS);
- ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_append_by_type(jingle_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
if (aco_process_config(&cfg_info, 0)) {
+ ao2_ref(jingle_tech.capabilities, -1);
ast_log(LOG_ERROR, "Unable to read config file motif.conf. Module loaded but not running.\n");
aco_info_destroy(&cfg_info);
return AST_MODULE_LOAD_DECLINE;
@@ -2763,6 +2781,7 @@ static int load_module(void)
return 0;
end:
+ ao2_cleanup(jingle_tech.capabilities);
ast_rtp_glue_unregister(&jingle_rtp_glue);
if (sched) {
@@ -2784,7 +2803,7 @@ static int reload(void)
static int unload_module(void)
{
ast_channel_unregister(&jingle_tech);
- ast_format_cap_destroy(jingle_tech.capabilities);
+ ao2_cleanup(jingle_tech.capabilities);
jingle_tech.capabilities = NULL;
ast_rtp_glue_unregister(&jingle_rtp_glue);
ast_sched_context_destroy(sched);
diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c
index 730b2f459..ae6022cb6 100644
--- a/channels/chan_multicast_rtp.c
+++ b/channels/chan_multicast_rtp.c
@@ -117,8 +117,10 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo
struct ast_sockaddr control_address;
struct ast_sockaddr destination_address;
struct ast_channel *chan;
- struct ast_format fmt;
- ast_best_codec(cap, &fmt);
+ struct ast_format_cap *caps = NULL;
+ struct ast_format *fmt = NULL;
+
+ fmt = ast_format_cap_get_format(cap, 0);
ast_sockaddr_setnull(&control_address);
@@ -145,6 +147,11 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo
goto failure;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ goto failure;
+ }
+
if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, multicast_type))) {
goto failure;
}
@@ -158,19 +165,25 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo
ast_channel_tech_set(chan, &multicast_rtp_tech);
- ast_format_cap_add(ast_channel_nativeformats(chan), &fmt);
- ast_format_copy(ast_channel_writeformat(chan), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
- ast_format_copy(ast_channel_readformat(chan), &fmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
+ ast_format_cap_append(caps, fmt, 0);
+ ast_channel_nativeformats_set(chan, caps);
+ ast_channel_set_writeformat(chan, fmt);
+ ast_channel_set_rawwriteformat(chan, fmt);
+ ast_channel_set_readformat(chan, fmt);
+ ast_channel_set_rawreadformat(chan, fmt);
ast_channel_tech_pvt_set(chan, instance);
ast_channel_unlock(chan);
+ ao2_ref(fmt, -1);
+ ao2_ref(caps, -1);
+
return chan;
failure:
+ ao2_cleanup(fmt);
+ ao2_cleanup(caps);
*cause = AST_CAUSE_FAILURE;
return NULL;
}
@@ -178,12 +191,14 @@ failure:
/*! \brief Function called when our module is loaded */
static int load_module(void)
{
- if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all(multicast_rtp_tech.capabilities);
+ ast_format_cap_append_by_type(multicast_rtp_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (ast_channel_register(&multicast_rtp_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n");
+ ao2_ref(multicast_rtp_tech.capabilities, -1);
+ multicast_rtp_tech.capabilities = NULL;
return AST_MODULE_LOAD_DECLINE;
}
@@ -194,7 +209,8 @@ static int load_module(void)
static int unload_module(void)
{
ast_channel_unregister(&multicast_rtp_tech);
- multicast_rtp_tech.capabilities = ast_format_cap_destroy(multicast_rtp_tech.capabilities);
+ ao2_ref(multicast_rtp_tech.capabilities, -1);
+ multicast_rtp_tech.capabilities = NULL;
return 0;
}
diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c
index cbfb6b3c4..1be9bffeb 100644
--- a/channels/chan_nbs.c
+++ b/channels/chan_nbs.c
@@ -47,12 +47,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
+#include "asterisk/format_cache.h"
static const char tdesc[] = "Network Broadcast Sound Driver";
-/* Only linear is allowed */
-static struct ast_format prefformat;
-
static char context[AST_MAX_EXTENSION] = "default";
static const char type[] = "NBS";
@@ -63,7 +61,6 @@ struct nbs_pvt {
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
char app[16]; /* Our app */
char stream[80]; /* Our stream */
- struct ast_frame fr; /* "null" frame */
struct ast_module_user *u; /*! for holding a reference to this module */
};
@@ -178,37 +175,14 @@ static int nbs_hangup(struct ast_channel *ast)
static struct ast_frame *nbs_xread(struct ast_channel *ast)
{
- struct nbs_pvt *p = ast_channel_tech_pvt(ast);
-
-
- /* Some nice norms */
- p->fr.datalen = 0;
- p->fr.samples = 0;
- p->fr.data.ptr = NULL;
- p->fr.src = type;
- p->fr.offset = 0;
- p->fr.mallocd=0;
- p->fr.delivery.tv_sec = 0;
- p->fr.delivery.tv_usec = 0;
-
ast_debug(1, "Returning null frame on %s\n", ast_channel_name(ast));
- return &p->fr;
+ return &ast_null_frame;
}
static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
{
struct nbs_pvt *p = ast_channel_tech_pvt(ast);
- /* Write a frame of (presumably voice) data */
- if (frame->frametype != AST_FRAME_VOICE) {
- if (frame->frametype != AST_FRAME_IMAGE)
- ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
- return 0;
- }
- if (frame->subclass.format.id != (AST_FORMAT_SLINEAR)) {
- ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
- return 0;
- }
if (ast_channel_state(ast) != AST_STATE_UP) {
/* Don't try tos end audio on-hook */
return 0;
@@ -226,11 +200,11 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const struct as
ast_channel_tech_set(tmp, &nbs_tech);
ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs));
- ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat);
- ast_format_copy(ast_channel_rawreadformat(tmp), &prefformat);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &prefformat);
- ast_format_copy(ast_channel_writeformat(tmp), &prefformat);
- ast_format_copy(ast_channel_readformat(tmp), &prefformat);
+ ast_channel_nativeformats_set(tmp, nbs_tech.capabilities);
+ ast_channel_set_rawreadformat(tmp, ast_format_slin);
+ ast_channel_set_rawwriteformat(tmp, ast_format_slin);
+ ast_channel_set_writeformat(tmp, ast_format_slin);
+ ast_channel_set_readformat(tmp, ast_format_slin);
if (state == AST_STATE_RING)
ast_channel_rings_set(tmp, 1);
ast_channel_tech_pvt_set(tmp, i);
@@ -257,9 +231,11 @@ static struct ast_channel *nbs_request(const char *type, struct ast_format_cap *
struct nbs_pvt *p;
struct ast_channel *tmp = NULL;
- if (!(ast_format_cap_iscompatible(cap, &prefformat))) {
- char tmp[256];
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
+ ast_format_cap_get_names(cap, &cap_buf));
return NULL;
}
p = nbs_alloc(data);
@@ -275,17 +251,17 @@ static int unload_module(void)
{
/* First, take us out of the channel loop */
ast_channel_unregister(&nbs_tech);
- nbs_tech.capabilities = ast_format_cap_destroy(nbs_tech.capabilities);
+ ao2_ref(nbs_tech.capabilities, -1);
+ nbs_tech.capabilities = NULL;
return 0;
}
static int load_module(void)
{
- ast_format_set(&prefformat, AST_FORMAT_SLINEAR, 0);
- if (!(nbs_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(nbs_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(nbs_tech.capabilities, &prefformat);
+ ast_format_cap_append(nbs_tech.capabilities, ast_format_slin, 0);
/* Make sure we can register our channel type */
if (ast_channel_register(&nbs_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 4459b4b6f..46b751d7c 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -69,6 +69,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/bridge.h"
+#include "asterisk/format_cache.h"
#include "console_video.h"
@@ -726,7 +727,7 @@ static struct ast_frame *oss_read(struct ast_channel *c)
return f;
/* ok we can build and deliver the frame to the caller */
f->frametype = AST_FRAME_VOICE;
- ast_format_set(&f->subclass.format, AST_FORMAT_SLINEAR, 0);
+ f->subclass.format = ao2_bump(ast_format_slin);
f->samples = FRAME_SIZE;
f->datalen = FRAME_SIZE * 2;
f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET;
@@ -804,9 +805,9 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
setformat(o, O_RDWR);
ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
- ast_format_set(ast_channel_readformat(c), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_writeformat(c), AST_FORMAT_SLINEAR, 0);
- ast_format_cap_add(ast_channel_nativeformats(c), ast_channel_readformat(c));
+ ast_channel_set_readformat(c, ast_format_slin);
+ ast_channel_set_writeformat(c, ast_format_slin);
+ ast_channel_nativeformats_set(c, oss_tech.capabilities);
/* if the console makes the call, add video to the offer */
/* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER
@@ -851,8 +852,6 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap *
AST_APP_ARG(flags);
);
char *parse = ast_strdupa(data);
- char buf[256];
- struct ast_format tmpfmt;
AST_NONSTANDARD_APP_ARGS(args, parse, '/');
o = find_desc(args.name);
@@ -863,8 +862,9 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap *
/* XXX we could default to 'dsp' perhaps ? */
return NULL;
}
- if (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)))) {
- ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
if (o->owner) {
@@ -1452,7 +1452,6 @@ static int load_module(void)
struct ast_config *cfg = NULL;
char *ctg = NULL;
struct ast_flags config_flags = { 0 };
- struct ast_format tmpfmt;
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
@@ -1482,7 +1481,7 @@ static int load_module(void)
if (!(oss_tech.capabilities = ast_format_cap_alloc(0))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(oss_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(oss_tech.capabilities, ast_format_slin, 0);
/* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER
* add console_video_formats to oss_tech.capabilities once this occurs. */
@@ -1517,7 +1516,9 @@ static int unload_module(void)
ast_free(o);
o = next;
}
- oss_tech.capabilities = ast_format_cap_destroy(oss_tech.capabilities);
+ ao2_cleanup(oss_tech.capabilities);
+ oss_tech.capabilities = NULL;
+
return 0;
}
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 1e5e19d57..72f38291b 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -67,6 +67,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
#include "chan_phone.h"
@@ -134,8 +136,8 @@ static struct phone_pvt {
int fd; /* Raw file descriptor for this device */
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
int mode; /* Is this in the */
- struct ast_format lastformat; /* Last output format */
- struct ast_format lastinput; /* Last input format */
+ struct ast_format *lastformat; /* Last output format */
+ struct ast_format *lastinput; /* Last input format */
int ministate; /* Miniature state, for dialtone mode */
char dev[256]; /* Device name */
struct phone_pvt *next; /* Next channel in list */
@@ -218,7 +220,8 @@ static int phone_indicate(struct ast_channel *chan, int condition, const void *d
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
usleep(320000);
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
- ast_format_clear(&p->lastformat);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
res = 0;
break;
case AST_CONTROL_HOLD:
@@ -282,7 +285,8 @@ static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int dur
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
usleep(320000);
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
- ast_format_clear(&p->lastformat);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
return 0;
default:
ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
@@ -290,7 +294,8 @@ static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int dur
}
ast_debug(1, "Dialed %d\n", outdigit);
ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
- ast_format_clear(&p->lastformat);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
return 0;
}
@@ -381,8 +386,10 @@ static int phone_hangup(struct ast_channel *ast)
ioctl(p->fd, PHONE_BUSY);
p->cpt = 1;
}
- ast_format_clear(&p->lastformat);
- ast_format_clear(&p->lastinput);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
+ ao2_cleanup(p->lastinput);
+ p->lastinput = NULL;
p->ministate = 0;
p->obuflen = 0;
p->dialtone = 0;
@@ -402,38 +409,38 @@ static int phone_setup(struct ast_channel *ast)
p = ast_channel_tech_pvt(ast);
ioctl(p->fd, PHONE_CPT_STOP);
/* Nothing to answering really, just start recording */
- if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_G729A) {
+ if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
/* Prefer g729 */
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_G729A) {
- ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_g729) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_g729);
if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
ast_log(LOG_WARNING, "Failed to set codec to g729\n");
return -1;
}
}
- } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_G723_1) {
+ } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_G723_1) {
- ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_g723) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_g723);
if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
return -1;
}
}
- } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
+ } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_SLINEAR) {
- ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_slin);
if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
return -1;
}
}
- } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) {
+ } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_ULAW) {
- ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_ulaw);
if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
ast_log(LOG_WARNING, "Failed to set codec to uLaw\n");
return -1;
@@ -441,16 +448,16 @@ static int phone_setup(struct ast_channel *ast)
}
} else if (p->mode == MODE_FXS) {
ioctl(p->fd, PHONE_REC_STOP);
- if (ast_format_cmp(&p->lastinput, ast_channel_rawreadformat(ast)) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_format_copy(&p->lastinput, ast_channel_rawreadformat(ast));
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_channel_rawreadformat(ast)) == AST_FORMAT_CMP_NOT_EQUAL)) {
+ ao2_replace(p->lastinput, ast_channel_rawreadformat(ast));
if (ioctl(p->fd, PHONE_REC_CODEC, ast_channel_rawreadformat(ast))) {
ast_log(LOG_WARNING, "Failed to set codec to %s\n",
- ast_getformatname(ast_channel_rawreadformat(ast)));
+ ast_format_get_name(ast_channel_rawreadformat(ast)));
return -1;
}
}
} else {
- ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
+ ast_log(LOG_WARNING, "Can't do format %s\n", ast_format_get_name(ast_channel_rawreadformat(ast)));
return -1;
}
if (ioctl(p->fd, PHONE_REC_START)) {
@@ -601,13 +608,13 @@ static struct ast_frame *phone_read(struct ast_channel *ast)
}
p->fr.samples = 240;
p->fr.datalen = res;
- p->fr.frametype = AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_AUDIO ?
- AST_FRAME_VOICE : AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_IMAGE ?
+ p->fr.frametype = ast_format_get_type(p->lastinput) == AST_MEDIA_TYPE_AUDIO ?
+ AST_FRAME_VOICE : ast_format_get_type(p->lastinput) == AST_MEDIA_TYPE_IMAGE ?
AST_FRAME_IMAGE : AST_FRAME_VIDEO;
- ast_format_copy(&p->fr.subclass.format, &p->lastinput);
+ p->fr.subclass.format = p->lastinput;
p->fr.offset = AST_FRIENDLY_OFFSET;
/* Byteswap from little-endian to native-endian */
- if (p->fr.subclass.format.id == AST_FORMAT_SLINEAR)
+ if (ast_format_cmp(p->fr.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
ast_frame_byteswap_le(&p->fr);
return &p->fr;
}
@@ -669,14 +676,6 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
return 0;
}
- if (!(frame->subclass.format.id == AST_FORMAT_G723_1 ||
- frame->subclass.format.id == AST_FORMAT_SLINEAR ||
- frame->subclass.format.id == AST_FORMAT_ULAW ||
- frame->subclass.format.id == AST_FORMAT_G729A) &&
- p->mode != MODE_FXS) {
- ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
- return -1;
- }
#if 0
/* If we're not in up mode, go into up mode now */
if (ast->_state != AST_STATE_UP) {
@@ -689,8 +688,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
#endif
- if (frame->subclass.format.id == AST_FORMAT_G729A) {
- if (p->lastformat.id != AST_FORMAT_G729A) {
+ if (ast_format_cmp(frame->subclass.format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_g729) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) {
@@ -701,8 +700,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set G729 mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_G729A, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0);
+ ao2_replace(p->lastformat, ast_format_g729);
+ ao2_replace(p->lastinput, ast_format_g729);
/* Reset output buffer */
p->obuflen = 0;
codecset = 1;
@@ -712,8 +711,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
return -1;
}
maxfr = 80;
- } else if (frame->subclass.format.id == AST_FORMAT_G723_1) {
- if (p->lastformat.id != AST_FORMAT_G723_1) {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_g723) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
@@ -724,8 +723,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_G723_1, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0);
+ ao2_replace(p->lastformat, ast_format_g723);
+ ao2_replace(p->lastinput, ast_format_g723);
/* Reset output buffer */
p->obuflen = 0;
codecset = 1;
@@ -735,8 +734,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
return -1;
}
maxfr = 24;
- } else if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
- if (p->lastformat.id != AST_FORMAT_SLINEAR) {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
@@ -747,15 +746,15 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0);
+ ao2_replace(p->lastformat, ast_format_slin);
+ ao2_replace(p->lastinput, ast_format_slin);
codecset = 1;
/* Reset output buffer */
p->obuflen = 0;
}
maxfr = 480;
- } else if (frame->subclass.format.id == AST_FORMAT_ULAW) {
- if (p->lastformat.id != AST_FORMAT_ULAW) {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
@@ -766,29 +765,29 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_ULAW, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0);
+ ao2_replace(p->lastformat, ast_format_ulaw);
+ ao2_replace(p->lastinput, ast_format_ulaw);
codecset = 1;
/* Reset output buffer */
p->obuflen = 0;
}
maxfr = 240;
} else {
- if (ast_format_cmp(&p->lastformat, &frame->subclass.format) != AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, frame->subclass.format) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
- if (ioctl(p->fd, PHONE_PLAY_CODEC, (int) frame->subclass.format.id)) {
+ if (ioctl(p->fd, PHONE_PLAY_CODEC, ast_format_compatibility_format2bitfield(frame->subclass.format))) {
ast_log(LOG_WARNING, "Unable to set %s mode\n",
- ast_getformatname(&frame->subclass.format));
+ ast_format_get_name(frame->subclass.format));
return -1;
}
- if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.format.id)) {
+ if (ioctl(p->fd, PHONE_REC_CODEC, ast_format_compatibility_format2bitfield(frame->subclass.format))) {
ast_log(LOG_WARNING, "Unable to set %s mode\n",
- ast_getformatname(&frame->subclass.format));
+ ast_format_get_name(frame->subclass.format));
return -1;
}
- ast_format_copy(&p->lastformat, &frame->subclass.format);
- ast_format_copy(&p->lastinput, &frame->subclass.format);
+ ao2_replace(p->lastformat, frame->subclass.format);
+ ao2_replace(p->lastinput, frame->subclass.format);
codecset = 1;
/* Reset output buffer */
p->obuflen = 0;
@@ -857,11 +856,13 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps = NULL;
struct ast_channel *tmp;
struct phone_codec_data queried_codec;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, assignedids, requestor, 0, "Phone/%s", i->dev + 5);
- if (tmp) {
+ if (tmp && caps) {
ast_channel_lock(tmp);
ast_channel_tech_set(tmp, cur_tech);
ast_channel_set_fd(tmp, 0, i->fd);
@@ -869,18 +870,20 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
if (i->mode == MODE_FXS &&
ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) {
if (queried_codec.type == LINEAR16) {
- ast_format_cap_add(ast_channel_nativeformats(tmp), ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_format_cap_append(caps, ast_format_slin, 0);
} else {
- ast_format_cap_remove(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_remove(prefcap, ast_format_slin);
+ ast_format_cap_append_from_cap(caps, prefcap, AST_MEDIA_TYPE_UNKNOWN);
}
} else {
- ast_format_cap_copy(ast_channel_nativeformats(tmp), prefcap);
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_format_cap_append_from_cap(caps, prefcap, AST_MEDIA_TYPE_UNKNOWN);
}
+ tmpfmt = ast_format_cap_get_format(caps, 0);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
/* no need to call ast_setstate: the channel_alloc already did its job */
if (state == AST_STATE_RING)
ast_channel_rings_set(tmp, 1);
@@ -913,8 +916,10 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
ast_hangup(tmp);
}
}
- } else
+ } else {
+ ao2_cleanup(caps);
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ }
return tmp;
}
@@ -989,7 +994,8 @@ static void phone_check_exception(struct phone_pvt *i)
ioctl(i->fd, PHONE_PLAY_STOP);
ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
ioctl(i->fd, PHONE_PLAY_START);
- ast_format_clear(&i->lastformat);
+ ao2_cleanup(i->lastformat);
+ i->lastformat = NULL;
} else if (i->mode == MODE_SIGMA) {
ast_module_ref(ast_module_info->self);
/* Reset the extension */
@@ -1010,7 +1016,8 @@ static void phone_check_exception(struct phone_pvt *i)
ioctl(i->fd, PHONE_PLAY_STOP);
ioctl(i->fd, PHONE_REC_STOP);
i->dialtone = 0;
- ast_format_clear(&i->lastformat);
+ ao2_cleanup(i->lastformat);
+ i->lastformat = NULL;
}
}
if (phonee.bits.pstn_ring) {
@@ -1222,8 +1229,10 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai
flags = fcntl(tmp->fd, F_GETFL);
fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
tmp->owner = NULL;
- ast_format_clear(&tmp->lastformat);
- ast_format_clear(&tmp->lastinput);
+ ao2_cleanup(tmp->lastformat);
+ tmp->lastformat = NULL;
+ ao2_cleanup(tmp->lastinput);
+ tmp->lastinput = NULL;
tmp->ministate = 0;
memset(tmp->ext, 0, sizeof(tmp->ext));
ast_copy_string(tmp->language, language, sizeof(tmp->language));
@@ -1256,7 +1265,7 @@ static struct ast_channel *phone_request(const char *type, struct ast_format_cap
}
p = iflist;
while(p) {
- if (p->mode == MODE_FXS || (ast_format_cap_has_joint(cap, phone_tech.capabilities))) {
+ if (p->mode == MODE_FXS || (ast_format_cap_iscompatible(cap, phone_tech.capabilities))) {
size_t length = strlen(p->dev + 5);
if (strncmp(name, p->dev + 5, length) == 0 &&
!isalnum(name[length])) {
@@ -1272,9 +1281,10 @@ static struct ast_channel *phone_request(const char *type, struct ast_format_cap
ast_mutex_unlock(&iflock);
restart_monitor();
if (tmp == NULL) {
- if (!(ast_format_cap_has_joint(cap, phone_tech.capabilities))) {
- char buf[256];
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (!(ast_format_cap_iscompatible(cap, phone_tech.capabilities))) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
+ ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
}
@@ -1357,9 +1367,10 @@ static int __unload_module(void)
return -1;
}
- phone_tech.capabilities = ast_format_cap_destroy(phone_tech.capabilities);
- phone_tech_fxs.capabilities = ast_format_cap_destroy(phone_tech_fxs.capabilities);
- prefcap = ast_format_cap_destroy(prefcap);
+ ao2_ref(phone_tech.capabilities, -1);
+ ao2_ref(phone_tech_fxs.capabilities, -1);
+ ao2_ref(prefcap, -1);
+
return 0;
}
@@ -1376,21 +1387,21 @@ static int load_module(void)
int mode = MODE_IMMEDIATE;
int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */
struct ast_flags config_flags = { 0 };
- struct ast_format tmpfmt;
- if (!(phone_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(phone_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0));
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0));
- if (!(prefcap = ast_format_cap_alloc(0))) {
+ ast_format_cap_append(phone_tech.capabilities, ast_format_g723, 0);
+ ast_format_cap_append(phone_tech.capabilities, ast_format_slin, 0);
+ ast_format_cap_append(phone_tech.capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(phone_tech.capabilities, ast_format_g729, 0);
+
+ if (!(prefcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_copy(prefcap, phone_tech.capabilities);
- if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc(0))) {
+ ast_format_cap_append_from_cap(prefcap, phone_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
+ if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -1440,7 +1451,7 @@ static int load_module(void)
mode = MODE_IMMEDIATE;
else if (!strncasecmp(v->value, "fxs", 3)) {
mode = MODE_FXS;
- ast_format_cap_remove_bytype(prefcap, AST_FORMAT_TYPE_AUDIO); /* All non-voice */
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_AUDIO); /* All non-voice */
}
else if (!strncasecmp(v->value, "fx", 2))
mode = MODE_FXO;
@@ -1450,18 +1461,21 @@ static int load_module(void)
ast_copy_string(context, v->value, sizeof(context));
} else if (!strcasecmp(v->name, "format")) {
if (!strcasecmp(v->value, "g729")) {
- ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0));
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_g729, 0);
} else if (!strcasecmp(v->value, "g723.1")) {
- ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0));
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_g723, 0);
} else if (!strcasecmp(v->value, "slinear")) {
- ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0);
if (mode == MODE_FXS) {
- ast_format_cap_add(prefcap, &tmpfmt);
+ ast_format_cap_append(prefcap, ast_format_slin, 0);
} else {
- ast_format_cap_set(prefcap, &tmpfmt);
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_slin, 0);
}
} else if (!strcasecmp(v->value, "ulaw")) {
- ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_ulaw, 0);
} else
ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
} else if (!strcasecmp(v->name, "echocancel")) {
@@ -1485,7 +1499,7 @@ static int load_module(void)
ast_mutex_unlock(&iflock);
if (mode == MODE_FXS) {
- ast_format_cap_copy(phone_tech_fxs.capabilities, prefcap);
+ ast_format_cap_append_from_cap(phone_tech_fxs.capabilities, prefcap, AST_MEDIA_TYPE_UNKNOWN);
cur_tech = &phone_tech_fxs;
} else
cur_tech = (struct ast_channel_tech *) &phone_tech;
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 695211480..5812360c5 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/indications.h"
+#include "asterisk/format_cache.h"
#include "asterisk/threadstorage.h"
#include "asterisk/features_config.h"
#include "asterisk/pickup.h"
@@ -210,7 +211,7 @@ static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
- ast_format_cap_copy(result, channel->session->endpoint->media.codecs);
+ ast_format_cap_append_from_cap(result, channel->session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
}
static int send_direct_media_request(void *data)
@@ -325,8 +326,9 @@ static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
return 0;
}
- if (cap && !ast_format_cap_is_empty(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) {
- ast_format_cap_copy(session->direct_media_cap, cap);
+ if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) {
+ ast_format_cap_remove_by_type(session->direct_media_cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(session->direct_media_cap, cap, AST_MEDIA_TYPE_UNKNOWN);
changed = 1;
}
@@ -355,7 +357,8 @@ static struct ast_rtp_glue chan_pjsip_rtp_glue = {
static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int state, const char *exten, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
{
struct ast_channel *chan;
- struct ast_format fmt;
+ struct ast_format_cap *caps;
+ struct ast_format *fmt;
RAII_VAR(struct chan_pjsip_pvt *, pvt, NULL, ao2_cleanup);
struct ast_sip_channel_pvt *channel;
struct ast_variable *var;
@@ -363,19 +366,21 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
if (!(pvt = ao2_alloc(sizeof(*pvt), chan_pjsip_pvt_dtor))) {
return NULL;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
-
- chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""),
- session->endpoint->accountcode, "", "", assignedids,
- requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint),
- (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1));
- if (!chan) {
+ if (!(chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), session->endpoint->accountcode, "", "", assignedids, requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint),
+ (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)))) {
+ ao2_ref(caps, -1);
return NULL;
}
ast_channel_tech_set(chan, &chan_pjsip_tech);
if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) {
+ ao2_ref(caps, -1);
ast_channel_unlock(chan);
ast_hangup(chan);
return NULL;
@@ -391,17 +396,21 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
ast_channel_tech_pvt_set(chan, channel);
- if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) {
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->endpoint->media.codecs);
+ if (!ast_format_cap_count(session->req_caps) ||
+ !ast_format_cap_iscompatible(session->req_caps, session->endpoint->media.codecs)) {
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
} else {
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->req_caps);
+ ast_format_cap_append_from_cap(caps, session->req_caps, AST_MEDIA_TYPE_UNKNOWN);
}
- ast_codec_choose(&session->endpoint->media.prefs, ast_channel_nativeformats(chan), 1, &fmt);
- ast_format_copy(ast_channel_writeformat(chan), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
- ast_format_copy(ast_channel_readformat(chan), &fmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
+ ast_channel_nativeformats_set(chan, caps);
+ fmt = ast_format_cap_get_format(caps, 0);
+ ast_channel_set_writeformat(chan, fmt);
+ ast_channel_set_rawwriteformat(chan, fmt);
+ ast_channel_set_readformat(chan, fmt);
+ ast_channel_set_rawreadformat(chan, fmt);
+ ao2_ref(fmt, -1);
+ ao2_ref(caps, -1);
if (state == AST_STATE_RING) {
ast_channel_rings_set(chan, 1);
@@ -584,9 +593,18 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
return f;
}
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
- ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(ast, caps);
+ ao2_ref(caps, -1);
+ }
+
ast_set_read_format(ast, ast_channel_readformat(ast));
ast_set_write_format(ast, ast_channel_writeformat(ast));
}
@@ -623,15 +641,15 @@ static int chan_pjsip_write(struct ast_channel *ast, struct ast_frame *frame)
if (!media) {
return 0;
}
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char buf[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return 0;
}
if (media->rtp) {
@@ -1127,10 +1145,8 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
if (media && media->rtp) {
/* FIXME: Only use this for VP8. Additional work would have to be done to
* fully support other video codecs */
- struct ast_format_cap *fcap = ast_channel_nativeformats(ast);
- struct ast_format vp8;
- ast_format_set(&vp8, AST_FORMAT_VP8, 0);
- if (ast_format_cap_iscompatible(fcap, &vp8)) {
+
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp8) != AST_FORMAT_CMP_NOT_EQUAL) {
/* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the
* RTP engine would provide a way to externally write/schedule RTCP
* packets */
@@ -2162,11 +2178,11 @@ static int load_module(void)
{
struct ao2_container *endpoints;
- if (!(chan_pjsip_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(chan_pjsip_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(chan_pjsip_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_append_by_type(chan_pjsip_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
ast_rtp_glue_register(&chan_pjsip_rtp_glue);
@@ -2259,6 +2275,7 @@ static int unload_module(void)
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
ast_channel_unregister(&chan_pjsip_tech);
+ ao2_ref(chan_pjsip_tech.capabilities, -1);
ast_rtp_glue_unregister(&chan_pjsip_rtp_glue);
return 0;
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 095b5a763..44629dc3d 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -285,6 +285,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_channels.h"
#include "asterisk/features_config.h"
#include "asterisk/http_websocket.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="SIPDtmfMode" language="en_US">
@@ -747,7 +748,6 @@ static char default_mohsuggest[MAX_MUSICCLASS]; /*!< Global setting for moh c
static char default_parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
static char default_engine[256]; /*!< Default RTP engine */
static int default_maxcallbitrate; /*!< Maximum bitrate for call */
-static struct ast_codec_pref default_prefs; /*!< Default codec prefs */
static char default_zone[MAX_TONEZONE_COUNTRY]; /*!< Default tone zone for channels created from the SIP driver */
static unsigned int default_transports; /*!< Default Transports (enum ast_transport) that are acceptable */
static unsigned int default_primary_transport; /*!< Default primary Transport (enum ast_transport) for outbound connections to devices */
@@ -1295,7 +1295,6 @@ static int str2dtmfmode(const char *str) attribute_unused;
static const char *insecure2str(int mode) attribute_const;
static const char *allowoverlap2str(int mode) attribute_const;
static void cleanup_stale_contexts(char *new, char *old);
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref);
static const char *domain_mode_to_text(const enum domain_mode mode);
static char *sip_show_domains(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]);
@@ -1764,7 +1763,7 @@ static void destroy_escs(void)
{
int i;
for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) {
- ao2_ref(event_state_compositors[i].compositor, -1);
+ ao2_cleanup(event_state_compositors[i].compositor);
}
}
@@ -3385,7 +3384,7 @@ static void unlink_peers_from_tables(peer_unlink_flag_t flag)
ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE,
match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers");
ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE,
- match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers");
+ match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers_by_ip");
}
/* \brief Unlink all marked peers from ao2 containers */
@@ -5308,7 +5307,7 @@ static void sip_destroy_peer(struct sip_peer *peer)
ast_string_field_free_memory(peer);
- peer->caps = ast_format_cap_destroy(peer->caps);
+ ao2_cleanup(peer->caps);
ast_rtp_dtls_cfg_free(&peer->dtls_cfg);
@@ -5967,7 +5966,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
}
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) ||
- (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) {
+ (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_MEDIA_TYPE_VIDEO)))) {
if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) {
return -1;
}
@@ -6053,8 +6052,11 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
- ast_format_cap_copy(dialog->caps, peer->caps);
- dialog->prefs = peer->prefs;
+ /* Take the peer's caps */
+ if (peer->caps) {
+ ast_format_cap_remove_by_type(dialog->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(dialog->caps, peer->caps, AST_MEDIA_TYPE_UNKNOWN);
+ }
dialog->amaflags = peer->amaflags;
ast_string_field_set(dialog, engine, peer->engine);
@@ -6078,8 +6080,8 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
/* Set Frame packetization */
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs);
dialog->autoframing = peer->autoframing;
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(dialog->rtp), ast_format_cap_get_framing(dialog->caps));
}
/* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */
@@ -6456,7 +6458,7 @@ static int sip_call(struct ast_channel *ast, const char *dest, int timeout)
p->jointnoncodeccapability = p->noncodeccapability;
/* If there are no audio formats left to offer, punt */
- if (!(ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO))) {
+ if (!(ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_AUDIO))) {
ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username);
res = -1;
} else {
@@ -6721,11 +6723,11 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
- p->caps = ast_format_cap_destroy(p->caps);
- p->jointcaps = ast_format_cap_destroy(p->jointcaps);
- p->peercaps = ast_format_cap_destroy(p->peercaps);
- p->redircaps = ast_format_cap_destroy(p->redircaps);
- p->prefcaps = ast_format_cap_destroy(p->prefcaps);
+ ao2_cleanup(p->caps);
+ ao2_cleanup(p->jointcaps);
+ ao2_cleanup(p->peercaps);
+ ao2_cleanup(p->redircaps);
+ ao2_cleanup(p->prefcaps);
ast_rtp_dtls_cfg_free(&p->dtls_cfg);
@@ -7308,7 +7310,6 @@ static int sip_hangup(struct ast_channel *ast)
/*! \brief Try setting the codecs suggested by the SIP_CODEC channel variable */
static void try_suggested_sip_codec(struct sip_pvt *p)
{
- struct ast_format fmt;
const char *codec_list;
char *codec_list_copy;
struct ast_format_cap *original_jointcaps;
@@ -7328,31 +7329,44 @@ static void try_suggested_sip_codec(struct sip_pvt *p)
}
codec_list_copy = ast_strdupa(codec_list);
- original_jointcaps = ast_format_cap_dup(p->jointcaps);
+
+ original_jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!original_jointcaps) {
+ return;
+ }
+ ast_format_cap_append_from_cap(original_jointcaps, p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
for (codec = strtok_r(codec_list_copy, ",", &strtok_ptr); codec; codec = strtok_r(NULL, ",", &strtok_ptr)) {
+ struct ast_format *fmt;
+
codec = ast_strip(codec);
- if (!ast_getformatbyname(codec, &fmt)) {
+ fmt = ast_format_cache_get(codec);
+ if (!fmt) {
ast_log(AST_LOG_NOTICE, "Ignoring ${SIP_CODEC*} variable because of unrecognized/not configured codec %s (check allow/disallow in sip.conf)\n", codec);
continue;
}
- if (ast_format_cap_iscompatible(original_jointcaps, &fmt)) {
+ if (ast_format_cap_iscompatible_format(original_jointcaps, fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
if (first_codec) {
ast_verb(4, "Set codec to '%s' for this call because of ${SIP_CODEC*} variable\n", codec);
- ast_format_cap_set(p->jointcaps, &fmt);
- ast_format_cap_set(p->caps, &fmt);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->jointcaps, fmt, 0);
+ ast_format_cap_remove_by_type(p->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->caps, fmt, 0);
first_codec = 0;
} else {
ast_verb(4, "Add codec to '%s' for this call because of ${SIP_CODEC*} variable\n", codec);
- ast_format_cap_add(p->jointcaps, &fmt);
- ast_format_cap_add(p->caps, &fmt);
+ /* Add the format to the capabilities structure */
+ ast_format_cap_append(p->jointcaps, fmt, 0);
+ ast_format_cap_append(p->caps, fmt, 0);
}
} else {
ast_log(AST_LOG_NOTICE, "Ignoring ${SIP_CODEC*} variable because it is not shared by both ends: %s\n", codec);
}
+
+ ao2_ref(fmt, -1);
}
- ast_format_cap_destroy(original_jointcaps);
+ ao2_ref(original_jointcaps, -1);
return;
}
@@ -7401,13 +7415,13 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
switch (frame->frametype) {
case AST_FRAME_VOICE:
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char s1[512];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s read/write = %s/%s\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(s1, sizeof(s1), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return 0;
}
if (p) {
@@ -7929,10 +7943,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
if (p->vrtp && !p->novideo) {
/* FIXME: Only use this for VP8. Additional work would have to be done to
* fully support other video codecs */
- struct ast_format_cap *fcap = ast_channel_nativeformats(ast);
- struct ast_format vp8;
- ast_format_set(&vp8, AST_FORMAT_VP8, 0);
- if (ast_format_cap_iscompatible(fcap, &vp8)) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp8) != AST_FORMAT_CMP_NOT_EQUAL) {
/* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the
* RTP engine would provide a way to externally write/schedule RTCP
* packets */
@@ -8036,15 +8047,21 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
*/
static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid)
{
+ struct ast_format_cap *caps;
struct ast_channel *tmp;
struct ast_variable *v = NULL;
- struct ast_format fmt;
+ struct ast_format *fmt;
struct ast_format_cap *what = NULL; /* SHALLOW COPY DO NOT DESTROY! */
+ struct ast_str *codec_buf = ast_str_alloca(64);
int needvideo = 0;
int needtext = 0;
- char buf[SIPBUFSIZE];
char *exten;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
{
const char *my_name; /* pick a good name */
@@ -8060,6 +8077,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
}
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n");
+ ao2_ref(caps, -1);
sip_pvt_lock(i);
return NULL;
}
@@ -8068,6 +8086,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) {
ast_channel_unlock(tmp);
ast_channel_unref(tmp);
+ ao2_ref(caps, -1);
sip_pvt_lock(i);
return NULL;
}
@@ -8088,27 +8107,40 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
/* Select our native format based on codec preference until we receive
something from another device to the contrary. */
- if (!(ast_format_cap_is_empty(i->jointcaps))) { /* The joint capabilities of us and peer */
+ if (ast_format_cap_count(i->jointcaps)) { /* The joint capabilities of us and peer */
what = i->jointcaps;
- } else if (!(ast_format_cap_is_empty(i->caps))) { /* Our configured capability for this peer */
+ } else if (ast_format_cap_count(i->caps)) { /* Our configured capability for this peer */
what = i->caps;
} else {
what = sip_cfg.caps;
}
/* Set the native formats */
- ast_format_cap_copy(ast_channel_nativeformats(tmp), what);
- /* choose and use only the best audio format for our native formats */
- ast_codec_choose(&i->prefs, ast_channel_nativeformats(tmp), 1, &fmt); /* get the best audio format */
- ast_format_cap_remove_bytype(ast_channel_nativeformats(tmp), AST_FORMAT_TYPE_AUDIO); /* remove only the other audio formats */
- ast_format_cap_add(ast_channel_nativeformats(tmp), &fmt); /* add our best choice back */
+ ast_format_cap_append_from_cap(caps, what, AST_MEDIA_TYPE_UNKNOWN);
+ /* Use only the preferred audio format, which is stored at the '0' index */
+ fmt = ast_format_cap_get_best_by_type(what, AST_MEDIA_TYPE_AUDIO); /* get the best audio format */
+ if (fmt) {
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); /* remove only the other audio formats */
+ ast_format_cap_append(caps, fmt, 0); /* add our best choice back */
+ } else {
+ /* If we don't have an audio format, try to get something */
+ fmt = ast_format_cap_get_format(caps, 0);
+ if (!fmt) {
+ ast_log(LOG_WARNING, "No compatible formats could be found for %s\n", ast_channel_name(tmp));
+ ao2_ref(caps, -1);
+ tmp = ast_channel_unref(tmp);
+ return NULL;
+ }
+ }
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
- ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_channel_nativeformats(tmp)));
- ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcaps));
- ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->caps));
- ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname(&fmt));
- if (!ast_format_cap_is_empty(i->prefcaps)) {
- ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcaps));
+ ast_debug(3, "*** Our native formats are %s \n", ast_format_cap_get_names(ast_channel_nativeformats(tmp), &codec_buf));
+ ast_debug(3, "*** Joint capabilities are %s \n", ast_format_cap_get_names(i->jointcaps, &codec_buf));
+ ast_debug(3, "*** Our capabilities are %s \n", ast_format_cap_get_names(i->caps, &codec_buf));
+ ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_format_get_name(fmt));
+ if (ast_format_cap_count(i->prefcaps)) {
+ ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_format_cap_get_names(i->prefcaps, &codec_buf));
}
/* If we have a prefcodec setting, we have an inbound channel that set a
@@ -8118,17 +8150,17 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (i->vrtp) {
if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT))
needvideo = 1;
- else if (!ast_format_cap_is_empty(i->prefcaps))
- needvideo = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_VIDEO); /* Outbound call */
+ else if (ast_format_cap_count(i->prefcaps))
+ needvideo = ast_format_cap_has_type(i->prefcaps, AST_MEDIA_TYPE_VIDEO); /* Outbound call */
else
- needvideo = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_VIDEO); /* Inbound call */
+ needvideo = ast_format_cap_has_type(i->jointcaps, AST_MEDIA_TYPE_VIDEO); /* Inbound call */
}
if (i->trtp) {
- if (!ast_format_cap_is_empty(i->prefcaps))
- needtext = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_TEXT); /* Outbound call */
+ if (ast_format_cap_count(i->prefcaps))
+ needtext = ast_format_cap_has_type(i->prefcaps, AST_MEDIA_TYPE_TEXT); /* Outbound call */
else
- needtext = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_TEXT); /* Inbound call */
+ needtext = ast_format_cap_has_type(i->jointcaps, AST_MEDIA_TYPE_TEXT); /* Inbound call */
}
if (needvideo) {
@@ -8156,8 +8188,8 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (i->rtp) {
ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
- ast_rtp_instance_set_write_format(i->rtp, &fmt);
- ast_rtp_instance_set_read_format(i->rtp, &fmt);
+ ast_rtp_instance_set_write_format(i->rtp, fmt);
+ ast_rtp_instance_set_read_format(i->rtp, fmt);
}
if (needvideo && i->vrtp) {
ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
@@ -8175,11 +8207,13 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
}
ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
- ast_format_copy(ast_channel_writeformat(tmp), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &fmt);
+ ast_channel_set_writeformat(tmp, fmt);
+ ast_channel_set_rawwriteformat(tmp, fmt);
+
+ ast_channel_set_readformat(tmp, fmt);
+ ast_channel_set_rawreadformat(tmp, fmt);
- ast_format_copy(ast_channel_readformat(tmp), &fmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &fmt);
+ ao2_ref(fmt, -1);
ast_channel_tech_pvt_set(tmp, dialog_ref(i, "sip_new: set chan->tech_pvt to i"));
@@ -8534,17 +8568,26 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
return f;
}
- if (f && !ast_format_cap_iscompatible(ast_channel_nativeformats(p->owner), &f->subclass.format)) {
- if (!ast_format_cap_iscompatible(p->jointcaps, &f->subclass.format)) {
+ if (f && ast_format_cap_iscompatible_format(ast_channel_nativeformats(p->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ if (ast_format_cap_iscompatible_format(p->jointcaps, f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
- ast_getformatname(&f->subclass.format), ast_channel_name(p->owner));
+ ast_format_get_name(f->subclass.format), ast_channel_name(p->owner));
ast_frfree(f);
return &ast_null_frame;
}
ast_debug(1, "Oooh, format changed to %s\n",
- ast_getformatname(&f->subclass.format));
- ast_format_cap_remove_bytype(ast_channel_nativeformats(p->owner), AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(ast_channel_nativeformats(p->owner), &f->subclass.format);
+ ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(p->owner), AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
}
@@ -8796,18 +8839,18 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
sip_pvt_callid_set(p, logger_callid);
}
- p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
- if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps) {
- p->caps = ast_format_cap_destroy(p->caps);
- p->jointcaps = ast_format_cap_destroy(p->jointcaps);
- p->peercaps = ast_format_cap_destroy(p->peercaps);
- p->redircaps = ast_format_cap_destroy(p->redircaps);
- p->prefcaps = ast_format_cap_destroy(p->prefcaps);
+ if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps || !p->prefcaps) {
+ ao2_cleanup(p->caps);
+ ao2_cleanup(p->jointcaps);
+ ao2_cleanup(p->peercaps);
+ ao2_cleanup(p->redircaps);
+ ao2_cleanup(p->prefcaps);
ao2_t_ref(p, -1, "Yuck, couldn't allocate format capabilities. Get rid o' p");
return NULL;
}
@@ -8857,7 +8900,6 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
p->sessionversion_remote = -1;
p->session_modify = TRUE;
p->stimer = NULL;
- p->prefs = default_prefs; /* Set default codecs for this call */
ast_copy_string(p->zone, default_zone, sizeof(p->zone));
p->maxforwards = sip_cfg.default_max_forwards;
@@ -8909,7 +8951,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
/* Assign default music on hold class */
ast_string_field_set(p, mohinterpret, default_mohinterpret);
ast_string_field_set(p, mohsuggest, default_mohsuggest);
- ast_format_cap_copy(p->caps, sip_cfg.caps);
+ ast_format_cap_append_from_cap(p->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN);
p->allowtransfer = sip_cfg.allowtransfer;
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
@@ -10034,15 +10076,17 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int udptlportno = -1; /*!< UDPTL image destination port number */
/* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */
- struct ast_format_cap *peercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *vpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *tpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *peercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *vpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *tpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int peernoncodeccapability = 0, vpeernoncodeccapability = 0, tpeernoncodeccapability = 0;
- struct ast_rtp_codecs newaudiortp = { 0, }, newvideortp = { 0, }, newtextrtp = { 0, };
- struct ast_format_cap *newjointcapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); /* Negotiated capability */
- struct ast_format_cap *newpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_rtp_codecs newaudiortp = AST_RTP_CODECS_NULL_INIT;
+ struct ast_rtp_codecs newvideortp = AST_RTP_CODECS_NULL_INIT;
+ struct ast_rtp_codecs newtextrtp = AST_RTP_CODECS_NULL_INIT;
+ struct ast_format_cap *newjointcapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); /* Negotiated capability */
+ struct ast_format_cap *newpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int newnoncodeccapability;
const char *codecs;
@@ -10062,8 +10106,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int debug = sip_debug_test_pvt(p);
/* START UNKNOWN */
- char buf[SIPBUFSIZE];
- struct ast_format tmp_fmt;
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_format *tmp_fmt;
/* END UNKNOWN */
/* Initial check */
@@ -10625,10 +10669,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Ensure crypto lines are provided where necessary */
if (audio && secure_audio && !processed_crypto) {
ast_log(LOG_WARNING, "Rejecting secure audio stream without encryption details: %s\n", m);
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
} else if (video && secure_video && !processed_crypto) {
ast_log(LOG_WARNING, "Rejecting secure video stream without encryption details: %s\n", m);
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
}
}
@@ -10687,12 +10733,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_rtp_codecs_payload_formats(&newvideortp, vpeercapability, &vpeernoncodeccapability);
ast_rtp_codecs_payload_formats(&newtextrtp, tpeercapability, &tpeernoncodeccapability);
- ast_format_cap_append(newpeercapability, peercapability);
- ast_format_cap_append(newpeercapability, vpeercapability);
- ast_format_cap_append(newpeercapability, tpeercapability);
+ ast_format_cap_append_from_cap(newpeercapability, peercapability, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_from_cap(newpeercapability, vpeercapability, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_from_cap(newpeercapability, tpeercapability, AST_MEDIA_TYPE_TEXT);
- ast_format_cap_joint_copy(p->caps, newpeercapability, newjointcapability);
- if (ast_format_cap_is_empty(newjointcapability) && udptlportno == -1) {
+ ast_format_cap_get_compatible(p->caps, newpeercapability, newjointcapability);
+ if (!ast_format_cap_count(newjointcapability) && udptlportno == -1) {
ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
/* Do NOT Change current setting */
res = -1;
@@ -10703,14 +10749,18 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (debug) {
/* shame on whoever coded this.... */
- char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *vpeer_buf = ast_str_alloca(64);
+ struct ast_str *tpeer_buf = ast_str_alloca(64);
+ struct ast_str *joint_buf = ast_str_alloca(64);
ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n",
- ast_getformatname_multiple(s1, SIPBUFSIZE, p->caps),
- ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability),
- ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability),
- ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability),
- ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability));
+ ast_format_cap_get_names(p->caps, &cap_buf),
+ ast_format_cap_get_names(peercapability, &peer_buf),
+ ast_format_cap_get_names(vpeercapability, &vpeer_buf),
+ ast_format_cap_get_names(tpeercapability, &tpeer_buf),
+ ast_format_cap_get_names(newjointcapability, &joint_buf));
}
if (debug) {
struct ast_str *s1 = ast_str_alloca(SIPBUFSIZE);
@@ -10726,14 +10776,21 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (portno != -1 || vportno != -1 || tportno != -1) {
/* We are now ready to change the sip session and RTP structures with the offered codecs, since
they are acceptable */
- ast_format_cap_copy(p->jointcaps, newjointcapability); /* Our joint codec profile for this call */
- ast_format_cap_copy(p->peercaps, newpeercapability); /* The other side's capability in latest offer */
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, newjointcapability, AST_MEDIA_TYPE_UNKNOWN); /* Our joint codec profile for this call */
+ ast_format_cap_remove_by_type(p->peercaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->peercaps, newpeercapability, AST_MEDIA_TYPE_UNKNOWN); /* The other side's capability in latest offer */
p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */
/* respond with single most preferred joint codec, limiting the other side's choice */
if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) {
- ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt);
- ast_format_cap_set(p->jointcaps, &tmp_fmt);
+ unsigned int framing;
+
+ tmp_fmt = ast_format_cap_get_format(p->jointcaps, 0);
+ framing = ast_format_cap_get_format_framing(p->jointcaps, tmp_fmt);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->jointcaps, tmp_fmt, framing);
+ ao2_ref(tmp_fmt, -1);
}
}
@@ -10813,7 +10870,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_verbose("Peer T.140 RTP is at port %s\n",
ast_sockaddr_stringify(tsa));
}
- if (ast_format_cap_iscompatible(p->jointcaps, ast_format_set(&tmp_fmt, AST_FORMAT_T140RED, 0))) {
+ if (ast_format_cap_iscompatible_format(p->jointcaps, ast_format_t140_red) != AST_FORMAT_CMP_NOT_EQUAL) {
p->red = 1;
ast_rtp_red_init(p->trtp, 300, red_data_pt, 2);
} else {
@@ -10890,7 +10947,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
/* Ok, we're going with this offer */
- ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcaps));
+ ast_debug(2, "We're settling with these formats: %s\n", ast_format_cap_get_names(p->jointcaps, &codec_buf));
if (!p->owner) { /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */
res = 0;
@@ -10898,19 +10955,30 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
ast_debug(4, "We have an owner, now see if we need to change this call\n");
- if (ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO)) {
+ if (ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_AUDIO)) {
+ struct ast_format_cap *caps;
+ unsigned int framing;
+
if (debug) {
- char s1[SIPBUFSIZE], s2[SIPBUFSIZE];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *joint_buf = ast_str_alloca(64);
+
ast_debug(1, "Setting native formats after processing SDP. peer joint formats %s, old nativeformats %s\n",
- ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcaps),
- ast_getformatname_multiple(s2, SIPBUFSIZE, ast_channel_nativeformats(p->owner)));
+ ast_format_cap_get_names(p->jointcaps, &joint_buf),
+ ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &cap_buf));
}
- ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt);
-
- ast_format_cap_set(ast_channel_nativeformats(p->owner), &tmp_fmt);
- ast_format_cap_joint_append(p->caps, vpeercapability, ast_channel_nativeformats(p->owner));
- ast_format_cap_joint_append(p->caps, tpeercapability, ast_channel_nativeformats(p->owner));
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ tmp_fmt = ast_format_cap_get_format(p->jointcaps, 0);
+ framing = ast_format_cap_get_format_framing(p->jointcaps, tmp_fmt);
+ ast_format_cap_append(caps, tmp_fmt, framing);
+ ast_format_cap_append_from_cap(caps, vpeercapability, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_from_cap(caps, tpeercapability, AST_MEDIA_TYPE_TEXT);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ ao2_ref(tmp_fmt, -1);
+ }
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
@@ -10942,11 +11010,11 @@ process_sdp_cleanup:
ast_rtp_codecs_payloads_destroy(&newtextrtp);
ast_rtp_codecs_payloads_destroy(&newvideortp);
ast_rtp_codecs_payloads_destroy(&newaudiortp);
- ast_format_cap_destroy(peercapability);
- ast_format_cap_destroy(vpeercapability);
- ast_format_cap_destroy(tpeercapability);
- ast_format_cap_destroy(newjointcapability);
- ast_format_cap_destroy(newpeercapability);
+ ao2_cleanup(peercapability);
+ ao2_cleanup(vpeercapability);
+ ao2_cleanup(tpeercapability);
+ ao2_cleanup(newjointcapability);
+ ao2_cleanup(newpeercapability);
return res;
}
@@ -11203,17 +11271,10 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
ast_debug(1, "Can't read framing from SDP: %s\n", a);
}
}
+
if (framing && p->autoframing) {
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
- int codec_n;
- for (codec_n = 0; codec_n < AST_RTP_MAX_PT; codec_n++) {
- struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n);
- if (!format.asterisk_format) /* non-codec or not found */
- continue;
- ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(&format.format), framing);
- ast_codec_pref_setsize(pref, &format.format, framing);
- }
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref);
+ ast_debug(1, "Setting framing to %ld\n", framing);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), framing);
}
found = TRUE;
} else if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) {
@@ -11240,15 +11301,19 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
if ((format = ast_rtp_codecs_get_payload_format(newaudiortp, codec))) {
unsigned int bit_rate;
+ struct ast_format *format_parsed;
- if (!ast_format_sdp_parse(format, fmtp_string)) {
+ format_parsed = ast_format_parse_sdp_fmtp(format, fmtp_string);
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(newaudiortp, codec, format_parsed);
+ ao2_replace(format, format_parsed);
+ ao2_ref(format_parsed, -1);
found = TRUE;
} else {
ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec);
}
- switch ((int) format->id) {
- case AST_FORMAT_SIREN7:
+ if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 32000) {
ast_log(LOG_WARNING, "Got Siren7 offer at %u bps, but only 32000 bps supported; ignoring.\n", bit_rate);
@@ -11257,8 +11322,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
found = TRUE;
}
}
- break;
- case AST_FORMAT_SIREN14:
+ } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) {
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 48000) {
ast_log(LOG_WARNING, "Got Siren14 offer at %u bps, but only 48000 bps supported; ignoring.\n", bit_rate);
@@ -11267,8 +11331,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
found = TRUE;
}
}
- break;
- case AST_FORMAT_G719:
+ } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 64000) {
ast_log(LOG_WARNING, "Got G.719 offer at %u bps, but only 64000 bps supported; ignoring.\n", bit_rate);
@@ -11277,8 +11340,8 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
found = TRUE;
}
}
- break;
}
+ ao2_ref(format, -1);
}
}
@@ -11320,11 +11383,19 @@ static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_
struct ast_format *format;
if ((format = ast_rtp_codecs_get_payload_format(newvideortp, codec))) {
- if (!ast_format_sdp_parse(format, fmtp_string)) {
+ struct ast_format *format_parsed;
+
+ format_parsed = ast_format_parse_sdp_fmtp(format, fmtp_string);
+
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(newvideortp, codec, format_parsed);
+ ao2_replace(format, format_parsed);
+ ao2_ref(format_parsed, -1);
found = TRUE;
} else {
ast_rtp_codecs_payloads_unset(newvideortp, NULL, codec);
}
+ ao2_ref(format, -1);
}
}
@@ -12890,12 +12961,11 @@ static void add_codec_to_sdp(const struct sip_pvt *p,
int *max_packet_size)
{
int rtp_code;
- struct ast_format_list fmt;
const char *mime;
- unsigned int rate;
+ unsigned int rate, framing;
if (debug)
- ast_verbose("Adding codec %u (%s) to SDP\n", format->id, ast_getformatname(format));
+ ast_verbose("Adding codec %s to SDP\n", ast_format_get_name(format));
if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, format, 0)) == -1) ||
!(mime = ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0)) ||
@@ -12903,63 +12973,54 @@ static void add_codec_to_sdp(const struct sip_pvt *p,
return;
}
- if (p->rtp) {
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
- fmt = ast_codec_pref_getsize(pref, format);
- } else /* I don't see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */
- return;
ast_str_append(m_buf, 0, " %d", rtp_code);
/* Opus mandates 2 channels in rtpmap */
- if ((int)format->id == AST_FORMAT_OPUS) {
+ if (ast_format_cmp(format, ast_format_opus) == AST_FORMAT_CMP_EQUAL) {
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u/2\r\n", rtp_code, mime, rate);
} else {
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u\r\n", rtp_code, mime, rate);
}
- ast_format_sdp_generate(format, rtp_code, a_buf);
+ ast_format_generate_sdp_fmtp(format, rtp_code, a_buf);
+
+ framing = ast_format_cap_get_format_framing(p->caps, format);
- switch ((int) format->id) {
- case AST_FORMAT_G729A:
+ if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we don't support VAD (G.729 annex B) */
ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code);
- break;
- case AST_FORMAT_G723_1:
+ } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we don't support VAD (G.723.1 annex A) */
ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code);
- break;
- case AST_FORMAT_ILBC:
+ } else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL) {
/* Add information about us using only 20/30 ms packetization */
- ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms);
- break;
- case AST_FORMAT_SIREN7:
+ ast_str_append(a_buf, 0, "a=fmtp:%d mode=%u\r\n", rtp_code, framing);
+ } else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we only expect 32Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=32000\r\n", rtp_code);
- break;
- case AST_FORMAT_SIREN14:
+ } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we only expect 48Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=48000\r\n", rtp_code);
- break;
- case AST_FORMAT_G719:
+ } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we only expect 64Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code);
- break;
}
- if (max_packet_size && fmt.max_ms && (fmt.max_ms < *max_packet_size)) {
- *max_packet_size = fmt.max_ms;
+ if (max_packet_size && ast_format_get_maximum_ms(format) &&
+ (ast_format_get_maximum_ms(format) < *max_packet_size)) {
+ *max_packet_size = ast_format_get_maximum_ms(format);
}
- if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) {
- *min_packet_size = fmt.cur_ms;
+ if (framing && (framing < *min_packet_size)) {
+ *min_packet_size = framing;
}
/* Our first codec packetization processed cannot be zero */
- if ((*min_packet_size) == 0 && fmt.cur_ms) {
- *min_packet_size = fmt.cur_ms;
+ if ((*min_packet_size) == 0 && framing) {
+ *min_packet_size = framing;
}
- if ((*max_packet_size) == 0 && fmt.max_ms) {
- *max_packet_size = fmt.max_ms;
+ if ((*max_packet_size) == 0 && ast_format_get_maximum_ms(format)) {
+ *max_packet_size = ast_format_get_maximum_ms(format);
}
}
@@ -12977,7 +13038,7 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
return;
if (debug)
- ast_verbose("Adding video codec %u (%s) to SDP\n", format->id, ast_getformatname(format));
+ ast_verbose("Adding video codec %s to SDP\n", ast_format_get_name(format));
if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, format, 0)) == -1) ||
!(subtype = ast_rtp_lookup_mime_subtype2(1, format, 0, 0)) ||
@@ -12988,11 +13049,11 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
ast_str_append(m_buf, 0, " %d", rtp_code);
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u\r\n", rtp_code, subtype, rate);
/* VP8: add RTCP FIR support */
- if ((int)format->id == AST_FORMAT_VP8) {
+ if (ast_format_cmp(format, ast_format_vp8) == AST_FORMAT_CMP_EQUAL) {
ast_str_append(a_buf, 0, "a=rtcp-fb:* ccm fir\r\n");
}
- ast_format_sdp_generate(format, rtp_code, a_buf);
+ ast_format_generate_sdp_fmtp(format, rtp_code, a_buf);
}
/*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */
@@ -13006,7 +13067,7 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
return;
if (debug)
- ast_verbose("Adding text codec %u (%s) to SDP\n", format->id, ast_getformatname(format));
+ ast_verbose("Adding text codec %s to SDP\n", ast_format_get_name(format));
if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, format, 0)) == -1)
return;
@@ -13017,9 +13078,8 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
ast_rtp_lookup_sample_rate2(1, format, 0));
/* Add fmtp code here */
- if (format->id == AST_FORMAT_T140RED) {
- struct ast_format tmp_fmt;
- int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_set(&tmp_fmt, AST_FORMAT_T140, 0), 0);
+ if (ast_format_cmp(format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {
+ int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_t140, 0);
ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code,
t140code,
t140code,
@@ -13194,8 +13254,8 @@ static char *crypto_get_attrib(struct ast_sdp_srtp *srtp, int dtls_enabled, int
*/
static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
{
- struct ast_format_cap *alreadysent = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *alreadysent = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int res = AST_SUCCESS;
int doing_directmedia = FALSE;
struct ast_sockaddr addr = { {0,} };
@@ -13229,7 +13289,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
RAII_VAR(char *, t_a_crypto, NULL, ast_free);
int x;
- struct ast_format tmp_fmt;
+ struct ast_format *tmp_fmt;
int needaudio = FALSE;
int needvideo = FALSE;
int needtext = FALSE;
@@ -13239,8 +13299,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
int min_video_packet_size = 0;
int min_text_packet_size = 0;
- char codecbuf[SIPBUFSIZE];
- char buf[SIPBUFSIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
/* Set the SDP session name */
snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession);
@@ -13268,11 +13327,24 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
}
if (add_audio) {
- doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && !(ast_format_cap_is_empty(p->redircaps))) ? TRUE : FALSE;
+ doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && (ast_format_cap_count(p->redircaps))) ? TRUE : FALSE;
+
+ if (doing_directmedia) {
+ ast_format_cap_get_compatible(p->jointcaps, p->redircaps, tmpcap);
+ ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_format_cap_get_names(tmpcap, &codec_buf));
+ } else {
+ ast_format_cap_append_from_cap(tmpcap, p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ }
+
+ /* Check if we need audio */
+ if (ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_AUDIO)
+ || ast_format_cap_has_type(p->caps, AST_MEDIA_TYPE_AUDIO)) {
+ needaudio = TRUE;
+ }
+
/* Check if we need video in this call */
- if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_VIDEO)) && !p->novideo) {
- ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap);
- if (doing_directmedia && !ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_VIDEO)) {
+ if ((ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_VIDEO)) && !p->novideo) {
+ if (doing_directmedia && !ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_VIDEO)) {
ast_debug(2, "This call needs video offers, but caller probably did not offer it!\n");
} else if (p->vrtp) {
needvideo = TRUE;
@@ -13281,8 +13353,9 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ast_debug(2, "This call needs video offers, but there's no video support enabled!\n");
}
}
+
/* Check if we need text in this call */
- if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_TEXT)) && !p->notext) {
+ if ((ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_TEXT)) && !p->notext) {
if (sipdebug_text)
ast_verbose("We think we can do text\n");
if (p->trtp) {
@@ -13295,6 +13368,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n");
}
}
+
+ /* XXX note, Video and Text are negated - 'true' means 'no' */
+ ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n",
+ ast_format_cap_get_names(tmpcap, &codec_buf),
+ p->novideo ? "True" : "False", p->notext ? "True" : "False");
+ ast_debug(1, "** Our prefcodec: %s \n", ast_format_cap_get_names(p->prefcaps, &codec_buf));
}
get_our_media_address(p, needvideo, needtext, &addr, &vaddr, &taddr, &dest, &vdest, &tdest);
@@ -13322,22 +13401,6 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
hold = "a=sendrecv\r\n";
}
- ast_format_cap_copy(tmpcap, p->jointcaps);
-
- /* XXX note, Video and Text are negated - 'true' means 'no' */
- ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap),
- p->novideo ? "True" : "False", p->notext ? "True" : "False");
- ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcaps));
-
- if (doing_directmedia) {
- ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap);
- ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap));
- }
-
- /* Check if we need audio */
- if (ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_AUDIO))
- needaudio = TRUE;
-
if (debug) {
ast_verbose("Audio is at %s\n", ast_sockaddr_stringify_port(&addr));
}
@@ -13406,8 +13469,8 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
/* Now, start adding audio codecs. These are added in this order:
- First what was requested by the calling channel
+ - Then our mutually shared capabilities, determined previous in tmpcap
- Then preferences in order from sip.conf device config for this peer/user
- - Then other codecs in capabilities, including video
*/
@@ -13415,57 +13478,62 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
* configured codecs.
*/
if (!ast_test_flag(&p->flags[2], SIP_PAGE3_IGNORE_PREFCAPS)) {
- ast_format_cap_iter_start(p->prefcaps);
- while (!(ast_format_cap_iter_next(p->prefcaps, &tmp_fmt))) {
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO ||
- !ast_format_cap_iscompatible(tmpcap, &tmp_fmt)) {
+ for (x = 0; x < ast_format_cap_count(p->prefcaps); x++) {
+ tmp_fmt = ast_format_cap_get_format(p->prefcaps, x);
+
+ if ((ast_format_get_type(tmp_fmt) != AST_MEDIA_TYPE_AUDIO) ||
+ (ast_format_cap_iscompatible_format(tmpcap, tmp_fmt) == AST_FORMAT_CMP_NOT_EQUAL)) {
+ ao2_ref(tmp_fmt, -1);
continue;
}
- add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
- ast_format_cap_add(alreadysent, &tmp_fmt);
+
+ add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
+ ast_format_cap_append(alreadysent, tmp_fmt, 0);
+ ao2_ref(tmp_fmt, -1);
}
- ast_format_cap_iter_end(p->prefcaps);
}
- /* Start by sending our preferred audio/video codecs */
- for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- struct ast_format pref;
-
- if (!(ast_codec_pref_index(&p->prefs, x, &pref)))
- break;
-
- if (!ast_format_cap_get_compatible_format(tmpcap, &pref, &tmp_fmt))
- continue;
+ /* Now send any other common codecs */
+ for (x = 0; x < ast_format_cap_count(tmpcap); x++) {
+ tmp_fmt = ast_format_cap_get_format(tmpcap, x);
- if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt))
+ if (ast_format_cap_iscompatible_format(alreadysent, tmp_fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ao2_ref(tmp_fmt, -1);
continue;
+ }
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) {
- add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
- } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) {
- add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
- } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) {
- add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
+ if (ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_AUDIO) {
+ add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
+ } else if (needvideo && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_VIDEO) {
+ add_vcodec_to_sdp(p, tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
+ } else if (needtext && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_TEXT) {
+ add_tcodec_to_sdp(p, tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
}
- ast_format_cap_add(alreadysent, &tmp_fmt);
+ ast_format_cap_append(alreadysent, tmp_fmt, 0);
+ ao2_ref(tmp_fmt, -1);
}
- /* Now send any other common audio and video codecs, and non-codec formats: */
- ast_format_cap_iter_start(tmpcap);
- while (!(ast_format_cap_iter_next(tmpcap, &tmp_fmt))) {
- if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt))
+ /* Finally our remaining audio/video codecs */
+ for (x = 0; x < ast_format_cap_count(p->caps); x++) {
+ tmp_fmt = ast_format_cap_get_format(p->caps, x);
+
+ if (ast_format_cap_iscompatible_format(alreadysent, tmp_fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ao2_ref(tmp_fmt, -1);
continue;
+ }
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) {
- add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
- } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) {
- add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
- } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) {
- add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
+ if (ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_AUDIO) {
+ add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
+ } else if (needvideo && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_VIDEO) {
+ add_vcodec_to_sdp(p, tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
+ } else if (needtext && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_TEXT) {
+ add_tcodec_to_sdp(p, tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
}
+
+ ast_format_cap_append(alreadysent, tmp_fmt, 0);
+ ao2_ref(tmp_fmt, -1);
}
- ast_format_cap_iter_end(tmpcap);
/* Now add DTMF RFC2833 telephony-event as a codec */
for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
@@ -13677,14 +13745,15 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ao2_t_link(dialogs_rtpcheck, p, "link pvt into dialogs_rtpcheck container");
ao2_unlock(dialogs_rtpcheck);
- ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmpcap));
+ ast_debug(3, "Done building SDP. Settling with this capability: %s\n",
+ ast_format_cap_get_names(tmpcap, &codec_buf));
add_sdp_cleanup:
ast_free(a_text);
ast_free(a_video);
ast_free(a_audio);
- alreadysent = ast_format_cap_destroy(alreadysent);
- tmpcap = ast_format_cap_destroy(tmpcap);
+ ao2_cleanup(alreadysent);
+ ao2_cleanup(tmpcap);
return res;
}
@@ -13792,7 +13861,7 @@ static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const
if (p->rtp) {
if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
ast_debug(1, "Setting framing from config on incoming call\n");
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(p->caps));
}
ast_rtp_instance_activate(p->rtp);
try_suggested_sip_codec(p);
@@ -18475,10 +18544,9 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
peer->name, of, ast_sockaddr_stringify(&p->recv));
}
- /* XXX what about p->prefs = peer->prefs; ? */
/* Set Frame packetization */
if (p->rtp) {
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(peer->caps));
p->autoframing = peer->autoframing;
}
@@ -18595,20 +18663,22 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
p->named_callgroups = ast_ref_namedgroups(peer->named_callgroups);
ast_unref_namedgroups(p->named_pickupgroups);
p->named_pickupgroups = ast_ref_namedgroups(peer->named_pickupgroups);
- ast_format_cap_copy(p->caps, peer->caps);
- ast_format_cap_copy(p->jointcaps, peer->caps);
- p->prefs = peer->prefs;
+ ast_format_cap_remove_by_type(p->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->caps, peer->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, peer->caps, AST_MEDIA_TYPE_UNKNOWN);
ast_copy_string(p->zone, peer->zone, sizeof(p->zone));
if (peer->maxforwards > 0) {
p->maxforwards = peer->maxforwards;
}
- if (!(ast_format_cap_is_empty(p->peercaps))) {
- struct ast_format_cap *tmp = ast_format_cap_joint(p->jointcaps, p->peercaps);
- struct ast_format_cap *tmp2;
- if (tmp) {
- tmp2 = p->jointcaps;
- p->jointcaps = tmp;
- ast_format_cap_destroy(tmp2);
+ if (ast_format_cap_count(p->peercaps)) {
+ struct ast_format_cap *joint;
+
+ joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (joint) {
+ ast_format_cap_get_compatible(p->jointcaps, p->peercaps, joint);
+ ao2_ref(p->jointcaps, -1);
+ p->jointcaps = joint;
}
}
p->maxcallbitrate = peer->maxcallbitrate;
@@ -18623,7 +18693,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
p->rtpkeepalive = peer->rtpkeepalive;
if (!dialog_initialize_rtp(p)) {
if (p->rtp) {
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(peer->caps));
p->autoframing = peer->autoframing;
}
} else {
@@ -19959,25 +20029,6 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli
return CLI_SUCCESS;
}
-/*! \brief Print codec list from preference to CLI/manager */
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
-{
- int x;
- struct ast_format codec;
-
- for(x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- if (!(ast_codec_pref_index(pref, x, &codec))) {
- break;
- }
- ast_cli(fd, "%s", ast_getformatname(&codec));
- ast_cli(fd, ":%d", pref->framing[x]);
- if (x < 31 && ast_codec_pref_index(pref, x + 1, &codec))
- ast_cli(fd, ",");
- }
- if (!x)
- ast_cli(fd, "none");
-}
-
/*! \brief Print domain mode to cli */
static const char *domain_mode_to_text(const enum domain_mode mode)
{
@@ -20262,11 +20313,9 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
char status[30] = "";
char cbuf[256];
struct sip_peer *peer;
- char codec_buf[512];
- struct ast_codec_pref *pref;
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_variable *v;
int x = 0, load_realtime;
- struct ast_format codec;
int realtimepeers;
realtimepeers = ast_check_realtime("sippeers");
@@ -20415,12 +20464,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
ast_cli(fd, "(none)");
ast_cli(fd, "\n");
- ast_cli(fd, " Codecs : ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, " Codec Order : (");
- print_codec_to_cli(fd, &peer->prefs);
- ast_cli(fd, ")\n");
+ ast_cli(fd, " Codecs : %s\n", ast_format_cap_get_names(peer->caps, &codec_buf));
ast_cli(fd, " Auto-Framing : %s\n", AST_CLI_YESNO(peer->autoframing));
ast_cli(fd, " Status : ");
@@ -20523,21 +20567,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
astman_append(s, "Default-Username: %s\r\n", peer->username);
if (!ast_strlen_zero(sip_cfg.regcontext))
astman_append(s, "RegExtension: %s\r\n", peer->regexten);
- astman_append(s, "Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps);
- astman_append(s, "%s\r\n", codec_buf);
- astman_append(s, "CodecOrder: ");
- pref = &peer->prefs;
- for(x = 0; x < AST_CODEC_PREF_SIZE ; x++) {
- if (!(ast_codec_pref_index(pref, x, &codec))) {
- break;
- }
- astman_append(s, "%s", ast_getformatname(&codec));
- if ((x < (AST_CODEC_PREF_SIZE - 1)) && ast_codec_pref_index(pref, x+1, &codec))
- astman_append(s, ",");
- }
-
- astman_append(s, "\r\n");
+ astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(peer->caps, &codec_buf));
astman_append(s, "Status: ");
peer_status(peer, status, sizeof(status));
astman_append(s, "%s\r\n", status);
@@ -20660,10 +20690,6 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args
ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se);
ast_cli(a->fd, " RTP Engine : %s\n", user->engine);
- ast_cli(a->fd, " Codec Order : (");
- print_codec_to_cli(a->fd, &user->prefs);
- ast_cli(a->fd, ")\n");
-
ast_cli(a->fd, " Auto-Framing: %s \n", AST_CLI_YESNO(user->autoframing));
if (user->chanvars) {
ast_cli(a->fd, " Variables :\n");
@@ -20916,7 +20942,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
{
int realtimepeers;
int realtimeregs;
- char codec_buf[SIPBUFSIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
const char *msg; /* temporary msg pointer */
struct sip_auth_container *credentials;
@@ -21069,12 +21095,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
}
ast_cli(a->fd, "\nGlobal Signalling Settings:\n");
ast_cli(a->fd, "---------------------------\n");
- ast_cli(a->fd, " Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, sip_cfg.caps);
- ast_cli(a->fd, "%s\n", codec_buf);
- ast_cli(a->fd, " Codec Order: ");
- print_codec_to_cli(a->fd, &default_prefs);
- ast_cli(a->fd, "\n");
+ ast_cli(a->fd, " Codecs: %s\n", ast_format_cap_get_names(sip_cfg.caps, &codec_buf));
ast_cli(a->fd, " Relax DTMF: %s\n", AST_CLI_YESNO(global_relaxdtmf));
ast_cli(a->fd, " RFC2833 Compensation: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_RFC2833_COMPENSATE)));
ast_cli(a->fd, " Symmetric RTP: %s\n", comedia_string(global_flags));
@@ -21233,12 +21254,12 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
if (cur->subscribed == NONE && !arg->subscriptions) {
/* set if SIP transfer in progress */
const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
- char formatbuf[SIPBUFSIZE/2];
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_cli(arg->fd, FORMAT, ast_sockaddr_stringify_addr(dst),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
- cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), ast_channel_nativeformats(cur->owner)) : "(nothing)",
+ cur->owner ? ast_format_cap_get_names(ast_channel_nativeformats(cur->owner), &codec_buf) : "(nothing)",
AST_CLI_YESNO(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)),
cur->needdestroy ? "(d)" : "",
cur->lastmsg ,
@@ -21479,7 +21500,8 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
if (!strncasecmp(cur->callid, a->argv[3], len)) {
struct ast_str *strbuf;
- char formatbuf[SIPBUFSIZE/2];
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
ast_cli(a->fd, "\n");
if (cur->subscribed != NONE) {
ast_cli(a->fd, " * Subscription (type: %s)\n", subscription_type2str(cur->subscribed));
@@ -21489,11 +21511,11 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
ast_cli(a->fd, " Curr. trans. direction: %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING) ? "Outgoing" : "Incoming");
ast_cli(a->fd, " Call-ID: %s\n", cur->callid);
ast_cli(a->fd, " Owner channel ID: %s\n", cur->owner ? ast_channel_name(cur->owner) : "<none>");
- ast_cli(a->fd, " Our Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->caps));
+ ast_cli(a->fd, " Our Codec Capability: %s\n", ast_format_cap_get_names(cur->caps, &codec_buf));
ast_cli(a->fd, " Non-Codec Capability (DTMF): %d\n", cur->noncodeccapability);
- ast_cli(a->fd, " Their Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->peercaps));
- ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->jointcaps));
- ast_cli(a->fd, " Format: %s\n", cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), ast_channel_nativeformats(cur->owner)) : "(nothing)" );
+ ast_cli(a->fd, " Their Codec Capability: %s\n", ast_format_cap_get_names(cur->peercaps, &codec_buf));
+ ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_format_cap_get_names(cur->jointcaps, &codec_buf));
+ ast_cli(a->fd, " Format: %s\n", cur->owner ? ast_format_cap_get_names(ast_channel_nativeformats(cur->owner), &codec_buf) : "(nothing)" );
ast_cli(a->fd, " T.38 support %s\n", AST_CLI_YESNO(cur->udptl != NULL));
ast_cli(a->fd, " Video support %s\n", AST_CLI_YESNO(cur->vrtp != NULL));
ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate);
@@ -22437,7 +22459,9 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
} else if (!strcasecmp(colname, "callerid_num")) {
ast_copy_string(buf, peer->cid_num, len);
} else if (!strcasecmp(colname, "codecs")) {
- ast_getformatname_multiple(buf, len -1, peer->caps);
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_format_cap_get_names(peer->caps, &codec_buf);
+ ast_copy_string(buf, ast_str_buffer(codec_buf), len);
} else if (!strcasecmp(colname, "encryption")) {
snprintf(buf, len, "%u", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP));
} else if (!strncasecmp(colname, "chanvar[", 8)) {
@@ -22452,12 +22476,14 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
}
} else if (!strncasecmp(colname, "codec[", 6)) {
char *codecnum;
- struct ast_format codec;
+ struct ast_format *codec;
codecnum = colname + 6; /* move past the '[' */
codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */
- if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &codec))) {
- ast_copy_string(buf, ast_getformatname(&codec), len);
+ codec = ast_format_cap_get_format(peer->caps, atoi(codecnum));
+ if (codec) {
+ ast_copy_string(buf, ast_format_get_name(codec), len);
+ ao2_ref(codec, -1);
} else {
buf[0] = '\0';
}
@@ -25476,7 +25502,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
}
ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE);
} else {
- ast_format_cap_copy(p->jointcaps, p->caps);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, p->caps, AST_MEDIA_TYPE_UNKNOWN);
ast_debug(1, "Hm.... No sdp for the moment\n");
/* Some devices signal they want to be put off hold by sending a re-invite
*without* an SDP, which is supposed to mean "Go back to your state"
@@ -25541,7 +25568,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
goto request_invite_cleanup;
}
} else { /* No SDP in invite, call control session */
- ast_format_cap_copy(p->jointcaps, p->caps);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, p->caps, AST_MEDIA_TYPE_UNKNOWN);
ast_debug(2, "No SDP in Invite, third party call control\n");
}
@@ -25855,7 +25883,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
if (p && (p->autokillid == -1)) {
const char *msg;
- if ((ast_format_cap_is_empty(p->jointcaps)))
+ if ((!ast_format_cap_count(p->jointcaps)))
msg = "488 Not Acceptable Here (codec error)";
else {
ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n");
@@ -29539,7 +29567,8 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
struct ast_channel *tmpc = NULL;
char *ext = NULL, *host;
char tmp[256];
- char tmp2[256];
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
char *dnid;
char *secret = NULL;
char *md5secret = NULL;
@@ -29562,14 +29591,14 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
* configured from sip.conf, and sip_tech.capabilities, which is
* hardwired to all audio formats.
*/
- if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
+ if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n",
- ast_getformatname_multiple(tmp, sizeof(tmp), cap),
- ast_getformatname_multiple(tmp2, sizeof(tmp2), sip_cfg.caps));
+ ast_format_cap_get_names(cap, &codec_buf),
+ ast_format_cap_get_names(sip_cfg.caps, &cap_buf));
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; /* Can't find codec to connect to host */
return NULL;
}
- ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_format_cap_get_names(cap, &codec_buf));
if (ast_strlen_zero(dest)) {
ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
@@ -29739,8 +29768,8 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
#if 0
printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host);
#endif
- ast_format_cap_append(p->prefcaps, cap);
- ast_format_cap_joint_copy(cap, p->caps, p->jointcaps);
+ ast_format_cap_append_from_cap(p->prefcaps, cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_get_compatible(cap, p->caps, p->jointcaps);
sip_pvt_lock(p);
@@ -30217,7 +30246,7 @@ static void set_peer_defaults(struct sip_peer *peer)
ast_string_field_set(peer, engine, default_engine);
ast_sockaddr_setnull(&peer->addr);
ast_sockaddr_setnull(&peer->defaddr);
- ast_format_cap_copy(peer->caps, sip_cfg.caps);
+ ast_format_cap_append_from_cap(peer->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN);
peer->maxcallbitrate = default_maxcallbitrate;
peer->rtptimeout = global_rtptimeout;
peer->rtpholdtimeout = global_rtpholdtimeout;
@@ -30243,7 +30272,6 @@ static void set_peer_defaults(struct sip_peer *peer)
peer->pickupgroup = 0;
peer->maxms = default_qualify;
peer->keepalive = default_keepalive;
- peer->prefs = default_prefs;
ast_string_field_set(peer, zone, default_zone);
peer->stimer.st_mode_oper = global_st_mode; /* Session-Timers */
peer->stimer.st_ref = global_st_refresher;
@@ -30279,7 +30307,7 @@ static struct sip_peer *temp_peer(const char *name)
return NULL;
}
- if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer");
return NULL;
}
@@ -30291,7 +30319,6 @@ static struct sip_peer *temp_peer(const char *name)
peer->selfdestruct = TRUE;
peer->host_dynamic = TRUE;
- peer->prefs = default_prefs;
reg_source_db(peer);
return peer;
@@ -30384,7 +30411,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
if (!(peer->endpoint = ast_endpoint_create("SIP", name))) {
return NULL;
}
- if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer");
return NULL;
}
@@ -30705,12 +30732,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
} else if (!strcasecmp(v->name, "namedpickupgroup")) {
peer->named_pickupgroups = ast_get_namedgroups(v->value);
} else if (!strcasecmp(v->name, "allow")) {
- int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, TRUE);
+ int error = ast_format_cap_update_by_allow_disallow(peer->caps, v->value, TRUE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
} else if (!strcasecmp(v->name, "disallow")) {
- int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, FALSE);
+ int error = ast_format_cap_update_by_allow_disallow(peer->caps, v->value, FALSE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
@@ -31104,14 +31131,11 @@ static int peer_markall_autopeers_func(void *device, void *arg, int flags)
*/
static void sip_set_default_format_capabilities(struct ast_format_cap *cap)
{
- struct ast_format tmp_fmt;
-
- ast_format_cap_remove_all(cap);
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_TESTLAW, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ALAW, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_H263, 0));
+ ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(cap, ast_format_ulaw, 0);
+ ast_format_cap_append(cap, ast_format_alaw, 0);
+ ast_format_cap_append(cap, ast_format_gsm, 0);
+ ast_format_cap_append(cap, ast_format_h263, 0);
}
static void display_nat_warning(const char *cat, int reason, struct ast_flags *flags) {
@@ -31276,7 +31300,6 @@ static int reload_config(enum channelreloadreason reason)
memset(&localaddr, 0, sizeof(localaddr));
memset(&externaddr, 0, sizeof(externaddr));
memset(&media_address, 0, sizeof(media_address));
- memset(&default_prefs, 0 , sizeof(default_prefs));
memset(&sip_cfg.outboundproxy, 0, sizeof(struct sip_proxy));
sip_cfg.outboundproxy.force = FALSE; /*!< Don't force proxy usage, use route: headers */
default_transports = AST_TRANSPORT_UDP;
@@ -31768,12 +31791,12 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "Invalid externtlsport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
}
} else if (!strcasecmp(v->name, "allow")) {
- int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, TRUE);
+ int error = ast_format_cap_update_by_allow_disallow(sip_cfg.caps, v->value, TRUE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
} else if (!strcasecmp(v->name, "disallow")) {
- int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, FALSE);
+ int error = ast_format_cap_update_by_allow_disallow(sip_cfg.caps, v->value, FALSE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
@@ -32565,8 +32588,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
memset(&p->tredirip, 0, sizeof(p->tredirip));
changed = 1;
}
- if (cap && !ast_format_cap_is_empty(cap) && !ast_format_cap_identical(p->redircaps, cap)) {
- ast_format_cap_copy(p->redircaps, cap);
+ if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(cap, p->redircaps)) {
+ ast_format_cap_remove_by_type(p->redircaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->redircaps, cap, AST_MEDIA_TYPE_UNKNOWN);
changed = 1;
}
@@ -32603,7 +32627,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
static void sip_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
{
struct sip_pvt *p = ast_channel_tech_pvt(chan);
- ast_format_cap_append(result, ast_format_cap_is_empty(p->peercaps) ? p->caps : p->peercaps);
+
+ ast_format_cap_append_from_cap(result, !ast_format_cap_count(p->peercaps) ? p->caps : p->peercaps, AST_MEDIA_TYPE_UNKNOWN);
}
static struct ast_rtp_glue sip_rtp_glue = {
@@ -34217,6 +34242,8 @@ static const struct ast_sip_api_tech chan_sip_api_provider = {
.sipinfo_send = sipinfo_send,
};
+static int unload_module(void);
+
/*!
* \brief Load the module
*
@@ -34232,14 +34259,17 @@ static int load_module(void)
ast_verbose("SIP channel loading...\n");
if (STASIS_MESSAGE_TYPE_INIT(session_timeout_type)) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (!(sip_tech.capabilities = ast_format_cap_alloc(0))) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (ast_sip_api_provider_register(&chan_sip_api_provider)) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
@@ -34254,24 +34284,28 @@ static int load_module(void)
if (!peers || !peers_by_ip || !dialogs || !dialogs_needdestroy || !dialogs_rtpcheck
|| !threadt) {
ast_log(LOG_ERROR, "Unable to create primary SIP container(s)\n");
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
- if (!(sip_cfg.caps = ast_format_cap_alloc(0))) {
+ if (!(sip_cfg.caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add_all_by_type(sip_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_append_by_type(sip_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
ASTOBJ_CONTAINER_INIT(&regl); /* Registry object list -- not searched for anything */
ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create scheduler context\n");
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (!(io = io_context_create())) {
ast_log(LOG_ERROR, "Unable to create I/O context\n");
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
@@ -34279,15 +34313,14 @@ static int load_module(void)
can_parse_xml = sip_is_xml_parsable();
if (reload_config(sip_reloadreason)) { /* Load the configuration from sip.conf */
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
/* Initialize bogus peer. Can be done first after reload_config() */
if (!(bogus_peer = temp_peer("(bogus_peer)"))) {
ast_log(LOG_ERROR, "Unable to create bogus_peer for authentication\n");
- io_context_destroy(io);
- ast_sched_context_destroy(sched);
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure the auth will always fail. */
@@ -34302,16 +34335,14 @@ static int load_module(void)
memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
if (ast_msg_tech_register(&sip_msg_tech)) {
- /* LOAD_FAILURE stops Asterisk, so cleanup is a moot point. */
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure we can register our sip channel type */
if (ast_channel_register(&sip_tech)) {
ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
- ao2_t_ref(bogus_peer, -1, "unref the bogus_peer");
- io_context_destroy(io);
- ast_sched_context_destroy(sched);
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
@@ -34358,13 +34389,13 @@ static int load_module(void)
initialize_escs();
if (sip_epa_register(&cc_epa_static_data)) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
if (sip_reqresp_parser_init() == -1) {
ast_log(LOG_ERROR, "Unable to initialize the SIP request and response parser\n");
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
@@ -34373,16 +34404,16 @@ static int load_module(void)
* in incoming PUBLISH requests
*/
if (ast_cc_agent_register(&sip_cc_agent_callbacks)) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
}
if (ast_cc_monitor_register(&sip_cc_monitor_callbacks)) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
if (!(sip_monitor_instances = ao2_container_alloc(37, sip_monitor_instance_hash_fn, sip_monitor_instance_cmp_fn))) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
@@ -34523,7 +34554,7 @@ static int unload_module(void)
ast_mutex_lock(&authl_lock);
if (authl) {
- ao2_t_ref(authl, -1, "Removing global authentication");
+ ao2_t_cleanup(authl, "Removing global authentication");
authl = NULL;
}
ast_mutex_unlock(&authl_lock);
@@ -34568,15 +34599,15 @@ static int unload_module(void)
ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
}
- ao2_t_ref(bogus_peer, -1, "unref the bogus_peer");
+ ao2_t_cleanup(bogus_peer, "unref the bogus_peer");
- ao2_t_ref(peers, -1, "unref the peers table");
- ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table");
- ao2_t_ref(dialogs, -1, "unref the dialogs table");
- ao2_t_ref(dialogs_needdestroy, -1, "unref dialogs_needdestroy");
- ao2_t_ref(dialogs_rtpcheck, -1, "unref dialogs_rtpcheck");
- ao2_t_ref(threadt, -1, "unref the thread table");
- ao2_t_ref(sip_monitor_instances, -1, "unref the sip_monitor_instances table");
+ ao2_t_cleanup(peers, "unref the peers table");
+ ao2_t_cleanup(peers_by_ip, "unref the peers_by_ip table");
+ ao2_t_cleanup(dialogs, "unref the dialogs table");
+ ao2_t_cleanup(dialogs_needdestroy, "unref dialogs_needdestroy");
+ ao2_t_cleanup(dialogs_rtpcheck, "unref dialogs_rtpcheck");
+ ao2_t_cleanup(threadt, "unref the thread table");
+ ao2_t_cleanup(sip_monitor_instances, "unref the sip_monitor_instances table");
clear_sip_domains();
sip_cfg.contact_acl = ast_free_acl_list(sip_cfg.contact_acl);
@@ -34604,8 +34635,10 @@ static int unload_module(void)
notify_types = NULL;
}
- ast_format_cap_destroy(sip_tech.capabilities);
- sip_cfg.caps = ast_format_cap_destroy(sip_cfg.caps);
+ ao2_cleanup(sip_tech.capabilities);
+ sip_tech.capabilities = NULL;
+ ao2_cleanup(sip_cfg.caps);
+ sip_cfg.caps = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(session_timeout_type);
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 49ff8d548..e4882dbba 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -84,6 +84,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/parking.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<manager name="SKINNYdevices" language="en_US">
@@ -146,8 +147,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#ifdef AST_DEVMODE
static int skinnydebug = 0;
char dbgcli_buf[256];
-char dbgreg_buf[256];
-char dbgsub_buf[256];
#define DEBUG_GENERAL (1 << 1)
#define DEBUG_SUB (1 << 2)
#define DEBUG_PACKET (1 << 3)
@@ -174,7 +173,6 @@ static const char tdesc[] = "Skinny Client Control Protocol (Skinny)";
static const char config[] = "skinny.conf";
static struct ast_format_cap *default_cap;
-static struct ast_codec_pref default_prefs;
enum skinny_codecs {
SKINNY_CODEC_ALAW = 2,
@@ -1454,8 +1452,6 @@ struct skinny_subchannel {
int amaflags; \
int instance; \
int group; \
- struct ast_codec_pref confprefs; \
- struct ast_codec_pref prefs; \
int nonCodecCapability; \
int immediate; \
int nat; \
@@ -1568,7 +1564,6 @@ struct skinny_addon {
int hookstate; \
int lastlineinstance; \
int lastcallreference; \
- struct ast_codec_pref confprefs; \
int earlyrtp; \
int transfer; \
int callwaiting; \
@@ -1679,11 +1674,11 @@ static struct skinny_line *skinny_line_alloc(void)
return NULL;
}
- l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- l->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ l->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!l->cap || !l->confcap) {
- l->cap = ast_format_cap_destroy(l->cap);
- l->confcap = ast_format_cap_destroy(l->confcap);
+ ao2_cleanup(l->cap);
+ ao2_cleanup(l->confcap);
ast_free(l);
return NULL;
}
@@ -1691,8 +1686,8 @@ static struct skinny_line *skinny_line_alloc(void)
}
static struct skinny_line *skinny_line_destroy(struct skinny_line *l)
{
- l->cap = ast_format_cap_destroy(l->cap);
- l->confcap = ast_format_cap_destroy(l->confcap);
+ ao2_ref(l->cap, -1);
+ ao2_ref(l->confcap, -1);
l->named_callgroups = ast_unref_namedgroups(l->named_callgroups);
l->named_pickupgroups = ast_unref_namedgroups(l->named_pickupgroups);
ast_free(l->container);
@@ -1706,12 +1701,12 @@ static struct skinny_device *skinny_device_alloc(const char *dname)
return NULL;
}
- d->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- d->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ d->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ d->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
d->endpoint = ast_endpoint_create("Skinny", dname);
if (!d->cap || !d->confcap || !d->endpoint) {
- d->cap = ast_format_cap_destroy(d->cap);
- d->confcap = ast_format_cap_destroy(d->confcap);
+ ao2_cleanup(d->cap);
+ ao2_cleanup(d->confcap);
ast_free(d);
return NULL;
}
@@ -1722,8 +1717,8 @@ static struct skinny_device *skinny_device_alloc(const char *dname)
}
static struct skinny_device *skinny_device_destroy(struct skinny_device *d)
{
- d->cap = ast_format_cap_destroy(d->cap);
- d->confcap = ast_format_cap_destroy(d->confcap);
+ ao2_ref(d->cap, -1);
+ ao2_ref(d->confcap, -1);
ast_endpoint_shutdown(d->endpoint);
ast_free(d);
return NULL;
@@ -2103,51 +2098,49 @@ static struct skinny_speeddial *find_speeddial_by_instance(struct skinny_device
return sd;
}
-static struct ast_format *codec_skinny2ast(enum skinny_codecs skinnycodec, struct ast_format *result)
+static struct ast_format *codec_skinny2ast(enum skinny_codecs skinnycodec)
{
switch (skinnycodec) {
case SKINNY_CODEC_ALAW:
- return ast_format_set(result, AST_FORMAT_ALAW, 0);
+ return ast_format_alaw;
case SKINNY_CODEC_ULAW:
- return ast_format_set(result, AST_FORMAT_ULAW, 0);
+ return ast_format_ulaw;
case SKINNY_CODEC_G722:
- return ast_format_set(result, AST_FORMAT_G722, 0);
+ return ast_format_g722;
case SKINNY_CODEC_G723_1:
- return ast_format_set(result, AST_FORMAT_G723_1, 0);
+ return ast_format_g723;
case SKINNY_CODEC_G729A:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case SKINNY_CODEC_G726_32:
- return ast_format_set(result, AST_FORMAT_G726_AAL2, 0); /* XXX Is this right? */
+ return ast_format_g726; /* XXX Is this right? */
case SKINNY_CODEC_H261:
- return ast_format_set(result, AST_FORMAT_H261, 0);
+ return ast_format_h261;
case SKINNY_CODEC_H263:
- return ast_format_set(result, AST_FORMAT_H263 ,0);
+ return ast_format_h263;
default:
- ast_format_clear(result);
- return result;
+ return ast_format_none;
}
}
static int codec_ast2skinny(const struct ast_format *astcodec)
{
- switch (astcodec->id) {
- case AST_FORMAT_ALAW:
+ if (ast_format_cmp(astcodec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_ALAW;
- case AST_FORMAT_ULAW:
+ } else if (ast_format_cmp(astcodec, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_ULAW;
- case AST_FORMAT_G722:
+ } else if (ast_format_cmp(astcodec, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G722;
- case AST_FORMAT_G723_1:
+ } else if (ast_format_cmp(astcodec, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G723_1;
- case AST_FORMAT_G729A:
+ } else if (ast_format_cmp(astcodec, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G729A;
- case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
+ } else if (ast_format_cmp(astcodec, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G726_32;
- case AST_FORMAT_H261:
+ } else if (ast_format_cmp(astcodec, ast_format_h261) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_H261;
- case AST_FORMAT_H263:
+ } else if (ast_format_cmp(astcodec, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_H263;
- default:
+ } else {
return 0;
}
}
@@ -2312,13 +2305,8 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
instance++;
}
AST_LIST_TRAVERSE(&d->lines, l, list) {
- ast_format_cap_joint_copy(l->confcap, d->cap, l->cap);
- l->prefs = l->confprefs;
- if (!l->prefs.order[0]) {
- l->prefs = d->confprefs;
- }
- /* l->capability = d->capability;
- l->prefs = d->prefs; */
+ ast_format_cap_get_compatible(l->confcap, d->cap, l->cap);
+ /* l->capability = d->capability; */
l->instance = instance;
l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
set_callforwards(l, NULL, SKINNY_CFWD_ALL|SKINNY_CFWD_BUSY|SKINNY_CFWD_NOANSWER);
@@ -2656,23 +2644,27 @@ static void transmit_connect(struct skinny_device *d, struct skinny_subchannel *
{
struct skinny_req *req;
struct skinny_line *l = sub->line;
- struct ast_format_list fmt;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ unsigned int framing;
if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
return;
- ast_best_codec(l->cap, &tmpfmt);
- fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
+
+ tmpfmt = ast_format_cap_get_format(l->cap, 0);
+ framing = ast_format_cap_get_format_framing(l->cap, tmpfmt);
req->data.openreceivechannel.conferenceId = htolel(sub->callid);
req->data.openreceivechannel.partyId = htolel(sub->callid);
- req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
- req->data.openreceivechannel.capability = htolel(codec_ast2skinny(&fmt.format));
+ req->data.openreceivechannel.packets = htolel(framing);
+ req->data.openreceivechannel.capability = htolel(codec_ast2skinny(tmpfmt));
req->data.openreceivechannel.echo = htolel(0);
req->data.openreceivechannel.bitrate = htolel(0);
SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting OPEN_RECEIVE_CHANNEL_MESSAGE to %s, confid %u, partyid %u, ms %d, fmt %d, echo %d, brate %d\n",
- d->name, sub->callid, sub->callid, fmt.cur_ms, codec_ast2skinny(&fmt.format), 0, 0);
+ d->name, sub->callid, sub->callid, framing, codec_ast2skinny(tmpfmt), 0, 0);
+
+ ao2_ref(tmpfmt, -1);
+
transmit_response(d, req);
}
@@ -3033,7 +3025,8 @@ static void transmit_stopmediatransmission(struct skinny_device *d, struct skinn
transmit_response(d, req);
}
-static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, struct ast_format_list fmt)
+static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest,
+ struct ast_format *format, unsigned int framing)
{
struct skinny_req *req;
@@ -3044,8 +3037,8 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin
req->data.startmedia_ip4.passThruPartyId = htolel(sub->callid);
req->data.startmedia_ip4.remoteIp = dest.sin_addr.s_addr;
req->data.startmedia_ip4.remotePort = htolel(ntohs(dest.sin_port));
- req->data.startmedia_ip4.packetSize = htolel(fmt.cur_ms);
- req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(&fmt.format));
+ req->data.startmedia_ip4.packetSize = htolel(framing);
+ req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(format));
req->data.startmedia_ip4.qualifier.precedence = htolel(127);
req->data.startmedia_ip4.qualifier.vad = htolel(0);
req->data.startmedia_ip4.qualifier.packets = htolel(0);
@@ -3057,8 +3050,8 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin
req->data.startmedia_ip6.passThruPartyId = htolel(sub->callid);
memcpy(req->data.startmedia_ip6.remoteIp, &dest.sin_addr.s_addr, sizeof(dest.sin_addr.s_addr));
req->data.startmedia_ip6.remotePort = htolel(ntohs(dest.sin_port));
- req->data.startmedia_ip6.packetSize = htolel(fmt.cur_ms);
- req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(&fmt.format));
+ req->data.startmedia_ip6.packetSize = htolel(framing);
+ req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(format));
req->data.startmedia_ip6.qualifier.precedence = htolel(127);
req->data.startmedia_ip6.qualifier.vad = htolel(0);
req->data.startmedia_ip6.qualifier.packets = htolel(0);
@@ -3066,7 +3059,7 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin
}
SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting START_MEDIA_TRANSMISSION_MESSAGE to %s, callid %u, passthrupartyid %u, ip %s:%d, ms %d, fmt %d, prec 127\n",
- d->name, sub->callid, sub->callid, ast_inet_ntoa(dest.sin_addr), dest.sin_port, fmt.cur_ms, codec_ast2skinny(&fmt.format));
+ d->name, sub->callid, sub->callid, ast_inet_ntoa(dest.sin_addr), dest.sin_port, framing, codec_ast2skinny(format));
transmit_response(d, req);
}
@@ -3643,7 +3636,6 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
struct skinny_subchannel *sub;
struct skinny_line *l;
struct skinny_device *d;
- struct ast_format_list fmt;
struct sockaddr_in us = { 0, };
struct sockaddr_in them = { 0, };
struct ast_sockaddr them_tmp;
@@ -3662,7 +3654,8 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
d = l->device;
if (rtp){
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ unsigned int framing;
ast_rtp_instance_get_remote_address(rtp, &them_tmp);
ast_sockaddr_to_sin(&them_tmp, &them);
@@ -3671,20 +3664,22 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
SKINNY_DEBUG(DEBUG_AUDIO, 4, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port));
- ast_best_codec(l->cap, &tmpfmt);
- fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(l->cap, 0);
+ framing = ast_format_cap_get_format_framing(l->cap, tmpfmt);
- SKINNY_DEBUG(DEBUG_AUDIO, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);
+ SKINNY_DEBUG(DEBUG_AUDIO, 4, "Setting payloadType to '%s' (%d ms)\n", ast_format_get_name(tmpfmt), framing);
if (!(l->directmedia) || (l->nat)){
ast_rtp_instance_get_local_address(rtp, &us_tmp);
ast_sockaddr_to_sin(&us_tmp, &us);
us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
- transmit_startmediatransmission(d, sub, us, fmt);
+ transmit_startmediatransmission(d, sub, us, tmpfmt, framing);
} else {
- transmit_startmediatransmission(d, sub, them, fmt);
+ transmit_startmediatransmission(d, sub, them, tmpfmt, framing);
}
+ ao2_ref(tmpfmt, -1);
+
return 0;
}
/* Need a return here to break the bridge */
@@ -4067,25 +4062,6 @@ static char *device2str(int type)
}
}
-/*! \brief Print codec list from preference to CLI/manager */
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
-{
- int x;
- struct ast_format tmpfmt;
-
- for(x = 0; x < 32 ; x++) {
- ast_codec_pref_index(pref, x, &tmpfmt);
- if (!tmpfmt.id)
- break;
- ast_cli(fd, "%s", ast_getformatname(&tmpfmt));
- ast_cli(fd, ":%d", pref->framing[x]);
- if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt))
- ast_cli(fd, ",");
- }
- if (!x)
- ast_cli(fd, "none");
-}
-
static char *_skinny_show_devices(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char * const *argv)
{
struct skinny_device *d;
@@ -4204,7 +4180,7 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s
struct skinny_speeddial *sd;
struct skinny_addon *sa;
struct skinny_serviceurl *surl;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
if (argc < 4) {
return CLI_SHOWUSAGE;
@@ -4238,12 +4214,8 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s
ast_cli(fd, "Ip address: %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
ast_cli(fd, "Port: %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
ast_cli(fd, "Device Type: %s\n", device2str(d->type));
- ast_cli(fd, "Conf Codecs:");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->confcap);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, "Neg Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->cap);
- ast_cli(fd, "%s\n", codec_buf);
+ ast_cli(fd, "Conf Codecs: %s\n", ast_format_cap_get_names(d->confcap, &codec_buf));
+ ast_cli(fd, "Neg Codecs: %s\n", ast_format_cap_get_names(d->cap, &codec_buf));
ast_cli(fd, "Registered: %s\n", (d->session ? "Yes" : "No"));
ast_cli(fd, "Lines: %d\n", numlines);
AST_LIST_TRAVERSE(&d->lines, l, list) {
@@ -4270,12 +4242,8 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s
astman_append(s, "Ipaddress: %s\r\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
astman_append(s, "Port: %d\r\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
astman_append(s, "DeviceType: %s\r\n", device2str(d->type));
- astman_append(s, "Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->confcap);
- astman_append(s, "%s\r\n", codec_buf);
- astman_append(s, "CodecOrder: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->cap);
- astman_append(s, "%s\r\n", codec_buf);
+ astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(d->confcap, &codec_buf));
+ astman_append(s, "CodecOrder: %s\r\n", ast_format_cap_get_names(d->cap, &codec_buf));
astman_append(s, "Devicestatus: %s\r\n", (d->session?"registered":"unregistered"));
astman_append(s, "NumberOfLines: %d\r\n", numlines);
AST_LIST_TRAVERSE(&d->lines, l, list) {
@@ -4468,9 +4436,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
struct skinny_device *d;
struct skinny_line *l;
struct skinny_subline *subline;
- struct ast_codec_pref *pref;
- int x = 0;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
char group_buf[256];
char cbuf[256];
@@ -4536,15 +4502,8 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
ast_cli(fd, "immediate: %s\n", (l->immediate ? "Yes" : "No"));
ast_cli(fd, "Group: %d\n", l->group);
ast_cli(fd, "Parkinglot: %s\n", S_OR(l->parkinglot, "<not set>"));
- ast_cli(fd, "Conf Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, "Neg Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->cap);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, "Codec Order: (");
- print_codec_to_cli(fd, &l->prefs);
- ast_cli(fd, ")\n");
+ ast_cli(fd, "Conf Codecs: %s\n", ast_format_cap_get_names(l->confcap, &codec_buf));
+ ast_cli(fd, "Neg Codecs: %s\n", ast_format_cap_get_names(l->cap, &codec_buf));
if (AST_LIST_FIRST(&l->sublines)) {
ast_cli(fd, "Sublines:\n");
AST_LIST_TRAVERSE(&l->sublines, subline, list) {
@@ -4592,19 +4551,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No"));
astman_append(s, "Group: %d\r\n", l->group);
astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>"));
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap);
- astman_append(s, "Codecs: %s\r\n", codec_buf);
- astman_append(s, "CodecOrder: ");
- pref = &l->prefs;
- for(x = 0; x < 32 ; x++) {
- struct ast_format tmpfmt;
- ast_codec_pref_index(pref, x, &tmpfmt);
- if (!tmpfmt.id)
- break;
- astman_append(s, "%s", ast_getformatname(&tmpfmt));
- if (x < 31 && ast_codec_pref_index(pref, x+1, &tmpfmt))
- astman_append(s, ",");
- }
+ astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(l->confcap, &codec_buf));
astman_append(s, "\r\n");
}
}
@@ -4802,7 +4749,7 @@ static void start_rtp(struct skinny_subchannel *sub)
struct ast_sockaddr bindaddr_tmp;
skinny_locksub(sub);
- /* Allocate the RTP */
+ SKINNY_DEBUG(DEBUG_AUDIO, 3, "Sub %u - Starting RTP\n", sub->callid);
ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
if (hasvideo)
@@ -4828,14 +4775,14 @@ static void start_rtp(struct skinny_subchannel *sub)
if (sub->rtp) {
ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat);
+ /* Set frame packetization */
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(sub->rtp),
+ ast_format_cap_get_framing(l->cap));
}
if (sub->vrtp) {
ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat);
}
- /* Set Frame packetization */
- if (sub->rtp)
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs);
/* Create the RTP connection */
transmit_connect(d, sub);
@@ -5097,9 +5044,17 @@ static struct ast_frame *skinny_rtp_read(struct skinny_subchannel *sub)
if (ast) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
- ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(ast, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(ast, ast_channel_readformat(ast));
ast_set_write_format(ast, ast_channel_writeformat(ast));
}
@@ -5130,13 +5085,13 @@ static int skinny_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
} else {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char buf[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return -1;
}
}
@@ -5403,23 +5358,33 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
struct skinny_subchannel *sub;
struct skinny_device *d = l->device;
struct ast_variable *v = NULL;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ struct ast_format_cap *caps;
if (!l->device || !l->device->session) {
ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
return NULL;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, assignedids, requestor, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ ao2_ref(caps, -1);
return NULL;
} else {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
sub = ast_calloc(1, sizeof(*sub));
if (!sub) {
ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
ast_channel_unlock(tmp);
ast_channel_unref(tmp);
+ ao2_ref(caps, -1);
return NULL;
} else {
skinny_set_owner(sub, tmp);
@@ -5452,25 +5417,28 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &skinny_tech);
ast_channel_tech_pvt_set(tmp, sub);
- ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
- // Should throw an error
- ast_format_cap_copy(ast_channel_nativeformats(tmp), default_cap);
+ if (!ast_format_cap_count(l->cap)) {
+ ast_format_cap_append_from_cap(caps, l->cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append_from_cap(caps, default_cap, AST_MEDIA_TYPE_UNKNOWN);
}
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_new: tmp->nativeformats=%s fmt=%s\n",
- ast_getformatname_multiple(dbgsub_buf, sizeof(dbgsub_buf), ast_channel_nativeformats(tmp)),
- ast_getformatname(&tmpfmt));
+ ast_format_cap_get_names(ast_channel_nativeformats(tmp), &codec_buf),
+ ast_format_get_name(tmpfmt));
if (sub->rtp) {
ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
}
if (state == AST_STATE_RING) {
ast_channel_rings_set(tmp, 1);
}
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
if (!ast_strlen_zero(l->language))
ast_channel_language_set(tmp, l->language);
@@ -6676,7 +6644,8 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny
struct skinny_device *d = s->device;
struct skinny_line *l;
uint32_t count = 0;
- struct ast_format_cap *codecs = ast_format_cap_alloc(0);
+ struct ast_format_cap *codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_str *codec_buf = ast_str_alloca(64);
int i;
if (!codecs) {
@@ -6690,23 +6659,23 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny
}
for (i = 0; i < count; i++) {
- struct ast_format acodec;
+ struct ast_format *acodec;
int scodec = 0;
scodec = letohl(req->data.caps.caps[i].codec);
- codec_skinny2ast(scodec, &acodec);
- SKINNY_DEBUG(DEBUG_AUDIO, 4, "Adding codec capability %s (%d)\n", ast_getformatname(&acodec), scodec);
- ast_format_cap_add(codecs, &acodec);
+ acodec = codec_skinny2ast(scodec);
+ SKINNY_DEBUG(DEBUG_AUDIO, 4, "Adding codec capability %s (%d)\n", ast_format_get_name(acodec), scodec);
+ ast_format_cap_append(codecs, acodec, 0);
}
- ast_format_cap_joint_copy(d->confcap, codecs, d->cap);
- SKINNY_DEBUG(DEBUG_AUDIO, 4, "Device capability set to '%s'\n", ast_getformatname_multiple(dbgreg_buf, sizeof(dbgreg_buf), d->cap));
+ ast_format_cap_get_compatible(d->confcap, codecs, d->cap);
+ SKINNY_DEBUG(DEBUG_AUDIO, 4, "Device capability set to '%s'\n", ast_format_cap_get_names(d->cap, &codec_buf));
AST_LIST_TRAVERSE(&d->lines, l, list) {
ast_mutex_lock(&l->lock);
- ast_format_cap_joint_copy(l->confcap, d->cap, l->cap);
+ ast_format_cap_get_compatible(l->confcap, d->cap, l->cap);
ast_mutex_unlock(&l->lock);
}
- codecs = ast_format_cap_destroy(codecs);
+ ao2_ref(codecs, -1);
return 1;
}
@@ -6877,16 +6846,16 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
struct skinny_device *d = s->device;
struct skinny_line *l;
struct skinny_subchannel *sub;
- struct ast_format_list fmt;
struct sockaddr_in sin = { 0, };
struct sockaddr_in us = { 0, };
struct ast_sockaddr sin_tmp;
struct ast_sockaddr us_tmp;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
uint32_t addr;
int port;
int status;
int callid;
+ unsigned int framing;
status = (d->protocolversion<17) ? letohl(req->data.openreceivechannelack_ip4.status) : letohl(req->data.openreceivechannelack_ip6.status);
@@ -6937,12 +6906,14 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
SKINNY_DEBUG(DEBUG_PACKET, 4, "device ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
SKINNY_DEBUG(DEBUG_PACKET, 4, "asterisk ipaddr = %s:%d\n", ast_inet_ntoa(us.sin_addr), ntohs(us.sin_port));
- ast_best_codec(l->cap, &tmpfmt);
- fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(l->cap, 0);
+ framing = ast_format_cap_get_format_framing(l->cap, tmpfmt);
- SKINNY_DEBUG(DEBUG_PACKET, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);
+ SKINNY_DEBUG(DEBUG_PACKET, 4, "Setting payloadType to '%s' (%d ms)\n", ast_format_get_name(tmpfmt), framing);
- transmit_startmediatransmission(d, sub, us, fmt);
+ transmit_startmediatransmission(d, sub, us, tmpfmt, framing);
+
+ ao2_ref(tmpfmt, -1);
return 1;
}
@@ -7496,8 +7467,8 @@ static void skinny_session_cleanup(void *data)
if (l->device != d) {
continue;
}
- ast_format_cap_remove_all(l->cap);
- ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0);
+ ast_format_cap_remove_by_type(l->cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_update_by_allow_disallow(l->cap, "all", 0);
l->instance = 0;
unregister_exten(l);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
@@ -7713,8 +7684,9 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca
struct ast_channel *tmpc = NULL;
char tmp[256];
- if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
@@ -7870,10 +7842,10 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp
}
continue;
} else if (!strcasecmp(v->name, "allow")) {
- ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 1);
+ ast_format_cap_update_by_allow_disallow(default_cap, v->value, 1);
continue;
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(default_cap, v->value, 0);
continue;
}
}
@@ -8080,20 +8052,20 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp
}
} else if (!strcasecmp(v->name, "allow")) {
if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
- ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 1);
+ ast_format_cap_update_by_allow_disallow(CDEV->confcap, v->value, 1);
continue;
}
if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
- ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 1);
+ ast_format_cap_update_by_allow_disallow(CLINE->confcap, v->value, 1);
continue;
}
} else if (!strcasecmp(v->name, "disallow")) {
if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
- ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(CDEV->confcap, v->value, 0);
continue;
}
if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
- ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(CLINE->confcap, v->value, 0);
continue;
}
} else if (!strcasecmp(v->name, "version")) {
@@ -8303,7 +8275,7 @@ static struct skinny_line *config_line(const char *lname, struct ast_variable *v
memcpy(l, default_line, sizeof(*default_line));
ast_mutex_init(&l->lock);
ast_copy_string(l->name, lname, sizeof(l->name));
- ast_format_cap_copy(l->confcap, default_cap);
+ ast_format_cap_append_from_cap(l->confcap, default_cap, AST_MEDIA_TYPE_UNKNOWN);
AST_LIST_INSERT_TAIL(&lines, l, all);
ast_mutex_lock(&l->lock);
@@ -8362,7 +8334,7 @@ static struct skinny_device *config_device(const char *dname, struct ast_variabl
memcpy(d, default_device, sizeof(*default_device));
ast_mutex_init(&d->lock);
ast_copy_string(d->name, dname, sizeof(d->name));
- ast_format_cap_copy(d->confcap, default_cap);
+ ast_format_cap_append_from_cap(d->confcap, default_cap, AST_MEDIA_TYPE_UNKNOWN);
AST_LIST_INSERT_TAIL(&devices, d, list);
ast_mutex_lock(&d->lock);
@@ -8453,7 +8425,6 @@ static int config_load(void)
}
memset(&bindaddr, 0, sizeof(bindaddr));
- memset(&default_prefs, 0, sizeof(default_prefs));
immed_dialchar = '\0';
memset(&vmexten, '\0', sizeof(vmexten));
@@ -8482,7 +8453,6 @@ static int config_load(void)
bindaddr.sin_family = AF_INET;
/* load the lines sections */
- default_line->confprefs = default_prefs;
config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines"));
cat = ast_category_browse(cfg, "lines");
while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) {
@@ -8491,7 +8461,6 @@ static int config_load(void)
}
/* load the devices sections */
- default_device->confprefs = default_prefs;
config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices"));
cat = ast_category_browse(cfg, "devices");
while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) {
@@ -8678,17 +8647,18 @@ int skinny_reload(void)
static int load_module(void)
{
int res = 0;
- struct ast_format tmpfmt;
- if (!(default_cap = ast_format_cap_alloc(0))) {
+
+ if (!(default_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- if (!(skinny_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(skinny_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ ao2_ref(default_cap, -1);
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(skinny_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append_by_type(skinny_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append(default_cap, ast_format_ulaw, 0);
+ ast_format_cap_append(default_cap, ast_format_alaw, 0);
for (; res < ARRAY_LEN(soft_key_template_default); res++) {
soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
@@ -8696,11 +8666,23 @@ static int load_module(void)
/* load and parse config */
res = config_load();
if (res == -1) {
+ ao2_ref(skinny_tech.capabilities, -1);
+ ao2_ref(default_cap, -1);
return AST_MODULE_LOAD_DECLINE;
}
+ sched = ast_sched_context_create();
+ if (!sched) {
+ ao2_ref(skinny_tech.capabilities, -1);
+ ao2_ref(default_cap, -1);
+ ast_log(LOG_WARNING, "Unable to create schedule context\n");
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
/* Make sure we can register our skinny channel type */
if (ast_channel_register(&skinny_tech)) {
+ ao2_ref(default_cap, -1);
+ ao2_ref(skinny_tech.capabilities, -1);
ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
return -1;
}
@@ -8713,14 +8695,12 @@ static int load_module(void)
ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
- sched = ast_sched_context_create();
- if (!sched) {
- ast_log(LOG_WARNING, "Unable to create schedule context\n");
- return AST_MODULE_LOAD_FAILURE;
- }
if (ast_sched_start_thread(sched)) {
ast_sched_context_destroy(sched);
sched = NULL;
+ ast_channel_unregister(&skinny_tech);
+ ao2_ref(default_cap, -1);
+ ao2_ref(skinny_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
@@ -8738,6 +8718,7 @@ static int unload_module(void)
ast_rtp_glue_unregister(&skinny_rtp_glue);
ast_channel_unregister(&skinny_tech);
+ ao2_cleanup(skinny_tech.capabilities);
ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
ast_manager_unregister("SKINNYdevices");
@@ -8797,8 +8778,7 @@ static int unload_module(void)
if (con)
ast_context_destroy(con, "Skinny");
- default_cap = ast_format_cap_destroy(default_cap);
- skinny_tech.capabilities = ast_format_cap_destroy(skinny_tech.capabilities);
+ ao2_ref(default_cap, -1);
return 0;
}
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 7525f3921..3f6fd01c8 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -78,6 +78,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
#define DEFAULTCONTEXT "default"
#define DEFAULTCALLERID "Unknown"
@@ -1933,7 +1934,7 @@ static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src
struct ast_format_cap *tmp = src->cap;
memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
src->cap = tmp;
- ast_format_cap_copy(src->cap, dst->cap);
+ ast_format_cap_append_from_cap(src->cap, dst->cap, AST_MEDIA_TYPE_UNKNOWN);
}
static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
@@ -1941,7 +1942,7 @@ static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
if (!l) {
return NULL;
}
- l->cap = ast_format_cap_destroy(l->cap);
+ ao2_ref(l->cap, -1);
ast_free(l);
return NULL;
}
@@ -1953,7 +1954,7 @@ static struct unistim_line *unistim_line_alloc(void)
return NULL;
}
- if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_free(l);
return NULL;
}
@@ -2699,15 +2700,15 @@ static void send_start_rtp(struct unistim_subchannel *sub)
if (unistimdebug) {
ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
ast_inet_ntoa(us.sin_addr),
- htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
+ htons(us.sin_port), ast_format_get_name(ast_channel_readformat(sub->owner)));
ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
ast_inet_ntoa(public.sin_addr));
}
pte = sub->parent->parent->session;
codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
- if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
- (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
+ if ((ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_alaw) == AST_FORMAT_CMP_EQUAL)) {
if (unistimdebug) {
ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
}
@@ -2804,17 +2805,17 @@ static void send_start_rtp(struct unistim_subchannel *sub)
/* Codec */
buffsend[40] = codec;
buffsend[41] = codec;
- if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
+ if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
- } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
+ } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
- } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
+ } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
- } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
+ } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
} else {
ast_log(LOG_WARNING, "Unsupported codec %s!\n",
- ast_getformatname(ast_channel_readformat(sub->owner)));
+ ast_format_get_name(ast_channel_readformat(sub->owner)));
}
/* Source port for transmit RTP and Destination port for receiving RTP */
buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
@@ -2883,18 +2884,20 @@ static void start_rtp(struct unistim_subchannel *sub)
sin.sin_port = htons(find_rtp_port(sub));
ast_sockaddr_from_sin(&sin_tmp, &sin);
ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
- if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
- struct ast_format tmpfmt;
- char tmp[256];
- ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner)) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format *tmpfmt;
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(sub->owner), 0);
ast_log(LOG_WARNING,
"Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
- ast_getformatname(ast_channel_readformat(sub->owner)),
- ast_getformatname(&tmpfmt),
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
+ ast_format_get_name(ast_channel_readformat(sub->owner)),
+ ast_format_get_name(tmpfmt),
+ ast_format_cap_get_names(ast_channel_nativeformats(sub->owner), &cap_buf));
- ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
+ ast_channel_set_readformat(sub->owner, tmpfmt);
+ ast_channel_set_writeformat(sub->owner, tmpfmt);
+ ao2_ref(tmpfmt, -1);
}
send_start_rtp(sub);
ast_mutex_unlock(&sub->lock);
@@ -5132,14 +5135,21 @@ static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
if (sub->owner) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format))) {
- char tmp[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_format_cap *caps;
+
ast_debug(1,
"Oooh, format changed from %s to %s\n",
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)),
- ast_getformatname(&f->subclass.format));
-
- ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
+ ast_format_cap_get_names(ast_channel_nativeformats(sub->owner), &cap_buf),
+ ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(sub->owner, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
}
@@ -5175,14 +5185,15 @@ static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
} else {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char tmp[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return -1;
}
}
@@ -5661,9 +5672,10 @@ static int unistim_send_mwi_to_peer(struct unistim_line *peer, unsigned int tick
/* called from unistim_request (calls from the pbx ) */
static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps;
struct ast_channel *tmp;
struct unistim_line *l;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
if (!sub) {
ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
@@ -5673,6 +5685,12 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
return NULL;
}
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
l = sub->parent;
tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
l->parent->context, assignedids, requestor, l->amaflags, "USTM/%s@%s-%p", l->name, l->parent->name, sub);
@@ -5681,24 +5699,32 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
}
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ ao2_ref(caps, -1);
return NULL;
}
ast_channel_stage_snapshot(tmp);
- ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
- ast_format_cap_copy(ast_channel_nativeformats(tmp), global_cap);
+ if (ast_format_cap_count(l->cap)) {
+ ast_format_cap_append_from_cap(caps, l->cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append_from_cap(caps, global_cap, AST_MEDIA_TYPE_UNKNOWN);
}
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
if (unistimdebug) {
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *native_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *global_buf = ast_str_alloca(64);
+
ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
- ast_getformatname(&tmpfmt),
- ast_getformatname_multiple(tmp1, sizeof(tmp1), ast_channel_nativeformats(tmp)),
- ast_getformatname_multiple(tmp2, sizeof(tmp2), l->cap),
- ast_getformatname_multiple(tmp3, sizeof(tmp3), global_cap));
+ ast_format_get_name(tmpfmt),
+ ast_format_cap_get_names(ast_channel_nativeformats(tmp), &native_buf),
+ ast_format_cap_get_names(l->cap, &cap_buf),
+ ast_format_cap_get_names(global_cap, &global_buf));
}
if ((sub->rtp) && (sub->subtype == 0)) {
if (unistimdebug) {
@@ -5716,10 +5742,13 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
ast_channel_rings_set(tmp, 1);
}
ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
+
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
+
ast_channel_tech_pvt_set(tmp, sub);
ast_channel_tech_set(tmp, &unistim_tech);
@@ -5900,12 +5929,14 @@ static struct ast_channel *unistim_request(const char *type, struct ast_format_c
struct unistim_device *d;
struct ast_channel *tmpc = NULL;
char tmp[256];
- char tmp2[256];
- if (!(ast_format_cap_has_joint(cap, global_cap))) {
+ if (!(ast_format_cap_iscompatible(cap, global_cap))) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *global_buf = ast_str_alloca(64);
ast_log(LOG_NOTICE,
"Asked to get a channel of unsupported format %s while capability is %s\n",
- ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_getformatname_multiple(tmp, sizeof(tmp), global_cap));
+ ast_format_cap_get_names(cap, &cap_buf),
+ ast_format_cap_get_names(global_cap, &global_buf));
return NULL;
}
@@ -5956,7 +5987,8 @@ static struct ast_channel *unistim_request(const char *type, struct ast_format_c
}
sub->subtype = SUB_RING;
sub->softkey = -1;
- ast_format_cap_copy(sub->parent->cap, cap);
+
+ ast_format_cap_append_from_cap(sub->parent->cap, cap, AST_MEDIA_TYPE_UNKNOWN);
tmpc = unistim_new(sub, AST_STATE_DOWN, assignedids, requestor);
if (!tmpc) {
ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
@@ -5975,6 +6007,7 @@ static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_
struct unistim_line *line;
struct unistim_subchannel *sub;
struct unistimsession *s;
+ struct ast_str *cap_buf = ast_str_alloca(64);
switch (cmd) {
case CLI_INIT:
@@ -6005,11 +6038,10 @@ static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_
device, device->selected, device->height);
AST_LIST_LOCK(&device->lines);
AST_LIST_TRAVERSE(&device->lines,line,list) {
- char tmp2[256];
ast_cli(a->fd,
"->name=%s fullname=%s exten=%s callid=%s cap=%s line=%p\n",
line->name, line->fullname, line->exten, line->cid_num,
- ast_getformatname_multiple(tmp2, sizeof(tmp2), line->cap), line);
+ ast_format_cap_get_names(line->cap, &cap_buf), line);
}
AST_LIST_UNLOCK(&device->lines);
@@ -6595,7 +6627,7 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var
ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
}
}
- ast_format_cap_copy(l->cap, global_cap);
+ ast_format_cap_append_from_cap(l->cap, global_cap, AST_MEDIA_TYPE_UNKNOWN);
l->parent = d;
linecnt++;
AST_LIST_LOCK(&d->lines);
@@ -7011,17 +7043,18 @@ static struct ast_rtp_glue unistim_rtp_glue = {
int load_module(void)
{
int res;
- struct ast_format tmpfmt;
- if (!(global_cap = ast_format_cap_alloc(0))) {
+
+ if (!(global_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
goto buff_failed;
}
- if (!(unistim_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(unistim_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
goto buff_failed;
}
- ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
- ast_format_cap_copy(unistim_tech.capabilities, global_cap);
+ ast_format_cap_append(global_cap, ast_format_ulaw, 0);
+ ast_format_cap_append(global_cap, ast_format_alaw, 0);
+ ast_format_cap_append_from_cap(unistim_tech.capabilities, global_cap, AST_MEDIA_TYPE_AUDIO);
+
if (!(buff = ast_malloc(SIZE_PAGE))) {
goto buff_failed;
}
@@ -7040,6 +7073,10 @@ int load_module(void)
res = reload_config();
if (res) {
+ ao2_ref(unistim_tech.capabilities, -1);
+ ao2_ref(global_cap, -1);
+ ast_sched_context_destroy(sched);
+ io_context_destroy(io);
return AST_MODULE_LOAD_DECLINE;
}
/* Make sure we can register our unistim channel type */
@@ -7066,9 +7103,11 @@ sched_failed:
io_failed:
ast_free(buff);
buff = NULL;
- global_cap = ast_format_cap_destroy(global_cap);
- unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
buff_failed:
+ ao2_cleanup(global_cap);
+ global_cap = NULL;
+ ao2_cleanup(unistim_tech.capabilities);
+ unistim_tech.capabilities = NULL;
return AST_MODULE_LOAD_FAILURE;
}
@@ -7082,6 +7121,7 @@ static int unload_module(void)
ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
ast_channel_unregister(&unistim_tech);
+ ao2_cleanup(unistim_tech.capabilities);
ast_rtp_glue_unregister(&unistim_rtp_glue);
ast_mutex_lock(&monlock);
@@ -7099,8 +7139,7 @@ static int unload_module(void)
if (unistimsock > -1) {
close(unistimsock);
}
- global_cap = ast_format_cap_destroy(global_cap);
- unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
+ ao2_ref(global_cap, -1);
return 0;
}
diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc
index f1a45ab63..181e50aee 100644
--- a/channels/chan_vpb.cc
+++ b/channels/chan_vpb.cc
@@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
}
#include <sys/socket.h>
@@ -766,11 +767,10 @@ static void get_callerid_ast(struct vpb_pvt *p)
#endif
vpb_record_buf_start(p->handle, VPB_MULAW);
while ((rc == 0) && (sam_count < 8000 * 3)) {
- struct ast_format tmpfmt;
vrc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));
if (vrc != VPB_OK)
ast_log(LOG_ERROR, "%s: Caller ID couldn't read audio buffer!\n", p->dev);
- rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
+ rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), ast_format_ulaw);
#ifdef ANALYSE_CID
vpb_wave_write(ws, (char *)buf, sizeof(buf));
#endif
@@ -2070,46 +2070,41 @@ static struct ast_frame *vpb_read(struct ast_channel *ast)
static inline AudioCompress ast2vpbformat(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_ALAW:
+ if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return VPB_ALAW;
- case AST_FORMAT_SLINEAR:
+ } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
return VPB_LINEAR;
- case AST_FORMAT_ULAW:
+ } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return VPB_MULAW;
- case AST_FORMAT_ADPCM:
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
return VPB_OKIADPCM;
- default:
+ } else {
return VPB_RAW;
}
}
static inline const char * ast2vpbformatname(struct ast_format *format)
{
- switch(format->id) {
- case AST_FORMAT_ALAW:
+ if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_ALAW:VPB_ALAW";
- case AST_FORMAT_SLINEAR:
+ } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_SLINEAR:VPB_LINEAR";
- case AST_FORMAT_ULAW:
+ } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_ULAW:VPB_MULAW";
- case AST_FORMAT_ADPCM:
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_ADPCM:VPB_OKIADPCM";
- default:
+ } else {
return "UNKN:UNKN";
}
}
static inline int astformatbits(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_SLINEAR:
+ if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
return 16;
- case AST_FORMAT_ADPCM:
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
return 4;
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- default:
+ } else {
return 8;
}
}
@@ -2146,7 +2141,8 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
/* ast_mutex_unlock(&p->lock); */
return 0;
} else if (ast_channel_state(ast) != AST_STATE_UP) {
- ast_verb(4, "%s: vpb_write: Attempt to Write frame type[%d]subclass[%s] on not up chan(state[%d])\n", ast_channel_name(ast), frame->frametype, ast_getformatname(&frame->subclass.format), ast_channel_state(ast));
+ ast_verb(4, "%s: vpb_write: Attempt to Write frame type[%d]subclass[%s] on not up chan(state[%d])\n",
+ ast_channel_name(ast), frame->frametype, ast_format_get_name(frame->subclass.format), ast_channel_state(ast));
p->lastoutput = -1;
/* ast_mutex_unlock(&p->lock); */
return 0;
@@ -2154,9 +2150,10 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
/* ast_debug(1, "%s: vpb_write: Checked frame type..\n", p->dev); */
- fmt = ast2vpbformat(&frame->subclass.format);
+ fmt = ast2vpbformat(frame->subclass.format);
if (fmt < 0) {
- ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast_channel_name(ast), ast_getformatname(&frame->subclass.format));
+ ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast_channel_name(ast),
+ ast_format_get_name(frame->subclass.format));
return -1;
}
@@ -2180,7 +2177,7 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
/* Check if we have set up the play_buf */
if (p->lastoutput == -1) {
vpb_play_buf_start(p->handle, fmt);
- ast_verb(2, "%s: vpb_write: Starting play mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(&frame->subclass.format));
+ ast_verb(2, "%s: vpb_write: Starting play mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(frame->subclass.format));
p->lastoutput = fmt;
ast_mutex_unlock(&p->play_lock);
return 0;
@@ -2230,7 +2227,7 @@ static void *do_chanreads(void *pvt)
struct ast_frame *fr = &p->fr;
char *readbuf = ((char *)p->buf) + AST_FRIENDLY_OFFSET;
int bridgerec = 0;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
int readlen, res, trycnt=0;
AudioCompress fmt;
int ignore_dtmf;
@@ -2315,22 +2312,22 @@ static void *do_chanreads(void *pvt)
ast_mutex_unlock(&p->play_dtmf_lock);
if (p->owner) {
- ast_format_copy(&tmpfmt, ast_channel_rawreadformat(p->owner));
+ tmpfmt = ast_channel_rawreadformat(p->owner);
} else {
- ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0);
+ tmpfmt = ast_format_slin;
}
- fmt = ast2vpbformat(&tmpfmt);
+ fmt = ast2vpbformat(tmpfmt);
if (fmt < 0) {
- ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_getformatname(&tmpfmt));
+ ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_format_get_name(tmpfmt));
return NULL;
}
- readlen = VPB_SAMPLES * astformatbits(&tmpfmt) / 8;
+ readlen = VPB_SAMPLES * astformatbits(tmpfmt) / 8;
if (p->lastinput == -1) {
vpb_record_buf_start(p->handle, fmt);
/* vpb_reset_record_fifo_alarm(p->handle); */
p->lastinput = fmt;
- ast_verb(2, "%s: Starting record mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(&tmpfmt));
+ ast_verb(2, "%s: Starting record mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(tmpfmt));
continue;
} else if (p->lastinput != fmt) {
vpb_record_buf_finish(p->handle);
@@ -2349,7 +2346,7 @@ static void *do_chanreads(void *pvt)
a_gain_vector(p->rxswgain - MAX_VPB_GAIN, (short *)readbuf, readlen / sizeof(short));
ast_verb(6, "%s: chanreads: applied gain\n", p->dev);
- ast_format_copy(&fr->subclass.format, &tmpfmt);
+ fr->subclass.format = tmpfmt;
fr->data.ptr = readbuf;
fr->datalen = readlen;
fr->frametype = AST_FRAME_VOICE;
@@ -2429,7 +2426,6 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
struct ast_channel *tmp;
char cid_num[256];
char cid_name[256];
- struct ast_format tmpfmt;
if (me->owner) {
ast_log(LOG_WARNING, "Called vpb_new on owned channel (%s) ?!\n", me->dev);
@@ -2452,9 +2448,9 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
* they are all converted to/from linear in the vpb code. Best for us to use
* linear since we can then adjust volume in this modules.
*/
- ast_format_cap_add(ast_channel_nativeformats(tmp), ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_channel_nativeformats_set(tmp, vpb_tech.capabilities);
+ ast_channel_set_rawreadformat(tmp, ast_format_slin);
+ ast_channel_set_rawwriteformat(tmp, ast_format_slin);
if (state == AST_STATE_RING) {
ast_channel_rings_set(tmp, 1);
cid_name[0] = '\0';
@@ -2508,13 +2504,17 @@ static struct ast_channel *vpb_request(const char *type, struct ast_format_cap *
char *sepstr, *name;
const char *s;
int group = -1;
- struct ast_format slin;
- ast_format_set(&slin, AST_FORMAT_SLINEAR, 0);
+ if (!(ast_format_cap_iscompatible_format(cap, ast_format_slin))) {
+ struct ast_str *buf;
- if (!(ast_format_cap_iscompatible(cap, &slin))) {
- char tmp[256];
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ buf = ast_str_create(256);
+ if (!buf) {
+ return NULL;
+ }
+ ast_log(LOG_NOTICE, "Asked to create a channel for unsupported formats: %s\n",
+ ast_format_cap_get_names(cap, &buf));
+ ast_free(buf);
return NULL;
}
@@ -2636,8 +2636,10 @@ static int unload_module(void)
ast_free(bridges);
}
- ast_format_cap_destroy(vpb_tech.capabilities);
- ast_format_cap_destroy(vpb_tech_indicate.capabilities);
+ ao2_cleanup(vpb_tech.capabilities);
+ vpb_tech.capabilities = NULL;
+ ao2_cleanup(vpb_tech_indicate.capabilities);
+ vpb_tech_indicate.capabilities = NULL;
return 0;
}
@@ -2671,19 +2673,18 @@ static enum ast_module_load_result load_module()
int bal2 = -1;
int bal3 = -1;
char * callerid = NULL;
- struct ast_format tmpfmt;
int num_cards = 0;
- vpb_tech.capabilities = ast_format_cap_alloc((enum ast_format_cap_flags) 0);
+ vpb_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!vpb_tech.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- vpb_tech_indicate.capabilities = ast_format_cap_alloc((enum ast_format_cap_flags) 0);
+ vpb_tech_indicate.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!vpb_tech_indicate.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(vpb_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(vpb_tech_indicate.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(vpb_tech.capabilities, ast_format_slin, 0);
+ ast_format_cap_append(vpb_tech_indicate.capabilities, ast_format_slin, 0);
try {
num_cards = vpb_get_num_cards();
} catch (std::exception e) {
diff --git a/channels/dahdi/bridge_native_dahdi.c b/channels/dahdi/bridge_native_dahdi.c
index 2f4fd170e..85cb4bfef 100644
--- a/channels/dahdi/bridge_native_dahdi.c
+++ b/channels/dahdi/bridge_native_dahdi.c
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/bridge_technology.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
/* ------------------------------------------------------------------- */
@@ -892,7 +893,7 @@ static struct ast_bridge_technology native_bridge = {
void dahdi_native_unload(void)
{
ast_bridge_technology_unregister(&native_bridge);
- ast_format_cap_destroy(native_bridge.format_capabilities);
+ ao2_cleanup(native_bridge.format_capabilities);
}
/*!
@@ -905,11 +906,9 @@ void dahdi_native_unload(void)
*/
int dahdi_native_load(struct ast_module *mod, const struct ast_channel_tech *tech)
{
- struct ast_format format;
-
dahdi_tech = tech;
- native_bridge.format_capabilities = ast_format_cap_alloc(0);
+ native_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!native_bridge.format_capabilities) {
return -1;
}
@@ -918,9 +917,9 @@ int dahdi_native_load(struct ast_module *mod, const struct ast_channel_tech *tec
* This is used to make channels compatible with the bridge
* itself not with each other.
*/
- ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(native_bridge.format_capabilities, ast_format_slin, 0);
+ ast_format_cap_append(native_bridge.format_capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(native_bridge.format_capabilities, ast_format_alaw, 0);
return __ast_bridge_technology_register(&native_bridge, mod);
}
diff --git a/channels/iax2/codec_pref.c b/channels/iax2/codec_pref.c
new file mode 100644
index 000000000..903dca4cc
--- /dev/null
+++ b/channels/iax2/codec_pref.c
@@ -0,0 +1,333 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_cap.h"
+
+#include "include/codec_pref.h"
+#include "include/format_compatibility.h"
+
+void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right)
+{
+ static int differential = (int) 'A';
+ int x;
+
+ if (right) {
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE && x < size; x++) {
+ if (!pref->order[x]) {
+ break;
+ }
+
+ buf[x] = pref->order[x] + differential;
+ }
+
+ buf[x] = '\0';
+ } else {
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE && x < size; x++) {
+ if (buf[x] == '\0') {
+ break;
+ }
+
+ pref->order[x] = buf[x] - differential;
+ }
+
+ if (x < size) {
+ pref->order[x] = 0;
+ }
+ }
+}
+
+struct ast_format *iax2_codec_pref_index(struct iax2_codec_pref *pref, int idx, struct ast_format **result)
+{
+ if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->order[idx]) {
+ *result = ast_format_compatibility_bitfield2format(pref->order[idx]);
+ } else {
+ *result = NULL;
+ }
+
+ return *result;
+}
+
+void iax2_codec_pref_to_cap(struct iax2_codec_pref *pref, struct ast_format_cap *cap)
+{
+ int idx;
+
+ for (idx = 0; idx < sizeof(pref->order); idx++) {
+ if (!pref->order[idx]) {
+ break;
+ }
+ ast_format_cap_append(cap, ast_format_compatibility_bitfield2format(pref->order[idx]), pref->framing[idx]);
+ }
+}
+
+int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size)
+{
+ int x;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ size_t total_len;
+ char *cur;
+
+ if (!cap) {
+ return -1;
+ }
+
+ /* This function is useless if you have less than a 6 character buffer.
+ * '(...)' is six characters. */
+ if (size < 6) {
+ return -1;
+ }
+
+ /* Convert the preferences into a format cap so that we can read the formst names */
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ uint64_t bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]);
+ if (!bitfield) {
+ break;
+ }
+
+ iax2_format_compatibility_bitfield2cap(bitfield, cap);
+ }
+
+ /* We know that at a minimum, 3 characters are used - (, ), and \0 */
+ total_len = size - 3;
+
+ memset(buf, 0, size);
+
+ /* This character has already been accounted for total_len purposes */
+ buf[0] = '(';
+ cur = buf + 1;
+
+ /* Loop through the formats and write as many into the buffer as we can */
+ for (x = 0; x < ast_format_cap_count(cap); x++) {
+ size_t name_len;
+ struct ast_format *fmt = ast_format_cap_get_format(cap, x);
+ const char *name = ast_format_get_name(fmt);
+
+ name_len = strlen(name);
+
+ /* all entries after the first need a delimiter character */
+ if (x) {
+ name_len++;
+ }
+
+ /* Terminate the list early if we don't have room for the entry.
+ * If it's not the last entry in the list, save enough room to write '...'.
+ */
+ if (((x == ast_format_cap_count(cap) - 1) && (total_len < name_len)) ||
+ ((x < ast_format_cap_count(cap) - 1) && (total_len < name_len + 3))) {
+ strcpy(cur, "...");
+ cur += 3;
+ total_len -= 3;
+ ao2_ref(fmt, -1);
+ break;
+ }
+
+ sprintf(cur, "%s%s", x ? "|" : "", name);
+ cur += name_len;
+ total_len -= name_len;
+
+ ao2_ref(fmt, -1);
+ }
+ ao2_ref(cap, -1);
+
+ /* These two characters have already been accounted for total_len purposes */
+ cur[0] = ')';
+ cur[1] = '\0';
+
+ return size - total_len;
+}
+
+static void codec_pref_remove_index(struct iax2_codec_pref *pref, int codec_pref_index)
+{
+ int x;
+
+ for (x = codec_pref_index; x < IAX2_CODEC_PREF_SIZE; x++) {
+ pref->order[x] = pref->order[x + 1];
+ pref->framing[x] = pref->framing[x + 1];
+ if (!pref->order[x]) {
+ return;
+ }
+ }
+}
+
+/*! \brief Remove codec from pref list */
+static void codec_pref_remove(struct iax2_codec_pref *pref, int format_index)
+{
+ int x;
+
+ if (!pref->order[0]) {
+ return;
+ }
+
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ if (!pref->order[x]) {
+ break;
+ }
+
+ if (pref->order[x] == format_index) {
+ codec_pref_remove_index(pref, x);
+ break;
+ }
+ }
+}
+
+void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield)
+{
+ int x;
+
+ if (!pref->order[0]) {
+ return;
+ }
+
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ uint64_t format_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]);
+ if (!pref->order[x]) {
+ break;
+ }
+
+ /* If this format isn't in the bitfield, remove it from the prefs. */
+ if (!(format_as_bitfield & bitfield)) {
+ codec_pref_remove_index(pref, x);
+ }
+ }
+}
+
+uint64_t iax2_codec_pref_order_value_to_format_bitfield(uint64_t order_value)
+{
+ if (!order_value) {
+ return 0;
+ }
+
+ return 1 << (order_value - 1);
+}
+
+uint64_t iax2_codec_pref_format_bitfield_to_order_value(uint64_t bitfield)
+{
+ int format_index = 1;
+
+ if (!bitfield) {
+ return 0;
+ }
+
+ while (bitfield > 1) {
+ bitfield = bitfield >> 1;
+ format_index++;
+ }
+
+ return format_index;
+}
+
+/*! \brief Append codec to list */
+int iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing)
+{
+ uint64_t bitfield = ast_format_compatibility_format2bitfield(format);
+ int format_index = iax2_codec_pref_format_bitfield_to_order_value(bitfield);
+ int x;
+
+ codec_pref_remove(pref, format_index);
+
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ if (!pref->order[x]) {
+ pref->order[x] = format_index;
+ pref->framing[x] = framing;
+ break;
+ }
+ }
+
+ return x;
+}
+
+/*! \brief Prepend codec to list */
+void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing,
+ int only_if_existing)
+{
+ uint64_t bitfield = ast_format_compatibility_format2bitfield(format);
+ int x;
+
+ /* Now find any existing occurrence, or the end */
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ if (!pref->order[x] || pref->order[x] == bitfield)
+ break;
+ }
+
+ /* If we failed to find any occurrence, set to the end */
+ if (x == IAX2_CODEC_PREF_SIZE) {
+ --x;
+ }
+
+ if (only_if_existing && !pref->order[x]) {
+ return;
+ }
+
+ /* Move down to make space to insert - either all the way to the end,
+ or as far as the existing location (which will be overwritten) */
+ for (; x > 0; x--) {
+ pref->order[x] = pref->order[x - 1];
+ pref->framing[x] = pref->framing[x - 1];
+ }
+
+ /* And insert the new entry */
+ pref->order[0] = bitfield;
+ pref->framing[0] = framing;
+}
+
+unsigned int iax2_codec_pref_getsize(struct iax2_codec_pref *pref, int idx)
+{
+ if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->order[idx]) {
+ return pref->framing[idx];
+ } else {
+ return 0;
+ }
+}
+
+int iax2_codec_pref_setsize(struct iax2_codec_pref *pref, struct ast_format *format, int framems)
+{
+ int idx;
+
+ for (idx = 0; idx < sizeof(pref->order); idx++) {
+ if (!pref->order[idx]) {
+ break;
+ } else if (ast_format_cmp(ast_format_compatibility_bitfield2format(pref->order[idx]),
+ format) != AST_FORMAT_CMP_EQUAL) {
+ continue;
+ }
+ pref->framing[idx] = framems;
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/channels/iax2/format_compatibility.c b/channels/iax2/format_compatibility.c
new file mode 100644
index 000000000..8085c2c26
--- /dev/null
+++ b/channels/iax2/format_compatibility.c
@@ -0,0 +1,73 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_cap.h"
+
+#include "include/format_compatibility.h"
+
+uint64_t iax2_format_compatibility_cap2bitfield(const struct ast_format_cap *cap)
+{
+ uint64_t bitfield = 0;
+ int x;
+
+ for (x = 0; x < ast_format_cap_count(cap); x++) {
+ struct ast_format *format = ast_format_cap_get_format(cap, x);
+
+ bitfield |= ast_format_compatibility_format2bitfield(format);
+
+ ao2_ref(format, -1);
+ }
+
+ return bitfield;
+}
+
+int iax2_format_compatibility_bitfield2cap(uint64_t bitfield, struct ast_format_cap *cap)
+{
+ int x;
+
+ for (x = 0; x < 64; x++) {
+ uint64_t tmp = (1ULL << x);
+
+ if ((tmp & bitfield) && ast_format_cap_append(cap, ast_format_compatibility_bitfield2format(tmp), 0)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/channels/iax2/include/codec_pref.h b/channels/iax2/include/codec_pref.h
new file mode 100644
index 000000000..bfb889164
--- /dev/null
+++ b/channels/iax2/include/codec_pref.h
@@ -0,0 +1,123 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _IAX2_CODEC_PREF_H_
+#define _IAX2_CODEC_PREF_H_
+
+struct ast_format;
+struct ast_codec;
+struct ast_format_cap;
+
+#define IAX2_CODEC_PREF_SIZE 64
+struct iax2_codec_pref {
+ /*! This array is ordered by preference and contains the codec bitfield. */
+ uint64_t order[IAX2_CODEC_PREF_SIZE];
+ /*! Framing size of the codec */
+ unsigned int framing[IAX2_CODEC_PREF_SIZE];
+};
+
+/*!
+ * \brief Convert an iax2_codec_pref order value into a format bitfield
+ *
+ * \param order_value value being converted
+ *
+ * \return the bitfield value of the order_value format
+ */
+uint64_t iax2_codec_pref_order_value_to_format_bitfield(uint64_t order_value);
+
+/*!
+ * \brief Convert a format bitfield into an iax2_codec_pref order value
+ *
+ * \param bitfield value being converted
+ *
+ * \return the iax2_codec_pref order value of the most significant format
+ * in the bitfield.
+ *
+ * \note This is really meant to be used on single format bitfields.
+ * It will work with multiformat bitfields, but it can only return the
+ * index of the most significant one if that is the case.
+ */
+uint64_t iax2_codec_pref_format_bitfield_to_order_value(uint64_t bitfield);
+
+/*!
+ * \brief Codec located at a particular place in the preference index.
+ * \param pref preference structure to get the codec out of
+ * \param index to retrieve from
+ * \param result ast_format structure to store the index value in
+ * \return pointer to input ast_format on success, NULL on failure
+*/
+struct ast_format *iax2_codec_pref_index(struct iax2_codec_pref *pref, int index, struct ast_format **result);
+
+/*! \brief Convert a preference structure to a capabilities structure */
+void iax2_codec_pref_to_cap(struct iax2_codec_pref *pref, struct ast_format_cap *cap);
+
+/*! \brief Removes format from the pref list that aren't in the bitfield */
+void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield);
+
+/*!
+ * \brief Dump audio codec preference list into a string
+ *
+ * \param pref preference structure to dump string representation of order for
+ * \param buf character buffer to put string into
+ * \param size size of the character buffer
+ *
+ * \return -1 on error. Otherwise returns the remaining spaaaaaace in the buffer.
+ *
+ * \note Format is (codec1|codec2|codec3|...) -- if the list is too long for the
+ * size of the buffer, codecs will be written until they exceed the length
+ * remaining in which case the list will be closed with '...)' after the last
+ * writable codec.
+ */
+int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size);
+
+/*! \brief Append a audio codec to a preference list, removing it first if it was already there
+*/
+int iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing);
+
+/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there
+*/
+void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing,
+ int only_if_existing);
+
+/*! \brief Get packet size for codec
+*/
+unsigned int iax2_codec_pref_getsize(struct iax2_codec_pref *pref, int index);
+
+/*! \brief Set packet size for codec
+*/
+int iax2_codec_pref_setsize(struct iax2_codec_pref *pref, struct ast_format *format, int framems);
+
+/*! \brief Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string
+ * \note Due to a misunderstanding in how codec preferences are stored, this
+ * list starts at 'B', not 'A'. For backwards compatibility reasons, this
+ * cannot change.
+ * \param pref A codec preference list structure
+ * \param buf A string denoting codec preference, appropriate for use in line transmission
+ * \param size Size of \a buf
+ * \param right Boolean: if 0, convert from \a buf to \a pref; if 1, convert from \a pref to \a buf.
+ */
+void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right);
+
+#endif /* _IAX2_CODEC_PREF_H_ */
diff --git a/channels/iax2/include/format_compatibility.h b/channels/iax2/include/format_compatibility.h
new file mode 100644
index 000000000..aa29cfa2c
--- /dev/null
+++ b/channels/iax2/include/format_compatibility.h
@@ -0,0 +1,55 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _IAX2_FORMAT_COMPATIBILITY_H_
+#define _IAX2_FORMAT_COMPATIBILITY_H_
+
+struct ast_format;
+struct ast_format_cap;
+
+/*!
+ * \brief Convert a format capabilities structure to a bitfield
+ *
+ * \param cap Capabilities structure containing formats
+ *
+ * \retval non-zero success
+ * \retval zero no formats present or no formats supported
+ */
+uint64_t iax2_format_compatibility_cap2bitfield(const struct ast_format_cap *cap);
+
+/*!
+ * \brief Convert a bitfield to a format capabilities structure
+ *
+ * \param bitfield The bitfield for the media formats
+ * \param cap Capabilities structure to place formats into
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note If failure occurs the capabilities structure may contain a partial set of formats
+ */
+int iax2_format_compatibility_bitfield2cap(uint64_t bitfield, struct ast_format_cap *cap);
+
+#endif /* _IAX2_FORMAT_COMPATIBILITY_H */
diff --git a/channels/iax2/parser.c b/channels/iax2/parser.c
index f5c7ba05d..f1fc8f82d 100644
--- a/channels/iax2/parser.c
+++ b/channels/iax2/parser.c
@@ -42,10 +42,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/threadstorage.h"
#include "asterisk/netsock2.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
#include "include/iax2.h"
#include "include/parser.h"
#include "include/provision.h"
+#include "include/codec_pref.h"
static int frames = 0;
static int iframes = 0;
@@ -124,7 +127,7 @@ static void dump_string(char *output, int maxlen, void *value, int len)
static void dump_prefs(char *output, int maxlen, void *value, int len)
{
- struct ast_codec_pref pref;
+ struct iax2_codec_pref pref;
int total_len = 0;
maxlen--;
@@ -136,9 +139,9 @@ static void dump_prefs(char *output, int maxlen, void *value, int len)
strncpy(output, value, maxlen);
output[maxlen] = '\0';
- ast_codec_pref_convert(&pref, output, total_len, 0);
+ iax2_codec_pref_convert(&pref, output, total_len, 0);
memset(output,0,total_len);
- ast_codec_pref_string(&pref, output, total_len);
+ iax2_codec_pref_string(&pref, output, total_len);
}
static void dump_int(char *output, int maxlen, void *value, int len)
@@ -1180,7 +1183,8 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
{
fr->af.frametype = f->frametype;
- ast_format_copy(&fr->af.subclass.format, &f->subclass.format);
+ fr->af.subclass.format = f->subclass.format;
+ fr->af.subclass.integer = f->subclass.integer;
fr->af.mallocd = 0; /* Our frame is static relative to the container */
fr->af.datalen = f->datalen;
fr->af.samples = f->samples;
@@ -1199,7 +1203,8 @@ void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
/* We need to byte-swap slinear samples from network byte order */
- if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.format.id == AST_FORMAT_SLINEAR)) {
+ if ((fr->af.frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(fr->af.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
/* 2 bytes / sample for SLINEAR */
ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
} else
diff --git a/channels/iax2/provision.c b/channels/iax2/provision.c
index 78e0b1b3d..85dfe9448 100644
--- a/channels/iax2/provision.c
+++ b/channels/iax2/provision.c
@@ -45,6 +45,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
#include "asterisk/acl.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
#include "include/iax2.h"
#include "include/provision.h"
@@ -345,9 +347,10 @@ static int iax_template_parse(struct iax_template *cur, struct ast_config *cfg,
} else
ast_log(LOG_WARNING, "Ignoring invalid %s '%s' for '%s' at line %d\n", v->name, v->value, s, v->lineno);
} else if (!strcasecmp(v->name, "codec")) {
- struct ast_format tmpfmt;
- if ((ast_getformatbyname(v->value, &tmpfmt)) > 0) {
- cur->format = ast_format_to_old_bitfield(&tmpfmt);
+ struct ast_format *tmpfmt;
+ if ((tmpfmt = ast_format_cache_get(v->value))) {
+ cur->format = ast_format_compatibility_format2bitfield(tmpfmt);
+ ao2_ref(tmpfmt, -1);
} else
ast_log(LOG_WARNING, "Ignoring invalid codec '%s' for '%s' at line %d\n", v->value, s, v->lineno);
} else if (!strcasecmp(v->name, "tos")) {
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index c50dbf3fc..054552b5a 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -806,35 +806,32 @@ int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char
}
static int media_offer_read_av(struct ast_sip_session *session, char *buf,
- size_t len, enum ast_format_type media_type)
+ size_t len, enum ast_media_type media_type)
{
int i, size = 0;
- struct ast_format fmt;
- const char *name;
- for (i = 0; ast_codec_pref_index(&session->override_prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) != media_type) {
- continue;
- }
+ for (i = 0; i < ast_format_cap_count(session->req_caps); i++) {
+ struct ast_format *fmt = ast_format_cap_get_format(session->req_caps, i);
- name = ast_getformatname(&fmt);
-
- if (ast_strlen_zero(name)) {
- ast_log(LOG_WARNING, "PJSIP_MEDIA_OFFER unrecognized format %s\n", name);
+ if (ast_format_get_type(fmt) != media_type) {
+ ao2_ref(fmt, -1);
continue;
}
/* add one since we'll include a comma */
- size = strlen(name) + 1;
+ size = strlen(ast_format_get_name(fmt)) + 1;
len -= size;
if ((len) < 0) {
+ ao2_ref(fmt, -1);
break;
}
/* no reason to use strncat here since we have already ensured buf has
enough space, so strcat can be safely used */
- strcat(buf, name);
+ strcat(buf, ast_format_get_name(fmt));
strcat(buf, ",");
+
+ ao2_ref(fmt, -1);
}
if (size) {
@@ -846,23 +843,16 @@ static int media_offer_read_av(struct ast_sip_session *session, char *buf,
struct media_offer_data {
struct ast_sip_session *session;
- enum ast_format_type media_type;
+ enum ast_media_type media_type;
const char *value;
};
static int media_offer_write_av(void *obj)
{
struct media_offer_data *data = obj;
- int i;
- struct ast_format fmt;
- /* remove all of the given media type first */
- for (i = 0; ast_codec_pref_index(&data->session->override_prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) == data->media_type) {
- ast_codec_pref_remove(&data->session->override_prefs, &fmt);
- }
- }
- ast_format_cap_remove_bytype(data->session->req_caps, data->media_type);
- ast_parse_allow_disallow(&data->session->override_prefs, data->session->req_caps, data->value, 1);
+
+ ast_format_cap_remove_by_type(data->session->req_caps, data->media_type);
+ ast_format_cap_update_by_allow_disallow(data->session->req_caps, data->value, 1);
return 0;
}
@@ -879,9 +869,9 @@ int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *
channel = ast_channel_tech_pvt(chan);
if (!strcmp(data, "audio")) {
- return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_AUDIO);
+ return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_AUDIO);
} else if (!strcmp(data, "video")) {
- return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_VIDEO);
+ return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_VIDEO);
}
return 0;
@@ -903,9 +893,9 @@ int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char
mdata.session = channel->session;
if (!strcmp(data, "audio")) {
- mdata.media_type = AST_FORMAT_TYPE_AUDIO;
+ mdata.media_type = AST_MEDIA_TYPE_AUDIO;
} else if (!strcmp(data, "video")) {
- mdata.media_type = AST_FORMAT_TYPE_VIDEO;
+ mdata.media_type = AST_MEDIA_TYPE_VIDEO;
}
return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata);
diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h
index 11078d5b7..8ce63ee9d 100644
--- a/channels/sip/include/sip.h
+++ b/channels/sip/include/sip.h
@@ -1082,7 +1082,6 @@ struct sip_pvt {
int timer_b; /*!< SIP timer B, ms */
unsigned int sipoptions; /*!< Supported SIP options on the other end */
unsigned int reqsipoptions; /*!< Required SIP options on the other end */
- struct ast_codec_pref prefs; /*!< codec prefs */
struct ast_format_cap *caps; /*!< Special capability (codec) */
struct ast_format_cap *jointcaps; /*!< Supported capability at both ends (codecs) */
struct ast_format_cap *peercaps; /*!< Supported peer capability */
@@ -1310,7 +1309,6 @@ struct sip_peer {
int busy_level; /*!< Level of active channels where we signal busy */
int maxforwards; /*!< SIP Loop prevention */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
- struct ast_codec_pref prefs; /*!< codec prefs */
int lastmsgssent; /*!< The last known VM message counts (new/old) */
unsigned int sipoptions; /*!< Supported SIP options */
struct ast_flags flags[3]; /*!< SIP_ flags */
diff --git a/codecs/codec_a_mu.c b/codecs/codec_a_mu.c
index 470f363e7..c21c706f5 100644
--- a/codecs/codec_a_mu.c
+++ b/codecs/codec_a_mu.c
@@ -80,6 +80,17 @@ static int ulawtoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator alawtoulaw = {
.name = "alawtoulaw",
+ .src_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "ulaw",
.framein = alawtoulaw_framein,
.sample = alaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -88,6 +99,17 @@ static struct ast_translator alawtoulaw = {
static struct ast_translator ulawtoalaw = {
.name = "ulawtoalaw",
+ .src_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "alaw",
.framein = ulawtoalaw_framein,
.sample = ulaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -111,23 +133,19 @@ static int load_module(void)
int res;
int x;
- ast_format_set(&alawtoulaw.src_format, AST_FORMAT_ALAW, 0);
- ast_format_set(&alawtoulaw.dst_format, AST_FORMAT_ULAW, 0);
-
- ast_format_set(&ulawtoalaw.src_format, AST_FORMAT_ULAW, 0);
- ast_format_set(&ulawtoalaw.dst_format, AST_FORMAT_ALAW, 0);
-
for (x=0;x<256;x++) {
mu2a[x] = AST_LIN2A(AST_MULAW(x));
a2mu[x] = AST_LIN2MU(AST_ALAW(x));
}
+
res = ast_register_translator(&alawtoulaw);
- if (!res)
- res = ast_register_translator(&ulawtoalaw);
- else
- ast_unregister_translator(&alawtoulaw);
- if (res)
+ res |= ast_register_translator(&ulawtoalaw);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c
index c48eb1ab2..03d2a4ab3 100644
--- a/codecs/codec_adpcm.c
+++ b/codecs/codec_adpcm.c
@@ -290,6 +290,17 @@ static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
static struct ast_translator adpcmtolin = {
.name = "adpcmtolin",
+ .src_codec = {
+ .name = "adpcm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = adpcmtolin_framein,
.sample = adpcm_sample,
.desc_size = sizeof(struct adpcm_decoder_pvt),
@@ -299,6 +310,17 @@ static struct ast_translator adpcmtolin = {
static struct ast_translator lintoadpcm = {
.name = "lintoadpcm",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "adpcm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "adpcm",
.framein = lintoadpcm_framein,
.frameout = lintoadpcm_frameout,
.sample = slin8_sample,
@@ -307,12 +329,6 @@ static struct ast_translator lintoadpcm = {
.buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */
};
-/*! \brief standard module glue */
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
@@ -325,26 +341,20 @@ static int unload_module(void)
static int load_module(void)
{
- int res;
-
- ast_format_set(&adpcmtolin.src_format, AST_FORMAT_ADPCM, 0);
- ast_format_set(&adpcmtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintoadpcm.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintoadpcm.dst_format, AST_FORMAT_ADPCM, 0);
+ int res = 0;
res = ast_register_translator(&adpcmtolin);
- if (!res)
- res = ast_register_translator(&lintoadpcm);
- else
- ast_unregister_translator(&adpcmtolin);
- if (res)
+ res |= ast_register_translator(&lintoadpcm);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c
index 34a71388e..2ca577d7f 100644
--- a/codecs/codec_alaw.c
+++ b/codecs/codec_alaw.c
@@ -77,6 +77,17 @@ static int lintoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator alawtolin = {
.name = "alawtolin",
+ .src_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = alawtolin_framein,
.sample = alaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -84,20 +95,24 @@ static struct ast_translator alawtolin = {
};
static struct ast_translator lintoalaw = {
- "lintoalaw",
+ .name = "lintoalaw",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "alaw",
.framein = lintoalaw_framein,
.sample = slin8_sample,
.buffer_samples = BUFFER_SAMPLES,
.buf_size = BUFFER_SAMPLES,
};
-/*! \brief standard module stuff */
-
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
@@ -112,24 +127,18 @@ static int load_module(void)
{
int res;
- ast_format_set(&lintoalaw.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintoalaw.dst_format, AST_FORMAT_ALAW, 0);
-
- ast_format_set(&alawtolin.src_format, AST_FORMAT_ALAW, 0);
- ast_format_set(&alawtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
res = ast_register_translator(&alawtolin);
- if (!res)
- res = ast_register_translator(&lintoalaw);
- else
- ast_unregister_translator(&alawtolin);
- if (res)
+ res |= ast_register_translator(&lintoalaw);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "A-law Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c
index caaf99cdf..64f220eef 100644
--- a/codecs/codec_dahdi.c
+++ b/codecs/codec_dahdi.c
@@ -51,6 +51,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/ulaw.h"
+#include "asterisk/format_compatibility.h"
#define BUFFER_SIZE 8000
@@ -58,17 +59,29 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define G729_SAMPLES 160
#define ULAW_SAMPLES 160
+/* Defines from DAHDI. */
#ifndef DAHDI_FORMAT_MAX_AUDIO
+/*! G.723.1 compression */
#define DAHDI_FORMAT_G723_1 (1 << 0)
+/*! GSM compression */
#define DAHDI_FORMAT_GSM (1 << 1)
+/*! Raw mu-law data (G.711) */
#define DAHDI_FORMAT_ULAW (1 << 2)
+/*! Raw A-law data (G.711) */
#define DAHDI_FORMAT_ALAW (1 << 3)
+/*! ADPCM (G.726, 32kbps) */
#define DAHDI_FORMAT_G726 (1 << 4)
+/*! ADPCM (IMA) */
#define DAHDI_FORMAT_ADPCM (1 << 5)
+/*! Raw 16-bit Signed Linear (8000 Hz) PCM */
#define DAHDI_FORMAT_SLINEAR (1 << 6)
+/*! LPC10, 180 samples/frame */
#define DAHDI_FORMAT_LPC10 (1 << 7)
+/*! G.729A audio */
#define DAHDI_FORMAT_G729A (1 << 8)
+/*! SpeeX Free Compression */
#define DAHDI_FORMAT_SPEEX (1 << 9)
+/*! iLBC Free Compression */
#define DAHDI_FORMAT_ILBC (1 << 10)
#endif
@@ -78,6 +91,233 @@ static struct channel_usage {
int decoders;
} channels;
+#if defined(NOT_NEEDED)
+/*!
+ * \internal
+ * \brief Convert DAHDI format bitfield to old Asterisk format bitfield.
+ * \since 13.0.0
+ *
+ * \param dahdi Bitfield from DAHDI to convert.
+ *
+ * \note They should be the same values but they don't have to be.
+ *
+ * \return Old Asterisk bitfield equivalent.
+ */
+static uint64_t bitfield_dahdi2ast(unsigned dahdi)
+{
+ uint64_t ast;
+
+ switch (dahdi) {
+ case DAHDI_FORMAT_G723_1:
+ ast = AST_FORMAT_G723;
+ break;
+ case DAHDI_FORMAT_GSM:
+ ast = AST_FORMAT_GSM;
+ break;
+ case DAHDI_FORMAT_ULAW:
+ ast = AST_FORMAT_ULAW;
+ break;
+ case DAHDI_FORMAT_ALAW:
+ ast = AST_FORMAT_ALAW;
+ break;
+ case DAHDI_FORMAT_G726:
+ ast = AST_FORMAT_G726_AAL2;
+ break;
+ case DAHDI_FORMAT_ADPCM:
+ ast = AST_FORMAT_ADPCM;
+ break;
+ case DAHDI_FORMAT_SLINEAR:
+ ast = AST_FORMAT_SLIN;
+ break;
+ case DAHDI_FORMAT_LPC10:
+ ast = AST_FORMAT_LPC10;
+ break;
+ case DAHDI_FORMAT_G729A:
+ ast = AST_FORMAT_G729;
+ break;
+ case DAHDI_FORMAT_SPEEX:
+ ast = AST_FORMAT_SPEEX;
+ break;
+ case DAHDI_FORMAT_ILBC:
+ ast = AST_FORMAT_ILBC;
+ break;
+ default:
+ ast = 0;
+ break;
+ }
+
+ return ast;
+}
+#endif /* defined(NOT_NEEDED) */
+
+/*!
+ * \internal
+ * \brief Convert old Asterisk format bitfield to DAHDI format bitfield.
+ * \since 13.0.0
+ *
+ * \param ast Old Asterisk bitfield to convert.
+ *
+ * \note They should be the same values but they don't have to be.
+ *
+ * \return DAHDI bitfield equivalent.
+ */
+static unsigned bitfield_ast2dahdi(uint64_t ast)
+{
+ unsigned dahdi;
+
+ switch (ast) {
+ case AST_FORMAT_G723:
+ dahdi = DAHDI_FORMAT_G723_1;
+ break;
+ case AST_FORMAT_GSM:
+ dahdi = DAHDI_FORMAT_GSM;
+ break;
+ case AST_FORMAT_ULAW:
+ dahdi = DAHDI_FORMAT_ULAW;
+ break;
+ case AST_FORMAT_ALAW:
+ dahdi = DAHDI_FORMAT_ALAW;
+ break;
+ case AST_FORMAT_G726_AAL2:
+ dahdi = DAHDI_FORMAT_G726;
+ break;
+ case AST_FORMAT_ADPCM:
+ dahdi = DAHDI_FORMAT_ADPCM;
+ break;
+ case AST_FORMAT_SLIN:
+ dahdi = DAHDI_FORMAT_SLINEAR;
+ break;
+ case AST_FORMAT_LPC10:
+ dahdi = DAHDI_FORMAT_LPC10;
+ break;
+ case AST_FORMAT_G729:
+ dahdi = DAHDI_FORMAT_G729A;
+ break;
+ case AST_FORMAT_SPEEX:
+ dahdi = DAHDI_FORMAT_SPEEX;
+ break;
+ case AST_FORMAT_ILBC:
+ dahdi = DAHDI_FORMAT_ILBC;
+ break;
+ default:
+ dahdi = 0;
+ break;
+ }
+
+ return dahdi;
+}
+
+/*!
+ * \internal
+ * \brief Get the DAHDI codec by index.
+ * \since 13.0.0
+ *
+ * \param idx Codex index (0-31).
+ *
+ * \return Specified codec if exists otherwise NULL.
+ */
+static const struct ast_codec *get_dahdi_codec(unsigned idx)
+{
+ const struct ast_codec *codec;
+
+ static const struct ast_codec dahdi_g723_1 = {
+ .name = "g723",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_gsm = {
+ .name = "gsm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_ulaw = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_alaw = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_g726 = {
+ .name = "g726",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_adpcm = {
+ .name = "adpcm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_slinear = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_lpc10 = {
+ .name = "lpc10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_g729a = {
+ .name = "g729",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_speex = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_ilbc = {
+ .name = "ilbc",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+
+ switch (1UL << idx) {
+ case DAHDI_FORMAT_G723_1:
+ codec = &dahdi_g723_1;
+ break;
+ case DAHDI_FORMAT_GSM:
+ codec = &dahdi_gsm;
+ break;
+ case DAHDI_FORMAT_ULAW:
+ codec = &dahdi_ulaw;
+ break;
+ case DAHDI_FORMAT_ALAW:
+ codec = &dahdi_alaw;
+ break;
+ case DAHDI_FORMAT_G726:
+ codec = &dahdi_g726;
+ break;
+ case DAHDI_FORMAT_ADPCM:
+ codec = &dahdi_adpcm;
+ break;
+ case DAHDI_FORMAT_SLINEAR:
+ codec = &dahdi_slinear;
+ break;
+ case DAHDI_FORMAT_LPC10:
+ codec = &dahdi_lpc10;
+ break;
+ case DAHDI_FORMAT_G729A:
+ codec = &dahdi_g729a;
+ break;
+ case DAHDI_FORMAT_SPEEX:
+ codec = &dahdi_speex;
+ break;
+ case DAHDI_FORMAT_ILBC:
+ codec = &dahdi_ilbc;
+ break;
+ default:
+ codec = NULL;
+ break;
+ }
+
+ return codec;
+}
+
static char *handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static struct ast_cli_entry cli[] = {
@@ -190,7 +430,7 @@ static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
struct codec_dahdi_pvt *dahdip = pvt->pvt;
- if (!f->subclass.format.id) {
+ if (!f->subclass.format) {
/* We're just faking a return for calculation purposes. */
dahdip->fake = 2;
pvt->samples = f->samples;
@@ -245,18 +485,16 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
int res;
if (2 == dahdip->fake) {
+ struct ast_frame frm = {
+ .frametype = AST_FRAME_VOICE,
+ .samples = dahdip->required_samples,
+ .src = pvt->t->name,
+ };
+
dahdip->fake = 1;
- pvt->f.frametype = AST_FRAME_VOICE;
- 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 = 0;
- pvt->f.mallocd = 0;
pvt->samples = 0;
- return ast_frisolate(&pvt->f);
-
+ return ast_frisolate(&frm);
} else if (1 == dahdip->fake) {
dahdip->fake = 0;
return NULL;
@@ -277,13 +515,7 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
}
} else {
pvt->f.datalen = res;
- pvt->f.frametype = AST_FRAME_VOICE;
- 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;
- pvt->f.data.ptr = pvt->outbuf.c;
- pvt->f.samples = ast_codec_get_samples(&pvt->f);
+ pvt->f.samples = ast_codec_samples_count(&pvt->f);
dahdip->samples_written_to_hardware =
(dahdip->samples_written_to_hardware >= pvt->f.samples) ?
@@ -302,7 +534,7 @@ static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
struct codec_dahdi_pvt *dahdip = pvt->pvt;
- if (!f->subclass.format.id) {
+ if (!f->subclass.format) {
/* We're just faking a return for calculation purposes. */
dahdip->fake = 2;
pvt->samples = f->samples;
@@ -327,16 +559,16 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
struct codec_dahdi_pvt *dahdip = pvt->pvt;
if (2 == dahdip->fake) {
+ struct ast_frame frm = {
+ .frametype = AST_FRAME_VOICE,
+ .samples = dahdip->required_samples,
+ .src = pvt->t->name,
+ };
+
dahdip->fake = 1;
- pvt->f.frametype = AST_FRAME_VOICE;
- 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 = 0;
- pvt->f.mallocd = 0;
pvt->samples = 0;
- return ast_frisolate(&pvt->f);
+
+ return ast_frisolate(&frm);
} else if (1 == dahdip->fake) {
pvt->samples = 0;
dahdip->fake = 0;
@@ -370,12 +602,6 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
pvt->f.datalen = res;
}
pvt->datalen = 0;
- pvt->f.frametype = AST_FRAME_VOICE;
- 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;
- pvt->f.data.ptr = pvt->outbuf.c;
pvt->f.samples = res;
pvt->samples = 0;
dahdip->samples_written_to_hardware =
@@ -394,9 +620,9 @@ static void dahdi_destroy(struct ast_trans_pvt *pvt)
{
struct codec_dahdi_pvt *dahdip = pvt->pvt;
- switch (ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) {
- case AST_FORMAT_G729A:
- case AST_FORMAT_G723_1:
+ switch (dahdip->fmts.dstfmt) {
+ case DAHDI_FORMAT_G729A:
+ case DAHDI_FORMAT_G723_1:
ast_atomic_fetchadd_int(&channels.encoders, -1);
break;
default:
@@ -407,7 +633,39 @@ static void dahdi_destroy(struct ast_trans_pvt *pvt)
close(dahdip->fd);
}
-static int dahdi_translate(struct ast_trans_pvt *pvt, struct ast_format *dst_format, struct ast_format *src_format)
+static struct ast_format *dahdi_format_to_cached(int format)
+{
+ switch (format) {
+ case DAHDI_FORMAT_G723_1:
+ return ast_format_g723;
+ case DAHDI_FORMAT_GSM:
+ return ast_format_gsm;
+ case DAHDI_FORMAT_ULAW:
+ return ast_format_ulaw;
+ case DAHDI_FORMAT_ALAW:
+ return ast_format_alaw;
+ case DAHDI_FORMAT_G726:
+ return ast_format_g726;
+ case DAHDI_FORMAT_ADPCM:
+ return ast_format_adpcm;
+ case DAHDI_FORMAT_SLINEAR:
+ return ast_format_slin;
+ case DAHDI_FORMAT_LPC10:
+ return ast_format_lpc10;
+ case DAHDI_FORMAT_G729A:
+ return ast_format_g729;
+ case DAHDI_FORMAT_SPEEX:
+ return ast_format_speex;
+ case DAHDI_FORMAT_ILBC:
+ return ast_format_ilbc;
+ }
+
+ /* This will never be reached */
+ ast_assert(0);
+ return NULL;
+}
+
+static int dahdi_translate(struct ast_trans_pvt *pvt, struct ast_codec *dst_codec, struct ast_codec *src_codec)
{
/* Request translation through zap if possible */
int fd;
@@ -421,10 +679,13 @@ static int dahdi_translate(struct ast_trans_pvt *pvt, struct ast_format *dst_for
return -1;
}
- dahdip->fmts.srcfmt = ast_format_to_old_bitfield(src_format);
- dahdip->fmts.dstfmt = ast_format_to_old_bitfield(dst_format);
+ dahdip->fmts.srcfmt = bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(src_codec));
+ dahdip->fmts.dstfmt = bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(dst_codec));
+
+ ast_assert(pvt->f.subclass.format == NULL);
+ pvt->f.subclass.format = ao2_bump(dahdi_format_to_cached(dahdip->fmts.dstfmt));
- ast_debug(1, "Opening transcoder channel from %s to %s.\n", ast_getformatname(src_format), ast_getformatname(dst_format));
+ ast_debug(1, "Opening transcoder channel from %s to %s.\n", src_codec->name, dst_codec->name);
retry:
if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) {
@@ -437,14 +698,14 @@ retry:
* support for ULAW instead of signed linear and then
* we'll just convert from ulaw to signed linear in
* software. */
- if (AST_FORMAT_SLINEAR == ast_format_id_from_old_bitfield(dahdip->fmts.srcfmt)) {
+ if (dahdip->fmts.srcfmt == DAHDI_FORMAT_SLINEAR) {
ast_debug(1, "Using soft_slin support on source\n");
dahdip->softslin = 1;
- 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)) {
+ dahdip->fmts.srcfmt = DAHDI_FORMAT_ULAW;
+ } else if (dahdip->fmts.dstfmt == DAHDI_FORMAT_SLINEAR) {
ast_debug(1, "Using soft_slin support on destination\n");
dahdip->softslin = 1;
- dahdip->fmts.dstfmt = ast_format_id_to_old_bitfield(AST_FORMAT_ULAW);
+ dahdip->fmts.dstfmt = DAHDI_FORMAT_ULAW;
}
tried_once = 1;
goto retry;
@@ -463,13 +724,13 @@ retry:
dahdip->fd = fd;
- dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (ast_format_id_to_old_bitfield(AST_FORMAT_G723_1))) ? G723_SAMPLES : G729_SAMPLES;
+ dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (DAHDI_FORMAT_G723_1)) ? G723_SAMPLES : G729_SAMPLES;
- switch (ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) {
- case AST_FORMAT_G729A:
+ switch (dahdip->fmts.dstfmt) {
+ case DAHDI_FORMAT_G729A:
ast_atomic_fetchadd_int(&channels.encoders, +1);
break;
- case AST_FORMAT_G723_1:
+ case DAHDI_FORMAT_G723_1:
ast_atomic_fetchadd_int(&channels.encoders, +1);
break;
default:
@@ -483,8 +744,8 @@ retry:
static int dahdi_new(struct ast_trans_pvt *pvt)
{
return dahdi_translate(pvt,
- &pvt->t->dst_format,
- &pvt->t->src_format);
+ pvt->t->core_dst_codec,
+ pvt->t->core_src_codec);
}
static struct ast_frame *fakesrc_sample(void)
@@ -501,33 +762,37 @@ static struct ast_frame *fakesrc_sample(void)
static int is_encoder(struct translator *zt)
{
- 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)) {
+ if ((zt->t.core_src_codec->id == ast_format_get_codec_id(ast_format_ulaw)) ||
+ (zt->t.core_src_codec->id == ast_format_get_codec_id(ast_format_alaw)) ||
+ (zt->t.core_src_codec->id == ast_format_get_codec_id(ast_format_slin))) {
return 1;
} else {
return 0;
}
}
-static int register_translator(int dst, int src)
+static int register_translator(unsigned dst, unsigned src)
{
+ const struct ast_codec *dst_codec;
+ const struct ast_codec *src_codec;
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));
+ dst_codec = get_dahdi_codec(dst);
+ src_codec = get_dahdi_codec(src);
+ if (!dst_codec || !src_codec) {
+ return -1;
+ }
if (!(zt = ast_calloc(1, sizeof(*zt)))) {
return -1;
}
- snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s",
- 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);
+ snprintf(zt->t.name, sizeof(zt->t.name), "dahdi_%s_to_%s",
+ src_codec->name, dst_codec->name);
+
+ memcpy(&zt->t.src_codec, src_codec, sizeof(*src_codec));
+ memcpy(&zt->t.dst_codec, dst_codec, sizeof(*dst_codec));
zt->t.buf_size = BUFFER_SIZE;
if (is_encoder(zt)) {
zt->t.framein = dahdi_encoder_framein;
@@ -557,17 +822,20 @@ static int register_translator(int dst, int src)
return res;
}
-static void drop_translator(int dst, int src)
+static void drop_translator(unsigned dst, unsigned src)
{
struct translator *cur;
AST_LIST_LOCK(&translators);
AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) {
- if (cur->t.src_format.id != ast_format_id_from_old_bitfield((1 << src)))
+ if (bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(cur->t.core_src_codec))
+ != (1U << src)) {
continue;
-
- if (cur->t.dst_format.id != ast_format_id_from_old_bitfield((1 << dst)))
+ }
+ if (bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(cur->t.core_dst_codec))
+ != (1U << dst)) {
continue;
+ }
AST_LIST_REMOVE_CURRENT(entry);
ast_unregister_translator(&cur->t);
@@ -678,7 +946,6 @@ static int unload_module(void)
static int load_module(void)
{
- ast_ulaw_init();
find_transcoders();
ast_cli_register_multiple(cli, ARRAY_LEN(cli));
return AST_MODULE_LOAD_SUCCESS;
diff --git a/codecs/codec_g722.c b/codecs/codec_g722.c
index 89641f175..1eba8067f 100644
--- a/codecs/codec_g722.c
+++ b/codecs/codec_g722.c
@@ -138,6 +138,17 @@ static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator g722tolin = {
.name = "g722tolin",
+ .src_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = g722tolin_new, /* same for both directions */
.framein = g722tolin_framein,
.sample = g722_sample,
@@ -148,6 +159,17 @@ static struct ast_translator g722tolin = {
static struct ast_translator lintog722 = {
.name = "lintog722",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "g722",
.newpvt = lintog722_new, /* same for both directions */
.framein = lintog722_framein,
.sample = slin8_sample,
@@ -158,6 +180,17 @@ static struct ast_translator lintog722 = {
static struct ast_translator g722tolin16 = {
.name = "g722tolin16",
+ .src_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "slin16",
.newpvt = g722tolin16_new, /* same for both directions */
.framein = g722tolin_framein,
.sample = g722_sample,
@@ -168,6 +201,17 @@ static struct ast_translator g722tolin16 = {
static struct ast_translator lin16tog722 = {
.name = "lin16tog722",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "g722",
.newpvt = lin16tog722_new, /* same for both directions */
.framein = lintog722_framein,
.sample = slin16_sample,
@@ -176,11 +220,6 @@ static struct ast_translator lin16tog722 = {
.buf_size = BUFFER_SAMPLES,
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res = 0;
@@ -197,18 +236,6 @@ static int load_module(void)
{
int res = 0;
- ast_format_set(&g722tolin.src_format, AST_FORMAT_G722, 0);
- ast_format_set(&g722tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintog722.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintog722.dst_format, AST_FORMAT_G722, 0);
-
- ast_format_set(&g722tolin16.src_format, AST_FORMAT_G722, 0);
- ast_format_set(&g722tolin16.dst_format, AST_FORMAT_SLINEAR16, 0);
-
- ast_format_set(&lin16tog722.src_format, AST_FORMAT_SLINEAR16, 0);
- ast_format_set(&lin16tog722.dst_format, AST_FORMAT_G722, 0);
-
res |= ast_register_translator(&g722tolin);
res |= ast_register_translator(&lintog722);
res |= ast_register_translator(&g722tolin16);
@@ -225,5 +252,4 @@ static int load_module(void)
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_g726.c b/codecs/codec_g726.c
index 72e77f955..a41039d53 100644
--- a/codecs/codec_g726.c
+++ b/codecs/codec_g726.c
@@ -785,6 +785,17 @@ static int lintog726_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator g726tolin = {
.name = "g726tolin",
+ .src_codec = {
+ .name = "g726",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = lintog726_new, /* same for both directions */
.framein = g726tolin_framein,
.sample = g726_sample,
@@ -795,6 +806,17 @@ static struct ast_translator g726tolin = {
static struct ast_translator lintog726 = {
.name = "lintog726",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "g726",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "g726",
.newpvt = lintog726_new, /* same for both directions */
.framein = lintog726_framein,
.sample = slin8_sample,
@@ -805,6 +827,17 @@ static struct ast_translator lintog726 = {
static struct ast_translator g726aal2tolin = {
.name = "g726aal2tolin",
+ .src_codec = {
+ .name = "g726aal2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = lintog726_new, /* same for both directions */
.framein = g726aal2tolin_framein,
.sample = g726_sample,
@@ -815,6 +848,17 @@ static struct ast_translator g726aal2tolin = {
static struct ast_translator lintog726aal2 = {
.name = "lintog726aal2",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "g726aal2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "g726aal2",
.newpvt = lintog726_new, /* same for both directions */
.framein = lintog726aal2_framein,
.sample = slin8_sample,
@@ -823,11 +867,6 @@ static struct ast_translator lintog726aal2 = {
.buf_size = BUFFER_SAMPLES / 2,
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res = 0;
@@ -845,18 +884,6 @@ static int load_module(void)
{
int res = 0;
- ast_format_set(&g726tolin.src_format, AST_FORMAT_G726, 0);
- ast_format_set(&g726tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintog726.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintog726.dst_format, AST_FORMAT_G726, 0);
-
- ast_format_set(&g726aal2tolin.src_format, AST_FORMAT_G726_AAL2, 0);
- ast_format_set(&g726aal2tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintog726aal2.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintog726aal2.dst_format, AST_FORMAT_G726_AAL2, 0);
-
res |= ast_register_translator(&g726tolin);
res |= ast_register_translator(&lintog726);
@@ -874,5 +901,4 @@ static int load_module(void)
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.726-32kbps G726 Transcoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c
index f42a5f1bd..49f672adb 100644
--- a/codecs/codec_gsm.c
+++ b/codecs/codec_gsm.c
@@ -168,7 +168,18 @@ static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
}
static struct ast_translator gsmtolin = {
- .name = "gsmtolin",
+ .name = "gsmtolin",
+ .src_codec = {
+ .name = "gsm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = gsm_new,
.framein = gsmtolin_framein,
.destroy = gsm_destroy_stuff,
@@ -179,7 +190,18 @@ static struct ast_translator gsmtolin = {
};
static struct ast_translator lintogsm = {
- .name = "lintogsm",
+ .name = "lintogsm",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "gsm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "gsm",
.newpvt = gsm_new,
.framein = lintogsm_framein,
.frameout = lintogsm_frameout,
@@ -189,19 +211,12 @@ static struct ast_translator lintogsm = {
.buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES,
};
-/*! \brief standard module glue */
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
res = ast_unregister_translator(&lintogsm);
- if (!res)
- res = ast_unregister_translator(&gsmtolin);
+ res |= ast_unregister_translator(&gsmtolin);
return res;
}
@@ -210,24 +225,18 @@ static int load_module(void)
{
int res;
- ast_format_set(&gsmtolin.src_format, AST_FORMAT_GSM, 0);
- ast_format_set(&gsmtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintogsm.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintogsm.dst_format, AST_FORMAT_GSM, 0);
-
res = ast_register_translator(&gsmtolin);
- if (!res)
- res=ast_register_translator(&lintogsm);
- else
- ast_unregister_translator(&gsmtolin);
- if (res)
+ res |= ast_register_translator(&lintogsm);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GSM Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_ilbc.c b/codecs/codec_ilbc.c
index 632169589..af23b906d 100644
--- a/codecs/codec_ilbc.c
+++ b/codecs/codec_ilbc.c
@@ -178,7 +178,18 @@ static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt)
}
static struct ast_translator ilbctolin = {
- .name = "ilbctolin",
+ .name = "ilbctolin",
+ .src_codec = {
+ .name = "ilbc",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = ilbctolin_new,
.framein = ilbctolin_framein,
.sample = ilbc_sample,
@@ -188,7 +199,18 @@ static struct ast_translator ilbctolin = {
};
static struct ast_translator lintoilbc = {
- .name = "lintoilbc",
+ .name = "lintoilbc",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "ilbc",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "ilbc",
.newpvt = lintoilbc_new,
.framein = lintoilbc_framein,
.frameout = lintoilbc_frameout,
@@ -211,20 +233,14 @@ static int load_module(void)
{
int res;
- ast_format_set(&ilbctolin.src_format, AST_FORMAT_ILBC, 0);
- ast_format_set(&ilbctolin.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);
- else
- ast_unregister_translator(&ilbctolin);
- if (res)
+ res |= ast_register_translator(&lintoilbc);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c
index 5f2047a3f..0ef8856ff 100644
--- a/codecs/codec_lpc10.c
+++ b/codecs/codec_lpc10.c
@@ -196,7 +196,18 @@ static void lpc10_destroy(struct ast_trans_pvt *arg)
}
static struct ast_translator lpc10tolin = {
- .name = "lpc10tolin",
+ .name = "lpc10tolin",
+ .src_codec = {
+ .name = "lpc10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = lpc10_dec_new,
.framein = lpc10tolin_framein,
.destroy = lpc10_destroy,
@@ -207,7 +218,18 @@ static struct ast_translator lpc10tolin = {
};
static struct ast_translator lintolpc10 = {
- .name = "lintolpc10",
+ .name = "lintolpc10",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "lpc10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "lpc10",
.newpvt = lpc10_enc_new,
.framein = lintolpc10_framein,
.frameout = lintolpc10_frameout,
@@ -218,12 +240,6 @@ static struct ast_translator lintolpc10 = {
.buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME),
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
-
static int unload_module(void)
{
int res;
@@ -238,24 +254,18 @@ static int load_module(void)
{
int res;
- ast_format_set(&lpc10tolin.src_format, AST_FORMAT_LPC10, 0);
- ast_format_set(&lpc10tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintolpc10.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintolpc10.dst_format, AST_FORMAT_LPC10, 0);
-
res = ast_register_translator(&lpc10tolin);
- if (!res)
- res = ast_register_translator(&lintolpc10);
- else
- ast_unregister_translator(&lpc10tolin);
- if (res)
+ res |= ast_register_translator(&lintolpc10);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LPC10 2.4kbps Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_resample.c b/codecs/codec_resample.c
index 29d95a798..26b1f0e08 100644
--- a/codecs/codec_resample.c
+++ b/codecs/codec_resample.c
@@ -42,32 +42,72 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static struct ast_translator *translators;
static int trans_size;
-static int id_list[] = {
- AST_FORMAT_SLINEAR,
- AST_FORMAT_SLINEAR12,
- AST_FORMAT_SLINEAR16,
- AST_FORMAT_SLINEAR24,
- AST_FORMAT_SLINEAR32,
- AST_FORMAT_SLINEAR44,
- AST_FORMAT_SLINEAR48,
- AST_FORMAT_SLINEAR96,
- AST_FORMAT_SLINEAR192,
+static struct ast_codec codec_list[] = {
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 12000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 24000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 44100,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 96000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 192000,
+ },
};
static int resamp_new(struct ast_trans_pvt *pvt)
{
int err;
- if (!(pvt->pvt = speex_resampler_init(1, ast_format_rate(&pvt->t->src_format), ast_format_rate(&pvt->t->dst_format), 5, &err))) {
+ if (!(pvt->pvt = speex_resampler_init(1, pvt->t->src_codec.sample_rate, pvt->t->dst_codec.sample_rate, 5, &err))) {
return -1;
}
+ ast_assert(pvt->f.subclass.format == NULL);
+ pvt->f.subclass.format = ao2_bump(ast_format_cache_get_slin_by_rate(pvt->t->dst_codec.sample_rate));
+
return 0;
}
static void resamp_destroy(struct ast_trans_pvt *pvt)
{
SpeexResamplerState *resamp_pvt = pvt->pvt;
+
speex_resampler_destroy(resamp_pvt);
}
@@ -113,13 +153,13 @@ static int load_module(void)
int res = 0;
int x, y, idx = 0;
- trans_size = ARRAY_LEN(id_list) * (ARRAY_LEN(id_list) - 1);
+ trans_size = ARRAY_LEN(codec_list) * (ARRAY_LEN(codec_list) - 1);
if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
return AST_MODULE_LOAD_FAILURE;
}
- for (x = 0; x < ARRAY_LEN(id_list); x++) {
- for (y = 0; y < ARRAY_LEN(id_list); y++) {
+ for (x = 0; x < ARRAY_LEN(codec_list); x++) {
+ for (y = 0; y < ARRAY_LEN(codec_list); y++) {
if (x == y) {
continue;
}
@@ -129,10 +169,10 @@ static int load_module(void)
translators[idx].desc_size = 0;
translators[idx].buffer_samples = (OUTBUF_SIZE / sizeof(int16_t));
translators[idx].buf_size = OUTBUF_SIZE;
- ast_format_set(&translators[idx].src_format, id_list[x], 0);
- ast_format_set(&translators[idx].dst_format, id_list[y], 0);
- snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %dkhz -> %dkhz",
- ast_format_rate(&translators[idx].src_format), ast_format_rate(&translators[idx].dst_format));
+ memcpy(&translators[idx].src_codec, &codec_list[x], sizeof(struct ast_codec));
+ memcpy(&translators[idx].dst_codec, &codec_list[y], sizeof(struct ast_codec));
+ snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %ukhz -> %ukhz",
+ translators[idx].src_codec.sample_rate, translators[idx].dst_codec.sample_rate);
res |= ast_register_translator(&translators[idx]);
idx++;
}
diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c
index 72e948057..8c2c3f395 100644
--- a/codecs/codec_speex.c
+++ b/codecs/codec_speex.c
@@ -308,10 +308,14 @@ static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
} else {
tmp->silent_state = 1;
speex_bits_reset(&tmp->bits);
+
+/* BUGBUG need to setup a new static frame to prevent destroying the translators normal static frame. */
+ ao2_cleanup(pvt->f.subclass.format);
memset(&pvt->f, 0, sizeof(pvt->f));
pvt->f.frametype = AST_FRAME_CNG;
pvt->f.samples = samples;
/* XXX what now ? format etc... */
+/* BUGBUG should return ast_frisolate(setup local static frame) here */
}
}
@@ -341,7 +345,18 @@ static void lintospeex_destroy(struct ast_trans_pvt *arg)
}
static struct ast_translator speextolin = {
- .name = "speextolin",
+ .name = "speextolin",
+ .src_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = speextolin_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
@@ -354,6 +369,17 @@ static struct ast_translator speextolin = {
static struct ast_translator lintospeex = {
.name = "lintospeex",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "speex",
.newpvt = lintospeex_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
@@ -365,7 +391,18 @@ static struct ast_translator lintospeex = {
};
static struct ast_translator speexwbtolin16 = {
- .name = "speexwbtolin16",
+ .name = "speexwbtolin16",
+ .src_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "slin16",
.newpvt = speexwbtolin16_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
@@ -377,7 +414,18 @@ static struct ast_translator speexwbtolin16 = {
};
static struct ast_translator lin16tospeexwb = {
- .name = "lin16tospeexwb",
+ .name = "lin16tospeexwb",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "speex16",
.newpvt = lin16tospeexwb_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
@@ -389,7 +437,18 @@ static struct ast_translator lin16tospeexwb = {
};
static struct ast_translator speexuwbtolin32 = {
- .name = "speexuwbtolin32",
+ .name = "speexuwbtolin32",
+ .src_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .format = "slin32",
.newpvt = speexuwbtolin32_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
@@ -400,7 +459,18 @@ static struct ast_translator speexuwbtolin32 = {
};
static struct ast_translator lin32tospeexuwb = {
- .name = "lin32tospeexuwb",
+ .name = "lin32tospeexuwb",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .dst_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .format = "speex32",
.newpvt = lin32tospeexuwb_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
@@ -534,25 +604,6 @@ static int load_module(void)
if (parse_config(0))
return AST_MODULE_LOAD_DECLINE;
-
- ast_format_set(&speextolin.src_format, AST_FORMAT_SPEEX, 0);
- ast_format_set(&speextolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintospeex.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintospeex.dst_format, AST_FORMAT_SPEEX, 0);
-
- ast_format_set(&speexwbtolin16.src_format, AST_FORMAT_SPEEX16, 0);
- ast_format_set(&speexwbtolin16.dst_format, AST_FORMAT_SLINEAR16, 0);
-
- ast_format_set(&lin16tospeexwb.src_format, AST_FORMAT_SLINEAR16, 0);
- ast_format_set(&lin16tospeexwb.dst_format, AST_FORMAT_SPEEX16, 0);
-
- ast_format_set(&speexuwbtolin32.src_format, AST_FORMAT_SPEEX32, 0);
- ast_format_set(&speexuwbtolin32.dst_format, AST_FORMAT_SLINEAR32, 0);
-
- ast_format_set(&lin32tospeexuwb.src_format, AST_FORMAT_SLINEAR32, 0);
- ast_format_set(&lin32tospeexuwb.dst_format, AST_FORMAT_SPEEX32, 0);
-
res |= ast_register_translator(&speextolin);
res |= ast_register_translator(&lintospeex);
res |= ast_register_translator(&speexwbtolin16);
@@ -560,6 +611,10 @@ static int load_module(void)
res |= ast_register_translator(&speexuwbtolin32);
res |= ast_register_translator(&lin32tospeexuwb);
+ if (res) {
+ unload_module();
+ return res;
+ }
return res;
}
diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c
index 86a0706c4..9d0aa3c14 100644
--- a/codecs/codec_ulaw.c
+++ b/codecs/codec_ulaw.c
@@ -82,6 +82,17 @@ static int lintoulaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator ulawtolin = {
.name = "ulawtolin",
+ .src_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = ulawtolin_framein,
.sample = ulaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -90,6 +101,17 @@ static struct ast_translator ulawtolin = {
static struct ast_translator testlawtolin = {
.name = "testlawtolin",
+ .src_codec = {
+ .name = "testlaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = ulawtolin_framein,
.sample = ulaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -102,6 +124,17 @@ static struct ast_translator testlawtolin = {
static struct ast_translator lintoulaw = {
.name = "lintoulaw",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "ulaw",
.framein = lintoulaw_framein,
.sample = slin8_sample,
.buf_size = BUFFER_SAMPLES,
@@ -110,17 +143,23 @@ static struct ast_translator lintoulaw = {
static struct ast_translator lintotestlaw = {
.name = "lintotestlaw",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "testlaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "testlaw",
.framein = lintoulaw_framein,
.sample = slin8_sample,
.buf_size = BUFFER_SAMPLES,
.buffer_samples = BUFFER_SAMPLES,
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
@@ -137,32 +176,20 @@ static int load_module(void)
{
int res;
- ast_format_set(&lintoulaw.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintoulaw.dst_format, AST_FORMAT_ULAW, 0);
-
- ast_format_set(&lintotestlaw.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintotestlaw.dst_format, AST_FORMAT_TESTLAW, 0);
-
- ast_format_set(&ulawtolin.src_format, AST_FORMAT_ULAW, 0);
- ast_format_set(&ulawtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&testlawtolin.src_format, AST_FORMAT_TESTLAW, 0);
- ast_format_set(&testlawtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
res = ast_register_translator(&ulawtolin);
- if (!res) {
- res = ast_register_translator(&lintoulaw);
- res |= ast_register_translator(&lintotestlaw);
- res |= ast_register_translator(&testlawtolin);
- } else
- ast_unregister_translator(&ulawtolin);
- if (res)
+ res |= ast_register_translator(&lintoulaw);
+ res |= ast_register_translator(&lintotestlaw);
+ res |= ast_register_translator(&testlawtolin);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "mu-Law Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/ex_adpcm.h b/codecs/ex_adpcm.h
index 96b7c51f8..360239789 100644
--- a/codecs/ex_adpcm.h
+++ b/codecs/ex_adpcm.h
@@ -26,7 +26,8 @@ static struct ast_frame *adpcm_sample(void)
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_adpcm,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ADPCM, 0);
+
+ f.subclass.format = ast_format_adpcm;
return &f;
}
diff --git a/codecs/ex_alaw.h b/codecs/ex_alaw.h
index bbf8ad982..e8629be5e 100644
--- a/codecs/ex_alaw.h
+++ b/codecs/ex_alaw.h
@@ -31,6 +31,6 @@ static struct ast_frame *alaw_sample(void)
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_alaw,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ALAW, 0);
+ f.subclass.format = ast_format_alaw;
return &f;
}
diff --git a/codecs/ex_g722.h b/codecs/ex_g722.h
index 0e9f22686..390cc7b5c 100644
--- a/codecs/ex_g722.h
+++ b/codecs/ex_g722.h
@@ -42,7 +42,7 @@ static struct ast_frame *g722_sample(void)
.data.ptr = ex_g722,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_G722, 0);
+ f.subclass.format = ast_format_slin;
return &f;
}
diff --git a/codecs/ex_g726.h b/codecs/ex_g726.h
index d5438c91a..f125253ee 100644
--- a/codecs/ex_g726.h
+++ b/codecs/ex_g726.h
@@ -27,7 +27,7 @@ static struct ast_frame *g726_sample(void)
.data.ptr = ex_g726,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_G726, 0);
+ f.subclass.format = ast_format_g726;
return &f;
}
diff --git a/codecs/ex_gsm.h b/codecs/ex_gsm.h
index 8f8b4f9fe..006706038 100644
--- a/codecs/ex_gsm.h
+++ b/codecs/ex_gsm.h
@@ -27,6 +27,7 @@ static struct ast_frame *gsm_sample(void)
.data.ptr = ex_gsm,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_GSM, 0);
+ f.subclass.format = ast_format_gsm;
+
return &f;
}
diff --git a/codecs/ex_ilbc.h b/codecs/ex_ilbc.h
index 93cf5eacf..3a79b0918 100644
--- a/codecs/ex_ilbc.h
+++ b/codecs/ex_ilbc.h
@@ -28,6 +28,7 @@ static struct ast_frame *ilbc_sample(void)
.data.ptr = ex_ilbc,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ILBC, 0);
+ f.subclass.format = ast_format_ilbc;
+
return &f;
}
diff --git a/codecs/ex_lpc10.h b/codecs/ex_lpc10.h
index a36e06add..2e271c005 100644
--- a/codecs/ex_lpc10.h
+++ b/codecs/ex_lpc10.h
@@ -25,7 +25,7 @@ static struct ast_frame *lpc10_sample(void)
.data.ptr = ex_lpc10,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_LPC10, 0);
+ f.subclass.format = ast_format_lpc10;
return &f;
}
diff --git a/codecs/ex_speex.h b/codecs/ex_speex.h
index e9411e5d7..76e5925b8 100644
--- a/codecs/ex_speex.h
+++ b/codecs/ex_speex.h
@@ -27,7 +27,7 @@ static struct ast_frame *speex_sample(void)
.data.ptr = ex_speex,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX, 0);
+ f.subclass.format = ast_format_speex;
return &f;
}
@@ -58,7 +58,8 @@ static struct ast_frame *speex16_sample(void)
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_speex16,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX16, 0);
+
+ f.subclass.format = ast_format_speex16;
return &f;
}
diff --git a/codecs/ex_ulaw.h b/codecs/ex_ulaw.h
index 2ab9222fb..d18a08e9c 100644
--- a/codecs/ex_ulaw.h
+++ b/codecs/ex_ulaw.h
@@ -32,6 +32,7 @@ static struct ast_frame *ulaw_sample(void)
.data.ptr = ex_ulaw,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ULAW, 0);
+ f.subclass.format = ast_format_ulaw;
+
return &f;
}
diff --git a/formats/format_g719.c b/formats/format_g719.c
index ee9221230..8d508f0e3 100644
--- a/formats/format_g719.c
+++ b/formats/format_g719.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 160 /* 20 milliseconds == 160 bytes, 960 samples */
#define SAMPLES_TO_BYTES(x) ((typeof(x)) x / ((float) 960 / 160))
@@ -44,9 +45,6 @@ static struct ast_frame *g719read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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) {
if (res)
@@ -61,14 +59,6 @@ static int g719write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -147,7 +137,8 @@ static struct ast_format_def g719_f = {
static int load_module(void)
{
- ast_format_set(&g719_f.format, AST_FORMAT_G719, 0);
+ g719_f.format = ast_format_g719;
+
if (ast_format_def_register(&g719_f))
return AST_MODULE_LOAD_DECLINE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_g723.c b/formats/format_g723.c
index c3c194d15..51fe6b049 100644
--- a/formats/format_g723.c
+++ b/formats/format_g723.c
@@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
+#include "asterisk/format_cache.h"
#define G723_MAX_SIZE 1024
@@ -64,9 +65,6 @@ static struct ast_frame *g723_read(struct ast_filestream *s, int *whennext)
return NULL;
}
/* Read the data into the buffer */
- s->fr.frametype = AST_FRAME_VOICE;
- 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, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno));
@@ -82,14 +80,6 @@ static int g723_write(struct ast_filestream *s, struct ast_frame *f)
uint16_t size;
int res;
/* XXX there used to be a check s->fr means a read stream */
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_G723_1) {
- ast_log(LOG_WARNING, "Asked to write non-g723 frame!\n");
- return -1;
- }
delay = 0;
if (f->datalen <= 0) {
ast_log(LOG_WARNING, "Short frame ignored (%d bytes long?)\n", f->datalen);
@@ -151,7 +141,7 @@ static struct ast_format_def g723_1_f = {
static int load_module(void)
{
- ast_format_set(&g723_1_f.format, AST_FORMAT_G723_1, 0);
+ g723_1_f.format = ast_format_g723;
if (ast_format_def_register(&g723_1_f))
return AST_MODULE_LOAD_FAILURE;
diff --git a/formats/format_g726.c b/formats/format_g726.c
index 636aff091..bde3e2d06 100644
--- a/formats/format_g726.c
+++ b/formats/format_g726.c
@@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define RATE_40 0
#define RATE_32 1
@@ -122,9 +123,6 @@ static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext)
struct g726_desc *fs = (struct g726_desc *)s->_private;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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;
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
@@ -141,15 +139,6 @@ static int g726_write(struct ast_filestream *s, struct ast_frame *f)
int res;
struct g726_desc *fs = (struct g726_desc *)s->_private;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_G726) {
- ast_log(LOG_WARNING, "Asked to write non-G726 frame (%s)!\n",
- ast_getformatname(&f->subclass.format));
- return -1;
- }
if (f->datalen % frame_size[fs->rate]) {
ast_log(LOG_WARNING, "Invalid data length %d, should be multiple of %d\n",
f->datalen, frame_size[fs->rate]);
@@ -239,7 +228,7 @@ static int load_module(void)
int i;
for (i = 0; f[i].desc_size ; i++) {
- ast_format_set(&f[i].format, AST_FORMAT_G726, 0);
+ f[i].format = ast_format_g726;
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;
diff --git a/formats/format_g729.c b/formats/format_g729.c
index f11fa97d9..7d562ede7 100644
--- a/formats/format_g729.c
+++ b/formats/format_g729.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeg729e.c by Jeffrey Chilton */
@@ -49,9 +50,6 @@ static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext)
{
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
@@ -66,14 +64,7 @@ static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext)
static int g729_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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) {
ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 10\n", f->datalen);
return -1;
@@ -147,7 +138,7 @@ static struct ast_format_def g729_f = {
static int load_module(void)
{
- ast_format_set(&g729_f.format, AST_FORMAT_G729A, 0);
+ g729_f.format = ast_format_g729;
if (ast_format_def_register(&g729_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_gsm.c b/formats/format_gsm.c
index 47ed41c3a..fe1e55c7a 100644
--- a/formats/format_gsm.c
+++ b/formats/format_gsm.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#include "msgsm.h"
@@ -56,10 +57,7 @@ static struct ast_frame *gsm_read(struct ast_filestream *s, int *whennext)
{
int res;
- s->fr.frametype = AST_FRAME_VOICE;
- 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) {
if (res)
ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
@@ -74,14 +72,6 @@ static int gsm_write(struct ast_filestream *fs, struct ast_frame *f)
int res;
unsigned char gsm[2*GSM_FRAME_SIZE];
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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)) {
/* This is in MSGSM format, need to be converted */
int len=0;
@@ -193,7 +183,7 @@ static struct ast_format_def gsm_f = {
static int load_module(void)
{
- ast_format_set(&gsm_f.format, AST_FORMAT_GSM, 0);
+ gsm_f.format = ast_format_gsm;
if (ast_format_def_register(&gsm_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_h263.c b/formats/format_h263.c
index 56e9b3aa0..6511cef04 100644
--- a/formats/format_h263.c
+++ b/formats/format_h263.c
@@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeh263e.c by Jeffrey Chilton */
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
* ridiculously large). */
#define BUF_SIZE 32768 /* Four real h.263 Frames */
+#define FRAME_ENDED 0x8000
+
struct h263_desc {
unsigned int lastts;
};
@@ -76,15 +79,12 @@ static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext)
if ((res = fread(&len, 1, sizeof(len), s->f)) < 1)
return NULL;
len = ntohs(len);
- mark = (len & 0x8000) ? 1 : 0;
+ mark = (len & FRAME_ENDED) ? 1 : 0;
len &= 0x7fff;
if (len > BUF_SIZE) {
ast_log(LOG_WARNING, "Length %d is too long\n", len);
return NULL;
}
- s->fr.frametype = AST_FRAME_VIDEO;
- 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) {
if (res)
@@ -93,11 +93,7 @@ static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext)
}
s->fr.samples = fs->lastts; /* XXX what ? */
s->fr.datalen = len;
- if (mark) {
- ast_format_set_video_mark(&s->fr.subclass.format);
- }
- s->fr.delivery.tv_sec = 0;
- s->fr.delivery.tv_usec = 0;
+ s->fr.subclass.frame_ending = mark;
if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) {
fs->lastts = ntohl(ts);
*whennext = fs->lastts * 4/45;
@@ -112,15 +108,7 @@ static int h263_write(struct ast_filestream *fs, struct ast_frame *f)
unsigned int ts;
unsigned short len;
uint32_t mark = 0;
- if (f->frametype != AST_FRAME_VIDEO) {
- ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
- return -1;
- }
- 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;
- }
+ mark = f->subclass.frame_ending ? FRAME_ENDED : 0;
ts = htonl(f->samples);
if ((res = fwrite(&ts, 1, sizeof(ts), fs->f)) != sizeof(ts)) {
ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
@@ -182,7 +170,7 @@ static struct ast_format_def h263_f = {
static int load_module(void)
{
- ast_format_set(&h263_f.format, AST_FORMAT_H263, 0);
+ h263_f.format = ast_format_h263;
if (ast_format_def_register(&h263_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_h264.c b/formats/format_h264.c
index e090c2bac..56ec007c0 100644
--- a/formats/format_h264.c
+++ b/formats/format_h264.c
@@ -35,12 +35,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeh264e.c by Jeffrey Chilton */
/* Portions of the conversion code are by guido@sienanet.it */
/*! \todo Check this buf size estimate, it may be totally wrong for large frame video */
+#define FRAME_ENDED 0x8000
+
#define BUF_SIZE 4096 /* Two Real h264 Frames */
struct h264_desc {
unsigned int lastts;
@@ -68,15 +71,12 @@ static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext)
if ((res = fread(&len, 1, sizeof(len), s->f)) < 1)
return NULL;
len = ntohs(len);
- mark = (len & 0x8000) ? 1 : 0;
+ mark = (len & FRAME_ENDED) ? 1 : 0;
len &= 0x7fff;
if (len > BUF_SIZE) {
ast_log(LOG_WARNING, "Length %d is too long\n", len);
len = BUF_SIZE; /* XXX truncate */
}
- s->fr.frametype = AST_FRAME_VIDEO;
- 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) {
if (res)
@@ -85,11 +85,7 @@ static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext)
}
s->fr.samples = fs->lastts;
s->fr.datalen = len;
- if (mark) {
- ast_format_set_video_mark(&s->fr.subclass.format);
- }
- s->fr.delivery.tv_sec = 0;
- s->fr.delivery.tv_usec = 0;
+ s->fr.subclass.frame_ending = mark;
if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) {
fs->lastts = ntohl(ts);
*whennext = fs->lastts * 4/45;
@@ -105,15 +101,7 @@ static int h264_write(struct ast_filestream *s, struct ast_frame *f)
unsigned short len;
int mark;
- if (f->frametype != AST_FRAME_VIDEO) {
- ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
- return -1;
- }
- 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;
- }
+ mark = f->subclass.frame_ending ? FRAME_ENDED : 0;
ts = htonl(f->samples);
if ((res = fwrite(&ts, 1, sizeof(ts), s->f)) != sizeof(ts)) {
ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
@@ -175,7 +163,7 @@ static struct ast_format_def h264_f = {
static int load_module(void)
{
- ast_format_set(&h264_f.format, AST_FORMAT_H264, 0);
+ h264_f.format = ast_format_h264;
if (ast_format_def_register(&h264_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_ilbc.c b/formats/format_ilbc.c
index 07155b717..ce5135f7b 100644
--- a/formats/format_ilbc.c
+++ b/formats/format_ilbc.c
@@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeg729e.c by Jeffrey Chilton */
@@ -48,9 +49,6 @@ static struct ast_frame *ilbc_read(struct ast_filestream *s, int *whennext)
{
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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) {
if (res)
@@ -64,14 +62,6 @@ static struct ast_frame *ilbc_read(struct ast_filestream *s, int *whennext)
static int ilbc_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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) {
ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 50\n", f->datalen);
return -1;
@@ -145,7 +135,7 @@ static struct ast_format_def ilbc_f = {
static int load_module(void)
{
- ast_format_set(&ilbc_f.format, AST_FORMAT_ILBC, 0);
+ ilbc_f.format = ast_format_ilbc;
if (ast_format_def_register(&ilbc_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_jpeg.c b/formats/format_jpeg.c
index d6733020e..1e91482f7 100644
--- a/formats/format_jpeg.c
+++ b/formats/format_jpeg.c
@@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/image.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
static struct ast_frame *jpeg_read_image(int fd, int len)
{
@@ -52,7 +53,7 @@ static struct ast_frame *jpeg_read_image(int fd, int len)
}
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_IMAGE;
- ast_format_set(&fr.subclass.format, AST_FORMAT_JPEG, 0);
+ fr.subclass.format = ast_format_jpeg;
fr.data.ptr = buf;
fr.src = "JPEG Read";
fr.datalen = len;
@@ -74,14 +75,6 @@ static int jpeg_identify(int fd)
static int jpeg_write_image(int fd, struct ast_frame *fr)
{
int res=0;
- if (fr->frametype != AST_FRAME_IMAGE) {
- ast_log(LOG_WARNING, "Not an image\n");
- return -1;
- }
- if (fr->subclass.format.id != AST_FORMAT_JPEG) {
- ast_log(LOG_WARNING, "Not a jpeg image\n");
- return -1;
- }
if (fr->datalen) {
res = write(fd, fr->data.ptr, fr->datalen);
if (res != fr->datalen) {
@@ -103,7 +96,7 @@ static struct ast_imager jpeg_format = {
static int load_module(void)
{
- ast_format_set(&jpeg_format.format, AST_FORMAT_JPEG, 0);
+ jpeg_format.format = ast_format_jpeg;
if (ast_image_register(&jpeg_format))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_ogg_vorbis.c b/formats/format_ogg_vorbis.c
index 9eb390066..6171491a8 100644
--- a/formats/format_ogg_vorbis.c
+++ b/formats/format_ogg_vorbis.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
+#include "asterisk/format_cache.h"
/*
* this is the number of samples we deal with. Samples are converted
@@ -242,16 +243,6 @@ static int ogg_vorbis_write(struct ast_filestream *fs, struct ast_frame *f)
ast_log(LOG_ERROR, "This stream is not set up for writing!\n");
return -1;
}
-
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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 (!f->datalen)
return -1;
@@ -310,9 +301,6 @@ static struct ast_frame *ogg_vorbis_read(struct ast_filestream *fs,
}
/* initialize frame */
- fs->fr.frametype = AST_FRAME_VOICE;
- 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);
out_buf = (char *) (fs->fr.data.ptr); /* SLIN data buffer */
@@ -435,7 +423,7 @@ static struct ast_format_def vorbis_f = {
static int load_module(void)
{
- ast_format_set(&vorbis_f.format, AST_FORMAT_SLINEAR, 0);
+ vorbis_f.format = ast_format_slin;
if (ast_format_def_register(&vorbis_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_pcm.c b/formats/format_pcm.c
index 1ee333fba..2d864078e 100644
--- a/formats/format_pcm.c
+++ b/formats/format_pcm.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/endian.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 160 /* 160 bytes, and same number of samples */
@@ -66,7 +67,7 @@ static unsigned long get_time(void)
static int pcma_open(struct ast_filestream *s)
{
- if (s->fmt->format == AST_FORMAT_ALAW)
+ if (ast_format_cmp(s->fmt->format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
pd->starttime = get_time();
return 0;
}
@@ -83,9 +84,6 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext)
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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) {
if (res)
@@ -93,7 +91,7 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext)
return NULL;
}
s->fr.datalen = res;
- if (s->fmt->format.id == AST_FORMAT_G722)
+ if (ast_format_cmp(s->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL)
*whennext = s->fr.samples = res * 2;
else
*whennext = s->fr.samples = res;
@@ -141,7 +139,7 @@ static int pcm_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
}
if (whence == SEEK_FORCECUR && offset > max) { /* extend the file */
size_t left = offset - max;
- const char *src = (fs->fmt->format.id == AST_FORMAT_ALAW) ? alaw_silence : ulaw_silence;
+ const char *src = (ast_format_cmp(fs->fmt->format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ? alaw_silence : ulaw_silence;
while (left) {
size_t written = fwrite(src, 1, (left > BUF_SIZE) ? BUF_SIZE : left, fs->f);
@@ -185,17 +183,8 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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;
- }
-
#ifdef REALTIME_WRITE
- if (s->fmt->format == AST_FORMAT_ALAW) {
+ if (ast_format_cmp(s->fmt->format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
struct pcm_desc *pd = (struct pcm_desc *)fs->_private;
struct stat stat_buf;
unsigned long cur_time = get_time();
@@ -399,7 +388,7 @@ static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
off_t min = AU_HEADER_SIZE, max, cur;
long offset = 0, bytes;
- if (fs->fmt->format.id == AST_FORMAT_G722)
+ if (ast_format_cmp(fs->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL)
bytes = sample_offset / 2;
else
bytes = sample_offset;
@@ -523,10 +512,10 @@ static int load_module(void)
for (i = 0; i < ARRAY_LEN(alaw_silence); i++)
alaw_silence[i] = AST_LIN2A(0);
- 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);
+ pcm_f.format = ast_format_ulaw;
+ alaw_f.format = ast_format_alaw;
+ au_f.format = ast_format_ulaw;
+ g722_f.format = ast_format_g722;
if ( ast_format_def_register(&pcm_f)
|| ast_format_def_register(&alaw_f)
|| ast_format_def_register(&au_f)
diff --git a/formats/format_siren14.c b/formats/format_siren14.c
index 77a9fe3ef..b7e2de1ec 100644
--- a/formats/format_siren14.c
+++ b/formats/format_siren14.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 120 /* 20 milliseconds == 120 bytes, 640 samples */
#define SAMPLES_TO_BYTES(x) ((typeof(x)) x / ((float) 640 / 120))
@@ -44,9 +45,6 @@ static struct ast_frame *siren14read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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) {
if (res)
@@ -61,14 +59,6 @@ static int siren14write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -148,7 +138,7 @@ static struct ast_format_def siren14_f = {
static int load_module(void)
{
- ast_format_set(&siren14_f.format, AST_FORMAT_SIREN14, 0);
+ siren14_f.format = ast_format_siren14;
if (ast_format_def_register(&siren14_f))
return AST_MODULE_LOAD_DECLINE;
diff --git a/formats/format_siren7.c b/formats/format_siren7.c
index 35e2a3460..0b3c75d9c 100644
--- a/formats/format_siren7.c
+++ b/formats/format_siren7.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 80 /* 20 milliseconds == 80 bytes, 320 samples */
#define SAMPLES_TO_BYTES(x) x / (320 / 80)
@@ -44,9 +45,6 @@ static struct ast_frame *siren7read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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) {
if (res)
@@ -61,14 +59,6 @@ static int siren7write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -148,7 +138,7 @@ static struct ast_format_def siren7_f = {
static int load_module(void)
{
- ast_format_set(&siren7_f.format, AST_FORMAT_SIREN7, 0);
+ siren7_f.format = ast_format_siren7;
if (ast_format_def_register(&siren7_f))
return AST_MODULE_LOAD_DECLINE;
diff --git a/formats/format_sln.c b/formats/format_sln.c
index 30a1ebe31..a3230637c 100644
--- a/formats/format_sln.c
+++ b/formats/format_sln.c
@@ -32,15 +32,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
-static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size, enum ast_format_id id)
+static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size)
{
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, id, 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) {
if (res)
@@ -52,17 +50,9 @@ static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, u
return &s->fr;
}
-static int generic_write(struct ast_filestream *fs, struct ast_frame *f, enum ast_format_id id)
+static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != id) {
- 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) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -127,8 +117,7 @@ static off_t slinear_tell(struct ast_filestream *fs)
return ftello(fs->f) / 2;
}
-static int slinear_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR);}
-static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 320, AST_FORMAT_SLINEAR);}
+static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 320);}
static struct ast_format_def slin_f = {
.name = "sln",
.exts = "sln|raw",
@@ -140,12 +129,11 @@ static struct ast_format_def slin_f = {
.buf_size = 320 + AST_FRIENDLY_OFFSET,
};
-static int slinear12_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR12);}
-static struct ast_frame *slinear12_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 480, AST_FORMAT_SLINEAR12);}
+static struct ast_frame *slinear12_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 480);}
static struct ast_format_def slin12_f = {
.name = "sln12",
.exts = "sln12",
- .write = slinear12_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -153,12 +141,11 @@ static struct ast_format_def slin12_f = {
.buf_size = 480 + AST_FRIENDLY_OFFSET,
};
-static int slinear16_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR16);}
-static struct ast_frame *slinear16_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 640, AST_FORMAT_SLINEAR16);}
+static struct ast_frame *slinear16_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 640);}
static struct ast_format_def slin16_f = {
.name = "sln16",
.exts = "sln16",
- .write = slinear16_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -166,12 +153,11 @@ static struct ast_format_def slin16_f = {
.buf_size = 640 + AST_FRIENDLY_OFFSET,
};
-static int slinear24_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR24);}
-static struct ast_frame *slinear24_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 960, AST_FORMAT_SLINEAR24);}
+static struct ast_frame *slinear24_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 960);}
static struct ast_format_def slin24_f = {
.name = "sln24",
.exts = "sln24",
- .write = slinear24_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -179,12 +165,11 @@ static struct ast_format_def slin24_f = {
.buf_size = 960 + AST_FRIENDLY_OFFSET,
};
-static int slinear32_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR32);}
-static struct ast_frame *slinear32_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1280, AST_FORMAT_SLINEAR32);}
+static struct ast_frame *slinear32_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1280);}
static struct ast_format_def slin32_f = {
.name = "sln32",
.exts = "sln32",
- .write = slinear32_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -192,12 +177,11 @@ static struct ast_format_def slin32_f = {
.buf_size = 1280 + AST_FRIENDLY_OFFSET,
};
-static int slinear44_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR44);}
-static struct ast_frame *slinear44_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1764, AST_FORMAT_SLINEAR44);}
+static struct ast_frame *slinear44_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1764);}
static struct ast_format_def slin44_f = {
.name = "sln44",
.exts = "sln44",
- .write = slinear44_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -205,12 +189,11 @@ static struct ast_format_def slin44_f = {
.buf_size = 1764 + AST_FRIENDLY_OFFSET,
};
-static int slinear48_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR48);}
-static struct ast_frame *slinear48_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1920, AST_FORMAT_SLINEAR48);}
+static struct ast_frame *slinear48_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1920);}
static struct ast_format_def slin48_f = {
.name = "sln48",
.exts = "sln48",
- .write = slinear48_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -218,12 +201,11 @@ static struct ast_format_def slin48_f = {
.buf_size = 1920 + AST_FRIENDLY_OFFSET,
};
-static int slinear96_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR96);}
-static struct ast_frame *slinear96_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 3840, AST_FORMAT_SLINEAR96);}
+static struct ast_frame *slinear96_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 3840);}
static struct ast_format_def slin96_f = {
.name = "sln96",
.exts = "sln96",
- .write = slinear96_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -231,12 +213,11 @@ static struct ast_format_def slin96_f = {
.buf_size = 3840 + AST_FRIENDLY_OFFSET,
};
-static int slinear192_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR192);}
-static struct ast_frame *slinear192_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 7680, AST_FORMAT_SLINEAR192);}
+static struct ast_frame *slinear192_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 7680);}
static struct ast_format_def slin192_f = {
.name = "sln192",
.exts = "sln192",
- .write = slinear192_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -259,15 +240,16 @@ static struct ast_format_def *slin_list[] = {
static int load_module(void)
{
int i;
- ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&slin12_f.format, AST_FORMAT_SLINEAR12, 0);
- ast_format_set(&slin16_f.format, AST_FORMAT_SLINEAR16, 0);
- ast_format_set(&slin24_f.format, AST_FORMAT_SLINEAR24, 0);
- ast_format_set(&slin32_f.format, AST_FORMAT_SLINEAR32, 0);
- ast_format_set(&slin44_f.format, AST_FORMAT_SLINEAR44, 0);
- ast_format_set(&slin48_f.format, AST_FORMAT_SLINEAR48, 0);
- ast_format_set(&slin96_f.format, AST_FORMAT_SLINEAR96, 0);
- ast_format_set(&slin192_f.format, AST_FORMAT_SLINEAR192, 0);
+
+ slin_f.format = ast_format_slin;
+ slin12_f.format = ast_format_slin12;
+ slin16_f.format = ast_format_slin16;
+ slin24_f.format = ast_format_slin24;
+ slin32_f.format = ast_format_slin32;
+ slin44_f.format = ast_format_slin44;
+ slin48_f.format = ast_format_slin48;
+ slin96_f.format = ast_format_slin96;
+ slin192_f.format = ast_format_slin192;
for (i = 0; i < ARRAY_LEN(slin_list); i++) {
if (ast_format_def_register(slin_list[i])) {
diff --git a/formats/format_vox.c b/formats/format_vox.c
index f640021d8..7beec5e6a 100644
--- a/formats/format_vox.c
+++ b/formats/format_vox.c
@@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 80 /* 80 bytes, 160 samples */
#define VOX_SAMPLES 160
@@ -44,9 +45,6 @@ static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- 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) {
if (res)
@@ -61,14 +59,6 @@ static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
static int vox_write(struct ast_filestream *s, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -147,7 +137,7 @@ static struct ast_format_def vox_f = {
static int load_module(void)
{
- ast_format_set(&vox_f.format, AST_FORMAT_ADPCM, 0);
+ vox_f.format = ast_format_adpcm;
if (ast_format_def_register(&vox_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_wav.c b/formats/format_wav.c
index 06d6ae12d..fb810625f 100644
--- a/formats/format_wav.c
+++ b/formats/format_wav.c
@@ -35,6 +35,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format.h"
+#include "asterisk/codec.h"
/* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
@@ -319,7 +322,7 @@ static int wav_open(struct ast_filestream *s)
if we did, it would go here. We also might want to check
and be sure it's a valid file. */
struct wav_desc *tmp = (struct wav_desc *)s->_private;
- if ((tmp->maxlen = check_header(s->f, (s->fmt->format.id == AST_FORMAT_SLINEAR16 ? 16000 : 8000))) < 0)
+ if ((tmp->maxlen = check_header(s->f, ast_format_get_sample_rate(s->fmt->format))) < 0)
return -1;
return 0;
}
@@ -331,7 +334,7 @@ static int wav_rewrite(struct ast_filestream *s, const char *comment)
and be sure it's a valid file. */
struct wav_desc *tmp = (struct wav_desc *)s->_private;
- tmp->hz = (s->fmt->format.id == AST_FORMAT_SLINEAR16 ? 16000 : 8000);
+ tmp->hz = ast_format_get_sample_rate(s->fmt->format);
if (write_header(s->f,tmp->hz))
return -1;
return 0;
@@ -379,9 +382,6 @@ static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
if (bytes < 0)
bytes = 0;
/* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
- s->fr.frametype = AST_FRAME_VOICE;
- 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);
if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) {
@@ -412,18 +412,6 @@ static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
struct wav_desc *s = (struct wav_desc *)fs->_private;
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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 (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;
- }
if (!f->datalen)
return -1;
@@ -547,8 +535,8 @@ static struct ast_format_def wav_f = {
static int load_module(void)
{
- ast_format_set(&wav_f.format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&wav16_f.format, AST_FORMAT_SLINEAR16, 0);
+ wav_f.format = ast_format_slin;
+ wav16_f.format = ast_format_slin16;
if (ast_format_def_register(&wav_f)
|| ast_format_def_register(&wav16_f))
return AST_MODULE_LOAD_FAILURE;
diff --git a/formats/format_wav_gsm.c b/formats/format_wav_gsm.c
index c8d83ff4c..bbb1977a9 100644
--- a/formats/format_wav_gsm.c
+++ b/formats/format_wav_gsm.c
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#include "msgsm.h"
@@ -409,11 +410,7 @@ static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
/* Send a frame from the file to the appropriate channel */
struct wavg_desc *fs = (struct wavg_desc *)s->_private;
- s->fr.frametype = AST_FRAME_VOICE;
- 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_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, GSM_FRAME_SIZE);
if (fs->secondhalf) {
/* Just return a frame based on the second GSM frame */
@@ -443,14 +440,6 @@ static int wav_write(struct ast_filestream *s, struct ast_frame *f)
int size;
struct wavg_desc *fs = (struct wavg_desc *)s->_private;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- 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
* we assume it is already in the correct format.
*/
@@ -577,7 +566,7 @@ static struct ast_format_def wav49_f = {
static int load_module(void)
{
- ast_format_set(&wav49_f.format, AST_FORMAT_GSM, 0);
+ wav49_f.format = ast_format_gsm;
if (ast_format_def_register(&wav49_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/funcs/func_channel.c b/funcs/func_channel.c
index 82fb4c348..3f756f0b5 100644
--- a/funcs/func_channel.c
+++ b/funcs/func_channel.c
@@ -427,23 +427,27 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
}
if (!strcasecmp(data, "audionativeformat")) {
- char tmp[512];
+ tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmpcap) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
- if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
- ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
- tmpcap = ast_format_cap_destroy(tmpcap);
+ ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
+ ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
+ ao2_ref(tmpcap, -1);
}
} else if (!strcasecmp(data, "videonativeformat")) {
- char tmp[512];
+ tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmpcap) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
- if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
- ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
- tmpcap = ast_format_cap_destroy(tmpcap);
+ ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
+ ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
+ ao2_ref(tmpcap, -1);
}
} else if (!strcasecmp(data, "audioreadformat")) {
- ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
+ ast_copy_string(buf, ast_format_get_name(ast_channel_readformat(chan)), len);
} else if (!strcasecmp(data, "audiowriteformat")) {
- ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
+ ast_copy_string(buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
#ifdef CHANNEL_TRACE
} else if (!strcasecmp(data, "trace")) {
ast_channel_lock(chan);
diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c
index ecebde4df..681a96924 100644
--- a/funcs/func_frame_trace.c
+++ b/funcs/func_frame_trace.c
@@ -219,14 +219,14 @@ static void print_frame(struct ast_frame *frame)
break;
case AST_FRAME_VOICE:
ast_verbose("FrameType: VOICE\n");
- ast_verbose("Codec: %s\n", ast_getformatname(&frame->subclass.format));
+ ast_verbose("Codec: %s\n", ast_format_get_name(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.format));
+ ast_verbose("Codec: %s\n", ast_format_get_name(frame->subclass.format));
ast_verbose("MS: %ld\n", frame->len);
ast_verbose("Samples: %d\n", frame->samples);
ast_verbose("Bytes: %d\n", frame->datalen);
diff --git a/funcs/func_pitchshift.c b/funcs/func_pitchshift.c
index e5091d95d..0aaa2b602 100644
--- a/funcs/func_pitchshift.c
+++ b/funcs/func_pitchshift.c
@@ -172,9 +172,7 @@ static int pitchshift_cb(struct ast_audiohook *audiohook, struct ast_channel *ch
if (!f) {
return 0;
}
- if ((audiohook->status == AST_AUDIOHOOK_STATUS_DONE) ||
- (f->frametype != AST_FRAME_VOICE) ||
- !(ast_format_is_slinear(&f->subclass.format))) {
+ if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
return -1;
}
@@ -489,7 +487,7 @@ static int pitch_shift(struct ast_frame *f, float amount, struct fft_data *fft)
return 0;
}
for (samples = 0; samples < f->samples; samples += 32) {
- smb_pitch_shift(amount, 32, MAX_FRAME_LENGTH, 32, ast_format_rate(&f->subclass.format), fun+samples, fun+samples, fft);
+ smb_pitch_shift(amount, 32, MAX_FRAME_LENGTH, 32, ast_format_get_sample_rate(f->subclass.format), fun+samples, fun+samples, fft);
}
return 0;
diff --git a/funcs/func_speex.c b/funcs/func_speex.c
index 4e3c13b87..d0d451bd1 100644
--- a/funcs/func_speex.c
+++ b/funcs/func_speex.c
@@ -165,8 +165,8 @@ static int speex_callback(struct ast_audiohook *audiohook, struct ast_channel *c
return -1;
}
- if ((sdi->samples != frame->samples) || (ast_format_rate(&frame->subclass.format) != si->lastrate)) {
- si->lastrate = ast_format_rate(&frame->subclass.format);
+ if ((sdi->samples != frame->samples) || (ast_format_get_sample_rate(frame->subclass.format) != si->lastrate)) {
+ si->lastrate = ast_format_get_sample_rate(frame->subclass.format);
if (sdi->state) {
speex_preprocess_state_destroy(sdi->state);
}
diff --git a/funcs/func_talkdetect.c b/funcs/func_talkdetect.c
index c4783f51f..f127fa3d7 100644
--- a/funcs/func_talkdetect.c
+++ b/funcs/func_talkdetect.c
@@ -284,7 +284,7 @@ static int set_talk_detect(struct ast_channel *chan, int dsp_silence_threshold,
td_params->audiohook.manipulate_callback = talk_detect_audiohook_cb;
ast_set_flag(&td_params->audiohook, AST_AUDIOHOOK_TRIGGER_READ);
- td_params->dsp = ast_dsp_new_with_rate(ast_format_rate(ast_channel_rawreadformat(chan)));
+ td_params->dsp = ast_dsp_new_with_rate(ast_format_get_sample_rate(ast_channel_rawreadformat(chan)));
if (!td_params->dsp) {
ast_datastore_free(datastore);
ast_free(td_params);
diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h
index 67d17382b..01a8352fc 100644
--- a/include/asterisk/_private.h
+++ b/include/asterisk/_private.h
@@ -121,16 +121,6 @@ int ast_xmldoc_load_documentation(void);
*/
int ast_plc_reload(void);
-/*!
- * \brief Init the ast_format attribute interface register container.
- */
-int ast_format_attr_init(void);
-
-/*!
- * \brief Init the Asterisk global format list after all format attribute modules have been loaded
- */
-int ast_format_list_init(void);
-
/*! \brief initializes the rtp engine arrays */
int ast_rtp_engine_init(void);
diff --git a/include/asterisk/abstract_jb.h b/include/asterisk/abstract_jb.h
index 6a4d0610d..8a5e3d27f 100644
--- a/include/asterisk/abstract_jb.h
+++ b/include/asterisk/abstract_jb.h
@@ -145,7 +145,7 @@ struct ast_jb
/*! \brief The time the next frame should be played. */
long next;
/*! \brief Voice format of the last frame in. */
- struct ast_format last_format;
+ struct ast_format *last_format;
/*! \brief File for frame timestamp tracing. */
FILE *logfile;
/*! \brief Jitterbuffer internal state flags. */
diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h
index 6b0716092..375b2dd9d 100644
--- a/include/asterisk/audiohook.h
+++ b/include/asterisk/audiohook.h
@@ -109,7 +109,7 @@ struct ast_audiohook {
struct ast_slinfactory write_factory; /*!< Factory where frames written to the channel will go through */
struct timeval read_time; /*!< Last time read factory was fed */
struct timeval write_time; /*!< Last time write factory was fed */
- struct ast_format 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 */
diff --git a/include/asterisk/bridge_channel.h b/include/asterisk/bridge_channel.h
index ae8369d15..387c048f8 100644
--- a/include/asterisk/bridge_channel.h
+++ b/include/asterisk/bridge_channel.h
@@ -133,9 +133,9 @@ struct ast_bridge_channel {
* optimizing based upon talk detection. */
struct ast_bridge_tech_optimizations tech_args;
/*! Copy of read format used by chan before join */
- struct ast_format read_format;
+ struct ast_format *read_format;
/*! Copy of write format used by chan before join */
- struct ast_format write_format;
+ struct ast_format *write_format;
/*! Call ID associated with bridge channel */
struct ast_callid *callid;
/*! A clone of the roles living on chan when the bridge channel joins the bridge. This may require some opacification */
diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h
index 4f32dbf66..f7d7719d2 100644
--- a/include/asterisk/callerid.h
+++ b/include/asterisk/callerid.h
@@ -75,8 +75,8 @@
/*! MWI MDMF format -- generate name, callerid, date and MWI fields */
#define CID_MWI_TYPE_MDMF_FULL 0x02
-#define AST_LIN2X(a) ((codec->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)))
+#define AST_LIN2X(a) ((ast_format_cmp(codec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ? (AST_LIN2A(a)) : (AST_LIN2MU(a)))
+#define AST_XLAW(a) ((ast_format_cmp(codec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ? (AST_ALAW(a)) : (AST_MULAW(a)))
struct callerid_state;
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index dec19cba0..d118bc81f 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1883,14 +1883,6 @@ int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap
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 id 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
@@ -1908,14 +1900,6 @@ int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_ca
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 id 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
*
* \param chan channel to act upon
@@ -2103,17 +2087,6 @@ char *ast_transfercapability2str(int transfercapability) attribute_const;
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block);
/*!
- * \brief Pick the best codec
- *
- * \param cap 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);
-
-
-/*!
* \brief Checks the value of an option
*
* Query the value of an option
@@ -4008,6 +3981,13 @@ struct ast_format *ast_channel_rawwriteformat(struct ast_channel *chan);
struct ast_format *ast_channel_readformat(struct ast_channel *chan);
struct ast_format *ast_channel_writeformat(struct ast_channel *chan);
+/* Format setters - all of these functions will increment the reference count of the format passed in */
+void ast_channel_set_oldwriteformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format);
+
/* Other struct getters */
struct ast_frame *ast_channel_dtmff(struct ast_channel *chan);
struct ast_jb *ast_channel_jb(struct ast_channel *chan);
diff --git a/include/asterisk/codec.h b/include/asterisk/codec.h
new file mode 100644
index 000000000..28befec50
--- /dev/null
+++ b/include/asterisk/codec.h
@@ -0,0 +1,186 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Codec API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _AST_CODEC_H_
+#define _AST_CODEC_H_
+
+/*! \brief Types of media */
+enum ast_media_type {
+ AST_MEDIA_TYPE_UNKNOWN = 0,
+ AST_MEDIA_TYPE_AUDIO,
+ AST_MEDIA_TYPE_VIDEO,
+ AST_MEDIA_TYPE_IMAGE,
+ AST_MEDIA_TYPE_TEXT,
+};
+
+struct ast_module;
+
+/*! \brief Represents a media codec within Asterisk. */
+struct ast_codec {
+ /*! \brief Internal unique identifier for this codec, set at registration time (starts at 1) */
+ unsigned int id;
+ /*! \brief Name for this codec */
+ const char *name;
+ /*! \brief Brief description */
+ const char *description;
+ /*! \brief Type of media this codec contains */
+ enum ast_media_type type;
+ /*! \brief Sample rate (number of samples carried in a second) */
+ unsigned int sample_rate;
+ /*! \brief Minimum length of media that can be carried (in milliseconds) in a frame */
+ unsigned int minimum_ms;
+ /*! \brief Maximum length of media that can be carried (in milliseconds) in a frame */
+ unsigned int maximum_ms;
+ /*! \brief Default length of media carried (in milliseconds) in a frame */
+ unsigned int default_ms;
+ /*! \brief Length in bytes of the data payload of a minimum_ms frame */
+ unsigned int minimum_bytes;
+ /*!
+ * \brief Retrieve the number of samples in a frame
+ *
+ * \param frame The frame to examine
+ *
+ * \return the number of samples
+ */
+ int (*samples_count)(struct ast_frame *frame);
+ /*!
+ * \brief Retrieve the length of media from number of samples
+ *
+ * \param samples The number of samples
+ *
+ * \return The length of media in milliseconds
+ */
+ int (*get_length)(unsigned int samples);
+ /*! \brief Whether the media can be smoothed or not */
+ unsigned int smooth;
+ /*! \brief The module that registered this codec */
+ struct ast_module *mod;
+};
+
+/*!
+ * \brief Initialize codec support within the core.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_codec_init(void);
+
+/*!
+ * \brief Initialize built-in codecs within the core.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_codec_builtin_init(void);
+
+/*!
+ * \brief This function is used to register a codec with the Asterisk core. Registering
+ * allows it to be passed through in frames and configured in channel drivers.
+ *
+ * \param codec to register
+ * \param mod the module this codec is provided by
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod);
+
+/*!
+ * \brief This function is used to register a codec with the Asterisk core. Registering
+ * allows it to be passed through in frames and configured in channel drivers.
+ *
+ * \param codec to register
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+#define ast_codec_register(codec) __ast_codec_register(codec, ast_module_info->self)
+
+/*!
+ * \brief Retrieve a codec given a name, type, and sample rate
+ *
+ * \param name The name of the codec
+ * \param type The type of the codec
+ * \param sample_rate Optional sample rate, may not be applicable for some types
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The returned codec is reference counted and ao2_ref or ao2_cleanup
+ * must be used to release the reference.
+ */
+struct ast_codec *ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate);
+
+/*!
+ * \brief Retrieve a codec given the unique identifier
+ *
+ * \param id The unique identifier
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note Identifiers start at 1 so if iterating don't start at 0.
+ *
+ * \note The returned codec is reference counted and ao2_ref or ao2_cleanup
+ * must be used to release the reference.
+ */
+struct ast_codec *ast_codec_get_by_id(int id);
+
+/*!
+ * \brief Retrieve the current maximum identifier for codec iteration
+ *
+ * \return Maximum codec identifier
+ */
+int ast_codec_get_max(void);
+
+/*!
+ * \brief Conversion function to take a media type and turn it into a string
+ *
+ * \param type The media type
+ *
+ * \retval string representation of the media type
+ */
+const char *ast_codec_media_type2str(enum ast_media_type type);
+
+/*!
+ * \brief Get the number of samples contained within a frame
+ *
+ * \param frame The frame itself
+ *
+ * \retval number of samples in the frame
+ */
+unsigned int ast_codec_samples_count(struct ast_frame *frame);
+
+/*!
+ * \brief Get the length of media (in milliseconds) given a number of samples
+ *
+ * \param codec The codec itself
+ * \param samples The number of samples
+ *
+ * \retval length of media (in milliseconds)
+ */
+unsigned int ast_codec_determine_length(const struct ast_codec *codec, unsigned int samples);
+
+#endif /* _AST_CODEC_H */
diff --git a/include/asterisk/config_options.h b/include/asterisk/config_options.h
index 11a8c5bf9..30c042176 100644
--- a/include/asterisk/config_options.h
+++ b/include/asterisk/config_options.h
@@ -317,21 +317,20 @@ enum aco_option_type {
*/
OPT_CHAR_ARRAY_T,
- /*! \brief Type for default option handler for codec preferences/capabilities
+ /*! \brief Type for default option handler for format capabilities
* \note aco_option_register flags:
* non-zero : This is an "allow" style option
* 0 : This is a "disallow" style option
* aco_option_register varargs:
- * FLDSET macro with fields representing a struct ast_codec_pref and a struct ast_format_cap *
+ * FLDSET macro with field representing a struct ast_format_cap *
*
* Example:
* {code}
* struct test_item {
- * struct ast_codec_pref pref;
* struct ast_format cap *cap;
* };
- * aco_option_register(&cfg_info, "allow", ACO_EXACT, my_types, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct test_item, pref, cap));
- * aco_option_register(&cfg_info, "disallow", ACO_EXACT, my_types, "all", OPT_CODEC_T, 0, FLDSET(struct test_item, pref, cap));
+ * aco_option_register(&cfg_info, "allow", ACO_EXACT, my_types, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct test_item, cap));
+ * aco_option_register(&cfg_info, "disallow", ACO_EXACT, my_types, "all", OPT_CODEC_T, 0, FLDSET(struct test_item, cap));
* {endcode}
*/
OPT_CODEC_T,
diff --git a/include/asterisk/data.h b/include/asterisk/data.h
index e3253377e..3676b8df5 100644
--- a/include/asterisk/data.h
+++ b/include/asterisk/data.h
@@ -26,6 +26,7 @@
#define ASTERISK_DATA_H
#include "asterisk/frame.h"
+#include "asterisk/format_cap.h"
/*!
* \page AstDataRetrieval The Asterisk DATA retrieval API.
diff --git a/include/asterisk/file.h b/include/asterisk/file.h
index 372c0f7ed..3d8d2c97c 100644
--- a/include/asterisk/file.h
+++ b/include/asterisk/file.h
@@ -385,7 +385,7 @@ char *ast_format_str_reduce(char *fmts);
* \retval NULL if not found
* \retval A pointer to the ast_format associated with this file extension
*/
-const struct ast_format *ast_get_format_for_file_ext(const char *file_ext);
+struct ast_format *ast_get_format_for_file_ext(const char *file_ext);
#if defined(__cplusplus) || defined(c_plusplus)
}
diff --git a/include/asterisk/format.h b/include/asterisk/format.h
index 885c62b2d..32f9f2b40 100644
--- a/include/asterisk/format.h
+++ b/include/asterisk/format.h
@@ -1,9 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -18,464 +18,354 @@
/*!
* \file
- * \brief Format API
+ * \brief Media Format API
*
- * \author David Vossel <dvossel@digium.com>
+ * \author Joshua Colp <jcolp@digium.com>
*/
+#include "asterisk/codec.h"
+
#ifndef _AST_FORMAT_H_
#define _AST_FORMAT_H_
-#include "asterisk/astobj2.h"
-#include "asterisk/silk.h"
-#include "asterisk/celt.h"
-#include "asterisk/opus.h"
-#define AST_FORMAT_ATTR_SIZE 64
-#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,
- /*! LPC10, 180 samples/frame */
- AST_FORMAT_LPC10 = 7 + AST_FORMAT_TYPE_AUDIO,
- /*! G.729A audio */
- AST_FORMAT_G729A = 8 + AST_FORMAT_TYPE_AUDIO,
- /*! SpeeX Free Compression */
- AST_FORMAT_SPEEX = 9 + AST_FORMAT_TYPE_AUDIO,
- /*! iLBC Free Compression */
- AST_FORMAT_ILBC = 10 + AST_FORMAT_TYPE_AUDIO,
- /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
- AST_FORMAT_G726 = 11 + AST_FORMAT_TYPE_AUDIO,
- /*! G.722 */
- AST_FORMAT_G722 = 12 + AST_FORMAT_TYPE_AUDIO,
- /*! G.722.1 (also known as Siren7, 32kbps assumed) */
- AST_FORMAT_SIREN7 = 13 + AST_FORMAT_TYPE_AUDIO,
- /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
- AST_FORMAT_SIREN14 = 14 + AST_FORMAT_TYPE_AUDIO,
- /*! G.719 (64 kbps assumed) */
- AST_FORMAT_G719 = 15 + AST_FORMAT_TYPE_AUDIO,
- /*! SpeeX Wideband (16kHz) Free Compression */
- AST_FORMAT_SPEEX16 = 16 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw mu-law data (G.711) */
- AST_FORMAT_TESTLAW = 17 + AST_FORMAT_TYPE_AUDIO,
- /*! SILK format */
- AST_FORMAT_SILK = 18 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
- AST_FORMAT_SLINEAR = 19 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (12000 Hz) PCM */
- AST_FORMAT_SLINEAR12 = 20 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
- AST_FORMAT_SLINEAR16 = 21 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (24000 Hz) PCM */
- AST_FORMAT_SLINEAR24 = 22 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (32000 Hz) PCM */
- AST_FORMAT_SLINEAR32 = 23 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (44100 Hz) PCM just because we can. */
- AST_FORMAT_SLINEAR44 = 24 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (48000 Hz) PCM */
- AST_FORMAT_SLINEAR48 = 25 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (96000 Hz) PCM */
- AST_FORMAT_SLINEAR96 = 26 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (192000 Hz) PCM. maybe we're taking this too far. */
- AST_FORMAT_SLINEAR192 = 27 + AST_FORMAT_TYPE_AUDIO,
- AST_FORMAT_SPEEX32 = 28 + AST_FORMAT_TYPE_AUDIO,
- AST_FORMAT_CELT = 29 + AST_FORMAT_TYPE_AUDIO,
- /*! Opus */
- AST_FORMAT_OPUS = 30 + 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,
- /*! VP8 */
- AST_FORMAT_VP8 = 6 + 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 */
- uint32_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;
-};
+struct ast_format;
+/*! \brief Format comparison results */
enum ast_format_cmp_res {
- /*! structure 1 is identical to structure 2. */
+ /*! Both formats are equivalent to eachother */
AST_FORMAT_CMP_EQUAL = 0,
- /*! structure 1 contains elements not in structure 2. */
+ /*! Both formats are completely different and not the same in any way */
AST_FORMAT_CMP_NOT_EQUAL,
- /*! structure 1 is a proper subset of the elements in structure 2.*/
+ /*! Both formats are similar but not equivalent */
AST_FORMAT_CMP_SUBSET,
};
-/*! \brief Definition of supported media formats (codecs) */
-struct ast_format_list {
- struct ast_format format; /*!< The unique format. */
- char name[64]; /*!< short name */
- unsigned int samplespersecond; /*!< Number of samples per second (8000/16000) */
- char desc[128]; /*!< Description */
- int fr_len; /*!< Single frame length in bytes */
- int min_ms; /*!< Min value */
- int max_ms; /*!< Max value */
- int inc_ms; /*!< Increment */
- int def_ms; /*!< Default value */
- unsigned int flags; /*!< Smoother flags */
- int cur_ms; /*!< Current value */
- int custom_entry;
-};
-
-/*! \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.
+/*! \brief Optional format interface to extend format operations */
+struct ast_format_interface {
+ /*!
+ * \brief Callback for when the format is destroyed, used to release attribute resources
*
- * \retval ast_format_cmp_res representing the result of comparing fattr1 and fattr2.
+ * \param format The format structure to destroy
*/
- enum ast_format_cmp_res (* const format_attr_cmp)(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2);
+ void (*const format_destroy)(struct ast_format *format);
- /*! \brief Get joint attributes of same format type if they exist.
+ /*!
+ * \brief Callback for when the format is cloned, used to clone attributes
+ *
+ * \param src Source format of attributes
+ * \param dst Destination format for attributes
*
- * \retval 0 if joint attributes exist
- * \retval -1 if no joint attributes are present
+ * \retval 0 success
+ * \retval -1 failure
*/
- 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);
+ int (*const format_clone)(const struct ast_format *src, struct ast_format *dst);
/*!
- * \brief Find out if format capabilities in va_list are in format.
- * \note This function does not need to call va_end of the va_list.
+ * \brief Determine if format 1 is a subset of format 2.
*
- * \note This function is optional. In many cases the format_attr_cmp
- * function can be used to derive these results. If it is possible
- * that some format attributes have no bearing on the equality of two formats, this
- * function must exist.
+ * \param format1 First format to compare
+ * \param format2 Second format which the first is compared against
*
- * \retval 0 if all attributes exist
- * \retval -1 if any of the attributes not present
+ * \retval ast_format_cmp_res representing the result of comparing format1 and format2.
*/
- int (* const format_attr_isset)(const struct ast_format_attr *format_attr, va_list ap);
+ enum ast_format_cmp_res (* const format_cmp)(const struct ast_format *format1,
+ const struct ast_format *format2);
- /*
- * \brief Return a value for a specific format key. Return that value in the void pointer.
+ /*!
+ * \brief Get a format with the joint compatible attributes of both provided formats.
+ *
+ * \param format1 The first format
+ * \param format2 The second format
+ *
+ * \retval non-NULL if joint format
+ * \retval NULL if no joint format
*
- * \note It is not expected that all key value pairs can be returned, but those that can should
- * be documented as such.
+ * \note The returned format has its reference count incremented and must be released using
+ * ao2_ref or ao2_cleanup.
+ */
+ struct ast_format *(* const format_get_joint)(const struct ast_format *format1,
+ const struct ast_format *format2);
+
+ /*!
+ * \brief Set an attribute on a format
*
- * \note This function is optional if key value pairs are not allowed to be accessed. This
- * will result in -1 always being returned.
+ * \param name The name of the attribute
+ * \param value The value of the attribute
*
- * \retval 0 Success, value was found and copied into void pointer.
- * \retval -1 failure, Value was either not found, or not allowed to be accessed.
+ * \retval non-NULL success
+ * \retval NULL failure
*/
- int (* const format_attr_get_val)(const struct ast_format_attr *format_attr, int key, void *val);
+ struct ast_format *(* const format_attribute_set)(const struct ast_format *format,
+ const char *name, const char *value);
- /*
- * \brief Parse SDP attribute information, interpret it, and store it in ast_format_attr structure.
+ /*!
+ * \brief Parse SDP attribute information, interpret it, and store it in the format structure.
+ *
+ * \param format Format to set attributes on
+ * \param attributes A string containing only the attributes from the fmtp line
*
- * \retval 0 Success, values were valid
- * \retval -1 Failure, some values were not acceptable
+ * \retval non-NULL Success, values were valid
+ * \retval NULL Failure, some values were not acceptable
*/
- int (* const format_attr_sdp_parse)(struct ast_format_attr *format_attr, const char *attributes);
+ struct ast_format *(* const format_parse_sdp_fmtp)(const struct ast_format *format, const char *attributes);
/*!
* \brief Generate SDP attribute information from an ast_format_attr structure.
*
+ * \param format The format containing attributes
+ * \param payload The payload number to place into the fmtp line
+ * \param str The generated fmtp line
+ *
* \note This callback should generate a full fmtp line using the provided payload number.
*/
- void (* const format_attr_sdp_generate)(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str);
+ void (* const format_generate_sdp_fmtp)(const struct ast_format *format, unsigned int payload,
+ struct ast_str **str);
};
/*!
- * \brief This function is used to have a media format aware module parse and interpret
- * SDP attribute information. Once interpreted this information is stored on the format
- * itself using Asterisk format attributes.
+ * \brief Initialize media format support
*
- * \param format to set
- * \param attributes string containing the fmtp line from the SDP
- *
- * \retval 0 success, attribute values were valid
- * \retval -1 failure, values were not acceptable
+ * \retval 0 success
+ * \retval -1 failure
*/
-int ast_format_sdp_parse(struct ast_format *format, const char *attributes);
+int ast_format_init(void);
/*!
- * \brief This function is used to produce an fmtp SDP line for an Asterisk format. The
- * attributes present on the Asterisk format are translated into the SDP equivalent.
+ * \brief Create a new media format
*
- * \param format to generate an fmtp line for
- * \param payload numerical payload for the fmtp line
- * \param str structure that the fmtp line will be appended to
+ * \param codec The codec to use
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The format is returned with reference count incremented. It must be released using
+ * ao2_ref or ao2_cleanup.
*/
-void ast_format_sdp_generate(const struct ast_format *format, unsigned int payload, struct ast_str **str);
+struct ast_format *ast_format_create(struct ast_codec *codec);
/*!
- * \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;
+ * \brief Create a new media format with a specific name
*
- * \details Example usage.
- * ast_format_set(format, AST_FORMAT_ULAW, 0); // no capability attributes are needed for ULAW
+ * \param format_name The name to use for the format
+ * \param codec The codec to use
*
- * 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 creation function should be used when the name of the \c codec
+ * cannot be explicitly used for the name of the format. This is the case for
+ * codecs with multiple sample rates
*
- * \note This function will initialize the ast_format structure.
+ * \note The format is returned with reference count incremented. It must be released using
+ * ao2_ref or ao2_cleanup.
*
- * \return Pointer to ast_format object, same pointer that is passed in
- * by the first argument.
+ * \retval non-NULL success
+ * \retval NULL failure
*/
-struct ast_format *ast_format_set(struct ast_format *format, enum ast_format_id id, int set_attributes, ... );
+struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec);
/*!
- * \brief After ast_format_set has been used on a function, this function can be used to
- * set additional format attributes to the structure.
+ * \brief Clone an existing media format so it can be modified
*
- * \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.
+ * \param format The existing media format
+ *
+ * \note The returned format is a new ao2 object. It must be released using ao2_cleanup.
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
*/
-struct ast_format *ast_format_append(struct ast_format *format, ... );
+struct ast_format *ast_format_clone(const struct ast_format *format);
/*!
- * \brief Clears the format stucture.
+ * \brief Compare two formats
+ *
+ * \retval ast_format_cmp_res representing the result of comparing format1 and format2.
*/
-void ast_format_clear(struct ast_format *format);
+enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2);
/*!
- * \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.
+ * \brief Get a common joint capability between two formats
*
- * \details Example usage. Is this SILK format capable of 8khz
- * is_8khz = ast_format_isset(format, AST_FORMAT_SILK_CAP_RATE, 8000);
+ * \retval non-NULL if joint capability exists
+ * \retval NULL if no joint capability exists
*
- * \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.
+ * \note The returned format must be treated as immutable.
*/
-int ast_format_isset(const struct ast_format *format, ... );
+struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2);
/*!
- * \brief Get a value from a format containing attributes.
- * \note The key represents the format attribute to be retrieved, and the void pointer
- * is to the structure that value will be stored in. It must be known what structure a
- * key represents.
+ * \brief Set an attribute on a format to a specific value
*
- * \retval 0, success
- * \retval -1, failure
- */
-int ast_format_get_value(const struct ast_format *format, int key, void *value);
-
-/*!
- * \brief Compare ast_formats structures
+ * \param format The format to set the attribute on
+ * \param name Attribute name
+ * \param value Attribute value
*
- * \retval ast_format_cmp_res representing the result of comparing format1 and format2.
+ * \retval non-NULL success
+ * \retval NULL failure
*/
-enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2);
+struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name,
+ const char *value);
/*!
- * \brief Find joint format attributes of two ast_format
- * structures containing the same uid and return the intersection in the
- * result structure.
+ * \brief This function is used to have a media format aware module parse and interpret
+ * SDP attribute information. Once interpreted this information is stored on the format
+ * itself using Asterisk format attributes.
*
- * retval 0, joint attribute capabilities exist.
- * retval -1, no joint attribute capabilities exist.
+ * \param format to set
+ * \param attributes string containing the fmtp line from the SDP
+ *
+ * \retval non-NULL success, attribute values were valid
+ * \retval NULL failure, values were not acceptable
*/
-int ast_format_joint(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result);
+struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes);
/*!
- * \brief copy format src into format dst.
+ * \brief This function is used to produce an fmtp SDP line for an Asterisk format. The
+ * attributes present on the Asterisk format are translated into the SDP equivalent.
+ *
+ * \param format to generate an fmtp line for
+ * \param payload numerical payload for the fmtp line
+ * \param str structure that the fmtp line will be appended to
*/
-void ast_format_copy(struct ast_format *dst, const struct ast_format *src);
+void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str);
/*!
- * \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.
+ * \brief Register a format interface for use with the provided codec
+ *
+ * \param codec The name of codec the interface is applicable to
+ * \param interface A pointer to the interface implementation
+ * \param mod The module this format interface is provided by
+ *
+ * \retval 0 success
+ * \retval -1 failure
*/
-void ast_format_set_video_mark(struct ast_format *format);
+int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod);
/*!
- * \brief Determine of the marker bit is set or not on this format.
+ * \brief Register a format interface for use with the provided codec
*
- * \retval 1, true
- * \retval 0, false
+ * \param codec The name of codec the interface is applicable to
+ * \param interface A pointer to the interface implementation
+ *
+ * \retval 0 success
+ * \retval -1 failure
*/
-int ast_format_get_video_mark(const struct ast_format *format);
+#define ast_format_interface_register(codec, interface) __ast_format_interface_register(codec, interface, ast_module_info->self)
/*!
- * \brief ast_format to old bitfield format represenatation
+ * \brief Get the attribute data on a format
*
- * \note This is only to be used for IAX2 compatibility
+ * \param format The media format
*
- * \retval iax2 representation of ast_format
- * \retval 0, if no representation existis for iax2
+ * \return Currently set attribute data
*/
-uint64_t ast_format_to_old_bitfield(const struct ast_format *format);
+void *ast_format_get_attribute_data(const struct ast_format *format);
/*!
- * \brief ast_format_id to old bitfield format represenatation
+ * \brief Set the attribute data on a format
*
+ * \param format The media format
+ * \param attribute_data The attribute data
*/
-uint64_t ast_format_id_to_old_bitfield(enum ast_format_id id);
+void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data);
/*!
- * \brief convert old bitfield format to ast_format represenatation
- * \note This is only to be used for IAX2 compatibility
+ * \brief Get the name associated with a format
*
- * \retval on success, pointer to the dst format in the input parameters
- * \retval on failure, NULL
+ * \param format The media format
+ *
+ * \return The name of the format
*/
-struct ast_format *ast_format_from_old_bitfield(struct ast_format *dst, uint64_t src);
+const char *ast_format_get_name(const struct ast_format *format);
/*!
- * \brief convert old bitfield format to ast_format_id value
+ * \brief Get the codec identifier associated with a format
+ *
+ * \param format The media format
+ *
+ * \return codec identifier
*/
-enum ast_format_id ast_format_id_from_old_bitfield(uint64_t src);
+unsigned int ast_format_get_codec_id(const struct ast_format *format);
/*!
- * \brief Retrieve the global format list in a read only array.
- * \note ast_format_list_destroy must be called on every format
- * list retrieved from this function.
+ * \brief Get the codec name associated with a format
+ *
+ * \param format The media format
+ *
+ * \return The codec name
*/
-const struct ast_format_list *ast_format_list_get(size_t *size);
+const char *ast_format_get_codec_name(const struct ast_format *format);
/*!
- * \brief Destroy an ast_format_list gotten from ast_format_list_get()
- */
-const struct ast_format_list *ast_format_list_destroy(const struct ast_format_list *list);
-
-/*! \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.
- */
-const char* ast_getformatname(const struct ast_format *format);
-
-/*! \brief Returns a string containing all formats pertaining to an format id.
- * \param buf a buffer for the output string
- * \param size size of buf (bytes)
- * \param id format id.
- * \return The return value is buf.
+ * \brief Get whether or not the format can be smoothed
+ *
+ * \param format The media format
+ *
+ * \retval 0 the format cannot be smoothed
+ * \retval 1 the format can be smoothed
*/
-char* ast_getformatname_multiple_byid(char *buf, size_t size, enum ast_format_id id);
+int ast_format_can_be_smoothed(const struct ast_format *format);
/*!
- * \brief Gets a format from a name.
- * \param name string of format
- * \param format structure to return the format in.
- * \return This returns the format pointer given to it on success and NULL on failure
+ * \brief Get the media type of a format
+ *
+ * \param format The media format
+ *
+ * \return the media type
*/
-struct ast_format *ast_getformatbyname(const char *name, struct ast_format *format);
+enum ast_media_type ast_format_get_type(const struct ast_format *format);
/*!
- * \brief Get a name from a format
- * \param format to get name of
- * \return This returns a static string identifying the format on success, 0 on error.
+ * \brief Get the default framing size (in milliseconds) for a format
+ *
+ * \param format The media format
+ *
+ * \return default framing size in milliseconds
*/
-const char *ast_codec2str(struct ast_format *format);
+unsigned int ast_format_get_default_ms(const struct ast_format *format);
/*!
- * \brief Get the sample rate for a given format.
+ * \brief Get the minimum amount of media carried in this format
+ *
+ * \param format The media format
+ *
+ * \return minimum framing size in milliseconds
*/
-int ast_format_rate(const struct ast_format *format);
+unsigned int ast_format_get_minimum_ms(const struct ast_format *format);
/*!
- * \brief register ast_format_attr_interface with core.
+ * \brief Get the maximum amount of media carried in this format
*
- * \retval 0 success
- * \retval -1 failure
+ * \param format The media format
+ *
+ * \return maximum framing size in milliseconds
*/
-int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interface);
+unsigned int ast_format_get_maximum_ms(const struct ast_format *format);
/*!
- * \brief unregister format_attr interface with core.
+ * \brief Get the minimum number of bytes expected in a frame for this format
*
- * \retval 0 success
- * \retval -1 failure
+ * \param format The media format
+ *
+ * \return minimum expected bytes in a frame for this format
*/
-int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *interface);
+unsigned int ast_format_get_minimum_bytes(const struct ast_format *format);
/*!
- * \brief Determine if a format is 16bit signed linear of any sample rate.
+ * \brief Get the sample rate of a media format
+ *
+ * \param format The media format
+ *
+ * \return sample rate
*/
-int ast_format_is_slinear(const struct ast_format *format);
+unsigned int ast_format_get_sample_rate(const struct ast_format *format);
/*!
- * \brief Get the best slinear format id for a given sample rate
+ * \brief Get the length (in milliseconds) for the format with a given number of samples
+ *
+ * \param format The media format
+ * \param samples The number of samples
+ *
+ * \return length of media (in milliseconds)
*/
-enum ast_format_id ast_format_slin_by_rate(unsigned int rate);
+unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples);
/*!
* \since 12
@@ -494,4 +384,5 @@ struct stasis_message_type *ast_format_register_type(void);
* \retval NULL on error
*/
struct stasis_message_type *ast_format_unregister_type(void);
+
#endif /* _AST_FORMAT_H */
diff --git a/include/asterisk/format_cache.h b/include/asterisk/format_cache.h
new file mode 100644
index 000000000..e0744054e
--- /dev/null
+++ b/include/asterisk/format_cache.h
@@ -0,0 +1,301 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Cache API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _AST_FORMAT_CACHE_H_
+#define _AST_FORMAT_CACHE_H_
+
+struct ast_format;
+
+/*!
+ * \brief Built-in cached signed linear 8kHz format.
+ */
+extern struct ast_format *ast_format_slin;
+
+/*!
+ * \brief Built-in cached signed linear 12kHz format.
+ */
+extern struct ast_format *ast_format_slin12;
+
+/*!
+ * \brief Built-in cached signed linear 16kHz format.
+ */
+extern struct ast_format *ast_format_slin16;
+
+/*!
+ * \brief Built-in cached signed linear 24kHz format.
+ */
+extern struct ast_format *ast_format_slin24;
+
+/*!
+ * \brief Built-in cached signed linear 32kHz format.
+ */
+extern struct ast_format *ast_format_slin32;
+
+/*!
+ * \brief Built-in cached signed linear 44kHz format.
+ */
+extern struct ast_format *ast_format_slin44;
+
+/*!
+ * \brief Built-in cached signed linear 48kHz format.
+ */
+extern struct ast_format *ast_format_slin48;
+
+/*!
+ * \brief Built-in cached signed linear 96kHz format.
+ */
+extern struct ast_format *ast_format_slin96;
+
+/*!
+ * \brief Built-in cached signed linear 192kHz format.
+ */
+extern struct ast_format *ast_format_slin192;
+
+/*!
+ * \brief Built-in cached ulaw format.
+ */
+extern struct ast_format *ast_format_ulaw;
+
+/*!
+ * \brief Built-in cached alaw format.
+ */
+extern struct ast_format *ast_format_alaw;
+
+/*!
+ * \brief Built-in cached testlaw format.
+ */
+extern struct ast_format *ast_format_testlaw;
+
+/*!
+ * \brief Built-in cached gsm format.
+ */
+extern struct ast_format *ast_format_gsm;
+
+/*!
+ * \brief Built-in cached adpcm format.
+ */
+extern struct ast_format *ast_format_adpcm;
+
+/*!
+ * \brief Built-in cached g722 format.
+ */
+extern struct ast_format *ast_format_g722;
+
+/*!
+ * \brief Built-in cached g726 format.
+ */
+extern struct ast_format *ast_format_g726;
+
+/*!
+ * \brief Built-in cached g726 aal2 format.
+ */
+extern struct ast_format *ast_format_g726_aal2;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+extern struct ast_format *ast_format_ilbc;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+extern struct ast_format *ast_format_lpc10;
+
+/*!
+ * \brief Built-in cached speex format.
+ */
+extern struct ast_format *ast_format_speex;
+
+/*!
+ * \brief Built-in cached speex at 16kHz format.
+ */
+extern struct ast_format *ast_format_speex16;
+
+/*!
+ * \brief Built-in cached speex at 32kHz format.
+ */
+extern struct ast_format *ast_format_speex32;
+
+/*!
+ * \brief Built-in cached g723.1 format.
+ */
+extern struct ast_format *ast_format_g723;
+
+/*!
+ * \brief Built-in cached g729 format.
+ */
+extern struct ast_format *ast_format_g729;
+
+/*!
+ * \brief Built-in cached g719 format.
+ */
+extern struct ast_format *ast_format_g719;
+
+/*!
+ * \brief Built-in cached h261 format.
+ */
+extern struct ast_format *ast_format_h261;
+
+/*!
+ * \brief Built-in cached h263 format.
+ */
+extern struct ast_format *ast_format_h263;
+
+/*!
+ * \brief Built-in cached h263 plus format.
+ */
+extern struct ast_format *ast_format_h263p;
+
+/*!
+ * \brief Built-in cached h264 format.
+ */
+extern struct ast_format *ast_format_h264;
+
+/*!
+ * \brief Built-in cached mp4 format.
+ */
+extern struct ast_format *ast_format_mp4;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+extern struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in cached jpeg format.
+ */
+extern struct ast_format *ast_format_jpeg;
+
+/*!
+ * \brief Built-in cached png format.
+ */
+extern struct ast_format *ast_format_png;
+
+/*!
+ * \brief Built-in cached siren14 format.
+ */
+extern struct ast_format *ast_format_siren14;
+
+/*!
+ * \brief Built-in cached siren7 format.
+ */
+extern struct ast_format *ast_format_siren7;
+
+/*!
+ * \brief Built-in cached opus format.
+ */
+extern struct ast_format *ast_format_opus;
+
+/*!
+ * \brief Built-in cached t140 format.
+ */
+extern struct ast_format *ast_format_t140;
+
+/*!
+ * \brief Built-in cached t140 red format.
+ */
+extern struct ast_format *ast_format_t140_red;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+extern struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in "null" format.
+ */
+extern struct ast_format *ast_format_none;
+
+/*!
+ * \brief Initialize format cache support within the core.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_format_cache_init(void);
+
+/*!
+ * \brief Set a named format cache entry.
+ *
+ * \param format A pointer to the format to cache
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_format_cache_set(struct ast_format *format);
+
+/*!
+ * \brief Retrieve a named format from the cache.
+ *
+ * \param name Name of the cached format
+ *
+ * \retval non-NULL if found
+ * \retval NULL if not found
+ *
+ * \note The returned format has its reference count incremented. It must be
+ * dropped using ao2_ref or ao2_cleanup.
+ */
+struct ast_format *__ast_format_cache_get(const char *name);
+struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func);
+
+#ifdef REF_DEBUG
+#define ast_format_cache_get(name) \
+ __ast_format_cache_get_debug((name), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_t_format_cache_get(name, tag) \
+ __ast_format_cache_get_debug((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#else
+#define ast_format_cache_get(name) \
+ __ast_format_cache_get((name))
+#define ast_t_format_cache_get(name, tag) \
+ __ast_format_cache_get((name))
+#endif
+
+
+/*!
+ * \brief Retrieve the best signed linear format given a sample rate.
+ *
+ * \param rate The sample rate
+ *
+ * \details
+ * This is a convenience function that returns one of the global
+ * ast_format_slinxxx formats.
+ *
+ * \return pointer to the signed linear format
+ *
+ * \note The returned format has NOT had its reference count incremented.
+ */
+struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate);
+
+/*!
+ * \brief Determines if a format is one of the cached slin formats
+ *
+ * \param format The format to check
+ *
+ * \retval 0 if the format is not an SLIN format
+ * \retval 1 if the format is an SLIN format
+ */
+int ast_format_cache_is_slinear(struct ast_format *format);
+
+#endif /* _AST_FORMAT_CACHE_H */
diff --git a/include/asterisk/format_cap.h b/include/asterisk/format_cap.h
index aa4eb3bfd..f7d33fccd 100644
--- a/include/asterisk/format_cap.h
+++ b/include/asterisk/format_cap.h
@@ -1,9 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -18,216 +18,289 @@
/*!
* \file
- * \brief Format Capability API
+ * \brief Format Capabilities API
*
- * \author David Vossel <dvossel@digium.com>
+ * \author Joshua Colp <jcolp@digium.com>
*/
-#ifndef _AST_FORMATCAP_H_
-#define _AST_FORMATCAP_H_
+#ifndef _AST_FORMAT_CAP_H_
+#define _AST_FORMAT_CAP_H_
-/*! Capabilities are represented by an opaque structure statically defined in format_capability.c */
+#include "asterisk/codec.h"
+
+/*! Capabilities are represented by an opaque structure statically defined in format_cap.c */
struct ast_format_cap;
enum ast_format_cap_flags {
/*!
- * The ast_format_cap will be allocated with no lock.
- * Useful if there is a separate lock used to protect the structure
- */
- AST_FORMAT_CAP_FLAG_NOLOCK = (1 << 0),
- /*!
- * String representations of the formats are cached on the structure.
- * Useful if string representation is frequently requested of the structure.
+ * Default format capabilities settings
*/
- AST_FORMAT_CAP_FLAG_CACHE_STRINGS = (1 << 1),
+ AST_FORMAT_CAP_FLAG_DEFAULT = 0,
};
/*!
* \brief Allocate a new ast_format_cap structure
*
* \param flags Modifiers of struct behavior.
+ *
* \retval ast_format_cap object on success.
* \retval NULL on failure.
*/
-struct ast_format_cap *ast_format_cap_alloc(enum ast_format_cap_flags flags);
+struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags);
+struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func);
+
+#ifdef REF_DEBUG
+#define ast_format_cap_alloc(flags) \
+ __ast_format_cap_alloc_debug((flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_t_format_cap_alloc(flags, tag) \
+ __ast_format_cap_alloc_debug((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#else
+#define ast_format_cap_alloc(flags) \
+ __ast_format_cap_alloc((flags))
+#define ast_t_format_cap_alloc(flags, tag) \
+ __ast_format_cap_alloc((flags))
+#endif
/*!
- * \brief Destroy an ast_format_cap structure.
+ * \brief Set the global framing.
+ *
+ * \param cap The capabilities structure.
+ * \param framing The framing value (in milliseconds).
*
- * \return NULL
+ * \note This is used if a format does not provide a framing itself. Note that
+ * adding subsequent formats to the \c ast_format_cap structure may
+ * override this value, if the framing they require is less than the
+ * value set by this function.
*/
-void *ast_format_cap_destroy(struct ast_format_cap *cap);
+void ast_format_cap_set_framing(struct ast_format_cap *cap, unsigned int framing);
/*!
- * \brief Add format capability to capabilities structure.
+ * \brief Get the global framing.
*
- * \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.
+ * \param cap The capabilities structure.
+ *
+ * \retval 0 if no formats are in the structure and no framing has been provided
+ * \retval The global framing value (in milliseconds)
+ *
+ * \note This will be the minimum framing allowed across all formats in the
+ * capabilities structure, or an overridden value
*/
-void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format);
+unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap);
/*!
- * \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.
+ * \brief Add format capability to capabilities structure.
+ *
+ * \param cap The capabilities structure to add to.
+ * \param format The format to add.
+ * \param framing The framing for the format (in milliseconds).
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note A reference to the format is taken and used in the capabilities structure.
+ *
+ * \note The order in which add is called determines the format preference order.
+ *
+ * \note If framing is specified here it overrides any global framing that has been set.
*/
-void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type);
+int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing);
+int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func);
+
+#ifdef REF_DEBUG
+#define ast_format_cap_append(cap, format, framing) \
+ __ast_format_cap_append_debug((cap), (format), (framing), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_t_format_cap_append(cap, format, framing, tag) \
+ __ast_format_cap_append_debug((cap), (format), (framing), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#else
+#define ast_format_cap_append(cap, format, framing) \
+ __ast_format_cap_append((cap), (format), (framing))
+#define ast_t_format_cap_append(cap, format, framing, tag) \
+ __ast_format_cap_append((cap), (format), (framing))
+#endif
/*!
- * \brief Add all known formats to the capabilities structure using default format attribute.
+ * \brief Add all codecs Asterisk knows about for a specific type to
+ * the capabilities structure.
+ *
+ * \param cap The capabilities structure to add to.
+ * \param type The type of formats to add.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note A generic format with no attributes is created using the codec.
+ *
+ * \note If AST_MEDIA_TYPE_UNKNOWN is passed as the type all known codecs will be added.
*/
-void ast_format_cap_add_all(struct ast_format_cap *cap);
+int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type);
/*!
- * \brief Append the formats in src to dst
+ * \brief Append the formats of provided type in src to dst
+ *
+ * \param dst The destination capabilities structure
+ * \param src The source capabilities structure
+ * \param type The type of formats to append.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note If AST_MEDIA_TYPE_UNKNOWN is passed as the type all known codecs will be added.
*/
-void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src);
+int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type);
/*!
- * \brief Copy all items in src to dst.
- * \note any items in dst will be removed before copying
+ * \brief Replace the formats of provided type in dst with equivalent formats from src
+ *
+ * \param dst The destination capabilities structure
+ * \param src The source capabilities structure
+ * \param type The type of formats to replace.
+ *
+ * \note If AST_MEDIA_TYPE_UNKNOWN is passed as the type all known codecs will be replaced.
+ * \note Formats present in src but not dst will not be appended to dst.
*/
-void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src);
+void ast_format_cap_replace_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type);
/*!
- * \brief create a deep copy of an ast_format_cap structure
+ * \brief Parse an "allow" or "deny" list and modify a format capabilities structure accordingly
+ *
+ * \param cap The capabilities structure to modify
+ * \param list The list containing formats to append or remove
+ * \param allowing If zero, start removing formats specified in the list. If non-zero,
+ * start appending formats specified in the list.
*
- * \retval cap on success
- * \retval NULL on failure
+ * \retval 0 on success
+ * \retval -1 on failure
*/
-struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *src);
+int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing);
/*!
- * \brief determine if a capabilities structure is empty or not
+ * \brief Get the number of formats present within the capabilities structure
*
- * \retval 1, true is empty
- * \retval 0, false, not empty
+ * \param cap The capabilities structure
+ *
+ * \return the number of formats
*/
-int ast_format_cap_is_empty(const struct ast_format_cap *cap);
+size_t ast_format_cap_count(const struct ast_format_cap *cap);
/*!
- * \brief Remove format capability from capability structure.
+ * \brief Get the format at a specific index
*
- * \note format must match Exactly to format in ast_format_cap object in order
- * to be removed.
+ * \param cap The capabilities structure
+ * \param position The position to get
*
- * \retval 0, remove was successful
- * \retval -1, remove failed. Could not find format to remove
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note This is a zero based index.
+ *
+ * \note Formats are returned in order of preference.
+ *
+ * \note The reference count of the returned format is increased. It must be released using ao2_ref
+ * or ao2_cleanup.
*/
-int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format);
+struct ast_format *ast_format_cap_get_format(const struct ast_format_cap *cap, int position);
/*!
- * \brief Remove all format capabilities from capability
- * structure for a specific format id.
+ * \brief Get the most preferred format for a particular media type
*
- * \note This will remove _ALL_ formats matching the format id from the
- * capabilities structure.
+ * \param cap The capabilities structure
+ * \param type The type of media to get
*
- * \retval 0, remove was successful
- * \retval -1, remove failed. Could not find formats to remove
+ * \retval non-NULL the preferred format
+ * \retval NULL no media of \c type present
+ *
+ * \note The reference count of the returned format is increased. It must be released using ao2_ref
+ * or ao2_cleanup.
*/
-int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id);
+struct ast_format *ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type);
/*!
- * \brief Remove all formats matching a specific format type.
+ * \brief Get the framing for a format
+ *
+ * \param cap The capabilities structure
+ * \param format The format to retrieve
+ *
+ * \return the framing (in milliseconds)
*/
-void ast_format_cap_remove_bytype(struct ast_format_cap *cap, enum ast_format_type type);
+unsigned int ast_format_cap_get_format_framing(const struct ast_format_cap *cap, const struct ast_format *format);
/*!
- * \brief Remove all format capabilities from capability structure
+ * \brief Remove format capability from capability structure.
+ *
+ * \note format must be an exact pointer match to remove from capabilities structure.
+ *
+ * \retval 0, remove was successful
+ * \retval -1, remove failed. Could not find format to remove
*/
-void ast_format_cap_remove_all(struct ast_format_cap *cap);
+int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format);
/*!
- * \brief Remove all previous formats and set a single new format.
+ * \brief Remove all formats matching a specific format type.
+ *
+ * \param cap The capabilities structure
+ * \param type The media type to remove formats of
+ *
+ * \note All formats can be removed by using the AST_MEDIA_TYPE_UNKNOWN type.
*/
-void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format);
+void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type);
/*!
* \brief Find if input ast_format is within the capabilities of the ast_format_cap object
* then return the compatible format from the capabilities structure in the result.
*
- * \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.
+ * \retval non-NULL if format is compatible
+ * \retval NULL if not compatible
+ *
+ * \note The reference count of the returned format is increased. It must be released using ao2_ref
+ * or ao2_cleanup.
*/
-int ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format, struct ast_format *result);
+struct ast_format *ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const 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.
+* \retval ast_format_cmp_res representing the result of the compatibility check between cap and format.
*/
-int ast_format_cap_iscompatible(const struct ast_format_cap *cap, const struct ast_format *format);
+enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format);
/*!
- * \brief Finds the best quality audio format for a given format id and returns it in result.
+ * \brief Find the compatible formats between two capabilities structures
*
- * \retval 1 format found and set to result structure.
- * \retval 0 no format found, result structure is cleared.
- */
-int ast_format_cap_best_byid(const struct ast_format_cap *cap, enum ast_format_id, struct ast_format *result);
-
-/*!
- * \brief is cap1 identical to cap2
+ * \param cap1 The first capabilities structure
+ * \param cap2 The second capabilities structure
+ * \param[out] result The capabilities structure to place the results into
*
- * 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.
+ * \retval 0 success
+ * \retval -1 failure
*
- * \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.
+ * \note The preference order of cap1 is respected.
*
- * \retval !NULL success, joint capabilties structure with _NO_ locking enabled.
- * \retval NULL failure
+ * \note If failure occurs the result format capabilities structure may contain a partial result.
*/
-struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
+int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2,
+ struct ast_format_cap *result);
/*!
- * \brief Get joint capability structure, copy into result capabilities structure
+ * \brief Determine if any joint capabilities exist between two capabilities structures
*
- * \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 Get joint capability structure, append into result capabilities structure
+ * \param cap1 The first capabilities structure
+ * \param cap2 The second capabilities structure
*
- * \retval 1, joint capabilities exist
- * \retval 0, joint capabilities do not exist
+ * \retval 0 no joint capabilities exist
+ * \retval 1 joint capabilities exist
*/
-int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result);
+int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
/*!
- * \brief Find out if capability structures have any joint capabilities without
- * returning those capabilities.
+ * \brief Determine if two capabilities structures are identical
*
- * \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
+ * \param cap1 The first capabilities structure
+ * \param cap2 The second capabilities structure
*
- * \retval !NULL success, new capabilities structure with _NO_ locking enabled on the new structure.
- * \retval NULL failure
+ * \retval 0 capabilities are not identical
+ * \retval 1 capabilities are identical
*/
-struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype);
+int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
/*!
* \brief Find out if the capabilities structure has any formats
@@ -236,68 +309,16 @@ struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap,
* \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);
+int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type);
/*!
- * \brief ast_format_cap to old bitfield format represenatation
+ * \brief Get the names of codecs of a set of formats
*
- * \note This is only to be used for IAX2 compatibility
+ * \param cap The capabilities structure containing the formats
+ * \param buf A \c ast_str buffer to populate with the names of the formats
*
- * \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);
-
-/*! \brief Get the names of a set of formats
- * \param buf a buffer for the output string
- * \param size size of buf (bytes)
- * \param cap format the format (combined IDs of codecs)
- * Prints a list of readable codec names corresponding to "format".
- * ex: for format=AST_FORMAT_GSM|AST_FORMAT_SPEEX|AST_FORMAT_ILBC it will return "0x602 (GSM|SPEEX|ILBC)"
- * \return The return value is buf.
+ * \return The contents of the buffer in \c buf
*/
-char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap);
+const char *ast_format_cap_get_names(struct ast_format_cap *cap, struct ast_str **buf);
-#endif /* _AST_FORMATCAP_H */
+#endif /* _AST_FORMAT_CAP_H */
diff --git a/include/asterisk/format_compatibility.h b/include/asterisk/format_compatibility.h
new file mode 100644
index 000000000..f14b7166c
--- /dev/null
+++ b/include/asterisk/format_compatibility.h
@@ -0,0 +1,129 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _AST_FORMAT_COMPATIBILITY_H_
+#define _AST_FORMAT_COMPATIBILITY_H_
+
+struct ast_format;
+struct ast_codec;
+
+/*
+ * Legacy bitfields for specific formats
+ */
+
+/*! G.723.1 compression */
+#define AST_FORMAT_G723 (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_SLIN (1ULL << 6)
+/*! LPC10, 180 samples/frame */
+#define AST_FORMAT_LPC10 (1ULL << 7)
+/*! G.729A audio */
+#define AST_FORMAT_G729 (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_SLIN16 (1ULL << 15)
+/*! G.719 (64 kbps assumed) */
+#define AST_FORMAT_G719 (1ULL << 32)
+/*! SpeeX Wideband (16kHz) Free Compression */
+#define AST_FORMAT_SPEEX16 (1ULL << 33)
+/*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
+#define AST_FORMAT_OPUS (1ULL << 34)
+/*! Raw testing-law data (G.711) */
+#define AST_FORMAT_TESTLAW (1ULL << 47)
+/*! H.261 Video */
+#define AST_FORMAT_H261 (1ULL << 18)
+/*! H.263 Video */
+#define AST_FORMAT_H263 (1ULL << 19)
+/*! H.263+ Video */
+#define AST_FORMAT_H263P (1ULL << 20)
+/*! H.264 Video */
+#define AST_FORMAT_H264 (1ULL << 21)
+/*! MPEG4 Video */
+#define AST_FORMAT_MP4 (1ULL << 22)
+/*! VP8 Video */
+#define AST_FORMAT_VP8 (1ULL << 23)
+/*! JPEG Images */
+#define AST_FORMAT_JPEG (1ULL << 16)
+/*! PNG Images */
+#define AST_FORMAT_PNG (1ULL << 17)
+/*! T.140 RED Text format RFC 4103 */
+#define AST_FORMAT_T140_RED (1ULL << 26)
+/*! T.140 Text format - ITU T.140, RFC 4103 */
+#define AST_FORMAT_T140 (1ULL << 27)
+
+/*!
+ * \brief Convert a format structure to its respective bitfield
+ *
+ * \param format The media format
+ *
+ * \retval non-zero success
+ * \retval zero format not supported
+ */
+uint64_t ast_format_compatibility_format2bitfield(const struct ast_format *format);
+
+/*!
+ * \brief Convert a codec structure to its respective bitfield
+ *
+ * \param codec The media codec
+ *
+ * \retval non-zero success
+ * \retval zero format not supported
+ */
+uint64_t ast_format_compatibility_codec2bitfield(const struct ast_codec *codec);
+
+/*!
+ * \brief Convert a bitfield to its respective format structure
+ *
+ * \param bitfield The bitfield for the media format
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The reference count of the returned format is NOT incremented
+ */
+struct ast_format *ast_format_compatibility_bitfield2format(uint64_t bitfield);
+
+#endif /* _AST_FORMAT_COMPATIBILITY_H */
diff --git a/include/asterisk/format_pref.h b/include/asterisk/format_pref.h
deleted file mode 100644
index f5c3c22a7..000000000
--- a/include/asterisk/format_pref.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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. */
- int 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 pref preference structure to get the codec out of
- * \param index to retrieve from
- * \param result ast_format structure to store the index value in
- * \return pointer to input ast_format on success, NULL on failure
-*/
-struct ast_format *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 all codecs to a preference list, without disturbing existing order */
-void ast_codec_pref_append_all(struct ast_codec_pref *pref);
-
-/*! \brief Append a audio codec to a preference list, removing it first if it was already there
-*/
-int ast_codec_pref_append(struct ast_codec_pref *pref, struct ast_format *format);
-
-/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there
-*/
-void ast_codec_pref_prepend(struct ast_codec_pref *pref, struct ast_format *format, int only_if_existing);
-
-/*! \brief Select the best audio format according to preference list from supplied options.
- * Best audio format is returned in the result format.
- *
- * \note If "find_best" is non-zero then if nothing is found, the "Best" format of
- * the format list is selected and returned in the result structure, otherwise
- * NULL is returned
- *
- * \retval ptr to result struture.
- * \retval NULL, best codec was not found
- */
-struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result);
-
-/*! \brief Set packet size for codec
-*/
-int ast_codec_pref_setsize(struct ast_codec_pref *pref, struct ast_format *format, int framems);
-
-/*! \brief Get packet size for codec
-*/
-struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format);
-
-/*! \brief Dump audio codec preference list into a string */
-int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size);
-
-/*! \brief Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string
- * \note Due to a misunderstanding in how codec preferences are stored, this
- * list starts at 'B', not 'A'. For backwards compatibility reasons, this
- * cannot change.
- * \param pref A codec preference list structure
- * \param buf A string denoting codec preference, appropriate for use in line transmission
- * \param size Size of \a buf
- * \param right Boolean: if 0, convert from \a buf to \a pref; if 1, convert from \a pref to \a buf.
- */
-void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right);
-
-#endif /* _AST_FORMATPREF_H */
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 846832aff..a981c7e72 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -31,7 +31,6 @@ extern "C" {
#include <sys/time.h>
-#include "asterisk/format_pref.h"
#include "asterisk/format.h"
#include "asterisk/endian.h"
#include "asterisk/linkedlists.h"
@@ -136,9 +135,13 @@ enum {
AST_FRFLAG_HAS_TIMING_INFO = (1 << 0),
};
-union ast_frame_subclass {
+struct ast_frame_subclass {
+ /*! A frame specific code */
int integer;
- struct ast_format format;
+ /*! The asterisk media format */
+ struct ast_format *format;
+ /*! For video formats, an indication that a frame ended */
+ unsigned int frame_ending;
};
/*! \brief Data structure associated with a single frame of data
@@ -147,7 +150,7 @@ struct ast_frame {
/*! Kind of frame */
enum ast_frame_type frametype;
/*! Subclass, frame dependent */
- union ast_frame_subclass subclass;
+ struct ast_frame_subclass subclass;
/*! Length of data */
int datalen;
/*! Number of samples in this frame */
@@ -384,9 +387,6 @@ struct ast_control_pvt_cause_code {
char code[1]; /*!< Tech-specific cause code information, beginning with the name of the tech */
};
-#define AST_SMOOTHER_FLAG_G729 (1 << 0)
-#define AST_SMOOTHER_FLAG_BE (1 << 1)
-
/* Option identifiers and flags */
#define AST_OPTION_FLAG_REQUEST 0
#define AST_OPTION_FLAG_ACCEPT 1
@@ -565,77 +565,11 @@ void ast_swapcopy_samples(void *dst, const void *src, int samples);
#define ast_frame_byteswap_be(fr) do { ; } while(0)
#endif
-/*! \brief Parse an "allow" or "deny" line in a channel or device configuration
- and update the capabilities and pref if provided.
- Video codecs are not added to codec preference lists, since we can not transcode
- \return Returns number of errors encountered during parsing
- */
-int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing);
-
-/*! \name AST_Smoother
-*/
-/*@{ */
-/*! \page ast_smooth The AST Frame Smoother
-The ast_smoother interface was designed specifically
-to take frames of variant sizes and produce frames of a single expected
-size, precisely what you want to do.
-
-The basic interface is:
-
-- Initialize with ast_smoother_new()
-- Queue input frames with ast_smoother_feed()
-- Get output frames with ast_smoother_read()
-- when you're done, free the structure with ast_smoother_free()
-- Also see ast_smoother_test_flag(), ast_smoother_set_flags(), ast_smoother_get_flags(), ast_smoother_reset()
-*/
-struct ast_smoother;
-
-struct ast_smoother *ast_smoother_new(int bytes);
-void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
-int ast_smoother_get_flags(struct ast_smoother *smoother);
-int ast_smoother_test_flag(struct ast_smoother *s, int flag);
-void ast_smoother_free(struct ast_smoother *s);
-void ast_smoother_reset(struct ast_smoother *s, int bytes);
-
-/*!
- * \brief Reconfigure an existing smoother to output a different number of bytes per frame
- * \param s the smoother to reconfigure
- * \param bytes the desired number of bytes per output frame
- * \return nothing
- *
- */
-void ast_smoother_reconfigure(struct ast_smoother *s, int bytes);
-
-int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
-struct ast_frame *ast_smoother_read(struct ast_smoother *s);
-#define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 1)
-#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 0)
-#else
-#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 0)
-#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 1)
-#endif
-/*@} Doxygen marker */
-
void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix);
-/*! \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(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(struct ast_format *format)
-{
- return (format->id == AST_FORMAT_ILBC) ? 30 : 20;
-}
-
/*!
\brief Adjusts the volume of the audio samples contained in a frame.
\param f The frame containing the samples (must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR)
diff --git a/include/asterisk/image.h b/include/asterisk/image.h
index 302f09e85..9e358ad52 100644
--- a/include/asterisk/image.h
+++ b/include/asterisk/image.h
@@ -28,7 +28,7 @@ struct ast_imager {
char *name; /*!< Name */
char *desc; /*!< Description */
char *exts; /*!< Extension(s) (separated by '|' ) */
- struct ast_format 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 */
diff --git a/include/asterisk/mod_format.h b/include/asterisk/mod_format.h
index ff3ab7bbf..7f17741fa 100644
--- a/include/asterisk/mod_format.h
+++ b/include/asterisk/mod_format.h
@@ -43,10 +43,10 @@ extern "C" {
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) */
- struct ast_format format; /*!< Format of frames it uses/provides (one only) */
- /*!
- * \brief Prepare an input stream for playback.
+ * this format can read. First is assumed for writing (e.g. .mp3) */
+ 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.
* The FILE is already open (in s->f) so this function only needs to perform
* any applicable validity checks on the file. If none is required, the
@@ -110,7 +110,7 @@ struct ast_filestream {
/*! Transparently translate from another format -- just once */
struct ast_trans_pvt *trans;
struct ast_tranlator_pvt *tr;
- struct ast_format lastwriteformat;
+ struct ast_format *lastwriteformat;
int lasttimeout;
struct ast_channel *owner;
FILE *f;
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index d569710e0..45d9325ee 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -530,8 +530,6 @@ struct ast_sip_endpoint_media_configuration {
struct ast_sip_direct_media_configuration direct_media;
/*! T.38 (FoIP) options */
struct ast_sip_t38_configuration t38;
- /*! Codec preferences */
- struct ast_codec_pref prefs;
/*! Configured codecs */
struct ast_format_cap *codecs;
/*! DSCP TOS bits for audio streams */
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 7340c6d71..51908f99b 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -126,8 +126,6 @@ struct ast_sip_session {
struct ast_party_id id;
/* Requested capabilities */
struct ast_format_cap *req_caps;
- /* Codecs overriden by dialplan on an outgoing request */
- struct ast_codec_pref override_prefs;
/* Optional DSP, used only for inband DTMF detection if configured */
struct ast_dsp *dsp;
/* Whether the termination of the session should be deferred */
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index 81e530e85..e5f38eecc 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -1,4 +1,4 @@
-/*
+ /*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2009, Digium, Inc.
@@ -71,10 +71,12 @@ extern "C" {
#include "asterisk/astobj2.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cap.h"
#include "asterisk/netsock2.h"
#include "asterisk/sched.h"
#include "asterisk/res_srtp.h"
#include "asterisk/stasis.h"
+#include "asterisk/vector.h"
/* Maximum number of payloads supported */
#if defined(LOW_MEMORY)
@@ -245,7 +247,7 @@ struct ast_rtp_payload_type {
int asterisk_format;
/*! If asterisk_format is set, this is the internal
* asterisk format represented by the payload */
- struct ast_format format;
+ struct ast_format *format;
/*! Actual internal RTP specific value of the payload */
int rtp_code;
/*! Actual payload number */
@@ -526,8 +528,6 @@ struct ast_rtp_engine {
void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
/*! 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 */
void (*remote_address_set)(struct ast_rtp_instance *instance, struct ast_sockaddr *sa);
/*! Callback for changing DTMF mode */
@@ -575,11 +575,16 @@ struct ast_rtp_engine {
/*! Structure that represents codec and packetization information */
struct ast_rtp_codecs {
/*! Payloads present */
- struct ao2_container *payloads;
- /*! Codec packetization preferences */
- struct ast_codec_pref pref;
+ AST_VECTOR(, struct ast_rtp_payload_type *) payloads;
+ /*! The framing for this media session */
+ unsigned int framing;
+ /*! RW lock that protects elements in this structure */
+ ast_rwlock_t codecs_lock;
};
+#define AST_RTP_CODECS_NULL_INIT \
+ { .payloads = { 0, }, .framing = 0, .codecs_lock = AST_RWLOCK_INIT_VALUE, }
+
/*! Structure that represents the glue that binds an RTP instance to a channel */
struct ast_rtp_glue {
/*! Name of the channel driver that this glue is responsible for */
@@ -622,6 +627,18 @@ struct ast_rtp_glue {
AST_RWLIST_ENTRY(ast_rtp_glue) entry;
};
+/*!
+ * \brief Allocation routine for \ref ast_rtp_payload_type
+ *
+ * \retval NULL on error
+ * \retval An ao2 ref counted \c ast_rtp_payload_type on success.
+ *
+ * \note The \c ast_rtp_payload_type returned by this function is an
+ * ao2 ref counted object.
+ *
+ */
+struct ast_rtp_payload_type *ast_rtp_engine_alloc_payload_type(void);
+
#define ast_rtp_engine_register(engine) ast_rtp_engine_register2(engine, ast_module_info->self)
/*!
@@ -1117,25 +1134,6 @@ void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs);
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
/*!
- * \brief Set payload information on an RTP instance to the default
- *
- * \param codecs The codecs structure to set defaults on
- * \param instance Optionally the instance that the codecs structure belongs to
- *
- * Example usage:
- *
- * \code
- * struct ast_rtp_codecs codecs;
- * ast_rtp_codecs_payloads_default(&codecs, NULL);
- * \endcode
- *
- * This sets the default payloads on the codecs structure.
- *
- * \since 1.8
- */
-void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
-
-/*!
* \brief Copy payload information from one RTP instance to another
*
* \param src The source codecs structure
@@ -1249,20 +1247,36 @@ void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp
* \param codecs Codecs structure to look in
* \param payload Numerical payload to look up
*
- * \retval Payload information
+ * \retval Payload information.
+ * \retval NULL if payload does not exist.
+ *
+ * \note The payload returned by this function has its reference count increased.
+ * Callers are responsible for decrementing the reference count.
*
* Example usage:
*
* \code
- * struct ast_rtp_payload_type payload_type;
- * payload_type = ast_rtp_codecs_payload_lookup(&codecs, 0);
+ * struct ast_rtp_payload_type *payload_type;
+ * payload_type = ast_rtp_codecs_get_payload(&codecs, 0);
* \endcode
*
* This looks up the information for payload '0' from the codecs structure.
+ */
+struct ast_rtp_payload_type *ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload);
+
+/*!
+ * \brief Update the format associated with a payload in a codecs structure
*
- * \since 1.8
+ * \param codecs Codecs structure to operate on
+ * \param payload Numerical payload to look up
+ * \param format The format to replace the existing one
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \since 13
*/
-struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload);
+int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format);
/*!
* \brief Retrieve the actual ast_format stored on the codecs structure for a specific payload
@@ -1273,11 +1287,35 @@ struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs
* \retval pointer to format structure on success
* \retval NULL on failure
*
+ * \note The format returned by this function has its reference count increased.
+ * Callers are responsible for decrementing the reference count.
+ *
* \since 10.0
*/
struct ast_format *ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload);
/*!
+ * \brief Set the framing used for a set of codecs
+ *
+ * \param codecs Codecs structure to set framing on
+ * \param framing The framing value to set on the codecs
+ *
+ * \since 13.0.0
+ */
+void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing);
+
+/*!
+ * \brief Get the framing used for a set of codecs
+ *
+ * \param codecs Codecs structure to get the framing from
+ *
+ * \retval The framing to be used for the media stream associated with these codecs
+ *
+ * \since 13.0.0
+ */
+unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs);
+
+/*!
* \brief Get the sample rate associated with known RTP payload types
*
* \param asterisk_format True if the value in format is to be used.
@@ -1393,8 +1431,8 @@ const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_f
* char buf[256] = "";
* 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));
+ * ast_format_cap_append(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0));
+ * ast_format_cap_append(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
@@ -1406,25 +1444,6 @@ const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_f
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
- *
- * \param codecs Codecs structure to muck with
- * \param instance Optionally the instance that the codecs structure belongs to
- * \param prefs Codec packetization preferences
- *
- * Example usage:
- *
- * \code
- * ast_rtp_codecs_packetization_set(&codecs, NULL, &prefs);
- * \endcode
- *
- * This sets the packetization preferences pointed to by prefs on the codecs structure pointed to by codecs.
- *
- * \since 1.8
- */
-void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs);
-
-/*!
* \brief Begin sending a DTMF digit
*
* \param instance The RTP instance to send the DTMF on
@@ -2111,12 +2130,12 @@ struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance);
/*! \brief Custom formats declared in codecs.conf at startup must be communicated to the rtp_engine
* so their mime type can payload number can be initialized. */
-int ast_rtp_engine_load_format(const struct ast_format *format);
+int ast_rtp_engine_load_format(struct ast_format *format);
/*! \brief Formats requiring the use of a format attribute interface must have that
* interface registered in order for the rtp engine to handle it correctly. If an
* attribute interface is unloaded, this function must be called to notify the rtp_engine. */
-int ast_rtp_engine_unload_format(const struct ast_format *format);
+int ast_rtp_engine_unload_format(struct ast_format *format);
/*!
* \brief Obtain a pointer to the ICE support present on an RTP instance
diff --git a/include/asterisk/slin.h b/include/asterisk/slin.h
index ab7d843ab..148ee09ab 100644
--- a/include/asterisk/slin.h
+++ b/include/asterisk/slin.h
@@ -70,7 +70,8 @@ static inline struct ast_frame *slin8_sample(void)
.data.ptr = ex_slin8,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ f.subclass.format = ast_format_slin;
+
return &f;
}
@@ -86,6 +87,7 @@ static inline struct ast_frame *slin16_sample(void)
.data.ptr = ex_slin16,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0);
+ f.subclass.format = ast_format_slin16;
+
return &f;
}
diff --git a/include/asterisk/slinfactory.h b/include/asterisk/slinfactory.h
index 324c0ae28..9a8ceae1e 100644
--- a/include/asterisk/slinfactory.h
+++ b/include/asterisk/slinfactory.h
@@ -39,8 +39,8 @@ struct ast_slinfactory {
short *offset; /*!< Offset into the hold where audio begins */
size_t holdlen; /*!< Number of samples currently in the hold */
unsigned int size; /*!< Number of samples currently in the factory */
- struct ast_format format; /*!< Current format the translation path is converting from */
- struct ast_format 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 */
};
/*!
@@ -60,7 +60,7 @@ void ast_slinfactory_init(struct ast_slinfactory *sf);
*
* \return 0 on success, non-zero on failure
*/
-int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, const struct ast_format *slin_out);
+int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, struct ast_format *slin_out);
/*!
* \brief Destroy the contents of a slinfactory
diff --git a/include/asterisk/smoother.h b/include/asterisk/smoother.h
new file mode 100644
index 000000000..e63aa77bd
--- /dev/null
+++ b/include/asterisk/smoother.h
@@ -0,0 +1,89 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, 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_SMOOTHER_H
+#define _ASTERISK_SMOOTHER_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include "asterisk/endian.h"
+
+#define AST_SMOOTHER_FLAG_G729 (1 << 0)
+#define AST_SMOOTHER_FLAG_BE (1 << 1)
+
+/*! \name AST_Smoother
+*/
+/*@{ */
+/*! \page ast_smooth The AST Frame Smoother
+The ast_smoother interface was designed specifically
+to take frames of variant sizes and produce frames of a single expected
+size, precisely what you want to do.
+
+The basic interface is:
+
+- Initialize with ast_smoother_new()
+- Queue input frames with ast_smoother_feed()
+- Get output frames with ast_smoother_read()
+- when you're done, free the structure with ast_smoother_free()
+- Also see ast_smoother_test_flag(), ast_smoother_set_flags(), ast_smoother_get_flags(), ast_smoother_reset()
+*/
+struct ast_smoother;
+
+struct ast_frame;
+
+struct ast_smoother *ast_smoother_new(int bytes);
+void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
+int ast_smoother_get_flags(struct ast_smoother *smoother);
+int ast_smoother_test_flag(struct ast_smoother *s, int flag);
+void ast_smoother_free(struct ast_smoother *s);
+void ast_smoother_reset(struct ast_smoother *s, int bytes);
+
+/*!
+ * \brief Reconfigure an existing smoother to output a different number of bytes per frame
+ * \param s the smoother to reconfigure
+ * \param bytes the desired number of bytes per output frame
+ * \return nothing
+ *
+ */
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes);
+
+int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
+struct ast_frame *ast_smoother_read(struct ast_smoother *s);
+#define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 1)
+#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 0)
+#else
+#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 0)
+#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 1)
+#endif
+/*@} Doxygen marker */
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _ASTERISK_SMOOTHER_H */
diff --git a/include/asterisk/speech.h b/include/asterisk/speech.h
index a914f4846..0da6f5cfc 100644
--- a/include/asterisk/speech.h
+++ b/include/asterisk/speech.h
@@ -58,7 +58,7 @@ struct ast_speech {
/*! Current state of structure */
int state;
/*! Expected write format */
- struct ast_format format;
+ struct ast_format *format;
/*! Data for speech engine */
void *data;
/*! Cached results */
diff --git a/include/asterisk/translate.h b/include/asterisk/translate.h
index 602c3097c..e8e4c02d2 100644
--- a/include/asterisk/translate.h
+++ b/include/asterisk/translate.h
@@ -32,6 +32,8 @@ extern "C" {
#include "asterisk/frame.h"
#include "asterisk/plc.h"
#include "asterisk/linkedlists.h"
+#include "asterisk/format_cap.h"
+#include "asterisk/format_cache.h"
#endif
struct ast_trans_pvt; /* declared below */
@@ -134,8 +136,11 @@ enum ast_trans_cost_table {
*/
struct ast_translator {
char name[80]; /*!< Name of translator */
- struct ast_format src_format; /*!< Source format */
- struct ast_format dst_format; /*!< Destination format */
+ struct ast_codec src_codec; /*!< Source codec */
+ struct ast_codec dst_codec; /*!< Destination codec */
+ struct ast_codec *core_src_codec; /*!< Core registered source codec */
+ struct ast_codec *core_dst_codec; /*!< Core registered destination codec */
+ const char *format; /*!< Optional name of a cached format this translator produces */
int table_cost; /*!< Cost value associated with this translator based
* on translation cost table. */
@@ -204,12 +209,6 @@ struct ast_translator {
struct ast_trans_pvt {
struct ast_translator *t;
struct ast_frame f; /*!< used in frameout */
- /*! If a translation path using a format with attributes requires the output
- * to be a specific set of attributes, this variable will be set describing those
- * attributes to the translator. Otherwise, the translator must choose a set
- * of format attributes for the destination that preserves the quality of the
- * audio in the best way possible. */
- struct ast_format explicit_dst;
int samples; /*!< samples available in outbuf */
/*! \brief actual space used in outbuf */
int datalen;
@@ -286,8 +285,8 @@ void ast_translator_deactivate(struct ast_translator *t);
*/
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);
+ struct ast_format **dst_fmt_out,
+ struct ast_format **src_fmt_out);
/*!
* \brief Builds a translator path
diff --git a/include/asterisk/vector.h b/include/asterisk/vector.h
index 0a2c6c965..0053d8a32 100644
--- a/include/asterisk/vector.h
+++ b/include/asterisk/vector.h
@@ -61,7 +61,7 @@
#define AST_VECTOR_INIT(vec, size) ({ \
size_t __size = (size); \
size_t alloc_size = __size * sizeof(*((vec)->elems)); \
- (vec)->elems = alloc_size ? ast_malloc(alloc_size) : NULL; \
+ (vec)->elems = alloc_size ? ast_calloc(1, alloc_size) : NULL; \
(vec)->current = 0; \
if ((vec)->elems) { \
(vec)->max = __size; \
@@ -116,6 +116,48 @@
})
/*!
+ * \brief Insert an element at a specific position in a vector, growing the vector if needed.
+ *
+ * \param vec Vector to insert into.
+ * \param idx Position to insert at.
+ * \param elem Element to insert.
+ *
+ * \return 0 on success.
+ * \return Non-zero on failure.
+ *
+ * \warning This macro will overwrite anything already present at the position provided.
+ *
+ * \warning Use of this macro with the expectation that the element will remain at the provided
+ * index means you can not use the UNORDERED assortment of macros. These macros alter the ordering
+ * of the vector itself.
+ */
+#define AST_VECTOR_INSERT(vec, idx, elem) ({ \
+ int res = 0; \
+ do { \
+ if (((idx) + 1) > (vec)->max) { \
+ size_t new_max = ((idx) + 1) * 2; \
+ typeof((vec)->elems) new_elems = ast_calloc(1, \
+ new_max * sizeof(*new_elems)); \
+ if (new_elems) { \
+ memcpy(new_elems, (vec)->elems, \
+ (vec)->current * sizeof(*new_elems)); \
+ ast_free((vec)->elems); \
+ (vec)->elems = new_elems; \
+ (vec)->max = new_max; \
+ } else { \
+ res = -1; \
+ break; \
+ } \
+ } \
+ (vec)->elems[(idx)] = (elem); \
+ if (((idx) + 1) > (vec)->current) { \
+ (vec)->current = (idx) + 1; \
+ } \
+ } while(0); \
+ res; \
+})
+
+/*!
* \brief Remove an element from a vector by index.
*
* Note that elements in the vector may be reordered, so that the remove can
@@ -134,6 +176,25 @@
res; \
})
+/*!
+ * \brief Remove an element from a vector by index while maintaining order.
+ *
+ * \param vec Vector to remove from.
+ * \param idx Index of the element to remove.
+ * \return The element that was removed.
+ */
+#define AST_VECTOR_REMOVE_ORDERED(vec, idx) ({ \
+ typeof((vec)->elems[0]) res; \
+ size_t __idx = (idx); \
+ size_t __move; \
+ ast_assert(__idx < (vec)->current); \
+ res = (vec)->elems[__idx]; \
+ __move = ((vec)->current - (__idx) - 1) * sizeof(typeof((vec)->elems[0])); \
+ memmove(&(vec)->elems[__idx], &(vec)->elems[__idx + 1], __move); \
+ (vec)->current--; \
+ res; \
+})
+
/*!
* \brief Remove an element from a vector that matches the given comparison
@@ -162,6 +223,32 @@
})
/*!
+ * \brief Remove an element from a vector that matches the given comparison while maintaining order
+ *
+ * \param vec Vector to remove from.
+ * \param value Value to pass into comparator.
+ * \param cmp Comparator function/macros (called as \c cmp(elem, value))
+ * \param cleanup How to cleanup a removed element macro/function.
+ *
+ * \return 0 if element was removed.
+ * \return Non-zero if element was not in the vector.
+ */
+#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
+ int res = -1; \
+ size_t idx; \
+ typeof(value) __value = (value); \
+ for (idx = 0; idx < (vec)->current; ++idx) { \
+ if (cmp((vec)->elems[idx], __value)) { \
+ cleanup((vec)->elems[idx]); \
+ AST_VECTOR_REMOVE_ORDERED((vec), idx); \
+ res = 0; \
+ break; \
+ } \
+ } \
+ res; \
+})
+
+/*!
* \brief Default comparator for AST_VECTOR_REMOVE_ELEM_UNORDERED()
*
* \param elem Element to compare against
@@ -197,6 +284,21 @@
})
/*!
+ * \brief Remove an element from a vector while maintaining order.
+ *
+ * \param vec Vector to remove from.
+ * \param elem Element to remove
+ * \param cleanup How to cleanup a removed element macro/function.
+ *
+ * \return 0 if element was removed.
+ * \return Non-zero if element was not in the vector.
+ */
+#define AST_VECTOR_REMOVE_ELEM_ORDERED(vec, elem, cleanup) ({ \
+ AST_VECTOR_REMOVE_CMP_ORDERED((vec), (elem), \
+ AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
+})
+
+/*!
* \brief Get the number of elements in a vector.
*
* \param vec Vector to query.
diff --git a/main/abstract_jb.c b/main/abstract_jb.c
index 7841b6a4e..85c188e88 100644
--- a/main/abstract_jb.c
+++ b/main/abstract_jb.c
@@ -360,7 +360,7 @@ static void jb_get_and_deliver(struct ast_channel *chan)
}
while (now >= jb->next) {
- interpolation_len = ast_codec_interp_len(&jb->last_format);
+ interpolation_len = ast_format_get_default_ms(jb->last_format);
res = jbimpl->get(jbobj, &f, now, interpolation_len);
@@ -371,13 +371,13 @@ static void jb_get_and_deliver(struct ast_channel *chan)
case AST_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);
- ast_format_copy(&jb->last_format, &f->subclass.format);
+ ao2_replace(jb->last_format, f->subclass.format);
ast_frfree(f);
break;
case AST_JB_IMPL_INTERP:
/* interpolate a frame */
f = &finterp;
- ast_format_copy(&f->subclass.format, &jb->last_format);
+ 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));
@@ -437,7 +437,7 @@ static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
jb->next = jbimpl->next(jbobj);
/* Init last format for a first time. */
- ast_format_copy(&jb->last_format, &frr->subclass.format);
+ jb->last_format = ao2_bump(frr->subclass.format);
/* Create a frame log file */
if (ast_test_flag(jbconf, AST_JB_LOG)) {
@@ -502,6 +502,8 @@ void ast_jb_destroy(struct ast_channel *chan)
jb->logfile = NULL;
}
+ ao2_cleanup(jb->last_format);
+
if (ast_test_flag(jb, JB_CREATED)) {
/* Remove and free all frames still queued in jb */
while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
@@ -820,7 +822,7 @@ struct jb_framedata {
const struct ast_jb_impl *jb_impl;
struct ast_jb_conf jb_conf;
struct timeval start_tv;
- struct ast_format last_format;
+ struct ast_format *last_format;
struct ast_timer *timer;
int timer_interval; /* ms between deliveries */
int timer_fd;
@@ -842,6 +844,7 @@ static void jb_framedata_destroy(struct jb_framedata *framedata)
framedata->jb_impl->destroy(framedata->jb_obj);
framedata->jb_obj = NULL;
}
+ ao2_cleanup(framedata->last_format);
ast_free(framedata);
}
@@ -909,7 +912,7 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
}
jbframe = ast_frisolate(frame);
- ast_format_copy(&framedata->last_format, &frame->subclass.format);
+ ao2_replace(framedata->last_format, frame->subclass.format);
if (frame->len && (frame->len != framedata->timer_interval)) {
framedata->timer_interval = frame->len;
@@ -959,12 +962,12 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
frame = &ast_null_frame;
break;
case AST_JB_IMPL_INTERP:
- if (framedata->last_format.id) {
+ if (framedata->last_format) {
struct ast_frame tmp = { 0, };
tmp.frametype = AST_FRAME_VOICE;
- ast_format_copy(&tmp.subclass.format, &framedata->last_format);
+ tmp.subclass.format = framedata->last_format;
/* example: 8000hz / (1000 / 20ms) = 160 samples */
- tmp.samples = ast_format_rate(&framedata->last_format) / (1000 / framedata->timer_interval);
+ tmp.samples = ast_format_get_sample_rate(framedata->last_format) / (1000 / framedata->timer_interval);
tmp.delivery = ast_tvadd(framedata->start_tv, ast_samp2tv(next, 1000));
tmp.offset = AST_FRIENDLY_OFFSET;
tmp.src = "func_jitterbuffer interpolation";
diff --git a/main/app.c b/main/app.c
index 822fe6c45..fa7c3ece1 100644
--- a/main/app.c
+++ b/main/app.c
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
#define MWI_TOPIC_BUCKETS 57
@@ -880,16 +881,18 @@ struct linear_state {
int fd;
int autoclose;
int allowoverride;
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
};
static void linear_release(struct ast_channel *chan, void *params)
{
struct linear_state *ls = params;
- if (ls->origwfmt.id && ast_set_write_format(chan, &ls->origwfmt)) {
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%u'\n", ast_channel_name(chan), ls->origwfmt.id);
+ if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n",
+ ast_channel_name(chan), ast_format_get_name(ls->origwfmt));
}
+ ao2_cleanup(ls->origwfmt);
if (ls->autoclose) {
close(ls->fd);
@@ -909,7 +912,7 @@ static int linear_generator(struct ast_channel *chan, void *data, int len, int s
};
int res;
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ f.subclass.format = ast_format_slin;
len = samples * 2;
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
@@ -943,10 +946,11 @@ static void *linear_alloc(struct ast_channel *chan, void *params)
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
}
- ast_format_copy(&ls->origwfmt, ast_channel_writeformat(chan));
+ ls->origwfmt = ao2_bump(ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", ast_channel_name(chan));
+ ao2_cleanup(ls->origwfmt);
ast_free(ls);
ls = params = NULL;
}
@@ -1358,7 +1362,7 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
return NULL;
}
- if (orig->subclass.format.id != AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
return NULL;
}
@@ -1385,7 +1389,7 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
silence->samples = samples;
silence->datalen = datalen;
- ast_format_set(&silence->subclass.format, AST_FORMAT_SLINEAR, 0);
+ silence->subclass.format = ast_format_slin;
return silence;
}
@@ -1400,13 +1404,13 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
* \return 0 on success.
* \return -1 on error.
*/
-static int set_read_to_slin(struct ast_channel *chan, struct ast_format *orig_format)
+static int set_read_to_slin(struct ast_channel *chan, struct ast_format **orig_format)
{
if (!chan || !orig_format) {
return -1;
}
- ast_format_copy(orig_format, ast_channel_readformat(chan));
- return ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ *orig_format = ao2_bump(ast_channel_readformat(chan));
+ return ast_set_read_format(chan, ast_format_slin);
}
static int global_silence_threshold = 128;
@@ -1448,7 +1452,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
int totalsilence = 0;
int dspsilence = 0;
int olddspsilence = 0;
- struct ast_format rfmt;
+ struct ast_format *rfmt = NULL;
struct ast_silence_generator *silgen = NULL;
char prependfile[PATH_MAX];
int ioflags; /* IO flags for writing output file */
@@ -1467,7 +1471,6 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
break;
}
- ast_format_clear(&rfmt);
if (silencethreshold < 0) {
silencethreshold = global_silence_threshold;
}
@@ -1542,6 +1545,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
ast_dsp_free(sildet);
+ ao2_cleanup(rfmt);
return -1;
}
}
@@ -1692,7 +1696,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
* set the mode, if we haven't already
* for sildet
*/
- if (muted && !rfmt.id) {
+ if (muted && !rfmt) {
ast_verb(3, "Setting read format to linear mode\n");
res = set_read_to_slin(chan, &rfmt);
if (res < 0) {
@@ -1812,9 +1816,10 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
ast_filedelete(prependfile, sfmt[x]);
}
}
- 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), ast_channel_name(chan));
+ if (rfmt && ast_set_read_format(chan, rfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
}
+ ao2_cleanup(rfmt);
if ((outmsg == 2) && (!skip_confirmation_sound)) {
ast_stream_and_wait(chan, "auth-thankyou", "");
}
diff --git a/main/asterisk.c b/main/asterisk.c
index 55e06c385..1c6994280 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -248,6 +248,8 @@ int daemon(int, int); /* defined in libresolv of all places */
#include "asterisk/stasis_system.h"
#include "asterisk/security_events.h"
#include "asterisk/endpoints.h"
+#include "asterisk/codec.h"
+#include "asterisk/format_cache.h"
#include "../defaults.h"
@@ -4316,6 +4318,26 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (ast_codec_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_format_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_format_cache_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_codec_builtin_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
#ifdef AST_XML_DOCS
/* Load XML documentation. */
ast_xmldoc_load_documentation();
@@ -4370,8 +4392,6 @@ int main(int argc, char *argv[])
threadstorage_init();
- ast_format_attr_init();
- ast_format_list_init();
if (ast_rtp_engine_init()) {
printf("%s", term_quit());
exit(1);
diff --git a/main/audiohook.c b/main/audiohook.c
index 549ad31eb..33dad38f9 100644
--- a/main/audiohook.c
+++ b/main/audiohook.c
@@ -41,13 +41,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/slinfactory.h"
#include "asterisk/frame.h"
#include "asterisk/translate.h"
+#include "asterisk/format_cache.h"
#define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*!< Tolerance in milliseconds for audiohooks synchronization */
#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE 100 /*!< When small queue is enabled, this is the maximum amount of audio that can remain queued at a time. */
struct ast_audiohook_translate {
struct ast_trans_pvt *trans_pvt;
- struct ast_format format;
+ struct ast_format *format;
};
struct ast_audiohook_list {
@@ -67,7 +68,7 @@ struct ast_audiohook_list {
static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate, int reset)
{
- struct ast_format slin;
+ struct ast_format *slin;
if (audiohook->hook_internal_samp_rate == rate) {
return 0;
@@ -75,7 +76,8 @@ static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate
audiohook->hook_internal_samp_rate = rate;
- ast_format_set(&slin, ast_format_slin_by_rate(rate), 0);
+ slin = ast_format_cache_get_slin_by_rate(rate);
+
/* Setup the factories that are needed for this audiohook type */
switch (audiohook->type) {
case AST_AUDIOHOOK_TYPE_SPY:
@@ -84,12 +86,13 @@ static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate
ast_slinfactory_destroy(&audiohook->read_factory);
ast_slinfactory_destroy(&audiohook->write_factory);
}
- ast_slinfactory_init_with_format(&audiohook->read_factory, &slin);
- ast_slinfactory_init_with_format(&audiohook->write_factory, &slin);
+ ast_slinfactory_init_with_format(&audiohook->read_factory, slin);
+ ast_slinfactory_init_with_format(&audiohook->write_factory, slin);
break;
default:
break;
}
+
return 0;
}
@@ -143,6 +146,8 @@ int ast_audiohook_destroy(struct ast_audiohook *audiohook)
if (audiohook->trans_pvt)
ast_translator_free_path(audiohook->trans_pvt);
+ ao2_cleanup(audiohook->format);
+
/* Lock and trigger be gone! */
ast_cond_destroy(&audiohook->trigger);
ast_mutex_destroy(&audiohook->lock);
@@ -220,11 +225,11 @@ static struct ast_frame *audiohook_read_frame_single(struct ast_audiohook *audio
short buf[samples];
struct ast_frame frame = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate),
.data.ptr = buf,
.datalen = sizeof(buf),
.samples = samples,
};
- ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0);
/* Ensure the factory is able to give us the samples we want */
if (samples > ast_slinfactory_available(factory)) {
@@ -254,7 +259,6 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
.datalen = sizeof(buf1),
.samples = samples,
};
- ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0);
/* Make sure both factories have the required samples */
usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
@@ -346,6 +350,8 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
/* Make the final buffer part of the frame, so it gets duplicated fine */
frame.data.ptr = final_buf;
+ frame.subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);
+
/* Yahoo, a combined copy of the audio! */
return ast_frdup(&frame);
}
@@ -353,17 +359,17 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
static struct ast_frame *audiohook_read_frame_helper(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format, struct ast_frame **read_reference, struct ast_frame **write_reference)
{
struct ast_frame *read_frame = NULL, *final_frame = NULL;
- struct ast_format tmp_fmt;
+ struct ast_format *slin;
int samples_converted;
/* the number of samples requested is based on the format they are requesting. Inorder
* to process this correctly samples must be converted to our internal sample rate */
- if (audiohook->hook_internal_samp_rate == ast_format_rate(format)) {
+ if (audiohook->hook_internal_samp_rate == ast_format_get_sample_rate(format)) {
samples_converted = samples;
- } else if (audiohook->hook_internal_samp_rate > ast_format_rate(format)) {
- samples_converted = samples * (audiohook->hook_internal_samp_rate / (float) ast_format_rate(format));
+ } else if (audiohook->hook_internal_samp_rate > ast_format_get_sample_rate(format)) {
+ samples_converted = samples * (audiohook->hook_internal_samp_rate / (float) ast_format_get_sample_rate(format));
} else {
- samples_converted = samples * (ast_format_rate(format) / (float) audiohook->hook_internal_samp_rate);
+ samples_converted = samples * (ast_format_get_sample_rate(format) / (float) audiohook->hook_internal_samp_rate);
}
if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ?
@@ -372,21 +378,23 @@ static struct ast_frame *audiohook_read_frame_helper(struct ast_audiohook *audio
return NULL;
}
+ slin = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);
+
/* If they don't want signed linear back out, we'll have to send it through the translation path */
- if (format->id != ast_format_slin_by_rate(audiohook->hook_internal_samp_rate)) {
+ if (ast_format_cmp(format, slin) != AST_FORMAT_CMP_EQUAL) {
/* Rebuild translation path if different format then previously */
- if (ast_format_cmp(format, &audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ 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_set(&tmp_fmt, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0)))) {
+ if (!(audiohook->trans_pvt = ast_translator_build_path(format, slin))) {
ast_frfree(read_frame);
return NULL;
}
- ast_format_copy(&audiohook->format, format);
+ ao2_replace(audiohook->format, format);
}
/* Convert to requested format, and allow the read in frame to be freed */
final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
@@ -752,8 +760,7 @@ static struct ast_frame *audiohook_list_translate_to_slin(struct ast_audiohook_l
struct ast_audiohook_translate *in_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ?
&audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
struct ast_frame *new_frame = frame;
- struct ast_format tmp_fmt;
- enum ast_format_id slin_id;
+ struct ast_format *slin;
/* If we are capable of maintaining doing samplerates other that 8khz, update
* the internal audiohook_list's rate and higher samplerate audio arrives. By
@@ -761,24 +768,24 @@ static struct ast_frame *audiohook_list_translate_to_slin(struct ast_audiohook_l
* as the are written and read from. */
if (audiohook_list->native_slin_compatible) {
audiohook_list->list_internal_samp_rate =
- MAX(ast_format_rate(&frame->subclass.format), audiohook_list->list_internal_samp_rate);
+ MAX(ast_format_get_sample_rate(frame->subclass.format), audiohook_list->list_internal_samp_rate);
}
- slin_id = ast_format_slin_by_rate(audiohook_list->list_internal_samp_rate);
-
- if (frame->subclass.format.id == slin_id) {
+ slin = ast_format_cache_get_slin_by_rate(audiohook_list->list_internal_samp_rate);
+ if (ast_format_cmp(frame->subclass.format, slin) == AST_FORMAT_CMP_EQUAL) {
return new_frame;
}
- if (ast_format_cmp(&frame->subclass.format, &in_translate->format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ 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_set(&tmp_fmt, slin_id, 0), &frame->subclass.format))) {
+ if (!(in_translate->trans_pvt = ast_translator_build_path(slin, frame->subclass.format))) {
return NULL;
}
- ast_format_copy(&in_translate->format, &frame->subclass.format);
+ ao2_replace(in_translate->format, frame->subclass.format);
}
+
if (!(new_frame = ast_translate(in_translate->trans_pvt, frame, 0))) {
return NULL;
}
@@ -791,16 +798,16 @@ static struct ast_frame *audiohook_list_translate_to_native(struct ast_audiohook
{
struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
struct ast_frame *outframe = NULL;
- if (ast_format_cmp(&slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
/* rebuild translators if necessary */
- if (ast_format_cmp(&out_translate->format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(out_translate->format, outformat) == 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(outformat, &slin_frame->subclass.format))) {
+ if (!(out_translate->trans_pvt = ast_translator_build_path(outformat, slin_frame->subclass.format))) {
return NULL;
}
- ast_format_copy(&out_translate->format, outformat);
+ ao2_replace(out_translate->format, outformat);
}
/* translate back to the format the frame came in as. */
if (!(outframe = ast_translate(out_translate->trans_pvt, slin_frame, 0))) {
@@ -924,7 +931,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st
/* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
if (middle_frame_manipulated) {
- if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, &start_frame->subclass.format))) {
+ if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, start_frame->subclass.format))) {
/* translation failed, so just pass back the input frame */
end_frame = start_frame;
}
diff --git a/main/bridge.c b/main/bridge.c
index 41053eb8a..d5fc1699a 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -934,61 +934,65 @@ int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
{
- struct ast_format read_format;
- struct ast_format write_format;
- struct ast_format best_format;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_format *read_format;
+ struct ast_format *write_format;
+ struct ast_format *best_format;
- ast_format_copy(&read_format, ast_channel_readformat(bridge_channel->chan));
- ast_format_copy(&write_format, ast_channel_writeformat(bridge_channel->chan));
+ read_format = ast_channel_readformat(bridge_channel->chan);
+ write_format = ast_channel_writeformat(bridge_channel->chan);
/* Are the formats currently in use something this bridge can handle? */
- if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, ast_channel_readformat(bridge_channel->chan))) {
- ast_best_codec(bridge->technology->format_capabilities, &best_format);
+ if (ast_format_cap_iscompatible_format(bridge->technology->format_capabilities, read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ best_format = ast_format_cap_get_format(bridge->technology->format_capabilities, 0);
/* Read format is a no go... */
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->format_capabilities),
- ast_getformatname(&read_format));
+ ast_format_cap_get_names(bridge->technology->format_capabilities, &codec_buf),
+ ast_format_get_name(read_format));
/* Switch read format to the best one chosen */
- if (ast_set_read_format(bridge_channel->chan, &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",
- ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format));
+ ast_channel_name(bridge_channel->chan), ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
return -1;
}
ast_debug(1, "Bridge %s put channel %s into read format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&best_format));
+ ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
} else {
ast_debug(1, "Bridge %s is happy that channel %s already has read format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&read_format));
+ ast_format_get_name(read_format));
}
- if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, &write_format)) {
- ast_best_codec(bridge->technology->format_capabilities, &best_format);
+ if (ast_format_cap_iscompatible_format(bridge->technology->format_capabilities, write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ best_format = ast_format_cap_get_format(bridge->technology->format_capabilities, 0);
/* Write format is a no go... */
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->format_capabilities),
- ast_getformatname(&write_format));
+ ast_format_cap_get_names(bridge->technology->format_capabilities, &codec_buf),
+ ast_format_get_name(write_format));
/* Switch write format to the best one chosen */
- if (ast_set_write_format(bridge_channel->chan, &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",
- ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format));
+ ast_channel_name(bridge_channel->chan), ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
return -1;
}
ast_debug(1, "Bridge %s put channel %s into write format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&best_format));
+ ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
} else {
ast_debug(1, "Bridge %s is happy that channel %s already has write format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&write_format));
+ ast_format_get_name(write_format));
}
return 0;
@@ -3525,7 +3529,7 @@ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct a
struct ast_bridge_video_talker_src_data *data;
/* If the channel doesn't support video, we don't care about it */
- if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO)) {
+ if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO)) {
return;
}
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index 60ce37a98..cb8c2f992 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -46,6 +46,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dial.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/features.h"
+#include "asterisk/format_cache.h"
#define NORMAL_FLAGS (AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY \
| AST_BRIDGE_FLAG_SMART)
@@ -2267,14 +2268,13 @@ static void recall_callback(struct ast_dial *dial)
static int recalling_enter(struct attended_transfer_properties *props)
{
- RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- struct ast_format fmt;
+ RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
/* When we dial the transfer target, since we are communicating
* with a local channel, we can place the local channel in a bridge
@@ -2395,8 +2395,7 @@ static int attach_framehook(struct attended_transfer_properties *props, struct a
static int retransfer_enter(struct attended_transfer_properties *props)
{
- RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- struct ast_format fmt;
+ RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
int cause;
@@ -2406,7 +2405,7 @@ static int retransfer_enter(struct attended_transfer_properties *props)
snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
- ast_format_cap_add(cap, ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
/* Get a channel that is the destination we wish to call */
props->recall_target = ast_request("Local", cap, NULL, NULL, destination, &cause);
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index 93cbed22d..ea9b3f868 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -320,25 +320,28 @@ struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *br
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel)
{
+ ast_assert(bridge_channel->read_format != NULL);
+ ast_assert(bridge_channel->write_format != NULL);
+
/* Restore original formats of the channel as they came in */
- if (ast_format_cmp(ast_channel_readformat(bridge_channel->chan), &bridge_channel->read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(ast_channel_readformat(bridge_channel->chan), bridge_channel->read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bridge is returning %p(%s) to read format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->read_format));
- if (ast_set_read_format(bridge_channel->chan, &bridge_channel->read_format)) {
+ ast_format_get_name(bridge_channel->read_format));
+ if (ast_set_read_format(bridge_channel->chan, bridge_channel->read_format)) {
ast_debug(1, "Bridge failed to return %p(%s) to read format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->read_format));
+ ast_format_get_name(bridge_channel->read_format));
}
}
- if (ast_format_cmp(ast_channel_writeformat(bridge_channel->chan), &bridge_channel->write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(ast_channel_writeformat(bridge_channel->chan), bridge_channel->write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bridge is returning %p(%s) to write format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->write_format));
- if (ast_set_write_format(bridge_channel->chan, &bridge_channel->write_format)) {
+ ast_format_get_name(bridge_channel->write_format));
+ if (ast_set_write_format(bridge_channel->chan, bridge_channel->write_format)) {
ast_debug(1, "Bridge failed to return %p(%s) to write format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->write_format));
+ ast_format_get_name(bridge_channel->write_format));
}
}
}
@@ -2342,8 +2345,8 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
int res = 0;
struct ast_bridge_features *channel_features;
- ast_format_copy(&bridge_channel->read_format, ast_channel_readformat(bridge_channel->chan));
- ast_format_copy(&bridge_channel->write_format, ast_channel_writeformat(bridge_channel->chan));
+ bridge_channel->read_format = ao2_bump(ast_channel_readformat(bridge_channel->chan));
+ bridge_channel->write_format = ao2_bump(ast_channel_writeformat(bridge_channel->chan));
ast_debug(1, "Bridge %s: %p(%s) is joining\n",
bridge_channel->bridge->uniqueid,
@@ -2590,6 +2593,9 @@ static void bridge_channel_destroy(void *obj)
pipe_close(bridge_channel->alert_pipe);
ast_cond_destroy(&bridge_channel->cond);
+
+ ao2_cleanup(bridge_channel->write_format);
+ ao2_cleanup(bridge_channel->read_format);
}
struct ast_bridge_channel *bridge_channel_internal_alloc(struct ast_bridge *bridge)
diff --git a/main/callerid.c b/main/callerid.c
index 5f53cb2ae..e3b2b139e 100644
--- a/main/callerid.c
+++ b/main/callerid.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/fskmodem.h"
#include "asterisk/utils.h"
+#include "asterisk/format_cache.h"
struct callerid_state {
fsk_data fskd;
diff --git a/main/ccss.c b/main/ccss.c
index 09fa2d114..9fcabfefd 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -52,6 +52,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/stasis_system.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="CallCompletionRequest" language="en_US">
@@ -2814,8 +2815,7 @@ static void *generic_recall(void *data)
const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
const char *callback_sub = ast_get_cc_callback_sub(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(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!tmp_cap) {
return NULL;
@@ -2826,17 +2826,17 @@ static void *generic_recall(void *data)
*target++ = '\0';
}
- ast_format_cap_add(tmp_cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(tmp_cap, ast_format_slin, 0);
if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, 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 %u: 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);
+ ao2_ref(tmp_cap, -1);
return NULL;
}
- ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
/* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
* This will be a common task for all recall functions. If it were possible, I'd have
diff --git a/main/channel.c b/main/channel.c
index 15f2cbce0..b17dddeef 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -342,7 +342,7 @@ static char *complete_channeltypes(struct ast_cli_args *a)
static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct chanlist *cl = NULL;
- char buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
switch (cmd) {
case CLI_INIT:
@@ -387,7 +387,7 @@ static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd,
(cl->tech->devicestate) ? "yes" : "no",
(cl->tech->indicate) ? "yes" : "no",
(cl->tech->transfer) ? "yes" : "no",
- ast_getformatname_multiple(buf, sizeof(buf), cl->tech->capabilities),
+ ast_format_cap_get_names(cl->tech->capabilities, &codec_buf),
(cl->tech->send_digit_begin) ? "yes" : "no",
(cl->tech->send_digit_end) ? "yes" : "no",
(cl->tech->send_html) ? "yes" : "no",
@@ -764,78 +764,6 @@ char *ast_transfercapability2str(int transfercapability)
}
}
-/*! \brief Pick the best audio codec */
-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 */
- static const enum ast_format_id prefs[] =
- {
- /*! Okay, ulaw is used by all telephony equipment, so start with it */
- AST_FORMAT_ULAW,
- /*! Unless of course, you're a silly European, so then prefer ALAW */
- AST_FORMAT_ALAW,
- AST_FORMAT_G719,
- AST_FORMAT_SIREN14,
- AST_FORMAT_SIREN7,
- AST_FORMAT_TESTLAW,
- /*! G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority */
- AST_FORMAT_G722,
- /*! Okay, well, signed linear is easy to translate into other stuff */
- AST_FORMAT_SLINEAR192,
- AST_FORMAT_SLINEAR96,
- AST_FORMAT_SLINEAR48,
- AST_FORMAT_SLINEAR44,
- AST_FORMAT_SLINEAR32,
- AST_FORMAT_SLINEAR24,
- AST_FORMAT_SLINEAR16,
- AST_FORMAT_SLINEAR12,
- AST_FORMAT_SLINEAR,
- /*! G.726 is standard ADPCM, in RFC3551 packing order */
- AST_FORMAT_G726,
- /*! G.726 is standard ADPCM, in AAL2 packing order */
- AST_FORMAT_G726_AAL2,
- /*! ADPCM has great sound quality and is still pretty easy to translate */
- AST_FORMAT_ADPCM,
- /*! Okay, we're down to vocoders now, so pick GSM because it's small and easier to
- translate and sounds pretty good */
- AST_FORMAT_GSM,
- /*! iLBC is not too bad */
- AST_FORMAT_ILBC,
- /*! Speex is free, but computationally more expensive than GSM */
- AST_FORMAT_SPEEX32,
- AST_FORMAT_SPEEX16,
- AST_FORMAT_SPEEX,
- /*! Opus */
- AST_FORMAT_OPUS,
- /*! SILK is pretty awesome. */
- AST_FORMAT_SILK,
- /*! CELT supports crazy high sample rates */
- AST_FORMAT_CELT,
- /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
- to use it */
- AST_FORMAT_LPC10,
- /*! G.729a is faster than 723 and slightly less expensive */
- AST_FORMAT_G729A,
- /*! Down to G.723.1 which is proprietary but at least designed for voice */
- AST_FORMAT_G723_1,
- };
- char buf[512];
- int x;
-
- /* Find the first preferred codec in the format given */
- for (x = 0; x < ARRAY_LEN(prefs); x++) {
- if (ast_format_cap_best_byid(cap, prefs[x], result)) {
- return result;
- }
- }
-
- ast_format_clear(result);
- ast_log(LOG_WARNING, "Don't know any of %s formats\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
-
- return NULL;
-}
-
/*! \brief Channel technology used to extract a channel from a running application. The
* channel created with this technology will be immediately hung up - most external
* applications won't ever want to see this.
@@ -883,11 +811,18 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_stage_snapshot(tmp);
- if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_CACHE_STRINGS))) {
+ if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
/* format capabilities structure allocation failure */
return ast_channel_unref(tmp);
}
+ ast_format_cap_append(nativeformats, ast_format_none, 0);
ast_channel_nativeformats_set(tmp, nativeformats);
+ ao2_ref(nativeformats, -1);
+
+ ast_channel_set_rawwriteformat(tmp, ast_format_none);
+ ast_channel_set_rawreadformat(tmp, ast_format_none);
+ ast_channel_set_writeformat(tmp, ast_format_none);
+ ast_channel_set_readformat(tmp, ast_format_none);
/*
* Init file descriptors to unopened state so
@@ -2317,6 +2252,13 @@ static void ast_channel_destructor(void *obj)
if (ast_channel_pbx(chan))
ast_log_callid(LOG_WARNING, callid, "PBX may not have been terminated properly on '%s'\n", ast_channel_name(chan));
+ /* Free formats */
+ ast_channel_set_oldwriteformat(chan, NULL);
+ ast_channel_set_rawreadformat(chan, NULL);
+ ast_channel_set_rawwriteformat(chan, NULL);
+ ast_channel_set_readformat(chan, NULL);
+ ast_channel_set_writeformat(chan, NULL);
+
ast_party_dialed_free(ast_channel_dialed(chan));
ast_party_caller_free(ast_channel_caller(chan));
ast_party_connected_line_free(ast_channel_connected(chan));
@@ -2373,7 +2315,7 @@ static void ast_channel_destructor(void *obj)
ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE) ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), device_name);
}
- ast_channel_nativeformats_set(chan, ast_format_cap_destroy(ast_channel_nativeformats(chan)));
+ ast_channel_nativeformats_set(chan, NULL);
if (callid) {
ast_callid_unref(callid);
}
@@ -2623,21 +2565,14 @@ int ast_softhangup(struct ast_channel *chan, int cause)
static void free_translation(struct ast_channel *clonechan)
{
- if (ast_channel_writetrans(clonechan))
+ if (ast_channel_writetrans(clonechan)) {
ast_translator_free_path(ast_channel_writetrans(clonechan));
- if (ast_channel_readtrans(clonechan))
+ }
+ if (ast_channel_readtrans(clonechan)) {
ast_translator_free_path(ast_channel_readtrans(clonechan));
+ }
ast_channel_writetrans_set(clonechan, NULL);
ast_channel_readtrans_set(clonechan, NULL);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(clonechan))) {
- ast_format_clear(ast_channel_rawwriteformat(clonechan));
- ast_format_clear(ast_channel_rawreadformat(clonechan));
- } else {
- struct ast_format tmpfmt;
- ast_best_codec(ast_channel_nativeformats(clonechan), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(clonechan), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(clonechan), &tmpfmt);
- }
}
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
@@ -2998,10 +2933,11 @@ static int generator_force(const void *data)
generate = ast_channel_generator(chan)->generate;
ast_channel_unlock(chan);
- if (!tmp || !generate)
+ if (!tmp || !generate) {
return 0;
+ }
- res = generate(chan, tmp, 0, ast_format_rate(ast_channel_writeformat(chan)) / 50);
+ res = generate(chan, tmp, 0, ast_format_get_sample_rate(ast_channel_writeformat(chan)) / 50);
ast_channel_lock(chan);
if (ast_channel_generator(chan) && generate == ast_channel_generator(chan)->generate) {
@@ -3677,11 +3613,9 @@ static void ast_read_generator_actions(struct ast_channel *chan, struct ast_fram
* We must generate frames in phase locked mode since
* we have no internal timer available.
*/
-
- if (ast_format_cmp(&f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
float factor;
-
- factor = ((float) ast_format_rate(ast_channel_writeformat(chan))) / ((float) ast_format_rate(&f->subclass.format));
+ factor = ((float) ast_format_get_sample_rate(ast_channel_writeformat(chan))) / ((float) ast_format_get_sample_rate(f->subclass.format));
samples = (int) (((float) f->samples) * factor);
} else {
samples = f->samples;
@@ -4186,11 +4120,11 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_frfree(f);
f = &ast_null_frame;
}
- } else if ((f->frametype == AST_FRAME_VOICE) && !ast_format_cap_iscompatible(ast_channel_nativeformats(chan), &f->subclass.format)) {
+ } else if ((f->frametype == AST_FRAME_VOICE) && ast_format_cap_iscompatible_format(ast_channel_nativeformats(chan), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
/* This frame is not one of the current native formats -- drop it on the floor */
- char to[200];
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n",
- ast_channel_name(chan), ast_getformatname(&f->subclass.format), ast_getformatname_multiple(to, sizeof(to), ast_channel_nativeformats(chan)));
+ ast_channel_name(chan), ast_format_get_name(f->subclass.format), ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf));
ast_frfree(f);
f = &ast_null_frame;
} else if ((f->frametype == AST_FRAME_VOICE)) {
@@ -4206,7 +4140,9 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
#ifndef MONITOR_CONSTANT_DELAY
int jump = ast_channel_outsmpl(chan) - ast_channel_insmpl(chan) - 4 * f->samples;
if (jump >= 0) {
- jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)), ast_format_rate(&f->subclass.format), ast_format_rate(&ast_channel_monitor(chan)->read_stream->fmt->format));
+ jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.format),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (ast_seekstream(ast_channel_monitor(chan)->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");
}
@@ -4215,7 +4151,9 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + f->samples);
}
#else
- int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)), ast_format_rate(f->subclass.codec), ast_format_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
+ int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.codec),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
@@ -4748,7 +4686,7 @@ int ast_sendtext(struct ast_channel *chan, const char *text)
}
CHECK_BLOCKING(chan);
- if (ast_channel_tech(chan)->write_text && (ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_TEXT))) {
+ if (ast_channel_tech(chan)->write_text && (ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_TEXT))) {
struct ast_frame f;
f.frametype = AST_FRAME_TEXT;
@@ -4759,7 +4697,7 @@ int ast_sendtext(struct ast_channel *chan, const char *text)
f.offset = 0;
f.seqno = 0;
- ast_format_set(&f.subclass.format, AST_FORMAT_T140, 0);
+ f.subclass.format = ast_format_t140;
res = ast_channel_tech(chan)->write_text(chan, &f);
} else if (ast_channel_tech(chan)->send_text) {
res = ast_channel_tech(chan)->send_text(chan, text);
@@ -4856,7 +4794,7 @@ int ast_prod(struct ast_channel *chan)
/* Send an empty audio frame to get things moving */
if (ast_channel_state(chan) != AST_STATE_UP) {
ast_debug(1, "Prodding channel '%s'\n", ast_channel_name(chan));
- ast_format_copy(&a.subclass.format, ast_channel_rawwriteformat(chan));
+ a.subclass.format = ast_channel_rawwriteformat(chan);
a.data.ptr = nothing + AST_FRIENDLY_OFFSET;
a.src = "ast_prod"; /* this better match check in ast_write */
if (ast_write(chan, &a))
@@ -5068,7 +5006,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
CHECK_BLOCKING(chan);
break;
case AST_FRAME_TEXT:
- if (fr->subclass.integer == AST_FORMAT_T140) {
+ if (ast_format_cmp(fr->subclass.format, ast_format_t140) == AST_FORMAT_CMP_EQUAL) {
res = (ast_channel_tech(chan)->write_text == NULL) ? 0 :
ast_channel_tech(chan)->write_text(chan, fr);
} else {
@@ -5093,17 +5031,17 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
if (ast_channel_tech(chan)->write == NULL)
break; /*! \todo XXX should return 0 maybe ? */
- if (ast_opt_generic_plc && fr->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (ast_opt_generic_plc && ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
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 (ast_format_cmp(&fr->subclass.format, ast_channel_rawwriteformat(chan)) != AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) != AST_FORMAT_CMP_NOT_EQUAL) {
f = fr;
} else {
- if ((!ast_format_cap_iscompatible(ast_channel_nativeformats(chan), &fr->subclass.format)) &&
- (ast_format_cmp(ast_channel_writeformat(chan), &fr->subclass.format) != AST_FORMAT_CMP_EQUAL)) {
- char nf[512];
+ if ((ast_format_cap_iscompatible_format(ast_channel_nativeformats(chan), fr->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ (ast_format_cmp(ast_channel_writeformat(chan), fr->subclass.format) != AST_FORMAT_CMP_EQUAL)) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
/*
* XXX Something is not right. We are not compatible with this
@@ -5115,9 +5053,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
* areas.
*/
ast_log(LOG_WARNING, "Codec mismatch on channel %s setting write format to %s from %s native formats %s\n",
- ast_channel_name(chan), ast_getformatname(&fr->subclass.format), ast_getformatname(ast_channel_writeformat(chan)),
- ast_getformatname_multiple(nf, sizeof(nf), ast_channel_nativeformats(chan)));
- ast_set_write_format_by_id(chan, fr->subclass.format.id);
+ ast_channel_name(chan), ast_format_get_name(fr->subclass.format), ast_format_get_name(ast_channel_writeformat(chan)),
+ ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf));
+ ast_set_write_format(chan, fr->subclass.format);
}
f = (ast_channel_writetrans(chan)) ? ast_translate(ast_channel_writetrans(chan), fr, 0) : fr;
@@ -5185,7 +5123,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
#ifndef MONITOR_CONSTANT_DELAY
int jump = ast_channel_insmpl(chan) - ast_channel_outsmpl(chan) - 4 * cur->samples;
if (jump >= 0) {
- jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)), ast_format_rate(&f->subclass.format), ast_format_rate(&ast_channel_monitor(chan)->read_stream->fmt->format));
+ jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.format),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (ast_seekstream(ast_channel_monitor(chan)->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");
}
@@ -5194,7 +5134,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
ast_channel_outsmpl_set(chan, ast_channel_outsmpl(chan) + cur->samples);
}
#else
- int jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)), ast_format_rate(f->subclass.codec), ast_format_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
+ int jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.codec),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(ast_channel_monitor(chan)->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1) {
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
@@ -5300,21 +5242,23 @@ static int set_format(struct ast_channel *chan,
{
struct ast_trans_pvt *trans_pvt;
struct ast_format_cap *cap_native;
- struct ast_format best_set_fmt;
- struct ast_format best_native_fmt;
+ RAII_VAR(struct ast_format *, best_set_fmt, ast_format_cap_get_format(cap_set, 0), ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_native_fmt, NULL, ao2_cleanup);
int res;
- ast_best_codec(cap_set, &best_set_fmt);
+ ast_assert(format != NULL);
+ ast_assert(rawformat != NULL);
/* 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, &best_set_fmt, sizeof(best_set_fmt), 0)) {
ast_debug(1, "Channel driver natively set channel %s to %s format %s\n", ast_channel_name(chan),
- direction ? "write" : "read", ast_getformatname(&best_set_fmt));
+ direction ? "write" : "read", ast_format_get_name(best_set_fmt));
ast_channel_lock(chan);
- ast_format_copy(format, &best_set_fmt);
- ast_format_copy(rawformat, &best_set_fmt);
- ast_format_cap_set(ast_channel_nativeformats(chan), &best_set_fmt);
+ cap_native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_append(cap_native, best_set_fmt, 0);
+ ast_channel_nativeformats_set(chan, cap_native);
+ ao2_cleanup(cap_native);
ast_channel_unlock(chan);
trans_pvt = trans->get(chan);
@@ -5344,31 +5288,27 @@ static int set_format(struct ast_channel *chan,
res = ast_translator_best_choice(cap_native, cap_set, &best_native_fmt, &best_set_fmt);
}
if (res < 0) {
- char from[200];
- char to[200];
+ struct ast_str *codec_from = ast_str_alloca(64);
+ struct ast_str *codec_to = ast_str_alloca(64);
- ast_getformatname_multiple(from, sizeof(from), cap_native);
+ ast_format_cap_get_names(cap_native, &codec_from);
ast_channel_unlock(chan);
- ast_getformatname_multiple(to, sizeof(to), cap_set);
+ ast_format_cap_get_names(cap_set, &codec_to);
ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n",
- from, to);
+ ast_str_buffer(codec_from), ast_str_buffer(codec_to));
return -1;
}
/* Now we have a good choice for both. */
- 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) &&
+ 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->get(chan))) {
/* the channel is already in these formats, so nothing to do */
ast_channel_unlock(chan);
return 0;
}
- ast_format_copy(rawformat, &best_native_fmt);
- /* User perspective is fmt */
- ast_format_copy(format, &best_set_fmt);
-
/* Free any translation we have right now */
trans_pvt = trans->get(chan);
if (trans_pvt) {
@@ -5377,7 +5317,7 @@ static int set_format(struct ast_channel *chan,
}
/* Build a translation path from the raw format to the desired format */
- if (ast_format_cmp(format, rawformat) != AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(best_set_fmt, best_native_fmt) != 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
@@ -5387,20 +5327,33 @@ static int set_format(struct ast_channel *chan,
} else {
if (!direction) {
/* reading */
- trans_pvt = ast_translator_build_path(format, rawformat);
+ trans_pvt = ast_translator_build_path(best_set_fmt, best_native_fmt);
} else {
/* writing */
- trans_pvt = ast_translator_build_path(rawformat, format);
+ trans_pvt = ast_translator_build_path(best_native_fmt, best_set_fmt);
}
trans->set(chan, trans_pvt);
res = trans_pvt ? 0 : -1;
}
- ast_channel_unlock(chan);
- ast_debug(1, "Set channel %s to %s format %s\n",
- ast_channel_name(chan),
- direction ? "write" : "read",
- ast_getformatname(&best_set_fmt));
+ if (!res) {
+ if (!direction) {
+ /* reading */
+ ast_channel_set_readformat(chan, best_set_fmt);
+ ast_channel_set_rawreadformat(chan, best_native_fmt);
+ } else {
+ /* writing */
+ ast_channel_set_writeformat(chan, best_set_fmt);
+ ast_channel_set_rawwriteformat(chan, best_native_fmt);
+ }
+
+ ast_debug(1, "Set channel %s to %s format %s\n",
+ ast_channel_name(chan),
+ direction ? "write" : "read",
+ ast_format_get_name(best_set_fmt));
+ }
+
+ ast_channel_unlock(chan);
/* If there is a generator on the channel, it needs to know about this
* change if it is the write format. */
@@ -5413,35 +5366,15 @@ static int set_format(struct ast_channel *chan,
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int res;
- if (!cap) {
- return -1;
- }
- ast_format_cap_add(cap, format);
-
- res = set_format(chan,
- cap,
- ast_channel_rawreadformat(chan),
- ast_channel_readformat(chan),
- &set_format_readtrans,
- 0);
-
- ast_format_cap_destroy(cap);
- return res;
-}
-
-int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id)
-{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_format;
- int res;
+ ast_assert(format != NULL);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_format, id, 0));
+ ast_format_cap_append(cap, format, 0);
res = set_format(chan,
cap,
@@ -5450,7 +5383,7 @@ int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id)
&set_format_readtrans,
0);
- ast_format_cap_destroy(cap);
+ ao2_cleanup(cap);
return res;
}
@@ -5466,35 +5399,15 @@ int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int res;
- if (!cap) {
- return -1;
- }
- ast_format_cap_add(cap, format);
-
- res = set_format(chan,
- cap,
- ast_channel_rawwriteformat(chan),
- ast_channel_writeformat(chan),
- &set_format_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(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_format;
- int res;
+ ast_assert(format != NULL);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_format, id, 0));
+ ast_format_cap_append(cap, format, 0);
res = set_format(chan,
cap,
@@ -5503,7 +5416,7 @@ int ast_set_write_format_by_id(struct ast_channel *chan, enum ast_format_id id)
&set_format_writetrans,
1);
- ast_format_cap_destroy(cap);
+ ao2_cleanup(cap);
return res;
}
@@ -5912,26 +5825,29 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
AST_RWLIST_TRAVERSE(&backends, chan, list) {
struct ast_format_cap *tmp_cap;
- struct ast_format tmp_fmt;
- struct ast_format best_audio_fmt;
+ RAII_VAR(struct ast_format *, tmp_fmt, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_audio_fmt, NULL, ao2_cleanup);
struct ast_format_cap *joint_cap;
if (strcasecmp(type, chan->tech->type))
continue;
- 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))) {
+ tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmp_cap) {
+ ast_format_cap_append_from_cap(tmp_cap, request_cap, AST_MEDIA_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(tmp_cap, chan->tech->capabilities, &tmp_fmt, &best_audio_fmt);
- ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
if (res < 0) {
- char tmp1[256], tmp2[256];
+ struct ast_str *tech_codecs = ast_str_alloca(64);
+ struct ast_str *request_codecs = ast_str_alloca(64);
+
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), request_cap));
+ ast_format_cap_get_names(chan->tech->capabilities, &tech_codecs),
+ ast_format_cap_get_names(request_cap, &request_codecs));
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
AST_RWLIST_UNLOCK(&backends);
return NULL;
@@ -5945,14 +5861,16 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
* 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))) {
+ joint_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!joint_cap) {
return NULL;
}
- ast_format_cap_remove_bytype(joint_cap, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(joint_cap, &best_audio_fmt);
+ ast_format_cap_append_from_cap(joint_cap, request_cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(joint_cap, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append(joint_cap, best_audio_fmt, 0);
if (!(c = chan->tech->requester(type, joint_cap, assignedids, requestor, addr, cause))) {
- ast_format_cap_destroy(joint_cap);
+ ao2_ref(joint_cap, -1);
return NULL;
}
@@ -5967,7 +5885,7 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
}
}
- joint_cap = ast_format_cap_destroy(joint_cap);
+ ao2_ref(joint_cap, -1);
if (set_security_requirements(requestor, c)) {
ast_log(LOG_WARNING, "Setting security requirements failed\n");
@@ -6164,8 +6082,8 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
{
struct ast_format_cap *src_cap;
struct ast_format_cap *dst_cap;
- struct ast_format best_src_fmt;
- struct ast_format best_dst_fmt;
+ RAII_VAR(struct ast_format *, best_src_fmt, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_dst_fmt, NULL, ao2_cleanup);
int no_path;
ast_channel_lock_both(from, to);
@@ -6182,8 +6100,8 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
dst_cap = ast_channel_nativeformats(to); /* shallow copy, do not destroy */
/* If there's no audio in this call, don't bother with trying to find a translation path */
- if (!ast_format_cap_has_type(src_cap, AST_FORMAT_TYPE_AUDIO)
- || !ast_format_cap_has_type(dst_cap, AST_FORMAT_TYPE_AUDIO)) {
+ if (!ast_format_cap_has_type(src_cap, AST_MEDIA_TYPE_AUDIO)
+ || !ast_format_cap_has_type(dst_cap, AST_MEDIA_TYPE_AUDIO)) {
ast_channel_unlock(to);
ast_channel_unlock(from);
return 0;
@@ -6206,28 +6124,29 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
* no direct conversion available. If generic PLC is
* desired, then transcoding via SLINEAR is a requirement
*/
- if (ast_format_cmp(&best_dst_fmt, &best_src_fmt) == AST_FORMAT_CMP_NOT_EQUAL
+ if (ast_format_cmp(best_dst_fmt, best_src_fmt) == AST_FORMAT_CMP_NOT_EQUAL
&& (ast_opt_generic_plc || ast_opt_transcode_via_slin)) {
- int use_slin = (ast_format_is_slinear(&best_src_fmt)
- || ast_format_is_slinear(&best_dst_fmt)) ? 1 : 0;
+ int use_slin = (ast_format_cache_is_slinear(best_src_fmt)
+ || ast_format_cache_is_slinear(best_dst_fmt)) ? 1 : 0;
- if (use_slin || ast_translate_path_steps(&best_dst_fmt, &best_src_fmt) != 1) {
- int best_sample_rate = (ast_format_rate(&best_src_fmt) > ast_format_rate(&best_dst_fmt)) ?
- ast_format_rate(&best_src_fmt) : ast_format_rate(&best_dst_fmt);
+ if (use_slin || ast_translate_path_steps(best_dst_fmt, best_src_fmt) != 1) {
+ int best_sample_rate = (ast_format_get_sample_rate(best_src_fmt) > ast_format_get_sample_rate(best_dst_fmt)) ?
+ ast_format_get_sample_rate(best_src_fmt) : ast_format_get_sample_rate(best_dst_fmt);
/* pick the best signed linear format based upon what preserves the sample rate the best. */
- ast_format_set(&best_src_fmt, ast_format_slin_by_rate(best_sample_rate), 0);
+ ao2_ref(best_src_fmt, -1);
+ best_src_fmt = ao2_bump(ast_format_cache_get_slin_by_rate(best_sample_rate));
}
}
- if (ast_set_read_format(from, &best_src_fmt)) {
+ if (ast_set_read_format(from, best_src_fmt)) {
ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n",
- ast_channel_name(from), ast_getformatname(&best_src_fmt));
+ ast_channel_name(from), ast_format_get_name(best_src_fmt));
return -1;
}
- if (ast_set_write_format(to, &best_src_fmt)) {
+ if (ast_set_write_format(to, best_src_fmt)) {
ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n",
- ast_channel_name(to), ast_getformatname(&best_src_fmt));
+ ast_channel_name(to), ast_format_get_name(best_src_fmt));
return -1;
}
return 0;
@@ -6387,9 +6306,10 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
struct ast_party_redirecting redirecting;
} exchange;
struct ast_channel *bridged;
- struct ast_format rformat;
- struct ast_format wformat;
- struct ast_format tmp_format;
+ struct ast_format *rformat;
+ struct ast_format *wformat;
+ struct ast_format *tmp_format;
+ struct ast_format_cap *tmp_cap;
char tmp_name[AST_CHANNEL_NAME];
char clone_sending_dtmf_digit;
struct timeval clone_sending_dtmf_tv;
@@ -6446,8 +6366,8 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
* Remember the original read/write formats. We turn off any
* translation on either one
*/
- ast_format_copy(&rformat, ast_channel_readformat(original));
- ast_format_copy(&wformat, ast_channel_writeformat(original));
+ rformat = ao2_bump(ast_channel_readformat(original));
+ wformat = ao2_bump(ast_channel_writeformat(original));
free_translation(clonechan);
free_translation(original);
@@ -6508,13 +6428,15 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
}
/* Swap the raw formats */
- ast_format_copy(&tmp_format, ast_channel_rawreadformat(original));
- ast_format_copy(ast_channel_rawreadformat(original), ast_channel_rawreadformat(clonechan));
- ast_format_copy(ast_channel_rawreadformat(clonechan), &tmp_format);
+ tmp_format = ao2_bump(ast_channel_rawreadformat(original));
+ ast_channel_set_rawreadformat(original, ast_channel_rawreadformat(clonechan));
+ ast_channel_set_rawreadformat(clonechan, tmp_format);
+ ao2_cleanup(tmp_format);
- ast_format_copy(&tmp_format, ast_channel_rawwriteformat(original));
- ast_format_copy(ast_channel_rawwriteformat(original), ast_channel_rawwriteformat(clonechan));
- ast_format_copy(ast_channel_rawwriteformat(clonechan), &tmp_format);
+ tmp_format = ao2_bump(ast_channel_rawwriteformat(original));
+ ast_channel_set_rawwriteformat(original, ast_channel_rawwriteformat(clonechan));
+ ast_channel_set_rawwriteformat(clonechan, tmp_format);
+ ao2_cleanup(tmp_format);
ast_channel_softhangup_internal_flag_set(clonechan, AST_SOFTHANGUP_DEV);
@@ -6642,16 +6564,21 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
ast_channel_set_fd(original, AST_TIMING_FD, ast_channel_timingfd(original));
/* Our native formats are different now */
- ast_format_cap_copy(ast_channel_nativeformats(original), ast_channel_nativeformats(clonechan));
+ tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmp_cap) {
+ ast_format_cap_append_from_cap(tmp_cap, ast_channel_nativeformats(clonechan), AST_MEDIA_TYPE_UNKNOWN);
+ ast_channel_nativeformats_set(original, tmp_cap);
+ ao2_ref(tmp_cap, -1);
+ }
/* 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_channel_musicclass_set(original, ast_channel_musicclass(clonechan));
@@ -6660,7 +6587,7 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
ast_channel_accountcode_set(original, S_OR(ast_channel_accountcode(clonechan), ""));
ast_debug(1, "Putting channel %s in %s/%s formats\n", ast_channel_name(original),
- ast_getformatname(&wformat), ast_getformatname(&rformat));
+ ast_format_get_name(wformat), ast_format_get_name(rformat));
/* Fixup the original clonechan's physical side */
if (ast_channel_tech(original)->fixup && ast_channel_tech(original)->fixup(clonechan, original)) {
@@ -6773,6 +6700,9 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
/* Release our held safety references. */
ast_channel_unref(original);
ast_channel_unref(clonechan);
+
+ ao2_cleanup(rformat);
+ ao2_cleanup(wformat);
}
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
@@ -6917,7 +6847,7 @@ struct tonepair_state {
int v1_2;
int v2_2;
int v3_2;
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
int pos;
int duration;
int modulate;
@@ -6930,8 +6860,10 @@ static void tonepair_release(struct ast_channel *chan, void *params)
{
struct tonepair_state *ts = params;
- if (chan)
- ast_set_write_format(chan, &ts->origwfmt);
+ if (chan) {
+ ast_set_write_format(chan, ts->origwfmt);
+ }
+ ao2_cleanup(ts->origwfmt);
ast_free(ts);
}
@@ -6940,10 +6872,12 @@ static void *tonepair_alloc(struct ast_channel *chan, void *params)
struct tonepair_state *ts;
struct tonepair_def *td = params;
- if (!(ts = ast_calloc(1, sizeof(*ts))))
+ if (!(ts = ast_calloc(1, sizeof(*ts)))) {
return NULL;
- ast_format_copy(&ts->origwfmt, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ }
+
+ ts->origwfmt = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", ast_channel_name(chan));
tonepair_release(NULL, ts);
ts = NULL;
@@ -6997,7 +6931,7 @@ static int tonepair_generator(struct ast_channel *chan, void *data, int len, int
ts->data[x] = ts->v3_1 + ts->v3_2;
}
ts->f.frametype = AST_FRAME_VOICE;
- ast_format_set(&ts->f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ ts->f.subclass.format = ast_format_slin;
ts->f.datalen = len;
ts->f.samples = samples;
ts->f.offset = AST_FRIENDLY_OFFSET;
@@ -7675,7 +7609,7 @@ static int silence_generator_generate(struct ast_channel *chan, void *data, int
.samples = samples,
.datalen = sizeof(buf),
};
- ast_format_set(&frame.subclass.format, AST_FORMAT_SLINEAR, 0);
+ frame.subclass.format = ast_format_slin;
memset(buf, 0, sizeof(buf));
@@ -7692,7 +7626,7 @@ static struct ast_generator silence_generator = {
};
struct ast_silence_generator {
- struct ast_format old_write_format;
+ struct ast_format *old_write_format;
};
struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan)
@@ -7703,9 +7637,9 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha
return NULL;
}
- ast_format_copy(&state->old_write_format, ast_channel_writeformat(chan));
+ state->old_write_format = ao2_bump(ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n");
ast_free(state);
return NULL;
@@ -7749,9 +7683,11 @@ void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_sil
if (deactivate_silence_generator(chan)) {
ast_debug(1, "Stopped silence generator on '%s'\n", ast_channel_name(chan));
- 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");
+ }
}
+ ao2_cleanup(state->old_write_format);
ast_free(state);
}
@@ -10199,8 +10135,8 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
char *context;
char *name;
int amaflags;
- struct ast_format readformat;
- struct ast_format writeformat;
+ struct ast_format *readformat;
+ struct ast_format *writeformat;
} my_vars = { 0, };
ast_channel_lock(yankee);
@@ -10209,8 +10145,8 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
my_vars.context = ast_strdupa(ast_channel_context(yankee));
my_vars.name = ast_strdupa(ast_channel_name(yankee));
my_vars.amaflags = ast_channel_amaflags(yankee);
- ast_format_copy(&my_vars.writeformat, ast_channel_writeformat(yankee));
- ast_format_copy(&my_vars.readformat, ast_channel_readformat(yankee));
+ my_vars.writeformat = ao2_bump(ast_channel_writeformat(yankee));
+ my_vars.readformat = ao2_bump(ast_channel_readformat(yankee));
ast_channel_unlock(yankee);
/* Do not hold any channel locks while calling channel_alloc() since the function
@@ -10218,12 +10154,16 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
if (!(yanked_chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, my_vars.accountcode,
my_vars.exten, my_vars.context, NULL, yankee, my_vars.amaflags,
"Surrogate/%s", my_vars.name))) {
+ ao2_cleanup(my_vars.writeformat);
+ ao2_cleanup(my_vars.readformat);
return NULL;
}
/* Make formats okay */
- ast_format_copy(ast_channel_readformat(yanked_chan), &my_vars.readformat);
- ast_format_copy(ast_channel_writeformat(yanked_chan), &my_vars.writeformat);
+ ast_channel_set_readformat(yanked_chan, my_vars.readformat);
+ ast_channel_set_writeformat(yanked_chan, my_vars.writeformat);
+ ao2_cleanup(my_vars.readformat);
+ ao2_cleanup(my_vars.writeformat);
ast_channel_unlock(yanked_chan);
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index c2dc2d737..4ad0ef3a0 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -176,7 +176,7 @@ struct ast_channel {
int fdno; /*!< Which fd had an event detected on */
int streamid; /*!< For streaming playback, the schedule ID */
int vstreamid; /*!< For streaming video playback, the schedule ID */
- struct ast_format 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 */
@@ -193,10 +193,10 @@ struct ast_channel {
struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */
int alertpipe[2];
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) */
+ 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;
@@ -826,7 +826,8 @@ struct ast_format_cap *ast_channel_nativeformats(const struct ast_channel *chan)
}
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
{
- chan->nativeformats = value;
+ ao2_cleanup(chan->nativeformats);
+ chan->nativeformats = ao2_bump(value);
}
struct ast_framehook_list *ast_channel_framehooks(const struct ast_channel *chan)
{
@@ -949,25 +950,50 @@ void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state valu
{
chan->state = value;
}
+void ast_channel_set_oldwriteformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->oldwriteformat);
+ chan->oldwriteformat = ao2_bump(format);
+}
+void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->rawreadformat);
+ chan->rawreadformat = ao2_bump(format);
+}
+void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->rawwriteformat);
+ chan->rawwriteformat = ao2_bump(format);
+}
+void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->readformat);
+ chan->readformat = ao2_bump(format);
+}
+void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->writeformat);
+ chan->writeformat = ao2_bump(format);
+}
struct ast_format *ast_channel_oldwriteformat(struct ast_channel *chan)
{
- return &chan->oldwriteformat;
+ return chan->oldwriteformat;
}
struct ast_format *ast_channel_rawreadformat(struct ast_channel *chan)
{
- return &chan->rawreadformat;
+ return chan->rawreadformat;
}
struct ast_format *ast_channel_rawwriteformat(struct ast_channel *chan)
{
- return &chan->rawwriteformat;
+ return chan->rawwriteformat;
}
struct ast_format *ast_channel_readformat(struct ast_channel *chan)
{
- return &chan->readformat;
+ return chan->readformat;
}
struct ast_format *ast_channel_writeformat(struct ast_channel *chan)
{
- return &chan->writeformat;
+ return chan->writeformat;
}
struct ast_hangup_handler_list *ast_channel_hangup_handlers(struct ast_channel *chan)
{
diff --git a/main/cli.c b/main/cli.c
index bff58695d..bb8e33e44 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -1521,9 +1521,9 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
long elapsed_seconds=0;
int hour=0, min=0, sec=0;
struct ast_var_t *var;
- char nativeformats[256];
struct ast_str *write_transpath = ast_str_alloca(256);
struct ast_str *read_transpath = ast_str_alloca(256);
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_bridge *bridge;
struct ast_callid *callid;
char callid_buf[32];
@@ -1634,9 +1634,9 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
ast_channel_language(chan),
ast_state2str(ast_channel_state(chan)),
ast_channel_state(chan),
- ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)),
- ast_getformatname(ast_channel_writeformat(chan)),
- ast_getformatname(ast_channel_readformat(chan)),
+ ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
+ ast_format_get_name(ast_channel_writeformat(chan)),
+ ast_format_get_name(ast_channel_readformat(chan)),
ast_str_strlen(write_transpath) ? "Yes" : "No",
ast_str_buffer(write_transpath),
ast_str_strlen(read_transpath) ? "Yes" : "No",
diff --git a/main/codec.c b/main/codec.c
new file mode 100644
index 000000000..e060efe3e
--- /dev/null
+++ b/main/codec.c
@@ -0,0 +1,381 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Codecs API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/frame.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/strings.h"
+#include "asterisk/module.h"
+#include "asterisk/cli.h"
+
+/*! \brief Number of buckets to use for codecs (should be prime for performance reasons) */
+#define CODEC_BUCKETS 53
+
+/*! \brief Current identifier value for newly registered codec */
+static int codec_id = 1;
+
+/*! \brief Registered codecs */
+static struct ao2_container *codecs;
+
+static int codec_hash(const void *obj, int flags)
+{
+ const struct ast_codec *codec;
+ const char *key;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_KEY:
+ key = obj;
+ return ast_str_hash(key);
+ case OBJ_SEARCH_OBJECT:
+ codec = obj;
+ return ast_str_hash(codec->name);
+ default:
+ /* Hash can only work on something with a full key. */
+ ast_assert(0);
+ return 0;
+ }
+}
+
+static int codec_cmp(void *obj, void *arg, int flags)
+{
+ const struct ast_codec *left = obj;
+ const struct ast_codec *right = arg;
+ const char *right_key = arg;
+ int cmp;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right->name;
+ cmp = strcmp(left->name, right_key);
+
+ if (right->type != AST_MEDIA_TYPE_UNKNOWN) {
+ cmp |= (right->type != left->type);
+ }
+
+ /* BUGBUG: this will allow a match on a codec by name only.
+ * This is particularly useful when executed by the CLI; if
+ * that is not needed in translate.c, this can be removed.
+ */
+ if (right->sample_rate) {
+ cmp |= (right->sample_rate != left->sample_rate);
+ }
+ break;
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left->name, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left->name, right_key, strlen(right_key));
+ break;
+ default:
+ ast_assert(0);
+ cmp = 0;
+ break;
+ }
+ if (cmp) {
+ return 0;
+ }
+
+ return CMP_MATCH;
+}
+
+static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ struct ao2_iterator i;
+ struct ast_codec *codec;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core show codecs [audio|video|image|text]";
+ e->usage =
+ "Usage: core show codecs [audio|video|image|text]\n"
+ " Displays codec mapping\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if ((a->argc < 3) || (a->argc > 4)) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (!ast_opt_dont_warn) {
+ 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, "%8s %5s %8s %s\n","ID","TYPE","NAME","DESCRIPTION");
+ ast_cli(a->fd, "-----------------------------------------------------------------------------------\n");
+
+ ao2_rdlock(codecs);
+ i = ao2_iterator_init(codecs, AO2_ITERATOR_DONTLOCK);
+
+ for (; (codec = ao2_iterator_next(&i)); ao2_ref(codec, -1)) {
+ if (a->argc == 4) {
+ if (!strcasecmp(a->argv[3], "audio")) {
+ if (codec->type != AST_MEDIA_TYPE_AUDIO) {
+ continue;
+ }
+ } else if (!strcasecmp(a->argv[3], "video")) {
+ if (codec->type != AST_MEDIA_TYPE_VIDEO) {
+ continue;
+ }
+ } else if (!strcasecmp(a->argv[3], "image")) {
+ if (codec->type != AST_MEDIA_TYPE_IMAGE) {
+ continue;
+ }
+ } else if (!strcasecmp(a->argv[3], "text")) {
+ if (codec->type != AST_MEDIA_TYPE_TEXT) {
+ continue;
+ }
+ } else {
+ continue;
+ }
+ }
+
+ ast_cli(a->fd, "%8u %5s %8s (%s)\n",
+ codec->id,
+ ast_codec_media_type2str(codec->type),
+ codec->name,
+ codec->description);
+ }
+
+ ao2_iterator_destroy(&i);
+ ao2_unlock(codecs);
+
+ return CLI_SUCCESS;
+}
+
+/*! \brief Callback function for getting a codec based on unique identifier */
+static int codec_id_cmp(void *obj, void *arg, int flags)
+{
+ struct ast_codec *codec = obj;
+ int *id = arg;
+
+ return (codec->id == *id) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+static char *show_codec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int type_punned_codec;
+ struct ast_codec *codec;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core show codec";
+ e->usage =
+ "Usage: core show codec <number>\n"
+ " Displays codec mapping\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (sscanf(a->argv[3], "%30d", &type_punned_codec) != 1) {
+ return CLI_SHOWUSAGE;
+ }
+
+ codec = ao2_callback(codecs, 0, codec_id_cmp, &type_punned_codec);
+ if (!codec) {
+ ast_cli(a->fd, "Codec %d not found\n", type_punned_codec);
+ return CLI_SUCCESS;
+ }
+
+ ast_cli(a->fd, "%11u %s\n", (unsigned int) codec->id, codec->description);
+
+ ao2_ref(codec, -1);
+
+ return CLI_SUCCESS;
+}
+
+/* Builtin Asterisk CLI-commands for debugging */
+static struct ast_cli_entry codec_cli[] = {
+ AST_CLI_DEFINE(show_codecs, "Displays a list of registered codecs"),
+ AST_CLI_DEFINE(show_codec, "Shows a specific codec"),
+};
+
+/*! \brief Function called when the process is shutting down */
+static void codec_shutdown(void)
+{
+ ast_cli_unregister_multiple(codec_cli, ARRAY_LEN(codec_cli));
+ ao2_cleanup(codecs);
+ codecs = NULL;
+}
+
+int ast_codec_init(void)
+{
+ codecs = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CODEC_BUCKETS, codec_hash, codec_cmp);
+ if (!codecs) {
+ return -1;
+ }
+
+ ast_cli_register_multiple(codec_cli, ARRAY_LEN(codec_cli));
+ ast_register_atexit(codec_shutdown);
+
+ return 0;
+}
+
+static void codec_dtor(void *obj)
+{
+ struct ast_codec *codec;
+
+ codec = obj;
+
+ ast_module_unref(codec->mod);
+}
+
+int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
+{
+ SCOPED_AO2WRLOCK(lock, codecs);
+ struct ast_codec *codec_new;
+
+ /* Some types have specific requirements */
+ if (codec->type == AST_MEDIA_TYPE_UNKNOWN) {
+ ast_log(LOG_ERROR, "A media type must be specified for codec '%s'\n", codec->name);
+ return -1;
+ } else if (codec->type == AST_MEDIA_TYPE_AUDIO) {
+ if (!codec->sample_rate) {
+ ast_log(LOG_ERROR, "A sample rate must be specified for codec '%s' of type '%s'\n",
+ codec->name, ast_codec_media_type2str(codec->type));
+ return -1;
+ }
+ }
+
+ codec_new = ao2_find(codecs, codec, OBJ_SEARCH_OBJECT | OBJ_NOLOCK);
+ if (codec_new) {
+ ast_log(LOG_ERROR, "A codec with name '%s' of type '%s' and sample rate '%u' is already registered\n",
+ codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
+ ao2_ref(codec_new, -1);
+ return -1;
+ }
+
+ codec_new = ao2_t_alloc_options(sizeof(*codec_new), codec_dtor,
+ AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
+ if (!codec_new) {
+ ast_log(LOG_ERROR, "Could not allocate a codec with name '%s' of type '%s' and sample rate '%u'\n",
+ codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
+ return -1;
+ }
+ *codec_new = *codec;
+ codec_new->id = codec_id++;
+
+ ao2_link_flags(codecs, codec_new, OBJ_NOLOCK);
+
+ /* Once registered a codec can not be unregistered, and the module must persist */
+ ast_module_ref(mod);
+
+ ast_verb(2, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n",
+ ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->id);
+
+ ao2_ref(codec_new, -1);
+
+ return 0;
+}
+
+struct ast_codec *ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate)
+{
+ struct ast_codec codec = {
+ .name = name,
+ .type = type,
+ .sample_rate = sample_rate,
+ };
+
+ return ao2_find(codecs, &codec, OBJ_SEARCH_OBJECT);
+}
+
+struct ast_codec *ast_codec_get_by_id(int id)
+{
+ return ao2_callback(codecs, 0, codec_id_cmp, &id);
+}
+
+int ast_codec_get_max(void)
+{
+ return codec_id;
+}
+
+const char *ast_codec_media_type2str(enum ast_media_type type)
+{
+ switch (type) {
+ case AST_MEDIA_TYPE_AUDIO:
+ return "audio";
+ case AST_MEDIA_TYPE_VIDEO:
+ return "video";
+ case AST_MEDIA_TYPE_IMAGE:
+ return "image";
+ case AST_MEDIA_TYPE_TEXT:
+ return "text";
+ default:
+ return "<unknown>";
+ }
+}
+
+unsigned int ast_codec_samples_count(struct ast_frame *frame)
+{
+ struct ast_codec *codec;
+ unsigned int samples = 0;
+
+ if ((frame->frametype != AST_FRAME_VOICE) &&
+ (frame->frametype != AST_FRAME_VIDEO) &&
+ (frame->frametype != AST_FRAME_IMAGE)) {
+ return 0;
+ }
+
+ /* BUGBUG - why not just get the codec pointer off the format?
+ This is a bit roundabout
+ */
+ codec = ast_codec_get_by_id(ast_format_get_codec_id(frame->subclass.format));
+
+ if (codec->samples_count) {
+ samples = codec->samples_count(frame);
+ } else {
+ ast_log(LOG_WARNING, "Unable to calculate samples for codec %s\n",
+ ast_format_get_name(frame->subclass.format));
+ }
+
+ ao2_ref(codec, -1);
+ return samples;
+}
+
+unsigned int ast_codec_determine_length(const struct ast_codec *codec, unsigned int samples)
+{
+ if (!codec->get_length) {
+ return 0;
+ }
+
+ return codec->get_length(samples);
+}
diff --git a/main/codec_builtin.c b/main/codec_builtin.c
new file mode 100644
index 000000000..594074aa4
--- /dev/null
+++ b/main/codec_builtin.c
@@ -0,0 +1,845 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Built-in supported codecs
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/frame.h"
+
+enum frame_type {
+ TYPE_HIGH, /* 0x0 */
+ TYPE_LOW, /* 0x1 */
+ TYPE_SILENCE, /* 0x2 */
+ TYPE_DONTSEND /* 0x3 */
+};
+
+#define TYPE_MASK 0x3
+
+static int g723_len(unsigned char buf)
+{
+ enum frame_type type = buf & TYPE_MASK;
+
+ switch(type) {
+ case TYPE_DONTSEND:
+ return 0;
+ break;
+ case TYPE_SILENCE:
+ return 4;
+ break;
+ case TYPE_HIGH:
+ return 24;
+ break;
+ case TYPE_LOW:
+ return 20;
+ break;
+ default:
+ ast_log(LOG_WARNING, "Badly encoded frame (%u)\n", type);
+ }
+ return -1;
+}
+
+static int g723_samples(struct ast_frame *frame)
+{
+ unsigned char *buf = frame->data.ptr;
+ int pos = 0, samples = 0, res;
+
+ while(pos < frame->datalen) {
+ res = g723_len(buf[pos]);
+ if (res <= 0)
+ break;
+ samples += 240;
+ pos += res;
+ }
+
+ return samples;
+}
+
+static int g723_length(unsigned int samples)
+{
+ return (samples / 240) * 20;
+}
+
+static struct ast_codec g723 = {
+ .name = "g723",
+ .description = "G.723.1",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 30,
+ .maximum_ms = 300,
+ .default_ms = 30,
+ .minimum_bytes = 20,
+ .samples_count = g723_samples,
+ .get_length = g723_length,
+};
+
+static int none_samples(struct ast_frame *frame)
+{
+ return frame->datalen;
+}
+
+static int none_length(unsigned int samples) {
+ return samples;
+}
+
+static struct ast_codec none = {
+ .name = "none",
+ .description = "<Null> codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000, /* This must have some sample rate to prevent divide by 0 */
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 20,
+ .samples_count = none_samples,
+ .get_length = none_length,
+};
+
+static int ulaw_samples(struct ast_frame *frame)
+{
+ return frame->datalen;
+}
+
+static int ulaw_length(unsigned int samples)
+{
+ return samples;
+}
+
+static struct ast_codec ulaw = {
+ .name = "ulaw",
+ .description = "G.711 u-law",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = ulaw_samples,
+ .get_length = ulaw_length,
+ .smooth = 1,
+};
+
+static struct ast_codec alaw = {
+ .name = "alaw",
+ .description = "G.711 a-law",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = ulaw_samples,
+ .get_length = ulaw_length,
+ .smooth = 1,
+};
+
+static int gsm_samples(struct ast_frame *frame)
+{
+ return 160 * (frame->datalen / 33);
+}
+
+static int gsm_length(unsigned int samples)
+{
+ return (samples / 160) * 33;
+}
+
+static struct ast_codec gsm = {
+ .name = "gsm",
+ .description = "GSM",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 20,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 33,
+ .samples_count = gsm_samples,
+ .get_length = gsm_length,
+ .smooth = 1,
+};
+
+static int g726_samples(struct ast_frame *frame)
+{
+ return frame->datalen * 2;
+}
+
+static int g726_length(unsigned int samples)
+{
+ return samples / 2;
+}
+
+static struct ast_codec g726rfc3551 = {
+ .name = "g726",
+ .description = "G.726 RFC3551",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 40,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static struct ast_codec g726aal2 = {
+ .name = "g726aal2",
+ .description = "G.726 AAL2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 40,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static struct ast_codec adpcm = {
+ .name = "adpcm",
+ .description = "Dialogic ADPCM",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 40,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static int slin_samples(struct ast_frame *frame)
+{
+ return frame->datalen / 2;
+}
+
+static int slin_length(unsigned int samples)
+{
+ return samples * 2;
+}
+
+static struct ast_codec slin8 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 160,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin12 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (12kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 12000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 240,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin16 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (16kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 320,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin24 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (24kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 24000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 480,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin32 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (32kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 640,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin44 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (44kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 44100,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 882,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin48 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (48kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 960,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin96 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (96kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 96000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 1920,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin192 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (192kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 192000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 3840,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static int lpc10_samples(struct ast_frame *frame)
+{
+ int samples = 22 * 8;
+
+ /* assumes that the RTP packet contains one LPC10 frame */
+ samples += (((char *)(frame->data.ptr))[7] & 0x1) * 8;
+
+ return samples;
+}
+
+static struct ast_codec lpc10 = {
+ .name = "lpc10",
+ .description = "LPC10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 20,
+ .maximum_ms = 20,
+ .default_ms = 20,
+ .minimum_bytes = 7,
+ .samples_count = lpc10_samples,
+ .smooth = 1,
+};
+
+static int g729_samples(struct ast_frame *frame)
+{
+ return frame->datalen * 8;
+}
+
+static int g729_length(unsigned int samples)
+{
+ return samples / 8;
+}
+
+static struct ast_codec g729a = {
+ .name = "g729",
+ .description = "G.729A",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 230,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = g729_samples,
+ .get_length = g729_length,
+ .smooth = 1,
+};
+
+static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
+{
+ int byte = bit / 8; /* byte containing first bit */
+ int rem = 8 - (bit % 8); /* remaining bits in first byte */
+ unsigned char ret = 0;
+
+ if (n <= 0 || n > 8)
+ return 0;
+
+ if (rem < n) {
+ ret = (data[byte] << (n - rem));
+ ret |= (data[byte + 1] >> (8 - n + rem));
+ } else {
+ ret = (data[byte] >> (rem - n));
+ }
+
+ return (ret & (0xff >> (8 - n)));
+}
+
+static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
+{
+ static const int SpeexWBSubModeSz[] = {
+ 4, 36, 112, 192,
+ 352, 0, 0, 0 };
+ int off = bit;
+ unsigned char c;
+
+ /* skip up to two wideband frames */
+ if (((len * 8 - off) >= 5) &&
+ get_n_bits_at(data, 1, off)) {
+ c = get_n_bits_at(data, 3, off + 1);
+ off += SpeexWBSubModeSz[c];
+
+ if (((len * 8 - off) >= 5) &&
+ get_n_bits_at(data, 1, off)) {
+ c = get_n_bits_at(data, 3, off + 1);
+ off += SpeexWBSubModeSz[c];
+
+ if (((len * 8 - off) >= 5) &&
+ get_n_bits_at(data, 1, off)) {
+ ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
+ return -1;
+ }
+ }
+
+ }
+ return off - bit;
+}
+
+static int speex_samples(unsigned char *data, int len)
+{
+ static const int SpeexSubModeSz[] = {
+ 5, 43, 119, 160,
+ 220, 300, 364, 492,
+ 79, 0, 0, 0,
+ 0, 0, 0, 0 };
+ static const int SpeexInBandSz[] = {
+ 1, 1, 4, 4,
+ 4, 4, 4, 4,
+ 8, 8, 16, 16,
+ 32, 32, 64, 64 };
+ int bit = 0;
+ int cnt = 0;
+ int off;
+ unsigned char c;
+
+ while ((len * 8 - bit) >= 5) {
+ /* skip wideband frames */
+ off = speex_get_wb_sz_at(data, len, bit);
+ if (off < 0) {
+ ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
+ break;
+ }
+ bit += off;
+
+ if ((len * 8 - bit) < 5)
+ break;
+
+ /* get control bits */
+ c = get_n_bits_at(data, 5, bit);
+ bit += 5;
+
+ if (c == 15) {
+ /* terminator */
+ break;
+ } else if (c == 14) {
+ /* in-band signal; next 4 bits contain signal id */
+ c = get_n_bits_at(data, 4, bit);
+ bit += 4;
+ bit += SpeexInBandSz[c];
+ } else if (c == 13) {
+ /* user in-band; next 4 bits contain msg len */
+ c = get_n_bits_at(data, 4, bit);
+ bit += 4;
+ /* after which it's 5-bit signal id + c bytes of data */
+ bit += 5 + c * 8;
+ } else if (c > 8) {
+ /* unknown */
+ ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
+ break;
+ } else {
+ /* skip number bits for submode (less the 5 control bits) */
+ bit += SpeexSubModeSz[c] - 5;
+ cnt += 160; /* new frame */
+ }
+ }
+ return cnt;
+}
+
+static int speex8_samples(struct ast_frame *frame)
+{
+ return speex_samples(frame->data.ptr, frame->datalen);
+}
+
+static struct ast_codec speex8 = {
+ .name = "speex",
+ .description = "SpeeX",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = speex8_samples,
+};
+
+static int speex16_samples(struct ast_frame *frame)
+{
+ return 2 * speex_samples(frame->data.ptr, frame->datalen);
+}
+
+static struct ast_codec speex16 = {
+ .name = "speex",
+ .description = "SpeeX 16khz",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 10,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = speex16_samples,
+};
+
+static int speex32_samples(struct ast_frame *frame)
+{
+ return 4 * speex_samples(frame->data.ptr, frame->datalen);
+}
+
+static struct ast_codec speex32 = {
+ .name = "speex",
+ .description = "SpeeX 32khz",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ .minimum_ms = 10,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = speex32_samples,
+};
+
+static int ilbc_samples(struct ast_frame *frame)
+{
+ return 240 * (frame->datalen / 50);
+}
+
+static struct ast_codec ilbc = {
+ .name = "ilbc",
+ .description = "iLBC",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 30,
+ .maximum_ms = 30,
+ .default_ms = 30,
+ .minimum_bytes = 50,
+ .samples_count = ilbc_samples,
+ .smooth = 1,
+};
+
+static struct ast_codec g722 = {
+ .name = "g722",
+ .description = "G722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static int siren7_samples(struct ast_frame *frame)
+{
+ return frame->datalen * (16000 / 4000);
+}
+
+static int siren7_length(unsigned int samples)
+{
+ return samples / (16000 / 4000);
+}
+
+static struct ast_codec siren7 = {
+ .name = "siren7",
+ .description = "ITU G.722.1 (Siren7, licensed from Polycom)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 20,
+ .maximum_ms = 80,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = siren7_samples,
+ .get_length = siren7_length,
+};
+
+static int siren14_samples(struct ast_frame *frame)
+{
+ return (int) frame->datalen * ((float) 32000 / 6000);
+}
+
+static int siren14_length(unsigned int samples)
+{
+ return (int) samples / ((float) 32000 / 6000);;
+}
+
+static struct ast_codec siren14 = {
+ .name = "siren14",
+ .description = "ITU G.722.1 Annex C, (Siren14, licensed from Polycom)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ .minimum_ms = 20,
+ .maximum_ms = 80,
+ .default_ms = 20,
+ .minimum_bytes = 120,
+ .samples_count = siren14_samples,
+ .get_length = siren14_length,
+};
+
+static struct ast_codec testlaw = {
+ .name = "testlaw",
+ .description = "G.711 test-law",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = ulaw_samples,
+ .get_length = ulaw_length,
+ .smooth = 1,
+};
+
+static int g719_samples(struct ast_frame *frame)
+{
+ return (int) frame->datalen * ((float) 48000 / 8000);
+}
+
+static int g719_length(unsigned int samples)
+{
+ return (int) samples / ((float) 48000 / 8000);
+}
+
+static struct ast_codec g719 = {
+ .name = "g719",
+ .description = "ITU G.719",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ .minimum_ms = 20,
+ .maximum_ms = 80,
+ .default_ms = 20,
+ .minimum_bytes = 160,
+ .samples_count = g719_samples,
+ .get_length = g719_length,
+};
+
+static struct ast_codec opus = {
+ .name = "opus",
+ .description = "Opus Codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ .minimum_ms = 20,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+};
+
+static struct ast_codec jpeg = {
+ .name = "jpeg",
+ .description = "JPEG image",
+ .type = AST_MEDIA_TYPE_IMAGE,
+};
+
+static struct ast_codec png = {
+ .name = "png",
+ .description = "PNG Image",
+ .type = AST_MEDIA_TYPE_IMAGE,
+};
+
+static struct ast_codec h261 = {
+ .name = "h261",
+ .description = "H.261 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec h263 = {
+ .name = "h263",
+ .description = "H.263 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec h263p = {
+ .name = "h263p",
+ .description = "H.263+ video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec h264 = {
+ .name = "h264",
+ .description = "H.264 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec mpeg4 = {
+ .name = "mpeg4",
+ .description = "MPEG4 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec vp8 = {
+ .name = "vp8",
+ .description = "VP8 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec t140red = {
+ .name = "red",
+ .description = "T.140 Realtime Text with redundancy",
+ .type = AST_MEDIA_TYPE_TEXT,
+};
+
+static struct ast_codec t140 = {
+ .name = "t140",
+ .description = "Passthrough T.140 Realtime Text",
+ .type = AST_MEDIA_TYPE_TEXT,
+};
+
+#define CODEC_REGISTER_AND_CACHE(codec) \
+ ({ \
+ int __res_ ## __LINE__ = 0; \
+ struct ast_format *__fmt_ ## __LINE__; \
+ struct ast_codec *__codec_ ## __LINE__; \
+ res |= __ast_codec_register(&(codec), NULL); \
+ __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
+ __fmt_ ## __LINE__ = ast_format_create(__codec_ ## __LINE__); \
+ res |= ast_format_cache_set(__fmt_ ## __LINE__); \
+ ao2_ref(__fmt_ ## __LINE__, -1); \
+ ao2_ref(__codec_ ## __LINE__, -1); \
+ __res_ ## __LINE__; \
+ })
+
+#define CODEC_REGISTER_AND_CACHE_NAMED(format_name, codec) \
+ ({ \
+ int __res_ ## __LINE__ = 0; \
+ struct ast_format *__fmt_ ## __LINE__; \
+ struct ast_codec *__codec_ ## __LINE__; \
+ res |= __ast_codec_register(&(codec), NULL); \
+ __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
+ __fmt_ ## __LINE__ = ast_format_create_named((format_name), __codec_ ## __LINE__); \
+ res |= ast_format_cache_set(__fmt_ ## __LINE__); \
+ ao2_ref(__fmt_ ## __LINE__, -1); \
+ ao2_ref(__codec_ ## __LINE__, -1); \
+ __res_ ## __LINE__; \
+ })
+
+int ast_codec_builtin_init(void)
+{
+ int res = 0;
+
+ res |= CODEC_REGISTER_AND_CACHE(g723);
+ res |= CODEC_REGISTER_AND_CACHE(ulaw);
+ res |= CODEC_REGISTER_AND_CACHE(alaw);
+ res |= CODEC_REGISTER_AND_CACHE(gsm);
+ res |= CODEC_REGISTER_AND_CACHE(g726rfc3551);
+ res |= CODEC_REGISTER_AND_CACHE(g726aal2);
+ res |= CODEC_REGISTER_AND_CACHE(adpcm);
+ res |= CODEC_REGISTER_AND_CACHE(slin8);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin12", slin12);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin16", slin16);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin24", slin24);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin32", slin32);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin44", slin44);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin48", slin48);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin96", slin96);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin192", slin192);
+ res |= CODEC_REGISTER_AND_CACHE(lpc10);
+ res |= CODEC_REGISTER_AND_CACHE(g729a);
+ res |= CODEC_REGISTER_AND_CACHE(speex8);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("speex16", speex16);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("speex32", speex32);
+ res |= CODEC_REGISTER_AND_CACHE(ilbc);
+ res |= CODEC_REGISTER_AND_CACHE(g722);
+ res |= CODEC_REGISTER_AND_CACHE(siren7);
+ res |= CODEC_REGISTER_AND_CACHE(siren14);
+ res |= CODEC_REGISTER_AND_CACHE(testlaw);
+ res |= CODEC_REGISTER_AND_CACHE(g719);
+ res |= CODEC_REGISTER_AND_CACHE(opus);
+ res |= CODEC_REGISTER_AND_CACHE(jpeg);
+ res |= CODEC_REGISTER_AND_CACHE(png);
+ res |= CODEC_REGISTER_AND_CACHE(h261);
+ res |= CODEC_REGISTER_AND_CACHE(h263);
+ res |= CODEC_REGISTER_AND_CACHE(h263p);
+ res |= CODEC_REGISTER_AND_CACHE(h264);
+ res |= CODEC_REGISTER_AND_CACHE(mpeg4);
+ res |= CODEC_REGISTER_AND_CACHE(vp8);
+ res |= CODEC_REGISTER_AND_CACHE(t140red);
+ res |= CODEC_REGISTER_AND_CACHE(t140);
+ res |= CODEC_REGISTER_AND_CACHE(none);
+
+ return res;
+}
diff --git a/main/config_options.c b/main/config_options.c
index ae40c6289..c86db0247 100644
--- a/main/config_options.c
+++ b/main/config_options.c
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/xmldoc.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
+#include "asterisk/format_cap.h"
#ifdef LOW_MEMORY
#define CONFIG_OPT_BUCKETS 5
@@ -1377,9 +1378,8 @@ static int acl_handler_fn(const struct aco_option *opt, struct ast_variable *var
* enum aco_option_type in config_options.h
*/
static int codec_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
- struct ast_codec_pref *pref = (struct ast_codec_pref *)(obj + opt->args[0]);
- struct ast_format_cap **cap = (struct ast_format_cap **)(obj + opt->args[1]);
- return ast_parse_allow_disallow(pref, *cap, var->value, opt->flags);
+ struct ast_format_cap **cap = (struct ast_format_cap **)(obj + opt->args[0]);
+ return ast_format_cap_update_by_allow_disallow(*cap, var->value, opt->flags);
}
/*! \brief Default option handler for stringfields
diff --git a/main/core_local.c b/main/core_local.c
index e803f29ec..e1b66d0a7 100644
--- a/main/core_local.c
+++ b/main/core_local.c
@@ -1008,7 +1008,8 @@ static void local_shutdown(void)
ao2_ref(locals, -1);
locals = NULL;
- ast_format_cap_destroy(local_tech.capabilities);
+ ao2_cleanup(local_tech.capabilities);
+ local_tech.capabilities = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
@@ -1030,14 +1031,15 @@ int ast_local_init(void)
return -1;
}
- if (!(local_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(local_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return -1;
}
- ast_format_cap_add_all(local_tech.capabilities);
+ ast_format_cap_append_by_type(local_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb);
if (!locals) {
- ast_format_cap_destroy(local_tech.capabilities);
+ ao2_cleanup(local_tech.capabilities);
+ local_tech.capabilities = NULL;
return -1;
}
@@ -1045,7 +1047,8 @@ int ast_local_init(void)
if (ast_channel_register(&local_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
ao2_ref(locals, -1);
- ast_format_cap_destroy(local_tech.capabilities);
+ ao2_cleanup(local_tech.capabilities);
+ local_tech.capabilities = NULL;
return -1;
}
ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local));
diff --git a/main/core_unreal.c b/main/core_unreal.c
index c9afa5194..a1ae897b9 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -859,7 +859,8 @@ void ast_unreal_destructor(void *vdoomed)
{
struct ast_unreal_pvt *doomed = vdoomed;
- doomed->reqcap = ast_format_cap_destroy(doomed->reqcap);
+ ao2_cleanup(doomed->reqcap);
+ doomed->reqcap = NULL;
}
struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
@@ -878,11 +879,13 @@ struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructo
if (!unreal) {
return NULL;
}
- unreal->reqcap = ast_format_cap_dup(cap);
+
+ unreal->reqcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!unreal->reqcap) {
ao2_ref(unreal, -1);
return NULL;
}
+ ast_format_cap_append_from_cap(unreal->reqcap, cap, AST_MEDIA_TYPE_UNKNOWN);
memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
@@ -896,7 +899,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
{
struct ast_channel *owner;
struct ast_channel *chan;
- struct ast_format fmt;
+ RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
struct ast_assigned_ids id1 = {NULL, NULL};
struct ast_assigned_ids id2 = {NULL, NULL};
int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
@@ -940,14 +943,22 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
ao2_ref(p, +1);
ast_channel_tech_pvt_set(owner, p);
- ast_format_cap_copy(ast_channel_nativeformats(owner), p->reqcap);
+ ast_channel_nativeformats_set(owner, p->reqcap);
/* Determine our read/write format and set it on each channel */
- ast_best_codec(p->reqcap, &fmt);
- ast_format_copy(ast_channel_writeformat(owner), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(owner), &fmt);
- ast_format_copy(ast_channel_readformat(owner), &fmt);
- ast_format_copy(ast_channel_rawreadformat(owner), &fmt);
+ fmt = ast_format_cap_get_format(p->reqcap, 0);
+ if (!fmt) {
+ ast_channel_tech_pvt_set(owner, NULL);
+ ao2_ref(p, -1);
+ ast_channel_unlock(owner);
+ ast_channel_release(owner);
+ return NULL;
+ }
+
+ ast_channel_set_writeformat(owner, fmt);
+ ast_channel_set_rawwriteformat(owner, fmt);
+ ast_channel_set_readformat(owner, fmt);
+ ast_channel_set_rawreadformat(owner, fmt);
ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE);
@@ -955,6 +966,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
if (ast_channel_cc_params_init(owner, requestor
? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
+ ast_channel_tech_pvt_set(owner, NULL);
ao2_ref(p, -1);
ast_channel_tech_pvt_set(owner, NULL);
ast_channel_unlock(owner);
@@ -970,6 +982,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
"%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno);
if (!chan) {
ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
+ ast_channel_tech_pvt_set(owner, NULL);
ao2_ref(p, -1);
ast_channel_tech_pvt_set(owner, NULL);
ast_channel_release(owner);
@@ -984,13 +997,13 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
ao2_ref(p, +1);
ast_channel_tech_pvt_set(chan, p);
- ast_format_cap_copy(ast_channel_nativeformats(chan), p->reqcap);
+ ast_channel_nativeformats_set(chan, p->reqcap);
/* Format was already determined when setting up owner */
- ast_format_copy(ast_channel_writeformat(chan), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
- ast_format_copy(ast_channel_readformat(chan), &fmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
+ ast_channel_set_writeformat(chan, fmt);
+ ast_channel_set_rawwriteformat(chan, fmt);
+ ast_channel_set_readformat(chan, fmt);
+ ast_channel_set_rawreadformat(chan, fmt);
ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE);
diff --git a/main/data.c b/main/data.c
index 092d7aad5..746c52dfd 100644
--- a/main/data.c
+++ b/main/data.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/manager.h"
#include "asterisk/test.h"
#include "asterisk/frame.h"
+#include "asterisk/codec.h"
/*** DOCUMENTATION
<manager name="DataGet" language="en_US">
@@ -3097,62 +3098,69 @@ static int manager_data_get(struct mansession *s, const struct message *m)
return RESULT_SUCCESS;
}
+static int data_add_codec(struct ast_data *codecs, struct ast_format *format) {
+ struct ast_data *codec;
+ struct ast_codec *tmp;
+
+ tmp = ast_codec_get_by_id(ast_format_get_codec_id(format));
+ if (!tmp) {
+ return -1;
+ }
+
+ codec = ast_data_add_node(codecs, "codec");
+ if (!codec) {
+ ao2_ref(tmp, -1);
+ return -1;
+ }
+
+ ast_data_add_str(codec, "name", tmp->name);
+ ast_data_add_int(codec, "samplespersecond", tmp->sample_rate);
+ ast_data_add_str(codec, "description", tmp->description);
+ ast_data_add_int(codec, "frame_length", tmp->minimum_bytes);
+ ao2_ref(tmp, -1);
+
+ return 0;
+}
+
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;
- const struct ast_format_list *fmlist;
- int x;
+ struct ast_data *codecs;
codecs = ast_data_add_node(root, node_name);
if (!codecs) {
return -1;
}
- fmlist = ast_format_list_get(&fmlist_size);
- for (x = 0; x < fmlist_size; x++) {
- if (ast_format_cmp(&fmlist[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- codec = ast_data_add_node(codecs, "codec");
- if (!codec) {
- ast_format_list_destroy(fmlist);
- 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);
- }
- }
- ast_format_list_destroy(fmlist);
- return 0;
+ return data_add_codec(codecs, format);
}
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;
- int x;
+ struct ast_data *codecs;
+ size_t i;
+ size_t count;
codecs = ast_data_add_node(root, node_name);
if (!codecs) {
return -1;
}
- fmlist = ast_format_list_get(&fmlist_size);
- for (x = 0; x < fmlist_size; x++) {
- if (ast_format_cap_iscompatible(cap, &fmlist[x].format)) {
- codec = ast_data_add_node(codecs, "codec");
- if (!codec) {
- ast_format_list_destroy(fmlist);
- 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);
+
+ count = ast_format_cap_count(cap);
+ for (i = 1; i <= count; ++i) {
+ struct ast_format *fmt;
+
+ fmt = ast_format_cap_get_format(cap, i);
+ if (!fmt) {
+ return -1;
}
+
+ if (data_add_codec(codecs, fmt)) {
+ ao2_ref(fmt, -1);
+ return -1;
+ }
+
+ ao2_ref(fmt, -1);
}
- ast_format_list_destroy(fmlist);
return 0;
}
diff --git a/main/dial.c b/main/dial.c
index f03d43d25..0955aad04 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -300,23 +300,23 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
/* Copy device string over */
ast_copy_string(numsubst, channel->device, sizeof(numsubst));
- if (!ast_format_cap_is_empty(cap)) {
+ if (ast_format_cap_count(cap)) {
cap_request = cap;
} else if (chan) {
cap_request = ast_channel_nativeformats(chan);
} else {
- cap_all_audio = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- ast_format_cap_add_all_by_type(cap_all_audio, AST_FORMAT_TYPE_AUDIO);
+ cap_all_audio = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_append_by_type(cap_all_audio, AST_MEDIA_TYPE_AUDIO);
cap_request = cap_all_audio;
}
/* If we fail to create our owner channel bail out */
if (!(channel->owner = ast_request(channel->tech, cap_request, &assignedids, chan, numsubst, &channel->cause))) {
- cap_all_audio = ast_format_cap_destroy(cap_all_audio);
+ ao2_cleanup(cap_all_audio);
return -1;
}
cap_request = NULL;
- cap_all_audio = ast_format_cap_destroy(cap_all_audio);
+ ao2_cleanup(cap_all_audio);
ast_channel_lock(channel->owner);
ast_channel_stage_snapshot(channel->owner);
diff --git a/main/dsp.c b/main/dsp.c
index 747ff28e5..3a5d1221a 100644
--- a/main/dsp.c
+++ b/main/dsp.c
@@ -60,6 +60,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <math.h>
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
@@ -1183,7 +1184,7 @@ int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
return 0;
}
- if (!ast_format_is_slinear(&inf->subclass.format)) {
+ if (!ast_format_cache_is_slinear(inf->subclass.format)) {
ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
return 0;
}
@@ -1408,30 +1409,29 @@ static int ast_dsp_silence_noise_with_energy(struct ast_dsp *dsp, struct ast_fra
ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
return 0;
}
- if (!ast_format_is_slinear(&f->subclass.format)) {
+
+ if (ast_format_cache_is_slinear(f->subclass.format)) {
+ s = f->data.ptr;
+ len = f->datalen/2;
+ } else {
odata = f->data.ptr;
len = f->datalen;
- switch (f->subclass.format.id) {
- case AST_FORMAT_ULAW:
- s = ast_alloca(len * 2);
- for (x = 0; x < len; x++) {
- s[x] = AST_MULAW(odata[x]);
- }
- break;
- case AST_FORMAT_ALAW:
- s = ast_alloca(len * 2);
- for (x = 0; x < len; x++) {
- s[x] = AST_ALAW(odata[x]);
- }
- break;
- default:
- ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames :(\n");
+ if (ast_format_cmp(f->subclass.format, ast_format_ulaw)) {
+ s = ast_alloca(len * 2);
+ for (x = 0; x < len; x++) {
+ s[x] = AST_MULAW(odata[x]);
+ }
+ } else if (ast_format_cmp(f->subclass.format, ast_format_alaw)) {
+ s = ast_alloca(len * 2);
+ for (x = 0; x < len; x++) {
+ s[x] = AST_ALAW(odata[x]);
+ }
+ } else {
+ ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames :(\n");
return 0;
}
- } else {
- s = f->data.ptr;
- len = f->datalen/2;
}
+
if (noise) {
return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
} else {
@@ -1476,31 +1476,26 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
odata = af->data.ptr;
len = af->datalen;
/* Make sure we have short data */
- if (ast_format_is_slinear(&af->subclass.format)) {
+ if (ast_format_cache_is_slinear(af->subclass.format)) {
shortdata = af->data.ptr;
len = af->datalen / 2;
+ } else if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+ shortdata = ast_alloca(af->datalen * 2);
+ for (x = 0; x < len; x++) {
+ shortdata[x] = AST_MULAW(odata[x]);
+ }
+ } else if (ast_format_cmp(af->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
+ shortdata = ast_alloca(af->datalen * 2);
+ for (x = 0; x < len; x++) {
+ shortdata[x] = AST_ALAW(odata[x]);
+ }
} else {
- switch (af->subclass.format.id) {
- case AST_FORMAT_ULAW:
- case AST_FORMAT_TESTLAW:
- shortdata = ast_alloca(af->datalen * 2);
- for (x = 0; x < len; x++) {
- shortdata[x] = AST_MULAW(odata[x]);
- }
- break;
- case AST_FORMAT_ALAW:
- shortdata = ast_alloca(af->datalen * 2);
- for (x = 0; x < len; x++) {
- shortdata[x] = AST_ALAW(odata[x]);
- }
- break;
- 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.format));
- dsp->display_inband_dtmf_warning = 0;
- return af;
+ /*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_format_get_name(af->subclass.format));
}
+ dsp->display_inband_dtmf_warning = 0;
+ return af;
}
/* Initially we do not want to mute anything */
@@ -1629,19 +1624,14 @@ done:
memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
}
- switch (af->subclass.format.id) {
- case AST_FORMAT_ULAW:
+ if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
for (x = 0; x < len; x++) {
odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
}
- break;
- case AST_FORMAT_ALAW:
+ } else if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
for (x = 0; x < len; x++) {
odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
}
- /* fall through */
- default:
- break;
}
if (outf) {
diff --git a/main/file.c b/main/file.c
index df67fbf43..fa4c63bd9 100644
--- a/main/file.c
+++ b/main/file.c
@@ -189,8 +189,8 @@ int ast_stopstream(struct ast_channel *tmp)
if (ast_channel_stream(tmp)) {
ast_closestream(ast_channel_stream(tmp));
ast_channel_stream_set(tmp, NULL);
- if (ast_channel_oldwriteformat(tmp)->id && ast_set_write_format(tmp, ast_channel_oldwriteformat(tmp)))
- ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_getformatname(ast_channel_oldwriteformat(tmp)));
+ if (ast_channel_oldwriteformat(tmp) && ast_set_write_format(tmp, ast_channel_oldwriteformat(tmp)))
+ ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_format_get_name(ast_channel_oldwriteformat(tmp)));
}
/* Stop the video stream too */
if (ast_channel_vstream(tmp) != NULL) {
@@ -207,10 +207,10 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
{
int res = -1;
if (f->frametype == AST_FRAME_VIDEO) {
- if (AST_FORMAT_GET_TYPE(fs->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) {
+ if (ast_format_get_type(fs->fmt->format) == AST_MEDIA_TYPE_AUDIO) {
/* This is the audio portion. Call the video one... */
if (!fs->vfs && fs->filename) {
- const char *type = ast_getformatname(&f->subclass.format);
+ const char *type = ast_format_get_name(f->subclass.format);
fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
ast_debug(1, "Opened video output file\n");
}
@@ -223,7 +223,7 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
return -1;
}
- if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) != AST_FORMAT_CMP_NOT_EQUAL) {
+ 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");
@@ -232,18 +232,19 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
} else {
/* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
the one we've setup a translator for, we do the "wrong thing" XXX */
- if (fs->trans && (ast_format_cmp(&f->subclass.format, &fs->lastwriteformat) != AST_FORMAT_CMP_EQUAL)) {
+ 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.format);
- if (!fs->trans)
+ if (!fs->trans) {
+ 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.format));
- else {
+ fs->fmt->name, ast_format_get_name(f->subclass.format));
+ } else {
struct ast_frame *trf;
- ast_format_copy(&fs->lastwriteformat, &f->subclass.format);
+ ao2_replace(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;
@@ -349,7 +350,7 @@ static int exts_compare(const char *exts, const char *type)
*/
static void filestream_close(struct ast_filestream *f)
{
- enum ast_format_type format_type = AST_FORMAT_GET_TYPE(f->fmt->format.id);
+ enum ast_media_type format_type = ast_format_get_type(f->fmt->format);
if (!f->owner) {
return;
@@ -358,12 +359,12 @@ static void filestream_close(struct ast_filestream *f)
/* Stop a running stream if there is one */
switch (format_type)
{
- case AST_FORMAT_TYPE_AUDIO:
+ case AST_MEDIA_TYPE_AUDIO:
ast_channel_stream_set(f->owner, NULL);
AST_SCHED_DEL_ACCESSOR(ast_channel_sched(f->owner), f->owner, ast_channel_streamid, ast_channel_streamid_set);
ast_settimeout(f->owner, 0, NULL, NULL);
break;
- case AST_FORMAT_TYPE_VIDEO:
+ case AST_MEDIA_TYPE_VIDEO:
ast_channel_vstream_set(f->owner, NULL);
AST_SCHED_DEL_ACCESSOR(ast_channel_sched(f->owner), f->owner, ast_channel_vstreamid, ast_channel_vstreamid_set);
break;
@@ -418,6 +419,8 @@ static void filestream_destructor(void *arg)
}
if (f->orig_chan_name)
free((void *) f->orig_chan_name);
+ ao2_cleanup(f->lastwriteformat);
+ ao2_cleanup(f->fr.subclass.format);
ast_module_unref(f->fmt->module);
}
@@ -436,6 +439,15 @@ static struct ast_filestream *get_filestream(struct ast_format_def *fmt, FILE *b
if (fmt->buf_size)
s->buf = (char *)(s + 1);
s->fr.src = fmt->name;
+
+ if (ast_format_get_type(fmt->format) == AST_MEDIA_TYPE_AUDIO) {
+ s->fr.frametype = AST_FRAME_VOICE;
+ } else if (ast_format_get_type(fmt->format) == AST_MEDIA_TYPE_VIDEO) {
+ s->fr.frametype = AST_FRAME_VIDEO;
+ }
+ s->fr.mallocd = 0;
+ s->fr.subclass.format = ao2_bump(fmt->format);
+
return s;
}
@@ -529,9 +541,9 @@ static int filehelper(const char *filename, const void *arg2, const char *fmt, c
FILE *bfile;
struct ast_filestream *s;
- if ((ast_format_cmp(ast_channel_writeformat(chan), &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))) {
+ if ((ast_format_cmp(ast_channel_writeformat(chan), f->format) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ !(((ast_format_get_type(f->format) == AST_MEDIA_TYPE_AUDIO) && fmt) ||
+ ((ast_format_get_type(f->format) == AST_MEDIA_TYPE_VIDEO) && fmt))) {
ast_free(fn);
continue; /* not a supported format */
}
@@ -559,7 +571,7 @@ static int filehelper(const char *filename, const void *arg2, const char *fmt, c
s->fmt = f;
s->trans = NULL;
s->filename = NULL;
- if (AST_FORMAT_GET_TYPE(s->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) {
+ if (ast_format_get_type(s->fmt->format) == AST_MEDIA_TYPE_AUDIO) {
if (ast_channel_stream(chan))
ast_closestream(ast_channel_stream(chan));
ast_channel_stream_set(chan, s);
@@ -579,7 +591,7 @@ static int filehelper(const char *filename, const void *arg2, const char *fmt, c
/* 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);
+ ast_format_cap_append((struct ast_format_cap *) arg2, f->format, 0);
}
res = 1; /* file does exist and format it exists in is returned in arg2 */
break;
@@ -749,23 +761,23 @@ struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char
buflen = strlen(preflang) + strlen(filename) + 4;
buf = ast_alloca(buflen);
- if (!(file_fmt_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(file_fmt_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
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_format_cap_has_type(file_fmt_cap, AST_MEDIA_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);
+ ao2_ref(file_fmt_cap, -1);
return NULL;
}
/* Set the channel to a format we can work with and save off the previous format. */
- ast_format_copy(ast_channel_oldwriteformat(chan), ast_channel_writeformat(chan));
+ ast_channel_set_oldwriteformat(chan, ast_channel_writeformat(chan));
/* 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);
+ ao2_ref(file_fmt_cap, -1);
if (res == -1) { /* No format available that works with this channel */
return NULL;
@@ -781,50 +793,50 @@ struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *fil
/* As above, but for video. But here we don't have translators
* so we must enforce a format.
*/
- struct ast_format tmp_fmt;
struct ast_format_cap *tmp_cap;
char *buf;
int buflen;
- const char *fmt;
- int fd;
+ int i, fd;
- if (preflang == NULL)
+ if (preflang == NULL) {
preflang = "";
+ }
buflen = strlen(preflang) + strlen(filename) + 4;
buf = ast_alloca(buflen);
/* is the channel capable of video without translation ?*/
- if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO)) {
+ if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO)) {
return NULL;
}
- if (!(tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
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);
+ ao2_ref(tmp_cap, -1);
return NULL;
}
/* 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(ast_channel_nativeformats(chan), &tmp_fmt)) {
+ for (i = 0; i < ast_format_cap_count(tmp_cap); ++i) {
+ struct ast_format *format = ast_format_cap_get_format(tmp_cap, i);
+
+ if ((ast_format_get_type(format) != AST_MEDIA_TYPE_VIDEO) ||
+ !ast_format_cap_iscompatible(ast_channel_nativeformats(chan), tmp_cap)) {
+ ao2_ref(format, -1);
continue;
}
- fd = filehelper(buf, chan, fmt, ACTION_OPEN);
+ fd = filehelper(buf, chan, ast_format_get_name(format), ACTION_OPEN);
if (fd >= 0) {
- ast_format_cap_iter_end(tmp_cap);
- tmp_cap = ast_format_cap_destroy(tmp_cap);
+ ao2_ref(format, -1);
+ ao2_ref(tmp_cap, -1);
return ast_channel_vstream(chan);
}
ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(tmp_cap);
- tmp_cap = ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
return NULL;
}
@@ -897,14 +909,14 @@ static enum fsread_res ast_readaudio_callback(struct ast_filestream *s)
if (whennext != s->lasttimeout) {
if (ast_channel_timingfd(s->owner) > -1) {
- float samp_rate = (float) ast_format_rate(&s->fmt->format);
+ float samp_rate = (float) ast_format_get_sample_rate(s->fmt->format);
unsigned int rate;
rate = (unsigned int) roundf(samp_rate / ((float) whennext));
ast_settimeout_full(s->owner, rate, ast_fsread_audio, s, 1);
} else {
- ast_channel_streamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_rate(&s->fmt->format) / 1000), ast_fsread_audio, s));
+ ast_channel_streamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_get_sample_rate(s->fmt->format) / 1000), ast_fsread_audio, s));
}
s->lasttimeout = whennext;
return FSREAD_SUCCESS_NOSCHED;
@@ -954,7 +966,7 @@ static enum fsread_res ast_readvideo_callback(struct ast_filestream *s)
}
if (whennext != s->lasttimeout) {
- ast_channel_vstreamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_rate(&s->fmt->format) / 1000), ast_fsread_video, s));
+ ast_channel_vstreamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_get_sample_rate(s->fmt->format) / 1000), ast_fsread_video, s));
s->lasttimeout = whennext;
return FSREAD_SUCCESS_NOSCHED;
}
@@ -985,7 +997,7 @@ int ast_playstream(struct ast_filestream *s)
{
enum fsread_res res;
- if (AST_FORMAT_GET_TYPE(s->fmt->format.id) == AST_FORMAT_TYPE_AUDIO)
+ if (ast_format_get_type(s->fmt->format) == AST_MEDIA_TYPE_AUDIO)
res = ast_readaudio_callback(s);
else
res = ast_readvideo_callback(s);
@@ -1067,14 +1079,15 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p
{
struct ast_filestream *fs;
struct ast_filestream *vfs=NULL;
- char fmt[256];
off_t pos;
int seekattempt;
int res;
fs = ast_openstream(chan, filename, preflang);
if (!fs) {
- ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), ast_channel_nativeformats(chan)), strerror(errno));
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n",
+ filename, ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf), strerror(errno));
return -1;
}
@@ -1096,7 +1109,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p
vfs = ast_openvstream(chan, filename, preflang);
if (vfs) {
- ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(&vfs->fmt->format));
+ ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_format_get_name(vfs->fmt->format));
}
if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_MASQ_NOSTREAM))
@@ -1108,7 +1121,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p
res = ast_playstream(fs);
if (!res && vfs)
res = ast_playstream(vfs);
- ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), filename, ast_getformatname(ast_channel_writeformat(chan)), preflang ? preflang : "default");
+ ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), filename, ast_format_get_name(ast_channel_writeformat(chan)), preflang ? preflang : "default");
return res;
}
@@ -1330,7 +1343,7 @@ static void waitstream_control(struct ast_channel *c,
}
if (cb) {
- long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_rate(&ast_channel_stream(c)->fmt->format) / 1000);
+ long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_get_sample_rate(ast_channel_stream(c)->fmt->format) / 1000);
cb(c, ms_len, type);
}
@@ -1373,7 +1386,7 @@ static int waitstream_core(struct ast_channel *c,
orig_chan_name = ast_strdupa(ast_channel_name(c));
if (ast_channel_stream(c) && cb) {
- long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_rate(&ast_channel_stream(c)->fmt->format) / 1000);
+ long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_get_sample_rate(ast_channel_stream(c)->fmt->format) / 1000);
cb(c, ms_len, AST_WAITSTREAM_CB_START);
}
@@ -1722,7 +1735,7 @@ static char *handle_cli_core_show_file_formats(struct ast_cli_entry *e, int cmd,
AST_RWLIST_RDLOCK(&formats);
AST_RWLIST_TRAVERSE(&formats, f, list) {
- ast_cli(a->fd, FORMAT2, ast_getformatname(&f->format), f->name, f->exts);
+ ast_cli(a->fd, FORMAT2, ast_format_get_name(f->format), f->name, f->exts);
count_fmt++;
}
AST_RWLIST_UNLOCK(&formats);
@@ -1732,13 +1745,13 @@ static char *handle_cli_core_show_file_formats(struct ast_cli_entry *e, int cmd,
#undef FORMAT2
}
-const struct ast_format *ast_get_format_for_file_ext(const char *file_ext)
+struct ast_format *ast_get_format_for_file_ext(const char *file_ext)
{
struct ast_format_def *f;
SCOPED_RDLOCK(lock, &formats.lock);
AST_RWLIST_TRAVERSE(&formats, f, list) {
if (exts_compare(f->exts, file_ext)) {
- return &f->format;
+ return f->format;
}
}
diff --git a/main/format.c b/main/format.c
index c4ad45b7f..83206f28c 100644
--- a/main/format.c
+++ b/main/format.c
@@ -1,10 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
- * Mark Spencer <markster@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -17,12 +16,11 @@
* at the top of the source tree.
*/
-/*!
- * \file
- * \brief Format API
+/*! \file
*
- * \author David Vossel <dvossel@digium.com>
- * \author Mark Spencer <markster@digium.com>
+ * \brief Media Format API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
*/
/*** MODULEINFO
@@ -31,1420 +29,351 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#include "asterisk/_private.h"
+#include "asterisk/logger.h"
+#include "asterisk/codec.h"
#include "asterisk/format.h"
#include "asterisk/astobj2.h"
-#include "asterisk/lock.h"
-#include "asterisk/frame.h"
-#include "asterisk/utils.h"
-#include "asterisk/cli.h"
-#include "asterisk/rtp_engine.h"
-#include "asterisk/config.h"
-
-#define FORMAT_CONFIG "codecs.conf"
-
-/*!
- * \brief Container for all the format attribute interfaces.
- * \note This container uses RWLOCKs instead of MUTEX locks. .
- * \note An ao2 container was chosen for fast lookup.
- */
-static struct ao2_container *interfaces;
-
-/*! 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;
+#include "asterisk/strings.h"
+
+/*! \brief Number of buckets to use for format interfaces (should be prime for performance reasons) */
+#define FORMAT_INTERFACE_BUCKETS 53
+
+/*! \brief Definition of a media format */
+struct ast_format {
+ /*! Name of the format */
+ const char *name;
+ /*! \brief Pointer to the codec in use for this format */
+ struct ast_codec *codec;
+ /*! \brief Attribute specific data, implementation specific */
+ void *attribute_data;
+ /*! \brief Pointer to the optional format interface */
+ const struct ast_format_interface *interface;
};
-/*! \brief Format List container, This container is never directly accessed outside
- * of this file, and It only exists for building the format_list_array. */
-static struct ao2_container *format_list;
-/*! \brief Format List array is a read only array protected by a read write lock.
- * This array may be used outside this file with the use of reference counting to
- * guarantee safety for access by multiple threads. */
-static struct ast_format_list *format_list_array;
-static size_t format_list_array_len = 0;
-/*! \brief Locks the format list array so a reference can be taken safely. */
-static ast_rwlock_t format_list_array_lock;
-
-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;
-}
-
-void ast_format_copy(struct ast_format *dst, const struct ast_format *src)
-{
- *dst = *src;
-}
-
-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 tmp_wrapper = {
- .id = format->id,
- };
+/*! \brief Structure used when registering a format interface */
+struct format_interface {
+ /*! \brief Pointer to the format interface itself */
+ const struct ast_format_interface *interface;
+ /*! \brief Name of the codec the interface is for */
+ char codec[0];
+};
- return ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER);
-}
+/*! \brief Container for registered format interfaces */
+static struct ao2_container *interfaces;
-static int has_interface(const struct ast_format *format)
+static int format_interface_hash(const void *obj, int flags)
{
- struct interface_ao2_wrapper *wrapper;
+ const struct format_interface *format_interface;
+ const char *key;
- wrapper = find_interface(format);
- if (!wrapper) {
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_KEY:
+ key = obj;
+ return ast_str_hash(key);
+ case OBJ_SEARCH_OBJECT:
+ format_interface = obj;
+ return ast_str_hash(format_interface->codec);
+ default:
+ /* Hash can only work on something with a full key. */
+ ast_assert(0);
return 0;
}
- ao2_ref(wrapper, -1);
- return 1;
}
-int ast_format_sdp_parse(struct ast_format *format, const char *attributes)
+static int format_interface_cmp(void *obj, void *arg, int flags)
{
- struct interface_ao2_wrapper *wrapper;
- int res;
+ const struct format_interface *left = obj;
+ const struct format_interface *right = arg;
+ const char *right_key = arg;
+ int cmp;
- if (!(wrapper = find_interface(format))) {
- return 0;
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ cmp = strcmp(left->codec, right->codec);
+ break;
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left->codec, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left->codec, right_key, strlen(right_key));
+ break;
+ default:
+ ast_assert(0);
+ cmp = 0;
+ break;
}
-
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_sdp_parse) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ if (cmp) {
return 0;
}
- res = wrapper->interface->format_attr_sdp_parse(&format->fattr, attributes);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
-
- return res;
+ return CMP_MATCH;
}
-void ast_format_sdp_generate(const struct ast_format *format, unsigned int payload, struct ast_str **str)
+/*! \brief Function called when the process is shutting down */
+static void format_shutdown(void)
{
- struct interface_ao2_wrapper *wrapper;
-
- if (!(wrapper = find_interface(format))) {
- return;
- }
-
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_sdp_generate) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
- return;
- }
-
- wrapper->interface->format_attr_sdp_generate(&format->fattr, payload, str);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ ao2_cleanup(interfaces);
+ interfaces = NULL;
}
-/*! \internal
- * \brief set format attributes using an interface
- */
-static int format_set_helper(struct ast_format *format, va_list ap)
+int ast_format_init(void)
{
- struct interface_ao2_wrapper *wrapper;
-
- if (!(wrapper = find_interface(format))) {
- ast_log(LOG_WARNING, "Could not find format interface to set.\n");
- return -1;
- }
-
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_set) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, FORMAT_INTERFACE_BUCKETS, format_interface_hash,
+ format_interface_cmp);
+ if (!interfaces) {
return -1;
}
- wrapper->interface->format_attr_set(&format->fattr, ap);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ ast_register_atexit(format_shutdown);
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, ... )
+int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod)
{
- /* initialize the structure before setting it. */
- ast_format_clear(format);
-
- format->id = id;
+ SCOPED_AO2WRLOCK(lock, interfaces);
+ struct format_interface *format_interface;
- if (set_attributes) {
- va_list ap;
- va_start(ap, set_attributes);
- format_set_helper(format, ap);
- va_end(ap);
+ if (!interface->format_clone || !interface->format_destroy) {
+ ast_log(LOG_ERROR, "Format interface for codec '%s' does not implement required callbacks\n", codec);
+ return -1;
}
- 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(const 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))) {
+ format_interface = ao2_find(interfaces, codec, OBJ_SEARCH_KEY | OBJ_NOLOCK);
+ if (format_interface) {
+ ast_log(LOG_ERROR, "A format interface is already present for codec '%s'\n", codec);
+ ao2_ref(format_interface, -1);
return -1;
}
- ao2_rdlock(wrapper);
- if (!wrapper->interface ||
- !wrapper->interface->format_attr_set ||
- !wrapper->interface->format_attr_cmp) {
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ format_interface = ao2_alloc_options(sizeof(*format_interface) + strlen(codec) + 1,
+ NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!format_interface) {
return -1;
}
+ format_interface->interface = interface;
+ strcpy(format_interface->codec, codec); /* Safe */
- /* if isset is present, use that function, else just build a new
- * format and use the cmp function */
- if (wrapper->interface->format_attr_isset) {
- res = wrapper->interface->format_attr_isset(&format->fattr, ap);
- } else {
- 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);
- res = (res == AST_FORMAT_CMP_NOT_EQUAL) ? -1 : 0;
- }
+ ao2_link_flags(interfaces, format_interface, OBJ_NOLOCK);
+ ao2_ref(format_interface, -1);
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ ast_verb(2, "Registered format interface for codec '%s'\n", codec);
- return res;
+ return 0;
}
-int ast_format_isset(const struct ast_format *format, ... )
+void *ast_format_get_attribute_data(const struct ast_format *format)
{
- va_list ap;
- int res;
-
- va_start(ap, format);
- res = format_isset_helper(format, ap);
- va_end(ap);
- return res;
+ return format->attribute_data;
}
-int ast_format_get_value(const struct ast_format *format, int key, void *value)
+void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
{
- int res = 0;
- struct interface_ao2_wrapper *wrapper;
-
- if (!(wrapper = find_interface(format))) {
- return -1;
- }
- ao2_rdlock(wrapper);
- if (!wrapper->interface ||
- !wrapper->interface->format_attr_get_val) {
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
- return -1;
- }
-
- res = wrapper->interface->format_attr_get_val(&format->fattr, key, value);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
-
- return res;
+ format->attribute_data = attribute_data;
}
-/*! \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)
+/*! \brief Destructor for media formats */
+static void format_destroy(void *obj)
{
- enum ast_format_cmp_res res = AST_FORMAT_CMP_EQUAL;
- struct interface_ao2_wrapper *wrapper;
+ struct ast_format *format = obj;
- if (!(wrapper = find_interface(format1))) {
- return res;
+ if (format->interface) {
+ format->interface->format_destroy(format);
}
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_cmp) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
- return res;
- }
-
- res = wrapper->interface->format_attr_cmp(&format1->fattr, &format2->fattr);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
-
- return res;
+ ao2_cleanup(format->codec);
}
-enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
+struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
{
- if (format1->id != format2->id) {
- return AST_FORMAT_CMP_NOT_EQUAL;
- }
-
- return format_cmp_helper(format1, format2);
-}
+ struct ast_format *format;
+ struct format_interface *format_interface;
-/*! \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;
+ format = ao2_t_alloc_options(sizeof(*format), format_destroy,
+ AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
+ if (!format) {
+ return NULL;
}
+ format->name = format_name;
+ format->codec = ao2_bump(codec);
- ao2_rdlock(wrapper);
- if (wrapper->interface && wrapper->interface->format_attr_get_joint) {
- res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr);
+ format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
+ if (format_interface) {
+ format->interface = format_interface->interface;
+ ao2_ref(format_interface, -1);
}
- ao2_unlock(wrapper);
-
- ao2_ref(wrapper, -1);
- return res;
+ return format;
}
-int ast_format_joint(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result)
+struct ast_format *ast_format_clone(const struct ast_format *format)
{
- if (format1->id != format2->id) {
- return -1;
- }
- result->id = format1->id;
- return format_joint_helper(format1, format2, result);
-}
+ struct ast_format *cloned = ast_format_create_named(format->name, format->codec);
-
-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);
- /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
- case AST_FORMAT_OPUS:
- return (1ULL << 34);
- /*! 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);
- /*! VP8 Video */
- case AST_FORMAT_VP8:
- return (1ULL << 23);
-
- /*! 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);
- default:
- return 0; /* not supported by old bitfield. */
+ if (!cloned) {
+ return NULL;
}
- 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);
- /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
- case (1ULL << 34):
- return ast_format_set(dst, AST_FORMAT_OPUS, 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);
- /*! VP8 Video */
- case (1ULL << 23):
- return ast_format_set(dst, AST_FORMAT_VP8, 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);
+ if (cloned->interface && cloned->interface->format_clone(format, cloned)) {
+ ao2_ref(cloned, -1);
+ return NULL;
}
- 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;
+ return cloned;
}
-int ast_format_is_slinear(const struct ast_format *format)
+struct ast_format *ast_format_create(struct ast_codec *codec)
{
- if (format->id == AST_FORMAT_SLINEAR ||
- format->id == AST_FORMAT_SLINEAR12 ||
- format->id == AST_FORMAT_SLINEAR16 ||
- format->id == AST_FORMAT_SLINEAR24 ||
- format->id == AST_FORMAT_SLINEAR32 ||
- format->id == AST_FORMAT_SLINEAR44 ||
- format->id == AST_FORMAT_SLINEAR48 ||
- format->id == AST_FORMAT_SLINEAR96 ||
- format->id == AST_FORMAT_SLINEAR192) {
- return 1;
- }
- return 0;
+ return ast_format_create_named(codec->name, codec);
}
-enum ast_format_id ast_format_slin_by_rate(unsigned int rate)
+enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
{
- if (rate >= 192000) {
- return AST_FORMAT_SLINEAR192;
- } else if (rate >= 96000) {
- return AST_FORMAT_SLINEAR96;
- } else if (rate >= 48000) {
- return AST_FORMAT_SLINEAR48;
- } else if (rate >= 44100) {
- return AST_FORMAT_SLINEAR44;
- } else if (rate >= 32000) {
- return AST_FORMAT_SLINEAR32;
- } else if (rate >= 24000) {
- return AST_FORMAT_SLINEAR24;
- } else if (rate >= 16000) {
- return AST_FORMAT_SLINEAR16;
- } else if (rate >= 12000) {
- return AST_FORMAT_SLINEAR12;
- }
- return AST_FORMAT_SLINEAR;
-}
+ const struct ast_format_interface *interface;
-const char* ast_getformatname(const struct ast_format *format)
-{
- int x;
- const char *ret = "unknown";
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- ret = f_list[x].name;
- break;
- }
+ if (format1 == NULL || format2 == NULL) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
}
- f_list = ast_format_list_destroy(f_list);
- return ret;
-}
-
-char *ast_getformatname_multiple_byid(char *buf, size_t size, enum ast_format_id id)
-{
- int x;
- unsigned len;
- char *start, *end = buf;
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- if (!size) {
- f_list = ast_format_list_destroy(f_list);
- return buf;
- }
- snprintf(end, size, "(");
- len = strlen(end);
- end += len;
- size -= len;
- start = end;
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == id) {
- snprintf(end, size, "%s|", f_list[x].name);
- len = strlen(end);
- end += len;
- size -= len;
- }
- }
- if (start == end) {
- ast_copy_string(start, "nothing)", size);
- } else if (size > 1) {
- *(end - 1) = ')';
+ if (format1 == format2) {
+ return AST_FORMAT_CMP_EQUAL;
}
- f_list = ast_format_list_destroy(f_list);
- return buf;
-}
-
-static struct ast_codec_alias_table {
- const char *alias;
- const char *realname;
-} ast_codec_alias_table[] = {
- { "slinear", "slin"},
- { "slinear16", "slin16"},
- { "g723.1", "g723"},
- { "g722.1", "siren7"},
- { "g722.1c", "siren14"},
-};
-static const char *ast_expand_codec_alias(const char *in)
-{
- int x;
-
- for (x = 0; x < ARRAY_LEN(ast_codec_alias_table); x++) {
- if (!strcmp(in,ast_codec_alias_table[x].alias))
- return ast_codec_alias_table[x].realname;
+ if (format1->codec != format2->codec) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
}
- return in;
-}
-
-struct ast_format *ast_getformatbyname(const char *name, struct ast_format *result)
-{
- int x;
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (!strcasecmp(f_list[x].name, name) ||
- !strcasecmp(f_list[x].name, ast_expand_codec_alias(name))) {
+ interface = format1->interface ? format1->interface : format2->interface;
- ast_format_copy(result, &f_list[x].format);
- f_list = ast_format_list_destroy(f_list);
- return result;
- }
+ if (interface) {
+ return interface->format_cmp(format1, format2);
}
- f_list = ast_format_list_destroy(f_list);
-
- return NULL;
-}
-const char *ast_codec2str(struct ast_format *format)
-{
- int x;
- const char *ret = "unknown";
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- ret = f_list[x].desc;
- break;
- }
- }
- f_list = ast_format_list_destroy(f_list);
- return ret;
+ return AST_FORMAT_CMP_EQUAL;
}
-int ast_format_rate(const struct ast_format *format)
+struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
{
- switch (format->id) {
- case AST_FORMAT_SLINEAR12:
- return 12000;
- case AST_FORMAT_SLINEAR24:
- return 24000;
- case AST_FORMAT_SLINEAR32:
- return 32000;
- case AST_FORMAT_SLINEAR44:
- return 44100;
- case AST_FORMAT_SLINEAR48:
- return 48000;
- case AST_FORMAT_SLINEAR96:
- return 96000;
- case AST_FORMAT_SLINEAR192:
- return 192000;
- case AST_FORMAT_G722:
- case AST_FORMAT_SLINEAR16:
- case AST_FORMAT_SIREN7:
- case AST_FORMAT_SPEEX16:
- return 16000;
- case AST_FORMAT_SIREN14:
- case AST_FORMAT_SPEEX32:
- return 32000;
- case AST_FORMAT_G719:
- return 48000;
- case AST_FORMAT_SILK:
- if (!(ast_format_isset(format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_24KHZ,
- AST_FORMAT_ATTR_END))) {
- return 24000;
- } else if (!(ast_format_isset(format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END))) {
- return 16000;
- } else if (!(ast_format_isset(format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_12KHZ,
- AST_FORMAT_ATTR_END))) {
- return 12000;
- } else {
- return 8000;
- }
- case AST_FORMAT_CELT:
- {
- int samplerate;
- if (!(ast_format_get_value(format,
- CELT_ATTR_KEY_SAMP_RATE,
- &samplerate))) {
- return samplerate;
- }
- }
- /* Opus */
- case AST_FORMAT_OPUS:
- return 48000;
- default:
- return 8000;
- }
-}
+ const struct ast_format_interface *interface;
-static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int x, found=0;
- size_t f_len;
- const struct ast_format_list *f_list;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "core show codecs [audio|video|image|text]";
- e->usage =
- "Usage: core show codecs [audio|video|image|text]\n"
- " Displays codec mapping\n";
- return NULL;
- case CLI_GENERATE:
+ if (format1->codec != format2->codec) {
return NULL;
}
- if ((a->argc < 3) || (a->argc > 4)) {
- return CLI_SHOWUSAGE;
+ /* If the two formats are the same structure OR if the codec is the same and no attributes
+ * exist we can immediately return a format with reference count bumped up, since they are
+ * the same.
+ */
+ if ((ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL && !format1->attribute_data && !format2->attribute_data)) {
+ return ao2_bump((struct ast_format*)format1);
}
- f_list = ast_format_list_get(&f_len);
- if (!ast_opt_dont_warn) {
- ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
- "\tIt does not indicate anything about your configuration.\n");
- }
+ interface = format1->interface ? format1->interface : format2->interface;
- ast_cli(a->fd, "%8s %5s %8s %s\n","ID","TYPE","NAME","DESCRIPTION");
- ast_cli(a->fd, "-----------------------------------------------------------------------------------\n");
-
- for (x = 0; x < f_len; x++) {
- if (a->argc == 4) {
- if (!strcasecmp(a->argv[3], "audio")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_AUDIO) {
- continue;
- }
- } else if (!strcasecmp(a->argv[3], "video")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_VIDEO) {
- continue;
- }
- } else if (!strcasecmp(a->argv[3], "image")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_IMAGE) {
- continue;
- }
- } else if (!strcasecmp(a->argv[3], "text")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_TEXT) {
- continue;
- }
- } else {
- continue;
- }
- }
-
- ast_cli(a->fd, "%8u %5s %8s (%s)\n",
- f_list[x].format.id,
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_AUDIO) ? "audio" :
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_IMAGE) ? "image" :
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_VIDEO) ? "video" :
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_TEXT) ? "text" :
- "(unk)",
- f_list[x].name,
- f_list[x].desc);
- found = 1;
- }
-
- f_list = ast_format_list_destroy(f_list);
- if (!found) {
- return CLI_SHOWUSAGE;
- } else {
- return CLI_SUCCESS;
- }
+ /* If there is attribute data on either there has to be an interface */
+ return interface->format_get_joint(format1, format2);
}
-static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
{
- enum ast_format_id format_id;
- int x, found = 0;
- int type_punned_codec;
- size_t f_len;
- const struct ast_format_list *f_list;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "core show codec";
- e->usage =
- "Usage: core show codec <number>\n"
- " Displays codec mapping\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 4) {
- return CLI_SHOWUSAGE;
- }
+ const struct ast_format_interface *interface = format->interface;
- if (sscanf(a->argv[3], "%30d", &type_punned_codec) != 1) {
- return CLI_SHOWUSAGE;
- }
- format_id = type_punned_codec;
-
- f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == format_id) {
- found = 1;
- ast_cli(a->fd, "%11u %s\n", (unsigned int) format_id, f_list[x].desc);
+ if (!interface) {
+ struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
+ if (format_interface) {
+ interface = format_interface->interface;
+ ao2_ref(format_interface, -1);
}
}
- if (!found) {
- ast_cli(a->fd, "Codec %u not found\n", format_id);
+ if (!interface || !interface->format_attribute_set) {
+ return ao2_bump((struct ast_format*)format);
}
- f_list = ast_format_list_destroy(f_list);
- return CLI_SUCCESS;
+ return interface->format_attribute_set(format, name, value);
}
-/* Builtin Asterisk CLI-commands for debugging */
-static struct ast_cli_entry my_clis[] = {
- AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
- AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
-};
-
-static int format_list_add_custom(struct ast_format_list *new)
+struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
{
- RAII_VAR(struct ast_format_list *, entry, NULL, ao2_cleanup);
- if (!(entry = ao2_alloc(sizeof(*entry), NULL))) {
- return -1;
- }
- memcpy(entry, new, sizeof(struct ast_format_list));
- entry->custom_entry = 1;
- ao2_link(format_list, entry);
- return 0;
-}
-static int format_list_add_static(
- const struct ast_format *format,
- const char *name,
- int samplespersecond,
- const char *description,
- int fr_len,
- int min_ms,
- int max_ms,
- int inc_ms,
- int def_ms,
- unsigned int flags,
- int cur_ms)
-{
- struct ast_format_list *entry;
- if (!(entry = ao2_alloc(sizeof(*entry), NULL))) {
- return -1;
- }
- ast_format_copy(&entry->format, format);
- ast_copy_string(entry->name, name, sizeof(entry->name));
- ast_copy_string(entry->desc, description, sizeof(entry->desc));
- entry->samplespersecond = samplespersecond;
- entry->fr_len = fr_len;
- entry->min_ms = min_ms;
- entry->max_ms = max_ms;
- entry->inc_ms = inc_ms;
- entry->def_ms = def_ms;
- entry->flags = flags;
- entry->cur_ms = cur_ms;
- entry->custom_entry = 0;
-
- ao2_link(format_list, entry);
- ao2_ref(entry, -1);
- return 0;
-}
+ const struct ast_format_interface *interface = format->interface;
-static int list_all_custom(void *obj, void *arg, int flag)
-{
- struct ast_format_list *entry = obj;
- return entry->custom_entry ? CMP_MATCH : 0;
-}
-
-static int list_cmp_cb(void *obj, void *arg, int flags)
-{
- struct ast_format_list *entry1 = obj;
- struct ast_format_list *entry2 = arg;
-
- return (ast_format_cmp(&entry1->format, &entry2->format) == AST_FORMAT_CMP_EQUAL) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-const struct ast_format_list *ast_format_list_get(size_t *size)
-{
- struct ast_format_list *list;
- ast_rwlock_rdlock(&format_list_array_lock);
- ao2_ref(format_list_array, 1);
- list = format_list_array;
- *size = format_list_array_len;
- ast_rwlock_unlock(&format_list_array_lock);
- return list;
-}
-const struct ast_format_list *ast_format_list_destroy(const struct ast_format_list *list)
-{
- ao2_ref((void *) list, -1);
- return NULL;
-}
-
-static int build_format_list_array(void)
-{
- struct ast_format_list *tmp;
- size_t arraysize = sizeof(struct ast_format_list) * ao2_container_count(format_list);
- int i = 0;
- struct ao2_iterator it;
-
- ast_rwlock_wrlock(&format_list_array_lock);
- tmp = format_list_array;
- if (!(format_list_array = ao2_alloc(arraysize, NULL))) {
- format_list_array = tmp;
- ast_rwlock_unlock(&format_list_array_lock);
- return -1;
- }
- format_list_array_len = ao2_container_count(format_list);
- if (tmp) {
- ao2_ref(tmp, -1);
+ if (!interface) {
+ struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
+ if (format_interface) {
+ interface = format_interface->interface;
+ ao2_ref(format_interface, -1);
+ }
}
- /* walk through the container adding elements to the static array */
- it = ao2_iterator_init(format_list, 0);
- while ((tmp = ao2_iterator_next(&it)) && (i < format_list_array_len)) {
- memcpy(&format_list_array[i], tmp, sizeof(struct ast_format_list));
- ao2_ref(tmp, -1);
- i++;
+ if (!interface || !interface->format_parse_sdp_fmtp) {
+ return ao2_bump((struct ast_format*)format);
}
- ao2_iterator_destroy(&it);
- ast_rwlock_unlock(&format_list_array_lock);
- return 0;
+ return interface->format_parse_sdp_fmtp(format, attributes);
}
-static int format_list_init(void)
+void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct ast_format tmpfmt;
- if (!(format_list = ao2_container_alloc(1, NULL, list_cmp_cb))) {
- return -1;
+ if (!format->interface || !format->interface->format_generate_sdp_fmtp) {
+ return;
}
- /* initiate static entries XXX DO NOT CHANGE THIS ORDER! */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0), "g723", 8000, "G.723.1", 20, 30, 300, 30, 30, 0, 0); /*!< G723.1 */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0), "gsm", 8000, "GSM", 33, 20, 300, 20, 20, 0, 0); /*!< codec_gsm.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20, 0, 0); /*!< codec_ulaw.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20, 0, 0); /*!< codec_alaw.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20, 0, 0); /*!< codec_g726.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), "adpcm" , 8000, "Dialogic ADPCM", 40, 10, 300, 10, 20, 0, 0); /*!< codec_adpcm.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0); /*!< Signed linear */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_LPC10, 0), "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20, 0, 0); /*!< codec_lpc10.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729, 0); /*!< Binary commercial distribution */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX, 0), "speex", 8000, "SpeeX", 10, 10, 60, 10, 20, 0, 0); /*!< codec_speex.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX16, 0), "speex16", 16000, "SpeeX 16khz", 10, 10, 60, 10, 20, 0, 0); /*!< codec_speex.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ILBC, 0), "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30, 0, 0); /*!< codec_ilbc.c */ /* inc=30ms - workaround */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G726_AAL2, 0), "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20, 0, 0); /*!< codec_g726.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G722, 0), "g722", 16000, "G722", 80, 10, 150, 10, 20, 0, 0); /*!< codec_g722.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (16kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_JPEG, 0), "jpeg", 0, "JPEG image", 0, 0, 0, 0 ,0 ,0 ,0); /*!< See format_jpeg.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_PNG, 0), "png", 0, "PNG image", 0, 0, 0, 0 ,0 ,0 ,0); /*!< PNG Image format */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H261, 0), "h261", 0, "H.261 Video", 0, 0, 0, 0 ,0 ,0 ,0); /*!< H.261 Video Passthrough */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H263, 0), "h263", 0, "H.263 Video", 0, 0, 0, 0 ,0 ,0 ,0); /*!< H.263 Passthrough support, see format_h263.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), "h263p", 0, "H.263+ Video", 0, 0, 0,0 ,0 ,0, 0); /*!< H.263plus passthrough support See format_h263.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H264, 0), "h264", 0, "H.264 Video", 0, 0, 0, 0 ,0 ,0, 0); /*!< Passthrough support, see format_h263.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_MP4_VIDEO, 0), "mpeg4", 0, "MPEG4 Video", 0, 0, 0, 0, 0 ,0, 0); /*!< Passthrough support for MPEG4 */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_T140RED, 0), "red", 1, "T.140 Realtime Text with redundancy", 0, 0, 0,0 ,0 ,0, 0); /*!< Redundant T.140 Realtime Text */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_T140, 0), "t140", 0, "Passthrough T.140 Realtime Text", 0, 0, 0, 0 ,0 ,0, 0); /*!< Passthrough support for T.140 Realtime Text */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), "siren7", 16000, "ITU G.722.1 (Siren7, licensed from Polycom)", 80, 20, 80, 20, 20, 0, 0); /*!< Binary commercial distribution */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), "siren14", 32000, "ITU G.722.1 Annex C, (Siren14, licensed from Polycom)", 120, 20, 80, 20, 20, 0, 0); /*!< Binary commercial distribution */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_TESTLAW, 0), "testlaw", 8000, "G.711 test-law", 80, 10, 150, 10, 20, 0, 0); /*!< codec_ulaw.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), "g719", 48000, "ITU G.719", 160, 20, 80, 20, 20, 0, 0);
-
- /* ORDER MAY CHANGE AFTER THIS POINT IN THE LIST */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), "speex32", 32000, "SpeeX 32khz", 10, 10, 60, 10, 20, 0, 0); /*!< codec_speex.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR12, 0), "slin12", 12000, "16 bit Signed Linear PCM (12kHz)", 240, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (12kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR24, 0), "slin24", 24000, "16 bit Signed Linear PCM (24kHz)", 480, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (24kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR32, 0), "slin32", 32000, "16 bit Signed Linear PCM (32kHz)", 640, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (32kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR44, 0), "slin44", 44100, "16 bit Signed Linear PCM (44kHz)", 882, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (44.1kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR48, 0), "slin48", 48000, "16 bit Signed Linear PCM (48kHz)", 960, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (48kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR96, 0), "slin96", 96000, "16 bit Signed Linear PCM (96kHz)", 1920, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (96kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR192, 0), "slin192", 192000, "16 bit Signed Linear PCM (192kHz)", 3840, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (192kHz) */
- /* Opus (FIXME: real min is 3/5/10, real max is 120...) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), "opus", 48000, "Opus Codec", 10, 20, 60, 20, 20, 0, 0); /*!< codec_opus.c */
- /* VP8 (passthrough) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), "vp8", 0, "VP8 Video", 0, 0, 0, 0 ,0 ,0, 0); /*!< Passthrough support, see format_h263.c */
- return 0;
+ format->interface->format_generate_sdp_fmtp(format, payload, str);
}
-/*!
- * \internal
- * \brief Clean up resources on Asterisk shutdown
- */
-static void format_list_shutdown(void)
+unsigned int ast_format_get_codec_id(const struct ast_format *format)
{
- ast_rwlock_destroy(&format_list_array_lock);
- if (format_list) {
- ao2_t_ref(format_list, -1, "Unref format_list container in shutdown");
- format_list = NULL;
- }
- if (format_list_array) {
- ao2_t_ref(format_list_array, -1, "Unref format_list_array in shutdown");
- format_list_array = NULL;
- }
+ return format->codec->id;
}
-int ast_format_list_init(void)
+const char *ast_format_get_name(const struct ast_format *format)
{
- if (ast_rwlock_init(&format_list_array_lock)) {
- return -1;
- }
- if (format_list_init()) {
- goto init_list_cleanup;
- }
- if (build_format_list_array()) {
- goto init_list_cleanup;
- }
-
- ast_register_atexit(format_list_shutdown);
- return 0;
-init_list_cleanup:
-
- format_list_shutdown();
- return -1;
+ return format->name;
}
-/*!
- * \internal
- * \brief Clean up resources on Asterisk shutdown
- */
-static void format_attr_shutdown(void)
+const char *ast_format_get_codec_name(const struct ast_format *format)
{
- ast_cli_unregister_multiple(my_clis, ARRAY_LEN(my_clis));
- if (interfaces) {
- ao2_ref(interfaces, -1);
- interfaces = NULL;
- }
+ return format->codec->name;
}
-int ast_format_attr_init(void)
+int ast_format_can_be_smoothed(const struct ast_format *format)
{
- interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK,
- 283, interface_hash_cb, interface_cmp_cb);
- if (!interfaces) {
- return -1;
- }
-
- ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis));
- ast_register_cleanup(format_attr_shutdown);
- return 0;
+ return format->codec->smooth;
}
-static int custom_celt_format(struct ast_format_list *entry, unsigned int maxbitrate, unsigned int framesize)
+enum ast_media_type ast_format_get_type(const struct ast_format *format)
{
- if (!entry->samplespersecond) {
- ast_log(LOG_WARNING, "Custom CELT format definition '%s' requires sample rate to be defined.\n", entry->name);
- }
- ast_format_set(&entry->format, AST_FORMAT_CELT, 0);
- if (!has_interface(&entry->format)) {
- return -1;
- }
-
- snprintf(entry->desc, sizeof(entry->desc), "CELT Custom Format %ukhz", entry->samplespersecond/1000);
-
- ast_format_append(&entry->format,
- CELT_ATTR_KEY_SAMP_RATE, entry->samplespersecond,
- CELT_ATTR_KEY_MAX_BITRATE, maxbitrate,
- CELT_ATTR_KEY_FRAME_SIZE, framesize,
- AST_FORMAT_ATTR_END);
-
- entry->fr_len = 80;
- entry->min_ms = 20;
- entry->max_ms = 20;
- entry->inc_ms = 20;
- entry->def_ms = 20;
- return 0;
+ return format->codec->type;
}
-static int custom_silk_format(struct ast_format_list *entry, unsigned int maxbitrate, int usedtx, int usefec, int packetloss_percentage)
+unsigned int ast_format_get_default_ms(const struct ast_format *format)
{
- if (!entry->samplespersecond) {
- ast_log(LOG_WARNING, "Custom SILK format definition '%s' requires sample rate to be defined.\n", entry->name);
- }
- ast_format_set(&entry->format, AST_FORMAT_SILK, 0);
-
- if (!has_interface(&entry->format)) {
- return -1;
- }
-
- switch (entry->samplespersecond) {
- case 8000:
- ast_copy_string(entry->desc, "SILK Custom Format 8khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_8KHZ,
- AST_FORMAT_ATTR_END);
- break;
- case 12000:
- ast_copy_string(entry->desc, "SILK Custom Format 12khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_12KHZ,
- AST_FORMAT_ATTR_END);
- break;
- case 16000:
- ast_copy_string(entry->desc, "SILK Custom Format 16khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END);
- break;
- case 24000:
- ast_copy_string(entry->desc, "SILK Custom Format 24khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_24KHZ,
- AST_FORMAT_ATTR_END);
- break;
- default:
- ast_log(LOG_WARNING, "Custom SILK format definition '%s' can not support sample rate %u\n", entry->name, entry->samplespersecond);
- return -1;
- }
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_MAX_BITRATE, maxbitrate,
- SILK_ATTR_KEY_DTX, usedtx ? 1 : 0,
- SILK_ATTR_KEY_FEC, usefec ? 1 : 0,
- SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE, packetloss_percentage,
- AST_FORMAT_ATTR_END);
-
- entry->fr_len = 80;
- entry->min_ms = 20;
- entry->max_ms = 20;
- entry->inc_ms = 20;
- entry->def_ms = 20;
- return 0;
+ return format->codec->default_ms;
}
-static int conf_process_format_name(const char *name, enum ast_format_id *id)
+unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
{
- if (!strcasecmp(name, "silk")) {
- *id = AST_FORMAT_SILK;
- } else if (!strcasecmp(name, "celt")) {
- *id = AST_FORMAT_CELT;
- } else {
- *id = 0;
- return -1;
- }
- return 0;
+ return format->codec->minimum_ms;
}
-static int conf_process_sample_rate(const char *rate, unsigned int *result)
+unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
{
- if (!strcasecmp(rate, "8000")) {
- *result = 8000;
- } else if (!strcasecmp(rate, "12000")) {
- *result = 12000;
- } else if (!strcasecmp(rate, "16000")) {
- *result = 16000;
- } else if (!strcasecmp(rate, "24000")) {
- *result = 24000;
- } else if (!strcasecmp(rate, "32000")) {
- *result = 32000;
- } else if (!strcasecmp(rate, "44100")) {
- *result = 44100;
- } else if (!strcasecmp(rate, "48000")) {
- *result = 48000;
- } else if (!strcasecmp(rate, "96000")) {
- *result = 96000;
- } else if (!strcasecmp(rate, "192000")) {
- *result = 192000;
- } else {
- *result = 0;
- return -1;
- }
-
- return 0;
+ return format->codec->maximum_ms;
}
-static int load_format_config(void)
-{
- struct ast_flags config_flags = { 0, };
- struct ast_config *cfg = ast_config_load(FORMAT_CONFIG, config_flags);
- struct ast_format_list entry;
- struct ast_variable *var;
- char *cat = NULL;
- int add_it = 0;
-
- struct {
- enum ast_format_id id;
- unsigned int maxbitrate;
- unsigned int framesize;
- unsigned int packetloss_percentage;
- int usefec;
- int usedtx;
- } settings;
-
- if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
- return 0;
- }
-
- /* remove all custom formats from the AO2 Container. Note, this has no affect on the
- * global format list until the list is rebuild. That is why this is okay to do while
- * reloading the config. */
- ao2_callback(format_list, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, list_all_custom, NULL);
- while ((cat = ast_category_browse(cfg, cat))) {
- memset(&entry, 0, sizeof(entry));
- memset(&settings, 0, sizeof(settings));
- add_it = 0;
-
- if (!(ast_variable_retrieve(cfg, cat, "type"))) {
- continue;
- }
- ast_copy_string(entry.name, cat, sizeof(entry.name));
- var = ast_variable_browse(cfg, cat);
- for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
- if (!strcasecmp(var->name, "type") && conf_process_format_name(var->value, &settings.id)) {
- ast_log(LOG_WARNING, "Can not make custom format type for '%s' at line %d of %s\n",
- var->value, var->lineno, FORMAT_CONFIG);
- continue;
- } else if (!strcasecmp(var->name, "samprate") && conf_process_sample_rate(var->value, &entry.samplespersecond)) {
- ast_log(LOG_WARNING, "Sample rate '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- } else if (!strcasecmp(var->name, "maxbitrate")) {
- if (sscanf(var->value, "%30u", &settings.maxbitrate) != 1) {
- ast_log(LOG_WARNING, "maxbitrate '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- }
- } else if (!strcasecmp(var->name, "framesize")) {
- if (sscanf(var->value, "%30u", &settings.framesize) != 1) {
- ast_log(LOG_WARNING, "framesize '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- }
- } else if (!strcasecmp(var->name, "dtx")) {
- settings.usedtx = ast_true(var->value) ? 1 : 0;
- } else if (!strcasecmp(var->name, "fec")) {
- settings.usefec = ast_true(var->value) ? 1 : 0;
- } else if (!strcasecmp(var->name, "packetloss_percentage")) {
- if ((sscanf(var->value, "%30u", &settings.packetloss_percentage) != 1) || (settings.packetloss_percentage > 100)) {
- ast_log(LOG_WARNING, "packetloss_percentage '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- }
- }
- }
-
- switch (settings.id) {
- case AST_FORMAT_SILK:
- if (!(custom_silk_format(&entry, settings.maxbitrate, settings.usedtx, settings.usefec, settings.packetloss_percentage))) {
- add_it = 1;
- }
- break;
- case AST_FORMAT_CELT:
- if (!(custom_celt_format(&entry, settings.maxbitrate, settings.framesize))) {
- add_it = 1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "Can not create custom format %s\n", entry.name);
- }
-
- if (add_it) {
- format_list_add_custom(&entry);
- }
- }
- ast_config_destroy(cfg);
- build_format_list_array();
- return 0;
+unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
+{
+ return format->codec->minimum_bytes;
}
-int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interface)
+unsigned int ast_format_get_sample_rate(const struct ast_format *format)
{
- int x;
- size_t f_len;
- const struct ast_format_list *f_list;
- struct interface_ao2_wrapper *wrapper;
- struct interface_ao2_wrapper tmp_wrapper = {
- .id = interface->id,
- };
-
- /*
- * Grab the write lock before checking for duplicates in
- * anticipation of adding a new interface and to prevent a
- * duplicate from sneaking in between the check and add.
- */
- ao2_wrlock(interfaces);
-
- /* check for duplicates first*/
- if ((wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
- ao2_unlock(interfaces);
- ast_log(LOG_WARNING, "Can not register attribute interface for format id %u, interface already exists.\n", interface->id);
- ao2_ref(wrapper, -1);
- return -1;
- }
-
- wrapper = ao2_alloc_options(sizeof(*wrapper), NULL, AO2_ALLOC_OPT_LOCK_RWLOCK);
- if (!wrapper) {
- ao2_unlock(interfaces);
- return -1;
- }
-
- wrapper->interface = interface;
- wrapper->id = interface->id;
-
- /* The write lock is already held. */
- ao2_link_flags(interfaces, wrapper, OBJ_NOLOCK);
- ao2_unlock(interfaces);
-
- ao2_ref(wrapper, -1);
-
- /* This will find all custom formats in codecs.conf for this new registered interface */
- load_format_config();
-
- /* update the RTP engine to all custom formats created for this interface */
- f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == tmp_wrapper.id) {
- ast_rtp_engine_load_format(&f_list[x].format);
- }
- }
- f_list = ast_format_list_destroy(f_list);
- return 0;
+ return format->codec->sample_rate;
}
-int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *interface)
+unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
{
- int x;
- size_t f_len;
- const struct ast_format_list *f_list;
- struct interface_ao2_wrapper *wrapper;
- struct interface_ao2_wrapper tmp_wrapper = {
- .id = interface->id,
- };
-
- if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_UNLINK)))) {
- return -1;
- }
-
- ao2_wrlock(wrapper);
- wrapper->interface = NULL;
- ao2_unlock(wrapper);
-
- ao2_ref(wrapper, -1);
-
- /* update the RTP engine to remove all custom formats created for this interface */
- f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == tmp_wrapper.id) {
- ast_rtp_engine_unload_format(&f_list[x].format);
- }
- }
-
- /* This will remove all custom formats previously created for this interface */
- load_format_config();
- f_list = ast_format_list_destroy(f_list);
- return 0;
+ return ast_codec_determine_length(format->codec, samples);
}
diff --git a/main/format_cache.c b/main/format_cache.c
new file mode 100644
index 000000000..c170a76f9
--- /dev/null
+++ b/main/format_cache.c
@@ -0,0 +1,519 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Cache API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/strings.h"
+
+/*!
+ * \brief Built-in cached signed linear 8kHz format.
+ */
+struct ast_format *ast_format_slin;
+
+/*!
+ * \brief Built-in cached signed linear 12kHz format.
+ */
+struct ast_format *ast_format_slin12;
+
+/*!
+ * \brief Built-in cached signed linear 16kHz format.
+ */
+struct ast_format *ast_format_slin16;
+
+/*!
+ * \brief Built-in cached signed linear 24kHz format.
+ */
+struct ast_format *ast_format_slin24;
+
+/*!
+ * \brief Built-in cached signed linear 32kHz format.
+ */
+struct ast_format *ast_format_slin32;
+
+/*!
+ * \brief Built-in cached signed linear 44kHz format.
+ */
+struct ast_format *ast_format_slin44;
+
+/*!
+ * \brief Built-in cached signed linear 48kHz format.
+ */
+struct ast_format *ast_format_slin48;
+
+/*!
+ * \brief Built-in cached signed linear 96kHz format.
+ */
+struct ast_format *ast_format_slin96;
+
+/*!
+ * \brief Built-in cached signed linear 192kHz format.
+ */
+struct ast_format *ast_format_slin192;
+
+/*!
+ * \brief Built-in cached ulaw format.
+ */
+struct ast_format *ast_format_ulaw;
+
+/*!
+ * \brief Built-in cached alaw format.
+ */
+struct ast_format *ast_format_alaw;
+
+/*!
+ * \brief Built-in cached testlaw format.
+ */
+struct ast_format *ast_format_testlaw;
+
+/*!
+ * \brief Built-in cached gsm format.
+ */
+struct ast_format *ast_format_gsm;
+
+/*!
+ * \brief Built-in cached adpcm format.
+ */
+struct ast_format *ast_format_adpcm;
+
+/*!
+ * \brief Built-in cached g722 format.
+ */
+struct ast_format *ast_format_g722;
+
+/*!
+ * \brief Built-in cached g726 format.
+ */
+struct ast_format *ast_format_g726;
+
+/*!
+ * \brief Built-in cached g726-aal2 format.
+ */
+struct ast_format *ast_format_g726_aal2;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+struct ast_format *ast_format_ilbc;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+struct ast_format *ast_format_lpc10;
+
+/*!
+ * \brief Built-in cached speex format.
+ */
+struct ast_format *ast_format_speex;
+
+/*!
+ * \brief Built-in cached speex at 16kHz format.
+ */
+struct ast_format *ast_format_speex16;
+
+/*!
+ * \brief Built-in cached speex at 32kHz format.
+ */
+struct ast_format *ast_format_speex32;
+
+/*!
+ * \brief Built-in cached g723.1 format.
+ */
+struct ast_format *ast_format_g723;
+
+/*!
+ * \brief Built-in cached g729 format.
+ */
+struct ast_format *ast_format_g729;
+
+/*!
+ * \brief Built-in cached g719 format.
+ */
+struct ast_format *ast_format_g719;
+
+/*!
+ * \brief Built-in cached h261 format.
+ */
+struct ast_format *ast_format_h261;
+
+/*!
+ * \brief Built-in cached h263 format.
+ */
+struct ast_format *ast_format_h263;
+
+/*!
+ * \brief Built-in cached h263 plus format.
+ */
+struct ast_format *ast_format_h263p;
+
+/*!
+ * \brief Built-in cached h264 format.
+ */
+struct ast_format *ast_format_h264;
+
+/*!
+ * \brief Built-in cached mp4 format.
+ */
+struct ast_format *ast_format_mp4;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in cached jpeg format.
+ */
+struct ast_format *ast_format_jpeg;
+
+/*!
+ * \brief Built-in cached png format.
+ */
+struct ast_format *ast_format_png;
+
+/*!
+ * \brief Built-in cached siren14 format.
+ */
+struct ast_format *ast_format_siren14;
+
+/*!
+ * \brief Built-in cached siren7 format.
+ */
+struct ast_format *ast_format_siren7;
+
+/*!
+ * \brief Built-in cached opus format.
+ */
+struct ast_format *ast_format_opus;
+
+/*!
+ * \brief Built-in cached t140 format.
+ */
+struct ast_format *ast_format_t140;
+
+/*!
+ * \brief Built-in cached t140 red format.
+ */
+struct ast_format *ast_format_t140_red;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in "null" format.
+ */
+struct ast_format *ast_format_none;
+
+/*! \brief Number of buckets to use for the media format cache (should be prime for performance reasons) */
+#define CACHE_BUCKETS 53
+
+/*! \brief Cached formats */
+static struct ao2_container *formats;
+
+static int format_hash_cb(const void *obj, int flags)
+{
+ const struct ast_format *format;
+ const char *key;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_KEY:
+ key = obj;
+ return ast_str_case_hash(key);
+ case OBJ_SEARCH_OBJECT:
+ format = obj;
+ return ast_str_case_hash(ast_format_get_name(format));
+ default:
+ /* Hash can only work on something with a full key. */
+ ast_assert(0);
+ return 0;
+ }
+}
+
+static int format_cmp_cb(void *obj, void *arg, int flags)
+{
+ const struct ast_format *left = obj;
+ const struct ast_format *right = arg;
+ const char *right_key = arg;
+ int cmp;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = ast_format_get_name(right);
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ cmp = strcasecmp(ast_format_get_name(left), right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncasecmp(ast_format_get_name(left), right_key, strlen(right_key));
+ break;
+ default:
+ ast_assert(0);
+ cmp = 0;
+ break;
+ }
+ if (cmp) {
+ return 0;
+ }
+
+ return CMP_MATCH;
+}
+
+/*! \brief Function called when the process is shutting down */
+static void format_cache_shutdown(void)
+{
+ ao2_cleanup(formats);
+ formats = NULL;
+
+ ao2_replace(ast_format_g723, NULL);
+ ao2_replace(ast_format_ulaw, NULL);
+ ao2_replace(ast_format_alaw, NULL);
+ ao2_replace(ast_format_gsm, NULL);
+ ao2_replace(ast_format_g726, NULL);
+ ao2_replace(ast_format_g726_aal2, NULL);
+ ao2_replace(ast_format_adpcm, NULL);
+ ao2_replace(ast_format_slin, NULL);
+ ao2_replace(ast_format_slin12, NULL);
+ ao2_replace(ast_format_slin16, NULL);
+ ao2_replace(ast_format_slin24, NULL);
+ ao2_replace(ast_format_slin32, NULL);
+ ao2_replace(ast_format_slin44, NULL);
+ ao2_replace(ast_format_slin48, NULL);
+ ao2_replace(ast_format_slin96, NULL);
+ ao2_replace(ast_format_slin192, NULL);
+ ao2_replace(ast_format_lpc10, NULL);
+ ao2_replace(ast_format_g729, NULL);
+ ao2_replace(ast_format_speex, NULL);
+ ao2_replace(ast_format_speex16, NULL);
+ ao2_replace(ast_format_speex32, NULL);
+ ao2_replace(ast_format_ilbc, NULL);
+ ao2_replace(ast_format_g722, NULL);
+ ao2_replace(ast_format_siren7, NULL);
+ ao2_replace(ast_format_siren14, NULL);
+ ao2_replace(ast_format_testlaw, NULL);
+ ao2_replace(ast_format_g719, NULL);
+ ao2_replace(ast_format_opus, NULL);
+ ao2_replace(ast_format_jpeg, NULL);
+ ao2_replace(ast_format_png, NULL);
+ ao2_replace(ast_format_h261, NULL);
+ ao2_replace(ast_format_h263, NULL);
+ ao2_replace(ast_format_h263p, NULL);
+ ao2_replace(ast_format_h264, NULL);
+ ao2_replace(ast_format_mp4, NULL);
+ ao2_replace(ast_format_vp8, NULL);
+ ao2_replace(ast_format_t140_red, NULL);
+ ao2_replace(ast_format_t140, NULL);
+ ao2_replace(ast_format_none, NULL);
+}
+
+int ast_format_cache_init(void)
+{
+ formats = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CACHE_BUCKETS,
+ format_hash_cb, format_cmp_cb);
+ if (!formats) {
+ return -1;
+ }
+
+ ast_register_atexit(format_cache_shutdown);
+
+ return 0;
+}
+
+static void set_cached_format(const char *name, struct ast_format *format)
+{
+ if (!strcmp(name, "g723")) {
+ ao2_replace(ast_format_g723, format);
+ } else if (!strcmp(name, "ulaw")) {
+ ao2_replace(ast_format_ulaw, format);
+ } else if (!strcmp(name, "alaw")) {
+ ao2_replace(ast_format_alaw, format);
+ } else if (!strcmp(name, "gsm")) {
+ ao2_replace(ast_format_gsm, format);
+ } else if (!strcmp(name, "g726")) {
+ ao2_replace(ast_format_g726, format);
+ } else if (!strcmp(name, "g726aal2")) {
+ ao2_replace(ast_format_g726_aal2, format);
+ } else if (!strcmp(name, "adpcm")) {
+ ao2_replace(ast_format_adpcm, format);
+ } else if (!strcmp(name, "slin")) {
+ ao2_replace(ast_format_slin, format);
+ } else if (!strcmp(name, "slin12")) {
+ ao2_replace(ast_format_slin12, format);
+ } else if (!strcmp(name, "slin16")) {
+ ao2_replace(ast_format_slin16, format);
+ } else if (!strcmp(name, "slin24")) {
+ ao2_replace(ast_format_slin24, format);
+ } else if (!strcmp(name, "slin32")) {
+ ao2_replace(ast_format_slin32, format);
+ } else if (!strcmp(name, "slin44")) {
+ ao2_replace(ast_format_slin44, format);
+ } else if (!strcmp(name, "slin48")) {
+ ao2_replace(ast_format_slin48, format);
+ } else if (!strcmp(name, "slin96")) {
+ ao2_replace(ast_format_slin96, format);
+ } else if (!strcmp(name, "slin192")) {
+ ao2_replace(ast_format_slin192, format);
+ } else if (!strcmp(name, "lpc10")) {
+ ao2_replace(ast_format_lpc10, format);
+ } else if (!strcmp(name, "g729")) {
+ ao2_replace(ast_format_g729, format);
+ } else if (!strcmp(name, "speex")) {
+ ao2_replace(ast_format_speex, format);
+ } else if (!strcmp(name, "speex16")) {
+ ao2_replace(ast_format_speex16, format);
+ } else if (!strcmp(name, "speex32")) {
+ ao2_replace(ast_format_speex32, format);
+ } else if (!strcmp(name, "ilbc")) {
+ ao2_replace(ast_format_ilbc, format);
+ } else if (!strcmp(name, "g722")) {
+ ao2_replace(ast_format_g722, format);
+ } else if (!strcmp(name, "siren7")) {
+ ao2_replace(ast_format_siren7, format);
+ } else if (!strcmp(name, "siren14")) {
+ ao2_replace(ast_format_siren14, format);
+ } else if (!strcmp(name, "testlaw")) {
+ ao2_replace(ast_format_testlaw, format);
+ } else if (!strcmp(name, "g719")) {
+ ao2_replace(ast_format_g719, format);
+ } else if (!strcmp(name, "opus")) {
+ ao2_replace(ast_format_opus, format);
+ } else if (!strcmp(name, "jpeg")) {
+ ao2_replace(ast_format_jpeg, format);
+ } else if (!strcmp(name, "png")) {
+ ao2_replace(ast_format_png, format);
+ } else if (!strcmp(name, "h261")) {
+ ao2_replace(ast_format_h261, format);
+ } else if (!strcmp(name, "h263")) {
+ ao2_replace(ast_format_h263, format);
+ } else if (!strcmp(name, "h263p")) {
+ ao2_replace(ast_format_h263p, format);
+ } else if (!strcmp(name, "h264")) {
+ ao2_replace(ast_format_h264, format);
+ } else if (!strcmp(name, "mpeg4")) {
+ ao2_replace(ast_format_mp4, format);
+ } else if (!strcmp(name, "vp8")) {
+ ao2_replace(ast_format_vp8, format);
+ } else if (!strcmp(name, "red")) {
+ ao2_replace(ast_format_t140_red, format);
+ } else if (!strcmp(name, "t140")) {
+ ao2_replace(ast_format_t140, format);
+ } else if (!strcmp(name, "none")) {
+ ao2_replace(ast_format_none, format);
+ }
+}
+
+int ast_format_cache_set(struct ast_format *format)
+{
+ SCOPED_AO2WRLOCK(lock, formats);
+ struct ast_format *old_format;
+
+ ast_assert(format != NULL);
+
+ if (ast_strlen_zero(ast_format_get_name(format))) {
+ return -1;
+ }
+
+ old_format = ao2_find(formats, ast_format_get_name(format), OBJ_SEARCH_KEY | OBJ_NOLOCK);
+ if (old_format) {
+ ao2_unlink_flags(formats, old_format, OBJ_NOLOCK);
+ }
+ ao2_link_flags(formats, format, OBJ_NOLOCK);
+
+ set_cached_format(ast_format_get_name(format), format);
+
+ ast_verb(2, "%s cached format with name '%s'\n",
+ old_format ? "Updated" : "Created",
+ ast_format_get_name(format));
+
+ ao2_cleanup(old_format);
+
+ return 0;
+}
+
+struct ast_format *__ast_format_cache_get(const char *name)
+{
+ if (ast_strlen_zero(name)) {
+ return NULL;
+ }
+
+ return ao2_find(formats, name, OBJ_SEARCH_KEY);
+}
+
+struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
+{
+ if (ast_strlen_zero(name)) {
+ return NULL;
+ }
+
+ return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
+}
+
+struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate)
+{
+ if (rate >= 192000) {
+ return ast_format_slin192;
+ } else if (rate >= 96000) {
+ return ast_format_slin96;
+ } else if (rate >= 48000) {
+ return ast_format_slin48;
+ } else if (rate >= 44100) {
+ return ast_format_slin44;
+ } else if (rate >= 32000) {
+ return ast_format_slin32;
+ } else if (rate >= 24000) {
+ return ast_format_slin24;
+ } else if (rate >= 16000) {
+ return ast_format_slin16;
+ } else if (rate >= 12000) {
+ return ast_format_slin12;
+ }
+ return ast_format_slin;
+}
+
+int ast_format_cache_is_slinear(struct ast_format *format)
+{
+ if ((ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin24) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin32) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin44) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin48) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin96) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin192) == AST_FORMAT_CMP_EQUAL)) {
+ return 1;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/main/format_cap.c b/main/format_cap.c
index 96c2fa3aa..65e469fc1 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -1,9 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -16,11 +16,11 @@
* at the top of the source tree.
*/
-/*!
- * \file
- * \brief Format Capability API
+/*! \file
+ *
+ * \brief Format Capabilities API
*
- * \author David Vossel <dvossel@digium.com>
+ * \author Joshua Colp <jcolp@digium.com>
*/
/*** MODULEINFO
@@ -29,653 +29,674 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#include "asterisk/_private.h"
+#include "asterisk/logger.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
-#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/codec.h"
#include "asterisk/astobj2.h"
+#include "asterisk/strings.h"
+#include "asterisk/vector.h"
+#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
-#define FORMAT_STR_BUFSIZE 256
+/*! \brief Structure used for capability formats, adds framing */
+struct format_cap_framed {
+ /*! \brief A pointer to the format */
+ struct ast_format *format;
+ /*! \brief The format framing size */
+ unsigned int framing;
+ /*! \brief Linked list information */
+ AST_LIST_ENTRY(format_cap_framed) entry;
+};
+/*! \brief Format capabilities structure, holds formats + preference order + etc */
struct ast_format_cap {
- /* The capabilities structure is just an ao2 container of ast_formats */
- struct ao2_container *formats;
- struct ao2_iterator it;
- /*! TRUE if the formats container created without a lock. */
- struct ast_flags flags;
- unsigned int string_cache_valid;
- char format_strs[0];
+ /*! \brief Vector of formats, indexed using the codec identifier */
+ AST_VECTOR(, struct format_cap_framed_list) formats;
+ /*! \brief Vector of formats, added in preference order */
+ AST_VECTOR(, struct format_cap_framed *) preference_order;
+ /*! \brief Global framing size, applies to all formats if no framing present on format */
+ unsigned int framing;
};
-/*! 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)
+/*! \brief Linked list for formats */
+AST_LIST_HEAD_NOLOCK(format_cap_framed_list, format_cap_framed);
+
+/*! \brief Dummy empty list for when we are inserting a new list */
+static const struct format_cap_framed_list format_cap_framed_list_empty = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+
+/*! \brief Destructor for format capabilities structure */
+static void format_cap_destroy(void *obj)
{
- 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;
+ struct ast_format_cap *cap = obj;
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->formats); idx++) {
+ struct format_cap_framed_list *list = AST_VECTOR_GET_ADDR(&cap->formats, idx);
+ struct format_cap_framed *framed;
+
+ while ((framed = AST_LIST_REMOVE_HEAD(list, entry))) {
+ ao2_ref(framed, -1);
+ }
+ }
+ AST_VECTOR_FREE(&cap->formats);
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->preference_order); idx++) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, idx);
+
+ /* This will always be non-null, unlike formats */
+ ao2_ref(framed, -1);
+ }
+ AST_VECTOR_FREE(&cap->preference_order);
}
-static int hash_cb(const void *obj, const int flags)
+static inline void format_cap_init(struct ast_format_cap *cap, enum ast_format_cap_flags flags)
{
- const struct ast_format *format = obj;
- return format->id;
+ AST_VECTOR_INIT(&cap->formats, 0);
+
+ /* TODO: Look at common usage of this and determine a good starting point */
+ AST_VECTOR_INIT(&cap->preference_order, 5);
+
+ cap->framing = UINT_MAX;
}
-struct ast_format_cap *ast_format_cap_alloc(enum ast_format_cap_flags flags)
+struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags)
{
struct ast_format_cap *cap;
- unsigned int alloc_size;
-
- alloc_size = sizeof(*cap);
- if (flags & AST_FORMAT_CAP_FLAG_CACHE_STRINGS) {
- alloc_size += FORMAT_STR_BUFSIZE;
- }
- cap = ast_calloc(1, alloc_size);
+ cap = ao2_alloc_options(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!cap) {
return NULL;
}
- ast_set_flag(&cap->flags, flags);
- cap->formats = ao2_container_alloc_options(
- (flags & AST_FORMAT_CAP_FLAG_NOLOCK) ?
- AO2_ALLOC_OPT_LOCK_NOLOCK :
- AO2_ALLOC_OPT_LOCK_MUTEX,
- 11, hash_cb, cmp_cb);
- if (!cap->formats) {
- ast_free(cap);
- return NULL;
- }
+ format_cap_init(cap, flags);
return cap;
}
-void *ast_format_cap_destroy(struct ast_format_cap *cap)
+struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func)
{
+ struct ast_format_cap *cap;
+
+ cap = __ao2_alloc_debug(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(tag, "ast_format_cap_alloc"), file, line, func, 1);
if (!cap) {
return NULL;
}
- ao2_ref(cap->formats, -1);
- ast_free(cap);
- return NULL;
-}
-static void format_cap_add(struct ast_format_cap *cap, const 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);
- ao2_link(cap->formats, fnew);
+ format_cap_init(cap, flags);
- ao2_ref(fnew, -1);
+ return cap;
}
-void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format)
+void ast_format_cap_set_framing(struct ast_format_cap *cap, unsigned int framing)
{
- format_cap_add(cap, format);
- cap->string_cache_valid = 0;
+ cap->framing = framing;
}
-void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type)
+/*! \brief Destructor for format capabilities framed structure */
+static void format_cap_framed_destroy(void *obj)
{
- int x;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
+ struct format_cap_framed *framed = obj;
- for (x = 0; x < f_len; x++) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) == type) {
- format_cap_add(cap, &f_list[x].format);
- }
- }
- cap->string_cache_valid = 0;
- ast_format_list_destroy(f_list);
+ ao2_cleanup(framed->format);
}
-void ast_format_cap_add_all(struct ast_format_cap *cap)
+static inline int format_cap_framed_init(struct format_cap_framed *framed, struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
{
- int x;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
+ struct format_cap_framed_list *list;
- for (x = 0; x < f_len; x++) {
- format_cap_add(cap, &f_list[x].format);
+ framed->framing = framing;
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
+ if (AST_VECTOR_INSERT(&cap->formats, ast_format_get_codec_id(format), format_cap_framed_list_empty)) {
+ ao2_ref(framed, -1);
+ return -1;
+ }
}
- cap->string_cache_valid = 0;
- ast_format_list_destroy(f_list);
-}
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
-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;
+ /* Order doesn't matter for formats, so insert at the head for performance reasons */
+ ao2_ref(framed, +1);
+ AST_LIST_INSERT_HEAD(list, framed, entry);
- if (!ast_format_cap_iscompatible(result, format)) {
- format_cap_add(result, format);
- }
+ /* This takes the allocation reference */
+ AST_VECTOR_APPEND(&cap->preference_order, framed);
+
+ cap->framing = MIN(cap->framing, framing ? framing : ast_format_get_default_ms(format));
return 0;
}
-void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src)
+/*! \internal \brief Determine if \c format is in \c cap */
+static int format_in_format_cap(struct ast_format_cap *cap, struct ast_format *format)
{
- ao2_callback(src->formats, OBJ_NODATA, append_cb, dst);
- dst->string_cache_valid = 0;
-}
+ struct format_cap_framed *framed;
+ int i;
-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;
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); i++) {
+ framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ if (ast_format_get_codec_id(format) == ast_format_get_codec_id(framed->format)) {
+ return 1;
+ }
+ }
- format_cap_add(result, format);
return 0;
}
-static void format_cap_remove_all(struct ast_format_cap *cap)
+int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
{
- ao2_callback(cap->formats, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, NULL, NULL);
-}
+ struct format_cap_framed *framed;
-void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src)
-{
- format_cap_remove_all(dst);
- ao2_callback(src->formats, OBJ_NODATA, copy_cb, dst);
- dst->string_cache_valid = 0;
-}
+ ast_assert(format != NULL);
-struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *cap)
-{
- struct ast_format_cap *dst;
+ if (format_in_format_cap(cap, format)) {
+ return 0;
+ }
- dst = ast_format_cap_alloc(ast_test_flag(&cap->flags, AST_FLAGS_ALL));
- if (!dst) {
- return NULL;
+ framed = ao2_alloc_options(sizeof(*framed), format_cap_framed_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!framed) {
+ return -1;
}
- ao2_callback(cap->formats, OBJ_NODATA, copy_cb, dst);
- dst->string_cache_valid = 0;
- return dst;
+ framed->format = ao2_bump(format);
+
+ return format_cap_framed_init(framed, cap, format, framing);
}
-int ast_format_cap_is_empty(const struct ast_format_cap *cap)
+int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func)
{
- if (!cap) {
- return 1;
+ struct format_cap_framed *framed;
+
+ ast_assert(format != NULL);
+
+ if (format_in_format_cap(cap, format)) {
+ return 0;
}
- 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;
+ framed = ao2_alloc_options(sizeof(*framed), format_cap_framed_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!framed) {
+ return -1;
+ }
- return (ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL) ? CMP_MATCH : 0;
+ __ao2_ref_debug(format, +1, S_OR(tag, "ast_format_cap_append"), file, line, func);
+ framed->format = format;
+
+ return format_cap_framed_init(framed, cap, format, framing);
}
-int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
+int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ast_format *fremove;
+ int id;
- fremove = ao2_callback(cap->formats, OBJ_POINTER | OBJ_UNLINK, find_exact_cb, format);
- if (fremove) {
- ao2_ref(fremove, -1);
- cap->string_cache_valid = 0;
- return 0;
+ for (id = 1; id < ast_codec_get_max(); ++id) {
+ struct ast_codec *codec = ast_codec_get_by_id(id);
+ struct ast_format *format;
+ int res;
+
+ if (!codec) {
+ continue;
+ }
+
+ if ((type != AST_MEDIA_TYPE_UNKNOWN) && codec->type != type) {
+ ao2_ref(codec, -1);
+ continue;
+ }
+
+ format = ast_format_create(codec);
+ ao2_ref(codec, -1);
+
+ if (!format) {
+ return -1;
+ }
+
+ /* Use the global framing or default framing of the codec */
+ res = ast_format_cap_append(cap, format, 0);
+ ao2_ref(format, -1);
+
+ if (res) {
+ return -1;
+ }
}
- return -1;
+ return 0;
}
-struct multiple_by_id_data {
- struct ast_format *format;
- int match_found;
-};
-
-static int multiple_by_id_cb(void *obj, void *arg, int flag)
+int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src,
+ enum ast_media_type type)
{
- struct multiple_by_id_data *data = arg;
- struct ast_format *format = obj;
- int res;
+ int idx, res = 0;
+
+ for (idx = 0; (idx < AST_VECTOR_SIZE(&src->preference_order)) && !res; ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&src->preference_order, idx);
- res = (format->id == data->format->id) ? CMP_MATCH : 0;
- if (res) {
- data->match_found = 1;
+ if (type == AST_MEDIA_TYPE_UNKNOWN || ast_format_get_type(framed->format) == type) {
+ res = ast_format_cap_append(dst, framed->format, framed->framing);
+ }
}
return res;
}
-int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id)
+static int format_cap_replace(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
{
- struct ast_format format = {
- .id = id,
- };
- struct multiple_by_id_data data = {
- .format = &format,
- .match_found = 0,
- };
-
- ao2_callback(cap->formats,
- OBJ_NODATA | 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) {
- cap->string_cache_valid = 0;
- return 0;
+ struct format_cap_framed *framed;
+ int i;
+
+ ast_assert(format != NULL);
+
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); i++) {
+ framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ if (ast_format_get_codec_id(format) == ast_format_get_codec_id(framed->format)) {
+ ao2_t_replace(framed->format, format, "replacing with new format");
+ framed->framing = framing;
+ return 0;
+ }
}
return -1;
}
-static int multiple_by_type_cb(void *obj, void *arg, int flag)
+void ast_format_cap_replace_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src,
+ enum ast_media_type type)
{
- int *type = arg;
- struct ast_format *format = obj;
- return ((AST_FORMAT_GET_TYPE(format->id)) == *type) ? CMP_MATCH : 0;
-}
+ int idx;
-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,
- multiple_by_type_cb,
- &type);
- cap->string_cache_valid = 0;
+ for (idx = 0; (idx < AST_VECTOR_SIZE(&src->preference_order)); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&src->preference_order, idx);
+
+ if (type == AST_MEDIA_TYPE_UNKNOWN || ast_format_get_type(framed->format) == type) {
+ format_cap_replace(dst, framed->format, framed->framing);
+ }
+ }
}
-void ast_format_cap_remove_all(struct ast_format_cap *cap)
+int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
{
- format_cap_remove_all(cap);
- cap->string_cache_valid = 0;
+ int res = 0, all = 0, iter_allowing;
+ char *parse = NULL, *this = NULL, *psize = NULL;
+
+ parse = ast_strdupa(list);
+ while ((this = strsep(&parse, ","))) {
+ int framems = 0;
+ struct ast_format *format = NULL;
+
+ iter_allowing = allowing;
+ if (*this == '!') {
+ this++;
+ iter_allowing = !allowing;
+ }
+ if ((psize = strrchr(this, ':'))) {
+ *psize++ = '\0';
+ ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
+ if (!sscanf(psize, "%30d", &framems) || (framems < 0)) {
+ framems = 0;
+ res = -1;
+ ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
+ continue;
+ }
+ }
+ all = strcasecmp(this, "all") ? 0 : 1;
+
+ if (!all && !(format = ast_format_cache_get(this))) {
+ ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", iter_allowing ? "allow" : "disallow", this);
+ res = -1;
+ continue;
+ }
+
+ if (cap) {
+ if (iter_allowing) {
+ if (all) {
+ ast_format_cap_append_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append(cap, format, framems);
+ }
+ } else {
+ if (all) {
+ ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_remove(cap, format);
+ }
+ }
+ }
+
+ ao2_cleanup(format);
+ }
+ return res;
}
-void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format)
+size_t ast_format_cap_count(const struct ast_format_cap *cap)
{
- format_cap_remove_all(cap);
- format_cap_add(cap, format);
- cap->string_cache_valid = 0;
+ return AST_VECTOR_SIZE(&cap->preference_order);
}
-int ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format, struct ast_format *result)
+struct ast_format *ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
{
- struct ast_format *f;
- struct ast_format_cap *tmp_cap = (struct ast_format_cap *) cap;
+ struct format_cap_framed *framed;
+
+ ast_assert(position < AST_VECTOR_SIZE(&cap->preference_order));
- f = ao2_find(tmp_cap->formats, format, OBJ_POINTER);
- if (f) {
- ast_format_copy(result, f);
- ao2_ref(f, -1);
- return 1;
+ if (position >= AST_VECTOR_SIZE(&cap->preference_order)) {
+ return NULL;
}
- ast_format_clear(result);
- return 0;
+
+ framed = AST_VECTOR_GET(&cap->preference_order, position);
+
+ ast_assert(framed->format != ast_format_none);
+ ao2_ref(framed->format, +1);
+ return framed->format;
}
-int ast_format_cap_iscompatible(const struct ast_format_cap *cap, const struct ast_format *format)
+struct ast_format *ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ast_format *f;
- struct ast_format_cap *tmp_cap = (struct ast_format_cap *) cap;
+ int i;
- if (!tmp_cap) {
- return 0;
+ if (type == AST_MEDIA_TYPE_UNKNOWN) {
+ return ast_format_cap_get_format(cap, 0);
}
- f = ao2_find(tmp_cap->formats, format, OBJ_POINTER);
- if (f) {
- ao2_ref(f, -1);
- return 1;
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); i++) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ if (ast_format_get_type(framed->format) == type) {
+ ao2_ref(framed->format, +1);
+ ast_assert(framed->format != ast_format_none);
+ return framed->format;
+ }
}
- return 0;
+ return NULL;
}
-struct byid_data {
- struct ast_format *result;
- enum ast_format_id id;
-};
-static int find_best_byid_cb(void *obj, void *arg, int flag)
+unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
{
- struct ast_format *format = obj;
- struct byid_data *data = arg;
+ return (cap->framing != UINT_MAX) ? cap->framing : 0;
+}
- if (data->id != format->id) {
+unsigned int ast_format_cap_get_format_framing(const struct ast_format_cap *cap, const struct ast_format *format)
+{
+ unsigned int framing;
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed, *result = NULL;
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
return 0;
}
- if (!data->result->id || (ast_format_rate(data->result) < ast_format_rate(format))) {
- ast_format_copy(data->result, format);
+
+ framing = cap->framing != UINT_MAX ? cap->framing : ast_format_get_default_ms(format);
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
+
+ AST_LIST_TRAVERSE(list, framed, entry) {
+ enum ast_format_cmp_res res = ast_format_cmp(format, framed->format);
+
+ if (res == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
+ }
+
+ result = framed;
+
+ if (res == AST_FORMAT_CMP_EQUAL) {
+ break;
+ }
}
- return 0;
-}
-int ast_format_cap_best_byid(const struct ast_format_cap *cap, enum ast_format_id id, struct ast_format *result)
-{
- struct byid_data data;
- data.result = result;
- data.id = id;
-
- ast_format_clear(result);
- ao2_callback(cap->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_best_byid_cb,
- &data);
- return result->id ? 1 : 0;
+ if (result && result->framing) {
+ framing = result->framing;
+ }
+
+ return framing;
}
-/*! \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.
+/*!
+ * \brief format_cap_framed comparator for AST_VECTOR_REMOVE_CMP_ORDERED()
+ *
+ * \param elem Element to compare against
+ * \param value Value to compare with the vector element.
+ *
+ * \return 0 if element does not match.
+ * \return Non-zero if element matches.
*/
-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;
-};
+#define FORMAT_CAP_FRAMED_ELEM_CMP(elem, value) ((elem)->format == (value))
-static int find_joint_cb(void *obj, void *arg, int flag)
+/*!
+ * \brief format_cap_framed vector element cleanup.
+ *
+ * \param elem Element to cleanup
+ *
+ * \return Nothing
+ */
+#define FORMAT_CAP_FRAMED_ELEM_CLEANUP(elem) ao2_cleanup((elem))
+
+int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
{
- struct ast_format *format = obj;
- struct find_joint_data *data = arg;
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed;
- 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++;
+ ast_assert(format != NULL);
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
+ return -1;
}
- return 0;
-}
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
-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, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- data.format = tmp;
- ao2_callback(cap2->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_joint_cb,
- &data);
- ao2_ref(tmp, -1);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(list, framed, entry) {
+ if (!FORMAT_CAP_FRAMED_ELEM_CMP(framed, format)) {
+ continue;
+ }
+
+ AST_LIST_REMOVE_CURRENT(entry);
+ FORMAT_CAP_FRAMED_ELEM_CLEANUP(framed);
+ break;
}
- ao2_iterator_destroy(&it);
+ AST_LIST_TRAVERSE_SAFE_END;
- return data.joint_found ? 1 : 0;
+ return AST_VECTOR_REMOVE_CMP_ORDERED(&cap->preference_order, format,
+ FORMAT_CAP_FRAMED_ELEM_CMP, FORMAT_CAP_FRAMED_ELEM_CLEANUP);
}
-int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
+void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ao2_iterator it;
- struct ast_format *tmp;
+ int idx;
- if (ao2_container_count(cap1->formats) != ao2_container_count(cap2->formats)) {
- return 0; /* if they are not the same size, they are not identical */
- }
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->formats); ++idx) {
+ struct format_cap_framed_list *list = AST_VECTOR_GET_ADDR(&cap->formats, idx);
+ struct format_cap_framed *framed;
- it = ao2_iterator_init(cap1->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- if (!ast_format_cap_iscompatible(cap2, tmp)) {
- ao2_ref(tmp, -1);
- ao2_iterator_destroy(&it);
- return 0;
+ AST_LIST_TRAVERSE_SAFE_BEGIN(list, framed, entry) {
+ if ((type != AST_MEDIA_TYPE_UNKNOWN) &&
+ ast_format_get_type(framed->format) != type) {
+ continue;
+ }
+
+ AST_LIST_REMOVE_CURRENT(entry);
+ AST_VECTOR_REMOVE_CMP_ORDERED(&cap->preference_order, framed->format,
+ FORMAT_CAP_FRAMED_ELEM_CMP, FORMAT_CAP_FRAMED_ELEM_CLEANUP);
+ ao2_ref(framed, -1);
}
- ao2_ref(tmp, -1);
+ AST_LIST_TRAVERSE_SAFE_END;
}
- 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 ast_format *ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
{
- struct ao2_iterator it;
- struct ast_format_cap *result = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format *tmp;
- struct find_joint_data data = {
- .joint_found = 0,
- .joint_cap = result,
- };
- if (!result) {
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed;
+ struct ast_format *result = NULL;
+
+ ast_assert(format != NULL);
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
return NULL;
}
- it = ao2_iterator_init(cap1->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- data.format = tmp;
- ao2_callback(cap2->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_joint_cb,
- &data);
- ao2_ref(tmp, -1);
- }
- ao2_iterator_destroy(&it);
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
- if (ao2_container_count(result->formats)) {
- return result;
- }
+ AST_LIST_TRAVERSE(list, framed, entry) {
+ enum ast_format_cmp_res res = ast_format_cmp(format, framed->format);
- result = ast_format_cap_destroy(result);
- return NULL;
-}
+ if (res == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
+ }
-static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result, int append)
-{
- struct ao2_iterator it;
- struct ast_format *tmp;
- struct find_joint_data data = {
- .joint_cap = result,
- .joint_found = 0,
- };
- if (!append) {
- format_cap_remove_all(result);
- }
- it = ao2_iterator_init(cap1->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- data.format = tmp;
- ao2_callback(cap2->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_joint_cb,
- &data);
- ao2_ref(tmp, -1);
- }
- ao2_iterator_destroy(&it);
+ /* Replace any current result, this one will also be a subset OR an exact match */
+ ao2_cleanup(result);
- result->string_cache_valid = 0;
+ result = ast_format_joint(format, framed->format);
- return ao2_container_count(result->formats) ? 1 : 0;
-}
+ /* If it's a match we can do no better so return asap */
+ if (res == AST_FORMAT_CMP_EQUAL) {
+ break;
+ }
+ }
-int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
-{
- return joint_copy_helper(cap1, cap2, result, 1);
+ return result;
}
-int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
+enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap,
+ const struct ast_format *format)
{
- return joint_copy_helper(cap1, cap2, result, 0);
-}
+ enum ast_format_cmp_res res = AST_FORMAT_CMP_NOT_EQUAL;
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed;
-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(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format *tmp;
+ ast_assert(format != NULL);
- if (!result) {
- return NULL;
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
}
- /* 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, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- if (AST_FORMAT_GET_TYPE(tmp->id) == ftype) {
- /* copy format */
- ast_format_cap_add(result, tmp);
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
+
+ AST_LIST_TRAVERSE(list, framed, entry) {
+ enum ast_format_cmp_res cmp = ast_format_cmp(format, framed->format);
+
+ if (cmp == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
}
- ao2_ref(tmp, -1);
- }
- ao2_iterator_destroy(&it);
- if (ao2_container_count(result->formats)) {
- return result;
+ res = cmp;
+
+ if (res == AST_FORMAT_CMP_EQUAL) {
+ break;
+ }
}
- result = ast_format_cap_destroy(result);
- return NULL;
+ return res;
}
-
-int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type)
+int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ao2_iterator it;
- struct ast_format *tmp;
+ int idx;
- it = ao2_iterator_init(cap->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- if (AST_FORMAT_GET_TYPE(tmp->id) == type) {
- ao2_ref(tmp, -1);
- ao2_iterator_destroy(&it);
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->preference_order); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, idx);
+
+ if (ast_format_get_type(framed->format) == type) {
return 1;
}
- ao2_ref(tmp, -1);
}
- ao2_iterator_destroy(&it);
return 0;
}
-void ast_format_cap_iter_start(struct ast_format_cap *cap)
+int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2,
+ struct ast_format_cap *result)
{
- /* We can unconditionally lock even if the container has no lock. */
- ao2_lock(cap->formats);
- cap->it = ao2_iterator_init(cap->formats, AO2_ITERATOR_DONTLOCK);
-}
+ int idx, res = 0;
-void ast_format_cap_iter_end(struct ast_format_cap *cap)
-{
- ao2_iterator_destroy(&cap->it);
- /* We can unconditionally unlock even if the container has no lock. */
- ao2_unlock(cap->formats);
-}
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap1->preference_order); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap1->preference_order, idx);
+ struct ast_format *format;
-int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format)
-{
- struct ast_format *tmp = ao2_iterator_next(&cap->it);
+ format = ast_format_cap_get_compatible_format(cap2, framed->format);
+ if (!format) {
+ continue;
+ }
- if (!tmp) {
- return -1;
+ res = ast_format_cap_append(result, format, framed->framing);
+ ao2_ref(format, -1);
+
+ if (res) {
+ break;
+ }
}
- ast_format_copy(format, tmp);
- ao2_ref(tmp, -1);
- return 0;
+ return res;
}
-static char *getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
+int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
- int x;
- unsigned len;
- char *start, *end = buf;
- struct ast_format tmp_fmt;
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- if (!size) {
- f_list = ast_format_list_destroy(f_list);
- return buf;
- }
- snprintf(end, size, "(");
- len = strlen(end);
- end += len;
- size -= len;
- start = end;
- for (x = 0; x < f_len; x++) {
- ast_format_copy(&tmp_fmt, &f_list[x].format);
- if (ast_format_cap_iscompatible(cap, &tmp_fmt)) {
- snprintf(end, size, "%s|", f_list[x].name);
- len = strlen(end);
- end += len;
- size -= len;
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap1->preference_order); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap1->preference_order, idx);
+
+ if (ast_format_cap_iscompatible_format(cap2, framed->format) != AST_FORMAT_CMP_NOT_EQUAL) {
+ return 1;
}
}
- if (start == end) {
- ast_copy_string(start, "nothing)", size);
- } else if (size > 1) {
- *(end - 1) = ')';
- }
- f_list = ast_format_list_destroy(f_list);
- return buf;
+
+ return 0;
}
-char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
+static int internal_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
- if (ast_test_flag(&cap->flags, AST_FORMAT_CAP_FLAG_CACHE_STRINGS)) {
- if (!cap->string_cache_valid) {
- getformatname_multiple(cap->format_strs, FORMAT_STR_BUFSIZE, cap);
- cap->string_cache_valid = 1;
+ int idx;
+ struct ast_format *tmp;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap1->preference_order); ++idx) {
+ tmp = ast_format_cap_get_format(cap1, idx);
+
+ if (ast_format_cap_iscompatible_format(cap2, tmp) != AST_FORMAT_CMP_EQUAL) {
+ ao2_ref(tmp, -1);
+ return 0;
}
- ast_copy_string(buf, cap->format_strs, size);
- return buf;
+
+ ao2_ref(tmp, -1);
}
- return getformatname_multiple(buf, size, cap);
+ return 1;
}
-uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap)
+int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
- uint64_t res = 0;
- struct ao2_iterator it;
- struct ast_format *tmp;
+ if (AST_VECTOR_SIZE(&cap1->preference_order) != AST_VECTOR_SIZE(&cap2->preference_order)) {
+ return 0; /* if they are not the same size, they are not identical */
+ }
- it = ao2_iterator_init(cap->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- res |= ast_format_to_old_bitfield(tmp);
- ao2_ref(tmp, -1);
+ if (!internal_format_cap_identical(cap1, cap2)) {
+ return 0;
}
- ao2_iterator_destroy(&it);
- return res;
+
+ return internal_format_cap_identical(cap2, cap1);
}
-void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src)
+const char *ast_format_cap_get_names(struct ast_format_cap *cap, struct ast_str **buf)
{
- uint64_t tmp = 0;
- int x;
- struct ast_format tmp_format = { 0, };
-
- format_cap_remove_all(dst);
- for (x = 0; x < 64; x++) {
- tmp = (1ULL << x);
- if (tmp & src) {
- format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp));
+ int i;
+
+ ast_str_set(buf, 0, "(");
+
+ if (!AST_VECTOR_SIZE(&cap->preference_order)) {
+ ast_str_append(buf, 0, "nothing)");
+ return ast_str_buffer(*buf);
+ }
+
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); ++i) {
+ int res;
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ res = ast_str_append(buf, 0, "%s%s", ast_format_get_name(framed->format),
+ i < AST_VECTOR_SIZE(&cap->preference_order) - 1 ? "|" : "");
+ if (res < 0) {
+ break;
}
}
- dst->string_cache_valid = 0;
+ ast_str_append(buf, 0, ")");
+
+ return ast_str_buffer(*buf);
}
diff --git a/main/format_compatibility.c b/main/format_compatibility.c
new file mode 100644
index 000000000..df82bacd5
--- /dev/null
+++ b/main/format_compatibility.c
@@ -0,0 +1,274 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cache.h"
+
+uint64_t ast_format_compatibility_format2bitfield(const struct ast_format *format)
+{
+ if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G723;
+ } else if (ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_GSM;
+ } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ULAW;
+ } else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ALAW;
+ } else if (ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G726_AAL2;
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ADPCM;
+ } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SLIN;
+ } else if (ast_format_cmp(format, ast_format_lpc10) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_LPC10;
+ } else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G729;
+ } else if (ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SPEEX;
+ } else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ILBC;
+ } else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G726;
+ } else if (ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G722;
+ } else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SIREN7;
+ } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SIREN14;
+ } else if (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SLIN16;
+ } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G719;
+ } else if (ast_format_cmp(format, ast_format_speex16) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SPEEX16;
+ } else if (ast_format_cmp(format, ast_format_opus) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_OPUS;
+ } else if (ast_format_cmp(format, ast_format_testlaw) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_TESTLAW;
+ } else if (ast_format_cmp(format, ast_format_h261) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H261;
+ } else if (ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H263;
+ } else if (ast_format_cmp(format, ast_format_h263p) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H263P;
+ } else if (ast_format_cmp(format, ast_format_h264) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H264;
+ } else if (ast_format_cmp(format, ast_format_mp4) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_MP4;
+ } else if (ast_format_cmp(format, ast_format_vp8) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_VP8;
+ } else if (ast_format_cmp(format, ast_format_jpeg) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_JPEG;
+ } else if (ast_format_cmp(format, ast_format_png) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_PNG;
+ } else if (ast_format_cmp(format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_T140_RED;
+ } else if (ast_format_cmp(format, ast_format_t140) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_T140;
+ }
+
+ return 0;
+}
+
+uint64_t ast_format_compatibility_codec2bitfield(const struct ast_codec *codec)
+{
+ if (codec->id == ast_format_get_codec_id(ast_format_g723)) {
+ return AST_FORMAT_G723;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_gsm)) {
+ return AST_FORMAT_GSM;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_ulaw)) {
+ return AST_FORMAT_ULAW;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_alaw)) {
+ return AST_FORMAT_ALAW;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g726_aal2)) {
+ return AST_FORMAT_G726_AAL2;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_adpcm)) {
+ return AST_FORMAT_ADPCM;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_slin)) {
+ return AST_FORMAT_SLIN;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_lpc10)) {
+ return AST_FORMAT_LPC10;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g729)) {
+ return AST_FORMAT_G729;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_speex)) {
+ return AST_FORMAT_SPEEX;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_ilbc)) {
+ return AST_FORMAT_ILBC;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g726)) {
+ return AST_FORMAT_G726;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g722)) {
+ return AST_FORMAT_G722;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_siren7)) {
+ return AST_FORMAT_SIREN7;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_siren14)) {
+ return AST_FORMAT_SIREN14;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_slin16)) {
+ return AST_FORMAT_SLIN16;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g719)) {
+ return AST_FORMAT_G719;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_speex16)) {
+ return AST_FORMAT_SPEEX16;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_opus)) {
+ return AST_FORMAT_OPUS;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_testlaw)) {
+ return AST_FORMAT_TESTLAW;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h261)) {
+ return AST_FORMAT_H261;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h263)) {
+ return AST_FORMAT_H263;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h263p)) {
+ return AST_FORMAT_H263P;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h264)) {
+ return AST_FORMAT_H264;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_mp4)) {
+ return AST_FORMAT_MP4;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_vp8)) {
+ return AST_FORMAT_VP8;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_jpeg)) {
+ return AST_FORMAT_JPEG;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_png)) {
+ return AST_FORMAT_PNG;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_t140_red)) {
+ return AST_FORMAT_T140_RED;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_t140)) {
+ return AST_FORMAT_T140;
+ }
+
+ return 0;
+}
+
+struct ast_format *ast_format_compatibility_bitfield2format(uint64_t bitfield)
+{
+ switch (bitfield) {
+ /*! G.723.1 compression */
+ case AST_FORMAT_G723:
+ return ast_format_g723;
+ /*! GSM compression */
+ case AST_FORMAT_GSM:
+ return ast_format_gsm;
+ /*! Raw mu-law data (G.711) */
+ case AST_FORMAT_ULAW:
+ return ast_format_ulaw;
+ /*! Raw A-law data (G.711) */
+ case AST_FORMAT_ALAW:
+ return ast_format_alaw;
+ /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
+ case AST_FORMAT_G726_AAL2:
+ return ast_format_g726_aal2;
+ /*! ADPCM (IMA) */
+ case AST_FORMAT_ADPCM:
+ return ast_format_adpcm;
+ /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
+ case AST_FORMAT_SLIN:
+ return ast_format_slin;
+ /*! LPC10, 180 samples/frame */
+ case AST_FORMAT_LPC10:
+ return ast_format_lpc10;
+ /*! G.729A audio */
+ case AST_FORMAT_G729:
+ return ast_format_g729;
+ /*! SpeeX Free Compression */
+ case AST_FORMAT_SPEEX:
+ return ast_format_speex;
+ /*! iLBC Free Compression */
+ case AST_FORMAT_ILBC:
+ return ast_format_ilbc;
+ /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
+ case AST_FORMAT_G726:
+ return ast_format_g726;
+ /*! G.722 */
+ case AST_FORMAT_G722:
+ return ast_format_g722;
+ /*! G.722.1 (also known as Siren7, 32kbps assumed) */
+ case AST_FORMAT_SIREN7:
+ return ast_format_siren7;
+ /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
+ case AST_FORMAT_SIREN14:
+ return ast_format_siren14;
+ /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
+ case AST_FORMAT_SLIN16:
+ return ast_format_slin16;
+ /*! G.719 (64 kbps assumed) */
+ case AST_FORMAT_G719:
+ return ast_format_g719;
+ /*! SpeeX Wideband (16kHz) Free Compression */
+ case AST_FORMAT_SPEEX16:
+ return ast_format_speex16;
+ /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
+ case AST_FORMAT_OPUS:
+ return ast_format_opus;
+ /*! Raw mu-law data (G.711) */
+ case AST_FORMAT_TESTLAW:
+ return ast_format_testlaw;
+
+ /*! H.261 Video */
+ case AST_FORMAT_H261:
+ return ast_format_h261;
+ /*! H.263 Video */
+ case AST_FORMAT_H263:
+ return ast_format_h263;
+ /*! H.263+ Video */
+ case AST_FORMAT_H263P:
+ return ast_format_h263p;
+ /*! H.264 Video */
+ case AST_FORMAT_H264:
+ return ast_format_h264;
+ /*! MPEG4 Video */
+ case AST_FORMAT_MP4:
+ return ast_format_mp4;
+ /*! VP8 Video */
+ case AST_FORMAT_VP8:
+ return ast_format_vp8;
+
+ /*! JPEG Images */
+ case AST_FORMAT_JPEG:
+ return ast_format_jpeg;
+ /*! PNG Images */
+ case AST_FORMAT_PNG:
+ return ast_format_png;
+
+ /*! T.140 RED Text format RFC 4103 */
+ case AST_FORMAT_T140_RED:
+ return ast_format_t140;
+ /*! T.140 Text format - ITU T.140, RFC 4103 */
+ case AST_FORMAT_T140:
+ return ast_format_t140_red;
+ }
+ return 0;
+}
+
diff --git a/main/format_pref.c b/main/format_pref.c
deleted file mode 100644
index b96184a08..000000000
--- a/main/format_pref.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * 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
- */
-
-/*** MODULEINFO
- <support_level>core</support_level>
- ***/
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
-
-#include "asterisk/_private.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_format_list_get(&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_copy(&pref->formats[x], &f_list[to[x]-1].format);
- }
- }
- ast_format_list_destroy(f_list);
-}
-
-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;
- const 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;
-
- if (!pref->order[0]) {
- return;
- }
-
- f_list = ast_format_list_get(&f_len);
- memcpy(&oldorder, pref, sizeof(oldorder));
- memset(pref, 0, sizeof(*pref));
-
- for (x = 0; x < f_len; x++) {
- if (!oldorder.order[x]) {
- break;
- }
- if (ast_format_cmp(&f_list[oldorder.order[x]-1].format, format) == AST_FORMAT_CMP_NOT_EQUAL) {
- pref->order[y] = oldorder.order[x];
- ast_format_copy(&pref->formats[y], &oldorder.formats[x]);
- pref->framing[y++] = oldorder.framing[x];
- }
- }
- ast_format_list_destroy(f_list);
-}
-
-/*! \brief Append all codecs to a preference list, without distrubing existing order */
-void ast_codec_pref_append_all(struct ast_codec_pref *pref)
-{
- int x, y, found;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- /* leave any existing entries, and don't create duplicates (e.g. allow=ulaw,all) */
- for (x = 0; x < f_len; x++) {
- /* x = codec to add */
- found = 0;
- for (y = 0; y < f_len; y++) {
- /* y = scan of existing preferences */
- if (!pref->order[y]) {
- break;
- }
- if (x + 1 == pref->order[y]) {
- found = 1;
- break;
- }
- }
- if (found) {
- continue;
- }
- for (; y < f_len; y++) {
- /* add x to the end of y */
- if (!pref->order[y])
- {
- pref->order[y] = x + 1;
- ast_format_copy(&pref->formats[y], &f_list[x].format);
- break;
- }
- }
- }
-}
-
-/*! \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_format_list_get(&f_len);
-
- ast_codec_pref_remove(pref, format);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- 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;
- }
- }
- }
-
- ast_format_list_destroy(f_list);
- 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_format_list_get(&f_len);
-
- /* First step is to get the codecs "index number" */
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- newindex = x + 1;
- break;
- }
- }
- /* Done if its unknown */
- if (!newindex) {
- ast_format_list_destroy(f_list);
- 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 we failed to find any occurrence, set to the end */
- if (x == AST_CODEC_PREF_SIZE) {
- --x;
- }
-
- if (only_if_existing && !pref->order[x]) {
- ast_format_list_destroy(f_list);
- 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);
- ast_format_list_destroy(f_list);
-}
-
-/*! \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_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- idx = x;
- break;
- }
- }
-
- if (idx < 0) {
- ast_format_list_destroy(f_list);
- 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;
- }
- }
-
- ast_format_list_destroy(f_list);
- 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_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- fmt = f_list[x];
- idx = x;
- break;
- }
- }
-
- if (idx < 0) {
- ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format));
- ast_format_list_destroy(f_list);
- return fmt;
- }
-
- 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;
- ast_format_list_destroy(f_list);
- 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 = 0;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- slot = pref->order[x];
-
- if (!slot)
- break;
- if (ast_format_cap_get_compatible_format(cap, &f_list[slot-1].format, result)) {
- found = 1; /*format is found and stored in result */
- break;
- }
- }
- ast_format_list_destroy(f_list);
- if (found && (AST_FORMAT_GET_TYPE(result->id) == AST_FORMAT_TYPE_AUDIO)) {
- return result;
- }
- ast_format_clear(result);
- ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
-
- return find_best ? ast_best_codec(cap, result) : NULL;
-}
-
-
diff --git a/main/frame.c b/main/frame.c
index 76ea3f66c..64af88237 100644
--- a/main/frame.c
+++ b/main/frame.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
@@ -71,199 +72,8 @@ struct ast_frame_cache {
};
#endif
-#define SMOOTHER_SIZE 8000
-
-enum frame_type {
- TYPE_HIGH, /* 0x0 */
- TYPE_LOW, /* 0x1 */
- TYPE_SILENCE, /* 0x2 */
- TYPE_DONTSEND /* 0x3 */
-};
-
-#define TYPE_MASK 0x3
-
-struct ast_smoother {
- int size;
- struct ast_format format;
- int flags;
- float samplesperbyte;
- unsigned int opt_needs_swap:1;
- struct ast_frame f;
- struct timeval delivery;
- char data[SMOOTHER_SIZE];
- char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
- struct ast_frame *opt;
- int len;
-};
-
struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
-static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
-{
- if (s->flags & AST_SMOOTHER_FLAG_G729) {
- if (s->len % 10) {
- ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
- return 0;
- }
- }
- if (swap) {
- ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
- } else {
- memcpy(s->data + s->len, f->data.ptr, f->datalen);
- }
- /* If either side is empty, reset the delivery time */
- if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) { /* XXX really ? */
- s->delivery = f->delivery;
- }
- s->len += f->datalen;
-
- return 0;
-}
-
-void ast_smoother_reset(struct ast_smoother *s, int bytes)
-{
- memset(s, 0, sizeof(*s));
- s->size = bytes;
-}
-
-void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
-{
- /* if there is no change, then nothing to do */
- if (s->size == bytes) {
- return;
- }
- /* set the new desired output size */
- s->size = bytes;
- /* if there is no 'optimized' frame in the smoother,
- * then there is nothing left to do
- */
- if (!s->opt) {
- return;
- }
- /* there is an 'optimized' frame here at the old size,
- * but it must now be put into the buffer so the data
- * can be extracted at the new size
- */
- smoother_frame_feed(s, s->opt, s->opt_needs_swap);
- s->opt = NULL;
-}
-
-struct ast_smoother *ast_smoother_new(int size)
-{
- struct ast_smoother *s;
- if (size < 1)
- return NULL;
- if ((s = ast_malloc(sizeof(*s))))
- ast_smoother_reset(s, size);
- return s;
-}
-
-int ast_smoother_get_flags(struct ast_smoother *s)
-{
- return s->flags;
-}
-
-void ast_smoother_set_flags(struct ast_smoother *s, int flags)
-{
- s->flags = flags;
-}
-
-int ast_smoother_test_flag(struct ast_smoother *s, int flag)
-{
- return (s->flags & flag);
-}
-
-int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
-{
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
- return -1;
- }
- if (!s->format.id) {
- ast_format_copy(&s->format, &f->subclass.format);
- s->samplesperbyte = (float)f->samples / (float)f->datalen;
- } 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.format));
- return -1;
- }
- if (s->len + f->datalen > SMOOTHER_SIZE) {
- ast_log(LOG_WARNING, "Out of smoother space\n");
- return -1;
- }
- if (((f->datalen == s->size) ||
- ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
- !s->opt &&
- !s->len &&
- (f->offset >= AST_MIN_OFFSET)) {
- /* Optimize by sending the frame we just got
- on the next read, thus eliminating the douple
- copy */
- if (swap)
- ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
- s->opt = f;
- s->opt_needs_swap = swap ? 1 : 0;
- return 0;
- }
-
- return smoother_frame_feed(s, f, swap);
-}
-
-struct ast_frame *ast_smoother_read(struct ast_smoother *s)
-{
- struct ast_frame *opt;
- int len;
-
- /* IF we have an optimization frame, send it */
- if (s->opt) {
- if (s->opt->offset < AST_FRIENDLY_OFFSET)
- ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
- s->opt->offset);
- opt = s->opt;
- s->opt = NULL;
- return opt;
- }
-
- /* Make sure we have enough data */
- if (s->len < s->size) {
- /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
- if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
- return NULL;
- }
- len = s->size;
- if (len > s->len)
- len = s->len;
- /* Make frame */
- s->f.frametype = AST_FRAME_VOICE;
- 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;
- /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
- s->f.samples = len * s->samplesperbyte; /* XXX rounding */
- s->f.delivery = s->delivery;
- /* Fill Data */
- memcpy(s->f.data.ptr, s->data, len);
- s->len -= len;
- /* Move remaining data to the front if applicable */
- if (s->len) {
- /* In principle this should all be fine because if we are sending
- G.729 VAD, the next timestamp will take over anyawy */
- 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)));
- }
- }
- /* Return frame */
- return &s->f;
-}
-
-void ast_smoother_free(struct ast_smoother *s)
-{
- ast_free(s);
-}
-
static struct ast_frame *ast_frame_header_new(void)
{
struct ast_frame *f;
@@ -316,9 +126,13 @@ static void __frame_free(struct ast_frame *fr, int cache)
/* Cool, only the header is malloc'd, let's just cache those for now
* to keep things simple... */
struct ast_frame_cache *frames;
-
if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
(frames->size < FRAME_CACHE_MAX_SIZE)) {
+ if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
+ (fr->frametype == AST_FRAME_IMAGE)) {
+ ao2_cleanup(fr->subclass.format);
+ }
+
AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
frames->size++;
return;
@@ -335,7 +149,14 @@ static void __frame_free(struct ast_frame *fr, int cache)
ast_free((void *) fr->src);
}
if (fr->mallocd & AST_MALLOCD_HDR) {
+ if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
+ (fr->frametype == AST_FRAME_IMAGE)) {
+ ao2_cleanup(fr->subclass.format);
+ }
+
ast_free(fr);
+ } else {
+ fr->mallocd = 0;
}
}
@@ -387,7 +208,12 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
return NULL;
}
out->frametype = fr->frametype;
- ast_format_copy(&out->subclass.format, &fr->subclass.format);
+ if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
+ (fr->frametype == AST_FRAME_IMAGE)) {
+ out->subclass.format = ao2_bump(fr->subclass.format);
+ } else {
+ memcpy(&out->subclass, &fr->subclass, sizeof(out->subclass));
+ }
out->datalen = fr->datalen;
out->samples = fr->samples;
out->offset = fr->offset;
@@ -494,7 +320,12 @@ struct ast_frame *ast_frdup(const struct ast_frame *f)
}
out->frametype = f->frametype;
- ast_format_copy(&out->subclass.format, &f->subclass.format);
+ if ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO) ||
+ (f->frametype == AST_FRAME_IMAGE)) {
+ out->subclass.format = ao2_bump(f->subclass.format);
+ } else {
+ memcpy(&out->subclass, &f->subclass, sizeof(out->subclass));
+ }
out->datalen = f->datalen;
out->samples = f->samples;
out->delivery = f->delivery;
@@ -650,7 +481,7 @@ void ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, ch
}
break;
case AST_FRAME_IMAGE:
- snprintf(subclass, slen, "Image format %s\n", ast_getformatname(&f->subclass.format));
+ snprintf(subclass, slen, "Image format %s\n", ast_format_get_name(f->subclass.format));
break;
case AST_FRAME_HTML:
switch (f->subclass.integer) {
@@ -816,369 +647,13 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
}
-int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing)
-{
- int errors = 0, framems = 0, all = 0, iter_allowing;
- char *parse = NULL, *this = NULL, *psize = NULL;
- struct ast_format format;
-
- parse = ast_strdupa(list);
- while ((this = strsep(&parse, ","))) {
- iter_allowing = allowing;
- framems = 0;
- if (*this == '!') {
- this++;
- iter_allowing = !allowing;
- }
- if ((psize = strrchr(this, ':'))) {
- *psize++ = '\0';
- ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
- framems = atoi(psize);
- if (framems < 0) {
- framems = 0;
- errors++;
- ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
- }
- }
- all = strcasecmp(this, "all") ? 0 : 1;
-
- if (!all && !ast_getformatbyname(this, &format)) {
- ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", iter_allowing ? "allow" : "disallow", this);
- errors++;
- continue;
- }
-
- if (cap) {
- if (iter_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);
- }
- }
- }
-
- if (pref) {
- if (!all) {
- if (iter_allowing) {
- ast_codec_pref_append(pref, &format);
- ast_codec_pref_setsize(pref, &format, framems);
- } else {
- ast_codec_pref_remove(pref, &format);
- }
- } else if (!iter_allowing) {
- memset(pref, 0, sizeof(*pref));
- } else {
- ast_codec_pref_append_all(pref);
- }
- }
- }
- return errors;
-}
-
-static int g723_len(unsigned char buf)
-{
- enum frame_type type = buf & TYPE_MASK;
-
- switch(type) {
- case TYPE_DONTSEND:
- return 0;
- break;
- case TYPE_SILENCE:
- return 4;
- break;
- case TYPE_HIGH:
- return 24;
- break;
- case TYPE_LOW:
- return 20;
- break;
- default:
- ast_log(LOG_WARNING, "Badly encoded frame (%u)\n", type);
- }
- return -1;
-}
-
-static int g723_samples(unsigned char *buf, int maxlen)
-{
- int pos = 0;
- int samples = 0;
- int res;
- while(pos < maxlen) {
- res = g723_len(buf[pos]);
- if (res <= 0)
- break;
- samples += 240;
- pos += res;
- }
- return samples;
-}
-
-static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
-{
- int byte = bit / 8; /* byte containing first bit */
- int rem = 8 - (bit % 8); /* remaining bits in first byte */
- unsigned char ret = 0;
-
- if (n <= 0 || n > 8)
- return 0;
-
- if (rem < n) {
- ret = (data[byte] << (n - rem));
- ret |= (data[byte + 1] >> (8 - n + rem));
- } else {
- ret = (data[byte] >> (rem - n));
- }
-
- return (ret & (0xff >> (8 - n)));
-}
-
-static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
-{
- static const int SpeexWBSubModeSz[] = {
- 4, 36, 112, 192,
- 352, 0, 0, 0 };
- int off = bit;
- unsigned char c;
-
- /* skip up to two wideband frames */
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
-
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
-
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
- return -1;
- }
- }
-
- }
- return off - bit;
-}
-
-static int speex_samples(unsigned char *data, int len)
-{
- static const int SpeexSubModeSz[] = {
- 5, 43, 119, 160,
- 220, 300, 364, 492,
- 79, 0, 0, 0,
- 0, 0, 0, 0 };
- static const int SpeexInBandSz[] = {
- 1, 1, 4, 4,
- 4, 4, 4, 4,
- 8, 8, 16, 16,
- 32, 32, 64, 64 };
- int bit = 0;
- int cnt = 0;
- int off;
- unsigned char c;
-
- while ((len * 8 - bit) >= 5) {
- /* skip wideband frames */
- off = speex_get_wb_sz_at(data, len, bit);
- if (off < 0) {
- ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
- break;
- }
- bit += off;
-
- if ((len * 8 - bit) < 5)
- break;
-
- /* get control bits */
- c = get_n_bits_at(data, 5, bit);
- bit += 5;
-
- if (c == 15) {
- /* terminator */
- break;
- } else if (c == 14) {
- /* in-band signal; next 4 bits contain signal id */
- c = get_n_bits_at(data, 4, bit);
- bit += 4;
- bit += SpeexInBandSz[c];
- } else if (c == 13) {
- /* user in-band; next 4 bits contain msg len */
- c = get_n_bits_at(data, 4, bit);
- bit += 4;
- /* after which it's 5-bit signal id + c bytes of data */
- bit += 5 + c * 8;
- } else if (c > 8) {
- /* unknown */
- ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
- break;
- } else {
- /* skip number bits for submode (less the 5 control bits) */
- bit += SpeexSubModeSz[c] - 5;
- cnt += 160; /* new frame */
- }
- }
- return cnt;
-}
-
-int ast_codec_get_samples(struct ast_frame *f)
-{
- int samples = 0;
-
- switch (f->subclass.format.id) {
- case AST_FORMAT_SPEEX:
- samples = speex_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_SPEEX16:
- samples = 2 * speex_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_SPEEX32:
- samples = 4 * speex_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_G723_1:
- samples = g723_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_ILBC:
- samples = 240 * (f->datalen / 50);
- break;
- case AST_FORMAT_GSM:
- samples = 160 * (f->datalen / 33);
- break;
- case AST_FORMAT_G729A:
- samples = f->datalen * 8;
- break;
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_SLINEAR16:
- samples = f->datalen / 2;
- break;
- case AST_FORMAT_LPC10:
- /* assumes that the RTP packet contains one LPC10 frame */
- samples = 22 * 8;
- samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
- break;
- case AST_FORMAT_ULAW:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_TESTLAW:
- samples = f->datalen;
- break;
- case AST_FORMAT_G722:
- case AST_FORMAT_ADPCM:
- case AST_FORMAT_G726:
- case AST_FORMAT_G726_AAL2:
- samples = f->datalen * 2;
- break;
- case AST_FORMAT_SIREN7:
- /* 16,000 samples per second at 32kbps is 4,000 bytes per second */
- samples = f->datalen * (16000 / 4000);
- break;
- case AST_FORMAT_SIREN14:
- /* 32,000 samples per second at 48kbps is 6,000 bytes per second */
- samples = (int) f->datalen * ((float) 32000 / 6000);
- break;
- case AST_FORMAT_G719:
- /* 48,000 samples per second at 64kbps is 8,000 bytes per second */
- samples = (int) f->datalen * ((float) 48000 / 8000);
- break;
- case AST_FORMAT_SILK:
- if (!(ast_format_isset(&f->subclass.format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_24KHZ,
- AST_FORMAT_ATTR_END))) {
- return 480;
- } else if (!(ast_format_isset(&f->subclass.format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END))) {
- return 320;
- } else if (!(ast_format_isset(&f->subclass.format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_12KHZ,
- AST_FORMAT_ATTR_END))) {
- return 240;
- } else {
- return 160;
- }
- case AST_FORMAT_CELT:
- /* TODO This assumes 20ms delivery right now, which is incorrect */
- samples = ast_format_rate(&f->subclass.format) / 50;
- break;
- case AST_FORMAT_OPUS:
- /* TODO This assumes 20ms delivery right now, which is incorrect */
- samples = 960;
- break;
- default:
- ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format));
- }
- return samples;
-}
-
-int ast_codec_get_len(struct ast_format *format, int samples)
-{
- int len = 0;
-
- /* XXX Still need speex, and lpc10 XXX */
- switch(format->id) {
- case AST_FORMAT_G723_1:
- len = (samples / 240) * 20;
- break;
- case AST_FORMAT_ILBC:
- len = (samples / 240) * 50;
- break;
- case AST_FORMAT_GSM:
- len = (samples / 160) * 33;
- break;
- case AST_FORMAT_G729A:
- len = samples / 8;
- break;
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_SLINEAR16:
- len = samples * 2;
- break;
- case AST_FORMAT_ULAW:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_TESTLAW:
- len = samples;
- break;
- case AST_FORMAT_G722:
- case AST_FORMAT_ADPCM:
- case AST_FORMAT_G726:
- case AST_FORMAT_G726_AAL2:
- len = samples / 2;
- break;
- case AST_FORMAT_SIREN7:
- /* 16,000 samples per second at 32kbps is 4,000 bytes per second */
- len = samples / (16000 / 4000);
- break;
- case AST_FORMAT_SIREN14:
- /* 32,000 samples per second at 48kbps is 6,000 bytes per second */
- len = (int) samples / ((float) 32000 / 6000);
- break;
- case AST_FORMAT_G719:
- /* 48,000 samples per second at 64kbps is 8,000 bytes per second */
- len = (int) samples / ((float) 48000 / 8000);
- break;
- default:
- ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
- }
-
- return len;
-}
-
int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
{
int count;
short *fdata = f->data.ptr;
short adjust_value = abs(adjustment);
- if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_is_slinear(&f->subclass.format))) {
+ if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_cache_is_slinear(f->subclass.format))) {
return -1;
}
@@ -1202,10 +677,10 @@ int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
int count;
short *data1, *data2;
- if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass.format.id != AST_FORMAT_SLINEAR))
+ if ((f1->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f1->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
return -1;
- if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass.format.id != AST_FORMAT_SLINEAR))
+ if ((f2->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f2->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
return -1;
if (f1->samples != f2->samples)
diff --git a/main/image.c b/main/image.c
index 08620d734..53638f30c 100644
--- a/main/image.c
+++ b/main/image.c
@@ -114,7 +114,7 @@ struct ast_frame *ast_read_image(const char *filename, const char *preflang, str
AST_RWLIST_RDLOCK(&imagers);
AST_RWLIST_TRAVERSE(&imagers, i, list) {
/* if NULL image format, just pick the first one, otherwise match it. */
- if (!format || (ast_format_cmp(&i->format, format) == AST_FORMAT_CMP_EQUAL)) {
+ 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;
@@ -194,7 +194,7 @@ static char *handle_core_show_image_formats(struct ast_cli_entry *e, int cmd, st
ast_cli(a->fd, FORMAT, "----", "----------", "-----------", "------");
AST_RWLIST_RDLOCK(&imagers);
AST_RWLIST_TRAVERSE(&imagers, i, list) {
- ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(&i->format));
+ ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_format_get_name(i->format));
count_fmt++;
}
AST_RWLIST_UNLOCK(&imagers);
diff --git a/main/indications.c b/main/indications.c
index 2f2bdce62..27d2b5356 100644
--- a/main/indications.c
+++ b/main/indications.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h"
#include "asterisk/indications.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
@@ -120,7 +121,7 @@ struct playtones_state {
int npos;
int oldnpos;
int pos;
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
struct ast_frame f;
unsigned char offset[AST_FRIENDLY_OFFSET];
short data[4000];
@@ -131,13 +132,11 @@ static void playtones_release(struct ast_channel *chan, void *params)
struct playtones_state *ps = params;
if (chan) {
- ast_set_write_format(chan, &ps->origwfmt);
+ ast_set_write_format(chan, ps->origwfmt);
}
- if (ps->items) {
- ast_free(ps->items);
- ps->items = NULL;
- }
+ ao2_cleanup(ps->origwfmt);
+ ast_free(ps->items);
ast_free(ps);
}
@@ -151,9 +150,9 @@ static void *playtones_alloc(struct ast_channel *chan, void *params)
return NULL;
}
- ast_format_copy(&ps->origwfmt, ast_channel_writeformat(chan));
+ ps->origwfmt = ao2_bump(ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", ast_channel_name(chan));
playtones_release(NULL, ps);
ps = NULL;
@@ -227,7 +226,7 @@ static int playtones_generator(struct ast_channel *chan, void *data, int len, in
}
ps->f.frametype = AST_FRAME_VOICE;
- ast_format_set(&ps->f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ ps->f.subclass.format = ast_format_slin;
ps->f.datalen = len;
ps->f.samples = samples;
ps->f.offset = AST_FRIENDLY_OFFSET;
diff --git a/main/manager.c b/main/manager.c
index 75811886f..35ba5d46c 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -99,6 +99,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/features_config.h"
#include "asterisk/rtp_engine.h"
+#include "asterisk/format_cache.h"
#include "asterisk/translate.h"
/*** DOCUMENTATION
@@ -3869,7 +3870,7 @@ static int action_status(struct mansession *s, const struct message *m)
struct ast_str *write_transpath = ast_str_alloca(256);
struct ast_str *read_transpath = ast_str_alloca(256);
struct ast_channel *chan;
- char nativeformats[256];
+ struct ast_str *codec_buf = ast_str_alloca(64);
int channels = 0;
int all = ast_strlen_zero(name); /* set if we want all channels */
char id_text[256];
@@ -4007,10 +4008,10 @@ static int action_status(struct mansession *s, const struct message *m)
ast_channel_linkedid(chan),
ast_channel_appl(chan),
ast_channel_data(chan),
- ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)),
- ast_getformatname(ast_channel_readformat(chan)),
+ ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(chan)),
ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath),
- ast_getformatname(ast_channel_writeformat(chan)),
+ ast_format_get_name(ast_channel_writeformat(chan)),
ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath),
ast_channel_callgroup(chan),
ast_channel_pickupgroup(chan),
@@ -4458,7 +4459,7 @@ struct fast_originate_helper {
*/
static void destroy_fast_originate_helper(struct fast_originate_helper *doomed)
{
- ast_format_cap_destroy(doomed->cap);
+ ao2_cleanup(doomed->cap);
ast_variables_destroy(doomed->vars);
ast_string_field_free_memory(doomed);
ast_free(doomed);
@@ -4781,8 +4782,7 @@ static int action_originate(struct mansession *s, const struct message *m)
int reason = 0;
char tmp[256];
char tmp2[256];
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_fmt;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
pthread_t th;
int bridge_early = 0;
@@ -4790,7 +4790,7 @@ static int action_originate(struct mansession *s, const struct message *m)
astman_send_error(s, m, "Internal Error. Memory allocation failure.");
return 0;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
|| (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
@@ -4840,8 +4840,8 @@ static int action_originate(struct mansession *s, const struct message *m)
}
}
if (!ast_strlen_zero(codecs)) {
- ast_format_cap_remove_all(cap);
- ast_parse_allow_disallow(NULL, cap, codecs, 1);
+ ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_update_by_allow_disallow(cap, codecs, 1);
}
if (!ast_strlen_zero(app) && s->session) {
@@ -4957,7 +4957,7 @@ static int action_originate(struct mansession *s, const struct message *m)
}
fast_orig_cleanup:
- ast_format_cap_destroy(cap);
+ ao2_cleanup(cap);
return 0;
}
diff --git a/main/media_index.c b/main/media_index.c
index a643c237f..3e3824580 100644
--- a/main/media_index.c
+++ b/main/media_index.c
@@ -56,7 +56,7 @@ static void media_variant_destroy(void *obj)
struct media_variant *variant = obj;
ast_string_field_free_memory(variant);
- variant->formats = ast_format_cap_destroy(variant->formats);
+ ao2_cleanup(variant->formats);
}
static struct media_variant *media_variant_alloc(const char *variant_str)
@@ -67,7 +67,7 @@ static struct media_variant *media_variant_alloc(const char *variant_str)
return NULL;
}
- variant->formats = ast_format_cap_alloc(0);
+ variant->formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!variant->formats) {
return NULL;
}
@@ -239,6 +239,7 @@ const char *ast_media_get_description(struct ast_media_index *index, const char
struct ast_format_cap *ast_media_get_format_cap(struct ast_media_index *index, const char *filename, const char *variant_str)
{
+ struct ast_format_cap *dupcap;
RAII_VAR(struct media_variant *, variant, NULL, ao2_cleanup);
if (ast_strlen_zero(filename) || ast_strlen_zero(variant_str)) {
return NULL;
@@ -249,7 +250,11 @@ struct ast_format_cap *ast_media_get_format_cap(struct ast_media_index *index, c
return NULL;
}
- return ast_format_cap_dup(variant->formats);
+ dupcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (dupcap) {
+ ast_format_cap_append_from_cap(dupcap, variant->formats, AST_MEDIA_TYPE_UNKNOWN);
+ }
+ return dupcap;
}
/*! \brief Add the variant to the list of variants requested */
@@ -317,7 +322,7 @@ struct ao2_container *ast_media_get_media(struct ast_media_index *index)
}
/*! \brief Update an index with new format/variant information */
-static int update_file_format_info(struct ast_media_index *index, const char *filename, const char *variant_str, const struct ast_format *file_format)
+static int update_file_format_info(struct ast_media_index *index, const char *filename, const char *variant_str, struct ast_format *file_format)
{
RAII_VAR(struct media_variant *, variant, find_variant(index, filename, variant_str), ao2_cleanup);
if (!variant) {
@@ -327,14 +332,14 @@ static int update_file_format_info(struct ast_media_index *index, const char *fi
}
}
- ast_format_cap_add(variant->formats, file_format);
+ ast_format_cap_append(variant->formats, file_format, 0);
return 0;
}
/*! \brief Process a media file into the index */
static int process_media_file(struct ast_media_index *index, const char *variant, const char *subdir, const char *filename_stripped, const char *ext)
{
- const struct ast_format *file_format;
+ struct ast_format *file_format;
const char *file_identifier = filename_stripped;
RAII_VAR(struct ast_str *, file_id_str, NULL, ast_free);
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 9e3d7d108..07ef1f697 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -196,12 +196,18 @@ static AST_RWLIST_HEAD_STATIC(engines, ast_rtp_engine);
/*! List of RTP glues */
static AST_RWLIST_HEAD_STATIC(glues, ast_rtp_glue);
+#define MAX_RTP_MIME_TYPES 128
+
/*! The following array defines the MIME Media type (and subtype) for each
of our codecs, or RTP-specific data type. */
static struct ast_rtp_mime_type {
+ /*! \brief A mapping object between the Asterisk codec and this RTP payload */
struct ast_rtp_payload_type payload_type;
- char *type;
- char *subtype;
+ /*! \brief The media type */
+ char type[16];
+ /*! \brief The format type */
+ char subtype[64];
+ /*! \brief Expected sample rate of the /c subtype */
unsigned int sample_rate;
} ast_rtp_mime_types[128]; /* This will Likely not need to grow any time soon. */
static ast_rwlock_t mime_types_lock;
@@ -223,6 +229,24 @@ static ast_rwlock_t static_RTP_PT_lock;
/*! \brief \ref stasis topic for RTP related messages */
static struct stasis_topic *rtp_topic;
+
+/*! \internal \brief Destructor for \c ast_rtp_payload_type */
+static void rtp_payload_type_dtor(void *obj)
+{
+ struct ast_rtp_payload_type *payload = obj;
+
+ ao2_cleanup(payload->format);
+}
+
+struct ast_rtp_payload_type *ast_rtp_engine_alloc_payload_type(void)
+{
+ struct ast_rtp_payload_type *payload;
+
+ payload = ao2_alloc(sizeof(*payload), rtp_payload_type_dtor);
+
+ return payload;
+}
+
int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
{
struct ast_rtp_engine *current_engine;
@@ -526,34 +550,30 @@ struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *inst
return &instance->codecs;
}
-static int rtp_payload_type_hash(const void *obj, const int flags)
+int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
{
- const struct ast_rtp_payload_type *type = obj;
- const int *payload = obj;
+ int res;
+
+ codecs->framing = 0;
+ ast_rwlock_init(&codecs->codecs_lock);
+ res = AST_VECTOR_INIT(&codecs->payloads, AST_RTP_MAX_PT);
- return (flags & OBJ_KEY) ? *payload : type->payload;
+ return res;
}
-static int rtp_payload_type_cmp(void *obj, void *arg, int flags)
+void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
{
- struct ast_rtp_payload_type *type1 = obj, *type2 = arg;
- const int *payload = arg;
+ int i;
- return (type1->payload == (OBJ_KEY ? *payload : type2->payload)) ? CMP_MATCH | CMP_STOP : 0;
-}
+ for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
+ struct ast_rtp_payload_type *type;
-int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
-{
- if (!(codecs->payloads = ao2_container_alloc(AST_RTP_MAX_PT, rtp_payload_type_hash, rtp_payload_type_cmp))) {
- return -1;
+ type = AST_VECTOR_GET(&codecs->payloads, i);
+ ao2_t_cleanup(type, "destroying ast_rtp_codec");
}
+ AST_VECTOR_FREE(&codecs->payloads);
- return 0;
-}
-
-void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
-{
- ao2_cleanup(codecs->payloads);
+ ast_rwlock_destroy(&codecs->codecs_lock);
}
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
@@ -570,106 +590,69 @@ void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp
ast_rtp_codecs_payloads_initialize(codecs);
}
-void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
-{
- int i;
-
- ast_rwlock_rdlock(&static_RTP_PT_lock);
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- if (static_RTP_PT[i].rtp_code || static_RTP_PT[i].asterisk_format) {
- struct ast_rtp_payload_type *type;
-
- if (!(type = ao2_alloc(sizeof(*type), NULL))) {
- /* Unfortunately if this occurs the payloads container will not contain all possible default payloads
- * but we err on the side of doing what we can in the hopes that the extreme memory conditions which
- * caused this to occur will go away.
- */
- continue;
- }
-
- type->payload = i;
- type->asterisk_format = static_RTP_PT[i].asterisk_format;
- type->rtp_code = static_RTP_PT[i].rtp_code;
- ast_format_copy(&type->format, &static_RTP_PT[i].format);
-
- ao2_link_flags(codecs->payloads, type, OBJ_NOLOCK);
-
- if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, i, type->asterisk_format, &type->format, type->rtp_code);
- }
-
- ao2_ref(type, -1);
- }
- }
- ast_rwlock_unlock(&static_RTP_PT_lock);
-}
-
void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
{
int i;
- struct ast_rtp_payload_type *type;
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- struct ast_rtp_payload_type *new_type;
+ ast_rwlock_rdlock(&src->codecs_lock);
+ ast_rwlock_wrlock(&dest->codecs_lock);
- if (!(type = ao2_find(src->payloads, &i, OBJ_KEY | OBJ_NOLOCK))) {
- continue;
- }
+ for (i = 0; i < AST_VECTOR_SIZE(&src->payloads); i++) {
+ struct ast_rtp_payload_type *type;
- if (!(new_type = ao2_alloc(sizeof(*new_type), NULL))) {
+ type = AST_VECTOR_GET(&src->payloads, i);
+ if (!type) {
continue;
}
-
- ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest);
-
- new_type->payload = i;
- *new_type = *type;
-
- ao2_link_flags(dest->payloads, new_type, OBJ_NOLOCK);
-
- ao2_ref(new_type, -1);
+ if (i < AST_VECTOR_SIZE(&dest->payloads)) {
+ ao2_t_cleanup(AST_VECTOR_GET(&dest->payloads, i), "cleaning up vector element about to be replaced");
+ }
+ ast_debug(2, "Copying payload %d (%p) from %p to %p\n", i, type, src, dest);
+ ao2_bump(type);
+ AST_VECTOR_INSERT(&dest->payloads, i, type);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, i, type->asterisk_format, &type->format, type->rtp_code);
+ instance->engine->payload_set(instance, i, type->asterisk_format, type->format, type->rtp_code);
}
-
- ao2_ref(type, -1);
}
+ dest->framing = src->framing;
+ ast_rwlock_unlock(&dest->codecs_lock);
+ ast_rwlock_unlock(&src->codecs_lock);
}
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
{
- struct ast_rtp_payload_type *type;
+ struct ast_rtp_payload_type *new_type;
- ast_rwlock_rdlock(&static_RTP_PT_lock);
+ new_type = ast_rtp_engine_alloc_payload_type();
+ if (!new_type) {
+ return;
+ }
+ ast_rwlock_rdlock(&static_RTP_PT_lock);
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
ast_rwlock_unlock(&static_RTP_PT_lock);
return;
}
- if (!(type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
- if (!(type = ao2_alloc(sizeof(*type), NULL))) {
- ast_rwlock_unlock(&static_RTP_PT_lock);
- return;
- }
- type->payload = payload;
- ao2_link_flags(codecs->payloads, type, OBJ_NOLOCK);
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ ao2_t_cleanup(AST_VECTOR_GET(&codecs->payloads, payload), "cleaning up replaced payload type");
}
- type->asterisk_format = static_RTP_PT[payload].asterisk_format;
- type->rtp_code = static_RTP_PT[payload].rtp_code;
- type->payload = payload;
- ast_format_copy(&type->format, &static_RTP_PT[payload].format);
+ new_type->asterisk_format = static_RTP_PT[payload].asterisk_format;
+ new_type->rtp_code = static_RTP_PT[payload].rtp_code;
+ new_type->payload = payload;
+ new_type->format = ao2_bump(static_RTP_PT[payload].format);
- ast_debug(1, "Setting payload %d based on m type on %p\n", payload, codecs);
+ ast_debug(1, "Setting payload %d (%p) based on m type on %p\n", payload, new_type, codecs);
+ AST_VECTOR_INSERT(&codecs->payloads, payload, new_type);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, payload, type->asterisk_format, &type->format, type->rtp_code);
+ instance->engine->payload_set(instance, payload, new_type->asterisk_format, new_type->format, new_type->rtp_code);
}
- ao2_ref(type, -1);
-
+ ast_rwlock_unlock(&codecs->codecs_lock);
ast_rwlock_unlock(&static_RTP_PT_lock);
}
@@ -681,13 +664,16 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
unsigned int i;
int found = 0;
- if (pt < 0 || pt >= AST_RTP_MAX_PT)
+ ast_rwlock_rdlock(&mime_types_lock);
+ if (pt < 0 || pt >= AST_RTP_MAX_PT) {
+ ast_rwlock_unlock(&mime_types_lock);
return -1; /* bogus payload type */
+ }
- ast_rwlock_rdlock(&mime_types_lock);
+ ast_rwlock_wrlock(&codecs->codecs_lock);
for (i = 0; i < mime_types_len; ++i) {
const struct ast_rtp_mime_type *t = &ast_rtp_mime_types[i];
- struct ast_rtp_payload_type *type;
+ struct ast_rtp_payload_type *new_type;
if (strcasecmp(mimesubtype, t->subtype)) {
continue;
@@ -707,29 +693,33 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
found = 1;
- if (!(type = ao2_find(codecs->payloads, &pt, OBJ_KEY | OBJ_NOLOCK))) {
- if (!(type = ao2_alloc(sizeof(*type), NULL))) {
- continue;
- }
- type->payload = pt;
- ao2_link_flags(codecs->payloads, type, OBJ_NOLOCK);
+ new_type = ast_rtp_engine_alloc_payload_type();
+ if (!new_type) {
+ continue;
}
- *type = t->payload_type;
- type->payload = pt;
+ if (pt < AST_VECTOR_SIZE(&codecs->payloads)) {
+ ao2_t_cleanup(AST_VECTOR_GET(&codecs->payloads, pt), "cleaning up replaced payload type");
+ }
- if ((t->payload_type.format.id == AST_FORMAT_G726) && t->payload_type.asterisk_format && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
- ast_format_set(&type->format, AST_FORMAT_G726_AAL2, 0);
+ new_type->payload = pt;
+ new_type->asterisk_format = t->payload_type.asterisk_format;
+ new_type->rtp_code = t->payload_type.rtp_code;
+ if ((ast_format_cmp(t->payload_type.format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) &&
+ t->payload_type.asterisk_format && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
+ new_type->format = ao2_bump(ast_format_g726_aal2);
+ } else {
+ new_type->format = ao2_bump(t->payload_type.format);
}
+ AST_VECTOR_INSERT(&codecs->payloads, pt, new_type);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, pt, type->asterisk_format, &type->format, type->rtp_code);
+ instance->engine->payload_set(instance, pt, new_type->asterisk_format, new_type->format, new_type->rtp_code);
}
- ao2_ref(type, -1);
-
break;
}
+ ast_rwlock_unlock(&codecs->codecs_lock);
ast_rwlock_unlock(&mime_types_lock);
return (found ? 0 : -2);
@@ -742,157 +732,209 @@ int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struc
void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
{
+ struct ast_rtp_payload_type *type;
+
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
return;
}
ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
- ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK | OBJ_NODATA | OBJ_UNLINK);
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ ao2_cleanup(type);
+ AST_VECTOR_INSERT(&codecs->payloads, payload, NULL);
+ }
if (instance && instance->engine && instance->engine->payload_set) {
instance->engine->payload_set(instance, payload, 0, NULL, 0);
}
+
+ ast_rwlock_unlock(&codecs->codecs_lock);
}
-struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload)
+struct ast_rtp_payload_type *ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
{
- struct ast_rtp_payload_type result = { .asterisk_format = 0, }, *type;
+ struct ast_rtp_payload_type *type = NULL;
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
- return result;
+ return NULL;
}
- if ((type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
- result = *type;
- ao2_ref(type, -1);
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ ao2_bump(type);
}
+ ast_rwlock_unlock(&codecs->codecs_lock);
- if (!result.rtp_code && !result.asterisk_format) {
+ if (!type) {
+ type = ast_rtp_engine_alloc_payload_type();
+ if (!type) {
+ return NULL;
+ }
ast_rwlock_rdlock(&static_RTP_PT_lock);
- result = static_RTP_PT[payload];
+ type->asterisk_format = static_RTP_PT[payload].asterisk_format;
+ type->rtp_code = static_RTP_PT[payload].rtp_code;
+ type->payload = payload;
+ type->format = ao2_bump(static_RTP_PT[payload].format);
ast_rwlock_unlock(&static_RTP_PT_lock);
}
- return result;
+ return type;
}
+int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
+{
+ struct ast_rtp_payload_type *type;
+
+ if (payload < 0 || payload >= AST_RTP_MAX_PT) {
+ return -1;
+ }
+
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ if (type && type->asterisk_format) {
+ ao2_replace(type->format, format);
+ }
+ }
+ ast_rwlock_unlock(&codecs->codecs_lock);
+
+ return 0;
+}
struct ast_format *ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload)
{
struct ast_rtp_payload_type *type;
- struct ast_format *format;
+ struct ast_format *format = NULL;
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
return NULL;
}
- if (!(type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
- return NULL;
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ if (type && type->asterisk_format) {
+ format = ao2_bump(type->format);
+ }
}
-
- format = type->asterisk_format ? &type->format : NULL;
-
- ao2_ref(type, -1);
+ ast_rwlock_unlock(&codecs->codecs_lock);
return format;
}
-static int rtp_payload_type_add_ast(void *obj, void *arg, int flags)
+void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
{
- struct ast_rtp_payload_type *type = obj;
- struct ast_format_cap *astformats = arg;
-
- if (type->asterisk_format) {
- ast_format_cap_add(astformats, &type->format);
+ if (!framing) {
+ return;
}
- return 0;
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ codecs->framing = framing;
+ ast_rwlock_unlock(&codecs->codecs_lock);
}
-static int rtp_payload_type_add_nonast(void *obj, void *arg, int flags)
+unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
{
- struct ast_rtp_payload_type *type = obj;
- int *nonastformats = arg;
+ unsigned int framing;
- if (!type->asterisk_format) {
- *nonastformats |= type->rtp_code;
- }
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ framing = codecs->framing;
+ ast_rwlock_unlock(&codecs->codecs_lock);
- return 0;
+ return framing;
}
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
{
- ast_format_cap_remove_all(astformats);
+ int i;
+
+ ast_format_cap_remove_by_type(astformats, AST_MEDIA_TYPE_UNKNOWN);
*nonastformats = 0;
- ao2_callback(codecs->payloads, OBJ_NODATA | OBJ_MULTIPLE | OBJ_NOLOCK, rtp_payload_type_add_ast, astformats);
- ao2_callback(codecs->payloads, OBJ_NODATA | OBJ_MULTIPLE | OBJ_NOLOCK, rtp_payload_type_add_nonast, nonastformats);
-}
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
+ struct ast_rtp_payload_type *type;
-static int rtp_payload_type_find_format(void *obj, void *arg, int flags)
-{
- struct ast_rtp_payload_type *type = obj;
- struct ast_format *format = arg;
+ type = AST_VECTOR_GET(&codecs->payloads, i);
+ if (!type) {
+ continue;
+ }
- return (type->asterisk_format && (ast_format_cmp(&type->format, format) != AST_FORMAT_CMP_NOT_EQUAL)) ? CMP_MATCH | CMP_STOP : 0;
-}
+ if (type->asterisk_format) {
+ ast_format_cap_append(astformats, type->format, 0);
+ } else {
+ *nonastformats |= type->rtp_code;
+ }
+ }
-static int rtp_payload_type_find_nonast_format(void *obj, void *arg, int flags)
-{
- struct ast_rtp_payload_type *type = obj;
- int *rtp_code = arg;
+ if (codecs->framing) {
+ ast_format_cap_set_framing(astformats, codecs->framing);
+ }
- return ((!type->asterisk_format && (type->rtp_code == *rtp_code)) ? CMP_MATCH | CMP_STOP : 0);
+ ast_rwlock_unlock(&codecs->codecs_lock);
}
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
{
struct ast_rtp_payload_type *type;
- int i, res = -1;
+ int i;
+ int payload = -1;
- if (asterisk_format && format && (type = ao2_callback(codecs->payloads, OBJ_NOLOCK, rtp_payload_type_find_format, (void*)format))) {
- res = type->payload;
- ao2_ref(type, -1);
- return res;
- } else if (!asterisk_format && (type = ao2_callback(codecs->payloads, OBJ_NOLOCK, rtp_payload_type_find_nonast_format, (void*)&code))) {
- res = type->payload;
- ao2_ref(type, -1);
- return res;
- }
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
+ type = AST_VECTOR_GET(&codecs->payloads, i);
+ if (!type) {
+ continue;
+ }
- ast_rwlock_rdlock(&static_RTP_PT_lock);
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- if (static_RTP_PT[i].asterisk_format && asterisk_format && format &&
- (ast_format_cmp(format, &static_RTP_PT[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) {
- res = i;
- break;
- } else if (!static_RTP_PT[i].asterisk_format && !asterisk_format &&
- (static_RTP_PT[i].rtp_code == code)) {
- res = i;
+ if ((asterisk_format && format && ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL)
+ || (!asterisk_format && type->rtp_code == code)) {
+ payload = i;
break;
}
}
- ast_rwlock_unlock(&static_RTP_PT_lock);
+ ast_rwlock_unlock(&codecs->codecs_lock);
- return res;
+ if (payload < 0) {
+ ast_rwlock_rdlock(&static_RTP_PT_lock);
+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
+ if (static_RTP_PT[i].asterisk_format && asterisk_format && format &&
+ (ast_format_cmp(format, static_RTP_PT[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) {
+ payload = i;
+ break;
+ } else if (!static_RTP_PT[i].asterisk_format && !asterisk_format &&
+ (static_RTP_PT[i].rtp_code == code)) {
+ payload = i;
+ break;
+ }
+ }
+ ast_rwlock_unlock(&static_RTP_PT_lock);
+ }
+
+ return payload;
}
+
int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int code)
{
struct ast_rtp_payload_type *type;
int res = -1;
- /* Search the payload type in the codecs passed */
- if ((type = ao2_find(codecs->payloads, &code, OBJ_NOLOCK | OBJ_KEY)))
- {
- res = type->payload;
- ao2_ref(type, -1);
- return res;
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ if (code < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, code);
+ if (type) {
+ res = type->payload;
+ }
}
+ ast_rwlock_unlock(&codecs->codecs_lock);
return res;
}
+
const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_format *format, int code, enum ast_rtp_options options)
{
int i;
@@ -901,8 +943,9 @@ const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_f
ast_rwlock_rdlock(&mime_types_lock);
for (i = 0; i < mime_types_len; i++) {
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)) {
+ (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
+ if ((ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) &&
+ (options & AST_RTP_OPT_G726_NONSTANDARD)) {
res = "G726-32";
break;
} else {
@@ -929,7 +972,7 @@ unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, struct ast_format
ast_rwlock_rdlock(&mime_types_lock);
for (i = 0; i < mime_types_len; ++i) {
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)) {
+ (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
res = ast_rtp_mime_types[i].sample_rate;
break;
} else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format &&
@@ -953,15 +996,15 @@ char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *
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);
+ int x;
+ struct ast_format *tmp_fmt;
+ for (x = 0; x < ast_format_cap_count(ast_format_capability); x++) {
+ tmp_fmt = ast_format_cap_get_format(ast_format_capability, x);
+ name = ast_rtp_lookup_mime_subtype2(asterisk_format, tmp_fmt, 0, options);
+ ao2_ref(tmp_fmt, -1);
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);
@@ -979,15 +1022,6 @@ char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *
return ast_str_buffer(buf);
}
-void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs)
-{
- codecs->pref = *prefs;
-
- if (instance && instance->engine->packetization_set) {
- instance->engine->packetization_set(instance, &instance->codecs.pref);
- }
-}
-
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
{
return instance->engine->dtmf_begin ? instance->engine->dtmf_begin(instance, digit) : -1;
@@ -1089,8 +1123,8 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c_dst, st
struct ast_rtp_glue *glue_dst, *glue_src;
enum ast_rtp_glue_result audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
- struct ast_format_cap *cap_dst = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *cap_src = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap_dst = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *cap_src = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
/* Lock both channels so we can look for the glue that binds them together */
ast_channel_lock_both(c_dst, c_src);
@@ -1131,7 +1165,7 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c_dst, st
}
/* Make sure we have matching codecs */
- if (!ast_format_cap_has_joint(cap_dst, cap_src)) {
+ if (!ast_format_cap_iscompatible(cap_dst, cap_src)) {
goto done;
}
@@ -1156,8 +1190,8 @@ done:
ast_channel_unlock(c_dst);
ast_channel_unlock(c_src);
- ast_format_cap_destroy(cap_dst);
- ast_format_cap_destroy(cap_src);
+ ao2_cleanup(cap_dst);
+ ao2_cleanup(cap_src);
unref_instance_cond(&instance_dst);
unref_instance_cond(&instance_src);
@@ -1175,13 +1209,13 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1
struct ast_rtp_glue *glue0, *glue1;
enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
- struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
/* If there is no second channel just immediately bail out, we are of no use in that scenario */
if (!c1 || !cap1 || !cap0) {
- ast_format_cap_destroy(cap0);
- ast_format_cap_destroy(cap1);
+ ao2_cleanup(cap0);
+ ao2_cleanup(cap1);
return -1;
}
@@ -1220,7 +1254,7 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1
}
/* Make sure we have matching codecs */
- if (!ast_format_cap_has_joint(cap0, cap1)) {
+ if (!ast_format_cap_iscompatible(cap0, cap1)) {
goto done;
}
@@ -1233,8 +1267,8 @@ done:
ast_channel_unlock(c0);
ast_channel_unlock(c1);
- ast_format_cap_destroy(cap0);
- ast_format_cap_destroy(cap1);
+ ao2_cleanup(cap0);
+ ao2_cleanup(cap1);
unref_instance_cond(&instance0);
unref_instance_cond(&instance1);
@@ -1419,7 +1453,7 @@ void ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, struc
{
if (instance->engine->available_formats) {
instance->engine->available_formats(instance, to_endpoint, to_asterisk, result);
- if (!ast_format_cap_is_empty(result)) {
+ if (ast_format_cap_count(result)) {
return;
}
}
@@ -1631,7 +1665,27 @@ void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg)
ast_free(dtls_cfg->capath);
}
-static void set_next_mime_type(const struct ast_format *format, int rtp_code, char *type, char *subtype, unsigned int sample_rate)
+/*! \internal
+ * \brief Small helper routine that cleans up entry i in
+ * \c static_RTP_PT.
+ */
+static void rtp_engine_static_RTP_PT_cleanup(int i)
+{
+ ao2_cleanup(static_RTP_PT[i].format);
+ memset(&static_RTP_PT[i], 0, sizeof(struct ast_rtp_payload_type));
+}
+
+/*! \internal
+ * \brief Small helper routine that cleans up entry i in
+ * \c ast_rtp_mime_types.
+ */
+static void rtp_engine_mime_type_cleanup(int i)
+{
+ ao2_cleanup(ast_rtp_mime_types[i].payload_type.format);
+ memset(&ast_rtp_mime_types[i], 0, sizeof(struct ast_rtp_mime_type));
+}
+
+static void set_next_mime_type(struct ast_format *format, int rtp_code, const char *type, const char *subtype, unsigned int sample_rate)
{
int x = mime_types_len;
if (ARRAY_LEN(ast_rtp_mime_types) == mime_types_len) {
@@ -1639,20 +1693,22 @@ static void set_next_mime_type(const struct ast_format *format, int rtp_code, ch
}
ast_rwlock_wrlock(&mime_types_lock);
+ /* Make sure any previous value in ast_rtp_mime_types is cleaned up */
+ memset(&ast_rtp_mime_types[x], 0, sizeof(struct ast_rtp_mime_type));
if (format) {
ast_rtp_mime_types[x].payload_type.asterisk_format = 1;
- ast_format_copy(&ast_rtp_mime_types[x].payload_type.format, format);
+ ast_rtp_mime_types[x].payload_type.format = ao2_bump(format);
} else {
ast_rtp_mime_types[x].payload_type.rtp_code = rtp_code;
}
- ast_rtp_mime_types[x].type = type;
- ast_rtp_mime_types[x].subtype = subtype;
+ ast_copy_string(ast_rtp_mime_types[x].type, type, sizeof(ast_rtp_mime_types[x].type));
+ ast_copy_string(ast_rtp_mime_types[x].subtype, subtype, sizeof(ast_rtp_mime_types[x].subtype));
ast_rtp_mime_types[x].sample_rate = sample_rate;
mime_types_len++;
ast_rwlock_unlock(&mime_types_lock);
}
-static void add_static_payload(int map, const struct ast_format *format, int rtp_code)
+static void add_static_payload(int map, struct ast_format *format, int rtp_code)
{
int x;
ast_rwlock_wrlock(&static_RTP_PT_lock);
@@ -1667,39 +1723,38 @@ static void add_static_payload(int map, const struct ast_format *format, int rtp
}
if (map < 0) {
- ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n" ,ast_getformatname(format));
+ ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n",
+ ast_format_get_name(format));
ast_rwlock_unlock(&static_RTP_PT_lock);
return;
}
if (format) {
static_RTP_PT[map].asterisk_format = 1;
- ast_format_copy(&static_RTP_PT[map].format, format);
+ static_RTP_PT[map].format = ao2_bump(format);
} else {
static_RTP_PT[map].rtp_code = rtp_code;
}
ast_rwlock_unlock(&static_RTP_PT_lock);
}
-int ast_rtp_engine_load_format(const struct ast_format *format)
+int ast_rtp_engine_load_format(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_SILK:
- set_next_mime_type(format, 0, "audio", "SILK", ast_format_rate(format));
- add_static_payload(-1, format, 0);
- break;
- case AST_FORMAT_CELT:
- set_next_mime_type(format, 0, "audio", "CELT", ast_format_rate(format));
- add_static_payload(-1, format, 0);
- break;
- default:
- break;
- }
+ char *codec_name = ast_strdupa(ast_format_get_name(format));
+
+ codec_name = ast_str_to_upper(codec_name);
+
+ set_next_mime_type(format,
+ 0,
+ ast_codec_media_type2str(ast_format_get_type(format)),
+ codec_name,
+ ast_format_get_sample_rate(format));
+ add_static_payload(-1, format, 0);
return 0;
}
-int ast_rtp_engine_unload_format(const struct ast_format *format)
+int ast_rtp_engine_unload_format(struct ast_format *format)
{
int x;
int y = 0;
@@ -1707,17 +1762,17 @@ int ast_rtp_engine_unload_format(const struct ast_format *format)
ast_rwlock_wrlock(&static_RTP_PT_lock);
/* remove everything pertaining to this format id from the lists */
for (x = 0; x < AST_RTP_MAX_PT; x++) {
- if (ast_format_cmp(&static_RTP_PT[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- memset(&static_RTP_PT[x], 0, sizeof(struct ast_rtp_payload_type));
+ if (ast_format_cmp(static_RTP_PT[x].format, format) == AST_FORMAT_CMP_EQUAL) {
+ rtp_engine_static_RTP_PT_cleanup(x);
}
}
ast_rwlock_unlock(&static_RTP_PT_lock);
-
ast_rwlock_wrlock(&mime_types_lock);
/* rebuild the list skipping the items matching this id */
for (x = 0; x < mime_types_len; x++) {
- if (ast_format_cmp(&ast_rtp_mime_types[x].payload_type.format, format) == AST_FORMAT_CMP_EQUAL) {
+ if (ast_format_cmp(ast_rtp_mime_types[x].payload_type.format, format) == AST_FORMAT_CMP_EQUAL) {
+ rtp_engine_mime_type_cleanup(x);
continue;
}
ast_rtp_mime_types[y] = ast_rtp_mime_types[x];
@@ -1976,16 +2031,32 @@ struct stasis_topic *ast_rtp_topic(void)
static void rtp_engine_shutdown(void)
{
+ int x;
+
ao2_cleanup(rtp_topic);
rtp_topic = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(ast_rtp_rtcp_received_type);
STASIS_MESSAGE_TYPE_CLEANUP(ast_rtp_rtcp_sent_type);
+
+ ast_rwlock_wrlock(&static_RTP_PT_lock);
+ for (x = 0; x < AST_RTP_MAX_PT; x++) {
+ if (static_RTP_PT[x].format) {
+ rtp_engine_static_RTP_PT_cleanup(x);
+ }
+ }
+ ast_rwlock_unlock(&static_RTP_PT_lock);
+
+ ast_rwlock_wrlock(&mime_types_lock);
+ for (x = 0; x < mime_types_len; x++) {
+ if (ast_rtp_mime_types[x].payload_type.format) {
+ rtp_engine_mime_type_cleanup(x);
+ }
+ }
+ ast_rwlock_unlock(&mime_types_lock);
}
int ast_rtp_engine_init()
{
- struct ast_format tmpfmt;
-
ast_rwlock_init(&mime_types_lock);
ast_rwlock_init(&static_RTP_PT_lock);
@@ -1998,90 +2069,90 @@ int ast_rtp_engine_init()
ast_register_atexit(rtp_engine_shutdown);
/* Define all the RTP mime types available */
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0), 0, "audio", "G723", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0), 0, "audio", "GSM", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0, "audio", "PCMU", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0, "audio", "G711U", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), 0, "audio", "PCMA", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), 0, "audio", "G711A", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), 0, "audio", "G726-32", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0, "audio", "DVI4", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), 0, "audio", "L16", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0, "audio", "L16", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0, "audio", "L16-256", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_LPC10, 0), 0, "audio", "LPC", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0, "audio", "G729", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0, "audio", "G729A", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0, "audio", "G.729", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX, 0), 0, "audio", "speex", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX16, 0), 0, "audio", "speex", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), 0, "audio", "speex", 32000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ILBC, 0), 0, "audio", "iLBC", 8000);
+ set_next_mime_type(ast_format_g723, 0, "audio", "G723", 8000);
+ set_next_mime_type(ast_format_gsm, 0, "audio", "GSM", 8000);
+ set_next_mime_type(ast_format_ulaw, 0, "audio", "PCMU", 8000);
+ set_next_mime_type(ast_format_ulaw, 0, "audio", "G711U", 8000);
+ set_next_mime_type(ast_format_alaw, 0, "audio", "PCMA", 8000);
+ set_next_mime_type(ast_format_alaw, 0, "audio", "G711A", 8000);
+ set_next_mime_type(ast_format_g726, 0, "audio", "G726-32", 8000);
+ set_next_mime_type(ast_format_adpcm, 0, "audio", "DVI4", 8000);
+ set_next_mime_type(ast_format_slin, 0, "audio", "L16", 8000);
+ set_next_mime_type(ast_format_slin16, 0, "audio", "L16", 16000);
+ set_next_mime_type(ast_format_slin16, 0, "audio", "L16-256", 16000);
+ set_next_mime_type(ast_format_lpc10, 0, "audio", "LPC", 8000);
+ set_next_mime_type(ast_format_g729, 0, "audio", "G729", 8000);
+ set_next_mime_type(ast_format_g729, 0, "audio", "G729A", 8000);
+ set_next_mime_type(ast_format_g729, 0, "audio", "G.729", 8000);
+ set_next_mime_type(ast_format_speex, 0, "audio", "speex", 8000);
+ set_next_mime_type(ast_format_speex16, 0, "audio", "speex", 16000);
+ set_next_mime_type(ast_format_speex32, 0, "audio", "speex", 32000);
+ set_next_mime_type(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 */
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G722, 0), 0, "audio", "G722", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G726_AAL2, 0), 0, "audio", "AAL2-G726-32", 8000);
+ set_next_mime_type(ast_format_g722, 0, "audio", "G722", 8000);
+ set_next_mime_type(ast_format_g726_aal2, 0, "audio", "AAL2-G726-32", 8000);
set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 8000);
set_next_mime_type(NULL, AST_RTP_CISCO_DTMF, "audio", "cisco-telephone-event", 8000);
set_next_mime_type(NULL, AST_RTP_CN, "audio", "CN", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_JPEG, 0), 0, "video", "JPEG", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_PNG, 0), 0, "video", "PNG", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H261, 0), 0, "video", "H261", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H263, 0), 0, "video", "H263", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0, "video", "H263-1998", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H264, 0), 0, "video", "H264", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_MP4_VIDEO, 0), 0, "video", "MP4V-ES", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_T140RED, 0), 0, "text", "RED", 1000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_T140, 0), 0, "text", "T140", 1000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), 0, "audio", "G7221", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), 0, "audio", "G7221", 32000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), 0, "audio", "G719", 48000);
+ set_next_mime_type(ast_format_jpeg, 0, "video", "JPEG", 90000);
+ set_next_mime_type(ast_format_png, 0, "video", "PNG", 90000);
+ set_next_mime_type(ast_format_h261, 0, "video", "H261", 90000);
+ set_next_mime_type(ast_format_h263, 0, "video", "H263", 90000);
+ set_next_mime_type(ast_format_h263p, 0, "video", "h263-1998", 90000);
+ set_next_mime_type(ast_format_h264, 0, "video", "H264", 90000);
+ set_next_mime_type(ast_format_mp4, 0, "video", "MP4V-ES", 90000);
+ set_next_mime_type(ast_format_t140_red, 0, "text", "RED", 1000);
+ set_next_mime_type(ast_format_t140, 0, "text", "T140", 1000);
+ set_next_mime_type(ast_format_siren7, 0, "audio", "G7221", 16000);
+ set_next_mime_type(ast_format_siren14, 0, "audio", "G7221", 32000);
+ set_next_mime_type(ast_format_g719, 0, "audio", "G719", 48000);
/* Opus and VP8 */
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0, "audio", "opus", 48000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0, "video", "VP8", 90000);
+ set_next_mime_type(ast_format_opus, 0, "audio", "opus", 48000);
+ set_next_mime_type(ast_format_vp8, 0, "video", "VP8", 90000);
/* Define the static rtp payload mappings */
- add_static_payload(0, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0);
+ add_static_payload(0, ast_format_ulaw, 0);
#ifdef USE_DEPRECATED_G726
- add_static_payload(2, ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), 0);/* Technically this is G.721, but if Cisco can do it, so can we... */
+ add_static_payload(2, ast_format_g726, 0);/* Technically this is G.721, but if Cisco can do it, so can we... */
#endif
- add_static_payload(3, ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0), 0);
- add_static_payload(4, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0), 0);
- add_static_payload(5, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0);/* 8 kHz */
- add_static_payload(6, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0); /* 16 kHz */
- add_static_payload(7, ast_format_set(&tmpfmt, AST_FORMAT_LPC10, 0), 0);
- add_static_payload(8, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), 0);
- add_static_payload(9, ast_format_set(&tmpfmt, AST_FORMAT_G722, 0), 0);
- add_static_payload(10, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), 0); /* 2 channels */
- add_static_payload(11, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), 0); /* 1 channel */
+ add_static_payload(3, ast_format_gsm, 0);
+ add_static_payload(4, ast_format_g723, 0);
+ add_static_payload(5, ast_format_adpcm, 0);/* 8 kHz */
+ add_static_payload(6, ast_format_adpcm, 0); /* 16 kHz */
+ add_static_payload(7, ast_format_lpc10, 0);
+ add_static_payload(8, ast_format_alaw, 0);
+ add_static_payload(9, ast_format_g722, 0);
+ add_static_payload(10, ast_format_slin, 0); /* 2 channels */
+ add_static_payload(11, ast_format_slin, 0); /* 1 channel */
add_static_payload(13, NULL, AST_RTP_CN);
- add_static_payload(16, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0); /* 11.025 kHz */
- add_static_payload(17, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0); /* 22.050 kHz */
- add_static_payload(18, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0);
+ add_static_payload(16, ast_format_adpcm, 0); /* 11.025 kHz */
+ add_static_payload(17, ast_format_adpcm, 0); /* 22.050 kHz */
+ add_static_payload(18, ast_format_g729, 0);
add_static_payload(19, NULL, AST_RTP_CN); /* Also used for CN */
- add_static_payload(26, ast_format_set(&tmpfmt, AST_FORMAT_JPEG, 0), 0);
- add_static_payload(31, ast_format_set(&tmpfmt, AST_FORMAT_H261, 0), 0);
- add_static_payload(34, ast_format_set(&tmpfmt, AST_FORMAT_H263, 0), 0);
- add_static_payload(97, ast_format_set(&tmpfmt, AST_FORMAT_ILBC, 0), 0);
- add_static_payload(98, ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0);
- add_static_payload(99, ast_format_set(&tmpfmt, AST_FORMAT_H264, 0), 0);
+ add_static_payload(26, ast_format_jpeg, 0);
+ add_static_payload(31, ast_format_h261, 0);
+ add_static_payload(34, ast_format_h263, 0);
+ add_static_payload(97, ast_format_ilbc, 0);
+ add_static_payload(98, ast_format_h263p, 0);
+ add_static_payload(99, ast_format_h264, 0);
add_static_payload(101, NULL, AST_RTP_DTMF);
- add_static_payload(102, ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), 0);
- add_static_payload(103, ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0);
- add_static_payload(104, ast_format_set(&tmpfmt, AST_FORMAT_MP4_VIDEO, 0), 0);
- add_static_payload(105, ast_format_set(&tmpfmt, AST_FORMAT_T140RED, 0), 0); /* Real time text chat (with redundancy encoding) */
- add_static_payload(106, ast_format_set(&tmpfmt, AST_FORMAT_T140, 0), 0); /* Real time text chat */
- add_static_payload(110, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX, 0), 0);
- add_static_payload(111, ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), 0);
- add_static_payload(112, ast_format_set(&tmpfmt, AST_FORMAT_G726_AAL2, 0), 0);
- add_static_payload(115, ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), 0);
- add_static_payload(116, ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), 0);
- add_static_payload(117, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX16, 0), 0);
- add_static_payload(118, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0); /* 16 Khz signed linear */
- add_static_payload(119, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), 0);
+ add_static_payload(102, ast_format_siren7, 0);
+ add_static_payload(103, ast_format_h263p, 0);
+ add_static_payload(104, ast_format_mp4, 0);
+ add_static_payload(105, ast_format_t140_red, 0); /* Real time text chat (with redundancy encoding) */
+ add_static_payload(106, ast_format_t140, 0); /* Real time text chat */
+ add_static_payload(110, ast_format_speex, 0);
+ add_static_payload(111, ast_format_g726, 0);
+ add_static_payload(112, ast_format_g726_aal2, 0);
+ add_static_payload(115, ast_format_siren14, 0);
+ add_static_payload(116, ast_format_g719, 0);
+ add_static_payload(117, ast_format_speex16, 0);
+ add_static_payload(118, ast_format_slin16, 0); /* 16 Khz signed linear */
+ add_static_payload(119, ast_format_speex32, 0);
add_static_payload(121, NULL, AST_RTP_CISCO_DTMF); /* Must be type 121 */
/* Opus and VP8 */
- add_static_payload(100, ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0);
- add_static_payload(107, ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0);
+ add_static_payload(100, ast_format_vp8, 0);
+ add_static_payload(107, ast_format_opus, 0);
return 0;
}
diff --git a/main/slinfactory.c b/main/slinfactory.c
index 44efc420f..8c117d652 100644
--- a/main/slinfactory.c
+++ b/main/slinfactory.c
@@ -33,24 +33,26 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/slinfactory.h"
#include "asterisk/translate.h"
+#include "asterisk/astobj2.h"
void ast_slinfactory_init(struct ast_slinfactory *sf)
{
memset(sf, 0, sizeof(*sf));
sf->offset = sf->hold;
- ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR, 0);
+ sf->output_format = ao2_bump(ast_format_slin);
}
-int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, const struct ast_format *slin_out)
+int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, struct ast_format *slin_out)
{
memset(sf, 0, sizeof(*sf));
sf->offset = sf->hold;
- if (!ast_format_is_slinear(slin_out)) {
+ if (!ast_format_cache_is_slinear(slin_out)) {
return -1;
}
- ast_format_copy(&sf->output_format, slin_out);
+ sf->output_format = ao2_bump(slin_out);
return 0;
}
@@ -64,8 +66,14 @@ void ast_slinfactory_destroy(struct ast_slinfactory *sf)
sf->trans = NULL;
}
- while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
+ while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
ast_frfree(f);
+ }
+
+ ao2_cleanup(sf->output_format);
+ sf->output_format = NULL;
+ ao2_cleanup(sf->format);
+ sf->format = NULL;
}
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
@@ -83,22 +91,22 @@ int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
return 0;
}
- 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)) {
+ 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.format))) {
+ if (!(sf->trans = ast_translator_build_path(sf->output_format, f->subclass.format))) {
ast_log(LOG_WARNING, "Cannot build a path from %s (%u)to %s (%u)\n",
- ast_getformatname(&f->subclass.format),
- f->subclass.format.id,
- ast_getformatname(&sf->output_format),
- sf->output_format.id);
+ ast_format_get_name(f->subclass.format),
+ ast_format_get_codec_id(f->subclass.format),
+ ast_format_get_name(sf->output_format),
+ ast_format_get_codec_id(sf->output_format));
return 0;
}
- ast_format_copy(&sf->format, &f->subclass.format);
+ ao2_replace(sf->format, f->subclass.format);
}
if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
diff --git a/main/smoother.c b/main/smoother.c
new file mode 100644
index 000000000..720ad8549
--- /dev/null
+++ b/main/smoother.c
@@ -0,0 +1,227 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, 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 Frame smoother manipulation routines
+ *
+ * \author Mark Spencer <markster@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/_private.h"
+#include "asterisk/frame.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/time.h"
+#include "asterisk/utils.h"
+#include "asterisk/format.h"
+#include "asterisk/codec.h"
+#include "asterisk/smoother.h"
+
+#define SMOOTHER_SIZE 8000
+
+struct ast_smoother {
+ int size;
+ struct ast_format *format;
+ int flags;
+ float samplesperbyte;
+ unsigned int opt_needs_swap:1;
+ struct ast_frame f;
+ struct timeval delivery;
+ char data[SMOOTHER_SIZE];
+ char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
+ struct ast_frame *opt;
+ int len;
+};
+
+static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
+{
+ if (s->flags & AST_SMOOTHER_FLAG_G729) {
+ if (s->len % 10) {
+ ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
+ return 0;
+ }
+ }
+ if (swap) {
+ ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
+ } else {
+ memcpy(s->data + s->len, f->data.ptr, f->datalen);
+ }
+ /* If either side is empty, reset the delivery time */
+ if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) { /* XXX really ? */
+ s->delivery = f->delivery;
+ }
+ s->len += f->datalen;
+
+ return 0;
+}
+
+void ast_smoother_reset(struct ast_smoother *s, int bytes)
+{
+ ao2_cleanup(s->format);
+ memset(s, 0, sizeof(*s));
+ s->size = bytes;
+}
+
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
+{
+ /* if there is no change, then nothing to do */
+ if (s->size == bytes) {
+ return;
+ }
+ /* set the new desired output size */
+ s->size = bytes;
+ /* if there is no 'optimized' frame in the smoother,
+ * then there is nothing left to do
+ */
+ if (!s->opt) {
+ return;
+ }
+ /* there is an 'optimized' frame here at the old size,
+ * but it must now be put into the buffer so the data
+ * can be extracted at the new size
+ */
+ smoother_frame_feed(s, s->opt, s->opt_needs_swap);
+ s->opt = NULL;
+}
+
+struct ast_smoother *ast_smoother_new(int size)
+{
+ struct ast_smoother *s;
+ if (size < 1)
+ return NULL;
+ if ((s = ast_calloc(1, sizeof(*s))))
+ ast_smoother_reset(s, size);
+ return s;
+}
+
+int ast_smoother_get_flags(struct ast_smoother *s)
+{
+ return s->flags;
+}
+
+void ast_smoother_set_flags(struct ast_smoother *s, int flags)
+{
+ s->flags = flags;
+}
+
+int ast_smoother_test_flag(struct ast_smoother *s, int flag)
+{
+ return (s->flags & flag);
+}
+
+int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
+{
+ if (f->frametype != AST_FRAME_VOICE) {
+ ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
+ return -1;
+ }
+ if (!s->format) {
+ s->format = ao2_bump(f->subclass.format);
+ s->samplesperbyte = (float)f->samples / (float)f->datalen;
+ } 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_format_get_name(s->format), ast_format_get_name(f->subclass.format));
+ return -1;
+ }
+ if (s->len + f->datalen > SMOOTHER_SIZE) {
+ ast_log(LOG_WARNING, "Out of smoother space\n");
+ return -1;
+ }
+ if (((f->datalen == s->size) ||
+ ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
+ !s->opt &&
+ !s->len &&
+ (f->offset >= AST_MIN_OFFSET)) {
+ /* Optimize by sending the frame we just got
+ on the next read, thus eliminating the douple
+ copy */
+ if (swap)
+ ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
+ s->opt = f;
+ s->opt_needs_swap = swap ? 1 : 0;
+ return 0;
+ }
+
+ return smoother_frame_feed(s, f, swap);
+}
+
+struct ast_frame *ast_smoother_read(struct ast_smoother *s)
+{
+ struct ast_frame *opt;
+ int len;
+
+ /* IF we have an optimization frame, send it */
+ if (s->opt) {
+ if (s->opt->offset < AST_FRIENDLY_OFFSET)
+ ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
+ s->opt->offset);
+ opt = s->opt;
+ s->opt = NULL;
+ return opt;
+ }
+
+ /* Make sure we have enough data */
+ if (s->len < s->size) {
+ /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
+ if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
+ return NULL;
+ }
+ len = s->size;
+ if (len > s->len)
+ len = s->len;
+ /* Make frame */
+ s->f.frametype = AST_FRAME_VOICE;
+ 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;
+ /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
+ s->f.samples = len * s->samplesperbyte; /* XXX rounding */
+ s->f.delivery = s->delivery;
+ /* Fill Data */
+ memcpy(s->f.data.ptr, s->data, len);
+ s->len -= len;
+ /* Move remaining data to the front if applicable */
+ if (s->len) {
+ /* In principle this should all be fine because if we are sending
+ G.729 VAD, the next timestamp will take over anyawy */
+ 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_get_sample_rate(s->format)));
+ }
+ }
+ /* Return frame */
+ return &s->f;
+}
+
+void ast_smoother_free(struct ast_smoother *s)
+{
+ ao2_cleanup(s->format);
+ ast_free(s);
+}
+
diff --git a/main/sorcery.c b/main/sorcery.c
index 9488dee4b..85a699bcb 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -43,7 +43,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/taskprocessor.h"
#include "asterisk/threadpool.h"
#include "asterisk/json.h"
-#include "asterisk/format_pref.h"
/* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
#undef open
@@ -233,10 +232,9 @@ static int chararray_handler_fn(const void *obj, const intptr_t *args, char **bu
static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
{
- char tmp_buf[256];
- struct ast_codec_pref *pref = (struct ast_codec_pref *)(obj + args[0]);
- ast_codec_pref_string(pref, tmp_buf, sizeof(tmp_buf));
- return !(*buf = ast_strdup(tmp_buf));
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
+ return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
}
static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
diff --git a/main/sounds_index.c b/main/sounds_index.c
index 41430fa45..bc5263908 100644
--- a/main/sounds_index.c
+++ b/main/sounds_index.c
@@ -158,10 +158,10 @@ static int show_sound_info_cb(void *obj, void *arg, int flags)
{
char *language = obj;
struct ast_cli_args *a = arg;
- struct ast_format format;
+ struct ast_format *format;
int formats_shown = 0;
RAII_VAR(struct ast_media_index *, local_index, ast_sounds_get_index(), ao2_cleanup);
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
+ struct ast_format_cap *cap;
const char *description = ast_media_get_description(local_index, a->argv[3], language);
ast_cli(a->fd, " Language %s:\n", language);
@@ -171,12 +171,14 @@ static int show_sound_info_cb(void *obj, void *arg, int flags)
cap = ast_media_get_format_cap(local_index, a->argv[3], language);
if (cap) {
- ast_format_cap_iter_start(cap);
- while (!ast_format_cap_iter_next(cap, &format)) {
- ast_cli(a->fd, " Format: %s\n", ast_getformatname(&format));
+ int x;
+ for (x = 0; x < ast_format_cap_count(cap); x++) {
+ format = ast_format_cap_get_format(cap, x);
+ ast_cli(a->fd, " Format: %s\n", ast_format_get_name(format));
+ ao2_ref(format, -1);
formats_shown = 1;
- }
- ast_format_cap_iter_end(cap);
+ }
+ ao2_ref(cap, -1);
}
if (!formats_shown) {
diff --git a/main/translate.c b/main/translate.c
index c24700b45..0696f5d83 100644
--- a/main/translate.c
+++ b/main/translate.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
+#include "asterisk/format.h"
/*! \todo
* TODO: sample frames for each supported input format.
@@ -76,11 +77,11 @@ struct translator_path {
static struct translator_path **__matrix;
/*!
- * \brief table for converting index to format id values.
+ * \brief table for converting index to format values.
*
* \note this table is protected by the table_lock.
*/
-static int *__indextable;
+static unsigned int *__indextable;
/*! protects the __indextable for resizing */
static ast_rwlock_t tablelock;
@@ -99,9 +100,9 @@ static void matrix_rebuild(int samples);
/*!
* \internal
- * \brief converts format id to index value.
+ * \brief converts codec id to index value.
*/
-static int format2index(enum ast_format_id id)
+static int codec_to_index(unsigned int id)
{
int x;
@@ -119,16 +120,34 @@ static int format2index(enum ast_format_id id)
/*!
* \internal
- * \brief add a new format to the matrix and index table structures.
+ * \brief converts codec to index value.
+ */
+static int codec2index(struct ast_codec *codec)
+{
+ return codec_to_index(codec->id);
+}
+
+/*!
+ * \internal
+ * \brief converts format to codec index value.
+ */
+static int format2index(struct ast_format *format)
+{
+ return codec_to_index(ast_format_get_codec_id(format));
+}
+
+/*!
+ * \internal
+ * \brief add a new codec to the matrix and index table structures.
*
- * \note it is perfectly safe to call this on formats already indexed.
+ * \note it is perfectly safe to call this on codecs already indexed.
*
* \retval 0, success
* \retval -1, matrix and index table need to be resized
*/
-static int add_format2index(enum ast_format_id id)
+static int add_codec2index(struct ast_codec *codec)
{
- if (format2index(id) >= 0) {
+ if (codec2index(codec) != -1) {
/* format is already already indexed */
return 0;
}
@@ -138,7 +157,7 @@ static int add_format2index(enum ast_format_id id)
ast_rwlock_unlock(&tablelock);
return -1; /* hit max length */
}
- __indextable[cur_max_index] = id;
+ __indextable[cur_max_index] = codec->id;
cur_max_index++;
ast_rwlock_unlock(&tablelock);
@@ -147,20 +166,20 @@ static int add_format2index(enum ast_format_id id)
/*!
* \internal
- * \brief converts index value back to format id
+ * \brief converts index value back to codec
*/
-static enum ast_format_id index2format(int index)
+static struct ast_codec *index2codec(int index)
{
- enum ast_format_id format_id;
+ struct ast_codec *codec;
if (index >= cur_max_index) {
return 0;
}
ast_rwlock_rdlock(&tablelock);
- format_id = __indextable[index];
+ codec = ast_codec_get_by_id(__indextable[index]);
ast_rwlock_unlock(&tablelock);
- return format_id;
+ return codec;
}
/*!
@@ -176,7 +195,7 @@ static enum ast_format_id index2format(int index)
static int matrix_resize(int init)
{
struct translator_path **tmp_matrix = NULL;
- int *tmp_table = NULL;
+ unsigned int *tmp_table = NULL;
int old_index;
int x;
@@ -202,7 +221,7 @@ static int matrix_resize(int init)
}
/* make new index table */
- if (!(tmp_table = ast_calloc(1, sizeof(int) * index_size))) {
+ if (!(tmp_table = ast_calloc(1, sizeof(unsigned int) * index_size))) {
goto resize_cleanup;
}
@@ -213,7 +232,7 @@ static int matrix_resize(int init)
}
ast_free(__matrix);
- memcpy(tmp_table, __indextable, sizeof(int) * old_index);
+ memcpy(tmp_table, __indextable, sizeof(unsigned int) * old_index);
ast_free(__indextable);
}
@@ -270,11 +289,23 @@ static struct translator_path *matrix_get(unsigned int x, unsigned int y)
* wrappers around the translator routines.
*/
+static void destroy(struct ast_trans_pvt *pvt)
+{
+ struct ast_translator *t = pvt->t;
+
+ if (t->destroy) {
+ t->destroy(pvt);
+ }
+ ao2_cleanup(pvt->f.subclass.format);
+ ast_free(pvt);
+ ast_module_unref(t->module);
+}
+
/*!
* \brief Allocate the descriptor, required outbuf space,
* and possibly desc.
*/
-static void *newpvt(struct ast_translator *t, const struct ast_format *explicit_dst)
+static struct ast_trans_pvt *newpvt(struct ast_translator *t)
{
struct ast_trans_pvt *pvt;
int len;
@@ -300,28 +331,49 @@ static void *newpvt(struct ast_translator *t, const struct ast_format *explicit_
if (t->buf_size) {/* finally buffer and header */
pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
}
- /* if a explicit destination format is provided, set that on the pvt so the
- * translator will process it. */
- if (explicit_dst) {
- ast_format_copy(&pvt->explicit_dst, explicit_dst);
- }
+
+ ast_module_ref(t->module);
+
/* call local init routine, if present */
if (t->newpvt && t->newpvt(pvt)) {
ast_free(pvt);
+ ast_module_unref(t->module);
return NULL;
}
- ast_module_ref(t->module);
- return pvt;
-}
-static void destroy(struct ast_trans_pvt *pvt)
-{
- struct ast_translator *t = pvt->t;
+ /* Setup normal static translation frame. */
+ pvt->f.frametype = AST_FRAME_VOICE;
+ pvt->f.mallocd = 0;
+ pvt->f.offset = AST_FRIENDLY_OFFSET;
+ pvt->f.src = pvt->t->name;
+ pvt->f.data.ptr = pvt->outbuf.c;
- if (t->destroy)
- t->destroy(pvt);
- ast_free(pvt);
- ast_module_unref(t->module);
+ /* if the translator has not provided a format find one in the cache or create one */
+ if (!pvt->f.subclass.format) {
+ if (!ast_strlen_zero(pvt->t->format)) {
+ pvt->f.subclass.format = ast_format_cache_get(pvt->t->format);
+ }
+
+ if (!pvt->f.subclass.format) {
+ struct ast_codec *codec = ast_codec_get(t->dst_codec.name,
+ t->dst_codec.type, t->dst_codec.sample_rate);
+ if (!codec) {
+ ast_log(LOG_ERROR, "Unable to get destination codec\n");
+ destroy(pvt);
+ return NULL;
+ }
+ pvt->f.subclass.format = ast_format_create(codec);
+ ao2_ref(codec, -1);
+ }
+
+ if (!pvt->f.subclass.format) {
+ ast_log(LOG_ERROR, "Unable to create format\n");
+ destroy(pvt);
+ return NULL;
+ }
+ }
+
+ return pvt;
}
/*! \brief framein wrapper, deals with bound checks. */
@@ -374,8 +426,9 @@ struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
if (samples) {
f->samples = samples;
} else {
- if (pvt->samples == 0)
+ if (pvt->samples == 0) {
return NULL;
+ }
f->samples = pvt->samples;
pvt->samples = 0;
}
@@ -386,13 +439,6 @@ struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
pvt->datalen = 0;
}
- f->frametype = AST_FRAME_VOICE;
- ast_format_copy(&f->subclass.format, &pvt->t->dst_format);
- f->mallocd = 0;
- f->offset = AST_FRIENDLY_OFFSET;
- f->src = pvt->t->name;
- f->data.ptr = pvt->outbuf.c;
-
return ast_frisolate(f);
}
@@ -417,11 +463,9 @@ struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct a
{
struct ast_trans_pvt *head = NULL, *tail = NULL;
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);
+ src_index = format2index(src);
+ dst_index = format2index(dst);
if (src_index < 0 || dst_index < 0) {
ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index < 0 ? "starting" : "ending");
@@ -432,26 +476,16 @@ struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct a
while (src_index != dst_index) {
struct ast_trans_pvt *cur;
- struct ast_format *explicit_dst = NULL;
struct ast_translator *t = matrix_get(src_index, dst_index)->step;
if (!t) {
- 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_format_get_name(src), ast_format_get_name(dst));
AST_RWLIST_UNLOCK(&translators);
return NULL;
}
- if (dst_index == t->dst_fmt_index) {
- explicit_dst = dst;
- }
- if (!(cur = newpvt(t, explicit_dst))) {
- int src_id = index2format(src_index);
- int dst_id = index2format(dst_index);
+ if (!(cur = newpvt(t))) {
ast_log(LOG_WARNING, "Failed to build translator step 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_format_get_name(src), ast_format_get_name(dst));
if (head) {
ast_translator_free_path(head);
}
@@ -508,7 +542,8 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f,
path->nextout = f->delivery;
}
/* Predict next incoming sample */
- path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(&f->subclass.format)));
+ path->nextin = ast_tvadd(path->nextin, ast_samp2tv(
+ f->samples, ast_format_get_sample_rate(f->subclass.format)));
}
delivery = f->delivery;
for (out = f; out && p ; p = p->next) {
@@ -531,7 +566,8 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f,
/* Predict next outgoing timestamp from samples in this
frame. */
- path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(&out->subclass.format)));
+ path->nextout = ast_tvadd(path->nextout, ast_samp2tv(
+ out->samples, ast_format_get_sample_rate(out->subclass.format)));
if (f->samples != out->samples && ast_test_flag(out, AST_FRFLAG_HAS_TIMING_INFO)) {
ast_debug(4, "Sample size different %d vs %d\n", f->samples, out->samples);
ast_clear_flag(out, AST_FRFLAG_HAS_TIMING_INFO);
@@ -572,7 +608,7 @@ static void generate_computational_cost(struct ast_translator *t, int seconds)
struct rusage start;
struct rusage end;
int cost;
- int out_rate = ast_format_rate(&t->dst_format);
+ int out_rate = t->dst_codec.sample_rate;
if (!seconds) {
seconds = 1;
@@ -585,7 +621,7 @@ static void generate_computational_cost(struct ast_translator *t, int seconds)
return;
}
- pvt = newpvt(t, NULL);
+ pvt = newpvt(t);
if (!pvt) {
ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
t->comp_cost = 999999;
@@ -643,21 +679,23 @@ static void generate_computational_cost(struct ast_translator *t, int seconds)
* \retval Table Cost value greater than 0.
* \retval 0 on error.
*/
-static int generate_table_cost(struct ast_format *src, struct ast_format *dst)
+static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
{
- int src_rate = ast_format_rate(src);
+ int src_rate = src->sample_rate;
int src_ll = 0;
- int dst_rate = ast_format_rate(dst);
+ int dst_rate = dst->sample_rate;
int dst_ll = 0;
- if ((AST_FORMAT_GET_TYPE(src->id) != AST_FORMAT_TYPE_AUDIO) || (AST_FORMAT_GET_TYPE(dst->id) != AST_FORMAT_TYPE_AUDIO)) {
+ if ((src->type != AST_MEDIA_TYPE_AUDIO) ||
+ (dst->type != AST_MEDIA_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;
}
- src_ll = ast_format_is_slinear(src);
- dst_ll = ast_format_is_slinear(dst);
+
+ src_ll = !strcmp(src->name, "slin");
+ dst_ll = !strcmp(dst->name, "slin");
if (src_ll) {
if (dst_ll && (src_rate == dst_rate)) {
return AST_TRANS_COST_LL_LL_ORIGSAMP;
@@ -763,18 +801,25 @@ static void matrix_rebuild(int samples)
/* 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(10, "Discovered %u 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 (DEBUG_ATLEAST(10)) {
+ struct ast_codec *x_codec = index2codec(x);
+ struct ast_codec *y_codec = index2codec(y);
+ struct ast_codec *z_codec = index2codec(z);
+
+ ast_log(LOG_DEBUG,
+ "Discovered %u cost path from %s to %s, via %s\n",
+ matrix_get(x, z)->table_cost, x_codec->name,
+ y_codec->name, z_codec->name);
+
+ ao2_ref(x_codec, -1);
+ ao2_ref(y_codec, -1);
+ ao2_ref(z_codec, -1);
+ }
}
}
}
@@ -785,20 +830,26 @@ static void matrix_rebuild(int samples)
}
}
-const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
+static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
{
- struct ast_trans_pvt *pn = p;
- char tmp[256];
+ if (codec) {
+ ast_str_append(buf, 0, "(%s@%u)", codec->name, codec->sample_rate);
+ } else {
+ ast_str_append(buf, 0, "(nothing)");
+ }
+}
+const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
+{
if (!p || !p->t) {
return "";
}
- ast_str_set(str, 0, "%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), p->t->src_format.id));
-
- while ( (p = pn) ) {
- pn = p->next;
- ast_str_append(str, 0, "->%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), p->t->dst_format.id));
+ codec_append_name(&p->t->src_codec, str);
+ while (p) {
+ ast_str_append(str, 0, "->");
+ codec_append_name(&p->t->dst_codec, str);
+ p = p->next;
}
return ast_str_buffer(*str);
@@ -806,24 +857,24 @@ const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **
static char *complete_trans_path_choice(const char *line, const char *word, int pos, int state)
{
- int which = 0;
+ int i = 1, which = 0;
int wordlen = strlen(word);
- int i;
- char *ret = NULL;
- size_t len = 0;
- const struct ast_format_list *format_list = ast_format_list_get(&len);
+ struct ast_codec *codec;
- for (i = 0; i < len; i++) {
- if (AST_FORMAT_GET_TYPE(format_list[i].format.id) != AST_FORMAT_TYPE_AUDIO) {
+ while ((codec = ast_codec_get_by_id(i))) {
+ ++i;
+ if (codec->type != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(codec, -1);
continue;
}
- if (!strncasecmp(word, format_list[i].name, wordlen) && ++which > state) {
- ret = ast_strdup(format_list[i].name);
- break;
+ if (!strncasecmp(word, codec->name, wordlen) && ++which > state) {
+ char *res = ast_strdup(codec->name);
+ ao2_ref(codec, -1);
+ return res;
}
+ ao2_ref(codec, -1);
}
- ast_format_list_destroy(format_list);
- return ret;
+ return NULL;
}
static void handle_cli_recalc(struct ast_cli_args *a)
@@ -847,63 +898,61 @@ static void handle_cli_recalc(struct ast_cli_args *a)
static char *handle_show_translation_table(struct ast_cli_args *a)
{
- int x;
- int y;
- int i;
- int k;
- int curlen = 0;
- int longest = 0;
- int f_len;
- size_t f_size = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_size);
+ int x, y, i, k;
+ int longest = 0, num_codecs = 0, curlen = 0;
struct ast_str *out = ast_str_create(1024);
+ struct ast_codec *codec;
- f_len = f_size;
- 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 (i = 0; i < f_len; i++) {
- /* translation only applies to audio right now. */
- if (AST_FORMAT_GET_TYPE(f_list[i].format.id) != AST_FORMAT_TYPE_AUDIO)
+ /* Get the length of the longest (usable?) codec name,
+ so we know how wide the left side should be */
+ for (i = 1; (codec = ast_codec_get_by_id(i)); ao2_ref(codec, -1), ++i) {
+ ++num_codecs;
+ if (codec->type != AST_MEDIA_TYPE_AUDIO) {
continue;
- curlen = strlen(ast_getformatname(&f_list[i].format));
+ }
+ curlen = strlen(codec->name);
if (curlen > longest) {
longest = curlen;
}
}
- for (i = -1; i < f_len; i++) {
+ 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");
+
+ for (i = 0; i < num_codecs; i++) {
+ struct ast_codec *row = i ? ast_codec_get_by_id(i) : NULL;
+
x = -1;
- if ((i >= 0) && ((x = format2index(f_list[i].format.id)) < 0)) {
- continue;
- }
- /* translation only applies to audio right now. */
- if (i >= 0 && (AST_FORMAT_GET_TYPE(f_list[i].format.id) != AST_FORMAT_TYPE_AUDIO)) {
+ if ((i > 0) && (row->type != AST_MEDIA_TYPE_AUDIO)) {
+ ao2_ref(row, -1);
continue;
}
- /*Go ahead and move to next iteration if dealing with an unknown codec*/
- if (i >= 0 && !strcmp(ast_getformatname(&f_list[i].format), "unknown")) {
+
+ if ((i > 0) && (x = codec2index(row)) == -1) {
+ ao2_ref(row, -1);
continue;
}
+
ast_str_set(&out, 0, " ");
- for (k = -1; k < f_len; k++) {
+ for (k = 0; k < num_codecs; k++) {
+ struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL;
+
y = -1;
- if ((k >= 0) && ((y = format2index(f_list[k].format.id)) < 0)) {
+ if ((k > 0) && (col->type != AST_MEDIA_TYPE_AUDIO)) {
+ ao2_ref(col, -1);
continue;
}
- /* translation only applies to audio right now. */
- if (k >= 0 && (AST_FORMAT_GET_TYPE(f_list[k].format.id) != AST_FORMAT_TYPE_AUDIO)) {
- continue;
- }
- /*Go ahead and move to next iteration if dealing with an unknown codec*/
- if (k >= 0 && !strcmp(ast_getformatname(&f_list[k].format), "unknown")) {
+
+ if ((k > 0) && (y = codec2index(col)) == -1) {
+ ao2_ref(col, -1);
continue;
}
- if (k >= 0) {
- curlen = strlen(ast_getformatname(&f_list[k].format));
+
+ if (k > 0) {
+ curlen = strlen(col->name);
}
+
if (curlen < 5) {
curlen = 5;
}
@@ -911,12 +960,12 @@ static char *handle_show_translation_table(struct ast_cli_args *a)
if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
/* Actual codec output */
ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost/100));
- } else if (i == -1 && k >= 0) {
+ } else if (i == 0 && k > 0) {
/* Top row - use a dynamic size */
- ast_str_append(&out, 0, "%*s", curlen + 1, ast_getformatname(&f_list[k].format));
- } else if (k == -1 && i >= 0) {
+ ast_str_append(&out, 0, "%*s", curlen + 1, col->name);
+ } else if (k == 0 && i > 0) {
/* Left column - use a static size. */
- ast_str_append(&out, 0, "%*s", longest, ast_getformatname(&f_list[i].format));
+ ast_str_append(&out, 0, "%*s", longest, row->name);
} else if (x >= 0 && y >= 0) {
/* Codec not supported */
ast_str_append(&out, 0, "%*s", curlen + 1, "-");
@@ -924,74 +973,79 @@ static char *handle_show_translation_table(struct ast_cli_args *a)
/* Upper left hand corner */
ast_str_append(&out, 0, "%*s", longest, "");
}
+ ao2_cleanup(col);
}
ast_str_append(&out, 0, "\n");
ast_cli(a->fd, "%s", ast_str_buffer(out));
+ ao2_cleanup(row);
}
ast_free(out);
AST_RWLIST_UNLOCK(&translators);
- ast_format_list_destroy(f_list);
return CLI_SUCCESS;
}
-static char *handle_show_translation_path(struct ast_cli_args *a)
+static char *handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
{
- struct ast_format input_src_format;
- size_t len = 0;
- int i;
- const struct ast_format_list *format_list = ast_format_list_get(&len);
+ int i = 1;
struct ast_str *str = ast_str_alloca(1024);
struct ast_translator *step;
- char tmp[256];
+ struct ast_codec *dst_codec;
+ struct ast_codec *src_codec = ast_codec_get(codec_name, AST_MEDIA_TYPE_AUDIO, sample_rate);
- ast_format_clear(&input_src_format);
- for (i = 0; i < len; i++) {
- if (AST_FORMAT_GET_TYPE(format_list[i].format.id) != AST_FORMAT_TYPE_AUDIO) {
- continue;
- }
- if (!strncasecmp(format_list[i].name, a->argv[4], strlen(format_list[i].name))) {
- ast_format_copy(&input_src_format, &format_list[i].format);
- }
- }
-
- if (!input_src_format.id) {
- ast_cli(a->fd, "Source codec \"%s\" is not found.\n", a->argv[4]);
- ast_format_list_destroy(format_list);
+ if (!src_codec) {
+ ast_cli(a->fd, "Source codec \"%s\" is not found.\n", codec_name);
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].format.id) != AST_FORMAT_TYPE_AUDIO) || (format_list[i].format.id == input_src_format.id)) {
+ ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
+ codec_name, src_codec->sample_rate);
+
+ while ((dst_codec = ast_codec_get_by_id(i))) {
+ int src, dst;
+ char src_buffer[64];
+ char dst_buffer[64];
+
+ ++i;
+ if (src_codec == dst_codec ||
+ dst_codec->type != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(dst_codec, -1);
continue;
}
- dst = format2index(format_list[i].format.id);
- src = format2index(input_src_format.id);
- ast_str_reset(str);
- if ((len >= cur_max_index) && (src >= 0) && (dst >= 0) && matrix_get(src, dst)->step) {
- ast_str_append(&str, 0, "%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), matrix_get(src, dst)->step->src_format.id));
- while (src != dst) {
- step = matrix_get(src, dst)->step;
- if (!step) {
- ast_str_reset(str);
- break;
+
+ dst = codec2index(dst_codec);
+ src = codec2index(src_codec);
+
+ if (src < 0 || dst < 0) {
+ ast_str_set(&str, 0, "No Translation Path");
+ } else {
+ step = matrix_get(src, dst)->step;
+
+ if (step) {
+ codec_append_name(&step->src_codec, &str);
+ while (src != dst) {
+ src = step->dst_fmt_index;
+ step = matrix_get(src, dst)->step;
+ if (!step) {
+ ast_str_append(&str, 0, "->");
+ codec_append_name(dst_codec, &str);
+ break;
+ }
+ ast_str_append(&str, 0, "->");
+ codec_append_name(&step->src_codec, &str);
}
- ast_str_append(&str, 0, "->%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), step->dst_format.id));
- 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));
+ snprintf(src_buffer, sizeof(src_buffer), "%s:%u", src_codec->name, src_codec->sample_rate);
+ snprintf(dst_buffer, sizeof(dst_buffer), "%s:%u", dst_codec->name, dst_codec->sample_rate);
+ ast_cli(a->fd, "\t%-16.16s To %-16.16s: %-60.60s\n",
+ src_buffer, dst_buffer, ast_str_buffer(str));
+ ast_str_reset(str);
+ ao2_ref(dst_codec, -1);
}
AST_RWLIST_UNLOCK(&translators);
-
- ast_format_list_destroy(format_list);
+ ao2_ref(src_codec, -1);
return CLI_SUCCESS;
}
@@ -1009,8 +1063,10 @@ static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd,
" 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";
+ " 2. 'core show translation paths [codec [sample_rate]]'\n"
+ " This will display all the translation paths associated with a codec.\n"
+ " If a codec has multiple sample rates, the sample rate must be\n"
+ " provided as well.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 3) {
@@ -1019,14 +1075,22 @@ static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd,
if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) {
return complete_trans_path_choice(a->line, a->word, a->pos, a->n);
}
+ /* BUGBUG - add tab completion for sample rates */
return NULL;
}
- if (a->argc > 5)
+ if (a->argc > 6)
return CLI_SHOWUSAGE;
if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */
- return handle_show_translation_path(a);
+ return handle_show_translation_path(a, a->argv[4], 0);
+ } else if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 6) {
+ unsigned int sample_rate;
+ if (sscanf(a->argv[5], "%30u", &sample_rate) != 1) {
+ ast_cli(a->fd, "Invalid sample rate: %s.\n", a->argv[5]);
+ return CLI_FAILURE;
+ }
+ return handle_show_translation_path(a, a->argv[4], sample_rate);
} 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 */
@@ -1045,14 +1109,29 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
{
struct ast_translator *u;
char tmp[80];
+ RAII_VAR(struct ast_codec *, src_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, dst_codec, NULL, ao2_cleanup);
- if (add_format2index(t->src_format.id) || add_format2index(t->dst_format.id)) {
+ src_codec = ast_codec_get(t->src_codec.name, t->src_codec.type, t->src_codec.sample_rate);
+ if (!src_codec) {
+ ast_assert(0);
+ ast_log(LOG_WARNING, "Failed to register translator: unknown source codec %s\n", t->src_codec.name);
+ return -1;
+ }
+
+ dst_codec = ast_codec_get(t->dst_codec.name, t->dst_codec.type, t->dst_codec.sample_rate);
+ if (!dst_codec) {
+ ast_log(LOG_WARNING, "Failed to register translator: unknown destination codec %s\n", t->dst_codec.name);
+ return -1;
+ }
+
+ if (add_codec2index(src_codec) || add_codec2index(dst_codec)) {
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);
+ add_codec2index(src_codec);
+ add_codec2index(dst_codec);
}
if (!mod) {
@@ -1064,15 +1143,15 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
return -1;
}
- if (!t->table_cost && !(t->table_cost = generate_table_cost(&t->src_format, &t->dst_format))) {
+ if (!t->table_cost && !(t->table_cost = generate_table_cost(src_codec, dst_codec))) {
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->src_fmt_index = format2index(t->src_format.id);
- t->dst_fmt_index = format2index(t->dst_format.id);
+ t->src_fmt_index = codec2index(src_codec);
+ t->dst_fmt_index = codec2index(dst_codec);
t->active = 1;
if (t->src_fmt_index < 0 || t->dst_fmt_index < 0) {
@@ -1080,12 +1159,12 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
return -1;
}
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));
+ ast_log(LOG_WARNING, "Source codec %s is larger than cur_max_index\n", t->src_codec.name);
return -1;
}
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));
+ ast_log(LOG_WARNING, "Destination codec %s is larger than cur_max_index\n", t->dst_codec.name);
return -1;
}
@@ -1106,9 +1185,9 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
generate_computational_cost(t, 1);
- 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_verb(2, "Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
+ term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
+ t->src_codec.name, t->dst_codec.name, t->table_cost, t->comp_cost);
AST_RWLIST_WRLOCK(&translators);
@@ -1125,7 +1204,7 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
}
AST_RWLIST_TRAVERSE_SAFE_END;
- /* if no existing translator was found for this format combination,
+ /* if no existing translator was found for this codec combination,
add it to the beginning of the list */
if (t) {
AST_RWLIST_INSERT_HEAD(&translators, t, list);
@@ -1149,10 +1228,9 @@ int ast_unregister_translator(struct ast_translator *t)
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
if (u == t) {
AST_RWLIST_REMOVE_CURRENT(list);
- ast_verb(2, "Unregistered translator '%s' from format %s to %s\n",
+ ast_verb(2, "Unregistered translator '%s' from codec %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));
+ t->src_codec.name, t->dst_codec.name);
found = 1;
break;
}
@@ -1187,91 +1265,105 @@ void ast_translator_deactivate(struct ast_translator *t)
/*! \brief Calculate our best translator source format, given costs, and a desired destination */
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)
+ struct ast_format **dst_fmt_out,
+ struct ast_format **src_fmt_out)
{
- struct ast_format best;
- struct ast_format_cap *joint_cap = ast_format_cap_joint(dst_cap, src_cap);
+ unsigned int besttablecost = INT_MAX;
+ unsigned int beststeps = INT_MAX;
+ RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, bestdst, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, joint_cap, NULL, ao2_cleanup);
+ int i;
+ int j;
- ast_format_clear(&best);
+ if (!(joint_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ return -1;
+ }
+ ast_format_cap_get_compatible(dst_cap, src_cap, joint_cap);
- if (joint_cap) { /* yes, pick one and return */
- struct ast_format tmp_fmt;
+ for (i = 0; i < ast_format_cap_count(joint_cap); ++i) {
+ struct ast_format *fmt =
+ ast_format_cap_get_format(joint_cap, i);
- 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.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(&tmp_fmt)) {
- ast_format_copy(&best, &tmp_fmt);
- continue;
- }
+ if (!fmt) {
+ continue;
+ }
+
+ if (!best) {
+ /* No ao2_ref operations needed, we're done with fmt */
+ best = fmt;
+ continue;
}
- ast_format_cap_iter_end(joint_cap);
- /* We are done, this is a common format to both. */
- ast_format_copy(dst_fmt_out, &best);
- ast_format_copy(src_fmt_out, &best);
- ast_format_cap_destroy(joint_cap);
+ if (ast_format_get_sample_rate(best) <
+ ast_format_get_sample_rate(fmt)) {
+ ao2_replace(best, fmt);
+ }
+ ao2_ref(fmt, -1);
+ }
+
+ if (best) {
+ ao2_replace(*dst_fmt_out, best);
+ ao2_replace(*src_fmt_out, best);
return 0;
- } else { /* No, we will need to translate */
- unsigned int besttablecost = INT_MAX;
- unsigned int beststeps = INT_MAX;
- struct ast_format cur_dst;
- struct ast_format cur_src;
- struct ast_format bestdst;
+ }
+ /* need to translate */
+ AST_RWLIST_RDLOCK(&translators);
- ast_format_clear(&bestdst);
+ for (i = 0; i < ast_format_cap_count(dst_cap); ++i) {
+ struct ast_format *dst =
+ ast_format_cap_get_format(dst_cap, i);
- AST_RWLIST_RDLOCK(&translators);
- 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);
- struct translator_path *trans;
-
- if (x < 0 || y < 0) {
- continue;
- }
- trans = matrix_get(x, y);
- if (!trans || !trans->step) {
- continue;
- }
- if (trans->table_cost < besttablecost || trans->multistep < beststeps) {
- /* better than what we have so far */
- ast_format_copy(&best, &cur_src);
- ast_format_copy(&bestdst, &cur_dst);
- besttablecost = trans->table_cost;
- beststeps = trans->multistep;
- }
- }
- ast_format_cap_iter_end(src_cap);
+ if (!dst) {
+ continue;
}
- ast_format_cap_iter_end(dst_cap);
- AST_RWLIST_UNLOCK(&translators);
- if (best.id) {
- ast_format_copy(dst_fmt_out, &bestdst);
- ast_format_copy(src_fmt_out, &best);
- return 0;
+ for (j = 0; j < ast_format_cap_count(src_cap); ++j) {
+ struct ast_format *src =
+ ast_format_cap_get_format(src_cap, j);
+ int x, y;
+
+ if (!src) {
+ continue;
+ }
+
+ x = format2index(src);
+ y = format2index(dst);
+ if (x < 0 || y < 0) {
+ ao2_ref(src, -1);
+ continue;
+ }
+ if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
+ ao2_ref(src, -1);
+ continue;
+ }
+ if (((matrix_get(x, y)->table_cost < besttablecost) ||
+ (matrix_get(x, y)->multistep < beststeps))) {
+ /* better than what we have so far */
+ ao2_replace(best, src);
+ ao2_replace(bestdst, dst);
+ besttablecost = matrix_get(x, y)->table_cost;
+ beststeps = matrix_get(x, y)->multistep;
+ }
+ ao2_ref(src, -1);
}
+ ao2_ref(dst, -1);
+ }
+ AST_RWLIST_UNLOCK(&translators);
+ if (!best) {
return -1;
}
+ ao2_replace(*dst_fmt_out, bestdst);
+ ao2_replace(*src_fmt_out, best);
+ return 0;
}
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 = format2index(src_format->id);
- dest = format2index(dst_format->id);
+ int src = format2index(src_format);
+ int dest = format2index(dst_format);
if (src < 0 || dest < 0) {
ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src < 0 ? "starting" : "ending");
@@ -1288,25 +1380,72 @@ unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_
return res;
}
+static void check_translation_path(
+ struct ast_format_cap *dest, struct ast_format_cap *src,
+ struct ast_format_cap *result, struct ast_format *src_fmt,
+ enum ast_media_type type)
+{
+ int index, src_index = format2index(src_fmt);
+ /* For a given source format, traverse the list of
+ known formats to determine whether there exists
+ a translation path from the source format to the
+ destination format. */
+ for (index = 0; (src_index >= 0) && index < cur_max_index; index++) {
+ struct ast_codec *codec = index2codec(index);
+ RAII_VAR(struct ast_format *, fmt, ast_format_create(codec), ao2_cleanup);
+
+ ao2_ref(codec, -1);
+
+ if (ast_format_get_type(fmt) != type) {
+ continue;
+ }
+
+ /* if this is not a desired format, nothing to do */
+ if (ast_format_cap_iscompatible_format(dest, fmt) == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
+ }
+
+ /* if the source is supplying this format, then
+ we can leave it in the result */
+ if (ast_format_cap_iscompatible_format(src, fmt) == AST_FORMAT_CMP_EQUAL) {
+ continue;
+ }
+
+ /* if we don't have a translation path from the src
+ to this format, remove it from the result */
+ if (!matrix_get(src_index, index)->step) {
+ ast_format_cap_remove(result, fmt);
+ continue;
+ }
+
+ /* now check the opposite direction */
+ if (!matrix_get(index, src_index)->step) {
+ ast_format_cap_remove(result, fmt);
+ }
+ }
+
+}
+
void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
{
- struct ast_format tmp_fmt;
- struct ast_format cur_dest, cur_src;
- int src_audio = 0;
- int src_video = 0;
+ struct ast_format *cur_dest, *cur_src;
int index;
- ast_format_cap_iter_start(dest);
- while (!ast_format_cap_iter_next(dest, &cur_dest)) {
+ for (index = 0; index < ast_format_cap_count(dest); ++index) {
+ if (!(cur_dest = ast_format_cap_get_format(dest, index))) {
+ continue;
+ }
+
/* We give preference to a joint format structure if possible */
- if (ast_format_cap_get_compatible_format(src, &cur_dest, &tmp_fmt)) {
- ast_format_cap_add(result, &tmp_fmt);
+ if ((cur_src = ast_format_cap_get_compatible_format(src, cur_dest))) {
+ ast_format_cap_append(result, cur_src, 0);
+ ao2_ref(cur_src, -1);
} else {
/* Otherwise we just use the destination format */
- ast_format_cap_add(result, &cur_dest);
+ ast_format_cap_append(result, cur_dest, 0);
}
+ ao2_ref(cur_dest, -1);
}
- ast_format_cap_iter_end(dest);
/* if we don't have a source format, we just have to try all
possible destination formats */
@@ -1314,91 +1453,19 @@ void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_for
return;
}
- 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 (AST_FORMAT_GET_TYPE(cur_src.id) == AST_FORMAT_TYPE_VIDEO) {
- src_video = format2index(cur_src.id);
+ for (index = 0; index < ast_format_cap_count(src); ++index) {
+ if (!(cur_src = ast_format_cap_get_format(src, index))) {
+ continue;
}
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 (index = 0; (src_audio >= 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_AUDIO) {
- continue;
- }
-
- /* if this is not a desired format, nothing to do */
- if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) {
- 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;
- }
-
- /* 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;
- }
-
- /* now check the opposite direction */
- if (!matrix_get(index, src_audio)->step) {
- ast_format_cap_remove_byid(result, tmp_fmt.id);
- }
- }
-
- /* 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 this is not a desired format, nothing to do */
- if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) {
- 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;
- }
-
- /* 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;
- }
-
- /* now check the opposite direction */
- if (!matrix_get(index, src_video)->step) {
- ast_format_cap_remove_byid(result, tmp_fmt.id);
- }
- }
+ check_translation_path(dest, src, result,
+ cur_src, AST_MEDIA_TYPE_AUDIO);
+ check_translation_path(dest, src, result,
+ cur_src, AST_MEDIA_TYPE_VIDEO);
AST_RWLIST_UNLOCK(&translators);
+ ao2_ref(cur_src, -1);
}
- ast_format_cap_iter_end(src);
}
static void translate_shutdown(void)
diff --git a/main/utils.c b/main/utils.c
index 0097487a3..a916e79c8 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -1054,10 +1054,10 @@ struct ast_str *ast_dump_locks(void)
if (!header_printed) {
if (lock_info->lwp != -1) {
ast_str_append(&str, 0, "=== Thread ID: 0x%lx LWP:%d (%s)\n",
- (long) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
+ (long unsigned) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
} else {
ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n",
- (long) lock_info->thread_id, lock_info->thread_name);
+ (long unsigned) lock_info->thread_id, lock_info->thread_name);
}
header_printed = 1;
}
diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c
index 4461d7fc7..adec3b26a 100644
--- a/pbx/pbx_spool.c
+++ b/pbx/pbx_spool.c
@@ -53,6 +53,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
/*
* pbx_spool is similar in spirit to qcall, but with substantially enhanced functionality...
@@ -108,7 +110,7 @@ static void free_outgoing(struct outgoing *o)
if (o->vars) {
ast_variables_destroy(o->vars);
}
- o->capabilities = ast_format_cap_destroy(o->capabilities);
+ ao2_cleanup(o->capabilities);
ast_string_field_free_memory(o);
ast_free(o);
}
@@ -116,7 +118,6 @@ static void free_outgoing(struct outgoing *o)
static struct outgoing *new_outgoing(const char *fn)
{
struct outgoing *o;
- struct ast_format tmpfmt;
o = ast_calloc(1, sizeof(*o));
if (!o) {
@@ -144,12 +145,12 @@ static struct outgoing *new_outgoing(const char *fn)
return NULL;
}
- o->capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ o->capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!o->capabilities) {
free_outgoing(o);
return NULL;
}
- ast_format_cap_add(o->capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(o->capabilities, ast_format_slin, 0);
return o;
}
@@ -226,7 +227,7 @@ static int apply_outgoing(struct outgoing *o, FILE *f)
o->maxretries = 0;
}
} else if (!strcasecmp(buf, "codecs")) {
- ast_parse_allow_disallow(NULL, o->capabilities, c, 1);
+ ast_format_cap_update_by_allow_disallow(o->capabilities, c, 1);
} else if (!strcasecmp(buf, "context")) {
ast_string_field_set(o, context, c);
} else if (!strcasecmp(buf, "extension")) {
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index eeb4237d0..93ecd14b7 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/format_cap.h"
#include "asterisk/file.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
/*!
* \brief Finds a bridge, filling the response with an error, if appropriate.
@@ -303,19 +304,14 @@ static void *bridge_channel_control_thread(void *data)
static struct ast_channel *prepare_bridge_media_channel(const char *type)
{
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
- struct ast_format format;
+ RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return NULL;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
-
- if (!cap) {
- return NULL;
- }
+ ast_format_cap_append(cap, ast_format_slin, 0);
return ast_request(type, cap, NULL, NULL, "ARI", NULL);
}
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index 393609298..cef1e7130 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_app_snoop.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/causes.h"
+#include "asterisk/format_cache.h"
#include "asterisk/core_local.h"
#include "resource_channels.h"
@@ -772,8 +773,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
char *cid_name = NULL;
int timeout = 30000;
RAII_VAR(struct ast_format_cap *, cap,
- ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- struct ast_format tmp_fmt;
+ ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
char *stuff;
struct ast_channel *chan;
struct ast_channel *local_peer;
@@ -787,7 +787,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
ast_ari_response_alloc_failed(response);
return;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
|| (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
diff --git a/res/ari/resource_sounds.c b/res/ari/resource_sounds.c
index 5be4bf9a8..5a523d387 100644
--- a/res/ari/resource_sounds.c
+++ b/res/ari/resource_sounds.c
@@ -46,8 +46,8 @@ static int add_format_information_cb(void *obj, void *arg, int flags)
{
char *language = obj;
struct lang_format_info *args = arg;
- struct ast_format format;
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
+ int idx;
+ RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
if (!sounds_index) {
@@ -59,27 +59,28 @@ static int add_format_information_cb(void *obj, void *arg, int flags)
return CMP_STOP;
}
- ast_format_cap_iter_start(cap);
- while (!ast_format_cap_iter_next(cap, &format)) {
+ for (idx = 0; idx < ast_format_cap_count(cap); idx++) {
+ struct ast_format *format = ast_format_cap_get_format(cap, idx);
struct ast_json *lang_format_pair;
- const char *format_name = ast_getformatname(&format);
if (!ast_strlen_zero(args->format_filter)
- && strcmp(args->format_filter, format_name)) {
+ && strcmp(args->format_filter, ast_format_get_name(format))) {
+ ao2_ref(format, -1);
continue;
}
lang_format_pair = ast_json_pack("{s: s, s: s}",
"language", language,
- "format", format_name);
+ "format", ast_format_get_name(format));
if (!lang_format_pair) {
- ast_format_cap_iter_end(cap);
+ ao2_ref(format, -1);
return CMP_STOP;
}
ast_json_array_append(args->format_list, lang_format_pair);
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(cap);
+
return 0;
}
diff --git a/res/parking/parking_applications.c b/res/parking/parking_applications.c
index 51d6aff8f..8bb57b62b 100644
--- a/res/parking/parking_applications.c
+++ b/res/parking/parking_applications.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/say.h"
#include "asterisk/bridge_basic.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Park" language="en_US">
@@ -688,11 +689,10 @@ static void announce_to_dial(char *dial_string, char *announce_string, int parki
struct ast_channel *dchan;
struct outgoing_helper oh = { 0, };
int outstate;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
char buf[13];
char *dial_tech;
char *cur_announce;
- struct ast_format tmpfmt;
dial_tech = strsep(&dial_string, "/");
ast_verb(3, "Dial Tech,String: (%s,%s)\n", dial_tech, dial_string);
@@ -701,7 +701,7 @@ static void announce_to_dial(char *dial_string, char *announce_string, int parki
ast_log(LOG_WARNING, "PARK: Failed to announce park.\n");
goto announce_cleanup;
}
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
snprintf(buf, sizeof(buf), "%d", parkingspace);
oh.vars = ast_variable_new("_PARKEDAT", buf, "");
@@ -737,7 +737,7 @@ static void announce_to_dial(char *dial_string, char *announce_string, int parki
ast_hangup(dchan);
announce_cleanup:
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
}
static void park_announce_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
diff --git a/res/res_adsi.c b/res/res_adsi.c
index 92987f072..e11432e29 100644
--- a/res/res_adsi.c
+++ b/res/res_adsi.c
@@ -50,6 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/file.h"
#include "asterisk/adsi.h"
+#include "asterisk/format_cache.h"
#define DEFAULT_ADSI_MAX_RETRIES 3
@@ -154,12 +155,14 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
{
/* Sends carefully on a full duplex channel by using reading for
timing */
- struct ast_frame *inf, outf;
+ struct ast_frame *inf;
+ struct ast_frame outf = {
+ .frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_ulaw,
+ .data.ptr = buf,
+ };
int amt;
- /* Zero out our outgoing frame */
- memset(&outf, 0, sizeof(outf));
-
if (remain && *remain) {
amt = len;
@@ -169,9 +172,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
} else {
*remain = *remain - amt;
}
- outf.frametype = AST_FRAME_VOICE;
- ast_format_set(&outf.subclass.format, AST_FORMAT_ULAW, 0);
- outf.data.ptr = buf;
+
outf.datalen = amt;
outf.samples = amt;
if (ast_write(chan, &outf)) {
@@ -201,7 +202,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
continue;
}
- if (inf->subclass.format.id != AST_FORMAT_ULAW) {
+ if (ast_format_cmp(inf->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL) {
ast_log(LOG_WARNING, "Channel not in ulaw?\n");
ast_frfree(inf);
return -1;
@@ -212,9 +213,6 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
} else if (remain) {
*remain = inf->datalen - amt;
}
- outf.frametype = AST_FRAME_VOICE;
- ast_format_set(&outf.subclass.format, AST_FORMAT_ULAW, 0);
- outf.data.ptr = buf;
outf.datalen = amt;
outf.samples = amt;
if (ast_write(chan, &outf)) {
@@ -245,11 +243,9 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms
}
while (retries < maxretries) {
- struct ast_format tmpfmt;
if (!(ast_channel_adsicpe(chan) & ADSI_FLAG_DATAMODE)) {
/* Generate CAS (no SAS) */
- ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0);
- ast_gen_cas(buf, 0, 680, &tmpfmt);
+ ast_gen_cas(buf, 0, 680, ast_format_ulaw);
/* Send CAS */
if (adsi_careful_send(chan, buf, 680, NULL)) {
@@ -308,7 +304,7 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms
def= ast_channel_defer_dtmf(chan);
#endif
while ((x < 6) && msg[x]) {
- if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], ast_format_set(&tmpfmt, AST_FORMAT_ULAW,0))) < 0) {
+ if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], ast_format_ulaw)) < 0) {
ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, ast_channel_name(chan));
return -1;
}
@@ -395,11 +391,8 @@ static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *m
{
unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
int msglens[5], msgtypes[5], newdatamode = (ast_channel_adsicpe(chan) & ADSI_FLAG_DATAMODE), res, x, waitforswitch = 0;
- struct ast_format writeformat;
- struct ast_format readformat;
-
- ast_format_copy(&writeformat, ast_channel_writeformat(chan));
- ast_format_copy(&readformat, ast_channel_readformat(chan));
+ RAII_VAR(struct ast_format *, writeformat, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, readformat, NULL, ao2_cleanup);
for (x = 0; x < msglen; x += (msg[x+1]+2)) {
if (msg[x] == ADSI_SWITCH_TO_DATA) {
@@ -426,16 +419,19 @@ static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *m
ast_stopstream(chan);
- if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW)) {
+ writeformat = ao2_bump(ast_channel_writeformat(chan));
+ readformat = ao2_bump(ast_channel_readformat(chan));
+
+ if (ast_set_write_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
return -1;
}
- if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW)) {
+ if (ast_set_read_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
- 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));
+ if (writeformat) {
+ if (ast_set_write_format(chan, writeformat)) {
+ ast_log(LOG_WARNING, "Unable to restore write format to %s\n", ast_format_get_name(writeformat));
}
}
return -1;
@@ -454,11 +450,11 @@ static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *m
ast_channel_adsicpe_set(chan, (ast_channel_adsicpe(chan) & ~ADSI_FLAG_DATAMODE) | newdatamode);
}
- if (writeformat.id) {
- ast_set_write_format(chan, &writeformat);
+ if (writeformat) {
+ ast_set_write_format(chan, writeformat);
}
- if (readformat.id) {
- ast_set_read_format(chan, &readformat);
+ if (readformat) {
+ ast_set_read_format(chan, readformat);
}
if (!res) {
diff --git a/res/res_agi.c b/res/res_agi.c
index 67a213f8d..b612f7d72 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -68,6 +68,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/netsock2.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_message_router.h"
+#include "asterisk/format_cache.h"
#define AST_API_MODULE
#include "asterisk/agi.h"
@@ -2538,8 +2539,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const
int silence = 0; /* amount of silence to allow */
int gotsilence = 0; /* did we timeout for silence? */
char *silencestr = NULL;
- struct ast_format rfmt;
- ast_format_clear(&rfmt);
+ RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
/* XXX EAGI FIXME XXX */
@@ -2569,8 +2569,8 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const
}
if (silence > 0) {
- ast_format_copy(&rfmt, ast_channel_readformat(chan));
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ rfmt = ao2_bump(ast_channel_readformat(chan));
+ res = ast_set_read_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
@@ -2694,7 +2694,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const
}
if (silence > 0) {
- res = ast_set_read_format(chan, &rfmt);
+ res = ast_set_read_format(chan, rfmt);
if (res)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
ast_dsp_free(sildet);
@@ -3032,7 +3032,6 @@ static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const c
static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
{
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
/* If a structure already exists, return an error */
if (agi->speech) {
@@ -3040,16 +3039,16 @@ static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, con
return RESULT_SUCCESS;
}
- if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return RESULT_FAILURE;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
if ((agi->speech = ast_speech_new(argv[2], cap))) {
ast_agi_send(agi->fd, chan, "200 result=1\n");
} else {
ast_agi_send(agi->fd, chan, "200 result=0\n");
}
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return RESULT_SUCCESS;
}
@@ -3182,7 +3181,6 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
const char *prompt;
char dtmf = 0, tmp[4096] = "", *buf = tmp;
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;
@@ -3206,8 +3204,7 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
offset = atoi(argv[4]);
/* We want frames coming in signed linear */
- ast_format_copy(&old_read_format, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_read_format(chan, ast_format_slin)) {
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@@ -4195,23 +4192,26 @@ static int agi_exec(struct ast_channel *chan, const char *data)
static int eagi_exec(struct ast_channel *chan, const char *data)
{
int res;
- struct ast_format readformat;
+ 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;
}
- ast_format_copy(&readformat, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ readformat = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", ast_channel_name(chan));
+ ao2_ref(readformat, -1);
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", ast_channel_name(chan), ast_getformatname(&readformat));
+ if (ast_set_read_format(chan, readformat)) {
+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", ast_channel_name(chan),
+ ast_format_get_name(readformat));
}
}
+ ao2_ref(readformat, -1);
return res;
}
diff --git a/res/res_calendar.c b/res/res_calendar.c
index ae52cbfce..77f8ef662 100644
--- a/res/res_calendar.c
+++ b/res/res_calendar.c
@@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<function name="CALENDAR_BUSY" language="en_US">
@@ -730,6 +731,7 @@ static void *do_notify(void *data)
struct ast_variable *itervar;
char *tech, *dest;
char buf[8];
+ struct ast_format_cap *caps;
tech = ast_strdupa(event->owner->notify_channel);
@@ -760,12 +762,19 @@ static void *do_notify(void *data)
}
ast_channel_tech_set(chan, &null_tech);
- ast_format_set(ast_channel_writeformat(chan), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_readformat(chan), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_rawwriteformat(chan), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_rawreadformat(chan), 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(ast_channel_nativeformats(chan), ast_channel_writeformat(chan));
+ ast_channel_set_writeformat(chan, ast_format_slin);
+ ast_channel_set_readformat(chan, ast_format_slin);
+ ast_channel_set_rawwriteformat(chan, ast_format_slin);
+ ast_channel_set_rawreadformat(chan, ast_format_slin);
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Could not allocate capabilities, notification not being sent!\n");
+ goto notify_cleanup;
+ }
+ ast_format_cap_append(caps, ast_format_slin, 0);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
ast_channel_unlock(chan);
diff --git a/res/res_clioriginate.c b/res/res_clioriginate.c
index cd8b5dde1..3903b6c3b 100644
--- a/res/res_clioriginate.c
+++ b/res/res_clioriginate.c
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
/*! The timeout for originated calls, in seconds */
#define TIMEOUT 30
@@ -57,7 +58,6 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app
char *chandata;
int reason = 0;
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
if (ast_strlen_zero(app))
return CLI_SHOWUSAGE;
@@ -70,12 +70,12 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app
return CLI_SHOWUSAGE;
}
- if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return CLI_FAILURE;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return CLI_SUCCESS;
}
@@ -96,7 +96,6 @@ static char *orig_exten(int fd, const char *chan, const char *data)
char *context = NULL;
int reason = 0;
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
chandata = ast_strdupa(chan);
@@ -115,12 +114,12 @@ static char *orig_exten(int fd, const char *chan, const char *data)
exten = "s";
if (ast_strlen_zero(context))
context = "default";
- if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return CLI_FAILURE;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return CLI_SUCCESS;
}
diff --git a/res/res_fax.c b/res/res_fax.c
index 758309822..d59ab09e6 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -89,6 +89,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/translate.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/smoother.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="ReceiveFAX" language="en_US" module="res_fax">
@@ -453,10 +455,10 @@ struct fax_gateway {
/*! \brief a flag to track the state of our negotiation */
enum ast_t38_state t38_state;
/*! \brief original audio formats */
- struct ast_format chan_read_format;
- struct ast_format chan_write_format;
- struct ast_format peer_read_format;
- struct ast_format peer_write_format;
+ struct ast_format *chan_read_format;
+ struct ast_format *chan_write_format;
+ struct ast_format *peer_read_format;
+ struct ast_format *peer_write_format;
};
/*! \brief used for fax detect framehook */
@@ -468,7 +470,7 @@ struct fax_detect {
/*! \brief DSP Processor */
struct ast_dsp *dsp;
/*! \brief original audio formats */
- struct ast_format orig_format;
+ struct ast_format *orig_format;
/*! \brief fax session details */
struct ast_fax_session_details *details;
/*! \brief mode */
@@ -1570,20 +1572,18 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
int timeout = RES_FAX_TIMEOUT;
int chancount;
unsigned int expected_frametype = -1;
- union ast_frame_subclass expected_framesubclass = { .integer = -1 };
+ struct ast_frame_subclass expected_framesubclass = { .integer = 0, };
unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
struct ast_control_t38_parameters t38_parameters;
const char *tempvar;
struct ast_fax_session *fax = NULL;
struct ast_frame *frame = NULL;
struct ast_channel *c = chan;
- struct ast_format orig_write_format;
- struct ast_format orig_read_format;
+ RAII_VAR(struct ast_format *, orig_write_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, orig_read_format, NULL, ao2_cleanup);
int remaining_time;
struct timeval start;
- ast_format_clear(&orig_write_format);
- ast_format_clear(&orig_read_format);
chancount = 1;
/* create the FAX session */
@@ -1607,10 +1607,10 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
report_fax_status(chan, details, "Allocating Resources");
if (details->caps & AST_FAX_TECH_AUDIO) {
- expected_frametype = AST_FRAME_VOICE;;
- ast_format_set(&expected_framesubclass.format, AST_FORMAT_SLINEAR, 0);
- ast_format_copy(&orig_write_format, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ expected_frametype = AST_FRAME_VOICE;
+ expected_framesubclass.format = ast_format_slin;
+ orig_write_format = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
ao2_lock(faxregistry.container);
ao2_unlink(faxregistry.container, fax);
@@ -1619,8 +1619,8 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_channel_unlock(chan);
return -1;
}
- ast_format_copy(&orig_read_format, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ orig_read_format = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
ao2_lock(faxregistry.container);
ao2_unlink(faxregistry.container, fax);
@@ -1724,8 +1724,10 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->id);
}
- } else if ((frame->frametype == expected_frametype) &&
- (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
+ } else if ((frame->frametype == expected_frametype) && (expected_framesubclass.integer == frame->subclass.integer) &&
+ ((!frame->subclass.format && !expected_framesubclass.format) ||
+ (frame->subclass.format && expected_framesubclass.format &&
+ (ast_format_cmp(frame->subclass.format, expected_framesubclass.format) != AST_FORMAT_CMP_NOT_EQUAL)))) {
struct ast_frame *f;
if (fax->smoother) {
@@ -1809,11 +1811,11 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
* restore them now
*/
if (chancount) {
- if (orig_read_format.id) {
- ast_set_read_format(chan, &orig_read_format);
+ if (orig_read_format) {
+ ast_set_read_format(chan, orig_read_format);
}
- if (orig_write_format.id) {
- ast_set_write_format(chan, &orig_write_format);
+ if (orig_write_format) {
+ ast_set_write_format(chan, orig_write_format);
}
}
@@ -2823,6 +2825,11 @@ static void destroy_gateway(void *data)
ao2_ref(gateway->s, -1);
gateway->s = NULL;
}
+
+ ao2_cleanup(gateway->chan_read_format);
+ ao2_cleanup(gateway->chan_write_format);
+ ao2_cleanup(gateway->peer_read_format);
+ ao2_cleanup(gateway->peer_write_format);
}
/*! \brief Create a new fax gateway object.
@@ -3274,14 +3281,14 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
set_channel_variables(chan, details);
if (gateway->bridged) {
- ast_set_read_format(chan, &gateway->chan_read_format);
- ast_set_read_format(chan, &gateway->chan_write_format);
+ ast_set_read_format(chan, gateway->chan_read_format);
+ ast_set_read_format(chan, gateway->chan_write_format);
ast_channel_unlock(chan);
peer = ast_channel_bridge_peer(chan);
if (peer) {
- ast_set_read_format(peer, &gateway->peer_read_format);
- ast_set_read_format(peer, &gateway->peer_write_format);
+ ast_set_read_format(peer, gateway->peer_read_format);
+ ast_set_read_format(peer, gateway->peer_write_format);
ast_channel_make_compatible(chan, peer);
}
ast_channel_lock(chan);
@@ -3326,18 +3333,18 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
/* we are bridged, change r/w formats to SLIN for v21 preamble
* detection and T.30 */
- ast_format_copy(&gateway->chan_read_format, ast_channel_readformat(chan));
- ast_format_copy(&gateway->chan_write_format, ast_channel_readformat(chan));
+ ao2_replace(gateway->chan_read_format, ast_channel_readformat(chan));
+ ao2_replace(gateway->chan_write_format, ast_channel_readformat(chan));
- ast_format_copy(&gateway->peer_read_format, ast_channel_readformat(peer));
- ast_format_copy(&gateway->peer_write_format, ast_channel_readformat(peer));
+ ao2_replace(gateway->peer_read_format, ast_channel_readformat(peer));
+ ao2_replace(gateway->peer_write_format, ast_channel_readformat(peer));
- ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(chan, ast_format_slin);
+ ast_set_write_format(chan, ast_format_slin);
ast_channel_unlock(chan);
- ast_set_read_format_by_id(peer, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(peer, AST_FORMAT_SLINEAR);
+ ast_set_read_format(peer, ast_format_slin);
+ ast_set_write_format(peer, ast_format_slin);
ast_channel_make_compatible(chan, peer);
ast_channel_lock(chan);
@@ -3361,12 +3368,9 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
/* only handle VOICE, MODEM, and CONTROL frames*/
switch (f->frametype) {
case AST_FRAME_VOICE:
- switch (f->subclass.format.id) {
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- break;
- default:
+ if ((ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
return f;
}
break;
@@ -3412,7 +3416,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
if (gateway->t38_state == T38_STATE_NEGOTIATED) {
/* framehooks are called in __ast_read() before frame format
* translation is done, so we need to translate here */
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR)) {
+ if ((f->frametype == AST_FRAME_VOICE) && (ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) {
if (ast_channel_readtrans(active) && (f = ast_translate(ast_channel_readtrans(active), f, 1)) == NULL) {
f = &ast_null_frame;
return f;
@@ -3424,7 +3428,8 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
* write would fail, or even if a failure would be fatal so for
* now we'll just ignore the return value. */
gateway->s->tech->write(gateway->s, f);
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR) && ast_channel_readtrans(active)) {
+ if ((f->frametype == AST_FRAME_VOICE) && (ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ ast_channel_readtrans(active)) {
/* Only free the frame if we translated / duplicated it - otherwise,
* let whatever is outside the frame hook do it */
ast_frfree(f);
@@ -3435,15 +3440,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
/* force silence on the line if T.38 negotiation might be taking place */
if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
- if (f->frametype == AST_FRAME_VOICE && f->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (f->frametype == AST_FRAME_VOICE &&
+ (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
short silence_buf[f->samples];
struct ast_frame silence_frame = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin,
.data.ptr = silence_buf,
.samples = f->samples,
.datalen = sizeof(silence_buf),
};
- ast_format_set(&silence_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
memset(silence_buf, 0, sizeof(silence_buf));
return ast_frisolate(&silence_frame);
} else {
@@ -3513,6 +3519,7 @@ static void destroy_faxdetect(void *data)
faxdetect->dsp = NULL;
}
ao2_ref(faxdetect->details, -1);
+ ao2_cleanup(faxdetect->orig_format);
}
/*! \brief Create a new fax detect object.
@@ -3587,23 +3594,22 @@ static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct a
switch (event) {
case AST_FRAMEHOOK_EVENT_ATTACHED:
/* Setup format for DSP on ATTACH*/
- ast_format_copy(&faxdetect->orig_format, ast_channel_readformat(chan));
- switch (ast_channel_readformat(chan)->id) {
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- break;
- default:
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
- ast_framehook_detach(chan, details->faxdetect_id);
- details->faxdetect_id = -1;
- return f;
- }
+ ao2_replace(faxdetect->orig_format, ast_channel_readformat(chan));
+
+ if ((ast_format_cmp(ast_channel_readformat(chan), ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(ast_channel_readformat(chan), ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(ast_channel_readformat(chan), ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
+ if (ast_set_read_format(chan, ast_format_slin)) {
+ ast_framehook_detach(chan, details->faxdetect_id);
+ details->faxdetect_id = -1;
+ return f;
+ }
}
+
return NULL;
case AST_FRAMEHOOK_EVENT_DETACHED:
/* restore audio formats when we are detached */
- ast_set_read_format(chan, &faxdetect->orig_format);
+ ast_set_read_format(chan, faxdetect->orig_format);
ast_channel_unlock(chan);
peer = ast_channel_bridge_peer(chan);
if (peer) {
@@ -3638,13 +3644,10 @@ static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct a
return f;
}
/* We can only process some formats*/
- switch (f->subclass.format.id) {
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- break;
- default:
- return f;
+ if ((ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
+ return f;
}
break;
case AST_FRAME_CONTROL:
diff --git a/res/res_fax_spandsp.c b/res/res_fax_spandsp.c
index 75018e864..63be1b3cb 100644
--- a/res/res_fax_spandsp.c
+++ b/res/res_fax_spandsp.c
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/res_fax.h"
#include "asterisk/channel.h"
+#include "asterisk/format_cache.h"
#define SPANDSP_FAX_SAMPLES 160
#define SPANDSP_FAX_TIMER_RATE 8000 / SPANDSP_FAX_SAMPLES /* 50 ticks per second, 20ms, 160 samples per second */
@@ -609,9 +610,9 @@ static struct ast_frame *spandsp_fax_read(struct ast_fax_session *s)
struct ast_frame fax_frame = {
.frametype = AST_FRAME_VOICE,
.src = "res_fax_spandsp_g711",
+ .subclass.format = ast_format_slin,
};
struct ast_frame *f = &fax_frame;
- ast_format_set(&fax_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
if (ast_timer_ack(p->timer, 1) < 0) {
ast_log(LOG_ERROR, "Failed to acknowledge timer for FAX session '%u'\n", s->id);
@@ -664,20 +665,21 @@ static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame
return -1;
}
- ast_debug(5, "frame={ datalen=%d, samples=%d, mallocd=%d, src=%s, flags=%u, ts=%ld, len=%ld, seqno=%d, data.ptr=%p, subclass.format.id=%u }\n", f->datalen, f->samples, f->mallocd, f->src, f->flags, f->ts, f->len, f->seqno, f->data.ptr, f->subclass.format.id);
+ ast_debug(5, "frame={ datalen=%d, samples=%d, mallocd=%d, src=%s, flags=%u, ts=%ld, len=%ld, seqno=%d, data.ptr=%p, subclass.format=%s }\n", f->datalen, f->samples, f->mallocd, f->src, f->flags, f->ts, f->len, f->seqno, f->data.ptr, ast_format_get_name(f->subclass.format));
/* slinear frame can be passed to spandsp */
- if (f->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
modem_connect_tones_rx(p->tone_state, f->data.ptr, f->samples);
/* alaw/ulaw frame must be converted to slinear before passing to spandsp */
- } else if (f->subclass.format.id == AST_FORMAT_ALAW || f->subclass.format.id == AST_FORMAT_ULAW) {
+ } else if (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL ||
+ ast_format_cmp(f->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
if (!(slndata = ast_malloc(sizeof(*slndata) * f->samples))) {
return -1;
}
- decoder = g711_init(NULL, (f->subclass.format.id == AST_FORMAT_ALAW ? G711_ALAW : G711_ULAW));
+ decoder = g711_init(NULL, (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL ? G711_ALAW : G711_ULAW));
g711_decode(decoder, slndata, f->data.ptr, f->samples);
- ast_debug(5, "spandsp transcoding frame from %s to slinear for v21 detection\n", (f->subclass.format.id == AST_FORMAT_ALAW ? "G711_ALAW" : "G711_ULAW"));
+ ast_debug(5, "spandsp transcoding frame from %s to slinear for v21 detection\n", ast_format_get_name(f->subclass.format));
modem_connect_tones_rx(p->tone_state, slndata, f->samples);
g711_release(decoder);
#if SPANDSP_RELEASE_DATE >= 20090220
@@ -687,7 +689,7 @@ static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame
/* frame in other formats cannot be passed to spandsp, it could cause segfault */
} else {
- ast_log(LOG_WARNING, "Unknown frame format %u, v.21 detection skipped\n", f->subclass.format.id);
+ ast_log(LOG_WARNING, "Frame format %s not supported, v.21 detection skipped\n", ast_format_get_name(f->subclass.format));
return -1;
}
@@ -749,6 +751,7 @@ static int spandsp_fax_gw_t30_gen(struct ast_channel *chan, void *data, int len,
struct ast_frame *f;
struct ast_frame t30_frame = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin,
.src = "res_fax_spandsp_g711",
.samples = samples,
.flags = AST_FAX_FRFLAG_GATEWAY,
@@ -756,7 +759,6 @@ static int spandsp_fax_gw_t30_gen(struct ast_channel *chan, void *data, int len,
AST_FRAME_SET_BUFFER(&t30_frame, buffer, AST_FRIENDLY_OFFSET, t30_frame.samples * sizeof(int16_t));
- ast_format_set(&t30_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
if (!(f = ast_frisolate(&t30_frame))) {
return p->isdone ? -1 : res;
}
@@ -878,7 +880,8 @@ static int spandsp_fax_gateway_process(struct ast_fax_session *s, const struct a
/* Process a IFP packet */
if ((f->frametype == AST_FRAME_MODEM) && (f->subclass.integer == AST_MODEM_T38)) {
return t38_core_rx_ifp_packet(p->t38_core_state, f->data.ptr, f->datalen, f->seqno);
- } else if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) {
+ } else if ((f->frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
return t38_gateway_rx(&p->t38_gw_state, f->data.ptr, f->samples);
}
diff --git a/res/res_format_attr_celt.c b/res/res_format_attr_celt.c
index 1249f0472..7d7c0f844 100644
--- a/res/res_format_attr_celt.c
+++ b/res/res_format_attr_celt.c
@@ -45,152 +45,148 @@ struct celt_attr {
unsigned int framesize;
};
-static int celt_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static void celt_destroy(struct ast_format *format)
{
- struct celt_attr *attr = (struct celt_attr *) format_attr;
+ struct celt_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int celt_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct celt_attr *original = ast_format_get_attribute_data(src);
+ struct celt_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static struct ast_format *celt_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *cloned;
+ struct celt_attr *attr;
unsigned int val;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
if (sscanf(attributes, "framesize=%30u", &val) == 1) {
attr->framesize = val;
}
- return 0;
+ return cloned;
}
-static void celt_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+static void celt_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct celt_attr *attr = (struct celt_attr *) format_attr;
+ struct celt_attr *attr = ast_format_get_attribute_data(format);
- if (!attr->framesize) {
+ if (!attr || !attr->framesize) {
return;
}
ast_str_append(str, 0, "a=fmtp:%u framesize=%u\r\n", payload, attr->framesize);
}
-static enum ast_format_cmp_res celt_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
+static enum ast_format_cmp_res celt_cmp(const struct ast_format *format1, const struct ast_format *format2)
{
- struct celt_attr *attr1 = (struct celt_attr *) fattr1;
- struct celt_attr *attr2 = (struct celt_attr *) fattr2;
+ struct celt_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct celt_attr *attr2 = ast_format_get_attribute_data(format2);
- if (attr1->samplerate == attr2->samplerate) {
+ if (((!attr1 || !attr1->samplerate) && (!attr2 || !attr2->samplerate)) ||
+ (attr1->samplerate == attr2->samplerate)) {
return AST_FORMAT_CMP_EQUAL;
}
+
return AST_FORMAT_CMP_NOT_EQUAL;
}
-static int celt_get_val(const struct ast_format_attr *fattr, int key, void *result)
+static struct ast_format *celt_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- const struct celt_attr *attr = (struct celt_attr *) fattr;
- int *val = result;
-
- switch (key) {
- case CELT_ATTR_KEY_SAMP_RATE:
- *val = attr->samplerate;
- break;
- case CELT_ATTR_KEY_MAX_BITRATE:
- *val = attr->maxbitrate;
- break;
- case CELT_ATTR_KEY_FRAME_SIZE:
- *val = attr->framesize;
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
- return -1;
- }
- return 0;
-}
+ struct celt_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct celt_attr *attr2 = ast_format_get_attribute_data(format2);
+ struct ast_format *jointformat;
+ struct celt_attr *jointattr;
-static int celt_isset(const struct ast_format_attr *fattr, va_list ap)
-{
- enum celt_attr_keys key;
- const struct celt_attr *attr = (struct celt_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case CELT_ATTR_KEY_SAMP_RATE:
- if (attr->samplerate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case CELT_ATTR_KEY_MAX_BITRATE:
- if (attr->maxbitrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case CELT_ATTR_KEY_FRAME_SIZE:
- if (attr->framesize != (va_arg(ap, int))) {
- return -1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- return -1;
- }
+ if (attr1 && attr2 && (attr1->samplerate != attr2->samplerate)) {
+ return NULL;
}
- return 0;
-}
-static int celt_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
-{
- struct celt_attr *attr1 = (struct celt_attr *) fattr1;
- struct celt_attr *attr2 = (struct celt_attr *) fattr2;
- struct celt_attr *attr_res = (struct celt_attr *) result;
- /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
- if (attr1->samplerate != attr2->samplerate) {
- return -1;
+ jointformat = ast_format_clone(format1);
+ if (!jointformat) {
+ return NULL;
}
+ jointattr = ast_format_get_attribute_data(jointformat);
+
/* either would work, they are guaranteed the same at this point. */
- attr_res->samplerate = attr1->samplerate;
+ jointattr->samplerate = attr1->samplerate;
/* Take the lowest max bitrate */
- attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
+ jointattr->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
- attr_res->framesize = attr2->framesize; /* TODO figure out what joint framesize means */
- return 0;
+ jointattr->framesize = attr2->framesize; /* TODO figure out what joint framesize means */
+
+ return jointformat;
}
-static void celt_set(struct ast_format_attr *fattr, va_list ap)
+static struct ast_format *celt_set(const struct ast_format *format, const char *name, const char *value)
{
- enum celt_attr_keys key;
- struct celt_attr *attr = (struct celt_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case CELT_ATTR_KEY_SAMP_RATE:
- attr->samplerate = (va_arg(ap, int));
- break;
- case CELT_ATTR_KEY_MAX_BITRATE:
- attr->maxbitrate = (va_arg(ap, int));
- break;
- case CELT_ATTR_KEY_FRAME_SIZE:
- attr->framesize = (va_arg(ap, int));
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- }
+ struct ast_format *cloned;
+ struct celt_attr *attr;
+ unsigned int val;
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ if (sscanf(value, "%30u", &val) != 1) {
+ ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
+ value, name);
+ ao2_ref(cloned, -1);
+ return NULL;
}
+
+ if (!strcasecmp(name, "sample_rate")) {
+ attr->samplerate = val;
+ } else if (!strcasecmp(name, "max_bitrate")) {
+ attr->maxbitrate = val;
+ } else if (!strcasecmp(name, "frame_size")) {
+ attr->framesize = val;
+ } else {
+ ast_log(LOG_WARNING, "Unknown attribute type '%s'\n", name);
+ ao2_ref(cloned, -1);
+ return NULL;
+ }
+
+ return cloned;
}
-static struct ast_format_attr_interface celt_interface = {
- .id = AST_FORMAT_CELT,
- .format_attr_cmp = celt_cmp,
- .format_attr_get_joint = celt_getjoint,
- .format_attr_set = celt_set,
- .format_attr_isset = celt_isset,
- .format_attr_get_val = celt_get_val,
- .format_attr_sdp_parse = celt_sdp_parse,
- .format_attr_sdp_generate = celt_sdp_generate,
+static struct ast_format_interface celt_interface = {
+ .format_destroy = celt_destroy,
+ .format_clone = celt_clone,
+ .format_cmp = celt_cmp,
+ .format_get_joint = celt_getjoint,
+ .format_attribute_set = celt_set,
+ .format_parse_sdp_fmtp = celt_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = celt_generate_sdp_fmtp,
};
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&celt_interface)) {
+ if (ast_format_interface_register("celt", &celt_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -199,7 +195,6 @@ static int load_module(void)
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&celt_interface);
return 0;
}
diff --git a/res/res_format_attr_h263.c b/res/res_format_attr_h263.c
index 8ec28aac9..121beb1bc 100644
--- a/res/res_format_attr_h263.c
+++ b/res/res_format_attr_h263.c
@@ -38,250 +38,231 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/format.h"
-enum h263_attr_keys {
- H263_ATTR_KEY_SQCIF, /*!< Minimum picture interval for SQCIF resolution */
- H263_ATTR_KEY_QCIF, /*!< Minimum picture interval for QCIF resolution */
- H263_ATTR_KEY_CIF, /*!< Minimum picture interval for CIF resolution */
- H263_ATTR_KEY_CIF4, /*!< Minimum picture interval for CIF4 resolution */
- H263_ATTR_KEY_CIF16, /*!< Minimum picture interval for CIF16 resolution */
- H263_ATTR_KEY_VGA, /*!< Minimum picture interval for VGA resolution */
- H263_ATTR_KEY_CUSTOM_XMAX, /*!< Custom resolution (Xmax) */
- H263_ATTR_KEY_CUSTOM_YMAX, /*!< Custom resolution (Ymax) */
- H263_ATTR_KEY_CUSTOM_MPI, /*!< Custom resolution (MPI) */
- H263_ATTR_KEY_F, /*!< F annex support */
- H263_ATTR_KEY_I, /*!< I annex support */
- H263_ATTR_KEY_J, /*!< J annex support */
- H263_ATTR_KEY_T, /*!< T annex support */
- H263_ATTR_KEY_K, /*!< K annex support */
- H263_ATTR_KEY_N, /*!< N annex support */
- H263_ATTR_KEY_P_SUB1, /*!< Reference picture resampling (sub mode 1) */
- H263_ATTR_KEY_P_SUB2, /*!< Reference picture resampling (sub mode 2) */
- H263_ATTR_KEY_P_SUB3, /*!< Reference picture resampling (sub mode 3) */
- H263_ATTR_KEY_P_SUB4, /*!< Reference picture resampling (sub mode 4) */
- H263_ATTR_KEY_PAR_WIDTH, /*!< Pixel aspect ratio (width) */
- H263_ATTR_KEY_PAR_HEIGHT, /*!< Pixel aspect ratio (height) */
- H263_ATTR_KEY_BPP, /*!< Bits per picture maximum */
- H263_ATTR_KEY_HRD, /*!< Hypothetical reference decoder status */
- H263_ATTR_KEY_END, /*!< End terminator for list */
+struct h263_attr {
+ unsigned int SQCIF; /*!< Minimum picture interval for SQCIF resolution */
+ unsigned int QCIF; /*!< Minimum picture interval for QCIF resolution */
+ unsigned int CIF; /*!< Minimum picture interval for CIF resolution */
+ unsigned int CIF4; /*!< Minimum picture interval for CIF4 resolution */
+ unsigned int CIF16; /*!< Minimum picture interval for CIF16 resolution */
+ unsigned int VGA; /*!< Minimum picture interval for VGA resolution */
+ unsigned int CUSTOM_XMAX; /*!< Custom resolution (Xmax) */
+ unsigned int CUSTOM_YMAX; /*!< Custom resolution (Ymax) */
+ unsigned int CUSTOM_MPI; /*!< Custom resolution (MPI) */
+ unsigned int F; /*!< F annex support */
+ unsigned int I; /*!< I annex support */
+ unsigned int J; /*!< J annex support */
+ unsigned int T; /*!< T annex support */
+ unsigned int K; /*!< K annex support */
+ unsigned int N; /*!< N annex support */
+ unsigned int P_SUB1; /*!< Reference picture resampling (sub mode 1) */
+ unsigned int P_SUB2; /*!< Reference picture resampling (sub mode 2) */
+ unsigned int P_SUB3; /*!< Reference picture resampling (sub mode 3) */
+ unsigned int P_SUB4; /*!< Reference picture resampling (sub mode 4) */
+ unsigned int PAR_WIDTH; /*!< Pixel aspect ratio (width) */
+ unsigned int PAR_HEIGHT; /*!< Pixel aspect ratio (height) */
+ unsigned int BPP; /*!< Bits per picture maximum */
+ unsigned int HRD; /*!< Hypothetical reference decoder status */
};
-static int h263_format_attr_get_joint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
+static void h263_destroy(struct ast_format *format)
{
- int i;
+ struct h263_attr *attr = ast_format_get_attribute_data(format);
- /* These are all receiver options so we just copy over what they sent */
- for (i = H263_ATTR_KEY_SQCIF; i < H263_ATTR_KEY_END; i++) {
- result->format_attr[i] = fattr1->format_attr[i] ? fattr1->format_attr[i] : fattr2->format_attr[i];
+ ast_free(attr);
+}
+
+static int h263_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct h263_attr *original = ast_format_get_attribute_data(src);
+ struct h263_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
}
+ ast_format_set_attribute_data(dst, attr);
+
return 0;
}
-static int h263_format_attr_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static enum ast_format_cmp_res h263_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct h263_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct h263_attr *attr2 = ast_format_get_attribute_data(format2);
+
+ if (!attr1 || !attr2 || (attr1 && attr2 && !memcmp(attr1, attr2, sizeof(*attr1)))) {
+ return AST_FORMAT_CMP_EQUAL;
+ }
+ return AST_FORMAT_CMP_NOT_EQUAL;
+}
+
+#define DETERMINE_JOINT(joint, attr1, attr2, field) (joint->field = (attr1 && attr1->field) ? attr1->field : (attr2 && attr2->field) ? attr2->field : 0)
+
+static struct ast_format *h263_getjoint(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct ast_format *cloned;
+ struct h263_attr *attr, *attr1, *attr2;
+
+ cloned = ast_format_clone(format1);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ attr1 = ast_format_get_attribute_data(format1);
+ attr2 = ast_format_get_attribute_data(format2);
+
+ DETERMINE_JOINT(attr, attr1, attr2, SQCIF);
+ DETERMINE_JOINT(attr, attr1, attr2, QCIF);
+ DETERMINE_JOINT(attr, attr1, attr2, CIF);
+ DETERMINE_JOINT(attr, attr1, attr2, CIF4);
+ DETERMINE_JOINT(attr, attr1, attr2, CIF16);
+ DETERMINE_JOINT(attr, attr1, attr2, VGA);
+ DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_XMAX);
+ DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_YMAX);
+ DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_MPI);
+ DETERMINE_JOINT(attr, attr1, attr2, F);
+ DETERMINE_JOINT(attr, attr1, attr2, I);
+ DETERMINE_JOINT(attr, attr1, attr2, J);
+ DETERMINE_JOINT(attr, attr1, attr2, T);
+ DETERMINE_JOINT(attr, attr1, attr2, K);
+ DETERMINE_JOINT(attr, attr1, attr2, N);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB1);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB2);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB3);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB4);
+ DETERMINE_JOINT(attr, attr1, attr2, PAR_WIDTH);
+ DETERMINE_JOINT(attr, attr1, attr2, PAR_HEIGHT);
+ DETERMINE_JOINT(attr, attr1, attr2, BPP);
+ DETERMINE_JOINT(attr, attr1, attr2, HRD);
+
+ return cloned;
+}
+
+static struct ast_format *h263_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
{
char *attribs = ast_strdupa(attributes), *attrib;
+ struct ast_format *cloned;
+ struct h263_attr *attr;
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
while ((attrib = strsep(&attribs, ";"))) {
unsigned int val, val2 = 0, val3 = 0, val4 = 0;
if (sscanf(attrib, "SQCIF=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_SQCIF] = val;
+ attr->SQCIF = val;
} else if (sscanf(attrib, "QCIF=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_QCIF] = val;
+ attr->QCIF = val;
} else if (sscanf(attrib, "CIF=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_CIF] = val;
+ attr->CIF = val;
} else if (sscanf(attrib, "CIF4=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_CIF4] = val;
+ attr->CIF4 = val;
} else if (sscanf(attrib, "CIF16=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_CIF16] = val;
+ attr->CIF16 = val;
} else if (sscanf(attrib, "VGA=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_VGA] = val;
+ attr->VGA = val;
} else if (sscanf(attrib, "CUSTOM=%30u,%30u,%30u", &val, &val2, &val3) == 3) {
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX] = val;
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX] = val2;
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI] = val3;
+ attr->CUSTOM_XMAX = val;
+ attr->CUSTOM_YMAX = val2;
+ attr->CUSTOM_MPI = val3;
} else if (sscanf(attrib, "F=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_F] = val;
+ attr->F = val;
} else if (sscanf(attrib, "I=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_I] = val;
+ attr->I = val;
} else if (sscanf(attrib, "J=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_J] = val;
+ attr->J = val;
} else if (sscanf(attrib, "T=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_T] = val;
+ attr->T = val;
} else if (sscanf(attrib, "K=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_K] = val;
+ attr->K = val;
} else if (sscanf(attrib, "N=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_N] = val;
+ attr->N = val;
} else if (sscanf(attrib, "PAR=%30u:%30u", &val, &val2) == 2) {
- format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH] = val;
- format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT] = val2;
+ attr->PAR_WIDTH = val;
+ attr->PAR_HEIGHT = val2;
} else if (sscanf(attrib, "BPP=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_BPP] = val;
+ attr->BPP = val;
} else if (sscanf(attrib, "HRD=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_HRD] = val;
+ attr->HRD = val;
} else if (sscanf(attrib, "P=%30u,%30u,%30u,%30u", &val, &val2, &val3, &val4) > 0) {
- format_attr->format_attr[H263_ATTR_KEY_P_SUB1] = val;
- format_attr->format_attr[H263_ATTR_KEY_P_SUB2] = val2;
- format_attr->format_attr[H263_ATTR_KEY_P_SUB3] = val3;
- format_attr->format_attr[H263_ATTR_KEY_P_SUB4] = val4;
+ attr->P_SUB1 = val;
+ attr->P_SUB2 = val2;
+ attr->P_SUB3 = val3;
+ attr->P_SUB4 = val4;
}
}
- return 0;
+ return cloned;
}
-/*! \brief Helper function which converts a key enum into a string value for SDP */
-static const char *h263_attr_key_to_str(enum h263_attr_keys key, const struct ast_format_attr *format_attr)
+static void h263_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- switch (key) {
- case H263_ATTR_KEY_SQCIF:
- return format_attr->format_attr[key] ? "SQCIF" : NULL;
- case H263_ATTR_KEY_QCIF:
- return format_attr->format_attr[key] ? "QCIF" : NULL;
- case H263_ATTR_KEY_CIF:
- return format_attr->format_attr[key] ? "CIF" : NULL;
- case H263_ATTR_KEY_CIF4:
- return format_attr->format_attr[key] ? "CIF4" : NULL;
- case H263_ATTR_KEY_CIF16:
- return format_attr->format_attr[key] ? "CIF16" : NULL;
- case H263_ATTR_KEY_VGA:
- return format_attr->format_attr[key] ? "VGA" : NULL;
- case H263_ATTR_KEY_F:
- return "F";
- case H263_ATTR_KEY_I:
- return "I";
- case H263_ATTR_KEY_J:
- return "J";
- case H263_ATTR_KEY_T:
- return "T";
- case H263_ATTR_KEY_K:
- return "K";
- case H263_ATTR_KEY_N:
- return "N";
- case H263_ATTR_KEY_BPP:
- return "BPP";
- case H263_ATTR_KEY_HRD:
- return "HRD";
- case H263_ATTR_KEY_CUSTOM_XMAX:
- case H263_ATTR_KEY_CUSTOM_YMAX:
- case H263_ATTR_KEY_CUSTOM_MPI:
- case H263_ATTR_KEY_P_SUB1:
- case H263_ATTR_KEY_P_SUB2:
- case H263_ATTR_KEY_P_SUB3:
- case H263_ATTR_KEY_P_SUB4:
- case H263_ATTR_KEY_PAR_WIDTH:
- case H263_ATTR_KEY_PAR_HEIGHT:
- case H263_ATTR_KEY_END:
- default:
- return NULL;
+ struct h263_attr *attr = ast_format_get_attribute_data(format);
+
+ if (!attr) {
+ return;
}
- return NULL;
-}
+ ast_str_append(str, 0, "a=fmtp:%u SQCIF=%u;QCIF=%u;CIF=%u;CIF4=%u;CIF16=%u;VGA=%u;F=%u;I=%u;J=%u;T=%u;K=%u;N=%u;BPP=%u;HRD=%u",
+ payload, attr->SQCIF, attr->QCIF, attr->CIF, attr->CIF4, attr->CIF16, attr->VGA, attr->F, attr->I, attr->J,
+ attr->T, attr->K, attr->N, attr->BPP, attr->HRD);
-static void h263_format_attr_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
-{
- int i, added = 0;
-
- for (i = H263_ATTR_KEY_SQCIF; i < H263_ATTR_KEY_END; i++) {
- const char *name;
-
- if (i == H263_ATTR_KEY_CUSTOM_XMAX) {
- if (!format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX] || !format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX] ||
- !format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]) {
- continue;
- }
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u CUSTOM=%u,%u,%u", payload, format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX],
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX], format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";CUSTOM=%u,%u,%u", format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX],
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX], format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]);
- }
- } else if (i == H263_ATTR_KEY_PAR_WIDTH) {
- if (!format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH] || !format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]) {
- continue;
- }
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u PAR=%u:%u", payload, format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH],
- format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";PAR=%u:%u", format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH],
- format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]);
- }
- } else if (i == H263_ATTR_KEY_P_SUB1) {
- if (!format_attr->format_attr[H263_ATTR_KEY_P_SUB1]) {
- continue;
- }
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u P=%u", payload, format_attr->format_attr[H263_ATTR_KEY_P_SUB1]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";P=%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB1]);
- }
-
- if (format_attr->format_attr[H263_ATTR_KEY_P_SUB2]) {
- ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB2]);
- }
- if (format_attr->format_attr[H263_ATTR_KEY_P_SUB3]) {
- ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB3]);
- }
- if (format_attr->format_attr[H263_ATTR_KEY_P_SUB4]) {
- ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB4]);
- }
-
- } else if ((name = h263_attr_key_to_str(i, format_attr))) {
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u %s=%u", payload, name, format_attr->format_attr[i]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";%s=%u", name, format_attr->format_attr[i]);
- }
- }
+ if (attr->CUSTOM_XMAX && attr->CUSTOM_YMAX && attr->CUSTOM_MPI) {
+ ast_str_append(str, 0, ";CUSTOM=%u,%u,%u", attr->CUSTOM_XMAX, attr->CUSTOM_YMAX, attr->CUSTOM_MPI);
}
- if (added) {
- ast_str_append(str, 0, "\r\n");
+ if (attr->PAR_WIDTH && attr->PAR_HEIGHT) {
+ ast_str_append(str, 0, ";PAR=%u:%u", attr->PAR_WIDTH, attr->PAR_HEIGHT);
}
+ if (attr->P_SUB1) {
+ ast_str_append(str, 0, ";P=%u", attr->P_SUB1);
+ if (attr->P_SUB2) {
+ ast_str_append(str, 0, ",%u", attr->P_SUB2);
+ }
+ if (attr->P_SUB3) {
+ ast_str_append(str, 0, ",%u", attr->P_SUB3);
+ }
+ if (attr->P_SUB4) {
+ ast_str_append(str, 0, ",%u", attr->P_SUB4);
+ }
+ }
+
+ ast_str_append(str, 0, "\r\n");
+
return;
}
-static struct ast_format_attr_interface h263_format_attr_interface = {
- .id = AST_FORMAT_H263,
- .format_attr_get_joint = h263_format_attr_get_joint,
- .format_attr_sdp_parse = h263_format_attr_sdp_parse,
- .format_attr_sdp_generate = h263_format_attr_sdp_generate,
-};
-
-static struct ast_format_attr_interface h263p_format_attr_interface = {
- .id = AST_FORMAT_H263_PLUS,
- .format_attr_get_joint = h263_format_attr_get_joint,
- .format_attr_sdp_parse = h263_format_attr_sdp_parse,
- .format_attr_sdp_generate = h263_format_attr_sdp_generate,
+static struct ast_format_interface h263_interface = {
+ .format_destroy = h263_destroy,
+ .format_clone = h263_clone,
+ .format_cmp = h263_cmp,
+ .format_get_joint = h263_getjoint,
+ .format_parse_sdp_fmtp = h263_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = h263_generate_sdp_fmtp,
};
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&h263_format_attr_interface);
- ast_format_attr_unreg_interface(&h263p_format_attr_interface);
-
return 0;
}
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&h263_format_attr_interface)) {
+ if (ast_format_interface_register("h263", &h263_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
- if (ast_format_attr_reg_interface(&h263p_format_attr_interface)) {
- ast_format_attr_unreg_interface(&h263_format_attr_interface);
+ if (ast_format_interface_register("h263p", &h263_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
diff --git a/res/res_format_attr_h264.c b/res/res_format_attr_h264.c
index 2bd47e025..81784bb48 100644
--- a/res/res_format_attr_h264.c
+++ b/res/res_format_attr_h264.c
@@ -50,266 +50,284 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
* H264_MAX_SPS_PPS_SIZE */
#define H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "15"
-enum h264_attr_keys {
- H264_ATTR_KEY_PROFILE_IDC,
- H264_ATTR_KEY_PROFILE_IOP,
- H264_ATTR_KEY_LEVEL,
- H264_ATTR_KEY_MAX_MBPS,
- H264_ATTR_KEY_MAX_FS,
- H264_ATTR_KEY_MAX_CPB,
- H264_ATTR_KEY_MAX_DPB,
- H264_ATTR_KEY_MAX_BR,
- H264_ATTR_KEY_MAX_SMBPS,
- H264_ATTR_KEY_MAX_FPS,
- H264_ATTR_KEY_REDUNDANT_PIC_CAP,
- H264_ATTR_KEY_PARAMETER_ADD,
- H264_ATTR_KEY_PACKETIZATION_MODE,
- H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH,
- H264_ATTR_KEY_SPROP_DEINT_BUF_REQ,
- H264_ATTR_KEY_DEINT_BUF_CAP,
- H264_ATTR_KEY_SPROP_INIT_BUF_TIME,
- H264_ATTR_KEY_SPROP_MAX_DON_DIFF,
- H264_ATTR_KEY_MAX_RCMD_NALU_SIZE,
- H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED,
- H264_ATTR_KEY_SPS_LEN,
- H264_ATTR_KEY_PPS_LEN,
- H264_ATTR_KEY_SPS,
- H264_ATTR_KEY_PPS = H264_ATTR_KEY_SPS + H264_MAX_SPS_PPS_SIZE,
- H264_ATTR_KEY_END = H264_ATTR_KEY_PPS + H264_MAX_SPS_PPS_SIZE,
+struct h264_attr {
+ unsigned int PROFILE_IDC;
+ unsigned int PROFILE_IOP;
+ unsigned int LEVEL;
+ unsigned int MAX_MBPS;
+ unsigned int MAX_FS;
+ unsigned int MAX_CPB;
+ unsigned int MAX_DPB;
+ unsigned int MAX_BR;
+ unsigned int MAX_SMBPS;
+ unsigned int MAX_FPS;
+ unsigned int REDUNDANT_PIC_CAP;
+ unsigned int PARAMETER_ADD;
+ unsigned int PACKETIZATION_MODE;
+ unsigned int SPROP_INTERLEAVING_DEPTH;
+ unsigned int SPROP_DEINT_BUF_REQ;
+ unsigned int DEINT_BUF_CAP;
+ unsigned int SPROP_INIT_BUF_TIME;
+ unsigned int SPROP_MAX_DON_DIFF;
+ unsigned int MAX_RCMD_NALU_SIZE;
+ unsigned int LEVEL_ASYMMETRY_ALLOWED;
+ char SPS[H264_MAX_SPS_PPS_SIZE];
+ char PPS[H264_MAX_SPS_PPS_SIZE];
};
-static enum ast_format_cmp_res h264_format_attr_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
+static void h264_destroy(struct ast_format *format)
{
- if (!fattr1->format_attr[H264_ATTR_KEY_PROFILE_IDC] || !fattr2->format_attr[H264_ATTR_KEY_PROFILE_IDC] ||
- (fattr1->format_attr[H264_ATTR_KEY_PROFILE_IDC] == fattr2->format_attr[H264_ATTR_KEY_PROFILE_IDC])) {
+ struct h264_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int h264_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct h264_attr *original = ast_format_get_attribute_data(src);
+ struct h264_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static enum ast_format_cmp_res h264_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct h264_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct h264_attr *attr2 = ast_format_get_attribute_data(format2);
+
+ if (!attr1 || !attr1->PROFILE_IDC || !attr2 || !attr2->PROFILE_IDC ||
+ (attr1->PROFILE_IDC == attr2->PROFILE_IDC)) {
return AST_FORMAT_CMP_EQUAL;
}
return AST_FORMAT_CMP_NOT_EQUAL;
}
-static int h264_format_attr_get_joint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
+#define DETERMINE_JOINT(joint, attr1, attr2, field) (joint->field = (attr1 && attr1->field) ? attr1->field : (attr2 && attr2->field) ? attr2->field : 0)
+
+static struct ast_format *h264_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- int i;
+ struct ast_format *cloned;
+ struct h264_attr *attr, *attr1, *attr2;
+
+ cloned = ast_format_clone(format1);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ attr1 = ast_format_get_attribute_data(format1);
+ attr2 = ast_format_get_attribute_data(format2);
+
+ DETERMINE_JOINT(attr, attr1, attr2, PROFILE_IDC);
+ DETERMINE_JOINT(attr, attr1, attr2, PROFILE_IOP);
+ DETERMINE_JOINT(attr, attr1, attr2, LEVEL);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_MBPS);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_FS);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_CPB);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_DPB);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_BR);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_SMBPS);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_FPS);
+ DETERMINE_JOINT(attr, attr1, attr2, REDUNDANT_PIC_CAP);
+ DETERMINE_JOINT(attr, attr1, attr2, PARAMETER_ADD);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_INTERLEAVING_DEPTH);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_DEINT_BUF_REQ);
+ DETERMINE_JOINT(attr, attr1, attr2, DEINT_BUF_CAP);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_INIT_BUF_TIME);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_MAX_DON_DIFF);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_RCMD_NALU_SIZE);
+ DETERMINE_JOINT(attr, attr1, attr2, LEVEL_ASYMMETRY_ALLOWED);
+ DETERMINE_JOINT(attr, attr1, attr2, PACKETIZATION_MODE);
+
+ if (attr1 && !ast_strlen_zero(attr1->SPS)) {
+ ast_copy_string(attr->SPS, attr1->SPS, sizeof(attr->SPS));
+ } else if (attr2 && !ast_strlen_zero(attr2->SPS)) {
+ ast_copy_string(attr->SPS, attr1->SPS, sizeof(attr->SPS));
+ }
- for (i = H264_ATTR_KEY_PROFILE_IDC; i < H264_ATTR_KEY_END; i++) {
- result->format_attr[i] = fattr1->format_attr[i] ? fattr1->format_attr[i] : fattr2->format_attr[i];
+ if (attr1 && !ast_strlen_zero(attr1->PPS)) {
+ ast_copy_string(attr->PPS, attr1->PPS, sizeof(attr->PPS));
+ } else if (attr2 && !ast_strlen_zero(attr2->PPS)) {
+ ast_copy_string(attr->PPS, attr1->PPS, sizeof(attr->PPS));
}
- return 0;
+ return cloned;
}
-static int h264_format_attr_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static struct ast_format *h264_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
{
char *attribs = ast_strdupa(attributes), *attrib;
+ struct ast_format *cloned;
+ struct h264_attr *attr;
- format_attr->format_attr[H264_ATTR_KEY_REDUNDANT_PIC_CAP] = H264_ATTR_KEY_UNSET;
- format_attr->format_attr[H264_ATTR_KEY_PARAMETER_ADD] = H264_ATTR_KEY_UNSET;
- format_attr->format_attr[H264_ATTR_KEY_PACKETIZATION_MODE] = H264_ATTR_KEY_UNSET;
- format_attr->format_attr[H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED] = H264_ATTR_KEY_UNSET;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ attr->REDUNDANT_PIC_CAP = H264_ATTR_KEY_UNSET;
+ attr->PARAMETER_ADD = H264_ATTR_KEY_UNSET;
+ attr->PACKETIZATION_MODE = H264_ATTR_KEY_UNSET;
+ attr->LEVEL_ASYMMETRY_ALLOWED = H264_ATTR_KEY_UNSET;
while ((attrib = strsep(&attribs, ";"))) {
unsigned int val;
unsigned long int val2;
- char sps[H264_MAX_SPS_PPS_SIZE], pps[H264_MAX_SPS_PPS_SIZE];
if (sscanf(attrib, "profile-level-id=%lx", &val2) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC] = ((val2 >> 16) & 0xFF);
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP] = ((val2 >> 8) & 0xFF);
- format_attr->format_attr[H264_ATTR_KEY_LEVEL] = (val2 & 0xFF);
- } else if (sscanf(attrib, "sprop-parameter-sets=%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "[^','],%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "s", sps, pps) == 2) {
+ attr->PROFILE_IDC = ((val2 >> 16) & 0xFF);
+ attr->PROFILE_IOP = ((val2 >> 8) & 0xFF);
+ attr->LEVEL = (val2 & 0xFF);
+ } else if (sscanf(attrib, "sprop-parameter-sets=%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "[^','],%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "s", attr->SPS, attr->PPS) == 2) {
/* XXX sprop-parameter-sets can actually be of unlimited length. This may need to be addressed later. */
- unsigned char spsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, }, ppsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, };
- int i;
-
- ast_base64decode(spsdecoded, sps, sizeof(spsdecoded));
- ast_base64decode(ppsdecoded, pps, sizeof(ppsdecoded));
-
- format_attr->format_attr[H264_ATTR_KEY_SPS_LEN] = 0;
- format_attr->format_attr[H264_ATTR_KEY_PPS_LEN] = 0;
-
- for (i = 0; i < H264_MAX_SPS_PPS_SIZE; i++) {
- if (spsdecoded[i]) {
- format_attr->format_attr[H264_ATTR_KEY_SPS + i] = spsdecoded[i];
- format_attr->format_attr[H264_ATTR_KEY_SPS_LEN]++;
- }
- if (ppsdecoded[i]) {
- format_attr->format_attr[H264_ATTR_KEY_PPS + i] = ppsdecoded[i];
- format_attr->format_attr[H264_ATTR_KEY_PPS_LEN]++;
- }
- }
} else if (sscanf(attrib, "max-mbps=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_MBPS] = val;
+ attr->MAX_MBPS = val;
} else if (sscanf(attrib, "max-fs=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_FS] = val;
+ attr->MAX_FS = val;
} else if (sscanf(attrib, "max-cpb=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_CPB] = val;
+ attr->MAX_CPB = val;
} else if (sscanf(attrib, "max-dpb=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_DPB] = val;
+ attr->MAX_DPB = val;
} else if (sscanf(attrib, "max-br=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_BR] = val;
+ attr->MAX_BR = val;
} else if (sscanf(attrib, "max-smbps=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_SMBPS] = val;
+ attr->MAX_SMBPS = val;
} else if (sscanf(attrib, "max-fps=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_FPS] = val;
+ attr->MAX_FPS = val;
} else if (sscanf(attrib, "redundant-pic-cap=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_REDUNDANT_PIC_CAP] = val;
+ attr->REDUNDANT_PIC_CAP = val;
} else if (sscanf(attrib, "parameter-add=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_PARAMETER_ADD] = val;
+ attr->PARAMETER_ADD = val;
} else if (sscanf(attrib, "packetization-mode=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_PACKETIZATION_MODE] = val;
+ attr->PACKETIZATION_MODE = val;
} else if (sscanf(attrib, "sprop-interleaving-depth=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH] = val;
+ attr->SPROP_INTERLEAVING_DEPTH = val;
} else if (sscanf(attrib, "sprop-deint-buf-req=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_DEINT_BUF_REQ] = val;
+ attr->SPROP_DEINT_BUF_REQ = val;
} else if (sscanf(attrib, "deint-buf-cap=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_DEINT_BUF_CAP] = val;
+ attr->DEINT_BUF_CAP = val;
} else if (sscanf(attrib, "sprop-init-buf-time=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_INIT_BUF_TIME] = val;
+ attr->SPROP_INIT_BUF_TIME = val;
} else if (sscanf(attrib, "sprop-max-don-diff=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_MAX_DON_DIFF] = val;
+ attr->SPROP_MAX_DON_DIFF = val;
} else if (sscanf(attrib, "max-rcmd-nalu-size=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_RCMD_NALU_SIZE] = val;
+ attr->MAX_RCMD_NALU_SIZE = val;
} else if (sscanf(attrib, "level-asymmetry-allowed=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED] = val;
+ attr->LEVEL_ASYMMETRY_ALLOWED = val;
}
}
- return 0;
+ return cloned;
}
-/*! \brief Helper function which converts a key enum into a string value for SDP */
-static const char *h264_attr_key_to_str(enum h264_attr_keys key)
+#define APPEND_IF_NOT_H264_UNSET(field, str, name) do { \
+ if (field != H264_ATTR_KEY_UNSET) { \
+ if (added) { \
+ ast_str_append(str, 0, ";"); \
+ } else { \
+ added = 1; \
+ } \
+ ast_str_append(str, 0, "%s=%u", name, field); \
+ } \
+} while (0)
+
+#define APPEND_IF_NONZERO(field, str, name) do { \
+ if (field) { \
+ if (added) { \
+ ast_str_append(str, 0, ";"); \
+ } else { \
+ added = 1; \
+ } \
+ ast_str_append(str, 0, "%s=%u", name, field); \
+ } \
+} while (0)
+
+static void h264_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- switch (key) {
- case H264_ATTR_KEY_MAX_MBPS:
- return "max-mbps";
- case H264_ATTR_KEY_MAX_FS:
- return "max-fs";
- case H264_ATTR_KEY_MAX_CPB:
- return "max-cpb";
- case H264_ATTR_KEY_MAX_DPB:
- return "max-dpb";
- case H264_ATTR_KEY_MAX_BR:
- return "max-br";
- case H264_ATTR_KEY_MAX_SMBPS:
- return "max-smbps";
- case H264_ATTR_KEY_MAX_FPS:
- return "max-fps";
- case H264_ATTR_KEY_REDUNDANT_PIC_CAP:
- return "redundant-pic-cap";
- case H264_ATTR_KEY_PARAMETER_ADD:
- return "parameter-add";
- case H264_ATTR_KEY_PACKETIZATION_MODE:
- return "packetization-mode";
- case H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH:
- return "sprop-interleaving-depth";
- case H264_ATTR_KEY_SPROP_DEINT_BUF_REQ:
- return "sprop-deint-buf-req";
- case H264_ATTR_KEY_DEINT_BUF_CAP:
- return "deint-buf-cap";
- case H264_ATTR_KEY_SPROP_INIT_BUF_TIME:
- return "sprop-init-buf-time";
- case H264_ATTR_KEY_SPROP_MAX_DON_DIFF:
- return "sprop-max-don-diff";
- case H264_ATTR_KEY_MAX_RCMD_NALU_SIZE:
- return "max-rcmd-nalu-size";
- case H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED:
- return "level-asymmetry-allowed";
- default:
- return NULL;
- }
+ struct h264_attr *attr = ast_format_get_attribute_data(format);
+ int added = 0;
- return NULL;
-}
-
-/*! \brief Helper function which determines if the value of an attribute can be placed into the SDP */
-static int h264_attr_key_addable(const struct ast_format_attr *format_attr, enum h264_attr_keys key)
-{
- switch (key) {
- case H264_ATTR_KEY_REDUNDANT_PIC_CAP:
- case H264_ATTR_KEY_PARAMETER_ADD:
- case H264_ATTR_KEY_PACKETIZATION_MODE:
- case H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED:
- return (format_attr->format_attr[key] != H264_ATTR_KEY_UNSET) ? 1 : 0;
- default:
- return format_attr->format_attr[key] ? 1 : 0;
+ if (!attr) {
+ return;
}
- return 1;
-}
+ ast_str_append(str, 0, "a=fmtp:%u ", payload);
+
+ APPEND_IF_NONZERO(attr->MAX_MBPS, str, "max-mbps");
+ APPEND_IF_NONZERO(attr->MAX_FS, str, "max-fs");
+ APPEND_IF_NONZERO(attr->MAX_CPB, str, "max-cpb");
+ APPEND_IF_NONZERO(attr->MAX_DPB, str, "max-dpb");
+ APPEND_IF_NONZERO(attr->MAX_BR, str, "max-br");
+ APPEND_IF_NONZERO(attr->MAX_SMBPS, str, "max-smbps");
+ APPEND_IF_NONZERO(attr->MAX_FPS, str, "max-fps");
+ APPEND_IF_NONZERO(attr->SPROP_INTERLEAVING_DEPTH, str, "sprop-interleaving-depth");
+ APPEND_IF_NONZERO(attr->SPROP_DEINT_BUF_REQ, str, "sprop-deint-buf-req");
+ APPEND_IF_NONZERO(attr->DEINT_BUF_CAP, str, "deint-buf-cap");
+ APPEND_IF_NONZERO(attr->SPROP_INIT_BUF_TIME, str, "sprop-init-buf-time");
+ APPEND_IF_NONZERO(attr->SPROP_MAX_DON_DIFF, str, "sprop-max-don-diff");
+ APPEND_IF_NONZERO(attr->MAX_RCMD_NALU_SIZE, str, "max-rcmd-nalu-size");
+
+ APPEND_IF_NOT_H264_UNSET(attr->REDUNDANT_PIC_CAP, str, "redundant-pic-cap");
+ APPEND_IF_NOT_H264_UNSET(attr->PARAMETER_ADD, str, "parameter-add");
+ APPEND_IF_NOT_H264_UNSET(attr->PACKETIZATION_MODE, str, "packetization-mode");
+ APPEND_IF_NOT_H264_UNSET(attr->LEVEL_ASYMMETRY_ALLOWED, str, "level-asymmetry-allowed");
+
+ if (attr->PROFILE_IDC && attr->PROFILE_IOP && attr->LEVEL) {
+ if (added) {
+ ast_str_append(str, 0, ";");
+ } else {
+ added = 1;
+ }
+ ast_str_append(str, 0, "profile-level-id=%02X%02X%02X", attr->PROFILE_IDC, attr->PROFILE_IOP, attr->LEVEL);
+ }
-static void h264_format_attr_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
-{
- int i, added = 0;
-
- for (i = H264_ATTR_KEY_PROFILE_IDC; i < H264_ATTR_KEY_END; i++) {
- const char *name;
-
- if (i == H264_ATTR_KEY_SPS && format_attr->format_attr[H264_ATTR_KEY_SPS] && format_attr->format_attr[H264_ATTR_KEY_PPS]) {
- unsigned char spsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, }, ppsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, };
- int pos;
- char sps[H264_MAX_SPS_PPS_SIZE], pps[H264_MAX_SPS_PPS_SIZE];
-
- for (pos = 0; pos < H264_MAX_SPS_PPS_SIZE; pos++) {
- spsdecoded[pos] = format_attr->format_attr[H264_ATTR_KEY_SPS + pos];
- ppsdecoded[pos] = format_attr->format_attr[H264_ATTR_KEY_PPS + pos];
- }
-
- ast_base64encode(sps, spsdecoded, format_attr->format_attr[H264_ATTR_KEY_SPS_LEN], H264_MAX_SPS_PPS_SIZE);
- ast_base64encode(pps, ppsdecoded, format_attr->format_attr[H264_ATTR_KEY_PPS_LEN], H264_MAX_SPS_PPS_SIZE);
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u sprop-parameter-sets=%s,%s", payload, sps, pps);
- added = 1;
- } else {
- ast_str_append(str, 0, ";sprop-parameter-sets=%s,%s", sps, pps);
- }
- } else if (i == H264_ATTR_KEY_PROFILE_IDC && format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC] &&
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP] && format_attr->format_attr[H264_ATTR_KEY_LEVEL]) {
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u profile-level-id=%02X%02X%02X", payload, format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP], format_attr->format_attr[H264_ATTR_KEY_LEVEL]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";profile-level-id=%02X%02X%02X", format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP], format_attr->format_attr[H264_ATTR_KEY_LEVEL]);
- }
- } else if ((name = h264_attr_key_to_str(i)) && h264_attr_key_addable(format_attr, i)) {
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u %s=%u", payload, name, format_attr->format_attr[i]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";%s=%u", name, format_attr->format_attr[i]);
- }
+ if (!ast_strlen_zero(attr->SPS) && !ast_strlen_zero(attr->PPS)) {
+ if (added) {
+ ast_str_append(str, 0, ";");
+ } else {
+ added = 1;
}
+ ast_str_append(str, 0, ";sprop-parameter-sets=%s,%s", attr->SPS, attr->PPS);
}
-
- if (added) {
+
+ if (!added) {
+ ast_str_reset(*str);
+ } else {
ast_str_append(str, 0, "\r\n");
}
return;
}
-static struct ast_format_attr_interface h264_format_attr_interface = {
- .id = AST_FORMAT_H264,
- .format_attr_cmp = h264_format_attr_cmp,
- .format_attr_get_joint = h264_format_attr_get_joint,
- .format_attr_sdp_parse = h264_format_attr_sdp_parse,
- .format_attr_sdp_generate = h264_format_attr_sdp_generate,
+static struct ast_format_interface h264_interface = {
+ .format_destroy = h264_destroy,
+ .format_clone = h264_clone,
+ .format_cmp = h264_cmp,
+ .format_get_joint = h264_getjoint,
+ .format_parse_sdp_fmtp = h264_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = h264_generate_sdp_fmtp,
};
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&h264_format_attr_interface);
-
return 0;
}
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&h264_format_attr_interface)) {
+ if (ast_format_interface_register("h264", &h264_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
diff --git a/res/res_format_attr_opus.c b/res/res_format_attr_opus.c
index 3fa7dcef3..9e84982fb 100644
--- a/res/res_format_attr_opus.c
+++ b/res/res_format_attr_opus.c
@@ -51,12 +51,44 @@ struct opus_attr {
unsigned int spropstereo; /* Default 0 */
};
-static int opus_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static void opus_destroy(struct ast_format *format)
{
- struct opus_attr *attr = (struct opus_attr *) format_attr;
+ struct opus_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int opus_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct opus_attr *original = ast_format_get_attribute_data(src);
+ struct opus_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static struct ast_format *opus_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *cloned;
+ struct opus_attr *attr;
const char *kvp;
unsigned int val;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
if ((kvp = strstr(attributes, "maxplaybackrate")) && sscanf(kvp, "maxplaybackrate=%30u", &val) == 1) {
attr->maxplayrate = val;
}
@@ -91,9 +123,13 @@ static int opus_sdp_parse(struct ast_format_attr *format_attr, const char *attri
return 0;
}
-static void opus_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+static void opus_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct opus_attr *attr = (struct opus_attr *) format_attr;
+ struct opus_attr *attr = ast_format_get_attribute_data(format);
+
+ if (!attr) {
+ return;
+ }
/* FIXME should we only generate attributes that were explicitly set? */
ast_str_append(str, 0,
@@ -120,114 +156,18 @@ static void opus_sdp_generate(const struct ast_format_attr *format_attr, unsigne
);
}
-static int opus_get_val(const struct ast_format_attr *fattr, int key, void *result)
+static struct ast_format *opus_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- const struct opus_attr *attr = (struct opus_attr *) fattr;
- int *val = result;
-
- switch (key) {
- case OPUS_ATTR_KEY_MAX_BITRATE:
- *val = attr->maxbitrate;
- break;
- case OPUS_ATTR_KEY_MAX_PLAYRATE:
- *val = attr->maxplayrate;
- break;
- case OPUS_ATTR_KEY_MINPTIME:
- *val = attr->minptime;
- break;
- case OPUS_ATTR_KEY_STEREO:
- *val = attr->stereo;
- break;
- case OPUS_ATTR_KEY_CBR:
- *val = attr->cbr;
- break;
- case OPUS_ATTR_KEY_FEC:
- *val = attr->fec;
- break;
- case OPUS_ATTR_KEY_DTX:
- *val = attr->dtx;
- break;
- case OPUS_ATTR_KEY_SPROP_CAPTURE_RATE:
- *val = attr->spropmaxcapturerate;
- break;
- case OPUS_ATTR_KEY_SPROP_STEREO:
- *val = attr->spropstereo;
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
- return -1;
- }
- return 0;
-}
+ struct opus_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct opus_attr *attr2 = ast_format_get_attribute_data(format2);
+ struct ast_format *jointformat;
+ struct opus_attr *attr_res;
-static int opus_isset(const struct ast_format_attr *fattr, va_list ap)
-{
- enum opus_attr_keys key;
- const struct opus_attr *attr = (struct opus_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case OPUS_ATTR_KEY_MAX_BITRATE:
- if (attr->maxbitrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_MAX_PLAYRATE:
- if (attr->maxplayrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_MINPTIME:
- if (attr->minptime != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_STEREO:
- if (attr->stereo != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_CBR:
- if (attr->cbr != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_FEC:
- if (attr->fec != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_DTX:
- if (attr->dtx != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_SPROP_CAPTURE_RATE:
- if (attr->spropmaxcapturerate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_SPROP_STEREO:
- if (attr->spropstereo != (va_arg(ap, int))) {
- return -1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- return -1;
- }
+ jointformat = ast_format_clone(format1);
+ if (!jointformat) {
+ return NULL;
}
- return 0;
-}
-static int opus_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
-{
- struct opus_attr *attr1 = (struct opus_attr *) fattr1;
- struct opus_attr *attr2 = (struct opus_attr *) fattr2;
- struct opus_attr *attr_res = (struct opus_attr *) result;
- int joint = 0;
+ attr_res = ast_format_get_attribute_data(jointformat);
/* Only do dtx if both sides want it. DTX is a trade off between
* computational complexity and bandwidth. */
@@ -243,65 +183,64 @@ static int opus_getjoint(const struct ast_format_attr *fattr1, const struct ast_
/* FIXME: do we need to join other attributes as well, e.g., minptime, cbr, etc.? */
- return joint;
+ return jointformat;
}
-static void opus_set(struct ast_format_attr *fattr, va_list ap)
+static struct ast_format *opus_set(const struct ast_format *format, const char *name, const char *value)
{
- enum opus_attr_keys key;
- struct opus_attr *attr = (struct opus_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case OPUS_ATTR_KEY_MAX_BITRATE:
- attr->maxbitrate = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_MAX_PLAYRATE:
- attr->maxplayrate = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_MINPTIME:
- attr->minptime = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_STEREO:
- attr->stereo = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_CBR:
- attr->cbr = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_FEC:
- attr->fec = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_DTX:
- attr->dtx = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_SPROP_CAPTURE_RATE:
- attr->spropmaxcapturerate = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_SPROP_STEREO:
- attr->spropstereo = (va_arg(ap, int));
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- }
+ struct ast_format *cloned;
+ struct opus_attr *attr;
+ unsigned int val;
+
+ if (sscanf(value, "%30u", &val) != 1) {
+ ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
+ value, name);
+ return NULL;
+ }
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
}
+ attr = ast_format_get_attribute_data(cloned);
+
+ if (!strcasecmp(name, "max_bitrate")) {
+ attr->maxbitrate = val;
+ } else if (!strcasecmp(name, "max_playrate")) {
+ attr->maxplayrate = val;
+ } else if (!strcasecmp(name, "minptime")) {
+ attr->minptime = val;
+ } else if (!strcasecmp(name, "stereo")) {
+ attr->stereo = val;
+ } else if (!strcasecmp(name, "cbr")) {
+ attr->cbr = val;
+ } else if (!strcasecmp(name, "fec")) {
+ attr->fec = val;
+ } else if (!strcasecmp(name, "dtx")) {
+ attr->dtx = val;
+ } else if (!strcasecmp(name, "sprop_capture_rate")) {
+ attr->spropmaxcapturerate = val;
+ } else if (!strcasecmp(name, "sprop_stereo")) {
+ attr->spropstereo = val;
+ } else {
+ ast_log(LOG_WARNING, "unknown attribute type %s\n", name);
+ }
+
+ return cloned;
}
-static struct ast_format_attr_interface opus_interface = {
- .id = AST_FORMAT_OPUS,
- .format_attr_get_joint = opus_getjoint,
- .format_attr_set = opus_set,
- .format_attr_isset = opus_isset,
- .format_attr_get_val = opus_get_val,
- .format_attr_sdp_parse = opus_sdp_parse,
- .format_attr_sdp_generate = opus_sdp_generate,
+static struct ast_format_interface opus_interface = {
+ .format_destroy = opus_destroy,
+ .format_clone = opus_clone,
+ .format_get_joint = opus_getjoint,
+ .format_attribute_set = opus_set,
+ .format_parse_sdp_fmtp = opus_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = opus_generate_sdp_fmtp,
};
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&opus_interface)) {
+ if (ast_format_interface_register("opus", &opus_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -310,7 +249,6 @@ static int load_module(void)
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&opus_interface);
return 0;
}
diff --git a/res/res_format_attr_silk.c b/res/res_format_attr_silk.c
index 075570fb5..a46c62099 100644
--- a/res/res_format_attr_silk.c
+++ b/res/res_format_attr_silk.c
@@ -47,11 +47,43 @@ struct silk_attr {
unsigned int packetloss_percentage;
};
-static int silk_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static void silk_destroy(struct ast_format *format)
{
- struct silk_attr *attr = (struct silk_attr *) format_attr;
+ struct silk_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int silk_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct silk_attr *original = ast_format_get_attribute_data(src);
+ struct silk_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static struct ast_format *silk_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *cloned;
+ struct silk_attr *attr;
unsigned int val;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
if (sscanf(attributes, "maxaveragebitrate=%30u", &val) == 1) {
attr->maxbitrate = val;
}
@@ -65,9 +97,13 @@ static int silk_sdp_parse(struct ast_format_attr *format_attr, const char *attri
return 0;
}
-static void silk_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+static void silk_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct silk_attr *attr = (struct silk_attr *) format_attr;
+ struct silk_attr *attr = ast_format_get_attribute_data(format);
+
+ if (!attr) {
+ return;
+ }
if ((attr->maxbitrate > 5000) && (attr->maxbitrate < 40000)) {
ast_str_append(str, 0, "a=fmtp:%u maxaveragebitrate=%u\r\n", payload, attr->maxbitrate);
@@ -77,99 +113,40 @@ static void silk_sdp_generate(const struct ast_format_attr *format_attr, unsigne
ast_str_append(str, 0, "a=fmtp:%u useinbandfec=%u\r\n", payload, attr->fec);
}
-static enum ast_format_cmp_res silk_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
+static enum ast_format_cmp_res silk_cmp(const struct ast_format *format1, const struct ast_format *format2)
{
- struct silk_attr *attr1 = (struct silk_attr *) fattr1;
- struct silk_attr *attr2 = (struct silk_attr *) fattr2;
+ struct silk_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct silk_attr *attr2 = ast_format_get_attribute_data(format2);
- if (attr1->samplerate == attr2->samplerate) {
+ if (((!attr1 || !attr1->samplerate) && (!attr2 || !attr2->samplerate)) ||
+ (attr1->samplerate == attr2->samplerate)) {
return AST_FORMAT_CMP_EQUAL;
}
+
return AST_FORMAT_CMP_NOT_EQUAL;
}
-static int silk_get_val(const struct ast_format_attr *fattr, int key, void *result)
+static struct ast_format *silk_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- const struct silk_attr *attr = (struct silk_attr *) fattr;
- int *val = result;
-
- switch (key) {
- case SILK_ATTR_KEY_SAMP_RATE:
- *val = attr->samplerate;
- break;
- case SILK_ATTR_KEY_MAX_BITRATE:
- *val = attr->maxbitrate;
- break;
- case SILK_ATTR_KEY_DTX:
- *val = attr->dtx;
- break;
- case SILK_ATTR_KEY_FEC:
- *val = attr->fec;
- break;
- case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
- *val = attr->packetloss_percentage;
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
- return -1;
- }
- return 0;
-}
+ struct silk_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct silk_attr *attr2 = ast_format_get_attribute_data(format2);
+ unsigned int samplerate;
+ struct ast_format *jointformat;
+ struct silk_attr *attr_res;
-static int silk_isset(const struct ast_format_attr *fattr, va_list ap)
-{
- enum silk_attr_keys key;
- const struct silk_attr *attr = (struct silk_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case SILK_ATTR_KEY_SAMP_RATE:
- if (attr->samplerate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_MAX_BITRATE:
- if (attr->maxbitrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_DTX:
- if (attr->dtx != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_FEC:
- if (attr->fec != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
- if (attr->packetloss_percentage != (va_arg(ap, int))) {
- return -1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- return -1;
- }
+ samplerate = attr1->samplerate & attr2->samplerate;
+ /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
+ if (samplerate) {
+ return NULL;
}
- return 0;
-}
-static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
-{
- struct silk_attr *attr1 = (struct silk_attr *) fattr1;
- struct silk_attr *attr2 = (struct silk_attr *) fattr2;
- struct silk_attr *attr_res = (struct silk_attr *) result;
- int joint = -1;
- attr_res->samplerate = attr1->samplerate & attr2->samplerate;
- /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
- if (attr_res->samplerate) {
- joint = 0;
+ jointformat = ast_format_clone(format1);
+ if (!jointformat) {
+ return NULL;
}
+ attr_res = ast_format_get_attribute_data(jointformat);
+ attr_res->samplerate = samplerate;
+
/* Take the lowest max bitrate */
attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
@@ -184,54 +161,58 @@ static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_
/* Use the maximum packetloss percentage between the two attributes. This affects how
* much redundancy is used in the FEC. */
attr_res->packetloss_percentage = MAX(attr1->packetloss_percentage, attr2->packetloss_percentage);
- return joint;
+
+ return jointformat;
}
-static void silk_set(struct ast_format_attr *fattr, va_list ap)
+static struct ast_format *silk_set(const struct ast_format *format, const char *name, const char *value)
{
- enum silk_attr_keys key;
- struct silk_attr *attr = (struct silk_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case SILK_ATTR_KEY_SAMP_RATE:
- attr->samplerate = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_MAX_BITRATE:
- attr->maxbitrate = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_DTX:
- attr->dtx = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_FEC:
- attr->fec = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
- attr->packetloss_percentage = (va_arg(ap, int));
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- }
+ struct ast_format *cloned;
+ struct silk_attr *attr;
+ unsigned int val;
+
+ if (sscanf(value, "%30u", &val) != 1) {
+ ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
+ value, name);
+ return NULL;
+ }
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ if (!strcasecmp(name, "sample_rate")) {
+ attr->samplerate = val;
+ } else if (!strcasecmp(name, "max_bitrate")) {
+ attr->maxbitrate = val;
+ } else if (!strcasecmp(name, "dtx")) {
+ attr->dtx = val;
+ } else if (!strcasecmp(name, "fec")) {
+ attr->fec = val;
+ } else if (!strcasecmp(name, "packetloss_percentage")) {
+ attr->packetloss_percentage = val;
+ } else {
+ ast_log(LOG_WARNING, "unknown attribute type %s\n", name);
}
+
+ return cloned;
}
-static struct ast_format_attr_interface silk_interface = {
- .id = AST_FORMAT_SILK,
- .format_attr_cmp = silk_cmp,
- .format_attr_get_joint = silk_getjoint,
- .format_attr_set = silk_set,
- .format_attr_isset = silk_isset,
- .format_attr_get_val = silk_get_val,
- .format_attr_sdp_parse = silk_sdp_parse,
- .format_attr_sdp_generate = silk_sdp_generate,
+static struct ast_format_interface silk_interface = {
+ .format_destroy = silk_destroy,
+ .format_clone = silk_clone,
+ .format_cmp = silk_cmp,
+ .format_get_joint = silk_getjoint,
+ .format_attribute_set = silk_set,
+ .format_parse_sdp_fmtp = silk_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = silk_generate_sdp_fmtp,
};
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&silk_interface)) {
+ if (ast_format_interface_register("silk", &silk_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -240,7 +221,6 @@ static int load_module(void)
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&silk_interface);
return 0;
}
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 1d05f0daa..093c846ee 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -131,8 +131,8 @@ static int respawn_time = 20;
struct moh_files_state {
/*! Holds a reference to the MOH class. */
struct mohclass *class;
- struct ast_format origwfmt;
- struct ast_format mohwfmt;
+ struct ast_format *origwfmt;
+ struct ast_format *mohwfmt;
int announcement;
int samples;
int sample_queue;
@@ -170,7 +170,7 @@ struct mohclass {
int total_files;
unsigned int flags;
/*! The format from the MOH source, not applicable to "files" mode */
- struct ast_format format;
+ struct ast_format *format;
/*! The pid of the external application delivering MOH */
int pid;
time_t start;
@@ -188,7 +188,7 @@ struct mohclass {
struct mohdata {
int pipe[2];
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
struct mohclass *parent;
struct ast_frame f;
AST_LIST_ENTRY(mohdata) list;
@@ -289,10 +289,14 @@ static void moh_files_release(struct ast_channel *chan, void *data)
moh_post_stop(chan);
- ast_format_clear(&state->mohwfmt); /* make sure to clear this format before restoring the original format. */
- if (state->origwfmt.id && ast_set_write_format(chan, &state->origwfmt)) {
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", ast_channel_name(chan), ast_getformatname(&state->origwfmt));
+ ao2_ref(state->mohwfmt, -1);
+ state->mohwfmt = NULL; /* make sure to clear this format before restoring the original format */
+ if (state->origwfmt && ast_set_write_format(chan, state->origwfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", ast_channel_name(chan),
+ ast_format_get_name(state->origwfmt));
}
+ ao2_cleanup(state->origwfmt);
+ state->origwfmt = NULL;
state->save_pos = state->pos;
state->announcement = 0;
@@ -405,15 +409,15 @@ static void moh_files_write_format_change(struct ast_channel *chan, void *data)
/* In order to prevent a recursive call to this function as a result
* of setting the moh write format back on the channel. Clear
* the moh write format before setting the write format on the channel.*/
- if (&state->origwfmt.id) {
- struct ast_format tmp;
+ if (state->origwfmt) {
+ struct ast_format *tmp;
- ast_format_copy(&tmp, ast_channel_writeformat(chan));
- if (state->mohwfmt.id) {
- ast_format_clear(&state->origwfmt);
- ast_set_write_format(chan, &state->mohwfmt);
+ tmp = ao2_bump(ast_channel_writeformat(chan));
+ ao2_replace(state->origwfmt, NULL);
+ if (state->mohwfmt) {
+ ast_set_write_format(chan, state->mohwfmt);
}
- ast_format_copy(&state->origwfmt, &tmp);
+ state->origwfmt = tmp;
}
}
@@ -442,8 +446,8 @@ static int moh_files_generator(struct ast_channel *chan, void *data, int len, in
state->samples += f->samples;
state->sample_queue -= f->samples;
- if (ast_format_cmp(&f->subclass.format, &state->mohwfmt) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_format_copy(&state->mohwfmt, &f->subclass.format);
+ if (ast_format_cmp(f->subclass.format, state->mohwfmt) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ao2_replace(state->mohwfmt, f->subclass.format);
}
res = ast_write(chan, f);
ast_frfree(f);
@@ -486,8 +490,9 @@ static void *moh_files_alloc(struct ast_channel *chan, void *params)
}
state->class = mohclass_ref(class, "Reffing music class for channel");
- ast_format_copy(&state->origwfmt, ast_channel_writeformat(chan));
- ast_format_copy(&state->mohwfmt, ast_channel_writeformat(chan));
+ /* it's possible state is not a new allocation, don't leak old refs */
+ ao2_replace(state->origwfmt, ast_channel_writeformat(chan));
+ ao2_replace(state->mohwfmt, ast_channel_writeformat(chan));
moh_post_start(chan, class->name);
@@ -733,12 +738,12 @@ static void *monmp3thread(void *data)
res = 8 * MOH_MS_INTERVAL; /* 800/100 = 8 samples/ms */
}
/* For non-8000Hz formats, we need to alter the resolution */
- res = res * ast_format_rate(&class->format) / 8000;
+ res = res * ast_format_get_sample_rate(class->format) / 8000;
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_format_determine_length(class->format, res);
if ((res2 = read(class->srcfd, sbuf, len)) != len) {
if (!res2) {
@@ -902,7 +907,7 @@ static struct mohdata *mohalloc(struct mohclass *cl)
fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
moh->f.frametype = AST_FRAME_VOICE;
- ast_format_copy(&moh->f.subclass.format, &cl->format);
+ moh->f.subclass.format = cl->format;
moh->f.offset = AST_FRIENDLY_OFFSET;
moh->parent = mohclass_ref(cl, "Reffing music class for mohdata parent");
@@ -918,7 +923,7 @@ static void moh_release(struct ast_channel *chan, void *data)
{
struct mohdata *moh = data;
struct mohclass *class = moh->parent;
- struct ast_format oldwfmt;
+ struct ast_format *oldwfmt;
ao2_lock(class);
AST_LIST_REMOVE(&moh->parent->members, moh, list);
@@ -927,7 +932,7 @@ static void moh_release(struct ast_channel *chan, void *data)
close(moh->pipe[0]);
close(moh->pipe[1]);
- ast_format_copy(&oldwfmt, &moh->origwfmt);
+ oldwfmt = moh->origwfmt;
moh->parent = class = mohclass_unref(class, "unreffing moh->parent upon deactivation of generator");
@@ -940,13 +945,15 @@ static void moh_release(struct ast_channel *chan, void *data)
if (state && state->class) {
state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
}
- if (oldwfmt.id && ast_set_write_format(chan, &oldwfmt)) {
+ if (oldwfmt && ast_set_write_format(chan, oldwfmt)) {
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n",
- ast_channel_name(chan), ast_getformatname(&oldwfmt));
+ ast_channel_name(chan), ast_format_get_name(oldwfmt));
}
moh_post_stop(chan);
}
+
+ ao2_cleanup(oldwfmt);
}
static void *moh_alloc(struct ast_channel *chan, void *params)
@@ -972,9 +979,10 @@ static void *moh_alloc(struct ast_channel *chan, void *params)
}
if ((res = mohalloc(class))) {
- ast_format_copy(&res->origwfmt, ast_channel_writeformat(chan));
- if (ast_set_write_format(chan, &class->format)) {
- ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", ast_channel_name(chan), ast_codec2str(&class->format));
+ res->origwfmt = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, class->format)) {
+ ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", ast_channel_name(chan),
+ ast_format_get_name(class->format));
moh_release(NULL, res);
res = NULL;
} else {
@@ -991,7 +999,7 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
short buf[1280 + AST_FRIENDLY_OFFSET / 2];
int res;
- len = ast_codec_get_len(&moh->parent->format, samples);
+ len = ast_format_determine_length(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, ast_channel_name(chan));
@@ -1003,7 +1011,7 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
moh->f.datalen = res;
moh->f.data.ptr = buf + AST_FRIENDLY_OFFSET / 2;
- moh->f.samples = ast_codec_get_samples(&moh->f);
+ moh->f.samples = ast_codec_samples_count(&moh->f);
if (ast_write(chan, &moh->f) < 0) {
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
@@ -1303,6 +1311,8 @@ static void local_ast_moh_cleanup(struct ast_channel *chan)
mohclass_unref(state->class, "Uh Oh. Cleaning up MOH with an active class");
ast_log(LOG_WARNING, "Uh Oh. Cleaning up MOH with an active class\n");
}
+ ao2_cleanup(state->origwfmt);
+ ao2_cleanup(state->mohwfmt);
ast_free(ast_channel_music_state(chan));
ast_channel_music_state_set(chan, NULL);
/* Only held a module reference if we had a music state */
@@ -1329,7 +1339,7 @@ static struct mohclass *_moh_class_malloc(const char *file, int line, const char
ao2_alloc(sizeof(*class), moh_class_destructor)
#endif
)) {
- ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
+ class->format = ao2_bump(ast_format_slin);
class->srcfd = -1;
}
@@ -1407,10 +1417,10 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con
else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "alpha"))
ast_set_flag(mohclass, MOH_SORTALPHA);
else if (!strcasecmp(tmp->name, "format")) {
- ast_getformatbyname(tmp->value, &mohclass->format);
- if (!mohclass->format.id) {
+ mohclass->format = ast_format_cache_get(tmp->value);
+ if (!mohclass->format) {
ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value);
- ast_format_set(&mohclass->format, AST_FORMAT_SLINEAR, 0);
+ mohclass->format = ao2_bump(ast_format_slin);
}
}
}
@@ -1643,6 +1653,8 @@ static void moh_class_destructor(void *obj)
class->timer = NULL;
}
+ ao2_cleanup(class->format);
+
/* Finally, collect the exit status of the monitor thread */
if (tid > 0) {
pthread_join(tid, NULL);
@@ -1737,10 +1749,10 @@ static int load_moh_classes(int reload)
} else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "alpha")) {
ast_set_flag(class, MOH_SORTALPHA);
} else if (!strcasecmp(var->name, "format")) {
- ast_getformatbyname(var->value, &class->format);
- if (!class->format.id) {
+ class->format = ast_format_cache_get(var->value);
+ if (!class->format) {
ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value);
- ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
+ class->format = ao2_bump(ast_format_slin);
}
}
}
@@ -1877,7 +1889,7 @@ static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struc
ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
}
if (strcasecmp(class->mode, "files")) {
- ast_cli(a->fd, "\tFormat: %s\n", ast_getformatname(&class->format));
+ ast_cli(a->fd, "\tFormat: %s\n", ast_format_get_name(class->format));
}
}
ao2_iterator_destroy(&i);
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 59db4eb1e..548372879 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1648,8 +1648,8 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "type", "", OPT_NOOP_T, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
- ast_sorcery_object_field_register_alias(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.prefs, media.codecs));
- ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.prefs, media.codecs));
+ ast_sorcery_object_field_register_alias(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.codecs));
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.codecs));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmf_mode", "rfc4733", dtmf_handler, dtmf_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ipv6));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.symmetric));
@@ -1851,9 +1851,7 @@ static void endpoint_destructor(void* obj)
ast_string_field_free_memory(endpoint);
- if (endpoint->media.codecs) {
- ast_format_cap_destroy(endpoint->media.codecs);
- }
+ ao2_ref(endpoint->media.codecs, -1);
subscription_configuration_destroy(&endpoint->subscription);
info_configuration_destroy(&endpoint->info);
media_configuration_destroy(&endpoint->media);
@@ -1891,7 +1889,7 @@ void *ast_sip_endpoint_alloc(const char *name)
ao2_cleanup(endpoint);
return NULL;
}
- if (!(endpoint->media.codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(endpoint->media.codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_cleanup(endpoint);
return NULL;
}
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index b7e1eef3d..90a2cec46 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -41,6 +41,8 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/netsock2.h"
#include "asterisk/channel.h"
@@ -68,38 +70,39 @@ static const char STR_VIDEO[] = "video";
static const int FD_VIDEO = 2;
/*! \brief Retrieves an ast_format_type based on the given stream_type */
-static enum ast_format_type stream_to_media_type(const char *stream_type)
+static enum ast_media_type stream_to_media_type(const char *stream_type)
{
if (!strcasecmp(stream_type, STR_AUDIO)) {
- return AST_FORMAT_TYPE_AUDIO;
+ return AST_MEDIA_TYPE_AUDIO;
} else if (!strcasecmp(stream_type, STR_VIDEO)) {
- return AST_FORMAT_TYPE_VIDEO;
+ return AST_MEDIA_TYPE_VIDEO;
}
return 0;
}
/*! \brief Get the starting descriptor for a media type */
-static int media_type_to_fdno(enum ast_format_type media_type)
+static int media_type_to_fdno(enum ast_media_type media_type)
{
switch (media_type) {
- case AST_FORMAT_TYPE_AUDIO: return FD_AUDIO;
- case AST_FORMAT_TYPE_VIDEO: return FD_VIDEO;
- case AST_FORMAT_TYPE_TEXT:
- case AST_FORMAT_TYPE_IMAGE: break;
+ case AST_MEDIA_TYPE_AUDIO: return FD_AUDIO;
+ case AST_MEDIA_TYPE_VIDEO: return FD_VIDEO;
+ case AST_MEDIA_TYPE_TEXT:
+ case AST_MEDIA_TYPE_UNKNOWN:
+ case AST_MEDIA_TYPE_IMAGE: break;
}
return -1;
}
/*! \brief Remove all other cap types but the one given */
-static void format_cap_only_type(struct ast_format_cap *caps, enum ast_format_type media_type)
+static void format_cap_only_type(struct ast_format_cap *caps, enum ast_media_type media_type)
{
- int i = AST_FORMAT_INC;
- while (i <= AST_FORMAT_TYPE_TEXT) {
- if (i != media_type) {
- ast_format_cap_remove_bytype(caps, i);
+ int i = 0;
+ while (i <= AST_MEDIA_TYPE_TEXT) {
+ if (i != media_type && i != AST_MEDIA_TYPE_UNKNOWN) {
+ ast_format_cap_remove_by_type(caps, i);
}
- i += AST_FORMAT_INC;
+ i += 1;
}
}
@@ -116,9 +119,6 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, 1);
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_NAT, session->endpoint->media.rtp.symmetric);
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session_media->rtp),
- session_media->rtp, &session->endpoint->media.prefs);
-
if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) {
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);
}
@@ -185,74 +185,97 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp
if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
sscanf(pj_strbuf(&fmtp.fmt), "%d", &num);
if ((format = ast_rtp_codecs_get_payload_format(codecs, num))) {
+ struct ast_format *format_parsed;
+
ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));
- ast_format_sdp_parse(format, fmt_param);
+
+ format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(codecs, num, format_parsed);
+ ao2_ref(format_parsed, -1);
+ }
+
+ ao2_ref(format, -1);
}
}
}
+
+ /* Get the packetization, if it exists */
+ if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
+ unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
+ if (framing && session->endpoint->media.rtp.use_ptime) {
+ ast_rtp_codecs_set_framing(codecs, framing);
+ }
+ }
}
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
const struct pjmedia_sdp_media *stream)
{
- RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, peer, NULL, ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
- struct ast_rtp_codecs codecs;
- struct ast_format fmt;
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
+ struct ast_rtp_codecs codecs = AST_RTP_CODECS_NULL_INIT;
int fmts = 0;
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
- !ast_format_cap_is_empty(session->direct_media_cap);
+ ast_format_cap_count(session->direct_media_cap);
- if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
- !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
return -1;
}
/* get the endpoint capabilities */
if (direct_media_enabled) {
- ast_format_cap_joint_copy(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ format_cap_only_type(caps, media_type);
} else {
- ast_format_cap_copy(caps, session->endpoint->media.codecs);
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
}
- format_cap_only_type(caps, media_type);
/* get the capabilities on the peer */
get_codecs(session, stream, &codecs);
ast_rtp_codecs_payload_formats(&codecs, peer, &fmts);
/* get the joint capabilities between peer and endpoint */
- if (!(joint = ast_format_cap_joint(caps, peer))) {
- char usbuf[64], thembuf[64];
+ ast_format_cap_get_compatible(caps, peer, joint);
+ if (!ast_format_cap_count(joint)) {
+ struct ast_str *usbuf = ast_str_alloca(64);
+ struct ast_str *thembuf = ast_str_alloca(64);
ast_rtp_codecs_payloads_destroy(&codecs);
-
- ast_getformatname_multiple(usbuf, sizeof(usbuf), caps);
- ast_getformatname_multiple(thembuf, sizeof(thembuf), peer);
- ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
+ ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n",
+ ast_format_cap_get_names(peer, &usbuf),
+ ast_format_cap_get_names(caps, &thembuf));
return -1;
}
ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp),
session_media->rtp);
- ast_format_cap_copy(caps, session->req_caps);
- ast_format_cap_remove_bytype(caps, media_type);
- ast_format_cap_append(caps, joint);
- ast_format_cap_append(session->req_caps, caps);
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(caps, session->req_caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, media_type);
+ ast_format_cap_append_from_cap(caps, joint, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(session->req_caps, caps, AST_MEDIA_TYPE_UNKNOWN);
if (session->channel) {
- ast_format_cap_copy(caps, ast_channel_nativeformats(session->channel));
- ast_format_cap_remove_bytype(caps, media_type);
- ast_codec_choose(&session->endpoint->media.prefs, joint, 1, &fmt);
- ast_format_cap_add(caps, &fmt);
+ struct ast_format *fmt;
+
+ ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, media_type);
+ fmt = ast_format_cap_get_format(joint, 0);
+ ast_format_cap_append(caps, fmt, 0);
/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
- ast_format_cap_copy(ast_channel_nativeformats(session->channel), caps);
- ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
- ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
+ ast_channel_nativeformats_set(session->channel, caps);
+ ast_channel_set_rawwriteformat(session->channel, fmt);
+ ast_channel_set_rawreadformat(session->channel, fmt);
+
+ ao2_ref(fmt, -1);
}
ast_rtp_codecs_payloads_destroy(&codecs);
@@ -286,7 +309,7 @@ static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *
pjmedia_sdp_attr *attr = NULL;
char *tmp;
- ast_format_sdp_generate(format, rtp_code, &fmtp0);
+ ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
if (ast_str_strlen(fmtp0)) {
tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
/* remove any carriage return line feeds */
@@ -304,18 +327,6 @@ static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *
return attr;
}
-static int codec_pref_has_type(struct ast_codec_pref *prefs, enum ast_format_type media_type)
-{
- int i;
- struct ast_format fmt;
- for (i = 0; ast_codec_pref_index(prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) == media_type) {
- return 1;
- }
- }
- return 0;
-}
-
/*! \brief Function which adds ICE attributes to a media stream */
static void add_ice_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
{
@@ -469,38 +480,6 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
ice->start(session_media->rtp);
}
-static void apply_packetization(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
- const struct pjmedia_sdp_media *remote_stream)
-{
- pjmedia_sdp_attr *attr;
- pj_str_t value;
- unsigned long framing;
- int codec;
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session_media->rtp)->pref;
-
- /* Apply packetization if available and configured to do so */
- if (!session->endpoint->media.rtp.use_ptime || !(attr = pjmedia_sdp_media_find_attr2(remote_stream, "ptime", NULL))) {
- return;
- }
-
- value = attr->value;
- framing = pj_strtoul(pj_strltrim(&value));
-
- for (codec = 0; codec < AST_RTP_MAX_PT; codec++) {
- struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(
- session_media->rtp), codec);
-
- if (!format.asterisk_format) {
- continue;
- }
-
- ast_codec_pref_setsize(pref, &format.format, framing);
- }
-
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session_media->rtp),
- session_media->rtp, pref);
-}
-
/*! \brief figure out media transport encryption type from the media transport string */
static enum ast_sip_session_media_encryption get_media_encryption_type(pj_str_t transport)
{
@@ -722,7 +701,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
{
char host[NI_MAXHOST];
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
/* If no type formats have been configured reject this stream */
if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
@@ -759,11 +738,6 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
if (set_caps(session, session_media, stream)) {
return -1;
}
-
- if (media_type == AST_FORMAT_TYPE_AUDIO) {
- apply_packetization(session, session_media, stream);
- }
-
return 1;
}
@@ -892,18 +866,14 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733) ? AST_RTP_DTMF : 0;
int min_packet_size = 0, max_packet_size = 0;
int rtp_code;
- struct ast_format format;
- RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
+ int use_override_prefs = ast_format_cap_count(session->req_caps);
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
- !ast_format_cap_is_empty(session->direct_media_cap);
+ ast_format_cap_count(session->direct_media_cap);
- int use_override_prefs = session->override_prefs.formats[0].id;
- struct ast_codec_pref *prefs = use_override_prefs ?
- &session->override_prefs : &session->endpoint->media.prefs;
-
- if ((use_override_prefs && !codec_pref_has_type(&session->override_prefs, media_type)) ||
+ if ((use_override_prefs && !ast_format_cap_has_type(session->req_caps, media_type)) ||
(!use_override_prefs && !ast_format_cap_has_type(session->endpoint->media.codecs, media_type))) {
/* If no type formats are configured don't add a stream */
return 0;
@@ -954,59 +924,53 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
/* Add ICE attributes and candidates */
add_ice_to_stream(session, session_media, pool, media);
- if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
return -1;
}
if (direct_media_enabled) {
- ast_format_cap_joint_copy(session->endpoint->media.codecs, session->direct_media_cap, caps);
- } else if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) {
- ast_format_cap_copy(caps, session->endpoint->media.codecs);
+ ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ } else if (!ast_format_cap_count(session->req_caps) ||
+ !ast_format_cap_iscompatible(session->req_caps, session->endpoint->media.codecs)) {
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
} else {
- ast_format_cap_copy(caps, session->req_caps);
+ ast_format_cap_append_from_cap(caps, session->req_caps, media_type);
}
- for (index = 0; ast_codec_pref_index(prefs, index, &format); ++index) {
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session_media->rtp)->pref;
-
- if (AST_FORMAT_GET_TYPE(format.id) != media_type) {
- continue;
- }
+ for (index = 0; index < ast_format_cap_count(caps); ++index) {
+ struct ast_format *format = ast_format_cap_get_format(caps, index);
- if (!use_override_prefs && !ast_format_cap_get_compatible_format(caps, &format, &format)) {
+ if (ast_format_get_type(format) != media_type) {
+ ao2_ref(format, -1);
continue;
}
- if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, &format, 0)) == -1) {
- ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n",ast_getformatname(&format));
+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0)) == -1) {
+ ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
+ ao2_ref(format, -1);
continue;
}
- if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 1, &format, 0))) {
+ if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 1, format, 0))) {
+ ao2_ref(format, -1);
continue;
}
-
media->attr[media->attr_count++] = attr;
- if ((attr = generate_fmtp_attr(pool, &format, rtp_code))) {
+ if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
media->attr[media->attr_count++] = attr;
}
- if (pref && media_type != AST_FORMAT_TYPE_VIDEO) {
- struct ast_format_list fmt = ast_codec_pref_getsize(pref, &format);
- if (fmt.cur_ms && ((fmt.cur_ms < min_packet_size) || !min_packet_size)) {
- min_packet_size = fmt.cur_ms;
- }
-
- if (fmt.max_ms && ((fmt.max_ms < max_packet_size) || !max_packet_size)) {
- max_packet_size = fmt.max_ms;
- }
+ if (ast_format_get_maximum_ms(format) &&
+ ((ast_format_get_maximum_ms(format) < max_packet_size) || !max_packet_size)) {
+ max_packet_size = ast_format_get_maximum_ms(format);
}
+ ao2_ref(format, -1);
}
/* Add non-codec formats */
- if (media_type != AST_FORMAT_TYPE_VIDEO) {
+ if (media_type != AST_MEDIA_TYPE_VIDEO) {
for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) {
if (!(noncodec & index) || (rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp),
0, NULL, index)) == -1) {
@@ -1033,6 +997,10 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
}
/* If ptime is set add it as an attribute */
+ min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(session_media->rtp));
+ if (!min_packet_size) {
+ min_packet_size = ast_format_cap_get_framing(caps);
+ }
if (min_packet_size) {
snprintf(tmp, sizeof(tmp), "%d", min_packet_size);
attr = pjmedia_sdp_attr_create(pool, "ptime", pj_cstr(&stmp, tmp));
@@ -1061,7 +1029,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
{
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
char host[NI_MAXHOST];
int fdno;
@@ -1095,15 +1063,10 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
/* Apply connection information to the RTP instance */
ast_sockaddr_set_port(addrs, remote_stream->desc.port);
ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
-
if (set_caps(session, session_media, local_stream)) {
return -1;
}
- if (media_type == AST_FORMAT_TYPE_AUDIO) {
- apply_packetization(session, session_media, remote_stream);
- }
-
if ((fdno = media_type_to_fdno(media_type)) < 0) {
return -1;
}
@@ -1117,7 +1080,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
ast_rtp_instance_activate(session_media->rtp);
/* audio stream handles music on hold */
- if (media_type != AST_FORMAT_TYPE_AUDIO) {
+ if (media_type != AST_MEDIA_TYPE_AUDIO) {
return 1;
}
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 336122040..96faa64bb 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1069,8 +1069,8 @@ static void session_destructor(void *obj)
ast_party_id_free(&session->id);
ao2_cleanup(session->endpoint);
ao2_cleanup(session->contact);
- ast_format_cap_destroy(session->req_caps);
- ast_format_cap_destroy(session->direct_media_cap);
+ ao2_cleanup(session->req_caps);
+ ao2_cleanup(session->direct_media_cap);
if (session->dsp) {
ast_dsp_free(session->dsp);
@@ -1169,7 +1169,7 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
session->endpoint = ao2_bump(endpoint);
session->contact = ao2_bump(contact);
session->inv_session = inv_session;
- session->req_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ session->req_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (endpoint->dtmf == AST_SIP_DTMF_INBAND) {
dsp_features |= DSP_FEATURE_DIGIT_DETECT;
@@ -1197,7 +1197,7 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
iter->session_begin(session);
}
}
- session->direct_media_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ session->direct_media_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
AST_LIST_HEAD_INIT_NOLOCK(&session->delayed_requests);
ast_party_id_init(&session->id);
ao2_ref(session, +1);
@@ -1273,9 +1273,19 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
return NULL;
}
- if (!ast_format_cap_is_empty(req_caps)) {
- ast_format_cap_copy(session->req_caps, session->endpoint->media.codecs);
- ast_format_cap_append(session->req_caps, req_caps);
+ if (ast_format_cap_count(req_caps)) {
+ /* get joint caps between req_caps and endpoint caps */
+ struct ast_format_cap *joint_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_get_compatible(req_caps, session->endpoint->media.codecs, joint_caps);
+
+ /* if joint caps */
+ if (ast_format_cap_count(joint_caps)) {
+ /* copy endpoint caps into session->req_caps */
+ ast_format_cap_append_from_cap(session->req_caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
+ /* replace instances of joint caps equivalents in session->req_caps */
+ ast_format_cap_replace_from_cap(session->req_caps, joint_caps, AST_MEDIA_TYPE_UNKNOWN);
+ }
+ ao2_cleanup(joint_caps);
}
if ((pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS)) {
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 7251e8f80..bd930295b 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -56,6 +56,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
@@ -66,6 +67,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
+#include "asterisk/smoother.h"
#include "asterisk/test.h"
#define MAX_TIMESTAMP_SKEW 640
@@ -216,8 +218,8 @@ struct ast_rtp {
unsigned int cycles; /*!< Shifted count of sequence number cycles */
double rxjitter; /*!< Interarrival jitter at the moment in seconds */
double rxtransit; /*!< Relative transit time for previous packet */
- struct ast_format lasttxformat;
- struct ast_format 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). */
@@ -1833,7 +1835,11 @@ static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size,
static int rtp_get_rate(struct ast_format *format)
{
- return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
+ /* For those wondering: due to a fluke in RFC publication, G.722 is advertised
+ * as having a sample rate of 8kHz, while implementations must know that its
+ * real rate is 16kHz. Seriously.
+ */
+ return (ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) ? 8000 : (int)ast_format_get_sample_rate(format);
}
static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
@@ -2184,6 +2190,10 @@ static int ast_rtp_new(struct ast_rtp_instance *instance,
rtp->dtlstimerid = -1;
#endif
+ rtp->f.subclass.format = ao2_bump(ast_format_none);
+ rtp->lastrxformat = ao2_bump(ast_format_none);
+ rtp->lasttxformat = ao2_bump(ast_format_none);
+
return 0;
}
@@ -2265,6 +2275,10 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
}
#endif
+ ao2_cleanup(rtp->lasttxformat);
+ ao2_cleanup(rtp->lastrxformat);
+ ao2_cleanup(rtp->f.subclass.format);
+
/* Destroy synchronization items */
ast_mutex_destroy(&rtp->lock);
ast_cond_destroy(&rtp->cond);
@@ -2444,7 +2458,7 @@ static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, cha
rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
- if (duration > 0 && (measured_samples = duration * rtp_get_rate(&rtp->f.subclass.format) / 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 %d to %u\n", rtp->send_duration, measured_samples);
rtp->send_duration = measured_samples;
}
@@ -2620,7 +2634,7 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
int fraction_lost;
struct timeval dlsr = { 0, };
char bdata[512];
- int rate = rtp_get_rate(&rtp->f.subclass.format);
+ int rate = rtp_get_rate(rtp->f.subclass.format);
int ice;
int header_offset = 0;
struct ast_sockaddr remote_address = { {0,} };
@@ -2791,9 +2805,9 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
int pred, mark = 0;
unsigned int ms = calc_txstamp(rtp, &frame->delivery);
struct ast_sockaddr remote_address = { {0,} };
- int rate = rtp_get_rate(&frame->subclass.format) / 1000;
+ int rate = rtp_get_rate(frame->subclass.format) / 1000;
- if (frame->subclass.format.id == AST_FORMAT_G722) {
+ if (ast_format_cmp(frame->subclass.format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
frame->samples /= 2;
}
@@ -2817,7 +2831,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
}
}
} else if (frame->frametype == AST_FRAME_VIDEO) {
- mark = ast_format_get_video_mark(&frame->subclass.format);
+ mark = frame->subclass.frame_ending;
pred = rtp->lastovidtimestamp + frame->samples;
/* Re-calculate last TS */
rtp->lastts = rtp->lastts + ms * 90;
@@ -2959,7 +2973,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_sockaddr remote_address = { {0,} };
- struct ast_format subclass;
+ struct ast_format *format;
int codec;
ast_rtp_instance_get_remote_address(instance, &remote_address);
@@ -3029,17 +3043,28 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
}
/* Grab the subclass and look up the payload we are going to use */
- 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));
+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance),
+ 1,
+ frame->subclass.format,
+ 0);
+ if (codec < 0) {
+ ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n",
+ ast_format_get_name(frame->subclass.format));
return -1;
}
- /* Oh dear, if the format changed we will have to set up a new smoother */
- 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);
+ /* Note that we do not increase the ref count here as this pointer
+ * will not be held by any thing explicitly. The format variable is
+ * merely a convenience reference to frame->subclass.format */
+ format = frame->subclass.format;
+ if (ast_format_cmp(rtp->lasttxformat, format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ /* Oh dear, if the format changed we will have to set up a new smoother */
+ if (option_debug > 0) {
+ ast_debug(1, "Ooh, format changed from %s to %s\n",
+ ast_format_get_name(rtp->lasttxformat),
+ ast_format_get_name(frame->subclass.format));
+ }
+ ao2_replace(rtp->lasttxformat, format);
if (rtp->smoother) {
ast_smoother_free(rtp->smoother);
rtp->smoother = NULL;
@@ -3047,34 +3072,15 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
}
/* If no smoother is present see if we have to set one up */
- if (!rtp->smoother) {
- struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, &subclass);
-
- switch (subclass.id) {
- case AST_FORMAT_SPEEX:
- case AST_FORMAT_SPEEX16:
- case AST_FORMAT_SPEEX32:
- case AST_FORMAT_SILK:
- case AST_FORMAT_CELT:
- case AST_FORMAT_G723_1:
- case AST_FORMAT_SIREN7:
- case AST_FORMAT_SIREN14:
- case AST_FORMAT_G719:
- /* Opus */
- case AST_FORMAT_OPUS:
- /* these are all frame-based codecs and cannot be safely run through
- a smoother */
- break;
- 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));
- 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));
+ if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
+ unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
+
+ if (framing_ms) {
+ rtp->smoother = ast_smoother_new((framing_ms * ast_format_get_minimum_bytes(format)) / ast_format_get_minimum_ms(format));
+ if (!rtp->smoother) {
+ ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len: %u\n",
+ ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
+ return -1;
}
}
}
@@ -3122,7 +3128,7 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
double d;
double dtv;
double prog;
- int rate = rtp_get_rate(&rtp->f.subclass.format);
+ int rate = rtp_get_rate(rtp->f.subclass.format);
double normdev_rxjitter_current;
if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
@@ -3277,7 +3283,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
rtp->dtmf_duration = new_duration;
rtp->resp = resp;
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.format)), 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);
@@ -3308,7 +3314,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
if (rtp->resp && rtp->resp != resp) {
/* Another digit already began. End it */
f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), 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);
@@ -3405,10 +3411,10 @@ static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, u
}
} else if ((rtp->resp == resp) && !power) {
f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
- f->samples = rtp->dtmfsamples * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8);
+ f->samples = rtp->dtmfsamples * (rtp_get_rate(rtp->lastrxformat) / 1000);
rtp->resp = 0;
} else if (rtp->resp == resp) {
- rtp->dtmfsamples += 20 * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8);
+ rtp->dtmfsamples += 20 * (rtp_get_rate(rtp->lastrxformat) / 1000);
}
rtp->dtmf_timeout = 0;
@@ -3424,7 +3430,8 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u
totally help us out becuase we don't have an engine to keep it going and we are not
guaranteed to have it every 20ms or anything */
if (rtpdebug) {
- ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", (int) rtp->lastrxformat.id, len);
+ ast_debug(0, "- RTP 3389 Comfort noise event: Format %s (len = %d)\n",
+ ast_format_get_name(rtp->lastrxformat), len);
}
if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
@@ -3796,7 +3803,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance);
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1);
int res = 0, payload = 0, bridged_payload = 0, mark;
- struct ast_rtp_payload_type payload_type;
+ RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
int reconstruct = ntohl(rtpheader[0]);
struct ast_sockaddr remote_address = { {0,} };
int ice;
@@ -3806,10 +3813,13 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
mark = (((reconstruct & 0x800000) >> 23) != 0);
/* Check what the payload value should be */
- payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
+ payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
+ if (!payload_type) {
+ return -1;
+ }
/* 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.format, payload_type.rtp_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 no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged. Bail. */
if (bridged_payload < 0) {
@@ -3880,7 +3890,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
struct ast_sockaddr addr;
int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
- struct ast_rtp_payload_type payload;
+ RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
struct ast_sockaddr remote_address = { {0,} };
struct frame_list frames;
@@ -4120,20 +4130,20 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
payloadtype, seqno, timestamp,res - hdrlen);
}
- payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
+ payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
/* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
- if (!payload.asterisk_format) {
+ if (!payload->asterisk_format) {
struct ast_frame *f = NULL;
- if (payload.rtp_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.rtp_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.rtp_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",
@@ -4153,10 +4163,25 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
return &ast_null_frame;
}
- 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;
-
+ ao2_replace(rtp->lastrxformat, payload->format);
+ ao2_replace(rtp->f.subclass.format, payload->format);
+ switch (ast_format_get_type(rtp->f.subclass.format)) {
+ case AST_MEDIA_TYPE_AUDIO:
+ rtp->f.frametype = AST_FRAME_VOICE;
+ break;
+ case AST_MEDIA_TYPE_VIDEO:
+ rtp->f.frametype = AST_FRAME_VIDEO;
+ break;
+ case AST_MEDIA_TYPE_TEXT:
+ rtp->f.frametype = AST_FRAME_TEXT;
+ break;
+ case AST_MEDIA_TYPE_IMAGE:
+ /* Fall through */
+ default:
+ ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
+ ast_codec_media_type2str(ast_format_get_type(rtp->f.subclass.format)));
+ return &ast_null_frame;
+ }
rtp->rxseqno = seqno;
if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
@@ -4165,7 +4190,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
if (rtp->resp) {
struct ast_frame *f;
f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), 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);
@@ -4182,7 +4207,9 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
rtp->f.seqno = seqno;
- if (rtp->f.subclass.format.id == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
+ if ((ast_format_cmp(rtp->f.subclass.format, ast_format_t140) == AST_FORMAT_CMP_EQUAL)
+ && ((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);
@@ -4192,7 +4219,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
*data = 0xBD;
}
- if (rtp->f.subclass.format.id == AST_FORMAT_T140RED) {
+ if (ast_format_cmp(rtp->f.subclass.format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {
unsigned char *data = rtp->f.data.ptr;
unsigned char *header_end;
int num_generations;
@@ -4201,7 +4228,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
int x;
- ast_format_set(&rtp->f.subclass.format, AST_FORMAT_T140, 0);
+ ao2_replace(rtp->f.subclass.format, ast_format_t140);
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;
@@ -4239,17 +4266,17 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
}
}
- if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) {
- rtp->f.samples = ast_codec_get_samples(&rtp->f);
- if (ast_format_is_slinear(&rtp->f.subclass.format)) {
+ if (ast_format_get_type(rtp->f.subclass.format) == AST_MEDIA_TYPE_AUDIO) {
+ rtp->f.samples = ast_codec_samples_count(&rtp->f);
+ if (ast_format_cache_is_slinear(rtp->f.subclass.format)) {
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.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) {
+ rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass.format) / 1000);
+ rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
+ } else if (ast_format_get_type(rtp->f.subclass.format) == AST_MEDIA_TYPE_VIDEO) {
/* Video -- samples is # of samples vs. 90000 */
if (!rtp->lastividtimestamp)
rtp->lastividtimestamp = timestamp;
@@ -4258,10 +4285,8 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
rtp->f.delivery.tv_sec = 0;
rtp->f.delivery.tv_usec = 0;
/* Pass the RTP marker bit as bit */
- if (mark) {
- ast_format_set_video_mark(&rtp->f.subclass.format);
- }
- } else {
+ rtp->f.subclass.frame_ending = mark;
+ } else if (ast_format_get_type(rtp->f.subclass.format) == AST_MEDIA_TYPE_TEXT) {
/* TEXT -- samples is # of samples vs. 1000 */
if (!rtp->lastitexttimestamp)
rtp->lastitexttimestamp = timestamp;
@@ -4269,6 +4294,10 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
rtp->lastitexttimestamp = timestamp;
rtp->f.delivery.tv_sec = 0;
rtp->f.delivery.tv_usec = 0;
+ } else {
+ ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
+ ast_codec_media_type2str(ast_format_get_type(rtp->f.subclass.format)));
+ return &ast_null_frame;;
}
AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
@@ -4413,7 +4442,7 @@ static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int
}
rtp->red->t140.frametype = AST_FRAME_TEXT;
- ast_format_set(&rtp->red->t140.subclass.format, AST_FORMAT_T140RED, 0);
+ ao2_replace(rtp->red->t140.subclass.format, ast_format_t140_red);
rtp->red->t140.data.ptr = &rtp->red->buf_data;
rtp->red->t140.ts = 0;
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index c13e9ad1e..7e8b24214 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
+#include "asterisk/format_cache.h"
/*! Command value used for Linksys paging to indicate we are starting */
#define LINKSYS_MCAST_STARTCMD 6
@@ -144,7 +145,8 @@ static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched
static int rtp_get_rate(struct ast_format *format)
{
- return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
+ return ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL ?
+ 8000 : ast_format_get_sample_rate(format);
}
static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
@@ -237,7 +239,7 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
int hdrlen = 12, res = 0, codec;
unsigned char *rtpheader;
unsigned int ms = calc_txstamp(multicast, &frame->delivery);
- int rate = rtp_get_rate(&frame->subclass.format) / 1000;
+ int rate = rtp_get_rate(frame->subclass.format) / 1000;
/* We only accept audio, nothing else */
if (frame->frametype != AST_FRAME_VOICE) {
@@ -245,7 +247,7 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
}
/* Grab the actual payload number for when we create the RTP packet */
- if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &frame->subclass.format, 0)) < 0) {
+ if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.format, 0)) < 0) {
return -1;
}
diff --git a/res/res_speech.c b/res/res_speech.c
index 71c283f40..0e4352da4 100644
--- a/res/res_speech.c
+++ b/res/res_speech.c
@@ -38,7 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#include "asterisk/cli.h"
#include "asterisk/term.h"
#include "asterisk/speech.h"
-
+#include "asterisk/format_cache.h"
static AST_RWLIST_HEAD_STATIC(engines, ast_speech_engine);
static struct ast_speech_engine *default_engine = NULL;
@@ -183,26 +183,34 @@ struct ast_speech *ast_speech_new(const char *engine_name, const struct ast_form
{
struct ast_speech_engine *engine = NULL;
struct ast_speech *new_speech = NULL;
- struct ast_format_cap *joint = NULL;
- struct ast_format best;
-
- ast_format_set(&best, AST_FORMAT_SLINEAR, 0);
+ struct ast_format_cap *joint;
+ RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
/* 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 ((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)) {
+ joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!joint) {
return NULL;
}
+ ast_format_cap_get_compatible(engine->formats, cap, joint);
+ best = ast_format_cap_get_format(joint, 0);
+ ao2_ref(joint, -1);
+
+ if (!best) {
+ if (ast_format_cap_iscompatible_format(engine->formats, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL) {
+ best = ao2_bump(ast_format_slin);
+ } else {
+ 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))))
+ if (!(new_speech = ast_calloc(1, sizeof(*new_speech)))) {
return NULL;
+ }
/* Initialize the lock */
ast_mutex_init(&new_speech->lock);
@@ -214,13 +222,13 @@ struct ast_speech *ast_speech_new(const char *engine_name, const struct ast_form
new_speech->engine = engine;
/* Can't forget the format audio is going to be in */
- ast_format_copy(&new_speech->format, &best);
+ 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, &best)) {
+ if (engine->create(new_speech, best)) {
ast_mutex_destroy(&new_speech->lock);
ast_free(new_speech);
new_speech = NULL;
@@ -248,6 +256,8 @@ int ast_speech_destroy(struct ast_speech *speech)
if (speech->processing_sound)
ast_free(speech->processing_sound);
+ ao2_ref(speech->format, -1);
+
/* Aloha we are done */
ast_free(speech);
diff --git a/res/res_stasis.c b/res/res_stasis.c
index d915914d5..cda0d80eb 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -72,6 +72,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/bridge_after.h"
+#include "asterisk/format_cache.h"
/*! Time to wait for a frame in the application */
#define MAX_WAIT_MS 200
@@ -435,15 +436,14 @@ static void moh_after_bridge_cb(struct ast_channel *chan, void *data)
/*! Request a bridge MOH channel */
static struct ast_channel *prepare_bridge_moh_channel(void)
{
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
- struct ast_format format;
+ RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return NULL;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
return ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);
}
diff --git a/res/res_stasis_snoop.c b/res/res_stasis_snoop.c
index e4a309d47..c39c8fae2 100644
--- a/res/res_stasis_snoop.c
+++ b/res/res_stasis_snoop.c
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/timing.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
/*! \brief The interval (in milliseconds) that the Snoop timer is triggered, also controls length of audio within frames */
#define SNOOP_INTERVAL 20
@@ -58,7 +59,7 @@ struct stasis_app_snoop {
/*! \brief Number of samples to be read in when spying */
unsigned int spy_samples;
/*! \brief Format in use by the spy audiohook */
- struct ast_format spy_format;
+ struct ast_format *spy_format;
/*! \brief Audiohook used to whisper on the channel */
struct ast_audiohook whisper;
/*! \brief Direction for whispering */
@@ -179,7 +180,7 @@ static struct ast_frame *snoop_read(struct ast_channel *chan)
/* Only get audio from the spy audiohook if it is active */
if (snoop->spy_active) {
ast_audiohook_lock(&snoop->spy);
- frame = ast_audiohook_read_frame(&snoop->spy, snoop->spy_samples, snoop->spy_direction, &snoop->spy_format);
+ frame = ast_audiohook_read_frame(&snoop->spy, snoop->spy_samples, snoop->spy_direction, snoop->spy_format);
ast_audiohook_unlock(&snoop->spy);
}
@@ -278,10 +279,10 @@ static int snoop_setup_audiohook(struct ast_channel *chan, enum ast_audiohook_ty
static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop)
{
SCOPED_CHANNELLOCK(lock, chan);
- unsigned int rate = MAX(ast_format_rate(ast_channel_rawwriteformat(chan)),
- ast_format_rate(ast_channel_rawreadformat(chan)));
+ unsigned int rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(chan)),
+ ast_format_get_sample_rate(ast_channel_rawreadformat(chan)));
- ast_format_set(&snoop->spy_format, ast_format_slin_by_rate(rate), 0);
+ snoop->spy_format = ast_format_cache_get_slin_by_rate(rate);
}
struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
@@ -289,6 +290,7 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
const char *app, const char *app_args, const char *snoop_id)
{
RAII_VAR(struct stasis_app_snoop *, snoop, NULL, ao2_cleanup);
+ struct ast_format_cap *caps;
pthread_t thread;
struct ast_assigned_ids assignedids = {
.uniqueid = snoop_id,
@@ -343,11 +345,18 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
ast_channel_set_fd(snoop->chan, 0, ast_timer_fd(snoop->timer));
/* The format on the Snoop channel will be this signed linear format, and it will never change */
- ast_format_cap_set(ast_channel_nativeformats(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_writeformat(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_rawwriteformat(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_readformat(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_rawreadformat(snoop->chan), &snoop->spy_format);
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+ ast_format_cap_append(caps, snoop->spy_format, 0);
+ ast_channel_nativeformats_set(snoop->chan, caps);
+ ao2_ref(caps, -1);
+
+ ast_channel_set_writeformat(snoop->chan, snoop->spy_format);
+ ast_channel_set_rawwriteformat(snoop->chan, snoop->spy_format);
+ ast_channel_set_readformat(snoop->chan, snoop->spy_format);
+ ast_channel_set_rawreadformat(snoop->chan, snoop->spy_format);
ast_channel_unlock(snoop->chan);
@@ -357,7 +366,7 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
return NULL;
}
- snoop->spy_samples = ast_format_rate(&snoop->spy_format) / (1000 / SNOOP_INTERVAL);
+ snoop->spy_samples = ast_format_get_sample_rate(snoop->spy_format) / (1000 / SNOOP_INTERVAL);
snoop->spy_active = 1;
}
diff --git a/tests/test_abstract_jb.c b/tests/test_abstract_jb.c
index f48307a3a..f0c0315bf 100644
--- a/tests/test_abstract_jb.c
+++ b/tests/test_abstract_jb.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/test.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#define DEFAULT_FRAME_MS 160
#define DEFAULT_CONFIG_FLAGS 0
@@ -85,7 +86,7 @@ static struct ast_frame *create_test_frame(long timestamp,
{
struct ast_frame f = {0};
- f.subclass.format.id = AST_FORMAT_SLINEAR;
+ f.subclass.format = ast_format_slin;
f.frametype = AST_FRAME_VOICE;
f.src = "TEST";
f.ts = timestamp;
diff --git a/tests/test_cel.c b/tests/test_cel.c
index ff0aaca24..010f19987 100644
--- a/tests/test_cel.c
+++ b/tests/test_cel.c
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/test.h"
#include "asterisk/cel.h"
#include "asterisk/channel.h"
+#include "asterisk/format_cache.h"
#include "asterisk/linkedlists.h"
#include "asterisk/chanvars.h"
#include "asterisk/utils.h"
@@ -1317,7 +1318,10 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_swap)
do_sleep();
/* Perform attended transfer */
- ast_bridge_transfer_attended(chan_alice, chan_david);
+ if (ast_bridge_transfer_attended(chan_alice, chan_david)) {
+ ast_test_status_update(test, "Attended transfer failed!\n");
+ return AST_TEST_FAIL;
+ }
do_sleep();
BRIDGE_ENTER_EVENT_PEER(chan_bob, bridge2, "CELTestChannel/David,CELTestChannel/Charlie");
@@ -1397,7 +1401,10 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
BRIDGE_ENTER(chan_david, bridge2);
/* Perform attended transfer */
- ast_bridge_transfer_attended(chan_alice, chan_david);
+ if (ast_bridge_transfer_attended(chan_alice, chan_david)) {
+ ast_test_status_update(test, "Attended transfer failed!\n");
+ return AST_TEST_FAIL;
+ }
do_sleep();
BRIDGE_EXIT_EVENT_PEER(chan_charlie, bridge2, "CELTestChannel/David");
BRIDGE_ENTER_EVENT_PEER(chan_charlie, bridge1, "CELTestChannel/Bob,CELTestChannel/Alice");
diff --git a/tests/test_config.c b/tests/test_config.c
index f9e9a6f48..a8a83b2b0 100644
--- a/tests/test_config.c
+++ b/tests/test_config.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#include "asterisk/frame.h"
#include "asterisk/utils.h"
#include "asterisk/logger.h"
+#include "asterisk/format_cap.h"
#define CONFIG_FILE "test_config.conf"
@@ -627,7 +628,6 @@ struct test_item {
struct ast_sockaddr sockaddropt;
int boolopt;
struct ast_ha *aclopt;
- struct ast_codec_pref codecprefopt;
struct ast_format_cap *codeccapopt;
unsigned int customopt:1;
};
@@ -653,9 +653,7 @@ static void test_item_destructor(void *obj)
{
struct test_item *item = obj;
ast_string_field_free_memory(item);
- if (item->codeccapopt) {
- ast_format_cap_destroy(item->codeccapopt);
- }
+ ao2_cleanup(item->codeccapopt);
if (item->aclopt) {
ast_free_ha(item->aclopt);
}
@@ -671,7 +669,7 @@ static void *test_item_alloc(const char *cat)
ao2_ref(item, -1);
return NULL;
}
- if (!(item->codeccapopt = ast_format_cap_alloc(0))) {
+ if (!(item->codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_ref(item, -1);
return NULL;
}
@@ -821,7 +819,7 @@ AST_TEST_DEFINE(config_options_test)
aco_option_register(&cfg_info, "boolflag3", ACO_EXACT, config_test_conf.types, BOOLFLAG3_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG3);
aco_option_register(&cfg_info, "aclpermitopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 1, FLDSET(struct test_item, aclopt));
aco_option_register(&cfg_info, "acldenyopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 0, FLDSET(struct test_item, aclopt));
- aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt));
+ aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codeccapopt));
aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt));
aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0);
aco_option_register_deprecated(&cfg_info, "permit", config_test_conf.types, "aclpermitopt");
@@ -855,11 +853,11 @@ AST_TEST_DEFINE(config_options_test)
ast_sockaddr_parse(&acl_allow, "1.2.3.4", PARSE_PORT_FORBID);
ast_sockaddr_parse(&acl_fail, "1.1.1.1", PARSE_PORT_FORBID);
- defaults.codeccapopt = ast_format_cap_alloc(0);
- ast_parse_allow_disallow(&defaults.codecprefopt, defaults.codeccapopt, CODEC_DEFAULT, 1);
+ defaults.codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_update_by_allow_disallow(defaults.codeccapopt, CODEC_DEFAULT, 1);
- configs.codeccapopt = ast_format_cap_alloc(0);
- ast_parse_allow_disallow(&configs.codecprefopt, configs.codeccapopt, CODEC_CONFIG, 1);
+ configs.codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_update_by_allow_disallow(configs.codeccapopt, CODEC_CONFIG, 1);
ast_string_field_init(&defaults, 128);
ast_string_field_init(&configs, 128);
@@ -907,10 +905,13 @@ AST_TEST_DEFINE(config_options_test)
res = AST_TEST_FAIL;
}
if (!ast_format_cap_identical(arr[x]->codeccapopt, control->codeccapopt)) {
- char buf1[128], buf2[128];
- ast_getformatname_multiple(buf1, sizeof(buf1), arr[x]->codeccapopt);
- ast_getformatname_multiple(buf2, sizeof(buf2), control->codeccapopt);
- ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n", buf1, buf2, x);
+ struct ast_str *codec_buf1 = ast_str_alloca(64);
+ struct ast_str *codec_buf2 = ast_str_alloca(64);
+
+ ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n",
+ ast_format_cap_get_names(arr[x]->codeccapopt, &codec_buf1),
+ ast_format_cap_get_names(control->codeccapopt, &codec_buf2),
+ x);
res = AST_TEST_FAIL;
}
if (strcasecmp(arr[x]->stropt, control->stropt)) {
@@ -925,8 +926,10 @@ AST_TEST_DEFINE(config_options_test)
}
ast_free_ha(configs.aclopt);
- ast_format_cap_destroy(defaults.codeccapopt);
- ast_format_cap_destroy(configs.codeccapopt);
+ ao2_cleanup(defaults.codeccapopt);
+ defaults.codeccapopt = NULL;
+ ao2_cleanup(configs.codeccapopt);
+ configs.codeccapopt = NULL;
ast_string_field_free_memory(&defaults);
ast_string_field_free_memory(&configs);
return res;
diff --git a/tests/test_core_codec.c b/tests/test_core_codec.c
new file mode 100644
index 000000000..499e633df
--- /dev/null
+++ b/tests/test_core_codec.c
@@ -0,0 +1,369 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Core Codec API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+
+static struct ast_codec known_unknown = {
+ .name = "unit_test",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec doubly = {
+ .name = "unit_test_double",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec unknown = {
+ .name = "unit_test_unknown",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_UNKNOWN,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_without_rate = {
+ .name = "unit_test_audio_without_rate",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_get = {
+ .name = "unit_test_audio_get",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_get_unknown = {
+ .name = "unit_test_audio_get_unknown",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_get_id = {
+ .name = "unit_test_audio_get_id",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+AST_TEST_DEFINE(codec_register)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test registration of a core codec that is known to be unknown";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&known_unknown)) {
+ ast_test_status_update(test, "Unsuccessfully registered a codec that is known to be unknown\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_register_twice)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register_twice";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test double registration of a core codec to confirm it fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&doubly)) {
+ ast_test_status_update(test, "Unsuccessfully registered a codec that is known to be unknown\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_codec_register(&doubly)) {
+ ast_test_status_update(test, "Successfully registered a codec twice\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_register_unknown)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register_unknown";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test that registration of an unknown codec type fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!ast_codec_register(&unknown)) {
+ ast_test_status_update(test, "Successfully registered a codec with an unknown media type\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_register_audio_no_sample_rate)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register_audio_no_sample_rate";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test that registration of an audio codec without sample rate fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!ast_codec_register(&audio_without_rate)) {
+ ast_test_status_update(test, "Successfully registered an audio codec without a sample rate\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a known codec succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&audio_get)) {
+ ast_test_status_update(test, "Unsucessfully registered a codec for getting\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("unit_test_audio_get", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n");
+ return AST_TEST_FAIL;
+ } else if (strcmp(codec->name, audio_get.name)) {
+ ast_test_status_update(test, "Name of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->type != audio_get.type) {
+ ast_test_status_update(test, "Type of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->sample_rate != audio_get.sample_rate) {
+ ast_test_status_update(test, "Sample rate of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get_unregistered)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get_unregistered";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a codec that is not registered fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("goats", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (codec) {
+ ast_test_status_update(test, "Successfully got a codec named '%s' when getting a codec named 'goats'\n",
+ codec->name);
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get_unknown)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get_unknown";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a known codec using name and unknown type succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&audio_get_unknown)) {
+ ast_test_status_update(test, "Unsucessfully registered a codec for getting\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("unit_test_audio_get_unknown", AST_MEDIA_TYPE_UNKNOWN, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n");
+ return AST_TEST_FAIL;
+ } else if (strcmp(codec->name, audio_get_unknown.name)) {
+ ast_test_status_update(test, "Name of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->type != audio_get_unknown.type) {
+ ast_test_status_update(test, "Type of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->sample_rate != audio_get_unknown.sample_rate) {
+ ast_test_status_update(test, "Sample rate of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get_id)
+{
+ RAII_VAR(struct ast_codec *, named, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get_unknown";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a known codec using name and unknown type succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&audio_get_id)) {
+ ast_test_status_update(test, "Unsucessfully registered a codec for getting\n");
+ return AST_TEST_FAIL;
+ }
+
+ named = ast_codec_get("unit_test_audio_get_id", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!named) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get_by_id(named->id);
+ if (!codec) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec using id of a named codec we just got\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(codec_register);
+ AST_TEST_UNREGISTER(codec_register_twice);
+ AST_TEST_UNREGISTER(codec_register_unknown);
+ AST_TEST_UNREGISTER(codec_register_audio_no_sample_rate);
+ AST_TEST_UNREGISTER(codec_get);
+ AST_TEST_UNREGISTER(codec_get_unregistered);
+ AST_TEST_UNREGISTER(codec_get_unknown);
+ AST_TEST_UNREGISTER(codec_get_id);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(codec_register);
+ AST_TEST_REGISTER(codec_register_twice);
+ AST_TEST_REGISTER(codec_register_unknown);
+ AST_TEST_REGISTER(codec_register_audio_no_sample_rate);
+ AST_TEST_REGISTER(codec_get);
+ AST_TEST_REGISTER(codec_get_unregistered);
+ AST_TEST_REGISTER(codec_get_unknown);
+ AST_TEST_REGISTER(codec_get_id);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core codec API test module");
diff --git a/tests/test_core_format.c b/tests/test_core_format.c
new file mode 100644
index 000000000..2ae944bb3
--- /dev/null
+++ b/tests/test_core_format.c
@@ -0,0 +1,975 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Core Format API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+
+#define TEST_CATEGORY "/main/core_format/"
+
+static void test_core_format_destroy(struct ast_format *format);
+static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst);
+static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2);
+static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2);
+static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value);
+static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes);
+static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str);
+
+/*! \brief A format attribute 'module' used by the unit tests */
+static struct ast_format_interface test_core_format_attr = {
+ .format_destroy = &test_core_format_destroy,
+ .format_clone = &test_core_format_clone,
+ .format_cmp = &test_core_format_cmp,
+ .format_get_joint = &test_core_format_get_joint,
+ .format_attribute_set = &test_core_format_attribute_set,
+ .format_parse_sdp_fmtp = &test_core_format_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = &test_core_format_generate_sdp_fmtp,
+};
+
+/*! \brief A test piece of data to associate with \ref test_core_format_attr */
+struct test_core_format_pvt {
+ /*! Some data field */
+ int field_one;
+ /*! Another arbitrary data field */
+ int field_two;
+};
+
+/*! \brief A test codec for these unit tests. Should be used with \c test_core_format */
+static struct ast_codec test_core_format_codec = {
+ .name = "test_core_format_codec",
+ .description = "Unit test codec used by test_core_format",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+/*! \brief Tracking object used to verify format attribute callbacks */
+struct callbacks_called {
+ /*! Number of times \ref test_core_format_destroy was called */
+ int format_destroy;
+ /*! Number of times \ref test_core_format_clone was called */
+ int format_clone;
+ /*! Number of times \ref test_core_format_cmp was called */
+ int format_cmp;
+ /*! Number of times \ref test_core_format_get_joint was called */
+ int format_get_joint;
+ /*! Number of times \ref test_core_format_attribute_set was called */
+ int format_attribute_set;
+ /*! Number of times \ref test_core_format_parse_sdp_fmtp was called */
+ int format_parse_sdp_fmtp;
+ /*! Number of times \ref test_core_format_generate_sdp_fmtp was called */
+ int format_generate_sdp_fmtp;
+};
+
+/*! \brief A global tracking object. Cleared out by the test init cb */
+static struct callbacks_called test_callbacks_called;
+
+/*! \brief Format attribute callback for when format attributes are to be destroyed */
+static void test_core_format_destroy(struct ast_format *format)
+{
+ struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format);
+
+ ast_free(pvt);
+ ++test_callbacks_called.format_destroy;
+}
+
+/*! \brief Format attribute callback called during format cloning */
+static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct test_core_format_pvt *pvt = ast_format_get_attribute_data(src);
+ struct test_core_format_pvt *new_pvt;
+
+ new_pvt = ast_calloc(1, sizeof(*new_pvt));
+ if (!new_pvt) {
+ return -1;
+ }
+
+ if (pvt) {
+ *new_pvt = *pvt;
+ }
+ ast_format_set_attribute_data(dst, new_pvt);
+
+ ++test_callbacks_called.format_clone;
+
+ return 0;
+}
+
+/*! \brief Format attribute callback called during format comparison */
+static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1);
+ struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2);
+
+ ++test_callbacks_called.format_cmp;
+ if (pvt1 == pvt2) {
+ return AST_FORMAT_CMP_EQUAL;
+ }
+
+ if ((!pvt1 && pvt2 && (pvt2->field_one != 0 || pvt2->field_two != 0))
+ || (pvt1 && !pvt2 && (pvt1->field_one != 0 || pvt1->field_two != 0))) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
+ }
+
+ if (pvt1 && pvt2) {
+ if (!memcmp(pvt1, pvt2, sizeof(*pvt1))) {
+ return AST_FORMAT_CMP_EQUAL;
+ } else {
+ return AST_FORMAT_CMP_NOT_EQUAL;
+ }
+ }
+
+ return AST_FORMAT_CMP_EQUAL;
+}
+
+/*!
+ * \brief Format attribute callback called during joint format capability
+ * \note Our test will assume the max of attributes \c field_one and \c field_two
+ */
+static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1);
+ struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2);
+ struct ast_format *joint;
+ struct test_core_format_pvt *joint_pvt;
+
+ joint = ast_format_clone(format1);
+ if (!joint) {
+ return NULL;
+ }
+ joint_pvt = ast_format_get_attribute_data(joint);
+
+ joint_pvt->field_one = MAX(pvt1 ? pvt1->field_one : 0, pvt2 ? pvt2->field_one : 0);
+ joint_pvt->field_two = MAX(pvt2 ? pvt2->field_two : 0, pvt2 ? pvt2->field_two : 0);
+
+ ++test_callbacks_called.format_get_joint;
+
+ return joint;
+}
+
+/*! \brief Format attribute callback for setting an attribute on a format */
+static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
+{
+ struct ast_format *clone = ast_format_clone(format);
+ struct test_core_format_pvt *clone_pvt;
+
+ if (!clone) {
+ return NULL;
+ }
+ clone_pvt = ast_format_get_attribute_data(clone);
+
+ if (!strcmp(name, "one")) {
+ clone_pvt->field_one = atoi(value);
+ } else if (!strcmp(name, "two")) {
+ clone_pvt->field_two = atoi(value);
+ }
+ ++test_callbacks_called.format_attribute_set;
+
+ return clone;
+}
+
+/*! \brief Format attribute callback to construct a format from an SDP fmtp line */
+static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *clone = ast_format_clone(format);
+ struct test_core_format_pvt *pvt;
+
+ if (!clone) {
+ return NULL;
+ }
+
+ pvt = ast_format_get_attribute_data(clone);
+
+ if (sscanf(attributes, "one=%d;two=%d", &pvt->field_one, &pvt->field_two) != 2) {
+ ao2_ref(clone, -1);
+ return NULL;
+ }
+
+ ++test_callbacks_called.format_parse_sdp_fmtp;
+ return clone;
+}
+
+/*! \brief Format attribute callback to generate an SDP fmtp line from a format */
+static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
+{
+ struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format);
+
+ if (!pvt) {
+ return;
+ }
+
+ ast_str_append(str, 0, "a=fmtp:%d one=%d;two=%d\r\n", payload, pvt->field_one, pvt->field_two);
+
+ ++test_callbacks_called.format_generate_sdp_fmtp;
+}
+
+AST_TEST_DEFINE(format_create)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format creation unit test";
+ info->description =
+ "Test creation of a format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ao2_ref(format, -1);
+ format = ast_format_create_named("super_ulaw", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_create_attr)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format creation w/ attributes unit test";
+ info->description =
+ "Test creation of a format with attributes";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format_w_attr = ast_format_attribute_set(format, "one", "1");
+ if (!format_w_attr) {
+ ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format_w_attr) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cmp(format, format_w_attr) == AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Format with attributes should not be equal to format without attributes\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 1);
+ ast_test_validate(test, test_callbacks_called.format_cmp == 1);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_clone)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, clone, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format cloning unit test";
+ info->description =
+ "Test cloning of a format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format_w_attr = ast_format_attribute_set(format, "one", "1");
+ if (!format_w_attr) {
+ ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format_w_attr) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ /* Test cloning a format without attributes */
+ clone = ast_format_clone(format);
+ if (!clone) {
+ ast_test_status_update(test, "Could not create cloned format\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(clone) != codec->id) {
+ ast_test_status_update(test, "Cloned format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ } else if (clone == format) {
+ ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cmp(clone, format) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Cloned format is not the same as its original format\n");
+ return AST_TEST_FAIL;
+ }
+ ao2_ref(clone, -1);
+
+ /* Test cloning a format with attributes */
+ clone = ast_format_clone(format_w_attr);
+ if (!clone) {
+ ast_test_status_update(test, "Could not create cloned format\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(clone) != codec->id) {
+ ast_test_status_update(test, "Cloned format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ } else if (clone == format_w_attr) {
+ ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cmp(clone, format_w_attr) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Cloned format is not the same as its original format\n");
+ return AST_TEST_FAIL;
+ }
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 1);
+ ast_test_validate(test, test_callbacks_called.format_clone == 3);
+ ast_test_validate(test, test_callbacks_called.format_cmp == 2);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cmp_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, named, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format comparison unit test";
+ info->description =
+ "Test comparison of two different formats with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ named = ast_format_create_named("super_ulaw", codec);
+ if (!named) {
+ ast_test_status_update(test, "Could not create named format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Two formats that are the same compared as not being equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, named) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Two formats that are the same compared as not being equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cmp_different_codec)
+{
+ RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format comparison unit test";
+ info->description =
+ "Test comparison of two different formats with different codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!first_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(first_codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!second_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(second_codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, second) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_test_status_update(test, "Two formats that have different codecs did not compare as being not equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_attr_cmp_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format with attributes comparison unit test";
+ info->description =
+ "Test comparison of two different formats with attributes with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ original = ast_format_create(codec);
+ if (!original) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_attribute_set(original, "one", "1");
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format with attributes\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_attribute_set(original, "two", "1");
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format with attributes\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, second) == AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Formats with different attributes were compared to be equal when they should not\n");
+ return AST_TEST_FAIL;
+ }
+
+ ao2_ref(second, -1);
+ second = ast_format_attribute_set(original, "one", "1");
+
+ if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Formats with the same attributes should be equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 3);
+ ast_test_validate(test, test_callbacks_called.format_cmp == 2);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_joint_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Joint format unit test";
+ info->description =
+ "Test joint format creation using two different formats with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ joint = ast_format_joint(first, second);
+ if (!joint) {
+ ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(joint) != codec->id) {
+ ast_test_status_update(test, "Returned joint format does not contain expected codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_attr_joint_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
+ struct ast_str *fmtp = ast_str_alloca(64);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Joint format attribute unit test";
+ info->description =
+ "Test joint format creation using two different formats with attributes and with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ original = ast_format_create(codec);
+ if (!original) {
+ ast_test_status_update(test, "Could not create format from test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_attribute_set(original, "one", "2");
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_attribute_set(original, "one", "5");
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ joint = ast_format_joint(first, second);
+ if (!joint) {
+ ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(joint) != codec->id) {
+ ast_test_status_update(test, "Returned joint format does not contain expected codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_generate_sdp_fmtp(joint, 100, &fmtp);
+ ast_test_validate(test, strcmp("a=fmtp:100 one=5;two=0\r\n", ast_str_buffer(fmtp)) == 0);
+
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 2);
+ ast_test_validate(test, test_callbacks_called.format_get_joint == 1);
+ ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_joint_different_codec)
+{
+ RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Joint format unit test";
+ info->description =
+ "Test that there is no joint format between two different formats with different codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!first_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(first_codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!second_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(second_codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ joint = ast_format_joint(first, second);
+ if (joint) {
+ ast_test_status_update(test, "Got a joint format between two formats with different codecs\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_copy)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, copy, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format copying unit test";
+ info->description =
+ "Test copying of a format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ copy = ao2_bump(format);
+ if (!copy) {
+ ast_test_status_update(test, "Copying of a just created format failed\n");
+ return AST_TEST_FAIL;
+ } else if (copy != format) {
+ ast_test_status_update(test, "Copying of a format returned a new format instead of the same one\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_attribute_set_without_interface)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format attribute setting unit test";
+ info->description =
+ "Test that attribute setting on a format without an interface fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_format_attribute_set(format, "bees", "cool")) {
+ ast_test_status_update(test, "Successfully set an attribute on a format without an interface\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_parse_sdp_fmtp_without_interface)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format sdp parse unit test";
+ info->description =
+ "Test that sdp parsing on a format without an interface fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ generated = ast_format_parse_sdp_fmtp(format, "tacos");
+ if (generated != format) {
+ ast_test_status_update(test, "Successfully parsed SDP on a format without an interface\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_parse_and_generate_sdp_fmtp)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup);
+ struct ast_str *fmtp = ast_str_alloca(64);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format sdp parse/generate unit test";
+ info->description =
+ "Test that sdp parsing and generation on a format with an interface succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ generated = ast_format_parse_sdp_fmtp(format, "one=1000;two=256");
+ if (format == generated) {
+ ast_test_status_update(test, "Failed to parse SDP on a format without an interface\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_generate_sdp_fmtp(generated, 8, &fmtp);
+
+ ast_test_validate(test, strcmp("a=fmtp:8 one=1000;two=256\r\n", ast_str_buffer(fmtp)) == 0);
+ ast_test_validate(test, test_callbacks_called.format_parse_sdp_fmtp == 1);
+ ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1);
+
+ return AST_TEST_PASS;
+}
+
+static int test_core_format_init(struct ast_test_info *info, struct ast_test *test)
+{
+ memset(&test_callbacks_called, 0, sizeof(test_callbacks_called));
+
+ return 0;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(format_create);
+ AST_TEST_UNREGISTER(format_create_attr);
+ AST_TEST_UNREGISTER(format_clone);
+ AST_TEST_UNREGISTER(format_cmp_same_codec);
+ AST_TEST_UNREGISTER(format_attr_cmp_same_codec);
+ AST_TEST_UNREGISTER(format_cmp_different_codec);
+ AST_TEST_UNREGISTER(format_joint_same_codec);
+ AST_TEST_UNREGISTER(format_attr_joint_same_codec);
+ AST_TEST_UNREGISTER(format_joint_different_codec);
+ AST_TEST_UNREGISTER(format_copy);
+ AST_TEST_UNREGISTER(format_attribute_set_without_interface);
+ AST_TEST_UNREGISTER(format_parse_sdp_fmtp_without_interface);
+ AST_TEST_UNREGISTER(format_parse_and_generate_sdp_fmtp);
+
+ return 0;
+}
+
+static int load_module(void)
+{
+ /* Test codec/format interface used by this module */
+ if (ast_codec_register(&test_core_format_codec)) {
+ ast_log(AST_LOG_ERROR, "Failed to register test_core_format_codec\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ if (ast_format_interface_register("test_core_format_codec", &test_core_format_attr)) {
+ ast_log(AST_LOG_ERROR, "Failed to register format interface for test_core_format_codec\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ AST_TEST_REGISTER(format_create);
+ AST_TEST_REGISTER(format_create_attr);
+ AST_TEST_REGISTER(format_clone);
+ AST_TEST_REGISTER(format_cmp_same_codec);
+ AST_TEST_REGISTER(format_attr_cmp_same_codec);
+ AST_TEST_REGISTER(format_cmp_different_codec);
+ AST_TEST_REGISTER(format_joint_same_codec);
+ AST_TEST_REGISTER(format_attr_joint_same_codec);
+ AST_TEST_REGISTER(format_joint_different_codec);
+ AST_TEST_REGISTER(format_copy);
+ AST_TEST_REGISTER(format_attribute_set_without_interface);
+ AST_TEST_REGISTER(format_parse_sdp_fmtp_without_interface);
+ AST_TEST_REGISTER(format_parse_and_generate_sdp_fmtp);
+
+ ast_test_register_init(TEST_CATEGORY, &test_core_format_init);
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core format API test module");
diff --git a/tests/test_format_api.c b/tests/test_format_api.c
deleted file mode 100644
index 6cc349570..000000000
--- a/tests/test_format_api.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/*
- * 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>
- <support_level>core</support_level>
- ***/
-
-#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 = NULL;
- 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;
- 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(AST_FORMAT_CAP_FLAG_NOLOCK);
- cap2 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_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(0);
- cap2 = ast_format_cap_alloc(0);
-
- 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(AST_FORMAT_CAP_FLAG_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(0);
- 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(AST_FORMAT_CAP_FLAG_NOLOCK);
- cap2 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- } else {
- cap1 = ast_format_cap_alloc(0);
- cap2 = ast_format_cap_alloc(0);
- joint = ast_format_cap_alloc(0);
- }
- 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");
diff --git a/tests/test_format_cache.c b/tests/test_format_cache.c
new file mode 100644
index 000000000..cc1696b70
--- /dev/null
+++ b/tests/test_format_cache.c
@@ -0,0 +1,281 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Format Cache API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
+
+AST_TEST_DEFINE(format_cache_set)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_set";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache add unit test";
+ info->description =
+ "Test that adding of a cached format succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@20_1", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_set_duplicate)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_set_duplicate";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache add unit test";
+ info->description =
+ "Test that adding of a cached format multiple times succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@20_2", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Failed to update cached format\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_set_null)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_set_null";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache add unit test";
+ info->description =
+ "Test that adding a NULL or empty format to the cache does not succeed";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Successfully cached a format with an empty name\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_get)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, cached, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_get";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache get unit test";
+ info->description =
+ "Test that getting of a cached format succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@20", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get("ulaw@20");
+ if (!cached) {
+ ast_test_status_update(test, "Failed to retrieve a format we just cached\n");
+ return AST_TEST_FAIL;
+ } else if (cached != format) {
+ ast_test_status_update(test, "Returned cached format does not match format we just added\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_get_nonexistent)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, cached, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_get_nonxistent";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache get unit test";
+ info->description =
+ "Test that getting of a non-existent cached format does not succeed";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@40", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get("ulaw@60");
+ if (cached) {
+ ast_test_status_update(test, "Retrieved a cached format when one should not have existed\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get("");
+ if (cached) {
+ ast_test_status_update(test, "Retrieved a cached format when we provided an empty name\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get(NULL);
+ if (cached) {
+ ast_test_status_update(test, "Retrieved a cached format when we provided a NULL name\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(format_cache_set);
+ AST_TEST_UNREGISTER(format_cache_set_duplicate);
+ AST_TEST_UNREGISTER(format_cache_set_null);
+ AST_TEST_UNREGISTER(format_cache_get);
+ AST_TEST_UNREGISTER(format_cache_get_nonexistent);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(format_cache_set);
+ AST_TEST_REGISTER(format_cache_set_duplicate);
+ AST_TEST_REGISTER(format_cache_set_null);
+ AST_TEST_REGISTER(format_cache_get);
+ AST_TEST_REGISTER(format_cache_get_nonexistent);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Format cache API test module");
diff --git a/tests/test_format_cap.c b/tests/test_format_cap.c
new file mode 100644
index 000000000..38320e635
--- /dev/null
+++ b/tests/test_format_cap.c
@@ -0,0 +1,1479 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Format Capabilities API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+#include "asterisk/frame.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
+
+AST_TEST_DEFINE(format_cap_alloc)
+{
+ struct ast_format_cap *caps;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_alloc";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities allocation unit test";
+ info->description =
+ "Test that allocation of a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ ao2_ref(caps, -1);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_single)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding a single format to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format, 42)) {
+ ast_test_status_update(test, "Could not add newly created format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get single format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != format) {
+ ast_test_status_update(test, "Retrieved format is not the same as the one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) {
+ ast_test_status_update(test, "Framing for format in capabilities structure does not match what we provided\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_multiple)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding multiple formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 2) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get first format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != ulaw_format) {
+ ast_test_status_update(test, "First retrieved format is not the ulaw one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) {
+ ast_test_status_update(test, "Framing for ulaw format in capabilities structure does not match what we provided\n");
+ }
+ ao2_ref(retrieved, -1);
+
+ retrieved = ast_format_cap_get_format(caps, 1);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get second format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != alaw_format) {
+ ast_test_status_update(test, "First retrieved format is not the alaw one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 84) {
+ ast_test_status_update(test, "Framing for alaw format in capabilities structure does not match what we provided\n");
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_all_unknown)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding of all formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Added all media formats but no audio formats exist when they should\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Added all media formats but no video formats exist when they should\n");
+ return AST_TEST_FAIL;
+ } else if ((ast_format_cap_count(caps) + 1) != ast_codec_get_max()) {
+ ast_test_status_update(test, "The number of formats in the capabilities structure does not match known number\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_all_audio)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding of all audio formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Added audio media formats but no audio formats exist when they should\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Added only audio media formats but video formats exist when they should not\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_TEXT)) {
+ ast_test_status_update(test, "Added only audio media formats but text formats exist when they should not\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_IMAGE)) {
+ ast_test_status_update(test, "Added only audio media formats but image formats exist when they should not\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_duplicate)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format_named, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities duplication unit test";
+ info->description =
+ "Test that adding a single format multiple times to a capabilities structure results in only a single format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format_named = ast_format_create_named("ulaw@20", codec);
+ if (!format_named) {
+ ast_test_status_update(test, "Could not create named format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format, 42)) {
+ ast_test_status_update(test, "Could not add newly created format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* Note: regardless of it being a duplicate, ast_format_cap_append should return success */
+ if (ast_format_cap_append(caps, format, 0)) {
+ ast_test_status_update(test, "Adding of duplicate format to capabilities structure failed\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format_named, 0)) {
+ ast_test_status_update(test, "Adding of duplicate named format to capabilities structure failed\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get single format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != format) {
+ ast_test_status_update(test, "Retrieved format is not the same as the one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) {
+ ast_test_status_update(test, "Framing for format in capabilities structure does not match what we provided\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_from_cap)
+{
+ RAII_VAR(struct ast_format_cap *, dst_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, src_caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities append unit test";
+ info->description =
+ "Test that appending video formats from one capabilities structure to another succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ dst_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!dst_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ src_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!src_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(src_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Failed to add all video media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to append formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Successfully appended video formats to destination capabilities but it no longer contains audio formats\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Successfully appended formats but video formats do not exist in destination capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_from_cap_duplicate)
+{
+ RAII_VAR(struct ast_format_cap *, dst_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, src_caps, NULL, ao2_cleanup);
+ unsigned int count;
+ unsigned int total_count;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities append duplicate unit test";
+ info->description =
+ "Test that appending capabilities structures multiple times does not result in duplicate formats";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ dst_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!dst_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ src_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!src_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(src_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Failed to add all video media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ total_count = ast_format_cap_count(src_caps) + ast_format_cap_count(dst_caps);
+
+ if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to append formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Successfully appended video formats to destination capabilities but it no longer contains audio formats\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Successfully appended formats but video formats do not exist in destination capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ count = ast_format_cap_count(dst_caps);
+
+ if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to append duplicate formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_test_validate(test, count == ast_format_cap_count(dst_caps));
+ ast_test_validate(test, count == total_count);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_set_framing)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_set_framing";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities framing unit test";
+ info->description =
+ "Test that global framing on a format capabilities structure is used when it should be";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_set_framing(caps, 160);
+
+ ast_test_validate(test, ast_format_cap_get_framing(caps) == 160);
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_get_format_framing(caps, ulaw_format) != 42) {
+ ast_test_status_update(test, "Added ulaw format to capabilities structure with explicit framing but did not get it back\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, alaw_format) != ast_format_get_default_ms(alaw_format)) {
+ ast_test_status_update(test, "Added alaw format to capabilities structure with no explicit framing but did not get global back\n");
+ return AST_TEST_FAIL;
+ }
+ ast_test_validate(test, ast_format_cap_get_framing(caps) == ast_format_get_default_ms(alaw_format));
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_single)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_single";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removing a single format from a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format, 42)) {
+ ast_test_status_update(test, "Could not add newly created format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_remove(caps, format)) {
+ ast_test_status_update(test, "Could not remove format that was just added to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_remove(caps, format)) {
+ ast_test_status_update(test, "Successfully removed a format twice from the capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps)) {
+ ast_test_status_update(test, "Capabilities structure should be empty but instead it contains '%zu' formats\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_multiple)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_multiple";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removing a format from a format capabilities structure containing multiple formats succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_remove(caps, ulaw_format)) {
+ ast_test_status_update(test, "Could not remove the ulaw format we just added to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Capabilities structure should contain 1 format but it contains '%zu'\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get first format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != alaw_format) {
+ ast_test_status_update(test, "First retrieved format is not the alaw one we added\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_bytype)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_bytype";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removal of a specific type of format from a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
+ if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Removed all audio type formats from capabilities structure but some remain\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Removed audio type formats from capabilities structure but video are gone as well\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_all)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_all";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removal of all formats from a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
+
+ if (ast_format_cap_count(caps)) {
+ ast_test_status_update(test, "Removed all formats from capabilities structure but some remain\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_get_compatible_format)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, compatible, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_get_compatible_format";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that getting a compatible format from a capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ compatible = ast_format_cap_get_compatible_format(caps, alaw_format);
+ if (compatible) {
+ ast_test_status_update(test, "Retrieved a compatible format from capabilities structure when none should exist\n");
+ return AST_TEST_FAIL;
+ }
+
+ compatible = ast_format_cap_get_compatible_format(caps, ulaw_format);
+ if (!compatible) {
+ ast_test_status_update(test, "Did not retrieve a compatible format from capabilities structure when there should be one\n");
+ return AST_TEST_FAIL;
+ } else if (compatible != ulaw_format) {
+ ast_test_status_update(test, "Compatible format is not the format we added to the capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_iscompatible_format)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_iscompatible_format";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that checking whether a format is compatible with a capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_iscompatible_format(caps, alaw_format) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_test_status_update(test, "Alaw format is compatible with capabilities structure when it only contains ulaw\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_iscompatible_format(caps, ulaw_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_test_status_update(test, "Ulaw format is not compatible with capabilities structure when it should be\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_get_compatible)
+{
+ RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, compatible_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_get_compatible";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that getting the compatible formats between two capabilities structures succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!alaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!ulaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ compatible_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!compatible_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_get_compatible(ulaw_caps, alaw_caps, compatible_caps);
+ if (ast_format_cap_count(compatible_caps)) {
+ ast_test_status_update(test, "A compatible format exists when none should\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_get_compatible(ulaw_caps, ulaw_caps, compatible_caps);
+ if (!ast_format_cap_count(compatible_caps)) {
+ ast_test_status_update(test, "No compatible formats exist when 1 should\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_iscompatible)
+{
+ RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_iscompatible";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that checking if there are compatible formats between two capabilities structures succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!alaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!ulaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_iscompatible(ulaw_caps, alaw_caps)) {
+ ast_test_status_update(test, "Two capability structures that should not be compatible are\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_iscompatible(ulaw_caps, ulaw_caps)) {
+ ast_test_status_update(test, "Capability structure is not compatible with itself\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_get_names)
+{
+ RAII_VAR(struct ast_format_cap *, empty_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, multi_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ struct ast_str *buffer = ast_str_alloca(128);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_get_names";
+ info->category = "/main/format_cap/";
+ info->summary = "Test getting the names of formats";
+ info->description =
+ "Test that obtaining the names from a format capabilities structure\n"
+ "produces the expected output.\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ empty_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!empty_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ multi_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!multi_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!alaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!ulaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(multi_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to multi capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(multi_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to multi capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_get_names(empty_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(nothing)"));
+ ast_format_cap_get_names(ulaw_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(ulaw)"));
+ ast_format_cap_get_names(alaw_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(alaw)"));
+ ast_format_cap_get_names(multi_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(ulaw|alaw)"));
+
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_best_by_type)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, h263, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, h263_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities best by type unit test";
+ info->description =
+ "Test that we can get the best format type out of a capabilities structure";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ h263 = ast_codec_get("h263", AST_MEDIA_TYPE_VIDEO, 0);
+ if (!h263) {
+ ast_test_status_update(test, "Could not retrieve built-in h263 codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ h263_format = ast_format_create(h263);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create h263 format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, h263_format, 0)) {
+ ast_test_status_update(test, "Could not add h263 format to capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_test_validate(test, ast_format_cmp(best_format, ulaw_format) == AST_FORMAT_CMP_EQUAL);
+ ao2_ref(best_format, -1);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_AUDIO);
+ ast_test_validate(test, ast_format_cmp(best_format, ulaw_format) == AST_FORMAT_CMP_EQUAL);
+ ao2_ref(best_format, -1);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_VIDEO);
+ ast_test_validate(test, ast_format_cmp(best_format, h263_format) == AST_FORMAT_CMP_EQUAL);
+ ao2_ref(best_format, -1);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_IMAGE);
+ ast_test_validate(test, best_format == NULL);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_TEXT);
+ ast_test_validate(test, best_format == NULL);
+
+ return AST_TEST_PASS;
+}
+
+static int test_law_samples(struct ast_frame *frame)
+{
+ return frame->datalen;
+}
+
+static int test_law_length(unsigned int samples)
+{
+ return samples;
+}
+
+static struct ast_codec test_law = {
+ .name = "test_law",
+ .description = "format cap unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .samples_count = test_law_samples,
+ .get_length = test_law_length,
+ .smooth = 1,
+};
+
+static enum ast_format_cmp_res test_law_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ ast_log(LOG_ERROR, "Comparing format1 %p and format2 %p\n", format1, format2);
+ return format1 == format2 ? AST_FORMAT_CMP_EQUAL : AST_FORMAT_CMP_NOT_EQUAL;
+}
+
+static void test_law_destroy(struct ast_format *format)
+{
+}
+
+static int test_law_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ return 0;
+}
+
+static struct ast_format_interface test_law_interface = {
+ .format_cmp = test_law_cmp,
+ .format_clone = test_law_clone,
+ .format_destroy = test_law_destroy,
+};
+
+AST_TEST_DEFINE(format_cap_replace_from_cap)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, replace_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, result_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format_variant, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding multiple formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ replace_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ result_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps || !replace_caps || !result_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("test_law", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve test_law codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format_variant = ast_format_create(ulaw);
+ if (!ulaw_format_variant) {
+ ast_test_status_update(test, "Could not create ulaw format variant using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ /* fill caps with ulaw and alaw */
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_append(caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_count(caps) != 2) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* fill replace_caps with the ulaw variant */
+ if (ast_format_cap_append(replace_caps, ulaw_format_variant, 42)) {
+ ast_test_status_update(test, "Could not add ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_count(replace_caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(replace_caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* fill result_caps with ulaw_variant and alaw */
+ if (ast_format_cap_append(result_caps, ulaw_format_variant, 42)) {
+ ast_test_status_update(test, "Could not add ulaw variant to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_append(result_caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_count(result_caps) != 2) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n",
+ ast_format_cap_count(result_caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* replace caps formats from replace_caps */
+ ast_format_cap_replace_from_cap(caps, replace_caps, AST_MEDIA_TYPE_UNKNOWN);
+
+ /* compare result_caps with caps */
+ if (!ast_format_cap_identical(caps, result_caps)) {
+ ast_test_status_update(test, "Actual and expected result caps differ\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(format_cap_alloc);
+ AST_TEST_UNREGISTER(format_cap_append_single);
+ AST_TEST_UNREGISTER(format_cap_append_multiple);
+ AST_TEST_UNREGISTER(format_cap_append_all_unknown);
+ AST_TEST_UNREGISTER(format_cap_append_all_audio);
+ AST_TEST_UNREGISTER(format_cap_append_duplicate);
+ AST_TEST_UNREGISTER(format_cap_append_from_cap);
+ AST_TEST_UNREGISTER(format_cap_append_from_cap_duplicate);
+ AST_TEST_UNREGISTER(format_cap_set_framing);
+ AST_TEST_UNREGISTER(format_cap_remove_single);
+ AST_TEST_UNREGISTER(format_cap_remove_multiple);
+ AST_TEST_UNREGISTER(format_cap_remove_bytype);
+ AST_TEST_UNREGISTER(format_cap_remove_all);
+ AST_TEST_UNREGISTER(format_cap_get_names);
+ AST_TEST_UNREGISTER(format_cap_get_compatible_format);
+ AST_TEST_UNREGISTER(format_cap_iscompatible_format);
+ AST_TEST_UNREGISTER(format_cap_get_compatible);
+ AST_TEST_UNREGISTER(format_cap_iscompatible);
+ AST_TEST_UNREGISTER(format_cap_best_by_type);
+ AST_TEST_UNREGISTER(format_cap_replace_from_cap);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(format_cap_alloc);
+ AST_TEST_REGISTER(format_cap_append_single);
+ AST_TEST_REGISTER(format_cap_append_multiple);
+ AST_TEST_REGISTER(format_cap_append_all_unknown);
+ AST_TEST_REGISTER(format_cap_append_all_audio);
+ AST_TEST_REGISTER(format_cap_append_duplicate);
+ AST_TEST_REGISTER(format_cap_append_from_cap);
+ AST_TEST_REGISTER(format_cap_append_from_cap_duplicate);
+ AST_TEST_REGISTER(format_cap_set_framing);
+ AST_TEST_REGISTER(format_cap_remove_single);
+ AST_TEST_REGISTER(format_cap_remove_multiple);
+ AST_TEST_REGISTER(format_cap_remove_bytype);
+ AST_TEST_REGISTER(format_cap_remove_all);
+ AST_TEST_REGISTER(format_cap_get_names);
+ AST_TEST_REGISTER(format_cap_get_compatible_format);
+ AST_TEST_REGISTER(format_cap_iscompatible_format);
+ AST_TEST_REGISTER(format_cap_get_compatible);
+ AST_TEST_REGISTER(format_cap_iscompatible);
+ AST_TEST_REGISTER(format_cap_best_by_type);
+ AST_TEST_REGISTER(format_cap_replace_from_cap);
+ ast_codec_register(&test_law);
+ ast_format_interface_register("test_law", &test_law_interface);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Format capabilities API test module");
diff --git a/tests/test_voicemail_api.c b/tests/test_voicemail_api.c
index 43293b0fc..ab1830298 100644
--- a/tests/test_voicemail_api.c
+++ b/tests/test_voicemail_api.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*!
* \internal
@@ -825,12 +826,12 @@ static struct ast_channel *test_vm_api_create_mock_channel(void)
return NULL;
}
- ast_format_set(ast_channel_writeformat(mock_channel), AST_FORMAT_GSM, 0);
+ ast_channel_set_writeformat(mock_channel, ast_format_gsm);
native_formats = ast_channel_nativeformats(mock_channel);
- ast_format_cap_add(native_formats, ast_channel_writeformat(mock_channel));
- ast_format_set(ast_channel_rawwriteformat(mock_channel), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_readformat(mock_channel), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_rawreadformat(mock_channel), AST_FORMAT_GSM, 0);
+ ast_format_cap_append(native_formats, ast_channel_writeformat(mock_channel), 0);
+ ast_channel_set_rawwriteformat(mock_channel, ast_format_gsm);
+ ast_channel_set_readformat(mock_channel, ast_format_gsm);
+ ast_channel_set_rawreadformat(mock_channel, ast_format_gsm);
ast_channel_tech_set(mock_channel, &mock_channel_tech);
ast_channel_unlock(mock_channel);