media formats: re-architect handling of media for performance improvements

In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
 1. Asterisk was limited in how many formats it could handle.
 2. Formats, being a bit field, could not include any attribute information.
    A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.

Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.

Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.

Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.

Generally, the new philosophy for handling formats is as follows:
 * The ast_format structure is reference counted. This removed a large amount
   of the memory allocations and copying that was done in prior versions.
 * In order to prevent race conditions while keeping things performant, the
   ast_format structure is immutable by convention and lock-free. Violate this
   tenet at your peril!
 * Because formats are reference counted, codecs are also reference counted.
   The Asterisk core generally provides built-in codecs and caches the
   ast_format structures created to represent them. Generally, to prevent
   inordinate amounts of module reference bumping, codecs and formats can be
   added at run-time but cannot be removed.
 * All compatibility with the bit field representation of codecs/formats has
   been moved to a compatibility API. The primary user of this representation
   is chan_iax2, which must continue to maintain its bit-field usage of formats
   for interoperability concerns.
 * When a format is negotiated with attributes, or when a format cannot be
   represented by one of the cached formats, a new format object is created or
   cloned from an existing format. That format may have the same codec
   underlying it, but is a different format than a version of the format with
   different attributes or without attributes.
 * While formats are reference counted objects, the reference count maintained
   on the format should be manipulated with care. Formats are generally cached
   and will persist for the lifetime of Asterisk and do not explicitly need
   to have their lifetime modified. An exception to this is when the user of a
   format does not know where the format came from *and* the user may outlive
   the provider of the format. This occurs, for example, when a format is read
   from a channel: the channel may have a format with attributes (hence,
   non-cached) and the user of the format may last longer than the channel (if
   the reference to the channel is released prior to the format's reference).

For more information on this work, see the API design notes:
  https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite

Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.

There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).

Reviews:
 https://reviewboard.asterisk.org/r/3814
 https://reviewboard.asterisk.org/r/3808
 https://reviewboard.asterisk.org/r/3805
 https://reviewboard.asterisk.org/r/3803
 https://reviewboard.asterisk.org/r/3801
 https://reviewboard.asterisk.org/r/3798
 https://reviewboard.asterisk.org/r/3800
 https://reviewboard.asterisk.org/r/3794
 https://reviewboard.asterisk.org/r/3793
 https://reviewboard.asterisk.org/r/3792
 https://reviewboard.asterisk.org/r/3791
 https://reviewboard.asterisk.org/r/3790
 https://reviewboard.asterisk.org/r/3789
 https://reviewboard.asterisk.org/r/3788
 https://reviewboard.asterisk.org/r/3787
 https://reviewboard.asterisk.org/r/3786
 https://reviewboard.asterisk.org/r/3784
 https://reviewboard.asterisk.org/r/3783
 https://reviewboard.asterisk.org/r/3778
 https://reviewboard.asterisk.org/r/3774
 https://reviewboard.asterisk.org/r/3775
 https://reviewboard.asterisk.org/r/3772
 https://reviewboard.asterisk.org/r/3761
 https://reviewboard.asterisk.org/r/3754
 https://reviewboard.asterisk.org/r/3753
 https://reviewboard.asterisk.org/r/3751
 https://reviewboard.asterisk.org/r/3750
 https://reviewboard.asterisk.org/r/3748
 https://reviewboard.asterisk.org/r/3747
 https://reviewboard.asterisk.org/r/3746
 https://reviewboard.asterisk.org/r/3742
 https://reviewboard.asterisk.org/r/3740
 https://reviewboard.asterisk.org/r/3739
 https://reviewboard.asterisk.org/r/3738
 https://reviewboard.asterisk.org/r/3737
 https://reviewboard.asterisk.org/r/3736
 https://reviewboard.asterisk.org/r/3734
 https://reviewboard.asterisk.org/r/3722
 https://reviewboard.asterisk.org/r/3713
 https://reviewboard.asterisk.org/r/3703
 https://reviewboard.asterisk.org/r/3689
 https://reviewboard.asterisk.org/r/3687
 https://reviewboard.asterisk.org/r/3674
 https://reviewboard.asterisk.org/r/3671
 https://reviewboard.asterisk.org/r/3667
 https://reviewboard.asterisk.org/r/3665
 https://reviewboard.asterisk.org/r/3625
 https://reviewboard.asterisk.org/r/3602
 https://reviewboard.asterisk.org/r/3519
 https://reviewboard.asterisk.org/r/3518
 https://reviewboard.asterisk.org/r/3516
 https://reviewboard.asterisk.org/r/3515
 https://reviewboard.asterisk.org/r/3512
 https://reviewboard.asterisk.org/r/3506
 https://reviewboard.asterisk.org/r/3413
 https://reviewboard.asterisk.org/r/3410
 https://reviewboard.asterisk.org/r/3387
 https://reviewboard.asterisk.org/r/3388
 https://reviewboard.asterisk.org/r/3389
 https://reviewboard.asterisk.org/r/3390
 https://reviewboard.asterisk.org/r/3321
 https://reviewboard.asterisk.org/r/3320
 https://reviewboard.asterisk.org/r/3319
 https://reviewboard.asterisk.org/r/3318
 https://reviewboard.asterisk.org/r/3266
 https://reviewboard.asterisk.org/r/3265
 https://reviewboard.asterisk.org/r/3234
 https://reviewboard.asterisk.org/r/3178

ASTERISK-23114 #close
Reported by: mjordan
  media_formats_translation_core.diff uploaded by kharwell (License 6464)
  rb3506.diff uploaded by mjordan (License 6283)
  media_format_app_file.diff uploaded by kharwell (License 6464) 
  misc-2.diff uploaded by file (License 5000)
  chan_mild-3.diff uploaded by file (License 5000) 
  chan_obscure.diff uploaded by file (License 5000) 
  jingle.diff uploaded by file (License 5000) 
  funcs.diff uploaded by file (License 5000) 
  formats.diff uploaded by file (License 5000) 
  core.diff uploaded by file (License 5000) 
  bridges.diff uploaded by file (License 5000) 
  mf-codecs-2.diff uploaded by file (License 5000) 
  mf-app_fax.diff uploaded by file (License 5000) 
  mf-apps-3.diff uploaded by file (License 5000) 
  media-formats-3.diff uploaded by file (License 5000) 

ASTERISK-23715
  rb3713.patch uploaded by coreyfarrell (License 5909)
  rb3689.patch uploaded by mjordan (License 6283)
  
ASTERISK-23957
  rb3722.patch uploaded by mjordan (License 6283) 
  mf-attributes-3.diff uploaded by file (License 5000) 

ASTERISK-23958
Tested by: jrose
  rb3822.patch uploaded by coreyfarrell (License 5909) 
  rb3800.patch uploaded by jrose (License 6182)
  chan_sip.diff uploaded by mjordan (License 6283) 
  rb3747.patch uploaded by jrose (License 6182)

ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
  sip_cleanup.diff uploaded by opticron (License 6273)
  chan_sip_caps.diff uploaded by mjordan (License 6283) 
  rb3751.patch uploaded by coreyfarrell (License 5909) 
  chan_sip-3.diff uploaded by file (License 5000) 

ASTERISK-23960 #close
Tested by: opticron
  direct_media.diff uploaded by opticron (License 6273) 
  pjsip-direct-media.diff uploaded by file (License 5000) 
  format_cap_remove.diff uploaded by opticron (License 6273) 
  media_format_fixes.diff uploaded by opticron (License 6273) 
  chan_pjsip-2.diff uploaded by file (License 5000) 

ASTERISK-23966 #close
Tested by: rmudgett
  rb3803.patch uploaded by rmudgetti (License 5621)
  chan_dahdi.diff uploaded by file (License 5000) 
  
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
  rb3814.patch uploaded by rmudgett (License 5621) 
  moh_cleanup.diff uploaded by opticron (License 6273) 
  bridge_leak.diff uploaded by opticron (License 6273) 
  translate.diff uploaded by file (License 5000) 
  rb3795.patch uploaded by rmudgett (License 5621) 
  tls_fix.diff uploaded by mjordan (License 6283) 
  fax-mf-fix-2.diff uploaded by file (License 5000) 
  rtp_transfer_stuff uploaded by mjordan (License 6283) 
  rb3787.patch uploaded by rmudgett (License 5621) 
  media-formats-explicit-translate-format-3.diff uploaded by file (License 5000) 
  format_cache_case_fix.diff uploaded by opticron (License 6273) 
  rb3774.patch uploaded by rmudgett (License 5621) 
  rb3775.patch uploaded by rmudgett (License 5621) 
  rtp_engine_fix.diff uploaded by opticron (License 6273) 
  rtp_crash_fix.diff uploaded by opticron (License 6273) 
  rb3753.patch uploaded by mjordan (License 6283) 
  rb3750.patch uploaded by mjordan (License 6283) 
  rb3748.patch uploaded by rmudgett (License 5621) 
  media_format_fixes.diff uploaded by opticron (License 6273) 
  rb3740.patch uploaded by mjordan (License 6283) 
  rb3739.patch uploaded by mjordan (License 6283) 
  rb3734.patch uploaded by mjordan (License 6283) 
  rb3689.patch uploaded by mjordan (License 6283) 
  rb3674.patch uploaded by coreyfarrell (License 5909) 
  rb3671.patch uploaded by coreyfarrell (License 5909) 
  rb3667.patch uploaded by coreyfarrell (License 5909) 
  rb3665.patch uploaded by mjordan (License 6283) 
  rb3625.patch uploaded by coreyfarrell (License 5909) 
  rb3602.patch uploaded by coreyfarrell (License 5909) 
  format_compatibility-2.diff uploaded by file (License 5000) 
  core.diff uploaded by file (License 5000) 
  


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Matthew Jordan 2014-07-20 22:06:33 +00:00
parent b299052e20
commit a2c912e997
205 changed files with 14244 additions and 9839 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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_add(ast_channel_nativeformats(ch), &tmpfmt);
ast_format_copy(ast_channel_rawwriteformat(ch), &tmpfmt);
ast_format_copy(ast_channel_rawreadformat(ch), &tmpfmt);
ast_format_cap_append(caps, tmpfmt, 0);
ast_channel_nativeformats_set(ch, caps);
ao2_ref(caps, -1);
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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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",

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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));
}

View File

@ -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");

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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",

View File

@ -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;

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
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);
/* 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);
}
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;
}
}
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");
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_log(LOG_WARNING, "Channel could not be created\n");
ao2_ref(caps, -1);
return NULL;
}
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);
}
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;
}
}
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;
}

View File

@ -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();

View File

@ -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_is_empty(session->cap)) {
if (!ast_format_cap_count(session->cap)) {
return NULL;
}
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) {
if (ast_format_get_type(format) != type) {
ao2_ref(format, -1);
continue;
}
if (!ast_format_cap_iscompatible(session->jointcap, &format)) {
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;
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);
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);
}
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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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_get_names(ast_channel_nativeformats(sub->owner), &cap_buf),
ast_format_get_name(f->subclass.format));
ast_format_cap_set(ast_channel_nativeformats(sub->owner), &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;
}

View File

@ -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) {

View File

@ -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);
}

333
channels/iax2/codec_pref.c Normal file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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 */

View File

@ -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

View File

@ -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")) {

View File

@ -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);

View File

@ -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 */

View File

@ -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;
}

View File

@ -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,
);

View File

@ -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,
);

View File

@ -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_debug(1, "Opening transcoder channel from %s to %s.\n", ast_getformatname(src_format), ast_getformatname(dst_format));
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", 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;

View File

@ -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,
);

View File

@ -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,
);

View File

@ -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,
);

View File

@ -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;
}

View File

@ -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,
);

View File

@ -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++;
}

View File

@ -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;
}

View File

@ -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,
);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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])) {

View File

@ -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;

View File

@ -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;

Some files were not shown because too many files have changed in this diff Show More