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:
parent
b299052e20
commit
a2c912e997
26
UPGRADE.txt
26
UPGRADE.txt
|
@ -208,6 +208,32 @@ chan_sip:
|
|||
progress indications into a 180 Ringing (if a 180 has not yet been
|
||||
transmitted) if 'progressinband=never'.
|
||||
|
||||
- The codec preference order in an SDP during an offer is slightly different
|
||||
than previous releases. Prior to Asterisk 13, the preference order of
|
||||
codecs used to be:
|
||||
(1) Our preferred codec
|
||||
(2) Our configured codecs
|
||||
(3) Any non-audio joint codecs
|
||||
|
||||
One of the ways the new media format architecture in Asterisk 13 improves
|
||||
performance is by reference counting formats, such that they can be reused
|
||||
in many places without additional allocation. To not require a large
|
||||
amount of locking, an instance of a format is immutable by convention.
|
||||
This works well except for formats with attributes. Since a media format
|
||||
with an attribute is a different object than the same format without an
|
||||
attribute, we have to carry over the formats with attributes from an
|
||||
inbound offer so that the correct attributes are offered in an outgoing
|
||||
INVITE request. This requires some subtle tweaks to the preference order
|
||||
to ensure that the media format with attributes is offered to a remote
|
||||
peer, as opposed to the same media format (but without attributes) that
|
||||
may be stored in the peer object.
|
||||
|
||||
All of this means that our offer offer list will now be:
|
||||
(1) Our preferred codec
|
||||
(2) Any joint codecs offered by the inbound offer
|
||||
(3) All other codecs that are not the preferred codec and not a joint
|
||||
codec offered by the inbound offer
|
||||
|
||||
CLI commands:
|
||||
- "core show settings" now lists the current console verbosity in addition
|
||||
to the root console verbosity.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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])) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue