summaryrefslogtreecommitdiff
path: root/main/rtp_engine.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2015-07-27 19:19:25 -0500
committerRichard Mudgett <rmudgett@digium.com>2015-08-20 11:56:13 -0500
commitf7df3e1a0119c26595adb1cb48bf2beee8b9cf89 (patch)
tree4a602fcd15c34d81129e8a614e8f1393b21ad26e /main/rtp_engine.c
parent38854a9f7bb9d741c89629008133172dd1beb8df (diff)
rtp_engine.c: Get current or create a needed rx payload type mapping.
* Make ast_rtp_codecs_payload_code() get the current mapping or create a rx payload type mapping. ASTERISK-25166 Reported by: Kevin Harwell ASTERISK-17410 Reported by: Boris Fox Change-Id: Ia4b2d45877a8f004f6ce3840e3d8afe533384e56
Diffstat (limited to 'main/rtp_engine.c')
-rw-r--r--main/rtp_engine.c169
1 files changed, 149 insertions, 20 deletions
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index cd2d38f7c..1460a7ac8 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -640,11 +640,13 @@ static void payload_mapping_rx_clear_primary(struct ast_rtp_codecs *codecs, stru
int idx;
struct ast_rtp_payload_type *current;
struct ast_rtp_payload_type *new_type;
+ struct timeval now;
if (!to_match->primary_mapping) {
return;
}
+ now = ast_tvnow();
for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
current = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
@@ -670,6 +672,7 @@ static void payload_mapping_rx_clear_primary(struct ast_rtp_codecs *codecs, stru
}
*new_type = *current;
new_type->primary_mapping = 0;
+ new_type->when_retired = now;
ao2_bump(new_type->format);
AST_VECTOR_REPLACE(&codecs->payload_mapping_rx, idx, new_type);
ao2_ref(current, -1);
@@ -1160,6 +1163,8 @@ void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_fo
* \param format Asterisk format to look for
* \param code The non-Asterisk format code to look for
*
+ * \note It is assumed that static_RTP_PT_lock is at least read locked before calling.
+ *
* \retval Numerical payload type
* \retval -1 if not found.
*/
@@ -1169,7 +1174,6 @@ static int find_static_payload_type(int asterisk_format, const struct ast_format
int payload = -1;
if (!asterisk_format) {
- ast_rwlock_rdlock(&static_RTP_PT_lock);
for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
if (static_RTP_PT[idx]
&& !static_RTP_PT[idx]->asterisk_format
@@ -1178,9 +1182,7 @@ static int find_static_payload_type(int asterisk_format, const struct ast_format
break;
}
}
- ast_rwlock_unlock(&static_RTP_PT_lock);
} else if (format) {
- ast_rwlock_rdlock(&static_RTP_PT_lock);
for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
if (static_RTP_PT[idx]
&& static_RTP_PT[idx]->asterisk_format
@@ -1190,18 +1192,149 @@ static int find_static_payload_type(int asterisk_format, const struct ast_format
break;
}
}
- ast_rwlock_unlock(&static_RTP_PT_lock);
}
return payload;
}
-int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
+/*!
+ * \internal
+ * \brief Find the first unused dynamic rx payload type.
+ * \since 14.0.0
+ *
+ * \param codecs Codecs structure to look in
+ *
+ * \note It is assumed that codecs is at least read locked before calling.
+ *
+ * \retval Numerical payload type
+ * \retval -1 if not found.
+ */
+static int rtp_codecs_find_empty_dynamic_rx(struct ast_rtp_codecs *codecs)
{
struct ast_rtp_payload_type *type;
int idx;
int payload = -1;
+ idx = AST_RTP_PT_FIRST_DYNAMIC;
+ for (; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
+ type = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
+ if (!type) {
+ payload = idx;
+ break;
+ }
+ }
+ return payload;
+}
+
+/*!
+ * \internal
+ * \brief Find the oldest non-primary dynamic rx payload type.
+ * \since 14.0.0
+ *
+ * \param codecs Codecs structure to look in
+ *
+ * \note It is assumed that codecs is at least read locked before calling.
+ *
+ * \retval Numerical payload type
+ * \retval -1 if not found.
+ */
+static int rtp_codecs_find_non_primary_dynamic_rx(struct ast_rtp_codecs *codecs)
+{
+ struct ast_rtp_payload_type *type;
+ struct timeval oldest;
+ int idx;
+ int payload = -1;
+
+ idx = AST_RTP_PT_FIRST_DYNAMIC;
+ for (; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
+ type = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
+ if (type
+ && !type->primary_mapping
+ && (payload == -1
+ || ast_tvdiff_ms(type->when_retired, oldest) < 0)) {
+ oldest = type->when_retired;
+ payload = idx;
+ }
+ }
+ return payload;
+}
+
+/*!
+ * \internal
+ * \brief Assign a payload type for the rx mapping.
+ * \since 14.0.0
+ *
+ * \param codecs Codecs structure to look in
+ * \param asterisk_format Non-zero if the given Asterisk format is present
+ * \param format Asterisk format to look for
+ * \param code The format to look for
+ *
+ * \note It is assumed that static_RTP_PT_lock is at least read locked before calling.
+ *
+ * \retval Numerical payload type
+ * \retval -1 if could not assign.
+ */
+static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
+{
+ int payload;
+ struct ast_rtp_payload_type *new_type;
+
+ payload = find_static_payload_type(asterisk_format, format, code);
+ if (payload < 0) {
+ return payload;
+ }
+
+ new_type = ast_rtp_engine_alloc_payload_type();
+ if (!new_type) {
+ return -1;
+ }
+ new_type->format = ao2_bump(format);
+ new_type->asterisk_format = asterisk_format;
+ new_type->rtp_code = code;
+ new_type->payload = payload;
+ new_type->primary_mapping = 1;
+
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ if (payload < AST_RTP_PT_FIRST_DYNAMIC
+ || AST_VECTOR_SIZE(&codecs->payload_mapping_rx) <= payload
+ || !AST_VECTOR_GET(&codecs->payload_mapping_rx, payload)) {
+ /*
+ * The payload type is a static assignment
+ * or our default dynamic position is available.
+ */
+ rtp_codecs_payload_replace_rx(codecs, payload, new_type);
+ } else if (-1 < (payload = rtp_codecs_find_empty_dynamic_rx(codecs))
+ || -1 < (payload = rtp_codecs_find_non_primary_dynamic_rx(codecs))) {
+ /*
+ * We found the first available empty dynamic position
+ * or we found a mapping that should no longer be
+ * actively used.
+ */
+ new_type->payload = payload;
+ rtp_codecs_payload_replace_rx(codecs, payload, new_type);
+ } else {
+ /*
+ * There are no empty or non-primary dynamic positions
+ * left. Sadness.
+ *
+ * I don't think this is really possible.
+ */
+ ast_log(LOG_WARNING, "No dynamic RTP payload type values available!\n");
+ }
+ ast_rwlock_unlock(&codecs->codecs_lock);
+
+ ao2_ref(new_type, -1);
+
+ return payload;
+}
+
+int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
+{
+ struct ast_rtp_payload_type *type;
+ int idx;
+ int payload = -1;
+
+ ast_rwlock_rdlock(&static_RTP_PT_lock);
if (!asterisk_format) {
ast_rwlock_rdlock(&codecs->codecs_lock);
for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
@@ -1211,14 +1344,10 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_form
}
if (!type->asterisk_format
+ && type->primary_mapping
&& type->rtp_code == code) {
- if (type->primary_mapping) {
- payload = idx;
- break;
- }
- if (payload == -1) {
- payload = idx;
- }
+ payload = idx;
+ break;
}
}
ast_rwlock_unlock(&codecs->codecs_lock);
@@ -1231,22 +1360,20 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_form
}
if (type->asterisk_format
+ && type->primary_mapping
&& ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL) {
- if (type->primary_mapping) {
- payload = idx;
- break;
- }
- if (payload == -1) {
- payload = idx;
- }
+ payload = idx;
+ break;
}
}
ast_rwlock_unlock(&codecs->codecs_lock);
}
if (payload < 0) {
- payload = find_static_payload_type(asterisk_format, format, code);
+ payload = rtp_codecs_assign_payload_code_rx(codecs, asterisk_format, format,
+ code);
}
+ ast_rwlock_unlock(&static_RTP_PT_lock);
return payload;
}
@@ -1290,7 +1417,9 @@ int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_f
}
if (payload < 0) {
+ ast_rwlock_rdlock(&static_RTP_PT_lock);
payload = find_static_payload_type(asterisk_format, format, code);
+ ast_rwlock_unlock(&static_RTP_PT_lock);
}
return payload;