diff options
author | Joshua Colp <jcolp@digium.com> | 2012-08-07 13:07:58 +0000 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2012-08-07 13:07:58 +0000 |
commit | 15e41c7542fba77244ec709a76c49efdc74d450e (patch) | |
tree | 08a86fa9d8e990a70f46121e79ed348b44cc0a33 | |
parent | 5c4578f4ad9af0d13638ec72a2bc141227ec8b3c (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.c | 8 | ||||
-rw-r--r-- | channels/chan_sip.c | 48 | ||||
-rw-r--r-- | include/asterisk/rtp_engine.h | 39 | ||||
-rw-r--r-- | main/rtp_engine.c | 226 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 4 |
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; } |