mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 04:30:28 +00:00
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
This commit is contained in:
@@ -242,17 +242,19 @@ enum ast_rtp_instance_stat {
|
|||||||
|
|
||||||
/*! Structure that represents a payload */
|
/*! Structure that represents a payload */
|
||||||
struct ast_rtp_payload_type {
|
struct ast_rtp_payload_type {
|
||||||
/*! Is this an Asterisk value */
|
|
||||||
int asterisk_format;
|
|
||||||
/*! If asterisk_format is set, this is the internal
|
/*! If asterisk_format is set, this is the internal
|
||||||
* asterisk format represented by the payload */
|
* asterisk format represented by the payload */
|
||||||
struct ast_format *format;
|
struct ast_format *format;
|
||||||
|
/*! Is this an Asterisk value */
|
||||||
|
int asterisk_format;
|
||||||
/*! Actual internal RTP specific value of the payload */
|
/*! Actual internal RTP specific value of the payload */
|
||||||
int rtp_code;
|
int rtp_code;
|
||||||
/*! Actual payload number */
|
/*! Actual payload number */
|
||||||
int payload;
|
int payload;
|
||||||
/*! TRUE if this is the primary mapping to the format. */
|
/*! TRUE if this is the primary mapping to the format. */
|
||||||
unsigned int primary_mapping:1;
|
unsigned int primary_mapping:1;
|
||||||
|
/*! When the payload type became non-primary. */
|
||||||
|
struct timeval when_retired;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Common RTCP report types */
|
/* Common RTCP report types */
|
||||||
@@ -1451,8 +1453,13 @@ void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_fo
|
|||||||
* \param format Asterisk format to look for
|
* \param format Asterisk format to look for
|
||||||
* \param code The 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 Numerical payload type
|
||||||
* \retval -1 if not found.
|
* \retval -1 if could not assign.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
*
|
*
|
||||||
@@ -1464,7 +1471,7 @@ void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_fo
|
|||||||
*
|
*
|
||||||
* \since 1.8
|
* \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
|
* \brief Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code
|
||||||
|
@@ -640,11 +640,13 @@ static void payload_mapping_rx_clear_primary(struct ast_rtp_codecs *codecs, stru
|
|||||||
int idx;
|
int idx;
|
||||||
struct ast_rtp_payload_type *current;
|
struct ast_rtp_payload_type *current;
|
||||||
struct ast_rtp_payload_type *new_type;
|
struct ast_rtp_payload_type *new_type;
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
if (!to_match->primary_mapping) {
|
if (!to_match->primary_mapping) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
now = ast_tvnow();
|
||||||
for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
|
for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
|
||||||
current = AST_VECTOR_GET(&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 = *current;
|
||||||
new_type->primary_mapping = 0;
|
new_type->primary_mapping = 0;
|
||||||
|
new_type->when_retired = now;
|
||||||
ao2_bump(new_type->format);
|
ao2_bump(new_type->format);
|
||||||
AST_VECTOR_REPLACE(&codecs->payload_mapping_rx, idx, new_type);
|
AST_VECTOR_REPLACE(&codecs->payload_mapping_rx, idx, new_type);
|
||||||
ao2_ref(current, -1);
|
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 format Asterisk format to look for
|
||||||
* \param code The non-Asterisk format code 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 Numerical payload type
|
||||||
* \retval -1 if not found.
|
* \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;
|
int payload = -1;
|
||||||
|
|
||||||
if (!asterisk_format) {
|
if (!asterisk_format) {
|
||||||
ast_rwlock_rdlock(&static_RTP_PT_lock);
|
|
||||||
for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
|
for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
|
||||||
if (static_RTP_PT[idx]
|
if (static_RTP_PT[idx]
|
||||||
&& !static_RTP_PT[idx]->asterisk_format
|
&& !static_RTP_PT[idx]->asterisk_format
|
||||||
@@ -1178,9 +1182,7 @@ static int find_static_payload_type(int asterisk_format, const struct ast_format
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast_rwlock_unlock(&static_RTP_PT_lock);
|
|
||||||
} else if (format) {
|
} else if (format) {
|
||||||
ast_rwlock_rdlock(&static_RTP_PT_lock);
|
|
||||||
for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
|
for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
|
||||||
if (static_RTP_PT[idx]
|
if (static_RTP_PT[idx]
|
||||||
&& static_RTP_PT[idx]->asterisk_format
|
&& static_RTP_PT[idx]->asterisk_format
|
||||||
@@ -1190,18 +1192,149 @@ static int find_static_payload_type(int asterisk_format, const struct ast_format
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast_rwlock_unlock(&static_RTP_PT_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return payload;
|
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;
|
struct ast_rtp_payload_type *type;
|
||||||
int idx;
|
int idx;
|
||||||
int payload = -1;
|
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) {
|
if (!asterisk_format) {
|
||||||
ast_rwlock_rdlock(&codecs->codecs_lock);
|
ast_rwlock_rdlock(&codecs->codecs_lock);
|
||||||
for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
|
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
|
if (!type->asterisk_format
|
||||||
|
&& type->primary_mapping
|
||||||
&& type->rtp_code == code) {
|
&& type->rtp_code == code) {
|
||||||
if (type->primary_mapping) {
|
payload = idx;
|
||||||
payload = idx;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (payload == -1) {
|
|
||||||
payload = idx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast_rwlock_unlock(&codecs->codecs_lock);
|
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
|
if (type->asterisk_format
|
||||||
|
&& type->primary_mapping
|
||||||
&& ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL) {
|
&& ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL) {
|
||||||
if (type->primary_mapping) {
|
payload = idx;
|
||||||
payload = idx;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (payload == -1) {
|
|
||||||
payload = idx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast_rwlock_unlock(&codecs->codecs_lock);
|
ast_rwlock_unlock(&codecs->codecs_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload < 0) {
|
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;
|
return payload;
|
||||||
}
|
}
|
||||||
@@ -1290,7 +1417,9 @@ int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_f
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (payload < 0) {
|
if (payload < 0) {
|
||||||
|
ast_rwlock_rdlock(&static_RTP_PT_lock);
|
||||||
payload = find_static_payload_type(asterisk_format, format, code);
|
payload = find_static_payload_type(asterisk_format, format, code);
|
||||||
|
ast_rwlock_unlock(&static_RTP_PT_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return payload;
|
return payload;
|
||||||
|
Reference in New Issue
Block a user