Merged revisions 46082-46083,46152-46153 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r46082 | kpfleming | 2006-10-23 22:45:42 -0500 (Mon, 23 Oct 2006) | 2 lines

add an API call to allow channel drivers to determine which media formats are compatible (passthrough or transcode) with the format an existing channel is already using

........
r46083 | kpfleming | 2006-10-23 22:53:32 -0500 (Mon, 23 Oct 2006) | 2 lines

ensure that the translation matrix is properly lock-protected every place it is used

........
r46152 | kpfleming | 2006-10-24 18:45:19 -0500 (Tue, 24 Oct 2006) | 2 lines

if multiple translators are registered for the same source/dest combination, ensure that the lowest-cost one is always inserted earlier in the list

........
r46153 | kpfleming | 2006-10-24 19:10:54 -0500 (Tue, 24 Oct 2006) | 2 lines

code zone experiment: don't offer formats in the outbound INVITE that aren't either passthrough or translatable

........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@46203 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.0
Kevin P. Fleming 19 years ago
parent 6ab133b9d2
commit 5f5faa310a

@ -142,6 +142,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
#include "asterisk/threadstorage.h"
#include "asterisk/translate.h"
#ifndef FALSE
#define FALSE 0
@ -927,7 +928,7 @@ struct sip_pvt {
unsigned int sipoptions; /*!< Supported SIP options on the other end */
struct ast_codec_pref prefs; /*!< codec prefs */
int capability; /*!< Special capability (codec) */
int jointcapability; /*!< Supported capability at both ends (codecs ) */
int jointcapability; /*!< Supported capability at both ends (codecs) */
int peercapability; /*!< Supported peer capability */
int prefcodec; /*!< Preferred codec (outbound only) */
int noncodeccapability; /*!< DTMF RFC2833 telephony-event */
@ -6091,15 +6092,13 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
if (p->redirip.sin_addr.s_addr) {
dest.sin_port = p->redirip.sin_port;
dest.sin_addr = p->redirip.sin_addr;
if (p->redircodecs)
capability = p->redircodecs;
} else {
dest.sin_addr = p->ourip;
dest.sin_port = sin.sin_port;
}
/* Ok, let's start working with codec selection here */
capability = p->jointcapability;
capability = ast_translate_available_formats(p->jointcapability, p->prefcodec);
if (option_debug > 1) {
char codecbuf[BUFSIZ];
@ -6107,26 +6106,25 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
ast_log(LOG_DEBUG, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
}
if ((ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP))) {
if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP)) {
ast_build_string(&m_audio_next, &m_audio_left, " %d", 191);
ast_build_string(&a_audio_next, &a_audio_left, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000);
}
/* Check if we need video in this call */
if((capability & AST_FORMAT_VIDEO_MASK) && !ast_test_flag(&p->flags[0], SIP_NOVIDEO)) {
if ((capability & AST_FORMAT_VIDEO_MASK) && !ast_test_flag(&p->flags[0], SIP_NOVIDEO)) {
if (p->vrtp) {
needvideo = TRUE;
if (option_debug > 1)
ast_log(LOG_DEBUG, "This call needs video offers! \n");
ast_log(LOG_DEBUG, "This call needs video offers!\n");
} else if (option_debug > 1)
ast_log(LOG_DEBUG, "This call needs video offers, but there's no video support enabled ! \n");
ast_log(LOG_DEBUG, "This call needs video offers, but there's no video support enabled!\n");
}
/* Ok, we need video. Let's add what we need for video and set codecs.
Video is handled differently than audio since we can not transcode. */
if (needvideo) {
/* Determine video destination */
if (p->vredirip.sin_addr.s_addr) {
vdest.sin_addr = p->vredirip.sin_addr;
@ -6142,31 +6140,8 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
if (debug)
ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(vsin.sin_port));
/* For video, we can't negotiate video offers. Let's compare the incoming call with what we got. */
if (p->prefcodec) {
int videocapability = (capability & p->prefcodec) & AST_FORMAT_VIDEO_MASK; /* Outbound call */
/*! \todo XXX We need to select one codec, not many, since there's no transcoding */
/* Now, merge this video capability into capability while removing unsupported codecs */
if (!videocapability) {
needvideo = FALSE;
if (option_debug > 2)
ast_log(LOG_DEBUG, "** No compatible video codecs... Disabling video.\n");
}
/* Replace video capabilities with the new videocapability */
capability = (capability & AST_FORMAT_AUDIO_MASK) | videocapability;
if (option_debug > 4) {
char codecbuf[BUFSIZ];
if (videocapability)
ast_log(LOG_DEBUG, "** Our video codec selection is: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), videocapability));
ast_log(LOG_DEBUG, "** Capability now set to : %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability));
}
}
}
if (debug)
ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(sin.sin_port));

@ -205,12 +205,26 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, i
/*!
* \brief Returns the number of steps required to convert from 'src' to 'dest'.
* \param dest Destination format
* \param src Source format
* \param dest destination format
* \param src source format
* \return the number of translation steps required, or -1 if no path is available
*/
unsigned int ast_translate_path_steps(unsigned int dest, unsigned int src);
/*!
* \brief Mask off unavailable formats from a format bitmask
* \param dest possible destination formats
* \param src source formats
* \return the destination formats that are available in the source or translatable
*
* The result will include all formats from 'dest' that are either present
* in 'src' or translatable from a format present in 'src'.
*
* Note that only a single audio format and a single video format can be
* present in 'src', or the function will produce unexpected results.
*/
unsigned int ast_translate_available_formats(unsigned int dest, unsigned int src);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

@ -63,6 +63,9 @@ struct translator_path {
* until step->dstfmt == desired_format.
*
* Array indexes are 'src' and 'dest', in that order.
*
* Note: the lock in the 'translators' list is also used to protect
* this structure.
*/
static struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT];
@ -253,18 +256,22 @@ struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
source = powerof(source);
dest = powerof(dest);
AST_LIST_LOCK(&translators);
while (source != dest) {
struct ast_trans_pvt *cur;
struct ast_translator *t = tr_matrix[source][dest].step;
if (!t) {
ast_log(LOG_WARNING, "No translator path from %s to %s\n",
ast_getformatname(source), ast_getformatname(dest));
AST_LIST_UNLOCK(&translators);
return NULL;
}
if (!(cur = newpvt(t))) {
ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
if (head)
ast_translator_free_path(head);
AST_LIST_UNLOCK(&translators);
return NULL;
}
if (!head)
@ -276,6 +283,8 @@ struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
/* Keep going if this isn't the final destination */
source = cur->t->dstfmt;
}
AST_LIST_UNLOCK(&translators);
return head;
}
@ -560,6 +569,7 @@ static struct ast_cli_entry cli_translate[] = {
int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
{
static int added_cli = 0;
struct ast_translator *u;
if (!mod) {
ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
@ -617,7 +627,24 @@ int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
added_cli++;
}
AST_LIST_INSERT_HEAD(&translators, t, list);
/* find any existing translators that provide this same srcfmt/dstfmt,
and put this one in order based on cost */
AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
if ((u->srcfmt == t->srcfmt) &&
(u->dstfmt == t->dstfmt) &&
(u->cost > t->cost)) {
AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list);
t = NULL;
}
}
AST_LIST_TRAVERSE_SAFE_END;
/* if no existing translator was found for this format combination,
add it to the beginning of the list */
if (t)
AST_LIST_INSERT_HEAD(&translators, t, list);
rebuild_matrix(0);
AST_LIST_UNLOCK(&translators);
return 0;
@ -637,7 +664,7 @@ int ast_unregister_translator(struct ast_translator *t)
break;
}
}
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_TRAVERSE_SAFE_END;
rebuild_matrix(0);
AST_LIST_UNLOCK(&translators);
return (u ? 0 : -1);
@ -693,12 +720,70 @@ int ast_translator_best_choice(int *dst, int *srcs)
unsigned int ast_translate_path_steps(unsigned int dest, unsigned int src)
{
unsigned int res = -1;
/* convert bitwise format numbers into array indices */
src = powerof(src);
dest = powerof(dest);
if (!tr_matrix[src][dest].step)
return -1;
else
return tr_matrix[src][dest].multistep + 1;
AST_LIST_LOCK(&translators);
if (tr_matrix[src][dest].step)
res = tr_matrix[src][dest].multistep + 1;
AST_LIST_UNLOCK(&translators);
return res;
}
unsigned int ast_translate_available_formats(unsigned int dest, unsigned int src)
{
unsigned int res = dest;
unsigned int x;
unsigned int src_audio = powerof(src & AST_FORMAT_AUDIO_MASK);
unsigned int src_video = powerof(src & AST_FORMAT_VIDEO_MASK);
/* if we don't have a source format, we just have to try all
possible destination formats */
if (!src)
return dest;
AST_LIST_LOCK(&translators);
for (x = 1; x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
/* if this is not a desired format, nothing to do */
if (!dest & x)
continue;
/* if the source is supplying this format, then
we can leave it in the result */
if (src & x)
continue;
/* if we don't have a translation path from the src
to this format, remove it from the result */
if (!tr_matrix[src_audio][powerof(x)].step)
res &= ~x;
}
/* roll over into video formats */
for (; x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
/* if this is not a desired format, nothing to do */
if (!dest & x)
continue;
/* if the source is supplying this format, then
we can leave it in the result */
if (src & x)
continue;
/* if we don't have a translation path from the src
to this format, remove it from the result */
if (!tr_matrix[src_video][powerof(x)].step)
res &= ~x;
}
AST_LIST_UNLOCK(&translators);
return res;
}

Loading…
Cancel
Save