diff --git a/CHANGES b/CHANGES index 9f0069933964d249b68ad8bc07af9b0f08ecac47..3d6b4fbc6460348d9f9632775ed4e07d382bb3c2 100644 --- a/CHANGES +++ b/CHANGES @@ -61,6 +61,7 @@ Changes since Asterisk 1.4-beta was branched: * Added the jittertargetextra configuration option. * Added the URI redirect option for the built-in HTTP server * Added the trunkmaxsize configuration option to chan_iax2. + * Added G729 passthrough support to chan_phone for Sigma Designs boards. SIP changes ----------- diff --git a/channels/chan_phone.c b/channels/chan_phone.c index cebbcd255f3132d848aeb9bd141710923608e553..20a0cb3719df57b99c2af3cf42f2ccb6b82ea152 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -98,7 +98,7 @@ static int echocancel = AEC_OFF; static int silencesupression = 0; -static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW; +static int prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW; /* Protect the interface list (of phone_pvt's) */ AST_MUTEX_DEFINE_STATIC(iflock); @@ -170,7 +170,7 @@ static int phone_indicate(struct ast_channel *chan, int condition, const void *d static const struct ast_channel_tech phone_tech = { .type = "Phone", .description = tdesc, - .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, + .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A, .requester = phone_request, .send_digit_begin = phone_digit_begin, .send_digit_end = phone_digit_end, @@ -399,8 +399,17 @@ static int phone_setup(struct ast_channel *ast) p = ast->tech_pvt; ioctl(p->fd, PHONE_CPT_STOP); /* Nothing to answering really, just start recording */ - if (ast->rawreadformat == AST_FORMAT_G723_1) { - /* Prefer g723 */ + if (ast->rawreadformat == AST_FORMAT_G729A) { + /* Prefer g729 */ + ioctl(p->fd, PHONE_REC_STOP); + if (p->lastinput != AST_FORMAT_G729A) { + p->lastinput = AST_FORMAT_G729A; + if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { + ast_log(LOG_WARNING, "Failed to set codec to g729\n"); + return -1; + } + } + } else if (ast->rawreadformat == AST_FORMAT_G723_1) { ioctl(p->fd, PHONE_REC_STOP); if (p->lastinput != AST_FORMAT_G723_1) { p->lastinput = AST_FORMAT_G723_1; @@ -667,7 +676,7 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } if (!(frame->subclass & - (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) && + (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A)) && p->mode != MODE_FXS) { ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); return -1; @@ -684,7 +693,30 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) return 0; } #endif - if (frame->subclass == AST_FORMAT_G723_1) { + if (frame->subclass == AST_FORMAT_G729A) { + if (p->lastformat != AST_FORMAT_G729A) { + ioctl(p->fd, PHONE_PLAY_STOP); + ioctl(p->fd, PHONE_REC_STOP); + if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) { + ast_log(LOG_WARNING, "Unable to set G729 mode\n"); + return -1; + } + if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { + ast_log(LOG_WARNING, "Unable to set G729 mode\n"); + return -1; + } + p->lastformat = AST_FORMAT_G729A; + p->lastinput = AST_FORMAT_G729A; + /* Reset output buffer */ + p->obuflen = 0; + codecset = 1; + } + if (frame->datalen > 80) { + ast_log(LOG_WARNING, "Frame size too large for G.729 (%d bytes)\n", frame->datalen); + return -1; + } + maxfr = 80; + } else if (frame->subclass == AST_FORMAT_G723_1) { if (p->lastformat != AST_FORMAT_G723_1) { ioctl(p->fd, PHONE_PLAY_STOP); ioctl(p->fd, PHONE_REC_STOP); @@ -1214,7 +1246,7 @@ static struct ast_channel *phone_request(const char *type, int format, void *dat p = iflist; while(p) { if (p->mode == MODE_FXS || - format & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) { + format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) { size_t length = strlen(p->dev + 5); if (strncmp(name, p->dev + 5, length) == 0 && !isalnum(name[length])) { @@ -1231,7 +1263,7 @@ static struct ast_channel *phone_request(const char *type, int format, void *dat restart_monitor(); if (tmp == NULL) { oldformat = format; - format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW); + format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW); if (!format) { ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat); return NULL; @@ -1382,7 +1414,9 @@ static int load_module(void) } else if (!strcasecmp(v->name, "context")) { ast_copy_string(context, v->value, sizeof(context)); } else if (!strcasecmp(v->name, "format")) { - if (!strcasecmp(v->value, "g723.1")) { + if (!strcasecmp(v->value, "g729")) { + prefformat = AST_FORMAT_G729A; + } else if (!strcasecmp(v->value, "g723.1")) { prefformat = AST_FORMAT_G723_1; } else if (!strcasecmp(v->value, "slinear")) { if (mode == MODE_FXS) diff --git a/configs/phone.conf.sample b/configs/phone.conf.sample index 649edc7bba91bf93893e27b1be812ca0f2f8a1de..17204501ebe920b7bab119a9c4cb9ed07e8764c3 100644 --- a/configs/phone.conf.sample +++ b/configs/phone.conf.sample @@ -18,12 +18,14 @@ mode=immediate ;mode=fxo ;mode=sig ; -; You can decide which format to use by default, "g723.1" or "slinear". +; You can decide which format to use by default, "g723.1", "g729", or "slinear". +; Note that g729 is only supported for Sigma Designs boards. ; XXX Be careful, sometimes the card causes kernel panics when running ; in signed linear mode for some reason... XXX ; format=slinear ;format=g723.1 +;format=g729 ; ; And set the echo cancellation to "off", "low", "medium", and "high". ; This is not supported on all phones.