[Asterisk-code-review] rtp engine.c: Get current or create a needed rx payload type... (asterisk[master])

Matt Jordan asteriskteam at digium.com
Fri Aug 21 08:39:21 CDT 2015


Matt Jordan has submitted this change and it was merged.

Change subject: rtp_engine.c: Get current or create a needed rx payload type mapping.
......................................................................


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
---
M include/asterisk/rtp_engine.h
M main/rtp_engine.c
2 files changed, 160 insertions(+), 24 deletions(-)

Approvals:
  Anonymous Coward #1000019: Verified
  Matt Jordan: Looks good to me, approved
  Ashley Sanders: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, but someone else must approve



diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index a52567a..0f6ec7a 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -242,17 +242,19 @@
 
 /*! Structure that represents a payload */
 struct ast_rtp_payload_type {
-	/*! Is this an Asterisk value */
-	int asterisk_format;
 	/*! If asterisk_format is set, this is the internal
 	 * asterisk format represented by the payload */
 	struct ast_format *format;
+	/*! Is this an Asterisk value */
+	int asterisk_format;
 	/*! Actual internal RTP specific value of the payload */
 	int rtp_code;
 	/*! Actual payload number */
 	int payload;
 	/*! TRUE if this is the primary mapping to the format. */
 	unsigned int primary_mapping:1;
+	/*! When the payload type became non-primary. */
+	struct timeval when_retired;
 };
 
 /* Common RTCP report types */
@@ -1451,8 +1453,13 @@
  * \param format Asterisk format to look for
  * \param code The format to look for
  *
+ * \details
+ * Find the currently assigned rx mapped payload type based on whether it
+ * is an Asterisk format or non-format code.  If one is currently not
+ * assigned then create a rx payload type mapping.
+ *
  * \retval Numerical payload type
- * \retval -1 if not found.
+ * \retval -1 if could not assign.
  *
  * Example usage:
  *
@@ -1464,7 +1471,7 @@
  *
  * \since 1.8
  */
-int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code);
+int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code);
 
 /*!
  * \brief Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index cd2d38f..1460a7a 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -640,11 +640,13 @@
 	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 @@
 		}
 		*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 @@
  * \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 @@
 	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 @@
 				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 @@
 				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 @@
 			}
 
 			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 @@
 			}
 
 			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 @@
 	}
 
 	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;

-- 
To view, visit https://gerrit.asterisk.org/1020
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ia4b2d45877a8f004f6ce3840e3d8afe533384e56
Gerrit-PatchSet: 3
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Ashley Sanders <asanders at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Matt Jordan <mjordan at digium.com>
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>



More information about the asterisk-code-review mailing list