aboutsummaryrefslogtreecommitdiffstats
path: root/main/translate.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-25 14:55:11 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-25 14:55:11 +0000
commit6d73a5efa0e08e68e0d87637dd54971df7cf7c6d (patch)
treeb8ff47ecf73c196ed8c4e061ad267b9a4a57220e /main/translate.c
parentfb76c79434f8a3dc418dcbabeffd96829a30033e (diff)
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: http://svn.digium.com/svn/asterisk/trunk@46203 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/translate.c')
-rw-r--r--main/translate.c97
1 files changed, 91 insertions, 6 deletions
diff --git a/main/translate.c b/main/translate.c
index d130a38de..bdee23e8d 100644
--- a/main/translate.c
+++ b/main/translate.c
@@ -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;
+}