aboutsummaryrefslogtreecommitdiffstats
path: root/frame.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2004-12-02 21:57:45 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2004-12-02 21:57:45 +0000
commitb46c98aa49d8fa316429cc1ab2316ad11429a9c8 (patch)
tree9ec84354082d30f27088d1d42c7665243c6b69c8 /frame.c
parent7742cd11fa4589649382188fe07e407c74b90029 (diff)
Merge updates to frame.h and frame.c (codec stuff from bug #2945, part 1)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4370 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'frame.c')
-rwxr-xr-xframe.c438
1 files changed, 316 insertions, 122 deletions
diff --git a/frame.c b/frame.c
index 3538d35b1..c3f0d94c9 100755
--- a/frame.c
+++ b/frame.c
@@ -15,6 +15,7 @@
#include <asterisk/frame.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
+#include <asterisk/channel.h>
#include <asterisk/cli.h>
#include <asterisk/term.h>
#include <asterisk/utils.h>
@@ -33,6 +34,13 @@ AST_MUTEX_DEFINE_STATIC(framelock);
#define SMOOTHER_SIZE 8000
+struct ast_format_list {
+ int visible; /* Can we see this entry */
+ int bits; /* bitmask value */
+ char *name; /* short name */
+ char *desc; /* Description */
+};
+
struct ast_smoother {
int size;
int format;
@@ -391,141 +399,137 @@ int ast_fr_fdhangup(int fd)
return ast_fr_fdwrite(fd, &hangup);
}
+static struct ast_format_list AST_FORMAT_LIST[] = {
+ { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1"},
+ { 1, AST_FORMAT_GSM, "gsm" , "GSM"},
+ { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law" },
+ { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law" },
+ { 1, AST_FORMAT_G726, "g726", "G.726" },
+ { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM"},
+ { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM"},
+ { 1, AST_FORMAT_LPC10, "lpc10", "LPC10" },
+ { 1, AST_FORMAT_G729A, "g729", "G.729A" },
+ { 1, AST_FORMAT_SPEEX, "speex", "SpeeX" },
+ { 1, AST_FORMAT_ILBC, "ilbc", "iLBC"},
+ { 0, 0, "nothing", "undefined" },
+ { 0, 0, "nothing", "undefined" },
+ { 0, 0, "nothing", "undefined" },
+ { 0, 0, "nothing", "undefined" },
+ { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
+ { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"},
+ { 1, AST_FORMAT_PNG, "png", "PNG image"},
+ { 1, AST_FORMAT_H261, "h261", "H.261 Video" },
+ { 1, AST_FORMAT_H263, "h263", "H.263 Video" },
+ { 0, 0, "nothing", "undefined" },
+ { 0, 0, "nothing", "undefined" },
+ { 0, 0, "nothing", "undefined" },
+ { 0, 0, "nothing", "undefined" },
+ { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
+};
+
+struct ast_format_list *ast_get_format_list_index(int index) {
+ return &AST_FORMAT_LIST[index];
+}
+
+struct ast_format_list *ast_get_format_list(size_t *size) {
+ *size = (sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list));
+ return AST_FORMAT_LIST;
+}
+
char* ast_getformatname(int format)
{
- if (format == AST_FORMAT_G723_1)
- return "G723";
- else if (format == AST_FORMAT_GSM)
- return "GSM";
- else if (format == AST_FORMAT_ULAW)
- return "ULAW";
- else if (format == AST_FORMAT_ALAW)
- return "ALAW";
- else if (format == AST_FORMAT_G726)
- return "G726";
- else if (format == AST_FORMAT_SLINEAR)
- return "SLINR";
- else if (format == AST_FORMAT_LPC10)
- return "LPC10";
- else if (format == AST_FORMAT_ADPCM)
- return "ADPCM";
- else if (format == AST_FORMAT_G729A)
- return "G729A";
- else if (format == AST_FORMAT_SPEEX)
- return "SPEEX";
- else if (format == AST_FORMAT_ILBC)
- return "ILBC";
- else if (format == AST_FORMAT_JPEG)
- return "JPEG";
- else if (format == AST_FORMAT_PNG)
- return "PNG";
- else if (format == AST_FORMAT_H261)
- return "H261";
- else if (format == AST_FORMAT_H263)
- return "H263";
- return "UNKN";
-}
-
-char* ast_getformatname_multiple(char *buf, unsigned n, int format) {
- unsigned u=1;
+ int x = 0;
+ char *ret = "unknown";
+ for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
+ if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
+ ret = AST_FORMAT_LIST[x].name;
+ break;
+ }
+ }
+ return ret;
+}
+
+char *ast_getformatname_multiple(char *buf, size_t size, int format) {
+
+ int x = 0;
unsigned len;
- char *b = buf;
+ char *end = buf;
char *start = buf;
- if (!n) return buf;
- snprintf(b,n,"0x%x(",format);
- len = strlen(b);
- b += len;
- n -= len;
- start = b;
- while (u) {
- if (u&format) {
- snprintf(b,n,"%s|",ast_getformatname(u));
- len = strlen(b);
- b += len;
- n -= len;
+ if (!size) return buf;
+ snprintf(end, size, "0x%x (", format);
+ len = strlen(end);
+ end += len;
+ size -= len;
+ start = end;
+ for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
+ if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
+ snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
+ len = strlen(end);
+ end += len;
+ size -= len;
}
- u *= 2;
}
- if (start==b)
- snprintf(start,n,"EMPTY)");
- else if (n>1)
- b[-1]=')';
+ if (start == end)
+ snprintf(start, size, "nothing)");
+ else if (size > 1)
+ *(end -1) = ')';
return buf;
}
+static struct ast_codec_alias_table {
+ char *alias;
+ char *realname;
+
+} ast_codec_alias_table[] = {
+ {"slinear","slin"},
+ {"g723.1","g723"},
+};
+
+static char *ast_expand_codec_alias(char *in) {
+ int x = 0;
+
+ for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(struct ast_codec_alias_table) ; x++) {
+ if(!strcmp(in,ast_codec_alias_table[x].alias))
+ return ast_codec_alias_table[x].realname;
+ }
+ return in;
+}
+
int ast_getformatbyname(char *name)
{
- if (!strcasecmp(name, "g723.1"))
- return AST_FORMAT_G723_1;
- else if (!strcasecmp(name, "gsm"))
- return AST_FORMAT_GSM;
- else if (!strcasecmp(name, "ulaw"))
- return AST_FORMAT_ULAW;
- else if (!strcasecmp(name, "alaw"))
- return AST_FORMAT_ALAW;
- else if (!strcasecmp(name, "g726"))
- return AST_FORMAT_G726;
- else if (!strcasecmp(name, "slinear"))
- return AST_FORMAT_SLINEAR;
- else if (!strcasecmp(name, "lpc10"))
- return AST_FORMAT_LPC10;
- else if (!strcasecmp(name, "adpcm"))
- return AST_FORMAT_ADPCM;
- else if (!strcasecmp(name, "g729"))
- return AST_FORMAT_G729A;
- else if (!strcasecmp(name, "speex"))
- return AST_FORMAT_SPEEX;
- else if (!strcasecmp(name, "ilbc"))
- return AST_FORMAT_ILBC;
- else if (!strcasecmp(name, "h261"))
- return AST_FORMAT_H261;
- else if (!strcasecmp(name, "h263"))
- return AST_FORMAT_H263;
- else if (!strcasecmp(name, "all"))
- return 0x7FFFFFFF;
- return 0;
+ int x = 0, all = 0, format = 0;
+
+ all = strcmp(name, "all") ? 0 : 1;
+ for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
+ if(AST_FORMAT_LIST[x].visible && (all ||
+ !strcmp(AST_FORMAT_LIST[x].name,name) ||
+ !strcmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
+ format |= AST_FORMAT_LIST[x].bits;
+ if(!all)
+ break;
+ }
+ }
+
+ return format;
}
char *ast_codec2str(int codec) {
- static char codecs[25][30] = {
- /* Audio formats */
- "G.723.1", /* 0 */
- "GSM", /* 1 */
- "G.711 u-law", /* 2 */
- "G.711 A-law", /* 3 */
- "G.726", /* 4 */
- "ADPCM", /* 5 */
- "16 bit Signed Linear PCM", /* 6 */
- "LPC10", /* 7 */
- "G.729A audio", /* 8 */
- "SpeeX", /* 9 */
- "iLBC", /* 10 */
- "undefined", /* 11 */
- "undefined", /* 12 */
- "undefined", /* 13 */
- "undefined", /* 14 */
- "Maximum audio format", /* 15 */
- /* Image formats */
- "JPEG image", /* 16 */
- "PNG image", /* 17 */
- "H.261 Video", /* 18 */
- "H.263 Video", /* 19 */
- "undefined", /* 20 */
- "undefined", /* 21 */
- "undefined", /* 22 */
- "undefined", /* 23 */
- "Maximum video format", /* 24 */
- };
- if ((codec >= 0) && (codec <= 24))
- return codecs[codec];
- else
- return "unknown";
+ int x = 0;
+ char *ret = "unknown";
+ for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
+ if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
+ ret = AST_FORMAT_LIST[x].desc;
+ break;
+ }
+ }
+ return ret;
}
static int show_codecs(int fd, int argc, char *argv[])
{
int i, found=0;
-
+ char hex[25];
+
if ((argc < 2) || (argc > 3))
return RESULT_SHOWUSAGE;
@@ -533,22 +537,30 @@ static int show_codecs(int fd, int argc, char *argv[])
ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
"\tIt does not indicate anything about your configuration.\n");
+ ast_cli(fd, "%11s %9s %10s TYPE %5s %s\n","INT","BINARY","HEX","NAME","DESC");
+ ast_cli(fd, "--------------------------------------------------------------------------------\n");
if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
found = 1;
- for (i=0;i<11;i++)
- ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(i));
+ for (i=0;i<11;i++) {
+ snprintf(hex,25,"(0x%x)",1<<i);
+ ast_cli(fd, "%11u (1 << %2d) %10s audio %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
+ }
}
if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
found = 1;
- for (i=16;i<18;i++)
- ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(i));
+ for (i=16;i<18;i++) {
+ snprintf(hex,25,"(0x%x)",1<<i);
+ ast_cli(fd, "%11u (1 << %2d) %10s image %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
+ }
}
if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
found = 1;
- for (i=18;i<20;i++)
- ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(i));
+ for (i=18;i<20;i++) {
+ snprintf(hex,25,"(0x%x)",1<<i);
+ ast_cli(fd, "%11u (1 << %2d) %10s video %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
+ }
}
if (! found)
@@ -797,3 +809,185 @@ int init_framer(void)
ast_cli_register(&cli_show_codec_n);
return 0;
}
+
+void ast_codec_pref_shift(struct ast_codec_pref *pref, char *buf, size_t size, int right)
+{
+ int x = 0, differential = 65, mem = 0;
+ char *from = NULL, *to = NULL;
+
+ if(right) {
+ from = pref->order;
+ to = buf;
+ mem = size;
+ } else {
+ to = pref->order;
+ from = buf;
+ mem = 32;
+ }
+
+ memset(to, 0, mem);
+ for (x = 0; x < 32 ; x++) {
+ if(!from[x])
+ break;
+ to[x] = right ? (from[x] + differential) : (from[x] - differential);
+ }
+}
+
+int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
+{
+ int x = 0, codec = 0;
+ size_t total_len = 0, slen = 0;
+ char *formatname = 0;
+
+ memset(buf,0,size);
+ total_len = size;
+ buf[0] = '(';
+ total_len--;
+ for(x = 0; x < 32 ; x++) {
+ if(total_len <= 0)
+ break;
+ if(!(codec = ast_codec_pref_index(pref,x)))
+ break;
+ if((formatname = ast_getformatname(codec))) {
+ slen = strlen(formatname);
+ if(slen > total_len)
+ break;
+ strncat(buf,formatname,total_len);
+ total_len -= slen;
+ }
+ if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
+ strncat(buf,"|",total_len);
+ total_len--;
+ }
+ }
+ if(total_len) {
+ strncat(buf,")",total_len);
+ total_len--;
+ }
+
+ return size - total_len;
+}
+
+int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
+{
+ int slot = 0;
+
+
+ if((index >= 0) && (index < sizeof(pref->order))) {
+ slot = pref->order[index];
+ }
+
+ return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
+}
+
+/*--- ast_codec_pref_remove: Remove codec from pref list ---*/
+void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
+{
+ struct ast_codec_pref oldorder;
+ int x=0, y=0;
+ size_t size = 0;
+ int slot = 0;
+
+ if(!pref->order[0])
+ return;
+
+ size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
+
+ memcpy(&oldorder,pref,sizeof(struct ast_codec_pref));
+ memset(pref,0,sizeof(struct ast_codec_pref));
+
+ for (x = 0; x < size; x++) {
+ slot = oldorder.order[x];
+ if(! slot)
+ break;
+ if(AST_FORMAT_LIST[slot-1].bits != format)
+ pref->order[y++] = slot;
+ }
+
+}
+
+/*--- ast_codec_pref_append: Append codec to list ---*/
+int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
+{
+ size_t size = 0;
+ int x = 0, newindex = -1;
+
+ ast_codec_pref_remove(pref, format);
+ size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
+
+ for (x = 0; x < size; x++) {
+ if(AST_FORMAT_LIST[x].bits == format) {
+ newindex = x + 1;
+ break;
+ }
+ }
+
+ if(newindex) {
+ for (x = 0; x < size; x++) {
+ if(!pref->order[x]) {
+ pref->order[x] = newindex;
+ break;
+ }
+ }
+ }
+
+ return x;
+}
+
+
+/*--- sip_codec_choose: Pick a codec ---*/
+int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
+{
+ size_t size = 0;
+ int x = 0, ret = 0, slot = 0;
+
+ size = sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list);
+ for (x = 0; x < size; x++) {
+ slot = pref->order[x];
+
+ if(!slot)
+ break;
+ if ( formats & AST_FORMAT_LIST[slot-1].bits ) {
+ ret = AST_FORMAT_LIST[slot-1].bits;
+ break;
+ }
+ }
+ if(ret)
+ return ret;
+
+ return find_best ? ast_best_codec(formats) : 0;
+}
+
+void ast_parse_allow_deny(struct ast_codec_pref *pref, int *mask, char *list, int allowing)
+{
+ int format_i = 0;
+ char *next_format = NULL, *last_format = NULL;
+
+ last_format = ast_strdupa(list);
+ while(last_format) {
+ if((next_format = strchr(last_format, ','))) {
+ *next_format = '\0';
+ next_format++;
+ }
+ if ((format_i = ast_getformatbyname(last_format)) > 0) {
+ if (mask) {
+ if (allowing)
+ (*mask) |= format_i;
+ else
+ (*mask) &= format_i;
+ }
+ /* can't consider 'all' a prefered codec*/
+ if(pref && strcasecmp(last_format, "all")) {
+ if(allowing)
+ ast_codec_pref_append(pref, format_i);
+ else
+ ast_codec_pref_remove(pref, format_i);
+ }
+ } else
+ ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", last_format);
+
+ last_format = next_format;
+ }
+}
+
+