Merged revisions 99004 via svnmerge from
authorRussell Bryant <russell@russellbryant.com>
Thu, 17 Jan 2008 22:50:13 +0000 (22:50 +0000)
committerRussell Bryant <russell@russellbryant.com>
Thu, 17 Jan 2008 22:50:13 +0000 (22:50 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r99004 | russell | 2008-01-17 16:37:22 -0600 (Thu, 17 Jan 2008) | 10 lines

Have IAX2 optimize the codec translation path just like chan_sip does it.  If
the caller's codec is in our codec list, move it to the top to avoid transcoding.

(closes issue #10500)
Reported by: stevedavies
Patches:
      iax-prefer-current-codec.patch uploaded by stevedavies (license 184)
      iax-prefer-current-codec.1.4.patch uploaded by stevedavies (license 184)
Tested by: stevedavies, pj, sheldonh

........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@99006 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c
include/asterisk/frame.h
main/frame.c

index e964eb4..c577466 100644 (file)
@@ -3162,10 +3162,11 @@ struct create_addr_info {
        char mohsuggest[MAX_MUSICCLASS];
 };
 
-static int create_addr(const char *peername, struct sockaddr_in *sin, struct create_addr_info *cai)
+static int create_addr(const char *peername, struct ast_channel *c, struct sockaddr_in *sin, struct create_addr_info *cai)
 {
        struct iax2_peer *peer;
        int res = -1;
+       struct ast_codec_pref ourprefs;
 
        ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
        cai->sockfd = defaultsockfd;
@@ -3180,7 +3181,11 @@ static int create_addr(const char *peername, struct sockaddr_in *sin, struct cre
                }
                sin->sin_port = htons(IAX_DEFAULT_PORTNO);
                /* use global iax prefs for unknown peer/user */
-               ast_codec_pref_convert(&prefs, cai->prefs, sizeof(cai->prefs), 1);
+               /* But move the calling channel's native codec to the top of the preference list */
+               memcpy(&ourprefs, &prefs, sizeof(ourprefs));
+               if (c)
+                       ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
+               ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
                return 0;
        }
 
@@ -3200,7 +3205,13 @@ static int create_addr(const char *peername, struct sockaddr_in *sin, struct cre
        cai->encmethods = peer->encmethods;
        cai->sockfd = peer->sockfd;
        cai->adsi = peer->adsi;
-       ast_codec_pref_convert(&peer->prefs, cai->prefs, sizeof(cai->prefs), 1);
+       memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
+       /* Move the calling channel's native codec to the top of the preference list */
+       if (c) {
+               ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
+               ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
+       }
+       ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
        ast_copy_string(cai->context, peer->context, sizeof(cai->context));
        ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
        ast_copy_string(cai->username, peer->username, sizeof(cai->username));
@@ -3378,7 +3389,7 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
        if (!pds.exten)
                pds.exten = defaultrdest;
 
-       if (create_addr(pds.peer, &sin, &cai)) {
+       if (create_addr(pds.peer, c, &sin, &cai)) {
                ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
                return -1;
        }
@@ -9289,7 +9300,7 @@ static int iax2_provision(struct sockaddr_in *end, int sockfd, char *dest, const
        if (end) {
                memcpy(&sin, end, sizeof(sin));
                cai.sockfd = sockfd;
-       } else if (create_addr(dest, &sin, &cai))
+       } else if (create_addr(dest, NULL, &sin, &cai))
                return -1;
 
        /* Build the rest of the message */
@@ -9525,7 +9536,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data
               
        
        /* Populate our address from the given */
-       if (create_addr(pds.peer, &sin, &cai)) {
+       if (create_addr(pds.peer, NULL, &sin, &cai)) {
                *cause = AST_CAUSE_UNREGISTERED;
                return NULL;
        }
@@ -10895,7 +10906,7 @@ static int cache_get_callno_locked(const char *data)
        parse_dial_string(tmpstr, &pds);
 
        /* Populate our address from the given */
-       if (create_addr(pds.peer, &sin, &cai))
+       if (create_addr(pds.peer, NULL, &sin, &cai))
                return -1;
 
        ast_debug(1, "peer: %s, username: %s, password: %s, context: %s\n",
index c4d5832..3983c84 100644 (file)
@@ -531,6 +531,10 @@ void ast_codec_pref_remove(struct ast_codec_pref *pref, int format);
 */
 int ast_codec_pref_append(struct ast_codec_pref *pref, int format);
 
+/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there 
+*/
+void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing);
+
 /*! \brief Select the best audio format according to preference list from supplied options. 
    If "find_best" is non-zero then if nothing is found, the "Best" format of 
    the format list is selected, otherwise 0 is returned. */
index 9b7d150..d46dd23 100644 (file)
@@ -1025,7 +1025,7 @@ void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
 /*! \brief Append codec to list */
 int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
 {
-       int x, newindex = -1;
+       int x, newindex = 0;
 
        ast_codec_pref_remove(pref, format);
 
@@ -1048,6 +1048,42 @@ int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
        return x;
 }
 
+/*! \brief Prepend codec to list */
+void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
+{
+       int x, newindex = 0;
+
+       /* First step is to get the codecs "index number" */
+       for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
+               if (AST_FORMAT_LIST[x].bits == format) {
+                       newindex = x + 1;
+                       break;
+               }
+       }
+       /* Done if its unknown */
+       if (!newindex)
+               return;
+
+       /* Now find any existing occurrence, or the end */
+       for (x = 0; x < 32; x++) {
+               if (!pref->order[x] || pref->order[x] == newindex)
+                       break;
+       }
+
+       if (only_if_existing && !pref->order[x])
+               return;
+
+       /* Move down to make space to insert - either all the way to the end,
+          or as far as the existing location (which will be overwritten) */
+       for (; x > 0; x--) {
+               pref->order[x] = pref->order[x - 1];
+               pref->framing[x] = pref->framing[x - 1];
+       }
+
+       /* And insert the new entry */
+       pref->order[0] = newindex;
+       pref->framing[0] = 0; /* ? */
+}
 
 /*! \brief Set packet size for codec */
 int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)