summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2014-07-20 22:06:33 +0000
committerMatthew Jordan <mjordan@digium.com>2014-07-20 22:06:33 +0000
commita2c912e9972c91973ea66902d217746133f96026 (patch)
tree50e01d14ba62950e3f78766d5ba435ba51ca327d
parentb299052e203807c9a2111eb2cd919246d7589cb3 (diff)
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
-rw-r--r--UPGRADE.txt26
-rw-r--r--addons/chan_mobile.c34
-rw-r--r--addons/chan_ooh323.c365
-rw-r--r--addons/chan_ooh323.h4
-rw-r--r--addons/format_mp3.c6
-rw-r--r--addons/ooh323cDriver.c159
-rw-r--r--addons/ooh323cDriver.h6
-rw-r--r--apps/app_agent_pool.c4
-rw-r--r--apps/app_alarmreceiver.c13
-rw-r--r--apps/app_amd.c20
-rw-r--r--apps/app_chanspy.c38
-rw-r--r--apps/app_confbridge.c21
-rw-r--r--apps/app_dictate.c14
-rw-r--r--apps/app_dumpchan.c12
-rw-r--r--apps/app_echo.c5
-rw-r--r--apps/app_fax.c49
-rw-r--r--apps/app_festival.c26
-rw-r--r--apps/app_ices.c14
-rw-r--r--apps/app_jack.c29
-rw-r--r--apps/app_meetme.c43
-rw-r--r--apps/app_milliwatt.c15
-rw-r--r--apps/app_mixmonitor.c10
-rw-r--r--apps/app_mp3.c31
-rw-r--r--apps/app_nbscat.c32
-rw-r--r--apps/app_originate.c25
-rw-r--r--apps/app_record.c13
-rw-r--r--apps/app_sms.c17
-rw-r--r--apps/app_speech_utils.c9
-rw-r--r--apps/app_talkdetect.c16
-rw-r--r--apps/app_test.c17
-rw-r--r--apps/app_voicemail.c29
-rw-r--r--apps/app_waitforsilence.c11
-rw-r--r--apps/confbridge/conf_chan_record.c21
-rw-r--r--bridges/bridge_holding.c18
-rw-r--r--bridges/bridge_native_rtp.c33
-rw-r--r--bridges/bridge_simple.c11
-rw-r--r--bridges/bridge_softmix.c74
-rw-r--r--channels/chan_alsa.c27
-rw-r--r--channels/chan_bridge_media.c14
-rw-r--r--channels/chan_console.c35
-rw-r--r--channels/chan_dahdi.c129
-rw-r--r--channels/chan_iax2.c505
-rw-r--r--channels/chan_mgcp.c378
-rw-r--r--channels/chan_misdn.c55
-rw-r--r--channels/chan_motif.c185
-rw-r--r--channels/chan_multicast_rtp.c36
-rw-r--r--channels/chan_nbs.c56
-rw-r--r--channels/chan_oss.c23
-rw-r--r--channels/chan_phone.c208
-rw-r--r--channels/chan_pjsip.c83
-rw-r--r--channels/chan_sip.c791
-rw-r--r--channels/chan_skinny.c362
-rw-r--r--channels/chan_unistim.c165
-rw-r--r--channels/chan_vpb.cc97
-rw-r--r--channels/dahdi/bridge_native_dahdi.c13
-rw-r--r--channels/iax2/codec_pref.c333
-rw-r--r--channels/iax2/format_compatibility.c73
-rw-r--r--channels/iax2/include/codec_pref.h123
-rw-r--r--channels/iax2/include/format_compatibility.h55
-rw-r--r--channels/iax2/parser.c15
-rw-r--r--channels/iax2/provision.c9
-rw-r--r--channels/pjsip/dialplan_functions.c46
-rw-r--r--channels/sip/include/sip.h2
-rw-r--r--codecs/codec_a_mu.c40
-rw-r--r--codecs/codec_adpcm.c48
-rw-r--r--codecs/codec_alaw.c49
-rw-r--r--codecs/codec_dahdi.c399
-rw-r--r--codecs/codec_g722.c62
-rw-r--r--codecs/codec_g726.c62
-rw-r--r--codecs/codec_gsm.c53
-rw-r--r--codecs/codec_ilbc.c44
-rw-r--r--codecs/codec_lpc10.c50
-rw-r--r--codecs/codec_resample.c76
-rw-r--r--codecs/codec_speex.c103
-rw-r--r--codecs/codec_ulaw.c77
-rw-r--r--codecs/ex_adpcm.h3
-rw-r--r--codecs/ex_alaw.h2
-rw-r--r--codecs/ex_g722.h2
-rw-r--r--codecs/ex_g726.h2
-rw-r--r--codecs/ex_gsm.h3
-rw-r--r--codecs/ex_ilbc.h3
-rw-r--r--codecs/ex_lpc10.h2
-rw-r--r--codecs/ex_speex.h5
-rw-r--r--codecs/ex_ulaw.h3
-rw-r--r--formats/format_g719.c15
-rw-r--r--formats/format_g723.c14
-rw-r--r--formats/format_g726.c15
-rw-r--r--formats/format_g729.c15
-rw-r--r--formats/format_gsm.c14
-rw-r--r--formats/format_h263.c26
-rw-r--r--formats/format_h264.c26
-rw-r--r--formats/format_ilbc.c14
-rw-r--r--formats/format_jpeg.c13
-rw-r--r--formats/format_ogg_vorbis.c16
-rw-r--r--formats/format_pcm.c31
-rw-r--r--formats/format_siren14.c14
-rw-r--r--formats/format_siren7.c14
-rw-r--r--formats/format_sln.c78
-rw-r--r--formats/format_vox.c14
-rw-r--r--formats/format_wav.c26
-rw-r--r--formats/format_wav_gsm.c15
-rw-r--r--funcs/func_channel.c24
-rw-r--r--funcs/func_frame_trace.c4
-rw-r--r--funcs/func_pitchshift.c6
-rw-r--r--funcs/func_speex.c4
-rw-r--r--funcs/func_talkdetect.c2
-rw-r--r--include/asterisk/_private.h10
-rw-r--r--include/asterisk/abstract_jb.h2
-rw-r--r--include/asterisk/audiohook.h2
-rw-r--r--include/asterisk/bridge_channel.h4
-rw-r--r--include/asterisk/callerid.h4
-rw-r--r--include/asterisk/channel.h34
-rw-r--r--include/asterisk/codec.h186
-rw-r--r--include/asterisk/config_options.h9
-rw-r--r--include/asterisk/data.h1
-rw-r--r--include/asterisk/file.h2
-rw-r--r--include/asterisk/format.h553
-rw-r--r--include/asterisk/format_cache.h301
-rw-r--r--include/asterisk/format_cap.h377
-rw-r--r--include/asterisk/format_compatibility.h129
-rw-r--r--include/asterisk/format_pref.h117
-rw-r--r--include/asterisk/frame.h80
-rw-r--r--include/asterisk/image.h2
-rw-r--r--include/asterisk/mod_format.h10
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--include/asterisk/res_pjsip_session.h2
-rw-r--r--include/asterisk/rtp_engine.h127
-rw-r--r--include/asterisk/slin.h6
-rw-r--r--include/asterisk/slinfactory.h6
-rw-r--r--include/asterisk/smoother.h89
-rw-r--r--include/asterisk/speech.h2
-rw-r--r--include/asterisk/translate.h19
-rw-r--r--include/asterisk/vector.h104
-rw-r--r--main/abstract_jb.c21
-rw-r--r--main/app.c37
-rw-r--r--main/asterisk.c24
-rw-r--r--main/audiohook.c67
-rw-r--r--main/bridge.c50
-rw-r--r--main/bridge_basic.c11
-rw-r--r--main/bridge_channel.c26
-rw-r--r--main/callerid.c1
-rw-r--r--main/ccss.c10
-rw-r--r--main/channel.c434
-rw-r--r--main/channel_internal_api.c48
-rw-r--r--main/cli.c8
-rw-r--r--main/codec.c381
-rw-r--r--main/codec_builtin.c845
-rw-r--r--main/config_options.c6
-rw-r--r--main/core_local.c13
-rw-r--r--main/core_unreal.c41
-rw-r--r--main/data.c82
-rw-r--r--main/dial.c10
-rw-r--r--main/dsp.c86
-rw-r--r--main/file.c123
-rw-r--r--main/format.c1473
-rw-r--r--main/format_cache.c519
-rw-r--r--main/format_cap.c937
-rw-r--r--main/format_compatibility.c274
-rw-r--r--main/format_pref.c380
-rw-r--r--main/frame.c583
-rw-r--r--main/image.c4
-rw-r--r--main/indications.c17
-rw-r--r--main/manager.c22
-rw-r--r--main/media_index.c17
-rw-r--r--main/rtp_engine.c687
-rw-r--r--main/slinfactory.c34
-rw-r--r--main/smoother.c227
-rw-r--r--main/sorcery.c8
-rw-r--r--main/sounds_index.c16
-rw-r--r--main/translate.c775
-rw-r--r--main/utils.c4
-rw-r--r--pbx/pbx_spool.c11
-rw-r--r--res/ari/resource_bridges.c12
-rw-r--r--res/ari/resource_channels.c6
-rw-r--r--res/ari/resource_sounds.c19
-rw-r--r--res/parking/parking_applications.c8
-rw-r--r--res/res_adsi.c54
-rw-r--r--res/res_agi.c34
-rw-r--r--res/res_calendar.c21
-rw-r--r--res/res_clioriginate.c15
-rw-r--r--res/res_fax.c131
-rw-r--r--res/res_fax_spandsp.c21
-rw-r--r--res/res_format_attr_celt.c205
-rw-r--r--res/res_format_attr_h263.c349
-rw-r--r--res/res_format_attr_h264.c400
-rw-r--r--res/res_format_attr_opus.c256
-rw-r--r--res/res_format_attr_silk.c228
-rw-r--r--res/res_musiconhold.c88
-rw-r--r--res/res_pjsip/pjsip_configuration.c10
-rw-r--r--res/res_pjsip_sdp_rtp.c245
-rw-r--r--res/res_pjsip_session.c24
-rw-r--r--res/res_rtp_asterisk.c187
-rw-r--r--res/res_rtp_multicast.c8
-rw-r--r--res/res_speech.c36
-rw-r--r--res/res_stasis.c8
-rw-r--r--res/res_stasis_snoop.c31
-rw-r--r--tests/test_abstract_jb.c3
-rw-r--r--tests/test_cel.c11
-rw-r--r--tests/test_config.c35
-rw-r--r--tests/test_core_codec.c369
-rw-r--r--tests/test_core_format.c975
-rw-r--r--tests/test_format_api.c859
-rw-r--r--tests/test_format_cache.c281
-rw-r--r--tests/test_format_cap.c1479
-rw-r--r--tests/test_voicemail_api.c11
205 files changed, 13946 insertions, 9541 deletions
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 84b3e8d5a..535782a86 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -208,6 +208,32 @@ chan_sip:
progress indications into a 180 Ringing (if a 180 has not yet been
transmitted) if 'progressinband=never'.
+ - The codec preference order in an SDP during an offer is slightly different
+ than previous releases. Prior to Asterisk 13, the preference order of
+ codecs used to be:
+ (1) Our preferred codec
+ (2) Our configured codecs
+ (3) Any non-audio joint codecs
+
+ One of the ways the new media format architecture in Asterisk 13 improves
+ performance is by reference counting formats, such that they can be reused
+ in many places without additional allocation. To not require a large
+ amount of locking, an instance of a format is immutable by convention.
+ This works well except for formats with attributes. Since a media format
+ with an attribute is a different object than the same format without an
+ attribute, we have to carry over the formats with attributes from an
+ inbound offer so that the correct attributes are offered in an outgoing
+ INVITE request. This requires some subtle tweaks to the preference order
+ to ensure that the media format with attributes is offered to a remote
+ peer, as opposed to the same media format (but without attributes) that
+ may be stored in the peer object.
+
+ All of this means that our offer offer list will now be:
+ (1) Our preferred codec
+ (2) Any joint codecs offered by the inbound offer
+ (3) All other codecs that are not the preferred codec and not a joint
+ codec offered by the inbound offer
+
CLI commands:
- "core show settings" now lists the current console verbosity in addition
to the root console verbosity.
diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c
index a7cbc00e2..75db0fad8 100644
--- a/addons/chan_mobile.c
+++ b/addons/chan_mobile.c
@@ -73,16 +73,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/io.h"
+#include "asterisk/smoother.h"
+#include "asterisk/format_cache.h"
#define MBL_CONFIG "chan_mobile.conf"
#define MBL_CONFIG_OLD "mobile.conf"
#define DEVICE_FRAME_SIZE 48
-#define DEVICE_FRAME_FORMAT AST_FORMAT_SLINEAR
+#define DEVICE_FRAME_FORMAT ast_format_slin
#define CHANNEL_FRAME_SIZE 320
-static struct ast_format prefformat;
-
static int discovery_interval = 60; /* The device discovery interval, default 60 seconds. */
static pthread_t discovery_thread = AST_PTHREADT_NULL; /* The discovery thread */
static sdp_session_t *sdp_session;
@@ -840,7 +840,6 @@ e_return:
static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num,
const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
-
struct ast_channel *chn;
pvt->answered = 0;
@@ -862,11 +861,11 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num
}
ast_channel_tech_set(chn, &mbl_tech);
- ast_format_cap_add(ast_channel_nativeformats(chn), &prefformat);
- ast_format_copy(ast_channel_rawreadformat(chn), &prefformat);
- ast_format_copy(ast_channel_rawwriteformat(chn), &prefformat);
- ast_format_copy(ast_channel_writeformat(chn), &prefformat);
- ast_format_copy(ast_channel_readformat(chn), &prefformat);
+ ast_channel_nativeformats_set(chn, mbl_tech.capabilities);
+ ast_channel_set_rawreadformat(chn, DEVICE_FRAME_FORMAT);
+ ast_channel_set_rawwriteformat(chn, DEVICE_FRAME_FORMAT);
+ ast_channel_set_writeformat(chn, DEVICE_FRAME_FORMAT);
+ ast_channel_set_readformat(chn, DEVICE_FRAME_FORMAT);
ast_channel_tech_pvt_set(chn, pvt);
if (state == AST_STATE_RING)
@@ -902,9 +901,9 @@ static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *
return NULL;
}
- if (!(ast_format_cap_iscompatible(cap, &prefformat))) {
- char tmp[256];
- ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ if (ast_format_cap_iscompatible_format(cap, DEVICE_FRAME_FORMAT) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
*cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED;
return NULL;
}
@@ -1116,7 +1115,7 @@ static struct ast_frame *mbl_read(struct ast_channel *ast)
memset(&pvt->fr, 0x00, sizeof(struct ast_frame));
pvt->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&pvt->fr.subclass.format, DEVICE_FRAME_FORMAT, 0);
+ pvt->fr.subclass.format = DEVICE_FRAME_FORMAT;
pvt->fr.src = "Mobile";
pvt->fr.offset = AST_FRIENDLY_OFFSET;
pvt->fr.mallocd = 0;
@@ -4697,7 +4696,8 @@ static int unload_module(void)
if (sdp_session)
sdp_close(sdp_session);
- mbl_tech.capabilities = ast_format_cap_destroy(mbl_tech.capabilities);
+ ao2_ref(mbl_tech.capabilities, -1);
+ mbl_tech.capabilities = NULL;
return 0;
}
@@ -4706,11 +4706,11 @@ static int load_module(void)
int dev_id, s;
- if (!(mbl_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(mbl_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_set(&prefformat, DEVICE_FRAME_FORMAT, 0);
- ast_format_cap_add(mbl_tech.capabilities, &prefformat);
+
+ ast_format_cap_append(mbl_tech.capabilities, DEVICE_FRAME_FORMAT, 0);
/* Check if we have Bluetooth, no point loading otherwise... */
dev_id = hci_get_route(NULL);
s = hci_open_dev(dev_id);
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 8f1ae76bc..f02002f60 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -92,8 +92,6 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance
static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *result);
void setup_rtp_remote(ooCallData *call, const char *remoteIp, int remotePort);
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref);
-
struct ooh323_peer *find_friend(const char *name, int port);
@@ -174,10 +172,9 @@ static struct ooh323_pvt {
char callee_url[AST_MAX_EXTENSION];
int port;
- struct ast_format readformat; /* negotiated read format */
- struct ast_format writeformat; /* negotiated write format */
+ struct ast_format *readformat; /* negotiated read format */
+ struct ast_format *writeformat; /* negotiated write format */
struct ast_format_cap *cap;
- struct ast_codec_pref prefs;
int dtmfmode;
int dtmfcodec;
char exten[AST_MAX_EXTENSION]; /* Requested extension */
@@ -212,7 +209,6 @@ struct ooh323_user{
char accountcode[20];
int amaflags;
struct ast_format_cap *cap;
- struct ast_codec_pref prefs;
int dtmfmode;
int dtmfcodec;
int faxdetect;
@@ -239,7 +235,6 @@ struct ooh323_peer{
unsigned outgoinglimit;
unsigned outUse;
struct ast_format_cap *cap;
- struct ast_codec_pref prefs;
char accountcode[20];
int amaflags;
int dtmfmode;
@@ -307,7 +302,6 @@ int v6mode = 0;
static char gCallerID[AST_MAX_EXTENSION] = "";
static struct ooAliases *gAliasList;
static struct ast_format_cap *gCap;
-static struct ast_codec_pref gPrefs;
static int gDTMFMode = H323_DTMF_RFC2833;
static int gDTMFCodec = 101;
static int gFAXdetect = FAXDETECT_CNG;
@@ -366,15 +360,17 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
const char *host, struct ast_format_cap *cap,
const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps = NULL;
struct ast_channel *ch = NULL;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt = NULL;
int features = 0;
if (gH323Debug) {
ast_verb(0, "--- ooh323_new - %s\n", host);
}
- ast_format_clear(&tmpfmt);
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+
/* Don't hold a h323 pvt lock while we allocate a channel */
ast_mutex_unlock(&i->lock);
ast_mutex_lock(&ooh323c_cn_lock);
@@ -386,17 +382,25 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_mutex_lock(&i->lock);
- if (ch) {
+ if (ch && caps) {
ast_channel_tech_set(ch, &ooh323_tech);
- if (cap)
- ast_best_codec(cap, &tmpfmt);
- if (!tmpfmt.id)
- ast_codec_pref_index(&i->prefs, 0, &tmpfmt);
+ if (cap) {
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ }
+ if (!tmpfmt) {
+ tmpfmt = ast_format_cap_get_format(i->cap, 0);
+ }
+
+ ast_format_cap_append(caps, tmpfmt, 0);
+ ast_channel_nativeformats_set(ch, caps);
+ ao2_ref(caps, -1);
- ast_format_cap_add(ast_channel_nativeformats(ch), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(ch), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(ch), &tmpfmt);
+ ast_channel_set_rawwriteformat(ch, tmpfmt);
+ ast_channel_set_rawreadformat(ch, tmpfmt);
+ ast_set_write_format(ch, tmpfmt);
+ ast_set_read_format(ch, tmpfmt);
+ ao2_ref(tmpfmt, -1);
ast_jb_configure(ch, &global_jbconf);
@@ -404,8 +408,6 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_channel_rings_set(ch, 1);
ast_channel_adsicpe_set(ch, AST_ADSI_UNAVAILABLE);
- ast_set_write_format(ch, &tmpfmt);
- ast_set_read_format(ch, &tmpfmt);
ast_channel_tech_pvt_set(ch, i);
i->owner = ch;
ast_module_ref(myself);
@@ -485,8 +487,10 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_publish_channel_state(ch);
}
- } else
+ } else {
+ ao2_cleanup(caps);
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ }
if(ch) ast_channel_unlock(ch);
@@ -512,7 +516,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
return NULL;
}
- if (!(pvt->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(pvt->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_free(pvt);
ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
return NULL;
@@ -546,8 +550,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode));
pvt->amaflags = gAMAFLAGS;
- ast_format_cap_copy(pvt->cap, gCap);
- memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs));
+ ast_format_cap_append_from_cap(pvt->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
pvt->aniasdni = gANIasDNI;
@@ -573,21 +576,21 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_channel *chan = NULL;
struct ooh323_pvt *p = NULL;
struct ooh323_peer *peer = NULL;
char *dest = NULL;
char *ext = NULL;
char tmp[256];
- char formats[FORMAT_STRING_SIZE];
int port = 0;
- if (gH323Debug)
- ast_verb(0, "--- ooh323_request - data %s format %s\n", data,
- ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
+ if (gH323Debug) {
+ ast_verb(0, "--- ooh323_request - data %s format %s\n", data, ast_format_cap_get_names(cap, &codec_buf));
+ }
- if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
+ if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
@@ -651,8 +654,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
if (ext)
ast_copy_string(p->exten, ext, sizeof(p->exten));
- ast_format_cap_copy(p->cap, peer->cap);
- memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref));
+ ast_format_cap_append_from_cap(p->cap, peer->cap, AST_MEDIA_TYPE_UNKNOWN);
p->g729onlyA = peer->g729onlyA;
p->dtmfmode |= peer->dtmfmode;
p->dtmfcodec = peer->dtmfcodec;
@@ -697,7 +699,7 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
p->t38support = gT38Support;
p->rtptimeout = gRTPTimeout;
p->nat = gNat;
- ast_format_cap_copy(p->cap, gCap);
+ ast_format_cap_append_from_cap(p->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
p->rtdrinterval = gRTDRInterval;
p->rtdrcount = gRTDRCount;
p->faststart = gFastStart;
@@ -705,7 +707,6 @@ static struct ast_channel *ooh323_request(const char *type, struct ast_format_ca
p->directrtp = gDirectRTP;
p->earlydirect = gEarlyDirect;
- memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
p->username = strdup(dest);
p->host = strdup(dest);
@@ -1164,7 +1165,6 @@ static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
{
struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
int res = 0;
- char buf[256];
if (p) {
ast_mutex_lock(&p->lock);
@@ -1190,16 +1190,17 @@ static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
}
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
- if (!(ast_format_cap_is_empty(ast_channel_nativeformats(ast)))) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cap_count(ast_channel_nativeformats(ast))) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&f->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(f->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
- ast_set_write_format(ast, &f->subclass.format);
+ ast_set_write_format(ast, f->subclass.format);
} else {
/* ast_set_write_format(ast, f->subclass);
ast->nativeformats = f->subclass; */
@@ -1508,11 +1509,10 @@ static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan
void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes)
{
struct ooh323_pvt *p = NULL;
- char formats[FORMAT_STRING_SIZE];
if (gH323Debug)
ast_verb(0, "--- ooh323_update_writeformat %s/%d\n",
- ast_getformatname(fmt), txframes);
+ ast_format_get_name(fmt), txframes);
p = find_call(call);
if (!p) {
@@ -1522,9 +1522,17 @@ void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txfra
ast_mutex_lock(&p->lock);
- ast_format_copy(&(p->writeformat), fmt);
+ ao2_replace(p->writeformat, fmt);
if (p->owner) {
+ struct ast_format_cap *caps;
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
+ return;
+ }
+
while (p->owner && ast_channel_trylock(p->owner)) {
ast_debug(1,"Failed to grab lock, trying again\n");
DEADLOCK_AVOIDANCE(&p->lock);
@@ -1532,15 +1540,16 @@ void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txfra
if (!p->owner) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
+ ao2_ref(caps, -1);
return;
}
- if (gH323Debug)
- ast_verb(0, "Writeformat before update %s/%s\n",
- ast_getformatname(ast_channel_writeformat(p->owner)),
- ast_getformatname_multiple(formats, sizeof(formats), ast_channel_nativeformats(p->owner)));
- if (txframes)
- ast_codec_pref_setsize(&p->prefs, fmt, txframes);
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ if (gH323Debug) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_verb(0, "Writeformat before update %s/%s\n",
+ ast_format_get_name(ast_channel_writeformat(p->owner)),
+ ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &codec_buf));
+ }
+
if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
@@ -1550,7 +1559,12 @@ void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txfra
p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
}
- ast_format_cap_set(ast_channel_nativeformats(p->owner), fmt);
+ if (txframes) {
+ ast_format_cap_set_framing(caps, txframes);
+ }
+ ast_format_cap_append(caps, fmt, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_channel_unlock(p->owner);
@@ -1570,7 +1584,7 @@ void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
if (gH323Debug)
ast_verb(0, "--- ooh323_update_readformat %s\n",
- ast_getformatname(fmt));
+ ast_format_get_name(fmt));
p = find_call(call);
if (!p) {
@@ -1580,9 +1594,17 @@ void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
ast_mutex_lock(&p->lock);
- ast_format_copy(&(p->readformat), fmt);
+ ao2_replace(p->readformat, fmt);
if (p->owner) {
+ struct ast_format_cap *caps;
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
+ return;
+ }
+
while (p->owner && ast_channel_trylock(p->owner)) {
ast_debug(1,"Failed to grab lock, trying again\n");
DEADLOCK_AVOIDANCE(&p->lock);
@@ -1590,14 +1612,18 @@ void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
if (!p->owner) {
ast_mutex_unlock(&p->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
+ ao2_ref(caps, -1);
return;
}
- if (gH323Debug)
- ast_verb(0, "Readformat before update %s\n",
- ast_getformatname(ast_channel_readformat(p->owner)));
- ast_format_cap_set(ast_channel_nativeformats(p->owner), fmt);
- ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
+ if (gH323Debug) {
+ ast_verb(0, "Readformat before update %s\n",
+ ast_format_get_name(ast_channel_readformat(p->owner)));
+ }
+ ast_format_cap_append(caps, fmt, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_channel_unlock(p->owner);
} else
ast_log(LOG_ERROR, "No owner found\n");
@@ -1854,9 +1880,8 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
ast_copy_string(p->context, user->context, sizeof(p->context));
ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
p->amaflags = user->amaflags;
- ast_format_cap_copy(p->cap, user->cap);
+ ast_format_cap_append_from_cap(p->cap, user->cap, AST_MEDIA_TYPE_UNKNOWN);
p->g729onlyA = user->g729onlyA;
- memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
p->dtmfmode |= user->dtmfmode;
p->dtmfcodec = user->dtmfcodec;
p->faxdetect = user->faxdetect;
@@ -1914,7 +1939,7 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
}
}
- ooh323c_set_capability_for_call(call, &p->prefs, p->cap, p->dtmfmode, p->dtmfcodec,
+ ooh323c_set_capability_for_call(call, p->cap, p->dtmfmode, p->dtmfcodec,
p->t38support, p->g729onlyA);
/* Incoming call */
c = ooh323_new(p, AST_STATE_RING, p->username, 0, NULL, NULL);
@@ -2088,13 +2113,14 @@ int onNewCallCreated(ooCallData *call)
}
if (gH323Debug) {
- char prefsBuf[256];
- ast_codec_pref_string(&p->prefs, prefsBuf, sizeof(prefsBuf));
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
ast_verb(0, " Outgoing call %s(%s) - Codec prefs - %s\n",
- p->username?p->username:"NULL", call->callToken, prefsBuf);
+ p->username?p->username:"NULL", call->callToken,
+ ast_format_cap_get_names(p->cap, &codec_buf));
}
- ooh323c_set_capability_for_call(call, &p->prefs, p->cap,
+ ooh323c_set_capability_for_call(call, p->cap,
p->dtmfmode, p->dtmfcodec, p->t38support, p->g729onlyA);
configure_local_rtp(p, call);
@@ -2284,7 +2310,7 @@ void ooh323_delete_peer(struct ooh323_peer *peer)
if(peer->url) free(peer->url);
if(peer->e164) free(peer->e164);
- peer->cap = ast_format_cap_destroy(peer->cap);
+ ao2_cleanup(peer->cap);
free(peer);
}
@@ -2311,8 +2337,7 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
}
ast_mutex_init(&user->lock);
ast_copy_string(user->name, name, sizeof(user->name));
- ast_format_cap_copy(user->cap, gCap);
- memcpy(&user->prefs, &gPrefs, sizeof(user->prefs));
+ ast_format_cap_append_from_cap(user->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
user->rtptimeout = gRTPTimeout;
user->nat = gNat;
user->dtmfmode = gDTMFMode;
@@ -2367,15 +2392,13 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
sizeof(user->rtpmaskstr));
} else user->rtpmask = NULL;
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&user->prefs,
- user->cap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(user->cap, v->value, 0);
} else if (!strcasecmp(v->name, "allow")) {
const char* tcodecs = v->value;
if (!strcasecmp(v->value, "all")) {
tcodecs = "ulaw,alaw,g729,g723,gsm";
}
- ast_parse_allow_disallow(&user->prefs,
- user->cap, tcodecs, 1);
+ ast_format_cap_update_by_allow_disallow(user->cap, tcodecs, 1);
} else if (!strcasecmp(v->name, "amaflags")) {
user->amaflags = ast_channel_string2amaflag(v->value);
} else if (!strcasecmp(v->name, "ip") || !strcasecmp(v->name, "host")) {
@@ -2461,8 +2484,7 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v,
}
ast_mutex_init(&peer->lock);
ast_copy_string(peer->name, name, sizeof(peer->name));
- ast_format_cap_copy(peer->cap, gCap);
- memcpy(&peer->prefs, &gPrefs, sizeof(peer->prefs));
+ ast_format_cap_append_from_cap(peer->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
peer->rtptimeout = gRTPTimeout;
peer->nat = gNat;
ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode));
@@ -2565,15 +2587,13 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v,
sizeof(peer->rtpmaskstr));
} else peer->rtpmask = NULL;
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&peer->prefs, peer->cap,
- v->value, 0);
+ ast_format_cap_update_by_allow_disallow(peer->cap, v->value, 0);
} else if (!strcasecmp(v->name, "allow")) {
const char* tcodecs = v->value;
if (!strcasecmp(v->value, "all")) {
tcodecs = "ulaw,alaw,g729,g723,gsm";
}
- ast_parse_allow_disallow(&peer->prefs, peer->cap,
- tcodecs, 1);
+ ast_format_cap_update_by_allow_disallow(peer->cap, tcodecs, 1);
} else if (!strcasecmp(v->name, "amaflags")) {
peer->amaflags = ast_channel_string2amaflag(v->value);
} else if (!strcasecmp(v->name, "roundtrip")) {
@@ -2754,7 +2774,6 @@ int reload_config(int reload)
struct ooh323_peer *peer = NULL;
char *cat;
const char *utype;
- struct ast_format tmpfmt;
if (gH323Debug)
ast_verb(0, "--- reload_config\n");
@@ -2790,8 +2809,8 @@ int reload_config(int reload)
gPort = 1720;
gIP[0] = '\0';
strcpy(gCallerID, DEFAULT_H323ID);
- ast_format_cap_set(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
- memset(&gPrefs, 0, sizeof(struct ast_codec_pref));
+ ast_format_cap_remove_by_type(gCap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(gCap, ast_format_ulaw, 0);
gDTMFMode = H323_DTMF_RFC2833;
gDTMFCodec = 101;
gFAXdetect = FAXDETECT_CNG;
@@ -2992,13 +3011,13 @@ int reload_config(int reload)
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode));
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&gPrefs, gCap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(gCap, v->value, 0);
} else if (!strcasecmp(v->name, "allow")) {
const char* tcodecs = v->value;
if (!strcasecmp(v->value, "all")) {
tcodecs = "ulaw,alaw,g729,g723,gsm";
}
- ast_parse_allow_disallow(&gPrefs, gCap, tcodecs, 1);
+ ast_format_cap_update_by_allow_disallow(gCap, tcodecs, 1);
} else if (!strcasecmp(v->name, "dtmfmode")) {
if (!strcasecmp(v->value, "inband"))
gDTMFMode = H323_DTMF_INBAND;
@@ -3150,9 +3169,6 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc
peer->h245tunneling?"yes":"no");
ast_cli(a->fd, "%-15s%s\n", "DirectRTP", peer->directrtp ? "yes" : "no");
ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", peer->earlydirect ? "yes" : "no");
- ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
- print_codec_to_cli(a->fd, &peer->prefs);
- ast_cli(a->fd, ")\n");
ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
if (peer->dtmfmode & H323_DTMF_CISCO) {
ast_cli(a->fd, "%s\n", "cisco");
@@ -3214,7 +3230,7 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc
static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ooh323_peer *prev = NULL, *peer = NULL;
- char formats[FORMAT_STRING_SIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
char ip_port[30];
#define FORMAT "%-15.15s %-15.15s %-23.23s %-s\n"
@@ -3239,10 +3255,10 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, stru
while (peer) {
ast_mutex_lock(&peer->lock);
snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
- ast_cli(a->fd, FORMAT, peer->name,
+ ast_cli(a->fd, FORMAT, peer->name,
peer->accountcode,
ip_port,
- ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,peer->cap));
+ ast_format_cap_get_names(peer->cap, &codec_buf));
prev = peer;
peer = peer->next;
ast_mutex_unlock(&prev->lock);
@@ -3253,24 +3269,6 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, stru
return CLI_SUCCESS;
}
-/*! \brief Print codec list from preference to CLI/manager */
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
-{
- int x;
- struct ast_format tmpfmt;
- for (x = 0; x < 32; x++) {
- ast_codec_pref_index(pref, x, &tmpfmt);
- if (!tmpfmt.id)
- break;
- ast_cli(fd, "%s", ast_getformatname(&tmpfmt));
- ast_cli(fd, ":%d", pref->framing[x]);
- if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt))
- ast_cli(fd, ",");
- }
- if (!x)
- ast_cli(fd, "none");
-}
-
static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ooh323_user *prev = NULL, *user = NULL;
@@ -3309,9 +3307,6 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc
user->h245tunneling?"yes":"no");
ast_cli(a->fd, "%-15s%s\n", "DirectRTP", user->directrtp ? "yes" : "no");
ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", user->earlydirect ? "yes" : "no");
- ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
- print_codec_to_cli(a->fd, &user->prefs);
- ast_cli(a->fd, ")\n");
ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
if (user->dtmfmode & H323_DTMF_CISCO) {
ast_cli(a->fd, "%s\n", "cisco");
@@ -3374,7 +3369,7 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc
static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ooh323_user *prev = NULL, *user = NULL;
- char formats[FORMAT_STRING_SIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
#define FORMAT1 "%-15.15s %-15.15s %-15.15s %-s\n"
switch (cmd) {
@@ -3401,7 +3396,7 @@ static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, stru
ast_mutex_lock(&user->lock);
ast_cli(a->fd, FORMAT1, user->name,
user->accountcode, user->context,
- ast_getformatname_multiple(formats, FORMAT_STRING_SIZE, user->cap));
+ ast_format_cap_get_names(user->cap, &codec_buf));
prev = user;
user = user->next;
ast_mutex_unlock(&prev->lock);
@@ -3508,6 +3503,7 @@ static char *handle_cli_ooh323_show_gk(struct ast_cli_entry *e, int cmd, struct
static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char value[FORMAT_STRING_SIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
ooAliases *pAlias = NULL, *pAliasNext = NULL;;
switch (cmd) {
@@ -3556,7 +3552,7 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str
ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile);
ast_cli(a->fd, "%-20s%s\n", "Context:", gContext);
ast_cli(a->fd, "%-20s%s\n", "Capability:",
- ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap));
+ ast_format_cap_get_names(gCap, &codec_buf));
ast_cli(a->fd, "%-20s", "DTMF Mode: ");
if (gDTMFMode & H323_DTMF_CISCO) {
ast_cli(a->fd, "%s\n", "cisco");
@@ -3737,7 +3733,6 @@ static int load_module(void)
{
struct ooAliases * pNewAlias = NULL;
struct ooh323_peer *peer = NULL;
- struct ast_format tmpfmt;
OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
OOH323CALLBACKS h323Callbacks = {
@@ -3753,14 +3748,16 @@ static int load_module(void)
.onModeChanged = onModeChanged,
.onMediaChanged = (cb_OnMediaChanged) setup_rtp_remote,
};
- if (!(gCap = ast_format_cap_alloc(0))) {
+ if (!(gCap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- if (!(ooh323_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(ooh323_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ ao2_ref(gCap, -1);
+ gCap = NULL;
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add_all(ooh323_tech.capabilities);
+ ast_format_cap_append(gCap, ast_format_ulaw, 0);
+ ast_format_cap_append_by_type(ooh323_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
myself = ast_module_info->self;
@@ -3789,12 +3786,20 @@ static int load_module(void)
if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) {
ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-"
"OOH323 Disabled\n");
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure we can register our OOH323 channel type */
if (ast_channel_register(&ooh323_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return AST_MODULE_LOAD_FAILURE;
}
ast_rtp_glue_register(&ooh323_rtp);
@@ -3876,8 +3881,12 @@ static int load_module(void)
ooH323EpSetH323Callbacks(h323Callbacks);
/* Add endpoint capabilities */
- if (ooh323c_set_capability(&gPrefs, gCap, gDTMFMode, gDTMFCodec) < 0) {
+ if (ooh323c_set_capability(gCap, gDTMFMode, gDTMFCodec) < 0) {
ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 1;
}
@@ -3887,6 +3896,10 @@ static int load_module(void)
"OOH323 DISABLED\n");
ooH323EpDestroy();
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 1;
}
@@ -3894,6 +3907,10 @@ static int load_module(void)
ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. "
"OOH323 DISABLED\n");
ooH323EpDestroy();
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 1;
}
/* And start the monitor for the first time */
@@ -4142,7 +4159,9 @@ int ooh323_destroy(struct ooh323_pvt *p)
ast_mutex_unlock(&cur->lock);
ast_mutex_destroy(&cur->lock);
- cur->cap = ast_format_cap_destroy(cur->cap);
+ ao2_cleanup(cur->writeformat);
+ ao2_cleanup(cur->readformat);
+ ao2_cleanup(cur->cap);
ast_free(cur);
}
@@ -4207,7 +4226,7 @@ int delete_users()
free(prev->rtpmask);
}
}
- prev->cap = ast_format_cap_destroy(prev->cap);
+ ao2_cleanup(prev->cap);
free(prev);
if (cur == userl.users) {
break;
@@ -4335,8 +4354,10 @@ static int unload_module(void)
ast_verb(0, "+++ ooh323 unload_module \n");
}
- gCap = ast_format_cap_destroy(gCap);
- ooh323_tech.capabilities = ast_format_cap_destroy(ooh323_tech.capabilities);
+ ao2_ref(gCap, -1);
+ gCap = NULL;
+ ao2_ref(ooh323_tech.capabilities, -1);
+ ooh323_tech.capabilities = NULL;
return 0;
}
@@ -4348,8 +4369,11 @@ static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *re
}
if (p) {
- ast_format_cap_append(result, ast_format_cap_is_empty(ast_channel_nativeformats(chan)) ?
- (ast_format_cap_is_empty(p->cap) ? NULL : p->cap) : ast_channel_nativeformats(chan));
+ if (ast_format_cap_count(ast_channel_nativeformats(chan))) {
+ ast_format_cap_append_from_cap(result, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_UNKNOWN);
+ } else if (ast_format_cap_count(p->cap)) {
+ ast_format_cap_append_from_cap(result, p->cap, AST_MEDIA_TYPE_UNKNOWN);
+ }
}
if (gH323Debug) {
@@ -4423,56 +4447,28 @@ static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, s
return res;
}
-
-int ooh323_update_capPrefsOrderForCall
- (ooCallData *call, struct ast_codec_pref *prefs)
-{
- int i = 0;
- struct ast_format tmpfmt;
-
- ast_codec_pref_index(prefs, i, &tmpfmt);
-
- ooResetCapPrefs(call);
- while (tmpfmt.id) {
- ooAppendCapToCapPrefs(call, ooh323_convertAsteriskCapToH323Cap(&tmpfmt));
- ast_codec_pref_index(prefs, ++i, &tmpfmt);
- }
-
- return 0;
-}
-
-
int ooh323_convertAsteriskCapToH323Cap(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_ULAW:
+ if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return OO_G711ULAW64K;
- case AST_FORMAT_ALAW:
+ } else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return OO_G711ALAW64K;
- case AST_FORMAT_GSM:
+ } else if (ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL) {
return OO_GSMFULLRATE;
-
-#ifdef AST_FORMAT_AMRNB
- case AST_FORMAT_AMRNB:
- return OO_AMRNB;
-#endif
-#ifdef AST_FORMAT_SPEEX
- case AST_FORMAT_SPEEX:
+ } else if (ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL) {
return OO_SPEEX;
-#endif
-
- case AST_FORMAT_G729A:
+ } else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
return OO_G729A;
- case AST_FORMAT_G726:
+ } else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
return OO_G726;
- case AST_FORMAT_G726_AAL2:
+ } else if (ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
return OO_G726AAL2;
- case AST_FORMAT_G723_1:
+ } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
return OO_G7231;
- case AST_FORMAT_H263:
+ } else if (ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
return OO_H263VIDEO;
- default:
- ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_getformatname(format));
+ } else {
+ ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_format_get_name(format));
return -1;
}
}
@@ -4551,9 +4547,6 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
struct ast_sockaddr tmp;
ooMediaInfo mediaInfo;
int x;
- struct ast_format tmpfmt;
-
- ast_format_clear(&tmpfmt);
if (gH323Debug)
ast_verb(0, "--- configure_local_rtp\n");
@@ -4599,7 +4592,10 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
ast_channel_unlock(p->owner);
if (p->rtp) {
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ if (p->cap) {
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp),
+ ast_format_cap_get_framing(p->cap));
+ }
if (p->nat) {
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, 1);
}
@@ -4636,9 +4632,11 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
mediaInfo.lMediaPort = lport;
mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort + 1;
- for (x = 0; ast_codec_pref_index(&p->prefs, x, &tmpfmt); x++) {
+ for (x = 0; x < ast_format_cap_count(p->cap); x++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, x);
+
strcpy(mediaInfo.dir, "transmit");
- mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(&tmpfmt);
+ mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format);
ooAddMediaInfo(call, mediaInfo);
strcpy(mediaInfo.dir, "receive");
ooAddMediaInfo(call, mediaInfo);
@@ -4655,6 +4653,8 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
strcpy(mediaInfo.dir, "receive");
ooAddMediaInfo(call, mediaInfo);
}
+
+ ao2_ref(format, -1);
}
if (p->udptl) {
@@ -4738,7 +4738,7 @@ void setup_rtp_connection(ooCallData *call, const char *remoteIp, int remotePort
ast_sockaddr_set_port(&tmp, remotePort);
ast_rtp_instance_set_remote_address(p->rtp, &tmp);
- if (p->writeformat.id == AST_FORMAT_G726_AAL2) {
+ if (ast_format_cmp(p->writeformat, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, 2,
"audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
}
@@ -4955,15 +4955,24 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p)
if (f && p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) {
/* We already hold the channel lock */
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(p->owner), &f->subclass.format))) {
- ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(p->owner), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(p->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, voice format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
}
if (((p->dtmfmode & H323_DTMF_INBAND) || (p->faxdetect & FAXDETECT_CNG)) && p->vad &&
- (f->subclass.format.id == AST_FORMAT_SLINEAR || f->subclass.format.id == AST_FORMAT_ALAW ||
- f->subclass.format.id == AST_FORMAT_ULAW)) {
+ ((ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(f->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL))) {
dfr = ast_frdup(f);
dfr = ast_dsp_process(p->owner, p->vad, dfr);
}
diff --git a/addons/chan_ooh323.h b/addons/chan_ooh323.h
index 689adced2..89caaff63 100644
--- a/addons/chan_ooh323.h
+++ b/addons/chan_ooh323.h
@@ -65,6 +65,7 @@
#include "asterisk/format_cap.h"
#include "asterisk/udptl.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
#include "ootypes.h"
#include "ooUtils.h"
@@ -104,9 +105,6 @@ struct ast_frame *ooh323_rtp_read
void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes);
void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt);
-int ooh323_update_capPrefsOrderForCall
- (ooCallData *call, struct ast_codec_pref *prefs);
-
int ooh323_convertAsteriskCapToH323Cap(struct ast_format *format);
int ooh323_convert_hangupcause_asteriskToH323(int cause);
diff --git a/addons/format_mp3.c b/addons/format_mp3.c
index 78fcc28c5..4c98789ab 100644
--- a/addons/format_mp3.c
+++ b/addons/format_mp3.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/mod_format.h"
#include "asterisk/logger.h"
+#include "asterisk/format_cache.h"
#define MP3_BUFLEN 320
#define MP3_SCACHE 16384
@@ -229,10 +230,7 @@ static struct ast_frame *mp3_read(struct ast_filestream *s, int *whennext)
p->offset += p->buflen;
delay = p->buflen / 2;
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_SLINEAR, 0);
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, p->buflen);
- s->fr.mallocd = 0;
s->fr.samples = delay;
*whennext = delay;
return &s->fr;
@@ -318,7 +316,7 @@ static struct ast_format_def mp3_f = {
static int load_module(void)
{
- ast_format_set(&mp3_f.format, AST_FORMAT_SLINEAR, 0);
+ mp3_f.format = ast_format_slin;
InitMP3Constants();
return ast_format_def_register(&mp3_f);
}
diff --git a/addons/ooh323cDriver.c b/addons/ooh323cDriver.c
index dd127a499..bceb07745 100644
--- a/addons/ooh323cDriver.c
+++ b/addons/ooh323cDriver.c
@@ -225,17 +225,17 @@ int ooh323c_stop_stack_thread(void)
}
int ooh323c_set_capability
- (struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec)
+ (struct ast_format_cap *cap, int dtmf, int dtmfcodec)
{
int ret = 0, x;
- struct ast_format tmpfmt;
if (gH323Debug) {
ast_verb(0, "\tAdding capabilities to H323 endpoint\n");
}
- for(x=0; ast_codec_pref_index(prefs, x, &tmpfmt); x++)
+ for(x=0; x<ast_format_cap_count(cap); x++)
{
- if(tmpfmt.id == AST_FORMAT_ULAW)
+ struct ast_format *format = ast_format_cap_get_format(cap, x);
+ if(ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 ulaw capability to H323 endpoint\n");
@@ -246,7 +246,7 @@ int ooh323c_set_capability
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_ALAW)
+ if(ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 alaw capability to H323 endpoint\n");
@@ -258,7 +258,7 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_G729A)
+ if(ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g729A capability to H323 endpoint\n");
@@ -287,7 +287,7 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_G723_1)
+ if(ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g7231 capability to H323 endpoint\n");
@@ -300,7 +300,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_G726)
+ if(ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726 capability to H323 endpoint\n");
@@ -313,7 +313,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_G726_AAL2)
+ if(ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726aal2 capability to H323 endpoint\n");
@@ -326,7 +326,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_H263)
+ if(ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding h263 capability to H323 endpoint\n");
@@ -339,7 +339,7 @@ int ooh323c_set_capability
}
- if(tmpfmt.id == AST_FORMAT_GSM)
+ if(ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding gsm capability to H323 endpoint\n");
@@ -351,24 +351,8 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
-
-#ifdef AST_FORMAT_AMRNB
- if(tmpfmt.id == AST_FORMAT_AMRNB)
- {
- if (gH323Debug) {
- ast_verb(0, "\tAdding amr nb capability to H323 endpoint\n");
- }
- ret = ooH323EpAddAMRNBCapability(OO_AMRNB, 4, 4, FALSE,
- OORXANDTX, &ooh323c_start_receive_channel,
- &ooh323c_start_transmit_channel,
- &ooh323c_stop_receive_channel,
- &ooh323c_stop_transmit_channel);
-
- }
-#endif
-#ifdef AST_FORMAT_SPEEX
- if(tmpfmt.id == AST_FORMAT_SPEEX)
+ if(ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding speex capability to H323 endpoint\n");
@@ -380,8 +364,8 @@ int ooh323c_set_capability
&ooh323c_stop_transmit_channel);
}
-#endif
-
+
+ ao2_ref(format, -1);
}
if(dtmf & H323_DTMF_CISCO)
@@ -397,11 +381,10 @@ int ooh323c_set_capability
}
int ooh323c_set_capability_for_call
- (ooCallData *call, struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
+ (ooCallData *call, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
int t38support, int g729onlyA)
{
int ret = 0, x, txframes;
- struct ast_format tmpfmt;
if (gH323Debug) {
ast_verb(0, "\tAdding capabilities to call(%s, %s)\n", call->callType,
call->callToken);
@@ -423,15 +406,16 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_transmit_datachannel,
0);
- for(x=0; ast_codec_pref_index(prefs, x, &tmpfmt); x++)
+ for(x=0; x<ast_format_cap_count(cap); x++)
{
- if(tmpfmt.id == AST_FORMAT_ULAW)
+ struct ast_format *format = ast_format_cap_get_format(cap, x);
+ if(ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 ulaw capability to call(%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret= ooCallAddG711Capability(call, OO_G711ULAW64K, txframes,
txframes, OORXANDTX,
&ooh323c_start_receive_channel,
@@ -439,13 +423,13 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_ALAW)
+ if(ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g711 alaw capability to call(%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret= ooCallAddG711Capability(call, OO_G711ALAW64K, txframes,
txframes, OORXANDTX,
&ooh323c_start_receive_channel,
@@ -454,13 +438,13 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_transmit_channel);
}
- if(tmpfmt.id == AST_FORMAT_G726)
+ if(ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726 capability to call (%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret = ooCallAddG726Capability(call, OO_G726, txframes, grxframes, FALSE,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
@@ -469,13 +453,13 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_G726_AAL2)
+ if(ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g726aal2 capability to call (%s, %s)\n",
call->callType, call->callToken);
}
- txframes = prefs->framing[x];
+ txframes = ast_format_cap_get_format_framing(cap, format);
ret = ooCallAddG726Capability(call, OO_G726AAL2, txframes, grxframes, FALSE,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
@@ -484,10 +468,10 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_G729A)
+ if(ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL)
{
- txframes = (prefs->framing[x])/10;
+ txframes = (ast_format_cap_get_format_framing(cap, format))/10;
if (gH323Debug) {
ast_verb(0, "\tAdding g729A capability to call(%s, %s)\n",
call->callType, call->callToken);
@@ -520,7 +504,7 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_G723_1)
+ if(ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding g7231 capability to call (%s, %s)\n",
@@ -534,7 +518,7 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_H263)
+ if(ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding h263 capability to call (%s, %s)\n",
@@ -548,7 +532,7 @@ int ooh323c_set_capability_for_call
}
- if(tmpfmt.id == AST_FORMAT_GSM)
+ if(ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding gsm capability to call(%s, %s)\n",
@@ -561,22 +545,7 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_transmit_channel);
}
-#ifdef AST_FORMAT_AMRNB
- if(tmpfmt.id == AST_FORMAT_AMRNB)
- {
- if (gH323Debug) {
- ast_verb(0, "\tAdding AMR capability to call(%s, %s)\n",
- call->callType, call->callToken);
- }
- ret = ooCallAddAMRNBCapability(call, OO_AMRNB, 4, 4, FALSE,
- OORXANDTX, &ooh323c_start_receive_channel,
- &ooh323c_start_transmit_channel,
- &ooh323c_stop_receive_channel,
- &ooh323c_stop_transmit_channel);
- }
-#endif
-#ifdef AST_FORMAT_SPEEX
- if(tmpfmt.id == AST_FORMAT_SPEEX)
+ if(ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL)
{
if (gH323Debug) {
ast_verb(0, "\tAdding Speex capability to call(%s, %s)\n",
@@ -588,7 +557,8 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
-#endif
+
+ ao2_ref(format, -1);
}
return ret;
}
@@ -622,9 +592,9 @@ int ooh323c_set_aliases(ooAliases * aliases)
int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel)
{
- struct ast_format tmpfmt;
- convertH323CapToAsteriskCap(pChannel->chanCap->cap, &tmpfmt);
- if(tmpfmt.id) {
+ struct ast_format *tmpfmt = NULL;
+ tmpfmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
+ if(tmpfmt) {
/* ooh323_set_read_format(call, fmt); */
}else{
ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
@@ -636,19 +606,17 @@ int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel)
int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel)
{
- struct ast_format tmpfmt;
- convertH323CapToAsteriskCap(pChannel->chanCap->cap, &tmpfmt);
- if(tmpfmt.id) {
- switch (tmpfmt.id) {
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- ooh323_set_write_format(call, &tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes);
- break;
- case AST_FORMAT_G729A:
- ooh323_set_write_format(call, &tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10);
- break;
- default:
- ooh323_set_write_format(call, &tmpfmt, 0);
+ struct ast_format *tmpfmt = NULL;
+ tmpfmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
+
+ if (tmpfmt) {
+ if ((ast_format_cmp(tmpfmt, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(tmpfmt, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)) {
+ ooh323_set_write_format(call, tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes);
+ } else if (ast_format_cmp(tmpfmt, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
+ ooh323_set_write_format(call, tmpfmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10);
+ } else {
+ ooh323_set_write_format(call, tmpfmt, 0);
}
}else{
ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
@@ -693,41 +661,32 @@ int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChann
return 1;
}
-struct ast_format *convertH323CapToAsteriskCap(int cap, struct ast_format *result)
+struct ast_format *convertH323CapToAsteriskCap(int cap)
{
- ast_format_clear(result);
switch(cap)
{
case OO_G711ULAW64K:
- return ast_format_set(result, AST_FORMAT_ULAW, 0);
+ return ast_format_ulaw;
case OO_G711ALAW64K:
- return ast_format_set(result, AST_FORMAT_ALAW, 0);
+ return ast_format_alaw;
case OO_GSMFULLRATE:
- return ast_format_set(result, AST_FORMAT_GSM, 0);
-
-#ifdef AST_FORMAT_AMRNB
- case OO_AMRNB:
- return ast_format_set(result, AST_FORMAT_AMRNB, 0);
-#endif
-#ifdef AST_FORMAT_SPEEX
+ return ast_format_gsm;
case OO_SPEEX:
- return ast_format_set(result, AST_FORMAT_SPEEX, 0);
-#endif
-
+ return ast_format_speex;
case OO_G729:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case OO_G729A:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case OO_G729B:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case OO_G7231:
- return ast_format_set(result, AST_FORMAT_G723_1, 0);
+ return ast_format_g723;
case OO_G726:
- return ast_format_set(result, AST_FORMAT_G726, 0);
+ return ast_format_g726;
case OO_G726AAL2:
- return ast_format_set(result, AST_FORMAT_G726_AAL2, 0);
+ return ast_format_g726_aal2;
case OO_H263VIDEO:
- return ast_format_set(result, AST_FORMAT_H263, 0);
+ return ast_format_h263;
default:
ast_debug(1, "Cap %d is not supported by driver yet\n", cap);
return NULL;
diff --git a/addons/ooh323cDriver.h b/addons/ooh323cDriver.h
index af03eeaea..98198019a 100644
--- a/addons/ooh323cDriver.h
+++ b/addons/ooh323cDriver.h
@@ -37,9 +37,9 @@ int ooh323c_stop_stack_thread(void);
int ooh323c_start_call_thread(ooCallData *call);
int ooh323c_stop_call_thread(ooCallData *call);
int ooh323c_set_capability
- (struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec);
-struct ast_format *convertH323CapToAsteriskCap(int cap, struct ast_format *format);
+ (struct ast_format_cap *cap, int dtmf, int dtmfcodec);
+struct ast_format *convertH323CapToAsteriskCap(int cap);
int ooh323c_set_capability_for_call
- (ooCallData *call, struct ast_codec_pref *prefs, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
+ (ooCallData *call, struct ast_format_cap *cap, int dtmf, int dtmfcodec,
int t38support, int g729onlyA);
#endif
diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c
index 5095001cf..f531c1613 100644
--- a/apps/app_agent_pool.c
+++ b/apps/app_agent_pool.c
@@ -2136,8 +2136,8 @@ static int agent_login_exec(struct ast_channel *chan, const char *data)
}
ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
- ast_getformatname(ast_channel_readformat(chan)),
- ast_getformatname(ast_channel_writeformat(chan)));
+ ast_format_get_name(ast_channel_readformat(chan)),
+ ast_format_get_name(ast_channel_writeformat(chan)));
ast_channel_lock(chan);
send_agent_login(chan, agent->username);
ast_channel_unlock(chan);
diff --git a/apps/app_alarmreceiver.c b/apps/app_alarmreceiver.c
index 9063e1a60..4f9de364d 100644
--- a/apps/app_alarmreceiver.c
+++ b/apps/app_alarmreceiver.c
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
#include "asterisk/indications.h"
+#include "asterisk/format_cache.h"
#define ALMRCV_CONFIG "alarmreceiver.conf"
#define UNKNOWN_FORMAT "UNKNOWN_FORMAT"
@@ -798,19 +799,19 @@ static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
char signalling_type[64] = "";
event_node_t *event_head = NULL;
- if (ast_channel_writeformat(chan)->id != AST_FORMAT_ALAW
- && ast_channel_writeformat(chan)->id != AST_FORMAT_ULAW) {
+ if ((ast_format_cmp(ast_channel_writeformat(chan), ast_format_ulaw) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ (ast_format_cmp(ast_channel_writeformat(chan), ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL)) {
ast_verb(4, "AlarmReceiver: Setting write format to Mu-law\n");
- if (ast_set_write_format_by_id(chan,AST_FORMAT_ULAW)) {
+ if (ast_set_write_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan));
return -1;
}
}
- if (ast_channel_readformat(chan)->id != AST_FORMAT_ALAW
- && ast_channel_readformat(chan)->id != AST_FORMAT_ULAW) {
+ if ((ast_format_cmp(ast_channel_readformat(chan), ast_format_ulaw) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ (ast_format_cmp(ast_channel_readformat(chan), ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL)) {
ast_verb(4, "AlarmReceiver: Setting read format to Mu-law\n");
- if (ast_set_read_format_by_id(chan,AST_FORMAT_ULAW)) {
+ if (ast_set_read_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan));
return -1;
}
diff --git a/apps/app_amd.c b/apps/app_amd.c
index d8f26b49b..3dd8cc617 100644
--- a/apps/app_amd.c
+++ b/apps/app_amd.c
@@ -52,6 +52,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="AMD" language="en_US">
@@ -163,7 +164,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
struct ast_frame *f = NULL;
struct ast_dsp *silenceDetector = NULL;
int dspsilence = 0, framelength = 0;
- struct ast_format readFormat;
+ RAII_VAR(struct ast_format *, readFormat, NULL, ao2_cleanup);
int inInitialSilence = 1;
int inGreeting = 0;
int voiceDuration = 0;
@@ -202,11 +203,10 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
AST_APP_ARG(argMaximumWordLength);
);
- ast_format_clear(&readFormat);
ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", ast_channel_name(chan),
S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, "(N/A)"),
S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "(N/A)"),
- ast_getformatname(ast_channel_readformat(chan)));
+ ast_format_get_name(ast_channel_readformat(chan)));
/* Lets parse the arguments. */
if (!ast_strlen_zero(parse)) {
@@ -255,8 +255,8 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold, maximumWordLength);
/* Set read format to signed linear so we get signed linear frames in */
- ast_format_copy(&readFormat, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0 ) {
+ readFormat = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin) < 0 ) {
ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", ast_channel_name(chan));
pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
@@ -289,7 +289,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) {
/* If the total time exceeds the analysis time then give up as we are not too sure */
if (f->frametype == AST_FRAME_VOICE) {
- framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
+ framelength = (ast_codec_samples_count(f) / DEFAULT_SAMPLES_PER_MS);
} else {
framelength = 2 * maxWaitTimeForFrame;
}
@@ -412,7 +412,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause);
/* Restore channel read format */
- if (readFormat.id && ast_set_read_format(chan, &readFormat))
+ if (readFormat && ast_set_read_format(chan, readFormat))
ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", ast_channel_name(chan));
/* Free the DSP used to detect silence */
@@ -510,10 +510,10 @@ static int unload_module(void)
*/
static int load_module(void)
{
- if (load_config(0))
+ if (load_config(0) || ast_register_application_xml(app, amd_exec)) {
return AST_MODULE_LOAD_DECLINE;
- if (ast_register_application_xml(app, amd_exec))
- return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c
index 47f755e5f..af69be303 100644
--- a/apps/app_chanspy.c
+++ b/apps/app_chanspy.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/autochan.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
#define AST_NAME_STRLEN 256
#define NUM_SPYGROUPS 128
@@ -451,9 +452,6 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
{
struct chanspy_translation_helper *csth = data;
struct ast_frame *f, *cur;
- struct ast_format format_slin;
-
- ast_format_set(&format_slin, AST_FORMAT_SLINEAR, 0);
ast_audiohook_lock(&csth->spy_audiohook);
if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
@@ -464,9 +462,9 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
if (ast_test_flag(&csth->flags, OPTION_READONLY)) {
/* Option 'o' was set, so don't mix channel audio */
- f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_READ, &format_slin);
+ f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_READ, ast_format_slin);
} else {
- f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, &format_slin);
+ f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, ast_format_slin);
}
ast_audiohook_unlock(&csth->spy_audiohook);
@@ -1181,7 +1179,7 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
.volume = '#',
.exit = '\0',
};
- struct ast_format oldwf;
+ RAII_VAR(struct ast_format *, oldwf, NULL, ao2_cleanup);
int volfactor = 0;
int res;
char *mailbox = NULL;
@@ -1194,7 +1192,6 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
char *parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_format_clear(&oldwf);
if (args.spec && !strcmp(args.spec, "all"))
args.spec = NULL;
@@ -1258,8 +1255,8 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
ast_clear_flag(&flags, AST_FLAGS_ALL);
}
- ast_format_copy(&oldwf, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ oldwf = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return -1;
}
@@ -1279,7 +1276,7 @@ static int chanspy_exec(struct ast_channel *chan, const char *data)
if (fd)
close(fd);
- if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
+ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
if (ast_test_flag(&flags, OPTION_EXITONHANGUP)) {
@@ -1301,7 +1298,7 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
.volume = '#',
.exit = '\0',
};
- struct ast_format oldwf;
+ RAII_VAR(struct ast_format *, oldwf, NULL, ao2_cleanup);
int volfactor = 0;
int res;
char *mailbox = NULL;
@@ -1313,7 +1310,6 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
char *parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_format_clear(&oldwf);
if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
exten = args.context;
@@ -1383,8 +1379,8 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
ast_clear_flag(&flags, AST_FLAGS_ALL);
}
- ast_format_copy(&oldwf, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ oldwf = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return -1;
}
@@ -1405,7 +1401,7 @@ static int extenspy_exec(struct ast_channel *chan, const char *data)
if (fd)
close(fd);
- if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
+ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
return res;
@@ -1420,13 +1416,13 @@ static int dahdiscan_exec(struct ast_channel *chan, const char *data)
.volume = '\0',
.exit = '*',
};
- struct ast_format oldwf;
+ struct ast_format *oldwf;
int res;
char *mygroup = NULL;
/* Coverity - This uninit_use should be ignored since this macro initializes the flags */
ast_clear_flag(&flags, AST_FLAGS_ALL);
- ast_format_clear(&oldwf);
+
if (!ast_strlen_zero(data)) {
mygroup = ast_strdupa(data);
}
@@ -1434,16 +1430,18 @@ static int dahdiscan_exec(struct ast_channel *chan, const char *data)
ast_set_flag(&flags, OPTION_DTMF_CYCLE);
ast_set_flag(&flags, OPTION_DAHDI_SCAN);
- ast_format_copy(&oldwf, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ oldwf = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
+ ao2_cleanup(oldwf);
return -1;
}
res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
- if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
+ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
+ ao2_cleanup(oldwf);
return res;
}
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 9a704ac93..445b196d4 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="ConfBridge" language="en_US">
@@ -676,7 +677,6 @@ static int conf_stop_record_thread(struct confbridge_conference *conference)
static int conf_start_record(struct confbridge_conference *conference)
{
struct ast_format_cap *cap;
- struct ast_format format;
if (conference->record_state != CONF_RECORD_STOP) {
return -1;
@@ -687,16 +687,16 @@ static int conf_start_record(struct confbridge_conference *conference)
return -1;
}
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
conference->record_chan = ast_request("CBRec", cap, NULL, NULL,
conference->name, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
if (!conference->record_chan) {
return -1;
}
@@ -1374,16 +1374,15 @@ static void leave_conference(struct confbridge_user *user)
static int alloc_playback_chan(struct confbridge_conference *conference)
{
struct ast_format_cap *cap;
- struct ast_format format;
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
conference->name, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
if (!conference->playback_chan) {
return -1;
}
@@ -3238,7 +3237,7 @@ void conf_remove_user_waiting(struct confbridge_conference *conference, struct c
static void unregister_channel_tech(struct ast_channel_tech *tech)
{
ast_channel_unregister(tech);
- tech->capabilities = ast_format_cap_destroy(tech->capabilities);
+ ao2_cleanup(tech->capabilities);
}
/*!
@@ -3253,11 +3252,11 @@ static void unregister_channel_tech(struct ast_channel_tech *tech)
*/
static int register_channel_tech(struct ast_channel_tech *tech)
{
- tech->capabilities = ast_format_cap_alloc(0);
+ tech->capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!tech->capabilities) {
return -1;
}
- ast_format_cap_add_all(tech->capabilities);
+ ast_format_cap_append_by_type(tech->capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (ast_channel_register(tech)) {
ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
tech->type, tech->description);
diff --git a/apps/app_dictate.c b/apps/app_dictate.c
index 1820a1f83..8f229f2a9 100644
--- a/apps/app_dictate.c
+++ b/apps/app_dictate.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Dictate" language="en_US">
@@ -108,8 +109,7 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
len = 0,
maxlen = 0,
mode = 0;
- struct ast_format oldr;
- ast_format_clear(&oldr);
+ struct ast_format *oldr;
snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
if (!ast_strlen_zero(data)) {
@@ -126,9 +126,10 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
if (args.argc > 1 && args.filename) {
filename = args.filename;
}
- ast_format_copy(&oldr, ast_channel_readformat(chan));
- if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) {
+ oldr = ao2_bump(ast_channel_readformat(chan));
+ if ((res = ast_set_read_format(chan, ast_format_slin)) < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
+ ao2_cleanup(oldr);
return -1;
}
@@ -335,8 +336,9 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
ast_frfree(f);
}
}
- if (oldr.id) {
- ast_set_read_format(chan, &oldr);
+ if (oldr) {
+ ast_set_read_format(chan, oldr);
+ ao2_ref(oldr, -1);
}
return 0;
}
diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c
index 5c5be18af..1794c2565 100644
--- a/apps/app_dumpchan.c
+++ b/apps/app_dumpchan.c
@@ -72,7 +72,7 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
{
long elapsed_seconds = 0;
int hour = 0, min = 0, sec = 0;
- char nf[256];
+ struct ast_str *format_buf = ast_str_alloca(64);
char cgrp[256];
char pgrp[256];
struct ast_str *write_transpath = ast_str_alloca(256);
@@ -143,11 +143,11 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
ast_state2str(ast_channel_state(c)),
ast_channel_state(c),
ast_channel_rings(c),
- ast_getformatname_multiple(nf, sizeof(nf), ast_channel_nativeformats(c)),
- ast_getformatname(ast_channel_writeformat(c)),
- ast_getformatname(ast_channel_readformat(c)),
- ast_getformatname(ast_channel_rawwriteformat(c)),
- ast_getformatname(ast_channel_rawreadformat(c)),
+ ast_format_cap_get_names(ast_channel_nativeformats(c), &format_buf),
+ ast_format_get_name(ast_channel_writeformat(c)),
+ ast_format_get_name(ast_channel_readformat(c)),
+ ast_format_get_name(ast_channel_rawwriteformat(c)),
+ ast_format_get_name(ast_channel_rawreadformat(c)),
ast_channel_writetrans(c) ? "Yes" : "No",
ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath),
ast_channel_readtrans(c) ? "Yes" : "No",
diff --git a/apps/app_echo.c b/apps/app_echo.c
index df5a914f1..d8b207967 100644
--- a/apps/app_echo.c
+++ b/apps/app_echo.c
@@ -58,11 +58,6 @@ static const char app[] = "Echo";
static int echo_exec(struct ast_channel *chan, const char *data)
{
int res = -1;
- struct ast_format format;
-
- ast_best_codec(ast_channel_nativeformats(chan), &format);
- ast_set_write_format(chan, &format);
- ast_set_read_format(chan, &format);
while (ast_waitfor(chan, -1) > -1) {
struct ast_frame *f = ast_read(chan);
diff --git a/apps/app_fax.c b/apps/app_fax.c
index e23ac431e..ceff38fef 100644
--- a/apps/app_fax.c
+++ b/apps/app_fax.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="SendFAX" language="en_US" module="app_fax">
@@ -332,9 +333,9 @@ static int fax_generator_generate(struct ast_channel *chan, void *data, int len,
struct ast_frame outf = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin,
.src = __FUNCTION__,
};
- ast_format_set(&outf.subclass.format, AST_FORMAT_SLINEAR, 0);
if (samples > MAX_SAMPLES) {
ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples);
@@ -365,8 +366,8 @@ static struct ast_generator generator = {
static int transmit_audio(fax_session *s)
{
int res = -1;
- struct ast_format original_read_fmt;
- struct ast_format original_write_fmt;
+ struct ast_format *original_read_fmt;
+ struct ast_format *original_write_fmt = NULL;
fax_state_t fax;
t30_state_t *t30state;
struct ast_frame *inf = NULL;
@@ -386,9 +387,6 @@ static int transmit_audio(fax_session *s)
*/
};
- ast_format_clear(&original_read_fmt);
- ast_format_clear(&original_write_fmt);
-
/* if in called party mode, try to use T.38 */
if (s->caller_mode == FALSE) {
/* check if we are already in T.38 mode (unlikely), or if we can request
@@ -461,22 +459,18 @@ static int transmit_audio(fax_session *s)
t30state = &fax.t30_state;
#endif
- ast_format_copy(&original_read_fmt, ast_channel_readformat(s->chan));
- if (original_read_fmt.id != AST_FORMAT_SLINEAR) {
- res = ast_set_read_format_by_id(s->chan, AST_FORMAT_SLINEAR);
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
- goto done;
- }
+ original_read_fmt = ao2_bump(ast_channel_readformat(s->chan));
+ res = ast_set_read_format(s->chan, ast_format_slin);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
+ goto done;
}
- ast_format_copy(&original_write_fmt, ast_channel_writeformat(s->chan));
- if (original_write_fmt.id != AST_FORMAT_SLINEAR) {
- res = ast_set_write_format_by_id(s->chan, AST_FORMAT_SLINEAR);
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
- goto done;
- }
+ original_write_fmt = ao2_bump(ast_channel_writeformat(s->chan));
+ res = ast_set_write_format(s->chan, ast_format_slin);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
+ goto done;
}
/* Initialize T30 terminal */
@@ -529,12 +523,13 @@ static int transmit_audio(fax_session *s)
break;
}
- ast_debug(10, "frame %d/%u, len=%d\n", inf->frametype, (unsigned int) inf->subclass.format.id, inf->datalen);
+ ast_debug(10, "frame %d/%s, len=%d\n", inf->frametype, ast_format_get_name(inf->subclass.format), inf->datalen);
/* Check the frame type. Format also must be checked because there is a chance
that a frame in old format was already queued before we set channel format
to slinear so it will still be received by ast_read */
- if (inf->frametype == AST_FRAME_VOICE && inf->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (inf->frametype == AST_FRAME_VOICE &&
+ (ast_format_cmp(inf->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
/* I know fax_rx never returns errors. The check here is for good style only */
ast_log(LOG_WARNING, "fax_rx returned error\n");
@@ -588,14 +583,16 @@ static int transmit_audio(fax_session *s)
fax_release(&fax);
done:
- if (original_write_fmt.id != AST_FORMAT_SLINEAR) {
- if (ast_set_write_format(s->chan, &original_write_fmt) < 0)
+ if (original_write_fmt) {
+ if (ast_set_write_format(s->chan, original_write_fmt) < 0)
ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", ast_channel_name(s->chan));
+ ao2_ref(original_write_fmt, -1);
}
- if (original_read_fmt.id != AST_FORMAT_SLINEAR) {
- if (ast_set_read_format(s->chan, &original_read_fmt) < 0)
+ if (original_read_fmt) {
+ if (ast_set_read_format(s->chan, original_read_fmt) < 0)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(s->chan));
+ ao2_ref(original_read_fmt, -1);
}
return res;
diff --git a/apps/app_festival.c b/apps/app_festival.c
index 3ccacb195..3626563c6 100644
--- a/apps/app_festival.c
+++ b/apps/app_festival.c
@@ -63,6 +63,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define FESTIVAL_CONFIG "festival.conf"
#define MAXLEN 180
@@ -177,7 +178,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
int res = 0;
int fds[2];
int needed = 0;
- struct ast_format owriteformat;
+ struct ast_format *owriteformat;
struct ast_frame *f;
struct myframe {
struct ast_frame f;
@@ -187,7 +188,6 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
.f = { 0, },
};
- ast_format_clear(&owriteformat);
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
@@ -199,12 +199,19 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
ast_stopstream(chan);
ast_indicate(chan, -1);
- ast_format_copy(&owriteformat, ast_channel_writeformat(chan));
- res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ owriteformat = ao2_bump(ast_channel_writeformat(chan));
+ res = ast_set_write_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
+ ao2_cleanup(owriteformat);
return -1;
}
+
+ myf.f.frametype = AST_FRAME_VOICE;
+ myf.f.subclass.format = ast_format_slin;
+ myf.f.offset = AST_FRIENDLY_OFFSET;
+ myf.f.src = __PRETTY_FUNCTION__;
+ myf.f.data.ptr = myf.frdata;
res = send_waveform_to_fd(waveform, length, fds[1]);
if (res >= 0) {
@@ -240,13 +247,8 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
}
res = read(fds[0], myf.frdata, needed);
if (res > 0) {
- myf.f.frametype = AST_FRAME_VOICE;
- ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0);
myf.f.datalen = res;
myf.f.samples = res / 2;
- myf.f.offset = AST_FRIENDLY_OFFSET;
- myf.f.src = __PRETTY_FUNCTION__;
- myf.f.data.ptr = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
ast_frfree(f);
@@ -269,8 +271,10 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
close(fds[0]);
close(fds[1]);
- if (!res && owriteformat.id)
- ast_set_write_format(chan, &owriteformat);
+ if (!res && owriteformat)
+ ast_set_write_format(chan, owriteformat);
+ ao2_cleanup(owriteformat);
+
return res;
}
diff --git a/apps/app_ices.c b/apps/app_ices.c
index bdccff43f..3122273c7 100644
--- a/apps/app_ices.c
+++ b/apps/app_ices.c
@@ -48,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="ICES" language="en_US">
@@ -115,12 +116,11 @@ static int ices_exec(struct ast_channel *chan, const char *data)
int ms = -1;
int pid = -1;
int flags;
- struct ast_format oreadformat;
+ struct ast_format *oreadformat;
struct ast_frame *f;
char filename[256]="";
char *c;
- ast_format_clear(&oreadformat);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
return -1;
@@ -145,12 +145,13 @@ static int ices_exec(struct ast_channel *chan, const char *data)
return -1;
}
- ast_format_copy(&oreadformat, ast_channel_readformat(chan));
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ oreadformat = ao2_bump(ast_channel_readformat(chan));
+ res = ast_set_read_format(chan, ast_format_slin);
if (res < 0) {
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
+ ao2_cleanup(oreadformat);
return -1;
}
if (((char *)data)[0] == '/')
@@ -197,8 +198,9 @@ static int ices_exec(struct ast_channel *chan, const char *data)
if (pid > -1)
kill(pid, SIGKILL);
- if (!res && oreadformat.id)
- ast_set_read_format(chan, &oreadformat);
+ if (!res && oreadformat)
+ ast_set_read_format(chan, oreadformat);
+ ao2_cleanup(oreadformat);
return res;
}
diff --git a/apps/app_jack.c b/apps/app_jack.c
index 9c59ceaf4..8adfbc4cb 100644
--- a/apps/app_jack.c
+++ b/apps/app_jack.c
@@ -58,6 +58,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/audiohook.h"
+#include "asterisk/format_cache.h"
#define RESAMPLE_QUALITY 1
@@ -129,7 +130,7 @@ struct jack_data {
jack_port_t *output_port;
jack_ringbuffer_t *input_rb;
jack_ringbuffer_t *output_rb;
- enum ast_format_id audiohook_format_id;
+ struct ast_format *audiohook_format;
unsigned int audiohook_rate;
unsigned int frame_datalen;
void *output_resampler;
@@ -394,7 +395,6 @@ static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
jack_status_t status = 0;
jack_options_t jack_options = JackNullOption;
- struct ast_format format_slin;
unsigned int channel_rate;
unsigned int ringbuffer_size;
@@ -402,19 +402,17 @@ static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
/* Deducing audiohook sample rate from channel format
ATTENTION: Might be problematic, if channel has different sampling than used by audiohook!
*/
- channel_rate = ast_format_rate(ast_channel_readformat(chan));
- jack_data->audiohook_format_id = ast_format_slin_by_rate(channel_rate);
-
- ast_format_set(&format_slin, jack_data->audiohook_format_id, 0);
- jack_data->audiohook_rate = ast_format_rate(&format_slin);
+ channel_rate = ast_format_get_sample_rate(ast_channel_readformat(chan));
+ jack_data->audiohook_format = ast_format_cache_get_slin_by_rate(channel_rate);
+ jack_data->audiohook_rate = ast_format_get_sample_rate(jack_data->audiohook_format);
/* Guessing frame->datalen assuming a ptime of 20ms */
jack_data->frame_datalen = jack_data->audiohook_rate / 50;
ringbuffer_size = jack_data->frame_datalen * RINGBUFFER_FRAME_CAPACITY;
- ast_debug(1, "Audiohook parameters: slin-format:%d, rate:%d, frame-len:%d, ringbuffer_size: %d\n",
- jack_data->audiohook_format_id, jack_data->audiohook_rate, jack_data->frame_datalen, ringbuffer_size);
+ ast_debug(1, "Audiohook parameters: slin-format:%s, rate:%d, frame-len:%d, ringbuffer_size: %d\n",
+ ast_format_get_name(jack_data->audiohook_format), jack_data->audiohook_rate, jack_data->frame_datalen, ringbuffer_size);
if (!ast_strlen_zero(jack_data->client_name)) {
client_name = jack_data->client_name;
@@ -628,12 +626,12 @@ static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_d
short buf[jack_data->frame_datalen];
struct ast_frame f = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = jack_data->audiohook_format,
.src = "JACK",
.data.ptr = buf,
.datalen = sizeof(buf),
.samples = ARRAY_LEN(buf),
};
- ast_format_set(&f.subclass.format, jack_data->audiohook_format_id, 0);
for (;;) {
size_t res, read_len;
@@ -778,12 +776,12 @@ static int jack_exec(struct ast_channel *chan, const char *data)
return -1;
}
- if (ast_set_read_format_by_id(chan, jack_data->audiohook_format_id)) {
+ if (ast_set_read_format(chan, jack_data->audiohook_format)) {
destroy_jack_data(jack_data);
return -1;
}
- if (ast_set_write_format_by_id(chan, jack_data->audiohook_format_id)) {
+ if (ast_set_write_format(chan, jack_data->audiohook_format)) {
destroy_jack_data(jack_data);
return -1;
}
@@ -859,9 +857,10 @@ static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channe
jack_data = datastore->data;
- if (frame->subclass.format.id != jack_data->audiohook_format_id) {
- ast_log(LOG_WARNING, "Expected frame in SLINEAR with id %d for the audiohook, but got format %s\n",
- jack_data->audiohook_format_id, ast_getformatname(&frame->subclass.format));
+ if (ast_format_cmp(frame->subclass.format, jack_data->audiohook_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_log(LOG_WARNING, "Expected frame in %s for the audiohook, but got format %s\n",
+ ast_format_get_name(jack_data->audiohook_format),
+ ast_format_get_name(frame->subclass.format));
ast_channel_unlock(chan);
return 0;
}
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index 1a780e6ff..6d0b5ac1b 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/json.h"
+#include "asterisk/format_compatibility.h"
#include "enter.h"
#include "leave.h"
@@ -1606,8 +1607,7 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
struct ast_conference *cnf;
struct dahdi_confinfo dahdic = { 0, };
int confno_int = 0;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_fmt;
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
AST_LIST_LOCK(&confs);
@@ -1619,7 +1619,7 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
if (cnf || (!make && !dynamic) || !cap_slin)
goto cnfout;
- ast_format_cap_add(cap_slin, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
/* Make a new one */
if (!(cnf = ast_calloc(1, sizeof(*cnf))) ||
!(cnf->usercontainer = ao2_container_alloc(1, NULL, user_no_cmp))) {
@@ -1667,8 +1667,8 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
/* Setup a new channel for playback of audio files */
cnf->chan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL);
if (cnf->chan) {
- ast_set_read_format_by_id(cnf->chan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(cnf->chan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(cnf->chan, ast_format_slin);
+ ast_set_write_format(cnf->chan, ast_format_slin);
dahdic.chan = 0;
dahdic.confno = cnf->dahdiconf;
dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
@@ -1704,7 +1704,7 @@ static struct ast_conference *build_conf(const char *confno, const char *pin,
conf_map[confno_int] = 1;
cnfout:
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
if (cnf)
ast_atomic_fetchadd_int(&cnf->refcount, refcount);
@@ -3089,8 +3089,8 @@ static void meetme_menu_admin_extended(enum menu_modes *menu_mode, int *dtmf,
if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL)))) {
struct dahdi_confinfo dahdic;
- ast_set_read_format_by_id(conf->lchan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(conf->lchan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(conf->lchan, ast_format_slin);
+ ast_set_write_format(conf->lchan, ast_format_slin);
dahdic.chan = 0;
dahdic.confno = conf->dahdiconf;
dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
@@ -3217,13 +3217,12 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
int setusercount = 0;
int confsilence = 0, totalsilence = 0;
char *mailbox, *context;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmpfmt;
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap_slin) {
goto conf_run_cleanup;
}
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
if (!(user = ao2_alloc(sizeof(*user), NULL))) {
goto conf_run_cleanup;
@@ -3345,8 +3344,8 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
ast_mutex_lock(&conf->recordthreadlock);
if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) &&
((conf->lchan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL)))) {
- ast_set_read_format_by_id(conf->lchan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(conf->lchan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(conf->lchan, ast_format_slin);
+ ast_set_write_format(conf->lchan, ast_format_slin);
dahdic.chan = 0;
dahdic.confno = conf->dahdiconf;
dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
@@ -3572,12 +3571,12 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
ast_indicate(chan, -1);
}
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", ast_channel_name(chan));
goto outrun;
}
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ if (ast_set_read_format(chan, ast_format_slin) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", ast_channel_name(chan));
goto outrun;
}
@@ -4131,7 +4130,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
dtmfstr[1] = '\0';
}
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) {
+ if ((f->frametype == AST_FRAME_VOICE) && (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
if (user->talk.actual) {
ast_frame_adjust_volume(f, user->talk.actual);
}
@@ -4289,7 +4288,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
if (res > 0) {
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&fr.subclass.format, AST_FORMAT_SLINEAR, 0);
+ fr.subclass.format = ast_format_slin;
fr.datalen = res;
fr.samples = res / 2;
fr.data.ptr = buf;
@@ -4301,7 +4300,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
)) {
int idx;
for (idx = 0; idx < AST_FRAME_BITS; idx++) {
- if (ast_format_to_old_bitfield(ast_channel_rawwriteformat(chan)) & (1 << idx)) {
+ if (ast_format_compatibility_format2bitfield(ast_channel_rawwriteformat(chan)) & (1 << idx)) {
break;
}
}
@@ -4319,11 +4318,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
mohtempstopped = 1;
}
if (!conf->transpath[idx]) {
- struct ast_format src;
- struct ast_format dst;
- ast_format_set(&src, AST_FORMAT_SLINEAR, 0);
- ast_format_from_old_bitfield(&dst, (1 << idx));
- conf->transpath[idx] = ast_translator_build_path(&dst, &src);
+ conf->transpath[idx] = ast_translator_build_path(ast_channel_rawwriteformat(chan), ast_format_slin);
}
if (conf->transpath[idx]) {
conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0);
@@ -4485,7 +4480,7 @@ bailoutandtrynormal:
conf_run_cleanup:
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
return ret;
}
diff --git a/apps/app_milliwatt.c b/apps/app_milliwatt.c
index a4adc08c5..a3509581d 100644
--- a/apps/app_milliwatt.c
+++ b/apps/app_milliwatt.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/indications.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Milliwatt" language="en_US">
@@ -79,13 +80,14 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
{
unsigned char buf[AST_FRIENDLY_OFFSET + 640];
const int maxsamples = ARRAY_LEN(buf) - (AST_FRIENDLY_OFFSET / sizeof(buf[0]));
- int i, *indexp = (int *) data;
+ int i, *indexp = (int *) data, res;
struct ast_frame wf = {
.frametype = AST_FRAME_VOICE,
.offset = AST_FRIENDLY_OFFSET,
.src = __FUNCTION__,
};
- ast_format_set(&wf.subclass.format, AST_FORMAT_ULAW, 0);
+
+ wf.subclass.format = ast_format_ulaw;
wf.data.ptr = buf + AST_FRIENDLY_OFFSET;
/* Instead of len, use samples, because channel.c generator_force
@@ -108,7 +110,10 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
*indexp &= 7;
}
- if (ast_write(chan,&wf) < 0) {
+ res = ast_write(chan, &wf);
+ ast_frfree(&wf);
+
+ if (res < 0) {
ast_log(LOG_WARNING,"Failed to write frame to '%s': %s\n",ast_channel_name(chan),strerror(errno));
return -1;
}
@@ -124,8 +129,8 @@ static struct ast_generator milliwattgen = {
static int old_milliwatt_exec(struct ast_channel *chan)
{
- ast_set_write_format_by_id(chan, AST_FORMAT_ULAW);
- ast_set_read_format_by_id(chan, AST_FORMAT_ULAW);
+ ast_set_write_format(chan, ast_format_ulaw);
+ ast_set_read_format(chan, ast_format_ulaw);
if (ast_channel_state(chan) != AST_STATE_UP) {
ast_answer(chan);
diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index ab1d0bad1..1e7833cea 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h"
#include "asterisk/test.h"
#include "asterisk/mixmonitor.h"
+#include "asterisk/format_cache.h"
#include "asterisk/beep.h"
/*** DOCUMENTATION
@@ -616,7 +617,7 @@ static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename,
*errflag = 1;
} else {
struct ast_filestream *tmp = *fs;
- mixmonitor->mixmonitor_ds->samp_rate = MAX(mixmonitor->mixmonitor_ds->samp_rate, ast_format_rate(&tmp->fmt->format));
+ mixmonitor->mixmonitor_ds->samp_rate = MAX(mixmonitor->mixmonitor_ds->samp_rate, ast_format_get_sample_rate(tmp->fmt->format));
}
}
}
@@ -635,7 +636,7 @@ static void *mixmonitor_thread(void *obj)
unsigned int oflags;
int errflag = 0;
- struct ast_format format_slin;
+ struct ast_format *format_slin;
/* Keep callid association before any log messages */
if (mixmonitor->callid) {
@@ -653,11 +654,10 @@ static void *mixmonitor_thread(void *obj)
mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag, &fs_read_ext);
mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag, &fs_write_ext);
- ast_format_set(&format_slin, ast_format_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate), 0);
+ format_slin = ast_format_cache_get_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate);
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
-
/* The audiohook must enter and exit the loop locked */
ast_audiohook_lock(&mixmonitor->audiohook);
while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
@@ -665,7 +665,7 @@ static void *mixmonitor_thread(void *obj)
struct ast_frame *fr_read = NULL;
struct ast_frame *fr_write = NULL;
- if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, &format_slin,
+ if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, format_slin,
&fr_read, &fr_write))) {
ast_audiohook_trigger_wait(&mixmonitor->audiohook);
diff --git a/apps/app_mp3.c b/apps/app_mp3.c
index 463a91906..7e4e8e490 100644
--- a/apps/app_mp3.c
+++ b/apps/app_mp3.c
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
#define MPG_123 "/usr/bin/mpg123"
@@ -143,7 +144,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
int fds[2];
int ms = -1;
int pid = -1;
- struct ast_format owriteformat;
+ RAII_VAR(struct ast_format *, owriteformat, NULL, ao2_cleanup);
int timeout = 2000;
struct timeval next;
struct ast_frame *f;
@@ -155,7 +156,6 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
.f = { 0, },
};
- ast_format_clear(&owriteformat);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
return -1;
@@ -168,12 +168,21 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
ast_stopstream(chan);
- ast_format_copy(&owriteformat, ast_channel_writeformat(chan));
- res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ owriteformat = ao2_bump(ast_channel_writeformat(chan));
+ res = ast_set_write_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
return -1;
}
+
+ myf.f.frametype = AST_FRAME_VOICE;
+ myf.f.subclass.format = ast_format_slin;
+ myf.f.mallocd = 0;
+ myf.f.offset = AST_FRIENDLY_OFFSET;
+ myf.f.src = __PRETTY_FUNCTION__;
+ myf.f.delivery.tv_sec = 0;
+ myf.f.delivery.tv_usec = 0;
+ myf.f.data.ptr = myf.frdata;
res = mp3play(data, fds[1]);
if (!strncasecmp(data, "http://", 7)) {
@@ -191,16 +200,8 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
if (ms <= 0) {
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
if (res > 0) {
- myf.f.frametype = AST_FRAME_VOICE;
- ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0);
myf.f.datalen = res;
myf.f.samples = res / 2;
- myf.f.mallocd = 0;
- myf.f.offset = AST_FRIENDLY_OFFSET;
- myf.f.src = __PRETTY_FUNCTION__;
- myf.f.delivery.tv_sec = 0;
- myf.f.delivery.tv_usec = 0;
- myf.f.data.ptr = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
@@ -241,8 +242,10 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
if (pid > -1)
kill(pid, SIGKILL);
- if (!res && owriteformat.id)
- ast_set_write_format(chan, &owriteformat);
+ if (!res && owriteformat)
+ ast_set_write_format(chan, owriteformat);
+
+ ast_frfree(&myf.f);
return res;
}
diff --git a/apps/app_nbscat.c b/apps/app_nbscat.c
index 8cf02b369..435af8a29 100644
--- a/apps/app_nbscat.c
+++ b/apps/app_nbscat.c
@@ -46,6 +46,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="NBScat" language="en_US">
@@ -115,7 +116,7 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
int fds[2];
int ms = -1;
int pid = -1;
- struct ast_format owriteformat;
+ struct ast_format *owriteformat;
struct timeval next;
struct ast_frame *f;
struct myframe {
@@ -124,7 +125,6 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
short frdata[160];
} myf;
- ast_format_clear(&owriteformat);
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
ast_log(LOG_WARNING, "Unable to create socketpair\n");
return -1;
@@ -132,12 +132,22 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
ast_stopstream(chan);
- ast_format_copy(&owriteformat, ast_channel_writeformat(chan));
- res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ owriteformat = ao2_bump(ast_channel_writeformat(chan));
+ res = ast_set_write_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
+ ao2_cleanup(owriteformat);
return -1;
}
+
+ myf.f.frametype = AST_FRAME_VOICE;
+ myf.f.subclass.format = ast_format_slin;
+ myf.f.mallocd = 0;
+ myf.f.offset = AST_FRIENDLY_OFFSET;
+ myf.f.src = __PRETTY_FUNCTION__;
+ myf.f.delivery.tv_sec = 0;
+ myf.f.delivery.tv_usec = 0;
+ myf.f.data.ptr = myf.frdata;
res = NBScatplay(fds[1]);
/* Wait 1000 ms first */
@@ -152,16 +162,8 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
if (ms <= 0) {
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
if (res > 0) {
- myf.f.frametype = AST_FRAME_VOICE;
- ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0);
myf.f.datalen = res;
myf.f.samples = res / 2;
- myf.f.mallocd = 0;
- myf.f.offset = AST_FRIENDLY_OFFSET;
- myf.f.src = __PRETTY_FUNCTION__;
- myf.f.delivery.tv_sec = 0;
- myf.f.delivery.tv_usec = 0;
- myf.f.data.ptr = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
@@ -199,11 +201,13 @@ static int NBScat_exec(struct ast_channel *chan, const char *data)
}
close(fds[0]);
close(fds[1]);
+ ast_frfree(&myf.f);
if (pid > -1)
kill(pid, SIGKILL);
- if (!res && owriteformat.id)
- ast_set_write_format(chan, &owriteformat);
+ if (!res && owriteformat)
+ ast_set_write_format(chan, owriteformat);
+ ao2_cleanup(owriteformat);
return res;
}
diff --git a/apps/app_originate.c b/apps/app_originate.c
index 9fceb0849..15898b240 100644
--- a/apps/app_originate.c
+++ b/apps/app_originate.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
static const char app_originate[] = "Originate";
@@ -112,22 +113,22 @@ static int originate_exec(struct ast_channel *chan, const char *data)
int outgoing_status = 0;
unsigned int timeout = 30;
static const char default_exten[] = "s";
- struct ast_format tmpfmt;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
ast_autoservice_start(chan);
if (!cap_slin) {
goto return_cleanup;
}
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR12, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR24, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR32, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR44, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR48, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR96, 0));
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR192, 0));
+
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin12, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin16, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin24, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin32, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin44, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin48, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin96, 0);
+ ast_format_cap_append(cap_slin, ast_format_slin192, 0);
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "Originate() requires arguments\n");
@@ -222,7 +223,7 @@ return_cleanup:
break;
}
}
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
ast_autoservice_stop(chan);
return res;
diff --git a/apps/app_record.c b/apps/app_record.c
index 45f1d8602..4008fc012 100644
--- a/apps/app_record.c
+++ b/apps/app_record.c
@@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h" /* use dsp routines for silence detection */
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Record" language="en_US">
@@ -196,7 +197,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
int maxduration = 0; /* max duration of recording in milliseconds */
int gottimeout = 0; /* did we timeout for maxduration exceeded? */
int terminator = '#';
- struct ast_format rfmt;
+ RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
int ioflags;
struct ast_silence_generator *silgen = NULL;
struct ast_flags flags = { 0, };
@@ -209,8 +210,6 @@ static int record_exec(struct ast_channel *chan, const char *data)
int ms;
struct timeval start;
- ast_format_clear(&rfmt);
-
/* The next few lines of code parse out the filename and header from the input string */
if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
@@ -331,8 +330,8 @@ static int record_exec(struct ast_channel *chan, const char *data)
/* The end of beep code. Now the recording starts */
if (silence > 0) {
- ast_format_copy(&rfmt, ast_channel_readformat(chan));
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ rfmt = ao2_bump(ast_channel_readformat(chan));
+ res = ast_set_read_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
@@ -459,8 +458,8 @@ static int record_exec(struct ast_channel *chan, const char *data)
ast_channel_stop_silence_generator(chan, silgen);
out:
- if ((silence > 0) && rfmt.id) {
- res = ast_set_read_format(chan, &rfmt);
+ if ((silence > 0) && rfmt) {
+ res = ast_set_read_format(chan, rfmt);
if (res) {
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
}
diff --git a/apps/app_sms.c b/apps/app_sms.c
index b7d247818..266f8abdc 100644
--- a/apps/app_sms.c
+++ b/apps/app_sms.c
@@ -56,6 +56,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="SMS" language="en_US">
@@ -140,11 +141,11 @@ static const signed short wave[] = {
static unsigned char wavea[80];
typedef unsigned char output_t;
static const output_t *wave_out = wavea; /* outgoing samples */
-#define __OUT_FMT AST_FORMAT_ALAW;
+#define __OUT_FMT ast_format_alaw
#else
typedef signed short output_t;
static const output_t *wave_out = wave; /* outgoing samples */
-#define __OUT_FMT AST_FORMAT_SLINEAR
+#define __OUT_FMT ast_format_slin
#endif
#define OSYNC_BITS 80 /* initial sync bits */
@@ -1599,7 +1600,7 @@ static int sms_generate(struct ast_channel *chan, void *data, int len, int sampl
#define MAXSAMPLES (800)
output_t *buf;
sms_t *h = data;
- int i;
+ int i, res;
if (samples > MAXSAMPLES) {
ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
@@ -1610,7 +1611,7 @@ static int sms_generate(struct ast_channel *chan, void *data, int len, int sampl
buf = ast_alloca(len);
f.frametype = AST_FRAME_VOICE;
- ast_format_set(&f.subclass.format, __OUT_FMT, 0);
+ f.subclass.format = __OUT_FMT;
f.datalen = samples * sizeof(*buf);
f.offset = AST_FRIENDLY_OFFSET;
f.mallocd = 0;
@@ -1660,7 +1661,9 @@ static int sms_generate(struct ast_channel *chan, void *data, int len, int sampl
}
}
}
- if (ast_write(chan, &f) < 0) {
+ res = ast_write(chan, &f);
+ ast_frfree(&f);
+ if (res < 0) {
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
return -1;
}
@@ -2012,9 +2015,9 @@ static int sms_exec(struct ast_channel *chan, const char *data)
sms_messagetx(&h);
}
- res = ast_set_write_format_by_id(chan, __OUT_FMT);
+ res = ast_set_write_format(chan, __OUT_FMT);
if (res >= 0) {
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ res = ast_set_read_format(chan, ast_format_slin);
}
if (res < 0) {
ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c
index e9ca63ea9..e52425d6a 100644
--- a/apps/app_speech_utils.c
+++ b/apps/app_speech_utils.c
@@ -672,7 +672,7 @@ static int speech_background(struct ast_channel *chan, const char *data)
int res = 0, done = 0, started = 0, quieted = 0, max_dtmf_len = 0;
struct ast_speech *speech = find_speech(chan);
struct ast_frame *f = NULL;
- struct ast_format oldreadformat;
+ RAII_VAR(struct ast_format *, oldreadformat, NULL, ao2_cleanup);
char dtmf[AST_MAX_EXTENSION] = "";
struct timeval start = { 0, 0 }, current;
struct ast_datastore *datastore = NULL;
@@ -688,7 +688,6 @@ static int speech_background(struct ast_channel *chan, const char *data)
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- ast_format_clear(&oldreadformat);
if (speech == NULL)
return -1;
@@ -704,10 +703,10 @@ static int speech_background(struct ast_channel *chan, const char *data)
}
/* Record old read format */
- ast_format_copy(&oldreadformat, ast_channel_readformat(chan));
+ oldreadformat = ao2_bump(ast_channel_readformat(chan));
/* Change read format to be signed linear */
- if (ast_set_read_format(chan, &speech->format))
+ if (ast_set_read_format(chan, speech->format))
return -1;
if (!ast_strlen_zero(args.soundfile)) {
@@ -912,7 +911,7 @@ static int speech_background(struct ast_channel *chan, const char *data)
ast_channel_datastore_remove(chan, datastore);
} else {
/* Channel is okay so restore read format */
- ast_set_read_format(chan, &oldreadformat);
+ ast_set_read_format(chan, oldreadformat);
}
return 0;
diff --git a/apps/app_talkdetect.c b/apps/app_talkdetect.c
index 5ef80c33c..5ccf2607e 100644
--- a/apps/app_talkdetect.c
+++ b/apps/app_talkdetect.c
@@ -42,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="BackgroundDetect" language="en_US">
@@ -91,7 +93,7 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
int analysistime = -1;
int continue_analysis = 1;
int x;
- struct ast_format origrformat;
+ RAII_VAR(struct ast_format *, origrformat, NULL, ao2_cleanup);
struct ast_dsp *dsp = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
@@ -101,7 +103,6 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
AST_APP_ARG(analysistime);
);
- ast_format_clear(&origrformat);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
return -1;
@@ -131,8 +132,8 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
}
}
- ast_format_copy(&origrformat, ast_channel_readformat(chan));
- if ((ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR))) {
+ origrformat = ao2_bump(ast_channel_readformat(chan));
+ if ((ast_set_read_format(chan, ast_format_slin))) {
ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
res = -1;
break;
@@ -187,7 +188,8 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
ast_frfree(fr);
break;
}
- } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass.format.id == AST_FORMAT_SLINEAR) && continue_analysis) {
+ } else if ((fr->frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) && continue_analysis) {
int totalsilence;
int ms;
res = ast_dsp_silence(dsp, fr, &totalsilence);
@@ -233,9 +235,9 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
} while (0);
if (res > -1) {
- if (origrformat.id && ast_set_read_format(chan, &origrformat)) {
+ if (origrformat && ast_set_read_format(chan, origrformat)) {
ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
- ast_channel_name(chan), ast_getformatname(&origrformat));
+ ast_channel_name(chan), ast_format_get_name(origrformat));
}
}
if (dsp) {
diff --git a/apps/app_test.c b/apps/app_test.c
index 5b7b979e6..54139ba80 100644
--- a/apps/app_test.c
+++ b/apps/app_test.c
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="TestServer" language="en_US">
@@ -91,11 +92,12 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who)
short *foo;
struct timeval start;
struct ast_frame *f;
- struct ast_format rformat;
+ struct ast_format *rformat;
- ast_format_copy(&rformat, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ rformat = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin)) {
ast_log(LOG_NOTICE, "Unable to set to linear mode!\n");
+ ao2_cleanup(rformat);
return -1;
}
start = ast_tvnow();
@@ -111,7 +113,8 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who)
res = -1;
break;
}
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) {
+ if ((f->frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
foo = (short *)f->data.ptr;
for (x=0;x<f->samples;x++) {
noise += abs(foo[x]);
@@ -121,11 +124,13 @@ static int measurenoise(struct ast_channel *chan, int ms, char *who)
ast_frfree(f);
}
- if (rformat.id) {
- if (ast_set_read_format(chan, &rformat)) {
+ if (rformat) {
+ if (ast_set_read_format(chan, rformat)) {
ast_log(LOG_NOTICE, "Unable to restore original format!\n");
+ ao2_ref(rformat, -1);
return -1;
}
+ ao2_ref(rformat, -1);
}
if (res < 0)
return res;
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 9c8a4b8ad..8a9c0f3ca 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -135,6 +135,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.h"
+#include "asterisk/format_cache.h"
#ifdef ODBC_STORAGE
#include "asterisk/res_odbc.h"
@@ -6112,13 +6113,16 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata)
if ((recording_fs = ast_readfile(recdata->recording_file, recdata->recording_ext, NULL, 0, 0, VOICEMAIL_DIR_MODE))) {
if (!ast_seekstream(recording_fs, 0, SEEK_END)) {
long framelength = ast_tellstream(recording_fs);
- struct ast_format result = {0,};
+ struct ast_format *result;
/* XXX This use of ast_getformatbyname seems incorrect here. The file extension does not necessarily correspond
* to the name of the format. For instance, if "raw" were passed in, I don't think ast_getformatbyname would
* find the slinear format
*/
- ast_getformatbyname(recdata->recording_ext, &result);
- duration = (int) (framelength / ast_format_rate(&result));
+ result = ast_format_cache_get(recdata->recording_ext);
+ if (result) {
+ duration = (int) (framelength / ast_format_get_sample_rate(result));
+ ao2_ref(result, -1);
+ }
}
}
@@ -14026,7 +14030,7 @@ AST_TEST_DEFINE(test_voicemail_vmsayname)
struct ast_channel *test_channel1 = NULL;
int res = -1;
- struct ast_format_cap *nativeformats;
+ struct ast_format_cap *capabilities;
static const struct ast_channel_tech fake_tech = {
.write = fake_write,
@@ -14051,12 +14055,17 @@ AST_TEST_DEFINE(test_voicemail_vmsayname)
}
/* normally this is done in the channel driver */
- ast_format_set(ast_channel_writeformat(test_channel1), AST_FORMAT_GSM, 0);
- nativeformats = ast_channel_nativeformats(test_channel1);
- ast_format_cap_add(nativeformats, ast_channel_writeformat(test_channel1));
- ast_format_set(ast_channel_rawwriteformat(test_channel1), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_readformat(test_channel1), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_rawreadformat(test_channel1), AST_FORMAT_GSM, 0);
+ capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!capabilities) {
+ goto exit_vmsayname_test;
+ }
+ ast_format_cap_append(capabilities, ast_format_gsm, 0);
+ ast_channel_nativeformats_set(test_channel1, capabilities);
+ ao2_ref(capabilities, -1);
+ ast_channel_set_writeformat(test_channel1, ast_format_gsm);
+ ast_channel_set_rawwriteformat(test_channel1, ast_format_gsm);
+ ast_channel_set_readformat(test_channel1, ast_format_gsm);
+ ast_channel_set_rawreadformat(test_channel1, ast_format_gsm);
ast_channel_tech_set(test_channel1, &fake_tech);
ast_channel_unlock(test_channel1);
diff --git a/apps/app_waitforsilence.c b/apps/app_waitforsilence.c
index 53870df30..f2111d720 100644
--- a/apps/app_waitforsilence.c
+++ b/apps/app_waitforsilence.c
@@ -51,6 +51,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/dsp.h"
#include "asterisk/module.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="WaitForSilence" language="en_US">
@@ -129,7 +130,7 @@ static char *app_noise = "WaitForNoise";
static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) {
struct ast_frame *f = NULL;
int dsptime = 0;
- struct ast_format rfmt;
+ RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
int res = 0;
struct ast_dsp *sildet; /* silence detector dsp */
time_t now;
@@ -138,8 +139,8 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart,
int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) =
wait_for_silence ? ast_dsp_silence : ast_dsp_noise;
- ast_format_copy(&rfmt, ast_channel_readformat(chan)); /* Set to linear mode */
- if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) {
+ rfmt = ao2_bump(ast_channel_readformat(chan));
+ if ((res = ast_set_read_format(chan, ast_format_slin)) < 0) {
ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
return -1;
}
@@ -199,8 +200,8 @@ static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart,
}
- if (rfmt.id && ast_set_read_format(chan, &rfmt)) {
- ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(&rfmt), ast_channel_name(chan));
+ if (rfmt && ast_set_read_format(chan, rfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
}
ast_dsp_free(sildet);
return res;
diff --git a/apps/confbridge/conf_chan_record.c b/apps/confbridge/conf_chan_record.c
index 34de5af3b..0e298e78d 100644
--- a/apps/confbridge/conf_chan_record.c
+++ b/apps/confbridge/conf_chan_record.c
@@ -33,6 +33,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
+#include "asterisk/format_cache.h"
#include "include/confbridge.h"
/* ------------------------------------------------------------------- */
@@ -56,8 +57,14 @@ static int rec_write(struct ast_channel *ast, struct ast_frame *f)
static struct ast_channel *rec_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
struct ast_channel *chan;
- struct ast_format format;
const char *conf_name = data;
+ RAII_VAR(struct ast_format_cap *, capabilities, NULL, ao2_cleanup);
+
+ capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!capabilities) {
+ return NULL;
+ }
+ ast_format_cap_append_by_type(capabilities, AST_MEDIA_TYPE_UNKNOWN);
chan = ast_channel_alloc(1, AST_STATE_UP, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0,
"CBRec/conf-%s-uid-%d",
@@ -70,13 +77,13 @@ static struct ast_channel *rec_request(const char *type, struct ast_format_cap *
ast_channel_release(chan);
return NULL;
}
- ast_format_set(&format, AST_FORMAT_SLINEAR, 0);
+
ast_channel_tech_set(chan, conf_record_get_tech());
- ast_format_cap_add_all(ast_channel_nativeformats(chan));
- ast_format_copy(ast_channel_writeformat(chan), &format);
- ast_format_copy(ast_channel_rawwriteformat(chan), &format);
- ast_format_copy(ast_channel_readformat(chan), &format);
- ast_format_copy(ast_channel_rawreadformat(chan), &format);
+ ast_channel_nativeformats_set(chan, capabilities);
+ ast_channel_set_writeformat(chan, ast_format_slin);
+ ast_channel_set_rawwriteformat(chan, ast_format_slin);
+ ast_channel_set_readformat(chan, ast_format_slin);
+ ast_channel_set_rawreadformat(chan, ast_format_slin);
ast_channel_unlock(chan);
return chan;
}
diff --git a/bridges/bridge_holding.c b/bridges/bridge_holding.c
index 5eeb4708d..c343cc624 100644
--- a/bridges/bridge_holding.c
+++ b/bridges/bridge_holding.c
@@ -48,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge_technology.h"
#include "asterisk/frame.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
enum holding_roles {
HOLDING_ROLE_PARTICIPANT,
@@ -180,7 +181,7 @@ static void participant_reaction_announcer_join(struct ast_bridge_channel *bridg
chan = bridge_channel->chan;
participant_entertainment_stop(bridge_channel);
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Could not make participant %s compatible.\n", ast_channel_name(chan));
}
}
@@ -233,7 +234,7 @@ static void handle_participant_join(struct ast_bridge_channel *bridge_channel, s
}
/* We need to get compatible with the announcer. */
- if (ast_set_write_format_by_id(us, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(us, ast_format_slin)) {
ast_log(LOG_WARNING, "Could not make participant %s compatible.\n", ast_channel_name(us));
}
}
@@ -270,7 +271,7 @@ static int holding_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan
hc->role = HOLDING_ROLE_ANNOUNCER;
/* The announcer should always be made compatible with signed linear */
- if (ast_set_read_format_by_id(us, AST_FORMAT_SLINEAR)) {
+ if (ast_set_read_format(us, ast_format_slin)) {
ast_log(LOG_ERROR, "Could not make announcer %s compatible.\n", ast_channel_name(us));
}
@@ -427,18 +428,19 @@ static void deferred_action(struct ast_bridge_channel *bridge_channel, const voi
static int unload_module(void)
{
- ast_format_cap_destroy(holding_bridge.format_capabilities);
+ ao2_cleanup(holding_bridge.format_capabilities);
+ holding_bridge.format_capabilities = NULL;
return ast_bridge_technology_unregister(&holding_bridge);
}
static int load_module(void)
{
- if (!(holding_bridge.format_capabilities = ast_format_cap_alloc(0))) {
+ if (!(holding_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(holding_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add_all_by_type(holding_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO);
- ast_format_cap_add_all_by_type(holding_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT);
+ ast_format_cap_append_by_type(holding_bridge.format_capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_by_type(holding_bridge.format_capabilities, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_by_type(holding_bridge.format_capabilities, AST_MEDIA_TYPE_TEXT);
return ast_bridge_technology_register(&holding_bridge);
}
diff --git a/bridges/bridge_native_rtp.c b/bridges/bridge_native_rtp.c
index 2362ad296..4655efeae 100644
--- a/bridges/bridge_native_rtp.c
+++ b/bridges/bridge_native_rtp.c
@@ -137,8 +137,8 @@ static void native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channe
RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, tinstance0, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, tinstance1, NULL, ao2_cleanup);
- RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
+ RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
if (c0 == c1) {
return;
@@ -316,8 +316,8 @@ static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
- RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
+ RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
int read_ptime0, read_ptime1, write_ptime0, write_ptime1;
/* We require two channels before even considering native bridging */
@@ -374,19 +374,18 @@ static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
if (glue1->get_codec) {
glue1->get_codec(c1->chan, cap1);
}
- if (!ast_format_cap_is_empty(cap0) && !ast_format_cap_is_empty(cap1) && !ast_format_cap_has_joint(cap0, cap1)) {
- char tmp0[256] = { 0, }, tmp1[256] = { 0, };
-
+ if (ast_format_cap_count(cap0) != 0 && ast_format_cap_count(cap1) != 0 && !ast_format_cap_iscompatible(cap0, cap1)) {
+ struct ast_str *codec_buf0 = ast_str_alloca(64);
+ struct ast_str *codec_buf1 = ast_str_alloca(64);
ast_debug(1, "Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
- ast_getformatname_multiple(tmp0, sizeof(tmp0), cap0),
- ast_getformatname_multiple(tmp1, sizeof(tmp1), cap1));
+ ast_format_cap_get_names(cap0, &codec_buf0), ast_format_cap_get_names(cap1, &codec_buf1));
return 0;
}
- read_ptime0 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance0)->pref, ast_channel_rawreadformat(c0->chan))).cur_ms;
- read_ptime1 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance1)->pref, ast_channel_rawreadformat(c1->chan))).cur_ms;
- write_ptime0 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance0)->pref, ast_channel_rawwriteformat(c0->chan))).cur_ms;
- write_ptime1 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance1)->pref, ast_channel_rawwriteformat(c1->chan))).cur_ms;
+ read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(c0->chan));
+ read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(c1->chan));
+ write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(c0->chan));
+ write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(c1->chan));
if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
ast_debug(1, "Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
@@ -518,7 +517,7 @@ static struct ast_bridge_technology native_rtp_bridge = {
static int unload_module(void)
{
- ast_format_cap_destroy(native_rtp_bridge.format_capabilities);
+ ao2_t_ref(native_rtp_bridge.format_capabilities, -1, "Dispose of capabilities in module unload");
return ast_bridge_technology_unregister(&native_rtp_bridge);
}
@@ -527,9 +526,9 @@ static int load_module(void)
if (!(native_rtp_bridge.format_capabilities = ast_format_cap_alloc(0))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO);
- ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT);
+ ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_TEXT);
return ast_bridge_technology_register(&native_rtp_bridge);
}
diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c
index 4a03dbe10..1626a3993 100644
--- a/bridges/bridge_simple.c
+++ b/bridges/bridge_simple.c
@@ -76,18 +76,19 @@ static struct ast_bridge_technology simple_bridge = {
static int unload_module(void)
{
- ast_format_cap_destroy(simple_bridge.format_capabilities);
+ ao2_cleanup(simple_bridge.format_capabilities);
+ simple_bridge.format_capabilities = NULL;
return ast_bridge_technology_unregister(&simple_bridge);
}
static int load_module(void)
{
- if (!(simple_bridge.format_capabilities = ast_format_cap_alloc(0))) {
+ if (!(simple_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO);
- ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT);
+ ast_format_cap_append_by_type(simple_bridge.format_capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_by_type(simple_bridge.format_capabilities, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_by_type(simple_bridge.format_capabilities, AST_MEDIA_TYPE_TEXT);
return ast_bridge_technology_register(&simple_bridge);
}
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index 3f743550c..f5f4c2b16 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -163,14 +163,14 @@ struct softmix_mixing_array {
struct softmix_translate_helper_entry {
int num_times_requested; /*!< Once this entry is no longer requested, free the trans_pvt
and re-init if it was usable. */
- struct ast_format dst_format; /*!< The destination format for this helper */
+ struct ast_format *dst_format; /*!< The destination format for this helper */
struct ast_trans_pvt *trans_pvt; /*!< the translator for this slot. */
struct ast_frame *out_frame; /*!< The output frame from the last translation */
AST_LIST_ENTRY(softmix_translate_helper_entry) entry;
};
struct softmix_translate_helper {
- struct ast_format slin_src; /*!< the source format expected for all the translators */
+ struct ast_format *slin_src; /*!< the source format expected for all the translators */
AST_LIST_HEAD_NOLOCK(, softmix_translate_helper_entry) entries;
};
@@ -180,12 +180,14 @@ static struct softmix_translate_helper_entry *softmix_translate_helper_entry_all
if (!(entry = ast_calloc(1, sizeof(*entry)))) {
return NULL;
}
- ast_format_copy(&entry->dst_format, dst);
+ entry->dst_format = ao2_bump(dst);
return entry;
}
static void *softmix_translate_helper_free_entry(struct softmix_translate_helper_entry *entry)
{
+ ao2_cleanup(entry->dst_format);
+
if (entry->trans_pvt) {
ast_translator_free_path(entry->trans_pvt);
}
@@ -199,7 +201,7 @@ static void *softmix_translate_helper_free_entry(struct softmix_translate_helper
static void softmix_translate_helper_init(struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
{
memset(trans_helper, 0, sizeof(*trans_helper));
- ast_format_set(&trans_helper->slin_src, ast_format_slin_by_rate(sample_rate), 0);
+ trans_helper->slin_src = ast_format_cache_get_slin_by_rate(sample_rate);
}
static void softmix_translate_helper_destroy(struct softmix_translate_helper *trans_helper)
@@ -215,11 +217,11 @@ static void softmix_translate_helper_change_rate(struct softmix_translate_helper
{
struct softmix_translate_helper_entry *entry;
- ast_format_set(&trans_helper->slin_src, ast_format_slin_by_rate(sample_rate), 0);
+ trans_helper->slin_src = ast_format_cache_get_slin_by_rate(sample_rate);
AST_LIST_TRAVERSE_SAFE_BEGIN(&trans_helper->entries, entry, entry) {
if (entry->trans_pvt) {
ast_translator_free_path(entry->trans_pvt);
- if (!(entry->trans_pvt = ast_translator_build_path(&entry->dst_format, &trans_helper->slin_src))) {
+ if (!(entry->trans_pvt = ast_translator_build_path(entry->dst_format, trans_helper->slin_src))) {
AST_LIST_REMOVE_CURRENT(entry);
entry = softmix_translate_helper_free_entry(entry);
}
@@ -274,19 +276,19 @@ static void softmix_process_write_audio(struct softmix_translate_helper *trans_h
}
AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
- if (ast_format_cmp(&entry->dst_format, raw_write_fmt) == AST_FORMAT_CMP_EQUAL) {
+ if (ast_format_cmp(entry->dst_format, raw_write_fmt) == AST_FORMAT_CMP_EQUAL) {
entry->num_times_requested++;
} else {
continue;
}
if (!entry->trans_pvt && (entry->num_times_requested > 1)) {
- entry->trans_pvt = ast_translator_build_path(&entry->dst_format, &trans_helper->slin_src);
+ entry->trans_pvt = ast_translator_build_path(entry->dst_format, trans_helper->slin_src);
}
if (entry->trans_pvt && !entry->out_frame) {
entry->out_frame = ast_translate(entry->trans_pvt, &sc->write_frame, 0);
}
if (entry->out_frame && (entry->out_frame->datalen < MAX_DATALEN)) {
- ast_format_copy(&sc->write_frame.subclass.format, &entry->out_frame->subclass.format);
+ ao2_replace(sc->write_frame.subclass.format, entry->out_frame->subclass.format);
memcpy(sc->final_buf, entry->out_frame->data.ptr, entry->out_frame->datalen);
sc->write_frame.datalen = entry->out_frame->datalen;
sc->write_frame.samples = entry->out_frame->samples;
@@ -316,32 +318,45 @@ static void softmix_translate_helper_cleanup(struct softmix_translate_helper *tr
static void set_softmix_bridge_data(int rate, int interval, struct ast_bridge_channel *bridge_channel, int reset)
{
struct softmix_channel *sc = bridge_channel->tech_pvt;
- unsigned int channel_read_rate = ast_format_rate(ast_channel_rawreadformat(bridge_channel->chan));
+ unsigned int channel_read_rate = ast_format_get_sample_rate(ast_channel_rawreadformat(bridge_channel->chan));
ast_mutex_lock(&sc->lock);
if (reset) {
ast_slinfactory_destroy(&sc->factory);
ast_dsp_free(sc->dsp);
}
- /* Setup read/write frame parameters */
+
+ /* Setup write frame parameters */
sc->write_frame.frametype = AST_FRAME_VOICE;
- ast_format_set(&sc->write_frame.subclass.format, ast_format_slin_by_rate(rate), 0);
+ ao2_cleanup(sc->write_frame.subclass.format);
+ /*
+ * NOTE: The format is bumped here because translation could
+ * be needed and the format changed to the translated format
+ * for the channel. The translated format may not be a
+ * static cached format.
+ */
+ sc->write_frame.subclass.format = ao2_bump(ast_format_cache_get_slin_by_rate(rate));
sc->write_frame.data.ptr = sc->final_buf;
sc->write_frame.datalen = SOFTMIX_DATALEN(rate, interval);
sc->write_frame.samples = SOFTMIX_SAMPLES(rate, interval);
+ /* Setup read frame parameters */
sc->read_frame.frametype = AST_FRAME_VOICE;
- ast_format_set(&sc->read_frame.subclass.format, ast_format_slin_by_rate(channel_read_rate), 0);
+ /*
+ * NOTE: The format is not bumbed here because it will always
+ * be a signed linear format.
+ */
+ sc->read_frame.subclass.format = ast_format_cache_get_slin_by_rate(channel_read_rate);
sc->read_frame.data.ptr = sc->our_buf;
sc->read_frame.datalen = SOFTMIX_DATALEN(channel_read_rate, interval);
sc->read_frame.samples = SOFTMIX_SAMPLES(channel_read_rate, interval);
/* Setup smoother */
- ast_slinfactory_init_with_format(&sc->factory, &sc->write_frame.subclass.format);
+ ast_slinfactory_init_with_format(&sc->factory, sc->write_frame.subclass.format);
/* set new read and write formats on channel. */
- ast_set_read_format(bridge_channel->chan, &sc->read_frame.subclass.format);
- ast_set_write_format(bridge_channel->chan, &sc->write_frame.subclass.format);
+ ast_set_read_format(bridge_channel->chan, sc->read_frame.subclass.format);
+ ast_set_write_format(bridge_channel->chan, sc->write_frame.subclass.format);
/* set up new DSP. This is on the read side only right before the read frame enters the smoother. */
sc->dsp = ast_dsp_new_with_rate(channel_read_rate);
@@ -446,6 +461,9 @@ static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch
/* Drop the factory */
ast_slinfactory_destroy(&sc->factory);
+ /* Drop any formats on the frames */
+ ao2_cleanup(sc->write_frame.subclass.format);
+
/* Drop the DSP */
ast_dsp_free(sc->dsp);
@@ -500,7 +518,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri
ast_mutex_lock(&sc->lock);
ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan,
sc->video_talker.energy_average,
- ast_format_get_video_mark(&frame->subclass.format));
+ frame->subclass.frame_ending);
ast_mutex_unlock(&sc->lock);
video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
if (video_src_priority == 1) {
@@ -575,8 +593,7 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
/* If a frame was provided add it to the smoother, unless drop silence is enabled and this frame
* is not determined to be talking. */
- if (!(bridge_channel->tech_args.drop_silence && !sc->talking) &&
- (frame->frametype == AST_FRAME_VOICE && ast_format_is_slinear(&frame->subclass.format))) {
+ if (!(bridge_channel->tech_args.drop_silence && !sc->talking)) {
ast_slinfactory_feed(&sc->factory, frame);
}
@@ -680,8 +697,8 @@ static void gather_softmix_stats(struct softmix_stats *stats,
int channel_native_rate;
int i;
/* Gather stats about channel sample rates. */
- channel_native_rate = MAX(ast_format_rate(ast_channel_rawwriteformat(bridge_channel->chan)),
- ast_format_rate(ast_channel_rawreadformat(bridge_channel->chan)));
+ channel_native_rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(bridge_channel->chan)),
+ ast_format_get_sample_rate(ast_channel_rawreadformat(bridge_channel->chan)));
if (channel_native_rate > stats->highest_supported_rate) {
stats->highest_supported_rate = channel_native_rate;
@@ -845,7 +862,7 @@ static int softmix_mixing_loop(struct ast_bridge *bridge)
while (!softmix_data->stop && bridge->num_active) {
struct ast_bridge_channel *bridge_channel;
int timeout = -1;
- enum ast_format_id cur_slin_id = ast_format_slin_by_rate(softmix_data->internal_rate);
+ struct ast_format *cur_slin = ast_format_cache_get_slin_by_rate(softmix_data->internal_rate);
unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
unsigned int softmix_datalen = SOFTMIX_DATALEN(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
@@ -927,9 +944,8 @@ static int softmix_mixing_loop(struct ast_bridge *bridge)
ast_mutex_lock(&sc->lock);
/* Make SLINEAR write frame from local buffer */
- if (sc->write_frame.subclass.format.id != cur_slin_id) {
- ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
- }
+ ao2_t_replace(sc->write_frame.subclass.format, cur_slin,
+ "Replace softmix channel slin format");
sc->write_frame.datalen = softmix_datalen;
sc->write_frame.samples = softmix_samples;
memcpy(sc->final_buf, buf, softmix_datalen);
@@ -1144,17 +1160,17 @@ static struct ast_bridge_technology softmix_bridge = {
static int unload_module(void)
{
- ast_format_cap_destroy(softmix_bridge.format_capabilities);
+ ao2_cleanup(softmix_bridge.format_capabilities);
+ softmix_bridge.format_capabilities = NULL;
return ast_bridge_technology_unregister(&softmix_bridge);
}
static int load_module(void)
{
- struct ast_format tmp;
- if (!(softmix_bridge.format_capabilities = ast_format_cap_alloc(0))) {
+ if (!(softmix_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(softmix_bridge.format_capabilities, ast_format_set(&tmp, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(softmix_bridge.format_capabilities, ast_format_slin, 0);
return ast_bridge_technology_register(&softmix_bridge);
}
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index 9d43ba139..f74e78fd6 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -63,6 +63,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/musiconhold.h"
#include "asterisk/poll-compat.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*! Global jitterbuffer configuration - by default, jb is disabled
* \note Values shown here match the defaults shown in alsa.conf.sample */
@@ -511,7 +512,7 @@ static struct ast_frame *alsa_read(struct ast_channel *chan)
}
f.frametype = AST_FRAME_VOICE;
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ f.subclass.format = ast_format_slin;
f.samples = FRAME_SIZE;
f.datalen = FRAME_SIZE * 2;
f.data.ptr = buf;
@@ -585,9 +586,9 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const st
ast_channel_tech_set(tmp, &alsa_tech);
ast_channel_set_fd(tmp, 0, readdev);
- ast_format_set(ast_channel_readformat(tmp), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_writeformat(tmp), AST_FORMAT_SLINEAR, 0);
- ast_format_cap_add(ast_channel_nativeformats(tmp), ast_channel_writeformat(tmp));
+ ast_channel_set_readformat(tmp, ast_format_slin);
+ ast_channel_set_writeformat(tmp, ast_format_slin);
+ ast_channel_nativeformats_set(tmp, alsa_tech.capabilities);
ast_channel_tech_pvt_set(tmp, p);
if (!ast_strlen_zero(p->context))
@@ -616,14 +617,11 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const st
static struct ast_channel *alsa_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
- struct ast_format tmpfmt;
- char buf[256];
struct ast_channel *tmp = NULL;
- ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0);
-
- if (!(ast_format_cap_iscompatible(cap, &tmpfmt))) {
- ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
@@ -959,12 +957,11 @@ static int load_module(void)
struct ast_config *cfg;
struct ast_variable *v;
struct ast_flags config_flags = { 0 };
- struct ast_format tmpfmt;
- if (!(alsa_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(alsa_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(alsa_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(alsa_tech.capabilities, ast_format_slin, 0);
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
@@ -1042,7 +1039,9 @@ static int unload_module(void)
if (alsa.owner)
return -1;
- alsa_tech.capabilities = ast_format_cap_destroy(alsa_tech.capabilities);
+ ao2_cleanup(alsa_tech.capabilities);
+ alsa_tech.capabilities = NULL;
+
return 0;
}
diff --git a/channels/chan_bridge_media.c b/channels/chan_bridge_media.c
index ac15e7d70..6502b5c77 100644
--- a/channels/chan_bridge_media.c
+++ b/channels/chan_bridge_media.c
@@ -164,11 +164,13 @@ static struct ast_channel *record_request(const char *type, struct ast_format_ca
static void cleanup_capabilities(void)
{
if (announce_tech.capabilities) {
- announce_tech.capabilities = ast_format_cap_destroy(announce_tech.capabilities);
+ ao2_ref(announce_tech.capabilities, -1);
+ announce_tech.capabilities = NULL;
}
if (record_tech.capabilities) {
- record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities);
+ ao2_ref(record_tech.capabilities, -1);
+ record_tech.capabilities = NULL;
}
}
@@ -182,18 +184,18 @@ static int unload_module(void)
static int load_module(void)
{
- announce_tech.capabilities = ast_format_cap_alloc(0);
+ announce_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!announce_tech.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- record_tech.capabilities = ast_format_cap_alloc(0);
+ record_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!record_tech.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all(announce_tech.capabilities);
- ast_format_cap_add_all(record_tech.capabilities);
+ ast_format_cap_append_by_type(announce_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_by_type(record_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (ast_channel_register(&announce_tech)) {
ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
diff --git a/channels/chan_console.c b/channels/chan_console.c
index b1f5cdf7c..3aeda931a 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*!
* \brief The sample rate to request from PortAudio
@@ -270,12 +271,12 @@ static void *stream_monitor(void *data)
PaError res;
struct ast_frame f = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin16,
.src = "console_stream_monitor",
.data.ptr = buf,
.datalen = sizeof(buf),
.samples = sizeof(buf) / sizeof(int16_t),
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0);
for (;;) {
pthread_testcancel();
@@ -421,19 +422,28 @@ static int stop_stream(struct console_pvt *pvt)
*/
static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps;
struct ast_channel *chan;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL,
ext, ctx, assignedids, requestor, 0, "Console/%s", pvt->name))) {
+ ao2_ref(caps, -1);
return NULL;
}
ast_channel_stage_snapshot(chan);
ast_channel_tech_set(chan, &console_tech);
- ast_format_set(ast_channel_readformat(chan), AST_FORMAT_SLINEAR16, 0);
- ast_format_set(ast_channel_writeformat(chan), AST_FORMAT_SLINEAR16, 0);
- ast_format_cap_add(ast_channel_nativeformats(chan), ast_channel_readformat(chan));
+ ast_channel_set_readformat(chan, ast_format_slin16);
+ ast_channel_set_writeformat(chan, ast_format_slin16);
+ ast_format_cap_append(caps, ast_format_slin16, 0);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
ast_channel_tech_pvt_set(chan, ref_pvt(pvt));
pvt->owner = chan;
@@ -462,15 +472,16 @@ static struct ast_channel *console_request(const char *type, struct ast_format_c
{
struct ast_channel *chan = NULL;
struct console_pvt *pvt;
- char buf[512];
if (!(pvt = find_pvt(data))) {
ast_log(LOG_ERROR, "Console device '%s' not found\n", data);
return NULL;
}
- if (!(ast_format_cap_has_joint(cap, console_tech.capabilities))) {
- ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (!(ast_format_cap_iscompatible(cap, console_tech.capabilities))) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n",
+ ast_format_cap_get_names(cap, &cap_buf));
goto return_unref;
}
@@ -1467,7 +1478,8 @@ static void stop_streams(void)
static int unload_module(void)
{
- console_tech.capabilities = ast_format_cap_destroy(console_tech.capabilities);
+ ao2_ref(console_tech.capabilities, -1);
+ console_tech.capabilities = NULL;
ast_channel_unregister(&console_tech);
ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
@@ -1495,13 +1507,12 @@ static int unload_module(void)
*/
static int load_module(void)
{
- struct ast_format tmpfmt;
PaError res;
- if (!(console_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(console_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(console_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0));
+ ast_format_cap_append(console_tech.capabilities, ast_format_slin16, 0);
init_pvt(&globals, NULL);
@@ -1538,6 +1549,8 @@ return_error:
if (pvts)
ao2_ref(pvts, -1);
pvts = NULL;
+ ao2_ref(console_tech.capabilities, -1);
+ console_tech.capabilities = NULL;
pvt_destructor(&globals);
return AST_MODULE_LOAD_DECLINE;
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 81242533e..c22833da5 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -129,6 +129,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/parking.h"
+#include "asterisk/format_cache.h"
#include "chan_dahdi.h"
#include "dahdi/bridge_native_dahdi.h"
@@ -461,7 +462,7 @@ static struct ast_jb_conf global_jbconf;
/*! \brief Typically, how many rings before we should send Caller*ID */
#define DEFAULT_CIDRINGS 1
-#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
+#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
/*! \brief Signaling types that need to use MF detection should be placed in this macro */
@@ -1321,7 +1322,6 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e
int res;
unsigned char buf[256];
int flags;
- struct ast_format tmpfmt;
poller.fd = p->subs[SUB_REAL].dfd;
poller.events = POLLPRI | POLLIN;
@@ -1354,9 +1354,9 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e
}
if (p->cid_signalling == CID_SIG_V23_JP) {
- res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
} else {
- res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed(p->cs, buf, res, AST_LAW(p));
}
if (res < 0) {
/*
@@ -1525,7 +1525,7 @@ static int restore_conference(struct dahdi_pvt *p);
static int my_callwait(void *pvt)
{
struct dahdi_pvt *p = pvt;
- struct ast_format tmpfmt;
+
p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
if (p->cidspill) {
ast_log(LOG_WARNING, "Spill already exists?!?\n");
@@ -1542,11 +1542,11 @@ static int my_callwait(void *pvt)
/* Silence */
memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
if (!p->callwaitrings && p->callwaitingcallerid) {
- ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
p->callwaitcas = 1;
p->cidlen = 2400 + 680 + READ_SIZE * 4;
} else {
- ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
p->callwaitcas = 0;
p->cidlen = 2400 + READ_SIZE * 4;
}
@@ -1559,7 +1559,6 @@ static int my_callwait(void *pvt)
static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
{
struct dahdi_pvt *p = pvt;
- struct ast_format tmpfmt;
ast_debug(2, "Starting cid spill\n");
@@ -1573,7 +1572,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle
p->cidlen = ast_callerid_generate(p->cidspill,
caller->id.name.str,
caller->id.number.str,
- ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ AST_LAW(p));
} else {
ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
caller->id.name.str, caller->id.number.str);
@@ -1582,7 +1581,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle
p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
caller->id.name.str,
caller->id.number.str,
- ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ AST_LAW(p));
p->cidlen += READ_SIZE * 4;
}
p->cidpos = 0;
@@ -4965,14 +4964,12 @@ static int restore_conference(struct dahdi_pvt *p)
static int send_cwcidspill(struct dahdi_pvt *p)
{
- struct ast_format tmpfmt;
-
p->callwaitcas = 0;
p->cidcwexpire = 0;
p->cid_suppress_expire = 0;
if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
return -1;
- p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
/* Make sure we account for the end */
p->cidlen += READ_SIZE * 4;
p->cidpos = 0;
@@ -5038,7 +5035,7 @@ static int send_callerid(struct dahdi_pvt *p)
static int dahdi_callwait(struct ast_channel *ast)
{
struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
- struct ast_format tmpfmt;
+
p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
if (p->cidspill) {
ast_log(LOG_WARNING, "Spill already exists?!?\n");
@@ -5055,11 +5052,11 @@ static int dahdi_callwait(struct ast_channel *ast)
/* Silence */
memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
if (!p->callwaitrings && p->callwaitingcallerid) {
- ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
p->callwaitcas = 1;
p->cidlen = 2400 + 680 + READ_SIZE * 4;
} else {
- ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
p->callwaitcas = 0;
p->cidlen = 2400 + READ_SIZE * 4;
}
@@ -8504,25 +8501,20 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
return f;
}
- if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
if (!p->subs[idx].linear) {
p->subs[idx].linear = 1;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
}
- } else if ((ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) ||
- (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ALAW)) {
+ } else {
if (p->subs[idx].linear) {
p->subs[idx].linear = 0;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
if (res)
ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
}
- } else {
- ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
- ast_mutex_unlock(&p->lock);
- return NULL;
}
readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
CHECK_BLOCKING(ast);
@@ -8612,7 +8604,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
}
p->subs[idx].f.frametype = AST_FRAME_VOICE;
- ast_format_copy(&p->subs[idx].f.subclass.format, ast_channel_rawreadformat(ast));
+ p->subs[idx].f.subclass.format = ast_channel_rawreadformat(ast);
p->subs[idx].f.samples = READ_SIZE;
p->subs[idx].f.mallocd = 0;
p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
@@ -8795,12 +8787,6 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
return 0;
}
- if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
- (frame->subclass.format.id != AST_FORMAT_ULAW) &&
- (frame->subclass.format.id != AST_FORMAT_ALAW)) {
- ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
- return -1;
- }
if (p->dialing) {
ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
return 0;
@@ -8818,7 +8804,7 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
if (!frame->data.ptr || !frame->datalen)
return 0;
- if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
if (!p->subs[idx].linear) {
p->subs[idx].linear = 1;
res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
@@ -8826,7 +8812,8 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
}
res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
- } else {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL
+ || ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
/* x-law already */
if (p->subs[idx].linear) {
p->subs[idx].linear = 0;
@@ -8835,6 +8822,10 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
}
res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
+ } else {
+ ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
+ ast_format_get_name(frame->subclass.format));
+ return -1;
}
if (res < 0) {
ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
@@ -9024,7 +9015,8 @@ static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state
static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid)
{
struct ast_channel *tmp;
- struct ast_format deflaw;
+ struct ast_format_cap *caps;
+ struct ast_format *deflaw;
int x;
int features;
struct ast_str *chan_name;
@@ -9037,7 +9029,6 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
return NULL;
}
- ast_format_clear(&deflaw);
#if defined(HAVE_PRI)
/*
* The dnid has been stuffed with the called-number[:subaddress]
@@ -9051,9 +9042,16 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
return NULL;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_free(chan_name);
+ return NULL;
+ }
+
tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
ast_free(chan_name);
if (!tmp) {
+ ao2_ref(caps, -1);
return NULL;
}
@@ -9073,9 +9071,9 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
if (law) {
i->law = law;
if (law == DAHDI_LAW_ALAW) {
- ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
+ deflaw = ast_format_alaw;
} else {
- ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
+ deflaw = ast_format_ulaw;
}
} else {
switch (i->sig) {
@@ -9089,18 +9087,20 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
break;
}
if (i->law_default == DAHDI_LAW_ALAW) {
- ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
+ deflaw = ast_format_alaw;
} else {
- ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
+ deflaw = ast_format_ulaw;
}
}
ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
- ast_format_cap_add(ast_channel_nativeformats(tmp), &deflaw);
+ ast_format_cap_append(caps, deflaw, 0);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
/* Start out assuming ulaw since it's smaller :) */
- ast_format_copy(ast_channel_rawreadformat(tmp), &deflaw);
- ast_format_copy(ast_channel_readformat(tmp), &deflaw);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &deflaw);
- ast_format_copy(ast_channel_writeformat(tmp), &deflaw);
+ ast_channel_set_rawreadformat(tmp, deflaw);
+ ast_channel_set_readformat(tmp, deflaw);
+ ast_channel_set_rawwriteformat(tmp, deflaw);
+ ast_channel_set_writeformat(tmp, deflaw);
i->subs[idx].linear = 0;
dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
features = 0;
@@ -9397,7 +9397,6 @@ static void *analog_ss_thread(void *data)
int len = 0;
int res;
int idx;
- struct ast_format tmpfmt;
RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
const char *pickupexten;
@@ -10114,9 +10113,9 @@ static void *analog_ss_thread(void *data)
samples += res;
if (p->cid_signalling == CID_SIG_V23_JP) {
- res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
} else {
- res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed(cs, buf, res, AST_LAW(p));
}
if (res < 0) {
/*
@@ -10399,7 +10398,7 @@ static void *analog_ss_thread(void *data)
}
}
samples += res;
- res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
+ res = callerid_feed(cs, buf, res, AST_LAW(p));
if (res < 0) {
/*
* The previous diagnostic message output likely
@@ -10569,7 +10568,7 @@ struct mwi_thread_data {
size_t len;
};
-static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
+static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
{
int x;
int sum = 0;
@@ -10578,7 +10577,7 @@ static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law
return 0;
for (x = 0; x < len; x++)
- sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
+ sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
return sum / len;
}
@@ -10594,13 +10593,12 @@ static void *mwi_thread(void *data)
int i, res;
unsigned int spill_done = 0;
int spill_result = -1;
- struct ast_format tmpfmt;
if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
goto quit_no_clean;
}
- callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
+ callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
bump_gains(mtd->pvt);
@@ -10686,7 +10684,7 @@ static void *mwi_thread(void *data)
}
samples += res;
if (!spill_done) {
- if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
+ if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
/*
* The previous diagnostic message output likely
* explains why it failed.
@@ -10744,7 +10742,6 @@ quit_no_clean:
static int mwi_send_init(struct dahdi_pvt * pvt)
{
int x;
- struct ast_format tmpfmt;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
/* Determine how this spill is to be sent */
@@ -10786,8 +10783,8 @@ static int mwi_send_init(struct dahdi_pvt * pvt)
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
if (pvt->mwisend_fsk) {
#endif
- pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
- ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
+ pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt),
+ CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
pvt->cidpos = 0;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
}
@@ -17314,7 +17311,8 @@ static int __unload_module(void)
dahdi_native_unload();
- dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
+ ao2_cleanup(dahdi_tech.capabilities);
+ dahdi_tech.capabilities = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
return 0;
}
@@ -19496,7 +19494,6 @@ static const struct ast_data_entry dahdi_data_providers[] = {
static int load_module(void)
{
int res;
- struct ast_format tmpfmt;
#if defined(HAVE_PRI) || defined(HAVE_SS7)
int y;
#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
@@ -19505,14 +19502,15 @@ static int load_module(void)
return AST_MODULE_LOAD_FAILURE;
}
- if (!(dahdi_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(dahdi_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(dahdi_tech.capabilities, ast_format_slin, 0);
+ ast_format_cap_append(dahdi_tech.capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(dahdi_tech.capabilities, ast_format_alaw, 0);
if (dahdi_native_load(ast_module_info->self, &dahdi_tech)) {
+ ao2_ref(dahdi_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
@@ -19558,8 +19556,10 @@ static int load_module(void)
#endif /* defined(HAVE_SS7) */
res = setup_dahdi(0);
/* Make sure we can register our DAHDI channel type */
- if (res)
+ if (res) {
+ __unload_module();
return AST_MODULE_LOAD_DECLINE;
+ }
if (ast_channel_register(&dahdi_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
__unload_module();
@@ -19652,10 +19652,9 @@ static int dahdi_sendtext(struct ast_channel *c, const char *text)
return -1;
mybuf = buf;
if (p->mate) {
- struct ast_format tmp;
/* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
- struct ast_format *codec = &tmp;
- ast_format_set(codec, AST_LAW(p), 0);
+ struct ast_format *codec = AST_LAW(p);
+
for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
PUT_CLID_MARKMS;
}
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 4beacfb22..be5b4c751 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -116,11 +116,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis.h"
#include "asterisk/stasis_system.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cap.h"
#include "iax2/include/iax2.h"
#include "iax2/include/firmware.h"
#include "iax2/include/parser.h"
#include "iax2/include/provision.h"
+#include "iax2/include/codec_pref.h"
+#include "iax2/include/format_compatibility.h"
+
#include "jitterbuf.h"
/*** DOCUMENTATION
@@ -279,7 +285,7 @@ static int nochecksums = 0;
/* Sample over last 100 units to determine historic jitter */
#define GAMMA (0.01)
-static struct ast_codec_pref prefs;
+static struct iax2_codec_pref prefs;
static const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)";
@@ -347,22 +353,22 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF
/* T1, maybe ISDN */
#define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SLINEAR) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SLINEAR16) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SIREN7) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_SIREN14) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G719) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_ULAW) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_ALAW) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G722))
+ ~ast_format_compatibility_format2bitfield(ast_format_slin) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_slin16) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_siren7) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_siren14) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_g719) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_ulaw) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_alaw) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_g722))
/* A modem */
#define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G726) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G726_AAL2) & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_ADPCM))
+ ~ast_format_compatibility_format2bitfield(ast_format_g726) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_g726_aal2) & \
+ ~ast_format_compatibility_format2bitfield(ast_format_adpcm))
#define IAX_CAPABILITY_LOWFREE (IAX_CAPABILITY_LOWBANDWIDTH & \
- ~ast_format_id_to_old_bitfield(AST_FORMAT_G723_1))
+ ~ast_format_compatibility_format2bitfield(ast_format_g723))
#define DEFAULT_MAXMS 2000 /* Must be faster than 2 seconds by default */
@@ -503,7 +509,7 @@ struct iax2_user {
iax2_format capability;
int maxauthreq; /*!< Maximum allowed outstanding AUTHREQs */
int curauthreq; /*!< Current number of outstanding AUTHREQs */
- struct ast_codec_pref prefs;
+ struct iax2_codec_pref prefs;
struct ast_acl_list *acl;
struct iax2_context *contexts;
struct ast_variable *vars;
@@ -532,7 +538,7 @@ struct iax2_peer {
AST_STRING_FIELD(zonetag); /*!< Time Zone */
AST_STRING_FIELD(parkinglot); /*!< Default parkinglot for device */
);
- struct ast_codec_pref prefs;
+ struct iax2_codec_pref prefs;
struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager */
struct ast_sockaddr addr;
int formats;
@@ -708,9 +714,9 @@ struct chan_iax2_pvt {
/*! Peer Address */
struct ast_sockaddr addr;
/*! Actual used codec preferences */
- struct ast_codec_pref prefs;
+ struct iax2_codec_pref prefs;
/*! Requested codec preferences */
- struct ast_codec_pref rprefs;
+ struct iax2_codec_pref rprefs;
/*! Our call number */
unsigned short callno;
/*! Our callno_entry entry */
@@ -1809,17 +1815,18 @@ static iax2_format uncompress_subclass(unsigned char csub)
return csub;
}
-static iax2_format iax2_codec_choose(struct ast_codec_pref *pref, iax2_format formats, int find_best)
+static iax2_format iax2_codec_choose(struct iax2_codec_pref *pref, iax2_format formats, int find_best)
{
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
iax2_format format = 0;
- if ((cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
- ast_format_clear(&tmpfmt);
- ast_format_cap_from_old_bitfield(cap, formats);
- ast_codec_choose(pref, cap, find_best, &tmpfmt);
- format = ast_format_to_old_bitfield(&tmpfmt);
- cap = ast_format_cap_destroy(cap);
+
+ if ((cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ iax2_format_compatibility_bitfield2cap(formats, cap);
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ format = ast_format_compatibility_format2bitfield(tmpfmt);
+ ao2_ref(tmpfmt, -1);
+ ao2_ref(cap, -1);
}
return format;
@@ -1827,55 +1834,84 @@ static iax2_format iax2_codec_choose(struct ast_codec_pref *pref, iax2_format fo
static iax2_format iax2_best_codec(iax2_format formats)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmpfmt;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format *tmpfmt;
+ iax2_format format;
+
if (!cap) {
return 0;
}
- ast_format_clear(&tmpfmt);
- ast_format_cap_from_old_bitfield(cap, formats);
- ast_best_codec(cap, &tmpfmt);
- cap = ast_format_cap_destroy(cap);
- return ast_format_to_old_bitfield(&tmpfmt);
+ iax2_format_compatibility_bitfield2cap(formats, cap);
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ format = ast_format_compatibility_format2bitfield(tmpfmt);
+ ao2_ref(tmpfmt, -1);
+ ao2_ref(cap, -1);
+
+ return format;
}
const char *iax2_getformatname(iax2_format format)
{
- struct ast_format tmpfmt;
- if (!(ast_format_from_old_bitfield(&tmpfmt, format))) {
+ struct ast_format *tmpfmt;
+
+ tmpfmt = ast_format_compatibility_bitfield2format(format);
+ if (!tmpfmt) {
return "Unknown";
}
- return ast_getformatname(&tmpfmt);
+ return ast_format_get_name(tmpfmt);
}
-static char *iax2_getformatname_multiple(char *codec_buf, size_t len, iax2_format format)
+static const char *iax2_getformatname_multiple(iax2_format format, struct ast_str **codec_buf)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return "(Nothing)";
}
- ast_format_cap_from_old_bitfield(cap, format);
- ast_getformatname_multiple(codec_buf, len, cap);
- cap = ast_format_cap_destroy(cap);
+ iax2_format_compatibility_bitfield2cap(format, cap);
+ ast_format_cap_get_names(cap, codec_buf);
+ ao2_ref(cap, -1);
- return codec_buf;
+ return ast_str_buffer(*codec_buf);
}
-static int iax2_parse_allow_disallow(struct ast_codec_pref *pref, iax2_format *formats, const char *list, int allowing)
+static int iax2_parse_allow_disallow(struct iax2_codec_pref *pref, iax2_format *formats, const char *list, int allowing)
{
- int res;
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ int res, i;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+
if (!cap) {
return 1;
}
- ast_format_cap_from_old_bitfield(cap, *formats);
- res = ast_parse_allow_disallow(pref, cap, list, allowing);
- *formats = ast_format_cap_to_old_bitfield(cap);
- cap = ast_format_cap_destroy(cap);
+ /* We want to add the formats to the cap in the preferred order */
+ for (i = 0; i < IAX2_CODEC_PREF_SIZE; i++) {
+ uint64_t pref_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[i]);
+
+ if (!pref_as_bitfield) {
+ break;
+ }
+
+ if (iax2_format_compatibility_bitfield2cap(pref_as_bitfield, cap)) {
+ ao2_ref(cap, -1);
+ return 1;
+ }
+ }
+
+ res = ast_format_cap_update_by_allow_disallow(cap, list, allowing);
+ *formats = iax2_format_compatibility_cap2bitfield(cap);
+
+ iax2_codec_pref_remove_missing(pref, *formats);
+
+ for (i = 0; i < ast_format_cap_count(cap); i++) {
+ struct ast_format *fmt = ast_format_cap_get_format(cap, i);
+ iax2_codec_pref_append(pref, fmt, ast_format_cap_get_format_framing(cap, fmt));
+ ao2_ref(fmt, -1);
+ }
+
+ ao2_ref(cap, -1);
return res;
}
@@ -1883,13 +1919,13 @@ static int iax2_parse_allow_disallow(struct ast_codec_pref *pref, iax2_format *f
static int iax2_data_add_codecs(struct ast_data *root, const char *node_name, iax2_format formats)
{
int res;
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return -1;
}
- ast_format_cap_from_old_bitfield(cap, formats);
+ iax2_format_compatibility_bitfield2cap(formats, cap);
res = ast_data_add_codecs(root, node_name, cap);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return res;
}
@@ -3737,9 +3773,9 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct
char status[30];
char cbuf[256];
struct iax2_peer *peer;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_str *encmethods = ast_str_alloca(256);
- int x = 0, load_realtime = 0;
+ int load_realtime = 0;
switch (cmd) {
case CLI_INIT:
@@ -3789,23 +3825,13 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct
ast_cli(a->fd, " Defaddr->IP : %s Port %s\n", str_defaddr, str_defport);
ast_cli(a->fd, " Username : %s\n", peer->username);
ast_cli(a->fd, " Codecs : ");
- iax2_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
- ast_cli(a->fd, "%s\n", codec_buf);
+ ast_cli(a->fd, "%s\n", iax2_getformatname_multiple(peer->capability, &codec_buf));
- ast_cli(a->fd, " Codec Order : (");
- for(x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- struct ast_format tmpfmt;
- if(!(ast_codec_pref_index(&peer->prefs, x, &tmpfmt)))
- break;
- ast_cli(a->fd, "%s", ast_getformatname(&tmpfmt));
- if(x < 31 && ast_codec_pref_index(&peer->prefs, x+1, &tmpfmt))
- ast_cli(a->fd, "|");
+ ast_cli(a->fd, " Codec Order : ");
+ if (iax2_codec_pref_string(&peer->prefs, cbuf, sizeof(cbuf)) != -1) {
+ ast_cli(a->fd, "%s\n", cbuf);
}
- if (!x)
- ast_cli(a->fd, "none");
- ast_cli(a->fd, ")\n");
-
ast_cli(a->fd, " Status : ");
peer_status(peer, status, sizeof(status));
ast_cli(a->fd, "%s\n",status);
@@ -4084,9 +4110,9 @@ static void __get_from_jb(const void *p)
ms = ast_tvdiff_ms(now, pvt->rxcore);
if(ms >= (next = jb_next(pvt->jb))) {
- struct ast_format voicefmt;
- ast_format_from_old_bitfield(&voicefmt, pvt->voiceformat);
- ret = jb_get(pvt->jb, &frame, ms, ast_codec_interp_len(&voicefmt));
+ struct ast_format *voicefmt;
+ voicefmt = ast_format_compatibility_bitfield2format(pvt->voiceformat);
+ ret = jb_get(pvt->jb, &frame, ms, ast_format_get_default_ms(voicefmt));
switch(ret) {
case JB_OK:
fr = frame.data;
@@ -4100,8 +4126,8 @@ static void __get_from_jb(const void *p)
/* create an interpolation frame */
af.frametype = AST_FRAME_VOICE;
- ast_format_copy(&af.subclass.format, &voicefmt);
- af.samples = frame.ms * (ast_format_rate(&voicefmt) / 1000);
+ af.subclass.format = voicefmt;
+ af.samples = frame.ms * (ast_format_get_sample_rate(voicefmt) / 1000);
af.src = "IAX2 JB interpolation";
af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
af.offset = AST_FRIENDLY_OFFSET;
@@ -4182,7 +4208,7 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
if(fr->af.frametype == AST_FRAME_VOICE) {
type = JB_TYPE_VOICE;
- len = ast_codec_get_samples(&fr->af) / (ast_format_rate(&fr->af.subclass.format) / 1000);
+ len = ast_codec_samples_count(&fr->af) / (ast_format_get_sample_rate(fr->af.subclass.format) / 1000);
} else if(fr->af.frametype == AST_FRAME_CNG) {
type = JB_TYPE_SILENCE;
}
@@ -4579,7 +4605,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
{
struct iax2_peer *peer;
int res = -1;
- struct ast_codec_pref ourprefs;
+ struct iax2_codec_pref ourprefs;
ast_clear_flag64(cai, IAX_SENDANI | IAX_TRUNK);
cai->sockfd = defaultsockfd;
@@ -4604,14 +4630,16 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
/* But move the calling channel's native codec to the top of the preference list */
memcpy(&ourprefs, &prefs, sizeof(ourprefs));
if (c) {
- struct ast_format tmpfmt;
- ast_format_cap_iter_start(ast_channel_nativeformats(c));
- while (!(ast_format_cap_iter_next(ast_channel_nativeformats(c), &tmpfmt))) {
- ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1);
+ int i;
+
+ for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) {
+ struct ast_format *format = ast_format_cap_get_format(
+ ast_channel_nativeformats(c), i);
+ iax2_codec_pref_prepend(&ourprefs, format, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), format), 1);
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(ast_channel_nativeformats(c));
}
- ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
+ iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
return 0;
}
@@ -4635,15 +4663,16 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
/* Move the calling channel's native codec to the top of the preference list */
if (c) {
- struct ast_format tmpfmt;
- ast_format_cap_iter_start(ast_channel_nativeformats(c));
- while (!(ast_format_cap_iter_next(ast_channel_nativeformats(c), &tmpfmt))) {
- ast_debug(1, "prepending %s to prefs\n", ast_getformatname(&tmpfmt));
- ast_codec_pref_prepend(&ourprefs, &tmpfmt, 1);
+ int i;
+
+ for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) {
+ struct ast_format *tmpfmt = ast_format_cap_get_format(
+ ast_channel_nativeformats(c), i);
+ iax2_codec_pref_prepend(&ourprefs, tmpfmt, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), tmpfmt), 1);
+ ao2_ref(tmpfmt, -1);
}
- ast_format_cap_iter_end(ast_channel_nativeformats(c));
}
- ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
+ iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
ast_copy_string(cai->context, peer->context, sizeof(cai->context));
ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
ast_copy_string(cai->username, peer->username, sizeof(cai->username));
@@ -5181,7 +5210,7 @@ static int iax2_call(struct ast_channel *c, const char *dest, int timeout)
if (pds.password)
ast_string_field_set(iaxs[callno], secret, pds.password);
- iax2_tmpfmt = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(c));
+ iax2_tmpfmt = iax2_format_compatibility_cap2bitfield(ast_channel_nativeformats(c));
iax_ie_append_int(&ied, IAX_IE_FORMAT, (int) iax2_tmpfmt);
iax_ie_append_versioned_uint64(&ied, IAX_IE_FORMAT2, 0, iax2_tmpfmt);
@@ -5551,11 +5580,13 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha
return AST_BRIDGE_FAILED_NOWARN;
}
if (!(ast_format_cap_identical(ast_channel_nativeformats(c0), ast_channel_nativeformats(c1)))) {
- char buf0[256];
- char buf1[256];
- ast_getformatname_multiple(buf0, sizeof(buf0), ast_channel_nativeformats(c0));
- ast_getformatname_multiple(buf1, sizeof(buf1), ast_channel_nativeformats(c1));
- ast_verb(3, "Operating with different codecs [%s] [%s] , can't native bridge...\n", buf0, buf1);
+ struct ast_str *c0_buf = ast_str_alloca(64);
+ struct ast_str *c1_buf = ast_str_alloca(64);
+
+ ast_verb(3, "Operating with different codecs [%s] [%s] , can't native bridge...\n",
+ ast_format_cap_get_names(ast_channel_nativeformats(c0), &c0_buf),
+ ast_format_cap_get_names(ast_channel_nativeformats(c1), &c1_buf));
+
/* Remove from native mode */
lock_both(callno0, callno1);
if (iaxs[callno0])
@@ -5780,7 +5811,8 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
struct ast_channel *tmp;
struct chan_iax2_pvt *i;
struct ast_variable *v = NULL;
- struct ast_format tmpfmt;
+ struct ast_format_cap *native;
+ struct ast_format *tmpfmt;
struct ast_callid *callid;
if (!(i = iaxs[callno])) {
@@ -5788,6 +5820,11 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
return NULL;
}
+ native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!native) {
+ return NULL;
+ }
+
/* Don't hold call lock */
ast_mutex_unlock(&iaxsl[callno]);
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
@@ -5800,9 +5837,11 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
tmp = ast_channel_release(tmp);
ast_mutex_lock(&iaxsl[callno]);
}
+ ao2_ref(native, -1);
return NULL;
}
if (!tmp) {
+ ao2_ref(native, -1);
return NULL;
}
@@ -5813,14 +5852,19 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
}
ast_channel_tech_set(tmp, &iax2_tech);
+
/* We can support any format by default, until we get restricted */
- ast_format_cap_from_old_bitfield(ast_channel_nativeformats(tmp), capability);
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
+ iax2_format_compatibility_bitfield2cap(capability, native);
+ ast_channel_nativeformats_set(tmp, native);
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+
+ ao2_ref(tmpfmt, -1);
+ ao2_ref(native, -1);
ast_channel_tech_pvt_set(tmp, CALLNO_TO_PTR(i->callno));
@@ -5971,7 +6015,7 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
int voice = 0;
int genuine = 0;
int adjust;
- int rate = ast_format_rate(&f->subclass.format) / 1000;
+ int rate = 0;
struct timeval *delivery = NULL;
@@ -5983,6 +6027,7 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
*/
if (f->frametype == AST_FRAME_VOICE) {
voice = 1;
+ rate = ast_format_get_sample_rate(f->subclass.format) / 1000;
delivery = &f->delivery;
} else if (f->frametype == AST_FRAME_IAX) {
genuine = 1;
@@ -6092,8 +6137,9 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
}
}
p->lastsent = ms;
- if (voice)
+ if (voice) {
p->nextpred = p->nextpred + f->samples / rate;
+ }
return ms;
}
@@ -6344,9 +6390,9 @@ static int decode_frame(ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh,
memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
f->frametype = fh->type;
if (f->frametype == AST_FRAME_VIDEO) {
- ast_format_from_old_bitfield(&f->subclass.format, (uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1)));
+ f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1));
} else if (f->frametype == AST_FRAME_VOICE) {
- ast_format_from_old_bitfield(&f->subclass.format, uncompress_subclass(fh->csub));
+ f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub));
} else {
f->subclass.integer = uncompress_subclass(fh->csub);
}
@@ -6487,7 +6533,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
/* High two bytes are the same on timestamp, or sending on a trunk */ &&
(f->frametype == AST_FRAME_VOICE)
/* is a voice frame */ &&
- (f->subclass.format.id == ast_format_id_from_old_bitfield(pvt->svoiceformat))
+ (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svoiceformat)))
/* is the same type */ ) {
/* Force immediate rather than delayed transmission */
now = 1;
@@ -6501,7 +6547,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
* Otherwise send a mini video frame
*/
if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
- ((f->subclass.format.id) == ast_format_id_from_old_bitfield(pvt->svideoformat))
+ (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svideoformat)))
) {
now = 1;
sendmini = 1;
@@ -6556,11 +6602,11 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
fh->type = fr->af.frametype & 0xFF;
if (fr->af.frametype == AST_FRAME_VIDEO) {
- iax2_format tmpfmt = ast_format_to_old_bitfield(&fr->af.subclass.format);
- tmpfmt |= ast_format_get_video_mark(&fr->af.subclass.format) ? 0x1LL : 0;
+ iax2_format tmpfmt = ast_format_compatibility_format2bitfield(fr->af.subclass.format);
+ tmpfmt |= fr->af.subclass.frame_ending ? 0x1LL : 0;
fh->csub = compress_subclass(tmpfmt | ((tmpfmt & 0x1LL) << 6));
} else if (fr->af.frametype == AST_FRAME_VOICE) {
- fh->csub = compress_subclass(ast_format_to_old_bitfield(&fr->af.subclass.format));
+ fh->csub = compress_subclass(ast_format_compatibility_format2bitfield(fr->af.subclass.format));
} else {
fh->csub = compress_subclass(fr->af.subclass.integer);
}
@@ -6583,9 +6629,9 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
if ((f->frametype == AST_FRAME_IAX) && (f->subclass.integer == IAX_COMMAND_ACK))
fr->retries = -1;
else if (f->frametype == AST_FRAME_VOICE)
- pvt->svoiceformat = ast_format_to_old_bitfield(&f->subclass.format);
+ pvt->svoiceformat = ast_format_compatibility_format2bitfield(f->subclass.format);
else if (f->frametype == AST_FRAME_VIDEO)
- pvt->svideoformat = ast_format_to_old_bitfield(&f->subclass.format);
+ pvt->svideoformat = ast_format_compatibility_format2bitfield(f->subclass.format);
if (ast_test_flag64(pvt, IAX_ENCRYPTED)) {
if (ast_test_flag64(pvt, IAX_KEYPOPULATED)) {
if (fr->transfer)
@@ -6616,7 +6662,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
vh = (struct ast_iax2_video_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_video_hdr));
vh->zeros = 0;
vh->callno = htons(0x8000 | fr->callno);
- vh->ts = htons((fr->ts & 0x7FFF) | (ast_format_get_video_mark(&fr->af.subclass.format) ? 0x8000 : 0));
+ vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass.frame_ending ? 0x8000 : 0));
fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
fr->data = vh;
fr->retries = -1;
@@ -7767,8 +7813,8 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i
/* Use provided preferences until told otherwise for actual preferences */
if (ies->codec_prefs) {
- ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
- ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
+ iax2_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
+ iax2_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
}
if (!gotcapability) {
@@ -9827,7 +9873,7 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s
ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n");
iax2_vnak(fr->callno);
} else {
- ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat);
+ f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat);
f.datalen = len;
if (f.datalen >= 0) {
if (f.datalen)
@@ -9847,7 +9893,7 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s
f.mallocd = 0;
f.offset = 0;
if (f.datalen && (f.frametype == AST_FRAME_VOICE))
- f.samples = ast_codec_get_samples(&f);
+ f.samples = ast_codec_samples_count(&f);
else
f.samples = 0;
fr->outoforder = 0;
@@ -10004,7 +10050,7 @@ static int socket_process_helper(struct iax2_thread *thread)
struct iax_frame *duped_fr;
char host_pref_buf[128];
char caller_pref_buf[128];
- struct ast_codec_pref pref;
+ struct iax2_codec_pref pref;
char *using_prefs = "mine";
/* allocate an iax_frame with 4096 bytes of data buffer */
@@ -10069,12 +10115,12 @@ static int socket_process_helper(struct iax2_thread *thread)
/* Retrieve the type and subclass */
f.frametype = fh->type;
if (f.frametype == AST_FRAME_VIDEO) {
- ast_format_from_old_bitfield(&f.subclass.format, (uncompress_subclass(fh->csub & ~0x40)));
+ f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40));
if ((fh->csub >> 6) & 0x1) {
- ast_format_set_video_mark(&f.subclass.format);
+ f.subclass.frame_ending = 1;
}
} else if (f.frametype == AST_FRAME_VOICE) {
- ast_format_from_old_bitfield(&f.subclass.format, uncompress_subclass(fh->csub));
+ f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub));
} else {
f.subclass.integer = uncompress_subclass(fh->csub);
}
@@ -10498,22 +10544,21 @@ static int socket_process_helper(struct iax2_thread *thread)
}
if (f.frametype == AST_FRAME_VOICE) {
- if (ast_format_to_old_bitfield(&f.subclass.format) != iaxs[fr->callno]->voiceformat) {
- iaxs[fr->callno]->voiceformat = ast_format_to_old_bitfield(&f.subclass.format);
- ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_getformatname(&f.subclass.format));
+ if (ast_format_compatibility_format2bitfield(f.subclass.format) != iaxs[fr->callno]->voiceformat) {
+ iaxs[fr->callno]->voiceformat = ast_format_compatibility_format2bitfield(f.subclass.format);
+ ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_format_get_name(f.subclass.format));
if (iaxs[fr->callno]->owner) {
iax2_lock_owner(fr->callno);
if (iaxs[fr->callno]) {
if (iaxs[fr->callno]->owner) {
- struct ast_format_cap *orignative = ast_format_cap_dup(ast_channel_nativeformats(iaxs[fr->callno]->owner));
- struct ast_format_cap *native = ast_channel_nativeformats(iaxs[fr->callno]->owner);
- if (orignative) {
- ast_format_cap_set(native, &f.subclass.format);
- if (ast_channel_readformat(iaxs[fr->callno]->owner)->id) {
+ struct ast_format_cap *native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (native) {
+ ast_format_cap_append(native, f.subclass.format, 0);
+ ast_channel_nativeformats_set(iaxs[fr->callno]->owner, native);
+ if (ast_channel_readformat(iaxs[fr->callno]->owner)) {
ast_set_read_format(iaxs[fr->callno]->owner, ast_channel_readformat(iaxs[fr->callno]->owner));
}
- ast_format_cap_copy(native, orignative);
- orignative = ast_format_cap_destroy(orignative);
+ ao2_ref(native, -1);
}
ast_channel_unlock(iaxs[fr->callno]->owner);
}
@@ -10532,9 +10577,9 @@ static int socket_process_helper(struct iax2_thread *thread)
}
}
if (f.frametype == AST_FRAME_VIDEO) {
- if (f.subclass.format.id != ast_format_id_from_old_bitfield(iaxs[fr->callno]->videoformat)) {
- ast_debug(1, "Ooh, video format changed to %s\n", ast_getformatname(&f.subclass.format));
- iaxs[fr->callno]->videoformat = ast_format_to_old_bitfield(&f.subclass.format);
+ if (ast_format_compatibility_format2bitfield(f.subclass.format) != iaxs[fr->callno]->videoformat) {
+ ast_debug(1, "Ooh, video format changed to %s\n", ast_format_get_name(f.subclass.format));
+ iaxs[fr->callno]->videoformat = ast_format_compatibility_format2bitfield(f.subclass.format);
}
}
if (f.frametype == AST_FRAME_IAX) {
@@ -10697,12 +10742,12 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf, "disabled");
strcpy(host_pref_buf, "disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
/* If the information elements are in here... use them */
if (ies.codec_prefs)
- ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ iax2_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
/* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->rprefs;
@@ -10714,8 +10759,8 @@ static int socket_process_helper(struct iax2_thread *thread)
pref = iaxs[fr->callno]->prefs;
format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
- ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
- ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
}
if (!format) {
if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP))
@@ -10729,18 +10774,21 @@ static int socket_process_helper(struct iax2_thread *thread)
break;
}
if (authdebug) {
- char tmp[256], tmp2[256], tmp3[256];
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
} else {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
}
} else {
@@ -10756,9 +10804,9 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf,"disabled");
strcpy(host_pref_buf,"disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
/* Do the opposite of what we tried above. */
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->prefs;
@@ -10773,11 +10821,14 @@ static int socket_process_helper(struct iax2_thread *thread)
}
if (!format) {
- char tmp[256], tmp2[256], tmp3[256];
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
- ast_log(LOG_ERROR, "No best format in '%s'???\n", iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability));
+ ast_log(LOG_ERROR, "No best format in '%s'???\n", iax2_getformatname_multiple(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, &cap_buf));
send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
if (!iaxs[fr->callno]) {
break;
@@ -10785,9 +10836,9 @@ static int socket_process_helper(struct iax2_thread *thread)
if (authdebug) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
break;
@@ -10935,7 +10986,7 @@ static int socket_process_helper(struct iax2_thread *thread)
iaxs[fr->callno]->peerformat = ies.format;
} else {
if (iaxs[fr->callno]->owner)
- iaxs[fr->callno]->peerformat = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner));
+ iaxs[fr->callno]->peerformat = iax2_format_compatibility_cap2bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner));
else
iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability;
}
@@ -10950,28 +11001,36 @@ static int socket_process_helper(struct iax2_thread *thread)
break;
}
if (authdebug) {
- char tmp1[256], tmp2[256];
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_NOTICE, "Rejected call to %s, format %s incompatible with our capability %s.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
} else {
+ struct ast_format_cap *native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
iax2_lock_owner(fr->callno);
- if (iaxs[fr->callno] && iaxs[fr->callno]->owner) {
- char tmp[256];
+ if (iaxs[fr->callno] && iaxs[fr->callno]->owner && native) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
/* Switch us to use a compatible format */
- ast_format_cap_from_old_bitfield(ast_channel_nativeformats(iaxs[fr->callno]->owner), iaxs[fr->callno]->peerformat);
- ast_verb(3, "Format for call is %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(iaxs[fr->callno]->owner)));
+ iax2_format_compatibility_bitfield2cap(iaxs[fr->callno]->peerformat, native);
+ ast_channel_nativeformats_set(iaxs[fr->callno]->owner, native);
+ ast_verb(3, "Format for call is %s\n", ast_format_cap_get_names(ast_channel_nativeformats(iaxs[fr->callno]->owner), &cap_buf));
/* Setup read/write formats properly. */
- if (ast_channel_writeformat(iaxs[fr->callno]->owner)->id)
+ if (ast_channel_writeformat(iaxs[fr->callno]->owner))
ast_set_write_format(iaxs[fr->callno]->owner, ast_channel_writeformat(iaxs[fr->callno]->owner));
- if (ast_channel_readformat(iaxs[fr->callno]->owner)->id)
+ if (ast_channel_readformat(iaxs[fr->callno]->owner))
ast_set_read_format(iaxs[fr->callno]->owner, ast_channel_readformat(iaxs[fr->callno]->owner));
ast_channel_unlock(iaxs[fr->callno]->owner);
}
+
+ ao2_cleanup(native);
}
if (iaxs[fr->callno]) {
AST_LIST_LOCK(&dpcache);
@@ -11140,11 +11199,11 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf, "disabled");
strcpy(host_pref_buf, "disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
if (ies.codec_prefs)
- ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ iax2_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->rprefs;
using_prefs = "caller";
@@ -11154,15 +11213,18 @@ static int socket_process_helper(struct iax2_thread *thread)
} else /* if no codec_prefs IE do it the old way */
pref = iaxs[fr->callno]->prefs;
format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
- ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
- ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
+ iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
}
if (!format) {
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_debug(1, "We don't do requested format %s, falling back to peer capability '%s'\n",
iax2_getformatname(iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf));
format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
}
if (!format) {
@@ -11170,14 +11232,14 @@ static int socket_process_helper(struct iax2_thread *thread)
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
} else {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
}
memset(&ied0, 0, sizeof(ied0));
@@ -11201,9 +11263,9 @@ static int socket_process_helper(struct iax2_thread *thread)
strcpy(caller_pref_buf,"disabled");
strcpy(host_pref_buf,"disabled");
} else {
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
using_prefs = "mine";
- if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
+ if (iax2_codec_pref_index(&iaxs[fr->callno]->rprefs, 0, &tmpfmt)) {
/* Do the opposite of what we tried above. */
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
pref = iaxs[fr->callno]->prefs;
@@ -11217,21 +11279,24 @@ static int socket_process_helper(struct iax2_thread *thread)
}
}
if (!format) {
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *peer_form_buf = ast_str_alloca(64);
+
ast_log(LOG_ERROR, "No best format in %s???\n",
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, &cap_buf));
if (authdebug) {
if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested '%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
} else {
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp1, sizeof(tmp1), iaxs[fr->callno]->peerformat),
- iax2_getformatname_multiple(tmp2, sizeof(tmp2), iaxs[fr->callno]->peercapability),
- iax2_getformatname_multiple(tmp3, sizeof(tmp3), iaxs[fr->callno]->capability));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &peer_form_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->peercapability, &peer_buf),
+ iax2_getformatname_multiple(iaxs[fr->callno]->capability, &cap_buf));
}
}
memset(&ied0, 0, sizeof(ied0));
@@ -11338,11 +11403,11 @@ immediatedial:
break;
}
} else {
- char tmp[256];
+ struct ast_str *cap_buf = ast_str_alloca(64);
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
ast_verb(3, "Accepting DIAL from %s, formats = %s\n",
ast_sockaddr_stringify(&addr),
- iax2_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat));
+ iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &cap_buf));
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat, NULL, NULL, 1)))
@@ -11662,9 +11727,9 @@ immediatedial:
f.frametype = AST_FRAME_VIDEO;
if (iaxs[fr->callno]->videoformat > 0) {
if (ntohs(vh->ts) & 0x8000LL) {
- ast_format_set_video_mark(&f.subclass.format);
+ f.subclass.frame_ending = 1;
}
- ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->videoformat);
+ f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->videoformat);
} else {
ast_log(LOG_WARNING, "Received mini frame before first full video frame\n");
iax2_vnak(fr->callno);
@@ -11687,7 +11752,7 @@ immediatedial:
/* A mini frame */
f.frametype = AST_FRAME_VOICE;
if (iaxs[fr->callno]->voiceformat > 0)
- ast_format_from_old_bitfield(&f.subclass.format, iaxs[fr->callno]->voiceformat);
+ f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat);
else {
ast_debug(1, "Received mini frame before first full voice frame\n");
iax2_vnak(fr->callno);
@@ -11795,9 +11860,9 @@ immediatedial:
f.offset = 0;
f.len = 0;
if (f.datalen && (f.frametype == AST_FRAME_VOICE)) {
- f.samples = ast_codec_get_samples(&f);
+ f.samples = ast_codec_samples_count(&f);
/* We need to byteswap incoming slinear samples from network byte order */
- if (f.subclass.format.id == AST_FORMAT_SLINEAR)
+ if (ast_format_cmp(f.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
ast_frame_byteswap_be(&f);
} else
f.samples = 0;
@@ -12376,32 +12441,48 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
if (c) {
struct ast_format_cap *joint;
+ struct ast_format *format;
if (callid) {
ast_channel_lock(c);
ast_channel_callid_set(c, callid);
ast_channel_unlock(c);
}
- /* Choose a format we can live with */
- if ((joint = ast_format_cap_joint(ast_channel_nativeformats(c), cap))) {
- ast_format_cap_copy(ast_channel_nativeformats(c), joint);
- joint = ast_format_cap_destroy(joint);
- } else {
- struct ast_format best_fmt_cap;
- struct ast_format best_fmt_native;
+ joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!joint) {
+ ast_hangup(c);
+ return NULL;
+ }
+
+ ast_format_cap_get_compatible(ast_channel_nativeformats(c), cap, joint);
+
+ /* If there is no joint format find one through translation */
+ if (!ast_format_cap_count(joint)) {
+ struct ast_format *best_fmt_cap = NULL;
+ struct ast_format *best_fmt_native = NULL;
res = ast_translator_best_choice(cap, ast_channel_nativeformats(c), &best_fmt_cap, &best_fmt_native);
if (res < 0) {
- char tmp[256];
- char tmp2[256];
+ struct ast_str *native_cap_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(c)), ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_channel_name(c));
+ ast_format_cap_get_names(ast_channel_nativeformats(c), &native_cap_buf),
+ ast_format_cap_get_names(cap, &cap_buf),
+ ast_channel_name(c));
ast_hangup(c);
return NULL;
}
- ast_format_cap_set(ast_channel_nativeformats(c), &best_fmt_native);
+ ast_format_cap_append(joint, best_fmt_native, 0);
+ ao2_ref(best_fmt_cap, -1);
+ ao2_ref(best_fmt_native, -1);
}
- ast_best_codec(ast_channel_nativeformats(c), ast_channel_readformat(c));
- ast_format_copy(ast_channel_writeformat(c), ast_channel_readformat(c));
+ ast_channel_nativeformats_set(c, joint);
+ format = ast_format_cap_get_format(ast_channel_nativeformats(c), 0);
+ ast_channel_set_readformat(c, format);
+ ast_channel_set_writeformat(c, format);
+
+ ao2_ref(joint, -1);
+ ao2_ref(format, -1);
}
if (callid) {
@@ -13355,7 +13436,7 @@ static int set_config(const char *config_file, int reload, int forced)
ast_sockaddr_parse(&bindaddr, "0.0.0.0:0", 0);
/* Reset global codec prefs */
- memset(&prefs, 0 , sizeof(struct ast_codec_pref));
+ memset(&prefs, 0 , sizeof(struct iax2_codec_pref));
/* Reset Global Flags */
memset(&globalflags, 0, sizeof(globalflags));
@@ -14234,10 +14315,13 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat
} else if (!strcasecmp(colname, "callerid_num")) {
ast_copy_string(buf, peer->cid_num, len);
} else if (!strcasecmp(colname, "codecs")) {
- iax2_getformatname_multiple(buf, len -1, peer->capability);
+ struct ast_str *codec_buf;
+
+ iax2_getformatname_multiple(peer->capability, &codec_buf);
+ ast_copy_string(buf, ast_str_buffer(codec_buf), len);
} else if (!strncasecmp(colname, "codec[", 6)) {
char *codecnum, *ptr;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
/* skip over "codec" to the '[' */
codecnum = colname + 5;
@@ -14246,8 +14330,8 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat
if ((ptr = strchr(codecnum, ']'))) {
*ptr = '\0';
}
- if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &tmpfmt))) {
- ast_copy_string(buf, ast_getformatname(&tmpfmt), len);
+ if((iax2_codec_pref_index(&peer->prefs, atoi(codecnum), &tmpfmt))) {
+ ast_copy_string(buf, ast_format_get_name(tmpfmt), len);
} else {
buf[0] = '\0';
}
@@ -14604,7 +14688,8 @@ static int __unload_module(void)
ast_context_destroy(con, "IAX2");
ast_unload_realtime("iaxpeers");
- iax2_tech.capabilities = ast_format_cap_destroy(iax2_tech.capabilities);
+ ao2_ref(iax2_tech.capabilities, -1);
+ iax2_tech.capabilities = NULL;
return 0;
}
@@ -14914,10 +14999,10 @@ static int load_module(void)
int x = 0;
struct iax2_registry *reg = NULL;
- if (!(iax2_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(iax2_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add_all(iax2_tech.capabilities);
+ ast_format_cap_append_by_type(iax2_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (load_objects()) {
return AST_MODULE_LOAD_FAILURE;
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 2d0afe29d..6021b6c1d 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -86,6 +86,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/features_config.h"
#include "asterisk/parking.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*
* Define to work around buggy dlink MGCP phone firmware which
@@ -1199,9 +1200,20 @@ static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
if (sub->owner) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
- if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format)) {
- ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(sub->owner, caps);
+ ao2_ref(caps, -1);
+ } else {
+ return &ast_null_frame;
+ }
+
ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
}
@@ -1239,7 +1251,6 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
{
struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
int res = 0;
- char buf[256];
if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype == AST_FRAME_IMAGE)
@@ -1249,12 +1260,14 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
} else {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
/* return -1; */
}
}
@@ -1490,90 +1503,103 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps = NULL;
struct ast_channel *tmp;
struct ast_variable *v = NULL;
struct mgcp_endpoint *i = sub->parent;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Format capabilities could not be created\n");
+ return NULL;
+ }
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
- if (tmp) {
- ast_channel_stage_snapshot(tmp);
- ast_channel_tech_set(tmp, &mgcp_tech);
- ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
- ast_format_cap_copy(ast_channel_nativeformats(tmp), global_capability);
- }
- if (sub->rtp) {
- ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
- }
- if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
- i->dsp = ast_dsp_new();
- ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
- /* this is to prevent clipping of dtmf tones during dsp processing */
- ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
- } else {
- i->dsp = NULL;
- }
- if (state == AST_STATE_RING)
- ast_channel_rings_set(tmp, 1);
-
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_channel_tech_pvt_set(tmp, sub);
- if (!ast_strlen_zero(i->language))
- ast_channel_language_set(tmp, i->language);
- if (!ast_strlen_zero(i->accountcode))
- ast_channel_accountcode_set(tmp, i->accountcode);
- if (i->amaflags)
- ast_channel_amaflags_set(tmp, i->amaflags);
- mgcp_set_owner(sub, tmp);
- ast_module_ref(ast_module_info->self);
- ast_channel_callgroup_set(tmp, i->callgroup);
- ast_channel_pickupgroup_set(tmp, i->pickupgroup);
- ast_channel_call_forward_set(tmp, i->call_forward);
- ast_channel_context_set(tmp, i->context);
- ast_channel_exten_set(tmp, i->exten);
-
- /* Don't use ast_set_callerid() here because it will
- * generate a needless NewCallerID event */
- if (!ast_strlen_zero(i->cid_num)) {
- ast_channel_caller(tmp)->ani.number.valid = 1;
- ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
- }
-
- if (!i->adsi) {
- ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
- }
- ast_channel_priority_set(tmp, 1);
+ if (!tmp) {
+ ast_log(LOG_WARNING, "Channel could not be created\n");
+ ao2_ref(caps, -1);
+ return NULL;
+ }
- /* Set channel variables for this call from configuration */
- for (v = i->chanvars ; v ; v = v->next) {
- char valuebuf[1024];
- pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
- }
+ ast_channel_stage_snapshot(tmp);
+ ast_channel_tech_set(tmp, &mgcp_tech);
+ if (ast_format_cap_count(i->cap)) {
+ ast_format_cap_append_from_cap(caps, i->cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append_from_cap(caps, global_capability, AST_MEDIA_TYPE_UNKNOWN);
+ }
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+ if (sub->rtp) {
+ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
+ }
+ if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
+ i->dsp = ast_dsp_new();
+ ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
+ /* this is to prevent clipping of dtmf tones during dsp processing */
+ ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
+ } else {
+ i->dsp = NULL;
+ }
+ if (state == AST_STATE_RING) {
+ ast_channel_rings_set(tmp, 1);
+ }
+
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
+ ast_channel_tech_pvt_set(tmp, sub);
+ if (!ast_strlen_zero(i->language))
+ ast_channel_language_set(tmp, i->language);
+ if (!ast_strlen_zero(i->accountcode))
+ ast_channel_accountcode_set(tmp, i->accountcode);
+ if (i->amaflags)
+ ast_channel_amaflags_set(tmp, i->amaflags);
+ mgcp_set_owner(sub, tmp);
+ ast_module_ref(ast_module_info->self);
+ ast_channel_callgroup_set(tmp, i->callgroup);
+ ast_channel_pickupgroup_set(tmp, i->pickupgroup);
+ ast_channel_call_forward_set(tmp, i->call_forward);
+ ast_channel_context_set(tmp, i->context);
+ ast_channel_exten_set(tmp, i->exten);
+ /* Don't use ast_set_callerid() here because it will
+ * generate a needless NewCallerID event */
+ if (!ast_strlen_zero(i->cid_num)) {
+ ast_channel_caller(tmp)->ani.number.valid = 1;
+ ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
+ }
+
+ if (!i->adsi) {
+ ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
+ }
+ ast_channel_priority_set(tmp, 1);
+
+ /* Set channel variables for this call from configuration */
+ for (v = i->chanvars ; v ; v = v->next) {
+ char valuebuf[1024];
+ pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
+ }
- if (sub->rtp) {
- ast_jb_configure(tmp, &global_jbconf);
- }
+ if (sub->rtp) {
+ ast_jb_configure(tmp, &global_jbconf);
+ }
- ast_channel_stage_snapshot_done(tmp);
- ast_channel_unlock(tmp);
+ ast_channel_stage_snapshot_done(tmp);
+ ast_channel_unlock(tmp);
- if (state != AST_STATE_DOWN) {
- if (ast_pbx_start(tmp)) {
- ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
- ast_hangup(tmp);
- tmp = NULL;
- }
+ if (state != AST_STATE_DOWN) {
+ if (ast_pbx_start(tmp)) {
+ ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
+ ast_hangup(tmp);
+ tmp = NULL;
}
- ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
- ast_channel_name(tmp), ast_state2str(state));
- } else {
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
}
+ ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
+ ast_channel_name(tmp), ast_state2str(state));
+
return tmp;
}
@@ -1973,7 +1999,9 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
int codec, codec_count=0;
int iterator;
struct mgcp_endpoint *p = sub->parent;
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *global_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *pvt_buf = ast_str_alloca(64);
/* Get codec and RTP info from SDP */
m = get_sdp(req, "m");
@@ -2030,20 +2058,20 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
}
/* Now gather all of the codecs that were asked for: */
- if (!(peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return -1;
}
ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability);
- ast_format_cap_joint_copy(global_capability, peercap, p->cap);
+ ast_format_cap_get_compatible(global_capability, peercap, p->cap);
ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n",
- ast_getformatname_multiple(tmp1, sizeof(tmp1), global_capability),
- ast_getformatname_multiple(tmp2, sizeof(tmp2), peercap),
- ast_getformatname_multiple(tmp3, sizeof(tmp3), p->cap));
- peercap = ast_format_cap_destroy(peercap);
+ ast_format_cap_get_names(global_capability, &global_buf),
+ ast_format_cap_get_names(peercap, &peer_buf),
+ ast_format_cap_get_names(p->cap, &pvt_buf));
+ ao2_ref(peercap, -1);
ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n",
nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
- if (ast_format_cap_is_empty(p->cap)) {
+ if (!ast_format_cap_count(p->cap)) {
ast_log(LOG_WARNING, "No compatible codecs!\n");
return -1;
}
@@ -2201,7 +2229,6 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
char m[256] = "";
char a[1024] = "";
int x;
- struct ast_format tmpfmt;
struct sockaddr_in dest = { 0, };
struct ast_sockaddr dest_tmp;
struct mgcp_endpoint *p = sub->parent;
@@ -2236,24 +2263,25 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
ast_copy_string(t, "t=0 0\r\n", sizeof(t));
snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
- /* Audio is now discontiguous */
+ for (x = 0; x < ast_format_cap_count(p->cap); x++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, x);
+
+ if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(format, -1);
continue;
}
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- ast_debug(1, "Answering with capability %s\n", ast_getformatname(&tmpfmt));
- codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &tmpfmt, 0);
- if (codec > -1) {
- snprintf(costr, sizeof(costr), " %d", codec);
- strncat(m, costr, sizeof(m) - strlen(m) - 1);
- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(a, costr, sizeof(a) - strlen(a) - 1);
- }
+
+ ast_debug(1, "Answering with capability %s\n", ast_format_get_name(format));
+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, format, 0);
+ if (codec > -1) {
+ snprintf(costr, sizeof(costr), " %d", codec);
+ strncat(m, costr, sizeof(m) - strlen(m) - 1);
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
+ strncat(a, costr, sizeof(a) - strlen(a) - 1);
}
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
if (p->nonCodecCapability & x) {
@@ -2292,7 +2320,7 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_
char local[256];
char tmp[80];
struct mgcp_endpoint *p = sub->parent;
- struct ast_format tmpfmt;
+ int i;
struct ast_sockaddr sub_tmpdest_tmp;
unsigned int oseq;
@@ -2304,18 +2332,20 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_
return 0;
}
ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
- /* Audio is now discontiguous */
+
+ for (i = 0; i < ast_format_cap_count(p->cap); i++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, i);
+
+ if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(format, -1);
continue;
}
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
+
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
if (sub->gate) {
if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
@@ -2351,7 +2381,7 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
struct mgcp_request resp;
char local[256];
char tmp[80];
- struct ast_format tmpfmt;
+ int i;
struct mgcp_endpoint *p = sub->parent;
unsigned int oseq;
@@ -2360,18 +2390,19 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
- /* Audio is now discontiguous */
+ for (i = 0; i < ast_format_cap_count(p->cap); i++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, i);
+
+ if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(format, -1);
continue;
}
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
+
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
if (sub->gate) {
if(sub->gate->state == GATE_ALLOCATED) {
@@ -2447,22 +2478,23 @@ static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub)
static int transmit_connect(struct mgcp_subchannel *sub)
{
struct mgcp_request resp;
+ int x;
char local[256];
char tmp[80];
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
struct mgcp_endpoint *p = sub->parent;
unsigned int oseq;
ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
- if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
+ for (x = 0; x < ast_format_cap_count(p->cap); x++) {
+ tmpfmt = ast_format_cap_get_format(p->cap, x);
+
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, tmpfmt, 0, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(tmpfmt, -1);
}
- ast_format_cap_iter_end(p->cap);
ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
@@ -2557,7 +2589,7 @@ static int transmit_modify_request(struct mgcp_subchannel *sub)
{
struct mgcp_request resp;
struct mgcp_endpoint *p = sub->parent;
- struct ast_format tmpfmt;
+ int i;
int fc = 1;
char local[256];
char tmp[80];
@@ -2572,18 +2604,22 @@ static int transmit_modify_request(struct mgcp_subchannel *sub)
p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
ast_copy_string(local, "", sizeof(local));
- ast_format_cap_iter_start(p->cap);
- while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
+ for (i = 0; i < ast_format_cap_count(p->cap); i++) {
+ struct ast_format *format = ast_format_cap_get_format(p->cap, i);
+
if (p->ncs && !fc) {
- ast_format_cap_set(p->cap, &tmpfmt); /* sb5120e bug */
+ ast_format_cap_remove_by_type(p->cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->cap, format, 0); /* sb5120e bug */
+ ao2_ref(format, -1);
break;
} else {
fc = 0;
- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
}
strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(p->cap);
if (!sub->sdpsent) {
if (sub->gate) {
@@ -3948,8 +3984,10 @@ static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap
struct ast_channel *tmpc = NULL;
char tmp[256];
- if (!(ast_format_cap_has_joint(cap, global_capability))) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ if (!(ast_format_cap_iscompatible(cap, global_capability))) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
+ ast_format_cap_get_names(cap, &cap_buf));
/*return NULL;*/
}
ast_copy_string(tmp, dest, sizeof(tmp));
@@ -4185,7 +4223,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
ast_mutex_init(&e->lock);
ast_mutex_init(&e->rqnt_queue_lock);
ast_mutex_init(&e->cmd_queue_lock);
- e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
ast_copy_string(e->name, v->value, sizeof(e->name));
e->needaudit = 1;
}
@@ -4210,7 +4248,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
e->msgstate = -1;
e->amaflags = amaflags;
- ast_format_cap_copy(e->cap, global_capability);
+ ast_format_cap_append_from_cap(e->cap, global_capability, AST_MEDIA_TYPE_UNKNOWN);
e->parent = gw;
e->ncs = ncs;
e->dtmfmode = dtmfmode;
@@ -4292,7 +4330,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
ast_mutex_init(&e->lock);
ast_mutex_init(&e->rqnt_queue_lock);
ast_mutex_init(&e->cmd_queue_lock);
- e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ e->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
ast_copy_string(e->name, v->value, sizeof(e->name));
e->needaudit = 1;
}
@@ -4314,7 +4352,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
e->parent = gw;
}
e->amaflags = amaflags;
- ast_format_cap_copy(e->cap, global_capability);
+ ast_format_cap_append_from_cap(e->cap, global_capability, AST_MEDIA_TYPE_UNKNOWN);
e->dtmfmode = dtmfmode;
e->ncs = ncs;
e->pktcgatealloc = pktcgatealloc;
@@ -4470,7 +4508,8 @@ static void mgcp_get_codec(struct ast_channel *chan, struct ast_format_cap *resu
{
struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
struct mgcp_endpoint *p = sub->parent;
- ast_format_cap_copy(result, p->cap);
+
+ ast_format_cap_append_from_cap(result, p->cap, AST_MEDIA_TYPE_UNKNOWN);
}
static struct ast_rtp_glue mgcp_rtp_glue = {
@@ -4556,7 +4595,7 @@ static void destroy_endpoint(struct mgcp_endpoint *e)
ast_mutex_destroy(&e->lock);
ast_mutex_destroy(&e->rqnt_queue_lock);
ast_mutex_destroy(&e->cmd_queue_lock);
- e->cap = ast_format_cap_destroy(e->cap);
+ ao2_ref(e->cap, -1);
ast_free(e);
}
@@ -4654,7 +4693,6 @@ static int reload_config(int reload)
char *cat;
struct ast_hostent ahp;
struct hostent *hp;
- struct ast_format format;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
if (gethostname(ourhost, sizeof(ourhost)-1)) {
@@ -4694,19 +4732,9 @@ static int reload_config(int reload)
memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
}
} else if (!strcasecmp(v->name, "allow")) {
- ast_getformatbyname(v->value, &format);
- if (!format.id) {
- ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
- } else {
- ast_format_cap_add(global_capability, &format);
- }
+ ast_format_cap_update_by_allow_disallow(global_capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
- ast_getformatbyname(v->value, &format);
- if (!format.id) {
- ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
- } else {
- ast_format_cap_remove(global_capability, &format);
- }
+ ast_format_cap_update_by_allow_disallow(global_capability, v->value, 0);
} else if (!strcasecmp(v->name, "tos")) {
if (ast_str2tos(v->value, &qos.tos)) {
ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
@@ -4831,36 +4859,44 @@ static int reload_config(int reload)
*/
static int load_module(void)
{
- struct ast_format tmpfmt;
-
- if (!(global_capability = ast_format_cap_alloc(0))) {
+ if (!(global_capability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- if (!(mgcp_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(mgcp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ ao2_ref(global_capability, -1);
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(global_capability, ast_format_ulaw, 0);
+ ast_format_cap_append(mgcp_tech.capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(mgcp_tech.capabilities, ast_format_alaw, 0);
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
if (!(io = io_context_create())) {
ast_log(LOG_WARNING, "Unable to create I/O context\n");
ast_sched_context_destroy(sched);
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
- if (reload_config(0))
+ if (reload_config(0)) {
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_DECLINE;
+ }
/* Make sure we can register our mgcp channel type */
if (ast_channel_register(&mgcp_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
io_context_destroy(io);
ast_sched_context_destroy(sched);
+ ao2_ref(global_capability, -1);
+ ao2_ref(mgcp_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
@@ -4973,8 +5009,10 @@ static int unload_module(void)
ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
ast_sched_context_destroy(sched);
- global_capability = ast_format_cap_destroy(global_capability);
- mgcp_tech.capabilities = ast_format_cap_destroy(mgcp_tech.capabilities);
+ ao2_ref(global_capability, -1);
+ global_capability = NULL;
+ ao2_ref(mgcp_tech.capabilities, -1);
+ mgcp_tech.capabilities = NULL;
return 0;
}
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 47d5947c3..0774e3c15 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -120,6 +120,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/pickup.h"
+#include "asterisk/format_cache.h"
#include "chan_misdn_config.h"
#include "isdn_lib.h"
@@ -691,9 +692,6 @@ static const char misdn_type[] = "mISDN";
static int tracing = 0;
-/*! \brief Only alaw and mulaw is allowed for now */
-static struct ast_format prefformat; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
-
static int *misdn_debug;
static int *misdn_debug_only;
static int max_ports;
@@ -7436,7 +7434,7 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
}
tmp->frame.frametype = AST_FRAME_VOICE;
- ast_format_set(&tmp->frame.subclass.format, AST_FORMAT_ALAW, 0);
+ tmp->frame.subclass.format = ast_format_alaw;
tmp->frame.datalen = len;
tmp->frame.samples = len;
tmp->frame.mallocd = 0;
@@ -7501,13 +7499,14 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
}
- if (!frame->subclass.format.id) {
+ if (!frame->subclass.format) {
chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
return 0;
}
- if (ast_format_cmp(&frame->subclass.format, &prefformat) == AST_FORMAT_CMP_NOT_EQUAL) {
- chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(&frame->subclass.format));
+ if (ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL) {
+ chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n",
+ ast_format_get_name(frame->subclass.format));
return 0;
}
@@ -8174,12 +8173,18 @@ static void update_name(struct ast_channel *tmp, int port, int c)
static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int port, int c)
{
+ struct ast_format_cap *native;
struct ast_channel *tmp;
char *cid_name = NULL;
char *cid_num = NULL;
int chan_offset = 0;
int tmp_port = misdn_cfg_get_next_port(0);
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+
+ native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!native) {
+ return NULL;
+ }
for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
if (tmp_port == port) {
@@ -8199,12 +8204,15 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char
if (tmp) {
chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
- ast_best_codec(cap, &tmpfmt);
- ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(cap, 0);
+ ast_format_cap_append(native, ast_format_alaw, 0);
+ ast_channel_nativeformats_set(tmp, native);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+
+ ao2_ref(tmpfmt, -1);
/* Link the channel and private together */
chan_list_ref(chlist, "Give a reference to ast_channel");
@@ -8242,6 +8250,8 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char
chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
}
+ ao2_ref(native, -1);
+
return tmp;
}
@@ -10207,14 +10217,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ch->addr = bc->addr;
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmpfmt;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!(cap)) {
return RESPONSE_ERR;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(cap, ast_format_alaw, 0);
chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, NULL, bc->port, bc->channel);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
}
if (!chan) {
chan_list_unref(ch, "Failed to create a new channel");
@@ -10849,7 +10858,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
/* In Data Modes we queue frames */
memset(&frame, 0, sizeof(frame));
frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
- ast_format_set(&frame.subclass.format, AST_FORMAT_ALAW, 0);
+ frame.subclass.format = ast_format_alaw;
frame.datalen = bc->bframe_len;
frame.samples = bc->bframe_len;
frame.mallocd = 0;
@@ -11287,7 +11296,8 @@ static int unload_module(void)
#if defined(AST_MISDN_ENHANCEMENTS)
misdn_cc_destroy();
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
- misdn_tech.capabilities = ast_format_cap_destroy(misdn_tech.capabilities);
+ ao2_cleanup(misdn_tech.capabilities);
+ misdn_tech.capabilities = NULL;
return 0;
}
@@ -11316,11 +11326,10 @@ static int load_module(void)
};
- if (!(misdn_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(misdn_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_set(&prefformat, AST_FORMAT_ALAW, 0);
- ast_format_cap_add(misdn_tech.capabilities, &prefformat);
+ ast_format_cap_append(misdn_tech.capabilities, ast_format_alaw, 0);
max_ports = misdn_lib_maxports_get();
diff --git a/channels/chan_motif.c b/channels/chan_motif.c
index d853839ab..4b1d7d26b 100644
--- a/channels/chan_motif.c
+++ b/channels/chan_motif.c
@@ -77,6 +77,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/abstract_jb.h"
#include "asterisk/xmpp.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<configInfo name="chan_motif" language="en_US">
@@ -286,7 +287,6 @@ struct jingle_endpoint {
iksrule *rule; /*!< Active matching rule */
unsigned int maxicecandidates; /*!< Maximum number of ICE candidates we will offer */
unsigned int maxpayloads; /*!< Maximum number of payloads we will offer */
- struct ast_codec_pref prefs; /*!< Codec preferences */
struct ast_format_cap *cap; /*!< Formats to use */
ast_group_t callgroup; /*!< Call group */
ast_group_t pickupgroup; /*!< Pickup group */
@@ -309,7 +309,6 @@ struct jingle_session {
char remote_original[XMPP_MAX_JIDLEN];/*!< Identifier of the original remote party (remote may have changed due to redirect) */
char remote[XMPP_MAX_JIDLEN]; /*!< Identifier of the remote party */
iksrule *rule; /*!< Session matching rule */
- struct ast_codec_pref prefs; /*!< Codec preferences */
struct ast_channel *owner; /*!< Master Channel */
struct ast_rtp_instance *rtp; /*!< RTP audio session */
struct ast_rtp_instance *vrtp; /*!< RTP video session */
@@ -454,8 +453,7 @@ static void jingle_endpoint_destructor(void *obj)
ast_xmpp_client_unref(endpoint->connection);
}
- ast_format_cap_destroy(endpoint->cap);
-
+ ao2_cleanup(endpoint->cap);
ao2_ref(endpoint->state, -1);
ast_string_field_free_memory(endpoint);
@@ -519,7 +517,7 @@ static void *jingle_endpoint_alloc(const char *cat)
ast_string_field_set(endpoint, name, cat);
- endpoint->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ endpoint->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
return endpoint;
@@ -583,9 +581,9 @@ static void jingle_session_destructor(void *obj)
ast_rtp_instance_destroy(session->vrtp);
}
- ast_format_cap_destroy(session->cap);
- ast_format_cap_destroy(session->jointcap);
- ast_format_cap_destroy(session->peercap);
+ ao2_cleanup(session->cap);
+ ao2_cleanup(session->jointcap);
+ ao2_cleanup(session->peercap);
if (session->callid) {
ast_callid_unref(session->callid);
@@ -681,7 +679,7 @@ static void jingle_enable_video(struct jingle_session *session)
}
/* If there are no configured video codecs do not turn video support on, it just won't work */
- if (!ast_format_cap_has_type(session->cap, AST_FORMAT_TYPE_VIDEO)) {
+ if (!ast_format_cap_has_type(session->cap, AST_MEDIA_TYPE_VIDEO)) {
return;
}
@@ -695,8 +693,8 @@ static void jingle_enable_video(struct jingle_session *session)
ast_rtp_instance_set_channel_id(session->vrtp, ast_channel_uniqueid(session->owner));
ast_channel_set_fd(session->owner, 2, ast_rtp_instance_fd(session->vrtp, 0));
ast_channel_set_fd(session->owner, 3, ast_rtp_instance_fd(session->vrtp, 1));
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->vrtp), session->vrtp, &session->prefs);
-
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(session->vrtp),
+ ast_format_cap_get_framing(session->cap));
if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
ice->stop(session->vrtp);
}
@@ -741,15 +739,15 @@ static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, con
session->connection = endpoint->connection;
session->transport = endpoint->transport;
- if (!(session->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
- !(session->jointcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
- !(session->peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
+ if (!(session->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(session->jointcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(session->peercap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
!session->callid) {
ao2_ref(session, -1);
return NULL;
}
- ast_format_cap_copy(session->cap, endpoint->cap);
+ ast_format_cap_append_from_cap(session->cap, endpoint->cap, AST_MEDIA_TYPE_UNKNOWN);
/* While we rely on res_xmpp for communication we still need a temporary ast_sockaddr to tell the RTP engine
* that we want IPv4 */
@@ -763,8 +761,6 @@ static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, con
ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_RTCP, 1);
ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_DTMF, 1);
- memcpy(&session->prefs, &endpoint->prefs, sizeof(session->prefs));
-
session->maxicecandidates = endpoint->maxicecandidates;
session->maxpayloads = endpoint->maxpayloads;
@@ -776,13 +772,20 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
{
struct ast_channel *chan;
const char *str = S_OR(title, session->remote);
- struct ast_format tmpfmt;
+ struct ast_format_cap *caps;
+ struct ast_format *tmpfmt;
+
+ if (!ast_format_cap_count(session->cap)) {
+ return NULL;
+ }
- if (ast_format_cap_is_empty(session->cap)) {
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
return NULL;
}
if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) {
+ ao2_ref(caps, -1);
return NULL;
}
@@ -794,15 +797,17 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
ast_channel_callid_set(chan, session->callid);
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->cap);
- ast_codec_choose(&session->prefs, session->cap, 1, &tmpfmt);
+ ast_format_cap_append_from_cap(caps, session->cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
if (session->rtp) {
struct ast_rtp_engine_ice *ice;
ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(session->rtp, 0));
ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(session->rtp, 1));
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->rtp), session->rtp, &session->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(session->rtp),
+ ast_format_cap_get_framing(session->cap));
if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
(session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
@@ -818,11 +823,12 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
ast_channel_adsicpe_set(chan, AST_ADSI_UNAVAILABLE);
- ast_best_codec(ast_channel_nativeformats(chan), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(chan), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &tmpfmt);
- ast_format_copy(ast_channel_readformat(chan), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(session->cap, 0);
+ ast_channel_set_writeformat(chan, tmpfmt);
+ ast_channel_set_rawwriteformat(chan, tmpfmt);
+ ast_channel_set_readformat(chan, tmpfmt);
+ ast_channel_set_rawreadformat(chan, tmpfmt);
+ ao2_ref(tmpfmt, -1);
ao2_lock(endpoint);
@@ -1300,30 +1306,24 @@ static void jingle_send_transport_info(struct jingle_session *session, const cha
}
/*! \brief Internal helper function which adds payloads to a description */
-static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_format_type type)
+static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_media_type type)
{
- struct ast_format format;
int x = 0, i = 0, res = 0;
- for (x = 0; (x < AST_CODEC_PREF_SIZE) && (i < (session->maxpayloads - 2)); x++) {
+ for (x = 0; (x < ast_format_cap_count(session->jointcap)) && (i < (session->maxpayloads - 2)); x++) {
+ struct ast_format *format = ast_format_cap_get_format(session->jointcap, x);
int rtp_code;
iks *payload;
char tmp[32];
- if (!ast_codec_pref_index(&session->prefs, x, &format)) {
- break;
- }
-
- if (AST_FORMAT_GET_TYPE(format.id) != type) {
- continue;
- }
-
- if (!ast_format_cap_iscompatible(session->jointcap, &format)) {
+ if (ast_format_get_type(format) != type) {
+ ao2_ref(format, -1);
continue;
}
- if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, &format, 0)) == -1) ||
+ if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, format, 0)) == -1) ||
(!(payload = iks_new("payload-type")))) {
+ ao2_ref(format, -1);
return -1;
}
@@ -1333,17 +1333,18 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st
snprintf(tmp, sizeof(tmp), "%d", rtp_code);
iks_insert_attrib(payload, "id", tmp);
- iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, &format, 0, 0));
+ iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
iks_insert_attrib(payload, "channels", "1");
- if ((format.id == AST_FORMAT_G722) && ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
+ if ((ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) &&
+ ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
iks_insert_attrib(payload, "clockrate", "16000");
} else {
- snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, &format, 0));
+ snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, format, 0));
iks_insert_attrib(payload, "clockrate", tmp);
}
- if ((type == AST_FORMAT_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
+ if ((type == AST_MEDIA_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
iks *parameter;
/* Google requires these parameters to be set, but alas we can not give accurate values so use some safe defaults */
@@ -1366,9 +1367,11 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st
iks_insert_node(description, payload);
payloads[i++] = payload;
+
+ ao2_ref(format, -1);
}
/* If this is for audio and there is room for RFC2833 add it in */
- if ((type == AST_FORMAT_TYPE_AUDIO) && (i < session->maxpayloads)) {
+ if ((type == AST_MEDIA_TYPE_AUDIO) && (i < session->maxpayloads)) {
iks *payload;
if ((payload = iks_new("payload-type"))) {
@@ -1390,7 +1393,7 @@ static int jingle_add_payloads_to_description(struct jingle_session *session, st
/*! \brief Helper function which adds content to a description */
static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *content, iks *description, iks *transport,
- const char *name, enum ast_format_type type, struct ast_rtp_instance *rtp, iks **payloads)
+ const char *name, enum ast_media_type type, struct ast_rtp_instance *rtp, iks **payloads)
{
int res = 0;
@@ -1400,9 +1403,9 @@ static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *
iks_insert_node(jingle, content);
iks_insert_attrib(description, "xmlns", JINGLE_RTP_NS);
- if (type == AST_FORMAT_TYPE_AUDIO) {
+ if (type == AST_MEDIA_TYPE_AUDIO) {
iks_insert_attrib(description, "media", "audio");
- } else if (type == AST_FORMAT_TYPE_VIDEO) {
+ } else if (type == AST_MEDIA_TYPE_VIDEO) {
iks_insert_attrib(description, "media", "video");
} else {
return -1;
@@ -1469,7 +1472,7 @@ static void jingle_send_session_action(struct jingle_session *session, const cha
if (session->rtp && (audio = iks_new("content")) && (audio_description = iks_new("description")) &&
(audio_transport = iks_new("transport"))) {
res = jingle_add_content(session, jingle, audio, audio_description, audio_transport, session->audio_name,
- AST_FORMAT_TYPE_AUDIO, session->rtp, audio_payloads);
+ AST_MEDIA_TYPE_AUDIO, session->rtp, audio_payloads);
} else {
ast_log(LOG_ERROR, "Failed to allocate audio content stanzas for session '%s', hanging up\n", session->sid);
res = -1;
@@ -1479,7 +1482,7 @@ static void jingle_send_session_action(struct jingle_session *session, const cha
if ((video = iks_new("content")) && (video_description = iks_new("description")) &&
(video_transport = iks_new("transport"))) {
res = jingle_add_content(session, jingle, video, video_description, video_transport, session->video_name,
- AST_FORMAT_TYPE_VIDEO, session->vrtp, video_payloads);
+ AST_MEDIA_TYPE_VIDEO, session->vrtp, video_payloads);
} else {
ast_log(LOG_ERROR, "Failed to allocate video content stanzas for session '%s', hanging up\n", session->sid);
res = -1;
@@ -1668,17 +1671,24 @@ static struct ast_frame *jingle_read(struct ast_channel *ast)
}
if (frame && frame->frametype == AST_FRAME_VOICE &&
- !ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format)) {
- if (!ast_format_cap_iscompatible(session->jointcap, &frame->subclass.format)) {
+ ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cap_iscompatible_format(session->jointcap, frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
- ast_getformatname(&frame->subclass.format), ast_channel_name(ast));
+ ast_format_get_name(frame->subclass.format), ast_channel_name(ast));
ast_frfree(frame);
frame = &ast_null_frame;
} else {
+ struct ast_format_cap *caps;
+
ast_debug(1, "Oooh, format changed to %s\n",
- ast_getformatname(&frame->subclass.format));
- ast_format_cap_remove_bytype(ast_channel_nativeformats(ast), AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(ast_channel_nativeformats(ast), &frame->subclass.format);
+ ast_format_get_name(frame->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, frame->subclass.format, 0);
+ ast_channel_nativeformats_set(ast, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(ast, ast_channel_readformat(ast));
ast_set_write_format(ast, ast_channel_writeformat(ast));
}
@@ -1692,17 +1702,18 @@ static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
{
struct jingle_session *session = ast_channel_tech_pvt(ast);
int res = 0;
- char buf[256];
switch (frame->frametype) {
case AST_FRAME_VOICE:
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return 0;
}
if (session && session->rtp) {
@@ -1845,7 +1856,7 @@ static int jingle_call(struct ast_channel *ast, const char *dest, int timeout)
ast_setstate(ast, AST_STATE_RING);
/* Since we have no idea of the remote capabilities use ours for now */
- ast_format_cap_copy(session->jointcap, session->cap);
+ ast_format_cap_append_from_cap(session->jointcap, session->cap, AST_MEDIA_TYPE_UNKNOWN);
/* We set up a hook so we can know when our session-initiate message was accepted or rejected */
session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
@@ -1908,7 +1919,7 @@ static struct ast_channel *jingle_request(const char *type, struct ast_format_ca
);
/* We require at a minimum one audio format to be requested */
- if (!ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO)) {
+ if (!ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO)) {
ast_log(LOG_ERROR, "Motif channel driver requires an audio format when dialing a destination\n");
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
return NULL;
@@ -2001,7 +2012,7 @@ static struct ast_channel *jingle_request(const char *type, struct ast_format_ca
}
/* If video was requested try to enable it on the session */
- if (ast_format_cap_has_type(cap, AST_FORMAT_TYPE_VIDEO)) {
+ if (ast_format_cap_has_type(cap, AST_MEDIA_TYPE_VIDEO)) {
jingle_enable_video(session);
}
@@ -2043,8 +2054,8 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
ast_string_field_set(session, audio_name, name);
}
*rtp = session->rtp;
- ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_remove_by_type(session->peercap, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_remove_by_type(session->jointcap, AST_MEDIA_TYPE_AUDIO);
} else if (!strcasecmp(media, "video")) {
if (!ast_strlen_zero(name)) {
ast_string_field_set(session, video_name, name);
@@ -2060,8 +2071,8 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
return -1;
}
- ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_VIDEO);
- ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_VIDEO);
+ ast_format_cap_remove_by_type(session->peercap, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_remove_by_type(session->jointcap, AST_MEDIA_TYPE_VIDEO);
} else {
/* Unknown media type */
jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
@@ -2082,8 +2093,6 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
int rtp_id, rtp_clockrate;
if (!ast_strlen_zero(id) && !ast_strlen_zero(name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
- ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, rtp_id);
-
if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) {
ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, name, 0, rtp_clockrate);
} else {
@@ -2093,9 +2102,9 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
}
ast_rtp_codecs_payload_formats(&codecs, session->peercap, &othercapability);
- ast_format_cap_joint_append(session->cap, session->peercap, session->jointcap);
+ ast_format_cap_get_compatible(session->cap, session->peercap, session->jointcap);
- if (ast_format_cap_is_empty(session->jointcap)) {
+ if (!ast_format_cap_count(session->jointcap)) {
/* We have no compatible codecs, so terminate the session appropriately */
jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
ast_rtp_codecs_payloads_destroy(&codecs);
@@ -2355,12 +2364,20 @@ static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
}
if ((chan = jingle_session_lock_full(session))) {
- struct ast_format fmt;
+ struct ast_format_cap *caps;
+ struct ast_format *fmt;
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append_from_cap(caps, session->jointcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
+ }
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->jointcap);
- ast_codec_choose(&session->prefs, session->jointcap, 1, &fmt);
- ast_set_read_format(chan, &fmt);
- ast_set_write_format(chan, &fmt);
+ fmt = ast_format_cap_get_format(session->jointcap, 0);
+ ast_set_read_format(chan, fmt);
+ ast_set_write_format(chan, fmt);
+ ao2_ref(fmt, -1);
ast_channel_unlock(chan);
ast_channel_unref(chan);
@@ -2710,7 +2727,7 @@ static int custom_transport_handler(const struct aco_option *opt, struct ast_var
*/
static int load_module(void)
{
- if (!(jingle_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(jingle_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -2726,8 +2743,8 @@ static int load_module(void)
aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass));
aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot));
aco_option_register(&cfg_info, "accountcode", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, accountcode));
- aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, prefs, cap));
- aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, prefs, cap));
+ aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, cap));
+ aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, cap));
aco_option_register_custom(&cfg_info, "connection", ACO_EXACT, endpoint_options, NULL, custom_connection_handler, 0);
aco_option_register_custom(&cfg_info, "transport", ACO_EXACT, endpoint_options, NULL, custom_transport_handler, 0);
aco_option_register(&cfg_info, "maxicecandidates", ACO_EXACT, endpoint_options, DEFAULT_MAX_ICE_CANDIDATES, OPT_UINT_T, PARSE_DEFAULT,
@@ -2735,9 +2752,10 @@ static int load_module(void)
aco_option_register(&cfg_info, "maxpayloads", ACO_EXACT, endpoint_options, DEFAULT_MAX_PAYLOADS, OPT_UINT_T, PARSE_DEFAULT,
FLDSET(struct jingle_endpoint, maxpayloads), DEFAULT_MAX_PAYLOADS);
- ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_append_by_type(jingle_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
if (aco_process_config(&cfg_info, 0)) {
+ ao2_ref(jingle_tech.capabilities, -1);
ast_log(LOG_ERROR, "Unable to read config file motif.conf. Module loaded but not running.\n");
aco_info_destroy(&cfg_info);
return AST_MODULE_LOAD_DECLINE;
@@ -2763,6 +2781,7 @@ static int load_module(void)
return 0;
end:
+ ao2_cleanup(jingle_tech.capabilities);
ast_rtp_glue_unregister(&jingle_rtp_glue);
if (sched) {
@@ -2784,7 +2803,7 @@ static int reload(void)
static int unload_module(void)
{
ast_channel_unregister(&jingle_tech);
- ast_format_cap_destroy(jingle_tech.capabilities);
+ ao2_cleanup(jingle_tech.capabilities);
jingle_tech.capabilities = NULL;
ast_rtp_glue_unregister(&jingle_rtp_glue);
ast_sched_context_destroy(sched);
diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c
index 730b2f459..ae6022cb6 100644
--- a/channels/chan_multicast_rtp.c
+++ b/channels/chan_multicast_rtp.c
@@ -117,8 +117,10 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo
struct ast_sockaddr control_address;
struct ast_sockaddr destination_address;
struct ast_channel *chan;
- struct ast_format fmt;
- ast_best_codec(cap, &fmt);
+ struct ast_format_cap *caps = NULL;
+ struct ast_format *fmt = NULL;
+
+ fmt = ast_format_cap_get_format(cap, 0);
ast_sockaddr_setnull(&control_address);
@@ -145,6 +147,11 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo
goto failure;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ goto failure;
+ }
+
if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, multicast_type))) {
goto failure;
}
@@ -158,19 +165,25 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo
ast_channel_tech_set(chan, &multicast_rtp_tech);
- ast_format_cap_add(ast_channel_nativeformats(chan), &fmt);
- ast_format_copy(ast_channel_writeformat(chan), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
- ast_format_copy(ast_channel_readformat(chan), &fmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
+ ast_format_cap_append(caps, fmt, 0);
+ ast_channel_nativeformats_set(chan, caps);
+ ast_channel_set_writeformat(chan, fmt);
+ ast_channel_set_rawwriteformat(chan, fmt);
+ ast_channel_set_readformat(chan, fmt);
+ ast_channel_set_rawreadformat(chan, fmt);
ast_channel_tech_pvt_set(chan, instance);
ast_channel_unlock(chan);
+ ao2_ref(fmt, -1);
+ ao2_ref(caps, -1);
+
return chan;
failure:
+ ao2_cleanup(fmt);
+ ao2_cleanup(caps);
*cause = AST_CAUSE_FAILURE;
return NULL;
}
@@ -178,12 +191,14 @@ failure:
/*! \brief Function called when our module is loaded */
static int load_module(void)
{
- if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all(multicast_rtp_tech.capabilities);
+ ast_format_cap_append_by_type(multicast_rtp_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
if (ast_channel_register(&multicast_rtp_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n");
+ ao2_ref(multicast_rtp_tech.capabilities, -1);
+ multicast_rtp_tech.capabilities = NULL;
return AST_MODULE_LOAD_DECLINE;
}
@@ -194,7 +209,8 @@ static int load_module(void)
static int unload_module(void)
{
ast_channel_unregister(&multicast_rtp_tech);
- multicast_rtp_tech.capabilities = ast_format_cap_destroy(multicast_rtp_tech.capabilities);
+ ao2_ref(multicast_rtp_tech.capabilities, -1);
+ multicast_rtp_tech.capabilities = NULL;
return 0;
}
diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c
index cbfb6b3c4..1be9bffeb 100644
--- a/channels/chan_nbs.c
+++ b/channels/chan_nbs.c
@@ -47,12 +47,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
+#include "asterisk/format_cache.h"
static const char tdesc[] = "Network Broadcast Sound Driver";
-/* Only linear is allowed */
-static struct ast_format prefformat;
-
static char context[AST_MAX_EXTENSION] = "default";
static const char type[] = "NBS";
@@ -63,7 +61,6 @@ struct nbs_pvt {
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
char app[16]; /* Our app */
char stream[80]; /* Our stream */
- struct ast_frame fr; /* "null" frame */
struct ast_module_user *u; /*! for holding a reference to this module */
};
@@ -178,37 +175,14 @@ static int nbs_hangup(struct ast_channel *ast)
static struct ast_frame *nbs_xread(struct ast_channel *ast)
{
- struct nbs_pvt *p = ast_channel_tech_pvt(ast);
-
-
- /* Some nice norms */
- p->fr.datalen = 0;
- p->fr.samples = 0;
- p->fr.data.ptr = NULL;
- p->fr.src = type;
- p->fr.offset = 0;
- p->fr.mallocd=0;
- p->fr.delivery.tv_sec = 0;
- p->fr.delivery.tv_usec = 0;
-
ast_debug(1, "Returning null frame on %s\n", ast_channel_name(ast));
- return &p->fr;
+ return &ast_null_frame;
}
static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
{
struct nbs_pvt *p = ast_channel_tech_pvt(ast);
- /* Write a frame of (presumably voice) data */
- if (frame->frametype != AST_FRAME_VOICE) {
- if (frame->frametype != AST_FRAME_IMAGE)
- ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
- return 0;
- }
- if (frame->subclass.format.id != (AST_FORMAT_SLINEAR)) {
- ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
- return 0;
- }
if (ast_channel_state(ast) != AST_STATE_UP) {
/* Don't try tos end audio on-hook */
return 0;
@@ -226,11 +200,11 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const struct as
ast_channel_tech_set(tmp, &nbs_tech);
ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs));
- ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat);
- ast_format_copy(ast_channel_rawreadformat(tmp), &prefformat);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &prefformat);
- ast_format_copy(ast_channel_writeformat(tmp), &prefformat);
- ast_format_copy(ast_channel_readformat(tmp), &prefformat);
+ ast_channel_nativeformats_set(tmp, nbs_tech.capabilities);
+ ast_channel_set_rawreadformat(tmp, ast_format_slin);
+ ast_channel_set_rawwriteformat(tmp, ast_format_slin);
+ ast_channel_set_writeformat(tmp, ast_format_slin);
+ ast_channel_set_readformat(tmp, ast_format_slin);
if (state == AST_STATE_RING)
ast_channel_rings_set(tmp, 1);
ast_channel_tech_pvt_set(tmp, i);
@@ -257,9 +231,11 @@ static struct ast_channel *nbs_request(const char *type, struct ast_format_cap *
struct nbs_pvt *p;
struct ast_channel *tmp = NULL;
- if (!(ast_format_cap_iscompatible(cap, &prefformat))) {
- char tmp[256];
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
+ ast_format_cap_get_names(cap, &cap_buf));
return NULL;
}
p = nbs_alloc(data);
@@ -275,17 +251,17 @@ static int unload_module(void)
{
/* First, take us out of the channel loop */
ast_channel_unregister(&nbs_tech);
- nbs_tech.capabilities = ast_format_cap_destroy(nbs_tech.capabilities);
+ ao2_ref(nbs_tech.capabilities, -1);
+ nbs_tech.capabilities = NULL;
return 0;
}
static int load_module(void)
{
- ast_format_set(&prefformat, AST_FORMAT_SLINEAR, 0);
- if (!(nbs_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(nbs_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(nbs_tech.capabilities, &prefformat);
+ ast_format_cap_append(nbs_tech.capabilities, ast_format_slin, 0);
/* Make sure we can register our channel type */
if (ast_channel_register(&nbs_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 4459b4b6f..46b751d7c 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -69,6 +69,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/bridge.h"
+#include "asterisk/format_cache.h"
#include "console_video.h"
@@ -726,7 +727,7 @@ static struct ast_frame *oss_read(struct ast_channel *c)
return f;
/* ok we can build and deliver the frame to the caller */
f->frametype = AST_FRAME_VOICE;
- ast_format_set(&f->subclass.format, AST_FORMAT_SLINEAR, 0);
+ f->subclass.format = ao2_bump(ast_format_slin);
f->samples = FRAME_SIZE;
f->datalen = FRAME_SIZE * 2;
f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET;
@@ -804,9 +805,9 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
setformat(o, O_RDWR);
ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
- ast_format_set(ast_channel_readformat(c), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_writeformat(c), AST_FORMAT_SLINEAR, 0);
- ast_format_cap_add(ast_channel_nativeformats(c), ast_channel_readformat(c));
+ ast_channel_set_readformat(c, ast_format_slin);
+ ast_channel_set_writeformat(c, ast_format_slin);
+ ast_channel_nativeformats_set(c, oss_tech.capabilities);
/* if the console makes the call, add video to the offer */
/* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER
@@ -851,8 +852,6 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap *
AST_APP_ARG(flags);
);
char *parse = ast_strdupa(data);
- char buf[256];
- struct ast_format tmpfmt;
AST_NONSTANDARD_APP_ARGS(args, parse, '/');
o = find_desc(args.name);
@@ -863,8 +862,9 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap *
/* XXX we could default to 'dsp' perhaps ? */
return NULL;
}
- if (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)))) {
- ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
if (o->owner) {
@@ -1452,7 +1452,6 @@ static int load_module(void)
struct ast_config *cfg = NULL;
char *ctg = NULL;
struct ast_flags config_flags = { 0 };
- struct ast_format tmpfmt;
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
@@ -1482,7 +1481,7 @@ static int load_module(void)
if (!(oss_tech.capabilities = ast_format_cap_alloc(0))) {
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add(oss_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(oss_tech.capabilities, ast_format_slin, 0);
/* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER
* add console_video_formats to oss_tech.capabilities once this occurs. */
@@ -1517,7 +1516,9 @@ static int unload_module(void)
ast_free(o);
o = next;
}
- oss_tech.capabilities = ast_format_cap_destroy(oss_tech.capabilities);
+ ao2_cleanup(oss_tech.capabilities);
+ oss_tech.capabilities = NULL;
+
return 0;
}
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 1e5e19d57..72f38291b 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -67,6 +67,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
#include "chan_phone.h"
@@ -134,8 +136,8 @@ static struct phone_pvt {
int fd; /* Raw file descriptor for this device */
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
int mode; /* Is this in the */
- struct ast_format lastformat; /* Last output format */
- struct ast_format lastinput; /* Last input format */
+ struct ast_format *lastformat; /* Last output format */
+ struct ast_format *lastinput; /* Last input format */
int ministate; /* Miniature state, for dialtone mode */
char dev[256]; /* Device name */
struct phone_pvt *next; /* Next channel in list */
@@ -218,7 +220,8 @@ static int phone_indicate(struct ast_channel *chan, int condition, const void *d
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
usleep(320000);
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
- ast_format_clear(&p->lastformat);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
res = 0;
break;
case AST_CONTROL_HOLD:
@@ -282,7 +285,8 @@ static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int dur
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
usleep(320000);
ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
- ast_format_clear(&p->lastformat);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
return 0;
default:
ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
@@ -290,7 +294,8 @@ static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int dur
}
ast_debug(1, "Dialed %d\n", outdigit);
ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
- ast_format_clear(&p->lastformat);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
return 0;
}
@@ -381,8 +386,10 @@ static int phone_hangup(struct ast_channel *ast)
ioctl(p->fd, PHONE_BUSY);
p->cpt = 1;
}
- ast_format_clear(&p->lastformat);
- ast_format_clear(&p->lastinput);
+ ao2_cleanup(p->lastformat);
+ p->lastformat = NULL;
+ ao2_cleanup(p->lastinput);
+ p->lastinput = NULL;
p->ministate = 0;
p->obuflen = 0;
p->dialtone = 0;
@@ -402,38 +409,38 @@ static int phone_setup(struct ast_channel *ast)
p = ast_channel_tech_pvt(ast);
ioctl(p->fd, PHONE_CPT_STOP);
/* Nothing to answering really, just start recording */
- if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_G729A) {
+ if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
/* Prefer g729 */
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_G729A) {
- ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_g729) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_g729);
if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
ast_log(LOG_WARNING, "Failed to set codec to g729\n");
return -1;
}
}
- } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_G723_1) {
+ } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_G723_1) {
- ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_g723) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_g723);
if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
return -1;
}
}
- } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
+ } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_SLINEAR) {
- ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_slin);
if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
return -1;
}
}
- } else if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) {
+ } else if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
ioctl(p->fd, PHONE_REC_STOP);
- if (p->lastinput.id != AST_FORMAT_ULAW) {
- ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0);
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
+ ao2_replace(p->lastinput, ast_format_ulaw);
if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
ast_log(LOG_WARNING, "Failed to set codec to uLaw\n");
return -1;
@@ -441,16 +448,16 @@ static int phone_setup(struct ast_channel *ast)
}
} else if (p->mode == MODE_FXS) {
ioctl(p->fd, PHONE_REC_STOP);
- if (ast_format_cmp(&p->lastinput, ast_channel_rawreadformat(ast)) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_format_copy(&p->lastinput, ast_channel_rawreadformat(ast));
+ if (!p->lastinput || (ast_format_cmp(p->lastinput, ast_channel_rawreadformat(ast)) == AST_FORMAT_CMP_NOT_EQUAL)) {
+ ao2_replace(p->lastinput, ast_channel_rawreadformat(ast));
if (ioctl(p->fd, PHONE_REC_CODEC, ast_channel_rawreadformat(ast))) {
ast_log(LOG_WARNING, "Failed to set codec to %s\n",
- ast_getformatname(ast_channel_rawreadformat(ast)));
+ ast_format_get_name(ast_channel_rawreadformat(ast)));
return -1;
}
}
} else {
- ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
+ ast_log(LOG_WARNING, "Can't do format %s\n", ast_format_get_name(ast_channel_rawreadformat(ast)));
return -1;
}
if (ioctl(p->fd, PHONE_REC_START)) {
@@ -601,13 +608,13 @@ static struct ast_frame *phone_read(struct ast_channel *ast)
}
p->fr.samples = 240;
p->fr.datalen = res;
- p->fr.frametype = AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_AUDIO ?
- AST_FRAME_VOICE : AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_IMAGE ?
+ p->fr.frametype = ast_format_get_type(p->lastinput) == AST_MEDIA_TYPE_AUDIO ?
+ AST_FRAME_VOICE : ast_format_get_type(p->lastinput) == AST_MEDIA_TYPE_IMAGE ?
AST_FRAME_IMAGE : AST_FRAME_VIDEO;
- ast_format_copy(&p->fr.subclass.format, &p->lastinput);
+ p->fr.subclass.format = p->lastinput;
p->fr.offset = AST_FRIENDLY_OFFSET;
/* Byteswap from little-endian to native-endian */
- if (p->fr.subclass.format.id == AST_FORMAT_SLINEAR)
+ if (ast_format_cmp(p->fr.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
ast_frame_byteswap_le(&p->fr);
return &p->fr;
}
@@ -669,14 +676,6 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
return 0;
}
- if (!(frame->subclass.format.id == AST_FORMAT_G723_1 ||
- frame->subclass.format.id == AST_FORMAT_SLINEAR ||
- frame->subclass.format.id == AST_FORMAT_ULAW ||
- frame->subclass.format.id == AST_FORMAT_G729A) &&
- p->mode != MODE_FXS) {
- ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
- return -1;
- }
#if 0
/* If we're not in up mode, go into up mode now */
if (ast->_state != AST_STATE_UP) {
@@ -689,8 +688,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
#endif
- if (frame->subclass.format.id == AST_FORMAT_G729A) {
- if (p->lastformat.id != AST_FORMAT_G729A) {
+ if (ast_format_cmp(frame->subclass.format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_g729) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) {
@@ -701,8 +700,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set G729 mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_G729A, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0);
+ ao2_replace(p->lastformat, ast_format_g729);
+ ao2_replace(p->lastinput, ast_format_g729);
/* Reset output buffer */
p->obuflen = 0;
codecset = 1;
@@ -712,8 +711,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
return -1;
}
maxfr = 80;
- } else if (frame->subclass.format.id == AST_FORMAT_G723_1) {
- if (p->lastformat.id != AST_FORMAT_G723_1) {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_g723) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
@@ -724,8 +723,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_G723_1, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0);
+ ao2_replace(p->lastformat, ast_format_g723);
+ ao2_replace(p->lastinput, ast_format_g723);
/* Reset output buffer */
p->obuflen = 0;
codecset = 1;
@@ -735,8 +734,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
return -1;
}
maxfr = 24;
- } else if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
- if (p->lastformat.id != AST_FORMAT_SLINEAR) {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
@@ -747,15 +746,15 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0);
+ ao2_replace(p->lastformat, ast_format_slin);
+ ao2_replace(p->lastinput, ast_format_slin);
codecset = 1;
/* Reset output buffer */
p->obuflen = 0;
}
maxfr = 480;
- } else if (frame->subclass.format.id == AST_FORMAT_ULAW) {
- if (p->lastformat.id != AST_FORMAT_ULAW) {
+ } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
@@ -766,29 +765,29 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
return -1;
}
- ast_format_set(&p->lastformat, AST_FORMAT_ULAW, 0);
- ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0);
+ ao2_replace(p->lastformat, ast_format_ulaw);
+ ao2_replace(p->lastinput, ast_format_ulaw);
codecset = 1;
/* Reset output buffer */
p->obuflen = 0;
}
maxfr = 240;
} else {
- if (ast_format_cmp(&p->lastformat, &frame->subclass.format) != AST_FORMAT_CMP_EQUAL) {
+ if (!p->lastformat || (ast_format_cmp(p->lastformat, frame->subclass.format) != AST_FORMAT_CMP_EQUAL)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
- if (ioctl(p->fd, PHONE_PLAY_CODEC, (int) frame->subclass.format.id)) {
+ if (ioctl(p->fd, PHONE_PLAY_CODEC, ast_format_compatibility_format2bitfield(frame->subclass.format))) {
ast_log(LOG_WARNING, "Unable to set %s mode\n",
- ast_getformatname(&frame->subclass.format));
+ ast_format_get_name(frame->subclass.format));
return -1;
}
- if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.format.id)) {
+ if (ioctl(p->fd, PHONE_REC_CODEC, ast_format_compatibility_format2bitfield(frame->subclass.format))) {
ast_log(LOG_WARNING, "Unable to set %s mode\n",
- ast_getformatname(&frame->subclass.format));
+ ast_format_get_name(frame->subclass.format));
return -1;
}
- ast_format_copy(&p->lastformat, &frame->subclass.format);
- ast_format_copy(&p->lastinput, &frame->subclass.format);
+ ao2_replace(p->lastformat, frame->subclass.format);
+ ao2_replace(p->lastinput, frame->subclass.format);
codecset = 1;
/* Reset output buffer */
p->obuflen = 0;
@@ -857,11 +856,13 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps = NULL;
struct ast_channel *tmp;
struct phone_codec_data queried_codec;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, assignedids, requestor, 0, "Phone/%s", i->dev + 5);
- if (tmp) {
+ if (tmp && caps) {
ast_channel_lock(tmp);
ast_channel_tech_set(tmp, cur_tech);
ast_channel_set_fd(tmp, 0, i->fd);
@@ -869,18 +870,20 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
if (i->mode == MODE_FXS &&
ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) {
if (queried_codec.type == LINEAR16) {
- ast_format_cap_add(ast_channel_nativeformats(tmp), ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_format_cap_append(caps, ast_format_slin, 0);
} else {
- ast_format_cap_remove(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_remove(prefcap, ast_format_slin);
+ ast_format_cap_append_from_cap(caps, prefcap, AST_MEDIA_TYPE_UNKNOWN);
}
} else {
- ast_format_cap_copy(ast_channel_nativeformats(tmp), prefcap);
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_format_cap_append_from_cap(caps, prefcap, AST_MEDIA_TYPE_UNKNOWN);
}
+ tmpfmt = ast_format_cap_get_format(caps, 0);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
/* no need to call ast_setstate: the channel_alloc already did its job */
if (state == AST_STATE_RING)
ast_channel_rings_set(tmp, 1);
@@ -913,8 +916,10 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
ast_hangup(tmp);
}
}
- } else
+ } else {
+ ao2_cleanup(caps);
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ }
return tmp;
}
@@ -989,7 +994,8 @@ static void phone_check_exception(struct phone_pvt *i)
ioctl(i->fd, PHONE_PLAY_STOP);
ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
ioctl(i->fd, PHONE_PLAY_START);
- ast_format_clear(&i->lastformat);
+ ao2_cleanup(i->lastformat);
+ i->lastformat = NULL;
} else if (i->mode == MODE_SIGMA) {
ast_module_ref(ast_module_info->self);
/* Reset the extension */
@@ -1010,7 +1016,8 @@ static void phone_check_exception(struct phone_pvt *i)
ioctl(i->fd, PHONE_PLAY_STOP);
ioctl(i->fd, PHONE_REC_STOP);
i->dialtone = 0;
- ast_format_clear(&i->lastformat);
+ ao2_cleanup(i->lastformat);
+ i->lastformat = NULL;
}
}
if (phonee.bits.pstn_ring) {
@@ -1222,8 +1229,10 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai
flags = fcntl(tmp->fd, F_GETFL);
fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
tmp->owner = NULL;
- ast_format_clear(&tmp->lastformat);
- ast_format_clear(&tmp->lastinput);
+ ao2_cleanup(tmp->lastformat);
+ tmp->lastformat = NULL;
+ ao2_cleanup(tmp->lastinput);
+ tmp->lastinput = NULL;
tmp->ministate = 0;
memset(tmp->ext, 0, sizeof(tmp->ext));
ast_copy_string(tmp->language, language, sizeof(tmp->language));
@@ -1256,7 +1265,7 @@ static struct ast_channel *phone_request(const char *type, struct ast_format_cap
}
p = iflist;
while(p) {
- if (p->mode == MODE_FXS || (ast_format_cap_has_joint(cap, phone_tech.capabilities))) {
+ if (p->mode == MODE_FXS || (ast_format_cap_iscompatible(cap, phone_tech.capabilities))) {
size_t length = strlen(p->dev + 5);
if (strncmp(name, p->dev + 5, length) == 0 &&
!isalnum(name[length])) {
@@ -1272,9 +1281,10 @@ static struct ast_channel *phone_request(const char *type, struct ast_format_cap
ast_mutex_unlock(&iflock);
restart_monitor();
if (tmp == NULL) {
- if (!(ast_format_cap_has_joint(cap, phone_tech.capabilities))) {
- char buf[256];
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+ if (!(ast_format_cap_iscompatible(cap, phone_tech.capabilities))) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
+ ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
}
@@ -1357,9 +1367,10 @@ static int __unload_module(void)
return -1;
}
- phone_tech.capabilities = ast_format_cap_destroy(phone_tech.capabilities);
- phone_tech_fxs.capabilities = ast_format_cap_destroy(phone_tech_fxs.capabilities);
- prefcap = ast_format_cap_destroy(prefcap);
+ ao2_ref(phone_tech.capabilities, -1);
+ ao2_ref(phone_tech_fxs.capabilities, -1);
+ ao2_ref(prefcap, -1);
+
return 0;
}
@@ -1376,21 +1387,21 @@ static int load_module(void)
int mode = MODE_IMMEDIATE;
int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */
struct ast_flags config_flags = { 0 };
- struct ast_format tmpfmt;
- if (!(phone_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(phone_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0));
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0));
- if (!(prefcap = ast_format_cap_alloc(0))) {
+ ast_format_cap_append(phone_tech.capabilities, ast_format_g723, 0);
+ ast_format_cap_append(phone_tech.capabilities, ast_format_slin, 0);
+ ast_format_cap_append(phone_tech.capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(phone_tech.capabilities, ast_format_g729, 0);
+
+ if (!(prefcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_copy(prefcap, phone_tech.capabilities);
- if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc(0))) {
+ ast_format_cap_append_from_cap(prefcap, phone_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
+ if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -1440,7 +1451,7 @@ static int load_module(void)
mode = MODE_IMMEDIATE;
else if (!strncasecmp(v->value, "fxs", 3)) {
mode = MODE_FXS;
- ast_format_cap_remove_bytype(prefcap, AST_FORMAT_TYPE_AUDIO); /* All non-voice */
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_AUDIO); /* All non-voice */
}
else if (!strncasecmp(v->value, "fx", 2))
mode = MODE_FXO;
@@ -1450,18 +1461,21 @@ static int load_module(void)
ast_copy_string(context, v->value, sizeof(context));
} else if (!strcasecmp(v->name, "format")) {
if (!strcasecmp(v->value, "g729")) {
- ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0));
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_g729, 0);
} else if (!strcasecmp(v->value, "g723.1")) {
- ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0));
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_g723, 0);
} else if (!strcasecmp(v->value, "slinear")) {
- ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0);
if (mode == MODE_FXS) {
- ast_format_cap_add(prefcap, &tmpfmt);
+ ast_format_cap_append(prefcap, ast_format_slin, 0);
} else {
- ast_format_cap_set(prefcap, &tmpfmt);
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_slin, 0);
}
} else if (!strcasecmp(v->value, "ulaw")) {
- ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
+ ast_format_cap_remove_by_type(prefcap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(prefcap, ast_format_ulaw, 0);
} else
ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
} else if (!strcasecmp(v->name, "echocancel")) {
@@ -1485,7 +1499,7 @@ static int load_module(void)
ast_mutex_unlock(&iflock);
if (mode == MODE_FXS) {
- ast_format_cap_copy(phone_tech_fxs.capabilities, prefcap);
+ ast_format_cap_append_from_cap(phone_tech_fxs.capabilities, prefcap, AST_MEDIA_TYPE_UNKNOWN);
cur_tech = &phone_tech_fxs;
} else
cur_tech = (struct ast_channel_tech *) &phone_tech;
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 695211480..5812360c5 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/indications.h"
+#include "asterisk/format_cache.h"
#include "asterisk/threadstorage.h"
#include "asterisk/features_config.h"
#include "asterisk/pickup.h"
@@ -210,7 +211,7 @@ static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
- ast_format_cap_copy(result, channel->session->endpoint->media.codecs);
+ ast_format_cap_append_from_cap(result, channel->session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
}
static int send_direct_media_request(void *data)
@@ -325,8 +326,9 @@ static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
return 0;
}
- if (cap && !ast_format_cap_is_empty(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) {
- ast_format_cap_copy(session->direct_media_cap, cap);
+ if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) {
+ ast_format_cap_remove_by_type(session->direct_media_cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(session->direct_media_cap, cap, AST_MEDIA_TYPE_UNKNOWN);
changed = 1;
}
@@ -355,7 +357,8 @@ static struct ast_rtp_glue chan_pjsip_rtp_glue = {
static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int state, const char *exten, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
{
struct ast_channel *chan;
- struct ast_format fmt;
+ struct ast_format_cap *caps;
+ struct ast_format *fmt;
RAII_VAR(struct chan_pjsip_pvt *, pvt, NULL, ao2_cleanup);
struct ast_sip_channel_pvt *channel;
struct ast_variable *var;
@@ -363,19 +366,21 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
if (!(pvt = ao2_alloc(sizeof(*pvt), chan_pjsip_pvt_dtor))) {
return NULL;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
-
- chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""),
- session->endpoint->accountcode, "", "", assignedids,
- requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint),
- (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1));
- if (!chan) {
+ if (!(chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), session->endpoint->accountcode, "", "", assignedids, requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint),
+ (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)))) {
+ ao2_ref(caps, -1);
return NULL;
}
ast_channel_tech_set(chan, &chan_pjsip_tech);
if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) {
+ ao2_ref(caps, -1);
ast_channel_unlock(chan);
ast_hangup(chan);
return NULL;
@@ -391,17 +396,21 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
ast_channel_tech_pvt_set(chan, channel);
- if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) {
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->endpoint->media.codecs);
+ if (!ast_format_cap_count(session->req_caps) ||
+ !ast_format_cap_iscompatible(session->req_caps, session->endpoint->media.codecs)) {
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
} else {
- ast_format_cap_copy(ast_channel_nativeformats(chan), session->req_caps);
+ ast_format_cap_append_from_cap(caps, session->req_caps, AST_MEDIA_TYPE_UNKNOWN);
}
- ast_codec_choose(&session->endpoint->media.prefs, ast_channel_nativeformats(chan), 1, &fmt);
- ast_format_copy(ast_channel_writeformat(chan), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
- ast_format_copy(ast_channel_readformat(chan), &fmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
+ ast_channel_nativeformats_set(chan, caps);
+ fmt = ast_format_cap_get_format(caps, 0);
+ ast_channel_set_writeformat(chan, fmt);
+ ast_channel_set_rawwriteformat(chan, fmt);
+ ast_channel_set_readformat(chan, fmt);
+ ast_channel_set_rawreadformat(chan, fmt);
+ ao2_ref(fmt, -1);
+ ao2_ref(caps, -1);
if (state == AST_STATE_RING) {
ast_channel_rings_set(chan, 1);
@@ -584,9 +593,18 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
return f;
}
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
- ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(ast, caps);
+ ao2_ref(caps, -1);
+ }
+
ast_set_read_format(ast, ast_channel_readformat(ast));
ast_set_write_format(ast, ast_channel_writeformat(ast));
}
@@ -623,15 +641,15 @@ static int chan_pjsip_write(struct ast_channel *ast, struct ast_frame *frame)
if (!media) {
return 0;
}
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char buf[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return 0;
}
if (media->rtp) {
@@ -1127,10 +1145,8 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
if (media && media->rtp) {
/* FIXME: Only use this for VP8. Additional work would have to be done to
* fully support other video codecs */
- struct ast_format_cap *fcap = ast_channel_nativeformats(ast);
- struct ast_format vp8;
- ast_format_set(&vp8, AST_FORMAT_VP8, 0);
- if (ast_format_cap_iscompatible(fcap, &vp8)) {
+
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp8) != AST_FORMAT_CMP_NOT_EQUAL) {
/* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the
* RTP engine would provide a way to externally write/schedule RTCP
* packets */
@@ -2162,11 +2178,11 @@ static int load_module(void)
{
struct ao2_container *endpoints;
- if (!(chan_pjsip_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(chan_pjsip_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(chan_pjsip_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_append_by_type(chan_pjsip_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
ast_rtp_glue_register(&chan_pjsip_rtp_glue);
@@ -2259,6 +2275,7 @@ static int unload_module(void)
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
ast_channel_unregister(&chan_pjsip_tech);
+ ao2_ref(chan_pjsip_tech.capabilities, -1);
ast_rtp_glue_unregister(&chan_pjsip_rtp_glue);
return 0;
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 095b5a763..44629dc3d 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -285,6 +285,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_channels.h"
#include "asterisk/features_config.h"
#include "asterisk/http_websocket.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="SIPDtmfMode" language="en_US">
@@ -747,7 +748,6 @@ static char default_mohsuggest[MAX_MUSICCLASS]; /*!< Global setting for moh c
static char default_parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
static char default_engine[256]; /*!< Default RTP engine */
static int default_maxcallbitrate; /*!< Maximum bitrate for call */
-static struct ast_codec_pref default_prefs; /*!< Default codec prefs */
static char default_zone[MAX_TONEZONE_COUNTRY]; /*!< Default tone zone for channels created from the SIP driver */
static unsigned int default_transports; /*!< Default Transports (enum ast_transport) that are acceptable */
static unsigned int default_primary_transport; /*!< Default primary Transport (enum ast_transport) for outbound connections to devices */
@@ -1295,7 +1295,6 @@ static int str2dtmfmode(const char *str) attribute_unused;
static const char *insecure2str(int mode) attribute_const;
static const char *allowoverlap2str(int mode) attribute_const;
static void cleanup_stale_contexts(char *new, char *old);
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref);
static const char *domain_mode_to_text(const enum domain_mode mode);
static char *sip_show_domains(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]);
@@ -1764,7 +1763,7 @@ static void destroy_escs(void)
{
int i;
for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) {
- ao2_ref(event_state_compositors[i].compositor, -1);
+ ao2_cleanup(event_state_compositors[i].compositor);
}
}
@@ -3385,7 +3384,7 @@ static void unlink_peers_from_tables(peer_unlink_flag_t flag)
ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE,
match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers");
ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE,
- match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers");
+ match_and_cleanup_peer_sched, &flag, "initiating callback to remove marked peers_by_ip");
}
/* \brief Unlink all marked peers from ao2 containers */
@@ -5308,7 +5307,7 @@ static void sip_destroy_peer(struct sip_peer *peer)
ast_string_field_free_memory(peer);
- peer->caps = ast_format_cap_destroy(peer->caps);
+ ao2_cleanup(peer->caps);
ast_rtp_dtls_cfg_free(&peer->dtls_cfg);
@@ -5967,7 +5966,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
}
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) ||
- (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) {
+ (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_MEDIA_TYPE_VIDEO)))) {
if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) {
return -1;
}
@@ -6053,8 +6052,11 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
- ast_format_cap_copy(dialog->caps, peer->caps);
- dialog->prefs = peer->prefs;
+ /* Take the peer's caps */
+ if (peer->caps) {
+ ast_format_cap_remove_by_type(dialog->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(dialog->caps, peer->caps, AST_MEDIA_TYPE_UNKNOWN);
+ }
dialog->amaflags = peer->amaflags;
ast_string_field_set(dialog, engine, peer->engine);
@@ -6078,8 +6080,8 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
/* Set Frame packetization */
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs);
dialog->autoframing = peer->autoframing;
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(dialog->rtp), ast_format_cap_get_framing(dialog->caps));
}
/* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */
@@ -6456,7 +6458,7 @@ static int sip_call(struct ast_channel *ast, const char *dest, int timeout)
p->jointnoncodeccapability = p->noncodeccapability;
/* If there are no audio formats left to offer, punt */
- if (!(ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO))) {
+ if (!(ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_AUDIO))) {
ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username);
res = -1;
} else {
@@ -6721,11 +6723,11 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
- p->caps = ast_format_cap_destroy(p->caps);
- p->jointcaps = ast_format_cap_destroy(p->jointcaps);
- p->peercaps = ast_format_cap_destroy(p->peercaps);
- p->redircaps = ast_format_cap_destroy(p->redircaps);
- p->prefcaps = ast_format_cap_destroy(p->prefcaps);
+ ao2_cleanup(p->caps);
+ ao2_cleanup(p->jointcaps);
+ ao2_cleanup(p->peercaps);
+ ao2_cleanup(p->redircaps);
+ ao2_cleanup(p->prefcaps);
ast_rtp_dtls_cfg_free(&p->dtls_cfg);
@@ -7308,7 +7310,6 @@ static int sip_hangup(struct ast_channel *ast)
/*! \brief Try setting the codecs suggested by the SIP_CODEC channel variable */
static void try_suggested_sip_codec(struct sip_pvt *p)
{
- struct ast_format fmt;
const char *codec_list;
char *codec_list_copy;
struct ast_format_cap *original_jointcaps;
@@ -7328,31 +7329,44 @@ static void try_suggested_sip_codec(struct sip_pvt *p)
}
codec_list_copy = ast_strdupa(codec_list);
- original_jointcaps = ast_format_cap_dup(p->jointcaps);
+
+ original_jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!original_jointcaps) {
+ return;
+ }
+ ast_format_cap_append_from_cap(original_jointcaps, p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
for (codec = strtok_r(codec_list_copy, ",", &strtok_ptr); codec; codec = strtok_r(NULL, ",", &strtok_ptr)) {
+ struct ast_format *fmt;
+
codec = ast_strip(codec);
- if (!ast_getformatbyname(codec, &fmt)) {
+ fmt = ast_format_cache_get(codec);
+ if (!fmt) {
ast_log(AST_LOG_NOTICE, "Ignoring ${SIP_CODEC*} variable because of unrecognized/not configured codec %s (check allow/disallow in sip.conf)\n", codec);
continue;
}
- if (ast_format_cap_iscompatible(original_jointcaps, &fmt)) {
+ if (ast_format_cap_iscompatible_format(original_jointcaps, fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
if (first_codec) {
ast_verb(4, "Set codec to '%s' for this call because of ${SIP_CODEC*} variable\n", codec);
- ast_format_cap_set(p->jointcaps, &fmt);
- ast_format_cap_set(p->caps, &fmt);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->jointcaps, fmt, 0);
+ ast_format_cap_remove_by_type(p->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->caps, fmt, 0);
first_codec = 0;
} else {
ast_verb(4, "Add codec to '%s' for this call because of ${SIP_CODEC*} variable\n", codec);
- ast_format_cap_add(p->jointcaps, &fmt);
- ast_format_cap_add(p->caps, &fmt);
+ /* Add the format to the capabilities structure */
+ ast_format_cap_append(p->jointcaps, fmt, 0);
+ ast_format_cap_append(p->caps, fmt, 0);
}
} else {
ast_log(AST_LOG_NOTICE, "Ignoring ${SIP_CODEC*} variable because it is not shared by both ends: %s\n", codec);
}
+
+ ao2_ref(fmt, -1);
}
- ast_format_cap_destroy(original_jointcaps);
+ ao2_ref(original_jointcaps, -1);
return;
}
@@ -7401,13 +7415,13 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
switch (frame->frametype) {
case AST_FRAME_VOICE:
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char s1[512];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s read/write = %s/%s\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(s1, sizeof(s1), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return 0;
}
if (p) {
@@ -7929,10 +7943,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
if (p->vrtp && !p->novideo) {
/* FIXME: Only use this for VP8. Additional work would have to be done to
* fully support other video codecs */
- struct ast_format_cap *fcap = ast_channel_nativeformats(ast);
- struct ast_format vp8;
- ast_format_set(&vp8, AST_FORMAT_VP8, 0);
- if (ast_format_cap_iscompatible(fcap, &vp8)) {
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp8) != AST_FORMAT_CMP_NOT_EQUAL) {
/* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the
* RTP engine would provide a way to externally write/schedule RTCP
* packets */
@@ -8036,15 +8047,21 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
*/
static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid)
{
+ struct ast_format_cap *caps;
struct ast_channel *tmp;
struct ast_variable *v = NULL;
- struct ast_format fmt;
+ struct ast_format *fmt;
struct ast_format_cap *what = NULL; /* SHALLOW COPY DO NOT DESTROY! */
+ struct ast_str *codec_buf = ast_str_alloca(64);
int needvideo = 0;
int needtext = 0;
- char buf[SIPBUFSIZE];
char *exten;
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
{
const char *my_name; /* pick a good name */
@@ -8060,6 +8077,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
}
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n");
+ ao2_ref(caps, -1);
sip_pvt_lock(i);
return NULL;
}
@@ -8068,6 +8086,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) {
ast_channel_unlock(tmp);
ast_channel_unref(tmp);
+ ao2_ref(caps, -1);
sip_pvt_lock(i);
return NULL;
}
@@ -8088,27 +8107,40 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
/* Select our native format based on codec preference until we receive
something from another device to the contrary. */
- if (!(ast_format_cap_is_empty(i->jointcaps))) { /* The joint capabilities of us and peer */
+ if (ast_format_cap_count(i->jointcaps)) { /* The joint capabilities of us and peer */
what = i->jointcaps;
- } else if (!(ast_format_cap_is_empty(i->caps))) { /* Our configured capability for this peer */
+ } else if (ast_format_cap_count(i->caps)) { /* Our configured capability for this peer */
what = i->caps;
} else {
what = sip_cfg.caps;
}
/* Set the native formats */
- ast_format_cap_copy(ast_channel_nativeformats(tmp), what);
- /* choose and use only the best audio format for our native formats */
- ast_codec_choose(&i->prefs, ast_channel_nativeformats(tmp), 1, &fmt); /* get the best audio format */
- ast_format_cap_remove_bytype(ast_channel_nativeformats(tmp), AST_FORMAT_TYPE_AUDIO); /* remove only the other audio formats */
- ast_format_cap_add(ast_channel_nativeformats(tmp), &fmt); /* add our best choice back */
+ ast_format_cap_append_from_cap(caps, what, AST_MEDIA_TYPE_UNKNOWN);
+ /* Use only the preferred audio format, which is stored at the '0' index */
+ fmt = ast_format_cap_get_best_by_type(what, AST_MEDIA_TYPE_AUDIO); /* get the best audio format */
+ if (fmt) {
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); /* remove only the other audio formats */
+ ast_format_cap_append(caps, fmt, 0); /* add our best choice back */
+ } else {
+ /* If we don't have an audio format, try to get something */
+ fmt = ast_format_cap_get_format(caps, 0);
+ if (!fmt) {
+ ast_log(LOG_WARNING, "No compatible formats could be found for %s\n", ast_channel_name(tmp));
+ ao2_ref(caps, -1);
+ tmp = ast_channel_unref(tmp);
+ return NULL;
+ }
+ }
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
- ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_channel_nativeformats(tmp)));
- ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcaps));
- ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->caps));
- ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname(&fmt));
- if (!ast_format_cap_is_empty(i->prefcaps)) {
- ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcaps));
+ ast_debug(3, "*** Our native formats are %s \n", ast_format_cap_get_names(ast_channel_nativeformats(tmp), &codec_buf));
+ ast_debug(3, "*** Joint capabilities are %s \n", ast_format_cap_get_names(i->jointcaps, &codec_buf));
+ ast_debug(3, "*** Our capabilities are %s \n", ast_format_cap_get_names(i->caps, &codec_buf));
+ ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_format_get_name(fmt));
+ if (ast_format_cap_count(i->prefcaps)) {
+ ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_format_cap_get_names(i->prefcaps, &codec_buf));
}
/* If we have a prefcodec setting, we have an inbound channel that set a
@@ -8118,17 +8150,17 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (i->vrtp) {
if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT))
needvideo = 1;
- else if (!ast_format_cap_is_empty(i->prefcaps))
- needvideo = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_VIDEO); /* Outbound call */
+ else if (ast_format_cap_count(i->prefcaps))
+ needvideo = ast_format_cap_has_type(i->prefcaps, AST_MEDIA_TYPE_VIDEO); /* Outbound call */
else
- needvideo = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_VIDEO); /* Inbound call */
+ needvideo = ast_format_cap_has_type(i->jointcaps, AST_MEDIA_TYPE_VIDEO); /* Inbound call */
}
if (i->trtp) {
- if (!ast_format_cap_is_empty(i->prefcaps))
- needtext = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_TEXT); /* Outbound call */
+ if (ast_format_cap_count(i->prefcaps))
+ needtext = ast_format_cap_has_type(i->prefcaps, AST_MEDIA_TYPE_TEXT); /* Outbound call */
else
- needtext = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_TEXT); /* Inbound call */
+ needtext = ast_format_cap_has_type(i->jointcaps, AST_MEDIA_TYPE_TEXT); /* Inbound call */
}
if (needvideo) {
@@ -8156,8 +8188,8 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (i->rtp) {
ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
- ast_rtp_instance_set_write_format(i->rtp, &fmt);
- ast_rtp_instance_set_read_format(i->rtp, &fmt);
+ ast_rtp_instance_set_write_format(i->rtp, fmt);
+ ast_rtp_instance_set_read_format(i->rtp, fmt);
}
if (needvideo && i->vrtp) {
ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
@@ -8175,11 +8207,13 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
}
ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
- ast_format_copy(ast_channel_writeformat(tmp), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &fmt);
+ ast_channel_set_writeformat(tmp, fmt);
+ ast_channel_set_rawwriteformat(tmp, fmt);
+
+ ast_channel_set_readformat(tmp, fmt);
+ ast_channel_set_rawreadformat(tmp, fmt);
- ast_format_copy(ast_channel_readformat(tmp), &fmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &fmt);
+ ao2_ref(fmt, -1);
ast_channel_tech_pvt_set(tmp, dialog_ref(i, "sip_new: set chan->tech_pvt to i"));
@@ -8534,17 +8568,26 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
return f;
}
- if (f && !ast_format_cap_iscompatible(ast_channel_nativeformats(p->owner), &f->subclass.format)) {
- if (!ast_format_cap_iscompatible(p->jointcaps, &f->subclass.format)) {
+ if (f && ast_format_cap_iscompatible_format(ast_channel_nativeformats(p->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ if (ast_format_cap_iscompatible_format(p->jointcaps, f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
- ast_getformatname(&f->subclass.format), ast_channel_name(p->owner));
+ ast_format_get_name(f->subclass.format), ast_channel_name(p->owner));
ast_frfree(f);
return &ast_null_frame;
}
ast_debug(1, "Oooh, format changed to %s\n",
- ast_getformatname(&f->subclass.format));
- ast_format_cap_remove_bytype(ast_channel_nativeformats(p->owner), AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(ast_channel_nativeformats(p->owner), &f->subclass.format);
+ ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(p->owner), AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
}
@@ -8796,18 +8839,18 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
sip_pvt_callid_set(p, logger_callid);
}
- p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
- if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps) {
- p->caps = ast_format_cap_destroy(p->caps);
- p->jointcaps = ast_format_cap_destroy(p->jointcaps);
- p->peercaps = ast_format_cap_destroy(p->peercaps);
- p->redircaps = ast_format_cap_destroy(p->redircaps);
- p->prefcaps = ast_format_cap_destroy(p->prefcaps);
+ if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps || !p->prefcaps) {
+ ao2_cleanup(p->caps);
+ ao2_cleanup(p->jointcaps);
+ ao2_cleanup(p->peercaps);
+ ao2_cleanup(p->redircaps);
+ ao2_cleanup(p->prefcaps);
ao2_t_ref(p, -1, "Yuck, couldn't allocate format capabilities. Get rid o' p");
return NULL;
}
@@ -8857,7 +8900,6 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
p->sessionversion_remote = -1;
p->session_modify = TRUE;
p->stimer = NULL;
- p->prefs = default_prefs; /* Set default codecs for this call */
ast_copy_string(p->zone, default_zone, sizeof(p->zone));
p->maxforwards = sip_cfg.default_max_forwards;
@@ -8909,7 +8951,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
/* Assign default music on hold class */
ast_string_field_set(p, mohinterpret, default_mohinterpret);
ast_string_field_set(p, mohsuggest, default_mohsuggest);
- ast_format_cap_copy(p->caps, sip_cfg.caps);
+ ast_format_cap_append_from_cap(p->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN);
p->allowtransfer = sip_cfg.allowtransfer;
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
@@ -10034,15 +10076,17 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int udptlportno = -1; /*!< UDPTL image destination port number */
/* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */
- struct ast_format_cap *peercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *vpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *tpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *peercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *vpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *tpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int peernoncodeccapability = 0, vpeernoncodeccapability = 0, tpeernoncodeccapability = 0;
- struct ast_rtp_codecs newaudiortp = { 0, }, newvideortp = { 0, }, newtextrtp = { 0, };
- struct ast_format_cap *newjointcapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); /* Negotiated capability */
- struct ast_format_cap *newpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_rtp_codecs newaudiortp = AST_RTP_CODECS_NULL_INIT;
+ struct ast_rtp_codecs newvideortp = AST_RTP_CODECS_NULL_INIT;
+ struct ast_rtp_codecs newtextrtp = AST_RTP_CODECS_NULL_INIT;
+ struct ast_format_cap *newjointcapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); /* Negotiated capability */
+ struct ast_format_cap *newpeercapability = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int newnoncodeccapability;
const char *codecs;
@@ -10062,8 +10106,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int debug = sip_debug_test_pvt(p);
/* START UNKNOWN */
- char buf[SIPBUFSIZE];
- struct ast_format tmp_fmt;
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_format *tmp_fmt;
/* END UNKNOWN */
/* Initial check */
@@ -10625,10 +10669,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Ensure crypto lines are provided where necessary */
if (audio && secure_audio && !processed_crypto) {
ast_log(LOG_WARNING, "Rejecting secure audio stream without encryption details: %s\n", m);
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
} else if (video && secure_video && !processed_crypto) {
ast_log(LOG_WARNING, "Rejecting secure video stream without encryption details: %s\n", m);
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
}
}
@@ -10687,12 +10733,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_rtp_codecs_payload_formats(&newvideortp, vpeercapability, &vpeernoncodeccapability);
ast_rtp_codecs_payload_formats(&newtextrtp, tpeercapability, &tpeernoncodeccapability);
- ast_format_cap_append(newpeercapability, peercapability);
- ast_format_cap_append(newpeercapability, vpeercapability);
- ast_format_cap_append(newpeercapability, tpeercapability);
+ ast_format_cap_append_from_cap(newpeercapability, peercapability, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append_from_cap(newpeercapability, vpeercapability, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_from_cap(newpeercapability, tpeercapability, AST_MEDIA_TYPE_TEXT);
- ast_format_cap_joint_copy(p->caps, newpeercapability, newjointcapability);
- if (ast_format_cap_is_empty(newjointcapability) && udptlportno == -1) {
+ ast_format_cap_get_compatible(p->caps, newpeercapability, newjointcapability);
+ if (!ast_format_cap_count(newjointcapability) && udptlportno == -1) {
ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
/* Do NOT Change current setting */
res = -1;
@@ -10703,14 +10749,18 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (debug) {
/* shame on whoever coded this.... */
- char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *peer_buf = ast_str_alloca(64);
+ struct ast_str *vpeer_buf = ast_str_alloca(64);
+ struct ast_str *tpeer_buf = ast_str_alloca(64);
+ struct ast_str *joint_buf = ast_str_alloca(64);
ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n",
- ast_getformatname_multiple(s1, SIPBUFSIZE, p->caps),
- ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability),
- ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability),
- ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability),
- ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability));
+ ast_format_cap_get_names(p->caps, &cap_buf),
+ ast_format_cap_get_names(peercapability, &peer_buf),
+ ast_format_cap_get_names(vpeercapability, &vpeer_buf),
+ ast_format_cap_get_names(tpeercapability, &tpeer_buf),
+ ast_format_cap_get_names(newjointcapability, &joint_buf));
}
if (debug) {
struct ast_str *s1 = ast_str_alloca(SIPBUFSIZE);
@@ -10726,14 +10776,21 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (portno != -1 || vportno != -1 || tportno != -1) {
/* We are now ready to change the sip session and RTP structures with the offered codecs, since
they are acceptable */
- ast_format_cap_copy(p->jointcaps, newjointcapability); /* Our joint codec profile for this call */
- ast_format_cap_copy(p->peercaps, newpeercapability); /* The other side's capability in latest offer */
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, newjointcapability, AST_MEDIA_TYPE_UNKNOWN); /* Our joint codec profile for this call */
+ ast_format_cap_remove_by_type(p->peercaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->peercaps, newpeercapability, AST_MEDIA_TYPE_UNKNOWN); /* The other side's capability in latest offer */
p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */
/* respond with single most preferred joint codec, limiting the other side's choice */
if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) {
- ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt);
- ast_format_cap_set(p->jointcaps, &tmp_fmt);
+ unsigned int framing;
+
+ tmp_fmt = ast_format_cap_get_format(p->jointcaps, 0);
+ framing = ast_format_cap_get_format_framing(p->jointcaps, tmp_fmt);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(p->jointcaps, tmp_fmt, framing);
+ ao2_ref(tmp_fmt, -1);
}
}
@@ -10813,7 +10870,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_verbose("Peer T.140 RTP is at port %s\n",
ast_sockaddr_stringify(tsa));
}
- if (ast_format_cap_iscompatible(p->jointcaps, ast_format_set(&tmp_fmt, AST_FORMAT_T140RED, 0))) {
+ if (ast_format_cap_iscompatible_format(p->jointcaps, ast_format_t140_red) != AST_FORMAT_CMP_NOT_EQUAL) {
p->red = 1;
ast_rtp_red_init(p->trtp, 300, red_data_pt, 2);
} else {
@@ -10890,7 +10947,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
/* Ok, we're going with this offer */
- ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcaps));
+ ast_debug(2, "We're settling with these formats: %s\n", ast_format_cap_get_names(p->jointcaps, &codec_buf));
if (!p->owner) { /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */
res = 0;
@@ -10898,19 +10955,30 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
ast_debug(4, "We have an owner, now see if we need to change this call\n");
- if (ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO)) {
+ if (ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_AUDIO)) {
+ struct ast_format_cap *caps;
+ unsigned int framing;
+
if (debug) {
- char s1[SIPBUFSIZE], s2[SIPBUFSIZE];
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *joint_buf = ast_str_alloca(64);
+
ast_debug(1, "Setting native formats after processing SDP. peer joint formats %s, old nativeformats %s\n",
- ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcaps),
- ast_getformatname_multiple(s2, SIPBUFSIZE, ast_channel_nativeformats(p->owner)));
+ ast_format_cap_get_names(p->jointcaps, &joint_buf),
+ ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &cap_buf));
}
- ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt);
-
- ast_format_cap_set(ast_channel_nativeformats(p->owner), &tmp_fmt);
- ast_format_cap_joint_append(p->caps, vpeercapability, ast_channel_nativeformats(p->owner));
- ast_format_cap_joint_append(p->caps, tpeercapability, ast_channel_nativeformats(p->owner));
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ tmp_fmt = ast_format_cap_get_format(p->jointcaps, 0);
+ framing = ast_format_cap_get_format_framing(p->jointcaps, tmp_fmt);
+ ast_format_cap_append(caps, tmp_fmt, framing);
+ ast_format_cap_append_from_cap(caps, vpeercapability, AST_MEDIA_TYPE_VIDEO);
+ ast_format_cap_append_from_cap(caps, tpeercapability, AST_MEDIA_TYPE_TEXT);
+ ast_channel_nativeformats_set(p->owner, caps);
+ ao2_ref(caps, -1);
+ ao2_ref(tmp_fmt, -1);
+ }
ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
@@ -10942,11 +11010,11 @@ process_sdp_cleanup:
ast_rtp_codecs_payloads_destroy(&newtextrtp);
ast_rtp_codecs_payloads_destroy(&newvideortp);
ast_rtp_codecs_payloads_destroy(&newaudiortp);
- ast_format_cap_destroy(peercapability);
- ast_format_cap_destroy(vpeercapability);
- ast_format_cap_destroy(tpeercapability);
- ast_format_cap_destroy(newjointcapability);
- ast_format_cap_destroy(newpeercapability);
+ ao2_cleanup(peercapability);
+ ao2_cleanup(vpeercapability);
+ ao2_cleanup(tpeercapability);
+ ao2_cleanup(newjointcapability);
+ ao2_cleanup(newpeercapability);
return res;
}
@@ -11203,17 +11271,10 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
ast_debug(1, "Can't read framing from SDP: %s\n", a);
}
}
+
if (framing && p->autoframing) {
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
- int codec_n;
- for (codec_n = 0; codec_n < AST_RTP_MAX_PT; codec_n++) {
- struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n);
- if (!format.asterisk_format) /* non-codec or not found */
- continue;
- ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(&format.format), framing);
- ast_codec_pref_setsize(pref, &format.format, framing);
- }
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref);
+ ast_debug(1, "Setting framing to %ld\n", framing);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), framing);
}
found = TRUE;
} else if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) {
@@ -11240,15 +11301,19 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
if ((format = ast_rtp_codecs_get_payload_format(newaudiortp, codec))) {
unsigned int bit_rate;
+ struct ast_format *format_parsed;
- if (!ast_format_sdp_parse(format, fmtp_string)) {
+ format_parsed = ast_format_parse_sdp_fmtp(format, fmtp_string);
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(newaudiortp, codec, format_parsed);
+ ao2_replace(format, format_parsed);
+ ao2_ref(format_parsed, -1);
found = TRUE;
} else {
ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec);
}
- switch ((int) format->id) {
- case AST_FORMAT_SIREN7:
+ if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 32000) {
ast_log(LOG_WARNING, "Got Siren7 offer at %u bps, but only 32000 bps supported; ignoring.\n", bit_rate);
@@ -11257,8 +11322,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
found = TRUE;
}
}
- break;
- case AST_FORMAT_SIREN14:
+ } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) {
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 48000) {
ast_log(LOG_WARNING, "Got Siren14 offer at %u bps, but only 48000 bps supported; ignoring.\n", bit_rate);
@@ -11267,8 +11331,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
found = TRUE;
}
}
- break;
- case AST_FORMAT_G719:
+ } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 64000) {
ast_log(LOG_WARNING, "Got G.719 offer at %u bps, but only 64000 bps supported; ignoring.\n", bit_rate);
@@ -11277,8 +11340,8 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
found = TRUE;
}
}
- break;
}
+ ao2_ref(format, -1);
}
}
@@ -11320,11 +11383,19 @@ static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_
struct ast_format *format;
if ((format = ast_rtp_codecs_get_payload_format(newvideortp, codec))) {
- if (!ast_format_sdp_parse(format, fmtp_string)) {
+ struct ast_format *format_parsed;
+
+ format_parsed = ast_format_parse_sdp_fmtp(format, fmtp_string);
+
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(newvideortp, codec, format_parsed);
+ ao2_replace(format, format_parsed);
+ ao2_ref(format_parsed, -1);
found = TRUE;
} else {
ast_rtp_codecs_payloads_unset(newvideortp, NULL, codec);
}
+ ao2_ref(format, -1);
}
}
@@ -12890,12 +12961,11 @@ static void add_codec_to_sdp(const struct sip_pvt *p,
int *max_packet_size)
{
int rtp_code;
- struct ast_format_list fmt;
const char *mime;
- unsigned int rate;
+ unsigned int rate, framing;
if (debug)
- ast_verbose("Adding codec %u (%s) to SDP\n", format->id, ast_getformatname(format));
+ ast_verbose("Adding codec %s to SDP\n", ast_format_get_name(format));
if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, format, 0)) == -1) ||
!(mime = ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0)) ||
@@ -12903,63 +12973,54 @@ static void add_codec_to_sdp(const struct sip_pvt *p,
return;
}
- if (p->rtp) {
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
- fmt = ast_codec_pref_getsize(pref, format);
- } else /* I don't see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */
- return;
ast_str_append(m_buf, 0, " %d", rtp_code);
/* Opus mandates 2 channels in rtpmap */
- if ((int)format->id == AST_FORMAT_OPUS) {
+ if (ast_format_cmp(format, ast_format_opus) == AST_FORMAT_CMP_EQUAL) {
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u/2\r\n", rtp_code, mime, rate);
} else {
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u\r\n", rtp_code, mime, rate);
}
- ast_format_sdp_generate(format, rtp_code, a_buf);
+ ast_format_generate_sdp_fmtp(format, rtp_code, a_buf);
+
+ framing = ast_format_cap_get_format_framing(p->caps, format);
- switch ((int) format->id) {
- case AST_FORMAT_G729A:
+ if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we don't support VAD (G.729 annex B) */
ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code);
- break;
- case AST_FORMAT_G723_1:
+ } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we don't support VAD (G.723.1 annex A) */
ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code);
- break;
- case AST_FORMAT_ILBC:
+ } else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL) {
/* Add information about us using only 20/30 ms packetization */
- ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms);
- break;
- case AST_FORMAT_SIREN7:
+ ast_str_append(a_buf, 0, "a=fmtp:%d mode=%u\r\n", rtp_code, framing);
+ } else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we only expect 32Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=32000\r\n", rtp_code);
- break;
- case AST_FORMAT_SIREN14:
+ } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we only expect 48Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=48000\r\n", rtp_code);
- break;
- case AST_FORMAT_G719:
+ } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we only expect 64Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code);
- break;
}
- if (max_packet_size && fmt.max_ms && (fmt.max_ms < *max_packet_size)) {
- *max_packet_size = fmt.max_ms;
+ if (max_packet_size && ast_format_get_maximum_ms(format) &&
+ (ast_format_get_maximum_ms(format) < *max_packet_size)) {
+ *max_packet_size = ast_format_get_maximum_ms(format);
}
- if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) {
- *min_packet_size = fmt.cur_ms;
+ if (framing && (framing < *min_packet_size)) {
+ *min_packet_size = framing;
}
/* Our first codec packetization processed cannot be zero */
- if ((*min_packet_size) == 0 && fmt.cur_ms) {
- *min_packet_size = fmt.cur_ms;
+ if ((*min_packet_size) == 0 && framing) {
+ *min_packet_size = framing;
}
- if ((*max_packet_size) == 0 && fmt.max_ms) {
- *max_packet_size = fmt.max_ms;
+ if ((*max_packet_size) == 0 && ast_format_get_maximum_ms(format)) {
+ *max_packet_size = ast_format_get_maximum_ms(format);
}
}
@@ -12977,7 +13038,7 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
return;
if (debug)
- ast_verbose("Adding video codec %u (%s) to SDP\n", format->id, ast_getformatname(format));
+ ast_verbose("Adding video codec %s to SDP\n", ast_format_get_name(format));
if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, format, 0)) == -1) ||
!(subtype = ast_rtp_lookup_mime_subtype2(1, format, 0, 0)) ||
@@ -12988,11 +13049,11 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
ast_str_append(m_buf, 0, " %d", rtp_code);
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u\r\n", rtp_code, subtype, rate);
/* VP8: add RTCP FIR support */
- if ((int)format->id == AST_FORMAT_VP8) {
+ if (ast_format_cmp(format, ast_format_vp8) == AST_FORMAT_CMP_EQUAL) {
ast_str_append(a_buf, 0, "a=rtcp-fb:* ccm fir\r\n");
}
- ast_format_sdp_generate(format, rtp_code, a_buf);
+ ast_format_generate_sdp_fmtp(format, rtp_code, a_buf);
}
/*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */
@@ -13006,7 +13067,7 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
return;
if (debug)
- ast_verbose("Adding text codec %u (%s) to SDP\n", format->id, ast_getformatname(format));
+ ast_verbose("Adding text codec %s to SDP\n", ast_format_get_name(format));
if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, format, 0)) == -1)
return;
@@ -13017,9 +13078,8 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format
ast_rtp_lookup_sample_rate2(1, format, 0));
/* Add fmtp code here */
- if (format->id == AST_FORMAT_T140RED) {
- struct ast_format tmp_fmt;
- int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_set(&tmp_fmt, AST_FORMAT_T140, 0), 0);
+ if (ast_format_cmp(format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {
+ int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_t140, 0);
ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code,
t140code,
t140code,
@@ -13194,8 +13254,8 @@ static char *crypto_get_attrib(struct ast_sdp_srtp *srtp, int dtls_enabled, int
*/
static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
{
- struct ast_format_cap *alreadysent = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *alreadysent = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int res = AST_SUCCESS;
int doing_directmedia = FALSE;
struct ast_sockaddr addr = { {0,} };
@@ -13229,7 +13289,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
RAII_VAR(char *, t_a_crypto, NULL, ast_free);
int x;
- struct ast_format tmp_fmt;
+ struct ast_format *tmp_fmt;
int needaudio = FALSE;
int needvideo = FALSE;
int needtext = FALSE;
@@ -13239,8 +13299,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
int min_video_packet_size = 0;
int min_text_packet_size = 0;
- char codecbuf[SIPBUFSIZE];
- char buf[SIPBUFSIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
/* Set the SDP session name */
snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession);
@@ -13268,11 +13327,24 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
}
if (add_audio) {
- doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && !(ast_format_cap_is_empty(p->redircaps))) ? TRUE : FALSE;
+ doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && (ast_format_cap_count(p->redircaps))) ? TRUE : FALSE;
+
+ if (doing_directmedia) {
+ ast_format_cap_get_compatible(p->jointcaps, p->redircaps, tmpcap);
+ ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_format_cap_get_names(tmpcap, &codec_buf));
+ } else {
+ ast_format_cap_append_from_cap(tmpcap, p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ }
+
+ /* Check if we need audio */
+ if (ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_AUDIO)
+ || ast_format_cap_has_type(p->caps, AST_MEDIA_TYPE_AUDIO)) {
+ needaudio = TRUE;
+ }
+
/* Check if we need video in this call */
- if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_VIDEO)) && !p->novideo) {
- ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap);
- if (doing_directmedia && !ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_VIDEO)) {
+ if ((ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_VIDEO)) && !p->novideo) {
+ if (doing_directmedia && !ast_format_cap_has_type(tmpcap, AST_MEDIA_TYPE_VIDEO)) {
ast_debug(2, "This call needs video offers, but caller probably did not offer it!\n");
} else if (p->vrtp) {
needvideo = TRUE;
@@ -13281,8 +13353,9 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ast_debug(2, "This call needs video offers, but there's no video support enabled!\n");
}
}
+
/* Check if we need text in this call */
- if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_TEXT)) && !p->notext) {
+ if ((ast_format_cap_has_type(p->jointcaps, AST_MEDIA_TYPE_TEXT)) && !p->notext) {
if (sipdebug_text)
ast_verbose("We think we can do text\n");
if (p->trtp) {
@@ -13295,6 +13368,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n");
}
}
+
+ /* XXX note, Video and Text are negated - 'true' means 'no' */
+ ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n",
+ ast_format_cap_get_names(tmpcap, &codec_buf),
+ p->novideo ? "True" : "False", p->notext ? "True" : "False");
+ ast_debug(1, "** Our prefcodec: %s \n", ast_format_cap_get_names(p->prefcaps, &codec_buf));
}
get_our_media_address(p, needvideo, needtext, &addr, &vaddr, &taddr, &dest, &vdest, &tdest);
@@ -13322,22 +13401,6 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
hold = "a=sendrecv\r\n";
}
- ast_format_cap_copy(tmpcap, p->jointcaps);
-
- /* XXX note, Video and Text are negated - 'true' means 'no' */
- ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap),
- p->novideo ? "True" : "False", p->notext ? "True" : "False");
- ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcaps));
-
- if (doing_directmedia) {
- ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap);
- ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap));
- }
-
- /* Check if we need audio */
- if (ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_AUDIO))
- needaudio = TRUE;
-
if (debug) {
ast_verbose("Audio is at %s\n", ast_sockaddr_stringify_port(&addr));
}
@@ -13406,8 +13469,8 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
/* Now, start adding audio codecs. These are added in this order:
- First what was requested by the calling channel
+ - Then our mutually shared capabilities, determined previous in tmpcap
- Then preferences in order from sip.conf device config for this peer/user
- - Then other codecs in capabilities, including video
*/
@@ -13415,57 +13478,62 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
* configured codecs.
*/
if (!ast_test_flag(&p->flags[2], SIP_PAGE3_IGNORE_PREFCAPS)) {
- ast_format_cap_iter_start(p->prefcaps);
- while (!(ast_format_cap_iter_next(p->prefcaps, &tmp_fmt))) {
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO ||
- !ast_format_cap_iscompatible(tmpcap, &tmp_fmt)) {
+ for (x = 0; x < ast_format_cap_count(p->prefcaps); x++) {
+ tmp_fmt = ast_format_cap_get_format(p->prefcaps, x);
+
+ if ((ast_format_get_type(tmp_fmt) != AST_MEDIA_TYPE_AUDIO) ||
+ (ast_format_cap_iscompatible_format(tmpcap, tmp_fmt) == AST_FORMAT_CMP_NOT_EQUAL)) {
+ ao2_ref(tmp_fmt, -1);
continue;
}
- add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
- ast_format_cap_add(alreadysent, &tmp_fmt);
+
+ add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
+ ast_format_cap_append(alreadysent, tmp_fmt, 0);
+ ao2_ref(tmp_fmt, -1);
}
- ast_format_cap_iter_end(p->prefcaps);
}
- /* Start by sending our preferred audio/video codecs */
- for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- struct ast_format pref;
-
- if (!(ast_codec_pref_index(&p->prefs, x, &pref)))
- break;
-
- if (!ast_format_cap_get_compatible_format(tmpcap, &pref, &tmp_fmt))
- continue;
+ /* Now send any other common codecs */
+ for (x = 0; x < ast_format_cap_count(tmpcap); x++) {
+ tmp_fmt = ast_format_cap_get_format(tmpcap, x);
- if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt))
+ if (ast_format_cap_iscompatible_format(alreadysent, tmp_fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ao2_ref(tmp_fmt, -1);
continue;
+ }
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) {
- add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
- } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) {
- add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
- } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) {
- add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
+ if (ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_AUDIO) {
+ add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
+ } else if (needvideo && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_VIDEO) {
+ add_vcodec_to_sdp(p, tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
+ } else if (needtext && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_TEXT) {
+ add_tcodec_to_sdp(p, tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
}
- ast_format_cap_add(alreadysent, &tmp_fmt);
+ ast_format_cap_append(alreadysent, tmp_fmt, 0);
+ ao2_ref(tmp_fmt, -1);
}
- /* Now send any other common audio and video codecs, and non-codec formats: */
- ast_format_cap_iter_start(tmpcap);
- while (!(ast_format_cap_iter_next(tmpcap, &tmp_fmt))) {
- if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt))
+ /* Finally our remaining audio/video codecs */
+ for (x = 0; x < ast_format_cap_count(p->caps); x++) {
+ tmp_fmt = ast_format_cap_get_format(p->caps, x);
+
+ if (ast_format_cap_iscompatible_format(alreadysent, tmp_fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ao2_ref(tmp_fmt, -1);
continue;
+ }
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) {
- add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
- } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) {
- add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
- } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) {
- add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
+ if (ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_AUDIO) {
+ add_codec_to_sdp(p, tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size, &max_audio_packet_size);
+ } else if (needvideo && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_VIDEO) {
+ add_vcodec_to_sdp(p, tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
+ } else if (needtext && ast_format_get_type(tmp_fmt) == AST_MEDIA_TYPE_TEXT) {
+ add_tcodec_to_sdp(p, tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
}
+
+ ast_format_cap_append(alreadysent, tmp_fmt, 0);
+ ao2_ref(tmp_fmt, -1);
}
- ast_format_cap_iter_end(tmpcap);
/* Now add DTMF RFC2833 telephony-event as a codec */
for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
@@ -13677,14 +13745,15 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ao2_t_link(dialogs_rtpcheck, p, "link pvt into dialogs_rtpcheck container");
ao2_unlock(dialogs_rtpcheck);
- ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmpcap));
+ ast_debug(3, "Done building SDP. Settling with this capability: %s\n",
+ ast_format_cap_get_names(tmpcap, &codec_buf));
add_sdp_cleanup:
ast_free(a_text);
ast_free(a_video);
ast_free(a_audio);
- alreadysent = ast_format_cap_destroy(alreadysent);
- tmpcap = ast_format_cap_destroy(tmpcap);
+ ao2_cleanup(alreadysent);
+ ao2_cleanup(tmpcap);
return res;
}
@@ -13792,7 +13861,7 @@ static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const
if (p->rtp) {
if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
ast_debug(1, "Setting framing from config on incoming call\n");
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(p->caps));
}
ast_rtp_instance_activate(p->rtp);
try_suggested_sip_codec(p);
@@ -18475,10 +18544,9 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
peer->name, of, ast_sockaddr_stringify(&p->recv));
}
- /* XXX what about p->prefs = peer->prefs; ? */
/* Set Frame packetization */
if (p->rtp) {
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(peer->caps));
p->autoframing = peer->autoframing;
}
@@ -18595,20 +18663,22 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
p->named_callgroups = ast_ref_namedgroups(peer->named_callgroups);
ast_unref_namedgroups(p->named_pickupgroups);
p->named_pickupgroups = ast_ref_namedgroups(peer->named_pickupgroups);
- ast_format_cap_copy(p->caps, peer->caps);
- ast_format_cap_copy(p->jointcaps, peer->caps);
- p->prefs = peer->prefs;
+ ast_format_cap_remove_by_type(p->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->caps, peer->caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, peer->caps, AST_MEDIA_TYPE_UNKNOWN);
ast_copy_string(p->zone, peer->zone, sizeof(p->zone));
if (peer->maxforwards > 0) {
p->maxforwards = peer->maxforwards;
}
- if (!(ast_format_cap_is_empty(p->peercaps))) {
- struct ast_format_cap *tmp = ast_format_cap_joint(p->jointcaps, p->peercaps);
- struct ast_format_cap *tmp2;
- if (tmp) {
- tmp2 = p->jointcaps;
- p->jointcaps = tmp;
- ast_format_cap_destroy(tmp2);
+ if (ast_format_cap_count(p->peercaps)) {
+ struct ast_format_cap *joint;
+
+ joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (joint) {
+ ast_format_cap_get_compatible(p->jointcaps, p->peercaps, joint);
+ ao2_ref(p->jointcaps, -1);
+ p->jointcaps = joint;
}
}
p->maxcallbitrate = peer->maxcallbitrate;
@@ -18623,7 +18693,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
p->rtpkeepalive = peer->rtpkeepalive;
if (!dialog_initialize_rtp(p)) {
if (p->rtp) {
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp), ast_format_cap_get_framing(peer->caps));
p->autoframing = peer->autoframing;
}
} else {
@@ -19959,25 +20029,6 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli
return CLI_SUCCESS;
}
-/*! \brief Print codec list from preference to CLI/manager */
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
-{
- int x;
- struct ast_format codec;
-
- for(x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- if (!(ast_codec_pref_index(pref, x, &codec))) {
- break;
- }
- ast_cli(fd, "%s", ast_getformatname(&codec));
- ast_cli(fd, ":%d", pref->framing[x]);
- if (x < 31 && ast_codec_pref_index(pref, x + 1, &codec))
- ast_cli(fd, ",");
- }
- if (!x)
- ast_cli(fd, "none");
-}
-
/*! \brief Print domain mode to cli */
static const char *domain_mode_to_text(const enum domain_mode mode)
{
@@ -20262,11 +20313,9 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
char status[30] = "";
char cbuf[256];
struct sip_peer *peer;
- char codec_buf[512];
- struct ast_codec_pref *pref;
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_variable *v;
int x = 0, load_realtime;
- struct ast_format codec;
int realtimepeers;
realtimepeers = ast_check_realtime("sippeers");
@@ -20415,12 +20464,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
ast_cli(fd, "(none)");
ast_cli(fd, "\n");
- ast_cli(fd, " Codecs : ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, " Codec Order : (");
- print_codec_to_cli(fd, &peer->prefs);
- ast_cli(fd, ")\n");
+ ast_cli(fd, " Codecs : %s\n", ast_format_cap_get_names(peer->caps, &codec_buf));
ast_cli(fd, " Auto-Framing : %s\n", AST_CLI_YESNO(peer->autoframing));
ast_cli(fd, " Status : ");
@@ -20523,21 +20567,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
astman_append(s, "Default-Username: %s\r\n", peer->username);
if (!ast_strlen_zero(sip_cfg.regcontext))
astman_append(s, "RegExtension: %s\r\n", peer->regexten);
- astman_append(s, "Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps);
- astman_append(s, "%s\r\n", codec_buf);
- astman_append(s, "CodecOrder: ");
- pref = &peer->prefs;
- for(x = 0; x < AST_CODEC_PREF_SIZE ; x++) {
- if (!(ast_codec_pref_index(pref, x, &codec))) {
- break;
- }
- astman_append(s, "%s", ast_getformatname(&codec));
- if ((x < (AST_CODEC_PREF_SIZE - 1)) && ast_codec_pref_index(pref, x+1, &codec))
- astman_append(s, ",");
- }
-
- astman_append(s, "\r\n");
+ astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(peer->caps, &codec_buf));
astman_append(s, "Status: ");
peer_status(peer, status, sizeof(status));
astman_append(s, "%s\r\n", status);
@@ -20660,10 +20690,6 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args
ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se);
ast_cli(a->fd, " RTP Engine : %s\n", user->engine);
- ast_cli(a->fd, " Codec Order : (");
- print_codec_to_cli(a->fd, &user->prefs);
- ast_cli(a->fd, ")\n");
-
ast_cli(a->fd, " Auto-Framing: %s \n", AST_CLI_YESNO(user->autoframing));
if (user->chanvars) {
ast_cli(a->fd, " Variables :\n");
@@ -20916,7 +20942,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
{
int realtimepeers;
int realtimeregs;
- char codec_buf[SIPBUFSIZE];
+ struct ast_str *codec_buf = ast_str_alloca(64);
const char *msg; /* temporary msg pointer */
struct sip_auth_container *credentials;
@@ -21069,12 +21095,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
}
ast_cli(a->fd, "\nGlobal Signalling Settings:\n");
ast_cli(a->fd, "---------------------------\n");
- ast_cli(a->fd, " Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, sip_cfg.caps);
- ast_cli(a->fd, "%s\n", codec_buf);
- ast_cli(a->fd, " Codec Order: ");
- print_codec_to_cli(a->fd, &default_prefs);
- ast_cli(a->fd, "\n");
+ ast_cli(a->fd, " Codecs: %s\n", ast_format_cap_get_names(sip_cfg.caps, &codec_buf));
ast_cli(a->fd, " Relax DTMF: %s\n", AST_CLI_YESNO(global_relaxdtmf));
ast_cli(a->fd, " RFC2833 Compensation: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_RFC2833_COMPENSATE)));
ast_cli(a->fd, " Symmetric RTP: %s\n", comedia_string(global_flags));
@@ -21233,12 +21254,12 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
if (cur->subscribed == NONE && !arg->subscriptions) {
/* set if SIP transfer in progress */
const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
- char formatbuf[SIPBUFSIZE/2];
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_cli(arg->fd, FORMAT, ast_sockaddr_stringify_addr(dst),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
- cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), ast_channel_nativeformats(cur->owner)) : "(nothing)",
+ cur->owner ? ast_format_cap_get_names(ast_channel_nativeformats(cur->owner), &codec_buf) : "(nothing)",
AST_CLI_YESNO(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)),
cur->needdestroy ? "(d)" : "",
cur->lastmsg ,
@@ -21479,7 +21500,8 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
if (!strncasecmp(cur->callid, a->argv[3], len)) {
struct ast_str *strbuf;
- char formatbuf[SIPBUFSIZE/2];
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
ast_cli(a->fd, "\n");
if (cur->subscribed != NONE) {
ast_cli(a->fd, " * Subscription (type: %s)\n", subscription_type2str(cur->subscribed));
@@ -21489,11 +21511,11 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
ast_cli(a->fd, " Curr. trans. direction: %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING) ? "Outgoing" : "Incoming");
ast_cli(a->fd, " Call-ID: %s\n", cur->callid);
ast_cli(a->fd, " Owner channel ID: %s\n", cur->owner ? ast_channel_name(cur->owner) : "<none>");
- ast_cli(a->fd, " Our Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->caps));
+ ast_cli(a->fd, " Our Codec Capability: %s\n", ast_format_cap_get_names(cur->caps, &codec_buf));
ast_cli(a->fd, " Non-Codec Capability (DTMF): %d\n", cur->noncodeccapability);
- ast_cli(a->fd, " Their Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->peercaps));
- ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->jointcaps));
- ast_cli(a->fd, " Format: %s\n", cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), ast_channel_nativeformats(cur->owner)) : "(nothing)" );
+ ast_cli(a->fd, " Their Codec Capability: %s\n", ast_format_cap_get_names(cur->peercaps, &codec_buf));
+ ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_format_cap_get_names(cur->jointcaps, &codec_buf));
+ ast_cli(a->fd, " Format: %s\n", cur->owner ? ast_format_cap_get_names(ast_channel_nativeformats(cur->owner), &codec_buf) : "(nothing)" );
ast_cli(a->fd, " T.38 support %s\n", AST_CLI_YESNO(cur->udptl != NULL));
ast_cli(a->fd, " Video support %s\n", AST_CLI_YESNO(cur->vrtp != NULL));
ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate);
@@ -22437,7 +22459,9 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
} else if (!strcasecmp(colname, "callerid_num")) {
ast_copy_string(buf, peer->cid_num, len);
} else if (!strcasecmp(colname, "codecs")) {
- ast_getformatname_multiple(buf, len -1, peer->caps);
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_format_cap_get_names(peer->caps, &codec_buf);
+ ast_copy_string(buf, ast_str_buffer(codec_buf), len);
} else if (!strcasecmp(colname, "encryption")) {
snprintf(buf, len, "%u", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP));
} else if (!strncasecmp(colname, "chanvar[", 8)) {
@@ -22452,12 +22476,14 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
}
} else if (!strncasecmp(colname, "codec[", 6)) {
char *codecnum;
- struct ast_format codec;
+ struct ast_format *codec;
codecnum = colname + 6; /* move past the '[' */
codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */
- if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &codec))) {
- ast_copy_string(buf, ast_getformatname(&codec), len);
+ codec = ast_format_cap_get_format(peer->caps, atoi(codecnum));
+ if (codec) {
+ ast_copy_string(buf, ast_format_get_name(codec), len);
+ ao2_ref(codec, -1);
} else {
buf[0] = '\0';
}
@@ -25476,7 +25502,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
}
ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE);
} else {
- ast_format_cap_copy(p->jointcaps, p->caps);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, p->caps, AST_MEDIA_TYPE_UNKNOWN);
ast_debug(1, "Hm.... No sdp for the moment\n");
/* Some devices signal they want to be put off hold by sending a re-invite
*without* an SDP, which is supposed to mean "Go back to your state"
@@ -25541,7 +25568,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
goto request_invite_cleanup;
}
} else { /* No SDP in invite, call control session */
- ast_format_cap_copy(p->jointcaps, p->caps);
+ ast_format_cap_remove_by_type(p->jointcaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->jointcaps, p->caps, AST_MEDIA_TYPE_UNKNOWN);
ast_debug(2, "No SDP in Invite, third party call control\n");
}
@@ -25855,7 +25883,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
if (p && (p->autokillid == -1)) {
const char *msg;
- if ((ast_format_cap_is_empty(p->jointcaps)))
+ if ((!ast_format_cap_count(p->jointcaps)))
msg = "488 Not Acceptable Here (codec error)";
else {
ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n");
@@ -29539,7 +29567,8 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
struct ast_channel *tmpc = NULL;
char *ext = NULL, *host;
char tmp[256];
- char tmp2[256];
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
char *dnid;
char *secret = NULL;
char *md5secret = NULL;
@@ -29562,14 +29591,14 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
* configured from sip.conf, and sip_tech.capabilities, which is
* hardwired to all audio formats.
*/
- if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
+ if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n",
- ast_getformatname_multiple(tmp, sizeof(tmp), cap),
- ast_getformatname_multiple(tmp2, sizeof(tmp2), sip_cfg.caps));
+ ast_format_cap_get_names(cap, &codec_buf),
+ ast_format_cap_get_names(sip_cfg.caps, &cap_buf));
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; /* Can't find codec to connect to host */
return NULL;
}
- ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_format_cap_get_names(cap, &codec_buf));
if (ast_strlen_zero(dest)) {
ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
@@ -29739,8 +29768,8 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
#if 0
printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host);
#endif
- ast_format_cap_append(p->prefcaps, cap);
- ast_format_cap_joint_copy(cap, p->caps, p->jointcaps);
+ ast_format_cap_append_from_cap(p->prefcaps, cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_get_compatible(cap, p->caps, p->jointcaps);
sip_pvt_lock(p);
@@ -30217,7 +30246,7 @@ static void set_peer_defaults(struct sip_peer *peer)
ast_string_field_set(peer, engine, default_engine);
ast_sockaddr_setnull(&peer->addr);
ast_sockaddr_setnull(&peer->defaddr);
- ast_format_cap_copy(peer->caps, sip_cfg.caps);
+ ast_format_cap_append_from_cap(peer->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN);
peer->maxcallbitrate = default_maxcallbitrate;
peer->rtptimeout = global_rtptimeout;
peer->rtpholdtimeout = global_rtpholdtimeout;
@@ -30243,7 +30272,6 @@ static void set_peer_defaults(struct sip_peer *peer)
peer->pickupgroup = 0;
peer->maxms = default_qualify;
peer->keepalive = default_keepalive;
- peer->prefs = default_prefs;
ast_string_field_set(peer, zone, default_zone);
peer->stimer.st_mode_oper = global_st_mode; /* Session-Timers */
peer->stimer.st_ref = global_st_refresher;
@@ -30279,7 +30307,7 @@ static struct sip_peer *temp_peer(const char *name)
return NULL;
}
- if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer");
return NULL;
}
@@ -30291,7 +30319,6 @@ static struct sip_peer *temp_peer(const char *name)
peer->selfdestruct = TRUE;
peer->host_dynamic = TRUE;
- peer->prefs = default_prefs;
reg_source_db(peer);
return peer;
@@ -30384,7 +30411,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
if (!(peer->endpoint = ast_endpoint_create("SIP", name))) {
return NULL;
}
- if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(peer->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer");
return NULL;
}
@@ -30705,12 +30732,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
} else if (!strcasecmp(v->name, "namedpickupgroup")) {
peer->named_pickupgroups = ast_get_namedgroups(v->value);
} else if (!strcasecmp(v->name, "allow")) {
- int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, TRUE);
+ int error = ast_format_cap_update_by_allow_disallow(peer->caps, v->value, TRUE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
} else if (!strcasecmp(v->name, "disallow")) {
- int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, FALSE);
+ int error = ast_format_cap_update_by_allow_disallow(peer->caps, v->value, FALSE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
@@ -31104,14 +31131,11 @@ static int peer_markall_autopeers_func(void *device, void *arg, int flags)
*/
static void sip_set_default_format_capabilities(struct ast_format_cap *cap)
{
- struct ast_format tmp_fmt;
-
- ast_format_cap_remove_all(cap);
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_TESTLAW, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ALAW, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_H263, 0));
+ ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append(cap, ast_format_ulaw, 0);
+ ast_format_cap_append(cap, ast_format_alaw, 0);
+ ast_format_cap_append(cap, ast_format_gsm, 0);
+ ast_format_cap_append(cap, ast_format_h263, 0);
}
static void display_nat_warning(const char *cat, int reason, struct ast_flags *flags) {
@@ -31276,7 +31300,6 @@ static int reload_config(enum channelreloadreason reason)
memset(&localaddr, 0, sizeof(localaddr));
memset(&externaddr, 0, sizeof(externaddr));
memset(&media_address, 0, sizeof(media_address));
- memset(&default_prefs, 0 , sizeof(default_prefs));
memset(&sip_cfg.outboundproxy, 0, sizeof(struct sip_proxy));
sip_cfg.outboundproxy.force = FALSE; /*!< Don't force proxy usage, use route: headers */
default_transports = AST_TRANSPORT_UDP;
@@ -31768,12 +31791,12 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "Invalid externtlsport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
}
} else if (!strcasecmp(v->name, "allow")) {
- int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, TRUE);
+ int error = ast_format_cap_update_by_allow_disallow(sip_cfg.caps, v->value, TRUE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
} else if (!strcasecmp(v->name, "disallow")) {
- int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, FALSE);
+ int error = ast_format_cap_update_by_allow_disallow(sip_cfg.caps, v->value, FALSE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
@@ -32565,8 +32588,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
memset(&p->tredirip, 0, sizeof(p->tredirip));
changed = 1;
}
- if (cap && !ast_format_cap_is_empty(cap) && !ast_format_cap_identical(p->redircaps, cap)) {
- ast_format_cap_copy(p->redircaps, cap);
+ if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(cap, p->redircaps)) {
+ ast_format_cap_remove_by_type(p->redircaps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(p->redircaps, cap, AST_MEDIA_TYPE_UNKNOWN);
changed = 1;
}
@@ -32603,7 +32627,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
static void sip_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
{
struct sip_pvt *p = ast_channel_tech_pvt(chan);
- ast_format_cap_append(result, ast_format_cap_is_empty(p->peercaps) ? p->caps : p->peercaps);
+
+ ast_format_cap_append_from_cap(result, !ast_format_cap_count(p->peercaps) ? p->caps : p->peercaps, AST_MEDIA_TYPE_UNKNOWN);
}
static struct ast_rtp_glue sip_rtp_glue = {
@@ -34217,6 +34242,8 @@ static const struct ast_sip_api_tech chan_sip_api_provider = {
.sipinfo_send = sipinfo_send,
};
+static int unload_module(void);
+
/*!
* \brief Load the module
*
@@ -34232,14 +34259,17 @@ static int load_module(void)
ast_verbose("SIP channel loading...\n");
if (STASIS_MESSAGE_TYPE_INIT(session_timeout_type)) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (!(sip_tech.capabilities = ast_format_cap_alloc(0))) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (ast_sip_api_provider_register(&chan_sip_api_provider)) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
@@ -34254,24 +34284,28 @@ static int load_module(void)
if (!peers || !peers_by_ip || !dialogs || !dialogs_needdestroy || !dialogs_rtpcheck
|| !threadt) {
ast_log(LOG_ERROR, "Unable to create primary SIP container(s)\n");
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
- if (!(sip_cfg.caps = ast_format_cap_alloc(0))) {
+ if (!(sip_cfg.caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
- ast_format_cap_add_all_by_type(sip_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_append_by_type(sip_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
ASTOBJ_CONTAINER_INIT(&regl); /* Registry object list -- not searched for anything */
ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create scheduler context\n");
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (!(io = io_context_create())) {
ast_log(LOG_ERROR, "Unable to create I/O context\n");
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
@@ -34279,15 +34313,14 @@ static int load_module(void)
can_parse_xml = sip_is_xml_parsable();
if (reload_config(sip_reloadreason)) { /* Load the configuration from sip.conf */
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
/* Initialize bogus peer. Can be done first after reload_config() */
if (!(bogus_peer = temp_peer("(bogus_peer)"))) {
ast_log(LOG_ERROR, "Unable to create bogus_peer for authentication\n");
- io_context_destroy(io);
- ast_sched_context_destroy(sched);
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure the auth will always fail. */
@@ -34302,16 +34335,14 @@ static int load_module(void)
memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
if (ast_msg_tech_register(&sip_msg_tech)) {
- /* LOAD_FAILURE stops Asterisk, so cleanup is a moot point. */
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure we can register our sip channel type */
if (ast_channel_register(&sip_tech)) {
ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
- ao2_t_ref(bogus_peer, -1, "unref the bogus_peer");
- io_context_destroy(io);
- ast_sched_context_destroy(sched);
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
}
@@ -34358,13 +34389,13 @@ static int load_module(void)
initialize_escs();
if (sip_epa_register(&cc_epa_static_data)) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
if (sip_reqresp_parser_init() == -1) {
ast_log(LOG_ERROR, "Unable to initialize the SIP request and response parser\n");
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
@@ -34373,16 +34404,16 @@ static int load_module(void)
* in incoming PUBLISH requests
*/
if (ast_cc_agent_register(&sip_cc_agent_callbacks)) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
}
if (ast_cc_monitor_register(&sip_cc_monitor_callbacks)) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
if (!(sip_monitor_instances = ao2_container_alloc(37, sip_monitor_instance_hash_fn, sip_monitor_instance_cmp_fn))) {
- ast_sip_api_provider_unregister();
+ unload_module();
return AST_MODULE_LOAD_DECLINE;
}
@@ -34523,7 +34554,7 @@ static int unload_module(void)
ast_mutex_lock(&authl_lock);
if (authl) {
- ao2_t_ref(authl, -1, "Removing global authentication");
+ ao2_t_cleanup(authl, "Removing global authentication");
authl = NULL;
}
ast_mutex_unlock(&authl_lock);
@@ -34568,15 +34599,15 @@ static int unload_module(void)
ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
}
- ao2_t_ref(bogus_peer, -1, "unref the bogus_peer");
+ ao2_t_cleanup(bogus_peer, "unref the bogus_peer");
- ao2_t_ref(peers, -1, "unref the peers table");
- ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table");
- ao2_t_ref(dialogs, -1, "unref the dialogs table");
- ao2_t_ref(dialogs_needdestroy, -1, "unref dialogs_needdestroy");
- ao2_t_ref(dialogs_rtpcheck, -1, "unref dialogs_rtpcheck");
- ao2_t_ref(threadt, -1, "unref the thread table");
- ao2_t_ref(sip_monitor_instances, -1, "unref the sip_monitor_instances table");
+ ao2_t_cleanup(peers, "unref the peers table");
+ ao2_t_cleanup(peers_by_ip, "unref the peers_by_ip table");
+ ao2_t_cleanup(dialogs, "unref the dialogs table");
+ ao2_t_cleanup(dialogs_needdestroy, "unref dialogs_needdestroy");
+ ao2_t_cleanup(dialogs_rtpcheck, "unref dialogs_rtpcheck");
+ ao2_t_cleanup(threadt, "unref the thread table");
+ ao2_t_cleanup(sip_monitor_instances, "unref the sip_monitor_instances table");
clear_sip_domains();
sip_cfg.contact_acl = ast_free_acl_list(sip_cfg.contact_acl);
@@ -34604,8 +34635,10 @@ static int unload_module(void)
notify_types = NULL;
}
- ast_format_cap_destroy(sip_tech.capabilities);
- sip_cfg.caps = ast_format_cap_destroy(sip_cfg.caps);
+ ao2_cleanup(sip_tech.capabilities);
+ sip_tech.capabilities = NULL;
+ ao2_cleanup(sip_cfg.caps);
+ sip_cfg.caps = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(session_timeout_type);
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 49ff8d548..e4882dbba 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -84,6 +84,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/parking.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<manager name="SKINNYdevices" language="en_US">
@@ -146,8 +147,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#ifdef AST_DEVMODE
static int skinnydebug = 0;
char dbgcli_buf[256];
-char dbgreg_buf[256];
-char dbgsub_buf[256];
#define DEBUG_GENERAL (1 << 1)
#define DEBUG_SUB (1 << 2)
#define DEBUG_PACKET (1 << 3)
@@ -174,7 +173,6 @@ static const char tdesc[] = "Skinny Client Control Protocol (Skinny)";
static const char config[] = "skinny.conf";
static struct ast_format_cap *default_cap;
-static struct ast_codec_pref default_prefs;
enum skinny_codecs {
SKINNY_CODEC_ALAW = 2,
@@ -1454,8 +1452,6 @@ struct skinny_subchannel {
int amaflags; \
int instance; \
int group; \
- struct ast_codec_pref confprefs; \
- struct ast_codec_pref prefs; \
int nonCodecCapability; \
int immediate; \
int nat; \
@@ -1568,7 +1564,6 @@ struct skinny_addon {
int hookstate; \
int lastlineinstance; \
int lastcallreference; \
- struct ast_codec_pref confprefs; \
int earlyrtp; \
int transfer; \
int callwaiting; \
@@ -1679,11 +1674,11 @@ static struct skinny_line *skinny_line_alloc(void)
return NULL;
}
- l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- l->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ l->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!l->cap || !l->confcap) {
- l->cap = ast_format_cap_destroy(l->cap);
- l->confcap = ast_format_cap_destroy(l->confcap);
+ ao2_cleanup(l->cap);
+ ao2_cleanup(l->confcap);
ast_free(l);
return NULL;
}
@@ -1691,8 +1686,8 @@ static struct skinny_line *skinny_line_alloc(void)
}
static struct skinny_line *skinny_line_destroy(struct skinny_line *l)
{
- l->cap = ast_format_cap_destroy(l->cap);
- l->confcap = ast_format_cap_destroy(l->confcap);
+ ao2_ref(l->cap, -1);
+ ao2_ref(l->confcap, -1);
l->named_callgroups = ast_unref_namedgroups(l->named_callgroups);
l->named_pickupgroups = ast_unref_namedgroups(l->named_pickupgroups);
ast_free(l->container);
@@ -1706,12 +1701,12 @@ static struct skinny_device *skinny_device_alloc(const char *dname)
return NULL;
}
- d->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- d->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ d->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ d->confcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
d->endpoint = ast_endpoint_create("Skinny", dname);
if (!d->cap || !d->confcap || !d->endpoint) {
- d->cap = ast_format_cap_destroy(d->cap);
- d->confcap = ast_format_cap_destroy(d->confcap);
+ ao2_cleanup(d->cap);
+ ao2_cleanup(d->confcap);
ast_free(d);
return NULL;
}
@@ -1722,8 +1717,8 @@ static struct skinny_device *skinny_device_alloc(const char *dname)
}
static struct skinny_device *skinny_device_destroy(struct skinny_device *d)
{
- d->cap = ast_format_cap_destroy(d->cap);
- d->confcap = ast_format_cap_destroy(d->confcap);
+ ao2_ref(d->cap, -1);
+ ao2_ref(d->confcap, -1);
ast_endpoint_shutdown(d->endpoint);
ast_free(d);
return NULL;
@@ -2103,51 +2098,49 @@ static struct skinny_speeddial *find_speeddial_by_instance(struct skinny_device
return sd;
}
-static struct ast_format *codec_skinny2ast(enum skinny_codecs skinnycodec, struct ast_format *result)
+static struct ast_format *codec_skinny2ast(enum skinny_codecs skinnycodec)
{
switch (skinnycodec) {
case SKINNY_CODEC_ALAW:
- return ast_format_set(result, AST_FORMAT_ALAW, 0);
+ return ast_format_alaw;
case SKINNY_CODEC_ULAW:
- return ast_format_set(result, AST_FORMAT_ULAW, 0);
+ return ast_format_ulaw;
case SKINNY_CODEC_G722:
- return ast_format_set(result, AST_FORMAT_G722, 0);
+ return ast_format_g722;
case SKINNY_CODEC_G723_1:
- return ast_format_set(result, AST_FORMAT_G723_1, 0);
+ return ast_format_g723;
case SKINNY_CODEC_G729A:
- return ast_format_set(result, AST_FORMAT_G729A, 0);
+ return ast_format_g729;
case SKINNY_CODEC_G726_32:
- return ast_format_set(result, AST_FORMAT_G726_AAL2, 0); /* XXX Is this right? */
+ return ast_format_g726; /* XXX Is this right? */
case SKINNY_CODEC_H261:
- return ast_format_set(result, AST_FORMAT_H261, 0);
+ return ast_format_h261;
case SKINNY_CODEC_H263:
- return ast_format_set(result, AST_FORMAT_H263 ,0);
+ return ast_format_h263;
default:
- ast_format_clear(result);
- return result;
+ return ast_format_none;
}
}
static int codec_ast2skinny(const struct ast_format *astcodec)
{
- switch (astcodec->id) {
- case AST_FORMAT_ALAW:
+ if (ast_format_cmp(astcodec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_ALAW;
- case AST_FORMAT_ULAW:
+ } else if (ast_format_cmp(astcodec, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_ULAW;
- case AST_FORMAT_G722:
+ } else if (ast_format_cmp(astcodec, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G722;
- case AST_FORMAT_G723_1:
+ } else if (ast_format_cmp(astcodec, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G723_1;
- case AST_FORMAT_G729A:
+ } else if (ast_format_cmp(astcodec, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G729A;
- case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
+ } else if (ast_format_cmp(astcodec, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_G726_32;
- case AST_FORMAT_H261:
+ } else if (ast_format_cmp(astcodec, ast_format_h261) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_H261;
- case AST_FORMAT_H263:
+ } else if (ast_format_cmp(astcodec, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
return SKINNY_CODEC_H263;
- default:
+ } else {
return 0;
}
}
@@ -2312,13 +2305,8 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
instance++;
}
AST_LIST_TRAVERSE(&d->lines, l, list) {
- ast_format_cap_joint_copy(l->confcap, d->cap, l->cap);
- l->prefs = l->confprefs;
- if (!l->prefs.order[0]) {
- l->prefs = d->confprefs;
- }
- /* l->capability = d->capability;
- l->prefs = d->prefs; */
+ ast_format_cap_get_compatible(l->confcap, d->cap, l->cap);
+ /* l->capability = d->capability; */
l->instance = instance;
l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
set_callforwards(l, NULL, SKINNY_CFWD_ALL|SKINNY_CFWD_BUSY|SKINNY_CFWD_NOANSWER);
@@ -2656,23 +2644,27 @@ static void transmit_connect(struct skinny_device *d, struct skinny_subchannel *
{
struct skinny_req *req;
struct skinny_line *l = sub->line;
- struct ast_format_list fmt;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ unsigned int framing;
if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
return;
- ast_best_codec(l->cap, &tmpfmt);
- fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
+
+ tmpfmt = ast_format_cap_get_format(l->cap, 0);
+ framing = ast_format_cap_get_format_framing(l->cap, tmpfmt);
req->data.openreceivechannel.conferenceId = htolel(sub->callid);
req->data.openreceivechannel.partyId = htolel(sub->callid);
- req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
- req->data.openreceivechannel.capability = htolel(codec_ast2skinny(&fmt.format));
+ req->data.openreceivechannel.packets = htolel(framing);
+ req->data.openreceivechannel.capability = htolel(codec_ast2skinny(tmpfmt));
req->data.openreceivechannel.echo = htolel(0);
req->data.openreceivechannel.bitrate = htolel(0);
SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting OPEN_RECEIVE_CHANNEL_MESSAGE to %s, confid %u, partyid %u, ms %d, fmt %d, echo %d, brate %d\n",
- d->name, sub->callid, sub->callid, fmt.cur_ms, codec_ast2skinny(&fmt.format), 0, 0);
+ d->name, sub->callid, sub->callid, framing, codec_ast2skinny(tmpfmt), 0, 0);
+
+ ao2_ref(tmpfmt, -1);
+
transmit_response(d, req);
}
@@ -3033,7 +3025,8 @@ static void transmit_stopmediatransmission(struct skinny_device *d, struct skinn
transmit_response(d, req);
}
-static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, struct ast_format_list fmt)
+static void transmit_startmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest,
+ struct ast_format *format, unsigned int framing)
{
struct skinny_req *req;
@@ -3044,8 +3037,8 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin
req->data.startmedia_ip4.passThruPartyId = htolel(sub->callid);
req->data.startmedia_ip4.remoteIp = dest.sin_addr.s_addr;
req->data.startmedia_ip4.remotePort = htolel(ntohs(dest.sin_port));
- req->data.startmedia_ip4.packetSize = htolel(fmt.cur_ms);
- req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(&fmt.format));
+ req->data.startmedia_ip4.packetSize = htolel(framing);
+ req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(format));
req->data.startmedia_ip4.qualifier.precedence = htolel(127);
req->data.startmedia_ip4.qualifier.vad = htolel(0);
req->data.startmedia_ip4.qualifier.packets = htolel(0);
@@ -3057,8 +3050,8 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin
req->data.startmedia_ip6.passThruPartyId = htolel(sub->callid);
memcpy(req->data.startmedia_ip6.remoteIp, &dest.sin_addr.s_addr, sizeof(dest.sin_addr.s_addr));
req->data.startmedia_ip6.remotePort = htolel(ntohs(dest.sin_port));
- req->data.startmedia_ip6.packetSize = htolel(fmt.cur_ms);
- req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(&fmt.format));
+ req->data.startmedia_ip6.packetSize = htolel(framing);
+ req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(format));
req->data.startmedia_ip6.qualifier.precedence = htolel(127);
req->data.startmedia_ip6.qualifier.vad = htolel(0);
req->data.startmedia_ip6.qualifier.packets = htolel(0);
@@ -3066,7 +3059,7 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin
}
SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting START_MEDIA_TRANSMISSION_MESSAGE to %s, callid %u, passthrupartyid %u, ip %s:%d, ms %d, fmt %d, prec 127\n",
- d->name, sub->callid, sub->callid, ast_inet_ntoa(dest.sin_addr), dest.sin_port, fmt.cur_ms, codec_ast2skinny(&fmt.format));
+ d->name, sub->callid, sub->callid, ast_inet_ntoa(dest.sin_addr), dest.sin_port, framing, codec_ast2skinny(format));
transmit_response(d, req);
}
@@ -3643,7 +3636,6 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
struct skinny_subchannel *sub;
struct skinny_line *l;
struct skinny_device *d;
- struct ast_format_list fmt;
struct sockaddr_in us = { 0, };
struct sockaddr_in them = { 0, };
struct ast_sockaddr them_tmp;
@@ -3662,7 +3654,8 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
d = l->device;
if (rtp){
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ unsigned int framing;
ast_rtp_instance_get_remote_address(rtp, &them_tmp);
ast_sockaddr_to_sin(&them_tmp, &them);
@@ -3671,20 +3664,22 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *r
SKINNY_DEBUG(DEBUG_AUDIO, 4, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port));
- ast_best_codec(l->cap, &tmpfmt);
- fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(l->cap, 0);
+ framing = ast_format_cap_get_format_framing(l->cap, tmpfmt);
- SKINNY_DEBUG(DEBUG_AUDIO, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);
+ SKINNY_DEBUG(DEBUG_AUDIO, 4, "Setting payloadType to '%s' (%d ms)\n", ast_format_get_name(tmpfmt), framing);
if (!(l->directmedia) || (l->nat)){
ast_rtp_instance_get_local_address(rtp, &us_tmp);
ast_sockaddr_to_sin(&us_tmp, &us);
us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
- transmit_startmediatransmission(d, sub, us, fmt);
+ transmit_startmediatransmission(d, sub, us, tmpfmt, framing);
} else {
- transmit_startmediatransmission(d, sub, them, fmt);
+ transmit_startmediatransmission(d, sub, them, tmpfmt, framing);
}
+ ao2_ref(tmpfmt, -1);
+
return 0;
}
/* Need a return here to break the bridge */
@@ -4067,25 +4062,6 @@ static char *device2str(int type)
}
}
-/*! \brief Print codec list from preference to CLI/manager */
-static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
-{
- int x;
- struct ast_format tmpfmt;
-
- for(x = 0; x < 32 ; x++) {
- ast_codec_pref_index(pref, x, &tmpfmt);
- if (!tmpfmt.id)
- break;
- ast_cli(fd, "%s", ast_getformatname(&tmpfmt));
- ast_cli(fd, ":%d", pref->framing[x]);
- if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt))
- ast_cli(fd, ",");
- }
- if (!x)
- ast_cli(fd, "none");
-}
-
static char *_skinny_show_devices(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char * const *argv)
{
struct skinny_device *d;
@@ -4204,7 +4180,7 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s
struct skinny_speeddial *sd;
struct skinny_addon *sa;
struct skinny_serviceurl *surl;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
if (argc < 4) {
return CLI_SHOWUSAGE;
@@ -4238,12 +4214,8 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s
ast_cli(fd, "Ip address: %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
ast_cli(fd, "Port: %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
ast_cli(fd, "Device Type: %s\n", device2str(d->type));
- ast_cli(fd, "Conf Codecs:");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->confcap);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, "Neg Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->cap);
- ast_cli(fd, "%s\n", codec_buf);
+ ast_cli(fd, "Conf Codecs: %s\n", ast_format_cap_get_names(d->confcap, &codec_buf));
+ ast_cli(fd, "Neg Codecs: %s\n", ast_format_cap_get_names(d->cap, &codec_buf));
ast_cli(fd, "Registered: %s\n", (d->session ? "Yes" : "No"));
ast_cli(fd, "Lines: %d\n", numlines);
AST_LIST_TRAVERSE(&d->lines, l, list) {
@@ -4270,12 +4242,8 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s
astman_append(s, "Ipaddress: %s\r\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
astman_append(s, "Port: %d\r\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
astman_append(s, "DeviceType: %s\r\n", device2str(d->type));
- astman_append(s, "Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->confcap);
- astman_append(s, "%s\r\n", codec_buf);
- astman_append(s, "CodecOrder: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->cap);
- astman_append(s, "%s\r\n", codec_buf);
+ astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(d->confcap, &codec_buf));
+ astman_append(s, "CodecOrder: %s\r\n", ast_format_cap_get_names(d->cap, &codec_buf));
astman_append(s, "Devicestatus: %s\r\n", (d->session?"registered":"unregistered"));
astman_append(s, "NumberOfLines: %d\r\n", numlines);
AST_LIST_TRAVERSE(&d->lines, l, list) {
@@ -4468,9 +4436,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
struct skinny_device *d;
struct skinny_line *l;
struct skinny_subline *subline;
- struct ast_codec_pref *pref;
- int x = 0;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
char group_buf[256];
char cbuf[256];
@@ -4536,15 +4502,8 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
ast_cli(fd, "immediate: %s\n", (l->immediate ? "Yes" : "No"));
ast_cli(fd, "Group: %d\n", l->group);
ast_cli(fd, "Parkinglot: %s\n", S_OR(l->parkinglot, "<not set>"));
- ast_cli(fd, "Conf Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, "Neg Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->cap);
- ast_cli(fd, "%s\n", codec_buf);
- ast_cli(fd, "Codec Order: (");
- print_codec_to_cli(fd, &l->prefs);
- ast_cli(fd, ")\n");
+ ast_cli(fd, "Conf Codecs: %s\n", ast_format_cap_get_names(l->confcap, &codec_buf));
+ ast_cli(fd, "Neg Codecs: %s\n", ast_format_cap_get_names(l->cap, &codec_buf));
if (AST_LIST_FIRST(&l->sublines)) {
ast_cli(fd, "Sublines:\n");
AST_LIST_TRAVERSE(&l->sublines, subline, list) {
@@ -4592,19 +4551,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No"));
astman_append(s, "Group: %d\r\n", l->group);
astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>"));
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap);
- astman_append(s, "Codecs: %s\r\n", codec_buf);
- astman_append(s, "CodecOrder: ");
- pref = &l->prefs;
- for(x = 0; x < 32 ; x++) {
- struct ast_format tmpfmt;
- ast_codec_pref_index(pref, x, &tmpfmt);
- if (!tmpfmt.id)
- break;
- astman_append(s, "%s", ast_getformatname(&tmpfmt));
- if (x < 31 && ast_codec_pref_index(pref, x+1, &tmpfmt))
- astman_append(s, ",");
- }
+ astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(l->confcap, &codec_buf));
astman_append(s, "\r\n");
}
}
@@ -4802,7 +4749,7 @@ static void start_rtp(struct skinny_subchannel *sub)
struct ast_sockaddr bindaddr_tmp;
skinny_locksub(sub);
- /* Allocate the RTP */
+ SKINNY_DEBUG(DEBUG_AUDIO, 3, "Sub %u - Starting RTP\n", sub->callid);
ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
if (hasvideo)
@@ -4828,14 +4775,14 @@ static void start_rtp(struct skinny_subchannel *sub)
if (sub->rtp) {
ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat);
+ /* Set frame packetization */
+ ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(sub->rtp),
+ ast_format_cap_get_framing(l->cap));
}
if (sub->vrtp) {
ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat);
}
- /* Set Frame packetization */
- if (sub->rtp)
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs);
/* Create the RTP connection */
transmit_connect(d, sub);
@@ -5097,9 +5044,17 @@ static struct ast_frame *skinny_rtp_read(struct skinny_subchannel *sub)
if (ast) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
- ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
- ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format_cap *caps;
+
+ ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(ast, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(ast, ast_channel_readformat(ast));
ast_set_write_format(ast, ast_channel_writeformat(ast));
}
@@ -5130,13 +5085,13 @@ static int skinny_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
} else {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char buf[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return -1;
}
}
@@ -5403,23 +5358,33 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
struct skinny_subchannel *sub;
struct skinny_device *d = l->device;
struct ast_variable *v = NULL;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
+ struct ast_format_cap *caps;
if (!l->device || !l->device->session) {
ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
return NULL;
}
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, assignedids, requestor, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ ao2_ref(caps, -1);
return NULL;
} else {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+
sub = ast_calloc(1, sizeof(*sub));
if (!sub) {
ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
ast_channel_unlock(tmp);
ast_channel_unref(tmp);
+ ao2_ref(caps, -1);
return NULL;
} else {
skinny_set_owner(sub, tmp);
@@ -5452,25 +5417,28 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &skinny_tech);
ast_channel_tech_pvt_set(tmp, sub);
- ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
- // Should throw an error
- ast_format_cap_copy(ast_channel_nativeformats(tmp), default_cap);
+ if (!ast_format_cap_count(l->cap)) {
+ ast_format_cap_append_from_cap(caps, l->cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append_from_cap(caps, default_cap, AST_MEDIA_TYPE_UNKNOWN);
}
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_new: tmp->nativeformats=%s fmt=%s\n",
- ast_getformatname_multiple(dbgsub_buf, sizeof(dbgsub_buf), ast_channel_nativeformats(tmp)),
- ast_getformatname(&tmpfmt));
+ ast_format_cap_get_names(ast_channel_nativeformats(tmp), &codec_buf),
+ ast_format_get_name(tmpfmt));
if (sub->rtp) {
ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
}
if (state == AST_STATE_RING) {
ast_channel_rings_set(tmp, 1);
}
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
if (!ast_strlen_zero(l->language))
ast_channel_language_set(tmp, l->language);
@@ -6676,7 +6644,8 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny
struct skinny_device *d = s->device;
struct skinny_line *l;
uint32_t count = 0;
- struct ast_format_cap *codecs = ast_format_cap_alloc(0);
+ struct ast_format_cap *codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_str *codec_buf = ast_str_alloca(64);
int i;
if (!codecs) {
@@ -6690,23 +6659,23 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny
}
for (i = 0; i < count; i++) {
- struct ast_format acodec;
+ struct ast_format *acodec;
int scodec = 0;
scodec = letohl(req->data.caps.caps[i].codec);
- codec_skinny2ast(scodec, &acodec);
- SKINNY_DEBUG(DEBUG_AUDIO, 4, "Adding codec capability %s (%d)\n", ast_getformatname(&acodec), scodec);
- ast_format_cap_add(codecs, &acodec);
+ acodec = codec_skinny2ast(scodec);
+ SKINNY_DEBUG(DEBUG_AUDIO, 4, "Adding codec capability %s (%d)\n", ast_format_get_name(acodec), scodec);
+ ast_format_cap_append(codecs, acodec, 0);
}
- ast_format_cap_joint_copy(d->confcap, codecs, d->cap);
- SKINNY_DEBUG(DEBUG_AUDIO, 4, "Device capability set to '%s'\n", ast_getformatname_multiple(dbgreg_buf, sizeof(dbgreg_buf), d->cap));
+ ast_format_cap_get_compatible(d->confcap, codecs, d->cap);
+ SKINNY_DEBUG(DEBUG_AUDIO, 4, "Device capability set to '%s'\n", ast_format_cap_get_names(d->cap, &codec_buf));
AST_LIST_TRAVERSE(&d->lines, l, list) {
ast_mutex_lock(&l->lock);
- ast_format_cap_joint_copy(l->confcap, d->cap, l->cap);
+ ast_format_cap_get_compatible(l->confcap, d->cap, l->cap);
ast_mutex_unlock(&l->lock);
}
- codecs = ast_format_cap_destroy(codecs);
+ ao2_ref(codecs, -1);
return 1;
}
@@ -6877,16 +6846,16 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
struct skinny_device *d = s->device;
struct skinny_line *l;
struct skinny_subchannel *sub;
- struct ast_format_list fmt;
struct sockaddr_in sin = { 0, };
struct sockaddr_in us = { 0, };
struct ast_sockaddr sin_tmp;
struct ast_sockaddr us_tmp;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
uint32_t addr;
int port;
int status;
int callid;
+ unsigned int framing;
status = (d->protocolversion<17) ? letohl(req->data.openreceivechannelack_ip4.status) : letohl(req->data.openreceivechannelack_ip6.status);
@@ -6937,12 +6906,14 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
SKINNY_DEBUG(DEBUG_PACKET, 4, "device ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
SKINNY_DEBUG(DEBUG_PACKET, 4, "asterisk ipaddr = %s:%d\n", ast_inet_ntoa(us.sin_addr), ntohs(us.sin_port));
- ast_best_codec(l->cap, &tmpfmt);
- fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);
+ tmpfmt = ast_format_cap_get_format(l->cap, 0);
+ framing = ast_format_cap_get_format_framing(l->cap, tmpfmt);
- SKINNY_DEBUG(DEBUG_PACKET, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);
+ SKINNY_DEBUG(DEBUG_PACKET, 4, "Setting payloadType to '%s' (%d ms)\n", ast_format_get_name(tmpfmt), framing);
- transmit_startmediatransmission(d, sub, us, fmt);
+ transmit_startmediatransmission(d, sub, us, tmpfmt, framing);
+
+ ao2_ref(tmpfmt, -1);
return 1;
}
@@ -7496,8 +7467,8 @@ static void skinny_session_cleanup(void *data)
if (l->device != d) {
continue;
}
- ast_format_cap_remove_all(l->cap);
- ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0);
+ ast_format_cap_remove_by_type(l->cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_update_by_allow_disallow(l->cap, "all", 0);
l->instance = 0;
unregister_exten(l);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
@@ -7713,8 +7684,9 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca
struct ast_channel *tmpc = NULL;
char tmp[256];
- if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
return NULL;
}
@@ -7870,10 +7842,10 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp
}
continue;
} else if (!strcasecmp(v->name, "allow")) {
- ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 1);
+ ast_format_cap_update_by_allow_disallow(default_cap, v->value, 1);
continue;
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(default_cap, v->value, 0);
continue;
}
}
@@ -8080,20 +8052,20 @@ static void config_parse_variables(int type, void *item, struct ast_variable *vp
}
} else if (!strcasecmp(v->name, "allow")) {
if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
- ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 1);
+ ast_format_cap_update_by_allow_disallow(CDEV->confcap, v->value, 1);
continue;
}
if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
- ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 1);
+ ast_format_cap_update_by_allow_disallow(CLINE->confcap, v->value, 1);
continue;
}
} else if (!strcasecmp(v->name, "disallow")) {
if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
- ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(CDEV->confcap, v->value, 0);
continue;
}
if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
- ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 0);
+ ast_format_cap_update_by_allow_disallow(CLINE->confcap, v->value, 0);
continue;
}
} else if (!strcasecmp(v->name, "version")) {
@@ -8303,7 +8275,7 @@ static struct skinny_line *config_line(const char *lname, struct ast_variable *v
memcpy(l, default_line, sizeof(*default_line));
ast_mutex_init(&l->lock);
ast_copy_string(l->name, lname, sizeof(l->name));
- ast_format_cap_copy(l->confcap, default_cap);
+ ast_format_cap_append_from_cap(l->confcap, default_cap, AST_MEDIA_TYPE_UNKNOWN);
AST_LIST_INSERT_TAIL(&lines, l, all);
ast_mutex_lock(&l->lock);
@@ -8362,7 +8334,7 @@ static struct skinny_device *config_device(const char *dname, struct ast_variabl
memcpy(d, default_device, sizeof(*default_device));
ast_mutex_init(&d->lock);
ast_copy_string(d->name, dname, sizeof(d->name));
- ast_format_cap_copy(d->confcap, default_cap);
+ ast_format_cap_append_from_cap(d->confcap, default_cap, AST_MEDIA_TYPE_UNKNOWN);
AST_LIST_INSERT_TAIL(&devices, d, list);
ast_mutex_lock(&d->lock);
@@ -8453,7 +8425,6 @@ static int config_load(void)
}
memset(&bindaddr, 0, sizeof(bindaddr));
- memset(&default_prefs, 0, sizeof(default_prefs));
immed_dialchar = '\0';
memset(&vmexten, '\0', sizeof(vmexten));
@@ -8482,7 +8453,6 @@ static int config_load(void)
bindaddr.sin_family = AF_INET;
/* load the lines sections */
- default_line->confprefs = default_prefs;
config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines"));
cat = ast_category_browse(cfg, "lines");
while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) {
@@ -8491,7 +8461,6 @@ static int config_load(void)
}
/* load the devices sections */
- default_device->confprefs = default_prefs;
config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices"));
cat = ast_category_browse(cfg, "devices");
while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) {
@@ -8678,17 +8647,18 @@ int skinny_reload(void)
static int load_module(void)
{
int res = 0;
- struct ast_format tmpfmt;
- if (!(default_cap = ast_format_cap_alloc(0))) {
+
+ if (!(default_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return AST_MODULE_LOAD_DECLINE;
}
- if (!(skinny_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(skinny_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ ao2_ref(default_cap, -1);
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add_all_by_type(skinny_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append_by_type(skinny_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append(default_cap, ast_format_ulaw, 0);
+ ast_format_cap_append(default_cap, ast_format_alaw, 0);
for (; res < ARRAY_LEN(soft_key_template_default); res++) {
soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
@@ -8696,11 +8666,23 @@ static int load_module(void)
/* load and parse config */
res = config_load();
if (res == -1) {
+ ao2_ref(skinny_tech.capabilities, -1);
+ ao2_ref(default_cap, -1);
return AST_MODULE_LOAD_DECLINE;
}
+ sched = ast_sched_context_create();
+ if (!sched) {
+ ao2_ref(skinny_tech.capabilities, -1);
+ ao2_ref(default_cap, -1);
+ ast_log(LOG_WARNING, "Unable to create schedule context\n");
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
/* Make sure we can register our skinny channel type */
if (ast_channel_register(&skinny_tech)) {
+ ao2_ref(default_cap, -1);
+ ao2_ref(skinny_tech.capabilities, -1);
ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
return -1;
}
@@ -8713,14 +8695,12 @@ static int load_module(void)
ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
- sched = ast_sched_context_create();
- if (!sched) {
- ast_log(LOG_WARNING, "Unable to create schedule context\n");
- return AST_MODULE_LOAD_FAILURE;
- }
if (ast_sched_start_thread(sched)) {
ast_sched_context_destroy(sched);
sched = NULL;
+ ast_channel_unregister(&skinny_tech);
+ ao2_ref(default_cap, -1);
+ ao2_ref(skinny_tech.capabilities, -1);
return AST_MODULE_LOAD_FAILURE;
}
@@ -8738,6 +8718,7 @@ static int unload_module(void)
ast_rtp_glue_unregister(&skinny_rtp_glue);
ast_channel_unregister(&skinny_tech);
+ ao2_cleanup(skinny_tech.capabilities);
ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
ast_manager_unregister("SKINNYdevices");
@@ -8797,8 +8778,7 @@ static int unload_module(void)
if (con)
ast_context_destroy(con, "Skinny");
- default_cap = ast_format_cap_destroy(default_cap);
- skinny_tech.capabilities = ast_format_cap_destroy(skinny_tech.capabilities);
+ ao2_ref(default_cap, -1);
return 0;
}
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 7525f3921..3f6fd01c8 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -78,6 +78,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
#define DEFAULTCONTEXT "default"
#define DEFAULTCALLERID "Unknown"
@@ -1933,7 +1934,7 @@ static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src
struct ast_format_cap *tmp = src->cap;
memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
src->cap = tmp;
- ast_format_cap_copy(src->cap, dst->cap);
+ ast_format_cap_append_from_cap(src->cap, dst->cap, AST_MEDIA_TYPE_UNKNOWN);
}
static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
@@ -1941,7 +1942,7 @@ static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
if (!l) {
return NULL;
}
- l->cap = ast_format_cap_destroy(l->cap);
+ ao2_ref(l->cap, -1);
ast_free(l);
return NULL;
}
@@ -1953,7 +1954,7 @@ static struct unistim_line *unistim_line_alloc(void)
return NULL;
}
- if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_free(l);
return NULL;
}
@@ -2699,15 +2700,15 @@ static void send_start_rtp(struct unistim_subchannel *sub)
if (unistimdebug) {
ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
ast_inet_ntoa(us.sin_addr),
- htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
+ htons(us.sin_port), ast_format_get_name(ast_channel_readformat(sub->owner)));
ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
ast_inet_ntoa(public.sin_addr));
}
pte = sub->parent->parent->session;
codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
- if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
- (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
+ if ((ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) ||
+ (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_alaw) == AST_FORMAT_CMP_EQUAL)) {
if (unistimdebug) {
ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
}
@@ -2804,17 +2805,17 @@ static void send_start_rtp(struct unistim_subchannel *sub)
/* Codec */
buffsend[40] = codec;
buffsend[41] = codec;
- if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
+ if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
- } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
+ } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
- } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
+ } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
- } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
+ } else if (ast_format_cmp(ast_channel_readformat(sub->owner), ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
} else {
ast_log(LOG_WARNING, "Unsupported codec %s!\n",
- ast_getformatname(ast_channel_readformat(sub->owner)));
+ ast_format_get_name(ast_channel_readformat(sub->owner)));
}
/* Source port for transmit RTP and Destination port for receiving RTP */
buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
@@ -2883,18 +2884,20 @@ static void start_rtp(struct unistim_subchannel *sub)
sin.sin_port = htons(find_rtp_port(sub));
ast_sockaddr_from_sin(&sin_tmp, &sin);
ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
- if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
- struct ast_format tmpfmt;
- char tmp[256];
- ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner)) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_format *tmpfmt;
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(sub->owner), 0);
ast_log(LOG_WARNING,
"Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
- ast_getformatname(ast_channel_readformat(sub->owner)),
- ast_getformatname(&tmpfmt),
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
+ ast_format_get_name(ast_channel_readformat(sub->owner)),
+ ast_format_get_name(tmpfmt),
+ ast_format_cap_get_names(ast_channel_nativeformats(sub->owner), &cap_buf));
- ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
- ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
+ ast_channel_set_readformat(sub->owner, tmpfmt);
+ ast_channel_set_writeformat(sub->owner, tmpfmt);
+ ao2_ref(tmpfmt, -1);
}
send_start_rtp(sub);
ast_mutex_unlock(&sub->lock);
@@ -5132,14 +5135,21 @@ static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
if (sub->owner) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format))) {
- char tmp[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(sub->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_format_cap *caps;
+
ast_debug(1,
"Oooh, format changed from %s to %s\n",
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)),
- ast_getformatname(&f->subclass.format));
-
- ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
+ ast_format_cap_get_names(ast_channel_nativeformats(sub->owner), &cap_buf),
+ ast_format_get_name(f->subclass.format));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(sub->owner, caps);
+ ao2_ref(caps, -1);
+ }
ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
}
@@ -5175,14 +5185,15 @@ static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
} else {
- if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
- char tmp[256];
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+
ast_log(LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
- ast_getformatname(&frame->subclass.format),
- ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(ast)),
- ast_getformatname(ast_channel_readformat(ast)),
- ast_getformatname(ast_channel_writeformat(ast)));
+ ast_format_get_name(frame->subclass.format),
+ ast_format_cap_get_names(ast_channel_nativeformats(ast), &cap_buf),
+ ast_format_get_name(ast_channel_readformat(ast)),
+ ast_format_get_name(ast_channel_writeformat(ast)));
return -1;
}
}
@@ -5661,9 +5672,10 @@ static int unistim_send_mwi_to_peer(struct unistim_line *peer, unsigned int tick
/* called from unistim_request (calls from the pbx ) */
static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
{
+ struct ast_format_cap *caps;
struct ast_channel *tmp;
struct unistim_line *l;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
if (!sub) {
ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
@@ -5673,6 +5685,12 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
return NULL;
}
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
l = sub->parent;
tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
l->parent->context, assignedids, requestor, l->amaflags, "USTM/%s@%s-%p", l->name, l->parent->name, sub);
@@ -5681,24 +5699,32 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
}
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ ao2_ref(caps, -1);
return NULL;
}
ast_channel_stage_snapshot(tmp);
- ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
- ast_format_cap_copy(ast_channel_nativeformats(tmp), global_cap);
+ if (ast_format_cap_count(l->cap)) {
+ ast_format_cap_append_from_cap(caps, l->cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append_from_cap(caps, global_cap, AST_MEDIA_TYPE_UNKNOWN);
}
- ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
+ ast_channel_nativeformats_set(tmp, caps);
+ ao2_ref(caps, -1);
+
+ tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
if (unistimdebug) {
- char tmp1[256], tmp2[256], tmp3[256];
+ struct ast_str *native_buf = ast_str_alloca(64);
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *global_buf = ast_str_alloca(64);
+
ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
- ast_getformatname(&tmpfmt),
- ast_getformatname_multiple(tmp1, sizeof(tmp1), ast_channel_nativeformats(tmp)),
- ast_getformatname_multiple(tmp2, sizeof(tmp2), l->cap),
- ast_getformatname_multiple(tmp3, sizeof(tmp3), global_cap));
+ ast_format_get_name(tmpfmt),
+ ast_format_cap_get_names(ast_channel_nativeformats(tmp), &native_buf),
+ ast_format_cap_get_names(l->cap, &cap_buf),
+ ast_format_cap_get_names(global_cap, &global_buf));
}
if ((sub->rtp) && (sub->subtype == 0)) {
if (unistimdebug) {
@@ -5716,10 +5742,13 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
ast_channel_rings_set(tmp, 1);
}
ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
- ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
+
+ ast_channel_set_writeformat(tmp, tmpfmt);
+ ast_channel_set_rawwriteformat(tmp, tmpfmt);
+ ast_channel_set_readformat(tmp, tmpfmt);
+ ast_channel_set_rawreadformat(tmp, tmpfmt);
+ ao2_ref(tmpfmt, -1);
+
ast_channel_tech_pvt_set(tmp, sub);
ast_channel_tech_set(tmp, &unistim_tech);
@@ -5900,12 +5929,14 @@ static struct ast_channel *unistim_request(const char *type, struct ast_format_c
struct unistim_device *d;
struct ast_channel *tmpc = NULL;
char tmp[256];
- char tmp2[256];
- if (!(ast_format_cap_has_joint(cap, global_cap))) {
+ if (!(ast_format_cap_iscompatible(cap, global_cap))) {
+ struct ast_str *cap_buf = ast_str_alloca(64);
+ struct ast_str *global_buf = ast_str_alloca(64);
ast_log(LOG_NOTICE,
"Asked to get a channel of unsupported format %s while capability is %s\n",
- ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_getformatname_multiple(tmp, sizeof(tmp), global_cap));
+ ast_format_cap_get_names(cap, &cap_buf),
+ ast_format_cap_get_names(global_cap, &global_buf));
return NULL;
}
@@ -5956,7 +5987,8 @@ static struct ast_channel *unistim_request(const char *type, struct ast_format_c
}
sub->subtype = SUB_RING;
sub->softkey = -1;
- ast_format_cap_copy(sub->parent->cap, cap);
+
+ ast_format_cap_append_from_cap(sub->parent->cap, cap, AST_MEDIA_TYPE_UNKNOWN);
tmpc = unistim_new(sub, AST_STATE_DOWN, assignedids, requestor);
if (!tmpc) {
ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
@@ -5975,6 +6007,7 @@ static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_
struct unistim_line *line;
struct unistim_subchannel *sub;
struct unistimsession *s;
+ struct ast_str *cap_buf = ast_str_alloca(64);
switch (cmd) {
case CLI_INIT:
@@ -6005,11 +6038,10 @@ static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_
device, device->selected, device->height);
AST_LIST_LOCK(&device->lines);
AST_LIST_TRAVERSE(&device->lines,line,list) {
- char tmp2[256];
ast_cli(a->fd,
"->name=%s fullname=%s exten=%s callid=%s cap=%s line=%p\n",
line->name, line->fullname, line->exten, line->cid_num,
- ast_getformatname_multiple(tmp2, sizeof(tmp2), line->cap), line);
+ ast_format_cap_get_names(line->cap, &cap_buf), line);
}
AST_LIST_UNLOCK(&device->lines);
@@ -6595,7 +6627,7 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var
ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
}
}
- ast_format_cap_copy(l->cap, global_cap);
+ ast_format_cap_append_from_cap(l->cap, global_cap, AST_MEDIA_TYPE_UNKNOWN);
l->parent = d;
linecnt++;
AST_LIST_LOCK(&d->lines);
@@ -7011,17 +7043,18 @@ static struct ast_rtp_glue unistim_rtp_glue = {
int load_module(void)
{
int res;
- struct ast_format tmpfmt;
- if (!(global_cap = ast_format_cap_alloc(0))) {
+
+ if (!(global_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
goto buff_failed;
}
- if (!(unistim_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(unistim_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
goto buff_failed;
}
- ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
- ast_format_cap_copy(unistim_tech.capabilities, global_cap);
+ ast_format_cap_append(global_cap, ast_format_ulaw, 0);
+ ast_format_cap_append(global_cap, ast_format_alaw, 0);
+ ast_format_cap_append_from_cap(unistim_tech.capabilities, global_cap, AST_MEDIA_TYPE_AUDIO);
+
if (!(buff = ast_malloc(SIZE_PAGE))) {
goto buff_failed;
}
@@ -7040,6 +7073,10 @@ int load_module(void)
res = reload_config();
if (res) {
+ ao2_ref(unistim_tech.capabilities, -1);
+ ao2_ref(global_cap, -1);
+ ast_sched_context_destroy(sched);
+ io_context_destroy(io);
return AST_MODULE_LOAD_DECLINE;
}
/* Make sure we can register our unistim channel type */
@@ -7066,9 +7103,11 @@ sched_failed:
io_failed:
ast_free(buff);
buff = NULL;
- global_cap = ast_format_cap_destroy(global_cap);
- unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
buff_failed:
+ ao2_cleanup(global_cap);
+ global_cap = NULL;
+ ao2_cleanup(unistim_tech.capabilities);
+ unistim_tech.capabilities = NULL;
return AST_MODULE_LOAD_FAILURE;
}
@@ -7082,6 +7121,7 @@ static int unload_module(void)
ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
ast_channel_unregister(&unistim_tech);
+ ao2_cleanup(unistim_tech.capabilities);
ast_rtp_glue_unregister(&unistim_rtp_glue);
ast_mutex_lock(&monlock);
@@ -7099,8 +7139,7 @@ static int unload_module(void)
if (unistimsock > -1) {
close(unistimsock);
}
- global_cap = ast_format_cap_destroy(global_cap);
- unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
+ ao2_ref(global_cap, -1);
return 0;
}
diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc
index f1a45ab63..181e50aee 100644
--- a/channels/chan_vpb.cc
+++ b/channels/chan_vpb.cc
@@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
}
#include <sys/socket.h>
@@ -766,11 +767,10 @@ static void get_callerid_ast(struct vpb_pvt *p)
#endif
vpb_record_buf_start(p->handle, VPB_MULAW);
while ((rc == 0) && (sam_count < 8000 * 3)) {
- struct ast_format tmpfmt;
vrc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));
if (vrc != VPB_OK)
ast_log(LOG_ERROR, "%s: Caller ID couldn't read audio buffer!\n", p->dev);
- rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
+ rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), ast_format_ulaw);
#ifdef ANALYSE_CID
vpb_wave_write(ws, (char *)buf, sizeof(buf));
#endif
@@ -2070,46 +2070,41 @@ static struct ast_frame *vpb_read(struct ast_channel *ast)
static inline AudioCompress ast2vpbformat(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_ALAW:
+ if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return VPB_ALAW;
- case AST_FORMAT_SLINEAR:
+ } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
return VPB_LINEAR;
- case AST_FORMAT_ULAW:
+ } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return VPB_MULAW;
- case AST_FORMAT_ADPCM:
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
return VPB_OKIADPCM;
- default:
+ } else {
return VPB_RAW;
}
}
static inline const char * ast2vpbformatname(struct ast_format *format)
{
- switch(format->id) {
- case AST_FORMAT_ALAW:
+ if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_ALAW:VPB_ALAW";
- case AST_FORMAT_SLINEAR:
+ } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_SLINEAR:VPB_LINEAR";
- case AST_FORMAT_ULAW:
+ } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_ULAW:VPB_MULAW";
- case AST_FORMAT_ADPCM:
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
return "AST_FORMAT_ADPCM:VPB_OKIADPCM";
- default:
+ } else {
return "UNKN:UNKN";
}
}
static inline int astformatbits(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_SLINEAR:
+ if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
return 16;
- case AST_FORMAT_ADPCM:
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
return 4;
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- default:
+ } else {
return 8;
}
}
@@ -2146,7 +2141,8 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
/* ast_mutex_unlock(&p->lock); */
return 0;
} else if (ast_channel_state(ast) != AST_STATE_UP) {
- ast_verb(4, "%s: vpb_write: Attempt to Write frame type[%d]subclass[%s] on not up chan(state[%d])\n", ast_channel_name(ast), frame->frametype, ast_getformatname(&frame->subclass.format), ast_channel_state(ast));
+ ast_verb(4, "%s: vpb_write: Attempt to Write frame type[%d]subclass[%s] on not up chan(state[%d])\n",
+ ast_channel_name(ast), frame->frametype, ast_format_get_name(frame->subclass.format), ast_channel_state(ast));
p->lastoutput = -1;
/* ast_mutex_unlock(&p->lock); */
return 0;
@@ -2154,9 +2150,10 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
/* ast_debug(1, "%s: vpb_write: Checked frame type..\n", p->dev); */
- fmt = ast2vpbformat(&frame->subclass.format);
+ fmt = ast2vpbformat(frame->subclass.format);
if (fmt < 0) {
- ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast_channel_name(ast), ast_getformatname(&frame->subclass.format));
+ ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %s format!\n", ast_channel_name(ast),
+ ast_format_get_name(frame->subclass.format));
return -1;
}
@@ -2180,7 +2177,7 @@ static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
/* Check if we have set up the play_buf */
if (p->lastoutput == -1) {
vpb_play_buf_start(p->handle, fmt);
- ast_verb(2, "%s: vpb_write: Starting play mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(&frame->subclass.format));
+ ast_verb(2, "%s: vpb_write: Starting play mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(frame->subclass.format));
p->lastoutput = fmt;
ast_mutex_unlock(&p->play_lock);
return 0;
@@ -2230,7 +2227,7 @@ static void *do_chanreads(void *pvt)
struct ast_frame *fr = &p->fr;
char *readbuf = ((char *)p->buf) + AST_FRIENDLY_OFFSET;
int bridgerec = 0;
- struct ast_format tmpfmt;
+ struct ast_format *tmpfmt;
int readlen, res, trycnt=0;
AudioCompress fmt;
int ignore_dtmf;
@@ -2315,22 +2312,22 @@ static void *do_chanreads(void *pvt)
ast_mutex_unlock(&p->play_dtmf_lock);
if (p->owner) {
- ast_format_copy(&tmpfmt, ast_channel_rawreadformat(p->owner));
+ tmpfmt = ast_channel_rawreadformat(p->owner);
} else {
- ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0);
+ tmpfmt = ast_format_slin;
}
- fmt = ast2vpbformat(&tmpfmt);
+ fmt = ast2vpbformat(tmpfmt);
if (fmt < 0) {
- ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_getformatname(&tmpfmt));
+ ast_log(LOG_WARNING, "%s: Record failure (unsupported format %s)\n", p->dev, ast_format_get_name(tmpfmt));
return NULL;
}
- readlen = VPB_SAMPLES * astformatbits(&tmpfmt) / 8;
+ readlen = VPB_SAMPLES * astformatbits(tmpfmt) / 8;
if (p->lastinput == -1) {
vpb_record_buf_start(p->handle, fmt);
/* vpb_reset_record_fifo_alarm(p->handle); */
p->lastinput = fmt;
- ast_verb(2, "%s: Starting record mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(&tmpfmt));
+ ast_verb(2, "%s: Starting record mode (codec=%d)[%s]\n", p->dev, fmt, ast2vpbformatname(tmpfmt));
continue;
} else if (p->lastinput != fmt) {
vpb_record_buf_finish(p->handle);
@@ -2349,7 +2346,7 @@ static void *do_chanreads(void *pvt)
a_gain_vector(p->rxswgain - MAX_VPB_GAIN, (short *)readbuf, readlen / sizeof(short));
ast_verb(6, "%s: chanreads: applied gain\n", p->dev);
- ast_format_copy(&fr->subclass.format, &tmpfmt);
+ fr->subclass.format = tmpfmt;
fr->data.ptr = readbuf;
fr->datalen = readlen;
fr->frametype = AST_FRAME_VOICE;
@@ -2429,7 +2426,6 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
struct ast_channel *tmp;
char cid_num[256];
char cid_name[256];
- struct ast_format tmpfmt;
if (me->owner) {
ast_log(LOG_WARNING, "Called vpb_new on owned channel (%s) ?!\n", me->dev);
@@ -2452,9 +2448,9 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
* they are all converted to/from linear in the vpb code. Best for us to use
* linear since we can then adjust volume in this modules.
*/
- ast_format_cap_add(ast_channel_nativeformats(tmp), ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+ ast_channel_nativeformats_set(tmp, vpb_tech.capabilities);
+ ast_channel_set_rawreadformat(tmp, ast_format_slin);
+ ast_channel_set_rawwriteformat(tmp, ast_format_slin);
if (state == AST_STATE_RING) {
ast_channel_rings_set(tmp, 1);
cid_name[0] = '\0';
@@ -2508,13 +2504,17 @@ static struct ast_channel *vpb_request(const char *type, struct ast_format_cap *
char *sepstr, *name;
const char *s;
int group = -1;
- struct ast_format slin;
- ast_format_set(&slin, AST_FORMAT_SLINEAR, 0);
+ if (!(ast_format_cap_iscompatible_format(cap, ast_format_slin))) {
+ struct ast_str *buf;
- if (!(ast_format_cap_iscompatible(cap, &slin))) {
- char tmp[256];
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+ buf = ast_str_create(256);
+ if (!buf) {
+ return NULL;
+ }
+ ast_log(LOG_NOTICE, "Asked to create a channel for unsupported formats: %s\n",
+ ast_format_cap_get_names(cap, &buf));
+ ast_free(buf);
return NULL;
}
@@ -2636,8 +2636,10 @@ static int unload_module(void)
ast_free(bridges);
}
- ast_format_cap_destroy(vpb_tech.capabilities);
- ast_format_cap_destroy(vpb_tech_indicate.capabilities);
+ ao2_cleanup(vpb_tech.capabilities);
+ vpb_tech.capabilities = NULL;
+ ao2_cleanup(vpb_tech_indicate.capabilities);
+ vpb_tech_indicate.capabilities = NULL;
return 0;
}
@@ -2671,19 +2673,18 @@ static enum ast_module_load_result load_module()
int bal2 = -1;
int bal3 = -1;
char * callerid = NULL;
- struct ast_format tmpfmt;
int num_cards = 0;
- vpb_tech.capabilities = ast_format_cap_alloc((enum ast_format_cap_flags) 0);
+ vpb_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!vpb_tech.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- vpb_tech_indicate.capabilities = ast_format_cap_alloc((enum ast_format_cap_flags) 0);
+ vpb_tech_indicate.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!vpb_tech_indicate.capabilities) {
return AST_MODULE_LOAD_DECLINE;
}
- ast_format_cap_add(vpb_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(vpb_tech_indicate.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(vpb_tech.capabilities, ast_format_slin, 0);
+ ast_format_cap_append(vpb_tech_indicate.capabilities, ast_format_slin, 0);
try {
num_cards = vpb_get_num_cards();
} catch (std::exception e) {
diff --git a/channels/dahdi/bridge_native_dahdi.c b/channels/dahdi/bridge_native_dahdi.c
index 2f4fd170e..85cb4bfef 100644
--- a/channels/dahdi/bridge_native_dahdi.c
+++ b/channels/dahdi/bridge_native_dahdi.c
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/bridge_technology.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
/* ------------------------------------------------------------------- */
@@ -892,7 +893,7 @@ static struct ast_bridge_technology native_bridge = {
void dahdi_native_unload(void)
{
ast_bridge_technology_unregister(&native_bridge);
- ast_format_cap_destroy(native_bridge.format_capabilities);
+ ao2_cleanup(native_bridge.format_capabilities);
}
/*!
@@ -905,11 +906,9 @@ void dahdi_native_unload(void)
*/
int dahdi_native_load(struct ast_module *mod, const struct ast_channel_tech *tech)
{
- struct ast_format format;
-
dahdi_tech = tech;
- native_bridge.format_capabilities = ast_format_cap_alloc(0);
+ native_bridge.format_capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!native_bridge.format_capabilities) {
return -1;
}
@@ -918,9 +917,9 @@ int dahdi_native_load(struct ast_module *mod, const struct ast_channel_tech *tec
* This is used to make channels compatible with the bridge
* itself not with each other.
*/
- ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
- ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(native_bridge.format_capabilities, ast_format_set(&format, AST_FORMAT_ALAW, 0));
+ ast_format_cap_append(native_bridge.format_capabilities, ast_format_slin, 0);
+ ast_format_cap_append(native_bridge.format_capabilities, ast_format_ulaw, 0);
+ ast_format_cap_append(native_bridge.format_capabilities, ast_format_alaw, 0);
return __ast_bridge_technology_register(&native_bridge, mod);
}
diff --git a/channels/iax2/codec_pref.c b/channels/iax2/codec_pref.c
new file mode 100644
index 000000000..903dca4cc
--- /dev/null
+++ b/channels/iax2/codec_pref.c
@@ -0,0 +1,333 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_cap.h"
+
+#include "include/codec_pref.h"
+#include "include/format_compatibility.h"
+
+void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right)
+{
+ static int differential = (int) 'A';
+ int x;
+
+ if (right) {
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE && x < size; x++) {
+ if (!pref->order[x]) {
+ break;
+ }
+
+ buf[x] = pref->order[x] + differential;
+ }
+
+ buf[x] = '\0';
+ } else {
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE && x < size; x++) {
+ if (buf[x] == '\0') {
+ break;
+ }
+
+ pref->order[x] = buf[x] - differential;
+ }
+
+ if (x < size) {
+ pref->order[x] = 0;
+ }
+ }
+}
+
+struct ast_format *iax2_codec_pref_index(struct iax2_codec_pref *pref, int idx, struct ast_format **result)
+{
+ if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->order[idx]) {
+ *result = ast_format_compatibility_bitfield2format(pref->order[idx]);
+ } else {
+ *result = NULL;
+ }
+
+ return *result;
+}
+
+void iax2_codec_pref_to_cap(struct iax2_codec_pref *pref, struct ast_format_cap *cap)
+{
+ int idx;
+
+ for (idx = 0; idx < sizeof(pref->order); idx++) {
+ if (!pref->order[idx]) {
+ break;
+ }
+ ast_format_cap_append(cap, ast_format_compatibility_bitfield2format(pref->order[idx]), pref->framing[idx]);
+ }
+}
+
+int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size)
+{
+ int x;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ size_t total_len;
+ char *cur;
+
+ if (!cap) {
+ return -1;
+ }
+
+ /* This function is useless if you have less than a 6 character buffer.
+ * '(...)' is six characters. */
+ if (size < 6) {
+ return -1;
+ }
+
+ /* Convert the preferences into a format cap so that we can read the formst names */
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ uint64_t bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]);
+ if (!bitfield) {
+ break;
+ }
+
+ iax2_format_compatibility_bitfield2cap(bitfield, cap);
+ }
+
+ /* We know that at a minimum, 3 characters are used - (, ), and \0 */
+ total_len = size - 3;
+
+ memset(buf, 0, size);
+
+ /* This character has already been accounted for total_len purposes */
+ buf[0] = '(';
+ cur = buf + 1;
+
+ /* Loop through the formats and write as many into the buffer as we can */
+ for (x = 0; x < ast_format_cap_count(cap); x++) {
+ size_t name_len;
+ struct ast_format *fmt = ast_format_cap_get_format(cap, x);
+ const char *name = ast_format_get_name(fmt);
+
+ name_len = strlen(name);
+
+ /* all entries after the first need a delimiter character */
+ if (x) {
+ name_len++;
+ }
+
+ /* Terminate the list early if we don't have room for the entry.
+ * If it's not the last entry in the list, save enough room to write '...'.
+ */
+ if (((x == ast_format_cap_count(cap) - 1) && (total_len < name_len)) ||
+ ((x < ast_format_cap_count(cap) - 1) && (total_len < name_len + 3))) {
+ strcpy(cur, "...");
+ cur += 3;
+ total_len -= 3;
+ ao2_ref(fmt, -1);
+ break;
+ }
+
+ sprintf(cur, "%s%s", x ? "|" : "", name);
+ cur += name_len;
+ total_len -= name_len;
+
+ ao2_ref(fmt, -1);
+ }
+ ao2_ref(cap, -1);
+
+ /* These two characters have already been accounted for total_len purposes */
+ cur[0] = ')';
+ cur[1] = '\0';
+
+ return size - total_len;
+}
+
+static void codec_pref_remove_index(struct iax2_codec_pref *pref, int codec_pref_index)
+{
+ int x;
+
+ for (x = codec_pref_index; x < IAX2_CODEC_PREF_SIZE; x++) {
+ pref->order[x] = pref->order[x + 1];
+ pref->framing[x] = pref->framing[x + 1];
+ if (!pref->order[x]) {
+ return;
+ }
+ }
+}
+
+/*! \brief Remove codec from pref list */
+static void codec_pref_remove(struct iax2_codec_pref *pref, int format_index)
+{
+ int x;
+
+ if (!pref->order[0]) {
+ return;
+ }
+
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ if (!pref->order[x]) {
+ break;
+ }
+
+ if (pref->order[x] == format_index) {
+ codec_pref_remove_index(pref, x);
+ break;
+ }
+ }
+}
+
+void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield)
+{
+ int x;
+
+ if (!pref->order[0]) {
+ return;
+ }
+
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ uint64_t format_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]);
+ if (!pref->order[x]) {
+ break;
+ }
+
+ /* If this format isn't in the bitfield, remove it from the prefs. */
+ if (!(format_as_bitfield & bitfield)) {
+ codec_pref_remove_index(pref, x);
+ }
+ }
+}
+
+uint64_t iax2_codec_pref_order_value_to_format_bitfield(uint64_t order_value)
+{
+ if (!order_value) {
+ return 0;
+ }
+
+ return 1 << (order_value - 1);
+}
+
+uint64_t iax2_codec_pref_format_bitfield_to_order_value(uint64_t bitfield)
+{
+ int format_index = 1;
+
+ if (!bitfield) {
+ return 0;
+ }
+
+ while (bitfield > 1) {
+ bitfield = bitfield >> 1;
+ format_index++;
+ }
+
+ return format_index;
+}
+
+/*! \brief Append codec to list */
+int iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing)
+{
+ uint64_t bitfield = ast_format_compatibility_format2bitfield(format);
+ int format_index = iax2_codec_pref_format_bitfield_to_order_value(bitfield);
+ int x;
+
+ codec_pref_remove(pref, format_index);
+
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ if (!pref->order[x]) {
+ pref->order[x] = format_index;
+ pref->framing[x] = framing;
+ break;
+ }
+ }
+
+ return x;
+}
+
+/*! \brief Prepend codec to list */
+void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing,
+ int only_if_existing)
+{
+ uint64_t bitfield = ast_format_compatibility_format2bitfield(format);
+ int x;
+
+ /* Now find any existing occurrence, or the end */
+ for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ if (!pref->order[x] || pref->order[x] == bitfield)
+ break;
+ }
+
+ /* If we failed to find any occurrence, set to the end */
+ if (x == IAX2_CODEC_PREF_SIZE) {
+ --x;
+ }
+
+ if (only_if_existing && !pref->order[x]) {
+ return;
+ }
+
+ /* Move down to make space to insert - either all the way to the end,
+ or as far as the existing location (which will be overwritten) */
+ for (; x > 0; x--) {
+ pref->order[x] = pref->order[x - 1];
+ pref->framing[x] = pref->framing[x - 1];
+ }
+
+ /* And insert the new entry */
+ pref->order[0] = bitfield;
+ pref->framing[0] = framing;
+}
+
+unsigned int iax2_codec_pref_getsize(struct iax2_codec_pref *pref, int idx)
+{
+ if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->order[idx]) {
+ return pref->framing[idx];
+ } else {
+ return 0;
+ }
+}
+
+int iax2_codec_pref_setsize(struct iax2_codec_pref *pref, struct ast_format *format, int framems)
+{
+ int idx;
+
+ for (idx = 0; idx < sizeof(pref->order); idx++) {
+ if (!pref->order[idx]) {
+ break;
+ } else if (ast_format_cmp(ast_format_compatibility_bitfield2format(pref->order[idx]),
+ format) != AST_FORMAT_CMP_EQUAL) {
+ continue;
+ }
+ pref->framing[idx] = framems;
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/channels/iax2/format_compatibility.c b/channels/iax2/format_compatibility.c
new file mode 100644
index 000000000..8085c2c26
--- /dev/null
+++ b/channels/iax2/format_compatibility.c
@@ -0,0 +1,73 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_cap.h"
+
+#include "include/format_compatibility.h"
+
+uint64_t iax2_format_compatibility_cap2bitfield(const struct ast_format_cap *cap)
+{
+ uint64_t bitfield = 0;
+ int x;
+
+ for (x = 0; x < ast_format_cap_count(cap); x++) {
+ struct ast_format *format = ast_format_cap_get_format(cap, x);
+
+ bitfield |= ast_format_compatibility_format2bitfield(format);
+
+ ao2_ref(format, -1);
+ }
+
+ return bitfield;
+}
+
+int iax2_format_compatibility_bitfield2cap(uint64_t bitfield, struct ast_format_cap *cap)
+{
+ int x;
+
+ for (x = 0; x < 64; x++) {
+ uint64_t tmp = (1ULL << x);
+
+ if ((tmp & bitfield) && ast_format_cap_append(cap, ast_format_compatibility_bitfield2format(tmp), 0)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/channels/iax2/include/codec_pref.h b/channels/iax2/include/codec_pref.h
new file mode 100644
index 000000000..bfb889164
--- /dev/null
+++ b/channels/iax2/include/codec_pref.h
@@ -0,0 +1,123 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _IAX2_CODEC_PREF_H_
+#define _IAX2_CODEC_PREF_H_
+
+struct ast_format;
+struct ast_codec;
+struct ast_format_cap;
+
+#define IAX2_CODEC_PREF_SIZE 64
+struct iax2_codec_pref {
+ /*! This array is ordered by preference and contains the codec bitfield. */
+ uint64_t order[IAX2_CODEC_PREF_SIZE];
+ /*! Framing size of the codec */
+ unsigned int framing[IAX2_CODEC_PREF_SIZE];
+};
+
+/*!
+ * \brief Convert an iax2_codec_pref order value into a format bitfield
+ *
+ * \param order_value value being converted
+ *
+ * \return the bitfield value of the order_value format
+ */
+uint64_t iax2_codec_pref_order_value_to_format_bitfield(uint64_t order_value);
+
+/*!
+ * \brief Convert a format bitfield into an iax2_codec_pref order value
+ *
+ * \param bitfield value being converted
+ *
+ * \return the iax2_codec_pref order value of the most significant format
+ * in the bitfield.
+ *
+ * \note This is really meant to be used on single format bitfields.
+ * It will work with multiformat bitfields, but it can only return the
+ * index of the most significant one if that is the case.
+ */
+uint64_t iax2_codec_pref_format_bitfield_to_order_value(uint64_t bitfield);
+
+/*!
+ * \brief Codec located at a particular place in the preference index.
+ * \param pref preference structure to get the codec out of
+ * \param index to retrieve from
+ * \param result ast_format structure to store the index value in
+ * \return pointer to input ast_format on success, NULL on failure
+*/
+struct ast_format *iax2_codec_pref_index(struct iax2_codec_pref *pref, int index, struct ast_format **result);
+
+/*! \brief Convert a preference structure to a capabilities structure */
+void iax2_codec_pref_to_cap(struct iax2_codec_pref *pref, struct ast_format_cap *cap);
+
+/*! \brief Removes format from the pref list that aren't in the bitfield */
+void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield);
+
+/*!
+ * \brief Dump audio codec preference list into a string
+ *
+ * \param pref preference structure to dump string representation of order for
+ * \param buf character buffer to put string into
+ * \param size size of the character buffer
+ *
+ * \return -1 on error. Otherwise returns the remaining spaaaaaace in the buffer.
+ *
+ * \note Format is (codec1|codec2|codec3|...) -- if the list is too long for the
+ * size of the buffer, codecs will be written until they exceed the length
+ * remaining in which case the list will be closed with '...)' after the last
+ * writable codec.
+ */
+int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size);
+
+/*! \brief Append a audio codec to a preference list, removing it first if it was already there
+*/
+int iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing);
+
+/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there
+*/
+void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing,
+ int only_if_existing);
+
+/*! \brief Get packet size for codec
+*/
+unsigned int iax2_codec_pref_getsize(struct iax2_codec_pref *pref, int index);
+
+/*! \brief Set packet size for codec
+*/
+int iax2_codec_pref_setsize(struct iax2_codec_pref *pref, struct ast_format *format, int framems);
+
+/*! \brief Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string
+ * \note Due to a misunderstanding in how codec preferences are stored, this
+ * list starts at 'B', not 'A'. For backwards compatibility reasons, this
+ * cannot change.
+ * \param pref A codec preference list structure
+ * \param buf A string denoting codec preference, appropriate for use in line transmission
+ * \param size Size of \a buf
+ * \param right Boolean: if 0, convert from \a buf to \a pref; if 1, convert from \a pref to \a buf.
+ */
+void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right);
+
+#endif /* _IAX2_CODEC_PREF_H_ */
diff --git a/channels/iax2/include/format_compatibility.h b/channels/iax2/include/format_compatibility.h
new file mode 100644
index 000000000..aa29cfa2c
--- /dev/null
+++ b/channels/iax2/include/format_compatibility.h
@@ -0,0 +1,55 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _IAX2_FORMAT_COMPATIBILITY_H_
+#define _IAX2_FORMAT_COMPATIBILITY_H_
+
+struct ast_format;
+struct ast_format_cap;
+
+/*!
+ * \brief Convert a format capabilities structure to a bitfield
+ *
+ * \param cap Capabilities structure containing formats
+ *
+ * \retval non-zero success
+ * \retval zero no formats present or no formats supported
+ */
+uint64_t iax2_format_compatibility_cap2bitfield(const struct ast_format_cap *cap);
+
+/*!
+ * \brief Convert a bitfield to a format capabilities structure
+ *
+ * \param bitfield The bitfield for the media formats
+ * \param cap Capabilities structure to place formats into
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note If failure occurs the capabilities structure may contain a partial set of formats
+ */
+int iax2_format_compatibility_bitfield2cap(uint64_t bitfield, struct ast_format_cap *cap);
+
+#endif /* _IAX2_FORMAT_COMPATIBILITY_H */
diff --git a/channels/iax2/parser.c b/channels/iax2/parser.c
index f5c7ba05d..f1fc8f82d 100644
--- a/channels/iax2/parser.c
+++ b/channels/iax2/parser.c
@@ -42,10 +42,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/threadstorage.h"
#include "asterisk/netsock2.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
#include "include/iax2.h"
#include "include/parser.h"
#include "include/provision.h"
+#include "include/codec_pref.h"
static int frames = 0;
static int iframes = 0;
@@ -124,7 +127,7 @@ static void dump_string(char *output, int maxlen, void *value, int len)
static void dump_prefs(char *output, int maxlen, void *value, int len)
{
- struct ast_codec_pref pref;
+ struct iax2_codec_pref pref;
int total_len = 0;
maxlen--;
@@ -136,9 +139,9 @@ static void dump_prefs(char *output, int maxlen, void *value, int len)
strncpy(output, value, maxlen);
output[maxlen] = '\0';
- ast_codec_pref_convert(&pref, output, total_len, 0);
+ iax2_codec_pref_convert(&pref, output, total_len, 0);
memset(output,0,total_len);
- ast_codec_pref_string(&pref, output, total_len);
+ iax2_codec_pref_string(&pref, output, total_len);
}
static void dump_int(char *output, int maxlen, void *value, int len)
@@ -1180,7 +1183,8 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
{
fr->af.frametype = f->frametype;
- ast_format_copy(&fr->af.subclass.format, &f->subclass.format);
+ fr->af.subclass.format = f->subclass.format;
+ fr->af.subclass.integer = f->subclass.integer;
fr->af.mallocd = 0; /* Our frame is static relative to the container */
fr->af.datalen = f->datalen;
fr->af.samples = f->samples;
@@ -1199,7 +1203,8 @@ void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
/* We need to byte-swap slinear samples from network byte order */
- if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.format.id == AST_FORMAT_SLINEAR)) {
+ if ((fr->af.frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(fr->af.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
/* 2 bytes / sample for SLINEAR */
ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
} else
diff --git a/channels/iax2/provision.c b/channels/iax2/provision.c
index 78e0b1b3d..85dfe9448 100644
--- a/channels/iax2/provision.c
+++ b/channels/iax2/provision.c
@@ -45,6 +45,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
#include "asterisk/acl.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
#include "include/iax2.h"
#include "include/provision.h"
@@ -345,9 +347,10 @@ static int iax_template_parse(struct iax_template *cur, struct ast_config *cfg,
} else
ast_log(LOG_WARNING, "Ignoring invalid %s '%s' for '%s' at line %d\n", v->name, v->value, s, v->lineno);
} else if (!strcasecmp(v->name, "codec")) {
- struct ast_format tmpfmt;
- if ((ast_getformatbyname(v->value, &tmpfmt)) > 0) {
- cur->format = ast_format_to_old_bitfield(&tmpfmt);
+ struct ast_format *tmpfmt;
+ if ((tmpfmt = ast_format_cache_get(v->value))) {
+ cur->format = ast_format_compatibility_format2bitfield(tmpfmt);
+ ao2_ref(tmpfmt, -1);
} else
ast_log(LOG_WARNING, "Ignoring invalid codec '%s' for '%s' at line %d\n", v->value, s, v->lineno);
} else if (!strcasecmp(v->name, "tos")) {
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index c50dbf3fc..054552b5a 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -806,35 +806,32 @@ int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char
}
static int media_offer_read_av(struct ast_sip_session *session, char *buf,
- size_t len, enum ast_format_type media_type)
+ size_t len, enum ast_media_type media_type)
{
int i, size = 0;
- struct ast_format fmt;
- const char *name;
- for (i = 0; ast_codec_pref_index(&session->override_prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) != media_type) {
- continue;
- }
+ for (i = 0; i < ast_format_cap_count(session->req_caps); i++) {
+ struct ast_format *fmt = ast_format_cap_get_format(session->req_caps, i);
- name = ast_getformatname(&fmt);
-
- if (ast_strlen_zero(name)) {
- ast_log(LOG_WARNING, "PJSIP_MEDIA_OFFER unrecognized format %s\n", name);
+ if (ast_format_get_type(fmt) != media_type) {
+ ao2_ref(fmt, -1);
continue;
}
/* add one since we'll include a comma */
- size = strlen(name) + 1;
+ size = strlen(ast_format_get_name(fmt)) + 1;
len -= size;
if ((len) < 0) {
+ ao2_ref(fmt, -1);
break;
}
/* no reason to use strncat here since we have already ensured buf has
enough space, so strcat can be safely used */
- strcat(buf, name);
+ strcat(buf, ast_format_get_name(fmt));
strcat(buf, ",");
+
+ ao2_ref(fmt, -1);
}
if (size) {
@@ -846,23 +843,16 @@ static int media_offer_read_av(struct ast_sip_session *session, char *buf,
struct media_offer_data {
struct ast_sip_session *session;
- enum ast_format_type media_type;
+ enum ast_media_type media_type;
const char *value;
};
static int media_offer_write_av(void *obj)
{
struct media_offer_data *data = obj;
- int i;
- struct ast_format fmt;
- /* remove all of the given media type first */
- for (i = 0; ast_codec_pref_index(&data->session->override_prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) == data->media_type) {
- ast_codec_pref_remove(&data->session->override_prefs, &fmt);
- }
- }
- ast_format_cap_remove_bytype(data->session->req_caps, data->media_type);
- ast_parse_allow_disallow(&data->session->override_prefs, data->session->req_caps, data->value, 1);
+
+ ast_format_cap_remove_by_type(data->session->req_caps, data->media_type);
+ ast_format_cap_update_by_allow_disallow(data->session->req_caps, data->value, 1);
return 0;
}
@@ -879,9 +869,9 @@ int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *
channel = ast_channel_tech_pvt(chan);
if (!strcmp(data, "audio")) {
- return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_AUDIO);
+ return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_AUDIO);
} else if (!strcmp(data, "video")) {
- return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_VIDEO);
+ return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_VIDEO);
}
return 0;
@@ -903,9 +893,9 @@ int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char
mdata.session = channel->session;
if (!strcmp(data, "audio")) {
- mdata.media_type = AST_FORMAT_TYPE_AUDIO;
+ mdata.media_type = AST_MEDIA_TYPE_AUDIO;
} else if (!strcmp(data, "video")) {
- mdata.media_type = AST_FORMAT_TYPE_VIDEO;
+ mdata.media_type = AST_MEDIA_TYPE_VIDEO;
}
return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata);
diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h
index 11078d5b7..8ce63ee9d 100644
--- a/channels/sip/include/sip.h
+++ b/channels/sip/include/sip.h
@@ -1082,7 +1082,6 @@ struct sip_pvt {
int timer_b; /*!< SIP timer B, ms */
unsigned int sipoptions; /*!< Supported SIP options on the other end */
unsigned int reqsipoptions; /*!< Required SIP options on the other end */
- struct ast_codec_pref prefs; /*!< codec prefs */
struct ast_format_cap *caps; /*!< Special capability (codec) */
struct ast_format_cap *jointcaps; /*!< Supported capability at both ends (codecs) */
struct ast_format_cap *peercaps; /*!< Supported peer capability */
@@ -1310,7 +1309,6 @@ struct sip_peer {
int busy_level; /*!< Level of active channels where we signal busy */
int maxforwards; /*!< SIP Loop prevention */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
- struct ast_codec_pref prefs; /*!< codec prefs */
int lastmsgssent; /*!< The last known VM message counts (new/old) */
unsigned int sipoptions; /*!< Supported SIP options */
struct ast_flags flags[3]; /*!< SIP_ flags */
diff --git a/codecs/codec_a_mu.c b/codecs/codec_a_mu.c
index 470f363e7..c21c706f5 100644
--- a/codecs/codec_a_mu.c
+++ b/codecs/codec_a_mu.c
@@ -80,6 +80,17 @@ static int ulawtoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator alawtoulaw = {
.name = "alawtoulaw",
+ .src_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "ulaw",
.framein = alawtoulaw_framein,
.sample = alaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -88,6 +99,17 @@ static struct ast_translator alawtoulaw = {
static struct ast_translator ulawtoalaw = {
.name = "ulawtoalaw",
+ .src_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "alaw",
.framein = ulawtoalaw_framein,
.sample = ulaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -111,23 +133,19 @@ static int load_module(void)
int res;
int x;
- ast_format_set(&alawtoulaw.src_format, AST_FORMAT_ALAW, 0);
- ast_format_set(&alawtoulaw.dst_format, AST_FORMAT_ULAW, 0);
-
- ast_format_set(&ulawtoalaw.src_format, AST_FORMAT_ULAW, 0);
- ast_format_set(&ulawtoalaw.dst_format, AST_FORMAT_ALAW, 0);
-
for (x=0;x<256;x++) {
mu2a[x] = AST_LIN2A(AST_MULAW(x));
a2mu[x] = AST_LIN2MU(AST_ALAW(x));
}
+
res = ast_register_translator(&alawtoulaw);
- if (!res)
- res = ast_register_translator(&ulawtoalaw);
- else
- ast_unregister_translator(&alawtoulaw);
- if (res)
+ res |= ast_register_translator(&ulawtoalaw);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c
index c48eb1ab2..03d2a4ab3 100644
--- a/codecs/codec_adpcm.c
+++ b/codecs/codec_adpcm.c
@@ -290,6 +290,17 @@ static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
static struct ast_translator adpcmtolin = {
.name = "adpcmtolin",
+ .src_codec = {
+ .name = "adpcm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = adpcmtolin_framein,
.sample = adpcm_sample,
.desc_size = sizeof(struct adpcm_decoder_pvt),
@@ -299,6 +310,17 @@ static struct ast_translator adpcmtolin = {
static struct ast_translator lintoadpcm = {
.name = "lintoadpcm",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "adpcm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "adpcm",
.framein = lintoadpcm_framein,
.frameout = lintoadpcm_frameout,
.sample = slin8_sample,
@@ -307,12 +329,6 @@ static struct ast_translator lintoadpcm = {
.buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */
};
-/*! \brief standard module glue */
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
@@ -325,26 +341,20 @@ static int unload_module(void)
static int load_module(void)
{
- int res;
-
- ast_format_set(&adpcmtolin.src_format, AST_FORMAT_ADPCM, 0);
- ast_format_set(&adpcmtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintoadpcm.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintoadpcm.dst_format, AST_FORMAT_ADPCM, 0);
+ int res = 0;
res = ast_register_translator(&adpcmtolin);
- if (!res)
- res = ast_register_translator(&lintoadpcm);
- else
- ast_unregister_translator(&adpcmtolin);
- if (res)
+ res |= ast_register_translator(&lintoadpcm);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c
index 34a71388e..2ca577d7f 100644
--- a/codecs/codec_alaw.c
+++ b/codecs/codec_alaw.c
@@ -77,6 +77,17 @@ static int lintoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator alawtolin = {
.name = "alawtolin",
+ .src_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = alawtolin_framein,
.sample = alaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -84,20 +95,24 @@ static struct ast_translator alawtolin = {
};
static struct ast_translator lintoalaw = {
- "lintoalaw",
+ .name = "lintoalaw",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "alaw",
.framein = lintoalaw_framein,
.sample = slin8_sample,
.buffer_samples = BUFFER_SAMPLES,
.buf_size = BUFFER_SAMPLES,
};
-/*! \brief standard module stuff */
-
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
@@ -112,24 +127,18 @@ static int load_module(void)
{
int res;
- ast_format_set(&lintoalaw.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintoalaw.dst_format, AST_FORMAT_ALAW, 0);
-
- ast_format_set(&alawtolin.src_format, AST_FORMAT_ALAW, 0);
- ast_format_set(&alawtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
res = ast_register_translator(&alawtolin);
- if (!res)
- res = ast_register_translator(&lintoalaw);
- else
- ast_unregister_translator(&alawtolin);
- if (res)
+ res |= ast_register_translator(&lintoalaw);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "A-law Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c
index caaf99cdf..64f220eef 100644
--- a/codecs/codec_dahdi.c
+++ b/codecs/codec_dahdi.c
@@ -51,6 +51,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/ulaw.h"
+#include "asterisk/format_compatibility.h"
#define BUFFER_SIZE 8000
@@ -58,17 +59,29 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define G729_SAMPLES 160
#define ULAW_SAMPLES 160
+/* Defines from DAHDI. */
#ifndef DAHDI_FORMAT_MAX_AUDIO
+/*! G.723.1 compression */
#define DAHDI_FORMAT_G723_1 (1 << 0)
+/*! GSM compression */
#define DAHDI_FORMAT_GSM (1 << 1)
+/*! Raw mu-law data (G.711) */
#define DAHDI_FORMAT_ULAW (1 << 2)
+/*! Raw A-law data (G.711) */
#define DAHDI_FORMAT_ALAW (1 << 3)
+/*! ADPCM (G.726, 32kbps) */
#define DAHDI_FORMAT_G726 (1 << 4)
+/*! ADPCM (IMA) */
#define DAHDI_FORMAT_ADPCM (1 << 5)
+/*! Raw 16-bit Signed Linear (8000 Hz) PCM */
#define DAHDI_FORMAT_SLINEAR (1 << 6)
+/*! LPC10, 180 samples/frame */
#define DAHDI_FORMAT_LPC10 (1 << 7)
+/*! G.729A audio */
#define DAHDI_FORMAT_G729A (1 << 8)
+/*! SpeeX Free Compression */
#define DAHDI_FORMAT_SPEEX (1 << 9)
+/*! iLBC Free Compression */
#define DAHDI_FORMAT_ILBC (1 << 10)
#endif
@@ -78,6 +91,233 @@ static struct channel_usage {
int decoders;
} channels;
+#if defined(NOT_NEEDED)
+/*!
+ * \internal
+ * \brief Convert DAHDI format bitfield to old Asterisk format bitfield.
+ * \since 13.0.0
+ *
+ * \param dahdi Bitfield from DAHDI to convert.
+ *
+ * \note They should be the same values but they don't have to be.
+ *
+ * \return Old Asterisk bitfield equivalent.
+ */
+static uint64_t bitfield_dahdi2ast(unsigned dahdi)
+{
+ uint64_t ast;
+
+ switch (dahdi) {
+ case DAHDI_FORMAT_G723_1:
+ ast = AST_FORMAT_G723;
+ break;
+ case DAHDI_FORMAT_GSM:
+ ast = AST_FORMAT_GSM;
+ break;
+ case DAHDI_FORMAT_ULAW:
+ ast = AST_FORMAT_ULAW;
+ break;
+ case DAHDI_FORMAT_ALAW:
+ ast = AST_FORMAT_ALAW;
+ break;
+ case DAHDI_FORMAT_G726:
+ ast = AST_FORMAT_G726_AAL2;
+ break;
+ case DAHDI_FORMAT_ADPCM:
+ ast = AST_FORMAT_ADPCM;
+ break;
+ case DAHDI_FORMAT_SLINEAR:
+ ast = AST_FORMAT_SLIN;
+ break;
+ case DAHDI_FORMAT_LPC10:
+ ast = AST_FORMAT_LPC10;
+ break;
+ case DAHDI_FORMAT_G729A:
+ ast = AST_FORMAT_G729;
+ break;
+ case DAHDI_FORMAT_SPEEX:
+ ast = AST_FORMAT_SPEEX;
+ break;
+ case DAHDI_FORMAT_ILBC:
+ ast = AST_FORMAT_ILBC;
+ break;
+ default:
+ ast = 0;
+ break;
+ }
+
+ return ast;
+}
+#endif /* defined(NOT_NEEDED) */
+
+/*!
+ * \internal
+ * \brief Convert old Asterisk format bitfield to DAHDI format bitfield.
+ * \since 13.0.0
+ *
+ * \param ast Old Asterisk bitfield to convert.
+ *
+ * \note They should be the same values but they don't have to be.
+ *
+ * \return DAHDI bitfield equivalent.
+ */
+static unsigned bitfield_ast2dahdi(uint64_t ast)
+{
+ unsigned dahdi;
+
+ switch (ast) {
+ case AST_FORMAT_G723:
+ dahdi = DAHDI_FORMAT_G723_1;
+ break;
+ case AST_FORMAT_GSM:
+ dahdi = DAHDI_FORMAT_GSM;
+ break;
+ case AST_FORMAT_ULAW:
+ dahdi = DAHDI_FORMAT_ULAW;
+ break;
+ case AST_FORMAT_ALAW:
+ dahdi = DAHDI_FORMAT_ALAW;
+ break;
+ case AST_FORMAT_G726_AAL2:
+ dahdi = DAHDI_FORMAT_G726;
+ break;
+ case AST_FORMAT_ADPCM:
+ dahdi = DAHDI_FORMAT_ADPCM;
+ break;
+ case AST_FORMAT_SLIN:
+ dahdi = DAHDI_FORMAT_SLINEAR;
+ break;
+ case AST_FORMAT_LPC10:
+ dahdi = DAHDI_FORMAT_LPC10;
+ break;
+ case AST_FORMAT_G729:
+ dahdi = DAHDI_FORMAT_G729A;
+ break;
+ case AST_FORMAT_SPEEX:
+ dahdi = DAHDI_FORMAT_SPEEX;
+ break;
+ case AST_FORMAT_ILBC:
+ dahdi = DAHDI_FORMAT_ILBC;
+ break;
+ default:
+ dahdi = 0;
+ break;
+ }
+
+ return dahdi;
+}
+
+/*!
+ * \internal
+ * \brief Get the DAHDI codec by index.
+ * \since 13.0.0
+ *
+ * \param idx Codex index (0-31).
+ *
+ * \return Specified codec if exists otherwise NULL.
+ */
+static const struct ast_codec *get_dahdi_codec(unsigned idx)
+{
+ const struct ast_codec *codec;
+
+ static const struct ast_codec dahdi_g723_1 = {
+ .name = "g723",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_gsm = {
+ .name = "gsm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_ulaw = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_alaw = {
+ .name = "alaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_g726 = {
+ .name = "g726",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_adpcm = {
+ .name = "adpcm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_slinear = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_lpc10 = {
+ .name = "lpc10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_g729a = {
+ .name = "g729",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_speex = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+ static const struct ast_codec dahdi_ilbc = {
+ .name = "ilbc",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ };
+
+ switch (1UL << idx) {
+ case DAHDI_FORMAT_G723_1:
+ codec = &dahdi_g723_1;
+ break;
+ case DAHDI_FORMAT_GSM:
+ codec = &dahdi_gsm;
+ break;
+ case DAHDI_FORMAT_ULAW:
+ codec = &dahdi_ulaw;
+ break;
+ case DAHDI_FORMAT_ALAW:
+ codec = &dahdi_alaw;
+ break;
+ case DAHDI_FORMAT_G726:
+ codec = &dahdi_g726;
+ break;
+ case DAHDI_FORMAT_ADPCM:
+ codec = &dahdi_adpcm;
+ break;
+ case DAHDI_FORMAT_SLINEAR:
+ codec = &dahdi_slinear;
+ break;
+ case DAHDI_FORMAT_LPC10:
+ codec = &dahdi_lpc10;
+ break;
+ case DAHDI_FORMAT_G729A:
+ codec = &dahdi_g729a;
+ break;
+ case DAHDI_FORMAT_SPEEX:
+ codec = &dahdi_speex;
+ break;
+ case DAHDI_FORMAT_ILBC:
+ codec = &dahdi_ilbc;
+ break;
+ default:
+ codec = NULL;
+ break;
+ }
+
+ return codec;
+}
+
static char *handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static struct ast_cli_entry cli[] = {
@@ -190,7 +430,7 @@ static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
struct codec_dahdi_pvt *dahdip = pvt->pvt;
- if (!f->subclass.format.id) {
+ if (!f->subclass.format) {
/* We're just faking a return for calculation purposes. */
dahdip->fake = 2;
pvt->samples = f->samples;
@@ -245,18 +485,16 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
int res;
if (2 == dahdip->fake) {
+ struct ast_frame frm = {
+ .frametype = AST_FRAME_VOICE,
+ .samples = dahdip->required_samples,
+ .src = pvt->t->name,
+ };
+
dahdip->fake = 1;
- pvt->f.frametype = AST_FRAME_VOICE;
- ast_format_clear(&pvt->f.subclass.format);
- pvt->f.samples = dahdip->required_samples;
- pvt->f.data.ptr = NULL;
- pvt->f.offset = 0;
- pvt->f.datalen = 0;
- pvt->f.mallocd = 0;
pvt->samples = 0;
- return ast_frisolate(&pvt->f);
-
+ return ast_frisolate(&frm);
} else if (1 == dahdip->fake) {
dahdip->fake = 0;
return NULL;
@@ -277,13 +515,7 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
}
} else {
pvt->f.datalen = res;
- pvt->f.frametype = AST_FRAME_VOICE;
- ast_format_copy(&pvt->f.subclass.format, &pvt->t->dst_format);
- pvt->f.mallocd = 0;
- pvt->f.offset = AST_FRIENDLY_OFFSET;
- pvt->f.src = pvt->t->name;
- pvt->f.data.ptr = pvt->outbuf.c;
- pvt->f.samples = ast_codec_get_samples(&pvt->f);
+ pvt->f.samples = ast_codec_samples_count(&pvt->f);
dahdip->samples_written_to_hardware =
(dahdip->samples_written_to_hardware >= pvt->f.samples) ?
@@ -302,7 +534,7 @@ static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
struct codec_dahdi_pvt *dahdip = pvt->pvt;
- if (!f->subclass.format.id) {
+ if (!f->subclass.format) {
/* We're just faking a return for calculation purposes. */
dahdip->fake = 2;
pvt->samples = f->samples;
@@ -327,16 +559,16 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
struct codec_dahdi_pvt *dahdip = pvt->pvt;
if (2 == dahdip->fake) {
+ struct ast_frame frm = {
+ .frametype = AST_FRAME_VOICE,
+ .samples = dahdip->required_samples,
+ .src = pvt->t->name,
+ };
+
dahdip->fake = 1;
- pvt->f.frametype = AST_FRAME_VOICE;
- ast_format_clear(&pvt->f.subclass.format);
- pvt->f.samples = dahdip->required_samples;
- pvt->f.data.ptr = NULL;
- pvt->f.offset = 0;
- pvt->f.datalen = 0;
- pvt->f.mallocd = 0;
pvt->samples = 0;
- return ast_frisolate(&pvt->f);
+
+ return ast_frisolate(&frm);
} else if (1 == dahdip->fake) {
pvt->samples = 0;
dahdip->fake = 0;
@@ -370,12 +602,6 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
pvt->f.datalen = res;
}
pvt->datalen = 0;
- pvt->f.frametype = AST_FRAME_VOICE;
- ast_format_copy(&pvt->f.subclass.format, &pvt->t->dst_format);
- pvt->f.mallocd = 0;
- pvt->f.offset = AST_FRIENDLY_OFFSET;
- pvt->f.src = pvt->t->name;
- pvt->f.data.ptr = pvt->outbuf.c;
pvt->f.samples = res;
pvt->samples = 0;
dahdip->samples_written_to_hardware =
@@ -394,9 +620,9 @@ static void dahdi_destroy(struct ast_trans_pvt *pvt)
{
struct codec_dahdi_pvt *dahdip = pvt->pvt;
- switch (ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) {
- case AST_FORMAT_G729A:
- case AST_FORMAT_G723_1:
+ switch (dahdip->fmts.dstfmt) {
+ case DAHDI_FORMAT_G729A:
+ case DAHDI_FORMAT_G723_1:
ast_atomic_fetchadd_int(&channels.encoders, -1);
break;
default:
@@ -407,7 +633,39 @@ static void dahdi_destroy(struct ast_trans_pvt *pvt)
close(dahdip->fd);
}
-static int dahdi_translate(struct ast_trans_pvt *pvt, struct ast_format *dst_format, struct ast_format *src_format)
+static struct ast_format *dahdi_format_to_cached(int format)
+{
+ switch (format) {
+ case DAHDI_FORMAT_G723_1:
+ return ast_format_g723;
+ case DAHDI_FORMAT_GSM:
+ return ast_format_gsm;
+ case DAHDI_FORMAT_ULAW:
+ return ast_format_ulaw;
+ case DAHDI_FORMAT_ALAW:
+ return ast_format_alaw;
+ case DAHDI_FORMAT_G726:
+ return ast_format_g726;
+ case DAHDI_FORMAT_ADPCM:
+ return ast_format_adpcm;
+ case DAHDI_FORMAT_SLINEAR:
+ return ast_format_slin;
+ case DAHDI_FORMAT_LPC10:
+ return ast_format_lpc10;
+ case DAHDI_FORMAT_G729A:
+ return ast_format_g729;
+ case DAHDI_FORMAT_SPEEX:
+ return ast_format_speex;
+ case DAHDI_FORMAT_ILBC:
+ return ast_format_ilbc;
+ }
+
+ /* This will never be reached */
+ ast_assert(0);
+ return NULL;
+}
+
+static int dahdi_translate(struct ast_trans_pvt *pvt, struct ast_codec *dst_codec, struct ast_codec *src_codec)
{
/* Request translation through zap if possible */
int fd;
@@ -421,10 +679,13 @@ static int dahdi_translate(struct ast_trans_pvt *pvt, struct ast_format *dst_for
return -1;
}
- dahdip->fmts.srcfmt = ast_format_to_old_bitfield(src_format);
- dahdip->fmts.dstfmt = ast_format_to_old_bitfield(dst_format);
+ dahdip->fmts.srcfmt = bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(src_codec));
+ dahdip->fmts.dstfmt = bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(dst_codec));
+
+ ast_assert(pvt->f.subclass.format == NULL);
+ pvt->f.subclass.format = ao2_bump(dahdi_format_to_cached(dahdip->fmts.dstfmt));
- ast_debug(1, "Opening transcoder channel from %s to %s.\n", ast_getformatname(src_format), ast_getformatname(dst_format));
+ ast_debug(1, "Opening transcoder channel from %s to %s.\n", src_codec->name, dst_codec->name);
retry:
if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) {
@@ -437,14 +698,14 @@ retry:
* support for ULAW instead of signed linear and then
* we'll just convert from ulaw to signed linear in
* software. */
- if (AST_FORMAT_SLINEAR == ast_format_id_from_old_bitfield(dahdip->fmts.srcfmt)) {
+ if (dahdip->fmts.srcfmt == DAHDI_FORMAT_SLINEAR) {
ast_debug(1, "Using soft_slin support on source\n");
dahdip->softslin = 1;
- dahdip->fmts.srcfmt = ast_format_id_to_old_bitfield(AST_FORMAT_ULAW);
- } else if (AST_FORMAT_SLINEAR == ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) {
+ dahdip->fmts.srcfmt = DAHDI_FORMAT_ULAW;
+ } else if (dahdip->fmts.dstfmt == DAHDI_FORMAT_SLINEAR) {
ast_debug(1, "Using soft_slin support on destination\n");
dahdip->softslin = 1;
- dahdip->fmts.dstfmt = ast_format_id_to_old_bitfield(AST_FORMAT_ULAW);
+ dahdip->fmts.dstfmt = DAHDI_FORMAT_ULAW;
}
tried_once = 1;
goto retry;
@@ -463,13 +724,13 @@ retry:
dahdip->fd = fd;
- dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (ast_format_id_to_old_bitfield(AST_FORMAT_G723_1))) ? G723_SAMPLES : G729_SAMPLES;
+ dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (DAHDI_FORMAT_G723_1)) ? G723_SAMPLES : G729_SAMPLES;
- switch (ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) {
- case AST_FORMAT_G729A:
+ switch (dahdip->fmts.dstfmt) {
+ case DAHDI_FORMAT_G729A:
ast_atomic_fetchadd_int(&channels.encoders, +1);
break;
- case AST_FORMAT_G723_1:
+ case DAHDI_FORMAT_G723_1:
ast_atomic_fetchadd_int(&channels.encoders, +1);
break;
default:
@@ -483,8 +744,8 @@ retry:
static int dahdi_new(struct ast_trans_pvt *pvt)
{
return dahdi_translate(pvt,
- &pvt->t->dst_format,
- &pvt->t->src_format);
+ pvt->t->core_dst_codec,
+ pvt->t->core_src_codec);
}
static struct ast_frame *fakesrc_sample(void)
@@ -501,33 +762,37 @@ static struct ast_frame *fakesrc_sample(void)
static int is_encoder(struct translator *zt)
{
- if ((zt->t.src_format.id == AST_FORMAT_ULAW) ||
- (zt->t.src_format.id == AST_FORMAT_ALAW) ||
- (zt->t.src_format.id == AST_FORMAT_SLINEAR)) {
+ if ((zt->t.core_src_codec->id == ast_format_get_codec_id(ast_format_ulaw)) ||
+ (zt->t.core_src_codec->id == ast_format_get_codec_id(ast_format_alaw)) ||
+ (zt->t.core_src_codec->id == ast_format_get_codec_id(ast_format_slin))) {
return 1;
} else {
return 0;
}
}
-static int register_translator(int dst, int src)
+static int register_translator(unsigned dst, unsigned src)
{
+ const struct ast_codec *dst_codec;
+ const struct ast_codec *src_codec;
struct translator *zt;
int res;
- struct ast_format dst_format;
- struct ast_format src_format;
- ast_format_from_old_bitfield(&dst_format, (1 << dst));
- ast_format_from_old_bitfield(&src_format, (1 << src));
+ dst_codec = get_dahdi_codec(dst);
+ src_codec = get_dahdi_codec(src);
+ if (!dst_codec || !src_codec) {
+ return -1;
+ }
if (!(zt = ast_calloc(1, sizeof(*zt)))) {
return -1;
}
- snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s",
- ast_getformatname(&src_format), ast_getformatname(&dst_format));
- ast_format_copy(&zt->t.src_format, &src_format);
- ast_format_copy(&zt->t.dst_format, &dst_format);
+ snprintf(zt->t.name, sizeof(zt->t.name), "dahdi_%s_to_%s",
+ src_codec->name, dst_codec->name);
+
+ memcpy(&zt->t.src_codec, src_codec, sizeof(*src_codec));
+ memcpy(&zt->t.dst_codec, dst_codec, sizeof(*dst_codec));
zt->t.buf_size = BUFFER_SIZE;
if (is_encoder(zt)) {
zt->t.framein = dahdi_encoder_framein;
@@ -557,17 +822,20 @@ static int register_translator(int dst, int src)
return res;
}
-static void drop_translator(int dst, int src)
+static void drop_translator(unsigned dst, unsigned src)
{
struct translator *cur;
AST_LIST_LOCK(&translators);
AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) {
- if (cur->t.src_format.id != ast_format_id_from_old_bitfield((1 << src)))
+ if (bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(cur->t.core_src_codec))
+ != (1U << src)) {
continue;
-
- if (cur->t.dst_format.id != ast_format_id_from_old_bitfield((1 << dst)))
+ }
+ if (bitfield_ast2dahdi(ast_format_compatibility_codec2bitfield(cur->t.core_dst_codec))
+ != (1U << dst)) {
continue;
+ }
AST_LIST_REMOVE_CURRENT(entry);
ast_unregister_translator(&cur->t);
@@ -678,7 +946,6 @@ static int unload_module(void)
static int load_module(void)
{
- ast_ulaw_init();
find_transcoders();
ast_cli_register_multiple(cli, ARRAY_LEN(cli));
return AST_MODULE_LOAD_SUCCESS;
diff --git a/codecs/codec_g722.c b/codecs/codec_g722.c
index 89641f175..1eba8067f 100644
--- a/codecs/codec_g722.c
+++ b/codecs/codec_g722.c
@@ -138,6 +138,17 @@ static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator g722tolin = {
.name = "g722tolin",
+ .src_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = g722tolin_new, /* same for both directions */
.framein = g722tolin_framein,
.sample = g722_sample,
@@ -148,6 +159,17 @@ static struct ast_translator g722tolin = {
static struct ast_translator lintog722 = {
.name = "lintog722",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "g722",
.newpvt = lintog722_new, /* same for both directions */
.framein = lintog722_framein,
.sample = slin8_sample,
@@ -158,6 +180,17 @@ static struct ast_translator lintog722 = {
static struct ast_translator g722tolin16 = {
.name = "g722tolin16",
+ .src_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "slin16",
.newpvt = g722tolin16_new, /* same for both directions */
.framein = g722tolin_framein,
.sample = g722_sample,
@@ -168,6 +201,17 @@ static struct ast_translator g722tolin16 = {
static struct ast_translator lin16tog722 = {
.name = "lin16tog722",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "g722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "g722",
.newpvt = lin16tog722_new, /* same for both directions */
.framein = lintog722_framein,
.sample = slin16_sample,
@@ -176,11 +220,6 @@ static struct ast_translator lin16tog722 = {
.buf_size = BUFFER_SAMPLES,
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res = 0;
@@ -197,18 +236,6 @@ static int load_module(void)
{
int res = 0;
- ast_format_set(&g722tolin.src_format, AST_FORMAT_G722, 0);
- ast_format_set(&g722tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintog722.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintog722.dst_format, AST_FORMAT_G722, 0);
-
- ast_format_set(&g722tolin16.src_format, AST_FORMAT_G722, 0);
- ast_format_set(&g722tolin16.dst_format, AST_FORMAT_SLINEAR16, 0);
-
- ast_format_set(&lin16tog722.src_format, AST_FORMAT_SLINEAR16, 0);
- ast_format_set(&lin16tog722.dst_format, AST_FORMAT_G722, 0);
-
res |= ast_register_translator(&g722tolin);
res |= ast_register_translator(&lintog722);
res |= ast_register_translator(&g722tolin16);
@@ -225,5 +252,4 @@ static int load_module(void)
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_g726.c b/codecs/codec_g726.c
index 72e77f955..a41039d53 100644
--- a/codecs/codec_g726.c
+++ b/codecs/codec_g726.c
@@ -785,6 +785,17 @@ static int lintog726_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator g726tolin = {
.name = "g726tolin",
+ .src_codec = {
+ .name = "g726",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = lintog726_new, /* same for both directions */
.framein = g726tolin_framein,
.sample = g726_sample,
@@ -795,6 +806,17 @@ static struct ast_translator g726tolin = {
static struct ast_translator lintog726 = {
.name = "lintog726",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "g726",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "g726",
.newpvt = lintog726_new, /* same for both directions */
.framein = lintog726_framein,
.sample = slin8_sample,
@@ -805,6 +827,17 @@ static struct ast_translator lintog726 = {
static struct ast_translator g726aal2tolin = {
.name = "g726aal2tolin",
+ .src_codec = {
+ .name = "g726aal2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = lintog726_new, /* same for both directions */
.framein = g726aal2tolin_framein,
.sample = g726_sample,
@@ -815,6 +848,17 @@ static struct ast_translator g726aal2tolin = {
static struct ast_translator lintog726aal2 = {
.name = "lintog726aal2",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "g726aal2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "g726aal2",
.newpvt = lintog726_new, /* same for both directions */
.framein = lintog726aal2_framein,
.sample = slin8_sample,
@@ -823,11 +867,6 @@ static struct ast_translator lintog726aal2 = {
.buf_size = BUFFER_SAMPLES / 2,
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res = 0;
@@ -845,18 +884,6 @@ static int load_module(void)
{
int res = 0;
- ast_format_set(&g726tolin.src_format, AST_FORMAT_G726, 0);
- ast_format_set(&g726tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintog726.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintog726.dst_format, AST_FORMAT_G726, 0);
-
- ast_format_set(&g726aal2tolin.src_format, AST_FORMAT_G726_AAL2, 0);
- ast_format_set(&g726aal2tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintog726aal2.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintog726aal2.dst_format, AST_FORMAT_G726_AAL2, 0);
-
res |= ast_register_translator(&g726tolin);
res |= ast_register_translator(&lintog726);
@@ -874,5 +901,4 @@ static int load_module(void)
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.726-32kbps G726 Transcoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c
index f42a5f1bd..49f672adb 100644
--- a/codecs/codec_gsm.c
+++ b/codecs/codec_gsm.c
@@ -168,7 +168,18 @@ static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
}
static struct ast_translator gsmtolin = {
- .name = "gsmtolin",
+ .name = "gsmtolin",
+ .src_codec = {
+ .name = "gsm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = gsm_new,
.framein = gsmtolin_framein,
.destroy = gsm_destroy_stuff,
@@ -179,7 +190,18 @@ static struct ast_translator gsmtolin = {
};
static struct ast_translator lintogsm = {
- .name = "lintogsm",
+ .name = "lintogsm",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "gsm",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "gsm",
.newpvt = gsm_new,
.framein = lintogsm_framein,
.frameout = lintogsm_frameout,
@@ -189,19 +211,12 @@ static struct ast_translator lintogsm = {
.buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES,
};
-/*! \brief standard module glue */
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
res = ast_unregister_translator(&lintogsm);
- if (!res)
- res = ast_unregister_translator(&gsmtolin);
+ res |= ast_unregister_translator(&gsmtolin);
return res;
}
@@ -210,24 +225,18 @@ static int load_module(void)
{
int res;
- ast_format_set(&gsmtolin.src_format, AST_FORMAT_GSM, 0);
- ast_format_set(&gsmtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintogsm.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintogsm.dst_format, AST_FORMAT_GSM, 0);
-
res = ast_register_translator(&gsmtolin);
- if (!res)
- res=ast_register_translator(&lintogsm);
- else
- ast_unregister_translator(&gsmtolin);
- if (res)
+ res |= ast_register_translator(&lintogsm);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GSM Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_ilbc.c b/codecs/codec_ilbc.c
index 632169589..af23b906d 100644
--- a/codecs/codec_ilbc.c
+++ b/codecs/codec_ilbc.c
@@ -178,7 +178,18 @@ static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt)
}
static struct ast_translator ilbctolin = {
- .name = "ilbctolin",
+ .name = "ilbctolin",
+ .src_codec = {
+ .name = "ilbc",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = ilbctolin_new,
.framein = ilbctolin_framein,
.sample = ilbc_sample,
@@ -188,7 +199,18 @@ static struct ast_translator ilbctolin = {
};
static struct ast_translator lintoilbc = {
- .name = "lintoilbc",
+ .name = "lintoilbc",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "ilbc",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "ilbc",
.newpvt = lintoilbc_new,
.framein = lintoilbc_framein,
.frameout = lintoilbc_frameout,
@@ -211,20 +233,14 @@ static int load_module(void)
{
int res;
- ast_format_set(&ilbctolin.src_format, AST_FORMAT_ILBC, 0);
- ast_format_set(&ilbctolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintoilbc.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintoilbc.dst_format, AST_FORMAT_ILBC, 0);
-
-
res = ast_register_translator(&ilbctolin);
- if (!res)
- res=ast_register_translator(&lintoilbc);
- else
- ast_unregister_translator(&ilbctolin);
- if (res)
+ res |= ast_register_translator(&lintoilbc);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c
index 5f2047a3f..0ef8856ff 100644
--- a/codecs/codec_lpc10.c
+++ b/codecs/codec_lpc10.c
@@ -196,7 +196,18 @@ static void lpc10_destroy(struct ast_trans_pvt *arg)
}
static struct ast_translator lpc10tolin = {
- .name = "lpc10tolin",
+ .name = "lpc10tolin",
+ .src_codec = {
+ .name = "lpc10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = lpc10_dec_new,
.framein = lpc10tolin_framein,
.destroy = lpc10_destroy,
@@ -207,7 +218,18 @@ static struct ast_translator lpc10tolin = {
};
static struct ast_translator lintolpc10 = {
- .name = "lintolpc10",
+ .name = "lintolpc10",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "lpc10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "lpc10",
.newpvt = lpc10_enc_new,
.framein = lintolpc10_framein,
.frameout = lintolpc10_frameout,
@@ -218,12 +240,6 @@ static struct ast_translator lintolpc10 = {
.buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME),
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
-
static int unload_module(void)
{
int res;
@@ -238,24 +254,18 @@ static int load_module(void)
{
int res;
- ast_format_set(&lpc10tolin.src_format, AST_FORMAT_LPC10, 0);
- ast_format_set(&lpc10tolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintolpc10.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintolpc10.dst_format, AST_FORMAT_LPC10, 0);
-
res = ast_register_translator(&lpc10tolin);
- if (!res)
- res = ast_register_translator(&lintolpc10);
- else
- ast_unregister_translator(&lpc10tolin);
- if (res)
+ res |= ast_register_translator(&lintolpc10);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LPC10 2.4kbps Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/codec_resample.c b/codecs/codec_resample.c
index 29d95a798..26b1f0e08 100644
--- a/codecs/codec_resample.c
+++ b/codecs/codec_resample.c
@@ -42,32 +42,72 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static struct ast_translator *translators;
static int trans_size;
-static int id_list[] = {
- AST_FORMAT_SLINEAR,
- AST_FORMAT_SLINEAR12,
- AST_FORMAT_SLINEAR16,
- AST_FORMAT_SLINEAR24,
- AST_FORMAT_SLINEAR32,
- AST_FORMAT_SLINEAR44,
- AST_FORMAT_SLINEAR48,
- AST_FORMAT_SLINEAR96,
- AST_FORMAT_SLINEAR192,
+static struct ast_codec codec_list[] = {
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 12000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 24000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 44100,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 96000,
+ },
+ {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 192000,
+ },
};
static int resamp_new(struct ast_trans_pvt *pvt)
{
int err;
- if (!(pvt->pvt = speex_resampler_init(1, ast_format_rate(&pvt->t->src_format), ast_format_rate(&pvt->t->dst_format), 5, &err))) {
+ if (!(pvt->pvt = speex_resampler_init(1, pvt->t->src_codec.sample_rate, pvt->t->dst_codec.sample_rate, 5, &err))) {
return -1;
}
+ ast_assert(pvt->f.subclass.format == NULL);
+ pvt->f.subclass.format = ao2_bump(ast_format_cache_get_slin_by_rate(pvt->t->dst_codec.sample_rate));
+
return 0;
}
static void resamp_destroy(struct ast_trans_pvt *pvt)
{
SpeexResamplerState *resamp_pvt = pvt->pvt;
+
speex_resampler_destroy(resamp_pvt);
}
@@ -113,13 +153,13 @@ static int load_module(void)
int res = 0;
int x, y, idx = 0;
- trans_size = ARRAY_LEN(id_list) * (ARRAY_LEN(id_list) - 1);
+ trans_size = ARRAY_LEN(codec_list) * (ARRAY_LEN(codec_list) - 1);
if (!(translators = ast_calloc(1, sizeof(struct ast_translator) * trans_size))) {
return AST_MODULE_LOAD_FAILURE;
}
- for (x = 0; x < ARRAY_LEN(id_list); x++) {
- for (y = 0; y < ARRAY_LEN(id_list); y++) {
+ for (x = 0; x < ARRAY_LEN(codec_list); x++) {
+ for (y = 0; y < ARRAY_LEN(codec_list); y++) {
if (x == y) {
continue;
}
@@ -129,10 +169,10 @@ static int load_module(void)
translators[idx].desc_size = 0;
translators[idx].buffer_samples = (OUTBUF_SIZE / sizeof(int16_t));
translators[idx].buf_size = OUTBUF_SIZE;
- ast_format_set(&translators[idx].src_format, id_list[x], 0);
- ast_format_set(&translators[idx].dst_format, id_list[y], 0);
- snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %dkhz -> %dkhz",
- ast_format_rate(&translators[idx].src_format), ast_format_rate(&translators[idx].dst_format));
+ memcpy(&translators[idx].src_codec, &codec_list[x], sizeof(struct ast_codec));
+ memcpy(&translators[idx].dst_codec, &codec_list[y], sizeof(struct ast_codec));
+ snprintf(translators[idx].name, sizeof(translators[idx].name), "slin %ukhz -> %ukhz",
+ translators[idx].src_codec.sample_rate, translators[idx].dst_codec.sample_rate);
res |= ast_register_translator(&translators[idx]);
idx++;
}
diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c
index 72e948057..8c2c3f395 100644
--- a/codecs/codec_speex.c
+++ b/codecs/codec_speex.c
@@ -308,10 +308,14 @@ static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
} else {
tmp->silent_state = 1;
speex_bits_reset(&tmp->bits);
+
+/* BUGBUG need to setup a new static frame to prevent destroying the translators normal static frame. */
+ ao2_cleanup(pvt->f.subclass.format);
memset(&pvt->f, 0, sizeof(pvt->f));
pvt->f.frametype = AST_FRAME_CNG;
pvt->f.samples = samples;
/* XXX what now ? format etc... */
+/* BUGBUG should return ast_frisolate(setup local static frame) here */
}
}
@@ -341,7 +345,18 @@ static void lintospeex_destroy(struct ast_trans_pvt *arg)
}
static struct ast_translator speextolin = {
- .name = "speextolin",
+ .name = "speextolin",
+ .src_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.newpvt = speextolin_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
@@ -354,6 +369,17 @@ static struct ast_translator speextolin = {
static struct ast_translator lintospeex = {
.name = "lintospeex",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "speex",
.newpvt = lintospeex_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
@@ -365,7 +391,18 @@ static struct ast_translator lintospeex = {
};
static struct ast_translator speexwbtolin16 = {
- .name = "speexwbtolin16",
+ .name = "speexwbtolin16",
+ .src_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "slin16",
.newpvt = speexwbtolin16_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
@@ -377,7 +414,18 @@ static struct ast_translator speexwbtolin16 = {
};
static struct ast_translator lin16tospeexwb = {
- .name = "lin16tospeexwb",
+ .name = "lin16tospeexwb",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .dst_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ },
+ .format = "speex16",
.newpvt = lin16tospeexwb_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
@@ -389,7 +437,18 @@ static struct ast_translator lin16tospeexwb = {
};
static struct ast_translator speexuwbtolin32 = {
- .name = "speexuwbtolin32",
+ .name = "speexuwbtolin32",
+ .src_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .format = "slin32",
.newpvt = speexuwbtolin32_new,
.framein = speextolin_framein,
.destroy = speextolin_destroy,
@@ -400,7 +459,18 @@ static struct ast_translator speexuwbtolin32 = {
};
static struct ast_translator lin32tospeexuwb = {
- .name = "lin32tospeexuwb",
+ .name = "lin32tospeexuwb",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .dst_codec = {
+ .name = "speex",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ },
+ .format = "speex32",
.newpvt = lin32tospeexuwb_new,
.framein = lintospeex_framein,
.frameout = lintospeex_frameout,
@@ -534,25 +604,6 @@ static int load_module(void)
if (parse_config(0))
return AST_MODULE_LOAD_DECLINE;
-
- ast_format_set(&speextolin.src_format, AST_FORMAT_SPEEX, 0);
- ast_format_set(&speextolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&lintospeex.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintospeex.dst_format, AST_FORMAT_SPEEX, 0);
-
- ast_format_set(&speexwbtolin16.src_format, AST_FORMAT_SPEEX16, 0);
- ast_format_set(&speexwbtolin16.dst_format, AST_FORMAT_SLINEAR16, 0);
-
- ast_format_set(&lin16tospeexwb.src_format, AST_FORMAT_SLINEAR16, 0);
- ast_format_set(&lin16tospeexwb.dst_format, AST_FORMAT_SPEEX16, 0);
-
- ast_format_set(&speexuwbtolin32.src_format, AST_FORMAT_SPEEX32, 0);
- ast_format_set(&speexuwbtolin32.dst_format, AST_FORMAT_SLINEAR32, 0);
-
- ast_format_set(&lin32tospeexuwb.src_format, AST_FORMAT_SLINEAR32, 0);
- ast_format_set(&lin32tospeexuwb.dst_format, AST_FORMAT_SPEEX32, 0);
-
res |= ast_register_translator(&speextolin);
res |= ast_register_translator(&lintospeex);
res |= ast_register_translator(&speexwbtolin16);
@@ -560,6 +611,10 @@ static int load_module(void)
res |= ast_register_translator(&speexuwbtolin32);
res |= ast_register_translator(&lin32tospeexuwb);
+ if (res) {
+ unload_module();
+ return res;
+ }
return res;
}
diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c
index 86a0706c4..9d0aa3c14 100644
--- a/codecs/codec_ulaw.c
+++ b/codecs/codec_ulaw.c
@@ -82,6 +82,17 @@ static int lintoulaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_translator ulawtolin = {
.name = "ulawtolin",
+ .src_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = ulawtolin_framein,
.sample = ulaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -90,6 +101,17 @@ static struct ast_translator ulawtolin = {
static struct ast_translator testlawtolin = {
.name = "testlawtolin",
+ .src_codec = {
+ .name = "testlaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
.framein = ulawtolin_framein,
.sample = ulaw_sample,
.buffer_samples = BUFFER_SAMPLES,
@@ -102,6 +124,17 @@ static struct ast_translator testlawtolin = {
static struct ast_translator lintoulaw = {
.name = "lintoulaw",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "ulaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "ulaw",
.framein = lintoulaw_framein,
.sample = slin8_sample,
.buf_size = BUFFER_SAMPLES,
@@ -110,17 +143,23 @@ static struct ast_translator lintoulaw = {
static struct ast_translator lintotestlaw = {
.name = "lintotestlaw",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "testlaw",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "testlaw",
.framein = lintoulaw_framein,
.sample = slin8_sample,
.buf_size = BUFFER_SAMPLES,
.buffer_samples = BUFFER_SAMPLES,
};
-static int reload(void)
-{
- return AST_MODULE_LOAD_SUCCESS;
-}
-
static int unload_module(void)
{
int res;
@@ -137,32 +176,20 @@ static int load_module(void)
{
int res;
- ast_format_set(&lintoulaw.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintoulaw.dst_format, AST_FORMAT_ULAW, 0);
-
- ast_format_set(&lintotestlaw.src_format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&lintotestlaw.dst_format, AST_FORMAT_TESTLAW, 0);
-
- ast_format_set(&ulawtolin.src_format, AST_FORMAT_ULAW, 0);
- ast_format_set(&ulawtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
- ast_format_set(&testlawtolin.src_format, AST_FORMAT_TESTLAW, 0);
- ast_format_set(&testlawtolin.dst_format, AST_FORMAT_SLINEAR, 0);
-
res = ast_register_translator(&ulawtolin);
- if (!res) {
- res = ast_register_translator(&lintoulaw);
- res |= ast_register_translator(&lintotestlaw);
- res |= ast_register_translator(&testlawtolin);
- } else
- ast_unregister_translator(&ulawtolin);
- if (res)
+ res |= ast_register_translator(&lintoulaw);
+ res |= ast_register_translator(&lintotestlaw);
+ res |= ast_register_translator(&testlawtolin);
+
+ if (res) {
+ unload_module();
return AST_MODULE_LOAD_FAILURE;
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "mu-Law Coder/Decoder",
.load = load_module,
.unload = unload_module,
- .reload = reload,
);
diff --git a/codecs/ex_adpcm.h b/codecs/ex_adpcm.h
index 96b7c51f8..360239789 100644
--- a/codecs/ex_adpcm.h
+++ b/codecs/ex_adpcm.h
@@ -26,7 +26,8 @@ static struct ast_frame *adpcm_sample(void)
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_adpcm,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ADPCM, 0);
+
+ f.subclass.format = ast_format_adpcm;
return &f;
}
diff --git a/codecs/ex_alaw.h b/codecs/ex_alaw.h
index bbf8ad982..e8629be5e 100644
--- a/codecs/ex_alaw.h
+++ b/codecs/ex_alaw.h
@@ -31,6 +31,6 @@ static struct ast_frame *alaw_sample(void)
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_alaw,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ALAW, 0);
+ f.subclass.format = ast_format_alaw;
return &f;
}
diff --git a/codecs/ex_g722.h b/codecs/ex_g722.h
index 0e9f22686..390cc7b5c 100644
--- a/codecs/ex_g722.h
+++ b/codecs/ex_g722.h
@@ -42,7 +42,7 @@ static struct ast_frame *g722_sample(void)
.data.ptr = ex_g722,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_G722, 0);
+ f.subclass.format = ast_format_slin;
return &f;
}
diff --git a/codecs/ex_g726.h b/codecs/ex_g726.h
index d5438c91a..f125253ee 100644
--- a/codecs/ex_g726.h
+++ b/codecs/ex_g726.h
@@ -27,7 +27,7 @@ static struct ast_frame *g726_sample(void)
.data.ptr = ex_g726,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_G726, 0);
+ f.subclass.format = ast_format_g726;
return &f;
}
diff --git a/codecs/ex_gsm.h b/codecs/ex_gsm.h
index 8f8b4f9fe..006706038 100644
--- a/codecs/ex_gsm.h
+++ b/codecs/ex_gsm.h
@@ -27,6 +27,7 @@ static struct ast_frame *gsm_sample(void)
.data.ptr = ex_gsm,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_GSM, 0);
+ f.subclass.format = ast_format_gsm;
+
return &f;
}
diff --git a/codecs/ex_ilbc.h b/codecs/ex_ilbc.h
index 93cf5eacf..3a79b0918 100644
--- a/codecs/ex_ilbc.h
+++ b/codecs/ex_ilbc.h
@@ -28,6 +28,7 @@ static struct ast_frame *ilbc_sample(void)
.data.ptr = ex_ilbc,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ILBC, 0);
+ f.subclass.format = ast_format_ilbc;
+
return &f;
}
diff --git a/codecs/ex_lpc10.h b/codecs/ex_lpc10.h
index a36e06add..2e271c005 100644
--- a/codecs/ex_lpc10.h
+++ b/codecs/ex_lpc10.h
@@ -25,7 +25,7 @@ static struct ast_frame *lpc10_sample(void)
.data.ptr = ex_lpc10,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_LPC10, 0);
+ f.subclass.format = ast_format_lpc10;
return &f;
}
diff --git a/codecs/ex_speex.h b/codecs/ex_speex.h
index e9411e5d7..76e5925b8 100644
--- a/codecs/ex_speex.h
+++ b/codecs/ex_speex.h
@@ -27,7 +27,7 @@ static struct ast_frame *speex_sample(void)
.data.ptr = ex_speex,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX, 0);
+ f.subclass.format = ast_format_speex;
return &f;
}
@@ -58,7 +58,8 @@ static struct ast_frame *speex16_sample(void)
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_speex16,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SPEEX16, 0);
+
+ f.subclass.format = ast_format_speex16;
return &f;
}
diff --git a/codecs/ex_ulaw.h b/codecs/ex_ulaw.h
index 2ab9222fb..d18a08e9c 100644
--- a/codecs/ex_ulaw.h
+++ b/codecs/ex_ulaw.h
@@ -32,6 +32,7 @@ static struct ast_frame *ulaw_sample(void)
.data.ptr = ex_ulaw,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_ULAW, 0);
+ f.subclass.format = ast_format_ulaw;
+
return &f;
}
diff --git a/formats/format_g719.c b/formats/format_g719.c
index ee9221230..8d508f0e3 100644
--- a/formats/format_g719.c
+++ b/formats/format_g719.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 160 /* 20 milliseconds == 160 bytes, 960 samples */
#define SAMPLES_TO_BYTES(x) ((typeof(x)) x / ((float) 960 / 160))
@@ -44,9 +45,6 @@ static struct ast_frame *g719read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_G719, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
if (res)
@@ -61,14 +59,6 @@ static int g719write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_G719) {
- ast_log(LOG_WARNING, "Asked to write non-G.719 frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -147,7 +137,8 @@ static struct ast_format_def g719_f = {
static int load_module(void)
{
- ast_format_set(&g719_f.format, AST_FORMAT_G719, 0);
+ g719_f.format = ast_format_g719;
+
if (ast_format_def_register(&g719_f))
return AST_MODULE_LOAD_DECLINE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_g723.c b/formats/format_g723.c
index c3c194d15..51fe6b049 100644
--- a/formats/format_g723.c
+++ b/formats/format_g723.c
@@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
+#include "asterisk/format_cache.h"
#define G723_MAX_SIZE 1024
@@ -64,9 +65,6 @@ static struct ast_frame *g723_read(struct ast_filestream *s, int *whennext)
return NULL;
}
/* Read the data into the buffer */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_G723_1, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, size);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != size) {
ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno));
@@ -82,14 +80,6 @@ static int g723_write(struct ast_filestream *s, struct ast_frame *f)
uint16_t size;
int res;
/* XXX there used to be a check s->fr means a read stream */
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_G723_1) {
- ast_log(LOG_WARNING, "Asked to write non-g723 frame!\n");
- return -1;
- }
delay = 0;
if (f->datalen <= 0) {
ast_log(LOG_WARNING, "Short frame ignored (%d bytes long?)\n", f->datalen);
@@ -151,7 +141,7 @@ static struct ast_format_def g723_1_f = {
static int load_module(void)
{
- ast_format_set(&g723_1_f.format, AST_FORMAT_G723_1, 0);
+ g723_1_f.format = ast_format_g723;
if (ast_format_def_register(&g723_1_f))
return AST_MODULE_LOAD_FAILURE;
diff --git a/formats/format_g726.c b/formats/format_g726.c
index 636aff091..bde3e2d06 100644
--- a/formats/format_g726.c
+++ b/formats/format_g726.c
@@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define RATE_40 0
#define RATE_32 1
@@ -122,9 +123,6 @@ static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext)
struct g726_desc *fs = (struct g726_desc *)s->_private;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_G726, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, frame_size[fs->rate]);
s->fr.samples = 8 * FRAME_TIME;
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
@@ -141,15 +139,6 @@ static int g726_write(struct ast_filestream *s, struct ast_frame *f)
int res;
struct g726_desc *fs = (struct g726_desc *)s->_private;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_G726) {
- ast_log(LOG_WARNING, "Asked to write non-G726 frame (%s)!\n",
- ast_getformatname(&f->subclass.format));
- return -1;
- }
if (f->datalen % frame_size[fs->rate]) {
ast_log(LOG_WARNING, "Invalid data length %d, should be multiple of %d\n",
f->datalen, frame_size[fs->rate]);
@@ -239,7 +228,7 @@ static int load_module(void)
int i;
for (i = 0; f[i].desc_size ; i++) {
- ast_format_set(&f[i].format, AST_FORMAT_G726, 0);
+ f[i].format = ast_format_g726;
if (ast_format_def_register(&f[i])) { /* errors are fatal */
ast_log(LOG_WARNING, "Failed to register format %s.\n", f[i].name);
return AST_MODULE_LOAD_FAILURE;
diff --git a/formats/format_g729.c b/formats/format_g729.c
index f11fa97d9..7d562ede7 100644
--- a/formats/format_g729.c
+++ b/formats/format_g729.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeg729e.c by Jeffrey Chilton */
@@ -49,9 +50,6 @@ static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext)
{
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_G729A, 0);
- s->fr.mallocd = 0;
s->fr.samples = G729A_SAMPLES;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
@@ -66,14 +64,7 @@ static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext)
static int g729_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_G729A) {
- ast_log(LOG_WARNING, "Asked to write non-G729 frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
+
if (f->datalen % 10) {
ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 10\n", f->datalen);
return -1;
@@ -147,7 +138,7 @@ static struct ast_format_def g729_f = {
static int load_module(void)
{
- ast_format_set(&g729_f.format, AST_FORMAT_G729A, 0);
+ g729_f.format = ast_format_g729;
if (ast_format_def_register(&g729_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_gsm.c b/formats/format_gsm.c
index 47ed41c3a..fe1e55c7a 100644
--- a/formats/format_gsm.c
+++ b/formats/format_gsm.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#include "msgsm.h"
@@ -56,10 +57,7 @@ static struct ast_frame *gsm_read(struct ast_filestream *s, int *whennext)
{
int res;
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_GSM, 0);
AST_FRAME_SET_BUFFER(&(s->fr), s->buf, AST_FRIENDLY_OFFSET, GSM_FRAME_SIZE)
- s->fr.mallocd = 0;
if ((res = fread(s->fr.data.ptr, 1, GSM_FRAME_SIZE, s->f)) != GSM_FRAME_SIZE) {
if (res)
ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
@@ -74,14 +72,6 @@ static int gsm_write(struct ast_filestream *fs, struct ast_frame *f)
int res;
unsigned char gsm[2*GSM_FRAME_SIZE];
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_GSM) {
- ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
if (!(f->datalen % 65)) {
/* This is in MSGSM format, need to be converted */
int len=0;
@@ -193,7 +183,7 @@ static struct ast_format_def gsm_f = {
static int load_module(void)
{
- ast_format_set(&gsm_f.format, AST_FORMAT_GSM, 0);
+ gsm_f.format = ast_format_gsm;
if (ast_format_def_register(&gsm_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_h263.c b/formats/format_h263.c
index 56e9b3aa0..6511cef04 100644
--- a/formats/format_h263.c
+++ b/formats/format_h263.c
@@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeh263e.c by Jeffrey Chilton */
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
* ridiculously large). */
#define BUF_SIZE 32768 /* Four real h.263 Frames */
+#define FRAME_ENDED 0x8000
+
struct h263_desc {
unsigned int lastts;
};
@@ -76,15 +79,12 @@ static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext)
if ((res = fread(&len, 1, sizeof(len), s->f)) < 1)
return NULL;
len = ntohs(len);
- mark = (len & 0x8000) ? 1 : 0;
+ mark = (len & FRAME_ENDED) ? 1 : 0;
len &= 0x7fff;
if (len > BUF_SIZE) {
ast_log(LOG_WARNING, "Length %d is too long\n", len);
return NULL;
}
- s->fr.frametype = AST_FRAME_VIDEO;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_H263, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, len);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
if (res)
@@ -93,11 +93,7 @@ static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext)
}
s->fr.samples = fs->lastts; /* XXX what ? */
s->fr.datalen = len;
- if (mark) {
- ast_format_set_video_mark(&s->fr.subclass.format);
- }
- s->fr.delivery.tv_sec = 0;
- s->fr.delivery.tv_usec = 0;
+ s->fr.subclass.frame_ending = mark;
if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) {
fs->lastts = ntohl(ts);
*whennext = fs->lastts * 4/45;
@@ -112,15 +108,7 @@ static int h263_write(struct ast_filestream *fs, struct ast_frame *f)
unsigned int ts;
unsigned short len;
uint32_t mark = 0;
- if (f->frametype != AST_FRAME_VIDEO) {
- ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
- return -1;
- }
- mark = ast_format_get_video_mark(&f->subclass.format) ? 0x8000 : 0;
- if (f->subclass.format.id != AST_FORMAT_H263) {
- ast_log(LOG_WARNING, "Asked to write non-h263 frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
+ mark = f->subclass.frame_ending ? FRAME_ENDED : 0;
ts = htonl(f->samples);
if ((res = fwrite(&ts, 1, sizeof(ts), fs->f)) != sizeof(ts)) {
ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
@@ -182,7 +170,7 @@ static struct ast_format_def h263_f = {
static int load_module(void)
{
- ast_format_set(&h263_f.format, AST_FORMAT_H263, 0);
+ h263_f.format = ast_format_h263;
if (ast_format_def_register(&h263_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_h264.c b/formats/format_h264.c
index e090c2bac..56ec007c0 100644
--- a/formats/format_h264.c
+++ b/formats/format_h264.c
@@ -35,12 +35,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeh264e.c by Jeffrey Chilton */
/* Portions of the conversion code are by guido@sienanet.it */
/*! \todo Check this buf size estimate, it may be totally wrong for large frame video */
+#define FRAME_ENDED 0x8000
+
#define BUF_SIZE 4096 /* Two Real h264 Frames */
struct h264_desc {
unsigned int lastts;
@@ -68,15 +71,12 @@ static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext)
if ((res = fread(&len, 1, sizeof(len), s->f)) < 1)
return NULL;
len = ntohs(len);
- mark = (len & 0x8000) ? 1 : 0;
+ mark = (len & FRAME_ENDED) ? 1 : 0;
len &= 0x7fff;
if (len > BUF_SIZE) {
ast_log(LOG_WARNING, "Length %d is too long\n", len);
len = BUF_SIZE; /* XXX truncate */
}
- s->fr.frametype = AST_FRAME_VIDEO;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_H264, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, len);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
if (res)
@@ -85,11 +85,7 @@ static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext)
}
s->fr.samples = fs->lastts;
s->fr.datalen = len;
- if (mark) {
- ast_format_set_video_mark(&s->fr.subclass.format);
- }
- s->fr.delivery.tv_sec = 0;
- s->fr.delivery.tv_usec = 0;
+ s->fr.subclass.frame_ending = mark;
if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) {
fs->lastts = ntohl(ts);
*whennext = fs->lastts * 4/45;
@@ -105,15 +101,7 @@ static int h264_write(struct ast_filestream *s, struct ast_frame *f)
unsigned short len;
int mark;
- if (f->frametype != AST_FRAME_VIDEO) {
- ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
- return -1;
- }
- mark = ast_format_get_video_mark(&f->subclass.format) ? 0x8000 : 0;
- if (f->subclass.format.id != AST_FORMAT_H264) {
- ast_log(LOG_WARNING, "Asked to write non-h264 frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
+ mark = f->subclass.frame_ending ? FRAME_ENDED : 0;
ts = htonl(f->samples);
if ((res = fwrite(&ts, 1, sizeof(ts), s->f)) != sizeof(ts)) {
ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
@@ -175,7 +163,7 @@ static struct ast_format_def h264_f = {
static int load_module(void)
{
- ast_format_set(&h264_f.format, AST_FORMAT_H264, 0);
+ h264_f.format = ast_format_h264;
if (ast_format_def_register(&h264_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_ilbc.c b/formats/format_ilbc.c
index 07155b717..ce5135f7b 100644
--- a/formats/format_ilbc.c
+++ b/formats/format_ilbc.c
@@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
/* Some Ideas for this code came from makeg729e.c by Jeffrey Chilton */
@@ -48,9 +49,6 @@ static struct ast_frame *ilbc_read(struct ast_filestream *s, int *whennext)
{
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_ILBC, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, ILBC_BUF_SIZE);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
if (res)
@@ -64,14 +62,6 @@ static struct ast_frame *ilbc_read(struct ast_filestream *s, int *whennext)
static int ilbc_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_ILBC) {
- ast_log(LOG_WARNING, "Asked to write non-iLBC frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
if (f->datalen % 50) {
ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 50\n", f->datalen);
return -1;
@@ -145,7 +135,7 @@ static struct ast_format_def ilbc_f = {
static int load_module(void)
{
- ast_format_set(&ilbc_f.format, AST_FORMAT_ILBC, 0);
+ ilbc_f.format = ast_format_ilbc;
if (ast_format_def_register(&ilbc_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_jpeg.c b/formats/format_jpeg.c
index d6733020e..1e91482f7 100644
--- a/formats/format_jpeg.c
+++ b/formats/format_jpeg.c
@@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/image.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
static struct ast_frame *jpeg_read_image(int fd, int len)
{
@@ -52,7 +53,7 @@ static struct ast_frame *jpeg_read_image(int fd, int len)
}
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_IMAGE;
- ast_format_set(&fr.subclass.format, AST_FORMAT_JPEG, 0);
+ fr.subclass.format = ast_format_jpeg;
fr.data.ptr = buf;
fr.src = "JPEG Read";
fr.datalen = len;
@@ -74,14 +75,6 @@ static int jpeg_identify(int fd)
static int jpeg_write_image(int fd, struct ast_frame *fr)
{
int res=0;
- if (fr->frametype != AST_FRAME_IMAGE) {
- ast_log(LOG_WARNING, "Not an image\n");
- return -1;
- }
- if (fr->subclass.format.id != AST_FORMAT_JPEG) {
- ast_log(LOG_WARNING, "Not a jpeg image\n");
- return -1;
- }
if (fr->datalen) {
res = write(fd, fr->data.ptr, fr->datalen);
if (res != fr->datalen) {
@@ -103,7 +96,7 @@ static struct ast_imager jpeg_format = {
static int load_module(void)
{
- ast_format_set(&jpeg_format.format, AST_FORMAT_JPEG, 0);
+ jpeg_format.format = ast_format_jpeg;
if (ast_image_register(&jpeg_format))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_ogg_vorbis.c b/formats/format_ogg_vorbis.c
index 9eb390066..6171491a8 100644
--- a/formats/format_ogg_vorbis.c
+++ b/formats/format_ogg_vorbis.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
+#include "asterisk/format_cache.h"
/*
* this is the number of samples we deal with. Samples are converted
@@ -242,16 +243,6 @@ static int ogg_vorbis_write(struct ast_filestream *fs, struct ast_frame *f)
ast_log(LOG_ERROR, "This stream is not set up for writing!\n");
return -1;
}
-
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_SLINEAR) {
- ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%s)!\n",
- ast_getformatname(&f->subclass.format));
- return -1;
- }
if (!f->datalen)
return -1;
@@ -310,9 +301,6 @@ static struct ast_frame *ogg_vorbis_read(struct ast_filestream *fs,
}
/* initialize frame */
- fs->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&fs->fr.subclass.format, AST_FORMAT_SLINEAR, 0);
- fs->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
out_buf = (char *) (fs->fr.data.ptr); /* SLIN data buffer */
@@ -435,7 +423,7 @@ static struct ast_format_def vorbis_f = {
static int load_module(void)
{
- ast_format_set(&vorbis_f.format, AST_FORMAT_SLINEAR, 0);
+ vorbis_f.format = ast_format_slin;
if (ast_format_def_register(&vorbis_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_pcm.c b/formats/format_pcm.c
index 1ee333fba..2d864078e 100644
--- a/formats/format_pcm.c
+++ b/formats/format_pcm.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/endian.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 160 /* 160 bytes, and same number of samples */
@@ -66,7 +67,7 @@ static unsigned long get_time(void)
static int pcma_open(struct ast_filestream *s)
{
- if (s->fmt->format == AST_FORMAT_ALAW)
+ if (ast_format_cmp(s->fmt->format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
pd->starttime = get_time();
return 0;
}
@@ -83,9 +84,6 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext)
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_copy(&s->fr.subclass.format, &s->fmt->format);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
if (res)
@@ -93,7 +91,7 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext)
return NULL;
}
s->fr.datalen = res;
- if (s->fmt->format.id == AST_FORMAT_G722)
+ if (ast_format_cmp(s->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL)
*whennext = s->fr.samples = res * 2;
else
*whennext = s->fr.samples = res;
@@ -141,7 +139,7 @@ static int pcm_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
}
if (whence == SEEK_FORCECUR && offset > max) { /* extend the file */
size_t left = offset - max;
- const char *src = (fs->fmt->format.id == AST_FORMAT_ALAW) ? alaw_silence : ulaw_silence;
+ const char *src = (ast_format_cmp(fs->fmt->format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ? alaw_silence : ulaw_silence;
while (left) {
size_t written = fwrite(src, 1, (left > BUF_SIZE) ? BUF_SIZE : left, fs->f);
@@ -185,17 +183,8 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_log(LOG_WARNING, "Asked to write incompatible format frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
-
#ifdef REALTIME_WRITE
- if (s->fmt->format == AST_FORMAT_ALAW) {
+ if (ast_format_cmp(s->fmt->format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
struct pcm_desc *pd = (struct pcm_desc *)fs->_private;
struct stat stat_buf;
unsigned long cur_time = get_time();
@@ -399,7 +388,7 @@ static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
off_t min = AU_HEADER_SIZE, max, cur;
long offset = 0, bytes;
- if (fs->fmt->format.id == AST_FORMAT_G722)
+ if (ast_format_cmp(fs->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL)
bytes = sample_offset / 2;
else
bytes = sample_offset;
@@ -523,10 +512,10 @@ static int load_module(void)
for (i = 0; i < ARRAY_LEN(alaw_silence); i++)
alaw_silence[i] = AST_LIN2A(0);
- ast_format_set(&pcm_f.format, AST_FORMAT_ULAW, 0);
- ast_format_set(&alaw_f.format, AST_FORMAT_ALAW, 0);
- ast_format_set(&au_f.format, AST_FORMAT_ULAW, 0);
- ast_format_set(&g722_f.format, AST_FORMAT_G722, 0);
+ pcm_f.format = ast_format_ulaw;
+ alaw_f.format = ast_format_alaw;
+ au_f.format = ast_format_ulaw;
+ g722_f.format = ast_format_g722;
if ( ast_format_def_register(&pcm_f)
|| ast_format_def_register(&alaw_f)
|| ast_format_def_register(&au_f)
diff --git a/formats/format_siren14.c b/formats/format_siren14.c
index 77a9fe3ef..b7e2de1ec 100644
--- a/formats/format_siren14.c
+++ b/formats/format_siren14.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 120 /* 20 milliseconds == 120 bytes, 640 samples */
#define SAMPLES_TO_BYTES(x) ((typeof(x)) x / ((float) 640 / 120))
@@ -44,9 +45,6 @@ static struct ast_frame *siren14read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_SIREN14, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
if (res)
@@ -61,14 +59,6 @@ static int siren14write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_SIREN14) {
- ast_log(LOG_WARNING, "Asked to write non-Siren14 frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -148,7 +138,7 @@ static struct ast_format_def siren14_f = {
static int load_module(void)
{
- ast_format_set(&siren14_f.format, AST_FORMAT_SIREN14, 0);
+ siren14_f.format = ast_format_siren14;
if (ast_format_def_register(&siren14_f))
return AST_MODULE_LOAD_DECLINE;
diff --git a/formats/format_siren7.c b/formats/format_siren7.c
index 35e2a3460..0b3c75d9c 100644
--- a/formats/format_siren7.c
+++ b/formats/format_siren7.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 80 /* 20 milliseconds == 80 bytes, 320 samples */
#define SAMPLES_TO_BYTES(x) x / (320 / 80)
@@ -44,9 +45,6 @@ static struct ast_frame *siren7read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_SIREN7, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
if (res)
@@ -61,14 +59,6 @@ static int siren7write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_SIREN7) {
- ast_log(LOG_WARNING, "Asked to write non-Siren7 frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -148,7 +138,7 @@ static struct ast_format_def siren7_f = {
static int load_module(void)
{
- ast_format_set(&siren7_f.format, AST_FORMAT_SIREN7, 0);
+ siren7_f.format = ast_format_siren7;
if (ast_format_def_register(&siren7_f))
return AST_MODULE_LOAD_DECLINE;
diff --git a/formats/format_sln.c b/formats/format_sln.c
index 30a1ebe31..a3230637c 100644
--- a/formats/format_sln.c
+++ b/formats/format_sln.c
@@ -32,15 +32,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
-static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size, enum ast_format_id id)
+static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size)
{
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, id, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, buf_size);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
if (res)
@@ -52,17 +50,9 @@ static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, u
return &s->fr;
}
-static int generic_write(struct ast_filestream *fs, struct ast_frame *f, enum ast_format_id id)
+static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != id) {
- ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -127,8 +117,7 @@ static off_t slinear_tell(struct ast_filestream *fs)
return ftello(fs->f) / 2;
}
-static int slinear_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR);}
-static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 320, AST_FORMAT_SLINEAR);}
+static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 320);}
static struct ast_format_def slin_f = {
.name = "sln",
.exts = "sln|raw",
@@ -140,12 +129,11 @@ static struct ast_format_def slin_f = {
.buf_size = 320 + AST_FRIENDLY_OFFSET,
};
-static int slinear12_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR12);}
-static struct ast_frame *slinear12_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 480, AST_FORMAT_SLINEAR12);}
+static struct ast_frame *slinear12_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 480);}
static struct ast_format_def slin12_f = {
.name = "sln12",
.exts = "sln12",
- .write = slinear12_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -153,12 +141,11 @@ static struct ast_format_def slin12_f = {
.buf_size = 480 + AST_FRIENDLY_OFFSET,
};
-static int slinear16_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR16);}
-static struct ast_frame *slinear16_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 640, AST_FORMAT_SLINEAR16);}
+static struct ast_frame *slinear16_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 640);}
static struct ast_format_def slin16_f = {
.name = "sln16",
.exts = "sln16",
- .write = slinear16_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -166,12 +153,11 @@ static struct ast_format_def slin16_f = {
.buf_size = 640 + AST_FRIENDLY_OFFSET,
};
-static int slinear24_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR24);}
-static struct ast_frame *slinear24_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 960, AST_FORMAT_SLINEAR24);}
+static struct ast_frame *slinear24_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 960);}
static struct ast_format_def slin24_f = {
.name = "sln24",
.exts = "sln24",
- .write = slinear24_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -179,12 +165,11 @@ static struct ast_format_def slin24_f = {
.buf_size = 960 + AST_FRIENDLY_OFFSET,
};
-static int slinear32_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR32);}
-static struct ast_frame *slinear32_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1280, AST_FORMAT_SLINEAR32);}
+static struct ast_frame *slinear32_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1280);}
static struct ast_format_def slin32_f = {
.name = "sln32",
.exts = "sln32",
- .write = slinear32_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -192,12 +177,11 @@ static struct ast_format_def slin32_f = {
.buf_size = 1280 + AST_FRIENDLY_OFFSET,
};
-static int slinear44_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR44);}
-static struct ast_frame *slinear44_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1764, AST_FORMAT_SLINEAR44);}
+static struct ast_frame *slinear44_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1764);}
static struct ast_format_def slin44_f = {
.name = "sln44",
.exts = "sln44",
- .write = slinear44_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -205,12 +189,11 @@ static struct ast_format_def slin44_f = {
.buf_size = 1764 + AST_FRIENDLY_OFFSET,
};
-static int slinear48_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR48);}
-static struct ast_frame *slinear48_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1920, AST_FORMAT_SLINEAR48);}
+static struct ast_frame *slinear48_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1920);}
static struct ast_format_def slin48_f = {
.name = "sln48",
.exts = "sln48",
- .write = slinear48_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -218,12 +201,11 @@ static struct ast_format_def slin48_f = {
.buf_size = 1920 + AST_FRIENDLY_OFFSET,
};
-static int slinear96_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR96);}
-static struct ast_frame *slinear96_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 3840, AST_FORMAT_SLINEAR96);}
+static struct ast_frame *slinear96_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 3840);}
static struct ast_format_def slin96_f = {
.name = "sln96",
.exts = "sln96",
- .write = slinear96_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -231,12 +213,11 @@ static struct ast_format_def slin96_f = {
.buf_size = 3840 + AST_FRIENDLY_OFFSET,
};
-static int slinear192_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR192);}
-static struct ast_frame *slinear192_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 7680, AST_FORMAT_SLINEAR192);}
+static struct ast_frame *slinear192_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 7680);}
static struct ast_format_def slin192_f = {
.name = "sln192",
.exts = "sln192",
- .write = slinear192_write,
+ .write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
@@ -259,15 +240,16 @@ static struct ast_format_def *slin_list[] = {
static int load_module(void)
{
int i;
- ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&slin12_f.format, AST_FORMAT_SLINEAR12, 0);
- ast_format_set(&slin16_f.format, AST_FORMAT_SLINEAR16, 0);
- ast_format_set(&slin24_f.format, AST_FORMAT_SLINEAR24, 0);
- ast_format_set(&slin32_f.format, AST_FORMAT_SLINEAR32, 0);
- ast_format_set(&slin44_f.format, AST_FORMAT_SLINEAR44, 0);
- ast_format_set(&slin48_f.format, AST_FORMAT_SLINEAR48, 0);
- ast_format_set(&slin96_f.format, AST_FORMAT_SLINEAR96, 0);
- ast_format_set(&slin192_f.format, AST_FORMAT_SLINEAR192, 0);
+
+ slin_f.format = ast_format_slin;
+ slin12_f.format = ast_format_slin12;
+ slin16_f.format = ast_format_slin16;
+ slin24_f.format = ast_format_slin24;
+ slin32_f.format = ast_format_slin32;
+ slin44_f.format = ast_format_slin44;
+ slin48_f.format = ast_format_slin48;
+ slin96_f.format = ast_format_slin96;
+ slin192_f.format = ast_format_slin192;
for (i = 0; i < ARRAY_LEN(slin_list); i++) {
if (ast_format_def_register(slin_list[i])) {
diff --git a/formats/format_vox.c b/formats/format_vox.c
index f640021d8..7beec5e6a 100644
--- a/formats/format_vox.c
+++ b/formats/format_vox.c
@@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#define BUF_SIZE 80 /* 80 bytes, 160 samples */
#define VOX_SAMPLES 160
@@ -44,9 +45,6 @@ static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
int res;
/* Send a frame from the file to the appropriate channel */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_ADPCM, 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
if (res)
@@ -61,14 +59,6 @@ static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
static int vox_write(struct ast_filestream *s, struct ast_frame *f)
{
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_ADPCM) {
- ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
@@ -147,7 +137,7 @@ static struct ast_format_def vox_f = {
static int load_module(void)
{
- ast_format_set(&vox_f.format, AST_FORMAT_ADPCM, 0);
+ vox_f.format = ast_format_adpcm;
if (ast_format_def_register(&vox_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/formats/format_wav.c b/formats/format_wav.c
index 06d6ae12d..fb810625f 100644
--- a/formats/format_wav.c
+++ b/formats/format_wav.c
@@ -35,6 +35,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format.h"
+#include "asterisk/codec.h"
/* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
@@ -319,7 +322,7 @@ static int wav_open(struct ast_filestream *s)
if we did, it would go here. We also might want to check
and be sure it's a valid file. */
struct wav_desc *tmp = (struct wav_desc *)s->_private;
- if ((tmp->maxlen = check_header(s->f, (s->fmt->format.id == AST_FORMAT_SLINEAR16 ? 16000 : 8000))) < 0)
+ if ((tmp->maxlen = check_header(s->f, ast_format_get_sample_rate(s->fmt->format))) < 0)
return -1;
return 0;
}
@@ -331,7 +334,7 @@ static int wav_rewrite(struct ast_filestream *s, const char *comment)
and be sure it's a valid file. */
struct wav_desc *tmp = (struct wav_desc *)s->_private;
- tmp->hz = (s->fmt->format.id == AST_FORMAT_SLINEAR16 ? 16000 : 8000);
+ tmp->hz = ast_format_get_sample_rate(s->fmt->format);
if (write_header(s->f,tmp->hz))
return -1;
return 0;
@@ -379,9 +382,6 @@ static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
if (bytes < 0)
bytes = 0;
/* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, (fs->hz == 16000 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR), 0);
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) {
@@ -412,18 +412,6 @@ static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
struct wav_desc *s = (struct wav_desc *)fs->_private;
int res;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if ((f->subclass.format.id != AST_FORMAT_SLINEAR) && (f->subclass.format.id != AST_FORMAT_SLINEAR16)) {
- ast_log(LOG_WARNING, "Asked to write non-SLINEAR%s frame (%s)!\n", s->hz == 16000 ? "16" : "", ast_getformatname(&f->subclass.format));
- return -1;
- }
- if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_log(LOG_WARNING, "Can't change SLINEAR frequency during write\n");
- return -1;
- }
if (!f->datalen)
return -1;
@@ -547,8 +535,8 @@ static struct ast_format_def wav_f = {
static int load_module(void)
{
- ast_format_set(&wav_f.format, AST_FORMAT_SLINEAR, 0);
- ast_format_set(&wav16_f.format, AST_FORMAT_SLINEAR16, 0);
+ wav_f.format = ast_format_slin;
+ wav16_f.format = ast_format_slin16;
if (ast_format_def_register(&wav_f)
|| ast_format_def_register(&wav16_f))
return AST_MODULE_LOAD_FAILURE;
diff --git a/formats/format_wav_gsm.c b/formats/format_wav_gsm.c
index c8d83ff4c..bbb1977a9 100644
--- a/formats/format_wav_gsm.c
+++ b/formats/format_wav_gsm.c
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/format_cache.h"
#include "msgsm.h"
@@ -409,11 +410,7 @@ static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
/* Send a frame from the file to the appropriate channel */
struct wavg_desc *fs = (struct wavg_desc *)s->_private;
- s->fr.frametype = AST_FRAME_VOICE;
- ast_format_set(&s->fr.subclass.format, AST_FORMAT_GSM, 0);
- s->fr.offset = AST_FRIENDLY_OFFSET;
s->fr.samples = GSM_SAMPLES;
- s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, GSM_FRAME_SIZE);
if (fs->secondhalf) {
/* Just return a frame based on the second GSM frame */
@@ -443,14 +440,6 @@ static int wav_write(struct ast_filestream *s, struct ast_frame *f)
int size;
struct wavg_desc *fs = (struct wavg_desc *)s->_private;
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
- return -1;
- }
- if (f->subclass.format.id != AST_FORMAT_GSM) {
- ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(&f->subclass.format));
- return -1;
- }
/* XXX this might fail... if the input is a multiple of MSGSM_FRAME_SIZE
* we assume it is already in the correct format.
*/
@@ -577,7 +566,7 @@ static struct ast_format_def wav49_f = {
static int load_module(void)
{
- ast_format_set(&wav49_f.format, AST_FORMAT_GSM, 0);
+ wav49_f.format = ast_format_gsm;
if (ast_format_def_register(&wav49_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
diff --git a/funcs/func_channel.c b/funcs/func_channel.c
index 82fb4c348..3f756f0b5 100644
--- a/funcs/func_channel.c
+++ b/funcs/func_channel.c
@@ -427,23 +427,27 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
}
if (!strcasecmp(data, "audionativeformat")) {
- char tmp[512];
+ tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmpcap) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
- if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
- ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
- tmpcap = ast_format_cap_destroy(tmpcap);
+ ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
+ ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
+ ao2_ref(tmpcap, -1);
}
} else if (!strcasecmp(data, "videonativeformat")) {
- char tmp[512];
+ tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmpcap) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
- if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
- ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
- tmpcap = ast_format_cap_destroy(tmpcap);
+ ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
+ ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
+ ao2_ref(tmpcap, -1);
}
} else if (!strcasecmp(data, "audioreadformat")) {
- ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
+ ast_copy_string(buf, ast_format_get_name(ast_channel_readformat(chan)), len);
} else if (!strcasecmp(data, "audiowriteformat")) {
- ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
+ ast_copy_string(buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
#ifdef CHANNEL_TRACE
} else if (!strcasecmp(data, "trace")) {
ast_channel_lock(chan);
diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c
index ecebde4df..681a96924 100644
--- a/funcs/func_frame_trace.c
+++ b/funcs/func_frame_trace.c
@@ -219,14 +219,14 @@ static void print_frame(struct ast_frame *frame)
break;
case AST_FRAME_VOICE:
ast_verbose("FrameType: VOICE\n");
- ast_verbose("Codec: %s\n", ast_getformatname(&frame->subclass.format));
+ ast_verbose("Codec: %s\n", ast_format_get_name(frame->subclass.format));
ast_verbose("MS: %ld\n", frame->len);
ast_verbose("Samples: %d\n", frame->samples);
ast_verbose("Bytes: %d\n", frame->datalen);
break;
case AST_FRAME_VIDEO:
ast_verbose("FrameType: VIDEO\n");
- ast_verbose("Codec: %s\n", ast_getformatname(&frame->subclass.format));
+ ast_verbose("Codec: %s\n", ast_format_get_name(frame->subclass.format));
ast_verbose("MS: %ld\n", frame->len);
ast_verbose("Samples: %d\n", frame->samples);
ast_verbose("Bytes: %d\n", frame->datalen);
diff --git a/funcs/func_pitchshift.c b/funcs/func_pitchshift.c
index e5091d95d..0aaa2b602 100644
--- a/funcs/func_pitchshift.c
+++ b/funcs/func_pitchshift.c
@@ -172,9 +172,7 @@ static int pitchshift_cb(struct ast_audiohook *audiohook, struct ast_channel *ch
if (!f) {
return 0;
}
- if ((audiohook->status == AST_AUDIOHOOK_STATUS_DONE) ||
- (f->frametype != AST_FRAME_VOICE) ||
- !(ast_format_is_slinear(&f->subclass.format))) {
+ if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
return -1;
}
@@ -489,7 +487,7 @@ static int pitch_shift(struct ast_frame *f, float amount, struct fft_data *fft)
return 0;
}
for (samples = 0; samples < f->samples; samples += 32) {
- smb_pitch_shift(amount, 32, MAX_FRAME_LENGTH, 32, ast_format_rate(&f->subclass.format), fun+samples, fun+samples, fft);
+ smb_pitch_shift(amount, 32, MAX_FRAME_LENGTH, 32, ast_format_get_sample_rate(f->subclass.format), fun+samples, fun+samples, fft);
}
return 0;
diff --git a/funcs/func_speex.c b/funcs/func_speex.c
index 4e3c13b87..d0d451bd1 100644
--- a/funcs/func_speex.c
+++ b/funcs/func_speex.c
@@ -165,8 +165,8 @@ static int speex_callback(struct ast_audiohook *audiohook, struct ast_channel *c
return -1;
}
- if ((sdi->samples != frame->samples) || (ast_format_rate(&frame->subclass.format) != si->lastrate)) {
- si->lastrate = ast_format_rate(&frame->subclass.format);
+ if ((sdi->samples != frame->samples) || (ast_format_get_sample_rate(frame->subclass.format) != si->lastrate)) {
+ si->lastrate = ast_format_get_sample_rate(frame->subclass.format);
if (sdi->state) {
speex_preprocess_state_destroy(sdi->state);
}
diff --git a/funcs/func_talkdetect.c b/funcs/func_talkdetect.c
index c4783f51f..f127fa3d7 100644
--- a/funcs/func_talkdetect.c
+++ b/funcs/func_talkdetect.c
@@ -284,7 +284,7 @@ static int set_talk_detect(struct ast_channel *chan, int dsp_silence_threshold,
td_params->audiohook.manipulate_callback = talk_detect_audiohook_cb;
ast_set_flag(&td_params->audiohook, AST_AUDIOHOOK_TRIGGER_READ);
- td_params->dsp = ast_dsp_new_with_rate(ast_format_rate(ast_channel_rawreadformat(chan)));
+ td_params->dsp = ast_dsp_new_with_rate(ast_format_get_sample_rate(ast_channel_rawreadformat(chan)));
if (!td_params->dsp) {
ast_datastore_free(datastore);
ast_free(td_params);
diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h
index 67d17382b..01a8352fc 100644
--- a/include/asterisk/_private.h
+++ b/include/asterisk/_private.h
@@ -121,16 +121,6 @@ int ast_xmldoc_load_documentation(void);
*/
int ast_plc_reload(void);
-/*!
- * \brief Init the ast_format attribute interface register container.
- */
-int ast_format_attr_init(void);
-
-/*!
- * \brief Init the Asterisk global format list after all format attribute modules have been loaded
- */
-int ast_format_list_init(void);
-
/*! \brief initializes the rtp engine arrays */
int ast_rtp_engine_init(void);
diff --git a/include/asterisk/abstract_jb.h b/include/asterisk/abstract_jb.h
index 6a4d0610d..8a5e3d27f 100644
--- a/include/asterisk/abstract_jb.h
+++ b/include/asterisk/abstract_jb.h
@@ -145,7 +145,7 @@ struct ast_jb
/*! \brief The time the next frame should be played. */
long next;
/*! \brief Voice format of the last frame in. */
- struct ast_format last_format;
+ struct ast_format *last_format;
/*! \brief File for frame timestamp tracing. */
FILE *logfile;
/*! \brief Jitterbuffer internal state flags. */
diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h
index 6b0716092..375b2dd9d 100644
--- a/include/asterisk/audiohook.h
+++ b/include/asterisk/audiohook.h
@@ -109,7 +109,7 @@ struct ast_audiohook {
struct ast_slinfactory write_factory; /*!< Factory where frames written to the channel will go through */
struct timeval read_time; /*!< Last time read factory was fed */
struct timeval write_time; /*!< Last time write factory was fed */
- struct ast_format format; /*!< Format translation path is setup as */
+ struct ast_format *format; /*!< Format translation path is setup as */
struct ast_trans_pvt *trans_pvt; /*!< Translation path for reading frames */
ast_audiohook_manipulate_callback manipulate_callback; /*!< Manipulation callback */
struct ast_audiohook_options options; /*!< Applicable options */
diff --git a/include/asterisk/bridge_channel.h b/include/asterisk/bridge_channel.h
index ae8369d15..387c048f8 100644
--- a/include/asterisk/bridge_channel.h
+++ b/include/asterisk/bridge_channel.h
@@ -133,9 +133,9 @@ struct ast_bridge_channel {
* optimizing based upon talk detection. */
struct ast_bridge_tech_optimizations tech_args;
/*! Copy of read format used by chan before join */
- struct ast_format read_format;
+ struct ast_format *read_format;
/*! Copy of write format used by chan before join */
- struct ast_format write_format;
+ struct ast_format *write_format;
/*! Call ID associated with bridge channel */
struct ast_callid *callid;
/*! A clone of the roles living on chan when the bridge channel joins the bridge. This may require some opacification */
diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h
index 4f32dbf66..f7d7719d2 100644
--- a/include/asterisk/callerid.h
+++ b/include/asterisk/callerid.h
@@ -75,8 +75,8 @@
/*! MWI MDMF format -- generate name, callerid, date and MWI fields */
#define CID_MWI_TYPE_MDMF_FULL 0x02
-#define AST_LIN2X(a) ((codec->id == AST_FORMAT_ALAW) ? (AST_LIN2A(a)) : (AST_LIN2MU(a)))
-#define AST_XLAW(a) ((codec->id == AST_FORMAT_ALAW) ? (AST_ALAW(a)) : (AST_MULAW(a)))
+#define AST_LIN2X(a) ((ast_format_cmp(codec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ? (AST_LIN2A(a)) : (AST_LIN2MU(a)))
+#define AST_XLAW(a) ((ast_format_cmp(codec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) ? (AST_ALAW(a)) : (AST_MULAW(a)))
struct callerid_state;
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index dec19cba0..d118bc81f 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1883,14 +1883,6 @@ int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format);
/*!
- * \brief Sets read format on channel chan by id
- * \param chan channel to change
- * \param id format id to set for reading, only used for formats without attributes
- * \return Returns 0 on success, -1 on failure
- */
-int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id);
-
-/*!
* \brief Sets write format on channel chan
* Set write format for channel to whichever component of "format" is best.
* \param chan channel to change
@@ -1908,14 +1900,6 @@ int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_ca
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format);
/*!
- * \brief Sets write format on channel chan
- * \param chan channel to change
- * \param id format id to set for writing, only used for formats without attributes
- * \return Returns 0 on success, -1 on failure
- */
-int ast_set_write_format_by_id(struct ast_channel *chan, enum ast_format_id id);
-
-/*!
* \brief Sends text to a channel
*
* \param chan channel to act upon
@@ -2103,17 +2087,6 @@ char *ast_transfercapability2str(int transfercapability) attribute_const;
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block);
/*!
- * \brief Pick the best codec
- *
- * \param cap capabilities to pick best codec out of
- * \param result stucture to store the best codec in.
- * \retval on success, pointer to result structure
- * \retval on failure, NULL
- */
-struct ast_format *ast_best_codec(struct ast_format_cap *cap, struct ast_format *result);
-
-
-/*!
* \brief Checks the value of an option
*
* Query the value of an option
@@ -4008,6 +3981,13 @@ struct ast_format *ast_channel_rawwriteformat(struct ast_channel *chan);
struct ast_format *ast_channel_readformat(struct ast_channel *chan);
struct ast_format *ast_channel_writeformat(struct ast_channel *chan);
+/* Format setters - all of these functions will increment the reference count of the format passed in */
+void ast_channel_set_oldwriteformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format);
+void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format);
+
/* Other struct getters */
struct ast_frame *ast_channel_dtmff(struct ast_channel *chan);
struct ast_jb *ast_channel_jb(struct ast_channel *chan);
diff --git a/include/asterisk/codec.h b/include/asterisk/codec.h
new file mode 100644
index 000000000..28befec50
--- /dev/null
+++ b/include/asterisk/codec.h
@@ -0,0 +1,186 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Codec API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _AST_CODEC_H_
+#define _AST_CODEC_H_
+
+/*! \brief Types of media */
+enum ast_media_type {
+ AST_MEDIA_TYPE_UNKNOWN = 0,
+ AST_MEDIA_TYPE_AUDIO,
+ AST_MEDIA_TYPE_VIDEO,
+ AST_MEDIA_TYPE_IMAGE,
+ AST_MEDIA_TYPE_TEXT,
+};
+
+struct ast_module;
+
+/*! \brief Represents a media codec within Asterisk. */
+struct ast_codec {
+ /*! \brief Internal unique identifier for this codec, set at registration time (starts at 1) */
+ unsigned int id;
+ /*! \brief Name for this codec */
+ const char *name;
+ /*! \brief Brief description */
+ const char *description;
+ /*! \brief Type of media this codec contains */
+ enum ast_media_type type;
+ /*! \brief Sample rate (number of samples carried in a second) */
+ unsigned int sample_rate;
+ /*! \brief Minimum length of media that can be carried (in milliseconds) in a frame */
+ unsigned int minimum_ms;
+ /*! \brief Maximum length of media that can be carried (in milliseconds) in a frame */
+ unsigned int maximum_ms;
+ /*! \brief Default length of media carried (in milliseconds) in a frame */
+ unsigned int default_ms;
+ /*! \brief Length in bytes of the data payload of a minimum_ms frame */
+ unsigned int minimum_bytes;
+ /*!
+ * \brief Retrieve the number of samples in a frame
+ *
+ * \param frame The frame to examine
+ *
+ * \return the number of samples
+ */
+ int (*samples_count)(struct ast_frame *frame);
+ /*!
+ * \brief Retrieve the length of media from number of samples
+ *
+ * \param samples The number of samples
+ *
+ * \return The length of media in milliseconds
+ */
+ int (*get_length)(unsigned int samples);
+ /*! \brief Whether the media can be smoothed or not */
+ unsigned int smooth;
+ /*! \brief The module that registered this codec */
+ struct ast_module *mod;
+};
+
+/*!
+ * \brief Initialize codec support within the core.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_codec_init(void);
+
+/*!
+ * \brief Initialize built-in codecs within the core.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_codec_builtin_init(void);
+
+/*!
+ * \brief This function is used to register a codec with the Asterisk core. Registering
+ * allows it to be passed through in frames and configured in channel drivers.
+ *
+ * \param codec to register
+ * \param mod the module this codec is provided by
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod);
+
+/*!
+ * \brief This function is used to register a codec with the Asterisk core. Registering
+ * allows it to be passed through in frames and configured in channel drivers.
+ *
+ * \param codec to register
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+#define ast_codec_register(codec) __ast_codec_register(codec, ast_module_info->self)
+
+/*!
+ * \brief Retrieve a codec given a name, type, and sample rate
+ *
+ * \param name The name of the codec
+ * \param type The type of the codec
+ * \param sample_rate Optional sample rate, may not be applicable for some types
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The returned codec is reference counted and ao2_ref or ao2_cleanup
+ * must be used to release the reference.
+ */
+struct ast_codec *ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate);
+
+/*!
+ * \brief Retrieve a codec given the unique identifier
+ *
+ * \param id The unique identifier
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note Identifiers start at 1 so if iterating don't start at 0.
+ *
+ * \note The returned codec is reference counted and ao2_ref or ao2_cleanup
+ * must be used to release the reference.
+ */
+struct ast_codec *ast_codec_get_by_id(int id);
+
+/*!
+ * \brief Retrieve the current maximum identifier for codec iteration
+ *
+ * \return Maximum codec identifier
+ */
+int ast_codec_get_max(void);
+
+/*!
+ * \brief Conversion function to take a media type and turn it into a string
+ *
+ * \param type The media type
+ *
+ * \retval string representation of the media type
+ */
+const char *ast_codec_media_type2str(enum ast_media_type type);
+
+/*!
+ * \brief Get the number of samples contained within a frame
+ *
+ * \param frame The frame itself
+ *
+ * \retval number of samples in the frame
+ */
+unsigned int ast_codec_samples_count(struct ast_frame *frame);
+
+/*!
+ * \brief Get the length of media (in milliseconds) given a number of samples
+ *
+ * \param codec The codec itself
+ * \param samples The number of samples
+ *
+ * \retval length of media (in milliseconds)
+ */
+unsigned int ast_codec_determine_length(const struct ast_codec *codec, unsigned int samples);
+
+#endif /* _AST_CODEC_H */
diff --git a/include/asterisk/config_options.h b/include/asterisk/config_options.h
index 11a8c5bf9..30c042176 100644
--- a/include/asterisk/config_options.h
+++ b/include/asterisk/config_options.h
@@ -317,21 +317,20 @@ enum aco_option_type {
*/
OPT_CHAR_ARRAY_T,
- /*! \brief Type for default option handler for codec preferences/capabilities
+ /*! \brief Type for default option handler for format capabilities
* \note aco_option_register flags:
* non-zero : This is an "allow" style option
* 0 : This is a "disallow" style option
* aco_option_register varargs:
- * FLDSET macro with fields representing a struct ast_codec_pref and a struct ast_format_cap *
+ * FLDSET macro with field representing a struct ast_format_cap *
*
* Example:
* {code}
* struct test_item {
- * struct ast_codec_pref pref;
* struct ast_format cap *cap;
* };
- * aco_option_register(&cfg_info, "allow", ACO_EXACT, my_types, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct test_item, pref, cap));
- * aco_option_register(&cfg_info, "disallow", ACO_EXACT, my_types, "all", OPT_CODEC_T, 0, FLDSET(struct test_item, pref, cap));
+ * aco_option_register(&cfg_info, "allow", ACO_EXACT, my_types, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct test_item, cap));
+ * aco_option_register(&cfg_info, "disallow", ACO_EXACT, my_types, "all", OPT_CODEC_T, 0, FLDSET(struct test_item, cap));
* {endcode}
*/
OPT_CODEC_T,
diff --git a/include/asterisk/data.h b/include/asterisk/data.h
index e3253377e..3676b8df5 100644
--- a/include/asterisk/data.h
+++ b/include/asterisk/data.h
@@ -26,6 +26,7 @@
#define ASTERISK_DATA_H
#include "asterisk/frame.h"
+#include "asterisk/format_cap.h"
/*!
* \page AstDataRetrieval The Asterisk DATA retrieval API.
diff --git a/include/asterisk/file.h b/include/asterisk/file.h
index 372c0f7ed..3d8d2c97c 100644
--- a/include/asterisk/file.h
+++ b/include/asterisk/file.h
@@ -385,7 +385,7 @@ char *ast_format_str_reduce(char *fmts);
* \retval NULL if not found
* \retval A pointer to the ast_format associated with this file extension
*/
-const struct ast_format *ast_get_format_for_file_ext(const char *file_ext);
+struct ast_format *ast_get_format_for_file_ext(const char *file_ext);
#if defined(__cplusplus) || defined(c_plusplus)
}
diff --git a/include/asterisk/format.h b/include/asterisk/format.h
index 885c62b2d..32f9f2b40 100644
--- a/include/asterisk/format.h
+++ b/include/asterisk/format.h
@@ -1,9 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -18,464 +18,354 @@
/*!
* \file
- * \brief Format API
+ * \brief Media Format API
*
- * \author David Vossel <dvossel@digium.com>
+ * \author Joshua Colp <jcolp@digium.com>
*/
+#include "asterisk/codec.h"
+
#ifndef _AST_FORMAT_H_
#define _AST_FORMAT_H_
-#include "asterisk/astobj2.h"
-#include "asterisk/silk.h"
-#include "asterisk/celt.h"
-#include "asterisk/opus.h"
-#define AST_FORMAT_ATTR_SIZE 64
-#define AST_FORMAT_INC 100000
-
-/*! This is the value that ends a var list of format attribute
- * key value pairs. */
-#define AST_FORMAT_ATTR_END -1
-
-/* \brief Format Categories*/
-enum ast_format_type {
- AST_FORMAT_TYPE_AUDIO = 1 * AST_FORMAT_INC,
- AST_FORMAT_TYPE_VIDEO = 2 * AST_FORMAT_INC,
- AST_FORMAT_TYPE_IMAGE = 3 * AST_FORMAT_INC,
- AST_FORMAT_TYPE_TEXT = 4 * AST_FORMAT_INC,
-};
-
-enum ast_format_id {
- /*! G.723.1 compression */
- AST_FORMAT_G723_1 = 1 + AST_FORMAT_TYPE_AUDIO,
- /*! GSM compression */
- AST_FORMAT_GSM = 2 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw mu-law data (G.711) */
- AST_FORMAT_ULAW = 3 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw A-law data (G.711) */
- AST_FORMAT_ALAW = 4 + AST_FORMAT_TYPE_AUDIO,
- /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
- AST_FORMAT_G726_AAL2 = 5 + AST_FORMAT_TYPE_AUDIO,
- /*! ADPCM (IMA) */
- AST_FORMAT_ADPCM = 6 + AST_FORMAT_TYPE_AUDIO,
- /*! LPC10, 180 samples/frame */
- AST_FORMAT_LPC10 = 7 + AST_FORMAT_TYPE_AUDIO,
- /*! G.729A audio */
- AST_FORMAT_G729A = 8 + AST_FORMAT_TYPE_AUDIO,
- /*! SpeeX Free Compression */
- AST_FORMAT_SPEEX = 9 + AST_FORMAT_TYPE_AUDIO,
- /*! iLBC Free Compression */
- AST_FORMAT_ILBC = 10 + AST_FORMAT_TYPE_AUDIO,
- /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
- AST_FORMAT_G726 = 11 + AST_FORMAT_TYPE_AUDIO,
- /*! G.722 */
- AST_FORMAT_G722 = 12 + AST_FORMAT_TYPE_AUDIO,
- /*! G.722.1 (also known as Siren7, 32kbps assumed) */
- AST_FORMAT_SIREN7 = 13 + AST_FORMAT_TYPE_AUDIO,
- /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
- AST_FORMAT_SIREN14 = 14 + AST_FORMAT_TYPE_AUDIO,
- /*! G.719 (64 kbps assumed) */
- AST_FORMAT_G719 = 15 + AST_FORMAT_TYPE_AUDIO,
- /*! SpeeX Wideband (16kHz) Free Compression */
- AST_FORMAT_SPEEX16 = 16 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw mu-law data (G.711) */
- AST_FORMAT_TESTLAW = 17 + AST_FORMAT_TYPE_AUDIO,
- /*! SILK format */
- AST_FORMAT_SILK = 18 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
- AST_FORMAT_SLINEAR = 19 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (12000 Hz) PCM */
- AST_FORMAT_SLINEAR12 = 20 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
- AST_FORMAT_SLINEAR16 = 21 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (24000 Hz) PCM */
- AST_FORMAT_SLINEAR24 = 22 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (32000 Hz) PCM */
- AST_FORMAT_SLINEAR32 = 23 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (44100 Hz) PCM just because we can. */
- AST_FORMAT_SLINEAR44 = 24 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (48000 Hz) PCM */
- AST_FORMAT_SLINEAR48 = 25 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (96000 Hz) PCM */
- AST_FORMAT_SLINEAR96 = 26 + AST_FORMAT_TYPE_AUDIO,
- /*! Raw 16-bit Signed Linear (192000 Hz) PCM. maybe we're taking this too far. */
- AST_FORMAT_SLINEAR192 = 27 + AST_FORMAT_TYPE_AUDIO,
- AST_FORMAT_SPEEX32 = 28 + AST_FORMAT_TYPE_AUDIO,
- AST_FORMAT_CELT = 29 + AST_FORMAT_TYPE_AUDIO,
- /*! Opus */
- AST_FORMAT_OPUS = 30 + AST_FORMAT_TYPE_AUDIO,
-
- /*! H.261 Video */
- AST_FORMAT_H261 = 1 + AST_FORMAT_TYPE_VIDEO,
- /*! H.263 Video */
- AST_FORMAT_H263 = 2 + AST_FORMAT_TYPE_VIDEO,
- /*! H.263+ Video */
- AST_FORMAT_H263_PLUS = 3 + AST_FORMAT_TYPE_VIDEO,
- /*! H.264 Video */
- AST_FORMAT_H264 = 4 + AST_FORMAT_TYPE_VIDEO,
- /*! MPEG4 Video */
- AST_FORMAT_MP4_VIDEO = 5 + AST_FORMAT_TYPE_VIDEO,
- /*! VP8 */
- AST_FORMAT_VP8 = 6 + AST_FORMAT_TYPE_VIDEO,
-
- /*! JPEG Images */
- AST_FORMAT_JPEG = 1 + AST_FORMAT_TYPE_IMAGE,
- /*! PNG Images */
- AST_FORMAT_PNG = 2 + AST_FORMAT_TYPE_IMAGE,
-
- /*! T.140 RED Text format RFC 4103 */
- AST_FORMAT_T140RED = 1 + AST_FORMAT_TYPE_TEXT,
- /*! T.140 Text format - ITU T.140, RFC 4103 */
- AST_FORMAT_T140 = 2 + AST_FORMAT_TYPE_TEXT,
-};
-
-/*! Determine what type of media a ast_format_id is. */
-#define AST_FORMAT_GET_TYPE(id) (((int) (id / AST_FORMAT_INC)) * AST_FORMAT_INC)
-
-
-/*! \brief This structure contains the buffer used for format attributes */
-struct ast_format_attr {
- /*! The buffer formats can use to represent attributes */
- uint32_t format_attr[AST_FORMAT_ATTR_SIZE];
- /*! If a format's payload needs to pass through that a new marker is required
- * for RTP, this variable will be set. */
- uint8_t rtp_marker_bit;
-};
-
-/*! \brief Represents a media format within Asterisk. */
-struct ast_format {
- /*! The unique id representing this format from all the other formats. */
- enum ast_format_id id;
- /*! Attribute structure used to associate attributes with a format. */
- struct ast_format_attr fattr;
-};
+struct ast_format;
+/*! \brief Format comparison results */
enum ast_format_cmp_res {
- /*! structure 1 is identical to structure 2. */
+ /*! Both formats are equivalent to eachother */
AST_FORMAT_CMP_EQUAL = 0,
- /*! structure 1 contains elements not in structure 2. */
+ /*! Both formats are completely different and not the same in any way */
AST_FORMAT_CMP_NOT_EQUAL,
- /*! structure 1 is a proper subset of the elements in structure 2.*/
+ /*! Both formats are similar but not equivalent */
AST_FORMAT_CMP_SUBSET,
};
-/*! \brief Definition of supported media formats (codecs) */
-struct ast_format_list {
- struct ast_format format; /*!< The unique format. */
- char name[64]; /*!< short name */
- unsigned int samplespersecond; /*!< Number of samples per second (8000/16000) */
- char desc[128]; /*!< Description */
- int fr_len; /*!< Single frame length in bytes */
- int min_ms; /*!< Min value */
- int max_ms; /*!< Max value */
- int inc_ms; /*!< Increment */
- int def_ms; /*!< Default value */
- unsigned int flags; /*!< Smoother flags */
- int cur_ms; /*!< Current value */
- int custom_entry;
-};
-
-/*! \brief A format must register an attribute interface if it requires the use of the format attributes void pointer */
-struct ast_format_attr_interface {
- /*! format type */
- enum ast_format_id id;
-
- /*! \brief Determine if format_attr 1 is a subset of format_attr 2.
+/*! \brief Optional format interface to extend format operations */
+struct ast_format_interface {
+ /*!
+ * \brief Callback for when the format is destroyed, used to release attribute resources
*
- * \retval ast_format_cmp_res representing the result of comparing fattr1 and fattr2.
+ * \param format The format structure to destroy
*/
- enum ast_format_cmp_res (* const format_attr_cmp)(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2);
+ void (*const format_destroy)(struct ast_format *format);
- /*! \brief Get joint attributes of same format type if they exist.
+ /*!
+ * \brief Callback for when the format is cloned, used to clone attributes
+ *
+ * \param src Source format of attributes
+ * \param dst Destination format for attributes
*
- * \retval 0 if joint attributes exist
- * \retval -1 if no joint attributes are present
+ * \retval 0 success
+ * \retval -1 failure
*/
- int (* const format_attr_get_joint)(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result);
-
- /*! \brief Set format capabilities from a list of key value pairs ending with AST_FORMAT_ATTR_END.
- * \note This function does not need to call va_end of the va_list. */
- void (* const format_attr_set)(struct ast_format_attr *format_attr, va_list ap);
+ int (*const format_clone)(const struct ast_format *src, struct ast_format *dst);
/*!
- * \brief Find out if format capabilities in va_list are in format.
- * \note This function does not need to call va_end of the va_list.
+ * \brief Determine if format 1 is a subset of format 2.
*
- * \note This function is optional. In many cases the format_attr_cmp
- * function can be used to derive these results. If it is possible
- * that some format attributes have no bearing on the equality of two formats, this
- * function must exist.
+ * \param format1 First format to compare
+ * \param format2 Second format which the first is compared against
*
- * \retval 0 if all attributes exist
- * \retval -1 if any of the attributes not present
+ * \retval ast_format_cmp_res representing the result of comparing format1 and format2.
*/
- int (* const format_attr_isset)(const struct ast_format_attr *format_attr, va_list ap);
+ enum ast_format_cmp_res (* const format_cmp)(const struct ast_format *format1,
+ const struct ast_format *format2);
- /*
- * \brief Return a value for a specific format key. Return that value in the void pointer.
+ /*!
+ * \brief Get a format with the joint compatible attributes of both provided formats.
+ *
+ * \param format1 The first format
+ * \param format2 The second format
+ *
+ * \retval non-NULL if joint format
+ * \retval NULL if no joint format
*
- * \note It is not expected that all key value pairs can be returned, but those that can should
- * be documented as such.
+ * \note The returned format has its reference count incremented and must be released using
+ * ao2_ref or ao2_cleanup.
+ */
+ struct ast_format *(* const format_get_joint)(const struct ast_format *format1,
+ const struct ast_format *format2);
+
+ /*!
+ * \brief Set an attribute on a format
*
- * \note This function is optional if key value pairs are not allowed to be accessed. This
- * will result in -1 always being returned.
+ * \param name The name of the attribute
+ * \param value The value of the attribute
*
- * \retval 0 Success, value was found and copied into void pointer.
- * \retval -1 failure, Value was either not found, or not allowed to be accessed.
+ * \retval non-NULL success
+ * \retval NULL failure
*/
- int (* const format_attr_get_val)(const struct ast_format_attr *format_attr, int key, void *val);
+ struct ast_format *(* const format_attribute_set)(const struct ast_format *format,
+ const char *name, const char *value);
- /*
- * \brief Parse SDP attribute information, interpret it, and store it in ast_format_attr structure.
+ /*!
+ * \brief Parse SDP attribute information, interpret it, and store it in the format structure.
+ *
+ * \param format Format to set attributes on
+ * \param attributes A string containing only the attributes from the fmtp line
*
- * \retval 0 Success, values were valid
- * \retval -1 Failure, some values were not acceptable
+ * \retval non-NULL Success, values were valid
+ * \retval NULL Failure, some values were not acceptable
*/
- int (* const format_attr_sdp_parse)(struct ast_format_attr *format_attr, const char *attributes);
+ struct ast_format *(* const format_parse_sdp_fmtp)(const struct ast_format *format, const char *attributes);
/*!
* \brief Generate SDP attribute information from an ast_format_attr structure.
*
+ * \param format The format containing attributes
+ * \param payload The payload number to place into the fmtp line
+ * \param str The generated fmtp line
+ *
* \note This callback should generate a full fmtp line using the provided payload number.
*/
- void (* const format_attr_sdp_generate)(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str);
+ void (* const format_generate_sdp_fmtp)(const struct ast_format *format, unsigned int payload,
+ struct ast_str **str);
};
/*!
- * \brief This function is used to have a media format aware module parse and interpret
- * SDP attribute information. Once interpreted this information is stored on the format
- * itself using Asterisk format attributes.
+ * \brief Initialize media format support
*
- * \param format to set
- * \param attributes string containing the fmtp line from the SDP
- *
- * \retval 0 success, attribute values were valid
- * \retval -1 failure, values were not acceptable
+ * \retval 0 success
+ * \retval -1 failure
*/
-int ast_format_sdp_parse(struct ast_format *format, const char *attributes);
+int ast_format_init(void);
/*!
- * \brief This function is used to produce an fmtp SDP line for an Asterisk format. The
- * attributes present on the Asterisk format are translated into the SDP equivalent.
+ * \brief Create a new media format
*
- * \param format to generate an fmtp line for
- * \param payload numerical payload for the fmtp line
- * \param str structure that the fmtp line will be appended to
+ * \param codec The codec to use
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The format is returned with reference count incremented. It must be released using
+ * ao2_ref or ao2_cleanup.
*/
-void ast_format_sdp_generate(const struct ast_format *format, unsigned int payload, struct ast_str **str);
+struct ast_format *ast_format_create(struct ast_codec *codec);
/*!
- * \brief This function is used to set an ast_format object to represent a media format
- * with optional format attributes represented by format specific key value pairs.
- *
- * \param format to set
- * \param id format id to set on format
- * \param set_attributes are there attributes to set on this format. 0 == false, 1 == True.
- * \param ... var list of attribute key value pairs, must end with AST_FORMAT_ATTR_END;
+ * \brief Create a new media format with a specific name
*
- * \details Example usage.
- * ast_format_set(format, AST_FORMAT_ULAW, 0); // no capability attributes are needed for ULAW
+ * \param format_name The name to use for the format
+ * \param codec The codec to use
*
- * ast_format_set(format, AST_FORMAT_SILK, 1, // SILK has capability attributes.
- * AST_FORMAT_SILK_ATTR_RATE, 24000,
- * AST_FORMAT_SILK_ATTR_RATE, 16000,
- * AST_FORMAT_SILK_ATTR_RATE, 12000,
- * AST_FORMAT_SILK_ATTR_RATE, 8000,
- * AST_FORMAT_ATTR_END);
+ * \note This creation function should be used when the name of the \c codec
+ * cannot be explicitly used for the name of the format. This is the case for
+ * codecs with multiple sample rates
*
- * \note This function will initialize the ast_format structure.
+ * \note The format is returned with reference count incremented. It must be released using
+ * ao2_ref or ao2_cleanup.
*
- * \return Pointer to ast_format object, same pointer that is passed in
- * by the first argument.
+ * \retval non-NULL success
+ * \retval NULL failure
*/
-struct ast_format *ast_format_set(struct ast_format *format, enum ast_format_id id, int set_attributes, ... );
+struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec);
/*!
- * \brief After ast_format_set has been used on a function, this function can be used to
- * set additional format attributes to the structure.
+ * \brief Clone an existing media format so it can be modified
*
- * \param format to set
- * \param ... var list of attribute key value pairs, must end with AST_FORMAT_ATTR_END;
- *
- * \details Example usage.
- * ast_format_set(format, AST_FORMAT_SILK, 0);
- * ast_format_append(format, // SILK has capability attributes.
- * AST_FORMAT_SILK_ATTR_RATE, 24000,
- * AST_FORMAT_SILK_ATTR_RATE, 16000,
- * AST_FORMAT_SILK_ATTR_RATE, 12000,
- * AST_FORMAT_SILK_ATTR_RATE, 8000,
- * AST_FORMAT_ATTR_END);
- *
- * \return Pointer to ast_format object, same pointer that is passed in
- * by the first argument.
+ * \param format The existing media format
+ *
+ * \note The returned format is a new ao2 object. It must be released using ao2_cleanup.
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
*/
-struct ast_format *ast_format_append(struct ast_format *format, ... );
+struct ast_format *ast_format_clone(const struct ast_format *format);
/*!
- * \brief Clears the format stucture.
+ * \brief Compare two formats
+ *
+ * \retval ast_format_cmp_res representing the result of comparing format1 and format2.
*/
-void ast_format_clear(struct ast_format *format);
+enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2);
/*!
- * \brief This function is used to set an ast_format object to represent a media format
- * with optional capability attributes represented by format specific key value pairs.
+ * \brief Get a common joint capability between two formats
*
- * \details Example usage. Is this SILK format capable of 8khz
- * is_8khz = ast_format_isset(format, AST_FORMAT_SILK_CAP_RATE, 8000);
+ * \retval non-NULL if joint capability exists
+ * \retval NULL if no joint capability exists
*
- * \return 0, The format key value pairs are within the capabilities defined in this structure.
- * \return -1, The format key value pairs are _NOT_ within the capabilities of this structure.
+ * \note The returned format must be treated as immutable.
*/
-int ast_format_isset(const struct ast_format *format, ... );
+struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2);
/*!
- * \brief Get a value from a format containing attributes.
- * \note The key represents the format attribute to be retrieved, and the void pointer
- * is to the structure that value will be stored in. It must be known what structure a
- * key represents.
+ * \brief Set an attribute on a format to a specific value
*
- * \retval 0, success
- * \retval -1, failure
- */
-int ast_format_get_value(const struct ast_format *format, int key, void *value);
-
-/*!
- * \brief Compare ast_formats structures
+ * \param format The format to set the attribute on
+ * \param name Attribute name
+ * \param value Attribute value
*
- * \retval ast_format_cmp_res representing the result of comparing format1 and format2.
+ * \retval non-NULL success
+ * \retval NULL failure
*/
-enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2);
+struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name,
+ const char *value);
/*!
- * \brief Find joint format attributes of two ast_format
- * structures containing the same uid and return the intersection in the
- * result structure.
+ * \brief This function is used to have a media format aware module parse and interpret
+ * SDP attribute information. Once interpreted this information is stored on the format
+ * itself using Asterisk format attributes.
*
- * retval 0, joint attribute capabilities exist.
- * retval -1, no joint attribute capabilities exist.
+ * \param format to set
+ * \param attributes string containing the fmtp line from the SDP
+ *
+ * \retval non-NULL success, attribute values were valid
+ * \retval NULL failure, values were not acceptable
*/
-int ast_format_joint(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result);
+struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes);
/*!
- * \brief copy format src into format dst.
+ * \brief This function is used to produce an fmtp SDP line for an Asterisk format. The
+ * attributes present on the Asterisk format are translated into the SDP equivalent.
+ *
+ * \param format to generate an fmtp line for
+ * \param payload numerical payload for the fmtp line
+ * \param str structure that the fmtp line will be appended to
*/
-void ast_format_copy(struct ast_format *dst, const struct ast_format *src);
+void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str);
/*!
- * \brief Set the rtp mark value on the format to indicate to the interface
- * writing this format's payload that a new RTP marker is necessary.
+ * \brief Register a format interface for use with the provided codec
+ *
+ * \param codec The name of codec the interface is applicable to
+ * \param interface A pointer to the interface implementation
+ * \param mod The module this format interface is provided by
+ *
+ * \retval 0 success
+ * \retval -1 failure
*/
-void ast_format_set_video_mark(struct ast_format *format);
+int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod);
/*!
- * \brief Determine of the marker bit is set or not on this format.
+ * \brief Register a format interface for use with the provided codec
*
- * \retval 1, true
- * \retval 0, false
+ * \param codec The name of codec the interface is applicable to
+ * \param interface A pointer to the interface implementation
+ *
+ * \retval 0 success
+ * \retval -1 failure
*/
-int ast_format_get_video_mark(const struct ast_format *format);
+#define ast_format_interface_register(codec, interface) __ast_format_interface_register(codec, interface, ast_module_info->self)
/*!
- * \brief ast_format to old bitfield format represenatation
+ * \brief Get the attribute data on a format
*
- * \note This is only to be used for IAX2 compatibility
+ * \param format The media format
*
- * \retval iax2 representation of ast_format
- * \retval 0, if no representation existis for iax2
+ * \return Currently set attribute data
*/
-uint64_t ast_format_to_old_bitfield(const struct ast_format *format);
+void *ast_format_get_attribute_data(const struct ast_format *format);
/*!
- * \brief ast_format_id to old bitfield format represenatation
+ * \brief Set the attribute data on a format
*
+ * \param format The media format
+ * \param attribute_data The attribute data
*/
-uint64_t ast_format_id_to_old_bitfield(enum ast_format_id id);
+void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data);
/*!
- * \brief convert old bitfield format to ast_format represenatation
- * \note This is only to be used for IAX2 compatibility
+ * \brief Get the name associated with a format
*
- * \retval on success, pointer to the dst format in the input parameters
- * \retval on failure, NULL
+ * \param format The media format
+ *
+ * \return The name of the format
*/
-struct ast_format *ast_format_from_old_bitfield(struct ast_format *dst, uint64_t src);
+const char *ast_format_get_name(const struct ast_format *format);
/*!
- * \brief convert old bitfield format to ast_format_id value
+ * \brief Get the codec identifier associated with a format
+ *
+ * \param format The media format
+ *
+ * \return codec identifier
*/
-enum ast_format_id ast_format_id_from_old_bitfield(uint64_t src);
+unsigned int ast_format_get_codec_id(const struct ast_format *format);
/*!
- * \brief Retrieve the global format list in a read only array.
- * \note ast_format_list_destroy must be called on every format
- * list retrieved from this function.
+ * \brief Get the codec name associated with a format
+ *
+ * \param format The media format
+ *
+ * \return The codec name
*/
-const struct ast_format_list *ast_format_list_get(size_t *size);
+const char *ast_format_get_codec_name(const struct ast_format *format);
/*!
- * \brief Destroy an ast_format_list gotten from ast_format_list_get()
- */
-const struct ast_format_list *ast_format_list_destroy(const struct ast_format_list *list);
-
-/*! \brief Get the name of a format
- * \param format id of format
- * \return A static string containing the name of the format or "unknown" if unknown.
- */
-const char* ast_getformatname(const struct ast_format *format);
-
-/*! \brief Returns a string containing all formats pertaining to an format id.
- * \param buf a buffer for the output string
- * \param size size of buf (bytes)
- * \param id format id.
- * \return The return value is buf.
+ * \brief Get whether or not the format can be smoothed
+ *
+ * \param format The media format
+ *
+ * \retval 0 the format cannot be smoothed
+ * \retval 1 the format can be smoothed
*/
-char* ast_getformatname_multiple_byid(char *buf, size_t size, enum ast_format_id id);
+int ast_format_can_be_smoothed(const struct ast_format *format);
/*!
- * \brief Gets a format from a name.
- * \param name string of format
- * \param format structure to return the format in.
- * \return This returns the format pointer given to it on success and NULL on failure
+ * \brief Get the media type of a format
+ *
+ * \param format The media format
+ *
+ * \return the media type
*/
-struct ast_format *ast_getformatbyname(const char *name, struct ast_format *format);
+enum ast_media_type ast_format_get_type(const struct ast_format *format);
/*!
- * \brief Get a name from a format
- * \param format to get name of
- * \return This returns a static string identifying the format on success, 0 on error.
+ * \brief Get the default framing size (in milliseconds) for a format
+ *
+ * \param format The media format
+ *
+ * \return default framing size in milliseconds
*/
-const char *ast_codec2str(struct ast_format *format);
+unsigned int ast_format_get_default_ms(const struct ast_format *format);
/*!
- * \brief Get the sample rate for a given format.
+ * \brief Get the minimum amount of media carried in this format
+ *
+ * \param format The media format
+ *
+ * \return minimum framing size in milliseconds
*/
-int ast_format_rate(const struct ast_format *format);
+unsigned int ast_format_get_minimum_ms(const struct ast_format *format);
/*!
- * \brief register ast_format_attr_interface with core.
+ * \brief Get the maximum amount of media carried in this format
*
- * \retval 0 success
- * \retval -1 failure
+ * \param format The media format
+ *
+ * \return maximum framing size in milliseconds
*/
-int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interface);
+unsigned int ast_format_get_maximum_ms(const struct ast_format *format);
/*!
- * \brief unregister format_attr interface with core.
+ * \brief Get the minimum number of bytes expected in a frame for this format
*
- * \retval 0 success
- * \retval -1 failure
+ * \param format The media format
+ *
+ * \return minimum expected bytes in a frame for this format
*/
-int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *interface);
+unsigned int ast_format_get_minimum_bytes(const struct ast_format *format);
/*!
- * \brief Determine if a format is 16bit signed linear of any sample rate.
+ * \brief Get the sample rate of a media format
+ *
+ * \param format The media format
+ *
+ * \return sample rate
*/
-int ast_format_is_slinear(const struct ast_format *format);
+unsigned int ast_format_get_sample_rate(const struct ast_format *format);
/*!
- * \brief Get the best slinear format id for a given sample rate
+ * \brief Get the length (in milliseconds) for the format with a given number of samples
+ *
+ * \param format The media format
+ * \param samples The number of samples
+ *
+ * \return length of media (in milliseconds)
*/
-enum ast_format_id ast_format_slin_by_rate(unsigned int rate);
+unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples);
/*!
* \since 12
@@ -494,4 +384,5 @@ struct stasis_message_type *ast_format_register_type(void);
* \retval NULL on error
*/
struct stasis_message_type *ast_format_unregister_type(void);
+
#endif /* _AST_FORMAT_H */
diff --git a/include/asterisk/format_cache.h b/include/asterisk/format_cache.h
new file mode 100644
index 000000000..e0744054e
--- /dev/null
+++ b/include/asterisk/format_cache.h
@@ -0,0 +1,301 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Cache API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _AST_FORMAT_CACHE_H_
+#define _AST_FORMAT_CACHE_H_
+
+struct ast_format;
+
+/*!
+ * \brief Built-in cached signed linear 8kHz format.
+ */
+extern struct ast_format *ast_format_slin;
+
+/*!
+ * \brief Built-in cached signed linear 12kHz format.
+ */
+extern struct ast_format *ast_format_slin12;
+
+/*!
+ * \brief Built-in cached signed linear 16kHz format.
+ */
+extern struct ast_format *ast_format_slin16;
+
+/*!
+ * \brief Built-in cached signed linear 24kHz format.
+ */
+extern struct ast_format *ast_format_slin24;
+
+/*!
+ * \brief Built-in cached signed linear 32kHz format.
+ */
+extern struct ast_format *ast_format_slin32;
+
+/*!
+ * \brief Built-in cached signed linear 44kHz format.
+ */
+extern struct ast_format *ast_format_slin44;
+
+/*!
+ * \brief Built-in cached signed linear 48kHz format.
+ */
+extern struct ast_format *ast_format_slin48;
+
+/*!
+ * \brief Built-in cached signed linear 96kHz format.
+ */
+extern struct ast_format *ast_format_slin96;
+
+/*!
+ * \brief Built-in cached signed linear 192kHz format.
+ */
+extern struct ast_format *ast_format_slin192;
+
+/*!
+ * \brief Built-in cached ulaw format.
+ */
+extern struct ast_format *ast_format_ulaw;
+
+/*!
+ * \brief Built-in cached alaw format.
+ */
+extern struct ast_format *ast_format_alaw;
+
+/*!
+ * \brief Built-in cached testlaw format.
+ */
+extern struct ast_format *ast_format_testlaw;
+
+/*!
+ * \brief Built-in cached gsm format.
+ */
+extern struct ast_format *ast_format_gsm;
+
+/*!
+ * \brief Built-in cached adpcm format.
+ */
+extern struct ast_format *ast_format_adpcm;
+
+/*!
+ * \brief Built-in cached g722 format.
+ */
+extern struct ast_format *ast_format_g722;
+
+/*!
+ * \brief Built-in cached g726 format.
+ */
+extern struct ast_format *ast_format_g726;
+
+/*!
+ * \brief Built-in cached g726 aal2 format.
+ */
+extern struct ast_format *ast_format_g726_aal2;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+extern struct ast_format *ast_format_ilbc;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+extern struct ast_format *ast_format_lpc10;
+
+/*!
+ * \brief Built-in cached speex format.
+ */
+extern struct ast_format *ast_format_speex;
+
+/*!
+ * \brief Built-in cached speex at 16kHz format.
+ */
+extern struct ast_format *ast_format_speex16;
+
+/*!
+ * \brief Built-in cached speex at 32kHz format.
+ */
+extern struct ast_format *ast_format_speex32;
+
+/*!
+ * \brief Built-in cached g723.1 format.
+ */
+extern struct ast_format *ast_format_g723;
+
+/*!
+ * \brief Built-in cached g729 format.
+ */
+extern struct ast_format *ast_format_g729;
+
+/*!
+ * \brief Built-in cached g719 format.
+ */
+extern struct ast_format *ast_format_g719;
+
+/*!
+ * \brief Built-in cached h261 format.
+ */
+extern struct ast_format *ast_format_h261;
+
+/*!
+ * \brief Built-in cached h263 format.
+ */
+extern struct ast_format *ast_format_h263;
+
+/*!
+ * \brief Built-in cached h263 plus format.
+ */
+extern struct ast_format *ast_format_h263p;
+
+/*!
+ * \brief Built-in cached h264 format.
+ */
+extern struct ast_format *ast_format_h264;
+
+/*!
+ * \brief Built-in cached mp4 format.
+ */
+extern struct ast_format *ast_format_mp4;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+extern struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in cached jpeg format.
+ */
+extern struct ast_format *ast_format_jpeg;
+
+/*!
+ * \brief Built-in cached png format.
+ */
+extern struct ast_format *ast_format_png;
+
+/*!
+ * \brief Built-in cached siren14 format.
+ */
+extern struct ast_format *ast_format_siren14;
+
+/*!
+ * \brief Built-in cached siren7 format.
+ */
+extern struct ast_format *ast_format_siren7;
+
+/*!
+ * \brief Built-in cached opus format.
+ */
+extern struct ast_format *ast_format_opus;
+
+/*!
+ * \brief Built-in cached t140 format.
+ */
+extern struct ast_format *ast_format_t140;
+
+/*!
+ * \brief Built-in cached t140 red format.
+ */
+extern struct ast_format *ast_format_t140_red;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+extern struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in "null" format.
+ */
+extern struct ast_format *ast_format_none;
+
+/*!
+ * \brief Initialize format cache support within the core.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_format_cache_init(void);
+
+/*!
+ * \brief Set a named format cache entry.
+ *
+ * \param format A pointer to the format to cache
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_format_cache_set(struct ast_format *format);
+
+/*!
+ * \brief Retrieve a named format from the cache.
+ *
+ * \param name Name of the cached format
+ *
+ * \retval non-NULL if found
+ * \retval NULL if not found
+ *
+ * \note The returned format has its reference count incremented. It must be
+ * dropped using ao2_ref or ao2_cleanup.
+ */
+struct ast_format *__ast_format_cache_get(const char *name);
+struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func);
+
+#ifdef REF_DEBUG
+#define ast_format_cache_get(name) \
+ __ast_format_cache_get_debug((name), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_t_format_cache_get(name, tag) \
+ __ast_format_cache_get_debug((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#else
+#define ast_format_cache_get(name) \
+ __ast_format_cache_get((name))
+#define ast_t_format_cache_get(name, tag) \
+ __ast_format_cache_get((name))
+#endif
+
+
+/*!
+ * \brief Retrieve the best signed linear format given a sample rate.
+ *
+ * \param rate The sample rate
+ *
+ * \details
+ * This is a convenience function that returns one of the global
+ * ast_format_slinxxx formats.
+ *
+ * \return pointer to the signed linear format
+ *
+ * \note The returned format has NOT had its reference count incremented.
+ */
+struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate);
+
+/*!
+ * \brief Determines if a format is one of the cached slin formats
+ *
+ * \param format The format to check
+ *
+ * \retval 0 if the format is not an SLIN format
+ * \retval 1 if the format is an SLIN format
+ */
+int ast_format_cache_is_slinear(struct ast_format *format);
+
+#endif /* _AST_FORMAT_CACHE_H */
diff --git a/include/asterisk/format_cap.h b/include/asterisk/format_cap.h
index aa4eb3bfd..f7d33fccd 100644
--- a/include/asterisk/format_cap.h
+++ b/include/asterisk/format_cap.h
@@ -1,9 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -18,216 +18,289 @@
/*!
* \file
- * \brief Format Capability API
+ * \brief Format Capabilities API
*
- * \author David Vossel <dvossel@digium.com>
+ * \author Joshua Colp <jcolp@digium.com>
*/
-#ifndef _AST_FORMATCAP_H_
-#define _AST_FORMATCAP_H_
+#ifndef _AST_FORMAT_CAP_H_
+#define _AST_FORMAT_CAP_H_
-/*! Capabilities are represented by an opaque structure statically defined in format_capability.c */
+#include "asterisk/codec.h"
+
+/*! Capabilities are represented by an opaque structure statically defined in format_cap.c */
struct ast_format_cap;
enum ast_format_cap_flags {
/*!
- * The ast_format_cap will be allocated with no lock.
- * Useful if there is a separate lock used to protect the structure
- */
- AST_FORMAT_CAP_FLAG_NOLOCK = (1 << 0),
- /*!
- * String representations of the formats are cached on the structure.
- * Useful if string representation is frequently requested of the structure.
+ * Default format capabilities settings
*/
- AST_FORMAT_CAP_FLAG_CACHE_STRINGS = (1 << 1),
+ AST_FORMAT_CAP_FLAG_DEFAULT = 0,
};
/*!
* \brief Allocate a new ast_format_cap structure
*
* \param flags Modifiers of struct behavior.
+ *
* \retval ast_format_cap object on success.
* \retval NULL on failure.
*/
-struct ast_format_cap *ast_format_cap_alloc(enum ast_format_cap_flags flags);
+struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags);
+struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func);
+
+#ifdef REF_DEBUG
+#define ast_format_cap_alloc(flags) \
+ __ast_format_cap_alloc_debug((flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_t_format_cap_alloc(flags, tag) \
+ __ast_format_cap_alloc_debug((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#else
+#define ast_format_cap_alloc(flags) \
+ __ast_format_cap_alloc((flags))
+#define ast_t_format_cap_alloc(flags, tag) \
+ __ast_format_cap_alloc((flags))
+#endif
/*!
- * \brief Destroy an ast_format_cap structure.
+ * \brief Set the global framing.
+ *
+ * \param cap The capabilities structure.
+ * \param framing The framing value (in milliseconds).
*
- * \return NULL
+ * \note This is used if a format does not provide a framing itself. Note that
+ * adding subsequent formats to the \c ast_format_cap structure may
+ * override this value, if the framing they require is less than the
+ * value set by this function.
*/
-void *ast_format_cap_destroy(struct ast_format_cap *cap);
+void ast_format_cap_set_framing(struct ast_format_cap *cap, unsigned int framing);
/*!
- * \brief Add format capability to capabilities structure.
+ * \brief Get the global framing.
*
- * \note A copy of the input format is made and that copy is
- * what is placed in the ast_format_cap structure. The actual
- * input format ptr is not stored.
+ * \param cap The capabilities structure.
+ *
+ * \retval 0 if no formats are in the structure and no framing has been provided
+ * \retval The global framing value (in milliseconds)
+ *
+ * \note This will be the minimum framing allowed across all formats in the
+ * capabilities structure, or an overridden value
*/
-void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format);
+unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap);
/*!
- * \brief Add all formats Asterisk knows about for a specific type to
- * the capabilities structure. Formats with attributes are set, but their
- * attributes are initilized to 0's. An attribute structure of 0's should
- * indicate to the format attribute interface that the format has full
- * capabilities.
- *
- * \note A copy of the input format is made and that copy is
- * what is placed in the ast_format_cap structure. The actual
- * input format ptr is not stored.
+ * \brief Add format capability to capabilities structure.
+ *
+ * \param cap The capabilities structure to add to.
+ * \param format The format to add.
+ * \param framing The framing for the format (in milliseconds).
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note A reference to the format is taken and used in the capabilities structure.
+ *
+ * \note The order in which add is called determines the format preference order.
+ *
+ * \note If framing is specified here it overrides any global framing that has been set.
*/
-void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type);
+int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing);
+int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func);
+
+#ifdef REF_DEBUG
+#define ast_format_cap_append(cap, format, framing) \
+ __ast_format_cap_append_debug((cap), (format), (framing), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_t_format_cap_append(cap, format, framing, tag) \
+ __ast_format_cap_append_debug((cap), (format), (framing), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#else
+#define ast_format_cap_append(cap, format, framing) \
+ __ast_format_cap_append((cap), (format), (framing))
+#define ast_t_format_cap_append(cap, format, framing, tag) \
+ __ast_format_cap_append((cap), (format), (framing))
+#endif
/*!
- * \brief Add all known formats to the capabilities structure using default format attribute.
+ * \brief Add all codecs Asterisk knows about for a specific type to
+ * the capabilities structure.
+ *
+ * \param cap The capabilities structure to add to.
+ * \param type The type of formats to add.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note A generic format with no attributes is created using the codec.
+ *
+ * \note If AST_MEDIA_TYPE_UNKNOWN is passed as the type all known codecs will be added.
*/
-void ast_format_cap_add_all(struct ast_format_cap *cap);
+int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type);
/*!
- * \brief Append the formats in src to dst
+ * \brief Append the formats of provided type in src to dst
+ *
+ * \param dst The destination capabilities structure
+ * \param src The source capabilities structure
+ * \param type The type of formats to append.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note If AST_MEDIA_TYPE_UNKNOWN is passed as the type all known codecs will be added.
*/
-void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src);
+int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type);
/*!
- * \brief Copy all items in src to dst.
- * \note any items in dst will be removed before copying
+ * \brief Replace the formats of provided type in dst with equivalent formats from src
+ *
+ * \param dst The destination capabilities structure
+ * \param src The source capabilities structure
+ * \param type The type of formats to replace.
+ *
+ * \note If AST_MEDIA_TYPE_UNKNOWN is passed as the type all known codecs will be replaced.
+ * \note Formats present in src but not dst will not be appended to dst.
*/
-void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src);
+void ast_format_cap_replace_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type);
/*!
- * \brief create a deep copy of an ast_format_cap structure
+ * \brief Parse an "allow" or "deny" list and modify a format capabilities structure accordingly
+ *
+ * \param cap The capabilities structure to modify
+ * \param list The list containing formats to append or remove
+ * \param allowing If zero, start removing formats specified in the list. If non-zero,
+ * start appending formats specified in the list.
*
- * \retval cap on success
- * \retval NULL on failure
+ * \retval 0 on success
+ * \retval -1 on failure
*/
-struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *src);
+int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing);
/*!
- * \brief determine if a capabilities structure is empty or not
+ * \brief Get the number of formats present within the capabilities structure
*
- * \retval 1, true is empty
- * \retval 0, false, not empty
+ * \param cap The capabilities structure
+ *
+ * \return the number of formats
*/
-int ast_format_cap_is_empty(const struct ast_format_cap *cap);
+size_t ast_format_cap_count(const struct ast_format_cap *cap);
/*!
- * \brief Remove format capability from capability structure.
+ * \brief Get the format at a specific index
*
- * \note format must match Exactly to format in ast_format_cap object in order
- * to be removed.
+ * \param cap The capabilities structure
+ * \param position The position to get
*
- * \retval 0, remove was successful
- * \retval -1, remove failed. Could not find format to remove
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note This is a zero based index.
+ *
+ * \note Formats are returned in order of preference.
+ *
+ * \note The reference count of the returned format is increased. It must be released using ao2_ref
+ * or ao2_cleanup.
*/
-int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format);
+struct ast_format *ast_format_cap_get_format(const struct ast_format_cap *cap, int position);
/*!
- * \brief Remove all format capabilities from capability
- * structure for a specific format id.
+ * \brief Get the most preferred format for a particular media type
*
- * \note This will remove _ALL_ formats matching the format id from the
- * capabilities structure.
+ * \param cap The capabilities structure
+ * \param type The type of media to get
*
- * \retval 0, remove was successful
- * \retval -1, remove failed. Could not find formats to remove
+ * \retval non-NULL the preferred format
+ * \retval NULL no media of \c type present
+ *
+ * \note The reference count of the returned format is increased. It must be released using ao2_ref
+ * or ao2_cleanup.
*/
-int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id);
+struct ast_format *ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type);
/*!
- * \brief Remove all formats matching a specific format type.
+ * \brief Get the framing for a format
+ *
+ * \param cap The capabilities structure
+ * \param format The format to retrieve
+ *
+ * \return the framing (in milliseconds)
*/
-void ast_format_cap_remove_bytype(struct ast_format_cap *cap, enum ast_format_type type);
+unsigned int ast_format_cap_get_format_framing(const struct ast_format_cap *cap, const struct ast_format *format);
/*!
- * \brief Remove all format capabilities from capability structure
+ * \brief Remove format capability from capability structure.
+ *
+ * \note format must be an exact pointer match to remove from capabilities structure.
+ *
+ * \retval 0, remove was successful
+ * \retval -1, remove failed. Could not find format to remove
*/
-void ast_format_cap_remove_all(struct ast_format_cap *cap);
+int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format);
/*!
- * \brief Remove all previous formats and set a single new format.
+ * \brief Remove all formats matching a specific format type.
+ *
+ * \param cap The capabilities structure
+ * \param type The media type to remove formats of
+ *
+ * \note All formats can be removed by using the AST_MEDIA_TYPE_UNKNOWN type.
*/
-void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format);
+void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type);
/*!
* \brief Find if input ast_format is within the capabilities of the ast_format_cap object
* then return the compatible format from the capabilities structure in the result.
*
- * \retval 1 format is compatible with formats held in ast_format_cap object.
- * \retval 0 format is not compatible with any formats in ast_format_cap object.
+ * \retval non-NULL if format is compatible
+ * \retval NULL if not compatible
+ *
+ * \note The reference count of the returned format is increased. It must be released using ao2_ref
+ * or ao2_cleanup.
*/
-int ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format, struct ast_format *result);
+struct ast_format *ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format);
/*!
* \brief Find if ast_format is within the capabilities of the ast_format_cap object.
*
- * \retval 1 format is compatible with formats held in ast_format_cap object.
- * \retval 0 format is not compatible with any formats in ast_format_cap object.
+* \retval ast_format_cmp_res representing the result of the compatibility check between cap and format.
*/
-int ast_format_cap_iscompatible(const struct ast_format_cap *cap, const struct ast_format *format);
+enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format);
/*!
- * \brief Finds the best quality audio format for a given format id and returns it in result.
+ * \brief Find the compatible formats between two capabilities structures
*
- * \retval 1 format found and set to result structure.
- * \retval 0 no format found, result structure is cleared.
- */
-int ast_format_cap_best_byid(const struct ast_format_cap *cap, enum ast_format_id, struct ast_format *result);
-
-/*!
- * \brief is cap1 identical to cap2
+ * \param cap1 The first capabilities structure
+ * \param cap2 The second capabilities structure
+ * \param[out] result The capabilities structure to place the results into
*
- * retval 1 true, identical
- * retval 0 false, not identical
- */
-int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
-
-/*!
- * \brief Get joint capability structure.
+ * \retval 0 success
+ * \retval -1 failure
*
- * \note returns an ast_format_cap object containing the joint capabilities on success. This new
- * capabilities structure is allocated with _NO_ locking enabled. If a joint structure requires
- * locking, allocate it and use the ast_format_cap_joint_copy function to fill it with the joint
- * capabilities.
+ * \note The preference order of cap1 is respected.
*
- * \retval !NULL success, joint capabilties structure with _NO_ locking enabled.
- * \retval NULL failure
+ * \note If failure occurs the result format capabilities structure may contain a partial result.
*/
-struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
+int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2,
+ struct ast_format_cap *result);
/*!
- * \brief Get joint capability structure, copy into result capabilities structure
+ * \brief Determine if any joint capabilities exist between two capabilities structures
*
- * \retval 1, joint capabilities exist
- * \retval 0, joint capabilities do not exist
- */
-int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result);
-
-/*!
- * \brief Get joint capability structure, append into result capabilities structure
+ * \param cap1 The first capabilities structure
+ * \param cap2 The second capabilities structure
*
- * \retval 1, joint capabilities exist
- * \retval 0, joint capabilities do not exist
+ * \retval 0 no joint capabilities exist
+ * \retval 1 joint capabilities exist
*/
-int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result);
+int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
/*!
- * \brief Find out if capability structures have any joint capabilities without
- * returning those capabilities.
+ * \brief Determine if two capabilities structures are identical
*
- * \retval 1 true, has joint capabilities
- * \retval 0 false, failure
- */
-int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
-
-/*!
- * \brief Get all capabilities for a specific media type
+ * \param cap1 The first capabilities structure
+ * \param cap2 The second capabilities structure
*
- * \retval !NULL success, new capabilities structure with _NO_ locking enabled on the new structure.
- * \retval NULL failure
+ * \retval 0 capabilities are not identical
+ * \retval 1 capabilities are identical
*/
-struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype);
+int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2);
/*!
* \brief Find out if the capabilities structure has any formats
@@ -236,68 +309,16 @@ struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap,
* \retval 1 true
* \retval 0 false, no formats of specific type.
*/
-int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type);
-
-/*! \brief Start iterating formats */
-void ast_format_cap_iter_start(struct ast_format_cap *cap);
-
-/*!
- * \brief Next format in interation
- *
- * \details
- * Here is how to use the ast_format_cap iterator.
- *
- * 1. call ast_format_cap_iter_start
- * 2. call ast_format_cap_iter_next in a loop until it returns -1
- * 3. call ast_format_cap_iter_end to terminate the iterator.
- *
- * example:
- *
- * ast_format_cap_iter_start(cap);
- * while (!ast_format_cap_iter_next(cap, &format)) {
- * }
- * ast_format_cap_iter_end(Cap);
- *
- * \note Unless the container was alloced using no_lock, the container
- * will be locked during the entire iteration until ast_format_cap_iter_end
- * is called. XXX Remember this, and do not attempt to lock any containers
- * within this iteration that will violate locking order.
- *
- * \retval 0 on success, new format is copied into input format struct
- * \retval -1, no more formats are present.
- */
-int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format);
-
-/*!
- * \brief Ends ast_format_cap iteration.
- * \note this must be call after every ast_format_cap_iter_start
- */
-void ast_format_cap_iter_end(struct ast_format_cap *cap);
+int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type);
/*!
- * \brief ast_format_cap to old bitfield format represenatation
+ * \brief Get the names of codecs of a set of formats
*
- * \note This is only to be used for IAX2 compatibility
+ * \param cap The capabilities structure containing the formats
+ * \param buf A \c ast_str buffer to populate with the names of the formats
*
- * \retval old bitfield representation of ast_format_cap
- * \retval 0, if no old bitfield capabilities are present in ast_format_cap
- */
-uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap);
-
-/*!
- * \brief convert old bitfield format to ast_format_cap represenatation
- * \note This is only to be used for IAX2 compatibility
- */
-void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src);
-
-/*! \brief Get the names of a set of formats
- * \param buf a buffer for the output string
- * \param size size of buf (bytes)
- * \param cap format the format (combined IDs of codecs)
- * Prints a list of readable codec names corresponding to "format".
- * ex: for format=AST_FORMAT_GSM|AST_FORMAT_SPEEX|AST_FORMAT_ILBC it will return "0x602 (GSM|SPEEX|ILBC)"
- * \return The return value is buf.
+ * \return The contents of the buffer in \c buf
*/
-char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap);
+const char *ast_format_cap_get_names(struct ast_format_cap *cap, struct ast_str **buf);
-#endif /* _AST_FORMATCAP_H */
+#endif /* _AST_FORMAT_CAP_H */
diff --git a/include/asterisk/format_compatibility.h b/include/asterisk/format_compatibility.h
new file mode 100644
index 000000000..f14b7166c
--- /dev/null
+++ b/include/asterisk/format_compatibility.h
@@ -0,0 +1,129 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+#ifndef _AST_FORMAT_COMPATIBILITY_H_
+#define _AST_FORMAT_COMPATIBILITY_H_
+
+struct ast_format;
+struct ast_codec;
+
+/*
+ * Legacy bitfields for specific formats
+ */
+
+/*! G.723.1 compression */
+#define AST_FORMAT_G723 (1ULL << 0)
+/*! GSM compression */
+#define AST_FORMAT_GSM (1ULL << 1)
+/*! Raw mu-law data (G.711) */
+#define AST_FORMAT_ULAW (1ULL << 2)
+/*! Raw A-law data (G.711) */
+#define AST_FORMAT_ALAW (1ULL << 3)
+/*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
+#define AST_FORMAT_G726_AAL2 (1ULL << 4)
+/*! ADPCM (IMA) */
+#define AST_FORMAT_ADPCM (1ULL << 5)
+/*! Raw 16-bit Signed Linear (8000 Hz) PCM */
+#define AST_FORMAT_SLIN (1ULL << 6)
+/*! LPC10, 180 samples/frame */
+#define AST_FORMAT_LPC10 (1ULL << 7)
+/*! G.729A audio */
+#define AST_FORMAT_G729 (1ULL << 8)
+/*! SpeeX Free Compression */
+#define AST_FORMAT_SPEEX (1ULL << 9)
+/*! iLBC Free Compression */
+#define AST_FORMAT_ILBC (1ULL << 10)
+/*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
+#define AST_FORMAT_G726 (1ULL << 11)
+/*! G.722 */
+#define AST_FORMAT_G722 (1ULL << 12)
+/*! G.722.1 (also known as Siren7, 32kbps assumed) */
+#define AST_FORMAT_SIREN7 (1ULL << 13)
+/*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
+#define AST_FORMAT_SIREN14 (1ULL << 14)
+/*! Raw 16-bit Signed Linear (16000 Hz) PCM */
+#define AST_FORMAT_SLIN16 (1ULL << 15)
+/*! G.719 (64 kbps assumed) */
+#define AST_FORMAT_G719 (1ULL << 32)
+/*! SpeeX Wideband (16kHz) Free Compression */
+#define AST_FORMAT_SPEEX16 (1ULL << 33)
+/*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
+#define AST_FORMAT_OPUS (1ULL << 34)
+/*! Raw testing-law data (G.711) */
+#define AST_FORMAT_TESTLAW (1ULL << 47)
+/*! H.261 Video */
+#define AST_FORMAT_H261 (1ULL << 18)
+/*! H.263 Video */
+#define AST_FORMAT_H263 (1ULL << 19)
+/*! H.263+ Video */
+#define AST_FORMAT_H263P (1ULL << 20)
+/*! H.264 Video */
+#define AST_FORMAT_H264 (1ULL << 21)
+/*! MPEG4 Video */
+#define AST_FORMAT_MP4 (1ULL << 22)
+/*! VP8 Video */
+#define AST_FORMAT_VP8 (1ULL << 23)
+/*! JPEG Images */
+#define AST_FORMAT_JPEG (1ULL << 16)
+/*! PNG Images */
+#define AST_FORMAT_PNG (1ULL << 17)
+/*! T.140 RED Text format RFC 4103 */
+#define AST_FORMAT_T140_RED (1ULL << 26)
+/*! T.140 Text format - ITU T.140, RFC 4103 */
+#define AST_FORMAT_T140 (1ULL << 27)
+
+/*!
+ * \brief Convert a format structure to its respective bitfield
+ *
+ * \param format The media format
+ *
+ * \retval non-zero success
+ * \retval zero format not supported
+ */
+uint64_t ast_format_compatibility_format2bitfield(const struct ast_format *format);
+
+/*!
+ * \brief Convert a codec structure to its respective bitfield
+ *
+ * \param codec The media codec
+ *
+ * \retval non-zero success
+ * \retval zero format not supported
+ */
+uint64_t ast_format_compatibility_codec2bitfield(const struct ast_codec *codec);
+
+/*!
+ * \brief Convert a bitfield to its respective format structure
+ *
+ * \param bitfield The bitfield for the media format
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The reference count of the returned format is NOT incremented
+ */
+struct ast_format *ast_format_compatibility_bitfield2format(uint64_t bitfield);
+
+#endif /* _AST_FORMAT_COMPATIBILITY_H */
diff --git a/include/asterisk/format_pref.h b/include/asterisk/format_pref.h
deleted file mode 100644
index f5c3c22a7..000000000
--- a/include/asterisk/format_pref.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2010, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- * \brief Format Preference API
- */
-
-#ifndef _AST_FORMATPREF_H_
-#define _AST_FORMATPREF_H_
-
-#include "asterisk/format.h"
-#include "asterisk/format_cap.h"
-
-#define AST_CODEC_PREF_SIZE 64
-struct ast_codec_pref {
- /*! This array represents the each format in the pref list */
- struct ast_format formats[AST_CODEC_PREF_SIZE];
- /*! This array represents the format id's index in the global format list. */
- char order[AST_CODEC_PREF_SIZE];
- /*! This array represents the format's framing size if present. */
- int framing[AST_CODEC_PREF_SIZE];
-};
-
-/*! \page AudioCodecPref Audio Codec Preferences
-
- In order to negotiate audio codecs in the order they are configured
- in \<channel\>.conf for a device, we set up codec preference lists
- in addition to the codec capabilities setting. The capabilities
- setting is a bitmask of audio and video codecs with no internal
- order. This will reflect the offer given to the other side, where
- the prefered codecs will be added to the top of the list in the
- order indicated by the "allow" lines in the device configuration.
-
- Video codecs are not included in the preference lists since they
- can't be transcoded and we just have to pick whatever is supported
-*/
-
-/*!
- *\brief Initialize an audio codec preference to "no preference".
- * \arg \ref AudioCodecPref
-*/
-void ast_codec_pref_init(struct ast_codec_pref *pref);
-
-/*!
- * \brief Codec located at a particular place in the preference index.
- * \param pref preference structure to get the codec out of
- * \param index to retrieve from
- * \param result ast_format structure to store the index value in
- * \return pointer to input ast_format on success, NULL on failure
-*/
-struct ast_format *ast_codec_pref_index(struct ast_codec_pref *pref, int index, struct ast_format *result);
-
-/*! \brief Remove audio a codec from a preference list */
-void ast_codec_pref_remove(struct ast_codec_pref *pref, struct ast_format *format);
-
-/*! \brief Append all codecs to a preference list, without disturbing existing order */
-void ast_codec_pref_append_all(struct ast_codec_pref *pref);
-
-/*! \brief Append a audio codec to a preference list, removing it first if it was already there
-*/
-int ast_codec_pref_append(struct ast_codec_pref *pref, struct ast_format *format);
-
-/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there
-*/
-void ast_codec_pref_prepend(struct ast_codec_pref *pref, struct ast_format *format, int only_if_existing);
-
-/*! \brief Select the best audio format according to preference list from supplied options.
- * Best audio format is returned in the result format.
- *
- * \note If "find_best" is non-zero then if nothing is found, the "Best" format of
- * the format list is selected and returned in the result structure, otherwise
- * NULL is returned
- *
- * \retval ptr to result struture.
- * \retval NULL, best codec was not found
- */
-struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result);
-
-/*! \brief Set packet size for codec
-*/
-int ast_codec_pref_setsize(struct ast_codec_pref *pref, struct ast_format *format, int framems);
-
-/*! \brief Get packet size for codec
-*/
-struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format);
-
-/*! \brief Dump audio codec preference list into a string */
-int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size);
-
-/*! \brief Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string
- * \note Due to a misunderstanding in how codec preferences are stored, this
- * list starts at 'B', not 'A'. For backwards compatibility reasons, this
- * cannot change.
- * \param pref A codec preference list structure
- * \param buf A string denoting codec preference, appropriate for use in line transmission
- * \param size Size of \a buf
- * \param right Boolean: if 0, convert from \a buf to \a pref; if 1, convert from \a pref to \a buf.
- */
-void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right);
-
-#endif /* _AST_FORMATPREF_H */
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 846832aff..a981c7e72 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -31,7 +31,6 @@ extern "C" {
#include <sys/time.h>
-#include "asterisk/format_pref.h"
#include "asterisk/format.h"
#include "asterisk/endian.h"
#include "asterisk/linkedlists.h"
@@ -136,9 +135,13 @@ enum {
AST_FRFLAG_HAS_TIMING_INFO = (1 << 0),
};
-union ast_frame_subclass {
+struct ast_frame_subclass {
+ /*! A frame specific code */
int integer;
- struct ast_format format;
+ /*! The asterisk media format */
+ struct ast_format *format;
+ /*! For video formats, an indication that a frame ended */
+ unsigned int frame_ending;
};
/*! \brief Data structure associated with a single frame of data
@@ -147,7 +150,7 @@ struct ast_frame {
/*! Kind of frame */
enum ast_frame_type frametype;
/*! Subclass, frame dependent */
- union ast_frame_subclass subclass;
+ struct ast_frame_subclass subclass;
/*! Length of data */
int datalen;
/*! Number of samples in this frame */
@@ -384,9 +387,6 @@ struct ast_control_pvt_cause_code {
char code[1]; /*!< Tech-specific cause code information, beginning with the name of the tech */
};
-#define AST_SMOOTHER_FLAG_G729 (1 << 0)
-#define AST_SMOOTHER_FLAG_BE (1 << 1)
-
/* Option identifiers and flags */
#define AST_OPTION_FLAG_REQUEST 0
#define AST_OPTION_FLAG_ACCEPT 1
@@ -565,77 +565,11 @@ void ast_swapcopy_samples(void *dst, const void *src, int samples);
#define ast_frame_byteswap_be(fr) do { ; } while(0)
#endif
-/*! \brief Parse an "allow" or "deny" line in a channel or device configuration
- and update the capabilities and pref if provided.
- Video codecs are not added to codec preference lists, since we can not transcode
- \return Returns number of errors encountered during parsing
- */
-int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing);
-
-/*! \name AST_Smoother
-*/
-/*@{ */
-/*! \page ast_smooth The AST Frame Smoother
-The ast_smoother interface was designed specifically
-to take frames of variant sizes and produce frames of a single expected
-size, precisely what you want to do.
-
-The basic interface is:
-
-- Initialize with ast_smoother_new()
-- Queue input frames with ast_smoother_feed()
-- Get output frames with ast_smoother_read()
-- when you're done, free the structure with ast_smoother_free()
-- Also see ast_smoother_test_flag(), ast_smoother_set_flags(), ast_smoother_get_flags(), ast_smoother_reset()
-*/
-struct ast_smoother;
-
-struct ast_smoother *ast_smoother_new(int bytes);
-void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
-int ast_smoother_get_flags(struct ast_smoother *smoother);
-int ast_smoother_test_flag(struct ast_smoother *s, int flag);
-void ast_smoother_free(struct ast_smoother *s);
-void ast_smoother_reset(struct ast_smoother *s, int bytes);
-
-/*!
- * \brief Reconfigure an existing smoother to output a different number of bytes per frame
- * \param s the smoother to reconfigure
- * \param bytes the desired number of bytes per output frame
- * \return nothing
- *
- */
-void ast_smoother_reconfigure(struct ast_smoother *s, int bytes);
-
-int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
-struct ast_frame *ast_smoother_read(struct ast_smoother *s);
-#define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 1)
-#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 0)
-#else
-#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 0)
-#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 1)
-#endif
-/*@} Doxygen marker */
-
void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix);
-/*! \brief Returns the number of samples contained in the frame */
-int ast_codec_get_samples(struct ast_frame *f);
-
-/*! \brief Returns the number of bytes for the number of samples of the given format */
-int ast_codec_get_len(struct ast_format *format, int samples);
-
/*! \brief Appends a frame to the end of a list of frames, truncating the maximum length of the list */
struct ast_frame *ast_frame_enqueue(struct ast_frame *head, struct ast_frame *f, int maxlen, int dupe);
-
-/*! \brief Gets duration in ms of interpolation frame for a format */
-static inline int ast_codec_interp_len(struct ast_format *format)
-{
- return (format->id == AST_FORMAT_ILBC) ? 30 : 20;
-}
-
/*!
\brief Adjusts the volume of the audio samples contained in a frame.
\param f The frame containing the samples (must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR)
diff --git a/include/asterisk/image.h b/include/asterisk/image.h
index 302f09e85..9e358ad52 100644
--- a/include/asterisk/image.h
+++ b/include/asterisk/image.h
@@ -28,7 +28,7 @@ struct ast_imager {
char *name; /*!< Name */
char *desc; /*!< Description */
char *exts; /*!< Extension(s) (separated by '|' ) */
- struct ast_format format; /*!< Image format */
+ struct ast_format *format; /*!< Image format */
struct ast_frame *(*read_image)(int fd, int len); /*!< Read an image from a file descriptor */
int (*identify)(int fd); /*!< Identify if this is that type of file */
int (*write_image)(int fd, struct ast_frame *frame); /*!< Returns length written */
diff --git a/include/asterisk/mod_format.h b/include/asterisk/mod_format.h
index ff3ab7bbf..7f17741fa 100644
--- a/include/asterisk/mod_format.h
+++ b/include/asterisk/mod_format.h
@@ -43,10 +43,10 @@ extern "C" {
struct ast_format_def {
char name[80]; /*!< Name of format */
char exts[80]; /*!< Extensions (separated by | if more than one)
- this format can read. First is assumed for writing (e.g. .mp3) */
- struct ast_format format; /*!< Format of frames it uses/provides (one only) */
- /*!
- * \brief Prepare an input stream for playback.
+ * this format can read. First is assumed for writing (e.g. .mp3) */
+ struct ast_format *format; /*!< Format of frames it uses/provides (one only) */
+ /*!
+ * \brief Prepare an input stream for playback.
* \return 0 on success, -1 on error.
* The FILE is already open (in s->f) so this function only needs to perform
* any applicable validity checks on the file. If none is required, the
@@ -110,7 +110,7 @@ struct ast_filestream {
/*! Transparently translate from another format -- just once */
struct ast_trans_pvt *trans;
struct ast_tranlator_pvt *tr;
- struct ast_format lastwriteformat;
+ struct ast_format *lastwriteformat;
int lasttimeout;
struct ast_channel *owner;
FILE *f;
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index d569710e0..45d9325ee 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -530,8 +530,6 @@ struct ast_sip_endpoint_media_configuration {
struct ast_sip_direct_media_configuration direct_media;
/*! T.38 (FoIP) options */
struct ast_sip_t38_configuration t38;
- /*! Codec preferences */
- struct ast_codec_pref prefs;
/*! Configured codecs */
struct ast_format_cap *codecs;
/*! DSCP TOS bits for audio streams */
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 7340c6d71..51908f99b 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -126,8 +126,6 @@ struct ast_sip_session {
struct ast_party_id id;
/* Requested capabilities */
struct ast_format_cap *req_caps;
- /* Codecs overriden by dialplan on an outgoing request */
- struct ast_codec_pref override_prefs;
/* Optional DSP, used only for inband DTMF detection if configured */
struct ast_dsp *dsp;
/* Whether the termination of the session should be deferred */
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index 81e530e85..e5f38eecc 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -1,4 +1,4 @@
-/*
+ /*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2009, Digium, Inc.
@@ -71,10 +71,12 @@ extern "C" {
#include "asterisk/astobj2.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cap.h"
#include "asterisk/netsock2.h"
#include "asterisk/sched.h"
#include "asterisk/res_srtp.h"
#include "asterisk/stasis.h"
+#include "asterisk/vector.h"
/* Maximum number of payloads supported */
#if defined(LOW_MEMORY)
@@ -245,7 +247,7 @@ struct ast_rtp_payload_type {
int asterisk_format;
/*! If asterisk_format is set, this is the internal
* asterisk format represented by the payload */
- struct ast_format format;
+ struct ast_format *format;
/*! Actual internal RTP specific value of the payload */
int rtp_code;
/*! Actual payload number */
@@ -526,8 +528,6 @@ struct ast_rtp_engine {
void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
/*! Callback for setting a payload. If asterisk is to be used, asterisk_format will be set, otherwise value in code is used. */
void (*payload_set)(struct ast_rtp_instance *instance, int payload, int asterisk_format, struct ast_format *format, int code);
- /*! Callback for setting packetization preferences */
- void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref);
/*! Callback for setting the remote address that RTP is to be sent to */
void (*remote_address_set)(struct ast_rtp_instance *instance, struct ast_sockaddr *sa);
/*! Callback for changing DTMF mode */
@@ -575,11 +575,16 @@ struct ast_rtp_engine {
/*! Structure that represents codec and packetization information */
struct ast_rtp_codecs {
/*! Payloads present */
- struct ao2_container *payloads;
- /*! Codec packetization preferences */
- struct ast_codec_pref pref;
+ AST_VECTOR(, struct ast_rtp_payload_type *) payloads;
+ /*! The framing for this media session */
+ unsigned int framing;
+ /*! RW lock that protects elements in this structure */
+ ast_rwlock_t codecs_lock;
};
+#define AST_RTP_CODECS_NULL_INIT \
+ { .payloads = { 0, }, .framing = 0, .codecs_lock = AST_RWLOCK_INIT_VALUE, }
+
/*! Structure that represents the glue that binds an RTP instance to a channel */
struct ast_rtp_glue {
/*! Name of the channel driver that this glue is responsible for */
@@ -622,6 +627,18 @@ struct ast_rtp_glue {
AST_RWLIST_ENTRY(ast_rtp_glue) entry;
};
+/*!
+ * \brief Allocation routine for \ref ast_rtp_payload_type
+ *
+ * \retval NULL on error
+ * \retval An ao2 ref counted \c ast_rtp_payload_type on success.
+ *
+ * \note The \c ast_rtp_payload_type returned by this function is an
+ * ao2 ref counted object.
+ *
+ */
+struct ast_rtp_payload_type *ast_rtp_engine_alloc_payload_type(void);
+
#define ast_rtp_engine_register(engine) ast_rtp_engine_register2(engine, ast_module_info->self)
/*!
@@ -1117,25 +1134,6 @@ void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs);
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
/*!
- * \brief Set payload information on an RTP instance to the default
- *
- * \param codecs The codecs structure to set defaults on
- * \param instance Optionally the instance that the codecs structure belongs to
- *
- * Example usage:
- *
- * \code
- * struct ast_rtp_codecs codecs;
- * ast_rtp_codecs_payloads_default(&codecs, NULL);
- * \endcode
- *
- * This sets the default payloads on the codecs structure.
- *
- * \since 1.8
- */
-void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
-
-/*!
* \brief Copy payload information from one RTP instance to another
*
* \param src The source codecs structure
@@ -1249,20 +1247,36 @@ void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp
* \param codecs Codecs structure to look in
* \param payload Numerical payload to look up
*
- * \retval Payload information
+ * \retval Payload information.
+ * \retval NULL if payload does not exist.
+ *
+ * \note The payload returned by this function has its reference count increased.
+ * Callers are responsible for decrementing the reference count.
*
* Example usage:
*
* \code
- * struct ast_rtp_payload_type payload_type;
- * payload_type = ast_rtp_codecs_payload_lookup(&codecs, 0);
+ * struct ast_rtp_payload_type *payload_type;
+ * payload_type = ast_rtp_codecs_get_payload(&codecs, 0);
* \endcode
*
* This looks up the information for payload '0' from the codecs structure.
+ */
+struct ast_rtp_payload_type *ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload);
+
+/*!
+ * \brief Update the format associated with a payload in a codecs structure
*
- * \since 1.8
+ * \param codecs Codecs structure to operate on
+ * \param payload Numerical payload to look up
+ * \param format The format to replace the existing one
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \since 13
*/
-struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload);
+int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format);
/*!
* \brief Retrieve the actual ast_format stored on the codecs structure for a specific payload
@@ -1273,11 +1287,35 @@ struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs
* \retval pointer to format structure on success
* \retval NULL on failure
*
+ * \note The format returned by this function has its reference count increased.
+ * Callers are responsible for decrementing the reference count.
+ *
* \since 10.0
*/
struct ast_format *ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload);
/*!
+ * \brief Set the framing used for a set of codecs
+ *
+ * \param codecs Codecs structure to set framing on
+ * \param framing The framing value to set on the codecs
+ *
+ * \since 13.0.0
+ */
+void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing);
+
+/*!
+ * \brief Get the framing used for a set of codecs
+ *
+ * \param codecs Codecs structure to get the framing from
+ *
+ * \retval The framing to be used for the media stream associated with these codecs
+ *
+ * \since 13.0.0
+ */
+unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs);
+
+/*!
* \brief Get the sample rate associated with known RTP payload types
*
* \param asterisk_format True if the value in format is to be used.
@@ -1393,8 +1431,8 @@ const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_f
* char buf[256] = "";
* struct ast_format tmp_fmt;
* struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
- * ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0));
- * ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
+ * ast_format_cap_append(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0));
+ * ast_format_cap_append(cap, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
* char *mime = ast_rtp_lookup_mime_multiple2(&buf, sizeof(buf), cap, 0, 1, 0);
* ast_format_cap_destroy(cap);
* \endcode
@@ -1406,25 +1444,6 @@ const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_f
char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *ast_format_capability, int rtp_capability, const int asterisk_format, enum ast_rtp_options options);
/*!
- * \brief Set codec packetization preferences
- *
- * \param codecs Codecs structure to muck with
- * \param instance Optionally the instance that the codecs structure belongs to
- * \param prefs Codec packetization preferences
- *
- * Example usage:
- *
- * \code
- * ast_rtp_codecs_packetization_set(&codecs, NULL, &prefs);
- * \endcode
- *
- * This sets the packetization preferences pointed to by prefs on the codecs structure pointed to by codecs.
- *
- * \since 1.8
- */
-void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs);
-
-/*!
* \brief Begin sending a DTMF digit
*
* \param instance The RTP instance to send the DTMF on
@@ -2111,12 +2130,12 @@ struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance);
/*! \brief Custom formats declared in codecs.conf at startup must be communicated to the rtp_engine
* so their mime type can payload number can be initialized. */
-int ast_rtp_engine_load_format(const struct ast_format *format);
+int ast_rtp_engine_load_format(struct ast_format *format);
/*! \brief Formats requiring the use of a format attribute interface must have that
* interface registered in order for the rtp engine to handle it correctly. If an
* attribute interface is unloaded, this function must be called to notify the rtp_engine. */
-int ast_rtp_engine_unload_format(const struct ast_format *format);
+int ast_rtp_engine_unload_format(struct ast_format *format);
/*!
* \brief Obtain a pointer to the ICE support present on an RTP instance
diff --git a/include/asterisk/slin.h b/include/asterisk/slin.h
index ab7d843ab..148ee09ab 100644
--- a/include/asterisk/slin.h
+++ b/include/asterisk/slin.h
@@ -70,7 +70,8 @@ static inline struct ast_frame *slin8_sample(void)
.data.ptr = ex_slin8,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ f.subclass.format = ast_format_slin;
+
return &f;
}
@@ -86,6 +87,7 @@ static inline struct ast_frame *slin16_sample(void)
.data.ptr = ex_slin16,
};
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0);
+ f.subclass.format = ast_format_slin16;
+
return &f;
}
diff --git a/include/asterisk/slinfactory.h b/include/asterisk/slinfactory.h
index 324c0ae28..9a8ceae1e 100644
--- a/include/asterisk/slinfactory.h
+++ b/include/asterisk/slinfactory.h
@@ -39,8 +39,8 @@ struct ast_slinfactory {
short *offset; /*!< Offset into the hold where audio begins */
size_t holdlen; /*!< Number of samples currently in the hold */
unsigned int size; /*!< Number of samples currently in the factory */
- struct ast_format format; /*!< Current format the translation path is converting from */
- struct ast_format output_format; /*!< The output format desired */
+ struct ast_format *format; /*!< Current format the translation path is converting from */
+ struct ast_format *output_format; /*!< The output format desired */
};
/*!
@@ -60,7 +60,7 @@ void ast_slinfactory_init(struct ast_slinfactory *sf);
*
* \return 0 on success, non-zero on failure
*/
-int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, const struct ast_format *slin_out);
+int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, struct ast_format *slin_out);
/*!
* \brief Destroy the contents of a slinfactory
diff --git a/include/asterisk/smoother.h b/include/asterisk/smoother.h
new file mode 100644
index 000000000..e63aa77bd
--- /dev/null
+++ b/include/asterisk/smoother.h
@@ -0,0 +1,89 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Asterisk internal frame definitions.
+ * \arg For an explanation of frames, see \ref Def_Frame
+ * \arg Frames are send of Asterisk channels, see \ref Def_Channel
+ */
+
+#ifndef _ASTERISK_SMOOTHER_H
+#define _ASTERISK_SMOOTHER_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#include "asterisk/endian.h"
+
+#define AST_SMOOTHER_FLAG_G729 (1 << 0)
+#define AST_SMOOTHER_FLAG_BE (1 << 1)
+
+/*! \name AST_Smoother
+*/
+/*@{ */
+/*! \page ast_smooth The AST Frame Smoother
+The ast_smoother interface was designed specifically
+to take frames of variant sizes and produce frames of a single expected
+size, precisely what you want to do.
+
+The basic interface is:
+
+- Initialize with ast_smoother_new()
+- Queue input frames with ast_smoother_feed()
+- Get output frames with ast_smoother_read()
+- when you're done, free the structure with ast_smoother_free()
+- Also see ast_smoother_test_flag(), ast_smoother_set_flags(), ast_smoother_get_flags(), ast_smoother_reset()
+*/
+struct ast_smoother;
+
+struct ast_frame;
+
+struct ast_smoother *ast_smoother_new(int bytes);
+void ast_smoother_set_flags(struct ast_smoother *smoother, int flags);
+int ast_smoother_get_flags(struct ast_smoother *smoother);
+int ast_smoother_test_flag(struct ast_smoother *s, int flag);
+void ast_smoother_free(struct ast_smoother *s);
+void ast_smoother_reset(struct ast_smoother *s, int bytes);
+
+/*!
+ * \brief Reconfigure an existing smoother to output a different number of bytes per frame
+ * \param s the smoother to reconfigure
+ * \param bytes the desired number of bytes per output frame
+ * \return nothing
+ *
+ */
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes);
+
+int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap);
+struct ast_frame *ast_smoother_read(struct ast_smoother *s);
+#define ast_smoother_feed(s,f) __ast_smoother_feed(s, f, 0)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 1)
+#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 0)
+#else
+#define ast_smoother_feed_be(s,f) __ast_smoother_feed(s, f, 0)
+#define ast_smoother_feed_le(s,f) __ast_smoother_feed(s, f, 1)
+#endif
+/*@} Doxygen marker */
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _ASTERISK_SMOOTHER_H */
diff --git a/include/asterisk/speech.h b/include/asterisk/speech.h
index a914f4846..0da6f5cfc 100644
--- a/include/asterisk/speech.h
+++ b/include/asterisk/speech.h
@@ -58,7 +58,7 @@ struct ast_speech {
/*! Current state of structure */
int state;
/*! Expected write format */
- struct ast_format format;
+ struct ast_format *format;
/*! Data for speech engine */
void *data;
/*! Cached results */
diff --git a/include/asterisk/translate.h b/include/asterisk/translate.h
index 602c3097c..e8e4c02d2 100644
--- a/include/asterisk/translate.h
+++ b/include/asterisk/translate.h
@@ -32,6 +32,8 @@ extern "C" {
#include "asterisk/frame.h"
#include "asterisk/plc.h"
#include "asterisk/linkedlists.h"
+#include "asterisk/format_cap.h"
+#include "asterisk/format_cache.h"
#endif
struct ast_trans_pvt; /* declared below */
@@ -134,8 +136,11 @@ enum ast_trans_cost_table {
*/
struct ast_translator {
char name[80]; /*!< Name of translator */
- struct ast_format src_format; /*!< Source format */
- struct ast_format dst_format; /*!< Destination format */
+ struct ast_codec src_codec; /*!< Source codec */
+ struct ast_codec dst_codec; /*!< Destination codec */
+ struct ast_codec *core_src_codec; /*!< Core registered source codec */
+ struct ast_codec *core_dst_codec; /*!< Core registered destination codec */
+ const char *format; /*!< Optional name of a cached format this translator produces */
int table_cost; /*!< Cost value associated with this translator based
* on translation cost table. */
@@ -204,12 +209,6 @@ struct ast_translator {
struct ast_trans_pvt {
struct ast_translator *t;
struct ast_frame f; /*!< used in frameout */
- /*! If a translation path using a format with attributes requires the output
- * to be a specific set of attributes, this variable will be set describing those
- * attributes to the translator. Otherwise, the translator must choose a set
- * of format attributes for the destination that preserves the quality of the
- * audio in the best way possible. */
- struct ast_format explicit_dst;
int samples; /*!< samples available in outbuf */
/*! \brief actual space used in outbuf */
int datalen;
@@ -286,8 +285,8 @@ void ast_translator_deactivate(struct ast_translator *t);
*/
int ast_translator_best_choice(struct ast_format_cap *dst_cap,
struct ast_format_cap *src_cap,
- struct ast_format *dst_fmt_out,
- struct ast_format *src_fmt_out);
+ struct ast_format **dst_fmt_out,
+ struct ast_format **src_fmt_out);
/*!
* \brief Builds a translator path
diff --git a/include/asterisk/vector.h b/include/asterisk/vector.h
index 0a2c6c965..0053d8a32 100644
--- a/include/asterisk/vector.h
+++ b/include/asterisk/vector.h
@@ -61,7 +61,7 @@
#define AST_VECTOR_INIT(vec, size) ({ \
size_t __size = (size); \
size_t alloc_size = __size * sizeof(*((vec)->elems)); \
- (vec)->elems = alloc_size ? ast_malloc(alloc_size) : NULL; \
+ (vec)->elems = alloc_size ? ast_calloc(1, alloc_size) : NULL; \
(vec)->current = 0; \
if ((vec)->elems) { \
(vec)->max = __size; \
@@ -116,6 +116,48 @@
})
/*!
+ * \brief Insert an element at a specific position in a vector, growing the vector if needed.
+ *
+ * \param vec Vector to insert into.
+ * \param idx Position to insert at.
+ * \param elem Element to insert.
+ *
+ * \return 0 on success.
+ * \return Non-zero on failure.
+ *
+ * \warning This macro will overwrite anything already present at the position provided.
+ *
+ * \warning Use of this macro with the expectation that the element will remain at the provided
+ * index means you can not use the UNORDERED assortment of macros. These macros alter the ordering
+ * of the vector itself.
+ */
+#define AST_VECTOR_INSERT(vec, idx, elem) ({ \
+ int res = 0; \
+ do { \
+ if (((idx) + 1) > (vec)->max) { \
+ size_t new_max = ((idx) + 1) * 2; \
+ typeof((vec)->elems) new_elems = ast_calloc(1, \
+ new_max * sizeof(*new_elems)); \
+ if (new_elems) { \
+ memcpy(new_elems, (vec)->elems, \
+ (vec)->current * sizeof(*new_elems)); \
+ ast_free((vec)->elems); \
+ (vec)->elems = new_elems; \
+ (vec)->max = new_max; \
+ } else { \
+ res = -1; \
+ break; \
+ } \
+ } \
+ (vec)->elems[(idx)] = (elem); \
+ if (((idx) + 1) > (vec)->current) { \
+ (vec)->current = (idx) + 1; \
+ } \
+ } while(0); \
+ res; \
+})
+
+/*!
* \brief Remove an element from a vector by index.
*
* Note that elements in the vector may be reordered, so that the remove can
@@ -134,6 +176,25 @@
res; \
})
+/*!
+ * \brief Remove an element from a vector by index while maintaining order.
+ *
+ * \param vec Vector to remove from.
+ * \param idx Index of the element to remove.
+ * \return The element that was removed.
+ */
+#define AST_VECTOR_REMOVE_ORDERED(vec, idx) ({ \
+ typeof((vec)->elems[0]) res; \
+ size_t __idx = (idx); \
+ size_t __move; \
+ ast_assert(__idx < (vec)->current); \
+ res = (vec)->elems[__idx]; \
+ __move = ((vec)->current - (__idx) - 1) * sizeof(typeof((vec)->elems[0])); \
+ memmove(&(vec)->elems[__idx], &(vec)->elems[__idx + 1], __move); \
+ (vec)->current--; \
+ res; \
+})
+
/*!
* \brief Remove an element from a vector that matches the given comparison
@@ -162,6 +223,32 @@
})
/*!
+ * \brief Remove an element from a vector that matches the given comparison while maintaining order
+ *
+ * \param vec Vector to remove from.
+ * \param value Value to pass into comparator.
+ * \param cmp Comparator function/macros (called as \c cmp(elem, value))
+ * \param cleanup How to cleanup a removed element macro/function.
+ *
+ * \return 0 if element was removed.
+ * \return Non-zero if element was not in the vector.
+ */
+#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
+ int res = -1; \
+ size_t idx; \
+ typeof(value) __value = (value); \
+ for (idx = 0; idx < (vec)->current; ++idx) { \
+ if (cmp((vec)->elems[idx], __value)) { \
+ cleanup((vec)->elems[idx]); \
+ AST_VECTOR_REMOVE_ORDERED((vec), idx); \
+ res = 0; \
+ break; \
+ } \
+ } \
+ res; \
+})
+
+/*!
* \brief Default comparator for AST_VECTOR_REMOVE_ELEM_UNORDERED()
*
* \param elem Element to compare against
@@ -197,6 +284,21 @@
})
/*!
+ * \brief Remove an element from a vector while maintaining order.
+ *
+ * \param vec Vector to remove from.
+ * \param elem Element to remove
+ * \param cleanup How to cleanup a removed element macro/function.
+ *
+ * \return 0 if element was removed.
+ * \return Non-zero if element was not in the vector.
+ */
+#define AST_VECTOR_REMOVE_ELEM_ORDERED(vec, elem, cleanup) ({ \
+ AST_VECTOR_REMOVE_CMP_ORDERED((vec), (elem), \
+ AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
+})
+
+/*!
* \brief Get the number of elements in a vector.
*
* \param vec Vector to query.
diff --git a/main/abstract_jb.c b/main/abstract_jb.c
index 7841b6a4e..85c188e88 100644
--- a/main/abstract_jb.c
+++ b/main/abstract_jb.c
@@ -360,7 +360,7 @@ static void jb_get_and_deliver(struct ast_channel *chan)
}
while (now >= jb->next) {
- interpolation_len = ast_codec_interp_len(&jb->last_format);
+ interpolation_len = ast_format_get_default_ms(jb->last_format);
res = jbimpl->get(jbobj, &f, now, interpolation_len);
@@ -371,13 +371,13 @@ static void jb_get_and_deliver(struct ast_channel *chan)
case AST_JB_IMPL_DROP:
jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
now, jb_get_actions[res], f->ts, f->len);
- ast_format_copy(&jb->last_format, &f->subclass.format);
+ ao2_replace(jb->last_format, f->subclass.format);
ast_frfree(f);
break;
case AST_JB_IMPL_INTERP:
/* interpolate a frame */
f = &finterp;
- ast_format_copy(&f->subclass.format, &jb->last_format);
+ f->subclass.format = jb->last_format;
f->samples = interpolation_len * 8;
f->src = "JB interpolation";
f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
@@ -437,7 +437,7 @@ static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
jb->next = jbimpl->next(jbobj);
/* Init last format for a first time. */
- ast_format_copy(&jb->last_format, &frr->subclass.format);
+ jb->last_format = ao2_bump(frr->subclass.format);
/* Create a frame log file */
if (ast_test_flag(jbconf, AST_JB_LOG)) {
@@ -502,6 +502,8 @@ void ast_jb_destroy(struct ast_channel *chan)
jb->logfile = NULL;
}
+ ao2_cleanup(jb->last_format);
+
if (ast_test_flag(jb, JB_CREATED)) {
/* Remove and free all frames still queued in jb */
while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
@@ -820,7 +822,7 @@ struct jb_framedata {
const struct ast_jb_impl *jb_impl;
struct ast_jb_conf jb_conf;
struct timeval start_tv;
- struct ast_format last_format;
+ struct ast_format *last_format;
struct ast_timer *timer;
int timer_interval; /* ms between deliveries */
int timer_fd;
@@ -842,6 +844,7 @@ static void jb_framedata_destroy(struct jb_framedata *framedata)
framedata->jb_impl->destroy(framedata->jb_obj);
framedata->jb_obj = NULL;
}
+ ao2_cleanup(framedata->last_format);
ast_free(framedata);
}
@@ -909,7 +912,7 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
}
jbframe = ast_frisolate(frame);
- ast_format_copy(&framedata->last_format, &frame->subclass.format);
+ ao2_replace(framedata->last_format, frame->subclass.format);
if (frame->len && (frame->len != framedata->timer_interval)) {
framedata->timer_interval = frame->len;
@@ -959,12 +962,12 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
frame = &ast_null_frame;
break;
case AST_JB_IMPL_INTERP:
- if (framedata->last_format.id) {
+ if (framedata->last_format) {
struct ast_frame tmp = { 0, };
tmp.frametype = AST_FRAME_VOICE;
- ast_format_copy(&tmp.subclass.format, &framedata->last_format);
+ tmp.subclass.format = framedata->last_format;
/* example: 8000hz / (1000 / 20ms) = 160 samples */
- tmp.samples = ast_format_rate(&framedata->last_format) / (1000 / framedata->timer_interval);
+ tmp.samples = ast_format_get_sample_rate(framedata->last_format) / (1000 / framedata->timer_interval);
tmp.delivery = ast_tvadd(framedata->start_tv, ast_samp2tv(next, 1000));
tmp.offset = AST_FRIENDLY_OFFSET;
tmp.src = "func_jitterbuffer interpolation";
diff --git a/main/app.c b/main/app.c
index 822fe6c45..fa7c3ece1 100644
--- a/main/app.c
+++ b/main/app.c
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
#define MWI_TOPIC_BUCKETS 57
@@ -880,16 +881,18 @@ struct linear_state {
int fd;
int autoclose;
int allowoverride;
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
};
static void linear_release(struct ast_channel *chan, void *params)
{
struct linear_state *ls = params;
- if (ls->origwfmt.id && ast_set_write_format(chan, &ls->origwfmt)) {
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%u'\n", ast_channel_name(chan), ls->origwfmt.id);
+ if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n",
+ ast_channel_name(chan), ast_format_get_name(ls->origwfmt));
}
+ ao2_cleanup(ls->origwfmt);
if (ls->autoclose) {
close(ls->fd);
@@ -909,7 +912,7 @@ static int linear_generator(struct ast_channel *chan, void *data, int len, int s
};
int res;
- ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ f.subclass.format = ast_format_slin;
len = samples * 2;
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
@@ -943,10 +946,11 @@ static void *linear_alloc(struct ast_channel *chan, void *params)
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
}
- ast_format_copy(&ls->origwfmt, ast_channel_writeformat(chan));
+ ls->origwfmt = ao2_bump(ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", ast_channel_name(chan));
+ ao2_cleanup(ls->origwfmt);
ast_free(ls);
ls = params = NULL;
}
@@ -1358,7 +1362,7 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
return NULL;
}
- if (orig->subclass.format.id != AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
return NULL;
}
@@ -1385,7 +1389,7 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
silence->samples = samples;
silence->datalen = datalen;
- ast_format_set(&silence->subclass.format, AST_FORMAT_SLINEAR, 0);
+ silence->subclass.format = ast_format_slin;
return silence;
}
@@ -1400,13 +1404,13 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
* \return 0 on success.
* \return -1 on error.
*/
-static int set_read_to_slin(struct ast_channel *chan, struct ast_format *orig_format)
+static int set_read_to_slin(struct ast_channel *chan, struct ast_format **orig_format)
{
if (!chan || !orig_format) {
return -1;
}
- ast_format_copy(orig_format, ast_channel_readformat(chan));
- return ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ *orig_format = ao2_bump(ast_channel_readformat(chan));
+ return ast_set_read_format(chan, ast_format_slin);
}
static int global_silence_threshold = 128;
@@ -1448,7 +1452,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
int totalsilence = 0;
int dspsilence = 0;
int olddspsilence = 0;
- struct ast_format rfmt;
+ struct ast_format *rfmt = NULL;
struct ast_silence_generator *silgen = NULL;
char prependfile[PATH_MAX];
int ioflags; /* IO flags for writing output file */
@@ -1467,7 +1471,6 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
break;
}
- ast_format_clear(&rfmt);
if (silencethreshold < 0) {
silencethreshold = global_silence_threshold;
}
@@ -1542,6 +1545,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
ast_dsp_free(sildet);
+ ao2_cleanup(rfmt);
return -1;
}
}
@@ -1692,7 +1696,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
* set the mode, if we haven't already
* for sildet
*/
- if (muted && !rfmt.id) {
+ if (muted && !rfmt) {
ast_verb(3, "Setting read format to linear mode\n");
res = set_read_to_slin(chan, &rfmt);
if (res < 0) {
@@ -1812,9 +1816,10 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
ast_filedelete(prependfile, sfmt[x]);
}
}
- if (rfmt.id && ast_set_read_format(chan, &rfmt)) {
- ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(&rfmt), ast_channel_name(chan));
+ if (rfmt && ast_set_read_format(chan, rfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
}
+ ao2_cleanup(rfmt);
if ((outmsg == 2) && (!skip_confirmation_sound)) {
ast_stream_and_wait(chan, "auth-thankyou", "");
}
diff --git a/main/asterisk.c b/main/asterisk.c
index 55e06c385..1c6994280 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -248,6 +248,8 @@ int daemon(int, int); /* defined in libresolv of all places */
#include "asterisk/stasis_system.h"
#include "asterisk/security_events.h"
#include "asterisk/endpoints.h"
+#include "asterisk/codec.h"
+#include "asterisk/format_cache.h"
#include "../defaults.h"
@@ -4316,6 +4318,26 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (ast_codec_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_format_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_format_cache_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
+ if (ast_codec_builtin_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
#ifdef AST_XML_DOCS
/* Load XML documentation. */
ast_xmldoc_load_documentation();
@@ -4370,8 +4392,6 @@ int main(int argc, char *argv[])
threadstorage_init();
- ast_format_attr_init();
- ast_format_list_init();
if (ast_rtp_engine_init()) {
printf("%s", term_quit());
exit(1);
diff --git a/main/audiohook.c b/main/audiohook.c
index 549ad31eb..33dad38f9 100644
--- a/main/audiohook.c
+++ b/main/audiohook.c
@@ -41,13 +41,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/slinfactory.h"
#include "asterisk/frame.h"
#include "asterisk/translate.h"
+#include "asterisk/format_cache.h"
#define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*!< Tolerance in milliseconds for audiohooks synchronization */
#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE 100 /*!< When small queue is enabled, this is the maximum amount of audio that can remain queued at a time. */
struct ast_audiohook_translate {
struct ast_trans_pvt *trans_pvt;
- struct ast_format format;
+ struct ast_format *format;
};
struct ast_audiohook_list {
@@ -67,7 +68,7 @@ struct ast_audiohook_list {
static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate, int reset)
{
- struct ast_format slin;
+ struct ast_format *slin;
if (audiohook->hook_internal_samp_rate == rate) {
return 0;
@@ -75,7 +76,8 @@ static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate
audiohook->hook_internal_samp_rate = rate;
- ast_format_set(&slin, ast_format_slin_by_rate(rate), 0);
+ slin = ast_format_cache_get_slin_by_rate(rate);
+
/* Setup the factories that are needed for this audiohook type */
switch (audiohook->type) {
case AST_AUDIOHOOK_TYPE_SPY:
@@ -84,12 +86,13 @@ static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate
ast_slinfactory_destroy(&audiohook->read_factory);
ast_slinfactory_destroy(&audiohook->write_factory);
}
- ast_slinfactory_init_with_format(&audiohook->read_factory, &slin);
- ast_slinfactory_init_with_format(&audiohook->write_factory, &slin);
+ ast_slinfactory_init_with_format(&audiohook->read_factory, slin);
+ ast_slinfactory_init_with_format(&audiohook->write_factory, slin);
break;
default:
break;
}
+
return 0;
}
@@ -143,6 +146,8 @@ int ast_audiohook_destroy(struct ast_audiohook *audiohook)
if (audiohook->trans_pvt)
ast_translator_free_path(audiohook->trans_pvt);
+ ao2_cleanup(audiohook->format);
+
/* Lock and trigger be gone! */
ast_cond_destroy(&audiohook->trigger);
ast_mutex_destroy(&audiohook->lock);
@@ -220,11 +225,11 @@ static struct ast_frame *audiohook_read_frame_single(struct ast_audiohook *audio
short buf[samples];
struct ast_frame frame = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate),
.data.ptr = buf,
.datalen = sizeof(buf),
.samples = samples,
};
- ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0);
/* Ensure the factory is able to give us the samples we want */
if (samples > ast_slinfactory_available(factory)) {
@@ -254,7 +259,6 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
.datalen = sizeof(buf1),
.samples = samples,
};
- ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0);
/* Make sure both factories have the required samples */
usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
@@ -346,6 +350,8 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
/* Make the final buffer part of the frame, so it gets duplicated fine */
frame.data.ptr = final_buf;
+ frame.subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);
+
/* Yahoo, a combined copy of the audio! */
return ast_frdup(&frame);
}
@@ -353,17 +359,17 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
static struct ast_frame *audiohook_read_frame_helper(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format, struct ast_frame **read_reference, struct ast_frame **write_reference)
{
struct ast_frame *read_frame = NULL, *final_frame = NULL;
- struct ast_format tmp_fmt;
+ struct ast_format *slin;
int samples_converted;
/* the number of samples requested is based on the format they are requesting. Inorder
* to process this correctly samples must be converted to our internal sample rate */
- if (audiohook->hook_internal_samp_rate == ast_format_rate(format)) {
+ if (audiohook->hook_internal_samp_rate == ast_format_get_sample_rate(format)) {
samples_converted = samples;
- } else if (audiohook->hook_internal_samp_rate > ast_format_rate(format)) {
- samples_converted = samples * (audiohook->hook_internal_samp_rate / (float) ast_format_rate(format));
+ } else if (audiohook->hook_internal_samp_rate > ast_format_get_sample_rate(format)) {
+ samples_converted = samples * (audiohook->hook_internal_samp_rate / (float) ast_format_get_sample_rate(format));
} else {
- samples_converted = samples * (ast_format_rate(format) / (float) audiohook->hook_internal_samp_rate);
+ samples_converted = samples * (ast_format_get_sample_rate(format) / (float) audiohook->hook_internal_samp_rate);
}
if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ?
@@ -372,21 +378,23 @@ static struct ast_frame *audiohook_read_frame_helper(struct ast_audiohook *audio
return NULL;
}
+ slin = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);
+
/* If they don't want signed linear back out, we'll have to send it through the translation path */
- if (format->id != ast_format_slin_by_rate(audiohook->hook_internal_samp_rate)) {
+ if (ast_format_cmp(format, slin) != AST_FORMAT_CMP_EQUAL) {
/* Rebuild translation path if different format then previously */
- if (ast_format_cmp(format, &audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(format, audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
if (audiohook->trans_pvt) {
ast_translator_free_path(audiohook->trans_pvt);
audiohook->trans_pvt = NULL;
}
/* Setup new translation path for this format... if we fail we can't very well return signed linear so free the frame and return nothing */
- if (!(audiohook->trans_pvt = ast_translator_build_path(format, ast_format_set(&tmp_fmt, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0)))) {
+ if (!(audiohook->trans_pvt = ast_translator_build_path(format, slin))) {
ast_frfree(read_frame);
return NULL;
}
- ast_format_copy(&audiohook->format, format);
+ ao2_replace(audiohook->format, format);
}
/* Convert to requested format, and allow the read in frame to be freed */
final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
@@ -752,8 +760,7 @@ static struct ast_frame *audiohook_list_translate_to_slin(struct ast_audiohook_l
struct ast_audiohook_translate *in_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ?
&audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
struct ast_frame *new_frame = frame;
- struct ast_format tmp_fmt;
- enum ast_format_id slin_id;
+ struct ast_format *slin;
/* If we are capable of maintaining doing samplerates other that 8khz, update
* the internal audiohook_list's rate and higher samplerate audio arrives. By
@@ -761,24 +768,24 @@ static struct ast_frame *audiohook_list_translate_to_slin(struct ast_audiohook_l
* as the are written and read from. */
if (audiohook_list->native_slin_compatible) {
audiohook_list->list_internal_samp_rate =
- MAX(ast_format_rate(&frame->subclass.format), audiohook_list->list_internal_samp_rate);
+ MAX(ast_format_get_sample_rate(frame->subclass.format), audiohook_list->list_internal_samp_rate);
}
- slin_id = ast_format_slin_by_rate(audiohook_list->list_internal_samp_rate);
-
- if (frame->subclass.format.id == slin_id) {
+ slin = ast_format_cache_get_slin_by_rate(audiohook_list->list_internal_samp_rate);
+ if (ast_format_cmp(frame->subclass.format, slin) == AST_FORMAT_CMP_EQUAL) {
return new_frame;
}
- if (ast_format_cmp(&frame->subclass.format, &in_translate->format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(frame->subclass.format, in_translate->format) == AST_FORMAT_CMP_NOT_EQUAL) {
if (in_translate->trans_pvt) {
ast_translator_free_path(in_translate->trans_pvt);
}
- if (!(in_translate->trans_pvt = ast_translator_build_path(ast_format_set(&tmp_fmt, slin_id, 0), &frame->subclass.format))) {
+ if (!(in_translate->trans_pvt = ast_translator_build_path(slin, frame->subclass.format))) {
return NULL;
}
- ast_format_copy(&in_translate->format, &frame->subclass.format);
+ ao2_replace(in_translate->format, frame->subclass.format);
}
+
if (!(new_frame = ast_translate(in_translate->trans_pvt, frame, 0))) {
return NULL;
}
@@ -791,16 +798,16 @@ static struct ast_frame *audiohook_list_translate_to_native(struct ast_audiohook
{
struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
struct ast_frame *outframe = NULL;
- if (ast_format_cmp(&slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
/* rebuild translators if necessary */
- if (ast_format_cmp(&out_translate->format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(out_translate->format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
if (out_translate->trans_pvt) {
ast_translator_free_path(out_translate->trans_pvt);
}
- if (!(out_translate->trans_pvt = ast_translator_build_path(outformat, &slin_frame->subclass.format))) {
+ if (!(out_translate->trans_pvt = ast_translator_build_path(outformat, slin_frame->subclass.format))) {
return NULL;
}
- ast_format_copy(&out_translate->format, outformat);
+ ao2_replace(out_translate->format, outformat);
}
/* translate back to the format the frame came in as. */
if (!(outframe = ast_translate(out_translate->trans_pvt, slin_frame, 0))) {
@@ -924,7 +931,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st
/* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
if (middle_frame_manipulated) {
- if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, &start_frame->subclass.format))) {
+ if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, start_frame->subclass.format))) {
/* translation failed, so just pass back the input frame */
end_frame = start_frame;
}
diff --git a/main/bridge.c b/main/bridge.c
index 41053eb8a..d5fc1699a 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -934,61 +934,65 @@ int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
{
- struct ast_format read_format;
- struct ast_format write_format;
- struct ast_format best_format;
- char codec_buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_format *read_format;
+ struct ast_format *write_format;
+ struct ast_format *best_format;
- ast_format_copy(&read_format, ast_channel_readformat(bridge_channel->chan));
- ast_format_copy(&write_format, ast_channel_writeformat(bridge_channel->chan));
+ read_format = ast_channel_readformat(bridge_channel->chan);
+ write_format = ast_channel_writeformat(bridge_channel->chan);
/* Are the formats currently in use something this bridge can handle? */
- if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, ast_channel_readformat(bridge_channel->chan))) {
- ast_best_codec(bridge->technology->format_capabilities, &best_format);
+ if (ast_format_cap_iscompatible_format(bridge->technology->format_capabilities, read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ best_format = ast_format_cap_get_format(bridge->technology->format_capabilities, 0);
/* Read format is a no go... */
ast_debug(1, "Bridge technology %s wants to read any of formats %s but channel has %s\n",
bridge->technology->name,
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->format_capabilities),
- ast_getformatname(&read_format));
+ ast_format_cap_get_names(bridge->technology->format_capabilities, &codec_buf),
+ ast_format_get_name(read_format));
/* Switch read format to the best one chosen */
- if (ast_set_read_format(bridge_channel->chan, &best_format)) {
+ if (ast_set_read_format(bridge_channel->chan, best_format)) {
ast_log(LOG_WARNING, "Failed to set channel %s to read format %s\n",
- ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format));
+ ast_channel_name(bridge_channel->chan), ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
return -1;
}
ast_debug(1, "Bridge %s put channel %s into read format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&best_format));
+ ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
} else {
ast_debug(1, "Bridge %s is happy that channel %s already has read format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&read_format));
+ ast_format_get_name(read_format));
}
- if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, &write_format)) {
- ast_best_codec(bridge->technology->format_capabilities, &best_format);
+ if (ast_format_cap_iscompatible_format(bridge->technology->format_capabilities, write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ best_format = ast_format_cap_get_format(bridge->technology->format_capabilities, 0);
/* Write format is a no go... */
ast_debug(1, "Bridge technology %s wants to write any of formats %s but channel has %s\n",
bridge->technology->name,
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->format_capabilities),
- ast_getformatname(&write_format));
+ ast_format_cap_get_names(bridge->technology->format_capabilities, &codec_buf),
+ ast_format_get_name(write_format));
/* Switch write format to the best one chosen */
- if (ast_set_write_format(bridge_channel->chan, &best_format)) {
+ if (ast_set_write_format(bridge_channel->chan, best_format)) {
ast_log(LOG_WARNING, "Failed to set channel %s to write format %s\n",
- ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format));
+ ast_channel_name(bridge_channel->chan), ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
return -1;
}
ast_debug(1, "Bridge %s put channel %s into write format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&best_format));
+ ast_format_get_name(best_format));
+ ao2_cleanup(best_format);
} else {
ast_debug(1, "Bridge %s is happy that channel %s already has write format %s\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&write_format));
+ ast_format_get_name(write_format));
}
return 0;
@@ -3525,7 +3529,7 @@ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct a
struct ast_bridge_video_talker_src_data *data;
/* If the channel doesn't support video, we don't care about it */
- if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO)) {
+ if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO)) {
return;
}
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index 60ce37a98..cb8c2f992 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -46,6 +46,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dial.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/features.h"
+#include "asterisk/format_cache.h"
#define NORMAL_FLAGS (AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY \
| AST_BRIDGE_FLAG_SMART)
@@ -2267,14 +2268,13 @@ static void recall_callback(struct ast_dial *dial)
static int recalling_enter(struct attended_transfer_properties *props)
{
- RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- struct ast_format fmt;
+ RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
/* When we dial the transfer target, since we are communicating
* with a local channel, we can place the local channel in a bridge
@@ -2395,8 +2395,7 @@ static int attach_framehook(struct attended_transfer_properties *props, struct a
static int retransfer_enter(struct attended_transfer_properties *props)
{
- RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- struct ast_format fmt;
+ RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
int cause;
@@ -2406,7 +2405,7 @@ static int retransfer_enter(struct attended_transfer_properties *props)
snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
- ast_format_cap_add(cap, ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
/* Get a channel that is the destination we wish to call */
props->recall_target = ast_request("Local", cap, NULL, NULL, destination, &cause);
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index 93cbed22d..ea9b3f868 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -320,25 +320,28 @@ struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *br
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel)
{
+ ast_assert(bridge_channel->read_format != NULL);
+ ast_assert(bridge_channel->write_format != NULL);
+
/* Restore original formats of the channel as they came in */
- if (ast_format_cmp(ast_channel_readformat(bridge_channel->chan), &bridge_channel->read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(ast_channel_readformat(bridge_channel->chan), bridge_channel->read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bridge is returning %p(%s) to read format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->read_format));
- if (ast_set_read_format(bridge_channel->chan, &bridge_channel->read_format)) {
+ ast_format_get_name(bridge_channel->read_format));
+ if (ast_set_read_format(bridge_channel->chan, bridge_channel->read_format)) {
ast_debug(1, "Bridge failed to return %p(%s) to read format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->read_format));
+ ast_format_get_name(bridge_channel->read_format));
}
}
- if (ast_format_cmp(ast_channel_writeformat(bridge_channel->chan), &bridge_channel->write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(ast_channel_writeformat(bridge_channel->chan), bridge_channel->write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Bridge is returning %p(%s) to write format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->write_format));
- if (ast_set_write_format(bridge_channel->chan, &bridge_channel->write_format)) {
+ ast_format_get_name(bridge_channel->write_format));
+ if (ast_set_write_format(bridge_channel->chan, bridge_channel->write_format)) {
ast_debug(1, "Bridge failed to return %p(%s) to write format %s\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
- ast_getformatname(&bridge_channel->write_format));
+ ast_format_get_name(bridge_channel->write_format));
}
}
}
@@ -2342,8 +2345,8 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
int res = 0;
struct ast_bridge_features *channel_features;
- ast_format_copy(&bridge_channel->read_format, ast_channel_readformat(bridge_channel->chan));
- ast_format_copy(&bridge_channel->write_format, ast_channel_writeformat(bridge_channel->chan));
+ bridge_channel->read_format = ao2_bump(ast_channel_readformat(bridge_channel->chan));
+ bridge_channel->write_format = ao2_bump(ast_channel_writeformat(bridge_channel->chan));
ast_debug(1, "Bridge %s: %p(%s) is joining\n",
bridge_channel->bridge->uniqueid,
@@ -2590,6 +2593,9 @@ static void bridge_channel_destroy(void *obj)
pipe_close(bridge_channel->alert_pipe);
ast_cond_destroy(&bridge_channel->cond);
+
+ ao2_cleanup(bridge_channel->write_format);
+ ao2_cleanup(bridge_channel->read_format);
}
struct ast_bridge_channel *bridge_channel_internal_alloc(struct ast_bridge *bridge)
diff --git a/main/callerid.c b/main/callerid.c
index 5f53cb2ae..e3b2b139e 100644
--- a/main/callerid.c
+++ b/main/callerid.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/fskmodem.h"
#include "asterisk/utils.h"
+#include "asterisk/format_cache.h"
struct callerid_state {
fsk_data fskd;
diff --git a/main/ccss.c b/main/ccss.c
index 09fa2d114..9fcabfefd 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -52,6 +52,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/stasis_system.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="CallCompletionRequest" language="en_US">
@@ -2814,8 +2815,7 @@ static void *generic_recall(void *data)
const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
- struct ast_format tmp_fmt;
- struct ast_format_cap *tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!tmp_cap) {
return NULL;
@@ -2826,17 +2826,17 @@ static void *generic_recall(void *data)
*target++ = '\0';
}
- ast_format_cap_add(tmp_cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(tmp_cap, ast_format_slin, 0);
if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
/* Hmm, no channel. Sucks for you, bud.
*/
ast_log_dynamic_level(cc_logger_level, "Core %u: Failed to call back %s for reason %d\n",
agent->core_id, agent->device_name, reason);
ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
- ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
return NULL;
}
- ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
/* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
* This will be a common task for all recall functions. If it were possible, I'd have
diff --git a/main/channel.c b/main/channel.c
index 15f2cbce0..b17dddeef 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -342,7 +342,7 @@ static char *complete_channeltypes(struct ast_cli_args *a)
static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct chanlist *cl = NULL;
- char buf[512];
+ struct ast_str *codec_buf = ast_str_alloca(64);
switch (cmd) {
case CLI_INIT:
@@ -387,7 +387,7 @@ static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd,
(cl->tech->devicestate) ? "yes" : "no",
(cl->tech->indicate) ? "yes" : "no",
(cl->tech->transfer) ? "yes" : "no",
- ast_getformatname_multiple(buf, sizeof(buf), cl->tech->capabilities),
+ ast_format_cap_get_names(cl->tech->capabilities, &codec_buf),
(cl->tech->send_digit_begin) ? "yes" : "no",
(cl->tech->send_digit_end) ? "yes" : "no",
(cl->tech->send_html) ? "yes" : "no",
@@ -764,78 +764,6 @@ char *ast_transfercapability2str(int transfercapability)
}
}
-/*! \brief Pick the best audio codec */
-struct ast_format *ast_best_codec(struct ast_format_cap *cap, struct ast_format *result)
-{
- /* This just our opinion, expressed in code. We are asked to choose
- the best codec to use, given no information */
- static const enum ast_format_id prefs[] =
- {
- /*! Okay, ulaw is used by all telephony equipment, so start with it */
- AST_FORMAT_ULAW,
- /*! Unless of course, you're a silly European, so then prefer ALAW */
- AST_FORMAT_ALAW,
- AST_FORMAT_G719,
- AST_FORMAT_SIREN14,
- AST_FORMAT_SIREN7,
- AST_FORMAT_TESTLAW,
- /*! G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority */
- AST_FORMAT_G722,
- /*! Okay, well, signed linear is easy to translate into other stuff */
- AST_FORMAT_SLINEAR192,
- AST_FORMAT_SLINEAR96,
- AST_FORMAT_SLINEAR48,
- AST_FORMAT_SLINEAR44,
- AST_FORMAT_SLINEAR32,
- AST_FORMAT_SLINEAR24,
- AST_FORMAT_SLINEAR16,
- AST_FORMAT_SLINEAR12,
- AST_FORMAT_SLINEAR,
- /*! G.726 is standard ADPCM, in RFC3551 packing order */
- AST_FORMAT_G726,
- /*! G.726 is standard ADPCM, in AAL2 packing order */
- AST_FORMAT_G726_AAL2,
- /*! ADPCM has great sound quality and is still pretty easy to translate */
- AST_FORMAT_ADPCM,
- /*! Okay, we're down to vocoders now, so pick GSM because it's small and easier to
- translate and sounds pretty good */
- AST_FORMAT_GSM,
- /*! iLBC is not too bad */
- AST_FORMAT_ILBC,
- /*! Speex is free, but computationally more expensive than GSM */
- AST_FORMAT_SPEEX32,
- AST_FORMAT_SPEEX16,
- AST_FORMAT_SPEEX,
- /*! Opus */
- AST_FORMAT_OPUS,
- /*! SILK is pretty awesome. */
- AST_FORMAT_SILK,
- /*! CELT supports crazy high sample rates */
- AST_FORMAT_CELT,
- /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
- to use it */
- AST_FORMAT_LPC10,
- /*! G.729a is faster than 723 and slightly less expensive */
- AST_FORMAT_G729A,
- /*! Down to G.723.1 which is proprietary but at least designed for voice */
- AST_FORMAT_G723_1,
- };
- char buf[512];
- int x;
-
- /* Find the first preferred codec in the format given */
- for (x = 0; x < ARRAY_LEN(prefs); x++) {
- if (ast_format_cap_best_byid(cap, prefs[x], result)) {
- return result;
- }
- }
-
- ast_format_clear(result);
- ast_log(LOG_WARNING, "Don't know any of %s formats\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
-
- return NULL;
-}
-
/*! \brief Channel technology used to extract a channel from a running application. The
* channel created with this technology will be immediately hung up - most external
* applications won't ever want to see this.
@@ -883,11 +811,18 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_stage_snapshot(tmp);
- if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_CACHE_STRINGS))) {
+ if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
/* format capabilities structure allocation failure */
return ast_channel_unref(tmp);
}
+ ast_format_cap_append(nativeformats, ast_format_none, 0);
ast_channel_nativeformats_set(tmp, nativeformats);
+ ao2_ref(nativeformats, -1);
+
+ ast_channel_set_rawwriteformat(tmp, ast_format_none);
+ ast_channel_set_rawreadformat(tmp, ast_format_none);
+ ast_channel_set_writeformat(tmp, ast_format_none);
+ ast_channel_set_readformat(tmp, ast_format_none);
/*
* Init file descriptors to unopened state so
@@ -2317,6 +2252,13 @@ static void ast_channel_destructor(void *obj)
if (ast_channel_pbx(chan))
ast_log_callid(LOG_WARNING, callid, "PBX may not have been terminated properly on '%s'\n", ast_channel_name(chan));
+ /* Free formats */
+ ast_channel_set_oldwriteformat(chan, NULL);
+ ast_channel_set_rawreadformat(chan, NULL);
+ ast_channel_set_rawwriteformat(chan, NULL);
+ ast_channel_set_readformat(chan, NULL);
+ ast_channel_set_writeformat(chan, NULL);
+
ast_party_dialed_free(ast_channel_dialed(chan));
ast_party_caller_free(ast_channel_caller(chan));
ast_party_connected_line_free(ast_channel_connected(chan));
@@ -2373,7 +2315,7 @@ static void ast_channel_destructor(void *obj)
ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE) ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), device_name);
}
- ast_channel_nativeformats_set(chan, ast_format_cap_destroy(ast_channel_nativeformats(chan)));
+ ast_channel_nativeformats_set(chan, NULL);
if (callid) {
ast_callid_unref(callid);
}
@@ -2623,21 +2565,14 @@ int ast_softhangup(struct ast_channel *chan, int cause)
static void free_translation(struct ast_channel *clonechan)
{
- if (ast_channel_writetrans(clonechan))
+ if (ast_channel_writetrans(clonechan)) {
ast_translator_free_path(ast_channel_writetrans(clonechan));
- if (ast_channel_readtrans(clonechan))
+ }
+ if (ast_channel_readtrans(clonechan)) {
ast_translator_free_path(ast_channel_readtrans(clonechan));
+ }
ast_channel_writetrans_set(clonechan, NULL);
ast_channel_readtrans_set(clonechan, NULL);
- if (ast_format_cap_is_empty(ast_channel_nativeformats(clonechan))) {
- ast_format_clear(ast_channel_rawwriteformat(clonechan));
- ast_format_clear(ast_channel_rawreadformat(clonechan));
- } else {
- struct ast_format tmpfmt;
- ast_best_codec(ast_channel_nativeformats(clonechan), &tmpfmt);
- ast_format_copy(ast_channel_rawwriteformat(clonechan), &tmpfmt);
- ast_format_copy(ast_channel_rawreadformat(clonechan), &tmpfmt);
- }
}
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
@@ -2998,10 +2933,11 @@ static int generator_force(const void *data)
generate = ast_channel_generator(chan)->generate;
ast_channel_unlock(chan);
- if (!tmp || !generate)
+ if (!tmp || !generate) {
return 0;
+ }
- res = generate(chan, tmp, 0, ast_format_rate(ast_channel_writeformat(chan)) / 50);
+ res = generate(chan, tmp, 0, ast_format_get_sample_rate(ast_channel_writeformat(chan)) / 50);
ast_channel_lock(chan);
if (ast_channel_generator(chan) && generate == ast_channel_generator(chan)->generate) {
@@ -3677,11 +3613,9 @@ static void ast_read_generator_actions(struct ast_channel *chan, struct ast_fram
* We must generate frames in phase locked mode since
* we have no internal timer available.
*/
-
- if (ast_format_cmp(&f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
float factor;
-
- factor = ((float) ast_format_rate(ast_channel_writeformat(chan))) / ((float) ast_format_rate(&f->subclass.format));
+ factor = ((float) ast_format_get_sample_rate(ast_channel_writeformat(chan))) / ((float) ast_format_get_sample_rate(f->subclass.format));
samples = (int) (((float) f->samples) * factor);
} else {
samples = f->samples;
@@ -4186,11 +4120,11 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_frfree(f);
f = &ast_null_frame;
}
- } else if ((f->frametype == AST_FRAME_VOICE) && !ast_format_cap_iscompatible(ast_channel_nativeformats(chan), &f->subclass.format)) {
+ } else if ((f->frametype == AST_FRAME_VOICE) && ast_format_cap_iscompatible_format(ast_channel_nativeformats(chan), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
/* This frame is not one of the current native formats -- drop it on the floor */
- char to[200];
+ struct ast_str *codec_buf = ast_str_alloca(64);
ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n",
- ast_channel_name(chan), ast_getformatname(&f->subclass.format), ast_getformatname_multiple(to, sizeof(to), ast_channel_nativeformats(chan)));
+ ast_channel_name(chan), ast_format_get_name(f->subclass.format), ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf));
ast_frfree(f);
f = &ast_null_frame;
} else if ((f->frametype == AST_FRAME_VOICE)) {
@@ -4206,7 +4140,9 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
#ifndef MONITOR_CONSTANT_DELAY
int jump = ast_channel_outsmpl(chan) - ast_channel_insmpl(chan) - 4 * f->samples;
if (jump >= 0) {
- jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)), ast_format_rate(&f->subclass.format), ast_format_rate(&ast_channel_monitor(chan)->read_stream->fmt->format));
+ jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.format),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump, SEEK_FORCECUR) == -1) {
ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
}
@@ -4215,7 +4151,9 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + f->samples);
}
#else
- int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)), ast_format_rate(f->subclass.codec), ast_format_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
+ int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.codec),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
@@ -4748,7 +4686,7 @@ int ast_sendtext(struct ast_channel *chan, const char *text)
}
CHECK_BLOCKING(chan);
- if (ast_channel_tech(chan)->write_text && (ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_TEXT))) {
+ if (ast_channel_tech(chan)->write_text && (ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_TEXT))) {
struct ast_frame f;
f.frametype = AST_FRAME_TEXT;
@@ -4759,7 +4697,7 @@ int ast_sendtext(struct ast_channel *chan, const char *text)
f.offset = 0;
f.seqno = 0;
- ast_format_set(&f.subclass.format, AST_FORMAT_T140, 0);
+ f.subclass.format = ast_format_t140;
res = ast_channel_tech(chan)->write_text(chan, &f);
} else if (ast_channel_tech(chan)->send_text) {
res = ast_channel_tech(chan)->send_text(chan, text);
@@ -4856,7 +4794,7 @@ int ast_prod(struct ast_channel *chan)
/* Send an empty audio frame to get things moving */
if (ast_channel_state(chan) != AST_STATE_UP) {
ast_debug(1, "Prodding channel '%s'\n", ast_channel_name(chan));
- ast_format_copy(&a.subclass.format, ast_channel_rawwriteformat(chan));
+ a.subclass.format = ast_channel_rawwriteformat(chan);
a.data.ptr = nothing + AST_FRIENDLY_OFFSET;
a.src = "ast_prod"; /* this better match check in ast_write */
if (ast_write(chan, &a))
@@ -5068,7 +5006,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
CHECK_BLOCKING(chan);
break;
case AST_FRAME_TEXT:
- if (fr->subclass.integer == AST_FORMAT_T140) {
+ if (ast_format_cmp(fr->subclass.format, ast_format_t140) == AST_FORMAT_CMP_EQUAL) {
res = (ast_channel_tech(chan)->write_text == NULL) ? 0 :
ast_channel_tech(chan)->write_text(chan, fr);
} else {
@@ -5093,17 +5031,17 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
if (ast_channel_tech(chan)->write == NULL)
break; /*! \todo XXX should return 0 maybe ? */
- if (ast_opt_generic_plc && fr->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (ast_opt_generic_plc && ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
apply_plc(chan, fr);
}
/* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */
- if (ast_format_cmp(&fr->subclass.format, ast_channel_rawwriteformat(chan)) != AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) != AST_FORMAT_CMP_NOT_EQUAL) {
f = fr;
} else {
- if ((!ast_format_cap_iscompatible(ast_channel_nativeformats(chan), &fr->subclass.format)) &&
- (ast_format_cmp(ast_channel_writeformat(chan), &fr->subclass.format) != AST_FORMAT_CMP_EQUAL)) {
- char nf[512];
+ if ((ast_format_cap_iscompatible_format(ast_channel_nativeformats(chan), fr->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ (ast_format_cmp(ast_channel_writeformat(chan), fr->subclass.format) != AST_FORMAT_CMP_EQUAL)) {
+ struct ast_str *codec_buf = ast_str_alloca(64);
/*
* XXX Something is not right. We are not compatible with this
@@ -5115,9 +5053,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
* areas.
*/
ast_log(LOG_WARNING, "Codec mismatch on channel %s setting write format to %s from %s native formats %s\n",
- ast_channel_name(chan), ast_getformatname(&fr->subclass.format), ast_getformatname(ast_channel_writeformat(chan)),
- ast_getformatname_multiple(nf, sizeof(nf), ast_channel_nativeformats(chan)));
- ast_set_write_format_by_id(chan, fr->subclass.format.id);
+ ast_channel_name(chan), ast_format_get_name(fr->subclass.format), ast_format_get_name(ast_channel_writeformat(chan)),
+ ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf));
+ ast_set_write_format(chan, fr->subclass.format);
}
f = (ast_channel_writetrans(chan)) ? ast_translate(ast_channel_writetrans(chan), fr, 0) : fr;
@@ -5185,7 +5123,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
#ifndef MONITOR_CONSTANT_DELAY
int jump = ast_channel_insmpl(chan) - ast_channel_outsmpl(chan) - 4 * cur->samples;
if (jump >= 0) {
- jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)), ast_format_rate(&f->subclass.format), ast_format_rate(&ast_channel_monitor(chan)->read_stream->fmt->format));
+ jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.format),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (ast_seekstream(ast_channel_monitor(chan)->write_stream, jump, SEEK_FORCECUR) == -1) {
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
}
@@ -5194,7 +5134,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
ast_channel_outsmpl_set(chan, ast_channel_outsmpl(chan) + cur->samples);
}
#else
- int jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)), ast_format_rate(f->subclass.codec), ast_format_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
+ int jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)),
+ ast_format_get_sample_rate(f->subclass.codec),
+ ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(ast_channel_monitor(chan)->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1) {
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
@@ -5300,21 +5242,23 @@ static int set_format(struct ast_channel *chan,
{
struct ast_trans_pvt *trans_pvt;
struct ast_format_cap *cap_native;
- struct ast_format best_set_fmt;
- struct ast_format best_native_fmt;
+ RAII_VAR(struct ast_format *, best_set_fmt, ast_format_cap_get_format(cap_set, 0), ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_native_fmt, NULL, ao2_cleanup);
int res;
- ast_best_codec(cap_set, &best_set_fmt);
+ ast_assert(format != NULL);
+ ast_assert(rawformat != NULL);
/* See if the underlying channel driver is capable of performing transcoding for us */
if (!ast_channel_setoption(chan, direction ? AST_OPTION_FORMAT_WRITE : AST_OPTION_FORMAT_READ, &best_set_fmt, sizeof(best_set_fmt), 0)) {
ast_debug(1, "Channel driver natively set channel %s to %s format %s\n", ast_channel_name(chan),
- direction ? "write" : "read", ast_getformatname(&best_set_fmt));
+ direction ? "write" : "read", ast_format_get_name(best_set_fmt));
ast_channel_lock(chan);
- ast_format_copy(format, &best_set_fmt);
- ast_format_copy(rawformat, &best_set_fmt);
- ast_format_cap_set(ast_channel_nativeformats(chan), &best_set_fmt);
+ cap_native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_append(cap_native, best_set_fmt, 0);
+ ast_channel_nativeformats_set(chan, cap_native);
+ ao2_cleanup(cap_native);
ast_channel_unlock(chan);
trans_pvt = trans->get(chan);
@@ -5344,31 +5288,27 @@ static int set_format(struct ast_channel *chan,
res = ast_translator_best_choice(cap_native, cap_set, &best_native_fmt, &best_set_fmt);
}
if (res < 0) {
- char from[200];
- char to[200];
+ struct ast_str *codec_from = ast_str_alloca(64);
+ struct ast_str *codec_to = ast_str_alloca(64);
- ast_getformatname_multiple(from, sizeof(from), cap_native);
+ ast_format_cap_get_names(cap_native, &codec_from);
ast_channel_unlock(chan);
- ast_getformatname_multiple(to, sizeof(to), cap_set);
+ ast_format_cap_get_names(cap_set, &codec_to);
ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n",
- from, to);
+ ast_str_buffer(codec_from), ast_str_buffer(codec_to));
return -1;
}
/* Now we have a good choice for both. */
- if ((ast_format_cmp(rawformat, &best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
- (ast_format_cmp(format, &best_set_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
+ if ((ast_format_cmp(rawformat, best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
+ (ast_format_cmp(format, best_set_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || trans->get(chan))) {
/* the channel is already in these formats, so nothing to do */
ast_channel_unlock(chan);
return 0;
}
- ast_format_copy(rawformat, &best_native_fmt);
- /* User perspective is fmt */
- ast_format_copy(format, &best_set_fmt);
-
/* Free any translation we have right now */
trans_pvt = trans->get(chan);
if (trans_pvt) {
@@ -5377,7 +5317,7 @@ static int set_format(struct ast_channel *chan,
}
/* Build a translation path from the raw format to the desired format */
- if (ast_format_cmp(format, rawformat) != AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(best_set_fmt, best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) {
/*
* If we were able to swap the native format to the format that
* has been requested, then there is no need to try to build
@@ -5387,20 +5327,33 @@ static int set_format(struct ast_channel *chan,
} else {
if (!direction) {
/* reading */
- trans_pvt = ast_translator_build_path(format, rawformat);
+ trans_pvt = ast_translator_build_path(best_set_fmt, best_native_fmt);
} else {
/* writing */
- trans_pvt = ast_translator_build_path(rawformat, format);
+ trans_pvt = ast_translator_build_path(best_native_fmt, best_set_fmt);
}
trans->set(chan, trans_pvt);
res = trans_pvt ? 0 : -1;
}
- ast_channel_unlock(chan);
- ast_debug(1, "Set channel %s to %s format %s\n",
- ast_channel_name(chan),
- direction ? "write" : "read",
- ast_getformatname(&best_set_fmt));
+ if (!res) {
+ if (!direction) {
+ /* reading */
+ ast_channel_set_readformat(chan, best_set_fmt);
+ ast_channel_set_rawreadformat(chan, best_native_fmt);
+ } else {
+ /* writing */
+ ast_channel_set_writeformat(chan, best_set_fmt);
+ ast_channel_set_rawwriteformat(chan, best_native_fmt);
+ }
+
+ ast_debug(1, "Set channel %s to %s format %s\n",
+ ast_channel_name(chan),
+ direction ? "write" : "read",
+ ast_format_get_name(best_set_fmt));
+ }
+
+ ast_channel_unlock(chan);
/* If there is a generator on the channel, it needs to know about this
* change if it is the write format. */
@@ -5413,35 +5366,15 @@ static int set_format(struct ast_channel *chan,
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int res;
- if (!cap) {
- return -1;
- }
- ast_format_cap_add(cap, format);
-
- res = set_format(chan,
- cap,
- ast_channel_rawreadformat(chan),
- ast_channel_readformat(chan),
- &set_format_readtrans,
- 0);
-
- ast_format_cap_destroy(cap);
- return res;
-}
-
-int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id)
-{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_format;
- int res;
+ ast_assert(format != NULL);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_format, id, 0));
+ ast_format_cap_append(cap, format, 0);
res = set_format(chan,
cap,
@@ -5450,7 +5383,7 @@ int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id)
&set_format_readtrans,
0);
- ast_format_cap_destroy(cap);
+ ao2_cleanup(cap);
return res;
}
@@ -5466,35 +5399,15 @@ int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
int res;
- if (!cap) {
- return -1;
- }
- ast_format_cap_add(cap, format);
-
- res = set_format(chan,
- cap,
- ast_channel_rawwriteformat(chan),
- ast_channel_writeformat(chan),
- &set_format_writetrans,
- 1);
-
- ast_format_cap_destroy(cap);
- return res;
-}
-
-int ast_set_write_format_by_id(struct ast_channel *chan, enum ast_format_id id)
-{
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_format;
- int res;
+ ast_assert(format != NULL);
if (!cap) {
return -1;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_format, id, 0));
+ ast_format_cap_append(cap, format, 0);
res = set_format(chan,
cap,
@@ -5503,7 +5416,7 @@ int ast_set_write_format_by_id(struct ast_channel *chan, enum ast_format_id id)
&set_format_writetrans,
1);
- ast_format_cap_destroy(cap);
+ ao2_cleanup(cap);
return res;
}
@@ -5912,26 +5825,29 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
AST_RWLIST_TRAVERSE(&backends, chan, list) {
struct ast_format_cap *tmp_cap;
- struct ast_format tmp_fmt;
- struct ast_format best_audio_fmt;
+ RAII_VAR(struct ast_format *, tmp_fmt, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_audio_fmt, NULL, ao2_cleanup);
struct ast_format_cap *joint_cap;
if (strcasecmp(type, chan->tech->type))
continue;
- ast_format_clear(&best_audio_fmt);
/* find the best audio format to use */
- if ((tmp_cap = ast_format_cap_get_type(request_cap, AST_FORMAT_TYPE_AUDIO))) {
+ tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmp_cap) {
+ ast_format_cap_append_from_cap(tmp_cap, request_cap, AST_MEDIA_TYPE_AUDIO);
/* We have audio - is it possible to connect the various calls to each other?
(Avoid this check for calls without audio, like text+video calls)
*/
res = ast_translator_best_choice(tmp_cap, chan->tech->capabilities, &tmp_fmt, &best_audio_fmt);
- ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
if (res < 0) {
- char tmp1[256], tmp2[256];
+ struct ast_str *tech_codecs = ast_str_alloca(64);
+ struct ast_str *request_codecs = ast_str_alloca(64);
+
ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %s) to %s\n", type,
- ast_getformatname_multiple(tmp1, sizeof(tmp1), chan->tech->capabilities),
- ast_getformatname_multiple(tmp2, sizeof(tmp2), request_cap));
+ ast_format_cap_get_names(chan->tech->capabilities, &tech_codecs),
+ ast_format_cap_get_names(request_cap, &request_codecs));
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
AST_RWLIST_UNLOCK(&backends);
return NULL;
@@ -5945,14 +5861,16 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
* purposes is used for the request. This needs to be re-evaluated. It may be
* a better choice to send all the audio formats capable of being translated
* during the request and allow the channel drivers to pick the best one. */
- if (!(joint_cap = ast_format_cap_dup(request_cap))) {
+ joint_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!joint_cap) {
return NULL;
}
- ast_format_cap_remove_bytype(joint_cap, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(joint_cap, &best_audio_fmt);
+ ast_format_cap_append_from_cap(joint_cap, request_cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(joint_cap, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append(joint_cap, best_audio_fmt, 0);
if (!(c = chan->tech->requester(type, joint_cap, assignedids, requestor, addr, cause))) {
- ast_format_cap_destroy(joint_cap);
+ ao2_ref(joint_cap, -1);
return NULL;
}
@@ -5967,7 +5885,7 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
}
}
- joint_cap = ast_format_cap_destroy(joint_cap);
+ ao2_ref(joint_cap, -1);
if (set_security_requirements(requestor, c)) {
ast_log(LOG_WARNING, "Setting security requirements failed\n");
@@ -6164,8 +6082,8 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
{
struct ast_format_cap *src_cap;
struct ast_format_cap *dst_cap;
- struct ast_format best_src_fmt;
- struct ast_format best_dst_fmt;
+ RAII_VAR(struct ast_format *, best_src_fmt, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_dst_fmt, NULL, ao2_cleanup);
int no_path;
ast_channel_lock_both(from, to);
@@ -6182,8 +6100,8 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
dst_cap = ast_channel_nativeformats(to); /* shallow copy, do not destroy */
/* If there's no audio in this call, don't bother with trying to find a translation path */
- if (!ast_format_cap_has_type(src_cap, AST_FORMAT_TYPE_AUDIO)
- || !ast_format_cap_has_type(dst_cap, AST_FORMAT_TYPE_AUDIO)) {
+ if (!ast_format_cap_has_type(src_cap, AST_MEDIA_TYPE_AUDIO)
+ || !ast_format_cap_has_type(dst_cap, AST_MEDIA_TYPE_AUDIO)) {
ast_channel_unlock(to);
ast_channel_unlock(from);
return 0;
@@ -6206,28 +6124,29 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
* no direct conversion available. If generic PLC is
* desired, then transcoding via SLINEAR is a requirement
*/
- if (ast_format_cmp(&best_dst_fmt, &best_src_fmt) == AST_FORMAT_CMP_NOT_EQUAL
+ if (ast_format_cmp(best_dst_fmt, best_src_fmt) == AST_FORMAT_CMP_NOT_EQUAL
&& (ast_opt_generic_plc || ast_opt_transcode_via_slin)) {
- int use_slin = (ast_format_is_slinear(&best_src_fmt)
- || ast_format_is_slinear(&best_dst_fmt)) ? 1 : 0;
+ int use_slin = (ast_format_cache_is_slinear(best_src_fmt)
+ || ast_format_cache_is_slinear(best_dst_fmt)) ? 1 : 0;
- if (use_slin || ast_translate_path_steps(&best_dst_fmt, &best_src_fmt) != 1) {
- int best_sample_rate = (ast_format_rate(&best_src_fmt) > ast_format_rate(&best_dst_fmt)) ?
- ast_format_rate(&best_src_fmt) : ast_format_rate(&best_dst_fmt);
+ if (use_slin || ast_translate_path_steps(best_dst_fmt, best_src_fmt) != 1) {
+ int best_sample_rate = (ast_format_get_sample_rate(best_src_fmt) > ast_format_get_sample_rate(best_dst_fmt)) ?
+ ast_format_get_sample_rate(best_src_fmt) : ast_format_get_sample_rate(best_dst_fmt);
/* pick the best signed linear format based upon what preserves the sample rate the best. */
- ast_format_set(&best_src_fmt, ast_format_slin_by_rate(best_sample_rate), 0);
+ ao2_ref(best_src_fmt, -1);
+ best_src_fmt = ao2_bump(ast_format_cache_get_slin_by_rate(best_sample_rate));
}
}
- if (ast_set_read_format(from, &best_src_fmt)) {
+ if (ast_set_read_format(from, best_src_fmt)) {
ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n",
- ast_channel_name(from), ast_getformatname(&best_src_fmt));
+ ast_channel_name(from), ast_format_get_name(best_src_fmt));
return -1;
}
- if (ast_set_write_format(to, &best_src_fmt)) {
+ if (ast_set_write_format(to, best_src_fmt)) {
ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n",
- ast_channel_name(to), ast_getformatname(&best_src_fmt));
+ ast_channel_name(to), ast_format_get_name(best_src_fmt));
return -1;
}
return 0;
@@ -6387,9 +6306,10 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
struct ast_party_redirecting redirecting;
} exchange;
struct ast_channel *bridged;
- struct ast_format rformat;
- struct ast_format wformat;
- struct ast_format tmp_format;
+ struct ast_format *rformat;
+ struct ast_format *wformat;
+ struct ast_format *tmp_format;
+ struct ast_format_cap *tmp_cap;
char tmp_name[AST_CHANNEL_NAME];
char clone_sending_dtmf_digit;
struct timeval clone_sending_dtmf_tv;
@@ -6446,8 +6366,8 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
* Remember the original read/write formats. We turn off any
* translation on either one
*/
- ast_format_copy(&rformat, ast_channel_readformat(original));
- ast_format_copy(&wformat, ast_channel_writeformat(original));
+ rformat = ao2_bump(ast_channel_readformat(original));
+ wformat = ao2_bump(ast_channel_writeformat(original));
free_translation(clonechan);
free_translation(original);
@@ -6508,13 +6428,15 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
}
/* Swap the raw formats */
- ast_format_copy(&tmp_format, ast_channel_rawreadformat(original));
- ast_format_copy(ast_channel_rawreadformat(original), ast_channel_rawreadformat(clonechan));
- ast_format_copy(ast_channel_rawreadformat(clonechan), &tmp_format);
+ tmp_format = ao2_bump(ast_channel_rawreadformat(original));
+ ast_channel_set_rawreadformat(original, ast_channel_rawreadformat(clonechan));
+ ast_channel_set_rawreadformat(clonechan, tmp_format);
+ ao2_cleanup(tmp_format);
- ast_format_copy(&tmp_format, ast_channel_rawwriteformat(original));
- ast_format_copy(ast_channel_rawwriteformat(original), ast_channel_rawwriteformat(clonechan));
- ast_format_copy(ast_channel_rawwriteformat(clonechan), &tmp_format);
+ tmp_format = ao2_bump(ast_channel_rawwriteformat(original));
+ ast_channel_set_rawwriteformat(original, ast_channel_rawwriteformat(clonechan));
+ ast_channel_set_rawwriteformat(clonechan, tmp_format);
+ ao2_cleanup(tmp_format);
ast_channel_softhangup_internal_flag_set(clonechan, AST_SOFTHANGUP_DEV);
@@ -6642,16 +6564,21 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
ast_channel_set_fd(original, AST_TIMING_FD, ast_channel_timingfd(original));
/* Our native formats are different now */
- ast_format_cap_copy(ast_channel_nativeformats(original), ast_channel_nativeformats(clonechan));
+ tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (tmp_cap) {
+ ast_format_cap_append_from_cap(tmp_cap, ast_channel_nativeformats(clonechan), AST_MEDIA_TYPE_UNKNOWN);
+ ast_channel_nativeformats_set(original, tmp_cap);
+ ao2_ref(tmp_cap, -1);
+ }
/* Context, extension, priority, app data, jump table, remain the same */
/* pvt switches. pbx stays the same, as does next */
/* Set the write format */
- ast_set_write_format(original, &wformat);
+ ast_set_write_format(original, wformat);
/* Set the read format */
- ast_set_read_format(original, &rformat);
+ ast_set_read_format(original, rformat);
/* Copy the music class */
ast_channel_musicclass_set(original, ast_channel_musicclass(clonechan));
@@ -6660,7 +6587,7 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
ast_channel_accountcode_set(original, S_OR(ast_channel_accountcode(clonechan), ""));
ast_debug(1, "Putting channel %s in %s/%s formats\n", ast_channel_name(original),
- ast_getformatname(&wformat), ast_getformatname(&rformat));
+ ast_format_get_name(wformat), ast_format_get_name(rformat));
/* Fixup the original clonechan's physical side */
if (ast_channel_tech(original)->fixup && ast_channel_tech(original)->fixup(clonechan, original)) {
@@ -6773,6 +6700,9 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
/* Release our held safety references. */
ast_channel_unref(original);
ast_channel_unref(clonechan);
+
+ ao2_cleanup(rformat);
+ ao2_cleanup(wformat);
}
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
@@ -6917,7 +6847,7 @@ struct tonepair_state {
int v1_2;
int v2_2;
int v3_2;
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
int pos;
int duration;
int modulate;
@@ -6930,8 +6860,10 @@ static void tonepair_release(struct ast_channel *chan, void *params)
{
struct tonepair_state *ts = params;
- if (chan)
- ast_set_write_format(chan, &ts->origwfmt);
+ if (chan) {
+ ast_set_write_format(chan, ts->origwfmt);
+ }
+ ao2_cleanup(ts->origwfmt);
ast_free(ts);
}
@@ -6940,10 +6872,12 @@ static void *tonepair_alloc(struct ast_channel *chan, void *params)
struct tonepair_state *ts;
struct tonepair_def *td = params;
- if (!(ts = ast_calloc(1, sizeof(*ts))))
+ if (!(ts = ast_calloc(1, sizeof(*ts)))) {
return NULL;
- ast_format_copy(&ts->origwfmt, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ }
+
+ ts->origwfmt = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", ast_channel_name(chan));
tonepair_release(NULL, ts);
ts = NULL;
@@ -6997,7 +6931,7 @@ static int tonepair_generator(struct ast_channel *chan, void *data, int len, int
ts->data[x] = ts->v3_1 + ts->v3_2;
}
ts->f.frametype = AST_FRAME_VOICE;
- ast_format_set(&ts->f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ ts->f.subclass.format = ast_format_slin;
ts->f.datalen = len;
ts->f.samples = samples;
ts->f.offset = AST_FRIENDLY_OFFSET;
@@ -7675,7 +7609,7 @@ static int silence_generator_generate(struct ast_channel *chan, void *data, int
.samples = samples,
.datalen = sizeof(buf),
};
- ast_format_set(&frame.subclass.format, AST_FORMAT_SLINEAR, 0);
+ frame.subclass.format = ast_format_slin;
memset(buf, 0, sizeof(buf));
@@ -7692,7 +7626,7 @@ static struct ast_generator silence_generator = {
};
struct ast_silence_generator {
- struct ast_format old_write_format;
+ struct ast_format *old_write_format;
};
struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan)
@@ -7703,9 +7637,9 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha
return NULL;
}
- ast_format_copy(&state->old_write_format, ast_channel_writeformat(chan));
+ state->old_write_format = ao2_bump(ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n");
ast_free(state);
return NULL;
@@ -7749,9 +7683,11 @@ void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_sil
if (deactivate_silence_generator(chan)) {
ast_debug(1, "Stopped silence generator on '%s'\n", ast_channel_name(chan));
- if (ast_set_write_format(chan, &state->old_write_format) < 0)
+ if (ast_set_write_format(chan, state->old_write_format) < 0) {
ast_log(LOG_ERROR, "Could not return write format to its original state\n");
+ }
}
+ ao2_cleanup(state->old_write_format);
ast_free(state);
}
@@ -10199,8 +10135,8 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
char *context;
char *name;
int amaflags;
- struct ast_format readformat;
- struct ast_format writeformat;
+ struct ast_format *readformat;
+ struct ast_format *writeformat;
} my_vars = { 0, };
ast_channel_lock(yankee);
@@ -10209,8 +10145,8 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
my_vars.context = ast_strdupa(ast_channel_context(yankee));
my_vars.name = ast_strdupa(ast_channel_name(yankee));
my_vars.amaflags = ast_channel_amaflags(yankee);
- ast_format_copy(&my_vars.writeformat, ast_channel_writeformat(yankee));
- ast_format_copy(&my_vars.readformat, ast_channel_readformat(yankee));
+ my_vars.writeformat = ao2_bump(ast_channel_writeformat(yankee));
+ my_vars.readformat = ao2_bump(ast_channel_readformat(yankee));
ast_channel_unlock(yankee);
/* Do not hold any channel locks while calling channel_alloc() since the function
@@ -10218,12 +10154,16 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
if (!(yanked_chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, my_vars.accountcode,
my_vars.exten, my_vars.context, NULL, yankee, my_vars.amaflags,
"Surrogate/%s", my_vars.name))) {
+ ao2_cleanup(my_vars.writeformat);
+ ao2_cleanup(my_vars.readformat);
return NULL;
}
/* Make formats okay */
- ast_format_copy(ast_channel_readformat(yanked_chan), &my_vars.readformat);
- ast_format_copy(ast_channel_writeformat(yanked_chan), &my_vars.writeformat);
+ ast_channel_set_readformat(yanked_chan, my_vars.readformat);
+ ast_channel_set_writeformat(yanked_chan, my_vars.writeformat);
+ ao2_cleanup(my_vars.readformat);
+ ao2_cleanup(my_vars.writeformat);
ast_channel_unlock(yanked_chan);
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index c2dc2d737..4ad0ef3a0 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -176,7 +176,7 @@ struct ast_channel {
int fdno; /*!< Which fd had an event detected on */
int streamid; /*!< For streaming playback, the schedule ID */
int vstreamid; /*!< For streaming video playback, the schedule ID */
- struct ast_format oldwriteformat; /*!< Original writer format */
+ struct ast_format *oldwriteformat; /*!< Original writer format */
int timingfd; /*!< Timing fd */
enum ast_channel_state state; /*!< State of line -- Don't write directly, use ast_setstate() */
int rings; /*!< Number of rings so far */
@@ -193,10 +193,10 @@ struct ast_channel {
struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */
int alertpipe[2];
struct ast_format_cap *nativeformats; /*!< Kinds of data this channel can natively handle */
- struct ast_format readformat; /*!< Requested read format (after translation) */
- struct ast_format writeformat; /*!< Requested write format (after translation) */
- struct ast_format rawreadformat; /*!< Raw read format (before translation) */
- struct ast_format rawwriteformat; /*!< Raw write format (before translation) */
+ struct ast_format *readformat; /*!< Requested read format (after translation) */
+ struct ast_format *writeformat; /*!< Requested write format (after translation) */
+ struct ast_format *rawreadformat; /*!< Raw read format (before translation) */
+ struct ast_format *rawwriteformat; /*!< Raw write format (before translation) */
unsigned int emulate_dtmf_duration; /*!< Number of ms left to emulate DTMF for */
#ifdef HAVE_EPOLL
int epfd;
@@ -826,7 +826,8 @@ struct ast_format_cap *ast_channel_nativeformats(const struct ast_channel *chan)
}
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
{
- chan->nativeformats = value;
+ ao2_cleanup(chan->nativeformats);
+ chan->nativeformats = ao2_bump(value);
}
struct ast_framehook_list *ast_channel_framehooks(const struct ast_channel *chan)
{
@@ -949,25 +950,50 @@ void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state valu
{
chan->state = value;
}
+void ast_channel_set_oldwriteformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->oldwriteformat);
+ chan->oldwriteformat = ao2_bump(format);
+}
+void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->rawreadformat);
+ chan->rawreadformat = ao2_bump(format);
+}
+void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->rawwriteformat);
+ chan->rawwriteformat = ao2_bump(format);
+}
+void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->readformat);
+ chan->readformat = ao2_bump(format);
+}
+void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
+{
+ ao2_cleanup(chan->writeformat);
+ chan->writeformat = ao2_bump(format);
+}
struct ast_format *ast_channel_oldwriteformat(struct ast_channel *chan)
{
- return &chan->oldwriteformat;
+ return chan->oldwriteformat;
}
struct ast_format *ast_channel_rawreadformat(struct ast_channel *chan)
{
- return &chan->rawreadformat;
+ return chan->rawreadformat;
}
struct ast_format *ast_channel_rawwriteformat(struct ast_channel *chan)
{
- return &chan->rawwriteformat;
+ return chan->rawwriteformat;
}
struct ast_format *ast_channel_readformat(struct ast_channel *chan)
{
- return &chan->readformat;
+ return chan->readformat;
}
struct ast_format *ast_channel_writeformat(struct ast_channel *chan)
{
- return &chan->writeformat;
+ return chan->writeformat;
}
struct ast_hangup_handler_list *ast_channel_hangup_handlers(struct ast_channel *chan)
{
diff --git a/main/cli.c b/main/cli.c
index bff58695d..bb8e33e44 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -1521,9 +1521,9 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
long elapsed_seconds=0;
int hour=0, min=0, sec=0;
struct ast_var_t *var;
- char nativeformats[256];
struct ast_str *write_transpath = ast_str_alloca(256);
struct ast_str *read_transpath = ast_str_alloca(256);
+ struct ast_str *codec_buf = ast_str_alloca(64);
struct ast_bridge *bridge;
struct ast_callid *callid;
char callid_buf[32];
@@ -1634,9 +1634,9 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
ast_channel_language(chan),
ast_state2str(ast_channel_state(chan)),
ast_channel_state(chan),
- ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)),
- ast_getformatname(ast_channel_writeformat(chan)),
- ast_getformatname(ast_channel_readformat(chan)),
+ ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
+ ast_format_get_name(ast_channel_writeformat(chan)),
+ ast_format_get_name(ast_channel_readformat(chan)),
ast_str_strlen(write_transpath) ? "Yes" : "No",
ast_str_buffer(write_transpath),
ast_str_strlen(read_transpath) ? "Yes" : "No",
diff --git a/main/codec.c b/main/codec.c
new file mode 100644
index 000000000..e060efe3e
--- /dev/null
+++ b/main/codec.c
@@ -0,0 +1,381 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Codecs API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/frame.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/strings.h"
+#include "asterisk/module.h"
+#include "asterisk/cli.h"
+
+/*! \brief Number of buckets to use for codecs (should be prime for performance reasons) */
+#define CODEC_BUCKETS 53
+
+/*! \brief Current identifier value for newly registered codec */
+static int codec_id = 1;
+
+/*! \brief Registered codecs */
+static struct ao2_container *codecs;
+
+static int codec_hash(const void *obj, int flags)
+{
+ const struct ast_codec *codec;
+ const char *key;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_KEY:
+ key = obj;
+ return ast_str_hash(key);
+ case OBJ_SEARCH_OBJECT:
+ codec = obj;
+ return ast_str_hash(codec->name);
+ default:
+ /* Hash can only work on something with a full key. */
+ ast_assert(0);
+ return 0;
+ }
+}
+
+static int codec_cmp(void *obj, void *arg, int flags)
+{
+ const struct ast_codec *left = obj;
+ const struct ast_codec *right = arg;
+ const char *right_key = arg;
+ int cmp;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right->name;
+ cmp = strcmp(left->name, right_key);
+
+ if (right->type != AST_MEDIA_TYPE_UNKNOWN) {
+ cmp |= (right->type != left->type);
+ }
+
+ /* BUGBUG: this will allow a match on a codec by name only.
+ * This is particularly useful when executed by the CLI; if
+ * that is not needed in translate.c, this can be removed.
+ */
+ if (right->sample_rate) {
+ cmp |= (right->sample_rate != left->sample_rate);
+ }
+ break;
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left->name, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left->name, right_key, strlen(right_key));
+ break;
+ default:
+ ast_assert(0);
+ cmp = 0;
+ break;
+ }
+ if (cmp) {
+ return 0;
+ }
+
+ return CMP_MATCH;
+}
+
+static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ struct ao2_iterator i;
+ struct ast_codec *codec;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core show codecs [audio|video|image|text]";
+ e->usage =
+ "Usage: core show codecs [audio|video|image|text]\n"
+ " Displays codec mapping\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if ((a->argc < 3) || (a->argc > 4)) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (!ast_opt_dont_warn) {
+ ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
+ "\tIt does not indicate anything about your configuration.\n");
+ }
+
+ ast_cli(a->fd, "%8s %5s %8s %s\n","ID","TYPE","NAME","DESCRIPTION");
+ ast_cli(a->fd, "-----------------------------------------------------------------------------------\n");
+
+ ao2_rdlock(codecs);
+ i = ao2_iterator_init(codecs, AO2_ITERATOR_DONTLOCK);
+
+ for (; (codec = ao2_iterator_next(&i)); ao2_ref(codec, -1)) {
+ if (a->argc == 4) {
+ if (!strcasecmp(a->argv[3], "audio")) {
+ if (codec->type != AST_MEDIA_TYPE_AUDIO) {
+ continue;
+ }
+ } else if (!strcasecmp(a->argv[3], "video")) {
+ if (codec->type != AST_MEDIA_TYPE_VIDEO) {
+ continue;
+ }
+ } else if (!strcasecmp(a->argv[3], "image")) {
+ if (codec->type != AST_MEDIA_TYPE_IMAGE) {
+ continue;
+ }
+ } else if (!strcasecmp(a->argv[3], "text")) {
+ if (codec->type != AST_MEDIA_TYPE_TEXT) {
+ continue;
+ }
+ } else {
+ continue;
+ }
+ }
+
+ ast_cli(a->fd, "%8u %5s %8s (%s)\n",
+ codec->id,
+ ast_codec_media_type2str(codec->type),
+ codec->name,
+ codec->description);
+ }
+
+ ao2_iterator_destroy(&i);
+ ao2_unlock(codecs);
+
+ return CLI_SUCCESS;
+}
+
+/*! \brief Callback function for getting a codec based on unique identifier */
+static int codec_id_cmp(void *obj, void *arg, int flags)
+{
+ struct ast_codec *codec = obj;
+ int *id = arg;
+
+ return (codec->id == *id) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+static char *show_codec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int type_punned_codec;
+ struct ast_codec *codec;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core show codec";
+ e->usage =
+ "Usage: core show codec <number>\n"
+ " Displays codec mapping\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (sscanf(a->argv[3], "%30d", &type_punned_codec) != 1) {
+ return CLI_SHOWUSAGE;
+ }
+
+ codec = ao2_callback(codecs, 0, codec_id_cmp, &type_punned_codec);
+ if (!codec) {
+ ast_cli(a->fd, "Codec %d not found\n", type_punned_codec);
+ return CLI_SUCCESS;
+ }
+
+ ast_cli(a->fd, "%11u %s\n", (unsigned int) codec->id, codec->description);
+
+ ao2_ref(codec, -1);
+
+ return CLI_SUCCESS;
+}
+
+/* Builtin Asterisk CLI-commands for debugging */
+static struct ast_cli_entry codec_cli[] = {
+ AST_CLI_DEFINE(show_codecs, "Displays a list of registered codecs"),
+ AST_CLI_DEFINE(show_codec, "Shows a specific codec"),
+};
+
+/*! \brief Function called when the process is shutting down */
+static void codec_shutdown(void)
+{
+ ast_cli_unregister_multiple(codec_cli, ARRAY_LEN(codec_cli));
+ ao2_cleanup(codecs);
+ codecs = NULL;
+}
+
+int ast_codec_init(void)
+{
+ codecs = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CODEC_BUCKETS, codec_hash, codec_cmp);
+ if (!codecs) {
+ return -1;
+ }
+
+ ast_cli_register_multiple(codec_cli, ARRAY_LEN(codec_cli));
+ ast_register_atexit(codec_shutdown);
+
+ return 0;
+}
+
+static void codec_dtor(void *obj)
+{
+ struct ast_codec *codec;
+
+ codec = obj;
+
+ ast_module_unref(codec->mod);
+}
+
+int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
+{
+ SCOPED_AO2WRLOCK(lock, codecs);
+ struct ast_codec *codec_new;
+
+ /* Some types have specific requirements */
+ if (codec->type == AST_MEDIA_TYPE_UNKNOWN) {
+ ast_log(LOG_ERROR, "A media type must be specified for codec '%s'\n", codec->name);
+ return -1;
+ } else if (codec->type == AST_MEDIA_TYPE_AUDIO) {
+ if (!codec->sample_rate) {
+ ast_log(LOG_ERROR, "A sample rate must be specified for codec '%s' of type '%s'\n",
+ codec->name, ast_codec_media_type2str(codec->type));
+ return -1;
+ }
+ }
+
+ codec_new = ao2_find(codecs, codec, OBJ_SEARCH_OBJECT | OBJ_NOLOCK);
+ if (codec_new) {
+ ast_log(LOG_ERROR, "A codec with name '%s' of type '%s' and sample rate '%u' is already registered\n",
+ codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
+ ao2_ref(codec_new, -1);
+ return -1;
+ }
+
+ codec_new = ao2_t_alloc_options(sizeof(*codec_new), codec_dtor,
+ AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
+ if (!codec_new) {
+ ast_log(LOG_ERROR, "Could not allocate a codec with name '%s' of type '%s' and sample rate '%u'\n",
+ codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
+ return -1;
+ }
+ *codec_new = *codec;
+ codec_new->id = codec_id++;
+
+ ao2_link_flags(codecs, codec_new, OBJ_NOLOCK);
+
+ /* Once registered a codec can not be unregistered, and the module must persist */
+ ast_module_ref(mod);
+
+ ast_verb(2, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n",
+ ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->id);
+
+ ao2_ref(codec_new, -1);
+
+ return 0;
+}
+
+struct ast_codec *ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate)
+{
+ struct ast_codec codec = {
+ .name = name,
+ .type = type,
+ .sample_rate = sample_rate,
+ };
+
+ return ao2_find(codecs, &codec, OBJ_SEARCH_OBJECT);
+}
+
+struct ast_codec *ast_codec_get_by_id(int id)
+{
+ return ao2_callback(codecs, 0, codec_id_cmp, &id);
+}
+
+int ast_codec_get_max(void)
+{
+ return codec_id;
+}
+
+const char *ast_codec_media_type2str(enum ast_media_type type)
+{
+ switch (type) {
+ case AST_MEDIA_TYPE_AUDIO:
+ return "audio";
+ case AST_MEDIA_TYPE_VIDEO:
+ return "video";
+ case AST_MEDIA_TYPE_IMAGE:
+ return "image";
+ case AST_MEDIA_TYPE_TEXT:
+ return "text";
+ default:
+ return "<unknown>";
+ }
+}
+
+unsigned int ast_codec_samples_count(struct ast_frame *frame)
+{
+ struct ast_codec *codec;
+ unsigned int samples = 0;
+
+ if ((frame->frametype != AST_FRAME_VOICE) &&
+ (frame->frametype != AST_FRAME_VIDEO) &&
+ (frame->frametype != AST_FRAME_IMAGE)) {
+ return 0;
+ }
+
+ /* BUGBUG - why not just get the codec pointer off the format?
+ This is a bit roundabout
+ */
+ codec = ast_codec_get_by_id(ast_format_get_codec_id(frame->subclass.format));
+
+ if (codec->samples_count) {
+ samples = codec->samples_count(frame);
+ } else {
+ ast_log(LOG_WARNING, "Unable to calculate samples for codec %s\n",
+ ast_format_get_name(frame->subclass.format));
+ }
+
+ ao2_ref(codec, -1);
+ return samples;
+}
+
+unsigned int ast_codec_determine_length(const struct ast_codec *codec, unsigned int samples)
+{
+ if (!codec->get_length) {
+ return 0;
+ }
+
+ return codec->get_length(samples);
+}
diff --git a/main/codec_builtin.c b/main/codec_builtin.c
new file mode 100644
index 000000000..594074aa4
--- /dev/null
+++ b/main/codec_builtin.c
@@ -0,0 +1,845 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Built-in supported codecs
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/frame.h"
+
+enum frame_type {
+ TYPE_HIGH, /* 0x0 */
+ TYPE_LOW, /* 0x1 */
+ TYPE_SILENCE, /* 0x2 */
+ TYPE_DONTSEND /* 0x3 */
+};
+
+#define TYPE_MASK 0x3
+
+static int g723_len(unsigned char buf)
+{
+ enum frame_type type = buf & TYPE_MASK;
+
+ switch(type) {
+ case TYPE_DONTSEND:
+ return 0;
+ break;
+ case TYPE_SILENCE:
+ return 4;
+ break;
+ case TYPE_HIGH:
+ return 24;
+ break;
+ case TYPE_LOW:
+ return 20;
+ break;
+ default:
+ ast_log(LOG_WARNING, "Badly encoded frame (%u)\n", type);
+ }
+ return -1;
+}
+
+static int g723_samples(struct ast_frame *frame)
+{
+ unsigned char *buf = frame->data.ptr;
+ int pos = 0, samples = 0, res;
+
+ while(pos < frame->datalen) {
+ res = g723_len(buf[pos]);
+ if (res <= 0)
+ break;
+ samples += 240;
+ pos += res;
+ }
+
+ return samples;
+}
+
+static int g723_length(unsigned int samples)
+{
+ return (samples / 240) * 20;
+}
+
+static struct ast_codec g723 = {
+ .name = "g723",
+ .description = "G.723.1",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 30,
+ .maximum_ms = 300,
+ .default_ms = 30,
+ .minimum_bytes = 20,
+ .samples_count = g723_samples,
+ .get_length = g723_length,
+};
+
+static int none_samples(struct ast_frame *frame)
+{
+ return frame->datalen;
+}
+
+static int none_length(unsigned int samples) {
+ return samples;
+}
+
+static struct ast_codec none = {
+ .name = "none",
+ .description = "<Null> codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000, /* This must have some sample rate to prevent divide by 0 */
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 20,
+ .samples_count = none_samples,
+ .get_length = none_length,
+};
+
+static int ulaw_samples(struct ast_frame *frame)
+{
+ return frame->datalen;
+}
+
+static int ulaw_length(unsigned int samples)
+{
+ return samples;
+}
+
+static struct ast_codec ulaw = {
+ .name = "ulaw",
+ .description = "G.711 u-law",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = ulaw_samples,
+ .get_length = ulaw_length,
+ .smooth = 1,
+};
+
+static struct ast_codec alaw = {
+ .name = "alaw",
+ .description = "G.711 a-law",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = ulaw_samples,
+ .get_length = ulaw_length,
+ .smooth = 1,
+};
+
+static int gsm_samples(struct ast_frame *frame)
+{
+ return 160 * (frame->datalen / 33);
+}
+
+static int gsm_length(unsigned int samples)
+{
+ return (samples / 160) * 33;
+}
+
+static struct ast_codec gsm = {
+ .name = "gsm",
+ .description = "GSM",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 20,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 33,
+ .samples_count = gsm_samples,
+ .get_length = gsm_length,
+ .smooth = 1,
+};
+
+static int g726_samples(struct ast_frame *frame)
+{
+ return frame->datalen * 2;
+}
+
+static int g726_length(unsigned int samples)
+{
+ return samples / 2;
+}
+
+static struct ast_codec g726rfc3551 = {
+ .name = "g726",
+ .description = "G.726 RFC3551",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 40,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static struct ast_codec g726aal2 = {
+ .name = "g726aal2",
+ .description = "G.726 AAL2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 40,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static struct ast_codec adpcm = {
+ .name = "adpcm",
+ .description = "Dialogic ADPCM",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 40,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static int slin_samples(struct ast_frame *frame)
+{
+ return frame->datalen / 2;
+}
+
+static int slin_length(unsigned int samples)
+{
+ return samples * 2;
+}
+
+static struct ast_codec slin8 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 160,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin12 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (12kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 12000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 240,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin16 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (16kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 320,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin24 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (24kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 24000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 480,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin32 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (32kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 640,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin44 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (44kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 44100,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 882,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin48 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (48kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 960,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin96 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (96kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 96000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 1920,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static struct ast_codec slin192 = {
+ .name = "slin",
+ .description = "16 bit Signed Linear PCM (192kHz)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 192000,
+ .minimum_ms = 10,
+ .maximum_ms = 70,
+ .default_ms = 20,
+ .minimum_bytes = 3840,
+ .samples_count = slin_samples,
+ .get_length = slin_length,
+ .smooth = 1,
+};
+
+static int lpc10_samples(struct ast_frame *frame)
+{
+ int samples = 22 * 8;
+
+ /* assumes that the RTP packet contains one LPC10 frame */
+ samples += (((char *)(frame->data.ptr))[7] & 0x1) * 8;
+
+ return samples;
+}
+
+static struct ast_codec lpc10 = {
+ .name = "lpc10",
+ .description = "LPC10",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 20,
+ .maximum_ms = 20,
+ .default_ms = 20,
+ .minimum_bytes = 7,
+ .samples_count = lpc10_samples,
+ .smooth = 1,
+};
+
+static int g729_samples(struct ast_frame *frame)
+{
+ return frame->datalen * 8;
+}
+
+static int g729_length(unsigned int samples)
+{
+ return samples / 8;
+}
+
+static struct ast_codec g729a = {
+ .name = "g729",
+ .description = "G.729A",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 230,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = g729_samples,
+ .get_length = g729_length,
+ .smooth = 1,
+};
+
+static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
+{
+ int byte = bit / 8; /* byte containing first bit */
+ int rem = 8 - (bit % 8); /* remaining bits in first byte */
+ unsigned char ret = 0;
+
+ if (n <= 0 || n > 8)
+ return 0;
+
+ if (rem < n) {
+ ret = (data[byte] << (n - rem));
+ ret |= (data[byte + 1] >> (8 - n + rem));
+ } else {
+ ret = (data[byte] >> (rem - n));
+ }
+
+ return (ret & (0xff >> (8 - n)));
+}
+
+static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
+{
+ static const int SpeexWBSubModeSz[] = {
+ 4, 36, 112, 192,
+ 352, 0, 0, 0 };
+ int off = bit;
+ unsigned char c;
+
+ /* skip up to two wideband frames */
+ if (((len * 8 - off) >= 5) &&
+ get_n_bits_at(data, 1, off)) {
+ c = get_n_bits_at(data, 3, off + 1);
+ off += SpeexWBSubModeSz[c];
+
+ if (((len * 8 - off) >= 5) &&
+ get_n_bits_at(data, 1, off)) {
+ c = get_n_bits_at(data, 3, off + 1);
+ off += SpeexWBSubModeSz[c];
+
+ if (((len * 8 - off) >= 5) &&
+ get_n_bits_at(data, 1, off)) {
+ ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
+ return -1;
+ }
+ }
+
+ }
+ return off - bit;
+}
+
+static int speex_samples(unsigned char *data, int len)
+{
+ static const int SpeexSubModeSz[] = {
+ 5, 43, 119, 160,
+ 220, 300, 364, 492,
+ 79, 0, 0, 0,
+ 0, 0, 0, 0 };
+ static const int SpeexInBandSz[] = {
+ 1, 1, 4, 4,
+ 4, 4, 4, 4,
+ 8, 8, 16, 16,
+ 32, 32, 64, 64 };
+ int bit = 0;
+ int cnt = 0;
+ int off;
+ unsigned char c;
+
+ while ((len * 8 - bit) >= 5) {
+ /* skip wideband frames */
+ off = speex_get_wb_sz_at(data, len, bit);
+ if (off < 0) {
+ ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
+ break;
+ }
+ bit += off;
+
+ if ((len * 8 - bit) < 5)
+ break;
+
+ /* get control bits */
+ c = get_n_bits_at(data, 5, bit);
+ bit += 5;
+
+ if (c == 15) {
+ /* terminator */
+ break;
+ } else if (c == 14) {
+ /* in-band signal; next 4 bits contain signal id */
+ c = get_n_bits_at(data, 4, bit);
+ bit += 4;
+ bit += SpeexInBandSz[c];
+ } else if (c == 13) {
+ /* user in-band; next 4 bits contain msg len */
+ c = get_n_bits_at(data, 4, bit);
+ bit += 4;
+ /* after which it's 5-bit signal id + c bytes of data */
+ bit += 5 + c * 8;
+ } else if (c > 8) {
+ /* unknown */
+ ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
+ break;
+ } else {
+ /* skip number bits for submode (less the 5 control bits) */
+ bit += SpeexSubModeSz[c] - 5;
+ cnt += 160; /* new frame */
+ }
+ }
+ return cnt;
+}
+
+static int speex8_samples(struct ast_frame *frame)
+{
+ return speex_samples(frame->data.ptr, frame->datalen);
+}
+
+static struct ast_codec speex8 = {
+ .name = "speex",
+ .description = "SpeeX",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = speex8_samples,
+};
+
+static int speex16_samples(struct ast_frame *frame)
+{
+ return 2 * speex_samples(frame->data.ptr, frame->datalen);
+}
+
+static struct ast_codec speex16 = {
+ .name = "speex",
+ .description = "SpeeX 16khz",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 10,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = speex16_samples,
+};
+
+static int speex32_samples(struct ast_frame *frame)
+{
+ return 4 * speex_samples(frame->data.ptr, frame->datalen);
+}
+
+static struct ast_codec speex32 = {
+ .name = "speex",
+ .description = "SpeeX 32khz",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ .minimum_ms = 10,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+ .samples_count = speex32_samples,
+};
+
+static int ilbc_samples(struct ast_frame *frame)
+{
+ return 240 * (frame->datalen / 50);
+}
+
+static struct ast_codec ilbc = {
+ .name = "ilbc",
+ .description = "iLBC",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 30,
+ .maximum_ms = 30,
+ .default_ms = 30,
+ .minimum_bytes = 50,
+ .samples_count = ilbc_samples,
+ .smooth = 1,
+};
+
+static struct ast_codec g722 = {
+ .name = "g722",
+ .description = "G722",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = g726_samples,
+ .get_length = g726_length,
+ .smooth = 1,
+};
+
+static int siren7_samples(struct ast_frame *frame)
+{
+ return frame->datalen * (16000 / 4000);
+}
+
+static int siren7_length(unsigned int samples)
+{
+ return samples / (16000 / 4000);
+}
+
+static struct ast_codec siren7 = {
+ .name = "siren7",
+ .description = "ITU G.722.1 (Siren7, licensed from Polycom)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 16000,
+ .minimum_ms = 20,
+ .maximum_ms = 80,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = siren7_samples,
+ .get_length = siren7_length,
+};
+
+static int siren14_samples(struct ast_frame *frame)
+{
+ return (int) frame->datalen * ((float) 32000 / 6000);
+}
+
+static int siren14_length(unsigned int samples)
+{
+ return (int) samples / ((float) 32000 / 6000);;
+}
+
+static struct ast_codec siren14 = {
+ .name = "siren14",
+ .description = "ITU G.722.1 Annex C, (Siren14, licensed from Polycom)",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 32000,
+ .minimum_ms = 20,
+ .maximum_ms = 80,
+ .default_ms = 20,
+ .minimum_bytes = 120,
+ .samples_count = siren14_samples,
+ .get_length = siren14_length,
+};
+
+static struct ast_codec testlaw = {
+ .name = "testlaw",
+ .description = "G.711 test-law",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .minimum_bytes = 80,
+ .samples_count = ulaw_samples,
+ .get_length = ulaw_length,
+ .smooth = 1,
+};
+
+static int g719_samples(struct ast_frame *frame)
+{
+ return (int) frame->datalen * ((float) 48000 / 8000);
+}
+
+static int g719_length(unsigned int samples)
+{
+ return (int) samples / ((float) 48000 / 8000);
+}
+
+static struct ast_codec g719 = {
+ .name = "g719",
+ .description = "ITU G.719",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ .minimum_ms = 20,
+ .maximum_ms = 80,
+ .default_ms = 20,
+ .minimum_bytes = 160,
+ .samples_count = g719_samples,
+ .get_length = g719_length,
+};
+
+static struct ast_codec opus = {
+ .name = "opus",
+ .description = "Opus Codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 48000,
+ .minimum_ms = 20,
+ .maximum_ms = 60,
+ .default_ms = 20,
+ .minimum_bytes = 10,
+};
+
+static struct ast_codec jpeg = {
+ .name = "jpeg",
+ .description = "JPEG image",
+ .type = AST_MEDIA_TYPE_IMAGE,
+};
+
+static struct ast_codec png = {
+ .name = "png",
+ .description = "PNG Image",
+ .type = AST_MEDIA_TYPE_IMAGE,
+};
+
+static struct ast_codec h261 = {
+ .name = "h261",
+ .description = "H.261 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec h263 = {
+ .name = "h263",
+ .description = "H.263 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec h263p = {
+ .name = "h263p",
+ .description = "H.263+ video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec h264 = {
+ .name = "h264",
+ .description = "H.264 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec mpeg4 = {
+ .name = "mpeg4",
+ .description = "MPEG4 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec vp8 = {
+ .name = "vp8",
+ .description = "VP8 video",
+ .type = AST_MEDIA_TYPE_VIDEO,
+};
+
+static struct ast_codec t140red = {
+ .name = "red",
+ .description = "T.140 Realtime Text with redundancy",
+ .type = AST_MEDIA_TYPE_TEXT,
+};
+
+static struct ast_codec t140 = {
+ .name = "t140",
+ .description = "Passthrough T.140 Realtime Text",
+ .type = AST_MEDIA_TYPE_TEXT,
+};
+
+#define CODEC_REGISTER_AND_CACHE(codec) \
+ ({ \
+ int __res_ ## __LINE__ = 0; \
+ struct ast_format *__fmt_ ## __LINE__; \
+ struct ast_codec *__codec_ ## __LINE__; \
+ res |= __ast_codec_register(&(codec), NULL); \
+ __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
+ __fmt_ ## __LINE__ = ast_format_create(__codec_ ## __LINE__); \
+ res |= ast_format_cache_set(__fmt_ ## __LINE__); \
+ ao2_ref(__fmt_ ## __LINE__, -1); \
+ ao2_ref(__codec_ ## __LINE__, -1); \
+ __res_ ## __LINE__; \
+ })
+
+#define CODEC_REGISTER_AND_CACHE_NAMED(format_name, codec) \
+ ({ \
+ int __res_ ## __LINE__ = 0; \
+ struct ast_format *__fmt_ ## __LINE__; \
+ struct ast_codec *__codec_ ## __LINE__; \
+ res |= __ast_codec_register(&(codec), NULL); \
+ __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
+ __fmt_ ## __LINE__ = ast_format_create_named((format_name), __codec_ ## __LINE__); \
+ res |= ast_format_cache_set(__fmt_ ## __LINE__); \
+ ao2_ref(__fmt_ ## __LINE__, -1); \
+ ao2_ref(__codec_ ## __LINE__, -1); \
+ __res_ ## __LINE__; \
+ })
+
+int ast_codec_builtin_init(void)
+{
+ int res = 0;
+
+ res |= CODEC_REGISTER_AND_CACHE(g723);
+ res |= CODEC_REGISTER_AND_CACHE(ulaw);
+ res |= CODEC_REGISTER_AND_CACHE(alaw);
+ res |= CODEC_REGISTER_AND_CACHE(gsm);
+ res |= CODEC_REGISTER_AND_CACHE(g726rfc3551);
+ res |= CODEC_REGISTER_AND_CACHE(g726aal2);
+ res |= CODEC_REGISTER_AND_CACHE(adpcm);
+ res |= CODEC_REGISTER_AND_CACHE(slin8);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin12", slin12);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin16", slin16);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin24", slin24);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin32", slin32);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin44", slin44);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin48", slin48);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin96", slin96);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("slin192", slin192);
+ res |= CODEC_REGISTER_AND_CACHE(lpc10);
+ res |= CODEC_REGISTER_AND_CACHE(g729a);
+ res |= CODEC_REGISTER_AND_CACHE(speex8);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("speex16", speex16);
+ res |= CODEC_REGISTER_AND_CACHE_NAMED("speex32", speex32);
+ res |= CODEC_REGISTER_AND_CACHE(ilbc);
+ res |= CODEC_REGISTER_AND_CACHE(g722);
+ res |= CODEC_REGISTER_AND_CACHE(siren7);
+ res |= CODEC_REGISTER_AND_CACHE(siren14);
+ res |= CODEC_REGISTER_AND_CACHE(testlaw);
+ res |= CODEC_REGISTER_AND_CACHE(g719);
+ res |= CODEC_REGISTER_AND_CACHE(opus);
+ res |= CODEC_REGISTER_AND_CACHE(jpeg);
+ res |= CODEC_REGISTER_AND_CACHE(png);
+ res |= CODEC_REGISTER_AND_CACHE(h261);
+ res |= CODEC_REGISTER_AND_CACHE(h263);
+ res |= CODEC_REGISTER_AND_CACHE(h263p);
+ res |= CODEC_REGISTER_AND_CACHE(h264);
+ res |= CODEC_REGISTER_AND_CACHE(mpeg4);
+ res |= CODEC_REGISTER_AND_CACHE(vp8);
+ res |= CODEC_REGISTER_AND_CACHE(t140red);
+ res |= CODEC_REGISTER_AND_CACHE(t140);
+ res |= CODEC_REGISTER_AND_CACHE(none);
+
+ return res;
+}
diff --git a/main/config_options.c b/main/config_options.c
index ae40c6289..c86db0247 100644
--- a/main/config_options.c
+++ b/main/config_options.c
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/xmldoc.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
+#include "asterisk/format_cap.h"
#ifdef LOW_MEMORY
#define CONFIG_OPT_BUCKETS 5
@@ -1377,9 +1378,8 @@ static int acl_handler_fn(const struct aco_option *opt, struct ast_variable *var
* enum aco_option_type in config_options.h
*/
static int codec_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
- struct ast_codec_pref *pref = (struct ast_codec_pref *)(obj + opt->args[0]);
- struct ast_format_cap **cap = (struct ast_format_cap **)(obj + opt->args[1]);
- return ast_parse_allow_disallow(pref, *cap, var->value, opt->flags);
+ struct ast_format_cap **cap = (struct ast_format_cap **)(obj + opt->args[0]);
+ return ast_format_cap_update_by_allow_disallow(*cap, var->value, opt->flags);
}
/*! \brief Default option handler for stringfields
diff --git a/main/core_local.c b/main/core_local.c
index e803f29ec..e1b66d0a7 100644
--- a/main/core_local.c
+++ b/main/core_local.c
@@ -1008,7 +1008,8 @@ static void local_shutdown(void)
ao2_ref(locals, -1);
locals = NULL;
- ast_format_cap_destroy(local_tech.capabilities);
+ ao2_cleanup(local_tech.capabilities);
+ local_tech.capabilities = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
@@ -1030,14 +1031,15 @@ int ast_local_init(void)
return -1;
}
- if (!(local_tech.capabilities = ast_format_cap_alloc(0))) {
+ if (!(local_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return -1;
}
- ast_format_cap_add_all(local_tech.capabilities);
+ ast_format_cap_append_by_type(local_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb);
if (!locals) {
- ast_format_cap_destroy(local_tech.capabilities);
+ ao2_cleanup(local_tech.capabilities);
+ local_tech.capabilities = NULL;
return -1;
}
@@ -1045,7 +1047,8 @@ int ast_local_init(void)
if (ast_channel_register(&local_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
ao2_ref(locals, -1);
- ast_format_cap_destroy(local_tech.capabilities);
+ ao2_cleanup(local_tech.capabilities);
+ local_tech.capabilities = NULL;
return -1;
}
ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local));
diff --git a/main/core_unreal.c b/main/core_unreal.c
index c9afa5194..a1ae897b9 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -859,7 +859,8 @@ void ast_unreal_destructor(void *vdoomed)
{
struct ast_unreal_pvt *doomed = vdoomed;
- doomed->reqcap = ast_format_cap_destroy(doomed->reqcap);
+ ao2_cleanup(doomed->reqcap);
+ doomed->reqcap = NULL;
}
struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
@@ -878,11 +879,13 @@ struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructo
if (!unreal) {
return NULL;
}
- unreal->reqcap = ast_format_cap_dup(cap);
+
+ unreal->reqcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!unreal->reqcap) {
ao2_ref(unreal, -1);
return NULL;
}
+ ast_format_cap_append_from_cap(unreal->reqcap, cap, AST_MEDIA_TYPE_UNKNOWN);
memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
@@ -896,7 +899,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
{
struct ast_channel *owner;
struct ast_channel *chan;
- struct ast_format fmt;
+ RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
struct ast_assigned_ids id1 = {NULL, NULL};
struct ast_assigned_ids id2 = {NULL, NULL};
int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
@@ -940,14 +943,22 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
ao2_ref(p, +1);
ast_channel_tech_pvt_set(owner, p);
- ast_format_cap_copy(ast_channel_nativeformats(owner), p->reqcap);
+ ast_channel_nativeformats_set(owner, p->reqcap);
/* Determine our read/write format and set it on each channel */
- ast_best_codec(p->reqcap, &fmt);
- ast_format_copy(ast_channel_writeformat(owner), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(owner), &fmt);
- ast_format_copy(ast_channel_readformat(owner), &fmt);
- ast_format_copy(ast_channel_rawreadformat(owner), &fmt);
+ fmt = ast_format_cap_get_format(p->reqcap, 0);
+ if (!fmt) {
+ ast_channel_tech_pvt_set(owner, NULL);
+ ao2_ref(p, -1);
+ ast_channel_unlock(owner);
+ ast_channel_release(owner);
+ return NULL;
+ }
+
+ ast_channel_set_writeformat(owner, fmt);
+ ast_channel_set_rawwriteformat(owner, fmt);
+ ast_channel_set_readformat(owner, fmt);
+ ast_channel_set_rawreadformat(owner, fmt);
ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE);
@@ -955,6 +966,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
if (ast_channel_cc_params_init(owner, requestor
? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
+ ast_channel_tech_pvt_set(owner, NULL);
ao2_ref(p, -1);
ast_channel_tech_pvt_set(owner, NULL);
ast_channel_unlock(owner);
@@ -970,6 +982,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
"%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno);
if (!chan) {
ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
+ ast_channel_tech_pvt_set(owner, NULL);
ao2_ref(p, -1);
ast_channel_tech_pvt_set(owner, NULL);
ast_channel_release(owner);
@@ -984,13 +997,13 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
ao2_ref(p, +1);
ast_channel_tech_pvt_set(chan, p);
- ast_format_cap_copy(ast_channel_nativeformats(chan), p->reqcap);
+ ast_channel_nativeformats_set(chan, p->reqcap);
/* Format was already determined when setting up owner */
- ast_format_copy(ast_channel_writeformat(chan), &fmt);
- ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
- ast_format_copy(ast_channel_readformat(chan), &fmt);
- ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
+ ast_channel_set_writeformat(chan, fmt);
+ ast_channel_set_rawwriteformat(chan, fmt);
+ ast_channel_set_readformat(chan, fmt);
+ ast_channel_set_rawreadformat(chan, fmt);
ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE);
diff --git a/main/data.c b/main/data.c
index 092d7aad5..746c52dfd 100644
--- a/main/data.c
+++ b/main/data.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/manager.h"
#include "asterisk/test.h"
#include "asterisk/frame.h"
+#include "asterisk/codec.h"
/*** DOCUMENTATION
<manager name="DataGet" language="en_US">
@@ -3097,62 +3098,69 @@ static int manager_data_get(struct mansession *s, const struct message *m)
return RESULT_SUCCESS;
}
+static int data_add_codec(struct ast_data *codecs, struct ast_format *format) {
+ struct ast_data *codec;
+ struct ast_codec *tmp;
+
+ tmp = ast_codec_get_by_id(ast_format_get_codec_id(format));
+ if (!tmp) {
+ return -1;
+ }
+
+ codec = ast_data_add_node(codecs, "codec");
+ if (!codec) {
+ ao2_ref(tmp, -1);
+ return -1;
+ }
+
+ ast_data_add_str(codec, "name", tmp->name);
+ ast_data_add_int(codec, "samplespersecond", tmp->sample_rate);
+ ast_data_add_str(codec, "description", tmp->description);
+ ast_data_add_int(codec, "frame_length", tmp->minimum_bytes);
+ ao2_ref(tmp, -1);
+
+ return 0;
+}
+
int ast_data_add_codec(struct ast_data *root, const char *node_name, struct ast_format *format)
{
- struct ast_data *codecs, *codec;
- size_t fmlist_size;
- const struct ast_format_list *fmlist;
- int x;
+ struct ast_data *codecs;
codecs = ast_data_add_node(root, node_name);
if (!codecs) {
return -1;
}
- fmlist = ast_format_list_get(&fmlist_size);
- for (x = 0; x < fmlist_size; x++) {
- if (ast_format_cmp(&fmlist[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- codec = ast_data_add_node(codecs, "codec");
- if (!codec) {
- ast_format_list_destroy(fmlist);
- return -1;
- }
- ast_data_add_str(codec, "name", fmlist[x].name);
- ast_data_add_int(codec, "samplespersecond", fmlist[x].samplespersecond);
- ast_data_add_str(codec, "description", fmlist[x].desc);
- ast_data_add_int(codec, "frame_length", fmlist[x].fr_len);
- }
- }
- ast_format_list_destroy(fmlist);
- return 0;
+ return data_add_codec(codecs, format);
}
int ast_data_add_codecs(struct ast_data *root, const char *node_name, struct ast_format_cap *cap)
{
- struct ast_data *codecs, *codec;
- size_t fmlist_size;
- const struct ast_format_list *fmlist;
- int x;
+ struct ast_data *codecs;
+ size_t i;
+ size_t count;
codecs = ast_data_add_node(root, node_name);
if (!codecs) {
return -1;
}
- fmlist = ast_format_list_get(&fmlist_size);
- for (x = 0; x < fmlist_size; x++) {
- if (ast_format_cap_iscompatible(cap, &fmlist[x].format)) {
- codec = ast_data_add_node(codecs, "codec");
- if (!codec) {
- ast_format_list_destroy(fmlist);
- return -1;
- }
- ast_data_add_str(codec, "name", fmlist[x].name);
- ast_data_add_int(codec, "samplespersecond", fmlist[x].samplespersecond);
- ast_data_add_str(codec, "description", fmlist[x].desc);
- ast_data_add_int(codec, "frame_length", fmlist[x].fr_len);
+
+ count = ast_format_cap_count(cap);
+ for (i = 1; i <= count; ++i) {
+ struct ast_format *fmt;
+
+ fmt = ast_format_cap_get_format(cap, i);
+ if (!fmt) {
+ return -1;
}
+
+ if (data_add_codec(codecs, fmt)) {
+ ao2_ref(fmt, -1);
+ return -1;
+ }
+
+ ao2_ref(fmt, -1);
}
- ast_format_list_destroy(fmlist);
return 0;
}
diff --git a/main/dial.c b/main/dial.c
index f03d43d25..0955aad04 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -300,23 +300,23 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
/* Copy device string over */
ast_copy_string(numsubst, channel->device, sizeof(numsubst));
- if (!ast_format_cap_is_empty(cap)) {
+ if (ast_format_cap_count(cap)) {
cap_request = cap;
} else if (chan) {
cap_request = ast_channel_nativeformats(chan);
} else {
- cap_all_audio = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- ast_format_cap_add_all_by_type(cap_all_audio, AST_FORMAT_TYPE_AUDIO);
+ cap_all_audio = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_append_by_type(cap_all_audio, AST_MEDIA_TYPE_AUDIO);
cap_request = cap_all_audio;
}
/* If we fail to create our owner channel bail out */
if (!(channel->owner = ast_request(channel->tech, cap_request, &assignedids, chan, numsubst, &channel->cause))) {
- cap_all_audio = ast_format_cap_destroy(cap_all_audio);
+ ao2_cleanup(cap_all_audio);
return -1;
}
cap_request = NULL;
- cap_all_audio = ast_format_cap_destroy(cap_all_audio);
+ ao2_cleanup(cap_all_audio);
ast_channel_lock(channel->owner);
ast_channel_stage_snapshot(channel->owner);
diff --git a/main/dsp.c b/main/dsp.c
index 747ff28e5..3a5d1221a 100644
--- a/main/dsp.c
+++ b/main/dsp.c
@@ -60,6 +60,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <math.h>
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
@@ -1183,7 +1184,7 @@ int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
return 0;
}
- if (!ast_format_is_slinear(&inf->subclass.format)) {
+ if (!ast_format_cache_is_slinear(inf->subclass.format)) {
ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
return 0;
}
@@ -1408,30 +1409,29 @@ static int ast_dsp_silence_noise_with_energy(struct ast_dsp *dsp, struct ast_fra
ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
return 0;
}
- if (!ast_format_is_slinear(&f->subclass.format)) {
+
+ if (ast_format_cache_is_slinear(f->subclass.format)) {
+ s = f->data.ptr;
+ len = f->datalen/2;
+ } else {
odata = f->data.ptr;
len = f->datalen;
- switch (f->subclass.format.id) {
- case AST_FORMAT_ULAW:
- s = ast_alloca(len * 2);
- for (x = 0; x < len; x++) {
- s[x] = AST_MULAW(odata[x]);
- }
- break;
- case AST_FORMAT_ALAW:
- s = ast_alloca(len * 2);
- for (x = 0; x < len; x++) {
- s[x] = AST_ALAW(odata[x]);
- }
- break;
- default:
- ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames :(\n");
+ if (ast_format_cmp(f->subclass.format, ast_format_ulaw)) {
+ s = ast_alloca(len * 2);
+ for (x = 0; x < len; x++) {
+ s[x] = AST_MULAW(odata[x]);
+ }
+ } else if (ast_format_cmp(f->subclass.format, ast_format_alaw)) {
+ s = ast_alloca(len * 2);
+ for (x = 0; x < len; x++) {
+ s[x] = AST_ALAW(odata[x]);
+ }
+ } else {
+ ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames :(\n");
return 0;
}
- } else {
- s = f->data.ptr;
- len = f->datalen/2;
}
+
if (noise) {
return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
} else {
@@ -1476,31 +1476,26 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
odata = af->data.ptr;
len = af->datalen;
/* Make sure we have short data */
- if (ast_format_is_slinear(&af->subclass.format)) {
+ if (ast_format_cache_is_slinear(af->subclass.format)) {
shortdata = af->data.ptr;
len = af->datalen / 2;
+ } else if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+ shortdata = ast_alloca(af->datalen * 2);
+ for (x = 0; x < len; x++) {
+ shortdata[x] = AST_MULAW(odata[x]);
+ }
+ } else if (ast_format_cmp(af->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
+ shortdata = ast_alloca(af->datalen * 2);
+ for (x = 0; x < len; x++) {
+ shortdata[x] = AST_ALAW(odata[x]);
+ }
} else {
- switch (af->subclass.format.id) {
- case AST_FORMAT_ULAW:
- case AST_FORMAT_TESTLAW:
- shortdata = ast_alloca(af->datalen * 2);
- for (x = 0; x < len; x++) {
- shortdata[x] = AST_MULAW(odata[x]);
- }
- break;
- case AST_FORMAT_ALAW:
- shortdata = ast_alloca(af->datalen * 2);
- for (x = 0; x < len; x++) {
- shortdata[x] = AST_ALAW(odata[x]);
- }
- break;
- default:
- /*Display warning only once. Otherwise you would get hundreds of warnings every second */
- if (dsp->display_inband_dtmf_warning)
- ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(&af->subclass.format));
- dsp->display_inband_dtmf_warning = 0;
- return af;
+ /*Display warning only once. Otherwise you would get hundreds of warnings every second */
+ if (dsp->display_inband_dtmf_warning) {
+ ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_format_get_name(af->subclass.format));
}
+ dsp->display_inband_dtmf_warning = 0;
+ return af;
}
/* Initially we do not want to mute anything */
@@ -1629,19 +1624,14 @@ done:
memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
}
- switch (af->subclass.format.id) {
- case AST_FORMAT_ULAW:
+ if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
for (x = 0; x < len; x++) {
odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
}
- break;
- case AST_FORMAT_ALAW:
+ } else if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
for (x = 0; x < len; x++) {
odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
}
- /* fall through */
- default:
- break;
}
if (outf) {
diff --git a/main/file.c b/main/file.c
index df67fbf43..fa4c63bd9 100644
--- a/main/file.c
+++ b/main/file.c
@@ -189,8 +189,8 @@ int ast_stopstream(struct ast_channel *tmp)
if (ast_channel_stream(tmp)) {
ast_closestream(ast_channel_stream(tmp));
ast_channel_stream_set(tmp, NULL);
- if (ast_channel_oldwriteformat(tmp)->id && ast_set_write_format(tmp, ast_channel_oldwriteformat(tmp)))
- ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_getformatname(ast_channel_oldwriteformat(tmp)));
+ if (ast_channel_oldwriteformat(tmp) && ast_set_write_format(tmp, ast_channel_oldwriteformat(tmp)))
+ ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_format_get_name(ast_channel_oldwriteformat(tmp)));
}
/* Stop the video stream too */
if (ast_channel_vstream(tmp) != NULL) {
@@ -207,10 +207,10 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
{
int res = -1;
if (f->frametype == AST_FRAME_VIDEO) {
- if (AST_FORMAT_GET_TYPE(fs->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) {
+ if (ast_format_get_type(fs->fmt->format) == AST_MEDIA_TYPE_AUDIO) {
/* This is the audio portion. Call the video one... */
if (!fs->vfs && fs->filename) {
- const char *type = ast_getformatname(&f->subclass.format);
+ const char *type = ast_format_get_name(f->subclass.format);
fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
ast_debug(1, "Opened video output file\n");
}
@@ -223,7 +223,7 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
return -1;
}
- if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) != AST_FORMAT_CMP_NOT_EQUAL) {
+ if (ast_format_cmp(f->subclass.format, fs->fmt->format) != AST_FORMAT_CMP_NOT_EQUAL) {
res = fs->fmt->write(fs, f);
if (res < 0)
ast_log(LOG_WARNING, "Natural write failed\n");
@@ -232,18 +232,19 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
} else {
/* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
the one we've setup a translator for, we do the "wrong thing" XXX */
- if (fs->trans && (ast_format_cmp(&f->subclass.format, &fs->lastwriteformat) != AST_FORMAT_CMP_EQUAL)) {
+ if (fs->trans && (ast_format_cmp(f->subclass.format, fs->lastwriteformat) != AST_FORMAT_CMP_EQUAL)) {
ast_translator_free_path(fs->trans);
fs->trans = NULL;
}
- if (!fs->trans)
- fs->trans = ast_translator_build_path(&fs->fmt->format, &f->subclass.format);
- if (!fs->trans)
+ if (!fs->trans) {
+ fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass.format);
+ }
+ if (!fs->trans) {
ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n",
- fs->fmt->name, ast_getformatname(&f->subclass.format));
- else {
+ fs->fmt->name, ast_format_get_name(f->subclass.format));
+ } else {
struct ast_frame *trf;
- ast_format_copy(&fs->lastwriteformat, &f->subclass.format);
+ ao2_replace(fs->lastwriteformat, f->subclass.format);
/* Get the translated frame but don't consume the original in case they're using it on another stream */
if ((trf = ast_translate(fs->trans, f, 0))) {
struct ast_frame *cur;
@@ -349,7 +350,7 @@ static int exts_compare(const char *exts, const char *type)
*/
static void filestream_close(struct ast_filestream *f)
{
- enum ast_format_type format_type = AST_FORMAT_GET_TYPE(f->fmt->format.id);
+ enum ast_media_type format_type = ast_format_get_type(f->fmt->format);
if (!f->owner) {
return;
@@ -358,12 +359,12 @@ static void filestream_close(struct ast_filestream *f)
/* Stop a running stream if there is one */
switch (format_type)
{
- case AST_FORMAT_TYPE_AUDIO:
+ case AST_MEDIA_TYPE_AUDIO:
ast_channel_stream_set(f->owner, NULL);
AST_SCHED_DEL_ACCESSOR(ast_channel_sched(f->owner), f->owner, ast_channel_streamid, ast_channel_streamid_set);
ast_settimeout(f->owner, 0, NULL, NULL);
break;
- case AST_FORMAT_TYPE_VIDEO:
+ case AST_MEDIA_TYPE_VIDEO:
ast_channel_vstream_set(f->owner, NULL);
AST_SCHED_DEL_ACCESSOR(ast_channel_sched(f->owner), f->owner, ast_channel_vstreamid, ast_channel_vstreamid_set);
break;
@@ -418,6 +419,8 @@ static void filestream_destructor(void *arg)
}
if (f->orig_chan_name)
free((void *) f->orig_chan_name);
+ ao2_cleanup(f->lastwriteformat);
+ ao2_cleanup(f->fr.subclass.format);
ast_module_unref(f->fmt->module);
}
@@ -436,6 +439,15 @@ static struct ast_filestream *get_filestream(struct ast_format_def *fmt, FILE *b
if (fmt->buf_size)
s->buf = (char *)(s + 1);
s->fr.src = fmt->name;
+
+ if (ast_format_get_type(fmt->format) == AST_MEDIA_TYPE_AUDIO) {
+ s->fr.frametype = AST_FRAME_VOICE;
+ } else if (ast_format_get_type(fmt->format) == AST_MEDIA_TYPE_VIDEO) {
+ s->fr.frametype = AST_FRAME_VIDEO;
+ }
+ s->fr.mallocd = 0;
+ s->fr.subclass.format = ao2_bump(fmt->format);
+
return s;
}
@@ -529,9 +541,9 @@ static int filehelper(const char *filename, const void *arg2, const char *fmt, c
FILE *bfile;
struct ast_filestream *s;
- if ((ast_format_cmp(ast_channel_writeformat(chan), &f->format) == AST_FORMAT_CMP_NOT_EQUAL) &&
- !(((AST_FORMAT_GET_TYPE(f->format.id) == AST_FORMAT_TYPE_AUDIO) && fmt) ||
- ((AST_FORMAT_GET_TYPE(f->format.id) == AST_FORMAT_TYPE_VIDEO) && fmt))) {
+ if ((ast_format_cmp(ast_channel_writeformat(chan), f->format) == AST_FORMAT_CMP_NOT_EQUAL) &&
+ !(((ast_format_get_type(f->format) == AST_MEDIA_TYPE_AUDIO) && fmt) ||
+ ((ast_format_get_type(f->format) == AST_MEDIA_TYPE_VIDEO) && fmt))) {
ast_free(fn);
continue; /* not a supported format */
}
@@ -559,7 +571,7 @@ static int filehelper(const char *filename, const void *arg2, const char *fmt, c
s->fmt = f;
s->trans = NULL;
s->filename = NULL;
- if (AST_FORMAT_GET_TYPE(s->fmt->format.id) == AST_FORMAT_TYPE_AUDIO) {
+ if (ast_format_get_type(s->fmt->format) == AST_MEDIA_TYPE_AUDIO) {
if (ast_channel_stream(chan))
ast_closestream(ast_channel_stream(chan));
ast_channel_stream_set(chan, s);
@@ -579,7 +591,7 @@ static int filehelper(const char *filename, const void *arg2, const char *fmt, c
/* if arg2 is present, it is a format capabilities structure.
* Add this format to the set of formats this file can be played in */
if (arg2) {
- ast_format_cap_add((struct ast_format_cap *) arg2, &f->format);
+ ast_format_cap_append((struct ast_format_cap *) arg2, f->format, 0);
}
res = 1; /* file does exist and format it exists in is returned in arg2 */
break;
@@ -749,23 +761,23 @@ struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char
buflen = strlen(preflang) + strlen(filename) + 4;
buf = ast_alloca(buflen);
- if (!(file_fmt_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(file_fmt_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return NULL;
}
if (!fileexists_core(filename, NULL, preflang, buf, buflen, file_fmt_cap) ||
- !ast_format_cap_has_type(file_fmt_cap, AST_FORMAT_TYPE_AUDIO)) {
+ !ast_format_cap_has_type(file_fmt_cap, AST_MEDIA_TYPE_AUDIO)) {
ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
- file_fmt_cap = ast_format_cap_destroy(file_fmt_cap);
+ ao2_ref(file_fmt_cap, -1);
return NULL;
}
/* Set the channel to a format we can work with and save off the previous format. */
- ast_format_copy(ast_channel_oldwriteformat(chan), ast_channel_writeformat(chan));
+ ast_channel_set_oldwriteformat(chan, ast_channel_writeformat(chan));
/* Set the channel to the best format that exists for the file. */
res = ast_set_write_format_from_cap(chan, file_fmt_cap);
/* don't need this anymore now that the channel's write format is set. */
- file_fmt_cap = ast_format_cap_destroy(file_fmt_cap);
+ ao2_ref(file_fmt_cap, -1);
if (res == -1) { /* No format available that works with this channel */
return NULL;
@@ -781,50 +793,50 @@ struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *fil
/* As above, but for video. But here we don't have translators
* so we must enforce a format.
*/
- struct ast_format tmp_fmt;
struct ast_format_cap *tmp_cap;
char *buf;
int buflen;
- const char *fmt;
- int fd;
+ int i, fd;
- if (preflang == NULL)
+ if (preflang == NULL) {
preflang = "";
+ }
buflen = strlen(preflang) + strlen(filename) + 4;
buf = ast_alloca(buflen);
/* is the channel capable of video without translation ?*/
- if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO)) {
+ if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO)) {
return NULL;
}
- if (!(tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return NULL;
}
/* Video is supported, so see what video formats exist for this file */
if (!fileexists_core(filename, NULL, preflang, buf, buflen, tmp_cap)) {
- tmp_cap = ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
return NULL;
}
/* iterate over file formats and pick the first one compatible with the channel's native formats */
- ast_format_cap_iter_start(tmp_cap);
- while (!ast_format_cap_iter_next(tmp_cap, &tmp_fmt)) {
- fmt = ast_getformatname(&tmp_fmt);
- if ((AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_VIDEO) ||
- !ast_format_cap_iscompatible(ast_channel_nativeformats(chan), &tmp_fmt)) {
+ for (i = 0; i < ast_format_cap_count(tmp_cap); ++i) {
+ struct ast_format *format = ast_format_cap_get_format(tmp_cap, i);
+
+ if ((ast_format_get_type(format) != AST_MEDIA_TYPE_VIDEO) ||
+ !ast_format_cap_iscompatible(ast_channel_nativeformats(chan), tmp_cap)) {
+ ao2_ref(format, -1);
continue;
}
- fd = filehelper(buf, chan, fmt, ACTION_OPEN);
+ fd = filehelper(buf, chan, ast_format_get_name(format), ACTION_OPEN);
if (fd >= 0) {
- ast_format_cap_iter_end(tmp_cap);
- tmp_cap = ast_format_cap_destroy(tmp_cap);
+ ao2_ref(format, -1);
+ ao2_ref(tmp_cap, -1);
return ast_channel_vstream(chan);
}
ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(tmp_cap);
- tmp_cap = ast_format_cap_destroy(tmp_cap);
+ ao2_ref(tmp_cap, -1);
return NULL;
}
@@ -897,14 +909,14 @@ static enum fsread_res ast_readaudio_callback(struct ast_filestream *s)
if (whennext != s->lasttimeout) {
if (ast_channel_timingfd(s->owner) > -1) {
- float samp_rate = (float) ast_format_rate(&s->fmt->format);
+ float samp_rate = (float) ast_format_get_sample_rate(s->fmt->format);
unsigned int rate;
rate = (unsigned int) roundf(samp_rate / ((float) whennext));
ast_settimeout_full(s->owner, rate, ast_fsread_audio, s, 1);
} else {
- ast_channel_streamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_rate(&s->fmt->format) / 1000), ast_fsread_audio, s));
+ ast_channel_streamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_get_sample_rate(s->fmt->format) / 1000), ast_fsread_audio, s));
}
s->lasttimeout = whennext;
return FSREAD_SUCCESS_NOSCHED;
@@ -954,7 +966,7 @@ static enum fsread_res ast_readvideo_callback(struct ast_filestream *s)
}
if (whennext != s->lasttimeout) {
- ast_channel_vstreamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_rate(&s->fmt->format) / 1000), ast_fsread_video, s));
+ ast_channel_vstreamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_get_sample_rate(s->fmt->format) / 1000), ast_fsread_video, s));
s->lasttimeout = whennext;
return FSREAD_SUCCESS_NOSCHED;
}
@@ -985,7 +997,7 @@ int ast_playstream(struct ast_filestream *s)
{
enum fsread_res res;
- if (AST_FORMAT_GET_TYPE(s->fmt->format.id) == AST_FORMAT_TYPE_AUDIO)
+ if (ast_format_get_type(s->fmt->format) == AST_MEDIA_TYPE_AUDIO)
res = ast_readaudio_callback(s);
else
res = ast_readvideo_callback(s);
@@ -1067,14 +1079,15 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p
{
struct ast_filestream *fs;
struct ast_filestream *vfs=NULL;
- char fmt[256];
off_t pos;
int seekattempt;
int res;
fs = ast_openstream(chan, filename, preflang);
if (!fs) {
- ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), ast_channel_nativeformats(chan)), strerror(errno));
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n",
+ filename, ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf), strerror(errno));
return -1;
}
@@ -1096,7 +1109,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p
vfs = ast_openvstream(chan, filename, preflang);
if (vfs) {
- ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(&vfs->fmt->format));
+ ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_format_get_name(vfs->fmt->format));
}
if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_MASQ_NOSTREAM))
@@ -1108,7 +1121,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p
res = ast_playstream(fs);
if (!res && vfs)
res = ast_playstream(vfs);
- ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), filename, ast_getformatname(ast_channel_writeformat(chan)), preflang ? preflang : "default");
+ ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), filename, ast_format_get_name(ast_channel_writeformat(chan)), preflang ? preflang : "default");
return res;
}
@@ -1330,7 +1343,7 @@ static void waitstream_control(struct ast_channel *c,
}
if (cb) {
- long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_rate(&ast_channel_stream(c)->fmt->format) / 1000);
+ long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_get_sample_rate(ast_channel_stream(c)->fmt->format) / 1000);
cb(c, ms_len, type);
}
@@ -1373,7 +1386,7 @@ static int waitstream_core(struct ast_channel *c,
orig_chan_name = ast_strdupa(ast_channel_name(c));
if (ast_channel_stream(c) && cb) {
- long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_rate(&ast_channel_stream(c)->fmt->format) / 1000);
+ long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_get_sample_rate(ast_channel_stream(c)->fmt->format) / 1000);
cb(c, ms_len, AST_WAITSTREAM_CB_START);
}
@@ -1722,7 +1735,7 @@ static char *handle_cli_core_show_file_formats(struct ast_cli_entry *e, int cmd,
AST_RWLIST_RDLOCK(&formats);
AST_RWLIST_TRAVERSE(&formats, f, list) {
- ast_cli(a->fd, FORMAT2, ast_getformatname(&f->format), f->name, f->exts);
+ ast_cli(a->fd, FORMAT2, ast_format_get_name(f->format), f->name, f->exts);
count_fmt++;
}
AST_RWLIST_UNLOCK(&formats);
@@ -1732,13 +1745,13 @@ static char *handle_cli_core_show_file_formats(struct ast_cli_entry *e, int cmd,
#undef FORMAT2
}
-const struct ast_format *ast_get_format_for_file_ext(const char *file_ext)
+struct ast_format *ast_get_format_for_file_ext(const char *file_ext)
{
struct ast_format_def *f;
SCOPED_RDLOCK(lock, &formats.lock);
AST_RWLIST_TRAVERSE(&formats, f, list) {
if (exts_compare(f->exts, file_ext)) {
- return &f->format;
+ return f->format;
}
}
diff --git a/main/format.c b/main/format.c
index c4ad45b7f..83206f28c 100644
--- a/main/format.c
+++ b/main/format.c
@@ -1,10 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
- * Mark Spencer <markster@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -17,12 +16,11 @@
* at the top of the source tree.
*/
-/*!
- * \file
- * \brief Format API
+/*! \file
*
- * \author David Vossel <dvossel@digium.com>
- * \author Mark Spencer <markster@digium.com>
+ * \brief Media Format API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
*/
/*** MODULEINFO
@@ -31,1420 +29,351 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#include "asterisk/_private.h"
+#include "asterisk/logger.h"
+#include "asterisk/codec.h"
#include "asterisk/format.h"
#include "asterisk/astobj2.h"
-#include "asterisk/lock.h"
-#include "asterisk/frame.h"
-#include "asterisk/utils.h"
-#include "asterisk/cli.h"
-#include "asterisk/rtp_engine.h"
-#include "asterisk/config.h"
-
-#define FORMAT_CONFIG "codecs.conf"
-
-/*!
- * \brief Container for all the format attribute interfaces.
- * \note This container uses RWLOCKs instead of MUTEX locks. .
- * \note An ao2 container was chosen for fast lookup.
- */
-static struct ao2_container *interfaces;
-
-/*! a wrapper is used put interfaces into the ao2 container. */
-struct interface_ao2_wrapper {
- enum ast_format_id id;
- const struct ast_format_attr_interface *interface;
+#include "asterisk/strings.h"
+
+/*! \brief Number of buckets to use for format interfaces (should be prime for performance reasons) */
+#define FORMAT_INTERFACE_BUCKETS 53
+
+/*! \brief Definition of a media format */
+struct ast_format {
+ /*! Name of the format */
+ const char *name;
+ /*! \brief Pointer to the codec in use for this format */
+ struct ast_codec *codec;
+ /*! \brief Attribute specific data, implementation specific */
+ void *attribute_data;
+ /*! \brief Pointer to the optional format interface */
+ const struct ast_format_interface *interface;
};
-/*! \brief Format List container, This container is never directly accessed outside
- * of this file, and It only exists for building the format_list_array. */
-static struct ao2_container *format_list;
-/*! \brief Format List array is a read only array protected by a read write lock.
- * This array may be used outside this file with the use of reference counting to
- * guarantee safety for access by multiple threads. */
-static struct ast_format_list *format_list_array;
-static size_t format_list_array_len = 0;
-/*! \brief Locks the format list array so a reference can be taken safely. */
-static ast_rwlock_t format_list_array_lock;
-
-static int interface_cmp_cb(void *obj, void *arg, int flags)
-{
- struct interface_ao2_wrapper *wrapper1 = obj;
- struct interface_ao2_wrapper *wrapper2 = arg;
-
- return (wrapper2->id == wrapper1->id) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-static int interface_hash_cb(const void *obj, const int flags)
-{
- const struct interface_ao2_wrapper *wrapper = obj;
- return wrapper->id;
-}
-
-void ast_format_copy(struct ast_format *dst, const struct ast_format *src)
-{
- *dst = *src;
-}
-
-void ast_format_set_video_mark(struct ast_format *format)
-{
- format->fattr.rtp_marker_bit = 1;
-}
-
-int ast_format_get_video_mark(const struct ast_format *format)
-{
- return format->fattr.rtp_marker_bit;
-}
-
-static struct interface_ao2_wrapper *find_interface(const struct ast_format *format)
-{
- struct interface_ao2_wrapper tmp_wrapper = {
- .id = format->id,
- };
+/*! \brief Structure used when registering a format interface */
+struct format_interface {
+ /*! \brief Pointer to the format interface itself */
+ const struct ast_format_interface *interface;
+ /*! \brief Name of the codec the interface is for */
+ char codec[0];
+};
- return ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER);
-}
+/*! \brief Container for registered format interfaces */
+static struct ao2_container *interfaces;
-static int has_interface(const struct ast_format *format)
+static int format_interface_hash(const void *obj, int flags)
{
- struct interface_ao2_wrapper *wrapper;
+ const struct format_interface *format_interface;
+ const char *key;
- wrapper = find_interface(format);
- if (!wrapper) {
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_KEY:
+ key = obj;
+ return ast_str_hash(key);
+ case OBJ_SEARCH_OBJECT:
+ format_interface = obj;
+ return ast_str_hash(format_interface->codec);
+ default:
+ /* Hash can only work on something with a full key. */
+ ast_assert(0);
return 0;
}
- ao2_ref(wrapper, -1);
- return 1;
}
-int ast_format_sdp_parse(struct ast_format *format, const char *attributes)
+static int format_interface_cmp(void *obj, void *arg, int flags)
{
- struct interface_ao2_wrapper *wrapper;
- int res;
+ const struct format_interface *left = obj;
+ const struct format_interface *right = arg;
+ const char *right_key = arg;
+ int cmp;
- if (!(wrapper = find_interface(format))) {
- return 0;
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ cmp = strcmp(left->codec, right->codec);
+ break;
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left->codec, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left->codec, right_key, strlen(right_key));
+ break;
+ default:
+ ast_assert(0);
+ cmp = 0;
+ break;
}
-
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_sdp_parse) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ if (cmp) {
return 0;
}
- res = wrapper->interface->format_attr_sdp_parse(&format->fattr, attributes);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
-
- return res;
+ return CMP_MATCH;
}
-void ast_format_sdp_generate(const struct ast_format *format, unsigned int payload, struct ast_str **str)
+/*! \brief Function called when the process is shutting down */
+static void format_shutdown(void)
{
- struct interface_ao2_wrapper *wrapper;
-
- if (!(wrapper = find_interface(format))) {
- return;
- }
-
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_sdp_generate) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
- return;
- }
-
- wrapper->interface->format_attr_sdp_generate(&format->fattr, payload, str);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ ao2_cleanup(interfaces);
+ interfaces = NULL;
}
-/*! \internal
- * \brief set format attributes using an interface
- */
-static int format_set_helper(struct ast_format *format, va_list ap)
+int ast_format_init(void)
{
- struct interface_ao2_wrapper *wrapper;
-
- if (!(wrapper = find_interface(format))) {
- ast_log(LOG_WARNING, "Could not find format interface to set.\n");
- return -1;
- }
-
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_set) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, FORMAT_INTERFACE_BUCKETS, format_interface_hash,
+ format_interface_cmp);
+ if (!interfaces) {
return -1;
}
- wrapper->interface->format_attr_set(&format->fattr, ap);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ ast_register_atexit(format_shutdown);
return 0;
}
-struct ast_format *ast_format_append(struct ast_format *format, ... )
-{
- va_list ap;
- va_start(ap, format);
- format_set_helper(format, ap);
- va_end(ap);
-
- return format;
-}
-
-struct ast_format *ast_format_set(struct ast_format *format, enum ast_format_id id, int set_attributes, ... )
+int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod)
{
- /* initialize the structure before setting it. */
- ast_format_clear(format);
-
- format->id = id;
+ SCOPED_AO2WRLOCK(lock, interfaces);
+ struct format_interface *format_interface;
- if (set_attributes) {
- va_list ap;
- va_start(ap, set_attributes);
- format_set_helper(format, ap);
- va_end(ap);
+ if (!interface->format_clone || !interface->format_destroy) {
+ ast_log(LOG_ERROR, "Format interface for codec '%s' does not implement required callbacks\n", codec);
+ return -1;
}
- return format;
-}
-
-void ast_format_clear(struct ast_format *format)
-{
- format->id = 0;
- memset(&format->fattr, 0, sizeof(format->fattr));
-}
-
-/*! \internal
- * \brief determine if a list of attribute key value pairs are set on a format
- */
-static int format_isset_helper(const struct ast_format *format, va_list ap)
-{
- int res;
- struct interface_ao2_wrapper *wrapper;
- struct ast_format tmp = {
- .id = format->id,
- .fattr = { { 0, }, },
- };
-
- if (!(wrapper = find_interface(format))) {
+ format_interface = ao2_find(interfaces, codec, OBJ_SEARCH_KEY | OBJ_NOLOCK);
+ if (format_interface) {
+ ast_log(LOG_ERROR, "A format interface is already present for codec '%s'\n", codec);
+ ao2_ref(format_interface, -1);
return -1;
}
- ao2_rdlock(wrapper);
- if (!wrapper->interface ||
- !wrapper->interface->format_attr_set ||
- !wrapper->interface->format_attr_cmp) {
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ format_interface = ao2_alloc_options(sizeof(*format_interface) + strlen(codec) + 1,
+ NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!format_interface) {
return -1;
}
+ format_interface->interface = interface;
+ strcpy(format_interface->codec, codec); /* Safe */
- /* if isset is present, use that function, else just build a new
- * format and use the cmp function */
- if (wrapper->interface->format_attr_isset) {
- res = wrapper->interface->format_attr_isset(&format->fattr, ap);
- } else {
- wrapper->interface->format_attr_set(&tmp.fattr, ap);
- /* use our tmp structure to tell if the attributes are set or not */
- res = wrapper->interface->format_attr_cmp(&tmp.fattr, &format->fattr);
- res = (res == AST_FORMAT_CMP_NOT_EQUAL) ? -1 : 0;
- }
+ ao2_link_flags(interfaces, format_interface, OBJ_NOLOCK);
+ ao2_ref(format_interface, -1);
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
+ ast_verb(2, "Registered format interface for codec '%s'\n", codec);
- return res;
+ return 0;
}
-int ast_format_isset(const struct ast_format *format, ... )
+void *ast_format_get_attribute_data(const struct ast_format *format)
{
- va_list ap;
- int res;
-
- va_start(ap, format);
- res = format_isset_helper(format, ap);
- va_end(ap);
- return res;
+ return format->attribute_data;
}
-int ast_format_get_value(const struct ast_format *format, int key, void *value)
+void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
{
- int res = 0;
- struct interface_ao2_wrapper *wrapper;
-
- if (!(wrapper = find_interface(format))) {
- return -1;
- }
- ao2_rdlock(wrapper);
- if (!wrapper->interface ||
- !wrapper->interface->format_attr_get_val) {
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
- return -1;
- }
-
- res = wrapper->interface->format_attr_get_val(&format->fattr, key, value);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
-
- return res;
+ format->attribute_data = attribute_data;
}
-/*! \internal
- * \brief cmp format attributes using an interface
- */
-static enum ast_format_cmp_res format_cmp_helper(const struct ast_format *format1, const struct ast_format *format2)
+/*! \brief Destructor for media formats */
+static void format_destroy(void *obj)
{
- enum ast_format_cmp_res res = AST_FORMAT_CMP_EQUAL;
- struct interface_ao2_wrapper *wrapper;
+ struct ast_format *format = obj;
- if (!(wrapper = find_interface(format1))) {
- return res;
+ if (format->interface) {
+ format->interface->format_destroy(format);
}
- ao2_rdlock(wrapper);
- if (!wrapper->interface || !wrapper->interface->format_attr_cmp) {
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
- return res;
- }
-
- res = wrapper->interface->format_attr_cmp(&format1->fattr, &format2->fattr);
-
- ao2_unlock(wrapper);
- ao2_ref(wrapper, -1);
-
- return res;
+ ao2_cleanup(format->codec);
}
-enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
+struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
{
- if (format1->id != format2->id) {
- return AST_FORMAT_CMP_NOT_EQUAL;
- }
-
- return format_cmp_helper(format1, format2);
-}
+ struct ast_format *format;
+ struct format_interface *format_interface;
-/*! \internal
- * \brief get joint format attributes using an interface
- */
-static int format_joint_helper(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result)
-{
- int res = 0;
- struct interface_ao2_wrapper *wrapper;
-
- if (!(wrapper = find_interface(format1))) {
- /* if no interface is present, we assume formats are joint by id alone */
- return res;
+ format = ao2_t_alloc_options(sizeof(*format), format_destroy,
+ AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
+ if (!format) {
+ return NULL;
}
+ format->name = format_name;
+ format->codec = ao2_bump(codec);
- ao2_rdlock(wrapper);
- if (wrapper->interface && wrapper->interface->format_attr_get_joint) {
- res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr);
+ format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
+ if (format_interface) {
+ format->interface = format_interface->interface;
+ ao2_ref(format_interface, -1);
}
- ao2_unlock(wrapper);
-
- ao2_ref(wrapper, -1);
- return res;
+ return format;
}
-int ast_format_joint(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result)
+struct ast_format *ast_format_clone(const struct ast_format *format)
{
- if (format1->id != format2->id) {
- return -1;
- }
- result->id = format1->id;
- return format_joint_helper(format1, format2, result);
-}
+ struct ast_format *cloned = ast_format_create_named(format->name, format->codec);
-
-uint64_t ast_format_id_to_old_bitfield(enum ast_format_id id)
-{
- switch (id) {
- /*! G.723.1 compression */
- case AST_FORMAT_G723_1:
- return (1ULL << 0);
- /*! GSM compression */
- case AST_FORMAT_GSM:
- return (1ULL << 1);
- /*! Raw mu-law data (G.711) */
- case AST_FORMAT_ULAW:
- return (1ULL << 2);
- /*! Raw A-law data (G.711) */
- case AST_FORMAT_ALAW:
- return (1ULL << 3);
- /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
- case AST_FORMAT_G726_AAL2:
- return (1ULL << 4);
- /*! ADPCM (IMA) */
- case AST_FORMAT_ADPCM:
- return (1ULL << 5);
- /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
- case AST_FORMAT_SLINEAR:
- return (1ULL << 6);
- /*! LPC10, 180 samples/frame */
- case AST_FORMAT_LPC10:
- return (1ULL << 7);
- /*! G.729A audio */
- case AST_FORMAT_G729A:
- return (1ULL << 8);
- /*! SpeeX Free Compression */
- case AST_FORMAT_SPEEX:
- return (1ULL << 9);
- /*! iLBC Free Compression */
- case AST_FORMAT_ILBC:
- return (1ULL << 10);
- /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
- case AST_FORMAT_G726:
- return (1ULL << 11);
- /*! G.722 */
- case AST_FORMAT_G722:
- return (1ULL << 12);
- /*! G.722.1 (also known as Siren7, 32kbps assumed) */
- case AST_FORMAT_SIREN7:
- return (1ULL << 13);
- /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
- case AST_FORMAT_SIREN14:
- return (1ULL << 14);
- /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
- case AST_FORMAT_SLINEAR16:
- return (1ULL << 15);
- /*! G.719 (64 kbps assumed) */
- case AST_FORMAT_G719:
- return (1ULL << 32);
- /*! SpeeX Wideband (16kHz) Free Compression */
- case AST_FORMAT_SPEEX16:
- return (1ULL << 33);
- /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
- case AST_FORMAT_OPUS:
- return (1ULL << 34);
- /*! Raw mu-law data (G.711) */
- case AST_FORMAT_TESTLAW:
- return (1ULL << 47);
-
- /*! H.261 Video */
- case AST_FORMAT_H261:
- return (1ULL << 18);
- /*! H.263 Video */
- case AST_FORMAT_H263:
- return (1ULL << 19);
- /*! H.263+ Video */
- case AST_FORMAT_H263_PLUS:
- return (1ULL << 20);
- /*! H.264 Video */
- case AST_FORMAT_H264:
- return (1ULL << 21);
- /*! MPEG4 Video */
- case AST_FORMAT_MP4_VIDEO:
- return (1ULL << 22);
- /*! VP8 Video */
- case AST_FORMAT_VP8:
- return (1ULL << 23);
-
- /*! JPEG Images */
- case AST_FORMAT_JPEG:
- return (1ULL << 16);
- /*! PNG Images */
- case AST_FORMAT_PNG:
- return (1ULL << 17);
-
- /*! T.140 RED Text format RFC 4103 */
- case AST_FORMAT_T140RED:
- return (1ULL << 26);
- /*! T.140 Text format - ITU T.140, RFC 4103 */
- case AST_FORMAT_T140:
- return (1ULL << 27);
- default:
- return 0; /* not supported by old bitfield. */
+ if (!cloned) {
+ return NULL;
}
- return 0;
-
-}
-uint64_t ast_format_to_old_bitfield(const struct ast_format *format)
-{
- return ast_format_id_to_old_bitfield(format->id);
-}
-
-struct ast_format *ast_format_from_old_bitfield(struct ast_format *dst, uint64_t src)
-{
- switch (src) {
- /*! G.723.1 compression */
- case (1ULL << 0):
- return ast_format_set(dst, AST_FORMAT_G723_1, 0);
- /*! GSM compression */
- case (1ULL << 1):
- return ast_format_set(dst, AST_FORMAT_GSM, 0);
- /*! Raw mu-law data (G.711) */
- case (1ULL << 2):
- return ast_format_set(dst, AST_FORMAT_ULAW, 0);
- /*! Raw A-law data (G.711) */
- case (1ULL << 3):
- return ast_format_set(dst, AST_FORMAT_ALAW, 0);
- /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
- case (1ULL << 4):
- return ast_format_set(dst, AST_FORMAT_G726_AAL2, 0);
- /*! ADPCM (IMA) */
- case (1ULL << 5):
- return ast_format_set(dst, AST_FORMAT_ADPCM, 0);
- /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
- case (1ULL << 6):
- return ast_format_set(dst, AST_FORMAT_SLINEAR, 0);
- /*! LPC10, 180 samples/frame */
- case (1ULL << 7):
- return ast_format_set(dst, AST_FORMAT_LPC10, 0);
- /*! G.729A audio */
- case (1ULL << 8):
- return ast_format_set(dst, AST_FORMAT_G729A, 0);
- /*! SpeeX Free Compression */
- case (1ULL << 9):
- return ast_format_set(dst, AST_FORMAT_SPEEX, 0);
- /*! iLBC Free Compression */
- case (1ULL << 10):
- return ast_format_set(dst, AST_FORMAT_ILBC, 0);
- /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
- case (1ULL << 11):
- return ast_format_set(dst, AST_FORMAT_G726, 0);
- /*! G.722 */
- case (1ULL << 12):
- return ast_format_set(dst, AST_FORMAT_G722, 0);
- /*! G.722.1 (also known as Siren7, 32kbps assumed) */
- case (1ULL << 13):
- return ast_format_set(dst, AST_FORMAT_SIREN7, 0);
- /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
- case (1ULL << 14):
- return ast_format_set(dst, AST_FORMAT_SIREN14, 0);
- /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
- case (1ULL << 15):
- return ast_format_set(dst, AST_FORMAT_SLINEAR16, 0);
- /*! G.719 (64 kbps assumed) */
- case (1ULL << 32):
- return ast_format_set(dst, AST_FORMAT_G719, 0);
- /*! SpeeX Wideband (16kHz) Free Compression */
- case (1ULL << 33):
- return ast_format_set(dst, AST_FORMAT_SPEEX16, 0);
- /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
- case (1ULL << 34):
- return ast_format_set(dst, AST_FORMAT_OPUS, 0);
- /*! Raw mu-law data (G.711) */
- case (1ULL << 47):
- return ast_format_set(dst, AST_FORMAT_TESTLAW, 0);
-
- /*! H.261 Video */
- case (1ULL << 18):
- return ast_format_set(dst, AST_FORMAT_H261, 0);
- /*! H.263 Video */
- case (1ULL << 19):
- return ast_format_set(dst, AST_FORMAT_H263, 0);
- /*! H.263+ Video */
- case (1ULL << 20):
- return ast_format_set(dst, AST_FORMAT_H263_PLUS, 0);
- /*! H.264 Video */
- case (1ULL << 21):
- return ast_format_set(dst, AST_FORMAT_H264, 0);
- /*! MPEG4 Video */
- case (1ULL << 22):
- return ast_format_set(dst, AST_FORMAT_MP4_VIDEO, 0);
- /*! VP8 Video */
- case (1ULL << 23):
- return ast_format_set(dst, AST_FORMAT_VP8, 0);
-
- /*! JPEG Images */
- case (1ULL << 16):
- return ast_format_set(dst, AST_FORMAT_JPEG, 0);
- /*! PNG Images */
- case (1ULL << 17):
- return ast_format_set(dst, AST_FORMAT_PNG, 0);
-
- /*! T.140 RED Text format RFC 4103 */
- case (1ULL << 26):
- return ast_format_set(dst, AST_FORMAT_T140RED, 0);
- /*! T.140 Text format - ITU T.140, RFC 4103 */
- case (1ULL << 27):
- return ast_format_set(dst, AST_FORMAT_T140, 0);
+ if (cloned->interface && cloned->interface->format_clone(format, cloned)) {
+ ao2_ref(cloned, -1);
+ return NULL;
}
- ast_format_clear(dst);
- return NULL;
-}
-enum ast_format_id ast_format_id_from_old_bitfield(uint64_t src)
-{
- struct ast_format dst;
- if (ast_format_from_old_bitfield(&dst, src)) {
- return dst.id;
- }
- return 0;
+ return cloned;
}
-int ast_format_is_slinear(const struct ast_format *format)
+struct ast_format *ast_format_create(struct ast_codec *codec)
{
- if (format->id == AST_FORMAT_SLINEAR ||
- format->id == AST_FORMAT_SLINEAR12 ||
- format->id == AST_FORMAT_SLINEAR16 ||
- format->id == AST_FORMAT_SLINEAR24 ||
- format->id == AST_FORMAT_SLINEAR32 ||
- format->id == AST_FORMAT_SLINEAR44 ||
- format->id == AST_FORMAT_SLINEAR48 ||
- format->id == AST_FORMAT_SLINEAR96 ||
- format->id == AST_FORMAT_SLINEAR192) {
- return 1;
- }
- return 0;
+ return ast_format_create_named(codec->name, codec);
}
-enum ast_format_id ast_format_slin_by_rate(unsigned int rate)
+enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
{
- if (rate >= 192000) {
- return AST_FORMAT_SLINEAR192;
- } else if (rate >= 96000) {
- return AST_FORMAT_SLINEAR96;
- } else if (rate >= 48000) {
- return AST_FORMAT_SLINEAR48;
- } else if (rate >= 44100) {
- return AST_FORMAT_SLINEAR44;
- } else if (rate >= 32000) {
- return AST_FORMAT_SLINEAR32;
- } else if (rate >= 24000) {
- return AST_FORMAT_SLINEAR24;
- } else if (rate >= 16000) {
- return AST_FORMAT_SLINEAR16;
- } else if (rate >= 12000) {
- return AST_FORMAT_SLINEAR12;
- }
- return AST_FORMAT_SLINEAR;
-}
+ const struct ast_format_interface *interface;
-const char* ast_getformatname(const struct ast_format *format)
-{
- int x;
- const char *ret = "unknown";
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- ret = f_list[x].name;
- break;
- }
+ if (format1 == NULL || format2 == NULL) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
}
- f_list = ast_format_list_destroy(f_list);
- return ret;
-}
-
-char *ast_getformatname_multiple_byid(char *buf, size_t size, enum ast_format_id id)
-{
- int x;
- unsigned len;
- char *start, *end = buf;
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- if (!size) {
- f_list = ast_format_list_destroy(f_list);
- return buf;
- }
- snprintf(end, size, "(");
- len = strlen(end);
- end += len;
- size -= len;
- start = end;
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == id) {
- snprintf(end, size, "%s|", f_list[x].name);
- len = strlen(end);
- end += len;
- size -= len;
- }
- }
- if (start == end) {
- ast_copy_string(start, "nothing)", size);
- } else if (size > 1) {
- *(end - 1) = ')';
+ if (format1 == format2) {
+ return AST_FORMAT_CMP_EQUAL;
}
- f_list = ast_format_list_destroy(f_list);
- return buf;
-}
-
-static struct ast_codec_alias_table {
- const char *alias;
- const char *realname;
-} ast_codec_alias_table[] = {
- { "slinear", "slin"},
- { "slinear16", "slin16"},
- { "g723.1", "g723"},
- { "g722.1", "siren7"},
- { "g722.1c", "siren14"},
-};
-static const char *ast_expand_codec_alias(const char *in)
-{
- int x;
-
- for (x = 0; x < ARRAY_LEN(ast_codec_alias_table); x++) {
- if (!strcmp(in,ast_codec_alias_table[x].alias))
- return ast_codec_alias_table[x].realname;
+ if (format1->codec != format2->codec) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
}
- return in;
-}
-
-struct ast_format *ast_getformatbyname(const char *name, struct ast_format *result)
-{
- int x;
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (!strcasecmp(f_list[x].name, name) ||
- !strcasecmp(f_list[x].name, ast_expand_codec_alias(name))) {
+ interface = format1->interface ? format1->interface : format2->interface;
- ast_format_copy(result, &f_list[x].format);
- f_list = ast_format_list_destroy(f_list);
- return result;
- }
+ if (interface) {
+ return interface->format_cmp(format1, format2);
}
- f_list = ast_format_list_destroy(f_list);
-
- return NULL;
-}
-const char *ast_codec2str(struct ast_format *format)
-{
- int x;
- const char *ret = "unknown";
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- ret = f_list[x].desc;
- break;
- }
- }
- f_list = ast_format_list_destroy(f_list);
- return ret;
+ return AST_FORMAT_CMP_EQUAL;
}
-int ast_format_rate(const struct ast_format *format)
+struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
{
- switch (format->id) {
- case AST_FORMAT_SLINEAR12:
- return 12000;
- case AST_FORMAT_SLINEAR24:
- return 24000;
- case AST_FORMAT_SLINEAR32:
- return 32000;
- case AST_FORMAT_SLINEAR44:
- return 44100;
- case AST_FORMAT_SLINEAR48:
- return 48000;
- case AST_FORMAT_SLINEAR96:
- return 96000;
- case AST_FORMAT_SLINEAR192:
- return 192000;
- case AST_FORMAT_G722:
- case AST_FORMAT_SLINEAR16:
- case AST_FORMAT_SIREN7:
- case AST_FORMAT_SPEEX16:
- return 16000;
- case AST_FORMAT_SIREN14:
- case AST_FORMAT_SPEEX32:
- return 32000;
- case AST_FORMAT_G719:
- return 48000;
- case AST_FORMAT_SILK:
- if (!(ast_format_isset(format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_24KHZ,
- AST_FORMAT_ATTR_END))) {
- return 24000;
- } else if (!(ast_format_isset(format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END))) {
- return 16000;
- } else if (!(ast_format_isset(format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_12KHZ,
- AST_FORMAT_ATTR_END))) {
- return 12000;
- } else {
- return 8000;
- }
- case AST_FORMAT_CELT:
- {
- int samplerate;
- if (!(ast_format_get_value(format,
- CELT_ATTR_KEY_SAMP_RATE,
- &samplerate))) {
- return samplerate;
- }
- }
- /* Opus */
- case AST_FORMAT_OPUS:
- return 48000;
- default:
- return 8000;
- }
-}
+ const struct ast_format_interface *interface;
-static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int x, found=0;
- size_t f_len;
- const struct ast_format_list *f_list;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "core show codecs [audio|video|image|text]";
- e->usage =
- "Usage: core show codecs [audio|video|image|text]\n"
- " Displays codec mapping\n";
- return NULL;
- case CLI_GENERATE:
+ if (format1->codec != format2->codec) {
return NULL;
}
- if ((a->argc < 3) || (a->argc > 4)) {
- return CLI_SHOWUSAGE;
+ /* If the two formats are the same structure OR if the codec is the same and no attributes
+ * exist we can immediately return a format with reference count bumped up, since they are
+ * the same.
+ */
+ if ((ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL && !format1->attribute_data && !format2->attribute_data)) {
+ return ao2_bump((struct ast_format*)format1);
}
- f_list = ast_format_list_get(&f_len);
- if (!ast_opt_dont_warn) {
- ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
- "\tIt does not indicate anything about your configuration.\n");
- }
+ interface = format1->interface ? format1->interface : format2->interface;
- ast_cli(a->fd, "%8s %5s %8s %s\n","ID","TYPE","NAME","DESCRIPTION");
- ast_cli(a->fd, "-----------------------------------------------------------------------------------\n");
-
- for (x = 0; x < f_len; x++) {
- if (a->argc == 4) {
- if (!strcasecmp(a->argv[3], "audio")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_AUDIO) {
- continue;
- }
- } else if (!strcasecmp(a->argv[3], "video")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_VIDEO) {
- continue;
- }
- } else if (!strcasecmp(a->argv[3], "image")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_IMAGE) {
- continue;
- }
- } else if (!strcasecmp(a->argv[3], "text")) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) != AST_FORMAT_TYPE_TEXT) {
- continue;
- }
- } else {
- continue;
- }
- }
-
- ast_cli(a->fd, "%8u %5s %8s (%s)\n",
- f_list[x].format.id,
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_AUDIO) ? "audio" :
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_IMAGE) ? "image" :
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_VIDEO) ? "video" :
- (AST_FORMAT_GET_TYPE(f_list[x].format.id) == AST_FORMAT_TYPE_TEXT) ? "text" :
- "(unk)",
- f_list[x].name,
- f_list[x].desc);
- found = 1;
- }
-
- f_list = ast_format_list_destroy(f_list);
- if (!found) {
- return CLI_SHOWUSAGE;
- } else {
- return CLI_SUCCESS;
- }
+ /* If there is attribute data on either there has to be an interface */
+ return interface->format_get_joint(format1, format2);
}
-static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
{
- enum ast_format_id format_id;
- int x, found = 0;
- int type_punned_codec;
- size_t f_len;
- const struct ast_format_list *f_list;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "core show codec";
- e->usage =
- "Usage: core show codec <number>\n"
- " Displays codec mapping\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 4) {
- return CLI_SHOWUSAGE;
- }
+ const struct ast_format_interface *interface = format->interface;
- if (sscanf(a->argv[3], "%30d", &type_punned_codec) != 1) {
- return CLI_SHOWUSAGE;
- }
- format_id = type_punned_codec;
-
- f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == format_id) {
- found = 1;
- ast_cli(a->fd, "%11u %s\n", (unsigned int) format_id, f_list[x].desc);
+ if (!interface) {
+ struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
+ if (format_interface) {
+ interface = format_interface->interface;
+ ao2_ref(format_interface, -1);
}
}
- if (!found) {
- ast_cli(a->fd, "Codec %u not found\n", format_id);
+ if (!interface || !interface->format_attribute_set) {
+ return ao2_bump((struct ast_format*)format);
}
- f_list = ast_format_list_destroy(f_list);
- return CLI_SUCCESS;
+ return interface->format_attribute_set(format, name, value);
}
-/* Builtin Asterisk CLI-commands for debugging */
-static struct ast_cli_entry my_clis[] = {
- AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
- AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
-};
-
-static int format_list_add_custom(struct ast_format_list *new)
+struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
{
- RAII_VAR(struct ast_format_list *, entry, NULL, ao2_cleanup);
- if (!(entry = ao2_alloc(sizeof(*entry), NULL))) {
- return -1;
- }
- memcpy(entry, new, sizeof(struct ast_format_list));
- entry->custom_entry = 1;
- ao2_link(format_list, entry);
- return 0;
-}
-static int format_list_add_static(
- const struct ast_format *format,
- const char *name,
- int samplespersecond,
- const char *description,
- int fr_len,
- int min_ms,
- int max_ms,
- int inc_ms,
- int def_ms,
- unsigned int flags,
- int cur_ms)
-{
- struct ast_format_list *entry;
- if (!(entry = ao2_alloc(sizeof(*entry), NULL))) {
- return -1;
- }
- ast_format_copy(&entry->format, format);
- ast_copy_string(entry->name, name, sizeof(entry->name));
- ast_copy_string(entry->desc, description, sizeof(entry->desc));
- entry->samplespersecond = samplespersecond;
- entry->fr_len = fr_len;
- entry->min_ms = min_ms;
- entry->max_ms = max_ms;
- entry->inc_ms = inc_ms;
- entry->def_ms = def_ms;
- entry->flags = flags;
- entry->cur_ms = cur_ms;
- entry->custom_entry = 0;
-
- ao2_link(format_list, entry);
- ao2_ref(entry, -1);
- return 0;
-}
+ const struct ast_format_interface *interface = format->interface;
-static int list_all_custom(void *obj, void *arg, int flag)
-{
- struct ast_format_list *entry = obj;
- return entry->custom_entry ? CMP_MATCH : 0;
-}
-
-static int list_cmp_cb(void *obj, void *arg, int flags)
-{
- struct ast_format_list *entry1 = obj;
- struct ast_format_list *entry2 = arg;
-
- return (ast_format_cmp(&entry1->format, &entry2->format) == AST_FORMAT_CMP_EQUAL) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-const struct ast_format_list *ast_format_list_get(size_t *size)
-{
- struct ast_format_list *list;
- ast_rwlock_rdlock(&format_list_array_lock);
- ao2_ref(format_list_array, 1);
- list = format_list_array;
- *size = format_list_array_len;
- ast_rwlock_unlock(&format_list_array_lock);
- return list;
-}
-const struct ast_format_list *ast_format_list_destroy(const struct ast_format_list *list)
-{
- ao2_ref((void *) list, -1);
- return NULL;
-}
-
-static int build_format_list_array(void)
-{
- struct ast_format_list *tmp;
- size_t arraysize = sizeof(struct ast_format_list) * ao2_container_count(format_list);
- int i = 0;
- struct ao2_iterator it;
-
- ast_rwlock_wrlock(&format_list_array_lock);
- tmp = format_list_array;
- if (!(format_list_array = ao2_alloc(arraysize, NULL))) {
- format_list_array = tmp;
- ast_rwlock_unlock(&format_list_array_lock);
- return -1;
- }
- format_list_array_len = ao2_container_count(format_list);
- if (tmp) {
- ao2_ref(tmp, -1);
+ if (!interface) {
+ struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
+ if (format_interface) {
+ interface = format_interface->interface;
+ ao2_ref(format_interface, -1);
+ }
}
- /* walk through the container adding elements to the static array */
- it = ao2_iterator_init(format_list, 0);
- while ((tmp = ao2_iterator_next(&it)) && (i < format_list_array_len)) {
- memcpy(&format_list_array[i], tmp, sizeof(struct ast_format_list));
- ao2_ref(tmp, -1);
- i++;
+ if (!interface || !interface->format_parse_sdp_fmtp) {
+ return ao2_bump((struct ast_format*)format);
}
- ao2_iterator_destroy(&it);
- ast_rwlock_unlock(&format_list_array_lock);
- return 0;
+ return interface->format_parse_sdp_fmtp(format, attributes);
}
-static int format_list_init(void)
+void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct ast_format tmpfmt;
- if (!(format_list = ao2_container_alloc(1, NULL, list_cmp_cb))) {
- return -1;
+ if (!format->interface || !format->interface->format_generate_sdp_fmtp) {
+ return;
}
- /* initiate static entries XXX DO NOT CHANGE THIS ORDER! */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0), "g723", 8000, "G.723.1", 20, 30, 300, 30, 30, 0, 0); /*!< G723.1 */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0), "gsm", 8000, "GSM", 33, 20, 300, 20, 20, 0, 0); /*!< codec_gsm.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20, 0, 0); /*!< codec_ulaw.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20, 0, 0); /*!< codec_alaw.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20, 0, 0); /*!< codec_g726.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), "adpcm" , 8000, "Dialogic ADPCM", 40, 10, 300, 10, 20, 0, 0); /*!< codec_adpcm.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0); /*!< Signed linear */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_LPC10, 0), "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20, 0, 0); /*!< codec_lpc10.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729, 0); /*!< Binary commercial distribution */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX, 0), "speex", 8000, "SpeeX", 10, 10, 60, 10, 20, 0, 0); /*!< codec_speex.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX16, 0), "speex16", 16000, "SpeeX 16khz", 10, 10, 60, 10, 20, 0, 0); /*!< codec_speex.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_ILBC, 0), "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30, 0, 0); /*!< codec_ilbc.c */ /* inc=30ms - workaround */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G726_AAL2, 0), "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20, 0, 0); /*!< codec_g726.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G722, 0), "g722", 16000, "G722", 80, 10, 150, 10, 20, 0, 0); /*!< codec_g722.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (16kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_JPEG, 0), "jpeg", 0, "JPEG image", 0, 0, 0, 0 ,0 ,0 ,0); /*!< See format_jpeg.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_PNG, 0), "png", 0, "PNG image", 0, 0, 0, 0 ,0 ,0 ,0); /*!< PNG Image format */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H261, 0), "h261", 0, "H.261 Video", 0, 0, 0, 0 ,0 ,0 ,0); /*!< H.261 Video Passthrough */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H263, 0), "h263", 0, "H.263 Video", 0, 0, 0, 0 ,0 ,0 ,0); /*!< H.263 Passthrough support, see format_h263.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), "h263p", 0, "H.263+ Video", 0, 0, 0,0 ,0 ,0, 0); /*!< H.263plus passthrough support See format_h263.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_H264, 0), "h264", 0, "H.264 Video", 0, 0, 0, 0 ,0 ,0, 0); /*!< Passthrough support, see format_h263.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_MP4_VIDEO, 0), "mpeg4", 0, "MPEG4 Video", 0, 0, 0, 0, 0 ,0, 0); /*!< Passthrough support for MPEG4 */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_T140RED, 0), "red", 1, "T.140 Realtime Text with redundancy", 0, 0, 0,0 ,0 ,0, 0); /*!< Redundant T.140 Realtime Text */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_T140, 0), "t140", 0, "Passthrough T.140 Realtime Text", 0, 0, 0, 0 ,0 ,0, 0); /*!< Passthrough support for T.140 Realtime Text */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), "siren7", 16000, "ITU G.722.1 (Siren7, licensed from Polycom)", 80, 20, 80, 20, 20, 0, 0); /*!< Binary commercial distribution */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), "siren14", 32000, "ITU G.722.1 Annex C, (Siren14, licensed from Polycom)", 120, 20, 80, 20, 20, 0, 0); /*!< Binary commercial distribution */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_TESTLAW, 0), "testlaw", 8000, "G.711 test-law", 80, 10, 150, 10, 20, 0, 0); /*!< codec_ulaw.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), "g719", 48000, "ITU G.719", 160, 20, 80, 20, 20, 0, 0);
-
- /* ORDER MAY CHANGE AFTER THIS POINT IN THE LIST */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), "speex32", 32000, "SpeeX 32khz", 10, 10, 60, 10, 20, 0, 0); /*!< codec_speex.c */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR12, 0), "slin12", 12000, "16 bit Signed Linear PCM (12kHz)", 240, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (12kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR24, 0), "slin24", 24000, "16 bit Signed Linear PCM (24kHz)", 480, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (24kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR32, 0), "slin32", 32000, "16 bit Signed Linear PCM (32kHz)", 640, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (32kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR44, 0), "slin44", 44100, "16 bit Signed Linear PCM (44kHz)", 882, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (44.1kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR48, 0), "slin48", 48000, "16 bit Signed Linear PCM (48kHz)", 960, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (48kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR96, 0), "slin96", 96000, "16 bit Signed Linear PCM (96kHz)", 1920, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (96kHz) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR192, 0), "slin192", 192000, "16 bit Signed Linear PCM (192kHz)", 3840, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (192kHz) */
- /* Opus (FIXME: real min is 3/5/10, real max is 120...) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), "opus", 48000, "Opus Codec", 10, 20, 60, 20, 20, 0, 0); /*!< codec_opus.c */
- /* VP8 (passthrough) */
- format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), "vp8", 0, "VP8 Video", 0, 0, 0, 0 ,0 ,0, 0); /*!< Passthrough support, see format_h263.c */
- return 0;
+ format->interface->format_generate_sdp_fmtp(format, payload, str);
}
-/*!
- * \internal
- * \brief Clean up resources on Asterisk shutdown
- */
-static void format_list_shutdown(void)
+unsigned int ast_format_get_codec_id(const struct ast_format *format)
{
- ast_rwlock_destroy(&format_list_array_lock);
- if (format_list) {
- ao2_t_ref(format_list, -1, "Unref format_list container in shutdown");
- format_list = NULL;
- }
- if (format_list_array) {
- ao2_t_ref(format_list_array, -1, "Unref format_list_array in shutdown");
- format_list_array = NULL;
- }
+ return format->codec->id;
}
-int ast_format_list_init(void)
+const char *ast_format_get_name(const struct ast_format *format)
{
- if (ast_rwlock_init(&format_list_array_lock)) {
- return -1;
- }
- if (format_list_init()) {
- goto init_list_cleanup;
- }
- if (build_format_list_array()) {
- goto init_list_cleanup;
- }
-
- ast_register_atexit(format_list_shutdown);
- return 0;
-init_list_cleanup:
-
- format_list_shutdown();
- return -1;
+ return format->name;
}
-/*!
- * \internal
- * \brief Clean up resources on Asterisk shutdown
- */
-static void format_attr_shutdown(void)
+const char *ast_format_get_codec_name(const struct ast_format *format)
{
- ast_cli_unregister_multiple(my_clis, ARRAY_LEN(my_clis));
- if (interfaces) {
- ao2_ref(interfaces, -1);
- interfaces = NULL;
- }
+ return format->codec->name;
}
-int ast_format_attr_init(void)
+int ast_format_can_be_smoothed(const struct ast_format *format)
{
- interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK,
- 283, interface_hash_cb, interface_cmp_cb);
- if (!interfaces) {
- return -1;
- }
-
- ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis));
- ast_register_cleanup(format_attr_shutdown);
- return 0;
+ return format->codec->smooth;
}
-static int custom_celt_format(struct ast_format_list *entry, unsigned int maxbitrate, unsigned int framesize)
+enum ast_media_type ast_format_get_type(const struct ast_format *format)
{
- if (!entry->samplespersecond) {
- ast_log(LOG_WARNING, "Custom CELT format definition '%s' requires sample rate to be defined.\n", entry->name);
- }
- ast_format_set(&entry->format, AST_FORMAT_CELT, 0);
- if (!has_interface(&entry->format)) {
- return -1;
- }
-
- snprintf(entry->desc, sizeof(entry->desc), "CELT Custom Format %ukhz", entry->samplespersecond/1000);
-
- ast_format_append(&entry->format,
- CELT_ATTR_KEY_SAMP_RATE, entry->samplespersecond,
- CELT_ATTR_KEY_MAX_BITRATE, maxbitrate,
- CELT_ATTR_KEY_FRAME_SIZE, framesize,
- AST_FORMAT_ATTR_END);
-
- entry->fr_len = 80;
- entry->min_ms = 20;
- entry->max_ms = 20;
- entry->inc_ms = 20;
- entry->def_ms = 20;
- return 0;
+ return format->codec->type;
}
-static int custom_silk_format(struct ast_format_list *entry, unsigned int maxbitrate, int usedtx, int usefec, int packetloss_percentage)
+unsigned int ast_format_get_default_ms(const struct ast_format *format)
{
- if (!entry->samplespersecond) {
- ast_log(LOG_WARNING, "Custom SILK format definition '%s' requires sample rate to be defined.\n", entry->name);
- }
- ast_format_set(&entry->format, AST_FORMAT_SILK, 0);
-
- if (!has_interface(&entry->format)) {
- return -1;
- }
-
- switch (entry->samplespersecond) {
- case 8000:
- ast_copy_string(entry->desc, "SILK Custom Format 8khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_8KHZ,
- AST_FORMAT_ATTR_END);
- break;
- case 12000:
- ast_copy_string(entry->desc, "SILK Custom Format 12khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_12KHZ,
- AST_FORMAT_ATTR_END);
- break;
- case 16000:
- ast_copy_string(entry->desc, "SILK Custom Format 16khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END);
- break;
- case 24000:
- ast_copy_string(entry->desc, "SILK Custom Format 24khz", sizeof(entry->desc));
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_SAMP_RATE, SILK_ATTR_VAL_SAMP_24KHZ,
- AST_FORMAT_ATTR_END);
- break;
- default:
- ast_log(LOG_WARNING, "Custom SILK format definition '%s' can not support sample rate %u\n", entry->name, entry->samplespersecond);
- return -1;
- }
- ast_format_append(&entry->format,
- SILK_ATTR_KEY_MAX_BITRATE, maxbitrate,
- SILK_ATTR_KEY_DTX, usedtx ? 1 : 0,
- SILK_ATTR_KEY_FEC, usefec ? 1 : 0,
- SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE, packetloss_percentage,
- AST_FORMAT_ATTR_END);
-
- entry->fr_len = 80;
- entry->min_ms = 20;
- entry->max_ms = 20;
- entry->inc_ms = 20;
- entry->def_ms = 20;
- return 0;
+ return format->codec->default_ms;
}
-static int conf_process_format_name(const char *name, enum ast_format_id *id)
+unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
{
- if (!strcasecmp(name, "silk")) {
- *id = AST_FORMAT_SILK;
- } else if (!strcasecmp(name, "celt")) {
- *id = AST_FORMAT_CELT;
- } else {
- *id = 0;
- return -1;
- }
- return 0;
+ return format->codec->minimum_ms;
}
-static int conf_process_sample_rate(const char *rate, unsigned int *result)
+unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
{
- if (!strcasecmp(rate, "8000")) {
- *result = 8000;
- } else if (!strcasecmp(rate, "12000")) {
- *result = 12000;
- } else if (!strcasecmp(rate, "16000")) {
- *result = 16000;
- } else if (!strcasecmp(rate, "24000")) {
- *result = 24000;
- } else if (!strcasecmp(rate, "32000")) {
- *result = 32000;
- } else if (!strcasecmp(rate, "44100")) {
- *result = 44100;
- } else if (!strcasecmp(rate, "48000")) {
- *result = 48000;
- } else if (!strcasecmp(rate, "96000")) {
- *result = 96000;
- } else if (!strcasecmp(rate, "192000")) {
- *result = 192000;
- } else {
- *result = 0;
- return -1;
- }
-
- return 0;
+ return format->codec->maximum_ms;
}
-static int load_format_config(void)
-{
- struct ast_flags config_flags = { 0, };
- struct ast_config *cfg = ast_config_load(FORMAT_CONFIG, config_flags);
- struct ast_format_list entry;
- struct ast_variable *var;
- char *cat = NULL;
- int add_it = 0;
-
- struct {
- enum ast_format_id id;
- unsigned int maxbitrate;
- unsigned int framesize;
- unsigned int packetloss_percentage;
- int usefec;
- int usedtx;
- } settings;
-
- if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
- return 0;
- }
-
- /* remove all custom formats from the AO2 Container. Note, this has no affect on the
- * global format list until the list is rebuild. That is why this is okay to do while
- * reloading the config. */
- ao2_callback(format_list, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, list_all_custom, NULL);
- while ((cat = ast_category_browse(cfg, cat))) {
- memset(&entry, 0, sizeof(entry));
- memset(&settings, 0, sizeof(settings));
- add_it = 0;
-
- if (!(ast_variable_retrieve(cfg, cat, "type"))) {
- continue;
- }
- ast_copy_string(entry.name, cat, sizeof(entry.name));
- var = ast_variable_browse(cfg, cat);
- for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
- if (!strcasecmp(var->name, "type") && conf_process_format_name(var->value, &settings.id)) {
- ast_log(LOG_WARNING, "Can not make custom format type for '%s' at line %d of %s\n",
- var->value, var->lineno, FORMAT_CONFIG);
- continue;
- } else if (!strcasecmp(var->name, "samprate") && conf_process_sample_rate(var->value, &entry.samplespersecond)) {
- ast_log(LOG_WARNING, "Sample rate '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- } else if (!strcasecmp(var->name, "maxbitrate")) {
- if (sscanf(var->value, "%30u", &settings.maxbitrate) != 1) {
- ast_log(LOG_WARNING, "maxbitrate '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- }
- } else if (!strcasecmp(var->name, "framesize")) {
- if (sscanf(var->value, "%30u", &settings.framesize) != 1) {
- ast_log(LOG_WARNING, "framesize '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- }
- } else if (!strcasecmp(var->name, "dtx")) {
- settings.usedtx = ast_true(var->value) ? 1 : 0;
- } else if (!strcasecmp(var->name, "fec")) {
- settings.usefec = ast_true(var->value) ? 1 : 0;
- } else if (!strcasecmp(var->name, "packetloss_percentage")) {
- if ((sscanf(var->value, "%30u", &settings.packetloss_percentage) != 1) || (settings.packetloss_percentage > 100)) {
- ast_log(LOG_WARNING, "packetloss_percentage '%s' at line %d of %s is not supported.\n",
- var->value, var->lineno, FORMAT_CONFIG);
- }
- }
- }
-
- switch (settings.id) {
- case AST_FORMAT_SILK:
- if (!(custom_silk_format(&entry, settings.maxbitrate, settings.usedtx, settings.usefec, settings.packetloss_percentage))) {
- add_it = 1;
- }
- break;
- case AST_FORMAT_CELT:
- if (!(custom_celt_format(&entry, settings.maxbitrate, settings.framesize))) {
- add_it = 1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "Can not create custom format %s\n", entry.name);
- }
-
- if (add_it) {
- format_list_add_custom(&entry);
- }
- }
- ast_config_destroy(cfg);
- build_format_list_array();
- return 0;
+unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
+{
+ return format->codec->minimum_bytes;
}
-int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interface)
+unsigned int ast_format_get_sample_rate(const struct ast_format *format)
{
- int x;
- size_t f_len;
- const struct ast_format_list *f_list;
- struct interface_ao2_wrapper *wrapper;
- struct interface_ao2_wrapper tmp_wrapper = {
- .id = interface->id,
- };
-
- /*
- * Grab the write lock before checking for duplicates in
- * anticipation of adding a new interface and to prevent a
- * duplicate from sneaking in between the check and add.
- */
- ao2_wrlock(interfaces);
-
- /* check for duplicates first*/
- if ((wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
- ao2_unlock(interfaces);
- ast_log(LOG_WARNING, "Can not register attribute interface for format id %u, interface already exists.\n", interface->id);
- ao2_ref(wrapper, -1);
- return -1;
- }
-
- wrapper = ao2_alloc_options(sizeof(*wrapper), NULL, AO2_ALLOC_OPT_LOCK_RWLOCK);
- if (!wrapper) {
- ao2_unlock(interfaces);
- return -1;
- }
-
- wrapper->interface = interface;
- wrapper->id = interface->id;
-
- /* The write lock is already held. */
- ao2_link_flags(interfaces, wrapper, OBJ_NOLOCK);
- ao2_unlock(interfaces);
-
- ao2_ref(wrapper, -1);
-
- /* This will find all custom formats in codecs.conf for this new registered interface */
- load_format_config();
-
- /* update the RTP engine to all custom formats created for this interface */
- f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == tmp_wrapper.id) {
- ast_rtp_engine_load_format(&f_list[x].format);
- }
- }
- f_list = ast_format_list_destroy(f_list);
- return 0;
+ return format->codec->sample_rate;
}
-int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *interface)
+unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
{
- int x;
- size_t f_len;
- const struct ast_format_list *f_list;
- struct interface_ao2_wrapper *wrapper;
- struct interface_ao2_wrapper tmp_wrapper = {
- .id = interface->id,
- };
-
- if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_UNLINK)))) {
- return -1;
- }
-
- ao2_wrlock(wrapper);
- wrapper->interface = NULL;
- ao2_unlock(wrapper);
-
- ao2_ref(wrapper, -1);
-
- /* update the RTP engine to remove all custom formats created for this interface */
- f_list = ast_format_list_get(&f_len);
- for (x = 0; x < f_len; x++) {
- if (f_list[x].format.id == tmp_wrapper.id) {
- ast_rtp_engine_unload_format(&f_list[x].format);
- }
- }
-
- /* This will remove all custom formats previously created for this interface */
- load_format_config();
- f_list = ast_format_list_destroy(f_list);
- return 0;
+ return ast_codec_determine_length(format->codec, samples);
}
diff --git a/main/format_cache.c b/main/format_cache.c
new file mode 100644
index 000000000..c170a76f9
--- /dev/null
+++ b/main/format_cache.c
@@ -0,0 +1,519 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Cache API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/strings.h"
+
+/*!
+ * \brief Built-in cached signed linear 8kHz format.
+ */
+struct ast_format *ast_format_slin;
+
+/*!
+ * \brief Built-in cached signed linear 12kHz format.
+ */
+struct ast_format *ast_format_slin12;
+
+/*!
+ * \brief Built-in cached signed linear 16kHz format.
+ */
+struct ast_format *ast_format_slin16;
+
+/*!
+ * \brief Built-in cached signed linear 24kHz format.
+ */
+struct ast_format *ast_format_slin24;
+
+/*!
+ * \brief Built-in cached signed linear 32kHz format.
+ */
+struct ast_format *ast_format_slin32;
+
+/*!
+ * \brief Built-in cached signed linear 44kHz format.
+ */
+struct ast_format *ast_format_slin44;
+
+/*!
+ * \brief Built-in cached signed linear 48kHz format.
+ */
+struct ast_format *ast_format_slin48;
+
+/*!
+ * \brief Built-in cached signed linear 96kHz format.
+ */
+struct ast_format *ast_format_slin96;
+
+/*!
+ * \brief Built-in cached signed linear 192kHz format.
+ */
+struct ast_format *ast_format_slin192;
+
+/*!
+ * \brief Built-in cached ulaw format.
+ */
+struct ast_format *ast_format_ulaw;
+
+/*!
+ * \brief Built-in cached alaw format.
+ */
+struct ast_format *ast_format_alaw;
+
+/*!
+ * \brief Built-in cached testlaw format.
+ */
+struct ast_format *ast_format_testlaw;
+
+/*!
+ * \brief Built-in cached gsm format.
+ */
+struct ast_format *ast_format_gsm;
+
+/*!
+ * \brief Built-in cached adpcm format.
+ */
+struct ast_format *ast_format_adpcm;
+
+/*!
+ * \brief Built-in cached g722 format.
+ */
+struct ast_format *ast_format_g722;
+
+/*!
+ * \brief Built-in cached g726 format.
+ */
+struct ast_format *ast_format_g726;
+
+/*!
+ * \brief Built-in cached g726-aal2 format.
+ */
+struct ast_format *ast_format_g726_aal2;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+struct ast_format *ast_format_ilbc;
+
+/*!
+ * \brief Built-in cached ilbc format.
+ */
+struct ast_format *ast_format_lpc10;
+
+/*!
+ * \brief Built-in cached speex format.
+ */
+struct ast_format *ast_format_speex;
+
+/*!
+ * \brief Built-in cached speex at 16kHz format.
+ */
+struct ast_format *ast_format_speex16;
+
+/*!
+ * \brief Built-in cached speex at 32kHz format.
+ */
+struct ast_format *ast_format_speex32;
+
+/*!
+ * \brief Built-in cached g723.1 format.
+ */
+struct ast_format *ast_format_g723;
+
+/*!
+ * \brief Built-in cached g729 format.
+ */
+struct ast_format *ast_format_g729;
+
+/*!
+ * \brief Built-in cached g719 format.
+ */
+struct ast_format *ast_format_g719;
+
+/*!
+ * \brief Built-in cached h261 format.
+ */
+struct ast_format *ast_format_h261;
+
+/*!
+ * \brief Built-in cached h263 format.
+ */
+struct ast_format *ast_format_h263;
+
+/*!
+ * \brief Built-in cached h263 plus format.
+ */
+struct ast_format *ast_format_h263p;
+
+/*!
+ * \brief Built-in cached h264 format.
+ */
+struct ast_format *ast_format_h264;
+
+/*!
+ * \brief Built-in cached mp4 format.
+ */
+struct ast_format *ast_format_mp4;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in cached jpeg format.
+ */
+struct ast_format *ast_format_jpeg;
+
+/*!
+ * \brief Built-in cached png format.
+ */
+struct ast_format *ast_format_png;
+
+/*!
+ * \brief Built-in cached siren14 format.
+ */
+struct ast_format *ast_format_siren14;
+
+/*!
+ * \brief Built-in cached siren7 format.
+ */
+struct ast_format *ast_format_siren7;
+
+/*!
+ * \brief Built-in cached opus format.
+ */
+struct ast_format *ast_format_opus;
+
+/*!
+ * \brief Built-in cached t140 format.
+ */
+struct ast_format *ast_format_t140;
+
+/*!
+ * \brief Built-in cached t140 red format.
+ */
+struct ast_format *ast_format_t140_red;
+
+/*!
+ * \brief Built-in cached vp8 format.
+ */
+struct ast_format *ast_format_vp8;
+
+/*!
+ * \brief Built-in "null" format.
+ */
+struct ast_format *ast_format_none;
+
+/*! \brief Number of buckets to use for the media format cache (should be prime for performance reasons) */
+#define CACHE_BUCKETS 53
+
+/*! \brief Cached formats */
+static struct ao2_container *formats;
+
+static int format_hash_cb(const void *obj, int flags)
+{
+ const struct ast_format *format;
+ const char *key;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_KEY:
+ key = obj;
+ return ast_str_case_hash(key);
+ case OBJ_SEARCH_OBJECT:
+ format = obj;
+ return ast_str_case_hash(ast_format_get_name(format));
+ default:
+ /* Hash can only work on something with a full key. */
+ ast_assert(0);
+ return 0;
+ }
+}
+
+static int format_cmp_cb(void *obj, void *arg, int flags)
+{
+ const struct ast_format *left = obj;
+ const struct ast_format *right = arg;
+ const char *right_key = arg;
+ int cmp;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = ast_format_get_name(right);
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ cmp = strcasecmp(ast_format_get_name(left), right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncasecmp(ast_format_get_name(left), right_key, strlen(right_key));
+ break;
+ default:
+ ast_assert(0);
+ cmp = 0;
+ break;
+ }
+ if (cmp) {
+ return 0;
+ }
+
+ return CMP_MATCH;
+}
+
+/*! \brief Function called when the process is shutting down */
+static void format_cache_shutdown(void)
+{
+ ao2_cleanup(formats);
+ formats = NULL;
+
+ ao2_replace(ast_format_g723, NULL);
+ ao2_replace(ast_format_ulaw, NULL);
+ ao2_replace(ast_format_alaw, NULL);
+ ao2_replace(ast_format_gsm, NULL);
+ ao2_replace(ast_format_g726, NULL);
+ ao2_replace(ast_format_g726_aal2, NULL);
+ ao2_replace(ast_format_adpcm, NULL);
+ ao2_replace(ast_format_slin, NULL);
+ ao2_replace(ast_format_slin12, NULL);
+ ao2_replace(ast_format_slin16, NULL);
+ ao2_replace(ast_format_slin24, NULL);
+ ao2_replace(ast_format_slin32, NULL);
+ ao2_replace(ast_format_slin44, NULL);
+ ao2_replace(ast_format_slin48, NULL);
+ ao2_replace(ast_format_slin96, NULL);
+ ao2_replace(ast_format_slin192, NULL);
+ ao2_replace(ast_format_lpc10, NULL);
+ ao2_replace(ast_format_g729, NULL);
+ ao2_replace(ast_format_speex, NULL);
+ ao2_replace(ast_format_speex16, NULL);
+ ao2_replace(ast_format_speex32, NULL);
+ ao2_replace(ast_format_ilbc, NULL);
+ ao2_replace(ast_format_g722, NULL);
+ ao2_replace(ast_format_siren7, NULL);
+ ao2_replace(ast_format_siren14, NULL);
+ ao2_replace(ast_format_testlaw, NULL);
+ ao2_replace(ast_format_g719, NULL);
+ ao2_replace(ast_format_opus, NULL);
+ ao2_replace(ast_format_jpeg, NULL);
+ ao2_replace(ast_format_png, NULL);
+ ao2_replace(ast_format_h261, NULL);
+ ao2_replace(ast_format_h263, NULL);
+ ao2_replace(ast_format_h263p, NULL);
+ ao2_replace(ast_format_h264, NULL);
+ ao2_replace(ast_format_mp4, NULL);
+ ao2_replace(ast_format_vp8, NULL);
+ ao2_replace(ast_format_t140_red, NULL);
+ ao2_replace(ast_format_t140, NULL);
+ ao2_replace(ast_format_none, NULL);
+}
+
+int ast_format_cache_init(void)
+{
+ formats = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CACHE_BUCKETS,
+ format_hash_cb, format_cmp_cb);
+ if (!formats) {
+ return -1;
+ }
+
+ ast_register_atexit(format_cache_shutdown);
+
+ return 0;
+}
+
+static void set_cached_format(const char *name, struct ast_format *format)
+{
+ if (!strcmp(name, "g723")) {
+ ao2_replace(ast_format_g723, format);
+ } else if (!strcmp(name, "ulaw")) {
+ ao2_replace(ast_format_ulaw, format);
+ } else if (!strcmp(name, "alaw")) {
+ ao2_replace(ast_format_alaw, format);
+ } else if (!strcmp(name, "gsm")) {
+ ao2_replace(ast_format_gsm, format);
+ } else if (!strcmp(name, "g726")) {
+ ao2_replace(ast_format_g726, format);
+ } else if (!strcmp(name, "g726aal2")) {
+ ao2_replace(ast_format_g726_aal2, format);
+ } else if (!strcmp(name, "adpcm")) {
+ ao2_replace(ast_format_adpcm, format);
+ } else if (!strcmp(name, "slin")) {
+ ao2_replace(ast_format_slin, format);
+ } else if (!strcmp(name, "slin12")) {
+ ao2_replace(ast_format_slin12, format);
+ } else if (!strcmp(name, "slin16")) {
+ ao2_replace(ast_format_slin16, format);
+ } else if (!strcmp(name, "slin24")) {
+ ao2_replace(ast_format_slin24, format);
+ } else if (!strcmp(name, "slin32")) {
+ ao2_replace(ast_format_slin32, format);
+ } else if (!strcmp(name, "slin44")) {
+ ao2_replace(ast_format_slin44, format);
+ } else if (!strcmp(name, "slin48")) {
+ ao2_replace(ast_format_slin48, format);
+ } else if (!strcmp(name, "slin96")) {
+ ao2_replace(ast_format_slin96, format);
+ } else if (!strcmp(name, "slin192")) {
+ ao2_replace(ast_format_slin192, format);
+ } else if (!strcmp(name, "lpc10")) {
+ ao2_replace(ast_format_lpc10, format);
+ } else if (!strcmp(name, "g729")) {
+ ao2_replace(ast_format_g729, format);
+ } else if (!strcmp(name, "speex")) {
+ ao2_replace(ast_format_speex, format);
+ } else if (!strcmp(name, "speex16")) {
+ ao2_replace(ast_format_speex16, format);
+ } else if (!strcmp(name, "speex32")) {
+ ao2_replace(ast_format_speex32, format);
+ } else if (!strcmp(name, "ilbc")) {
+ ao2_replace(ast_format_ilbc, format);
+ } else if (!strcmp(name, "g722")) {
+ ao2_replace(ast_format_g722, format);
+ } else if (!strcmp(name, "siren7")) {
+ ao2_replace(ast_format_siren7, format);
+ } else if (!strcmp(name, "siren14")) {
+ ao2_replace(ast_format_siren14, format);
+ } else if (!strcmp(name, "testlaw")) {
+ ao2_replace(ast_format_testlaw, format);
+ } else if (!strcmp(name, "g719")) {
+ ao2_replace(ast_format_g719, format);
+ } else if (!strcmp(name, "opus")) {
+ ao2_replace(ast_format_opus, format);
+ } else if (!strcmp(name, "jpeg")) {
+ ao2_replace(ast_format_jpeg, format);
+ } else if (!strcmp(name, "png")) {
+ ao2_replace(ast_format_png, format);
+ } else if (!strcmp(name, "h261")) {
+ ao2_replace(ast_format_h261, format);
+ } else if (!strcmp(name, "h263")) {
+ ao2_replace(ast_format_h263, format);
+ } else if (!strcmp(name, "h263p")) {
+ ao2_replace(ast_format_h263p, format);
+ } else if (!strcmp(name, "h264")) {
+ ao2_replace(ast_format_h264, format);
+ } else if (!strcmp(name, "mpeg4")) {
+ ao2_replace(ast_format_mp4, format);
+ } else if (!strcmp(name, "vp8")) {
+ ao2_replace(ast_format_vp8, format);
+ } else if (!strcmp(name, "red")) {
+ ao2_replace(ast_format_t140_red, format);
+ } else if (!strcmp(name, "t140")) {
+ ao2_replace(ast_format_t140, format);
+ } else if (!strcmp(name, "none")) {
+ ao2_replace(ast_format_none, format);
+ }
+}
+
+int ast_format_cache_set(struct ast_format *format)
+{
+ SCOPED_AO2WRLOCK(lock, formats);
+ struct ast_format *old_format;
+
+ ast_assert(format != NULL);
+
+ if (ast_strlen_zero(ast_format_get_name(format))) {
+ return -1;
+ }
+
+ old_format = ao2_find(formats, ast_format_get_name(format), OBJ_SEARCH_KEY | OBJ_NOLOCK);
+ if (old_format) {
+ ao2_unlink_flags(formats, old_format, OBJ_NOLOCK);
+ }
+ ao2_link_flags(formats, format, OBJ_NOLOCK);
+
+ set_cached_format(ast_format_get_name(format), format);
+
+ ast_verb(2, "%s cached format with name '%s'\n",
+ old_format ? "Updated" : "Created",
+ ast_format_get_name(format));
+
+ ao2_cleanup(old_format);
+
+ return 0;
+}
+
+struct ast_format *__ast_format_cache_get(const char *name)
+{
+ if (ast_strlen_zero(name)) {
+ return NULL;
+ }
+
+ return ao2_find(formats, name, OBJ_SEARCH_KEY);
+}
+
+struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
+{
+ if (ast_strlen_zero(name)) {
+ return NULL;
+ }
+
+ return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
+}
+
+struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate)
+{
+ if (rate >= 192000) {
+ return ast_format_slin192;
+ } else if (rate >= 96000) {
+ return ast_format_slin96;
+ } else if (rate >= 48000) {
+ return ast_format_slin48;
+ } else if (rate >= 44100) {
+ return ast_format_slin44;
+ } else if (rate >= 32000) {
+ return ast_format_slin32;
+ } else if (rate >= 24000) {
+ return ast_format_slin24;
+ } else if (rate >= 16000) {
+ return ast_format_slin16;
+ } else if (rate >= 12000) {
+ return ast_format_slin12;
+ }
+ return ast_format_slin;
+}
+
+int ast_format_cache_is_slinear(struct ast_format *format)
+{
+ if ((ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin24) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin32) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin44) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin48) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin96) == AST_FORMAT_CMP_EQUAL)
+ || (ast_format_cmp(format, ast_format_slin192) == AST_FORMAT_CMP_EQUAL)) {
+ return 1;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/main/format_cap.c b/main/format_cap.c
index 96c2fa3aa..65e469fc1 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -1,9 +1,9 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2014, Digium, Inc.
*
- * David Vossel <dvossel@digium.com>
+ * Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -16,11 +16,11 @@
* at the top of the source tree.
*/
-/*!
- * \file
- * \brief Format Capability API
+/*! \file
+ *
+ * \brief Format Capabilities API
*
- * \author David Vossel <dvossel@digium.com>
+ * \author Joshua Colp <jcolp@digium.com>
*/
/*** MODULEINFO
@@ -29,653 +29,674 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#include "asterisk/_private.h"
+#include "asterisk/logger.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
-#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/codec.h"
#include "asterisk/astobj2.h"
+#include "asterisk/strings.h"
+#include "asterisk/vector.h"
+#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
-#define FORMAT_STR_BUFSIZE 256
+/*! \brief Structure used for capability formats, adds framing */
+struct format_cap_framed {
+ /*! \brief A pointer to the format */
+ struct ast_format *format;
+ /*! \brief The format framing size */
+ unsigned int framing;
+ /*! \brief Linked list information */
+ AST_LIST_ENTRY(format_cap_framed) entry;
+};
+/*! \brief Format capabilities structure, holds formats + preference order + etc */
struct ast_format_cap {
- /* The capabilities structure is just an ao2 container of ast_formats */
- struct ao2_container *formats;
- struct ao2_iterator it;
- /*! TRUE if the formats container created without a lock. */
- struct ast_flags flags;
- unsigned int string_cache_valid;
- char format_strs[0];
+ /*! \brief Vector of formats, indexed using the codec identifier */
+ AST_VECTOR(, struct format_cap_framed_list) formats;
+ /*! \brief Vector of formats, added in preference order */
+ AST_VECTOR(, struct format_cap_framed *) preference_order;
+ /*! \brief Global framing size, applies to all formats if no framing present on format */
+ unsigned int framing;
};
-/*! format exists within capabilities structure if it is identical to
- * another format, or if the format is a proper subset of another format. */
-static int cmp_cb(void *obj, void *arg, int flags)
+/*! \brief Linked list for formats */
+AST_LIST_HEAD_NOLOCK(format_cap_framed_list, format_cap_framed);
+
+/*! \brief Dummy empty list for when we are inserting a new list */
+static const struct format_cap_framed_list format_cap_framed_list_empty = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+
+/*! \brief Destructor for format capabilities structure */
+static void format_cap_destroy(void *obj)
{
- struct ast_format *format1 = arg;
- struct ast_format *format2 = obj;
- enum ast_format_cmp_res res = ast_format_cmp(format1, format2);
-
- return ((res == AST_FORMAT_CMP_EQUAL) ||
- (res == AST_FORMAT_CMP_SUBSET)) ?
- CMP_MATCH | CMP_STOP :
- 0;
+ struct ast_format_cap *cap = obj;
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->formats); idx++) {
+ struct format_cap_framed_list *list = AST_VECTOR_GET_ADDR(&cap->formats, idx);
+ struct format_cap_framed *framed;
+
+ while ((framed = AST_LIST_REMOVE_HEAD(list, entry))) {
+ ao2_ref(framed, -1);
+ }
+ }
+ AST_VECTOR_FREE(&cap->formats);
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->preference_order); idx++) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, idx);
+
+ /* This will always be non-null, unlike formats */
+ ao2_ref(framed, -1);
+ }
+ AST_VECTOR_FREE(&cap->preference_order);
}
-static int hash_cb(const void *obj, const int flags)
+static inline void format_cap_init(struct ast_format_cap *cap, enum ast_format_cap_flags flags)
{
- const struct ast_format *format = obj;
- return format->id;
+ AST_VECTOR_INIT(&cap->formats, 0);
+
+ /* TODO: Look at common usage of this and determine a good starting point */
+ AST_VECTOR_INIT(&cap->preference_order, 5);
+
+ cap->framing = UINT_MAX;
}
-struct ast_format_cap *ast_format_cap_alloc(enum ast_format_cap_flags flags)
+struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags)
{
struct ast_format_cap *cap;
- unsigned int alloc_size;
-
- alloc_size = sizeof(*cap);
- if (flags & AST_FORMAT_CAP_FLAG_CACHE_STRINGS) {
- alloc_size += FORMAT_STR_BUFSIZE;
- }
- cap = ast_calloc(1, alloc_size);
+ cap = ao2_alloc_options(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!cap) {
return NULL;
}
- ast_set_flag(&cap->flags, flags);
- cap->formats = ao2_container_alloc_options(
- (flags & AST_FORMAT_CAP_FLAG_NOLOCK) ?
- AO2_ALLOC_OPT_LOCK_NOLOCK :
- AO2_ALLOC_OPT_LOCK_MUTEX,
- 11, hash_cb, cmp_cb);
- if (!cap->formats) {
- ast_free(cap);
- return NULL;
- }
+ format_cap_init(cap, flags);
return cap;
}
-void *ast_format_cap_destroy(struct ast_format_cap *cap)
+struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func)
{
+ struct ast_format_cap *cap;
+
+ cap = __ao2_alloc_debug(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(tag, "ast_format_cap_alloc"), file, line, func, 1);
if (!cap) {
return NULL;
}
- ao2_ref(cap->formats, -1);
- ast_free(cap);
- return NULL;
-}
-static void format_cap_add(struct ast_format_cap *cap, const struct ast_format *format)
-{
- struct ast_format *fnew;
-
- if (!format || !format->id) {
- return;
- }
- if (!(fnew = ao2_alloc(sizeof(struct ast_format), NULL))) {
- return;
- }
- ast_format_copy(fnew, format);
- ao2_link(cap->formats, fnew);
+ format_cap_init(cap, flags);
- ao2_ref(fnew, -1);
+ return cap;
}
-void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format)
+void ast_format_cap_set_framing(struct ast_format_cap *cap, unsigned int framing)
{
- format_cap_add(cap, format);
- cap->string_cache_valid = 0;
+ cap->framing = framing;
}
-void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type)
+/*! \brief Destructor for format capabilities framed structure */
+static void format_cap_framed_destroy(void *obj)
{
- int x;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
+ struct format_cap_framed *framed = obj;
- for (x = 0; x < f_len; x++) {
- if (AST_FORMAT_GET_TYPE(f_list[x].format.id) == type) {
- format_cap_add(cap, &f_list[x].format);
- }
- }
- cap->string_cache_valid = 0;
- ast_format_list_destroy(f_list);
+ ao2_cleanup(framed->format);
}
-void ast_format_cap_add_all(struct ast_format_cap *cap)
+static inline int format_cap_framed_init(struct format_cap_framed *framed, struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
{
- int x;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
+ struct format_cap_framed_list *list;
- for (x = 0; x < f_len; x++) {
- format_cap_add(cap, &f_list[x].format);
+ framed->framing = framing;
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
+ if (AST_VECTOR_INSERT(&cap->formats, ast_format_get_codec_id(format), format_cap_framed_list_empty)) {
+ ao2_ref(framed, -1);
+ return -1;
+ }
}
- cap->string_cache_valid = 0;
- ast_format_list_destroy(f_list);
-}
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
-static int append_cb(void *obj, void *arg, int flag)
-{
- struct ast_format_cap *result = (struct ast_format_cap *) arg;
- struct ast_format *format = (struct ast_format *) obj;
+ /* Order doesn't matter for formats, so insert at the head for performance reasons */
+ ao2_ref(framed, +1);
+ AST_LIST_INSERT_HEAD(list, framed, entry);
- if (!ast_format_cap_iscompatible(result, format)) {
- format_cap_add(result, format);
- }
+ /* This takes the allocation reference */
+ AST_VECTOR_APPEND(&cap->preference_order, framed);
+
+ cap->framing = MIN(cap->framing, framing ? framing : ast_format_get_default_ms(format));
return 0;
}
-void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src)
+/*! \internal \brief Determine if \c format is in \c cap */
+static int format_in_format_cap(struct ast_format_cap *cap, struct ast_format *format)
{
- ao2_callback(src->formats, OBJ_NODATA, append_cb, dst);
- dst->string_cache_valid = 0;
-}
+ struct format_cap_framed *framed;
+ int i;
-static int copy_cb(void *obj, void *arg, int flag)
-{
- struct ast_format_cap *result = (struct ast_format_cap *) arg;
- struct ast_format *format = (struct ast_format *) obj;
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); i++) {
+ framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ if (ast_format_get_codec_id(format) == ast_format_get_codec_id(framed->format)) {
+ return 1;
+ }
+ }
- format_cap_add(result, format);
return 0;
}
-static void format_cap_remove_all(struct ast_format_cap *cap)
+int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
{
- ao2_callback(cap->formats, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, NULL, NULL);
-}
+ struct format_cap_framed *framed;
-void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src)
-{
- format_cap_remove_all(dst);
- ao2_callback(src->formats, OBJ_NODATA, copy_cb, dst);
- dst->string_cache_valid = 0;
-}
+ ast_assert(format != NULL);
-struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *cap)
-{
- struct ast_format_cap *dst;
+ if (format_in_format_cap(cap, format)) {
+ return 0;
+ }
- dst = ast_format_cap_alloc(ast_test_flag(&cap->flags, AST_FLAGS_ALL));
- if (!dst) {
- return NULL;
+ framed = ao2_alloc_options(sizeof(*framed), format_cap_framed_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!framed) {
+ return -1;
}
- ao2_callback(cap->formats, OBJ_NODATA, copy_cb, dst);
- dst->string_cache_valid = 0;
- return dst;
+ framed->format = ao2_bump(format);
+
+ return format_cap_framed_init(framed, cap, format, framing);
}
-int ast_format_cap_is_empty(const struct ast_format_cap *cap)
+int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func)
{
- if (!cap) {
- return 1;
+ struct format_cap_framed *framed;
+
+ ast_assert(format != NULL);
+
+ if (format_in_format_cap(cap, format)) {
+ return 0;
}
- return ao2_container_count(cap->formats) == 0 ? 1 : 0;
-}
-static int find_exact_cb(void *obj, void *arg, int flag)
-{
- struct ast_format *format1 = (struct ast_format *) arg;
- struct ast_format *format2 = (struct ast_format *) obj;
+ framed = ao2_alloc_options(sizeof(*framed), format_cap_framed_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!framed) {
+ return -1;
+ }
- return (ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL) ? CMP_MATCH : 0;
+ __ao2_ref_debug(format, +1, S_OR(tag, "ast_format_cap_append"), file, line, func);
+ framed->format = format;
+
+ return format_cap_framed_init(framed, cap, format, framing);
}
-int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
+int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ast_format *fremove;
+ int id;
- fremove = ao2_callback(cap->formats, OBJ_POINTER | OBJ_UNLINK, find_exact_cb, format);
- if (fremove) {
- ao2_ref(fremove, -1);
- cap->string_cache_valid = 0;
- return 0;
+ for (id = 1; id < ast_codec_get_max(); ++id) {
+ struct ast_codec *codec = ast_codec_get_by_id(id);
+ struct ast_format *format;
+ int res;
+
+ if (!codec) {
+ continue;
+ }
+
+ if ((type != AST_MEDIA_TYPE_UNKNOWN) && codec->type != type) {
+ ao2_ref(codec, -1);
+ continue;
+ }
+
+ format = ast_format_create(codec);
+ ao2_ref(codec, -1);
+
+ if (!format) {
+ return -1;
+ }
+
+ /* Use the global framing or default framing of the codec */
+ res = ast_format_cap_append(cap, format, 0);
+ ao2_ref(format, -1);
+
+ if (res) {
+ return -1;
+ }
}
- return -1;
+ return 0;
}
-struct multiple_by_id_data {
- struct ast_format *format;
- int match_found;
-};
-
-static int multiple_by_id_cb(void *obj, void *arg, int flag)
+int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src,
+ enum ast_media_type type)
{
- struct multiple_by_id_data *data = arg;
- struct ast_format *format = obj;
- int res;
+ int idx, res = 0;
+
+ for (idx = 0; (idx < AST_VECTOR_SIZE(&src->preference_order)) && !res; ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&src->preference_order, idx);
- res = (format->id == data->format->id) ? CMP_MATCH : 0;
- if (res) {
- data->match_found = 1;
+ if (type == AST_MEDIA_TYPE_UNKNOWN || ast_format_get_type(framed->format) == type) {
+ res = ast_format_cap_append(dst, framed->format, framed->framing);
+ }
}
return res;
}
-int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id)
+static int format_cap_replace(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
{
- struct ast_format format = {
- .id = id,
- };
- struct multiple_by_id_data data = {
- .format = &format,
- .match_found = 0,
- };
-
- ao2_callback(cap->formats,
- OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
- multiple_by_id_cb,
- &data);
-
- /* match_found will be set if at least one item was removed */
- if (data.match_found) {
- cap->string_cache_valid = 0;
- return 0;
+ struct format_cap_framed *framed;
+ int i;
+
+ ast_assert(format != NULL);
+
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); i++) {
+ framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ if (ast_format_get_codec_id(format) == ast_format_get_codec_id(framed->format)) {
+ ao2_t_replace(framed->format, format, "replacing with new format");
+ framed->framing = framing;
+ return 0;
+ }
}
return -1;
}
-static int multiple_by_type_cb(void *obj, void *arg, int flag)
+void ast_format_cap_replace_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src,
+ enum ast_media_type type)
{
- int *type = arg;
- struct ast_format *format = obj;
- return ((AST_FORMAT_GET_TYPE(format->id)) == *type) ? CMP_MATCH : 0;
-}
+ int idx;
-void ast_format_cap_remove_bytype(struct ast_format_cap *cap, enum ast_format_type type)
-{
- ao2_callback(cap->formats,
- OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE,
- multiple_by_type_cb,
- &type);
- cap->string_cache_valid = 0;
+ for (idx = 0; (idx < AST_VECTOR_SIZE(&src->preference_order)); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&src->preference_order, idx);
+
+ if (type == AST_MEDIA_TYPE_UNKNOWN || ast_format_get_type(framed->format) == type) {
+ format_cap_replace(dst, framed->format, framed->framing);
+ }
+ }
}
-void ast_format_cap_remove_all(struct ast_format_cap *cap)
+int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
{
- format_cap_remove_all(cap);
- cap->string_cache_valid = 0;
+ int res = 0, all = 0, iter_allowing;
+ char *parse = NULL, *this = NULL, *psize = NULL;
+
+ parse = ast_strdupa(list);
+ while ((this = strsep(&parse, ","))) {
+ int framems = 0;
+ struct ast_format *format = NULL;
+
+ iter_allowing = allowing;
+ if (*this == '!') {
+ this++;
+ iter_allowing = !allowing;
+ }
+ if ((psize = strrchr(this, ':'))) {
+ *psize++ = '\0';
+ ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
+ if (!sscanf(psize, "%30d", &framems) || (framems < 0)) {
+ framems = 0;
+ res = -1;
+ ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
+ continue;
+ }
+ }
+ all = strcasecmp(this, "all") ? 0 : 1;
+
+ if (!all && !(format = ast_format_cache_get(this))) {
+ ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", iter_allowing ? "allow" : "disallow", this);
+ res = -1;
+ continue;
+ }
+
+ if (cap) {
+ if (iter_allowing) {
+ if (all) {
+ ast_format_cap_append_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_append(cap, format, framems);
+ }
+ } else {
+ if (all) {
+ ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ } else {
+ ast_format_cap_remove(cap, format);
+ }
+ }
+ }
+
+ ao2_cleanup(format);
+ }
+ return res;
}
-void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format)
+size_t ast_format_cap_count(const struct ast_format_cap *cap)
{
- format_cap_remove_all(cap);
- format_cap_add(cap, format);
- cap->string_cache_valid = 0;
+ return AST_VECTOR_SIZE(&cap->preference_order);
}
-int ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format, struct ast_format *result)
+struct ast_format *ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
{
- struct ast_format *f;
- struct ast_format_cap *tmp_cap = (struct ast_format_cap *) cap;
+ struct format_cap_framed *framed;
+
+ ast_assert(position < AST_VECTOR_SIZE(&cap->preference_order));
- f = ao2_find(tmp_cap->formats, format, OBJ_POINTER);
- if (f) {
- ast_format_copy(result, f);
- ao2_ref(f, -1);
- return 1;
+ if (position >= AST_VECTOR_SIZE(&cap->preference_order)) {
+ return NULL;
}
- ast_format_clear(result);
- return 0;
+
+ framed = AST_VECTOR_GET(&cap->preference_order, position);
+
+ ast_assert(framed->format != ast_format_none);
+ ao2_ref(framed->format, +1);
+ return framed->format;
}
-int ast_format_cap_iscompatible(const struct ast_format_cap *cap, const struct ast_format *format)
+struct ast_format *ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ast_format *f;
- struct ast_format_cap *tmp_cap = (struct ast_format_cap *) cap;
+ int i;
- if (!tmp_cap) {
- return 0;
+ if (type == AST_MEDIA_TYPE_UNKNOWN) {
+ return ast_format_cap_get_format(cap, 0);
}
- f = ao2_find(tmp_cap->formats, format, OBJ_POINTER);
- if (f) {
- ao2_ref(f, -1);
- return 1;
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); i++) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ if (ast_format_get_type(framed->format) == type) {
+ ao2_ref(framed->format, +1);
+ ast_assert(framed->format != ast_format_none);
+ return framed->format;
+ }
}
- return 0;
+ return NULL;
}
-struct byid_data {
- struct ast_format *result;
- enum ast_format_id id;
-};
-static int find_best_byid_cb(void *obj, void *arg, int flag)
+unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
{
- struct ast_format *format = obj;
- struct byid_data *data = arg;
+ return (cap->framing != UINT_MAX) ? cap->framing : 0;
+}
- if (data->id != format->id) {
+unsigned int ast_format_cap_get_format_framing(const struct ast_format_cap *cap, const struct ast_format *format)
+{
+ unsigned int framing;
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed, *result = NULL;
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
return 0;
}
- if (!data->result->id || (ast_format_rate(data->result) < ast_format_rate(format))) {
- ast_format_copy(data->result, format);
+
+ framing = cap->framing != UINT_MAX ? cap->framing : ast_format_get_default_ms(format);
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
+
+ AST_LIST_TRAVERSE(list, framed, entry) {
+ enum ast_format_cmp_res res = ast_format_cmp(format, framed->format);
+
+ if (res == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
+ }
+
+ result = framed;
+
+ if (res == AST_FORMAT_CMP_EQUAL) {
+ break;
+ }
}
- return 0;
-}
-int ast_format_cap_best_byid(const struct ast_format_cap *cap, enum ast_format_id id, struct ast_format *result)
-{
- struct byid_data data;
- data.result = result;
- data.id = id;
-
- ast_format_clear(result);
- ao2_callback(cap->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_best_byid_cb,
- &data);
- return result->id ? 1 : 0;
+ if (result && result->framing) {
+ framing = result->framing;
+ }
+
+ return framing;
}
-/*! \internal
- * \brief this struct is just used for the ast_format_cap_joint function so we can provide
- * both a format and a result ast_format_cap structure as arguments to the find_joint_cb
- * ao2 callback function.
+/*!
+ * \brief format_cap_framed comparator for AST_VECTOR_REMOVE_CMP_ORDERED()
+ *
+ * \param elem Element to compare against
+ * \param value Value to compare with the vector element.
+ *
+ * \return 0 if element does not match.
+ * \return Non-zero if element matches.
*/
-struct find_joint_data {
- /*! format to compare to for joint capabilities */
- struct ast_format *format;
- /*! if joint formmat exists with above format, add it to the result container */
- struct ast_format_cap *joint_cap;
- int joint_found;
-};
+#define FORMAT_CAP_FRAMED_ELEM_CMP(elem, value) ((elem)->format == (value))
-static int find_joint_cb(void *obj, void *arg, int flag)
+/*!
+ * \brief format_cap_framed vector element cleanup.
+ *
+ * \param elem Element to cleanup
+ *
+ * \return Nothing
+ */
+#define FORMAT_CAP_FRAMED_ELEM_CLEANUP(elem) ao2_cleanup((elem))
+
+int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
{
- struct ast_format *format = obj;
- struct find_joint_data *data = arg;
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed;
- struct ast_format tmp = { 0, };
- if (!ast_format_joint(format, data->format, &tmp)) {
- if (data->joint_cap) {
- ast_format_cap_add(data->joint_cap, &tmp);
- }
- data->joint_found++;
+ ast_assert(format != NULL);
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
+ return -1;
}
- return 0;
-}
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
-int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
-{
- struct ao2_iterator it;
- struct ast_format *tmp;
- struct find_joint_data data = {
- .joint_found = 0,
- .joint_cap = NULL,
- };
-
- it = ao2_iterator_init(cap1->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- data.format = tmp;
- ao2_callback(cap2->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_joint_cb,
- &data);
- ao2_ref(tmp, -1);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(list, framed, entry) {
+ if (!FORMAT_CAP_FRAMED_ELEM_CMP(framed, format)) {
+ continue;
+ }
+
+ AST_LIST_REMOVE_CURRENT(entry);
+ FORMAT_CAP_FRAMED_ELEM_CLEANUP(framed);
+ break;
}
- ao2_iterator_destroy(&it);
+ AST_LIST_TRAVERSE_SAFE_END;
- return data.joint_found ? 1 : 0;
+ return AST_VECTOR_REMOVE_CMP_ORDERED(&cap->preference_order, format,
+ FORMAT_CAP_FRAMED_ELEM_CMP, FORMAT_CAP_FRAMED_ELEM_CLEANUP);
}
-int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
+void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ao2_iterator it;
- struct ast_format *tmp;
+ int idx;
- if (ao2_container_count(cap1->formats) != ao2_container_count(cap2->formats)) {
- return 0; /* if they are not the same size, they are not identical */
- }
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->formats); ++idx) {
+ struct format_cap_framed_list *list = AST_VECTOR_GET_ADDR(&cap->formats, idx);
+ struct format_cap_framed *framed;
- it = ao2_iterator_init(cap1->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- if (!ast_format_cap_iscompatible(cap2, tmp)) {
- ao2_ref(tmp, -1);
- ao2_iterator_destroy(&it);
- return 0;
+ AST_LIST_TRAVERSE_SAFE_BEGIN(list, framed, entry) {
+ if ((type != AST_MEDIA_TYPE_UNKNOWN) &&
+ ast_format_get_type(framed->format) != type) {
+ continue;
+ }
+
+ AST_LIST_REMOVE_CURRENT(entry);
+ AST_VECTOR_REMOVE_CMP_ORDERED(&cap->preference_order, framed->format,
+ FORMAT_CAP_FRAMED_ELEM_CMP, FORMAT_CAP_FRAMED_ELEM_CLEANUP);
+ ao2_ref(framed, -1);
}
- ao2_ref(tmp, -1);
+ AST_LIST_TRAVERSE_SAFE_END;
}
- ao2_iterator_destroy(&it);
-
- return 1;
}
-struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
+struct ast_format *ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
{
- struct ao2_iterator it;
- struct ast_format_cap *result = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format *tmp;
- struct find_joint_data data = {
- .joint_found = 0,
- .joint_cap = result,
- };
- if (!result) {
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed;
+ struct ast_format *result = NULL;
+
+ ast_assert(format != NULL);
+
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
return NULL;
}
- it = ao2_iterator_init(cap1->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- data.format = tmp;
- ao2_callback(cap2->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_joint_cb,
- &data);
- ao2_ref(tmp, -1);
- }
- ao2_iterator_destroy(&it);
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
- if (ao2_container_count(result->formats)) {
- return result;
- }
+ AST_LIST_TRAVERSE(list, framed, entry) {
+ enum ast_format_cmp_res res = ast_format_cmp(format, framed->format);
- result = ast_format_cap_destroy(result);
- return NULL;
-}
+ if (res == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
+ }
-static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result, int append)
-{
- struct ao2_iterator it;
- struct ast_format *tmp;
- struct find_joint_data data = {
- .joint_cap = result,
- .joint_found = 0,
- };
- if (!append) {
- format_cap_remove_all(result);
- }
- it = ao2_iterator_init(cap1->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- data.format = tmp;
- ao2_callback(cap2->formats,
- OBJ_MULTIPLE | OBJ_NODATA,
- find_joint_cb,
- &data);
- ao2_ref(tmp, -1);
- }
- ao2_iterator_destroy(&it);
+ /* Replace any current result, this one will also be a subset OR an exact match */
+ ao2_cleanup(result);
- result->string_cache_valid = 0;
+ result = ast_format_joint(format, framed->format);
- return ao2_container_count(result->formats) ? 1 : 0;
-}
+ /* If it's a match we can do no better so return asap */
+ if (res == AST_FORMAT_CMP_EQUAL) {
+ break;
+ }
+ }
-int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
-{
- return joint_copy_helper(cap1, cap2, result, 1);
+ return result;
}
-int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
+enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap,
+ const struct ast_format *format)
{
- return joint_copy_helper(cap1, cap2, result, 0);
-}
+ enum ast_format_cmp_res res = AST_FORMAT_CMP_NOT_EQUAL;
+ struct format_cap_framed_list *list;
+ struct format_cap_framed *framed;
-struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype)
-{
- struct ao2_iterator it;
- struct ast_format_cap *result = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format *tmp;
+ ast_assert(format != NULL);
- if (!result) {
- return NULL;
+ if (ast_format_get_codec_id(format) >= AST_VECTOR_SIZE(&cap->formats)) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
}
- /* for each format in cap1, see if that format is
- * compatible with cap2. If so copy it to the result */
- it = ao2_iterator_init(cap->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- if (AST_FORMAT_GET_TYPE(tmp->id) == ftype) {
- /* copy format */
- ast_format_cap_add(result, tmp);
+ list = AST_VECTOR_GET_ADDR(&cap->formats, ast_format_get_codec_id(format));
+
+ AST_LIST_TRAVERSE(list, framed, entry) {
+ enum ast_format_cmp_res cmp = ast_format_cmp(format, framed->format);
+
+ if (cmp == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
}
- ao2_ref(tmp, -1);
- }
- ao2_iterator_destroy(&it);
- if (ao2_container_count(result->formats)) {
- return result;
+ res = cmp;
+
+ if (res == AST_FORMAT_CMP_EQUAL) {
+ break;
+ }
}
- result = ast_format_cap_destroy(result);
- return NULL;
+ return res;
}
-
-int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type)
+int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type)
{
- struct ao2_iterator it;
- struct ast_format *tmp;
+ int idx;
- it = ao2_iterator_init(cap->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- if (AST_FORMAT_GET_TYPE(tmp->id) == type) {
- ao2_ref(tmp, -1);
- ao2_iterator_destroy(&it);
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap->preference_order); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, idx);
+
+ if (ast_format_get_type(framed->format) == type) {
return 1;
}
- ao2_ref(tmp, -1);
}
- ao2_iterator_destroy(&it);
return 0;
}
-void ast_format_cap_iter_start(struct ast_format_cap *cap)
+int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2,
+ struct ast_format_cap *result)
{
- /* We can unconditionally lock even if the container has no lock. */
- ao2_lock(cap->formats);
- cap->it = ao2_iterator_init(cap->formats, AO2_ITERATOR_DONTLOCK);
-}
+ int idx, res = 0;
-void ast_format_cap_iter_end(struct ast_format_cap *cap)
-{
- ao2_iterator_destroy(&cap->it);
- /* We can unconditionally unlock even if the container has no lock. */
- ao2_unlock(cap->formats);
-}
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap1->preference_order); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap1->preference_order, idx);
+ struct ast_format *format;
-int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format)
-{
- struct ast_format *tmp = ao2_iterator_next(&cap->it);
+ format = ast_format_cap_get_compatible_format(cap2, framed->format);
+ if (!format) {
+ continue;
+ }
- if (!tmp) {
- return -1;
+ res = ast_format_cap_append(result, format, framed->framing);
+ ao2_ref(format, -1);
+
+ if (res) {
+ break;
+ }
}
- ast_format_copy(format, tmp);
- ao2_ref(tmp, -1);
- return 0;
+ return res;
}
-static char *getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
+int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
- int x;
- unsigned len;
- char *start, *end = buf;
- struct ast_format tmp_fmt;
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- if (!size) {
- f_list = ast_format_list_destroy(f_list);
- return buf;
- }
- snprintf(end, size, "(");
- len = strlen(end);
- end += len;
- size -= len;
- start = end;
- for (x = 0; x < f_len; x++) {
- ast_format_copy(&tmp_fmt, &f_list[x].format);
- if (ast_format_cap_iscompatible(cap, &tmp_fmt)) {
- snprintf(end, size, "%s|", f_list[x].name);
- len = strlen(end);
- end += len;
- size -= len;
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap1->preference_order); ++idx) {
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap1->preference_order, idx);
+
+ if (ast_format_cap_iscompatible_format(cap2, framed->format) != AST_FORMAT_CMP_NOT_EQUAL) {
+ return 1;
}
}
- if (start == end) {
- ast_copy_string(start, "nothing)", size);
- } else if (size > 1) {
- *(end - 1) = ')';
- }
- f_list = ast_format_list_destroy(f_list);
- return buf;
+
+ return 0;
}
-char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
+static int internal_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
- if (ast_test_flag(&cap->flags, AST_FORMAT_CAP_FLAG_CACHE_STRINGS)) {
- if (!cap->string_cache_valid) {
- getformatname_multiple(cap->format_strs, FORMAT_STR_BUFSIZE, cap);
- cap->string_cache_valid = 1;
+ int idx;
+ struct ast_format *tmp;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&cap1->preference_order); ++idx) {
+ tmp = ast_format_cap_get_format(cap1, idx);
+
+ if (ast_format_cap_iscompatible_format(cap2, tmp) != AST_FORMAT_CMP_EQUAL) {
+ ao2_ref(tmp, -1);
+ return 0;
}
- ast_copy_string(buf, cap->format_strs, size);
- return buf;
+
+ ao2_ref(tmp, -1);
}
- return getformatname_multiple(buf, size, cap);
+ return 1;
}
-uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap)
+int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
- uint64_t res = 0;
- struct ao2_iterator it;
- struct ast_format *tmp;
+ if (AST_VECTOR_SIZE(&cap1->preference_order) != AST_VECTOR_SIZE(&cap2->preference_order)) {
+ return 0; /* if they are not the same size, they are not identical */
+ }
- it = ao2_iterator_init(cap->formats, 0);
- while ((tmp = ao2_iterator_next(&it))) {
- res |= ast_format_to_old_bitfield(tmp);
- ao2_ref(tmp, -1);
+ if (!internal_format_cap_identical(cap1, cap2)) {
+ return 0;
}
- ao2_iterator_destroy(&it);
- return res;
+
+ return internal_format_cap_identical(cap2, cap1);
}
-void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src)
+const char *ast_format_cap_get_names(struct ast_format_cap *cap, struct ast_str **buf)
{
- uint64_t tmp = 0;
- int x;
- struct ast_format tmp_format = { 0, };
-
- format_cap_remove_all(dst);
- for (x = 0; x < 64; x++) {
- tmp = (1ULL << x);
- if (tmp & src) {
- format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp));
+ int i;
+
+ ast_str_set(buf, 0, "(");
+
+ if (!AST_VECTOR_SIZE(&cap->preference_order)) {
+ ast_str_append(buf, 0, "nothing)");
+ return ast_str_buffer(*buf);
+ }
+
+ for (i = 0; i < AST_VECTOR_SIZE(&cap->preference_order); ++i) {
+ int res;
+ struct format_cap_framed *framed = AST_VECTOR_GET(&cap->preference_order, i);
+
+ res = ast_str_append(buf, 0, "%s%s", ast_format_get_name(framed->format),
+ i < AST_VECTOR_SIZE(&cap->preference_order) - 1 ? "|" : "");
+ if (res < 0) {
+ break;
}
}
- dst->string_cache_valid = 0;
+ ast_str_append(buf, 0, ")");
+
+ return ast_str_buffer(*buf);
}
diff --git a/main/format_compatibility.c b/main/format_compatibility.c
new file mode 100644
index 000000000..df82bacd5
--- /dev/null
+++ b/main/format_compatibility.c
@@ -0,0 +1,274 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Media Format Bitfield Compatibility API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_compatibility.h"
+#include "asterisk/format_cache.h"
+
+uint64_t ast_format_compatibility_format2bitfield(const struct ast_format *format)
+{
+ if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G723;
+ } else if (ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_GSM;
+ } else if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ULAW;
+ } else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ALAW;
+ } else if (ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G726_AAL2;
+ } else if (ast_format_cmp(format, ast_format_adpcm) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ADPCM;
+ } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SLIN;
+ } else if (ast_format_cmp(format, ast_format_lpc10) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_LPC10;
+ } else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G729;
+ } else if (ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SPEEX;
+ } else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_ILBC;
+ } else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G726;
+ } else if (ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G722;
+ } else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SIREN7;
+ } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SIREN14;
+ } else if (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SLIN16;
+ } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_G719;
+ } else if (ast_format_cmp(format, ast_format_speex16) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_SPEEX16;
+ } else if (ast_format_cmp(format, ast_format_opus) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_OPUS;
+ } else if (ast_format_cmp(format, ast_format_testlaw) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_TESTLAW;
+ } else if (ast_format_cmp(format, ast_format_h261) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H261;
+ } else if (ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H263;
+ } else if (ast_format_cmp(format, ast_format_h263p) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H263P;
+ } else if (ast_format_cmp(format, ast_format_h264) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_H264;
+ } else if (ast_format_cmp(format, ast_format_mp4) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_MP4;
+ } else if (ast_format_cmp(format, ast_format_vp8) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_VP8;
+ } else if (ast_format_cmp(format, ast_format_jpeg) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_JPEG;
+ } else if (ast_format_cmp(format, ast_format_png) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_PNG;
+ } else if (ast_format_cmp(format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_T140_RED;
+ } else if (ast_format_cmp(format, ast_format_t140) == AST_FORMAT_CMP_EQUAL) {
+ return AST_FORMAT_T140;
+ }
+
+ return 0;
+}
+
+uint64_t ast_format_compatibility_codec2bitfield(const struct ast_codec *codec)
+{
+ if (codec->id == ast_format_get_codec_id(ast_format_g723)) {
+ return AST_FORMAT_G723;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_gsm)) {
+ return AST_FORMAT_GSM;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_ulaw)) {
+ return AST_FORMAT_ULAW;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_alaw)) {
+ return AST_FORMAT_ALAW;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g726_aal2)) {
+ return AST_FORMAT_G726_AAL2;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_adpcm)) {
+ return AST_FORMAT_ADPCM;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_slin)) {
+ return AST_FORMAT_SLIN;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_lpc10)) {
+ return AST_FORMAT_LPC10;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g729)) {
+ return AST_FORMAT_G729;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_speex)) {
+ return AST_FORMAT_SPEEX;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_ilbc)) {
+ return AST_FORMAT_ILBC;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g726)) {
+ return AST_FORMAT_G726;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g722)) {
+ return AST_FORMAT_G722;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_siren7)) {
+ return AST_FORMAT_SIREN7;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_siren14)) {
+ return AST_FORMAT_SIREN14;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_slin16)) {
+ return AST_FORMAT_SLIN16;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_g719)) {
+ return AST_FORMAT_G719;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_speex16)) {
+ return AST_FORMAT_SPEEX16;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_opus)) {
+ return AST_FORMAT_OPUS;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_testlaw)) {
+ return AST_FORMAT_TESTLAW;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h261)) {
+ return AST_FORMAT_H261;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h263)) {
+ return AST_FORMAT_H263;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h263p)) {
+ return AST_FORMAT_H263P;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_h264)) {
+ return AST_FORMAT_H264;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_mp4)) {
+ return AST_FORMAT_MP4;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_vp8)) {
+ return AST_FORMAT_VP8;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_jpeg)) {
+ return AST_FORMAT_JPEG;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_png)) {
+ return AST_FORMAT_PNG;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_t140_red)) {
+ return AST_FORMAT_T140_RED;
+ } else if (codec->id == ast_format_get_codec_id(ast_format_t140)) {
+ return AST_FORMAT_T140;
+ }
+
+ return 0;
+}
+
+struct ast_format *ast_format_compatibility_bitfield2format(uint64_t bitfield)
+{
+ switch (bitfield) {
+ /*! G.723.1 compression */
+ case AST_FORMAT_G723:
+ return ast_format_g723;
+ /*! GSM compression */
+ case AST_FORMAT_GSM:
+ return ast_format_gsm;
+ /*! Raw mu-law data (G.711) */
+ case AST_FORMAT_ULAW:
+ return ast_format_ulaw;
+ /*! Raw A-law data (G.711) */
+ case AST_FORMAT_ALAW:
+ return ast_format_alaw;
+ /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
+ case AST_FORMAT_G726_AAL2:
+ return ast_format_g726_aal2;
+ /*! ADPCM (IMA) */
+ case AST_FORMAT_ADPCM:
+ return ast_format_adpcm;
+ /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
+ case AST_FORMAT_SLIN:
+ return ast_format_slin;
+ /*! LPC10, 180 samples/frame */
+ case AST_FORMAT_LPC10:
+ return ast_format_lpc10;
+ /*! G.729A audio */
+ case AST_FORMAT_G729:
+ return ast_format_g729;
+ /*! SpeeX Free Compression */
+ case AST_FORMAT_SPEEX:
+ return ast_format_speex;
+ /*! iLBC Free Compression */
+ case AST_FORMAT_ILBC:
+ return ast_format_ilbc;
+ /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
+ case AST_FORMAT_G726:
+ return ast_format_g726;
+ /*! G.722 */
+ case AST_FORMAT_G722:
+ return ast_format_g722;
+ /*! G.722.1 (also known as Siren7, 32kbps assumed) */
+ case AST_FORMAT_SIREN7:
+ return ast_format_siren7;
+ /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
+ case AST_FORMAT_SIREN14:
+ return ast_format_siren14;
+ /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
+ case AST_FORMAT_SLIN16:
+ return ast_format_slin16;
+ /*! G.719 (64 kbps assumed) */
+ case AST_FORMAT_G719:
+ return ast_format_g719;
+ /*! SpeeX Wideband (16kHz) Free Compression */
+ case AST_FORMAT_SPEEX16:
+ return ast_format_speex16;
+ /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */
+ case AST_FORMAT_OPUS:
+ return ast_format_opus;
+ /*! Raw mu-law data (G.711) */
+ case AST_FORMAT_TESTLAW:
+ return ast_format_testlaw;
+
+ /*! H.261 Video */
+ case AST_FORMAT_H261:
+ return ast_format_h261;
+ /*! H.263 Video */
+ case AST_FORMAT_H263:
+ return ast_format_h263;
+ /*! H.263+ Video */
+ case AST_FORMAT_H263P:
+ return ast_format_h263p;
+ /*! H.264 Video */
+ case AST_FORMAT_H264:
+ return ast_format_h264;
+ /*! MPEG4 Video */
+ case AST_FORMAT_MP4:
+ return ast_format_mp4;
+ /*! VP8 Video */
+ case AST_FORMAT_VP8:
+ return ast_format_vp8;
+
+ /*! JPEG Images */
+ case AST_FORMAT_JPEG:
+ return ast_format_jpeg;
+ /*! PNG Images */
+ case AST_FORMAT_PNG:
+ return ast_format_png;
+
+ /*! T.140 RED Text format RFC 4103 */
+ case AST_FORMAT_T140_RED:
+ return ast_format_t140;
+ /*! T.140 Text format - ITU T.140, RFC 4103 */
+ case AST_FORMAT_T140:
+ return ast_format_t140_red;
+ }
+ return 0;
+}
+
diff --git a/main/format_pref.c b/main/format_pref.c
deleted file mode 100644
index b96184a08..000000000
--- a/main/format_pref.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2010, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- * \brief Format Preference API
- */
-
-/*** MODULEINFO
- <support_level>core</support_level>
- ***/
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
-
-#include "asterisk/_private.h"
-#include "asterisk/frame.h"
-#include "asterisk/channel.h"
-#include "asterisk/utils.h"
-
-void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
-{
- size_t f_len;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
- int x, differential = (int) 'A', mem;
- char *from, *to;
-
- /* TODO re-evaluate this function. It is using the order of the formats specified
- * in the global format list in a way that may not be safe. */
- if (right) {
- from = pref->order;
- to = buf;
- mem = size;
- } else {
- to = pref->order;
- from = buf;
- mem = AST_CODEC_PREF_SIZE;
- }
-
- memset(to, 0, mem);
- for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- if (!from[x]) {
- break;
- }
- to[x] = right ? (from[x] + differential) : (from[x] - differential);
- if (!right && to[x] && (to[x] < f_len)) {
- ast_format_copy(&pref->formats[x], &f_list[to[x]-1].format);
- }
- }
- ast_format_list_destroy(f_list);
-}
-
-int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
-{
- int x;
- struct ast_format format;
- size_t total_len, slen;
- const char *formatname;
-
- memset(buf, 0, size);
- total_len = size;
- buf[0] = '(';
- total_len--;
- for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- if (total_len <= 0)
- break;
- if (!(ast_codec_pref_index(pref, x, &format)))
- break;
- if ((formatname = ast_getformatname(&format))) {
- slen = strlen(formatname);
- if (slen > total_len)
- break;
- strncat(buf, formatname, total_len - 1); /* safe */
- total_len -= slen;
- }
- if (total_len && x < AST_CODEC_PREF_SIZE - 1 && ast_codec_pref_index(pref, x + 1, &format)) {
- strncat(buf, "|", total_len - 1); /* safe */
- total_len--;
- }
- }
- if (total_len) {
- strncat(buf, ")", total_len - 1); /* safe */
- total_len--;
- }
-
- return size - total_len;
-}
-
-struct ast_format *ast_codec_pref_index(struct ast_codec_pref *pref, int idx, struct ast_format *result)
-{
- if ((idx >= 0) && (idx < sizeof(pref->order)) && pref->formats[idx].id) {
- ast_format_copy(result, &pref->formats[idx]);
- } else {
- ast_format_clear(result);
- return NULL;
- }
-
- return result;
-}
-
-/*! \brief Remove codec from pref list */
-void ast_codec_pref_remove(struct ast_codec_pref *pref, struct ast_format *format)
-{
- struct ast_codec_pref oldorder;
- int x, y = 0;
- size_t f_len = 0;
- const struct ast_format_list *f_list;
-
- if (!pref->order[0]) {
- return;
- }
-
- f_list = ast_format_list_get(&f_len);
- memcpy(&oldorder, pref, sizeof(oldorder));
- memset(pref, 0, sizeof(*pref));
-
- for (x = 0; x < f_len; x++) {
- if (!oldorder.order[x]) {
- break;
- }
- if (ast_format_cmp(&f_list[oldorder.order[x]-1].format, format) == AST_FORMAT_CMP_NOT_EQUAL) {
- pref->order[y] = oldorder.order[x];
- ast_format_copy(&pref->formats[y], &oldorder.formats[x]);
- pref->framing[y++] = oldorder.framing[x];
- }
- }
- ast_format_list_destroy(f_list);
-}
-
-/*! \brief Append all codecs to a preference list, without distrubing existing order */
-void ast_codec_pref_append_all(struct ast_codec_pref *pref)
-{
- int x, y, found;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- /* leave any existing entries, and don't create duplicates (e.g. allow=ulaw,all) */
- for (x = 0; x < f_len; x++) {
- /* x = codec to add */
- found = 0;
- for (y = 0; y < f_len; y++) {
- /* y = scan of existing preferences */
- if (!pref->order[y]) {
- break;
- }
- if (x + 1 == pref->order[y]) {
- found = 1;
- break;
- }
- }
- if (found) {
- continue;
- }
- for (; y < f_len; y++) {
- /* add x to the end of y */
- if (!pref->order[y])
- {
- pref->order[y] = x + 1;
- ast_format_copy(&pref->formats[y], &f_list[x].format);
- break;
- }
- }
- }
-}
-
-/*! \brief Append codec to list */
-int ast_codec_pref_append(struct ast_codec_pref *pref, struct ast_format *format)
-{
- int x, newindex = 0;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- ast_codec_pref_remove(pref, format);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- newindex = x + 1;
- break;
- }
- }
-
- if (newindex) {
- for (x = 0; x < f_len; x++) {
- if (!pref->order[x]) {
- pref->order[x] = newindex;
- ast_format_copy(&pref->formats[x], format);
- break;
- }
- }
- }
-
- ast_format_list_destroy(f_list);
- return x;
-}
-
-/*! \brief Prepend codec to list */
-void ast_codec_pref_prepend(struct ast_codec_pref *pref, struct ast_format *format, int only_if_existing)
-{
- int x, newindex = 0;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- /* First step is to get the codecs "index number" */
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- newindex = x + 1;
- break;
- }
- }
- /* Done if its unknown */
- if (!newindex) {
- ast_format_list_destroy(f_list);
- return;
- }
-
- /* Now find any existing occurrence, or the end */
- for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
- if (!pref->order[x] || pref->order[x] == newindex)
- break;
- }
-
- /* If we failed to find any occurrence, set to the end */
- if (x == AST_CODEC_PREF_SIZE) {
- --x;
- }
-
- if (only_if_existing && !pref->order[x]) {
- ast_format_list_destroy(f_list);
- return;
- }
-
- /* Move down to make space to insert - either all the way to the end,
- or as far as the existing location (which will be overwritten) */
- for (; x > 0; x--) {
- pref->order[x] = pref->order[x - 1];
- pref->framing[x] = pref->framing[x - 1];
- ast_format_copy(&pref->formats[x], &pref->formats[x - 1]);
- }
-
- /* And insert the new entry */
- pref->order[0] = newindex;
- pref->framing[0] = 0; /* ? */
- ast_format_copy(&pref->formats[0], format);
- ast_format_list_destroy(f_list);
-}
-
-/*! \brief Set packet size for codec */
-int ast_codec_pref_setsize(struct ast_codec_pref *pref, struct ast_format *format, int framems)
-{
- int x, idx = -1;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- idx = x;
- break;
- }
- }
-
- if (idx < 0) {
- ast_format_list_destroy(f_list);
- return -1;
- }
-
- /* size validation */
- if (!framems)
- framems = f_list[idx].def_ms;
-
- if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms) /* avoid division by zero */
- framems -= framems % f_list[idx].inc_ms;
-
- if (framems < f_list[idx].min_ms)
- framems = f_list[idx].min_ms;
-
- if (framems > f_list[idx].max_ms)
- framems = f_list[idx].max_ms;
-
- for (x = 0; x < f_len; x++) {
- if (pref->order[x] == (idx + 1)) {
- pref->framing[x] = framems;
- break;
- }
- }
-
- ast_format_list_destroy(f_list);
- return x;
-}
-
-/*! \brief Get packet size for codec */
-struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format)
-{
- int x, idx = -1, framems = 0;
- struct ast_format_list fmt = { { 0, }, };
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- fmt = f_list[x];
- idx = x;
- break;
- }
- }
-
- if (idx < 0) {
- ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format));
- ast_format_list_destroy(f_list);
- return fmt;
- }
-
- for (x = 0; x < f_len; x++) {
- if (pref->order[x] == (idx + 1)) {
- framems = pref->framing[x];
- break;
- }
- }
-
- /* size validation */
- if (!framems)
- framems = f_list[idx].def_ms;
-
- if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms) /* avoid division by zero */
- framems -= framems % f_list[idx].inc_ms;
-
- if (framems < f_list[idx].min_ms)
- framems = f_list[idx].min_ms;
-
- if (framems > f_list[idx].max_ms)
- framems = f_list[idx].max_ms;
-
- fmt.cur_ms = framems;
- ast_format_list_destroy(f_list);
- return fmt;
-}
-
-/*! \brief Pick a codec */
-struct ast_format *ast_codec_choose(struct ast_codec_pref *pref, struct ast_format_cap *cap, int find_best, struct ast_format *result)
-{
- int x, slot, found = 0;
- size_t f_len = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_len);
-
- for (x = 0; x < f_len; x++) {
- slot = pref->order[x];
-
- if (!slot)
- break;
- if (ast_format_cap_get_compatible_format(cap, &f_list[slot-1].format, result)) {
- found = 1; /*format is found and stored in result */
- break;
- }
- }
- ast_format_list_destroy(f_list);
- if (found && (AST_FORMAT_GET_TYPE(result->id) == AST_FORMAT_TYPE_AUDIO)) {
- return result;
- }
- ast_format_clear(result);
- ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
-
- return find_best ? ast_best_codec(cap, result) : NULL;
-}
-
-
diff --git a/main/frame.c b/main/frame.c
index 76ea3f66c..64af88237 100644
--- a/main/frame.c
+++ b/main/frame.c
@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
@@ -71,199 +72,8 @@ struct ast_frame_cache {
};
#endif
-#define SMOOTHER_SIZE 8000
-
-enum frame_type {
- TYPE_HIGH, /* 0x0 */
- TYPE_LOW, /* 0x1 */
- TYPE_SILENCE, /* 0x2 */
- TYPE_DONTSEND /* 0x3 */
-};
-
-#define TYPE_MASK 0x3
-
-struct ast_smoother {
- int size;
- struct ast_format format;
- int flags;
- float samplesperbyte;
- unsigned int opt_needs_swap:1;
- struct ast_frame f;
- struct timeval delivery;
- char data[SMOOTHER_SIZE];
- char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
- struct ast_frame *opt;
- int len;
-};
-
struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
-static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
-{
- if (s->flags & AST_SMOOTHER_FLAG_G729) {
- if (s->len % 10) {
- ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
- return 0;
- }
- }
- if (swap) {
- ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
- } else {
- memcpy(s->data + s->len, f->data.ptr, f->datalen);
- }
- /* If either side is empty, reset the delivery time */
- if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) { /* XXX really ? */
- s->delivery = f->delivery;
- }
- s->len += f->datalen;
-
- return 0;
-}
-
-void ast_smoother_reset(struct ast_smoother *s, int bytes)
-{
- memset(s, 0, sizeof(*s));
- s->size = bytes;
-}
-
-void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
-{
- /* if there is no change, then nothing to do */
- if (s->size == bytes) {
- return;
- }
- /* set the new desired output size */
- s->size = bytes;
- /* if there is no 'optimized' frame in the smoother,
- * then there is nothing left to do
- */
- if (!s->opt) {
- return;
- }
- /* there is an 'optimized' frame here at the old size,
- * but it must now be put into the buffer so the data
- * can be extracted at the new size
- */
- smoother_frame_feed(s, s->opt, s->opt_needs_swap);
- s->opt = NULL;
-}
-
-struct ast_smoother *ast_smoother_new(int size)
-{
- struct ast_smoother *s;
- if (size < 1)
- return NULL;
- if ((s = ast_malloc(sizeof(*s))))
- ast_smoother_reset(s, size);
- return s;
-}
-
-int ast_smoother_get_flags(struct ast_smoother *s)
-{
- return s->flags;
-}
-
-void ast_smoother_set_flags(struct ast_smoother *s, int flags)
-{
- s->flags = flags;
-}
-
-int ast_smoother_test_flag(struct ast_smoother *s, int flag)
-{
- return (s->flags & flag);
-}
-
-int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
-{
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
- return -1;
- }
- if (!s->format.id) {
- ast_format_copy(&s->format, &f->subclass.format);
- s->samplesperbyte = (float)f->samples / (float)f->datalen;
- } else if (ast_format_cmp(&s->format, &f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_log(LOG_WARNING, "Smoother was working on %s format frames, now trying to feed %s?\n",
- ast_getformatname(&s->format), ast_getformatname(&f->subclass.format));
- return -1;
- }
- if (s->len + f->datalen > SMOOTHER_SIZE) {
- ast_log(LOG_WARNING, "Out of smoother space\n");
- return -1;
- }
- if (((f->datalen == s->size) ||
- ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
- !s->opt &&
- !s->len &&
- (f->offset >= AST_MIN_OFFSET)) {
- /* Optimize by sending the frame we just got
- on the next read, thus eliminating the douple
- copy */
- if (swap)
- ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
- s->opt = f;
- s->opt_needs_swap = swap ? 1 : 0;
- return 0;
- }
-
- return smoother_frame_feed(s, f, swap);
-}
-
-struct ast_frame *ast_smoother_read(struct ast_smoother *s)
-{
- struct ast_frame *opt;
- int len;
-
- /* IF we have an optimization frame, send it */
- if (s->opt) {
- if (s->opt->offset < AST_FRIENDLY_OFFSET)
- ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
- s->opt->offset);
- opt = s->opt;
- s->opt = NULL;
- return opt;
- }
-
- /* Make sure we have enough data */
- if (s->len < s->size) {
- /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
- if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
- return NULL;
- }
- len = s->size;
- if (len > s->len)
- len = s->len;
- /* Make frame */
- s->f.frametype = AST_FRAME_VOICE;
- ast_format_copy(&s->f.subclass.format, &s->format);
- s->f.data.ptr = s->framedata + AST_FRIENDLY_OFFSET;
- s->f.offset = AST_FRIENDLY_OFFSET;
- s->f.datalen = len;
- /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
- s->f.samples = len * s->samplesperbyte; /* XXX rounding */
- s->f.delivery = s->delivery;
- /* Fill Data */
- memcpy(s->f.data.ptr, s->data, len);
- s->len -= len;
- /* Move remaining data to the front if applicable */
- if (s->len) {
- /* In principle this should all be fine because if we are sending
- G.729 VAD, the next timestamp will take over anyawy */
- memmove(s->data, s->data + len, s->len);
- if (!ast_tvzero(s->delivery)) {
- /* If we have delivery time, increment it, otherwise, leave it at 0 */
- s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, ast_format_rate(&s->format)));
- }
- }
- /* Return frame */
- return &s->f;
-}
-
-void ast_smoother_free(struct ast_smoother *s)
-{
- ast_free(s);
-}
-
static struct ast_frame *ast_frame_header_new(void)
{
struct ast_frame *f;
@@ -316,9 +126,13 @@ static void __frame_free(struct ast_frame *fr, int cache)
/* Cool, only the header is malloc'd, let's just cache those for now
* to keep things simple... */
struct ast_frame_cache *frames;
-
if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
(frames->size < FRAME_CACHE_MAX_SIZE)) {
+ if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
+ (fr->frametype == AST_FRAME_IMAGE)) {
+ ao2_cleanup(fr->subclass.format);
+ }
+
AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
frames->size++;
return;
@@ -335,7 +149,14 @@ static void __frame_free(struct ast_frame *fr, int cache)
ast_free((void *) fr->src);
}
if (fr->mallocd & AST_MALLOCD_HDR) {
+ if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
+ (fr->frametype == AST_FRAME_IMAGE)) {
+ ao2_cleanup(fr->subclass.format);
+ }
+
ast_free(fr);
+ } else {
+ fr->mallocd = 0;
}
}
@@ -387,7 +208,12 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
return NULL;
}
out->frametype = fr->frametype;
- ast_format_copy(&out->subclass.format, &fr->subclass.format);
+ if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
+ (fr->frametype == AST_FRAME_IMAGE)) {
+ out->subclass.format = ao2_bump(fr->subclass.format);
+ } else {
+ memcpy(&out->subclass, &fr->subclass, sizeof(out->subclass));
+ }
out->datalen = fr->datalen;
out->samples = fr->samples;
out->offset = fr->offset;
@@ -494,7 +320,12 @@ struct ast_frame *ast_frdup(const struct ast_frame *f)
}
out->frametype = f->frametype;
- ast_format_copy(&out->subclass.format, &f->subclass.format);
+ if ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO) ||
+ (f->frametype == AST_FRAME_IMAGE)) {
+ out->subclass.format = ao2_bump(f->subclass.format);
+ } else {
+ memcpy(&out->subclass, &f->subclass, sizeof(out->subclass));
+ }
out->datalen = f->datalen;
out->samples = f->samples;
out->delivery = f->delivery;
@@ -650,7 +481,7 @@ void ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, ch
}
break;
case AST_FRAME_IMAGE:
- snprintf(subclass, slen, "Image format %s\n", ast_getformatname(&f->subclass.format));
+ snprintf(subclass, slen, "Image format %s\n", ast_format_get_name(f->subclass.format));
break;
case AST_FRAME_HTML:
switch (f->subclass.integer) {
@@ -816,369 +647,13 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
}
-int ast_parse_allow_disallow(struct ast_codec_pref *pref, struct ast_format_cap *cap, const char *list, int allowing)
-{
- int errors = 0, framems = 0, all = 0, iter_allowing;
- char *parse = NULL, *this = NULL, *psize = NULL;
- struct ast_format format;
-
- parse = ast_strdupa(list);
- while ((this = strsep(&parse, ","))) {
- iter_allowing = allowing;
- framems = 0;
- if (*this == '!') {
- this++;
- iter_allowing = !allowing;
- }
- if ((psize = strrchr(this, ':'))) {
- *psize++ = '\0';
- ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
- framems = atoi(psize);
- if (framems < 0) {
- framems = 0;
- errors++;
- ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
- }
- }
- all = strcasecmp(this, "all") ? 0 : 1;
-
- if (!all && !ast_getformatbyname(this, &format)) {
- ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", iter_allowing ? "allow" : "disallow", this);
- errors++;
- continue;
- }
-
- if (cap) {
- if (iter_allowing) {
- if (all) {
- ast_format_cap_add_all(cap);
- } else {
- ast_format_cap_add(cap, &format);
- }
- } else {
- if (all) {
- ast_format_cap_remove_all(cap);
- } else {
- ast_format_cap_remove(cap, &format);
- }
- }
- }
-
- if (pref) {
- if (!all) {
- if (iter_allowing) {
- ast_codec_pref_append(pref, &format);
- ast_codec_pref_setsize(pref, &format, framems);
- } else {
- ast_codec_pref_remove(pref, &format);
- }
- } else if (!iter_allowing) {
- memset(pref, 0, sizeof(*pref));
- } else {
- ast_codec_pref_append_all(pref);
- }
- }
- }
- return errors;
-}
-
-static int g723_len(unsigned char buf)
-{
- enum frame_type type = buf & TYPE_MASK;
-
- switch(type) {
- case TYPE_DONTSEND:
- return 0;
- break;
- case TYPE_SILENCE:
- return 4;
- break;
- case TYPE_HIGH:
- return 24;
- break;
- case TYPE_LOW:
- return 20;
- break;
- default:
- ast_log(LOG_WARNING, "Badly encoded frame (%u)\n", type);
- }
- return -1;
-}
-
-static int g723_samples(unsigned char *buf, int maxlen)
-{
- int pos = 0;
- int samples = 0;
- int res;
- while(pos < maxlen) {
- res = g723_len(buf[pos]);
- if (res <= 0)
- break;
- samples += 240;
- pos += res;
- }
- return samples;
-}
-
-static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
-{
- int byte = bit / 8; /* byte containing first bit */
- int rem = 8 - (bit % 8); /* remaining bits in first byte */
- unsigned char ret = 0;
-
- if (n <= 0 || n > 8)
- return 0;
-
- if (rem < n) {
- ret = (data[byte] << (n - rem));
- ret |= (data[byte + 1] >> (8 - n + rem));
- } else {
- ret = (data[byte] >> (rem - n));
- }
-
- return (ret & (0xff >> (8 - n)));
-}
-
-static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
-{
- static const int SpeexWBSubModeSz[] = {
- 4, 36, 112, 192,
- 352, 0, 0, 0 };
- int off = bit;
- unsigned char c;
-
- /* skip up to two wideband frames */
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
-
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
-
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
- return -1;
- }
- }
-
- }
- return off - bit;
-}
-
-static int speex_samples(unsigned char *data, int len)
-{
- static const int SpeexSubModeSz[] = {
- 5, 43, 119, 160,
- 220, 300, 364, 492,
- 79, 0, 0, 0,
- 0, 0, 0, 0 };
- static const int SpeexInBandSz[] = {
- 1, 1, 4, 4,
- 4, 4, 4, 4,
- 8, 8, 16, 16,
- 32, 32, 64, 64 };
- int bit = 0;
- int cnt = 0;
- int off;
- unsigned char c;
-
- while ((len * 8 - bit) >= 5) {
- /* skip wideband frames */
- off = speex_get_wb_sz_at(data, len, bit);
- if (off < 0) {
- ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
- break;
- }
- bit += off;
-
- if ((len * 8 - bit) < 5)
- break;
-
- /* get control bits */
- c = get_n_bits_at(data, 5, bit);
- bit += 5;
-
- if (c == 15) {
- /* terminator */
- break;
- } else if (c == 14) {
- /* in-band signal; next 4 bits contain signal id */
- c = get_n_bits_at(data, 4, bit);
- bit += 4;
- bit += SpeexInBandSz[c];
- } else if (c == 13) {
- /* user in-band; next 4 bits contain msg len */
- c = get_n_bits_at(data, 4, bit);
- bit += 4;
- /* after which it's 5-bit signal id + c bytes of data */
- bit += 5 + c * 8;
- } else if (c > 8) {
- /* unknown */
- ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
- break;
- } else {
- /* skip number bits for submode (less the 5 control bits) */
- bit += SpeexSubModeSz[c] - 5;
- cnt += 160; /* new frame */
- }
- }
- return cnt;
-}
-
-int ast_codec_get_samples(struct ast_frame *f)
-{
- int samples = 0;
-
- switch (f->subclass.format.id) {
- case AST_FORMAT_SPEEX:
- samples = speex_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_SPEEX16:
- samples = 2 * speex_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_SPEEX32:
- samples = 4 * speex_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_G723_1:
- samples = g723_samples(f->data.ptr, f->datalen);
- break;
- case AST_FORMAT_ILBC:
- samples = 240 * (f->datalen / 50);
- break;
- case AST_FORMAT_GSM:
- samples = 160 * (f->datalen / 33);
- break;
- case AST_FORMAT_G729A:
- samples = f->datalen * 8;
- break;
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_SLINEAR16:
- samples = f->datalen / 2;
- break;
- case AST_FORMAT_LPC10:
- /* assumes that the RTP packet contains one LPC10 frame */
- samples = 22 * 8;
- samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
- break;
- case AST_FORMAT_ULAW:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_TESTLAW:
- samples = f->datalen;
- break;
- case AST_FORMAT_G722:
- case AST_FORMAT_ADPCM:
- case AST_FORMAT_G726:
- case AST_FORMAT_G726_AAL2:
- samples = f->datalen * 2;
- break;
- case AST_FORMAT_SIREN7:
- /* 16,000 samples per second at 32kbps is 4,000 bytes per second */
- samples = f->datalen * (16000 / 4000);
- break;
- case AST_FORMAT_SIREN14:
- /* 32,000 samples per second at 48kbps is 6,000 bytes per second */
- samples = (int) f->datalen * ((float) 32000 / 6000);
- break;
- case AST_FORMAT_G719:
- /* 48,000 samples per second at 64kbps is 8,000 bytes per second */
- samples = (int) f->datalen * ((float) 48000 / 8000);
- break;
- case AST_FORMAT_SILK:
- if (!(ast_format_isset(&f->subclass.format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_24KHZ,
- AST_FORMAT_ATTR_END))) {
- return 480;
- } else if (!(ast_format_isset(&f->subclass.format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END))) {
- return 320;
- } else if (!(ast_format_isset(&f->subclass.format,
- SILK_ATTR_KEY_SAMP_RATE,
- SILK_ATTR_VAL_SAMP_12KHZ,
- AST_FORMAT_ATTR_END))) {
- return 240;
- } else {
- return 160;
- }
- case AST_FORMAT_CELT:
- /* TODO This assumes 20ms delivery right now, which is incorrect */
- samples = ast_format_rate(&f->subclass.format) / 50;
- break;
- case AST_FORMAT_OPUS:
- /* TODO This assumes 20ms delivery right now, which is incorrect */
- samples = 960;
- break;
- default:
- ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format));
- }
- return samples;
-}
-
-int ast_codec_get_len(struct ast_format *format, int samples)
-{
- int len = 0;
-
- /* XXX Still need speex, and lpc10 XXX */
- switch(format->id) {
- case AST_FORMAT_G723_1:
- len = (samples / 240) * 20;
- break;
- case AST_FORMAT_ILBC:
- len = (samples / 240) * 50;
- break;
- case AST_FORMAT_GSM:
- len = (samples / 160) * 33;
- break;
- case AST_FORMAT_G729A:
- len = samples / 8;
- break;
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_SLINEAR16:
- len = samples * 2;
- break;
- case AST_FORMAT_ULAW:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_TESTLAW:
- len = samples;
- break;
- case AST_FORMAT_G722:
- case AST_FORMAT_ADPCM:
- case AST_FORMAT_G726:
- case AST_FORMAT_G726_AAL2:
- len = samples / 2;
- break;
- case AST_FORMAT_SIREN7:
- /* 16,000 samples per second at 32kbps is 4,000 bytes per second */
- len = samples / (16000 / 4000);
- break;
- case AST_FORMAT_SIREN14:
- /* 32,000 samples per second at 48kbps is 6,000 bytes per second */
- len = (int) samples / ((float) 32000 / 6000);
- break;
- case AST_FORMAT_G719:
- /* 48,000 samples per second at 64kbps is 8,000 bytes per second */
- len = (int) samples / ((float) 48000 / 8000);
- break;
- default:
- ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
- }
-
- return len;
-}
-
int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
{
int count;
short *fdata = f->data.ptr;
short adjust_value = abs(adjustment);
- if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_is_slinear(&f->subclass.format))) {
+ if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_cache_is_slinear(f->subclass.format))) {
return -1;
}
@@ -1202,10 +677,10 @@ int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
int count;
short *data1, *data2;
- if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass.format.id != AST_FORMAT_SLINEAR))
+ if ((f1->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f1->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
return -1;
- if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass.format.id != AST_FORMAT_SLINEAR))
+ if ((f2->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f2->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
return -1;
if (f1->samples != f2->samples)
diff --git a/main/image.c b/main/image.c
index 08620d734..53638f30c 100644
--- a/main/image.c
+++ b/main/image.c
@@ -114,7 +114,7 @@ struct ast_frame *ast_read_image(const char *filename, const char *preflang, str
AST_RWLIST_RDLOCK(&imagers);
AST_RWLIST_TRAVERSE(&imagers, i, list) {
/* if NULL image format, just pick the first one, otherwise match it. */
- if (!format || (ast_format_cmp(&i->format, format) == AST_FORMAT_CMP_EQUAL)) {
+ if (!format || (ast_format_cmp(i->format, format) == AST_FORMAT_CMP_EQUAL)) {
char *stringp=NULL;
ast_copy_string(tmp, i->exts, sizeof(tmp));
stringp = tmp;
@@ -194,7 +194,7 @@ static char *handle_core_show_image_formats(struct ast_cli_entry *e, int cmd, st
ast_cli(a->fd, FORMAT, "----", "----------", "-----------", "------");
AST_RWLIST_RDLOCK(&imagers);
AST_RWLIST_TRAVERSE(&imagers, i, list) {
- ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(&i->format));
+ ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_format_get_name(i->format));
count_fmt++;
}
AST_RWLIST_UNLOCK(&imagers);
diff --git a/main/indications.c b/main/indications.c
index 2f2bdce62..27d2b5356 100644
--- a/main/indications.c
+++ b/main/indications.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h"
#include "asterisk/indications.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
@@ -120,7 +121,7 @@ struct playtones_state {
int npos;
int oldnpos;
int pos;
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
struct ast_frame f;
unsigned char offset[AST_FRIENDLY_OFFSET];
short data[4000];
@@ -131,13 +132,11 @@ static void playtones_release(struct ast_channel *chan, void *params)
struct playtones_state *ps = params;
if (chan) {
- ast_set_write_format(chan, &ps->origwfmt);
+ ast_set_write_format(chan, ps->origwfmt);
}
- if (ps->items) {
- ast_free(ps->items);
- ps->items = NULL;
- }
+ ao2_cleanup(ps->origwfmt);
+ ast_free(ps->items);
ast_free(ps);
}
@@ -151,9 +150,9 @@ static void *playtones_alloc(struct ast_channel *chan, void *params)
return NULL;
}
- ast_format_copy(&ps->origwfmt, ast_channel_writeformat(chan));
+ ps->origwfmt = ao2_bump(ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_write_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", ast_channel_name(chan));
playtones_release(NULL, ps);
ps = NULL;
@@ -227,7 +226,7 @@ static int playtones_generator(struct ast_channel *chan, void *data, int len, in
}
ps->f.frametype = AST_FRAME_VOICE;
- ast_format_set(&ps->f.subclass.format, AST_FORMAT_SLINEAR, 0);
+ ps->f.subclass.format = ast_format_slin;
ps->f.datalen = len;
ps->f.samples = samples;
ps->f.offset = AST_FRIENDLY_OFFSET;
diff --git a/main/manager.c b/main/manager.c
index 75811886f..35ba5d46c 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -99,6 +99,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridge.h"
#include "asterisk/features_config.h"
#include "asterisk/rtp_engine.h"
+#include "asterisk/format_cache.h"
#include "asterisk/translate.h"
/*** DOCUMENTATION
@@ -3869,7 +3870,7 @@ static int action_status(struct mansession *s, const struct message *m)
struct ast_str *write_transpath = ast_str_alloca(256);
struct ast_str *read_transpath = ast_str_alloca(256);
struct ast_channel *chan;
- char nativeformats[256];
+ struct ast_str *codec_buf = ast_str_alloca(64);
int channels = 0;
int all = ast_strlen_zero(name); /* set if we want all channels */
char id_text[256];
@@ -4007,10 +4008,10 @@ static int action_status(struct mansession *s, const struct message *m)
ast_channel_linkedid(chan),
ast_channel_appl(chan),
ast_channel_data(chan),
- ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)),
- ast_getformatname(ast_channel_readformat(chan)),
+ ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(chan)),
ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath),
- ast_getformatname(ast_channel_writeformat(chan)),
+ ast_format_get_name(ast_channel_writeformat(chan)),
ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath),
ast_channel_callgroup(chan),
ast_channel_pickupgroup(chan),
@@ -4458,7 +4459,7 @@ struct fast_originate_helper {
*/
static void destroy_fast_originate_helper(struct fast_originate_helper *doomed)
{
- ast_format_cap_destroy(doomed->cap);
+ ao2_cleanup(doomed->cap);
ast_variables_destroy(doomed->vars);
ast_string_field_free_memory(doomed);
ast_free(doomed);
@@ -4781,8 +4782,7 @@ static int action_originate(struct mansession *s, const struct message *m)
int reason = 0;
char tmp[256];
char tmp2[256];
- struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format tmp_fmt;
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
pthread_t th;
int bridge_early = 0;
@@ -4790,7 +4790,7 @@ static int action_originate(struct mansession *s, const struct message *m)
astman_send_error(s, m, "Internal Error. Memory allocation failure.");
return 0;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
|| (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
@@ -4840,8 +4840,8 @@ static int action_originate(struct mansession *s, const struct message *m)
}
}
if (!ast_strlen_zero(codecs)) {
- ast_format_cap_remove_all(cap);
- ast_parse_allow_disallow(NULL, cap, codecs, 1);
+ ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_update_by_allow_disallow(cap, codecs, 1);
}
if (!ast_strlen_zero(app) && s->session) {
@@ -4957,7 +4957,7 @@ static int action_originate(struct mansession *s, const struct message *m)
}
fast_orig_cleanup:
- ast_format_cap_destroy(cap);
+ ao2_cleanup(cap);
return 0;
}
diff --git a/main/media_index.c b/main/media_index.c
index a643c237f..3e3824580 100644
--- a/main/media_index.c
+++ b/main/media_index.c
@@ -56,7 +56,7 @@ static void media_variant_destroy(void *obj)
struct media_variant *variant = obj;
ast_string_field_free_memory(variant);
- variant->formats = ast_format_cap_destroy(variant->formats);
+ ao2_cleanup(variant->formats);
}
static struct media_variant *media_variant_alloc(const char *variant_str)
@@ -67,7 +67,7 @@ static struct media_variant *media_variant_alloc(const char *variant_str)
return NULL;
}
- variant->formats = ast_format_cap_alloc(0);
+ variant->formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!variant->formats) {
return NULL;
}
@@ -239,6 +239,7 @@ const char *ast_media_get_description(struct ast_media_index *index, const char
struct ast_format_cap *ast_media_get_format_cap(struct ast_media_index *index, const char *filename, const char *variant_str)
{
+ struct ast_format_cap *dupcap;
RAII_VAR(struct media_variant *, variant, NULL, ao2_cleanup);
if (ast_strlen_zero(filename) || ast_strlen_zero(variant_str)) {
return NULL;
@@ -249,7 +250,11 @@ struct ast_format_cap *ast_media_get_format_cap(struct ast_media_index *index, c
return NULL;
}
- return ast_format_cap_dup(variant->formats);
+ dupcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (dupcap) {
+ ast_format_cap_append_from_cap(dupcap, variant->formats, AST_MEDIA_TYPE_UNKNOWN);
+ }
+ return dupcap;
}
/*! \brief Add the variant to the list of variants requested */
@@ -317,7 +322,7 @@ struct ao2_container *ast_media_get_media(struct ast_media_index *index)
}
/*! \brief Update an index with new format/variant information */
-static int update_file_format_info(struct ast_media_index *index, const char *filename, const char *variant_str, const struct ast_format *file_format)
+static int update_file_format_info(struct ast_media_index *index, const char *filename, const char *variant_str, struct ast_format *file_format)
{
RAII_VAR(struct media_variant *, variant, find_variant(index, filename, variant_str), ao2_cleanup);
if (!variant) {
@@ -327,14 +332,14 @@ static int update_file_format_info(struct ast_media_index *index, const char *fi
}
}
- ast_format_cap_add(variant->formats, file_format);
+ ast_format_cap_append(variant->formats, file_format, 0);
return 0;
}
/*! \brief Process a media file into the index */
static int process_media_file(struct ast_media_index *index, const char *variant, const char *subdir, const char *filename_stripped, const char *ext)
{
- const struct ast_format *file_format;
+ struct ast_format *file_format;
const char *file_identifier = filename_stripped;
RAII_VAR(struct ast_str *, file_id_str, NULL, ast_free);
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 9e3d7d108..07ef1f697 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -196,12 +196,18 @@ static AST_RWLIST_HEAD_STATIC(engines, ast_rtp_engine);
/*! List of RTP glues */
static AST_RWLIST_HEAD_STATIC(glues, ast_rtp_glue);
+#define MAX_RTP_MIME_TYPES 128
+
/*! The following array defines the MIME Media type (and subtype) for each
of our codecs, or RTP-specific data type. */
static struct ast_rtp_mime_type {
+ /*! \brief A mapping object between the Asterisk codec and this RTP payload */
struct ast_rtp_payload_type payload_type;
- char *type;
- char *subtype;
+ /*! \brief The media type */
+ char type[16];
+ /*! \brief The format type */
+ char subtype[64];
+ /*! \brief Expected sample rate of the /c subtype */
unsigned int sample_rate;
} ast_rtp_mime_types[128]; /* This will Likely not need to grow any time soon. */
static ast_rwlock_t mime_types_lock;
@@ -223,6 +229,24 @@ static ast_rwlock_t static_RTP_PT_lock;
/*! \brief \ref stasis topic for RTP related messages */
static struct stasis_topic *rtp_topic;
+
+/*! \internal \brief Destructor for \c ast_rtp_payload_type */
+static void rtp_payload_type_dtor(void *obj)
+{
+ struct ast_rtp_payload_type *payload = obj;
+
+ ao2_cleanup(payload->format);
+}
+
+struct ast_rtp_payload_type *ast_rtp_engine_alloc_payload_type(void)
+{
+ struct ast_rtp_payload_type *payload;
+
+ payload = ao2_alloc(sizeof(*payload), rtp_payload_type_dtor);
+
+ return payload;
+}
+
int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
{
struct ast_rtp_engine *current_engine;
@@ -526,34 +550,30 @@ struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *inst
return &instance->codecs;
}
-static int rtp_payload_type_hash(const void *obj, const int flags)
+int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
{
- const struct ast_rtp_payload_type *type = obj;
- const int *payload = obj;
+ int res;
+
+ codecs->framing = 0;
+ ast_rwlock_init(&codecs->codecs_lock);
+ res = AST_VECTOR_INIT(&codecs->payloads, AST_RTP_MAX_PT);
- return (flags & OBJ_KEY) ? *payload : type->payload;
+ return res;
}
-static int rtp_payload_type_cmp(void *obj, void *arg, int flags)
+void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
{
- struct ast_rtp_payload_type *type1 = obj, *type2 = arg;
- const int *payload = arg;
+ int i;
- return (type1->payload == (OBJ_KEY ? *payload : type2->payload)) ? CMP_MATCH | CMP_STOP : 0;
-}
+ for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
+ struct ast_rtp_payload_type *type;
-int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
-{
- if (!(codecs->payloads = ao2_container_alloc(AST_RTP_MAX_PT, rtp_payload_type_hash, rtp_payload_type_cmp))) {
- return -1;
+ type = AST_VECTOR_GET(&codecs->payloads, i);
+ ao2_t_cleanup(type, "destroying ast_rtp_codec");
}
+ AST_VECTOR_FREE(&codecs->payloads);
- return 0;
-}
-
-void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
-{
- ao2_cleanup(codecs->payloads);
+ ast_rwlock_destroy(&codecs->codecs_lock);
}
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
@@ -570,106 +590,69 @@ void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp
ast_rtp_codecs_payloads_initialize(codecs);
}
-void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
-{
- int i;
-
- ast_rwlock_rdlock(&static_RTP_PT_lock);
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- if (static_RTP_PT[i].rtp_code || static_RTP_PT[i].asterisk_format) {
- struct ast_rtp_payload_type *type;
-
- if (!(type = ao2_alloc(sizeof(*type), NULL))) {
- /* Unfortunately if this occurs the payloads container will not contain all possible default payloads
- * but we err on the side of doing what we can in the hopes that the extreme memory conditions which
- * caused this to occur will go away.
- */
- continue;
- }
-
- type->payload = i;
- type->asterisk_format = static_RTP_PT[i].asterisk_format;
- type->rtp_code = static_RTP_PT[i].rtp_code;
- ast_format_copy(&type->format, &static_RTP_PT[i].format);
-
- ao2_link_flags(codecs->payloads, type, OBJ_NOLOCK);
-
- if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, i, type->asterisk_format, &type->format, type->rtp_code);
- }
-
- ao2_ref(type, -1);
- }
- }
- ast_rwlock_unlock(&static_RTP_PT_lock);
-}
-
void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
{
int i;
- struct ast_rtp_payload_type *type;
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- struct ast_rtp_payload_type *new_type;
+ ast_rwlock_rdlock(&src->codecs_lock);
+ ast_rwlock_wrlock(&dest->codecs_lock);
- if (!(type = ao2_find(src->payloads, &i, OBJ_KEY | OBJ_NOLOCK))) {
- continue;
- }
+ for (i = 0; i < AST_VECTOR_SIZE(&src->payloads); i++) {
+ struct ast_rtp_payload_type *type;
- if (!(new_type = ao2_alloc(sizeof(*new_type), NULL))) {
+ type = AST_VECTOR_GET(&src->payloads, i);
+ if (!type) {
continue;
}
-
- ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest);
-
- new_type->payload = i;
- *new_type = *type;
-
- ao2_link_flags(dest->payloads, new_type, OBJ_NOLOCK);
-
- ao2_ref(new_type, -1);
+ if (i < AST_VECTOR_SIZE(&dest->payloads)) {
+ ao2_t_cleanup(AST_VECTOR_GET(&dest->payloads, i), "cleaning up vector element about to be replaced");
+ }
+ ast_debug(2, "Copying payload %d (%p) from %p to %p\n", i, type, src, dest);
+ ao2_bump(type);
+ AST_VECTOR_INSERT(&dest->payloads, i, type);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, i, type->asterisk_format, &type->format, type->rtp_code);
+ instance->engine->payload_set(instance, i, type->asterisk_format, type->format, type->rtp_code);
}
-
- ao2_ref(type, -1);
}
+ dest->framing = src->framing;
+ ast_rwlock_unlock(&dest->codecs_lock);
+ ast_rwlock_unlock(&src->codecs_lock);
}
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
{
- struct ast_rtp_payload_type *type;
+ struct ast_rtp_payload_type *new_type;
- ast_rwlock_rdlock(&static_RTP_PT_lock);
+ new_type = ast_rtp_engine_alloc_payload_type();
+ if (!new_type) {
+ return;
+ }
+ ast_rwlock_rdlock(&static_RTP_PT_lock);
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
ast_rwlock_unlock(&static_RTP_PT_lock);
return;
}
- if (!(type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
- if (!(type = ao2_alloc(sizeof(*type), NULL))) {
- ast_rwlock_unlock(&static_RTP_PT_lock);
- return;
- }
- type->payload = payload;
- ao2_link_flags(codecs->payloads, type, OBJ_NOLOCK);
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ ao2_t_cleanup(AST_VECTOR_GET(&codecs->payloads, payload), "cleaning up replaced payload type");
}
- type->asterisk_format = static_RTP_PT[payload].asterisk_format;
- type->rtp_code = static_RTP_PT[payload].rtp_code;
- type->payload = payload;
- ast_format_copy(&type->format, &static_RTP_PT[payload].format);
+ new_type->asterisk_format = static_RTP_PT[payload].asterisk_format;
+ new_type->rtp_code = static_RTP_PT[payload].rtp_code;
+ new_type->payload = payload;
+ new_type->format = ao2_bump(static_RTP_PT[payload].format);
- ast_debug(1, "Setting payload %d based on m type on %p\n", payload, codecs);
+ ast_debug(1, "Setting payload %d (%p) based on m type on %p\n", payload, new_type, codecs);
+ AST_VECTOR_INSERT(&codecs->payloads, payload, new_type);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, payload, type->asterisk_format, &type->format, type->rtp_code);
+ instance->engine->payload_set(instance, payload, new_type->asterisk_format, new_type->format, new_type->rtp_code);
}
- ao2_ref(type, -1);
-
+ ast_rwlock_unlock(&codecs->codecs_lock);
ast_rwlock_unlock(&static_RTP_PT_lock);
}
@@ -681,13 +664,16 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
unsigned int i;
int found = 0;
- if (pt < 0 || pt >= AST_RTP_MAX_PT)
+ ast_rwlock_rdlock(&mime_types_lock);
+ if (pt < 0 || pt >= AST_RTP_MAX_PT) {
+ ast_rwlock_unlock(&mime_types_lock);
return -1; /* bogus payload type */
+ }
- ast_rwlock_rdlock(&mime_types_lock);
+ ast_rwlock_wrlock(&codecs->codecs_lock);
for (i = 0; i < mime_types_len; ++i) {
const struct ast_rtp_mime_type *t = &ast_rtp_mime_types[i];
- struct ast_rtp_payload_type *type;
+ struct ast_rtp_payload_type *new_type;
if (strcasecmp(mimesubtype, t->subtype)) {
continue;
@@ -707,29 +693,33 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
found = 1;
- if (!(type = ao2_find(codecs->payloads, &pt, OBJ_KEY | OBJ_NOLOCK))) {
- if (!(type = ao2_alloc(sizeof(*type), NULL))) {
- continue;
- }
- type->payload = pt;
- ao2_link_flags(codecs->payloads, type, OBJ_NOLOCK);
+ new_type = ast_rtp_engine_alloc_payload_type();
+ if (!new_type) {
+ continue;
}
- *type = t->payload_type;
- type->payload = pt;
+ if (pt < AST_VECTOR_SIZE(&codecs->payloads)) {
+ ao2_t_cleanup(AST_VECTOR_GET(&codecs->payloads, pt), "cleaning up replaced payload type");
+ }
- if ((t->payload_type.format.id == AST_FORMAT_G726) && t->payload_type.asterisk_format && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
- ast_format_set(&type->format, AST_FORMAT_G726_AAL2, 0);
+ new_type->payload = pt;
+ new_type->asterisk_format = t->payload_type.asterisk_format;
+ new_type->rtp_code = t->payload_type.rtp_code;
+ if ((ast_format_cmp(t->payload_type.format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) &&
+ t->payload_type.asterisk_format && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
+ new_type->format = ao2_bump(ast_format_g726_aal2);
+ } else {
+ new_type->format = ao2_bump(t->payload_type.format);
}
+ AST_VECTOR_INSERT(&codecs->payloads, pt, new_type);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, pt, type->asterisk_format, &type->format, type->rtp_code);
+ instance->engine->payload_set(instance, pt, new_type->asterisk_format, new_type->format, new_type->rtp_code);
}
- ao2_ref(type, -1);
-
break;
}
+ ast_rwlock_unlock(&codecs->codecs_lock);
ast_rwlock_unlock(&mime_types_lock);
return (found ? 0 : -2);
@@ -742,157 +732,209 @@ int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struc
void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
{
+ struct ast_rtp_payload_type *type;
+
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
return;
}
ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
- ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK | OBJ_NODATA | OBJ_UNLINK);
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ ao2_cleanup(type);
+ AST_VECTOR_INSERT(&codecs->payloads, payload, NULL);
+ }
if (instance && instance->engine && instance->engine->payload_set) {
instance->engine->payload_set(instance, payload, 0, NULL, 0);
}
+
+ ast_rwlock_unlock(&codecs->codecs_lock);
}
-struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload)
+struct ast_rtp_payload_type *ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
{
- struct ast_rtp_payload_type result = { .asterisk_format = 0, }, *type;
+ struct ast_rtp_payload_type *type = NULL;
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
- return result;
+ return NULL;
}
- if ((type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
- result = *type;
- ao2_ref(type, -1);
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ ao2_bump(type);
}
+ ast_rwlock_unlock(&codecs->codecs_lock);
- if (!result.rtp_code && !result.asterisk_format) {
+ if (!type) {
+ type = ast_rtp_engine_alloc_payload_type();
+ if (!type) {
+ return NULL;
+ }
ast_rwlock_rdlock(&static_RTP_PT_lock);
- result = static_RTP_PT[payload];
+ type->asterisk_format = static_RTP_PT[payload].asterisk_format;
+ type->rtp_code = static_RTP_PT[payload].rtp_code;
+ type->payload = payload;
+ type->format = ao2_bump(static_RTP_PT[payload].format);
ast_rwlock_unlock(&static_RTP_PT_lock);
}
- return result;
+ return type;
}
+int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
+{
+ struct ast_rtp_payload_type *type;
+
+ if (payload < 0 || payload >= AST_RTP_MAX_PT) {
+ return -1;
+ }
+
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ if (type && type->asterisk_format) {
+ ao2_replace(type->format, format);
+ }
+ }
+ ast_rwlock_unlock(&codecs->codecs_lock);
+
+ return 0;
+}
struct ast_format *ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload)
{
struct ast_rtp_payload_type *type;
- struct ast_format *format;
+ struct ast_format *format = NULL;
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
return NULL;
}
- if (!(type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
- return NULL;
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, payload);
+ if (type && type->asterisk_format) {
+ format = ao2_bump(type->format);
+ }
}
-
- format = type->asterisk_format ? &type->format : NULL;
-
- ao2_ref(type, -1);
+ ast_rwlock_unlock(&codecs->codecs_lock);
return format;
}
-static int rtp_payload_type_add_ast(void *obj, void *arg, int flags)
+void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
{
- struct ast_rtp_payload_type *type = obj;
- struct ast_format_cap *astformats = arg;
-
- if (type->asterisk_format) {
- ast_format_cap_add(astformats, &type->format);
+ if (!framing) {
+ return;
}
- return 0;
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ codecs->framing = framing;
+ ast_rwlock_unlock(&codecs->codecs_lock);
}
-static int rtp_payload_type_add_nonast(void *obj, void *arg, int flags)
+unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
{
- struct ast_rtp_payload_type *type = obj;
- int *nonastformats = arg;
+ unsigned int framing;
- if (!type->asterisk_format) {
- *nonastformats |= type->rtp_code;
- }
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ framing = codecs->framing;
+ ast_rwlock_unlock(&codecs->codecs_lock);
- return 0;
+ return framing;
}
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
{
- ast_format_cap_remove_all(astformats);
+ int i;
+
+ ast_format_cap_remove_by_type(astformats, AST_MEDIA_TYPE_UNKNOWN);
*nonastformats = 0;
- ao2_callback(codecs->payloads, OBJ_NODATA | OBJ_MULTIPLE | OBJ_NOLOCK, rtp_payload_type_add_ast, astformats);
- ao2_callback(codecs->payloads, OBJ_NODATA | OBJ_MULTIPLE | OBJ_NOLOCK, rtp_payload_type_add_nonast, nonastformats);
-}
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
+ struct ast_rtp_payload_type *type;
-static int rtp_payload_type_find_format(void *obj, void *arg, int flags)
-{
- struct ast_rtp_payload_type *type = obj;
- struct ast_format *format = arg;
+ type = AST_VECTOR_GET(&codecs->payloads, i);
+ if (!type) {
+ continue;
+ }
- return (type->asterisk_format && (ast_format_cmp(&type->format, format) != AST_FORMAT_CMP_NOT_EQUAL)) ? CMP_MATCH | CMP_STOP : 0;
-}
+ if (type->asterisk_format) {
+ ast_format_cap_append(astformats, type->format, 0);
+ } else {
+ *nonastformats |= type->rtp_code;
+ }
+ }
-static int rtp_payload_type_find_nonast_format(void *obj, void *arg, int flags)
-{
- struct ast_rtp_payload_type *type = obj;
- int *rtp_code = arg;
+ if (codecs->framing) {
+ ast_format_cap_set_framing(astformats, codecs->framing);
+ }
- return ((!type->asterisk_format && (type->rtp_code == *rtp_code)) ? CMP_MATCH | CMP_STOP : 0);
+ ast_rwlock_unlock(&codecs->codecs_lock);
}
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
{
struct ast_rtp_payload_type *type;
- int i, res = -1;
+ int i;
+ int payload = -1;
- if (asterisk_format && format && (type = ao2_callback(codecs->payloads, OBJ_NOLOCK, rtp_payload_type_find_format, (void*)format))) {
- res = type->payload;
- ao2_ref(type, -1);
- return res;
- } else if (!asterisk_format && (type = ao2_callback(codecs->payloads, OBJ_NOLOCK, rtp_payload_type_find_nonast_format, (void*)&code))) {
- res = type->payload;
- ao2_ref(type, -1);
- return res;
- }
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
+ type = AST_VECTOR_GET(&codecs->payloads, i);
+ if (!type) {
+ continue;
+ }
- ast_rwlock_rdlock(&static_RTP_PT_lock);
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- if (static_RTP_PT[i].asterisk_format && asterisk_format && format &&
- (ast_format_cmp(format, &static_RTP_PT[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) {
- res = i;
- break;
- } else if (!static_RTP_PT[i].asterisk_format && !asterisk_format &&
- (static_RTP_PT[i].rtp_code == code)) {
- res = i;
+ if ((asterisk_format && format && ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL)
+ || (!asterisk_format && type->rtp_code == code)) {
+ payload = i;
break;
}
}
- ast_rwlock_unlock(&static_RTP_PT_lock);
+ ast_rwlock_unlock(&codecs->codecs_lock);
- return res;
+ if (payload < 0) {
+ ast_rwlock_rdlock(&static_RTP_PT_lock);
+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
+ if (static_RTP_PT[i].asterisk_format && asterisk_format && format &&
+ (ast_format_cmp(format, static_RTP_PT[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) {
+ payload = i;
+ break;
+ } else if (!static_RTP_PT[i].asterisk_format && !asterisk_format &&
+ (static_RTP_PT[i].rtp_code == code)) {
+ payload = i;
+ break;
+ }
+ }
+ ast_rwlock_unlock(&static_RTP_PT_lock);
+ }
+
+ return payload;
}
+
int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int code)
{
struct ast_rtp_payload_type *type;
int res = -1;
- /* Search the payload type in the codecs passed */
- if ((type = ao2_find(codecs->payloads, &code, OBJ_NOLOCK | OBJ_KEY)))
- {
- res = type->payload;
- ao2_ref(type, -1);
- return res;
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ if (code < AST_VECTOR_SIZE(&codecs->payloads)) {
+ type = AST_VECTOR_GET(&codecs->payloads, code);
+ if (type) {
+ res = type->payload;
+ }
}
+ ast_rwlock_unlock(&codecs->codecs_lock);
return res;
}
+
const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_format *format, int code, enum ast_rtp_options options)
{
int i;
@@ -901,8 +943,9 @@ const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_f
ast_rwlock_rdlock(&mime_types_lock);
for (i = 0; i < mime_types_len; i++) {
if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format &&
- (ast_format_cmp(format, &ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
- if ((format->id == AST_FORMAT_G726_AAL2) && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
+ (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
+ if ((ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) &&
+ (options & AST_RTP_OPT_G726_NONSTANDARD)) {
res = "G726-32";
break;
} else {
@@ -929,7 +972,7 @@ unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, struct ast_format
ast_rwlock_rdlock(&mime_types_lock);
for (i = 0; i < mime_types_len; ++i) {
if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format &&
- (ast_format_cmp(format, &ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
+ (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
res = ast_rtp_mime_types[i].sample_rate;
break;
} else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format &&
@@ -953,15 +996,15 @@ char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *
if (asterisk_format) {
- struct ast_format tmp_fmt;
- ast_format_cap_iter_start(ast_format_capability);
- while (!ast_format_cap_iter_next(ast_format_capability, &tmp_fmt)) {
- name = ast_rtp_lookup_mime_subtype2(asterisk_format, &tmp_fmt, 0, options);
+ int x;
+ struct ast_format *tmp_fmt;
+ for (x = 0; x < ast_format_cap_count(ast_format_capability); x++) {
+ tmp_fmt = ast_format_cap_get_format(ast_format_capability, x);
+ name = ast_rtp_lookup_mime_subtype2(asterisk_format, tmp_fmt, 0, options);
+ ao2_ref(tmp_fmt, -1);
ast_str_append(&buf, 0, "%s|", name);
found = 1;
}
- ast_format_cap_iter_end(ast_format_capability);
-
} else {
int x;
ast_str_append(&buf, 0, "0x%x (", (unsigned int) rtp_capability);
@@ -979,15 +1022,6 @@ char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *
return ast_str_buffer(buf);
}
-void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs)
-{
- codecs->pref = *prefs;
-
- if (instance && instance->engine->packetization_set) {
- instance->engine->packetization_set(instance, &instance->codecs.pref);
- }
-}
-
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
{
return instance->engine->dtmf_begin ? instance->engine->dtmf_begin(instance, digit) : -1;
@@ -1089,8 +1123,8 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c_dst, st
struct ast_rtp_glue *glue_dst, *glue_src;
enum ast_rtp_glue_result audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
- struct ast_format_cap *cap_dst = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *cap_src = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap_dst = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *cap_src = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
/* Lock both channels so we can look for the glue that binds them together */
ast_channel_lock_both(c_dst, c_src);
@@ -1131,7 +1165,7 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c_dst, st
}
/* Make sure we have matching codecs */
- if (!ast_format_cap_has_joint(cap_dst, cap_src)) {
+ if (!ast_format_cap_iscompatible(cap_dst, cap_src)) {
goto done;
}
@@ -1156,8 +1190,8 @@ done:
ast_channel_unlock(c_dst);
ast_channel_unlock(c_src);
- ast_format_cap_destroy(cap_dst);
- ast_format_cap_destroy(cap_src);
+ ao2_cleanup(cap_dst);
+ ao2_cleanup(cap_src);
unref_instance_cond(&instance_dst);
unref_instance_cond(&instance_src);
@@ -1175,13 +1209,13 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1
struct ast_rtp_glue *glue0, *glue1;
enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
- struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
/* If there is no second channel just immediately bail out, we are of no use in that scenario */
if (!c1 || !cap1 || !cap0) {
- ast_format_cap_destroy(cap0);
- ast_format_cap_destroy(cap1);
+ ao2_cleanup(cap0);
+ ao2_cleanup(cap1);
return -1;
}
@@ -1220,7 +1254,7 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1
}
/* Make sure we have matching codecs */
- if (!ast_format_cap_has_joint(cap0, cap1)) {
+ if (!ast_format_cap_iscompatible(cap0, cap1)) {
goto done;
}
@@ -1233,8 +1267,8 @@ done:
ast_channel_unlock(c0);
ast_channel_unlock(c1);
- ast_format_cap_destroy(cap0);
- ast_format_cap_destroy(cap1);
+ ao2_cleanup(cap0);
+ ao2_cleanup(cap1);
unref_instance_cond(&instance0);
unref_instance_cond(&instance1);
@@ -1419,7 +1453,7 @@ void ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, struc
{
if (instance->engine->available_formats) {
instance->engine->available_formats(instance, to_endpoint, to_asterisk, result);
- if (!ast_format_cap_is_empty(result)) {
+ if (ast_format_cap_count(result)) {
return;
}
}
@@ -1631,7 +1665,27 @@ void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg)
ast_free(dtls_cfg->capath);
}
-static void set_next_mime_type(const struct ast_format *format, int rtp_code, char *type, char *subtype, unsigned int sample_rate)
+/*! \internal
+ * \brief Small helper routine that cleans up entry i in
+ * \c static_RTP_PT.
+ */
+static void rtp_engine_static_RTP_PT_cleanup(int i)
+{
+ ao2_cleanup(static_RTP_PT[i].format);
+ memset(&static_RTP_PT[i], 0, sizeof(struct ast_rtp_payload_type));
+}
+
+/*! \internal
+ * \brief Small helper routine that cleans up entry i in
+ * \c ast_rtp_mime_types.
+ */
+static void rtp_engine_mime_type_cleanup(int i)
+{
+ ao2_cleanup(ast_rtp_mime_types[i].payload_type.format);
+ memset(&ast_rtp_mime_types[i], 0, sizeof(struct ast_rtp_mime_type));
+}
+
+static void set_next_mime_type(struct ast_format *format, int rtp_code, const char *type, const char *subtype, unsigned int sample_rate)
{
int x = mime_types_len;
if (ARRAY_LEN(ast_rtp_mime_types) == mime_types_len) {
@@ -1639,20 +1693,22 @@ static void set_next_mime_type(const struct ast_format *format, int rtp_code, ch
}
ast_rwlock_wrlock(&mime_types_lock);
+ /* Make sure any previous value in ast_rtp_mime_types is cleaned up */
+ memset(&ast_rtp_mime_types[x], 0, sizeof(struct ast_rtp_mime_type));
if (format) {
ast_rtp_mime_types[x].payload_type.asterisk_format = 1;
- ast_format_copy(&ast_rtp_mime_types[x].payload_type.format, format);
+ ast_rtp_mime_types[x].payload_type.format = ao2_bump(format);
} else {
ast_rtp_mime_types[x].payload_type.rtp_code = rtp_code;
}
- ast_rtp_mime_types[x].type = type;
- ast_rtp_mime_types[x].subtype = subtype;
+ ast_copy_string(ast_rtp_mime_types[x].type, type, sizeof(ast_rtp_mime_types[x].type));
+ ast_copy_string(ast_rtp_mime_types[x].subtype, subtype, sizeof(ast_rtp_mime_types[x].subtype));
ast_rtp_mime_types[x].sample_rate = sample_rate;
mime_types_len++;
ast_rwlock_unlock(&mime_types_lock);
}
-static void add_static_payload(int map, const struct ast_format *format, int rtp_code)
+static void add_static_payload(int map, struct ast_format *format, int rtp_code)
{
int x;
ast_rwlock_wrlock(&static_RTP_PT_lock);
@@ -1667,39 +1723,38 @@ static void add_static_payload(int map, const struct ast_format *format, int rtp
}
if (map < 0) {
- ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n" ,ast_getformatname(format));
+ ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n",
+ ast_format_get_name(format));
ast_rwlock_unlock(&static_RTP_PT_lock);
return;
}
if (format) {
static_RTP_PT[map].asterisk_format = 1;
- ast_format_copy(&static_RTP_PT[map].format, format);
+ static_RTP_PT[map].format = ao2_bump(format);
} else {
static_RTP_PT[map].rtp_code = rtp_code;
}
ast_rwlock_unlock(&static_RTP_PT_lock);
}
-int ast_rtp_engine_load_format(const struct ast_format *format)
+int ast_rtp_engine_load_format(struct ast_format *format)
{
- switch (format->id) {
- case AST_FORMAT_SILK:
- set_next_mime_type(format, 0, "audio", "SILK", ast_format_rate(format));
- add_static_payload(-1, format, 0);
- break;
- case AST_FORMAT_CELT:
- set_next_mime_type(format, 0, "audio", "CELT", ast_format_rate(format));
- add_static_payload(-1, format, 0);
- break;
- default:
- break;
- }
+ char *codec_name = ast_strdupa(ast_format_get_name(format));
+
+ codec_name = ast_str_to_upper(codec_name);
+
+ set_next_mime_type(format,
+ 0,
+ ast_codec_media_type2str(ast_format_get_type(format)),
+ codec_name,
+ ast_format_get_sample_rate(format));
+ add_static_payload(-1, format, 0);
return 0;
}
-int ast_rtp_engine_unload_format(const struct ast_format *format)
+int ast_rtp_engine_unload_format(struct ast_format *format)
{
int x;
int y = 0;
@@ -1707,17 +1762,17 @@ int ast_rtp_engine_unload_format(const struct ast_format *format)
ast_rwlock_wrlock(&static_RTP_PT_lock);
/* remove everything pertaining to this format id from the lists */
for (x = 0; x < AST_RTP_MAX_PT; x++) {
- if (ast_format_cmp(&static_RTP_PT[x].format, format) == AST_FORMAT_CMP_EQUAL) {
- memset(&static_RTP_PT[x], 0, sizeof(struct ast_rtp_payload_type));
+ if (ast_format_cmp(static_RTP_PT[x].format, format) == AST_FORMAT_CMP_EQUAL) {
+ rtp_engine_static_RTP_PT_cleanup(x);
}
}
ast_rwlock_unlock(&static_RTP_PT_lock);
-
ast_rwlock_wrlock(&mime_types_lock);
/* rebuild the list skipping the items matching this id */
for (x = 0; x < mime_types_len; x++) {
- if (ast_format_cmp(&ast_rtp_mime_types[x].payload_type.format, format) == AST_FORMAT_CMP_EQUAL) {
+ if (ast_format_cmp(ast_rtp_mime_types[x].payload_type.format, format) == AST_FORMAT_CMP_EQUAL) {
+ rtp_engine_mime_type_cleanup(x);
continue;
}
ast_rtp_mime_types[y] = ast_rtp_mime_types[x];
@@ -1976,16 +2031,32 @@ struct stasis_topic *ast_rtp_topic(void)
static void rtp_engine_shutdown(void)
{
+ int x;
+
ao2_cleanup(rtp_topic);
rtp_topic = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(ast_rtp_rtcp_received_type);
STASIS_MESSAGE_TYPE_CLEANUP(ast_rtp_rtcp_sent_type);
+
+ ast_rwlock_wrlock(&static_RTP_PT_lock);
+ for (x = 0; x < AST_RTP_MAX_PT; x++) {
+ if (static_RTP_PT[x].format) {
+ rtp_engine_static_RTP_PT_cleanup(x);
+ }
+ }
+ ast_rwlock_unlock(&static_RTP_PT_lock);
+
+ ast_rwlock_wrlock(&mime_types_lock);
+ for (x = 0; x < mime_types_len; x++) {
+ if (ast_rtp_mime_types[x].payload_type.format) {
+ rtp_engine_mime_type_cleanup(x);
+ }
+ }
+ ast_rwlock_unlock(&mime_types_lock);
}
int ast_rtp_engine_init()
{
- struct ast_format tmpfmt;
-
ast_rwlock_init(&mime_types_lock);
ast_rwlock_init(&static_RTP_PT_lock);
@@ -1998,90 +2069,90 @@ int ast_rtp_engine_init()
ast_register_atexit(rtp_engine_shutdown);
/* Define all the RTP mime types available */
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0), 0, "audio", "G723", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0), 0, "audio", "GSM", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0, "audio", "PCMU", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0, "audio", "G711U", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), 0, "audio", "PCMA", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), 0, "audio", "G711A", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), 0, "audio", "G726-32", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0, "audio", "DVI4", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), 0, "audio", "L16", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0, "audio", "L16", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0, "audio", "L16-256", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_LPC10, 0), 0, "audio", "LPC", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0, "audio", "G729", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0, "audio", "G729A", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0, "audio", "G.729", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX, 0), 0, "audio", "speex", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX16, 0), 0, "audio", "speex", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), 0, "audio", "speex", 32000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_ILBC, 0), 0, "audio", "iLBC", 8000);
+ set_next_mime_type(ast_format_g723, 0, "audio", "G723", 8000);
+ set_next_mime_type(ast_format_gsm, 0, "audio", "GSM", 8000);
+ set_next_mime_type(ast_format_ulaw, 0, "audio", "PCMU", 8000);
+ set_next_mime_type(ast_format_ulaw, 0, "audio", "G711U", 8000);
+ set_next_mime_type(ast_format_alaw, 0, "audio", "PCMA", 8000);
+ set_next_mime_type(ast_format_alaw, 0, "audio", "G711A", 8000);
+ set_next_mime_type(ast_format_g726, 0, "audio", "G726-32", 8000);
+ set_next_mime_type(ast_format_adpcm, 0, "audio", "DVI4", 8000);
+ set_next_mime_type(ast_format_slin, 0, "audio", "L16", 8000);
+ set_next_mime_type(ast_format_slin16, 0, "audio", "L16", 16000);
+ set_next_mime_type(ast_format_slin16, 0, "audio", "L16-256", 16000);
+ set_next_mime_type(ast_format_lpc10, 0, "audio", "LPC", 8000);
+ set_next_mime_type(ast_format_g729, 0, "audio", "G729", 8000);
+ set_next_mime_type(ast_format_g729, 0, "audio", "G729A", 8000);
+ set_next_mime_type(ast_format_g729, 0, "audio", "G.729", 8000);
+ set_next_mime_type(ast_format_speex, 0, "audio", "speex", 8000);
+ set_next_mime_type(ast_format_speex16, 0, "audio", "speex", 16000);
+ set_next_mime_type(ast_format_speex32, 0, "audio", "speex", 32000);
+ set_next_mime_type(ast_format_ilbc, 0, "audio", "iLBC", 8000);
/* this is the sample rate listed in the RTP profile for the G.722 codec, *NOT* the actual sample rate of the media stream */
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G722, 0), 0, "audio", "G722", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G726_AAL2, 0), 0, "audio", "AAL2-G726-32", 8000);
+ set_next_mime_type(ast_format_g722, 0, "audio", "G722", 8000);
+ set_next_mime_type(ast_format_g726_aal2, 0, "audio", "AAL2-G726-32", 8000);
set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 8000);
set_next_mime_type(NULL, AST_RTP_CISCO_DTMF, "audio", "cisco-telephone-event", 8000);
set_next_mime_type(NULL, AST_RTP_CN, "audio", "CN", 8000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_JPEG, 0), 0, "video", "JPEG", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_PNG, 0), 0, "video", "PNG", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H261, 0), 0, "video", "H261", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H263, 0), 0, "video", "H263", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0, "video", "H263-1998", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H264, 0), 0, "video", "H264", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_MP4_VIDEO, 0), 0, "video", "MP4V-ES", 90000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_T140RED, 0), 0, "text", "RED", 1000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_T140, 0), 0, "text", "T140", 1000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), 0, "audio", "G7221", 16000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), 0, "audio", "G7221", 32000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), 0, "audio", "G719", 48000);
+ set_next_mime_type(ast_format_jpeg, 0, "video", "JPEG", 90000);
+ set_next_mime_type(ast_format_png, 0, "video", "PNG", 90000);
+ set_next_mime_type(ast_format_h261, 0, "video", "H261", 90000);
+ set_next_mime_type(ast_format_h263, 0, "video", "H263", 90000);
+ set_next_mime_type(ast_format_h263p, 0, "video", "h263-1998", 90000);
+ set_next_mime_type(ast_format_h264, 0, "video", "H264", 90000);
+ set_next_mime_type(ast_format_mp4, 0, "video", "MP4V-ES", 90000);
+ set_next_mime_type(ast_format_t140_red, 0, "text", "RED", 1000);
+ set_next_mime_type(ast_format_t140, 0, "text", "T140", 1000);
+ set_next_mime_type(ast_format_siren7, 0, "audio", "G7221", 16000);
+ set_next_mime_type(ast_format_siren14, 0, "audio", "G7221", 32000);
+ set_next_mime_type(ast_format_g719, 0, "audio", "G719", 48000);
/* Opus and VP8 */
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0, "audio", "opus", 48000);
- set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0, "video", "VP8", 90000);
+ set_next_mime_type(ast_format_opus, 0, "audio", "opus", 48000);
+ set_next_mime_type(ast_format_vp8, 0, "video", "VP8", 90000);
/* Define the static rtp payload mappings */
- add_static_payload(0, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0);
+ add_static_payload(0, ast_format_ulaw, 0);
#ifdef USE_DEPRECATED_G726
- add_static_payload(2, ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), 0);/* Technically this is G.721, but if Cisco can do it, so can we... */
+ add_static_payload(2, ast_format_g726, 0);/* Technically this is G.721, but if Cisco can do it, so can we... */
#endif
- add_static_payload(3, ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0), 0);
- add_static_payload(4, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0), 0);
- add_static_payload(5, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0);/* 8 kHz */
- add_static_payload(6, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0); /* 16 kHz */
- add_static_payload(7, ast_format_set(&tmpfmt, AST_FORMAT_LPC10, 0), 0);
- add_static_payload(8, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0), 0);
- add_static_payload(9, ast_format_set(&tmpfmt, AST_FORMAT_G722, 0), 0);
- add_static_payload(10, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), 0); /* 2 channels */
- add_static_payload(11, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0), 0); /* 1 channel */
+ add_static_payload(3, ast_format_gsm, 0);
+ add_static_payload(4, ast_format_g723, 0);
+ add_static_payload(5, ast_format_adpcm, 0);/* 8 kHz */
+ add_static_payload(6, ast_format_adpcm, 0); /* 16 kHz */
+ add_static_payload(7, ast_format_lpc10, 0);
+ add_static_payload(8, ast_format_alaw, 0);
+ add_static_payload(9, ast_format_g722, 0);
+ add_static_payload(10, ast_format_slin, 0); /* 2 channels */
+ add_static_payload(11, ast_format_slin, 0); /* 1 channel */
add_static_payload(13, NULL, AST_RTP_CN);
- add_static_payload(16, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0); /* 11.025 kHz */
- add_static_payload(17, ast_format_set(&tmpfmt, AST_FORMAT_ADPCM, 0), 0); /* 22.050 kHz */
- add_static_payload(18, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0), 0);
+ add_static_payload(16, ast_format_adpcm, 0); /* 11.025 kHz */
+ add_static_payload(17, ast_format_adpcm, 0); /* 22.050 kHz */
+ add_static_payload(18, ast_format_g729, 0);
add_static_payload(19, NULL, AST_RTP_CN); /* Also used for CN */
- add_static_payload(26, ast_format_set(&tmpfmt, AST_FORMAT_JPEG, 0), 0);
- add_static_payload(31, ast_format_set(&tmpfmt, AST_FORMAT_H261, 0), 0);
- add_static_payload(34, ast_format_set(&tmpfmt, AST_FORMAT_H263, 0), 0);
- add_static_payload(97, ast_format_set(&tmpfmt, AST_FORMAT_ILBC, 0), 0);
- add_static_payload(98, ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0);
- add_static_payload(99, ast_format_set(&tmpfmt, AST_FORMAT_H264, 0), 0);
+ add_static_payload(26, ast_format_jpeg, 0);
+ add_static_payload(31, ast_format_h261, 0);
+ add_static_payload(34, ast_format_h263, 0);
+ add_static_payload(97, ast_format_ilbc, 0);
+ add_static_payload(98, ast_format_h263p, 0);
+ add_static_payload(99, ast_format_h264, 0);
add_static_payload(101, NULL, AST_RTP_DTMF);
- add_static_payload(102, ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), 0);
- add_static_payload(103, ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0);
- add_static_payload(104, ast_format_set(&tmpfmt, AST_FORMAT_MP4_VIDEO, 0), 0);
- add_static_payload(105, ast_format_set(&tmpfmt, AST_FORMAT_T140RED, 0), 0); /* Real time text chat (with redundancy encoding) */
- add_static_payload(106, ast_format_set(&tmpfmt, AST_FORMAT_T140, 0), 0); /* Real time text chat */
- add_static_payload(110, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX, 0), 0);
- add_static_payload(111, ast_format_set(&tmpfmt, AST_FORMAT_G726, 0), 0);
- add_static_payload(112, ast_format_set(&tmpfmt, AST_FORMAT_G726_AAL2, 0), 0);
- add_static_payload(115, ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), 0);
- add_static_payload(116, ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), 0);
- add_static_payload(117, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX16, 0), 0);
- add_static_payload(118, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0); /* 16 Khz signed linear */
- add_static_payload(119, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), 0);
+ add_static_payload(102, ast_format_siren7, 0);
+ add_static_payload(103, ast_format_h263p, 0);
+ add_static_payload(104, ast_format_mp4, 0);
+ add_static_payload(105, ast_format_t140_red, 0); /* Real time text chat (with redundancy encoding) */
+ add_static_payload(106, ast_format_t140, 0); /* Real time text chat */
+ add_static_payload(110, ast_format_speex, 0);
+ add_static_payload(111, ast_format_g726, 0);
+ add_static_payload(112, ast_format_g726_aal2, 0);
+ add_static_payload(115, ast_format_siren14, 0);
+ add_static_payload(116, ast_format_g719, 0);
+ add_static_payload(117, ast_format_speex16, 0);
+ add_static_payload(118, ast_format_slin16, 0); /* 16 Khz signed linear */
+ add_static_payload(119, ast_format_speex32, 0);
add_static_payload(121, NULL, AST_RTP_CISCO_DTMF); /* Must be type 121 */
/* Opus and VP8 */
- add_static_payload(100, ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0);
- add_static_payload(107, ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0);
+ add_static_payload(100, ast_format_vp8, 0);
+ add_static_payload(107, ast_format_opus, 0);
return 0;
}
diff --git a/main/slinfactory.c b/main/slinfactory.c
index 44efc420f..8c117d652 100644
--- a/main/slinfactory.c
+++ b/main/slinfactory.c
@@ -33,24 +33,26 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/slinfactory.h"
#include "asterisk/translate.h"
+#include "asterisk/astobj2.h"
void ast_slinfactory_init(struct ast_slinfactory *sf)
{
memset(sf, 0, sizeof(*sf));
sf->offset = sf->hold;
- ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR, 0);
+ sf->output_format = ao2_bump(ast_format_slin);
}
-int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, const struct ast_format *slin_out)
+int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, struct ast_format *slin_out)
{
memset(sf, 0, sizeof(*sf));
sf->offset = sf->hold;
- if (!ast_format_is_slinear(slin_out)) {
+ if (!ast_format_cache_is_slinear(slin_out)) {
return -1;
}
- ast_format_copy(&sf->output_format, slin_out);
+ sf->output_format = ao2_bump(slin_out);
return 0;
}
@@ -64,8 +66,14 @@ void ast_slinfactory_destroy(struct ast_slinfactory *sf)
sf->trans = NULL;
}
- while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
+ while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
ast_frfree(f);
+ }
+
+ ao2_cleanup(sf->output_format);
+ sf->output_format = NULL;
+ ao2_cleanup(sf->format);
+ sf->format = NULL;
}
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
@@ -83,22 +91,22 @@ int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
return 0;
}
- if (ast_format_cmp(&f->subclass.format, &sf->output_format) == AST_FORMAT_CMP_NOT_EQUAL) {
- if (sf->trans && (ast_format_cmp(&f->subclass.format, &sf->format) == AST_FORMAT_CMP_NOT_EQUAL)) {
+ if (ast_format_cmp(f->subclass.format, sf->output_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ if (sf->trans && (ast_format_cmp(f->subclass.format, sf->format) == AST_FORMAT_CMP_NOT_EQUAL)) {
ast_translator_free_path(sf->trans);
sf->trans = NULL;
}
if (!sf->trans) {
- if (!(sf->trans = ast_translator_build_path(&sf->output_format, &f->subclass.format))) {
+ if (!(sf->trans = ast_translator_build_path(sf->output_format, f->subclass.format))) {
ast_log(LOG_WARNING, "Cannot build a path from %s (%u)to %s (%u)\n",
- ast_getformatname(&f->subclass.format),
- f->subclass.format.id,
- ast_getformatname(&sf->output_format),
- sf->output_format.id);
+ ast_format_get_name(f->subclass.format),
+ ast_format_get_codec_id(f->subclass.format),
+ ast_format_get_name(sf->output_format),
+ ast_format_get_codec_id(sf->output_format));
return 0;
}
- ast_format_copy(&sf->format, &f->subclass.format);
+ ao2_replace(sf->format, f->subclass.format);
}
if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
diff --git a/main/smoother.c b/main/smoother.c
new file mode 100644
index 000000000..720ad8549
--- /dev/null
+++ b/main/smoother.c
@@ -0,0 +1,227 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Frame smoother manipulation routines
+ *
+ * \author Mark Spencer <markster@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/_private.h"
+#include "asterisk/frame.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/time.h"
+#include "asterisk/utils.h"
+#include "asterisk/format.h"
+#include "asterisk/codec.h"
+#include "asterisk/smoother.h"
+
+#define SMOOTHER_SIZE 8000
+
+struct ast_smoother {
+ int size;
+ struct ast_format *format;
+ int flags;
+ float samplesperbyte;
+ unsigned int opt_needs_swap:1;
+ struct ast_frame f;
+ struct timeval delivery;
+ char data[SMOOTHER_SIZE];
+ char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
+ struct ast_frame *opt;
+ int len;
+};
+
+static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
+{
+ if (s->flags & AST_SMOOTHER_FLAG_G729) {
+ if (s->len % 10) {
+ ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
+ return 0;
+ }
+ }
+ if (swap) {
+ ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
+ } else {
+ memcpy(s->data + s->len, f->data.ptr, f->datalen);
+ }
+ /* If either side is empty, reset the delivery time */
+ if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) { /* XXX really ? */
+ s->delivery = f->delivery;
+ }
+ s->len += f->datalen;
+
+ return 0;
+}
+
+void ast_smoother_reset(struct ast_smoother *s, int bytes)
+{
+ ao2_cleanup(s->format);
+ memset(s, 0, sizeof(*s));
+ s->size = bytes;
+}
+
+void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
+{
+ /* if there is no change, then nothing to do */
+ if (s->size == bytes) {
+ return;
+ }
+ /* set the new desired output size */
+ s->size = bytes;
+ /* if there is no 'optimized' frame in the smoother,
+ * then there is nothing left to do
+ */
+ if (!s->opt) {
+ return;
+ }
+ /* there is an 'optimized' frame here at the old size,
+ * but it must now be put into the buffer so the data
+ * can be extracted at the new size
+ */
+ smoother_frame_feed(s, s->opt, s->opt_needs_swap);
+ s->opt = NULL;
+}
+
+struct ast_smoother *ast_smoother_new(int size)
+{
+ struct ast_smoother *s;
+ if (size < 1)
+ return NULL;
+ if ((s = ast_calloc(1, sizeof(*s))))
+ ast_smoother_reset(s, size);
+ return s;
+}
+
+int ast_smoother_get_flags(struct ast_smoother *s)
+{
+ return s->flags;
+}
+
+void ast_smoother_set_flags(struct ast_smoother *s, int flags)
+{
+ s->flags = flags;
+}
+
+int ast_smoother_test_flag(struct ast_smoother *s, int flag)
+{
+ return (s->flags & flag);
+}
+
+int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
+{
+ if (f->frametype != AST_FRAME_VOICE) {
+ ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
+ return -1;
+ }
+ if (!s->format) {
+ s->format = ao2_bump(f->subclass.format);
+ s->samplesperbyte = (float)f->samples / (float)f->datalen;
+ } else if (ast_format_cmp(s->format, f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_log(LOG_WARNING, "Smoother was working on %s format frames, now trying to feed %s?\n",
+ ast_format_get_name(s->format), ast_format_get_name(f->subclass.format));
+ return -1;
+ }
+ if (s->len + f->datalen > SMOOTHER_SIZE) {
+ ast_log(LOG_WARNING, "Out of smoother space\n");
+ return -1;
+ }
+ if (((f->datalen == s->size) ||
+ ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
+ !s->opt &&
+ !s->len &&
+ (f->offset >= AST_MIN_OFFSET)) {
+ /* Optimize by sending the frame we just got
+ on the next read, thus eliminating the douple
+ copy */
+ if (swap)
+ ast_swapcopy_samples(f->data.ptr, f->data.ptr, f->samples);
+ s->opt = f;
+ s->opt_needs_swap = swap ? 1 : 0;
+ return 0;
+ }
+
+ return smoother_frame_feed(s, f, swap);
+}
+
+struct ast_frame *ast_smoother_read(struct ast_smoother *s)
+{
+ struct ast_frame *opt;
+ int len;
+
+ /* IF we have an optimization frame, send it */
+ if (s->opt) {
+ if (s->opt->offset < AST_FRIENDLY_OFFSET)
+ ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
+ s->opt->offset);
+ opt = s->opt;
+ s->opt = NULL;
+ return opt;
+ }
+
+ /* Make sure we have enough data */
+ if (s->len < s->size) {
+ /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
+ if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
+ return NULL;
+ }
+ len = s->size;
+ if (len > s->len)
+ len = s->len;
+ /* Make frame */
+ s->f.frametype = AST_FRAME_VOICE;
+ s->f.subclass.format = s->format;
+ s->f.data.ptr = s->framedata + AST_FRIENDLY_OFFSET;
+ s->f.offset = AST_FRIENDLY_OFFSET;
+ s->f.datalen = len;
+ /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
+ s->f.samples = len * s->samplesperbyte; /* XXX rounding */
+ s->f.delivery = s->delivery;
+ /* Fill Data */
+ memcpy(s->f.data.ptr, s->data, len);
+ s->len -= len;
+ /* Move remaining data to the front if applicable */
+ if (s->len) {
+ /* In principle this should all be fine because if we are sending
+ G.729 VAD, the next timestamp will take over anyawy */
+ memmove(s->data, s->data + len, s->len);
+ if (!ast_tvzero(s->delivery)) {
+ /* If we have delivery time, increment it, otherwise, leave it at 0 */
+ s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples,
+ ast_format_get_sample_rate(s->format)));
+ }
+ }
+ /* Return frame */
+ return &s->f;
+}
+
+void ast_smoother_free(struct ast_smoother *s)
+{
+ ao2_cleanup(s->format);
+ ast_free(s);
+}
+
diff --git a/main/sorcery.c b/main/sorcery.c
index 9488dee4b..85a699bcb 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -43,7 +43,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/taskprocessor.h"
#include "asterisk/threadpool.h"
#include "asterisk/json.h"
-#include "asterisk/format_pref.h"
/* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
#undef open
@@ -233,10 +232,9 @@ static int chararray_handler_fn(const void *obj, const intptr_t *args, char **bu
static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
{
- char tmp_buf[256];
- struct ast_codec_pref *pref = (struct ast_codec_pref *)(obj + args[0]);
- ast_codec_pref_string(pref, tmp_buf, sizeof(tmp_buf));
- return !(*buf = ast_strdup(tmp_buf));
+ struct ast_str *codec_buf = ast_str_alloca(64);
+ struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
+ return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
}
static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
diff --git a/main/sounds_index.c b/main/sounds_index.c
index 41430fa45..bc5263908 100644
--- a/main/sounds_index.c
+++ b/main/sounds_index.c
@@ -158,10 +158,10 @@ static int show_sound_info_cb(void *obj, void *arg, int flags)
{
char *language = obj;
struct ast_cli_args *a = arg;
- struct ast_format format;
+ struct ast_format *format;
int formats_shown = 0;
RAII_VAR(struct ast_media_index *, local_index, ast_sounds_get_index(), ao2_cleanup);
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
+ struct ast_format_cap *cap;
const char *description = ast_media_get_description(local_index, a->argv[3], language);
ast_cli(a->fd, " Language %s:\n", language);
@@ -171,12 +171,14 @@ static int show_sound_info_cb(void *obj, void *arg, int flags)
cap = ast_media_get_format_cap(local_index, a->argv[3], language);
if (cap) {
- ast_format_cap_iter_start(cap);
- while (!ast_format_cap_iter_next(cap, &format)) {
- ast_cli(a->fd, " Format: %s\n", ast_getformatname(&format));
+ int x;
+ for (x = 0; x < ast_format_cap_count(cap); x++) {
+ format = ast_format_cap_get_format(cap, x);
+ ast_cli(a->fd, " Format: %s\n", ast_format_get_name(format));
+ ao2_ref(format, -1);
formats_shown = 1;
- }
- ast_format_cap_iter_end(cap);
+ }
+ ao2_ref(cap, -1);
}
if (!formats_shown) {
diff --git a/main/translate.c b/main/translate.c
index c24700b45..0696f5d83 100644
--- a/main/translate.c
+++ b/main/translate.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
+#include "asterisk/format.h"
/*! \todo
* TODO: sample frames for each supported input format.
@@ -76,11 +77,11 @@ struct translator_path {
static struct translator_path **__matrix;
/*!
- * \brief table for converting index to format id values.
+ * \brief table for converting index to format values.
*
* \note this table is protected by the table_lock.
*/
-static int *__indextable;
+static unsigned int *__indextable;
/*! protects the __indextable for resizing */
static ast_rwlock_t tablelock;
@@ -99,9 +100,9 @@ static void matrix_rebuild(int samples);
/*!
* \internal
- * \brief converts format id to index value.
+ * \brief converts codec id to index value.
*/
-static int format2index(enum ast_format_id id)
+static int codec_to_index(unsigned int id)
{
int x;
@@ -119,16 +120,34 @@ static int format2index(enum ast_format_id id)
/*!
* \internal
- * \brief add a new format to the matrix and index table structures.
+ * \brief converts codec to index value.
+ */
+static int codec2index(struct ast_codec *codec)
+{
+ return codec_to_index(codec->id);
+}
+
+/*!
+ * \internal
+ * \brief converts format to codec index value.
+ */
+static int format2index(struct ast_format *format)
+{
+ return codec_to_index(ast_format_get_codec_id(format));
+}
+
+/*!
+ * \internal
+ * \brief add a new codec to the matrix and index table structures.
*
- * \note it is perfectly safe to call this on formats already indexed.
+ * \note it is perfectly safe to call this on codecs already indexed.
*
* \retval 0, success
* \retval -1, matrix and index table need to be resized
*/
-static int add_format2index(enum ast_format_id id)
+static int add_codec2index(struct ast_codec *codec)
{
- if (format2index(id) >= 0) {
+ if (codec2index(codec) != -1) {
/* format is already already indexed */
return 0;
}
@@ -138,7 +157,7 @@ static int add_format2index(enum ast_format_id id)
ast_rwlock_unlock(&tablelock);
return -1; /* hit max length */
}
- __indextable[cur_max_index] = id;
+ __indextable[cur_max_index] = codec->id;
cur_max_index++;
ast_rwlock_unlock(&tablelock);
@@ -147,20 +166,20 @@ static int add_format2index(enum ast_format_id id)
/*!
* \internal
- * \brief converts index value back to format id
+ * \brief converts index value back to codec
*/
-static enum ast_format_id index2format(int index)
+static struct ast_codec *index2codec(int index)
{
- enum ast_format_id format_id;
+ struct ast_codec *codec;
if (index >= cur_max_index) {
return 0;
}
ast_rwlock_rdlock(&tablelock);
- format_id = __indextable[index];
+ codec = ast_codec_get_by_id(__indextable[index]);
ast_rwlock_unlock(&tablelock);
- return format_id;
+ return codec;
}
/*!
@@ -176,7 +195,7 @@ static enum ast_format_id index2format(int index)
static int matrix_resize(int init)
{
struct translator_path **tmp_matrix = NULL;
- int *tmp_table = NULL;
+ unsigned int *tmp_table = NULL;
int old_index;
int x;
@@ -202,7 +221,7 @@ static int matrix_resize(int init)
}
/* make new index table */
- if (!(tmp_table = ast_calloc(1, sizeof(int) * index_size))) {
+ if (!(tmp_table = ast_calloc(1, sizeof(unsigned int) * index_size))) {
goto resize_cleanup;
}
@@ -213,7 +232,7 @@ static int matrix_resize(int init)
}
ast_free(__matrix);
- memcpy(tmp_table, __indextable, sizeof(int) * old_index);
+ memcpy(tmp_table, __indextable, sizeof(unsigned int) * old_index);
ast_free(__indextable);
}
@@ -270,11 +289,23 @@ static struct translator_path *matrix_get(unsigned int x, unsigned int y)
* wrappers around the translator routines.
*/
+static void destroy(struct ast_trans_pvt *pvt)
+{
+ struct ast_translator *t = pvt->t;
+
+ if (t->destroy) {
+ t->destroy(pvt);
+ }
+ ao2_cleanup(pvt->f.subclass.format);
+ ast_free(pvt);
+ ast_module_unref(t->module);
+}
+
/*!
* \brief Allocate the descriptor, required outbuf space,
* and possibly desc.
*/
-static void *newpvt(struct ast_translator *t, const struct ast_format *explicit_dst)
+static struct ast_trans_pvt *newpvt(struct ast_translator *t)
{
struct ast_trans_pvt *pvt;
int len;
@@ -300,28 +331,49 @@ static void *newpvt(struct ast_translator *t, const struct ast_format *explicit_
if (t->buf_size) {/* finally buffer and header */
pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
}
- /* if a explicit destination format is provided, set that on the pvt so the
- * translator will process it. */
- if (explicit_dst) {
- ast_format_copy(&pvt->explicit_dst, explicit_dst);
- }
+
+ ast_module_ref(t->module);
+
/* call local init routine, if present */
if (t->newpvt && t->newpvt(pvt)) {
ast_free(pvt);
+ ast_module_unref(t->module);
return NULL;
}
- ast_module_ref(t->module);
- return pvt;
-}
-static void destroy(struct ast_trans_pvt *pvt)
-{
- struct ast_translator *t = pvt->t;
+ /* Setup normal static translation frame. */
+ pvt->f.frametype = AST_FRAME_VOICE;
+ pvt->f.mallocd = 0;
+ pvt->f.offset = AST_FRIENDLY_OFFSET;
+ pvt->f.src = pvt->t->name;
+ pvt->f.data.ptr = pvt->outbuf.c;
- if (t->destroy)
- t->destroy(pvt);
- ast_free(pvt);
- ast_module_unref(t->module);
+ /* if the translator has not provided a format find one in the cache or create one */
+ if (!pvt->f.subclass.format) {
+ if (!ast_strlen_zero(pvt->t->format)) {
+ pvt->f.subclass.format = ast_format_cache_get(pvt->t->format);
+ }
+
+ if (!pvt->f.subclass.format) {
+ struct ast_codec *codec = ast_codec_get(t->dst_codec.name,
+ t->dst_codec.type, t->dst_codec.sample_rate);
+ if (!codec) {
+ ast_log(LOG_ERROR, "Unable to get destination codec\n");
+ destroy(pvt);
+ return NULL;
+ }
+ pvt->f.subclass.format = ast_format_create(codec);
+ ao2_ref(codec, -1);
+ }
+
+ if (!pvt->f.subclass.format) {
+ ast_log(LOG_ERROR, "Unable to create format\n");
+ destroy(pvt);
+ return NULL;
+ }
+ }
+
+ return pvt;
}
/*! \brief framein wrapper, deals with bound checks. */
@@ -374,8 +426,9 @@ struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
if (samples) {
f->samples = samples;
} else {
- if (pvt->samples == 0)
+ if (pvt->samples == 0) {
return NULL;
+ }
f->samples = pvt->samples;
pvt->samples = 0;
}
@@ -386,13 +439,6 @@ struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
pvt->datalen = 0;
}
- f->frametype = AST_FRAME_VOICE;
- ast_format_copy(&f->subclass.format, &pvt->t->dst_format);
- f->mallocd = 0;
- f->offset = AST_FRIENDLY_OFFSET;
- f->src = pvt->t->name;
- f->data.ptr = pvt->outbuf.c;
-
return ast_frisolate(f);
}
@@ -417,11 +463,9 @@ struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct a
{
struct ast_trans_pvt *head = NULL, *tail = NULL;
int src_index, dst_index;
- struct ast_format tmp_fmt1;
- struct ast_format tmp_fmt2;
- src_index = format2index(src->id);
- dst_index = format2index(dst->id);
+ src_index = format2index(src);
+ dst_index = format2index(dst);
if (src_index < 0 || dst_index < 0) {
ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index < 0 ? "starting" : "ending");
@@ -432,26 +476,16 @@ struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct a
while (src_index != dst_index) {
struct ast_trans_pvt *cur;
- struct ast_format *explicit_dst = NULL;
struct ast_translator *t = matrix_get(src_index, dst_index)->step;
if (!t) {
- int src_id = index2format(src_index);
- int dst_id = index2format(dst_index);
ast_log(LOG_WARNING, "No translator path from %s to %s\n",
- ast_getformatname(ast_format_set(&tmp_fmt1, src_id, 0)),
- ast_getformatname(ast_format_set(&tmp_fmt2, dst_id, 0)));
+ ast_format_get_name(src), ast_format_get_name(dst));
AST_RWLIST_UNLOCK(&translators);
return NULL;
}
- if (dst_index == t->dst_fmt_index) {
- explicit_dst = dst;
- }
- if (!(cur = newpvt(t, explicit_dst))) {
- int src_id = index2format(src_index);
- int dst_id = index2format(dst_index);
+ if (!(cur = newpvt(t))) {
ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
- ast_getformatname(ast_format_set(&tmp_fmt1, src_id, 0)),
- ast_getformatname(ast_format_set(&tmp_fmt2, dst_id, 0)));
+ ast_format_get_name(src), ast_format_get_name(dst));
if (head) {
ast_translator_free_path(head);
}
@@ -508,7 +542,8 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f,
path->nextout = f->delivery;
}
/* Predict next incoming sample */
- path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(&f->subclass.format)));
+ path->nextin = ast_tvadd(path->nextin, ast_samp2tv(
+ f->samples, ast_format_get_sample_rate(f->subclass.format)));
}
delivery = f->delivery;
for (out = f; out && p ; p = p->next) {
@@ -531,7 +566,8 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f,
/* Predict next outgoing timestamp from samples in this
frame. */
- path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(&out->subclass.format)));
+ path->nextout = ast_tvadd(path->nextout, ast_samp2tv(
+ out->samples, ast_format_get_sample_rate(out->subclass.format)));
if (f->samples != out->samples && ast_test_flag(out, AST_FRFLAG_HAS_TIMING_INFO)) {
ast_debug(4, "Sample size different %d vs %d\n", f->samples, out->samples);
ast_clear_flag(out, AST_FRFLAG_HAS_TIMING_INFO);
@@ -572,7 +608,7 @@ static void generate_computational_cost(struct ast_translator *t, int seconds)
struct rusage start;
struct rusage end;
int cost;
- int out_rate = ast_format_rate(&t->dst_format);
+ int out_rate = t->dst_codec.sample_rate;
if (!seconds) {
seconds = 1;
@@ -585,7 +621,7 @@ static void generate_computational_cost(struct ast_translator *t, int seconds)
return;
}
- pvt = newpvt(t, NULL);
+ pvt = newpvt(t);
if (!pvt) {
ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
t->comp_cost = 999999;
@@ -643,21 +679,23 @@ static void generate_computational_cost(struct ast_translator *t, int seconds)
* \retval Table Cost value greater than 0.
* \retval 0 on error.
*/
-static int generate_table_cost(struct ast_format *src, struct ast_format *dst)
+static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
{
- int src_rate = ast_format_rate(src);
+ int src_rate = src->sample_rate;
int src_ll = 0;
- int dst_rate = ast_format_rate(dst);
+ int dst_rate = dst->sample_rate;
int dst_ll = 0;
- if ((AST_FORMAT_GET_TYPE(src->id) != AST_FORMAT_TYPE_AUDIO) || (AST_FORMAT_GET_TYPE(dst->id) != AST_FORMAT_TYPE_AUDIO)) {
+ if ((src->type != AST_MEDIA_TYPE_AUDIO) ||
+ (dst->type != AST_MEDIA_TYPE_AUDIO)) {
/* This method of generating table cost is limited to audio.
* Translators for media other than audio must manually set their
* table cost. */
return 0;
}
- src_ll = ast_format_is_slinear(src);
- dst_ll = ast_format_is_slinear(dst);
+
+ src_ll = !strcmp(src->name, "slin");
+ dst_ll = !strcmp(dst->name, "slin");
if (src_ll) {
if (dst_ll && (src_rate == dst_rate)) {
return AST_TRANS_COST_LL_LL_ORIGSAMP;
@@ -763,18 +801,25 @@ static void matrix_rebuild(int samples)
/* if no step already exists between x and z OR the new cost of using the intermediate
* step is cheaper, use this step. */
if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) {
- struct ast_format tmpx;
- struct ast_format tmpy;
- struct ast_format tmpz;
matrix_get(x, z)->step = matrix_get(x, y)->step;
matrix_get(x, z)->table_cost = newtablecost;
matrix_get(x, z)->multistep = 1;
changed++;
- ast_debug(10, "Discovered %u cost path from %s to %s, via %s\n",
- matrix_get(x, z)->table_cost,
- ast_getformatname(ast_format_set(&tmpx, index2format(x), 0)),
- ast_getformatname(ast_format_set(&tmpy, index2format(z), 0)),
- ast_getformatname(ast_format_set(&tmpz, index2format(y), 0)));
+
+ if (DEBUG_ATLEAST(10)) {
+ struct ast_codec *x_codec = index2codec(x);
+ struct ast_codec *y_codec = index2codec(y);
+ struct ast_codec *z_codec = index2codec(z);
+
+ ast_log(LOG_DEBUG,
+ "Discovered %u cost path from %s to %s, via %s\n",
+ matrix_get(x, z)->table_cost, x_codec->name,
+ y_codec->name, z_codec->name);
+
+ ao2_ref(x_codec, -1);
+ ao2_ref(y_codec, -1);
+ ao2_ref(z_codec, -1);
+ }
}
}
}
@@ -785,20 +830,26 @@ static void matrix_rebuild(int samples)
}
}
-const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
+static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
{
- struct ast_trans_pvt *pn = p;
- char tmp[256];
+ if (codec) {
+ ast_str_append(buf, 0, "(%s@%u)", codec->name, codec->sample_rate);
+ } else {
+ ast_str_append(buf, 0, "(nothing)");
+ }
+}
+const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
+{
if (!p || !p->t) {
return "";
}
- ast_str_set(str, 0, "%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), p->t->src_format.id));
-
- while ( (p = pn) ) {
- pn = p->next;
- ast_str_append(str, 0, "->%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), p->t->dst_format.id));
+ codec_append_name(&p->t->src_codec, str);
+ while (p) {
+ ast_str_append(str, 0, "->");
+ codec_append_name(&p->t->dst_codec, str);
+ p = p->next;
}
return ast_str_buffer(*str);
@@ -806,24 +857,24 @@ const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **
static char *complete_trans_path_choice(const char *line, const char *word, int pos, int state)
{
- int which = 0;
+ int i = 1, which = 0;
int wordlen = strlen(word);
- int i;
- char *ret = NULL;
- size_t len = 0;
- const struct ast_format_list *format_list = ast_format_list_get(&len);
+ struct ast_codec *codec;
- for (i = 0; i < len; i++) {
- if (AST_FORMAT_GET_TYPE(format_list[i].format.id) != AST_FORMAT_TYPE_AUDIO) {
+ while ((codec = ast_codec_get_by_id(i))) {
+ ++i;
+ if (codec->type != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(codec, -1);
continue;
}
- if (!strncasecmp(word, format_list[i].name, wordlen) && ++which > state) {
- ret = ast_strdup(format_list[i].name);
- break;
+ if (!strncasecmp(word, codec->name, wordlen) && ++which > state) {
+ char *res = ast_strdup(codec->name);
+ ao2_ref(codec, -1);
+ return res;
}
+ ao2_ref(codec, -1);
}
- ast_format_list_destroy(format_list);
- return ret;
+ return NULL;
}
static void handle_cli_recalc(struct ast_cli_args *a)
@@ -847,63 +898,61 @@ static void handle_cli_recalc(struct ast_cli_args *a)
static char *handle_show_translation_table(struct ast_cli_args *a)
{
- int x;
- int y;
- int i;
- int k;
- int curlen = 0;
- int longest = 0;
- int f_len;
- size_t f_size = 0;
- const struct ast_format_list *f_list = ast_format_list_get(&f_size);
+ int x, y, i, k;
+ int longest = 0, num_codecs = 0, curlen = 0;
struct ast_str *out = ast_str_create(1024);
+ struct ast_codec *codec;
- f_len = f_size;
- AST_RWLIST_RDLOCK(&translators);
- ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
- ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n");
-
- /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
- for (i = 0; i < f_len; i++) {
- /* translation only applies to audio right now. */
- if (AST_FORMAT_GET_TYPE(f_list[i].format.id) != AST_FORMAT_TYPE_AUDIO)
+ /* Get the length of the longest (usable?) codec name,
+ so we know how wide the left side should be */
+ for (i = 1; (codec = ast_codec_get_by_id(i)); ao2_ref(codec, -1), ++i) {
+ ++num_codecs;
+ if (codec->type != AST_MEDIA_TYPE_AUDIO) {
continue;
- curlen = strlen(ast_getformatname(&f_list[i].format));
+ }
+ curlen = strlen(codec->name);
if (curlen > longest) {
longest = curlen;
}
}
- for (i = -1; i < f_len; i++) {
+ AST_RWLIST_RDLOCK(&translators);
+ ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
+ ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n");
+
+ for (i = 0; i < num_codecs; i++) {
+ struct ast_codec *row = i ? ast_codec_get_by_id(i) : NULL;
+
x = -1;
- if ((i >= 0) && ((x = format2index(f_list[i].format.id)) < 0)) {
- continue;
- }
- /* translation only applies to audio right now. */
- if (i >= 0 && (AST_FORMAT_GET_TYPE(f_list[i].format.id) != AST_FORMAT_TYPE_AUDIO)) {
+ if ((i > 0) && (row->type != AST_MEDIA_TYPE_AUDIO)) {
+ ao2_ref(row, -1);
continue;
}
- /*Go ahead and move to next iteration if dealing with an unknown codec*/
- if (i >= 0 && !strcmp(ast_getformatname(&f_list[i].format), "unknown")) {
+
+ if ((i > 0) && (x = codec2index(row)) == -1) {
+ ao2_ref(row, -1);
continue;
}
+
ast_str_set(&out, 0, " ");
- for (k = -1; k < f_len; k++) {
+ for (k = 0; k < num_codecs; k++) {
+ struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL;
+
y = -1;
- if ((k >= 0) && ((y = format2index(f_list[k].format.id)) < 0)) {
+ if ((k > 0) && (col->type != AST_MEDIA_TYPE_AUDIO)) {
+ ao2_ref(col, -1);
continue;
}
- /* translation only applies to audio right now. */
- if (k >= 0 && (AST_FORMAT_GET_TYPE(f_list[k].format.id) != AST_FORMAT_TYPE_AUDIO)) {
- continue;
- }
- /*Go ahead and move to next iteration if dealing with an unknown codec*/
- if (k >= 0 && !strcmp(ast_getformatname(&f_list[k].format), "unknown")) {
+
+ if ((k > 0) && (y = codec2index(col)) == -1) {
+ ao2_ref(col, -1);
continue;
}
- if (k >= 0) {
- curlen = strlen(ast_getformatname(&f_list[k].format));
+
+ if (k > 0) {
+ curlen = strlen(col->name);
}
+
if (curlen < 5) {
curlen = 5;
}
@@ -911,12 +960,12 @@ static char *handle_show_translation_table(struct ast_cli_args *a)
if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
/* Actual codec output */
ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost/100));
- } else if (i == -1 && k >= 0) {
+ } else if (i == 0 && k > 0) {
/* Top row - use a dynamic size */
- ast_str_append(&out, 0, "%*s", curlen + 1, ast_getformatname(&f_list[k].format));
- } else if (k == -1 && i >= 0) {
+ ast_str_append(&out, 0, "%*s", curlen + 1, col->name);
+ } else if (k == 0 && i > 0) {
/* Left column - use a static size. */
- ast_str_append(&out, 0, "%*s", longest, ast_getformatname(&f_list[i].format));
+ ast_str_append(&out, 0, "%*s", longest, row->name);
} else if (x >= 0 && y >= 0) {
/* Codec not supported */
ast_str_append(&out, 0, "%*s", curlen + 1, "-");
@@ -924,74 +973,79 @@ static char *handle_show_translation_table(struct ast_cli_args *a)
/* Upper left hand corner */
ast_str_append(&out, 0, "%*s", longest, "");
}
+ ao2_cleanup(col);
}
ast_str_append(&out, 0, "\n");
ast_cli(a->fd, "%s", ast_str_buffer(out));
+ ao2_cleanup(row);
}
ast_free(out);
AST_RWLIST_UNLOCK(&translators);
- ast_format_list_destroy(f_list);
return CLI_SUCCESS;
}
-static char *handle_show_translation_path(struct ast_cli_args *a)
+static char *handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
{
- struct ast_format input_src_format;
- size_t len = 0;
- int i;
- const struct ast_format_list *format_list = ast_format_list_get(&len);
+ int i = 1;
struct ast_str *str = ast_str_alloca(1024);
struct ast_translator *step;
- char tmp[256];
+ struct ast_codec *dst_codec;
+ struct ast_codec *src_codec = ast_codec_get(codec_name, AST_MEDIA_TYPE_AUDIO, sample_rate);
- ast_format_clear(&input_src_format);
- for (i = 0; i < len; i++) {
- if (AST_FORMAT_GET_TYPE(format_list[i].format.id) != AST_FORMAT_TYPE_AUDIO) {
- continue;
- }
- if (!strncasecmp(format_list[i].name, a->argv[4], strlen(format_list[i].name))) {
- ast_format_copy(&input_src_format, &format_list[i].format);
- }
- }
-
- if (!input_src_format.id) {
- ast_cli(a->fd, "Source codec \"%s\" is not found.\n", a->argv[4]);
- ast_format_list_destroy(format_list);
+ if (!src_codec) {
+ ast_cli(a->fd, "Source codec \"%s\" is not found.\n", codec_name);
return CLI_FAILURE;
}
AST_RWLIST_RDLOCK(&translators);
- ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %d ---\n", a->argv[4], ast_format_rate(&input_src_format));
- for (i = 0; i < len; i++) {
- int src;
- int dst;
- if ((AST_FORMAT_GET_TYPE(format_list[i].format.id) != AST_FORMAT_TYPE_AUDIO) || (format_list[i].format.id == input_src_format.id)) {
+ ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
+ codec_name, src_codec->sample_rate);
+
+ while ((dst_codec = ast_codec_get_by_id(i))) {
+ int src, dst;
+ char src_buffer[64];
+ char dst_buffer[64];
+
+ ++i;
+ if (src_codec == dst_codec ||
+ dst_codec->type != AST_MEDIA_TYPE_AUDIO) {
+ ao2_ref(dst_codec, -1);
continue;
}
- dst = format2index(format_list[i].format.id);
- src = format2index(input_src_format.id);
- ast_str_reset(str);
- if ((len >= cur_max_index) && (src >= 0) && (dst >= 0) && matrix_get(src, dst)->step) {
- ast_str_append(&str, 0, "%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), matrix_get(src, dst)->step->src_format.id));
- while (src != dst) {
- step = matrix_get(src, dst)->step;
- if (!step) {
- ast_str_reset(str);
- break;
+
+ dst = codec2index(dst_codec);
+ src = codec2index(src_codec);
+
+ if (src < 0 || dst < 0) {
+ ast_str_set(&str, 0, "No Translation Path");
+ } else {
+ step = matrix_get(src, dst)->step;
+
+ if (step) {
+ codec_append_name(&step->src_codec, &str);
+ while (src != dst) {
+ src = step->dst_fmt_index;
+ step = matrix_get(src, dst)->step;
+ if (!step) {
+ ast_str_append(&str, 0, "->");
+ codec_append_name(dst_codec, &str);
+ break;
+ }
+ ast_str_append(&str, 0, "->");
+ codec_append_name(&step->src_codec, &str);
}
- ast_str_append(&str, 0, "->%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), step->dst_format.id));
- src = step->dst_fmt_index;
}
}
- if (ast_strlen_zero(ast_str_buffer(str))) {
- ast_str_set(&str, 0, "No Translation Path");
- }
- ast_cli(a->fd, "\t%-10.10s To %-10.10s: %-60.60s\n", a->argv[4], format_list[i].name, ast_str_buffer(str));
+ snprintf(src_buffer, sizeof(src_buffer), "%s:%u", src_codec->name, src_codec->sample_rate);
+ snprintf(dst_buffer, sizeof(dst_buffer), "%s:%u", dst_codec->name, dst_codec->sample_rate);
+ ast_cli(a->fd, "\t%-16.16s To %-16.16s: %-60.60s\n",
+ src_buffer, dst_buffer, ast_str_buffer(str));
+ ast_str_reset(str);
+ ao2_ref(dst_codec, -1);
}
AST_RWLIST_UNLOCK(&translators);
-
- ast_format_list_destroy(format_list);
+ ao2_ref(src_codec, -1);
return CLI_SUCCESS;
}
@@ -1009,8 +1063,10 @@ static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd,
" with each conversion. If the argument 'recalc' is supplied along\n"
" with optional number of seconds to test a new test will be performed\n"
" as the chart is being displayed.\n"
- " 2. 'core show translation paths [codec]'\n"
- " This will display all the translation paths associated with a codec\n";
+ " 2. 'core show translation paths [codec [sample_rate]]'\n"
+ " This will display all the translation paths associated with a codec.\n"
+ " If a codec has multiple sample rates, the sample rate must be\n"
+ " provided as well.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 3) {
@@ -1019,14 +1075,22 @@ static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd,
if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) {
return complete_trans_path_choice(a->line, a->word, a->pos, a->n);
}
+ /* BUGBUG - add tab completion for sample rates */
return NULL;
}
- if (a->argc > 5)
+ if (a->argc > 6)
return CLI_SHOWUSAGE;
if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */
- return handle_show_translation_path(a);
+ return handle_show_translation_path(a, a->argv[4], 0);
+ } else if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 6) {
+ unsigned int sample_rate;
+ if (sscanf(a->argv[5], "%30u", &sample_rate) != 1) {
+ ast_cli(a->fd, "Invalid sample rate: %s.\n", a->argv[5]);
+ return CLI_FAILURE;
+ }
+ return handle_show_translation_path(a, a->argv[4], sample_rate);
} else if (a->argv[3] && !strcasecmp(a->argv[3], option[0])) { /* recalc and then fall through to show table */
handle_cli_recalc(a);
} else if (a->argc > 3) { /* wrong input */
@@ -1045,14 +1109,29 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
{
struct ast_translator *u;
char tmp[80];
+ RAII_VAR(struct ast_codec *, src_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, dst_codec, NULL, ao2_cleanup);
- if (add_format2index(t->src_format.id) || add_format2index(t->dst_format.id)) {
+ src_codec = ast_codec_get(t->src_codec.name, t->src_codec.type, t->src_codec.sample_rate);
+ if (!src_codec) {
+ ast_assert(0);
+ ast_log(LOG_WARNING, "Failed to register translator: unknown source codec %s\n", t->src_codec.name);
+ return -1;
+ }
+
+ dst_codec = ast_codec_get(t->dst_codec.name, t->dst_codec.type, t->dst_codec.sample_rate);
+ if (!dst_codec) {
+ ast_log(LOG_WARNING, "Failed to register translator: unknown destination codec %s\n", t->dst_codec.name);
+ return -1;
+ }
+
+ if (add_codec2index(src_codec) || add_codec2index(dst_codec)) {
if (matrix_resize(0)) {
ast_log(LOG_WARNING, "Translator matrix can not represent any more translators. Out of resources.\n");
return -1;
}
- add_format2index(t->src_format.id);
- add_format2index(t->dst_format.id);
+ add_codec2index(src_codec);
+ add_codec2index(dst_codec);
}
if (!mod) {
@@ -1064,15 +1143,15 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
return -1;
}
- if (!t->table_cost && !(t->table_cost = generate_table_cost(&t->src_format, &t->dst_format))) {
+ if (!t->table_cost && !(t->table_cost = generate_table_cost(src_codec, dst_codec))) {
ast_log(LOG_WARNING, "Table cost could not be generated for %s, "
"Please set table_cost variable on translator.\n", t->name);
return -1;
}
t->module = mod;
- t->src_fmt_index = format2index(t->src_format.id);
- t->dst_fmt_index = format2index(t->dst_format.id);
+ t->src_fmt_index = codec2index(src_codec);
+ t->dst_fmt_index = codec2index(dst_codec);
t->active = 1;
if (t->src_fmt_index < 0 || t->dst_fmt_index < 0) {
@@ -1080,12 +1159,12 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
return -1;
}
if (t->src_fmt_index >= cur_max_index) {
- ast_log(LOG_WARNING, "Source format %s is larger than cur_max_index\n", ast_getformatname(&t->src_format));
+ ast_log(LOG_WARNING, "Source codec %s is larger than cur_max_index\n", t->src_codec.name);
return -1;
}
if (t->dst_fmt_index >= cur_max_index) {
- ast_log(LOG_WARNING, "Destination format %s is larger than cur_max_index\n", ast_getformatname(&t->dst_format));
+ ast_log(LOG_WARNING, "Destination codec %s is larger than cur_max_index\n", t->dst_codec.name);
return -1;
}
@@ -1106,9 +1185,9 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
generate_computational_cost(t, 1);
- ast_verb(2, "Registered translator '%s' from format %s to %s, table cost, %d, computational cost %d\n",
- term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
- ast_getformatname(&t->src_format), ast_getformatname(&t->dst_format), t->table_cost, t->comp_cost);
+ ast_verb(2, "Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
+ term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
+ t->src_codec.name, t->dst_codec.name, t->table_cost, t->comp_cost);
AST_RWLIST_WRLOCK(&translators);
@@ -1125,7 +1204,7 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
}
AST_RWLIST_TRAVERSE_SAFE_END;
- /* if no existing translator was found for this format combination,
+ /* if no existing translator was found for this codec combination,
add it to the beginning of the list */
if (t) {
AST_RWLIST_INSERT_HEAD(&translators, t, list);
@@ -1149,10 +1228,9 @@ int ast_unregister_translator(struct ast_translator *t)
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
if (u == t) {
AST_RWLIST_REMOVE_CURRENT(list);
- ast_verb(2, "Unregistered translator '%s' from format %s to %s\n",
+ ast_verb(2, "Unregistered translator '%s' from codec %s to %s\n",
term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
- ast_getformatname(&t->src_format),
- ast_getformatname(&t->dst_format));
+ t->src_codec.name, t->dst_codec.name);
found = 1;
break;
}
@@ -1187,91 +1265,105 @@ void ast_translator_deactivate(struct ast_translator *t)
/*! \brief Calculate our best translator source format, given costs, and a desired destination */
int ast_translator_best_choice(struct ast_format_cap *dst_cap,
struct ast_format_cap *src_cap,
- struct ast_format *dst_fmt_out,
- struct ast_format *src_fmt_out)
+ struct ast_format **dst_fmt_out,
+ struct ast_format **src_fmt_out)
{
- struct ast_format best;
- struct ast_format_cap *joint_cap = ast_format_cap_joint(dst_cap, src_cap);
+ unsigned int besttablecost = INT_MAX;
+ unsigned int beststeps = INT_MAX;
+ RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, bestdst, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, joint_cap, NULL, ao2_cleanup);
+ int i;
+ int j;
- ast_format_clear(&best);
+ if (!(joint_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+ return -1;
+ }
+ ast_format_cap_get_compatible(dst_cap, src_cap, joint_cap);
- if (joint_cap) { /* yes, pick one and return */
- struct ast_format tmp_fmt;
+ for (i = 0; i < ast_format_cap_count(joint_cap); ++i) {
+ struct ast_format *fmt =
+ ast_format_cap_get_format(joint_cap, i);
- ast_format_cap_iter_start(joint_cap);
- while (!ast_format_cap_iter_next(joint_cap, &tmp_fmt)) {
- /* We are guaranteed to find one common format. */
- if (!best.id) {
- ast_format_copy(&best, &tmp_fmt);
- continue;
- }
- /* If there are multiple common formats, pick the one with the highest sample rate */
- if (ast_format_rate(&best) < ast_format_rate(&tmp_fmt)) {
- ast_format_copy(&best, &tmp_fmt);
- continue;
- }
+ if (!fmt) {
+ continue;
+ }
+
+ if (!best) {
+ /* No ao2_ref operations needed, we're done with fmt */
+ best = fmt;
+ continue;
}
- ast_format_cap_iter_end(joint_cap);
- /* We are done, this is a common format to both. */
- ast_format_copy(dst_fmt_out, &best);
- ast_format_copy(src_fmt_out, &best);
- ast_format_cap_destroy(joint_cap);
+ if (ast_format_get_sample_rate(best) <
+ ast_format_get_sample_rate(fmt)) {
+ ao2_replace(best, fmt);
+ }
+ ao2_ref(fmt, -1);
+ }
+
+ if (best) {
+ ao2_replace(*dst_fmt_out, best);
+ ao2_replace(*src_fmt_out, best);
return 0;
- } else { /* No, we will need to translate */
- unsigned int besttablecost = INT_MAX;
- unsigned int beststeps = INT_MAX;
- struct ast_format cur_dst;
- struct ast_format cur_src;
- struct ast_format bestdst;
+ }
+ /* need to translate */
+ AST_RWLIST_RDLOCK(&translators);
- ast_format_clear(&bestdst);
+ for (i = 0; i < ast_format_cap_count(dst_cap); ++i) {
+ struct ast_format *dst =
+ ast_format_cap_get_format(dst_cap, i);
- AST_RWLIST_RDLOCK(&translators);
- ast_format_cap_iter_start(dst_cap);
- while (!ast_format_cap_iter_next(dst_cap, &cur_dst)) {
- ast_format_cap_iter_start(src_cap);
- while (!ast_format_cap_iter_next(src_cap, &cur_src)) {
- int x = format2index(cur_src.id);
- int y = format2index(cur_dst.id);
- struct translator_path *trans;
-
- if (x < 0 || y < 0) {
- continue;
- }
- trans = matrix_get(x, y);
- if (!trans || !trans->step) {
- continue;
- }
- if (trans->table_cost < besttablecost || trans->multistep < beststeps) {
- /* better than what we have so far */
- ast_format_copy(&best, &cur_src);
- ast_format_copy(&bestdst, &cur_dst);
- besttablecost = trans->table_cost;
- beststeps = trans->multistep;
- }
- }
- ast_format_cap_iter_end(src_cap);
+ if (!dst) {
+ continue;
}
- ast_format_cap_iter_end(dst_cap);
- AST_RWLIST_UNLOCK(&translators);
- if (best.id) {
- ast_format_copy(dst_fmt_out, &bestdst);
- ast_format_copy(src_fmt_out, &best);
- return 0;
+ for (j = 0; j < ast_format_cap_count(src_cap); ++j) {
+ struct ast_format *src =
+ ast_format_cap_get_format(src_cap, j);
+ int x, y;
+
+ if (!src) {
+ continue;
+ }
+
+ x = format2index(src);
+ y = format2index(dst);
+ if (x < 0 || y < 0) {
+ ao2_ref(src, -1);
+ continue;
+ }
+ if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
+ ao2_ref(src, -1);
+ continue;
+ }
+ if (((matrix_get(x, y)->table_cost < besttablecost) ||
+ (matrix_get(x, y)->multistep < beststeps))) {
+ /* better than what we have so far */
+ ao2_replace(best, src);
+ ao2_replace(bestdst, dst);
+ besttablecost = matrix_get(x, y)->table_cost;
+ beststeps = matrix_get(x, y)->multistep;
+ }
+ ao2_ref(src, -1);
}
+ ao2_ref(dst, -1);
+ }
+ AST_RWLIST_UNLOCK(&translators);
+ if (!best) {
return -1;
}
+ ao2_replace(*dst_fmt_out, bestdst);
+ ao2_replace(*src_fmt_out, best);
+ return 0;
}
unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_format *src_format)
{
unsigned int res = -1;
- int src, dest;
/* convert bitwise format numbers into array indices */
- src = format2index(src_format->id);
- dest = format2index(dst_format->id);
+ int src = format2index(src_format);
+ int dest = format2index(dst_format);
if (src < 0 || dest < 0) {
ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src < 0 ? "starting" : "ending");
@@ -1288,25 +1380,72 @@ unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_
return res;
}
+static void check_translation_path(
+ struct ast_format_cap *dest, struct ast_format_cap *src,
+ struct ast_format_cap *result, struct ast_format *src_fmt,
+ enum ast_media_type type)
+{
+ int index, src_index = format2index(src_fmt);
+ /* For a given source format, traverse the list of
+ known formats to determine whether there exists
+ a translation path from the source format to the
+ destination format. */
+ for (index = 0; (src_index >= 0) && index < cur_max_index; index++) {
+ struct ast_codec *codec = index2codec(index);
+ RAII_VAR(struct ast_format *, fmt, ast_format_create(codec), ao2_cleanup);
+
+ ao2_ref(codec, -1);
+
+ if (ast_format_get_type(fmt) != type) {
+ continue;
+ }
+
+ /* if this is not a desired format, nothing to do */
+ if (ast_format_cap_iscompatible_format(dest, fmt) == AST_FORMAT_CMP_NOT_EQUAL) {
+ continue;
+ }
+
+ /* if the source is supplying this format, then
+ we can leave it in the result */
+ if (ast_format_cap_iscompatible_format(src, fmt) == AST_FORMAT_CMP_EQUAL) {
+ continue;
+ }
+
+ /* if we don't have a translation path from the src
+ to this format, remove it from the result */
+ if (!matrix_get(src_index, index)->step) {
+ ast_format_cap_remove(result, fmt);
+ continue;
+ }
+
+ /* now check the opposite direction */
+ if (!matrix_get(index, src_index)->step) {
+ ast_format_cap_remove(result, fmt);
+ }
+ }
+
+}
+
void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
{
- struct ast_format tmp_fmt;
- struct ast_format cur_dest, cur_src;
- int src_audio = 0;
- int src_video = 0;
+ struct ast_format *cur_dest, *cur_src;
int index;
- ast_format_cap_iter_start(dest);
- while (!ast_format_cap_iter_next(dest, &cur_dest)) {
+ for (index = 0; index < ast_format_cap_count(dest); ++index) {
+ if (!(cur_dest = ast_format_cap_get_format(dest, index))) {
+ continue;
+ }
+
/* We give preference to a joint format structure if possible */
- if (ast_format_cap_get_compatible_format(src, &cur_dest, &tmp_fmt)) {
- ast_format_cap_add(result, &tmp_fmt);
+ if ((cur_src = ast_format_cap_get_compatible_format(src, cur_dest))) {
+ ast_format_cap_append(result, cur_src, 0);
+ ao2_ref(cur_src, -1);
} else {
/* Otherwise we just use the destination format */
- ast_format_cap_add(result, &cur_dest);
+ ast_format_cap_append(result, cur_dest, 0);
}
+ ao2_ref(cur_dest, -1);
}
- ast_format_cap_iter_end(dest);
/* if we don't have a source format, we just have to try all
possible destination formats */
@@ -1314,91 +1453,19 @@ void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_for
return;
}
- ast_format_cap_iter_start(src);
- while (!ast_format_cap_iter_next(src, &cur_src)) {
- /* If we have a source audio format, get its format index */
- if (AST_FORMAT_GET_TYPE(cur_src.id) == AST_FORMAT_TYPE_AUDIO) {
- src_audio = format2index(cur_src.id);
- }
-
- /* If we have a source video format, get its format index */
- if (AST_FORMAT_GET_TYPE(cur_src.id) == AST_FORMAT_TYPE_VIDEO) {
- src_video = format2index(cur_src.id);
+ for (index = 0; index < ast_format_cap_count(src); ++index) {
+ if (!(cur_src = ast_format_cap_get_format(src, index))) {
+ continue;
}
AST_RWLIST_RDLOCK(&translators);
-
- /* For a given source audio format, traverse the list of
- known audio formats to determine whether there exists
- a translation path from the source format to the
- destination format. */
- for (index = 0; (src_audio >= 0) && index < cur_max_index; index++) {
- ast_format_set(&tmp_fmt, index2format(index), 0);
-
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO) {
- continue;
- }
-
- /* if this is not a desired format, nothing to do */
- if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) {
- continue;
- }
-
- /* if the source is supplying this format, then
- we can leave it in the result */
- if (ast_format_cap_iscompatible(src, &tmp_fmt)) {
- continue;
- }
-
- /* if we don't have a translation path from the src
- to this format, remove it from the result */
- if (!matrix_get(src_audio, index)->step) {
- ast_format_cap_remove_byid(result, tmp_fmt.id);
- continue;
- }
-
- /* now check the opposite direction */
- if (!matrix_get(index, src_audio)->step) {
- ast_format_cap_remove_byid(result, tmp_fmt.id);
- }
- }
-
- /* For a given source video format, traverse the list of
- known video formats to determine whether there exists
- a translation path from the source format to the
- destination format. */
- for (index = 0; (src_video >= 0) && index < cur_max_index; index++) {
- ast_format_set(&tmp_fmt, index2format(index), 0);
- if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_VIDEO) {
- continue;
- }
-
- /* if this is not a desired format, nothing to do */
- if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) {
- continue;
- }
-
- /* if the source is supplying this format, then
- we can leave it in the result */
- if (ast_format_cap_iscompatible(src, &tmp_fmt)) {
- continue;
- }
-
- /* if we don't have a translation path from the src
- to this format, remove it from the result */
- if (!matrix_get(src_video, index)->step) {
- ast_format_cap_remove_byid(result, tmp_fmt.id);
- continue;
- }
-
- /* now check the opposite direction */
- if (!matrix_get(index, src_video)->step) {
- ast_format_cap_remove_byid(result, tmp_fmt.id);
- }
- }
+ check_translation_path(dest, src, result,
+ cur_src, AST_MEDIA_TYPE_AUDIO);
+ check_translation_path(dest, src, result,
+ cur_src, AST_MEDIA_TYPE_VIDEO);
AST_RWLIST_UNLOCK(&translators);
+ ao2_ref(cur_src, -1);
}
- ast_format_cap_iter_end(src);
}
static void translate_shutdown(void)
diff --git a/main/utils.c b/main/utils.c
index 0097487a3..a916e79c8 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -1054,10 +1054,10 @@ struct ast_str *ast_dump_locks(void)
if (!header_printed) {
if (lock_info->lwp != -1) {
ast_str_append(&str, 0, "=== Thread ID: 0x%lx LWP:%d (%s)\n",
- (long) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
+ (long unsigned) lock_info->thread_id, lock_info->lwp, lock_info->thread_name);
} else {
ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n",
- (long) lock_info->thread_id, lock_info->thread_name);
+ (long unsigned) lock_info->thread_id, lock_info->thread_name);
}
header_printed = 1;
}
diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c
index 4461d7fc7..adec3b26a 100644
--- a/pbx/pbx_spool.c
+++ b/pbx/pbx_spool.c
@@ -53,6 +53,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
/*
* pbx_spool is similar in spirit to qcall, but with substantially enhanced functionality...
@@ -108,7 +110,7 @@ static void free_outgoing(struct outgoing *o)
if (o->vars) {
ast_variables_destroy(o->vars);
}
- o->capabilities = ast_format_cap_destroy(o->capabilities);
+ ao2_cleanup(o->capabilities);
ast_string_field_free_memory(o);
ast_free(o);
}
@@ -116,7 +118,6 @@ static void free_outgoing(struct outgoing *o)
static struct outgoing *new_outgoing(const char *fn)
{
struct outgoing *o;
- struct ast_format tmpfmt;
o = ast_calloc(1, sizeof(*o));
if (!o) {
@@ -144,12 +145,12 @@ static struct outgoing *new_outgoing(const char *fn)
return NULL;
}
- o->capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ o->capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!o->capabilities) {
free_outgoing(o);
return NULL;
}
- ast_format_cap_add(o->capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(o->capabilities, ast_format_slin, 0);
return o;
}
@@ -226,7 +227,7 @@ static int apply_outgoing(struct outgoing *o, FILE *f)
o->maxretries = 0;
}
} else if (!strcasecmp(buf, "codecs")) {
- ast_parse_allow_disallow(NULL, o->capabilities, c, 1);
+ ast_format_cap_update_by_allow_disallow(o->capabilities, c, 1);
} else if (!strcasecmp(buf, "context")) {
ast_string_field_set(o, context, c);
} else if (!strcasecmp(buf, "extension")) {
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index eeb4237d0..93ecd14b7 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/format_cap.h"
#include "asterisk/file.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/format_cache.h"
/*!
* \brief Finds a bridge, filling the response with an error, if appropriate.
@@ -303,19 +304,14 @@ static void *bridge_channel_control_thread(void *data)
static struct ast_channel *prepare_bridge_media_channel(const char *type)
{
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
- struct ast_format format;
+ RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return NULL;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
-
- if (!cap) {
- return NULL;
- }
+ ast_format_cap_append(cap, ast_format_slin, 0);
return ast_request(type, cap, NULL, NULL, "ARI", NULL);
}
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index 393609298..cef1e7130 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_app_snoop.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/causes.h"
+#include "asterisk/format_cache.h"
#include "asterisk/core_local.h"
#include "resource_channels.h"
@@ -772,8 +773,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
char *cid_name = NULL;
int timeout = 30000;
RAII_VAR(struct ast_format_cap *, cap,
- ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
- struct ast_format tmp_fmt;
+ ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
char *stuff;
struct ast_channel *chan;
struct ast_channel *local_peer;
@@ -787,7 +787,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
ast_ari_response_alloc_failed(response);
return;
}
- ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
|| (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
diff --git a/res/ari/resource_sounds.c b/res/ari/resource_sounds.c
index 5be4bf9a8..5a523d387 100644
--- a/res/ari/resource_sounds.c
+++ b/res/ari/resource_sounds.c
@@ -46,8 +46,8 @@ static int add_format_information_cb(void *obj, void *arg, int flags)
{
char *language = obj;
struct lang_format_info *args = arg;
- struct ast_format format;
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
+ int idx;
+ RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
if (!sounds_index) {
@@ -59,27 +59,28 @@ static int add_format_information_cb(void *obj, void *arg, int flags)
return CMP_STOP;
}
- ast_format_cap_iter_start(cap);
- while (!ast_format_cap_iter_next(cap, &format)) {
+ for (idx = 0; idx < ast_format_cap_count(cap); idx++) {
+ struct ast_format *format = ast_format_cap_get_format(cap, idx);
struct ast_json *lang_format_pair;
- const char *format_name = ast_getformatname(&format);
if (!ast_strlen_zero(args->format_filter)
- && strcmp(args->format_filter, format_name)) {
+ && strcmp(args->format_filter, ast_format_get_name(format))) {
+ ao2_ref(format, -1);
continue;
}
lang_format_pair = ast_json_pack("{s: s, s: s}",
"language", language,
- "format", format_name);
+ "format", ast_format_get_name(format));
if (!lang_format_pair) {
- ast_format_cap_iter_end(cap);
+ ao2_ref(format, -1);
return CMP_STOP;
}
ast_json_array_append(args->format_list, lang_format_pair);
+ ao2_ref(format, -1);
}
- ast_format_cap_iter_end(cap);
+
return 0;
}
diff --git a/res/parking/parking_applications.c b/res/parking/parking_applications.c
index 51d6aff8f..8bb57b62b 100644
--- a/res/parking/parking_applications.c
+++ b/res/parking/parking_applications.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/say.h"
#include "asterisk/bridge_basic.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="Park" language="en_US">
@@ -688,11 +689,10 @@ static void announce_to_dial(char *dial_string, char *announce_string, int parki
struct ast_channel *dchan;
struct outgoing_helper oh = { 0, };
int outstate;
- struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
char buf[13];
char *dial_tech;
char *cur_announce;
- struct ast_format tmpfmt;
dial_tech = strsep(&dial_string, "/");
ast_verb(3, "Dial Tech,String: (%s,%s)\n", dial_tech, dial_string);
@@ -701,7 +701,7 @@ static void announce_to_dial(char *dial_string, char *announce_string, int parki
ast_log(LOG_WARNING, "PARK: Failed to announce park.\n");
goto announce_cleanup;
}
- ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap_slin, ast_format_slin, 0);
snprintf(buf, sizeof(buf), "%d", parkingspace);
oh.vars = ast_variable_new("_PARKEDAT", buf, "");
@@ -737,7 +737,7 @@ static void announce_to_dial(char *dial_string, char *announce_string, int parki
ast_hangup(dchan);
announce_cleanup:
- cap_slin = ast_format_cap_destroy(cap_slin);
+ ao2_cleanup(cap_slin);
}
static void park_announce_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
diff --git a/res/res_adsi.c b/res/res_adsi.c
index 92987f072..e11432e29 100644
--- a/res/res_adsi.c
+++ b/res/res_adsi.c
@@ -50,6 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/file.h"
#include "asterisk/adsi.h"
+#include "asterisk/format_cache.h"
#define DEFAULT_ADSI_MAX_RETRIES 3
@@ -154,12 +155,14 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
{
/* Sends carefully on a full duplex channel by using reading for
timing */
- struct ast_frame *inf, outf;
+ struct ast_frame *inf;
+ struct ast_frame outf = {
+ .frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_ulaw,
+ .data.ptr = buf,
+ };
int amt;
- /* Zero out our outgoing frame */
- memset(&outf, 0, sizeof(outf));
-
if (remain && *remain) {
amt = len;
@@ -169,9 +172,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
} else {
*remain = *remain - amt;
}
- outf.frametype = AST_FRAME_VOICE;
- ast_format_set(&outf.subclass.format, AST_FORMAT_ULAW, 0);
- outf.data.ptr = buf;
+
outf.datalen = amt;
outf.samples = amt;
if (ast_write(chan, &outf)) {
@@ -201,7 +202,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
continue;
}
- if (inf->subclass.format.id != AST_FORMAT_ULAW) {
+ if (ast_format_cmp(inf->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL) {
ast_log(LOG_WARNING, "Channel not in ulaw?\n");
ast_frfree(inf);
return -1;
@@ -212,9 +213,6 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
} else if (remain) {
*remain = inf->datalen - amt;
}
- outf.frametype = AST_FRAME_VOICE;
- ast_format_set(&outf.subclass.format, AST_FORMAT_ULAW, 0);
- outf.data.ptr = buf;
outf.datalen = amt;
outf.samples = amt;
if (ast_write(chan, &outf)) {
@@ -245,11 +243,9 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms
}
while (retries < maxretries) {
- struct ast_format tmpfmt;
if (!(ast_channel_adsicpe(chan) & ADSI_FLAG_DATAMODE)) {
/* Generate CAS (no SAS) */
- ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0);
- ast_gen_cas(buf, 0, 680, &tmpfmt);
+ ast_gen_cas(buf, 0, 680, ast_format_ulaw);
/* Send CAS */
if (adsi_careful_send(chan, buf, 680, NULL)) {
@@ -308,7 +304,7 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms
def= ast_channel_defer_dtmf(chan);
#endif
while ((x < 6) && msg[x]) {
- if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], ast_format_set(&tmpfmt, AST_FORMAT_ULAW,0))) < 0) {
+ if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], ast_format_ulaw)) < 0) {
ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, ast_channel_name(chan));
return -1;
}
@@ -395,11 +391,8 @@ static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *m
{
unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
int msglens[5], msgtypes[5], newdatamode = (ast_channel_adsicpe(chan) & ADSI_FLAG_DATAMODE), res, x, waitforswitch = 0;
- struct ast_format writeformat;
- struct ast_format readformat;
-
- ast_format_copy(&writeformat, ast_channel_writeformat(chan));
- ast_format_copy(&readformat, ast_channel_readformat(chan));
+ RAII_VAR(struct ast_format *, writeformat, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, readformat, NULL, ao2_cleanup);
for (x = 0; x < msglen; x += (msg[x+1]+2)) {
if (msg[x] == ADSI_SWITCH_TO_DATA) {
@@ -426,16 +419,19 @@ static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *m
ast_stopstream(chan);
- if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW)) {
+ writeformat = ao2_bump(ast_channel_writeformat(chan));
+ readformat = ao2_bump(ast_channel_readformat(chan));
+
+ if (ast_set_write_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
return -1;
}
- if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW)) {
+ if (ast_set_read_format(chan, ast_format_ulaw)) {
ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
- if (writeformat.id) {
- if (ast_set_write_format(chan, &writeformat)) {
- ast_log(LOG_WARNING, "Unable to restore write format to %s\n", ast_getformatname(&writeformat));
+ if (writeformat) {
+ if (ast_set_write_format(chan, writeformat)) {
+ ast_log(LOG_WARNING, "Unable to restore write format to %s\n", ast_format_get_name(writeformat));
}
}
return -1;
@@ -454,11 +450,11 @@ static int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *m
ast_channel_adsicpe_set(chan, (ast_channel_adsicpe(chan) & ~ADSI_FLAG_DATAMODE) | newdatamode);
}
- if (writeformat.id) {
- ast_set_write_format(chan, &writeformat);
+ if (writeformat) {
+ ast_set_write_format(chan, writeformat);
}
- if (readformat.id) {
- ast_set_read_format(chan, &readformat);
+ if (readformat) {
+ ast_set_read_format(chan, readformat);
}
if (!res) {
diff --git a/res/res_agi.c b/res/res_agi.c
index 67a213f8d..b612f7d72 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -68,6 +68,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/netsock2.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_message_router.h"
+#include "asterisk/format_cache.h"
#define AST_API_MODULE
#include "asterisk/agi.h"
@@ -2538,8 +2539,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const
int silence = 0; /* amount of silence to allow */
int gotsilence = 0; /* did we timeout for silence? */
char *silencestr = NULL;
- struct ast_format rfmt;
- ast_format_clear(&rfmt);
+ RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
/* XXX EAGI FIXME XXX */
@@ -2569,8 +2569,8 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const
}
if (silence > 0) {
- ast_format_copy(&rfmt, ast_channel_readformat(chan));
- res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ rfmt = ao2_bump(ast_channel_readformat(chan));
+ res = ast_set_read_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
@@ -2694,7 +2694,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const
}
if (silence > 0) {
- res = ast_set_read_format(chan, &rfmt);
+ res = ast_set_read_format(chan, rfmt);
if (res)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
ast_dsp_free(sildet);
@@ -3032,7 +3032,6 @@ static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const c
static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
{
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
/* If a structure already exists, return an error */
if (agi->speech) {
@@ -3040,16 +3039,16 @@ static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, con
return RESULT_SUCCESS;
}
- if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return RESULT_FAILURE;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
if ((agi->speech = ast_speech_new(argv[2], cap))) {
ast_agi_send(agi->fd, chan, "200 result=1\n");
} else {
ast_agi_send(agi->fd, chan, "200 result=0\n");
}
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return RESULT_SUCCESS;
}
@@ -3182,7 +3181,6 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
const char *prompt;
char dtmf = 0, tmp[4096] = "", *buf = tmp;
int timeout = 0, offset = 0, res = 0, i = 0;
- struct ast_format old_read_format;
long current_offset = 0;
const char *reason = NULL;
struct ast_frame *fr = NULL;
@@ -3206,8 +3204,7 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
offset = atoi(argv[4]);
/* We want frames coming in signed linear */
- ast_format_copy(&old_read_format, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ if (ast_set_read_format(chan, ast_format_slin)) {
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@@ -4195,23 +4192,26 @@ static int agi_exec(struct ast_channel *chan, const char *data)
static int eagi_exec(struct ast_channel *chan, const char *data)
{
int res;
- struct ast_format readformat;
+ struct ast_format *readformat;
if (ast_check_hangup(chan)) {
ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n");
return 0;
}
- ast_format_copy(&readformat, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
+ readformat = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin)) {
ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", ast_channel_name(chan));
+ ao2_ref(readformat, -1);
return -1;
}
res = agi_exec_full(chan, data, 1, 0);
if (!res) {
- if (ast_set_read_format(chan, &readformat)) {
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", ast_channel_name(chan), ast_getformatname(&readformat));
+ if (ast_set_read_format(chan, readformat)) {
+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", ast_channel_name(chan),
+ ast_format_get_name(readformat));
}
}
+ ao2_ref(readformat, -1);
return res;
}
diff --git a/res/res_calendar.c b/res/res_calendar.c
index ae52cbfce..77f8ef662 100644
--- a/res/res_calendar.c
+++ b/res/res_calendar.c
@@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<function name="CALENDAR_BUSY" language="en_US">
@@ -730,6 +731,7 @@ static void *do_notify(void *data)
struct ast_variable *itervar;
char *tech, *dest;
char buf[8];
+ struct ast_format_cap *caps;
tech = ast_strdupa(event->owner->notify_channel);
@@ -760,12 +762,19 @@ static void *do_notify(void *data)
}
ast_channel_tech_set(chan, &null_tech);
- ast_format_set(ast_channel_writeformat(chan), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_readformat(chan), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_rawwriteformat(chan), AST_FORMAT_SLINEAR, 0);
- ast_format_set(ast_channel_rawreadformat(chan), AST_FORMAT_SLINEAR, 0);
- /* clear native formats and set to slinear. write format is signlear so just use that to set it */
- ast_format_cap_set(ast_channel_nativeformats(chan), ast_channel_writeformat(chan));
+ ast_channel_set_writeformat(chan, ast_format_slin);
+ ast_channel_set_readformat(chan, ast_format_slin);
+ ast_channel_set_rawwriteformat(chan, ast_format_slin);
+ ast_channel_set_rawreadformat(chan, ast_format_slin);
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_log(LOG_ERROR, "Could not allocate capabilities, notification not being sent!\n");
+ goto notify_cleanup;
+ }
+ ast_format_cap_append(caps, ast_format_slin, 0);
+ ast_channel_nativeformats_set(chan, caps);
+ ao2_ref(caps, -1);
ast_channel_unlock(chan);
diff --git a/res/res_clioriginate.c b/res/res_clioriginate.c
index cd8b5dde1..3903b6c3b 100644
--- a/res/res_clioriginate.c
+++ b/res/res_clioriginate.c
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
/*! The timeout for originated calls, in seconds */
#define TIMEOUT 30
@@ -57,7 +58,6 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app
char *chandata;
int reason = 0;
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
if (ast_strlen_zero(app))
return CLI_SHOWUSAGE;
@@ -70,12 +70,12 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app
return CLI_SHOWUSAGE;
}
- if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return CLI_FAILURE;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return CLI_SUCCESS;
}
@@ -96,7 +96,6 @@ static char *orig_exten(int fd, const char *chan, const char *data)
char *context = NULL;
int reason = 0;
struct ast_format_cap *cap;
- struct ast_format tmpfmt;
chandata = ast_strdupa(chan);
@@ -115,12 +114,12 @@ static char *orig_exten(int fd, const char *chan, const char *data)
exten = "s";
if (ast_strlen_zero(context))
context = "default";
- if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
return CLI_FAILURE;
}
- ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL);
- cap = ast_format_cap_destroy(cap);
+ ao2_ref(cap, -1);
return CLI_SUCCESS;
}
diff --git a/res/res_fax.c b/res/res_fax.c
index 758309822..d59ab09e6 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -89,6 +89,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/translate.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/smoother.h"
+#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="ReceiveFAX" language="en_US" module="res_fax">
@@ -453,10 +455,10 @@ struct fax_gateway {
/*! \brief a flag to track the state of our negotiation */
enum ast_t38_state t38_state;
/*! \brief original audio formats */
- struct ast_format chan_read_format;
- struct ast_format chan_write_format;
- struct ast_format peer_read_format;
- struct ast_format peer_write_format;
+ struct ast_format *chan_read_format;
+ struct ast_format *chan_write_format;
+ struct ast_format *peer_read_format;
+ struct ast_format *peer_write_format;
};
/*! \brief used for fax detect framehook */
@@ -468,7 +470,7 @@ struct fax_detect {
/*! \brief DSP Processor */
struct ast_dsp *dsp;
/*! \brief original audio formats */
- struct ast_format orig_format;
+ struct ast_format *orig_format;
/*! \brief fax session details */
struct ast_fax_session_details *details;
/*! \brief mode */
@@ -1570,20 +1572,18 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
int timeout = RES_FAX_TIMEOUT;
int chancount;
unsigned int expected_frametype = -1;
- union ast_frame_subclass expected_framesubclass = { .integer = -1 };
+ struct ast_frame_subclass expected_framesubclass = { .integer = 0, };
unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
struct ast_control_t38_parameters t38_parameters;
const char *tempvar;
struct ast_fax_session *fax = NULL;
struct ast_frame *frame = NULL;
struct ast_channel *c = chan;
- struct ast_format orig_write_format;
- struct ast_format orig_read_format;
+ RAII_VAR(struct ast_format *, orig_write_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, orig_read_format, NULL, ao2_cleanup);
int remaining_time;
struct timeval start;
- ast_format_clear(&orig_write_format);
- ast_format_clear(&orig_read_format);
chancount = 1;
/* create the FAX session */
@@ -1607,10 +1607,10 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
report_fax_status(chan, details, "Allocating Resources");
if (details->caps & AST_FAX_TECH_AUDIO) {
- expected_frametype = AST_FRAME_VOICE;;
- ast_format_set(&expected_framesubclass.format, AST_FORMAT_SLINEAR, 0);
- ast_format_copy(&orig_write_format, ast_channel_writeformat(chan));
- if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ expected_frametype = AST_FRAME_VOICE;
+ expected_framesubclass.format = ast_format_slin;
+ orig_write_format = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
ao2_lock(faxregistry.container);
ao2_unlink(faxregistry.container, fax);
@@ -1619,8 +1619,8 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_channel_unlock(chan);
return -1;
}
- ast_format_copy(&orig_read_format, ast_channel_readformat(chan));
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
+ orig_read_format = ao2_bump(ast_channel_readformat(chan));
+ if (ast_set_read_format(chan, ast_format_slin) < 0) {
ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
ao2_lock(faxregistry.container);
ao2_unlink(faxregistry.container, fax);
@@ -1724,8 +1724,10 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->id);
}
- } else if ((frame->frametype == expected_frametype) &&
- (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
+ } else if ((frame->frametype == expected_frametype) && (expected_framesubclass.integer == frame->subclass.integer) &&
+ ((!frame->subclass.format && !expected_framesubclass.format) ||
+ (frame->subclass.format && expected_framesubclass.format &&
+ (ast_format_cmp(frame->subclass.format, expected_framesubclass.format) != AST_FORMAT_CMP_NOT_EQUAL)))) {
struct ast_frame *f;
if (fax->smoother) {
@@ -1809,11 +1811,11 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
* restore them now
*/
if (chancount) {
- if (orig_read_format.id) {
- ast_set_read_format(chan, &orig_read_format);
+ if (orig_read_format) {
+ ast_set_read_format(chan, orig_read_format);
}
- if (orig_write_format.id) {
- ast_set_write_format(chan, &orig_write_format);
+ if (orig_write_format) {
+ ast_set_write_format(chan, orig_write_format);
}
}
@@ -2823,6 +2825,11 @@ static void destroy_gateway(void *data)
ao2_ref(gateway->s, -1);
gateway->s = NULL;
}
+
+ ao2_cleanup(gateway->chan_read_format);
+ ao2_cleanup(gateway->chan_write_format);
+ ao2_cleanup(gateway->peer_read_format);
+ ao2_cleanup(gateway->peer_write_format);
}
/*! \brief Create a new fax gateway object.
@@ -3274,14 +3281,14 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
set_channel_variables(chan, details);
if (gateway->bridged) {
- ast_set_read_format(chan, &gateway->chan_read_format);
- ast_set_read_format(chan, &gateway->chan_write_format);
+ ast_set_read_format(chan, gateway->chan_read_format);
+ ast_set_read_format(chan, gateway->chan_write_format);
ast_channel_unlock(chan);
peer = ast_channel_bridge_peer(chan);
if (peer) {
- ast_set_read_format(peer, &gateway->peer_read_format);
- ast_set_read_format(peer, &gateway->peer_write_format);
+ ast_set_read_format(peer, gateway->peer_read_format);
+ ast_set_read_format(peer, gateway->peer_write_format);
ast_channel_make_compatible(chan, peer);
}
ast_channel_lock(chan);
@@ -3326,18 +3333,18 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
/* we are bridged, change r/w formats to SLIN for v21 preamble
* detection and T.30 */
- ast_format_copy(&gateway->chan_read_format, ast_channel_readformat(chan));
- ast_format_copy(&gateway->chan_write_format, ast_channel_readformat(chan));
+ ao2_replace(gateway->chan_read_format, ast_channel_readformat(chan));
+ ao2_replace(gateway->chan_write_format, ast_channel_readformat(chan));
- ast_format_copy(&gateway->peer_read_format, ast_channel_readformat(peer));
- ast_format_copy(&gateway->peer_write_format, ast_channel_readformat(peer));
+ ao2_replace(gateway->peer_read_format, ast_channel_readformat(peer));
+ ao2_replace(gateway->peer_write_format, ast_channel_readformat(peer));
- ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(chan, ast_format_slin);
+ ast_set_write_format(chan, ast_format_slin);
ast_channel_unlock(chan);
- ast_set_read_format_by_id(peer, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(peer, AST_FORMAT_SLINEAR);
+ ast_set_read_format(peer, ast_format_slin);
+ ast_set_write_format(peer, ast_format_slin);
ast_channel_make_compatible(chan, peer);
ast_channel_lock(chan);
@@ -3361,12 +3368,9 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
/* only handle VOICE, MODEM, and CONTROL frames*/
switch (f->frametype) {
case AST_FRAME_VOICE:
- switch (f->subclass.format.id) {
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- break;
- default:
+ if ((ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
return f;
}
break;
@@ -3412,7 +3416,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
if (gateway->t38_state == T38_STATE_NEGOTIATED) {
/* framehooks are called in __ast_read() before frame format
* translation is done, so we need to translate here */
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR)) {
+ if ((f->frametype == AST_FRAME_VOICE) && (ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL)) {
if (ast_channel_readtrans(active) && (f = ast_translate(ast_channel_readtrans(active), f, 1)) == NULL) {
f = &ast_null_frame;
return f;
@@ -3424,7 +3428,8 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
* write would fail, or even if a failure would be fatal so for
* now we'll just ignore the return value. */
gateway->s->tech->write(gateway->s, f);
- if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR) && ast_channel_readtrans(active)) {
+ if ((f->frametype == AST_FRAME_VOICE) && (ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ ast_channel_readtrans(active)) {
/* Only free the frame if we translated / duplicated it - otherwise,
* let whatever is outside the frame hook do it */
ast_frfree(f);
@@ -3435,15 +3440,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
/* force silence on the line if T.38 negotiation might be taking place */
if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
- if (f->frametype == AST_FRAME_VOICE && f->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (f->frametype == AST_FRAME_VOICE &&
+ (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
short silence_buf[f->samples];
struct ast_frame silence_frame = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin,
.data.ptr = silence_buf,
.samples = f->samples,
.datalen = sizeof(silence_buf),
};
- ast_format_set(&silence_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
memset(silence_buf, 0, sizeof(silence_buf));
return ast_frisolate(&silence_frame);
} else {
@@ -3513,6 +3519,7 @@ static void destroy_faxdetect(void *data)
faxdetect->dsp = NULL;
}
ao2_ref(faxdetect->details, -1);
+ ao2_cleanup(faxdetect->orig_format);
}
/*! \brief Create a new fax detect object.
@@ -3587,23 +3594,22 @@ static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct a
switch (event) {
case AST_FRAMEHOOK_EVENT_ATTACHED:
/* Setup format for DSP on ATTACH*/
- ast_format_copy(&faxdetect->orig_format, ast_channel_readformat(chan));
- switch (ast_channel_readformat(chan)->id) {
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- break;
- default:
- if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
- ast_framehook_detach(chan, details->faxdetect_id);
- details->faxdetect_id = -1;
- return f;
- }
+ ao2_replace(faxdetect->orig_format, ast_channel_readformat(chan));
+
+ if ((ast_format_cmp(ast_channel_readformat(chan), ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(ast_channel_readformat(chan), ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(ast_channel_readformat(chan), ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
+ if (ast_set_read_format(chan, ast_format_slin)) {
+ ast_framehook_detach(chan, details->faxdetect_id);
+ details->faxdetect_id = -1;
+ return f;
+ }
}
+
return NULL;
case AST_FRAMEHOOK_EVENT_DETACHED:
/* restore audio formats when we are detached */
- ast_set_read_format(chan, &faxdetect->orig_format);
+ ast_set_read_format(chan, faxdetect->orig_format);
ast_channel_unlock(chan);
peer = ast_channel_bridge_peer(chan);
if (peer) {
@@ -3638,13 +3644,10 @@ static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct a
return f;
}
/* We can only process some formats*/
- switch (f->subclass.format.id) {
- case AST_FORMAT_SLINEAR:
- case AST_FORMAT_ALAW:
- case AST_FORMAT_ULAW:
- break;
- default:
- return f;
+ if ((ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
+ (ast_format_cmp(f->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
+ return f;
}
break;
case AST_FRAME_CONTROL:
diff --git a/res/res_fax_spandsp.c b/res/res_fax_spandsp.c
index 75018e864..63be1b3cb 100644
--- a/res/res_fax_spandsp.c
+++ b/res/res_fax_spandsp.c
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/res_fax.h"
#include "asterisk/channel.h"
+#include "asterisk/format_cache.h"
#define SPANDSP_FAX_SAMPLES 160
#define SPANDSP_FAX_TIMER_RATE 8000 / SPANDSP_FAX_SAMPLES /* 50 ticks per second, 20ms, 160 samples per second */
@@ -609,9 +610,9 @@ static struct ast_frame *spandsp_fax_read(struct ast_fax_session *s)
struct ast_frame fax_frame = {
.frametype = AST_FRAME_VOICE,
.src = "res_fax_spandsp_g711",
+ .subclass.format = ast_format_slin,
};
struct ast_frame *f = &fax_frame;
- ast_format_set(&fax_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
if (ast_timer_ack(p->timer, 1) < 0) {
ast_log(LOG_ERROR, "Failed to acknowledge timer for FAX session '%u'\n", s->id);
@@ -664,20 +665,21 @@ static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame
return -1;
}
- ast_debug(5, "frame={ datalen=%d, samples=%d, mallocd=%d, src=%s, flags=%u, ts=%ld, len=%ld, seqno=%d, data.ptr=%p, subclass.format.id=%u }\n", f->datalen, f->samples, f->mallocd, f->src, f->flags, f->ts, f->len, f->seqno, f->data.ptr, f->subclass.format.id);
+ ast_debug(5, "frame={ datalen=%d, samples=%d, mallocd=%d, src=%s, flags=%u, ts=%ld, len=%ld, seqno=%d, data.ptr=%p, subclass.format=%s }\n", f->datalen, f->samples, f->mallocd, f->src, f->flags, f->ts, f->len, f->seqno, f->data.ptr, ast_format_get_name(f->subclass.format));
/* slinear frame can be passed to spandsp */
- if (f->subclass.format.id == AST_FORMAT_SLINEAR) {
+ if (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
modem_connect_tones_rx(p->tone_state, f->data.ptr, f->samples);
/* alaw/ulaw frame must be converted to slinear before passing to spandsp */
- } else if (f->subclass.format.id == AST_FORMAT_ALAW || f->subclass.format.id == AST_FORMAT_ULAW) {
+ } else if (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL ||
+ ast_format_cmp(f->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
if (!(slndata = ast_malloc(sizeof(*slndata) * f->samples))) {
return -1;
}
- decoder = g711_init(NULL, (f->subclass.format.id == AST_FORMAT_ALAW ? G711_ALAW : G711_ULAW));
+ decoder = g711_init(NULL, (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL ? G711_ALAW : G711_ULAW));
g711_decode(decoder, slndata, f->data.ptr, f->samples);
- ast_debug(5, "spandsp transcoding frame from %s to slinear for v21 detection\n", (f->subclass.format.id == AST_FORMAT_ALAW ? "G711_ALAW" : "G711_ULAW"));
+ ast_debug(5, "spandsp transcoding frame from %s to slinear for v21 detection\n", ast_format_get_name(f->subclass.format));
modem_connect_tones_rx(p->tone_state, slndata, f->samples);
g711_release(decoder);
#if SPANDSP_RELEASE_DATE >= 20090220
@@ -687,7 +689,7 @@ static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame
/* frame in other formats cannot be passed to spandsp, it could cause segfault */
} else {
- ast_log(LOG_WARNING, "Unknown frame format %u, v.21 detection skipped\n", f->subclass.format.id);
+ ast_log(LOG_WARNING, "Frame format %s not supported, v.21 detection skipped\n", ast_format_get_name(f->subclass.format));
return -1;
}
@@ -749,6 +751,7 @@ static int spandsp_fax_gw_t30_gen(struct ast_channel *chan, void *data, int len,
struct ast_frame *f;
struct ast_frame t30_frame = {
.frametype = AST_FRAME_VOICE,
+ .subclass.format = ast_format_slin,
.src = "res_fax_spandsp_g711",
.samples = samples,
.flags = AST_FAX_FRFLAG_GATEWAY,
@@ -756,7 +759,6 @@ static int spandsp_fax_gw_t30_gen(struct ast_channel *chan, void *data, int len,
AST_FRAME_SET_BUFFER(&t30_frame, buffer, AST_FRIENDLY_OFFSET, t30_frame.samples * sizeof(int16_t));
- ast_format_set(&t30_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
if (!(f = ast_frisolate(&t30_frame))) {
return p->isdone ? -1 : res;
}
@@ -878,7 +880,8 @@ static int spandsp_fax_gateway_process(struct ast_fax_session *s, const struct a
/* Process a IFP packet */
if ((f->frametype == AST_FRAME_MODEM) && (f->subclass.integer == AST_MODEM_T38)) {
return t38_core_rx_ifp_packet(p->t38_core_state, f->data.ptr, f->datalen, f->seqno);
- } else if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) {
+ } else if ((f->frametype == AST_FRAME_VOICE) &&
+ (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
return t38_gateway_rx(&p->t38_gw_state, f->data.ptr, f->samples);
}
diff --git a/res/res_format_attr_celt.c b/res/res_format_attr_celt.c
index 1249f0472..7d7c0f844 100644
--- a/res/res_format_attr_celt.c
+++ b/res/res_format_attr_celt.c
@@ -45,152 +45,148 @@ struct celt_attr {
unsigned int framesize;
};
-static int celt_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static void celt_destroy(struct ast_format *format)
{
- struct celt_attr *attr = (struct celt_attr *) format_attr;
+ struct celt_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int celt_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct celt_attr *original = ast_format_get_attribute_data(src);
+ struct celt_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static struct ast_format *celt_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *cloned;
+ struct celt_attr *attr;
unsigned int val;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
if (sscanf(attributes, "framesize=%30u", &val) == 1) {
attr->framesize = val;
}
- return 0;
+ return cloned;
}
-static void celt_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+static void celt_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct celt_attr *attr = (struct celt_attr *) format_attr;
+ struct celt_attr *attr = ast_format_get_attribute_data(format);
- if (!attr->framesize) {
+ if (!attr || !attr->framesize) {
return;
}
ast_str_append(str, 0, "a=fmtp:%u framesize=%u\r\n", payload, attr->framesize);
}
-static enum ast_format_cmp_res celt_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
+static enum ast_format_cmp_res celt_cmp(const struct ast_format *format1, const struct ast_format *format2)
{
- struct celt_attr *attr1 = (struct celt_attr *) fattr1;
- struct celt_attr *attr2 = (struct celt_attr *) fattr2;
+ struct celt_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct celt_attr *attr2 = ast_format_get_attribute_data(format2);
- if (attr1->samplerate == attr2->samplerate) {
+ if (((!attr1 || !attr1->samplerate) && (!attr2 || !attr2->samplerate)) ||
+ (attr1->samplerate == attr2->samplerate)) {
return AST_FORMAT_CMP_EQUAL;
}
+
return AST_FORMAT_CMP_NOT_EQUAL;
}
-static int celt_get_val(const struct ast_format_attr *fattr, int key, void *result)
+static struct ast_format *celt_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- const struct celt_attr *attr = (struct celt_attr *) fattr;
- int *val = result;
-
- switch (key) {
- case CELT_ATTR_KEY_SAMP_RATE:
- *val = attr->samplerate;
- break;
- case CELT_ATTR_KEY_MAX_BITRATE:
- *val = attr->maxbitrate;
- break;
- case CELT_ATTR_KEY_FRAME_SIZE:
- *val = attr->framesize;
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
- return -1;
- }
- return 0;
-}
+ struct celt_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct celt_attr *attr2 = ast_format_get_attribute_data(format2);
+ struct ast_format *jointformat;
+ struct celt_attr *jointattr;
-static int celt_isset(const struct ast_format_attr *fattr, va_list ap)
-{
- enum celt_attr_keys key;
- const struct celt_attr *attr = (struct celt_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case CELT_ATTR_KEY_SAMP_RATE:
- if (attr->samplerate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case CELT_ATTR_KEY_MAX_BITRATE:
- if (attr->maxbitrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case CELT_ATTR_KEY_FRAME_SIZE:
- if (attr->framesize != (va_arg(ap, int))) {
- return -1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- return -1;
- }
+ if (attr1 && attr2 && (attr1->samplerate != attr2->samplerate)) {
+ return NULL;
}
- return 0;
-}
-static int celt_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
-{
- struct celt_attr *attr1 = (struct celt_attr *) fattr1;
- struct celt_attr *attr2 = (struct celt_attr *) fattr2;
- struct celt_attr *attr_res = (struct celt_attr *) result;
- /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
- if (attr1->samplerate != attr2->samplerate) {
- return -1;
+ jointformat = ast_format_clone(format1);
+ if (!jointformat) {
+ return NULL;
}
+ jointattr = ast_format_get_attribute_data(jointformat);
+
/* either would work, they are guaranteed the same at this point. */
- attr_res->samplerate = attr1->samplerate;
+ jointattr->samplerate = attr1->samplerate;
/* Take the lowest max bitrate */
- attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
+ jointattr->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
- attr_res->framesize = attr2->framesize; /* TODO figure out what joint framesize means */
- return 0;
+ jointattr->framesize = attr2->framesize; /* TODO figure out what joint framesize means */
+
+ return jointformat;
}
-static void celt_set(struct ast_format_attr *fattr, va_list ap)
+static struct ast_format *celt_set(const struct ast_format *format, const char *name, const char *value)
{
- enum celt_attr_keys key;
- struct celt_attr *attr = (struct celt_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case CELT_ATTR_KEY_SAMP_RATE:
- attr->samplerate = (va_arg(ap, int));
- break;
- case CELT_ATTR_KEY_MAX_BITRATE:
- attr->maxbitrate = (va_arg(ap, int));
- break;
- case CELT_ATTR_KEY_FRAME_SIZE:
- attr->framesize = (va_arg(ap, int));
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- }
+ struct ast_format *cloned;
+ struct celt_attr *attr;
+ unsigned int val;
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ if (sscanf(value, "%30u", &val) != 1) {
+ ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
+ value, name);
+ ao2_ref(cloned, -1);
+ return NULL;
}
+
+ if (!strcasecmp(name, "sample_rate")) {
+ attr->samplerate = val;
+ } else if (!strcasecmp(name, "max_bitrate")) {
+ attr->maxbitrate = val;
+ } else if (!strcasecmp(name, "frame_size")) {
+ attr->framesize = val;
+ } else {
+ ast_log(LOG_WARNING, "Unknown attribute type '%s'\n", name);
+ ao2_ref(cloned, -1);
+ return NULL;
+ }
+
+ return cloned;
}
-static struct ast_format_attr_interface celt_interface = {
- .id = AST_FORMAT_CELT,
- .format_attr_cmp = celt_cmp,
- .format_attr_get_joint = celt_getjoint,
- .format_attr_set = celt_set,
- .format_attr_isset = celt_isset,
- .format_attr_get_val = celt_get_val,
- .format_attr_sdp_parse = celt_sdp_parse,
- .format_attr_sdp_generate = celt_sdp_generate,
+static struct ast_format_interface celt_interface = {
+ .format_destroy = celt_destroy,
+ .format_clone = celt_clone,
+ .format_cmp = celt_cmp,
+ .format_get_joint = celt_getjoint,
+ .format_attribute_set = celt_set,
+ .format_parse_sdp_fmtp = celt_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = celt_generate_sdp_fmtp,
};
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&celt_interface)) {
+ if (ast_format_interface_register("celt", &celt_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -199,7 +195,6 @@ static int load_module(void)
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&celt_interface);
return 0;
}
diff --git a/res/res_format_attr_h263.c b/res/res_format_attr_h263.c
index 8ec28aac9..121beb1bc 100644
--- a/res/res_format_attr_h263.c
+++ b/res/res_format_attr_h263.c
@@ -38,250 +38,231 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/format.h"
-enum h263_attr_keys {
- H263_ATTR_KEY_SQCIF, /*!< Minimum picture interval for SQCIF resolution */
- H263_ATTR_KEY_QCIF, /*!< Minimum picture interval for QCIF resolution */
- H263_ATTR_KEY_CIF, /*!< Minimum picture interval for CIF resolution */
- H263_ATTR_KEY_CIF4, /*!< Minimum picture interval for CIF4 resolution */
- H263_ATTR_KEY_CIF16, /*!< Minimum picture interval for CIF16 resolution */
- H263_ATTR_KEY_VGA, /*!< Minimum picture interval for VGA resolution */
- H263_ATTR_KEY_CUSTOM_XMAX, /*!< Custom resolution (Xmax) */
- H263_ATTR_KEY_CUSTOM_YMAX, /*!< Custom resolution (Ymax) */
- H263_ATTR_KEY_CUSTOM_MPI, /*!< Custom resolution (MPI) */
- H263_ATTR_KEY_F, /*!< F annex support */
- H263_ATTR_KEY_I, /*!< I annex support */
- H263_ATTR_KEY_J, /*!< J annex support */
- H263_ATTR_KEY_T, /*!< T annex support */
- H263_ATTR_KEY_K, /*!< K annex support */
- H263_ATTR_KEY_N, /*!< N annex support */
- H263_ATTR_KEY_P_SUB1, /*!< Reference picture resampling (sub mode 1) */
- H263_ATTR_KEY_P_SUB2, /*!< Reference picture resampling (sub mode 2) */
- H263_ATTR_KEY_P_SUB3, /*!< Reference picture resampling (sub mode 3) */
- H263_ATTR_KEY_P_SUB4, /*!< Reference picture resampling (sub mode 4) */
- H263_ATTR_KEY_PAR_WIDTH, /*!< Pixel aspect ratio (width) */
- H263_ATTR_KEY_PAR_HEIGHT, /*!< Pixel aspect ratio (height) */
- H263_ATTR_KEY_BPP, /*!< Bits per picture maximum */
- H263_ATTR_KEY_HRD, /*!< Hypothetical reference decoder status */
- H263_ATTR_KEY_END, /*!< End terminator for list */
+struct h263_attr {
+ unsigned int SQCIF; /*!< Minimum picture interval for SQCIF resolution */
+ unsigned int QCIF; /*!< Minimum picture interval for QCIF resolution */
+ unsigned int CIF; /*!< Minimum picture interval for CIF resolution */
+ unsigned int CIF4; /*!< Minimum picture interval for CIF4 resolution */
+ unsigned int CIF16; /*!< Minimum picture interval for CIF16 resolution */
+ unsigned int VGA; /*!< Minimum picture interval for VGA resolution */
+ unsigned int CUSTOM_XMAX; /*!< Custom resolution (Xmax) */
+ unsigned int CUSTOM_YMAX; /*!< Custom resolution (Ymax) */
+ unsigned int CUSTOM_MPI; /*!< Custom resolution (MPI) */
+ unsigned int F; /*!< F annex support */
+ unsigned int I; /*!< I annex support */
+ unsigned int J; /*!< J annex support */
+ unsigned int T; /*!< T annex support */
+ unsigned int K; /*!< K annex support */
+ unsigned int N; /*!< N annex support */
+ unsigned int P_SUB1; /*!< Reference picture resampling (sub mode 1) */
+ unsigned int P_SUB2; /*!< Reference picture resampling (sub mode 2) */
+ unsigned int P_SUB3; /*!< Reference picture resampling (sub mode 3) */
+ unsigned int P_SUB4; /*!< Reference picture resampling (sub mode 4) */
+ unsigned int PAR_WIDTH; /*!< Pixel aspect ratio (width) */
+ unsigned int PAR_HEIGHT; /*!< Pixel aspect ratio (height) */
+ unsigned int BPP; /*!< Bits per picture maximum */
+ unsigned int HRD; /*!< Hypothetical reference decoder status */
};
-static int h263_format_attr_get_joint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
+static void h263_destroy(struct ast_format *format)
{
- int i;
+ struct h263_attr *attr = ast_format_get_attribute_data(format);
- /* These are all receiver options so we just copy over what they sent */
- for (i = H263_ATTR_KEY_SQCIF; i < H263_ATTR_KEY_END; i++) {
- result->format_attr[i] = fattr1->format_attr[i] ? fattr1->format_attr[i] : fattr2->format_attr[i];
+ ast_free(attr);
+}
+
+static int h263_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct h263_attr *original = ast_format_get_attribute_data(src);
+ struct h263_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
}
+ ast_format_set_attribute_data(dst, attr);
+
return 0;
}
-static int h263_format_attr_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static enum ast_format_cmp_res h263_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct h263_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct h263_attr *attr2 = ast_format_get_attribute_data(format2);
+
+ if (!attr1 || !attr2 || (attr1 && attr2 && !memcmp(attr1, attr2, sizeof(*attr1)))) {
+ return AST_FORMAT_CMP_EQUAL;
+ }
+ return AST_FORMAT_CMP_NOT_EQUAL;
+}
+
+#define DETERMINE_JOINT(joint, attr1, attr2, field) (joint->field = (attr1 && attr1->field) ? attr1->field : (attr2 && attr2->field) ? attr2->field : 0)
+
+static struct ast_format *h263_getjoint(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct ast_format *cloned;
+ struct h263_attr *attr, *attr1, *attr2;
+
+ cloned = ast_format_clone(format1);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ attr1 = ast_format_get_attribute_data(format1);
+ attr2 = ast_format_get_attribute_data(format2);
+
+ DETERMINE_JOINT(attr, attr1, attr2, SQCIF);
+ DETERMINE_JOINT(attr, attr1, attr2, QCIF);
+ DETERMINE_JOINT(attr, attr1, attr2, CIF);
+ DETERMINE_JOINT(attr, attr1, attr2, CIF4);
+ DETERMINE_JOINT(attr, attr1, attr2, CIF16);
+ DETERMINE_JOINT(attr, attr1, attr2, VGA);
+ DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_XMAX);
+ DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_YMAX);
+ DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_MPI);
+ DETERMINE_JOINT(attr, attr1, attr2, F);
+ DETERMINE_JOINT(attr, attr1, attr2, I);
+ DETERMINE_JOINT(attr, attr1, attr2, J);
+ DETERMINE_JOINT(attr, attr1, attr2, T);
+ DETERMINE_JOINT(attr, attr1, attr2, K);
+ DETERMINE_JOINT(attr, attr1, attr2, N);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB1);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB2);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB3);
+ DETERMINE_JOINT(attr, attr1, attr2, P_SUB4);
+ DETERMINE_JOINT(attr, attr1, attr2, PAR_WIDTH);
+ DETERMINE_JOINT(attr, attr1, attr2, PAR_HEIGHT);
+ DETERMINE_JOINT(attr, attr1, attr2, BPP);
+ DETERMINE_JOINT(attr, attr1, attr2, HRD);
+
+ return cloned;
+}
+
+static struct ast_format *h263_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
{
char *attribs = ast_strdupa(attributes), *attrib;
+ struct ast_format *cloned;
+ struct h263_attr *attr;
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
while ((attrib = strsep(&attribs, ";"))) {
unsigned int val, val2 = 0, val3 = 0, val4 = 0;
if (sscanf(attrib, "SQCIF=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_SQCIF] = val;
+ attr->SQCIF = val;
} else if (sscanf(attrib, "QCIF=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_QCIF] = val;
+ attr->QCIF = val;
} else if (sscanf(attrib, "CIF=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_CIF] = val;
+ attr->CIF = val;
} else if (sscanf(attrib, "CIF4=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_CIF4] = val;
+ attr->CIF4 = val;
} else if (sscanf(attrib, "CIF16=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_CIF16] = val;
+ attr->CIF16 = val;
} else if (sscanf(attrib, "VGA=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_VGA] = val;
+ attr->VGA = val;
} else if (sscanf(attrib, "CUSTOM=%30u,%30u,%30u", &val, &val2, &val3) == 3) {
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX] = val;
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX] = val2;
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI] = val3;
+ attr->CUSTOM_XMAX = val;
+ attr->CUSTOM_YMAX = val2;
+ attr->CUSTOM_MPI = val3;
} else if (sscanf(attrib, "F=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_F] = val;
+ attr->F = val;
} else if (sscanf(attrib, "I=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_I] = val;
+ attr->I = val;
} else if (sscanf(attrib, "J=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_J] = val;
+ attr->J = val;
} else if (sscanf(attrib, "T=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_T] = val;
+ attr->T = val;
} else if (sscanf(attrib, "K=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_K] = val;
+ attr->K = val;
} else if (sscanf(attrib, "N=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_N] = val;
+ attr->N = val;
} else if (sscanf(attrib, "PAR=%30u:%30u", &val, &val2) == 2) {
- format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH] = val;
- format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT] = val2;
+ attr->PAR_WIDTH = val;
+ attr->PAR_HEIGHT = val2;
} else if (sscanf(attrib, "BPP=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_BPP] = val;
+ attr->BPP = val;
} else if (sscanf(attrib, "HRD=%30u", &val) == 1) {
- format_attr->format_attr[H263_ATTR_KEY_HRD] = val;
+ attr->HRD = val;
} else if (sscanf(attrib, "P=%30u,%30u,%30u,%30u", &val, &val2, &val3, &val4) > 0) {
- format_attr->format_attr[H263_ATTR_KEY_P_SUB1] = val;
- format_attr->format_attr[H263_ATTR_KEY_P_SUB2] = val2;
- format_attr->format_attr[H263_ATTR_KEY_P_SUB3] = val3;
- format_attr->format_attr[H263_ATTR_KEY_P_SUB4] = val4;
+ attr->P_SUB1 = val;
+ attr->P_SUB2 = val2;
+ attr->P_SUB3 = val3;
+ attr->P_SUB4 = val4;
}
}
- return 0;
+ return cloned;
}
-/*! \brief Helper function which converts a key enum into a string value for SDP */
-static const char *h263_attr_key_to_str(enum h263_attr_keys key, const struct ast_format_attr *format_attr)
+static void h263_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- switch (key) {
- case H263_ATTR_KEY_SQCIF:
- return format_attr->format_attr[key] ? "SQCIF" : NULL;
- case H263_ATTR_KEY_QCIF:
- return format_attr->format_attr[key] ? "QCIF" : NULL;
- case H263_ATTR_KEY_CIF:
- return format_attr->format_attr[key] ? "CIF" : NULL;
- case H263_ATTR_KEY_CIF4:
- return format_attr->format_attr[key] ? "CIF4" : NULL;
- case H263_ATTR_KEY_CIF16:
- return format_attr->format_attr[key] ? "CIF16" : NULL;
- case H263_ATTR_KEY_VGA:
- return format_attr->format_attr[key] ? "VGA" : NULL;
- case H263_ATTR_KEY_F:
- return "F";
- case H263_ATTR_KEY_I:
- return "I";
- case H263_ATTR_KEY_J:
- return "J";
- case H263_ATTR_KEY_T:
- return "T";
- case H263_ATTR_KEY_K:
- return "K";
- case H263_ATTR_KEY_N:
- return "N";
- case H263_ATTR_KEY_BPP:
- return "BPP";
- case H263_ATTR_KEY_HRD:
- return "HRD";
- case H263_ATTR_KEY_CUSTOM_XMAX:
- case H263_ATTR_KEY_CUSTOM_YMAX:
- case H263_ATTR_KEY_CUSTOM_MPI:
- case H263_ATTR_KEY_P_SUB1:
- case H263_ATTR_KEY_P_SUB2:
- case H263_ATTR_KEY_P_SUB3:
- case H263_ATTR_KEY_P_SUB4:
- case H263_ATTR_KEY_PAR_WIDTH:
- case H263_ATTR_KEY_PAR_HEIGHT:
- case H263_ATTR_KEY_END:
- default:
- return NULL;
+ struct h263_attr *attr = ast_format_get_attribute_data(format);
+
+ if (!attr) {
+ return;
}
- return NULL;
-}
+ ast_str_append(str, 0, "a=fmtp:%u SQCIF=%u;QCIF=%u;CIF=%u;CIF4=%u;CIF16=%u;VGA=%u;F=%u;I=%u;J=%u;T=%u;K=%u;N=%u;BPP=%u;HRD=%u",
+ payload, attr->SQCIF, attr->QCIF, attr->CIF, attr->CIF4, attr->CIF16, attr->VGA, attr->F, attr->I, attr->J,
+ attr->T, attr->K, attr->N, attr->BPP, attr->HRD);
-static void h263_format_attr_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
-{
- int i, added = 0;
-
- for (i = H263_ATTR_KEY_SQCIF; i < H263_ATTR_KEY_END; i++) {
- const char *name;
-
- if (i == H263_ATTR_KEY_CUSTOM_XMAX) {
- if (!format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX] || !format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX] ||
- !format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]) {
- continue;
- }
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u CUSTOM=%u,%u,%u", payload, format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX],
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX], format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";CUSTOM=%u,%u,%u", format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX],
- format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX], format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]);
- }
- } else if (i == H263_ATTR_KEY_PAR_WIDTH) {
- if (!format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH] || !format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]) {
- continue;
- }
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u PAR=%u:%u", payload, format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH],
- format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";PAR=%u:%u", format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH],
- format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]);
- }
- } else if (i == H263_ATTR_KEY_P_SUB1) {
- if (!format_attr->format_attr[H263_ATTR_KEY_P_SUB1]) {
- continue;
- }
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u P=%u", payload, format_attr->format_attr[H263_ATTR_KEY_P_SUB1]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";P=%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB1]);
- }
-
- if (format_attr->format_attr[H263_ATTR_KEY_P_SUB2]) {
- ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB2]);
- }
- if (format_attr->format_attr[H263_ATTR_KEY_P_SUB3]) {
- ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB3]);
- }
- if (format_attr->format_attr[H263_ATTR_KEY_P_SUB4]) {
- ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB4]);
- }
-
- } else if ((name = h263_attr_key_to_str(i, format_attr))) {
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u %s=%u", payload, name, format_attr->format_attr[i]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";%s=%u", name, format_attr->format_attr[i]);
- }
- }
+ if (attr->CUSTOM_XMAX && attr->CUSTOM_YMAX && attr->CUSTOM_MPI) {
+ ast_str_append(str, 0, ";CUSTOM=%u,%u,%u", attr->CUSTOM_XMAX, attr->CUSTOM_YMAX, attr->CUSTOM_MPI);
}
- if (added) {
- ast_str_append(str, 0, "\r\n");
+ if (attr->PAR_WIDTH && attr->PAR_HEIGHT) {
+ ast_str_append(str, 0, ";PAR=%u:%u", attr->PAR_WIDTH, attr->PAR_HEIGHT);
}
+ if (attr->P_SUB1) {
+ ast_str_append(str, 0, ";P=%u", attr->P_SUB1);
+ if (attr->P_SUB2) {
+ ast_str_append(str, 0, ",%u", attr->P_SUB2);
+ }
+ if (attr->P_SUB3) {
+ ast_str_append(str, 0, ",%u", attr->P_SUB3);
+ }
+ if (attr->P_SUB4) {
+ ast_str_append(str, 0, ",%u", attr->P_SUB4);
+ }
+ }
+
+ ast_str_append(str, 0, "\r\n");
+
return;
}
-static struct ast_format_attr_interface h263_format_attr_interface = {
- .id = AST_FORMAT_H263,
- .format_attr_get_joint = h263_format_attr_get_joint,
- .format_attr_sdp_parse = h263_format_attr_sdp_parse,
- .format_attr_sdp_generate = h263_format_attr_sdp_generate,
-};
-
-static struct ast_format_attr_interface h263p_format_attr_interface = {
- .id = AST_FORMAT_H263_PLUS,
- .format_attr_get_joint = h263_format_attr_get_joint,
- .format_attr_sdp_parse = h263_format_attr_sdp_parse,
- .format_attr_sdp_generate = h263_format_attr_sdp_generate,
+static struct ast_format_interface h263_interface = {
+ .format_destroy = h263_destroy,
+ .format_clone = h263_clone,
+ .format_cmp = h263_cmp,
+ .format_get_joint = h263_getjoint,
+ .format_parse_sdp_fmtp = h263_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = h263_generate_sdp_fmtp,
};
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&h263_format_attr_interface);
- ast_format_attr_unreg_interface(&h263p_format_attr_interface);
-
return 0;
}
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&h263_format_attr_interface)) {
+ if (ast_format_interface_register("h263", &h263_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
- if (ast_format_attr_reg_interface(&h263p_format_attr_interface)) {
- ast_format_attr_unreg_interface(&h263_format_attr_interface);
+ if (ast_format_interface_register("h263p", &h263_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
diff --git a/res/res_format_attr_h264.c b/res/res_format_attr_h264.c
index 2bd47e025..81784bb48 100644
--- a/res/res_format_attr_h264.c
+++ b/res/res_format_attr_h264.c
@@ -50,266 +50,284 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
* H264_MAX_SPS_PPS_SIZE */
#define H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "15"
-enum h264_attr_keys {
- H264_ATTR_KEY_PROFILE_IDC,
- H264_ATTR_KEY_PROFILE_IOP,
- H264_ATTR_KEY_LEVEL,
- H264_ATTR_KEY_MAX_MBPS,
- H264_ATTR_KEY_MAX_FS,
- H264_ATTR_KEY_MAX_CPB,
- H264_ATTR_KEY_MAX_DPB,
- H264_ATTR_KEY_MAX_BR,
- H264_ATTR_KEY_MAX_SMBPS,
- H264_ATTR_KEY_MAX_FPS,
- H264_ATTR_KEY_REDUNDANT_PIC_CAP,
- H264_ATTR_KEY_PARAMETER_ADD,
- H264_ATTR_KEY_PACKETIZATION_MODE,
- H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH,
- H264_ATTR_KEY_SPROP_DEINT_BUF_REQ,
- H264_ATTR_KEY_DEINT_BUF_CAP,
- H264_ATTR_KEY_SPROP_INIT_BUF_TIME,
- H264_ATTR_KEY_SPROP_MAX_DON_DIFF,
- H264_ATTR_KEY_MAX_RCMD_NALU_SIZE,
- H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED,
- H264_ATTR_KEY_SPS_LEN,
- H264_ATTR_KEY_PPS_LEN,
- H264_ATTR_KEY_SPS,
- H264_ATTR_KEY_PPS = H264_ATTR_KEY_SPS + H264_MAX_SPS_PPS_SIZE,
- H264_ATTR_KEY_END = H264_ATTR_KEY_PPS + H264_MAX_SPS_PPS_SIZE,
+struct h264_attr {
+ unsigned int PROFILE_IDC;
+ unsigned int PROFILE_IOP;
+ unsigned int LEVEL;
+ unsigned int MAX_MBPS;
+ unsigned int MAX_FS;
+ unsigned int MAX_CPB;
+ unsigned int MAX_DPB;
+ unsigned int MAX_BR;
+ unsigned int MAX_SMBPS;
+ unsigned int MAX_FPS;
+ unsigned int REDUNDANT_PIC_CAP;
+ unsigned int PARAMETER_ADD;
+ unsigned int PACKETIZATION_MODE;
+ unsigned int SPROP_INTERLEAVING_DEPTH;
+ unsigned int SPROP_DEINT_BUF_REQ;
+ unsigned int DEINT_BUF_CAP;
+ unsigned int SPROP_INIT_BUF_TIME;
+ unsigned int SPROP_MAX_DON_DIFF;
+ unsigned int MAX_RCMD_NALU_SIZE;
+ unsigned int LEVEL_ASYMMETRY_ALLOWED;
+ char SPS[H264_MAX_SPS_PPS_SIZE];
+ char PPS[H264_MAX_SPS_PPS_SIZE];
};
-static enum ast_format_cmp_res h264_format_attr_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
+static void h264_destroy(struct ast_format *format)
{
- if (!fattr1->format_attr[H264_ATTR_KEY_PROFILE_IDC] || !fattr2->format_attr[H264_ATTR_KEY_PROFILE_IDC] ||
- (fattr1->format_attr[H264_ATTR_KEY_PROFILE_IDC] == fattr2->format_attr[H264_ATTR_KEY_PROFILE_IDC])) {
+ struct h264_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int h264_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct h264_attr *original = ast_format_get_attribute_data(src);
+ struct h264_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static enum ast_format_cmp_res h264_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct h264_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct h264_attr *attr2 = ast_format_get_attribute_data(format2);
+
+ if (!attr1 || !attr1->PROFILE_IDC || !attr2 || !attr2->PROFILE_IDC ||
+ (attr1->PROFILE_IDC == attr2->PROFILE_IDC)) {
return AST_FORMAT_CMP_EQUAL;
}
return AST_FORMAT_CMP_NOT_EQUAL;
}
-static int h264_format_attr_get_joint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
+#define DETERMINE_JOINT(joint, attr1, attr2, field) (joint->field = (attr1 && attr1->field) ? attr1->field : (attr2 && attr2->field) ? attr2->field : 0)
+
+static struct ast_format *h264_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- int i;
+ struct ast_format *cloned;
+ struct h264_attr *attr, *attr1, *attr2;
+
+ cloned = ast_format_clone(format1);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ attr1 = ast_format_get_attribute_data(format1);
+ attr2 = ast_format_get_attribute_data(format2);
+
+ DETERMINE_JOINT(attr, attr1, attr2, PROFILE_IDC);
+ DETERMINE_JOINT(attr, attr1, attr2, PROFILE_IOP);
+ DETERMINE_JOINT(attr, attr1, attr2, LEVEL);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_MBPS);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_FS);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_CPB);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_DPB);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_BR);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_SMBPS);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_FPS);
+ DETERMINE_JOINT(attr, attr1, attr2, REDUNDANT_PIC_CAP);
+ DETERMINE_JOINT(attr, attr1, attr2, PARAMETER_ADD);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_INTERLEAVING_DEPTH);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_DEINT_BUF_REQ);
+ DETERMINE_JOINT(attr, attr1, attr2, DEINT_BUF_CAP);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_INIT_BUF_TIME);
+ DETERMINE_JOINT(attr, attr1, attr2, SPROP_MAX_DON_DIFF);
+ DETERMINE_JOINT(attr, attr1, attr2, MAX_RCMD_NALU_SIZE);
+ DETERMINE_JOINT(attr, attr1, attr2, LEVEL_ASYMMETRY_ALLOWED);
+ DETERMINE_JOINT(attr, attr1, attr2, PACKETIZATION_MODE);
+
+ if (attr1 && !ast_strlen_zero(attr1->SPS)) {
+ ast_copy_string(attr->SPS, attr1->SPS, sizeof(attr->SPS));
+ } else if (attr2 && !ast_strlen_zero(attr2->SPS)) {
+ ast_copy_string(attr->SPS, attr1->SPS, sizeof(attr->SPS));
+ }
- for (i = H264_ATTR_KEY_PROFILE_IDC; i < H264_ATTR_KEY_END; i++) {
- result->format_attr[i] = fattr1->format_attr[i] ? fattr1->format_attr[i] : fattr2->format_attr[i];
+ if (attr1 && !ast_strlen_zero(attr1->PPS)) {
+ ast_copy_string(attr->PPS, attr1->PPS, sizeof(attr->PPS));
+ } else if (attr2 && !ast_strlen_zero(attr2->PPS)) {
+ ast_copy_string(attr->PPS, attr1->PPS, sizeof(attr->PPS));
}
- return 0;
+ return cloned;
}
-static int h264_format_attr_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static struct ast_format *h264_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
{
char *attribs = ast_strdupa(attributes), *attrib;
+ struct ast_format *cloned;
+ struct h264_attr *attr;
- format_attr->format_attr[H264_ATTR_KEY_REDUNDANT_PIC_CAP] = H264_ATTR_KEY_UNSET;
- format_attr->format_attr[H264_ATTR_KEY_PARAMETER_ADD] = H264_ATTR_KEY_UNSET;
- format_attr->format_attr[H264_ATTR_KEY_PACKETIZATION_MODE] = H264_ATTR_KEY_UNSET;
- format_attr->format_attr[H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED] = H264_ATTR_KEY_UNSET;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ attr->REDUNDANT_PIC_CAP = H264_ATTR_KEY_UNSET;
+ attr->PARAMETER_ADD = H264_ATTR_KEY_UNSET;
+ attr->PACKETIZATION_MODE = H264_ATTR_KEY_UNSET;
+ attr->LEVEL_ASYMMETRY_ALLOWED = H264_ATTR_KEY_UNSET;
while ((attrib = strsep(&attribs, ";"))) {
unsigned int val;
unsigned long int val2;
- char sps[H264_MAX_SPS_PPS_SIZE], pps[H264_MAX_SPS_PPS_SIZE];
if (sscanf(attrib, "profile-level-id=%lx", &val2) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC] = ((val2 >> 16) & 0xFF);
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP] = ((val2 >> 8) & 0xFF);
- format_attr->format_attr[H264_ATTR_KEY_LEVEL] = (val2 & 0xFF);
- } else if (sscanf(attrib, "sprop-parameter-sets=%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "[^','],%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "s", sps, pps) == 2) {
+ attr->PROFILE_IDC = ((val2 >> 16) & 0xFF);
+ attr->PROFILE_IOP = ((val2 >> 8) & 0xFF);
+ attr->LEVEL = (val2 & 0xFF);
+ } else if (sscanf(attrib, "sprop-parameter-sets=%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "[^','],%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "s", attr->SPS, attr->PPS) == 2) {
/* XXX sprop-parameter-sets can actually be of unlimited length. This may need to be addressed later. */
- unsigned char spsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, }, ppsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, };
- int i;
-
- ast_base64decode(spsdecoded, sps, sizeof(spsdecoded));
- ast_base64decode(ppsdecoded, pps, sizeof(ppsdecoded));
-
- format_attr->format_attr[H264_ATTR_KEY_SPS_LEN] = 0;
- format_attr->format_attr[H264_ATTR_KEY_PPS_LEN] = 0;
-
- for (i = 0; i < H264_MAX_SPS_PPS_SIZE; i++) {
- if (spsdecoded[i]) {
- format_attr->format_attr[H264_ATTR_KEY_SPS + i] = spsdecoded[i];
- format_attr->format_attr[H264_ATTR_KEY_SPS_LEN]++;
- }
- if (ppsdecoded[i]) {
- format_attr->format_attr[H264_ATTR_KEY_PPS + i] = ppsdecoded[i];
- format_attr->format_attr[H264_ATTR_KEY_PPS_LEN]++;
- }
- }
} else if (sscanf(attrib, "max-mbps=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_MBPS] = val;
+ attr->MAX_MBPS = val;
} else if (sscanf(attrib, "max-fs=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_FS] = val;
+ attr->MAX_FS = val;
} else if (sscanf(attrib, "max-cpb=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_CPB] = val;
+ attr->MAX_CPB = val;
} else if (sscanf(attrib, "max-dpb=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_DPB] = val;
+ attr->MAX_DPB = val;
} else if (sscanf(attrib, "max-br=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_BR] = val;
+ attr->MAX_BR = val;
} else if (sscanf(attrib, "max-smbps=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_SMBPS] = val;
+ attr->MAX_SMBPS = val;
} else if (sscanf(attrib, "max-fps=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_FPS] = val;
+ attr->MAX_FPS = val;
} else if (sscanf(attrib, "redundant-pic-cap=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_REDUNDANT_PIC_CAP] = val;
+ attr->REDUNDANT_PIC_CAP = val;
} else if (sscanf(attrib, "parameter-add=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_PARAMETER_ADD] = val;
+ attr->PARAMETER_ADD = val;
} else if (sscanf(attrib, "packetization-mode=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_PACKETIZATION_MODE] = val;
+ attr->PACKETIZATION_MODE = val;
} else if (sscanf(attrib, "sprop-interleaving-depth=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH] = val;
+ attr->SPROP_INTERLEAVING_DEPTH = val;
} else if (sscanf(attrib, "sprop-deint-buf-req=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_DEINT_BUF_REQ] = val;
+ attr->SPROP_DEINT_BUF_REQ = val;
} else if (sscanf(attrib, "deint-buf-cap=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_DEINT_BUF_CAP] = val;
+ attr->DEINT_BUF_CAP = val;
} else if (sscanf(attrib, "sprop-init-buf-time=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_INIT_BUF_TIME] = val;
+ attr->SPROP_INIT_BUF_TIME = val;
} else if (sscanf(attrib, "sprop-max-don-diff=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_SPROP_MAX_DON_DIFF] = val;
+ attr->SPROP_MAX_DON_DIFF = val;
} else if (sscanf(attrib, "max-rcmd-nalu-size=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_MAX_RCMD_NALU_SIZE] = val;
+ attr->MAX_RCMD_NALU_SIZE = val;
} else if (sscanf(attrib, "level-asymmetry-allowed=%30u", &val) == 1) {
- format_attr->format_attr[H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED] = val;
+ attr->LEVEL_ASYMMETRY_ALLOWED = val;
}
}
- return 0;
+ return cloned;
}
-/*! \brief Helper function which converts a key enum into a string value for SDP */
-static const char *h264_attr_key_to_str(enum h264_attr_keys key)
+#define APPEND_IF_NOT_H264_UNSET(field, str, name) do { \
+ if (field != H264_ATTR_KEY_UNSET) { \
+ if (added) { \
+ ast_str_append(str, 0, ";"); \
+ } else { \
+ added = 1; \
+ } \
+ ast_str_append(str, 0, "%s=%u", name, field); \
+ } \
+} while (0)
+
+#define APPEND_IF_NONZERO(field, str, name) do { \
+ if (field) { \
+ if (added) { \
+ ast_str_append(str, 0, ";"); \
+ } else { \
+ added = 1; \
+ } \
+ ast_str_append(str, 0, "%s=%u", name, field); \
+ } \
+} while (0)
+
+static void h264_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- switch (key) {
- case H264_ATTR_KEY_MAX_MBPS:
- return "max-mbps";
- case H264_ATTR_KEY_MAX_FS:
- return "max-fs";
- case H264_ATTR_KEY_MAX_CPB:
- return "max-cpb";
- case H264_ATTR_KEY_MAX_DPB:
- return "max-dpb";
- case H264_ATTR_KEY_MAX_BR:
- return "max-br";
- case H264_ATTR_KEY_MAX_SMBPS:
- return "max-smbps";
- case H264_ATTR_KEY_MAX_FPS:
- return "max-fps";
- case H264_ATTR_KEY_REDUNDANT_PIC_CAP:
- return "redundant-pic-cap";
- case H264_ATTR_KEY_PARAMETER_ADD:
- return "parameter-add";
- case H264_ATTR_KEY_PACKETIZATION_MODE:
- return "packetization-mode";
- case H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH:
- return "sprop-interleaving-depth";
- case H264_ATTR_KEY_SPROP_DEINT_BUF_REQ:
- return "sprop-deint-buf-req";
- case H264_ATTR_KEY_DEINT_BUF_CAP:
- return "deint-buf-cap";
- case H264_ATTR_KEY_SPROP_INIT_BUF_TIME:
- return "sprop-init-buf-time";
- case H264_ATTR_KEY_SPROP_MAX_DON_DIFF:
- return "sprop-max-don-diff";
- case H264_ATTR_KEY_MAX_RCMD_NALU_SIZE:
- return "max-rcmd-nalu-size";
- case H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED:
- return "level-asymmetry-allowed";
- default:
- return NULL;
- }
+ struct h264_attr *attr = ast_format_get_attribute_data(format);
+ int added = 0;
- return NULL;
-}
-
-/*! \brief Helper function which determines if the value of an attribute can be placed into the SDP */
-static int h264_attr_key_addable(const struct ast_format_attr *format_attr, enum h264_attr_keys key)
-{
- switch (key) {
- case H264_ATTR_KEY_REDUNDANT_PIC_CAP:
- case H264_ATTR_KEY_PARAMETER_ADD:
- case H264_ATTR_KEY_PACKETIZATION_MODE:
- case H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED:
- return (format_attr->format_attr[key] != H264_ATTR_KEY_UNSET) ? 1 : 0;
- default:
- return format_attr->format_attr[key] ? 1 : 0;
+ if (!attr) {
+ return;
}
- return 1;
-}
+ ast_str_append(str, 0, "a=fmtp:%u ", payload);
+
+ APPEND_IF_NONZERO(attr->MAX_MBPS, str, "max-mbps");
+ APPEND_IF_NONZERO(attr->MAX_FS, str, "max-fs");
+ APPEND_IF_NONZERO(attr->MAX_CPB, str, "max-cpb");
+ APPEND_IF_NONZERO(attr->MAX_DPB, str, "max-dpb");
+ APPEND_IF_NONZERO(attr->MAX_BR, str, "max-br");
+ APPEND_IF_NONZERO(attr->MAX_SMBPS, str, "max-smbps");
+ APPEND_IF_NONZERO(attr->MAX_FPS, str, "max-fps");
+ APPEND_IF_NONZERO(attr->SPROP_INTERLEAVING_DEPTH, str, "sprop-interleaving-depth");
+ APPEND_IF_NONZERO(attr->SPROP_DEINT_BUF_REQ, str, "sprop-deint-buf-req");
+ APPEND_IF_NONZERO(attr->DEINT_BUF_CAP, str, "deint-buf-cap");
+ APPEND_IF_NONZERO(attr->SPROP_INIT_BUF_TIME, str, "sprop-init-buf-time");
+ APPEND_IF_NONZERO(attr->SPROP_MAX_DON_DIFF, str, "sprop-max-don-diff");
+ APPEND_IF_NONZERO(attr->MAX_RCMD_NALU_SIZE, str, "max-rcmd-nalu-size");
+
+ APPEND_IF_NOT_H264_UNSET(attr->REDUNDANT_PIC_CAP, str, "redundant-pic-cap");
+ APPEND_IF_NOT_H264_UNSET(attr->PARAMETER_ADD, str, "parameter-add");
+ APPEND_IF_NOT_H264_UNSET(attr->PACKETIZATION_MODE, str, "packetization-mode");
+ APPEND_IF_NOT_H264_UNSET(attr->LEVEL_ASYMMETRY_ALLOWED, str, "level-asymmetry-allowed");
+
+ if (attr->PROFILE_IDC && attr->PROFILE_IOP && attr->LEVEL) {
+ if (added) {
+ ast_str_append(str, 0, ";");
+ } else {
+ added = 1;
+ }
+ ast_str_append(str, 0, "profile-level-id=%02X%02X%02X", attr->PROFILE_IDC, attr->PROFILE_IOP, attr->LEVEL);
+ }
-static void h264_format_attr_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
-{
- int i, added = 0;
-
- for (i = H264_ATTR_KEY_PROFILE_IDC; i < H264_ATTR_KEY_END; i++) {
- const char *name;
-
- if (i == H264_ATTR_KEY_SPS && format_attr->format_attr[H264_ATTR_KEY_SPS] && format_attr->format_attr[H264_ATTR_KEY_PPS]) {
- unsigned char spsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, }, ppsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, };
- int pos;
- char sps[H264_MAX_SPS_PPS_SIZE], pps[H264_MAX_SPS_PPS_SIZE];
-
- for (pos = 0; pos < H264_MAX_SPS_PPS_SIZE; pos++) {
- spsdecoded[pos] = format_attr->format_attr[H264_ATTR_KEY_SPS + pos];
- ppsdecoded[pos] = format_attr->format_attr[H264_ATTR_KEY_PPS + pos];
- }
-
- ast_base64encode(sps, spsdecoded, format_attr->format_attr[H264_ATTR_KEY_SPS_LEN], H264_MAX_SPS_PPS_SIZE);
- ast_base64encode(pps, ppsdecoded, format_attr->format_attr[H264_ATTR_KEY_PPS_LEN], H264_MAX_SPS_PPS_SIZE);
-
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u sprop-parameter-sets=%s,%s", payload, sps, pps);
- added = 1;
- } else {
- ast_str_append(str, 0, ";sprop-parameter-sets=%s,%s", sps, pps);
- }
- } else if (i == H264_ATTR_KEY_PROFILE_IDC && format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC] &&
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP] && format_attr->format_attr[H264_ATTR_KEY_LEVEL]) {
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u profile-level-id=%02X%02X%02X", payload, format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP], format_attr->format_attr[H264_ATTR_KEY_LEVEL]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";profile-level-id=%02X%02X%02X", format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
- format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP], format_attr->format_attr[H264_ATTR_KEY_LEVEL]);
- }
- } else if ((name = h264_attr_key_to_str(i)) && h264_attr_key_addable(format_attr, i)) {
- if (!added) {
- ast_str_append(str, 0, "a=fmtp:%u %s=%u", payload, name, format_attr->format_attr[i]);
- added = 1;
- } else {
- ast_str_append(str, 0, ";%s=%u", name, format_attr->format_attr[i]);
- }
+ if (!ast_strlen_zero(attr->SPS) && !ast_strlen_zero(attr->PPS)) {
+ if (added) {
+ ast_str_append(str, 0, ";");
+ } else {
+ added = 1;
}
+ ast_str_append(str, 0, ";sprop-parameter-sets=%s,%s", attr->SPS, attr->PPS);
}
-
- if (added) {
+
+ if (!added) {
+ ast_str_reset(*str);
+ } else {
ast_str_append(str, 0, "\r\n");
}
return;
}
-static struct ast_format_attr_interface h264_format_attr_interface = {
- .id = AST_FORMAT_H264,
- .format_attr_cmp = h264_format_attr_cmp,
- .format_attr_get_joint = h264_format_attr_get_joint,
- .format_attr_sdp_parse = h264_format_attr_sdp_parse,
- .format_attr_sdp_generate = h264_format_attr_sdp_generate,
+static struct ast_format_interface h264_interface = {
+ .format_destroy = h264_destroy,
+ .format_clone = h264_clone,
+ .format_cmp = h264_cmp,
+ .format_get_joint = h264_getjoint,
+ .format_parse_sdp_fmtp = h264_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = h264_generate_sdp_fmtp,
};
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&h264_format_attr_interface);
-
return 0;
}
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&h264_format_attr_interface)) {
+ if (ast_format_interface_register("h264", &h264_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
diff --git a/res/res_format_attr_opus.c b/res/res_format_attr_opus.c
index 3fa7dcef3..9e84982fb 100644
--- a/res/res_format_attr_opus.c
+++ b/res/res_format_attr_opus.c
@@ -51,12 +51,44 @@ struct opus_attr {
unsigned int spropstereo; /* Default 0 */
};
-static int opus_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static void opus_destroy(struct ast_format *format)
{
- struct opus_attr *attr = (struct opus_attr *) format_attr;
+ struct opus_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int opus_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct opus_attr *original = ast_format_get_attribute_data(src);
+ struct opus_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static struct ast_format *opus_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *cloned;
+ struct opus_attr *attr;
const char *kvp;
unsigned int val;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
if ((kvp = strstr(attributes, "maxplaybackrate")) && sscanf(kvp, "maxplaybackrate=%30u", &val) == 1) {
attr->maxplayrate = val;
}
@@ -91,9 +123,13 @@ static int opus_sdp_parse(struct ast_format_attr *format_attr, const char *attri
return 0;
}
-static void opus_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+static void opus_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct opus_attr *attr = (struct opus_attr *) format_attr;
+ struct opus_attr *attr = ast_format_get_attribute_data(format);
+
+ if (!attr) {
+ return;
+ }
/* FIXME should we only generate attributes that were explicitly set? */
ast_str_append(str, 0,
@@ -120,114 +156,18 @@ static void opus_sdp_generate(const struct ast_format_attr *format_attr, unsigne
);
}
-static int opus_get_val(const struct ast_format_attr *fattr, int key, void *result)
+static struct ast_format *opus_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- const struct opus_attr *attr = (struct opus_attr *) fattr;
- int *val = result;
-
- switch (key) {
- case OPUS_ATTR_KEY_MAX_BITRATE:
- *val = attr->maxbitrate;
- break;
- case OPUS_ATTR_KEY_MAX_PLAYRATE:
- *val = attr->maxplayrate;
- break;
- case OPUS_ATTR_KEY_MINPTIME:
- *val = attr->minptime;
- break;
- case OPUS_ATTR_KEY_STEREO:
- *val = attr->stereo;
- break;
- case OPUS_ATTR_KEY_CBR:
- *val = attr->cbr;
- break;
- case OPUS_ATTR_KEY_FEC:
- *val = attr->fec;
- break;
- case OPUS_ATTR_KEY_DTX:
- *val = attr->dtx;
- break;
- case OPUS_ATTR_KEY_SPROP_CAPTURE_RATE:
- *val = attr->spropmaxcapturerate;
- break;
- case OPUS_ATTR_KEY_SPROP_STEREO:
- *val = attr->spropstereo;
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
- return -1;
- }
- return 0;
-}
+ struct opus_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct opus_attr *attr2 = ast_format_get_attribute_data(format2);
+ struct ast_format *jointformat;
+ struct opus_attr *attr_res;
-static int opus_isset(const struct ast_format_attr *fattr, va_list ap)
-{
- enum opus_attr_keys key;
- const struct opus_attr *attr = (struct opus_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case OPUS_ATTR_KEY_MAX_BITRATE:
- if (attr->maxbitrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_MAX_PLAYRATE:
- if (attr->maxplayrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_MINPTIME:
- if (attr->minptime != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_STEREO:
- if (attr->stereo != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_CBR:
- if (attr->cbr != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_FEC:
- if (attr->fec != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_DTX:
- if (attr->dtx != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_SPROP_CAPTURE_RATE:
- if (attr->spropmaxcapturerate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case OPUS_ATTR_KEY_SPROP_STEREO:
- if (attr->spropstereo != (va_arg(ap, int))) {
- return -1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- return -1;
- }
+ jointformat = ast_format_clone(format1);
+ if (!jointformat) {
+ return NULL;
}
- return 0;
-}
-static int opus_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
-{
- struct opus_attr *attr1 = (struct opus_attr *) fattr1;
- struct opus_attr *attr2 = (struct opus_attr *) fattr2;
- struct opus_attr *attr_res = (struct opus_attr *) result;
- int joint = 0;
+ attr_res = ast_format_get_attribute_data(jointformat);
/* Only do dtx if both sides want it. DTX is a trade off between
* computational complexity and bandwidth. */
@@ -243,65 +183,64 @@ static int opus_getjoint(const struct ast_format_attr *fattr1, const struct ast_
/* FIXME: do we need to join other attributes as well, e.g., minptime, cbr, etc.? */
- return joint;
+ return jointformat;
}
-static void opus_set(struct ast_format_attr *fattr, va_list ap)
+static struct ast_format *opus_set(const struct ast_format *format, const char *name, const char *value)
{
- enum opus_attr_keys key;
- struct opus_attr *attr = (struct opus_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case OPUS_ATTR_KEY_MAX_BITRATE:
- attr->maxbitrate = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_MAX_PLAYRATE:
- attr->maxplayrate = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_MINPTIME:
- attr->minptime = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_STEREO:
- attr->stereo = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_CBR:
- attr->cbr = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_FEC:
- attr->fec = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_DTX:
- attr->dtx = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_SPROP_CAPTURE_RATE:
- attr->spropmaxcapturerate = (va_arg(ap, int));
- break;
- case OPUS_ATTR_KEY_SPROP_STEREO:
- attr->spropstereo = (va_arg(ap, int));
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- }
+ struct ast_format *cloned;
+ struct opus_attr *attr;
+ unsigned int val;
+
+ if (sscanf(value, "%30u", &val) != 1) {
+ ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
+ value, name);
+ return NULL;
+ }
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
}
+ attr = ast_format_get_attribute_data(cloned);
+
+ if (!strcasecmp(name, "max_bitrate")) {
+ attr->maxbitrate = val;
+ } else if (!strcasecmp(name, "max_playrate")) {
+ attr->maxplayrate = val;
+ } else if (!strcasecmp(name, "minptime")) {
+ attr->minptime = val;
+ } else if (!strcasecmp(name, "stereo")) {
+ attr->stereo = val;
+ } else if (!strcasecmp(name, "cbr")) {
+ attr->cbr = val;
+ } else if (!strcasecmp(name, "fec")) {
+ attr->fec = val;
+ } else if (!strcasecmp(name, "dtx")) {
+ attr->dtx = val;
+ } else if (!strcasecmp(name, "sprop_capture_rate")) {
+ attr->spropmaxcapturerate = val;
+ } else if (!strcasecmp(name, "sprop_stereo")) {
+ attr->spropstereo = val;
+ } else {
+ ast_log(LOG_WARNING, "unknown attribute type %s\n", name);
+ }
+
+ return cloned;
}
-static struct ast_format_attr_interface opus_interface = {
- .id = AST_FORMAT_OPUS,
- .format_attr_get_joint = opus_getjoint,
- .format_attr_set = opus_set,
- .format_attr_isset = opus_isset,
- .format_attr_get_val = opus_get_val,
- .format_attr_sdp_parse = opus_sdp_parse,
- .format_attr_sdp_generate = opus_sdp_generate,
+static struct ast_format_interface opus_interface = {
+ .format_destroy = opus_destroy,
+ .format_clone = opus_clone,
+ .format_get_joint = opus_getjoint,
+ .format_attribute_set = opus_set,
+ .format_parse_sdp_fmtp = opus_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = opus_generate_sdp_fmtp,
};
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&opus_interface)) {
+ if (ast_format_interface_register("opus", &opus_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -310,7 +249,6 @@ static int load_module(void)
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&opus_interface);
return 0;
}
diff --git a/res/res_format_attr_silk.c b/res/res_format_attr_silk.c
index 075570fb5..a46c62099 100644
--- a/res/res_format_attr_silk.c
+++ b/res/res_format_attr_silk.c
@@ -47,11 +47,43 @@ struct silk_attr {
unsigned int packetloss_percentage;
};
-static int silk_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+static void silk_destroy(struct ast_format *format)
{
- struct silk_attr *attr = (struct silk_attr *) format_attr;
+ struct silk_attr *attr = ast_format_get_attribute_data(format);
+
+ ast_free(attr);
+}
+
+static int silk_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct silk_attr *original = ast_format_get_attribute_data(src);
+ struct silk_attr *attr = ast_calloc(1, sizeof(*attr));
+
+ if (!attr) {
+ return -1;
+ }
+
+ if (original) {
+ *attr = *original;
+ }
+
+ ast_format_set_attribute_data(dst, attr);
+
+ return 0;
+}
+
+static struct ast_format *silk_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *cloned;
+ struct silk_attr *attr;
unsigned int val;
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
if (sscanf(attributes, "maxaveragebitrate=%30u", &val) == 1) {
attr->maxbitrate = val;
}
@@ -65,9 +97,13 @@ static int silk_sdp_parse(struct ast_format_attr *format_attr, const char *attri
return 0;
}
-static void silk_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+static void silk_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
{
- struct silk_attr *attr = (struct silk_attr *) format_attr;
+ struct silk_attr *attr = ast_format_get_attribute_data(format);
+
+ if (!attr) {
+ return;
+ }
if ((attr->maxbitrate > 5000) && (attr->maxbitrate < 40000)) {
ast_str_append(str, 0, "a=fmtp:%u maxaveragebitrate=%u\r\n", payload, attr->maxbitrate);
@@ -77,99 +113,40 @@ static void silk_sdp_generate(const struct ast_format_attr *format_attr, unsigne
ast_str_append(str, 0, "a=fmtp:%u useinbandfec=%u\r\n", payload, attr->fec);
}
-static enum ast_format_cmp_res silk_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
+static enum ast_format_cmp_res silk_cmp(const struct ast_format *format1, const struct ast_format *format2)
{
- struct silk_attr *attr1 = (struct silk_attr *) fattr1;
- struct silk_attr *attr2 = (struct silk_attr *) fattr2;
+ struct silk_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct silk_attr *attr2 = ast_format_get_attribute_data(format2);
- if (attr1->samplerate == attr2->samplerate) {
+ if (((!attr1 || !attr1->samplerate) && (!attr2 || !attr2->samplerate)) ||
+ (attr1->samplerate == attr2->samplerate)) {
return AST_FORMAT_CMP_EQUAL;
}
+
return AST_FORMAT_CMP_NOT_EQUAL;
}
-static int silk_get_val(const struct ast_format_attr *fattr, int key, void *result)
+static struct ast_format *silk_getjoint(const struct ast_format *format1, const struct ast_format *format2)
{
- const struct silk_attr *attr = (struct silk_attr *) fattr;
- int *val = result;
-
- switch (key) {
- case SILK_ATTR_KEY_SAMP_RATE:
- *val = attr->samplerate;
- break;
- case SILK_ATTR_KEY_MAX_BITRATE:
- *val = attr->maxbitrate;
- break;
- case SILK_ATTR_KEY_DTX:
- *val = attr->dtx;
- break;
- case SILK_ATTR_KEY_FEC:
- *val = attr->fec;
- break;
- case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
- *val = attr->packetloss_percentage;
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
- return -1;
- }
- return 0;
-}
+ struct silk_attr *attr1 = ast_format_get_attribute_data(format1);
+ struct silk_attr *attr2 = ast_format_get_attribute_data(format2);
+ unsigned int samplerate;
+ struct ast_format *jointformat;
+ struct silk_attr *attr_res;
-static int silk_isset(const struct ast_format_attr *fattr, va_list ap)
-{
- enum silk_attr_keys key;
- const struct silk_attr *attr = (struct silk_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case SILK_ATTR_KEY_SAMP_RATE:
- if (attr->samplerate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_MAX_BITRATE:
- if (attr->maxbitrate != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_DTX:
- if (attr->dtx != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_FEC:
- if (attr->fec != (va_arg(ap, int))) {
- return -1;
- }
- break;
- case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
- if (attr->packetloss_percentage != (va_arg(ap, int))) {
- return -1;
- }
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- return -1;
- }
+ samplerate = attr1->samplerate & attr2->samplerate;
+ /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
+ if (samplerate) {
+ return NULL;
}
- return 0;
-}
-static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
-{
- struct silk_attr *attr1 = (struct silk_attr *) fattr1;
- struct silk_attr *attr2 = (struct silk_attr *) fattr2;
- struct silk_attr *attr_res = (struct silk_attr *) result;
- int joint = -1;
- attr_res->samplerate = attr1->samplerate & attr2->samplerate;
- /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
- if (attr_res->samplerate) {
- joint = 0;
+ jointformat = ast_format_clone(format1);
+ if (!jointformat) {
+ return NULL;
}
+ attr_res = ast_format_get_attribute_data(jointformat);
+ attr_res->samplerate = samplerate;
+
/* Take the lowest max bitrate */
attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
@@ -184,54 +161,58 @@ static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_
/* Use the maximum packetloss percentage between the two attributes. This affects how
* much redundancy is used in the FEC. */
attr_res->packetloss_percentage = MAX(attr1->packetloss_percentage, attr2->packetloss_percentage);
- return joint;
+
+ return jointformat;
}
-static void silk_set(struct ast_format_attr *fattr, va_list ap)
+static struct ast_format *silk_set(const struct ast_format *format, const char *name, const char *value)
{
- enum silk_attr_keys key;
- struct silk_attr *attr = (struct silk_attr *) fattr;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case SILK_ATTR_KEY_SAMP_RATE:
- attr->samplerate = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_MAX_BITRATE:
- attr->maxbitrate = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_DTX:
- attr->dtx = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_FEC:
- attr->fec = (va_arg(ap, int));
- break;
- case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
- attr->packetloss_percentage = (va_arg(ap, int));
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
- }
+ struct ast_format *cloned;
+ struct silk_attr *attr;
+ unsigned int val;
+
+ if (sscanf(value, "%30u", &val) != 1) {
+ ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
+ value, name);
+ return NULL;
+ }
+
+ cloned = ast_format_clone(format);
+ if (!cloned) {
+ return NULL;
+ }
+ attr = ast_format_get_attribute_data(cloned);
+
+ if (!strcasecmp(name, "sample_rate")) {
+ attr->samplerate = val;
+ } else if (!strcasecmp(name, "max_bitrate")) {
+ attr->maxbitrate = val;
+ } else if (!strcasecmp(name, "dtx")) {
+ attr->dtx = val;
+ } else if (!strcasecmp(name, "fec")) {
+ attr->fec = val;
+ } else if (!strcasecmp(name, "packetloss_percentage")) {
+ attr->packetloss_percentage = val;
+ } else {
+ ast_log(LOG_WARNING, "unknown attribute type %s\n", name);
}
+
+ return cloned;
}
-static struct ast_format_attr_interface silk_interface = {
- .id = AST_FORMAT_SILK,
- .format_attr_cmp = silk_cmp,
- .format_attr_get_joint = silk_getjoint,
- .format_attr_set = silk_set,
- .format_attr_isset = silk_isset,
- .format_attr_get_val = silk_get_val,
- .format_attr_sdp_parse = silk_sdp_parse,
- .format_attr_sdp_generate = silk_sdp_generate,
+static struct ast_format_interface silk_interface = {
+ .format_destroy = silk_destroy,
+ .format_clone = silk_clone,
+ .format_cmp = silk_cmp,
+ .format_get_joint = silk_getjoint,
+ .format_attribute_set = silk_set,
+ .format_parse_sdp_fmtp = silk_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = silk_generate_sdp_fmtp,
};
static int load_module(void)
{
- if (ast_format_attr_reg_interface(&silk_interface)) {
+ if (ast_format_interface_register("silk", &silk_interface)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -240,7 +221,6 @@ static int load_module(void)
static int unload_module(void)
{
- ast_format_attr_unreg_interface(&silk_interface);
return 0;
}
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 1d05f0daa..093c846ee 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -131,8 +131,8 @@ static int respawn_time = 20;
struct moh_files_state {
/*! Holds a reference to the MOH class. */
struct mohclass *class;
- struct ast_format origwfmt;
- struct ast_format mohwfmt;
+ struct ast_format *origwfmt;
+ struct ast_format *mohwfmt;
int announcement;
int samples;
int sample_queue;
@@ -170,7 +170,7 @@ struct mohclass {
int total_files;
unsigned int flags;
/*! The format from the MOH source, not applicable to "files" mode */
- struct ast_format format;
+ struct ast_format *format;
/*! The pid of the external application delivering MOH */
int pid;
time_t start;
@@ -188,7 +188,7 @@ struct mohclass {
struct mohdata {
int pipe[2];
- struct ast_format origwfmt;
+ struct ast_format *origwfmt;
struct mohclass *parent;
struct ast_frame f;
AST_LIST_ENTRY(mohdata) list;
@@ -289,10 +289,14 @@ static void moh_files_release(struct ast_channel *chan, void *data)
moh_post_stop(chan);
- ast_format_clear(&state->mohwfmt); /* make sure to clear this format before restoring the original format. */
- if (state->origwfmt.id && ast_set_write_format(chan, &state->origwfmt)) {
- ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", ast_channel_name(chan), ast_getformatname(&state->origwfmt));
+ ao2_ref(state->mohwfmt, -1);
+ state->mohwfmt = NULL; /* make sure to clear this format before restoring the original format */
+ if (state->origwfmt && ast_set_write_format(chan, state->origwfmt)) {
+ ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", ast_channel_name(chan),
+ ast_format_get_name(state->origwfmt));
}
+ ao2_cleanup(state->origwfmt);
+ state->origwfmt = NULL;
state->save_pos = state->pos;
state->announcement = 0;
@@ -405,15 +409,15 @@ static void moh_files_write_format_change(struct ast_channel *chan, void *data)
/* In order to prevent a recursive call to this function as a result
* of setting the moh write format back on the channel. Clear
* the moh write format before setting the write format on the channel.*/
- if (&state->origwfmt.id) {
- struct ast_format tmp;
+ if (state->origwfmt) {
+ struct ast_format *tmp;
- ast_format_copy(&tmp, ast_channel_writeformat(chan));
- if (state->mohwfmt.id) {
- ast_format_clear(&state->origwfmt);
- ast_set_write_format(chan, &state->mohwfmt);
+ tmp = ao2_bump(ast_channel_writeformat(chan));
+ ao2_replace(state->origwfmt, NULL);
+ if (state->mohwfmt) {
+ ast_set_write_format(chan, state->mohwfmt);
}
- ast_format_copy(&state->origwfmt, &tmp);
+ state->origwfmt = tmp;
}
}
@@ -442,8 +446,8 @@ static int moh_files_generator(struct ast_channel *chan, void *data, int len, in
state->samples += f->samples;
state->sample_queue -= f->samples;
- if (ast_format_cmp(&f->subclass.format, &state->mohwfmt) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_format_copy(&state->mohwfmt, &f->subclass.format);
+ if (ast_format_cmp(f->subclass.format, state->mohwfmt) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ao2_replace(state->mohwfmt, f->subclass.format);
}
res = ast_write(chan, f);
ast_frfree(f);
@@ -486,8 +490,9 @@ static void *moh_files_alloc(struct ast_channel *chan, void *params)
}
state->class = mohclass_ref(class, "Reffing music class for channel");
- ast_format_copy(&state->origwfmt, ast_channel_writeformat(chan));
- ast_format_copy(&state->mohwfmt, ast_channel_writeformat(chan));
+ /* it's possible state is not a new allocation, don't leak old refs */
+ ao2_replace(state->origwfmt, ast_channel_writeformat(chan));
+ ao2_replace(state->mohwfmt, ast_channel_writeformat(chan));
moh_post_start(chan, class->name);
@@ -733,12 +738,12 @@ static void *monmp3thread(void *data)
res = 8 * MOH_MS_INTERVAL; /* 800/100 = 8 samples/ms */
}
/* For non-8000Hz formats, we need to alter the resolution */
- res = res * ast_format_rate(&class->format) / 8000;
+ res = res * ast_format_get_sample_rate(class->format) / 8000;
if ((strncasecmp(class->dir, "http://", 7) && strcasecmp(class->dir, "nodir")) && AST_LIST_EMPTY(&class->members))
continue;
/* Read mp3 audio */
- len = ast_codec_get_len(&class->format, res);
+ len = ast_format_determine_length(class->format, res);
if ((res2 = read(class->srcfd, sbuf, len)) != len) {
if (!res2) {
@@ -902,7 +907,7 @@ static struct mohdata *mohalloc(struct mohclass *cl)
fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
moh->f.frametype = AST_FRAME_VOICE;
- ast_format_copy(&moh->f.subclass.format, &cl->format);
+ moh->f.subclass.format = cl->format;
moh->f.offset = AST_FRIENDLY_OFFSET;
moh->parent = mohclass_ref(cl, "Reffing music class for mohdata parent");
@@ -918,7 +923,7 @@ static void moh_release(struct ast_channel *chan, void *data)
{
struct mohdata *moh = data;
struct mohclass *class = moh->parent;
- struct ast_format oldwfmt;
+ struct ast_format *oldwfmt;
ao2_lock(class);
AST_LIST_REMOVE(&moh->parent->members, moh, list);
@@ -927,7 +932,7 @@ static void moh_release(struct ast_channel *chan, void *data)
close(moh->pipe[0]);
close(moh->pipe[1]);
- ast_format_copy(&oldwfmt, &moh->origwfmt);
+ oldwfmt = moh->origwfmt;
moh->parent = class = mohclass_unref(class, "unreffing moh->parent upon deactivation of generator");
@@ -940,13 +945,15 @@ static void moh_release(struct ast_channel *chan, void *data)
if (state && state->class) {
state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
}
- if (oldwfmt.id && ast_set_write_format(chan, &oldwfmt)) {
+ if (oldwfmt && ast_set_write_format(chan, oldwfmt)) {
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n",
- ast_channel_name(chan), ast_getformatname(&oldwfmt));
+ ast_channel_name(chan), ast_format_get_name(oldwfmt));
}
moh_post_stop(chan);
}
+
+ ao2_cleanup(oldwfmt);
}
static void *moh_alloc(struct ast_channel *chan, void *params)
@@ -972,9 +979,10 @@ static void *moh_alloc(struct ast_channel *chan, void *params)
}
if ((res = mohalloc(class))) {
- ast_format_copy(&res->origwfmt, ast_channel_writeformat(chan));
- if (ast_set_write_format(chan, &class->format)) {
- ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", ast_channel_name(chan), ast_codec2str(&class->format));
+ res->origwfmt = ao2_bump(ast_channel_writeformat(chan));
+ if (ast_set_write_format(chan, class->format)) {
+ ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", ast_channel_name(chan),
+ ast_format_get_name(class->format));
moh_release(NULL, res);
res = NULL;
} else {
@@ -991,7 +999,7 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
short buf[1280 + AST_FRIENDLY_OFFSET / 2];
int res;
- len = ast_codec_get_len(&moh->parent->format, samples);
+ len = ast_format_determine_length(moh->parent->format, samples);
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, ast_channel_name(chan));
@@ -1003,7 +1011,7 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
moh->f.datalen = res;
moh->f.data.ptr = buf + AST_FRIENDLY_OFFSET / 2;
- moh->f.samples = ast_codec_get_samples(&moh->f);
+ moh->f.samples = ast_codec_samples_count(&moh->f);
if (ast_write(chan, &moh->f) < 0) {
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
@@ -1303,6 +1311,8 @@ static void local_ast_moh_cleanup(struct ast_channel *chan)
mohclass_unref(state->class, "Uh Oh. Cleaning up MOH with an active class");
ast_log(LOG_WARNING, "Uh Oh. Cleaning up MOH with an active class\n");
}
+ ao2_cleanup(state->origwfmt);
+ ao2_cleanup(state->mohwfmt);
ast_free(ast_channel_music_state(chan));
ast_channel_music_state_set(chan, NULL);
/* Only held a module reference if we had a music state */
@@ -1329,7 +1339,7 @@ static struct mohclass *_moh_class_malloc(const char *file, int line, const char
ao2_alloc(sizeof(*class), moh_class_destructor)
#endif
)) {
- ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
+ class->format = ao2_bump(ast_format_slin);
class->srcfd = -1;
}
@@ -1407,10 +1417,10 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con
else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "alpha"))
ast_set_flag(mohclass, MOH_SORTALPHA);
else if (!strcasecmp(tmp->name, "format")) {
- ast_getformatbyname(tmp->value, &mohclass->format);
- if (!mohclass->format.id) {
+ mohclass->format = ast_format_cache_get(tmp->value);
+ if (!mohclass->format) {
ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value);
- ast_format_set(&mohclass->format, AST_FORMAT_SLINEAR, 0);
+ mohclass->format = ao2_bump(ast_format_slin);
}
}
}
@@ -1643,6 +1653,8 @@ static void moh_class_destructor(void *obj)
class->timer = NULL;
}
+ ao2_cleanup(class->format);
+
/* Finally, collect the exit status of the monitor thread */
if (tid > 0) {
pthread_join(tid, NULL);
@@ -1737,10 +1749,10 @@ static int load_moh_classes(int reload)
} else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "alpha")) {
ast_set_flag(class, MOH_SORTALPHA);
} else if (!strcasecmp(var->name, "format")) {
- ast_getformatbyname(var->value, &class->format);
- if (!class->format.id) {
+ class->format = ast_format_cache_get(var->value);
+ if (!class->format) {
ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value);
- ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
+ class->format = ao2_bump(ast_format_slin);
}
}
}
@@ -1877,7 +1889,7 @@ static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struc
ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
}
if (strcasecmp(class->mode, "files")) {
- ast_cli(a->fd, "\tFormat: %s\n", ast_getformatname(&class->format));
+ ast_cli(a->fd, "\tFormat: %s\n", ast_format_get_name(class->format));
}
}
ao2_iterator_destroy(&i);
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 59db4eb1e..548372879 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1648,8 +1648,8 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "type", "", OPT_NOOP_T, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
- ast_sorcery_object_field_register_alias(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.prefs, media.codecs));
- ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.prefs, media.codecs));
+ ast_sorcery_object_field_register_alias(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.codecs));
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.codecs));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmf_mode", "rfc4733", dtmf_handler, dtmf_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ipv6));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.symmetric));
@@ -1851,9 +1851,7 @@ static void endpoint_destructor(void* obj)
ast_string_field_free_memory(endpoint);
- if (endpoint->media.codecs) {
- ast_format_cap_destroy(endpoint->media.codecs);
- }
+ ao2_ref(endpoint->media.codecs, -1);
subscription_configuration_destroy(&endpoint->subscription);
info_configuration_destroy(&endpoint->info);
media_configuration_destroy(&endpoint->media);
@@ -1891,7 +1889,7 @@ void *ast_sip_endpoint_alloc(const char *name)
ao2_cleanup(endpoint);
return NULL;
}
- if (!(endpoint->media.codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(endpoint->media.codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_cleanup(endpoint);
return NULL;
}
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index b7e1eef3d..90a2cec46 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -41,6 +41,8 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/netsock2.h"
#include "asterisk/channel.h"
@@ -68,38 +70,39 @@ static const char STR_VIDEO[] = "video";
static const int FD_VIDEO = 2;
/*! \brief Retrieves an ast_format_type based on the given stream_type */
-static enum ast_format_type stream_to_media_type(const char *stream_type)
+static enum ast_media_type stream_to_media_type(const char *stream_type)
{
if (!strcasecmp(stream_type, STR_AUDIO)) {
- return AST_FORMAT_TYPE_AUDIO;
+ return AST_MEDIA_TYPE_AUDIO;
} else if (!strcasecmp(stream_type, STR_VIDEO)) {
- return AST_FORMAT_TYPE_VIDEO;
+ return AST_MEDIA_TYPE_VIDEO;
}
return 0;
}
/*! \brief Get the starting descriptor for a media type */
-static int media_type_to_fdno(enum ast_format_type media_type)
+static int media_type_to_fdno(enum ast_media_type media_type)
{
switch (media_type) {
- case AST_FORMAT_TYPE_AUDIO: return FD_AUDIO;
- case AST_FORMAT_TYPE_VIDEO: return FD_VIDEO;
- case AST_FORMAT_TYPE_TEXT:
- case AST_FORMAT_TYPE_IMAGE: break;
+ case AST_MEDIA_TYPE_AUDIO: return FD_AUDIO;
+ case AST_MEDIA_TYPE_VIDEO: return FD_VIDEO;
+ case AST_MEDIA_TYPE_TEXT:
+ case AST_MEDIA_TYPE_UNKNOWN:
+ case AST_MEDIA_TYPE_IMAGE: break;
}
return -1;
}
/*! \brief Remove all other cap types but the one given */
-static void format_cap_only_type(struct ast_format_cap *caps, enum ast_format_type media_type)
+static void format_cap_only_type(struct ast_format_cap *caps, enum ast_media_type media_type)
{
- int i = AST_FORMAT_INC;
- while (i <= AST_FORMAT_TYPE_TEXT) {
- if (i != media_type) {
- ast_format_cap_remove_bytype(caps, i);
+ int i = 0;
+ while (i <= AST_MEDIA_TYPE_TEXT) {
+ if (i != media_type && i != AST_MEDIA_TYPE_UNKNOWN) {
+ ast_format_cap_remove_by_type(caps, i);
}
- i += AST_FORMAT_INC;
+ i += 1;
}
}
@@ -116,9 +119,6 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, 1);
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_NAT, session->endpoint->media.rtp.symmetric);
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session_media->rtp),
- session_media->rtp, &session->endpoint->media.prefs);
-
if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) {
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);
}
@@ -185,74 +185,97 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp
if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
sscanf(pj_strbuf(&fmtp.fmt), "%d", &num);
if ((format = ast_rtp_codecs_get_payload_format(codecs, num))) {
+ struct ast_format *format_parsed;
+
ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));
- ast_format_sdp_parse(format, fmt_param);
+
+ format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(codecs, num, format_parsed);
+ ao2_ref(format_parsed, -1);
+ }
+
+ ao2_ref(format, -1);
}
}
}
+
+ /* Get the packetization, if it exists */
+ if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
+ unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
+ if (framing && session->endpoint->media.rtp.use_ptime) {
+ ast_rtp_codecs_set_framing(codecs, framing);
+ }
+ }
}
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
const struct pjmedia_sdp_media *stream)
{
- RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, peer, NULL, ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
- struct ast_rtp_codecs codecs;
- struct ast_format fmt;
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
+ struct ast_rtp_codecs codecs = AST_RTP_CODECS_NULL_INIT;
int fmts = 0;
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
- !ast_format_cap_is_empty(session->direct_media_cap);
+ ast_format_cap_count(session->direct_media_cap);
- if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
- !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
return -1;
}
/* get the endpoint capabilities */
if (direct_media_enabled) {
- ast_format_cap_joint_copy(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ format_cap_only_type(caps, media_type);
} else {
- ast_format_cap_copy(caps, session->endpoint->media.codecs);
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
}
- format_cap_only_type(caps, media_type);
/* get the capabilities on the peer */
get_codecs(session, stream, &codecs);
ast_rtp_codecs_payload_formats(&codecs, peer, &fmts);
/* get the joint capabilities between peer and endpoint */
- if (!(joint = ast_format_cap_joint(caps, peer))) {
- char usbuf[64], thembuf[64];
+ ast_format_cap_get_compatible(caps, peer, joint);
+ if (!ast_format_cap_count(joint)) {
+ struct ast_str *usbuf = ast_str_alloca(64);
+ struct ast_str *thembuf = ast_str_alloca(64);
ast_rtp_codecs_payloads_destroy(&codecs);
-
- ast_getformatname_multiple(usbuf, sizeof(usbuf), caps);
- ast_getformatname_multiple(thembuf, sizeof(thembuf), peer);
- ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
+ ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n",
+ ast_format_cap_get_names(peer, &usbuf),
+ ast_format_cap_get_names(caps, &thembuf));
return -1;
}
ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp),
session_media->rtp);
- ast_format_cap_copy(caps, session->req_caps);
- ast_format_cap_remove_bytype(caps, media_type);
- ast_format_cap_append(caps, joint);
- ast_format_cap_append(session->req_caps, caps);
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(caps, session->req_caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, media_type);
+ ast_format_cap_append_from_cap(caps, joint, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(session->req_caps, caps, AST_MEDIA_TYPE_UNKNOWN);
if (session->channel) {
- ast_format_cap_copy(caps, ast_channel_nativeformats(session->channel));
- ast_format_cap_remove_bytype(caps, media_type);
- ast_codec_choose(&session->endpoint->media.prefs, joint, 1, &fmt);
- ast_format_cap_add(caps, &fmt);
+ struct ast_format *fmt;
+
+ ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, media_type);
+ fmt = ast_format_cap_get_format(joint, 0);
+ ast_format_cap_append(caps, fmt, 0);
/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
- ast_format_cap_copy(ast_channel_nativeformats(session->channel), caps);
- ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
- ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
+ ast_channel_nativeformats_set(session->channel, caps);
+ ast_channel_set_rawwriteformat(session->channel, fmt);
+ ast_channel_set_rawreadformat(session->channel, fmt);
+
+ ao2_ref(fmt, -1);
}
ast_rtp_codecs_payloads_destroy(&codecs);
@@ -286,7 +309,7 @@ static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *
pjmedia_sdp_attr *attr = NULL;
char *tmp;
- ast_format_sdp_generate(format, rtp_code, &fmtp0);
+ ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
if (ast_str_strlen(fmtp0)) {
tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
/* remove any carriage return line feeds */
@@ -304,18 +327,6 @@ static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *
return attr;
}
-static int codec_pref_has_type(struct ast_codec_pref *prefs, enum ast_format_type media_type)
-{
- int i;
- struct ast_format fmt;
- for (i = 0; ast_codec_pref_index(prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) == media_type) {
- return 1;
- }
- }
- return 0;
-}
-
/*! \brief Function which adds ICE attributes to a media stream */
static void add_ice_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
{
@@ -469,38 +480,6 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
ice->start(session_media->rtp);
}
-static void apply_packetization(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
- const struct pjmedia_sdp_media *remote_stream)
-{
- pjmedia_sdp_attr *attr;
- pj_str_t value;
- unsigned long framing;
- int codec;
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session_media->rtp)->pref;
-
- /* Apply packetization if available and configured to do so */
- if (!session->endpoint->media.rtp.use_ptime || !(attr = pjmedia_sdp_media_find_attr2(remote_stream, "ptime", NULL))) {
- return;
- }
-
- value = attr->value;
- framing = pj_strtoul(pj_strltrim(&value));
-
- for (codec = 0; codec < AST_RTP_MAX_PT; codec++) {
- struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(
- session_media->rtp), codec);
-
- if (!format.asterisk_format) {
- continue;
- }
-
- ast_codec_pref_setsize(pref, &format.format, framing);
- }
-
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session_media->rtp),
- session_media->rtp, pref);
-}
-
/*! \brief figure out media transport encryption type from the media transport string */
static enum ast_sip_session_media_encryption get_media_encryption_type(pj_str_t transport)
{
@@ -722,7 +701,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
{
char host[NI_MAXHOST];
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
/* If no type formats have been configured reject this stream */
if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
@@ -759,11 +738,6 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
if (set_caps(session, session_media, stream)) {
return -1;
}
-
- if (media_type == AST_FORMAT_TYPE_AUDIO) {
- apply_packetization(session, session_media, stream);
- }
-
return 1;
}
@@ -892,18 +866,14 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733) ? AST_RTP_DTMF : 0;
int min_packet_size = 0, max_packet_size = 0;
int rtp_code;
- struct ast_format format;
- RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
+ int use_override_prefs = ast_format_cap_count(session->req_caps);
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
- !ast_format_cap_is_empty(session->direct_media_cap);
+ ast_format_cap_count(session->direct_media_cap);
- int use_override_prefs = session->override_prefs.formats[0].id;
- struct ast_codec_pref *prefs = use_override_prefs ?
- &session->override_prefs : &session->endpoint->media.prefs;
-
- if ((use_override_prefs && !codec_pref_has_type(&session->override_prefs, media_type)) ||
+ if ((use_override_prefs && !ast_format_cap_has_type(session->req_caps, media_type)) ||
(!use_override_prefs && !ast_format_cap_has_type(session->endpoint->media.codecs, media_type))) {
/* If no type formats are configured don't add a stream */
return 0;
@@ -954,59 +924,53 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
/* Add ICE attributes and candidates */
add_ice_to_stream(session, session_media, pool, media);
- if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
return -1;
}
if (direct_media_enabled) {
- ast_format_cap_joint_copy(session->endpoint->media.codecs, session->direct_media_cap, caps);
- } else if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) {
- ast_format_cap_copy(caps, session->endpoint->media.codecs);
+ ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ } else if (!ast_format_cap_count(session->req_caps) ||
+ !ast_format_cap_iscompatible(session->req_caps, session->endpoint->media.codecs)) {
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
} else {
- ast_format_cap_copy(caps, session->req_caps);
+ ast_format_cap_append_from_cap(caps, session->req_caps, media_type);
}
- for (index = 0; ast_codec_pref_index(prefs, index, &format); ++index) {
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session_media->rtp)->pref;
-
- if (AST_FORMAT_GET_TYPE(format.id) != media_type) {
- continue;
- }
+ for (index = 0; index < ast_format_cap_count(caps); ++index) {
+ struct ast_format *format = ast_format_cap_get_format(caps, index);
- if (!use_override_prefs && !ast_format_cap_get_compatible_format(caps, &format, &format)) {
+ if (ast_format_get_type(format) != media_type) {
+ ao2_ref(format, -1);
continue;
}
- if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, &format, 0)) == -1) {
- ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n",ast_getformatname(&format));
+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0)) == -1) {
+ ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
+ ao2_ref(format, -1);
continue;
}
- if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 1, &format, 0))) {
+ if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 1, format, 0))) {
+ ao2_ref(format, -1);
continue;
}
-
media->attr[media->attr_count++] = attr;
- if ((attr = generate_fmtp_attr(pool, &format, rtp_code))) {
+ if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
media->attr[media->attr_count++] = attr;
}
- if (pref && media_type != AST_FORMAT_TYPE_VIDEO) {
- struct ast_format_list fmt = ast_codec_pref_getsize(pref, &format);
- if (fmt.cur_ms && ((fmt.cur_ms < min_packet_size) || !min_packet_size)) {
- min_packet_size = fmt.cur_ms;
- }
-
- if (fmt.max_ms && ((fmt.max_ms < max_packet_size) || !max_packet_size)) {
- max_packet_size = fmt.max_ms;
- }
+ if (ast_format_get_maximum_ms(format) &&
+ ((ast_format_get_maximum_ms(format) < max_packet_size) || !max_packet_size)) {
+ max_packet_size = ast_format_get_maximum_ms(format);
}
+ ao2_ref(format, -1);
}
/* Add non-codec formats */
- if (media_type != AST_FORMAT_TYPE_VIDEO) {
+ if (media_type != AST_MEDIA_TYPE_VIDEO) {
for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) {
if (!(noncodec & index) || (rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp),
0, NULL, index)) == -1) {
@@ -1033,6 +997,10 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
}
/* If ptime is set add it as an attribute */
+ min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(session_media->rtp));
+ if (!min_packet_size) {
+ min_packet_size = ast_format_cap_get_framing(caps);
+ }
if (min_packet_size) {
snprintf(tmp, sizeof(tmp), "%d", min_packet_size);
attr = pjmedia_sdp_attr_create(pool, "ptime", pj_cstr(&stmp, tmp));
@@ -1061,7 +1029,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
{
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
char host[NI_MAXHOST];
int fdno;
@@ -1095,15 +1063,10 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
/* Apply connection information to the RTP instance */
ast_sockaddr_set_port(addrs, remote_stream->desc.port);
ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
-
if (set_caps(session, session_media, local_stream)) {
return -1;
}
- if (media_type == AST_FORMAT_TYPE_AUDIO) {
- apply_packetization(session, session_media, remote_stream);
- }
-
if ((fdno = media_type_to_fdno(media_type)) < 0) {
return -1;
}
@@ -1117,7 +1080,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
ast_rtp_instance_activate(session_media->rtp);
/* audio stream handles music on hold */
- if (media_type != AST_FORMAT_TYPE_AUDIO) {
+ if (media_type != AST_MEDIA_TYPE_AUDIO) {
return 1;
}
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 336122040..96faa64bb 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1069,8 +1069,8 @@ static void session_destructor(void *obj)
ast_party_id_free(&session->id);
ao2_cleanup(session->endpoint);
ao2_cleanup(session->contact);
- ast_format_cap_destroy(session->req_caps);
- ast_format_cap_destroy(session->direct_media_cap);
+ ao2_cleanup(session->req_caps);
+ ao2_cleanup(session->direct_media_cap);
if (session->dsp) {
ast_dsp_free(session->dsp);
@@ -1169,7 +1169,7 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
session->endpoint = ao2_bump(endpoint);
session->contact = ao2_bump(contact);
session->inv_session = inv_session;
- session->req_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ session->req_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (endpoint->dtmf == AST_SIP_DTMF_INBAND) {
dsp_features |= DSP_FEATURE_DIGIT_DETECT;
@@ -1197,7 +1197,7 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
iter->session_begin(session);
}
}
- session->direct_media_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ session->direct_media_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
AST_LIST_HEAD_INIT_NOLOCK(&session->delayed_requests);
ast_party_id_init(&session->id);
ao2_ref(session, +1);
@@ -1273,9 +1273,19 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
return NULL;
}
- if (!ast_format_cap_is_empty(req_caps)) {
- ast_format_cap_copy(session->req_caps, session->endpoint->media.codecs);
- ast_format_cap_append(session->req_caps, req_caps);
+ if (ast_format_cap_count(req_caps)) {
+ /* get joint caps between req_caps and endpoint caps */
+ struct ast_format_cap *joint_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_get_compatible(req_caps, session->endpoint->media.codecs, joint_caps);
+
+ /* if joint caps */
+ if (ast_format_cap_count(joint_caps)) {
+ /* copy endpoint caps into session->req_caps */
+ ast_format_cap_append_from_cap(session->req_caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
+ /* replace instances of joint caps equivalents in session->req_caps */
+ ast_format_cap_replace_from_cap(session->req_caps, joint_caps, AST_MEDIA_TYPE_UNKNOWN);
+ }
+ ao2_cleanup(joint_caps);
}
if ((pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS)) {
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 7251e8f80..bd930295b 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -56,6 +56,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
@@ -66,6 +67,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
+#include "asterisk/smoother.h"
#include "asterisk/test.h"
#define MAX_TIMESTAMP_SKEW 640
@@ -216,8 +218,8 @@ struct ast_rtp {
unsigned int cycles; /*!< Shifted count of sequence number cycles */
double rxjitter; /*!< Interarrival jitter at the moment in seconds */
double rxtransit; /*!< Relative transit time for previous packet */
- struct ast_format lasttxformat;
- struct ast_format lastrxformat;
+ struct ast_format *lasttxformat;
+ struct ast_format *lastrxformat;
int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
@@ -1833,7 +1835,11 @@ static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size,
static int rtp_get_rate(struct ast_format *format)
{
- return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
+ /* For those wondering: due to a fluke in RFC publication, G.722 is advertised
+ * as having a sample rate of 8kHz, while implementations must know that its
+ * real rate is 16kHz. Seriously.
+ */
+ return (ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) ? 8000 : (int)ast_format_get_sample_rate(format);
}
static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
@@ -2184,6 +2190,10 @@ static int ast_rtp_new(struct ast_rtp_instance *instance,
rtp->dtlstimerid = -1;
#endif
+ rtp->f.subclass.format = ao2_bump(ast_format_none);
+ rtp->lastrxformat = ao2_bump(ast_format_none);
+ rtp->lasttxformat = ao2_bump(ast_format_none);
+
return 0;
}
@@ -2265,6 +2275,10 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
}
#endif
+ ao2_cleanup(rtp->lasttxformat);
+ ao2_cleanup(rtp->lastrxformat);
+ ao2_cleanup(rtp->f.subclass.format);
+
/* Destroy synchronization items */
ast_mutex_destroy(&rtp->lock);
ast_cond_destroy(&rtp->cond);
@@ -2444,7 +2458,7 @@ static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, cha
rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
- if (duration > 0 && (measured_samples = duration * rtp_get_rate(&rtp->f.subclass.format) / 1000) > rtp->send_duration) {
+ if (duration > 0 && (measured_samples = duration * rtp_get_rate(rtp->f.subclass.format) / 1000) > rtp->send_duration) {
ast_debug(2, "Adjusting final end duration from %d to %u\n", rtp->send_duration, measured_samples);
rtp->send_duration = measured_samples;
}
@@ -2620,7 +2634,7 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
int fraction_lost;
struct timeval dlsr = { 0, };
char bdata[512];
- int rate = rtp_get_rate(&rtp->f.subclass.format);
+ int rate = rtp_get_rate(rtp->f.subclass.format);
int ice;
int header_offset = 0;
struct ast_sockaddr remote_address = { {0,} };
@@ -2791,9 +2805,9 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
int pred, mark = 0;
unsigned int ms = calc_txstamp(rtp, &frame->delivery);
struct ast_sockaddr remote_address = { {0,} };
- int rate = rtp_get_rate(&frame->subclass.format) / 1000;
+ int rate = rtp_get_rate(frame->subclass.format) / 1000;
- if (frame->subclass.format.id == AST_FORMAT_G722) {
+ if (ast_format_cmp(frame->subclass.format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
frame->samples /= 2;
}
@@ -2817,7 +2831,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
}
}
} else if (frame->frametype == AST_FRAME_VIDEO) {
- mark = ast_format_get_video_mark(&frame->subclass.format);
+ mark = frame->subclass.frame_ending;
pred = rtp->lastovidtimestamp + frame->samples;
/* Re-calculate last TS */
rtp->lastts = rtp->lastts + ms * 90;
@@ -2959,7 +2973,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_sockaddr remote_address = { {0,} };
- struct ast_format subclass;
+ struct ast_format *format;
int codec;
ast_rtp_instance_get_remote_address(instance, &remote_address);
@@ -3029,17 +3043,28 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
}
/* Grab the subclass and look up the payload we are going to use */
- ast_format_copy(&subclass, &frame->subclass.format);
- if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &subclass, 0)) < 0) {
- ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(&frame->subclass.format));
+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance),
+ 1,
+ frame->subclass.format,
+ 0);
+ if (codec < 0) {
+ ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n",
+ ast_format_get_name(frame->subclass.format));
return -1;
}
- /* Oh dear, if the format changed we will have to set up a new smoother */
- if (ast_format_cmp(&rtp->lasttxformat, &subclass) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(&rtp->lasttxformat), ast_getformatname(&subclass));
- rtp->lasttxformat = subclass;
- ast_format_copy(&rtp->lasttxformat, &subclass);
+ /* Note that we do not increase the ref count here as this pointer
+ * will not be held by any thing explicitly. The format variable is
+ * merely a convenience reference to frame->subclass.format */
+ format = frame->subclass.format;
+ if (ast_format_cmp(rtp->lasttxformat, format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ /* Oh dear, if the format changed we will have to set up a new smoother */
+ if (option_debug > 0) {
+ ast_debug(1, "Ooh, format changed from %s to %s\n",
+ ast_format_get_name(rtp->lasttxformat),
+ ast_format_get_name(frame->subclass.format));
+ }
+ ao2_replace(rtp->lasttxformat, format);
if (rtp->smoother) {
ast_smoother_free(rtp->smoother);
rtp->smoother = NULL;
@@ -3047,34 +3072,15 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
}
/* If no smoother is present see if we have to set one up */
- if (!rtp->smoother) {
- struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, &subclass);
-
- switch (subclass.id) {
- case AST_FORMAT_SPEEX:
- case AST_FORMAT_SPEEX16:
- case AST_FORMAT_SPEEX32:
- case AST_FORMAT_SILK:
- case AST_FORMAT_CELT:
- case AST_FORMAT_G723_1:
- case AST_FORMAT_SIREN7:
- case AST_FORMAT_SIREN14:
- case AST_FORMAT_G719:
- /* Opus */
- case AST_FORMAT_OPUS:
- /* these are all frame-based codecs and cannot be safely run through
- a smoother */
- break;
- default:
- if (fmt.inc_ms) {
- if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
- ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
- return -1;
- }
- if (fmt.flags) {
- ast_smoother_set_flags(rtp->smoother, fmt.flags);
- }
- ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
+ if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
+ unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
+
+ if (framing_ms) {
+ rtp->smoother = ast_smoother_new((framing_ms * ast_format_get_minimum_bytes(format)) / ast_format_get_minimum_ms(format));
+ if (!rtp->smoother) {
+ ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len: %u\n",
+ ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
+ return -1;
}
}
}
@@ -3122,7 +3128,7 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
double d;
double dtv;
double prog;
- int rate = rtp_get_rate(&rtp->f.subclass.format);
+ int rate = rtp_get_rate(rtp->f.subclass.format);
double normdev_rxjitter_current;
if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
@@ -3277,7 +3283,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
rtp->dtmf_duration = new_duration;
rtp->resp = resp;
f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
+ f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.format)), ast_tv(0, 0));
rtp->resp = 0;
rtp->dtmf_duration = rtp->dtmf_timeout = 0;
AST_LIST_INSERT_TAIL(frames, f, frame_list);
@@ -3308,7 +3314,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
if (rtp->resp && rtp->resp != resp) {
/* Another digit already began. End it */
f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
+ f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.format)), ast_tv(0, 0));
rtp->resp = 0;
rtp->dtmf_duration = rtp->dtmf_timeout = 0;
AST_LIST_INSERT_TAIL(frames, f, frame_list);
@@ -3405,10 +3411,10 @@ static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, u
}
} else if ((rtp->resp == resp) && !power) {
f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
- f->samples = rtp->dtmfsamples * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8);
+ f->samples = rtp->dtmfsamples * (rtp_get_rate(rtp->lastrxformat) / 1000);
rtp->resp = 0;
} else if (rtp->resp == resp) {
- rtp->dtmfsamples += 20 * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8);
+ rtp->dtmfsamples += 20 * (rtp_get_rate(rtp->lastrxformat) / 1000);
}
rtp->dtmf_timeout = 0;
@@ -3424,7 +3430,8 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u
totally help us out becuase we don't have an engine to keep it going and we are not
guaranteed to have it every 20ms or anything */
if (rtpdebug) {
- ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", (int) rtp->lastrxformat.id, len);
+ ast_debug(0, "- RTP 3389 Comfort noise event: Format %s (len = %d)\n",
+ ast_format_get_name(rtp->lastrxformat), len);
}
if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
@@ -3796,7 +3803,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance);
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1);
int res = 0, payload = 0, bridged_payload = 0, mark;
- struct ast_rtp_payload_type payload_type;
+ RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
int reconstruct = ntohl(rtpheader[0]);
struct ast_sockaddr remote_address = { {0,} };
int ice;
@@ -3806,10 +3813,13 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
mark = (((reconstruct & 0x800000) >> 23) != 0);
/* Check what the payload value should be */
- payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
+ payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
+ if (!payload_type) {
+ return -1;
+ }
/* Otherwise adjust bridged payload to match */
- bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, &payload_type.format, payload_type.rtp_code);
+ bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type->asterisk_format, payload_type->format, payload_type->rtp_code);
/* If no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged. Bail. */
if (bridged_payload < 0) {
@@ -3880,7 +3890,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
struct ast_sockaddr addr;
int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
- struct ast_rtp_payload_type payload;
+ RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
struct ast_sockaddr remote_address = { {0,} };
struct frame_list frames;
@@ -4120,20 +4130,20 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
payloadtype, seqno, timestamp,res - hdrlen);
}
- payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
+ payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
/* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
- if (!payload.asterisk_format) {
+ if (!payload->asterisk_format) {
struct ast_frame *f = NULL;
- if (payload.rtp_code == AST_RTP_DTMF) {
+ if (payload->rtp_code == AST_RTP_DTMF) {
/* process_dtmf_rfc2833 may need to return multiple frames. We do this
* by passing the pointer to the frame list to it so that the method
* can append frames to the list as needed.
*/
process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames);
- } else if (payload.rtp_code == AST_RTP_CISCO_DTMF) {
+ } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
- } else if (payload.rtp_code == AST_RTP_CN) {
+ } else if (payload->rtp_code == AST_RTP_CN) {
f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
} else {
ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
@@ -4153,10 +4163,25 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
return &ast_null_frame;
}
- ast_format_copy(&rtp->lastrxformat, &payload.format);
- ast_format_copy(&rtp->f.subclass.format, &payload.format);
- rtp->f.frametype = (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) ? AST_FRAME_VOICE : (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
-
+ ao2_replace(rtp->lastrxformat, payload->format);
+ ao2_replace(rtp->f.subclass.format, payload->format);
+ switch (ast_format_get_type(rtp->f.subclass.format)) {
+ case AST_MEDIA_TYPE_AUDIO:
+ rtp->f.frametype = AST_FRAME_VOICE;
+ break;
+ case AST_MEDIA_TYPE_VIDEO:
+ rtp->f.frametype = AST_FRAME_VIDEO;
+ break;
+ case AST_MEDIA_TYPE_TEXT:
+ rtp->f.frametype = AST_FRAME_TEXT;
+ break;
+ case AST_MEDIA_TYPE_IMAGE:
+ /* Fall through */
+ default:
+ ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
+ ast_codec_media_type2str(ast_format_get_type(rtp->f.subclass.format)));
+ return &ast_null_frame;
+ }
rtp->rxseqno = seqno;
if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
@@ -4165,7 +4190,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
if (rtp->resp) {
struct ast_frame *f;
f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
+ f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.format)), ast_tv(0, 0));
rtp->resp = 0;
rtp->dtmf_timeout = rtp->dtmf_duration = 0;
AST_LIST_INSERT_TAIL(&frames, f, frame_list);
@@ -4182,7 +4207,9 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
rtp->f.seqno = seqno;
- if (rtp->f.subclass.format.id == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
+ if ((ast_format_cmp(rtp->f.subclass.format, ast_format_t140) == AST_FORMAT_CMP_EQUAL)
+ && ((int)seqno - (prev_seqno + 1) > 0)
+ && ((int)seqno - (prev_seqno + 1) < 10)) {
unsigned char *data = rtp->f.data.ptr;
memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
@@ -4192,7 +4219,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
*data = 0xBD;
}
- if (rtp->f.subclass.format.id == AST_FORMAT_T140RED) {
+ if (ast_format_cmp(rtp->f.subclass.format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {
unsigned char *data = rtp->f.data.ptr;
unsigned char *header_end;
int num_generations;
@@ -4201,7 +4228,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
int x;
- ast_format_set(&rtp->f.subclass.format, AST_FORMAT_T140, 0);
+ ao2_replace(rtp->f.subclass.format, ast_format_t140);
header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
if (header_end == NULL) {
return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
@@ -4239,17 +4266,17 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
}
}
- if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) {
- rtp->f.samples = ast_codec_get_samples(&rtp->f);
- if (ast_format_is_slinear(&rtp->f.subclass.format)) {
+ if (ast_format_get_type(rtp->f.subclass.format) == AST_MEDIA_TYPE_AUDIO) {
+ rtp->f.samples = ast_codec_samples_count(&rtp->f);
+ if (ast_format_cache_is_slinear(rtp->f.subclass.format)) {
ast_frame_byteswap_be(&rtp->f);
}
calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
/* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
- rtp->f.ts = timestamp / (rtp_get_rate(&rtp->f.subclass.format) / 1000);
- rtp->f.len = rtp->f.samples / ((ast_format_rate(&rtp->f.subclass.format) / 1000));
- } else if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) {
+ rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass.format) / 1000);
+ rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
+ } else if (ast_format_get_type(rtp->f.subclass.format) == AST_MEDIA_TYPE_VIDEO) {
/* Video -- samples is # of samples vs. 90000 */
if (!rtp->lastividtimestamp)
rtp->lastividtimestamp = timestamp;
@@ -4258,10 +4285,8 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
rtp->f.delivery.tv_sec = 0;
rtp->f.delivery.tv_usec = 0;
/* Pass the RTP marker bit as bit */
- if (mark) {
- ast_format_set_video_mark(&rtp->f.subclass.format);
- }
- } else {
+ rtp->f.subclass.frame_ending = mark;
+ } else if (ast_format_get_type(rtp->f.subclass.format) == AST_MEDIA_TYPE_TEXT) {
/* TEXT -- samples is # of samples vs. 1000 */
if (!rtp->lastitexttimestamp)
rtp->lastitexttimestamp = timestamp;
@@ -4269,6 +4294,10 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
rtp->lastitexttimestamp = timestamp;
rtp->f.delivery.tv_sec = 0;
rtp->f.delivery.tv_usec = 0;
+ } else {
+ ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
+ ast_codec_media_type2str(ast_format_get_type(rtp->f.subclass.format)));
+ return &ast_null_frame;;
}
AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
@@ -4413,7 +4442,7 @@ static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int
}
rtp->red->t140.frametype = AST_FRAME_TEXT;
- ast_format_set(&rtp->red->t140.subclass.format, AST_FORMAT_T140RED, 0);
+ ao2_replace(rtp->red->t140.subclass.format, ast_format_t140_red);
rtp->red->t140.data.ptr = &rtp->red->buf_data;
rtp->red->t140.ts = 0;
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index c13e9ad1e..7e8b24214 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
+#include "asterisk/format_cache.h"
/*! Command value used for Linksys paging to indicate we are starting */
#define LINKSYS_MCAST_STARTCMD 6
@@ -144,7 +145,8 @@ static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched
static int rtp_get_rate(struct ast_format *format)
{
- return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
+ return ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL ?
+ 8000 : ast_format_get_sample_rate(format);
}
static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
@@ -237,7 +239,7 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
int hdrlen = 12, res = 0, codec;
unsigned char *rtpheader;
unsigned int ms = calc_txstamp(multicast, &frame->delivery);
- int rate = rtp_get_rate(&frame->subclass.format) / 1000;
+ int rate = rtp_get_rate(frame->subclass.format) / 1000;
/* We only accept audio, nothing else */
if (frame->frametype != AST_FRAME_VOICE) {
@@ -245,7 +247,7 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
}
/* Grab the actual payload number for when we create the RTP packet */
- if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &frame->subclass.format, 0)) < 0) {
+ if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.format, 0)) < 0) {
return -1;
}
diff --git a/res/res_speech.c b/res/res_speech.c
index 71c283f40..0e4352da4 100644
--- a/res/res_speech.c
+++ b/res/res_speech.c
@@ -38,7 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#include "asterisk/cli.h"
#include "asterisk/term.h"
#include "asterisk/speech.h"
-
+#include "asterisk/format_cache.h"
static AST_RWLIST_HEAD_STATIC(engines, ast_speech_engine);
static struct ast_speech_engine *default_engine = NULL;
@@ -183,26 +183,34 @@ struct ast_speech *ast_speech_new(const char *engine_name, const struct ast_form
{
struct ast_speech_engine *engine = NULL;
struct ast_speech *new_speech = NULL;
- struct ast_format_cap *joint = NULL;
- struct ast_format best;
-
- ast_format_set(&best, AST_FORMAT_SLINEAR, 0);
+ struct ast_format_cap *joint;
+ RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
/* Try to find the speech recognition engine that was requested */
if (!(engine = find_engine(engine_name)))
return NULL;
- /* Before even allocating the memory below do some codec negotiation, we choose the best codec possible and fall back to signed linear if possible */
- if ((joint = ast_format_cap_joint(engine->formats, cap))) {
- ast_best_codec(joint, &best);
- joint = ast_format_cap_destroy(joint);
- } else if (!ast_format_cap_iscompatible(engine->formats, &best)) {
+ joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!joint) {
return NULL;
}
+ ast_format_cap_get_compatible(engine->formats, cap, joint);
+ best = ast_format_cap_get_format(joint, 0);
+ ao2_ref(joint, -1);
+
+ if (!best) {
+ if (ast_format_cap_iscompatible_format(engine->formats, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL) {
+ best = ao2_bump(ast_format_slin);
+ } else {
+ return NULL;
+ }
+ }
+
/* Allocate our own speech structure, and try to allocate a structure from the engine too */
- if (!(new_speech = ast_calloc(1, sizeof(*new_speech))))
+ if (!(new_speech = ast_calloc(1, sizeof(*new_speech)))) {
return NULL;
+ }
/* Initialize the lock */
ast_mutex_init(&new_speech->lock);
@@ -214,13 +222,13 @@ struct ast_speech *ast_speech_new(const char *engine_name, const struct ast_form
new_speech->engine = engine;
/* Can't forget the format audio is going to be in */
- ast_format_copy(&new_speech->format, &best);
+ new_speech->format = best;
/* We are not ready to accept audio yet */
ast_speech_change_state(new_speech, AST_SPEECH_STATE_NOT_READY);
/* Pass ourselves to the engine so they can set us up some more and if they error out then do not create a structure */
- if (engine->create(new_speech, &best)) {
+ if (engine->create(new_speech, best)) {
ast_mutex_destroy(&new_speech->lock);
ast_free(new_speech);
new_speech = NULL;
@@ -248,6 +256,8 @@ int ast_speech_destroy(struct ast_speech *speech)
if (speech->processing_sound)
ast_free(speech->processing_sound);
+ ao2_ref(speech->format, -1);
+
/* Aloha we are done */
ast_free(speech);
diff --git a/res/res_stasis.c b/res/res_stasis.c
index d915914d5..cda0d80eb 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -72,6 +72,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/bridge_after.h"
+#include "asterisk/format_cache.h"
/*! Time to wait for a frame in the application */
#define MAX_WAIT_MS 200
@@ -435,15 +436,14 @@ static void moh_after_bridge_cb(struct ast_channel *chan, void *data)
/*! Request a bridge MOH channel */
static struct ast_channel *prepare_bridge_moh_channel(void)
{
- RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
- struct ast_format format;
+ RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
return NULL;
}
- ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
+ ast_format_cap_append(cap, ast_format_slin, 0);
return ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);
}
diff --git a/res/res_stasis_snoop.c b/res/res_stasis_snoop.c
index e4a309d47..c39c8fae2 100644
--- a/res/res_stasis_snoop.c
+++ b/res/res_stasis_snoop.c
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/timing.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
+#include "asterisk/format_cache.h"
/*! \brief The interval (in milliseconds) that the Snoop timer is triggered, also controls length of audio within frames */
#define SNOOP_INTERVAL 20
@@ -58,7 +59,7 @@ struct stasis_app_snoop {
/*! \brief Number of samples to be read in when spying */
unsigned int spy_samples;
/*! \brief Format in use by the spy audiohook */
- struct ast_format spy_format;
+ struct ast_format *spy_format;
/*! \brief Audiohook used to whisper on the channel */
struct ast_audiohook whisper;
/*! \brief Direction for whispering */
@@ -179,7 +180,7 @@ static struct ast_frame *snoop_read(struct ast_channel *chan)
/* Only get audio from the spy audiohook if it is active */
if (snoop->spy_active) {
ast_audiohook_lock(&snoop->spy);
- frame = ast_audiohook_read_frame(&snoop->spy, snoop->spy_samples, snoop->spy_direction, &snoop->spy_format);
+ frame = ast_audiohook_read_frame(&snoop->spy, snoop->spy_samples, snoop->spy_direction, snoop->spy_format);
ast_audiohook_unlock(&snoop->spy);
}
@@ -278,10 +279,10 @@ static int snoop_setup_audiohook(struct ast_channel *chan, enum ast_audiohook_ty
static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop)
{
SCOPED_CHANNELLOCK(lock, chan);
- unsigned int rate = MAX(ast_format_rate(ast_channel_rawwriteformat(chan)),
- ast_format_rate(ast_channel_rawreadformat(chan)));
+ unsigned int rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(chan)),
+ ast_format_get_sample_rate(ast_channel_rawreadformat(chan)));
- ast_format_set(&snoop->spy_format, ast_format_slin_by_rate(rate), 0);
+ snoop->spy_format = ast_format_cache_get_slin_by_rate(rate);
}
struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
@@ -289,6 +290,7 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
const char *app, const char *app_args, const char *snoop_id)
{
RAII_VAR(struct stasis_app_snoop *, snoop, NULL, ao2_cleanup);
+ struct ast_format_cap *caps;
pthread_t thread;
struct ast_assigned_ids assignedids = {
.uniqueid = snoop_id,
@@ -343,11 +345,18 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
ast_channel_set_fd(snoop->chan, 0, ast_timer_fd(snoop->timer));
/* The format on the Snoop channel will be this signed linear format, and it will never change */
- ast_format_cap_set(ast_channel_nativeformats(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_writeformat(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_rawwriteformat(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_readformat(snoop->chan), &snoop->spy_format);
- ast_format_copy(ast_channel_rawreadformat(snoop->chan), &snoop->spy_format);
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+ ast_format_cap_append(caps, snoop->spy_format, 0);
+ ast_channel_nativeformats_set(snoop->chan, caps);
+ ao2_ref(caps, -1);
+
+ ast_channel_set_writeformat(snoop->chan, snoop->spy_format);
+ ast_channel_set_rawwriteformat(snoop->chan, snoop->spy_format);
+ ast_channel_set_readformat(snoop->chan, snoop->spy_format);
+ ast_channel_set_rawreadformat(snoop->chan, snoop->spy_format);
ast_channel_unlock(snoop->chan);
@@ -357,7 +366,7 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
return NULL;
}
- snoop->spy_samples = ast_format_rate(&snoop->spy_format) / (1000 / SNOOP_INTERVAL);
+ snoop->spy_samples = ast_format_get_sample_rate(snoop->spy_format) / (1000 / SNOOP_INTERVAL);
snoop->spy_active = 1;
}
diff --git a/tests/test_abstract_jb.c b/tests/test_abstract_jb.c
index f48307a3a..f0c0315bf 100644
--- a/tests/test_abstract_jb.c
+++ b/tests/test_abstract_jb.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/test.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/frame.h"
+#include "asterisk/format_cache.h"
#define DEFAULT_FRAME_MS 160
#define DEFAULT_CONFIG_FLAGS 0
@@ -85,7 +86,7 @@ static struct ast_frame *create_test_frame(long timestamp,
{
struct ast_frame f = {0};
- f.subclass.format.id = AST_FORMAT_SLINEAR;
+ f.subclass.format = ast_format_slin;
f.frametype = AST_FRAME_VOICE;
f.src = "TEST";
f.ts = timestamp;
diff --git a/tests/test_cel.c b/tests/test_cel.c
index ff0aaca24..010f19987 100644
--- a/tests/test_cel.c
+++ b/tests/test_cel.c
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/test.h"
#include "asterisk/cel.h"
#include "asterisk/channel.h"
+#include "asterisk/format_cache.h"
#include "asterisk/linkedlists.h"
#include "asterisk/chanvars.h"
#include "asterisk/utils.h"
@@ -1317,7 +1318,10 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_swap)
do_sleep();
/* Perform attended transfer */
- ast_bridge_transfer_attended(chan_alice, chan_david);
+ if (ast_bridge_transfer_attended(chan_alice, chan_david)) {
+ ast_test_status_update(test, "Attended transfer failed!\n");
+ return AST_TEST_FAIL;
+ }
do_sleep();
BRIDGE_ENTER_EVENT_PEER(chan_bob, bridge2, "CELTestChannel/David,CELTestChannel/Charlie");
@@ -1397,7 +1401,10 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
BRIDGE_ENTER(chan_david, bridge2);
/* Perform attended transfer */
- ast_bridge_transfer_attended(chan_alice, chan_david);
+ if (ast_bridge_transfer_attended(chan_alice, chan_david)) {
+ ast_test_status_update(test, "Attended transfer failed!\n");
+ return AST_TEST_FAIL;
+ }
do_sleep();
BRIDGE_EXIT_EVENT_PEER(chan_charlie, bridge2, "CELTestChannel/David");
BRIDGE_ENTER_EVENT_PEER(chan_charlie, bridge1, "CELTestChannel/Bob,CELTestChannel/Alice");
diff --git a/tests/test_config.c b/tests/test_config.c
index f9e9a6f48..a8a83b2b0 100644
--- a/tests/test_config.c
+++ b/tests/test_config.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#include "asterisk/frame.h"
#include "asterisk/utils.h"
#include "asterisk/logger.h"
+#include "asterisk/format_cap.h"
#define CONFIG_FILE "test_config.conf"
@@ -627,7 +628,6 @@ struct test_item {
struct ast_sockaddr sockaddropt;
int boolopt;
struct ast_ha *aclopt;
- struct ast_codec_pref codecprefopt;
struct ast_format_cap *codeccapopt;
unsigned int customopt:1;
};
@@ -653,9 +653,7 @@ static void test_item_destructor(void *obj)
{
struct test_item *item = obj;
ast_string_field_free_memory(item);
- if (item->codeccapopt) {
- ast_format_cap_destroy(item->codeccapopt);
- }
+ ao2_cleanup(item->codeccapopt);
if (item->aclopt) {
ast_free_ha(item->aclopt);
}
@@ -671,7 +669,7 @@ static void *test_item_alloc(const char *cat)
ao2_ref(item, -1);
return NULL;
}
- if (!(item->codeccapopt = ast_format_cap_alloc(0))) {
+ if (!(item->codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ao2_ref(item, -1);
return NULL;
}
@@ -821,7 +819,7 @@ AST_TEST_DEFINE(config_options_test)
aco_option_register(&cfg_info, "boolflag3", ACO_EXACT, config_test_conf.types, BOOLFLAG3_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG3);
aco_option_register(&cfg_info, "aclpermitopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 1, FLDSET(struct test_item, aclopt));
aco_option_register(&cfg_info, "acldenyopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 0, FLDSET(struct test_item, aclopt));
- aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt));
+ aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codeccapopt));
aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt));
aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0);
aco_option_register_deprecated(&cfg_info, "permit", config_test_conf.types, "aclpermitopt");
@@ -855,11 +853,11 @@ AST_TEST_DEFINE(config_options_test)
ast_sockaddr_parse(&acl_allow, "1.2.3.4", PARSE_PORT_FORBID);
ast_sockaddr_parse(&acl_fail, "1.1.1.1", PARSE_PORT_FORBID);
- defaults.codeccapopt = ast_format_cap_alloc(0);
- ast_parse_allow_disallow(&defaults.codecprefopt, defaults.codeccapopt, CODEC_DEFAULT, 1);
+ defaults.codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_update_by_allow_disallow(defaults.codeccapopt, CODEC_DEFAULT, 1);
- configs.codeccapopt = ast_format_cap_alloc(0);
- ast_parse_allow_disallow(&configs.codecprefopt, configs.codeccapopt, CODEC_CONFIG, 1);
+ configs.codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ ast_format_cap_update_by_allow_disallow(configs.codeccapopt, CODEC_CONFIG, 1);
ast_string_field_init(&defaults, 128);
ast_string_field_init(&configs, 128);
@@ -907,10 +905,13 @@ AST_TEST_DEFINE(config_options_test)
res = AST_TEST_FAIL;
}
if (!ast_format_cap_identical(arr[x]->codeccapopt, control->codeccapopt)) {
- char buf1[128], buf2[128];
- ast_getformatname_multiple(buf1, sizeof(buf1), arr[x]->codeccapopt);
- ast_getformatname_multiple(buf2, sizeof(buf2), control->codeccapopt);
- ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n", buf1, buf2, x);
+ struct ast_str *codec_buf1 = ast_str_alloca(64);
+ struct ast_str *codec_buf2 = ast_str_alloca(64);
+
+ ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n",
+ ast_format_cap_get_names(arr[x]->codeccapopt, &codec_buf1),
+ ast_format_cap_get_names(control->codeccapopt, &codec_buf2),
+ x);
res = AST_TEST_FAIL;
}
if (strcasecmp(arr[x]->stropt, control->stropt)) {
@@ -925,8 +926,10 @@ AST_TEST_DEFINE(config_options_test)
}
ast_free_ha(configs.aclopt);
- ast_format_cap_destroy(defaults.codeccapopt);
- ast_format_cap_destroy(configs.codeccapopt);
+ ao2_cleanup(defaults.codeccapopt);
+ defaults.codeccapopt = NULL;
+ ao2_cleanup(configs.codeccapopt);
+ configs.codeccapopt = NULL;
ast_string_field_free_memory(&defaults);
ast_string_field_free_memory(&configs);
return res;
diff --git a/tests/test_core_codec.c b/tests/test_core_codec.c
new file mode 100644
index 000000000..499e633df
--- /dev/null
+++ b/tests/test_core_codec.c
@@ -0,0 +1,369 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Core Codec API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+
+static struct ast_codec known_unknown = {
+ .name = "unit_test",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec doubly = {
+ .name = "unit_test_double",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec unknown = {
+ .name = "unit_test_unknown",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_UNKNOWN,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_without_rate = {
+ .name = "unit_test_audio_without_rate",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_get = {
+ .name = "unit_test_audio_get",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_get_unknown = {
+ .name = "unit_test_audio_get_unknown",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+static struct ast_codec audio_get_id = {
+ .name = "unit_test_audio_get_id",
+ .description = "Unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+AST_TEST_DEFINE(codec_register)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test registration of a core codec that is known to be unknown";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&known_unknown)) {
+ ast_test_status_update(test, "Unsuccessfully registered a codec that is known to be unknown\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_register_twice)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register_twice";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test double registration of a core codec to confirm it fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&doubly)) {
+ ast_test_status_update(test, "Unsuccessfully registered a codec that is known to be unknown\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_codec_register(&doubly)) {
+ ast_test_status_update(test, "Successfully registered a codec twice\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_register_unknown)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register_unknown";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test that registration of an unknown codec type fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!ast_codec_register(&unknown)) {
+ ast_test_status_update(test, "Successfully registered a codec with an unknown media type\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_register_audio_no_sample_rate)
+{
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_register_audio_no_sample_rate";
+ info->category = "/main/core_codec/";
+ info->summary = "codec registration unit test";
+ info->description =
+ "Test that registration of an audio codec without sample rate fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!ast_codec_register(&audio_without_rate)) {
+ ast_test_status_update(test, "Successfully registered an audio codec without a sample rate\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a known codec succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&audio_get)) {
+ ast_test_status_update(test, "Unsucessfully registered a codec for getting\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("unit_test_audio_get", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n");
+ return AST_TEST_FAIL;
+ } else if (strcmp(codec->name, audio_get.name)) {
+ ast_test_status_update(test, "Name of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->type != audio_get.type) {
+ ast_test_status_update(test, "Type of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->sample_rate != audio_get.sample_rate) {
+ ast_test_status_update(test, "Sample rate of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get_unregistered)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get_unregistered";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a codec that is not registered fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("goats", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (codec) {
+ ast_test_status_update(test, "Successfully got a codec named '%s' when getting a codec named 'goats'\n",
+ codec->name);
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get_unknown)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get_unknown";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a known codec using name and unknown type succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&audio_get_unknown)) {
+ ast_test_status_update(test, "Unsucessfully registered a codec for getting\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("unit_test_audio_get_unknown", AST_MEDIA_TYPE_UNKNOWN, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n");
+ return AST_TEST_FAIL;
+ } else if (strcmp(codec->name, audio_get_unknown.name)) {
+ ast_test_status_update(test, "Name of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->type != audio_get_unknown.type) {
+ ast_test_status_update(test, "Type of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ } else if (codec->sample_rate != audio_get_unknown.sample_rate) {
+ ast_test_status_update(test, "Sample rate of retrieved codec does not match registered codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(codec_get_id)
+{
+ RAII_VAR(struct ast_codec *, named, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "codec_get_unknown";
+ info->category = "/main/core_codec/";
+ info->summary = "codec get unit test";
+ info->description =
+ "Test that getting of a known codec using name and unknown type succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (ast_codec_register(&audio_get_id)) {
+ ast_test_status_update(test, "Unsucessfully registered a codec for getting\n");
+ return AST_TEST_FAIL;
+ }
+
+ named = ast_codec_get("unit_test_audio_get_id", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!named) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get_by_id(named->id);
+ if (!codec) {
+ ast_test_status_update(test, "Unsuccessfully retrieved a codec using id of a named codec we just got\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(codec_register);
+ AST_TEST_UNREGISTER(codec_register_twice);
+ AST_TEST_UNREGISTER(codec_register_unknown);
+ AST_TEST_UNREGISTER(codec_register_audio_no_sample_rate);
+ AST_TEST_UNREGISTER(codec_get);
+ AST_TEST_UNREGISTER(codec_get_unregistered);
+ AST_TEST_UNREGISTER(codec_get_unknown);
+ AST_TEST_UNREGISTER(codec_get_id);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(codec_register);
+ AST_TEST_REGISTER(codec_register_twice);
+ AST_TEST_REGISTER(codec_register_unknown);
+ AST_TEST_REGISTER(codec_register_audio_no_sample_rate);
+ AST_TEST_REGISTER(codec_get);
+ AST_TEST_REGISTER(codec_get_unregistered);
+ AST_TEST_REGISTER(codec_get_unknown);
+ AST_TEST_REGISTER(codec_get_id);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core codec API test module");
diff --git a/tests/test_core_format.c b/tests/test_core_format.c
new file mode 100644
index 000000000..2ae944bb3
--- /dev/null
+++ b/tests/test_core_format.c
@@ -0,0 +1,975 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Core Format API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+
+#define TEST_CATEGORY "/main/core_format/"
+
+static void test_core_format_destroy(struct ast_format *format);
+static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst);
+static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2);
+static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2);
+static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value);
+static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes);
+static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str);
+
+/*! \brief A format attribute 'module' used by the unit tests */
+static struct ast_format_interface test_core_format_attr = {
+ .format_destroy = &test_core_format_destroy,
+ .format_clone = &test_core_format_clone,
+ .format_cmp = &test_core_format_cmp,
+ .format_get_joint = &test_core_format_get_joint,
+ .format_attribute_set = &test_core_format_attribute_set,
+ .format_parse_sdp_fmtp = &test_core_format_parse_sdp_fmtp,
+ .format_generate_sdp_fmtp = &test_core_format_generate_sdp_fmtp,
+};
+
+/*! \brief A test piece of data to associate with \ref test_core_format_attr */
+struct test_core_format_pvt {
+ /*! Some data field */
+ int field_one;
+ /*! Another arbitrary data field */
+ int field_two;
+};
+
+/*! \brief A test codec for these unit tests. Should be used with \c test_core_format */
+static struct ast_codec test_core_format_codec = {
+ .name = "test_core_format_codec",
+ .description = "Unit test codec used by test_core_format",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+};
+
+/*! \brief Tracking object used to verify format attribute callbacks */
+struct callbacks_called {
+ /*! Number of times \ref test_core_format_destroy was called */
+ int format_destroy;
+ /*! Number of times \ref test_core_format_clone was called */
+ int format_clone;
+ /*! Number of times \ref test_core_format_cmp was called */
+ int format_cmp;
+ /*! Number of times \ref test_core_format_get_joint was called */
+ int format_get_joint;
+ /*! Number of times \ref test_core_format_attribute_set was called */
+ int format_attribute_set;
+ /*! Number of times \ref test_core_format_parse_sdp_fmtp was called */
+ int format_parse_sdp_fmtp;
+ /*! Number of times \ref test_core_format_generate_sdp_fmtp was called */
+ int format_generate_sdp_fmtp;
+};
+
+/*! \brief A global tracking object. Cleared out by the test init cb */
+static struct callbacks_called test_callbacks_called;
+
+/*! \brief Format attribute callback for when format attributes are to be destroyed */
+static void test_core_format_destroy(struct ast_format *format)
+{
+ struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format);
+
+ ast_free(pvt);
+ ++test_callbacks_called.format_destroy;
+}
+
+/*! \brief Format attribute callback called during format cloning */
+static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ struct test_core_format_pvt *pvt = ast_format_get_attribute_data(src);
+ struct test_core_format_pvt *new_pvt;
+
+ new_pvt = ast_calloc(1, sizeof(*new_pvt));
+ if (!new_pvt) {
+ return -1;
+ }
+
+ if (pvt) {
+ *new_pvt = *pvt;
+ }
+ ast_format_set_attribute_data(dst, new_pvt);
+
+ ++test_callbacks_called.format_clone;
+
+ return 0;
+}
+
+/*! \brief Format attribute callback called during format comparison */
+static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1);
+ struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2);
+
+ ++test_callbacks_called.format_cmp;
+ if (pvt1 == pvt2) {
+ return AST_FORMAT_CMP_EQUAL;
+ }
+
+ if ((!pvt1 && pvt2 && (pvt2->field_one != 0 || pvt2->field_two != 0))
+ || (pvt1 && !pvt2 && (pvt1->field_one != 0 || pvt1->field_two != 0))) {
+ return AST_FORMAT_CMP_NOT_EQUAL;
+ }
+
+ if (pvt1 && pvt2) {
+ if (!memcmp(pvt1, pvt2, sizeof(*pvt1))) {
+ return AST_FORMAT_CMP_EQUAL;
+ } else {
+ return AST_FORMAT_CMP_NOT_EQUAL;
+ }
+ }
+
+ return AST_FORMAT_CMP_EQUAL;
+}
+
+/*!
+ * \brief Format attribute callback called during joint format capability
+ * \note Our test will assume the max of attributes \c field_one and \c field_two
+ */
+static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2)
+{
+ struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1);
+ struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2);
+ struct ast_format *joint;
+ struct test_core_format_pvt *joint_pvt;
+
+ joint = ast_format_clone(format1);
+ if (!joint) {
+ return NULL;
+ }
+ joint_pvt = ast_format_get_attribute_data(joint);
+
+ joint_pvt->field_one = MAX(pvt1 ? pvt1->field_one : 0, pvt2 ? pvt2->field_one : 0);
+ joint_pvt->field_two = MAX(pvt2 ? pvt2->field_two : 0, pvt2 ? pvt2->field_two : 0);
+
+ ++test_callbacks_called.format_get_joint;
+
+ return joint;
+}
+
+/*! \brief Format attribute callback for setting an attribute on a format */
+static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
+{
+ struct ast_format *clone = ast_format_clone(format);
+ struct test_core_format_pvt *clone_pvt;
+
+ if (!clone) {
+ return NULL;
+ }
+ clone_pvt = ast_format_get_attribute_data(clone);
+
+ if (!strcmp(name, "one")) {
+ clone_pvt->field_one = atoi(value);
+ } else if (!strcmp(name, "two")) {
+ clone_pvt->field_two = atoi(value);
+ }
+ ++test_callbacks_called.format_attribute_set;
+
+ return clone;
+}
+
+/*! \brief Format attribute callback to construct a format from an SDP fmtp line */
+static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
+{
+ struct ast_format *clone = ast_format_clone(format);
+ struct test_core_format_pvt *pvt;
+
+ if (!clone) {
+ return NULL;
+ }
+
+ pvt = ast_format_get_attribute_data(clone);
+
+ if (sscanf(attributes, "one=%d;two=%d", &pvt->field_one, &pvt->field_two) != 2) {
+ ao2_ref(clone, -1);
+ return NULL;
+ }
+
+ ++test_callbacks_called.format_parse_sdp_fmtp;
+ return clone;
+}
+
+/*! \brief Format attribute callback to generate an SDP fmtp line from a format */
+static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
+{
+ struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format);
+
+ if (!pvt) {
+ return;
+ }
+
+ ast_str_append(str, 0, "a=fmtp:%d one=%d;two=%d\r\n", payload, pvt->field_one, pvt->field_two);
+
+ ++test_callbacks_called.format_generate_sdp_fmtp;
+}
+
+AST_TEST_DEFINE(format_create)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format creation unit test";
+ info->description =
+ "Test creation of a format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ao2_ref(format, -1);
+ format = ast_format_create_named("super_ulaw", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_create_attr)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format creation w/ attributes unit test";
+ info->description =
+ "Test creation of a format with attributes";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format_w_attr = ast_format_attribute_set(format, "one", "1");
+ if (!format_w_attr) {
+ ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format_w_attr) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cmp(format, format_w_attr) == AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Format with attributes should not be equal to format without attributes\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 1);
+ ast_test_validate(test, test_callbacks_called.format_cmp == 1);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_clone)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, clone, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format cloning unit test";
+ info->description =
+ "Test cloning of a format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format_w_attr = ast_format_attribute_set(format, "one", "1");
+ if (!format_w_attr) {
+ ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(format_w_attr) != codec->id) {
+ ast_test_status_update(test, "Created format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ /* Test cloning a format without attributes */
+ clone = ast_format_clone(format);
+ if (!clone) {
+ ast_test_status_update(test, "Could not create cloned format\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(clone) != codec->id) {
+ ast_test_status_update(test, "Cloned format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ } else if (clone == format) {
+ ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cmp(clone, format) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Cloned format is not the same as its original format\n");
+ return AST_TEST_FAIL;
+ }
+ ao2_ref(clone, -1);
+
+ /* Test cloning a format with attributes */
+ clone = ast_format_clone(format_w_attr);
+ if (!clone) {
+ ast_test_status_update(test, "Could not create cloned format\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(clone) != codec->id) {
+ ast_test_status_update(test, "Cloned format does not contain provided codec\n");
+ return AST_TEST_FAIL;
+ } else if (clone == format_w_attr) {
+ ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cmp(clone, format_w_attr) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Cloned format is not the same as its original format\n");
+ return AST_TEST_FAIL;
+ }
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 1);
+ ast_test_validate(test, test_callbacks_called.format_clone == 3);
+ ast_test_validate(test, test_callbacks_called.format_cmp == 2);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cmp_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, named, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format comparison unit test";
+ info->description =
+ "Test comparison of two different formats with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ named = ast_format_create_named("super_ulaw", codec);
+ if (!named) {
+ ast_test_status_update(test, "Could not create named format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Two formats that are the same compared as not being equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, named) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Two formats that are the same compared as not being equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cmp_different_codec)
+{
+ RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format comparison unit test";
+ info->description =
+ "Test comparison of two different formats with different codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!first_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(first_codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!second_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(second_codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, second) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_test_status_update(test, "Two formats that have different codecs did not compare as being not equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_attr_cmp_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format with attributes comparison unit test";
+ info->description =
+ "Test comparison of two different formats with attributes with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ original = ast_format_create(codec);
+ if (!original) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_attribute_set(original, "one", "1");
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format with attributes\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_attribute_set(original, "two", "1");
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format with attributes\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cmp(first, second) == AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Formats with different attributes were compared to be equal when they should not\n");
+ return AST_TEST_FAIL;
+ }
+
+ ao2_ref(second, -1);
+ second = ast_format_attribute_set(original, "one", "1");
+
+ if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) {
+ ast_test_status_update(test, "Formats with the same attributes should be equal\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 3);
+ ast_test_validate(test, test_callbacks_called.format_cmp == 2);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_joint_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Joint format unit test";
+ info->description =
+ "Test joint format creation using two different formats with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ joint = ast_format_joint(first, second);
+ if (!joint) {
+ ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(joint) != codec->id) {
+ ast_test_status_update(test, "Returned joint format does not contain expected codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_attr_joint_same_codec)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
+ struct ast_str *fmtp = ast_str_alloca(64);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Joint format attribute unit test";
+ info->description =
+ "Test joint format creation using two different formats with attributes and with same codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ original = ast_format_create(codec);
+ if (!original) {
+ ast_test_status_update(test, "Could not create format from test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_attribute_set(original, "one", "2");
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_attribute_set(original, "one", "5");
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ joint = ast_format_joint(first, second);
+ if (!joint) {
+ ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_get_codec_id(joint) != codec->id) {
+ ast_test_status_update(test, "Returned joint format does not contain expected codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_generate_sdp_fmtp(joint, 100, &fmtp);
+ ast_test_validate(test, strcmp("a=fmtp:100 one=5;two=0\r\n", ast_str_buffer(fmtp)) == 0);
+
+ ast_test_validate(test, test_callbacks_called.format_attribute_set == 2);
+ ast_test_validate(test, test_callbacks_called.format_get_joint == 1);
+ ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_joint_different_codec)
+{
+ RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Joint format unit test";
+ info->description =
+ "Test that there is no joint format between two different formats with different codec";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!first_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ first = ast_format_create(first_codec);
+ if (!first) {
+ ast_test_status_update(test, "Could not create first format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!second_codec) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ second = ast_format_create(second_codec);
+ if (!second) {
+ ast_test_status_update(test, "Could not create second format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ joint = ast_format_joint(first, second);
+ if (joint) {
+ ast_test_status_update(test, "Got a joint format between two formats with different codecs\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_copy)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, copy, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format copying unit test";
+ info->description =
+ "Test copying of a format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ copy = ao2_bump(format);
+ if (!copy) {
+ ast_test_status_update(test, "Copying of a just created format failed\n");
+ return AST_TEST_FAIL;
+ } else if (copy != format) {
+ ast_test_status_update(test, "Copying of a format returned a new format instead of the same one\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_attribute_set_without_interface)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format attribute setting unit test";
+ info->description =
+ "Test that attribute setting on a format without an interface fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_format_attribute_set(format, "bees", "cool")) {
+ ast_test_status_update(test, "Successfully set an attribute on a format without an interface\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_parse_sdp_fmtp_without_interface)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format sdp parse unit test";
+ info->description =
+ "Test that sdp parsing on a format without an interface fails";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ generated = ast_format_parse_sdp_fmtp(format, "tacos");
+ if (generated != format) {
+ ast_test_status_update(test, "Successfully parsed SDP on a format without an interface\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_parse_and_generate_sdp_fmtp)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup);
+ struct ast_str *fmtp = ast_str_alloca(64);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Format sdp parse/generate unit test";
+ info->description =
+ "Test that sdp parsing and generation on a format with an interface succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ generated = ast_format_parse_sdp_fmtp(format, "one=1000;two=256");
+ if (format == generated) {
+ ast_test_status_update(test, "Failed to parse SDP on a format without an interface\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_generate_sdp_fmtp(generated, 8, &fmtp);
+
+ ast_test_validate(test, strcmp("a=fmtp:8 one=1000;two=256\r\n", ast_str_buffer(fmtp)) == 0);
+ ast_test_validate(test, test_callbacks_called.format_parse_sdp_fmtp == 1);
+ ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1);
+
+ return AST_TEST_PASS;
+}
+
+static int test_core_format_init(struct ast_test_info *info, struct ast_test *test)
+{
+ memset(&test_callbacks_called, 0, sizeof(test_callbacks_called));
+
+ return 0;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(format_create);
+ AST_TEST_UNREGISTER(format_create_attr);
+ AST_TEST_UNREGISTER(format_clone);
+ AST_TEST_UNREGISTER(format_cmp_same_codec);
+ AST_TEST_UNREGISTER(format_attr_cmp_same_codec);
+ AST_TEST_UNREGISTER(format_cmp_different_codec);
+ AST_TEST_UNREGISTER(format_joint_same_codec);
+ AST_TEST_UNREGISTER(format_attr_joint_same_codec);
+ AST_TEST_UNREGISTER(format_joint_different_codec);
+ AST_TEST_UNREGISTER(format_copy);
+ AST_TEST_UNREGISTER(format_attribute_set_without_interface);
+ AST_TEST_UNREGISTER(format_parse_sdp_fmtp_without_interface);
+ AST_TEST_UNREGISTER(format_parse_and_generate_sdp_fmtp);
+
+ return 0;
+}
+
+static int load_module(void)
+{
+ /* Test codec/format interface used by this module */
+ if (ast_codec_register(&test_core_format_codec)) {
+ ast_log(AST_LOG_ERROR, "Failed to register test_core_format_codec\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ if (ast_format_interface_register("test_core_format_codec", &test_core_format_attr)) {
+ ast_log(AST_LOG_ERROR, "Failed to register format interface for test_core_format_codec\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ AST_TEST_REGISTER(format_create);
+ AST_TEST_REGISTER(format_create_attr);
+ AST_TEST_REGISTER(format_clone);
+ AST_TEST_REGISTER(format_cmp_same_codec);
+ AST_TEST_REGISTER(format_attr_cmp_same_codec);
+ AST_TEST_REGISTER(format_cmp_different_codec);
+ AST_TEST_REGISTER(format_joint_same_codec);
+ AST_TEST_REGISTER(format_attr_joint_same_codec);
+ AST_TEST_REGISTER(format_joint_different_codec);
+ AST_TEST_REGISTER(format_copy);
+ AST_TEST_REGISTER(format_attribute_set_without_interface);
+ AST_TEST_REGISTER(format_parse_sdp_fmtp_without_interface);
+ AST_TEST_REGISTER(format_parse_and_generate_sdp_fmtp);
+
+ ast_test_register_init(TEST_CATEGORY, &test_core_format_init);
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core format API test module");
diff --git a/tests/test_format_api.c b/tests/test_format_api.c
deleted file mode 100644
index 6cc349570..000000000
--- a/tests/test_format_api.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2010, Digium, Inc.
- *
- * David Vossel <dvossel@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- * \brief Tests for the ast_event API
- *
- * \author David Vossel <dvossel@digium.com>
- *
- * \ingroup tests
- *
- */
-
-/*** MODULEINFO
- <depend>TEST_FRAMEWORK</depend>
- <support_level>core</support_level>
- ***/
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/module.h"
-#include "asterisk/test.h"
-#include "asterisk/format.h"
-#include "asterisk/format_cap.h"
-#include "asterisk/strings.h"
-
-/*! These are the keys for accessing attributes */
-enum test_attr_keys {
- TEST_ATTR_KEY_SAMP_RATE,
- TEST_ATTR_KEY_STRING,
-};
-
-/*! These are the values for the TEST_ATTR_KEY_SAMP_RATE key */
-enum test_attr_vals_samp {
- TEST_ATTR_VAL_SAMP_8KHZ = (1 << 0),
- TEST_ATTR_VAL_SAMP_12KHZ = (1 << 1),
- TEST_ATTR_VAL_SAMP_16KHZ = (1 << 2),
- TEST_ATTR_VAL_SAMP_32KHZ = (1 << 3),
- TEST_ATTR_VAL_SAMP_48KHZ = (1 << 4),
-};
-
-/*! This is the attribute structure used for our test interface. */
-struct test_attr {
- enum test_attr_vals_samp samp_flags;
- char string[32];
-};
-
-static enum ast_format_cmp_res test_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
-{
- struct test_attr *attr1 = (struct test_attr *) fattr1;
- struct test_attr *attr2 = (struct test_attr *) fattr2;
-
- if ((attr1->samp_flags == attr2->samp_flags) &&
- !(strcmp(attr1->string, attr2->string))) {
- return AST_FORMAT_CMP_EQUAL;
- }
- if ((attr1->samp_flags != (attr1->samp_flags & attr2->samp_flags)) ||
- (!ast_strlen_zero(attr1->string) && strcmp(attr1->string, attr2->string))) {
- return AST_FORMAT_CMP_NOT_EQUAL;
- }
- return AST_FORMAT_CMP_SUBSET;
-}
-
-static int test_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
-{
- struct test_attr *attr1 = (struct test_attr *) fattr1;
- struct test_attr *attr2 = (struct test_attr *) fattr2;
- struct test_attr *attr_res = (struct test_attr *) result;
- int joint = -1;
-
- attr_res->samp_flags = (attr1->samp_flags & attr2->samp_flags);
-
- if (attr_res->samp_flags) {
- joint = 0;
- }
-
- if (!strcmp(attr1->string, attr2->string)) {
- ast_copy_string(attr_res->string, attr1->string, sizeof(attr_res->string));
- joint = 0;
- }
-
- return joint;
-}
-
-static void test_set(struct ast_format_attr *fattr, va_list ap)
-{
- enum test_attr_keys key;
- struct test_attr *attr = (struct test_attr *) fattr;
- char *string;
-
- for (key = va_arg(ap, int);
- key != AST_FORMAT_ATTR_END;
- key = va_arg(ap, int))
- {
- switch (key) {
- case TEST_ATTR_KEY_SAMP_RATE:
- attr->samp_flags = (va_arg(ap, int) | attr->samp_flags);
- break;
- case TEST_ATTR_KEY_STRING:
- string = va_arg(ap, char *);
- if (!ast_strlen_zero(string)) {
- ast_copy_string(attr->string, string, sizeof(attr->string));
- }
- break;
- default:
- ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
- }
- }
-}
-
-/*! uLaw does not actually have any attributes associated with it.
- * This is just for the purpose of testing. We are guaranteed there
- * will never exist a interface for uLaw already. */
-static struct ast_format_attr_interface test_interface = {
- .id = AST_FORMAT_TESTLAW,
- .format_attr_cmp = test_cmp,
- .format_attr_get_joint = test_getjoint,
- .format_attr_set = test_set
-};
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(format_test1)
-{
- struct ast_format format1 = { 0, };
- struct ast_format format2 = { 0, };
- struct ast_format joint = { 0, };
-
- switch (cmd) {
- case TEST_INIT:
- info->name = "ast_format_test1";
- info->category = "/main/format/";
- info->summary = "Test ast_format with attributes.";
- info->description =
- "This test exercises the Ast Format API by creating and registering "
- "a custom ast_format_attr_interface and performing various function "
- "calls on ast_formats using the interface. ";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- if (ast_format_attr_reg_interface(&test_interface)) {
- ast_test_status_update(test, "test_interface failed to register.\n");
- return AST_TEST_FAIL;
- }
-
- /* set a format with a single attribute. */
- ast_format_set(&format1, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- AST_FORMAT_ATTR_END);
- if (ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) {
- ast_test_status_update(test, "format1 did not set number attribute correctly.\n");
- return AST_TEST_FAIL;
- }
- if (!ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, AST_FORMAT_ATTR_END)) {
- ast_test_status_update(test, "format1 did not determine isset on number correctly. \n");
- return AST_TEST_FAIL;
- }
-
- /* append the string attribute to a format with previous attributes already set */
- ast_format_append(&format1,
- TEST_ATTR_KEY_STRING,"String",
- AST_FORMAT_ATTR_END);
- if (ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "String", AST_FORMAT_ATTR_END)) {
- ast_test_status_update(test, "format1 did not set string attribute correctly.\n");
- return AST_TEST_FAIL;
- }
- if (!ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "Not a string", AST_FORMAT_ATTR_END)) {
- ast_test_status_update(test, "format1 did not determine isset on string correctly. \n");
- return AST_TEST_FAIL;
- }
-
- /* set format2 with both STRING and NUMBER at the same time */
- ast_format_set(&format2, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_STRING, "MOOOoo",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END);
- /* perform isset with multiple key value pairs. */
-
- if (ast_format_isset(&format2,
- TEST_ATTR_KEY_STRING, "MOOOoo",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END)) {
-
- ast_test_status_update(test, "format2 did not set attributes correctly.\n");
- return AST_TEST_FAIL;
- }
- if (!ast_format_isset(&format2,
- TEST_ATTR_KEY_STRING, "WRONG",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END)) {
-
- ast_test_status_update(test, "format2 did not deterine isset correctly.\n");
- return AST_TEST_FAIL;
- }
-
- /* get joint attributes between format1 and format2. */
- if (ast_format_joint(&format1, &format2, &joint)) {
- ast_test_status_update(test, "failed to get joint attributes.\n");
- return AST_TEST_FAIL;
- }
- if (ast_format_isset(&joint, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) {
- ast_test_status_update(test, "joint attribute was not what we expected.\n");
- return AST_TEST_FAIL;
- }
-
- /* exercise compare functions */
- if (ast_format_cmp(&format1, &format2) != AST_FORMAT_CMP_NOT_EQUAL) {
- ast_test_status_update(test, "cmp 1 failed.\n");
- return AST_TEST_FAIL;
- }
- if (ast_format_cmp(&format1, &format1) != AST_FORMAT_CMP_EQUAL) {
- ast_test_status_update(test, "cmp 2 failed.\n");
- return AST_TEST_FAIL;
- }
- if (ast_format_cmp(&joint, &format1) != AST_FORMAT_CMP_SUBSET) {
- ast_test_status_update(test, "cmp 3 failed.\n");
- return AST_TEST_FAIL;
- }
-
- /* unregister interface */
- if (ast_format_attr_unreg_interface(&test_interface)) {
- ast_test_status_update(test, "test_interface failed to unregister.\n");
- return AST_TEST_FAIL;
- }
-
- return AST_TEST_PASS;
-}
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(format_test2)
-{
- struct ast_format format = { 0, };
-
- switch (cmd) {
- case TEST_INIT:
- info->name = "ast_format_test2";
- info->category = "/main/format/";
- info->summary = "Test ast_format unique id and category system";
- info->description =
- "This test exercises the Ast Format unique id and category "
- "system by creating formats of various types and verifying "
- "their category matches what we expect.";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- ast_format_set(&format, AST_FORMAT_ULAW, 0);
- if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_AUDIO) {
- ast_test_status_update(test, "audio type failed\n");
- return AST_TEST_FAIL;
- }
-
- ast_format_set(&format, AST_FORMAT_H264, 0);
- if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_VIDEO) {
- ast_test_status_update(test, "video type failed\n");
- return AST_TEST_FAIL;
- }
-
- ast_format_set(&format, AST_FORMAT_JPEG, 0);
- if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_IMAGE) {
- ast_test_status_update(test, "image type failed\n");
- return AST_TEST_FAIL;
- }
-
- ast_format_set(&format, AST_FORMAT_T140, 0);
- if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_TEXT) {
- ast_test_status_update(test, "text type failed\n");
- return AST_TEST_FAIL;
- }
-
- return AST_TEST_PASS;
-}
-
-static int container_test1_helper(struct ast_format_cap *cap1, struct ast_format_cap *cap2, struct ast_test *test)
-{
-
- int res = AST_TEST_PASS;
- struct ast_format_cap *cap_joint = NULL;
- struct ast_format tmpformat;
-
- if (ast_format_attr_reg_interface(&test_interface)) {
- ast_test_status_update(test, "test_interface failed to register.\n");
- ast_format_cap_destroy(cap1);
- ast_format_cap_destroy(cap2);
- return AST_TEST_FAIL;
- }
-
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_G722, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H263, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0));
- ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_STRING, "testing caps hooray",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ,
- AST_FORMAT_ATTR_END));
-
- /* Test is compatible */
- if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) ||
- !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) ||
- !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) ||
- !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) ||
- !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) ||
- !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) {
- ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 1.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* Test things that are not compatible */
- if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX, 0)) ||
- ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX16, 0)) ||
- ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H261, 0))) {
- ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 2.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* Test compatiblity with format with attributes. */
- if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_STRING, "testing caps hooray",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END))) {
-
- ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 3.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- AST_FORMAT_ATTR_END))) {
-
- ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 4.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, /* 48khz was not compatible, so this should fail iscompatible check */
- AST_FORMAT_ATTR_END))) {
-
- ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 5.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* Lets start testing the functions that compare ast_format_cap objects.
- * Genreate the cap2 object to contain some similar formats as cap1
- * and some different formats as well. */
- ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0));
- ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0));
- ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_H261, 0));
- ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_T140, 0));
- ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_STRING, "testing caps hooray",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ,
- AST_FORMAT_ATTR_END));
-
-
- /* find joint formats between cap1 and cap2 */
- cap_joint = ast_format_cap_joint(cap1, cap2);
-
- if (!cap_joint) {
- ast_test_status_update(test, "failed to create joint capabilities correctly.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- /* determine if cap_joint is what we think it should be */
- if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) ||
- !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) ||
- !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)) ||
- !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_STRING, "testing caps hooray",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- AST_FORMAT_ATTR_END))) {
-
- ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- /* make sure joint cap does not have formats that should not be there */
- if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)) ||
- ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
- TEST_ATTR_KEY_STRING, "testing caps hooray",
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
- TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ,
- AST_FORMAT_ATTR_END))) {
-
- ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* Lets test removing a capability */
- if (ast_format_cap_remove(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) {
- ast_test_status_update(test, "ast_format_cap_remove failed. \n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- /* Lets make sure what we just removed does not still exist */
- if (ast_format_cap_iscompatible(cap_joint, &tmpformat)) {
- ast_test_status_update(test, "ast_format_cap_remove failed 2. \n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- /* Lets test removing a capability by id.*/
- if (ast_format_cap_remove_byid(cap_joint, AST_FORMAT_GSM)) {
- ast_test_status_update(test, "ast_format_cap_remove failed 3. \n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- /* Lets make sure what we just removed does not still exist */
- if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0))) {
- ast_test_status_update(test, "ast_format_cap_remove failed 4. \n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* lets test getting joint formats by type */
- ast_format_cap_destroy(cap_joint);
- if (!(cap_joint = ast_format_cap_get_type(cap1, AST_FORMAT_TYPE_VIDEO))) {
- ast_test_status_update(test, "ast_format_cap_get_type failed.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- /* lets make sure our joint capability structure has what we expect */
- if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) ||
- !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H263, 0))) {
- ast_test_status_update(test, "get_type failed 2.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- /* now make sure joint does not have anything but video */
- if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) ||
- ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) ||
- ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) ||
- ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) ||
- ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) {
- ast_test_status_update(test, "get_type failed 3.\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* now lets remove everythign from cap_joint */
- ast_format_cap_remove_all(cap_joint);
- if (!ast_format_cap_is_empty(cap_joint)) {
- ast_test_status_update(test, "failed to remove all\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* now lets add all by type */
- ast_format_cap_add_all_by_type(cap_joint, AST_FORMAT_TYPE_AUDIO);
- if (ast_format_cap_is_empty(cap_joint)) {
- ast_test_status_update(test, "failed to add all by type AUDIO\n");
- res = AST_TEST_FAIL;
- }
- ast_format_cap_iter_start(cap_joint);
- while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) {
- if (AST_FORMAT_GET_TYPE(tmpformat.id) != AST_FORMAT_TYPE_AUDIO) {
- ast_test_status_update(test, "failed to add all by type AUDIO\n");
- res = AST_TEST_FAIL;
- ast_format_cap_iter_end(cap_joint);
- goto test3_cleanup;
- }
- }
- ast_format_cap_iter_end(cap_joint);
-
- /* test append */
- ast_format_cap_append(cap_joint, cap1);
- ast_format_cap_iter_start(cap1);
- while (!(ast_format_cap_iter_next(cap1, &tmpformat))) {
- if (!ast_format_cap_iscompatible(cap_joint, &tmpformat)) {
- ast_test_status_update(test, "failed to append format capabilities.\n");
- res = AST_TEST_FAIL;
- ast_format_cap_iter_end(cap1);
- goto test3_cleanup;
- }
- }
- ast_format_cap_iter_end(cap1);
-
- /* test copy */
- cap1 = ast_format_cap_destroy(cap1);
- cap1 = ast_format_cap_dup(cap_joint);
- if (!ast_format_cap_identical(cap_joint, cap1)) {
- ast_test_status_update(test, "failed to copy capabilities\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
- /* test remove by type */
- ast_format_cap_remove_bytype(cap_joint, AST_FORMAT_TYPE_AUDIO);
- if (ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_AUDIO)) {
- ast_test_status_update(test, "failed to remove all by type audio\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- if (!ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_TEXT)) { /* it should still have text */
- ast_test_status_update(test, "failed to remove all by type audio\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- ast_format_cap_iter_start(cap_joint);
- while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) {
- if (AST_FORMAT_GET_TYPE(tmpformat.id) == AST_FORMAT_TYPE_AUDIO) {
- ast_test_status_update(test, "failed to remove all by type audio\n");
- res = AST_TEST_FAIL;
- ast_format_cap_iter_end(cap_joint);
- goto test3_cleanup;
- }
- }
- ast_format_cap_iter_end(cap_joint);
-
- /* test add all */
- ast_format_cap_remove_all(cap_joint);
- ast_format_cap_add_all(cap_joint);
- {
- int video = 0, audio = 0, text = 0, image = 0;
- ast_format_cap_iter_start(cap_joint);
- while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) {
- switch (AST_FORMAT_GET_TYPE(tmpformat.id)) {
- case AST_FORMAT_TYPE_AUDIO:
- audio++;
- break;
- case AST_FORMAT_TYPE_VIDEO:
- video++;
- break;
- case AST_FORMAT_TYPE_TEXT:
- text++;
- break;
- case AST_FORMAT_TYPE_IMAGE:
- image++;
- break;
- }
- }
- ast_format_cap_iter_end(cap_joint);
- if (!video || !audio || !text || !image) {
- ast_test_status_update(test, "failed to add all\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
- }
-
- /* test copy2 */
- ast_format_cap_copy(cap2, cap_joint);
- if (!ast_format_cap_identical(cap2, cap_joint)) {
- ast_test_status_update(test, "ast_format_cap_copy failed\n");
- res = AST_TEST_FAIL;
- goto test3_cleanup;
- }
-
-test3_cleanup:
- ast_format_cap_destroy(cap1);
- ast_format_cap_destroy(cap2);
- ast_format_cap_destroy(cap_joint);
-
- /* unregister interface */
- if (ast_format_attr_unreg_interface(&test_interface)) {
- ast_test_status_update(test, "test_interface failed to unregister.\n");
- res = AST_TEST_FAIL;
- }
-
- return res;
-}
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(container_test1_nolock)
-{
- struct ast_format_cap *cap1;
- struct ast_format_cap *cap2;
-
- switch (cmd) {
- case TEST_INIT:
- info->name = "container_test_1_no_locking";
- info->category = "/main/format/";
- info->summary = "Test ast_format and ast_format_cap structures, no locking";
- info->description =
- "This test exercises the Ast Format Capability API by creating "
- "capability structures and performing various API calls on them.";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- cap2 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
-
- if (!cap1 || !cap2) {
- ast_test_status_update(test, "cap alloc failed.\n");
- return AST_TEST_FAIL;
- }
- return container_test1_helper(cap1, cap2, test);
-}
-
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(container_test1_withlock)
-{
- struct ast_format_cap *cap1;
- struct ast_format_cap *cap2;
-
- switch (cmd) {
- case TEST_INIT:
- info->name = "container_test1_with_locking";
- info->category = "/main/format/";
- info->summary = "Test ast_format and ast_format_cap structures, with locking";
- info->description =
- "This test exercises the Ast Format Capability API by creating "
- "capability structures and performing various API calls on them.";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- cap1 = ast_format_cap_alloc(0);
- cap2 = ast_format_cap_alloc(0);
-
- if (!cap1 || !cap2) {
- ast_test_status_update(test, "cap alloc failed.\n");
- return AST_TEST_FAIL;
- }
- return container_test1_helper(cap1, cap2, test);
-}
-
-static int container_test2_no_locking_helper(struct ast_format_cap *cap, struct ast_test *test)
-{
- int num = 0;
- struct ast_format tmpformat = { 0, };
-
- ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0));
- ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0));
- ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_G722, 0));
-
- ast_format_cap_iter_start(cap);
- while (!ast_format_cap_iter_next(cap, &tmpformat)) {
- num++;
- }
- ast_format_cap_iter_end(cap);
-
- ast_format_cap_iter_start(cap);
- while (!ast_format_cap_iter_next(cap, &tmpformat)) {
- num++;
- }
- ast_format_cap_iter_end(cap);
-
- ast_format_cap_destroy(cap);
- ast_test_status_update(test, "%d items iterated over\n", num);
- return (num == 6) ? AST_TEST_PASS : AST_TEST_FAIL;
-
-}
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(container_test2_no_locking)
-{
- struct ast_format_cap *cap;
-
- switch (cmd) {
- case TEST_INIT:
- info->name = "container_test2_no_locking";
- info->category = "/main/format/";
- info->summary = "Test ast_format_cap iterator, no locking";
- info->description =
- "This test exercises the Ast Capability API iterators.";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- if (!cap) {
- ast_test_status_update(test, "alloc failed\n");
- return AST_TEST_FAIL;
- }
- return container_test2_no_locking_helper(cap, test);
-}
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(container_test2_with_locking)
-{
- struct ast_format_cap *cap;
-
- switch (cmd) {
- case TEST_INIT:
- info->name = "container_test2_with_locking";
- info->category = "/main/format/";
- info->summary = "Test ast_format_cap iterator, with locking";
- info->description =
- "This test exercises the Ast Capability API iterators.";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- cap = ast_format_cap_alloc(0);
- if (!cap) {
- ast_test_status_update(test, "alloc failed\n");
- return AST_TEST_FAIL;
- }
- return container_test2_no_locking_helper(cap, test);
-}
-
-
-static int container_test3_helper(int nolocking, struct ast_test *test)
-{
- int x;
- int res = AST_TEST_PASS;
- struct ast_format_cap *cap1;
- struct ast_format_cap *cap2;
- struct ast_format_cap *joint;
-
- for (x = 0; x < 2000; x++) {
- if (nolocking) {
- cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- cap2 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
- } else {
- cap1 = ast_format_cap_alloc(0);
- cap2 = ast_format_cap_alloc(0);
- joint = ast_format_cap_alloc(0);
- }
- if (!cap1 || !cap2 || !joint) {
- ast_test_status_update(test, "cap alloc fail\n");
- return AST_TEST_FAIL;
- }
- ast_format_cap_add_all(cap1);
- ast_format_cap_add_all_by_type(cap2, AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_joint_copy(cap1, cap2, joint);
- if (!(ast_format_cap_identical(cap2, joint))) {
- ast_test_status_update(test, "failed identical test\n");
- res = AST_TEST_FAIL;
- cap1 = ast_format_cap_destroy(cap1);
- cap2 = ast_format_cap_destroy(cap2);
- joint = ast_format_cap_destroy(joint);
- break;
- }
- cap1 = ast_format_cap_destroy(cap1);
- cap2 = ast_format_cap_destroy(cap2);
- joint = ast_format_cap_destroy(joint);
- }
- return res;
-}
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(container_test3_nolock)
-{
- switch (cmd) {
- case TEST_INIT:
- info->name = "container_test3_no_locking";
- info->category = "/main/format/";
- info->summary = "Load Test ast_format_cap no locking.";
- info->description =
- "This test exercises the Ast Capability API and its iterators for the purpose "
- "of measuring performance.";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- return container_test3_helper(1, test);
-}
-
-/*!
- * \internal
- */
-AST_TEST_DEFINE(container_test3_withlock)
-{
- switch (cmd) {
- case TEST_INIT:
- info->name = "container_test3_with_locking";
- info->category = "/main/format/";
- info->summary = "Load Test ast_format_cap with locking.";
- info->description =
- "This test exercises the Ast Capability API and its iterators for the purpose "
- "of measuring performance.";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- return container_test3_helper(0, test);
-}
-
-static int unload_module(void)
-{
- AST_TEST_UNREGISTER(format_test1);
- AST_TEST_UNREGISTER(format_test2);
- AST_TEST_UNREGISTER(container_test1_nolock);
- AST_TEST_UNREGISTER(container_test1_withlock);
- AST_TEST_UNREGISTER(container_test2_no_locking);
- AST_TEST_UNREGISTER(container_test2_with_locking);
- AST_TEST_UNREGISTER(container_test3_nolock);
- AST_TEST_UNREGISTER(container_test3_withlock);
-
- return 0;
-}
-
-static int load_module(void)
-{
- AST_TEST_REGISTER(format_test1);
- AST_TEST_REGISTER(format_test2);
- AST_TEST_REGISTER(container_test1_nolock);
- AST_TEST_REGISTER(container_test1_withlock);
- AST_TEST_REGISTER(container_test2_no_locking);
- AST_TEST_REGISTER(container_test2_with_locking);
- AST_TEST_REGISTER(container_test3_nolock);
- AST_TEST_REGISTER(container_test3_withlock);
-
- return AST_MODULE_LOAD_SUCCESS;
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_format API Tests");
diff --git a/tests/test_format_cache.c b/tests/test_format_cache.c
new file mode 100644
index 000000000..cc1696b70
--- /dev/null
+++ b/tests/test_format_cache.c
@@ -0,0 +1,281 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Format Cache API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cache.h"
+
+AST_TEST_DEFINE(format_cache_set)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_set";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache add unit test";
+ info->description =
+ "Test that adding of a cached format succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@20_1", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_set_duplicate)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_set_duplicate";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache add unit test";
+ info->description =
+ "Test that adding of a cached format multiple times succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@20_2", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Failed to update cached format\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_set_null)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_set_null";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache add unit test";
+ info->description =
+ "Test that adding a NULL or empty format to the cache does not succeed";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Successfully cached a format with an empty name\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_get)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, cached, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_get";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache get unit test";
+ info->description =
+ "Test that getting of a cached format succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@20", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get("ulaw@20");
+ if (!cached) {
+ ast_test_status_update(test, "Failed to retrieve a format we just cached\n");
+ return AST_TEST_FAIL;
+ } else if (cached != format) {
+ ast_test_status_update(test, "Returned cached format does not match format we just added\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cache_get_nonexistent)
+{
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, cached, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cache_get_nonxistent";
+ info->category = "/main/format_cache/";
+ info->summary = "format cache get unit test";
+ info->description =
+ "Test that getting of a non-existent cached format does not succeed";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create_named("ulaw@40", codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cache_set(format)) {
+ ast_test_status_update(test, "Could not add just created format to cache\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get("ulaw@60");
+ if (cached) {
+ ast_test_status_update(test, "Retrieved a cached format when one should not have existed\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get("");
+ if (cached) {
+ ast_test_status_update(test, "Retrieved a cached format when we provided an empty name\n");
+ return AST_TEST_FAIL;
+ }
+
+ cached = ast_format_cache_get(NULL);
+ if (cached) {
+ ast_test_status_update(test, "Retrieved a cached format when we provided a NULL name\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(format_cache_set);
+ AST_TEST_UNREGISTER(format_cache_set_duplicate);
+ AST_TEST_UNREGISTER(format_cache_set_null);
+ AST_TEST_UNREGISTER(format_cache_get);
+ AST_TEST_UNREGISTER(format_cache_get_nonexistent);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(format_cache_set);
+ AST_TEST_REGISTER(format_cache_set_duplicate);
+ AST_TEST_REGISTER(format_cache_set_null);
+ AST_TEST_REGISTER(format_cache_get);
+ AST_TEST_REGISTER(format_cache_get_nonexistent);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Format cache API test module");
diff --git a/tests/test_format_cap.c b/tests/test_format_cap.c
new file mode 100644
index 000000000..38320e635
--- /dev/null
+++ b/tests/test_format_cap.c
@@ -0,0 +1,1479 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Format Capabilities API Unit Tests
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/codec.h"
+#include "asterisk/frame.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
+
+AST_TEST_DEFINE(format_cap_alloc)
+{
+ struct ast_format_cap *caps;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_alloc";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities allocation unit test";
+ info->description =
+ "Test that allocation of a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ ao2_ref(caps, -1);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_single)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding a single format to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format, 42)) {
+ ast_test_status_update(test, "Could not add newly created format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get single format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != format) {
+ ast_test_status_update(test, "Retrieved format is not the same as the one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) {
+ ast_test_status_update(test, "Framing for format in capabilities structure does not match what we provided\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_multiple)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding multiple formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 2) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get first format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != ulaw_format) {
+ ast_test_status_update(test, "First retrieved format is not the ulaw one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) {
+ ast_test_status_update(test, "Framing for ulaw format in capabilities structure does not match what we provided\n");
+ }
+ ao2_ref(retrieved, -1);
+
+ retrieved = ast_format_cap_get_format(caps, 1);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get second format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != alaw_format) {
+ ast_test_status_update(test, "First retrieved format is not the alaw one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 84) {
+ ast_test_status_update(test, "Framing for alaw format in capabilities structure does not match what we provided\n");
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_all_unknown)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding of all formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Added all media formats but no audio formats exist when they should\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Added all media formats but no video formats exist when they should\n");
+ return AST_TEST_FAIL;
+ } else if ((ast_format_cap_count(caps) + 1) != ast_codec_get_max()) {
+ ast_test_status_update(test, "The number of formats in the capabilities structure does not match known number\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_all_audio)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding of all audio formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Added audio media formats but no audio formats exist when they should\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Added only audio media formats but video formats exist when they should not\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_TEXT)) {
+ ast_test_status_update(test, "Added only audio media formats but text formats exist when they should not\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_IMAGE)) {
+ ast_test_status_update(test, "Added only audio media formats but image formats exist when they should not\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_duplicate)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format_named, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities duplication unit test";
+ info->description =
+ "Test that adding a single format multiple times to a capabilities structure results in only a single format";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format_named = ast_format_create_named("ulaw@20", codec);
+ if (!format_named) {
+ ast_test_status_update(test, "Could not create named format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format, 42)) {
+ ast_test_status_update(test, "Could not add newly created format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* Note: regardless of it being a duplicate, ast_format_cap_append should return success */
+ if (ast_format_cap_append(caps, format, 0)) {
+ ast_test_status_update(test, "Adding of duplicate format to capabilities structure failed\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format_named, 0)) {
+ ast_test_status_update(test, "Adding of duplicate named format to capabilities structure failed\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get single format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != format) {
+ ast_test_status_update(test, "Retrieved format is not the same as the one we added\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) {
+ ast_test_status_update(test, "Framing for format in capabilities structure does not match what we provided\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_from_cap)
+{
+ RAII_VAR(struct ast_format_cap *, dst_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, src_caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities append unit test";
+ info->description =
+ "Test that appending video formats from one capabilities structure to another succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ dst_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!dst_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ src_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!src_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(src_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Failed to add all video media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to append formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Successfully appended video formats to destination capabilities but it no longer contains audio formats\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Successfully appended formats but video formats do not exist in destination capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_append_from_cap_duplicate)
+{
+ RAII_VAR(struct ast_format_cap *, dst_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, src_caps, NULL, ao2_cleanup);
+ unsigned int count;
+ unsigned int total_count;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities append duplicate unit test";
+ info->description =
+ "Test that appending capabilities structures multiple times does not result in duplicate formats";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ dst_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!dst_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ src_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!src_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(src_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Failed to add all video media formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ total_count = ast_format_cap_count(src_caps) + ast_format_cap_count(dst_caps);
+
+ if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to append formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Successfully appended video formats to destination capabilities but it no longer contains audio formats\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Successfully appended formats but video formats do not exist in destination capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ count = ast_format_cap_count(dst_caps);
+
+ if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to append duplicate formats to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_test_validate(test, count == ast_format_cap_count(dst_caps));
+ ast_test_validate(test, count == total_count);
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_set_framing)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_set_framing";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities framing unit test";
+ info->description =
+ "Test that global framing on a format capabilities structure is used when it should be";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_set_framing(caps, 160);
+
+ ast_test_validate(test, ast_format_cap_get_framing(caps) == 160);
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_get_format_framing(caps, ulaw_format) != 42) {
+ ast_test_status_update(test, "Added ulaw format to capabilities structure with explicit framing but did not get it back\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_get_format_framing(caps, alaw_format) != ast_format_get_default_ms(alaw_format)) {
+ ast_test_status_update(test, "Added alaw format to capabilities structure with no explicit framing but did not get global back\n");
+ return AST_TEST_FAIL;
+ }
+ ast_test_validate(test, ast_format_cap_get_framing(caps) == ast_format_get_default_ms(alaw_format));
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_single)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_single";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removing a single format from a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!codec) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ format = ast_format_create(codec);
+ if (!format) {
+ ast_test_status_update(test, "Could not create format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, format, 42)) {
+ ast_test_status_update(test, "Could not add newly created format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_remove(caps, format)) {
+ ast_test_status_update(test, "Could not remove format that was just added to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_remove(caps, format)) {
+ ast_test_status_update(test, "Successfully removed a format twice from the capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps)) {
+ ast_test_status_update(test, "Capabilities structure should be empty but instead it contains '%zu' formats\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_multiple)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_multiple";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removing a format from a format capabilities structure containing multiple formats succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_remove(caps, ulaw_format)) {
+ ast_test_status_update(test, "Could not remove the ulaw format we just added to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_count(caps) != 1) {
+ ast_test_status_update(test, "Capabilities structure should contain 1 format but it contains '%zu'\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ retrieved = ast_format_cap_get_format(caps, 0);
+ if (!retrieved) {
+ ast_test_status_update(test, "Attempted to get first format from capabilities structure but got nothing\n");
+ return AST_TEST_FAIL;
+ } else if (retrieved != alaw_format) {
+ ast_test_status_update(test, "First retrieved format is not the alaw one we added\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_bytype)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_bytype";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removal of a specific type of format from a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
+ if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) {
+ ast_test_status_update(test, "Removed all audio type formats from capabilities structure but some remain\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) {
+ ast_test_status_update(test, "Removed audio type formats from capabilities structure but video are gone as well\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_remove_all)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_remove_all";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities removal unit test";
+ info->description =
+ "Test that removal of all formats from a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) {
+ ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
+
+ if (ast_format_cap_count(caps)) {
+ ast_test_status_update(test, "Removed all formats from capabilities structure but some remain\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_get_compatible_format)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, compatible, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_get_compatible_format";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that getting a compatible format from a capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ compatible = ast_format_cap_get_compatible_format(caps, alaw_format);
+ if (compatible) {
+ ast_test_status_update(test, "Retrieved a compatible format from capabilities structure when none should exist\n");
+ return AST_TEST_FAIL;
+ }
+
+ compatible = ast_format_cap_get_compatible_format(caps, ulaw_format);
+ if (!compatible) {
+ ast_test_status_update(test, "Did not retrieve a compatible format from capabilities structure when there should be one\n");
+ return AST_TEST_FAIL;
+ } else if (compatible != ulaw_format) {
+ ast_test_status_update(test, "Compatible format is not the format we added to the capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_iscompatible_format)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_iscompatible_format";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that checking whether a format is compatible with a capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_iscompatible_format(caps, alaw_format) != AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_test_status_update(test, "Alaw format is compatible with capabilities structure when it only contains ulaw\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_iscompatible_format(caps, ulaw_format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_test_status_update(test, "Ulaw format is not compatible with capabilities structure when it should be\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_get_compatible)
+{
+ RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, compatible_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_get_compatible";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that getting the compatible formats between two capabilities structures succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!alaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!ulaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ compatible_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!compatible_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_get_compatible(ulaw_caps, alaw_caps, compatible_caps);
+ if (ast_format_cap_count(compatible_caps)) {
+ ast_test_status_update(test, "A compatible format exists when none should\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_get_compatible(ulaw_caps, ulaw_caps, compatible_caps);
+ if (!ast_format_cap_count(compatible_caps)) {
+ ast_test_status_update(test, "No compatible formats exist when 1 should\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_iscompatible)
+{
+ RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_iscompatible";
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities negotiation unit test";
+ info->description =
+ "Test that checking if there are compatible formats between two capabilities structures succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!alaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!ulaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_iscompatible(ulaw_caps, alaw_caps)) {
+ ast_test_status_update(test, "Two capability structures that should not be compatible are\n");
+ return AST_TEST_FAIL;
+ } else if (!ast_format_cap_iscompatible(ulaw_caps, ulaw_caps)) {
+ ast_test_status_update(test, "Capability structure is not compatible with itself\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_get_names)
+{
+ RAII_VAR(struct ast_format_cap *, empty_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, multi_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ struct ast_str *buffer = ast_str_alloca(128);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "format_cap_get_names";
+ info->category = "/main/format_cap/";
+ info->summary = "Test getting the names of formats";
+ info->description =
+ "Test that obtaining the names from a format capabilities structure\n"
+ "produces the expected output.\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ empty_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!empty_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ multi_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!multi_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!alaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!ulaw_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(multi_caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to multi capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(multi_caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to multi capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ ast_format_cap_get_names(empty_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(nothing)"));
+ ast_format_cap_get_names(ulaw_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(ulaw)"));
+ ast_format_cap_get_names(alaw_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(alaw)"));
+ ast_format_cap_get_names(multi_caps, &buffer);
+ ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(ulaw|alaw)"));
+
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(format_cap_best_by_type)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, h263, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, h263_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, best_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities best by type unit test";
+ info->description =
+ "Test that we can get the best format type out of a capabilities structure";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ h263 = ast_codec_get("h263", AST_MEDIA_TYPE_VIDEO, 0);
+ if (!h263) {
+ ast_test_status_update(test, "Could not retrieve built-in h263 codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ h263_format = ast_format_create(h263);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create h263 format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_format_cap_append(caps, ulaw_format, 0)) {
+ ast_test_status_update(test, "Could not add ulaw format to capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, alaw_format, 0)) {
+ ast_test_status_update(test, "Could not add alaw format to capabilities\n");
+ return AST_TEST_FAIL;
+ } else if (ast_format_cap_append(caps, h263_format, 0)) {
+ ast_test_status_update(test, "Could not add h263 format to capabilities\n");
+ return AST_TEST_FAIL;
+ }
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_test_validate(test, ast_format_cmp(best_format, ulaw_format) == AST_FORMAT_CMP_EQUAL);
+ ao2_ref(best_format, -1);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_AUDIO);
+ ast_test_validate(test, ast_format_cmp(best_format, ulaw_format) == AST_FORMAT_CMP_EQUAL);
+ ao2_ref(best_format, -1);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_VIDEO);
+ ast_test_validate(test, ast_format_cmp(best_format, h263_format) == AST_FORMAT_CMP_EQUAL);
+ ao2_ref(best_format, -1);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_IMAGE);
+ ast_test_validate(test, best_format == NULL);
+
+ best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_TEXT);
+ ast_test_validate(test, best_format == NULL);
+
+ return AST_TEST_PASS;
+}
+
+static int test_law_samples(struct ast_frame *frame)
+{
+ return frame->datalen;
+}
+
+static int test_law_length(unsigned int samples)
+{
+ return samples;
+}
+
+static struct ast_codec test_law = {
+ .name = "test_law",
+ .description = "format cap unit test codec",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 10,
+ .maximum_ms = 150,
+ .default_ms = 20,
+ .samples_count = test_law_samples,
+ .get_length = test_law_length,
+ .smooth = 1,
+};
+
+static enum ast_format_cmp_res test_law_cmp(const struct ast_format *format1, const struct ast_format *format2)
+{
+ ast_log(LOG_ERROR, "Comparing format1 %p and format2 %p\n", format1, format2);
+ return format1 == format2 ? AST_FORMAT_CMP_EQUAL : AST_FORMAT_CMP_NOT_EQUAL;
+}
+
+static void test_law_destroy(struct ast_format *format)
+{
+}
+
+static int test_law_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ return 0;
+}
+
+static struct ast_format_interface test_law_interface = {
+ .format_cmp = test_law_cmp,
+ .format_clone = test_law_clone,
+ .format_destroy = test_law_destroy,
+};
+
+AST_TEST_DEFINE(format_cap_replace_from_cap)
+{
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, replace_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, result_caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, ulaw_format_variant, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __PRETTY_FUNCTION__;
+ info->category = "/main/format_cap/";
+ info->summary = "format capabilities adding unit test";
+ info->description =
+ "Test that adding multiple formats to a format capabilities structure succeeds";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ replace_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ result_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps || !replace_caps || !result_caps) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw = ast_codec_get("test_law", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!ulaw) {
+ ast_test_status_update(test, "Could not retrieve test_law codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format = ast_format_create(ulaw);
+ if (!ulaw_format) {
+ ast_test_status_update(test, "Could not create ulaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ ulaw_format_variant = ast_format_create(ulaw);
+ if (!ulaw_format_variant) {
+ ast_test_status_update(test, "Could not create ulaw format variant using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
+ if (!alaw) {
+ ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ alaw_format = ast_format_create(alaw);
+ if (!alaw_format) {
+ ast_test_status_update(test, "Could not create alaw format using built-in codec\n");
+ return AST_TEST_FAIL;
+ }
+
+ /* fill caps with ulaw and alaw */
+ if (ast_format_cap_append(caps, ulaw_format, 42)) {
+ ast_test_status_update(test, "Could not add ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_append(caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_count(caps) != 2) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n",
+ ast_format_cap_count(caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* fill replace_caps with the ulaw variant */
+ if (ast_format_cap_append(replace_caps, ulaw_format_variant, 42)) {
+ ast_test_status_update(test, "Could not add ulaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_count(replace_caps) != 1) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n",
+ ast_format_cap_count(replace_caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* fill result_caps with ulaw_variant and alaw */
+ if (ast_format_cap_append(result_caps, ulaw_format_variant, 42)) {
+ ast_test_status_update(test, "Could not add ulaw variant to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_append(result_caps, alaw_format, 84)) {
+ ast_test_status_update(test, "Could not add alaw format to capabilities structure\n");
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_count(result_caps) != 2) {
+ ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n",
+ ast_format_cap_count(result_caps));
+ return AST_TEST_FAIL;
+ }
+
+ /* replace caps formats from replace_caps */
+ ast_format_cap_replace_from_cap(caps, replace_caps, AST_MEDIA_TYPE_UNKNOWN);
+
+ /* compare result_caps with caps */
+ if (!ast_format_cap_identical(caps, result_caps)) {
+ ast_test_status_update(test, "Actual and expected result caps differ\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(format_cap_alloc);
+ AST_TEST_UNREGISTER(format_cap_append_single);
+ AST_TEST_UNREGISTER(format_cap_append_multiple);
+ AST_TEST_UNREGISTER(format_cap_append_all_unknown);
+ AST_TEST_UNREGISTER(format_cap_append_all_audio);
+ AST_TEST_UNREGISTER(format_cap_append_duplicate);
+ AST_TEST_UNREGISTER(format_cap_append_from_cap);
+ AST_TEST_UNREGISTER(format_cap_append_from_cap_duplicate);
+ AST_TEST_UNREGISTER(format_cap_set_framing);
+ AST_TEST_UNREGISTER(format_cap_remove_single);
+ AST_TEST_UNREGISTER(format_cap_remove_multiple);
+ AST_TEST_UNREGISTER(format_cap_remove_bytype);
+ AST_TEST_UNREGISTER(format_cap_remove_all);
+ AST_TEST_UNREGISTER(format_cap_get_names);
+ AST_TEST_UNREGISTER(format_cap_get_compatible_format);
+ AST_TEST_UNREGISTER(format_cap_iscompatible_format);
+ AST_TEST_UNREGISTER(format_cap_get_compatible);
+ AST_TEST_UNREGISTER(format_cap_iscompatible);
+ AST_TEST_UNREGISTER(format_cap_best_by_type);
+ AST_TEST_UNREGISTER(format_cap_replace_from_cap);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(format_cap_alloc);
+ AST_TEST_REGISTER(format_cap_append_single);
+ AST_TEST_REGISTER(format_cap_append_multiple);
+ AST_TEST_REGISTER(format_cap_append_all_unknown);
+ AST_TEST_REGISTER(format_cap_append_all_audio);
+ AST_TEST_REGISTER(format_cap_append_duplicate);
+ AST_TEST_REGISTER(format_cap_append_from_cap);
+ AST_TEST_REGISTER(format_cap_append_from_cap_duplicate);
+ AST_TEST_REGISTER(format_cap_set_framing);
+ AST_TEST_REGISTER(format_cap_remove_single);
+ AST_TEST_REGISTER(format_cap_remove_multiple);
+ AST_TEST_REGISTER(format_cap_remove_bytype);
+ AST_TEST_REGISTER(format_cap_remove_all);
+ AST_TEST_REGISTER(format_cap_get_names);
+ AST_TEST_REGISTER(format_cap_get_compatible_format);
+ AST_TEST_REGISTER(format_cap_iscompatible_format);
+ AST_TEST_REGISTER(format_cap_get_compatible);
+ AST_TEST_REGISTER(format_cap_iscompatible);
+ AST_TEST_REGISTER(format_cap_best_by_type);
+ AST_TEST_REGISTER(format_cap_replace_from_cap);
+ ast_codec_register(&test_law);
+ ast_format_interface_register("test_law", &test_law_interface);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Format capabilities API test module");
diff --git a/tests/test_voicemail_api.c b/tests/test_voicemail_api.c
index 43293b0fc..ab1830298 100644
--- a/tests/test_voicemail_api.c
+++ b/tests/test_voicemail_api.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"
+#include "asterisk/format_cache.h"
/*!
* \internal
@@ -825,12 +826,12 @@ static struct ast_channel *test_vm_api_create_mock_channel(void)
return NULL;
}
- ast_format_set(ast_channel_writeformat(mock_channel), AST_FORMAT_GSM, 0);
+ ast_channel_set_writeformat(mock_channel, ast_format_gsm);
native_formats = ast_channel_nativeformats(mock_channel);
- ast_format_cap_add(native_formats, ast_channel_writeformat(mock_channel));
- ast_format_set(ast_channel_rawwriteformat(mock_channel), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_readformat(mock_channel), AST_FORMAT_GSM, 0);
- ast_format_set(ast_channel_rawreadformat(mock_channel), AST_FORMAT_GSM, 0);
+ ast_format_cap_append(native_formats, ast_channel_writeformat(mock_channel), 0);
+ ast_channel_set_rawwriteformat(mock_channel, ast_format_gsm);
+ ast_channel_set_readformat(mock_channel, ast_format_gsm);
+ ast_channel_set_rawreadformat(mock_channel, ast_format_gsm);
ast_channel_tech_set(mock_channel, &mock_channel_tech);
ast_channel_unlock(mock_channel);