summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2012-08-07 13:07:58 +0000
committerJoshua Colp <jcolp@digium.com>2012-08-07 13:07:58 +0000
commit15e41c7542fba77244ec709a76c49efdc74d450e (patch)
tree08a86fa9d8e990a70f46121e79ed348b44cc0a33
parent5c4578f4ad9af0d13638ec72a2bc141227ec8b3c (diff)
Reduce memory consumption significantly for users of the RTP engine API by storing only the payloads present and in use instead of every possible one.
Review: https://reviewboard.asterisk.org/r/2052/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@370832 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_motif.c8
-rw-r--r--channels/chan_sip.c48
-rw-r--r--include/asterisk/rtp_engine.h39
-rw-r--r--main/rtp_engine.c226
-rw-r--r--res/res_rtp_asterisk.c4
5 files changed, 236 insertions, 89 deletions
diff --git a/channels/chan_motif.c b/channels/chan_motif.c
index 52d15d00a..8c4c11a7a 100644
--- a/channels/chan_motif.c
+++ b/channels/chan_motif.c
@@ -1869,7 +1869,11 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
return -1;
}
- ast_rtp_codecs_payloads_clear(&codecs, NULL);
+ if (ast_rtp_codecs_payloads_initialize(&codecs)) {
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+ ast_log(LOG_ERROR, "Could not initialize codecs for negotiation on session '%s'\n", session->sid);
+ return -1;
+ }
/* Iterate the codecs updating the relevant RTP instance as we go */
for (codec = iks_child(description); codec; codec = iks_next(codec)) {
@@ -1894,10 +1898,12 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
if (ast_format_cap_is_empty(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);
return -1;
}
ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(*rtp), *rtp);
+ ast_rtp_codecs_payloads_destroy(&codecs);
return 0;
}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index b002254ef..b65390aac 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -9450,7 +9450,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int peernoncodeccapability = 0, vpeernoncodeccapability = 0, tpeernoncodeccapability = 0;
- struct ast_rtp_codecs *newaudiortp = NULL, *newvideortp = NULL, *newtextrtp = NULL;
+ struct ast_rtp_codecs newaudiortp = { 0, }, newvideortp = { 0, }, newtextrtp = { 0, };
struct ast_format_cap *newjointcapability = ast_format_cap_alloc_nolock(); /* Negotiated capability */
struct ast_format_cap *newpeercapability = ast_format_cap_alloc_nolock();
int newnoncodeccapability;
@@ -9487,8 +9487,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
goto process_sdp_cleanup;
}
- if (!(newaudiortp = ast_calloc(1, sizeof(*newaudiortp))) || !(newvideortp = ast_calloc(1, sizeof(*newvideortp))) ||
- !(newtextrtp = ast_calloc(1, sizeof(*newtextrtp)))) {
+ if (ast_rtp_codecs_payloads_initialize(&newaudiortp) || ast_rtp_codecs_payloads_initialize(&newvideortp) ||
+ ast_rtp_codecs_payloads_initialize(&newtextrtp)) {
res = -1;
goto process_sdp_cleanup;
}
@@ -9532,11 +9532,11 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (process_sdp_a_sendonly(value, &sendonly)) {
processed = TRUE;
}
- else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec))
+ else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec))
processed = TRUE;
- else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec))
+ else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec))
processed = TRUE;
- else if (process_sdp_a_text(value, p, newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec))
+ else if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec))
processed = TRUE;
else if (process_sdp_a_image(value, p))
processed = TRUE;
@@ -9650,7 +9650,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_verbose("Found RTP audio format %d\n", codec);
}
- ast_rtp_codecs_payloads_set_m_type(newaudiortp, NULL, codec);
+ ast_rtp_codecs_payloads_set_m_type(&newaudiortp, NULL, codec);
}
} else {
ast_log(LOG_WARNING, "Rejecting audio media offer due to invalid or unsupported syntax: %s\n", m);
@@ -9722,7 +9722,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (debug) {
ast_verbose("Found RTP video format %d\n", codec);
}
- ast_rtp_codecs_payloads_set_m_type(newvideortp, NULL, codec);
+ ast_rtp_codecs_payloads_set_m_type(&newvideortp, NULL, codec);
}
} else {
ast_log(LOG_WARNING, "Rejecting video media offer due to invalid or unsupported syntax: %s\n", m);
@@ -9786,7 +9786,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (debug) {
ast_verbose("Found RTP text format %d\n", codec);
}
- ast_rtp_codecs_payloads_set_m_type(newtextrtp, NULL, codec);
+ ast_rtp_codecs_payloads_set_m_type(&newtextrtp, NULL, codec);
}
} else {
ast_log(LOG_WARNING, "Rejecting text stream offer due to invalid or unsupported syntax: %s\n", m);
@@ -9904,7 +9904,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} else if (!processed_crypto && process_crypto(p, p->rtp, &p->srtp, value)) {
processed_crypto = TRUE;
processed = TRUE;
- } else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) {
+ } else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) {
processed = TRUE;
}
}
@@ -9915,7 +9915,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} else if (!processed_crypto && process_crypto(p, p->vrtp, &p->vsrtp, value)) {
processed_crypto = TRUE;
processed = TRUE;
- } else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) {
+ } else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) {
processed = TRUE;
}
}
@@ -9923,7 +9923,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
else if (text) {
if (process_sdp_a_ice(value, p, p->trtp)) {
processed = TRUE;
- } if (process_sdp_a_text(value, p, newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) {
+ } if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) {
processed = TRUE;
} else if (!processed_crypto && process_crypto(p, p->trtp, &p->tsrtp, value)) {
processed_crypto = TRUE;
@@ -9996,9 +9996,9 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
/* Now gather all of the codecs that we are asked for: */
- ast_rtp_codecs_payload_formats(newaudiortp, peercapability, &peernoncodeccapability);
- ast_rtp_codecs_payload_formats(newvideortp, vpeercapability, &vpeernoncodeccapability);
- ast_rtp_codecs_payload_formats(newtextrtp, tpeercapability, &tpeernoncodeccapability);
+ ast_rtp_codecs_payload_formats(&newaudiortp, peercapability, &peernoncodeccapability);
+ ast_rtp_codecs_payload_formats(&newvideortp, vpeercapability, &vpeernoncodeccapability);
+ ast_rtp_codecs_payload_formats(&newtextrtp, tpeercapability, &tpeernoncodeccapability);
ast_format_cap_append(newpeercapability, peercapability);
ast_format_cap_append(newpeercapability, vpeercapability);
@@ -10061,7 +10061,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_sockaddr_stringify(sa));
}
- ast_rtp_codecs_payloads_copy(newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp);
+ ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp);
/* Ensure RTCP is enabled since it may be inactive
if we're coming back from a T.38 session */
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1);
@@ -10108,7 +10108,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_verbose("Peer video RTP is at port %s\n",
ast_sockaddr_stringify(vsa));
}
- ast_rtp_codecs_payloads_copy(newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp);
+ ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp);
} else {
ast_rtp_instance_stop(p->vrtp);
if (debug)
@@ -10132,7 +10132,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} else {
p->red = 0;
}
- ast_rtp_codecs_payloads_copy(newtextrtp, ast_rtp_instance_get_codecs(p->trtp), p->trtp);
+ ast_rtp_codecs_payloads_copy(&newtextrtp, ast_rtp_instance_get_codecs(p->trtp), p->trtp);
} else {
ast_rtp_instance_stop(p->trtp);
if (debug)
@@ -10250,15 +10250,9 @@ process_sdp_cleanup:
if (res) {
offered_media_list_destroy(p);
}
- if (newtextrtp) {
- ast_free(newtextrtp);
- }
- if (newvideortp) {
- ast_free(newvideortp);
- }
- if (newaudiortp) {
- ast_free(newaudiortp);
- }
+ 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);
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index bd47e42b1..dad2a60f8 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -431,10 +431,10 @@ 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;
- /*! Payloads present */
- struct ast_rtp_payload_type payloads[AST_RTP_MAX_PT];
};
/*! Structure that represents the glue that binds an RTP instance to a channel */
@@ -945,6 +945,41 @@ int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_pr
struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance);
/*!
+ * \brief Initialize an RTP codecs structure
+ *
+ * \param codecs The codecs structure to initialize
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * Example usage:
+ *
+ * \code
+ * struct ast_rtp_codecs codecs;
+ * ast_rtp_codecs_payloads_initialize(&codecs);
+ * \endcode
+ *
+ * \since 11
+ */
+int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs);
+
+/*!
+ * \brief Destroy the contents of an RTP codecs structure (but not the structure itself)
+ *
+ * \param codecs The codecs structure to destroy the contents of
+ *
+ * Example usage:
+ *
+ * \code
+ * struct ast_rtp_codecs codecs;
+ * ast_rtp_codecs_payloads_destroy(&codecs);
+ * \endcode
+ *
+ * \since 11
+ */
+void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs);
+
+/*!
* \brief Clear payload information from an RTP instance
*
* \param codecs The codecs structure that payloads will be cleared from
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 68cdfd306..46b75be72 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -218,6 +218,8 @@ static void instance_destructor(void *obj)
res_srtp->destroy(instance->srtp);
}
+ ast_rtp_codecs_payloads_destroy(&instance->codecs);
+
/* Drop our engine reference */
ast_module_unref(instance->engine->mod);
@@ -273,6 +275,11 @@ struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
ast_sockaddr_copy(&instance->local_address, sa);
ast_sockaddr_copy(&address, sa);
+ if (ast_rtp_codecs_payloads_initialize(&instance->codecs)) {
+ ao2_ref(instance, -1);
+ return NULL;
+ }
+
ast_debug(1, "Using engine '%s' for RTP instance '%p'\n", engine->name, instance);
/* And pass it off to the engine to setup */
@@ -411,18 +418,48 @@ 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)
+{
+ const struct ast_rtp_payload_type *type = obj;
+ const int *rtp_code = obj;
+
+ return (flags & OBJ_KEY) ? *rtp_code : type->rtp_code;
+}
+
+static int rtp_payload_type_cmp(void *obj, void *arg, int flags)
+{
+ struct ast_rtp_payload_type *type1 = obj, *type2 = arg;
+ const int *rtp_code = arg;
+
+ return (type1->rtp_code == (OBJ_KEY ? *rtp_code : type2->rtp_code)) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+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;
+ }
+
+ return 0;
+}
+
+void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
+{
+ ao2_cleanup(codecs->payloads);
+}
+
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
{
- int i;
+ ast_rtp_codecs_payloads_destroy(codecs);
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- codecs->payloads[i].asterisk_format = 0;
- codecs->payloads[i].rtp_code = 0;
- ast_format_clear(&codecs->payloads[i].format);
- if (instance && instance->engine && instance->engine->payload_set) {
+ if (instance && instance->engine && instance->engine->payload_set) {
+ int i;
+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
instance->engine->payload_set(instance, i, 0, NULL, 0);
}
}
+
+ ast_rtp_codecs_payloads_initialize(codecs);
}
void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
@@ -432,13 +469,27 @@ void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_r
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->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);
- codecs->payloads[i].asterisk_format = static_RTP_PT[i].asterisk_format;
- codecs->payloads[i].rtp_code = static_RTP_PT[i].rtp_code;
- ast_format_copy(&codecs->payloads[i].format, &static_RTP_PT[i].format);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, i, codecs->payloads[i].asterisk_format, &codecs->payloads[i].format, codecs->payloads[i].rtp_code);
+ 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);
@@ -447,38 +498,57 @@ void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_r
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++) {
- if (src->payloads[i].rtp_code || src->payloads[i].asterisk_format) {
- ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest);
- dest->payloads[i].asterisk_format = src->payloads[i].asterisk_format;
- dest->payloads[i].rtp_code = src->payloads[i].rtp_code;
- ast_format_copy(&dest->payloads[i].format, &src->payloads[i].format);
- if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, i, dest->payloads[i].asterisk_format, &dest->payloads[i].format, dest->payloads[i].rtp_code);
- }
+ struct ast_rtp_payload_type *new_type;
+
+ if (!(type = ao2_find(src->payloads, &i, OBJ_KEY | OBJ_NOLOCK))) {
+ continue;
+ }
+
+ if (!(new_type = ao2_alloc(sizeof(*new_type), NULL))) {
+ continue;
}
+
+ ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest);
+
+ *new_type = *type;
+
+ ao2_link_flags(dest->payloads, new_type, OBJ_NOLOCK);
+
+ ao2_ref(new_type, -1);
+
+ 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);
}
}
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;
ast_rwlock_rdlock(&static_RTP_PT_lock);
- if (payload < 0 || payload >= AST_RTP_MAX_PT || (!static_RTP_PT[payload].rtp_code && !static_RTP_PT[payload].asterisk_format)) {
+ if (payload < 0 || payload >= AST_RTP_MAX_PT || !(type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
ast_rwlock_unlock(&static_RTP_PT_lock);
return;
}
- codecs->payloads[payload].asterisk_format = static_RTP_PT[payload].asterisk_format;
- codecs->payloads[payload].rtp_code = static_RTP_PT[payload].rtp_code;
- ast_format_copy(&codecs->payloads[payload].format, &static_RTP_PT[payload].format);
+ type->asterisk_format = static_RTP_PT[payload].asterisk_format;
+ type->rtp_code = static_RTP_PT[payload].rtp_code;
+ ast_format_copy(&type->format, &static_RTP_PT[payload].format);
ast_debug(1, "Setting payload %d based on m type on %p\n", payload, codecs);
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, payload, codecs->payloads[payload].asterisk_format, &codecs->payloads[payload].format, codecs->payloads[payload].rtp_code);
+ instance->engine->payload_set(instance, payload, type->asterisk_format, &type->format, type->rtp_code);
}
+
+ ao2_ref(type, -1);
+
ast_rwlock_unlock(&static_RTP_PT_lock);
}
@@ -496,6 +566,7 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
ast_rwlock_rdlock(&mime_types_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;
if (strcasecmp(mimesubtype, t->subtype)) {
continue;
@@ -514,16 +585,26 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
}
found = 1;
- codecs->payloads[pt] = t->payload_type;
+
+ if (!(type = ao2_find(codecs->payloads, &pt, OBJ_KEY | OBJ_NOLOCK))) {
+ if (!(type = ao2_alloc(sizeof(*type), NULL))) {
+ continue;
+ }
+ ao2_link_flags(codecs->payloads, type, OBJ_NOLOCK);
+ }
+
+ *type = t->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(&codecs->payloads[pt].format, AST_FORMAT_G726_AAL2, 0);
+ ast_format_set(&type->format, AST_FORMAT_G726_AAL2, 0);
}
if (instance && instance->engine && instance->engine->payload_set) {
- instance->engine->payload_set(instance, pt, codecs->payloads[i].asterisk_format, &codecs->payloads[i].format, codecs->payloads[i].rtp_code);
+ instance->engine->payload_set(instance, pt, type->asterisk_format, &type->format, type->rtp_code);
}
+ ao2_ref(type, -1);
+
break;
}
ast_rwlock_unlock(&mime_types_lock);
@@ -544,9 +625,7 @@ void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp
ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
- codecs->payloads[payload].asterisk_format = 0;
- codecs->payloads[payload].rtp_code = 0;
- ast_format_clear(&codecs->payloads[payload].format);
+ ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK | OBJ_NODATA | OBJ_UNLINK);
if (instance && instance->engine && instance->engine->payload_set) {
instance->engine->payload_set(instance, payload, 0, NULL, 0);
@@ -555,15 +634,16 @@ void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp
struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload)
{
- struct ast_rtp_payload_type result = { .asterisk_format = 0, };
+ struct ast_rtp_payload_type result = { .asterisk_format = 0, }, *type;
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
return result;
}
- result.asterisk_format = codecs->payloads[payload].asterisk_format;
- result.rtp_code = codecs->payloads[payload].rtp_code;
- ast_format_copy(&result.format, &codecs->payloads[payload].format);
+ if ((type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
+ result = *type;
+ ao2_ref(type, -1);
+ }
if (!result.rtp_code && !result.asterisk_format) {
ast_rwlock_rdlock(&static_RTP_PT_lock);
@@ -577,46 +657,78 @@ struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs
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;
+
if (payload < 0 || payload >= AST_RTP_MAX_PT) {
return NULL;
}
- if (!codecs->payloads[payload].asterisk_format) {
+
+ if (!(type = ao2_find(codecs->payloads, &payload, OBJ_KEY | OBJ_NOLOCK))) {
return NULL;
}
- return &codecs->payloads[payload].format;
+
+ format = type->asterisk_format ? &type->format : NULL;
+
+ ao2_ref(type, -1);
+
+ return format;
}
-void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
+static int rtp_payload_type_add_ast(void *obj, void *arg, int flags)
{
- int i;
+ struct ast_rtp_payload_type *type = obj;
+ struct ast_format_cap *astformats = arg;
+
+ if (type->asterisk_format) {
+ ast_format_cap_add(astformats, &type->format);
+ }
+
+ return 0;
+}
+static int rtp_payload_type_add_nonast(void *obj, void *arg, int flags)
+{
+ struct ast_rtp_payload_type *type = obj;
+ int *nonastformats = arg;
+
+ if (!type->asterisk_format) {
+ *nonastformats |= type->rtp_code;
+ }
+
+ return 0;
+}
+
+void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
+{
ast_format_cap_remove_all(astformats);
*nonastformats = 0;
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- if (codecs->payloads[i].rtp_code || codecs->payloads[i].asterisk_format) {
- ast_debug(1, "Incorporating payload %d on %p\n", i, codecs);
- }
- if (codecs->payloads[i].asterisk_format) {
- ast_format_cap_add(astformats, &codecs->payloads[i].format);
- } else {
- *nonastformats |= codecs->payloads[i].rtp_code;
- }
- }
+ 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);
+}
+
+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;
+
+ return (type->asterisk_format && (ast_format_cmp(&type->format, format) != AST_FORMAT_CMP_NOT_EQUAL)) ? CMP_MATCH | CMP_STOP : 0;
}
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
{
- int i;
- int res = -1;
- for (i = 0; i < AST_RTP_MAX_PT; i++) {
- if (codecs->payloads[i].asterisk_format && asterisk_format && format &&
- (ast_format_cmp(format, &codecs->payloads[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) {
- return i;
- } else if (!codecs->payloads[i].asterisk_format && !asterisk_format &&
- (codecs->payloads[i].rtp_code == code)) {
- return i;
- }
+ struct ast_rtp_payload_type *type;
+ int i, res = -1;
+
+ if (asterisk_format && format && (type = ao2_callback(codecs->payloads, OBJ_NOLOCK, rtp_payload_type_find_format, (void*)format))) {
+ res = type->rtp_code;
+ ao2_ref(type, -1);
+ return res;
+ } else if (!asterisk_format && (type = ao2_find(codecs->payloads, &code, OBJ_NOLOCK | OBJ_KEY))) {
+ res = type->rtp_code;
+ ao2_ref(type, -1);
+ return res;
}
ast_rwlock_rdlock(&static_RTP_PT_lock);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 97e63b48f..bdb4a251d 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -2774,8 +2774,8 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
}
/* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
- if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].rtp_code) &&
- !(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].asterisk_format)) {
+ if (!ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), 0, NULL, bridged_payload) &&
+ !ast_rtp_codecs_get_payload_format(ast_rtp_instance_get_codecs(instance1), bridged_payload)) {
return -1;
}