diff options
author | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-10-25 14:55:11 +0000 |
---|---|---|
committer | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-10-25 14:55:11 +0000 |
commit | 6d73a5efa0e08e68e0d87637dd54971df7cf7c6d (patch) | |
tree | b8ff47ecf73c196ed8c4e061ad267b9a4a57220e /main/translate.c | |
parent | fb76c79434f8a3dc418dcbabeffd96829a30033e (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.c | 97 |
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; +} |